1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-04-25 21:49:23 +03:00
This commit is contained in:
Alexander Yakovlev 2017-02-17 14:10:48 +07:00
commit 86093d41ff
111 changed files with 28282 additions and 384 deletions

8
Readme.EN.txt Normal file
View file

@ -0,0 +1,8 @@
LiveStreet 2.0.0
Free social engine.
INSTALLATION
1. Copy files to the engine to the desired directory site
2. Go the address http://you_site/
3. Follow the instructions of the installer.

29
Readme.RU.txt Normal file
View file

@ -0,0 +1,29 @@
LiveStreet 2.0.0
Бесплатный движок блого-социальной сети.
УСТАНОВКА
1. Скопировать файлы движка в нужный каталог сайта
2. Зайти через браузер на ваш сайт ( http://ваш_сайт_на_ls/ ), автоматически запустится инсталлятор
3. Следовать инструкциям установщика.
ОБНОВЛЕНИЕ С ВЕРСИИ 1.0.3
0. ОБЯЗАТЕЛЬНО СДЕЛАЙТЕ РЕЗЕРВНЫЕ КОПИИ ВАШЕГО САЙТА И БАЗЫ ДАННЫХ
1. Обновить до версии 2.0.0 возможно только базу данных, поэтому копировать новую версию поверх старой НЕЛЬЗЯ, для установки используйте чистый каталог
2. Скопировать файлы движка в новый нужный каталог сайта
3. Скопировать в новый каталог (/application/config/) файл config.local.php от вашей старой версии 1.0 и скопировать каталог /uploads/ со всеми файлами. Обязательно дать права на запись в этот каталог и перезапись всех файлов.
4. Зайти через браузер на ваш сайт ( http://ваш_сайт_на_ls/ ), автоматически запустится инсталлятор
5. На первом шаге следует выбрать режим обновления сайта, далее следовать инструкциям установщика.
КОНФИГУРАЦИЯ И НАСТРОЙКА ДВИЖКА
Настройки находятся в файле /application/config/config.php. Для их изменения желательно переопределять эти настройки в файле config.local.php, это позволит избежать проблем при последующих обновлениях.
Управление плагинами находится по адресу /admin/plugins/
Для более удобного управления сайтом рекомендуем активировать плагин админ-панели (входит в комплект)
По всем вопросам обращайтесь на сайт русского комьюнити http://livestreet.ru
Официальный сайт проекта http://livestreetcms.com
Каталог плагинов и шаблонов https://catalog.livestreetcms.com

View file

@ -84,8 +84,6 @@ class ActionAjax extends Action
$this->AddEventPreg('/^geo$/i', '/^get/', '/^regions$/', 'EventGeoGetRegions');
$this->AddEventPreg('/^geo$/i', '/^get/', '/^cities$/', 'EventGeoGetCities');
$this->AddEventPreg('/^infobox$/i', '/^info$/', '/^blog$/', 'EventInfoboxInfoBlog');
$this->AddEventPreg('/^media$/i', '/^upload$/', '/^$/', 'EventMediaUpload');
$this->AddEventPreg('/^media$/i', '/^upload-link$/', '/^$/', 'EventMediaUploadLink');
$this->AddEventPreg('/^media$/i', '/^generate-target-tmp$/', '/^$/', 'EventMediaGenerateTargetTmp');
@ -192,14 +190,14 @@ class ActionAjax extends Action
* Истекло время голосования?
*/
if (!$oPoll->isAllowVote()) {
$this->Message_AddErrorSingle('В этом опросе уже нельзя голосовать');
$this->Message_AddErrorSingle($this->Lang_Get('poll.notices.error_not_allow_vote'));
return;
}
/**
* Пользователь уже голосовал?
*/
if ($this->Poll_CheckUserAlreadyVote($oPoll, $this->oUserCurrent)) {
$this->Message_AddErrorSingle('Вы уже голосовали');
$this->Message_AddErrorSingle($this->Lang_Get('poll.notices.error_already_vote'));
return;
}
@ -210,7 +208,7 @@ class ActionAjax extends Action
* Проверяем варианты ответов
*/
if (!$aAnswer = (array)getRequest('answers')) {
$this->Message_AddErrorSingle('Необходимо выбрать вариант');
$this->Message_AddErrorSingle($this->Lang_Get('poll.notices.error_no_answers'));
return;
}
@ -234,7 +232,7 @@ class ActionAjax extends Action
* Ограничение на максимальное число ответов
*/
if (count($aAnswerIds) > $oPoll->getCountAnswerMax()) {
$this->Message_AddErrorSingle('Максимум можно выбрать вариантов: ' . $oPoll->getCountAnswerMax());
$this->Message_AddErrorSingle($this->Lang_Get('poll.notices.error_answers_max', array('count' => $oPoll->getCountAnswerMax())));
return;
}
}
@ -362,7 +360,7 @@ class ActionAjax extends Action
}
if (!$oPoll->isAllowRemove()) {
$this->Message_AddError('Этот опрос уже нельзя удалить');
$this->Message_AddError($this->Lang_Get('poll.notices.error_not_allow_remove'));
return;
}
@ -847,7 +845,7 @@ class ActionAjax extends Action
}
if (!($aMediaItems = $this->Media_GetAllowMediaItemsById($aIds))) {
$this->Message_AddError('Необходимо выбрать элементы');
$this->Message_AddError($this->Lang_Get('media.error.need_choose_items'));
return false;
}
@ -874,7 +872,7 @@ class ActionAjax extends Action
{
$aMediaItems = $this->Media_GetAllowMediaItemsById(getRequest('ids'));
if (!$aMediaItems) {
$this->Message_AddError('Необходимо выбрать элементы');
$this->Message_AddError($this->Lang_Get('media.error.need_choose_items'));
return false;
}
@ -978,40 +976,6 @@ class ActionAjax extends Action
}
}
/**
* Вывод информации о блоге
*/
protected function EventInfoboxInfoBlog()
{
/**
* Если блог существует и он не персональный
*/
if (!is_string(getRequest('iBlogId'))) {
return $this->EventErrorDebug();
}
if (!($oBlog = $this->Blog_GetBlogById(getRequest('iBlogId'))) or $oBlog->getType() == 'personal') {
return $this->EventErrorDebug();
}
/**
* Получаем локальный вьюер для рендеринга шаблона
*/
$oViewer = $this->Viewer_GetLocalViewer();
$oViewer->Assign('oBlog', $oBlog);
if ($oBlog->getType() != 'close' or $oBlog->getUserIsJoin()) {
/**
* Получаем последний топик
*/
$aResult = $this->Topic_GetTopicsByFilter(array('blog_id' => $oBlog->getId(), 'topic_publish' => 1), 1, 1);
$oViewer->Assign('oTopicLast', reset($aResult['collection']));
}
$oViewer->Assign('oUserCurrent', $this->oUserCurrent);
/**
* Устанавливаем переменные для ajax ответа
*/
$this->Viewer_AssignAjax('sText', $oViewer->Fetch("actions/ActionBlogs/popover.blog.info.tpl"));
}
/**
* Получение информации о голосовании за топик
*/
@ -1797,7 +1761,7 @@ class ActionAjax extends Action
if ($bReturnExtended) {
$aItems[] = array(
'value' => $oUser->getId(),
'label' => $oUser->getDisplayName(),
'label' => $oUser->getDisplayName(),
);
} else {
$aItems[] = $oUser->getDisplayName();

View file

@ -113,8 +113,7 @@ class ActionAuth extends Action
/**
* Сверяем хеши паролей и проверяем активен ли юзер
*/
if ($oUser->getPassword() == func_encrypt(getRequest('password'))) {
if ($this->User_VerifyAccessAuth($oUser) and $oUser->verifyPassword(getRequest('password'))) {
if (!$oUser->getActivate()) {
$this->Message_AddErrorSingle($this->Lang_Get('auth.login.notices.error_not_activated',
array('reactivation_path' => Router::GetPath('auth/reactivation'))));
@ -236,7 +235,7 @@ class ActionAuth extends Action
if ($oReminder = $this->User_GetReminderByCode($this->GetParam(0))) {
if (!$oReminder->getIsUsed() and strtotime($oReminder->getDateExpire()) > time() and $oUser = $this->User_GetUserById($oReminder->getUserId())) {
$sNewPassword = func_generator(7);
$oUser->setPassword(func_encrypt($sNewPassword));
$oUser->setPassword($this->User_MakeHashPassword($sNewPassword));
if ($this->User_Update($oUser)) {
$oReminder->setDateUsed(date("Y-m-d H:i:s"));
$oReminder->setIsUsed(1);
@ -383,7 +382,7 @@ class ActionAuth extends Action
*/
if ($oUser->_Validate()) {
$this->Hook_Run('registration_validate_after', array('oUser' => $oUser));
$oUser->setPassword(func_encrypt($oUser->getPassword()));
$oUser->setPassword($this->User_MakeHashPassword($oUser->getPassword()));
if ($this->User_Add($oUser)) {
$this->Hook_Run('registration_after', array('oUser' => $oUser));
/**
@ -436,6 +435,7 @@ class ActionAuth extends Action
* Получаем ошибки
*/
$this->Viewer_AssignAjax('errors', $oUser->_getValidateErrors());
$this->Message_AddErrorSingle(null);
}
}

View file

@ -133,7 +133,7 @@ class ActionBlogs extends Action
if (getRequestStr('relation') == 'my') {
$aFilter['user_owner_id'] = $this->oUserCurrent->getId();
} elseif (getRequestStr('relation') == 'join') {
$aFilter['roles']=array(ModuleBlog::BLOG_USER_ROLE_USER,ModuleBlog::BLOG_USER_ROLE_ADMINISTRATOR,ModuleBlog::BLOG_USER_ROLE_MODERATOR);
$aFilter['roles'] = array(ModuleBlog::BLOG_USER_ROLE_USER, ModuleBlog::BLOG_USER_ROLE_ADMINISTRATOR, ModuleBlog::BLOG_USER_ROLE_MODERATOR);
}
}
/**

View file

@ -447,7 +447,7 @@ class ActionContent extends Action
}
$this->Viewer_AssignAjax('sUrlRedirect', $sUrlRedirect);
$this->Message_AddNotice('Обновление прошло успешно', $this->Lang_Get('common.attention'));
$this->Message_AddNotice($this->Lang_Get('topic.add.notices.update_complete'), $this->Lang_Get('common.attention'));
} else {
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.base'));
}
@ -589,9 +589,9 @@ class ActionContent extends Action
$this->Viewer_AssignAjax('sUrlRedirect', $oTopic->getUrl());
$this->Message_AddNotice('Добавление прошло успешно', $this->Lang_Get('common.attention'));
$this->Message_AddNotice($this->Lang_Get('topic.add.notices.create_complete'), $this->Lang_Get('common.attention'));
} else {
$this->Message_AddError('Возникла ошибка при добавлении', $this->Lang_Get('common.error.error'));
$this->Message_AddError($this->Lang_Get('common.error.error'));
}
} else {
$this->Message_AddError($oTopic->_getValidateError(), $this->Lang_Get('common.error.error'));

View file

@ -459,8 +459,8 @@ class ActionSettings extends Action
if (getRequestStr('password', '') != '') {
if (func_check(getRequestStr('password'), 'password', 5)) {
if (getRequestStr('password') == getRequestStr('password_confirm')) {
if (func_encrypt(getRequestStr('password_now')) == $this->oUserCurrent->getPassword()) {
$this->oUserCurrent->setPassword(func_encrypt(getRequestStr('password')));
if ($this->oUserCurrent->verifyPassword(getRequestStr('password_now'))) {
$this->oUserCurrent->setPassword($this->User_MakeHashPassword(getRequestStr('password')));
} else {
$bError = true;
$this->Message_AddError($this->Lang_Get('user.settings.account.fields.password.notices.error'),
@ -547,11 +547,11 @@ class ActionSettings extends Action
$aGeo = getRequest('geo');
if (isset($aGeo['city']) && $aGeo['city']) {
$oGeoObject = $this->Geo_GetGeoObject('city', (int) $aGeo['city']);
$oGeoObject = $this->Geo_GetGeoObject('city', (int)$aGeo['city']);
} elseif (isset($aGeo['region']) && $aGeo['region']) {
$oGeoObject = $this->Geo_GetGeoObject('region', (int) $aGeo['region']);
$oGeoObject = $this->Geo_GetGeoObject('region', (int)$aGeo['region']);
} elseif (isset($aGeo['country']) && $aGeo['country']) {
$oGeoObject = $this->Geo_GetGeoObject('country', (int) $aGeo['country']);
$oGeoObject = $this->Geo_GetGeoObject('country', (int)$aGeo['country']);
} else {
$oGeoObject = null;
}
@ -574,10 +574,14 @@ class ActionSettings extends Action
/**
* Проверяем дату рождения
*/
if (preg_match('#^(\d{1,2})\.(\d{1,2})\.(\d{4})$#', getRequestStr('profile_birthday'), $aMatch)) {
$this->oUserCurrent->setProfileBirthday(date("Y-m-d H:i:s", mktime(0, 0, 0, $aMatch[2], $aMatch[1], $aMatch[3])));
} else {
$this->oUserCurrent->setProfileBirthday(null);
$this->oUserCurrent->setProfileBirthday(null);
if ($this->Validate_Validate('date', getRequestStr('profile_birthday'),
array('format' => 'dd.MM.yyyy', 'allowEmpty' => false))
) {
$iBirthdayTime = strtotime(getRequestStr('profile_birthday'));
if ($iBirthdayTime < time() and $iBirthdayTime > strtotime('-100 year')) {
$this->oUserCurrent->setProfileBirthday(date("Y-m-d H:i:s", $iBirthdayTime));
}
}
/**
* Проверяем информацию о себе

View file

@ -142,7 +142,7 @@ class ActionStream extends Action
return parent::EventNotFound();
}
$_this=$this;
$_this = $this;
$this->GetMore(function ($lastId) use ($_this) {
return $_this->Stream_Read(null, $lastId);
});
@ -153,7 +153,7 @@ class ActionStream extends Action
*/
protected function EventGetMoreAll()
{
$_this=$this;
$_this = $this;
$this->GetMore(function ($lastId) use ($_this) {
return $_this->Stream_ReadAll(null, $lastId);
});
@ -164,7 +164,7 @@ class ActionStream extends Action
*/
protected function EventGetMoreUser()
{
$_this=$this;
$_this = $this;
$this->GetMore(function ($lastId) use ($_this) {
if (!($oUser = $_this->User_GetUserById(getRequestStr('target_id')))) {
return false;
@ -201,7 +201,9 @@ class ActionStream extends Action
$oViewer = $this->Viewer_GetLocalViewer();
$oViewer->Assign('events', $aEvents, true);
$oViewer->Assign('dateLast', getRequestStr('date_last'), true);
if (preg_match('#^\d{4}\-\d{1,2}\-\d{1,2}$#', getRequestStr('date_last'))) {
$oViewer->Assign('dateLast', getRequestStr('date_last'), true);
}
if (count($aEvents)) {
$this->Viewer_AssignAjax('last_id', end($aEvents)->getId(), true);
@ -275,7 +277,7 @@ class ActionStream extends Action
* Обрабатываем добавление по каждому из переданных логинов
*/
foreach ($aUsers as $iUserId) {
$iUserId = (int) $iUserId;
$iUserId = (int)$iUserId;
if (!$iUserId) {
continue;
@ -291,12 +293,12 @@ class ActionStream extends Action
$oViewer->Assign('showActions', true, true);
$aResult[] = array(
'bStateError' => false,
'sMsgTitle' => $this->Lang_Get('common.attention'),
'sMsg' => $this->Lang_Get('common.success.add', array('login' => $oUser->getLogin())),
'user_id' => $oUser->getId(),
'user_login' => $oUser->getLogin(),
'html' => $oViewer->Fetch("component@user-list-add.item")
'bStateError' => false,
'sMsgTitle' => $this->Lang_Get('common.attention'),
'sMsg' => $this->Lang_Get('common.success.add', array('login' => $oUser->getLogin())),
'user_id' => $oUser->getId(),
'user_login' => $oUser->getLogin(),
'html' => $oViewer->Fetch("component@user-list-add.item")
);
} else {
$aResult[] = array(
@ -317,7 +319,7 @@ class ActionStream extends Action
*/
protected function EventAjaxRemoveUser()
{
$iUserId = (int) getRequestStr('user_id');
$iUserId = (int)getRequestStr('user_id');
/**
* Устанавливаем формат Ajax ответа
*/

View file

@ -42,9 +42,6 @@ class HookCopyright extends Hook
*/
public function CopyrightLink()
{
/**
* Выводим везде, кроме страницы списка блогов и списка всех комментов
*/
return '&copy; Powered by <a href="http://livestreetcms.org">LiveStreet CMS</a>';
return '&copy; Powered by <a href="https://catalog.livestreetcms.com">LiveStreet CMS</a>';
}
}

View file

@ -61,7 +61,7 @@ class HookMain extends Hook
/**
* Запуск обработки сборщика
*/
//$this->Ls_SenderRun();
$this->Ls_SenderRun();
}
/**

View file

@ -241,7 +241,7 @@ class ModuleBlog_EntityBlog extends Entity
if ($sPath = $this->getAvatar()) {
return $this->Media_GetImageWebPath($sPath, $iSize);
} else {
return $this->Media_GetImagePathBySize(Config::Get('path.skin.assets.web') . '/images/avatars/avatar_blog.png', $iSize);
return $this->Media_GetImagePathBySize(Router::GetFixPathWeb(Config::Get('path.skin.assets.web')) . '/images/avatars/avatar_blog.png', $iSize);
}
}

View file

@ -160,18 +160,19 @@ class ModuleCategory_BehaviorEntity extends Behavior
}
if ($this->getParam('validate_require') and !$aCategories) {
return 'Необходимо выбрать категорию';
return $this->Lang_Get('category.notices.validate_require');
}
if (!$this->getParam('multiple') and count($aCategories) > 1) {
$aCategories = array_slice($aCategories, 0, 1);
}
if ($this->getParam('multiple') and $aCategories and (count($aCategories) < $this->getParam('validate_min') or count($aCategories) > $this->getParam('validate_max'))) {
return 'Количество категорий должно быть от ' . $this->getParam('validate_min') . ' до ' . $this->getParam('validate_max');
return $this->Lang_Get('category.notices.validate_count',
array('min' => $this->getParam('validate_min'), 'max' => $this->getParam('validate_max')));
}
if ($this->getParam('validate_only_without_children')) {
foreach ($aCategories as $oCategory) {
if ($oCategory->getChildren()) {
return 'Для выбора доступны только конечные категории';
return $this->Lang_Get('category.notices.validate_children');
}
}
}

View file

@ -59,14 +59,14 @@ class ModuleCategory_EntityCategory extends EntityORM
if ($this->getPid()) {
if ($oCategory = $this->Category_GetCategoryById($this->getPid())) {
if ($oCategory->getId() == $this->getId()) {
return 'Попытка вложить категорию в саму себя';
return $this->Lang_Get('category.notices.validate_recursion');
}
if ($oCategory->getTypeId() != $this->getTypeId()) {
return 'Неверная родительская категория';
return $this->Lang_Get('category.notices.validate_parent');
}
$this->setUrlFull($oCategory->getUrlFull() . '/' . $this->getUrl());
} else {
return 'Неверная категория';
return $this->Lang_Get('category.notices.validate_wrong');
}
} else {
$this->setPid(null);

View file

@ -135,7 +135,7 @@ class ModulePoll_EntityPoll extends EntityORM
return true;
} else {
if ($iCount < 2) {
return 'Максимальное количество вариантов ответа должно быть больше одного';
return $this->Lang_Get('poll.notices.error_answers_max_wrong');
}
}
return true;
@ -148,11 +148,8 @@ class ModulePoll_EntityPoll extends EntityORM
}
$aAnswersRaw = $this->getAnswersRaw();
if (!is_array($aAnswersRaw)) {
return 'Необходимо заполнить варианты ответов';
}
if (count($aAnswersRaw) < 2) {
return 'Необходимо заполнить больше одного варианта ответов';
if (!is_array($aAnswersRaw) or count($aAnswersRaw) < 2) {
return $this->Lang_Get('poll.notices.error_answers_count');
}
/**
* Здесь может быть два варианта - создание опроса или редактирование, при редактирование могут передаваться ID ответов
@ -186,7 +183,7 @@ class ModulePoll_EntityPoll extends EntityORM
foreach ($aAnswersOld as $oAnswer) {
if ($oAnswer->getCountVote()) {
return 'Нельзя удалить вариант ответа, за который уже голосовали';
return $this->Lang_Get('poll.notices.error_answer_remove');
}
}
@ -205,15 +202,15 @@ class ModulePoll_EntityPoll extends EntityORM
if ($sTargetId) {
$sTargetTmp = null;
if (!$this->Poll_CheckTarget($sTargetType, $sTargetId)) {
return 'Неверный тип объекта';
return $this->Lang_Get('poll.notices.error_target_type');
}
} else {
$sTargetId = null;
if (!$sTargetTmp or !$this->Poll_IsAllowTargetType($sTargetType)) {
return 'Неверный тип объекта';
return $this->Lang_Get('poll.notices.error_target_type');
}
if ($this->Poll_GetPollByFilter(array('target_tmp' => $sTargetTmp, 'target_type <>' => $sTargetType))) {
return 'Временный идентификатор уже занят';
return $this->Lang_Get('poll.notices.error_target_tmp');
}
}

View file

@ -282,7 +282,8 @@ class ModuleProperty extends ModuleORM
$oValueType->setValue($oValueType->getValueForValidate());
$aPropertiesResult[$oProperty->getId()] = $oProperty;
} else {
return 'Поле "' . $oProperty->getTitle() . '": ' . ($sRes ? $sRes : 'неверное значение');
return $this->Lang_Get('property.notices.validate_value_wrong',
array('field' => $oProperty->getTitle())) . ($sRes ? $sRes : $this->Lang_Get('property.notices.validate_value_wrong_base'));
}
}
$oTarget->setPropertiesObject($aPropertiesResult);
@ -871,7 +872,7 @@ class ModuleProperty extends ModuleORM
if ($oProperty->Add()) {
return $oProperty;
} else {
return 'Возникла ошибка при добавлении поля';
return $this->Lang_Get('property.notices.create_error');
}
} else {
return $oProperty->_getValidateError();

View file

@ -68,14 +68,14 @@ class ModuleProperty_EntityProperty extends EntityORM
if ($this->Property_IsAllowPropertyType($this->getType())) {
return true;
}
return 'Неверный тип поля';
return $this->Lang_Get('property.notices.validate_type');
}
public function ValidateCheckCode()
{
if ($oProperty = $this->Property_GetPropertyByTargetTypeAndCode($this->getTargetType(), $this->getCode())) {
if ($this->getId() != $oProperty->getId()) {
return 'Код поля должен быть уникальным';
return $this->Lang_Get('property.notices.validate_code');
}
}
return true;

View file

@ -36,8 +36,7 @@ class ModuleProperty_EntityValueTypeDate extends ModuleProperty_EntityValueType
$oValue = $this->getValueObject();
$oProperty = $oValue->getProperty();
return $oValue->getValueDate() ? date($oProperty->getParam('format_out'),
strtotime($oValue->getValueDate())) : '';
return $oValue->getValueDate() ? $this->Viewer_GetDateFormat(strtotime($oValue->getValueDate()), $oProperty->getParam('format_out')) : '';
}
public function isEmpty()
@ -48,18 +47,23 @@ class ModuleProperty_EntityValueTypeDate extends ModuleProperty_EntityValueType
public function getValueForForm()
{
$oValue = $this->getValueObject();
$oProperty = $oValue->getProperty();
$sDate = $oValue->getValueDate();
$iTime = strtotime($sDate);
// TODO: нужен конвертор формата дат вида Y в yyyy для учета $this->sFormatDateInput
return $sDate ? date('d.m.Y', $iTime) . ($oProperty->getParam('use_time') ? date(' H:i', $iTime) : '') : '';
return $sDate ? date('d.m.Y', $iTime) : '';
}
public function getValueTimeForForm()
{
$oValue = $this->getValueObject();
$sDate = $oValue->getValueDate();
return $sDate ? date('H:i', strtotime($sDate)) : '';
}
public function validate()
{
/**
* Данные поступают ввиде массива array( 'date'=>'..', 'time' => array( 'h' => '..', 'm' => '..' ) )
* Данные поступают ввиде массива array( 'date'=>'..', 'time' => '..' )
*/
$aValue = $this->getValueForValidate();
$oValueObject = $this->getValueObject();
@ -69,7 +73,14 @@ class ModuleProperty_EntityValueTypeDate extends ModuleProperty_EntityValueType
* Формируем формат для валидации даты
* В инпуте дата идет в формате d.m.Y и плюс H:i если используется время
*/
$sFormatValidate = $oProperty->getParam('use_time') ? $this->sFormatDateTimeInput : $this->sFormatDateInput;
if ($oProperty->getParam('use_time')) {
$sFormatValidate = $this->sFormatDateTimeInput;
if (isset($aValue['time'])) {
$this->setValueForValidateDate($this->getValueForValidateDate() . ' ' . $aValue['time']);
}
} else {
$sFormatValidate = $this->sFormatDateInput;
}
$mRes = $this->validateStandart('date', array('format' => $sFormatValidate), 'value_for_validate_date');
if ($mRes === true) {
@ -83,7 +94,7 @@ class ModuleProperty_EntityValueTypeDate extends ModuleProperty_EntityValueType
*/
if ($oProperty->getValidateRuleOne('disallowFuture')) {
if ($sTimeFull > time()) {
return "{$oProperty->getTitle()}: дата не может быть в будущем";
return "{$oProperty->getTitle()}: " . $this->Lang_Get('property.notices.validate_value_date_future');
}
}
/**
@ -92,7 +103,7 @@ class ModuleProperty_EntityValueTypeDate extends ModuleProperty_EntityValueType
if ($oValueObject->_isNew() or strtotime($oValueObject->getValueDate()) != $sTimeFull) {
if ($oProperty->getValidateRuleOne('disallowPast')) {
if ($sTimeFull < time()) {
return "{$oProperty->getTitle()}: дата не может быть в прошлом";
return "{$oProperty->getTitle()}: " . $this->Lang_Get('property.notices.validate_value_date_past');
}
}
}

View file

@ -44,10 +44,10 @@ class ModuleProperty_EntityValueTypeFile extends ModuleProperty_EntityValueType
$oProperty = $oValue->getProperty();
$iPropertyId = $oProperty->getId();
$bNeedRemove=false;
$bNeedRemove = false;
$mValue = $this->getValueForValidate();
if (isset($mValue['remove']) and $mValue['remove']) {
$bNeedRemove=true;
$bNeedRemove = true;
$this->setValueForValidate(array('remove' => true));
}
@ -62,14 +62,14 @@ class ModuleProperty_EntityValueTypeFile extends ModuleProperty_EntityValueType
} elseif ($aFilePrev = $oValue->getDataOne('file') and isset($aFilePrev['path']) and !$bNeedRemove) {
return true;
} else {
return 'Необходимо выбрать файл';
return $this->Lang_Get('property.notices.validate_value_file_empty');
}
}
/**
* Проверяем на ошибки
*/
if ($sFileError and $sFileError != UPLOAD_ERR_NO_FILE) {
return "При загрузке файла возникла ошибка - {$sFileError}";
return $this->Lang_Get('property.notices.validate_value_file_upload') . " - {$sFileError}";
}
/**
* На корректность загрузки
@ -81,7 +81,7 @@ class ModuleProperty_EntityValueTypeFile extends ModuleProperty_EntityValueType
* На ограничение по размеру файла
*/
if ($iSizeKb = $oProperty->getValidateRuleOne('size_max') and $iSizeKb * 1024 < $sFileSize) {
return "Превышен размер файла, максимальный {$iSizeKb}Kb";
return $this->Lang_Get('property.notices.validate_value_file_size_max', array('size' => $iSizeKb));
}
/**
* На допустимые типы файлов
@ -91,7 +91,7 @@ class ModuleProperty_EntityValueTypeFile extends ModuleProperty_EntityValueType
return false;
}
if ($aTypes = $oProperty->getParam('types') and !in_array($aPath['extension'], $aTypes)) {
return 'Неверный тип файла, допустимы ' . join(', ', $aTypes);
return $this->Lang_Get('property.notices.validate_value_file_type', array('types' => join(', ', $aTypes)));
}
/**
* Пробрасываем данные по файлу
@ -257,7 +257,7 @@ class ModuleProperty_EntityValueTypeFile extends ModuleProperty_EntityValueType
public function getCountDownloads()
{
$aStats=$this->oValue->getDataOne('stats');
$aStats = $this->oValue->getDataOne('stats');
return isset($aStats['count_download']) ? $aStats['count_download'] : 0;
}

View file

@ -34,7 +34,7 @@ class ModuleProperty_EntityValueTypeImage extends ModuleProperty_EntityValueType
* Показываем превью, в качестве изображения берем первый ресайз из списка размеров
*/
if ($aFile = $this->oValue->getDataOne('file') and isset($aFile['path'])) {
return '<a href="'.$this->getImageWebPath().'" class="js-lbx"><img src="' . $this->getImageWebPath($this->getImageSizeFirst()) . '" /></a>';
return '<a href="' . $this->getImageWebPath() . '" class="js-lbx"><img src="' . $this->getImageWebPath($this->getImageSizeFirst()) . '" /></a>';
}
return $this->getFileFullName();
}
@ -73,19 +73,19 @@ class ModuleProperty_EntityValueTypeImage extends ModuleProperty_EntityValueType
$aValue = $this->getValueForValidate();
if (isset($aValue['tmp_name'])) {
if (!$aImageInfo = (@getimagesize($aValue['tmp_name']))) {
return 'Файл не является изображением';
return $this->Lang_Get('property.notices.validate_value_image_wrong');
}
/**
* Проверяем на максимальную ширину
*/
if ($iWMax = $oProperty->getValidateRuleOne('width_max') and $iWMax < $aImageInfo[0]) {
return 'Максимальная допустимая ширина изображения ' . $iWMax . 'px';
return $this->Lang_Get('property.notices.validate_value_image_width_max', array('size' => $iWMax));
}
/**
* Проверяем на максимальную высоту
*/
if ($iHMax = $oProperty->getValidateRuleOne('height_max') and $iHMax < $aImageInfo[1]) {
return 'Максимальная допустимая высота изображения ' . $iHMax . 'px';
return $this->Lang_Get('property.notices.validate_value_image_height_max', array('size' => $iHMax));
}
}

View file

@ -63,10 +63,10 @@ class ModuleProperty_EntityValueTypeSelect extends ModuleProperty_EntityValueTyp
if (is_array($iValue)) {
if ($oProperty->getValidateRuleOne('allowMany')) {
if ($oProperty->getValidateRuleOne('max') and count($iValue) > $oProperty->getValidateRuleOne('max')) {
return 'Максимально можно выбрать только ' . $oProperty->getValidateRuleOne('max') . ' элемента';
return $this->Lang_Get('property.notices.validate_value_select_max', array('count' => $oProperty->getValidateRuleOne('max')));
}
if ($oProperty->getValidateRuleOne('min') and count($iValue) < $oProperty->getValidateRuleOne('min')) {
return 'Минимально можно выбрать только ' . $oProperty->getValidateRuleOne('min') . ' элемента';
return $this->Lang_Get('property.notices.validate_value_select_min', array('count' => $oProperty->getValidateRuleOne('min')));
}
/**
* Для безопасности
@ -76,19 +76,19 @@ class ModuleProperty_EntityValueTypeSelect extends ModuleProperty_EntityValueTyp
$aValues[] = (int)$iV;
}
if (count($aValues) == count($this->Property_GetSelectItemsByFilter(array(
'property_id' => $oProperty->getId(),
'id in' => $aValues
)))
'property_id' => $oProperty->getId(),
'id in' => $aValues
)))
) {
$this->setValueForValidate($aValues);
return true;
} else {
return 'Проверьте корректность выбранных элементов';
return $this->Lang_Get('property.notices.validate_value_select_wrong');
}
} elseif (count($iValue) == 1) {
$iValue = (int)reset($iValue);
} else {
return 'Можно выбрать только один элемент';
return $this->Lang_Get('property.notices.validate_value_select_only_one');
}
}
/**
@ -113,9 +113,9 @@ class ModuleProperty_EntityValueTypeSelect extends ModuleProperty_EntityValueTyp
if ($mValue) {
if (is_array($mValue)) {
$aSelectItems = $this->Property_GetSelectItemsByFilter(array(
'property_id' => $oProperty->getId(),
'id in' => $mValue
));
'property_id' => $oProperty->getId(),
'id in' => $mValue
));
foreach ($aSelectItems as $oSelect) {
$aValues[$oSelect->getId()] = $oSelect->getValue();
}
@ -168,9 +168,9 @@ class ModuleProperty_EntityValueTypeSelect extends ModuleProperty_EntityValueTyp
* Удаляем значения select'а из дополнительной таблицы
*/
if ($aSelects = $this->Property_GetValueSelectItemsByFilter(array(
'property_id' => $oValue->getPropertyId(),
'target_id' => $oValue->getTargetId()
))
'property_id' => $oValue->getPropertyId(),
'target_id' => $oValue->getTargetId()
))
) {
foreach ($aSelects as $oSelect) {
$oSelect->Delete();

View file

@ -45,7 +45,7 @@ class ModuleProperty_EntityValueTypeVideoLink extends ModuleProperty_EntityValue
* Теперь проверяем на принадлежность к разным видео-хостингам
*/
if ($this->getValueForValidate() and !$this->checkVideo($this->getValueForValidate())) {
return 'Необходимо указать корректную ссылку на видео: YouTube, Vimeo';
return $this->Lang_Get('property.notices.validate_value_video_wrong');
}
return true;
} else {

View file

@ -215,7 +215,7 @@ class ModuleRbac extends ModuleORM
/**
* Дефолтное сообщение об ошибке
*/
$sMsg = 'У вас нет прав на "' . $sPermissionCode . '"';
$sMsg = $this->Lang_Get('rbac.notices.error_not_allow', array('permission' => $sPermissionCode));
/**
* Проверяем результат кастомной обработки
*/
@ -235,7 +235,7 @@ class ModuleRbac extends ModuleORM
if ($aPerm['msg_error']) {
$sMsg = $this->Lang_Get($aPerm['msg_error']);
} else {
$sMsg = 'У вас нет прав на "' . ($aPerm['title'] ? $aPerm['title'] : $aPerm['code']) . '"';
$sMsg = $this->Lang_Get('rbac.notices.error_not_allow', array('permission' => $aPerm['title'] ? $aPerm['title'] : $aPerm['code']));
}
}
}

View file

@ -55,7 +55,7 @@ class ModuleRbac_EntityGroup extends EntityORM
{
if ($oObject = $this->Rbac_GetGroupByCode($this->getCode())) {
if ($this->getId() != $oObject->getId()) {
return 'Код должен быть уникальным';
return $this->Lang_Get('rbac.notices.validate_group_code');
}
}
return true;

View file

@ -67,7 +67,7 @@ class ModuleRbac_EntityPermission extends EntityORM
if ($oObject = $this->Rbac_GetGroupById($this->getGroupId())) {
$this->setGroupId($oObject->getId());
} else {
return 'Неверная группа';
return $this->Lang_Get('rbac.notices.validate_group_wrong');
}
} else {
$this->setGroupId(null);
@ -85,7 +85,7 @@ class ModuleRbac_EntityPermission extends EntityORM
$sPlugin = $this->getPlugin() ? $this->getPlugin() : '';
if ($oObject = $this->Rbac_GetPermissionByCodeAndPlugin($this->getCode(), $sPlugin)) {
if ($this->getId() != $oObject->getId()) {
return 'Код должен быть уникальным';
return $this->Lang_Get('rbac.notices.validate_permission_code');
}
}
return true;

View file

@ -110,7 +110,7 @@ class ModuleRbac_EntityRole extends EntityORM
{
if ($oObject = $this->Rbac_GetRoleByCode($this->getCode())) {
if ($this->getId() != $oObject->getId()) {
return 'Код должен быть уникальным';
return $this->Lang_Get('rbac.notices.validate_role_code');
}
}
return true;
@ -128,10 +128,10 @@ class ModuleRbac_EntityRole extends EntityORM
if ($this->getPid()) {
if ($oRole = $this->Rbac_GetRoleById($this->getPid())) {
if ($oRole->getId() == $this->getId()) {
return 'Попытка вложить роль в саму себя';
return $this->Lang_Get('rbac.notices.validate_role_recursive');
}
} else {
return 'Неверная роль';
return $this->Lang_Get('rbac.notices.validate_role_wrong');
}
} else {
$this->setPid(null);

View file

@ -47,6 +47,7 @@ class ModuleTopic_EntityTopicType extends Entity
$aParamsResult['allow_preview'] = (isset($aParams['allow_preview']) and $aParams['allow_preview']) ? true : false;
$aParamsResult['allow_text'] = (isset($aParams['allow_text']) and $aParams['allow_text']) ? true : false;
$aParamsResult['allow_tags'] = (isset($aParams['allow_tags']) and $aParams['allow_tags']) ? true : false;
$aParamsResult['css_icon'] = (isset($aParams['css_icon']) and is_string($aParams['css_icon']) and $aParams['css_icon']) ? htmlspecialchars($aParams['css_icon']) : null;
$this->setParams($aParamsResult);
return true;
@ -68,7 +69,7 @@ class ModuleTopic_EntityTopicType extends Entity
{
if ($oType = $this->Topic_GetTopicTypeByCode($this->getCode())) {
if ($oType->getId() != $this->getId()) {
return 'Тип с таким кодом уже существует';
return $this->Lang_Get('topic.content_type.notices.error_code');
}
}
return true;
@ -102,24 +103,25 @@ class ModuleTopic_EntityTopicType extends Entity
* Возвращает конкретный параметр типа
*
* @param string $sName
* @param mixed $mDefault
*
* @return null
*/
public function getParam($sName)
public function getParam($sName, $mDefault = null)
{
$aParams = $this->getParamsArray();
return isset($aParams[$sName]) ? $aParams[$sName] : null;
return isset($aParams[$sName]) ? $aParams[$sName] : $mDefault;
}
public function getStateText()
{
if ($this->getState() == ModuleTopic::TOPIC_TYPE_STATE_ACTIVE) {
return 'активен';
return $this->Lang_Get('topic.content_type.states.active');
}
if ($this->getState() == ModuleTopic::TOPIC_TYPE_STATE_NOT_ACTIVE) {
return 'не активен';
return $this->Lang_Get('topic.content_type.states.not_active');
}
return 'неизвестный статус';
return $this->Lang_Get('topic.content_type.states.wrong');
}
public function getUrlForAdd()

View file

@ -1406,7 +1406,7 @@ class ModuleUser extends Module
$charset = Config::Get('module.user.login.charset');
$min = Config::Get('module.user.login.min_size');
$max = Config::Get('module.user.login.max_size');
if (preg_match('/^[' . $charset . ']{' . $min . ',' . $max . '}$/i', $sLogin)) {
if (preg_match('/^[' . $charset . ']{' . $min . ',' . $max . '}$/ui', $sLogin)) {
return true;
}
return false;
@ -1951,4 +1951,38 @@ class ModuleUser extends Module
)
);
}
/**
* Генерация хеша пароля
*
* @param $sPassword
* @return string
*/
public function MakeHashPassword($sPassword)
{
return func_encrypt($sPassword);
}
/**
* Проверка пароля
*
* @param $sPassword
* @param $sHash
* @return string
*/
public function VerifyPassword($sPassword, $sHash)
{
return $this->MakeHashPassword($sPassword) == $sHash;
}
/**
* Проверка доступа к авторизации
*
* @param $oUser
* @return bool
*/
public function VerifyAccessAuth($oUser)
{
return true;
}
}

View file

@ -486,7 +486,7 @@ class ModuleUser_EntityUser extends Entity
if ($this->getProfileAvatar()) {
return $this->Media_GetImageWebPath($this->getProfileAvatar(), $iSize);
} else {
return $this->Media_GetImagePathBySize(Config::Get('path.skin.assets.web') . '/images/avatars/avatar_' . ($this->getProfileSex() == 'woman' ? 'female' : 'male') . '.png',
return $this->Media_GetImagePathBySize(Router::GetFixPathWeb(Config::Get('path.skin.assets.web')) . '/images/avatars/avatar_' . ($this->getProfileSex() == 'woman' ? 'female' : 'male') . '.png',
$iSize);
}
}
@ -528,7 +528,7 @@ class ModuleUser_EntityUser extends Entity
*/
public function getProfileFotoDefault()
{
return Config::Get('path.skin.assets.web') . '/images/avatars/user_photo_' . ($this->getProfileSex() == 'woman' ? 'female' : 'male') . '.png';
return Router::GetFixPathWeb(Config::Get('path.skin.assets.web')) . '/images/avatars/user_photo_' . ($this->getProfileSex() == 'woman' ? 'female' : 'male') . '.png';
}
/**
@ -646,6 +646,17 @@ class ModuleUser_EntityUser extends Entity
return false;
}
/**
* Проверка пароля
*
* @param $sPassword
* @return string
*/
public function verifyPassword($sPassword)
{
return $this->User_VerifyPassword($sPassword, $this->getPassword());
}
/**
* Устанавливает ID пользователя

View file

@ -16,4 +16,18 @@ $config['db']['params']['type'] = 'mysqli';
$config['db']['params']['dbname'] = 'social';
$config['db']['table']['prefix'] = 'prefix_';
/**
* Настройки кеширования
*/
$config['sys']['cache']['use'] = false; // использовать кеширование или нет
$config['sys']['cache']['type'] = 'file'; // тип кеширования: file, xcache и memory. memory использует мемкеш, xcache - использует XCache
/**
* Параметры обработки css/js-файлов
*/
$config['module']['asset']['force_https'] = true; // При использовании https принудительно заменять http на https у путях до css/js
$config['module']['asset']['css']['merge'] = true; // указывает на необходимость слияния css файлов
$config['module']['asset']['js']['merge'] = true; // указывает на необходимость слияния js файлов
return $config;

View file

@ -21,7 +21,7 @@
* Ничего не изменяйте в этом файле!
* Все изменения нужно вносить в файл config/config.local.php
*/
define('LS_VERSION', '2.0.0.alfa-2');
define('LS_VERSION', '2.0.0');
/**
* Основные настройки путей
@ -333,6 +333,12 @@ $config['module']['validate']['recaptcha']= array(
'secret_key' => '', // Секретный ключ
'use_ip' => false, // Использовать при валидации IP адрес клиента
);
/**
* Модель Component
*/
$config['module']['component']['cache_tree'] = true; // кешировать или нет построение дерева компонентов
$config['module']['component']['cache_data'] = true; // кешировать или нет данные компонентов
// Какие модули должны быть загружены на старте
$config['module']['autoLoad'] = array('Hook', 'Cache', 'Logger', 'Security', 'Session', 'Lang', 'Message', 'User');
@ -567,11 +573,6 @@ if ( $config['view']['rtl'] ) {
//$config['head']['default']['css'][] = "___path.skin.web___/components/alert/css/alert-rtl.css";
}
// Подключение темы
if ( $config['view']['theme'] ) {
$config['head']['default']['css'][] = "___path.skin.web___/themes/___view.theme___/style.css";
}
/**
* Установка локали
*/

View file

@ -0,0 +1,5 @@
Options -Indexes
<Files ~ "(\.tpl)|(\.php)$">
Order allow,deny
Deny from all
</Files>

View file

@ -34,7 +34,7 @@
{component 'field' template='text'
name = 'password_confirm'
type = 'password'
rules = [ 'required' => true, 'minlength' => '5', 'equalto' => '.js-input-password-reg' ]
rules = [ 'required' => true, 'minlength' => '5', 'equalto' => '.js-input-password-reg', 'equalto-message' => {lang 'auth.registration.notices.error_password_equal'} ]
label = $aLang.auth.registration.form.fields.password_confirm.label}
{* Каптча *}

View file

@ -5,11 +5,12 @@
*}
{$component = 'ls-comment-list'}
{component_define_params params=[ 'comments', 'mods', 'classes', 'attributes' ]}
{component_define_params params=[ 'hookPrefixComment', 'comments', 'mods', 'classes', 'attributes' ]}
{if $comments}
<div class="{$component} {cmods name=$component mods=$mods} {$classes}" {cattr list=$attributes}>
{component 'comment' template='tree'
hookPrefixComment = $hookPrefixComment
comments = $comments
forbidAdd = true
maxLevel = 0

View file

@ -13,7 +13,7 @@
* @param boolean $forbidAdd
*}
{component_define_params params=[ 'authorId', 'authorText', 'commentParams', 'comments', 'dateReadLast', 'forbidAdd', 'maxLevel', 'showReply' ]}
{component_define_params params=[ 'hookPrefixComment', 'authorId', 'authorText', 'commentParams', 'comments', 'dateReadLast', 'forbidAdd', 'maxLevel', 'showReply' ]}
{* Текущая вложенность *}
{$currentLevel = -1}
@ -39,6 +39,7 @@
{* Комментарий *}
{block 'comment_tree_comment'}
{component 'comment'
hookPrefix = $hookPrefixComment
comment = $comment
dateReadLast = $dateReadLast
authorId = $authorId

View file

@ -17,11 +17,11 @@
{* Название компонента *}
{$component = 'ls-comment'}
{component_define_params params=[ 'dateReadLast', 'showPath', 'showReply', 'authorId', 'comment', 'useFavourite', 'useScroll', 'useVote', 'useEdit', 'mods', 'classes', 'attributes' ]}
{component_define_params params=[ 'hookPrefix', 'dateReadLast', 'showPath', 'showReply', 'authorId', 'comment', 'useFavourite', 'useScroll', 'useVote', 'useEdit', 'mods', 'classes', 'attributes' ]}
{* Переменные *}
{$useEdit = $useEdit|default:true}
{$hookPrefix = $hookPrefix|default:'comment'}
{$isDeleted = $comment->getDelete()}
{$user = $comment->getUser()}
{$commentId = $comment->getId()}
@ -69,7 +69,7 @@
data-parent-id = "{$comment->getPid()}"
{cattr list=$attributes}>
{* @hook Начало комментария *}
{hook run='comment_comment_begin' params=$params}
{hook run="{$hookPrefix}_comment_begin" params=$params}
{* Путь до комментария *}
{if $showPath}
@ -96,7 +96,7 @@
{* Информация *}
<ul class="{$component}-info ls-clearfix">
{* @hook Начало блока с информацией *}
{hook run='comment_info_begin' params=$params}
{hook run="{$hookPrefix}_info_begin" params=$params}
{* Автор комментария *}
{component 'comment.info-item'
@ -138,20 +138,20 @@
{/if}
{* @hook Конец блока с информацией *}
{hook run='comment_info_end' params=$params}
{hook run="{$hookPrefix}_info_end" params=$params}
</ul>
{* Текст комментария *}
<div class="{$component}-content">
{* @hook Начало блока с содержимым комментария *}
{hook run='comment_content_begin' params=$params}
{hook run="{$hookPrefix}_content_begin" params=$params}
<div class="{$component}-text ls-text">
{$comment->getText()}
</div>
{* @hook Конец блока с содержимым комментария *}
{hook run='comment_content_end' params=$params}
{hook run="{$hookPrefix}_content_end" params=$params}
</div>
{* Информация о редактировании *}
@ -172,33 +172,36 @@
{* Действия *}
<ul class="{$component}-actions ls-clearfix">
{* @hook Начало списка экшенов комментария *}
{hook run='comment_actions_begin' params=$params}
{hook run="{$hookPrefix}_actions_begin" params=$params}
{* Ответить *}
{if $oUserCurrent && ! $isDeleted && $showReply|default:true}
<li>
<a href="#" class="ls-link-dotted js-comment-reply" data-id="{$commentId}">{$aLang.comments.comment.reply}</a>
</li>
{component 'comment.actions-item'
link=[ classes => 'js-comment-reply', attributes => [ 'data-id' => $commentId ] ]
text=$aLang.comments.comment.reply}
{/if}
{* Сворачивание *}
<li class="{$component}-fold js-comment-fold open" data-id="{$commentId}">
<a href="#" class="ls-link-dotted">{$aLang.comments.folding.fold}</a>
</li>
{component 'comment.actions-item'
classes="{$component}-fold open"
link=[ classes => 'js-comment-fold', attributes => [ 'data-id' => $commentId ] ]
text=$aLang.comments.folding.fold}
{* Редактировать *}
{if $useEdit && $oUserCurrent && $comment->IsAllowEdit()}
<li>
<a href="#" class="ls-link-dotted js-comment-update" data-id="{$commentId}">
{$aLang.common.edit}
{capture assign="ls_comment_edit_text"}
{$aLang.common.edit}
{* Отображение времени отведенного для редактирования *}
{* Используется плагин jquery.timers *}
{if $comment->getEditTimeRemaining()}
(<span class="js-comment-update-timer" data-seconds="{$comment->getEditTimeRemaining()}">...</span>)
{/if}
</a>
</li>
{* Отображение времени отведенного для редактирования *}
{* Используется плагин jquery.timers *}
{if $comment->getEditTimeRemaining()}
(<span class="js-comment-update-timer" data-seconds="{$comment->getEditTimeRemaining()}">...</span>)
{/if}
{/capture}
{component 'comment.actions-item'
link=[ classes => 'js-comment-update', attributes => [ 'data-id' => $commentId ] ]
text=$ls_comment_edit_text}
{/if}
{* Удалить *}
@ -209,12 +212,12 @@
{/if}
{* @hook Конец списка экшенов комментария *}
{hook run='comment_actions_end' params=$params}
{hook run="{$hookPrefix}_actions_end" params=$params}
</ul>
{else}
{$aLang.comments.comment.deleted}
{/if}
{* @hook Конец комментария *}
{hook run='comment_comment_end' params=$params}
{hook run="{$hookPrefix}_comment_end" params=$params}
</section>

View file

@ -28,13 +28,14 @@
*}
{$component = 'ls-comments'}
{component_define_params params=[ 'addCommentText', 'authorId', 'authorText', 'commentParams', 'comments', 'count', 'dateReadLast', 'forbidAdd',
{component_define_params params=[ 'hookPrefix', 'hookPrefixComment', 'addCommentText', 'authorId', 'authorText', 'commentParams', 'comments', 'count', 'dateReadLast', 'forbidAdd',
'forbidText', 'isSubscribed', 'lastCommentId', 'maxLevel', 'pagination', 'targetId', 'targetType', 'title', 'titleNoComments',
'useSubscribe', 'mods', 'classes', 'attributes' ]}
{block 'comment-list-options'}
{* Максимальная вложенность *}
{$maxLevel = $maxLevel|default:Config::Get('module.comment.max_tree')}
{$hookPrefix = $hookPrefix|default:'comments'}
{if $forbidAdd}
{$mods = "$mods forbid"}
@ -52,7 +53,7 @@
{cattr list=$attributes}>
{* @hook Начало блока с комментариями *}
{hook run='comments_begin' params=$params}
{hook run="{$hookPrefix}_begin" params=$params}
{**
* Заголовок
@ -67,7 +68,7 @@
</h3>
{* @hook Конец шапки *}
{hook run='comments_header_end' params=$params}
{hook run="{$hookPrefix}_header_end" params=$params}
</header>
@ -99,7 +100,7 @@
{/if}
{* @hook Хук перед списком комментариев *}
{hook run='comments_list_before' params=$params}
{hook run="{$hookPrefix}_list_before" params=$params}
{**
* Комментарии
@ -108,15 +109,17 @@
{component 'comment' template='tree'
comments = $comments
forbidAdd = $forbidAdd
forbidAdd = $forbidAdd
maxLevel = $maxLevel
authorId = $authorId
authorText = $authorText
dateReadLast = $dateReadLast
commentParams = $commentParams}
commentParams = $commentParams
hookPrefixComment = $hookPrefixComment}
</div>
{* @hook Хук после списка комментариев *}
{hook run='comments_list_after' params=$params}
{hook run="{$hookPrefix}_list_after" params=$params}
{**
@ -151,5 +154,5 @@
{/if}
{* @hook Конец блока с комментариями *}
{hook run='comments_end' params=$params}
{hook run="{$hookPrefix}_end" params=$params}
</div>

View file

@ -4,22 +4,10 @@
* @template toolbar.comment.tpl
*/
.ls-toolbar-item--comments .ls-toolbar-comments-count {
border-top: 1px solid #eee;
padding: 10px 0;
.ls-toolbar-item--comments .ls-comments-toolbar-count {
margin-top: 5px;
color: #333;
text-align: center;
font-size: 11px;
cursor: pointer;
}
.ls-toolbar-comments-update i {
-webkit-transition: -webkit-transform 1s;
transition: transform 1s;
}
.ls-toolbar-comments-update.active i {
-ms-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}

View file

@ -88,7 +88,7 @@
// Сворчивание
if ( this.options.folding ) {
if ( this.hasChildren() ) this.elements.fold.show();
if ( this.hasChildren() ) this.elements.fold.parent().show();
this.elements.fold.on( 'click' + this.eventNamespace, this.foldToggle.bind( this ) );
}
@ -252,14 +252,14 @@
* Коллбэк вызываемый после сворачивания ветки комментариев
*/
onFold: function() {
this.elements.fold.find('a').text(this._i18n('unfold'));
this.elements.fold.text(this._i18n('unfold'));
},
/**
* Коллбэк вызываемый после разворачивания ветки комментариев
*/
onUnfold: function() {
this.elements.fold.find('a').text(this._i18n('fold'));
this.elements.fold.text(this._i18n('fold'));
},
/**

View file

@ -29,7 +29,7 @@
counter: '.js-toolbar-comments-count',
// Иконка
icon: '.ls-toolbar-comments-update .fa'
icon: '.js-toolbar-comments-update .fa'
},
classes: {
@ -99,14 +99,14 @@
showCounter: function() {
if ( this.elements.counter.is( ':visible' ) ) return;
this.element.append( this.elements.counter.show() );
this.elements.counter.show();
},
/**
* Скрывает счетчик
*/
hideCounter: function() {
this.elements.counter.hide().detach();
this.elements.counter.hide();
},
/**

View file

@ -3,20 +3,14 @@
* Кнопка обновления комментариев
*}
{component_define_params params=[ 'mods', 'classes', 'attributes' ]}
{capture toolbar_comments}
<div class="ls-comments-toolbar-update js-toolbar-comments-update" title="{lang 'comments.update'}">
{component 'icon' icon='refresh'}
</div>
<div class="ls-comments-toolbar-count js-toolbar-comments-count" title="{lang 'comments.count_new'}">0</div>
{/capture}
{component 'toolbar' template='item'
classes = "{$classes} js-comments-toolbar"
mods = 'comments'
buttons = [
[
classes => 'ls-toolbar-comments-update js-toolbar-comments-update',
attributes => [ 'title' => {lang 'comments.update'} ],
icon => 'refresh'
],
[
classes => 'js-toolbar-comments-count',
attributes => [ 'title' => {lang 'comments.count_new'} ],
text => '0'
]
]}
{component 'toolbar.item'
html=$smarty.capture.toolbar_comments
classes='js-comments-toolbar'
mods='comments'}

View file

@ -1,6 +1,23 @@
{component 'field.date'
{$_mods=''}
{$desc = $property->getDescription()}
{if $property->getParam('use_time')}
{$_mods='inline'}
{/if}
{component 'field.date' mods = $_mods
name = "property[{$property->getId()}][date]"
inputClasses = "js-field-{$template}-default"
inputAttributes=[ "data-lsdate-format" => 'DD.MM.YYYY' ]
inputClasses = "js-field-date-default"
value = $property->getValue()->getValueForForm()
note = $property->getDescription()
label = $property->getTitle()}
note = $desc
label = $property->getTitle()}
{if $property->getParam('use_time')}
{component 'field.time' mods = $_mods
name = "property[{$property->getId()}][time]"
inputAttributes=[ "data-lstime-time-format" => 'H:i' ]
inputClasses = "js-field-time-default"
note = ($desc) ? '&nbsp;' : ''
value = $property->getValue()->getValueTypeObject()->getValueTimeForForm()}
{/if}

View file

@ -3,6 +3,7 @@
name = "property[{$property->getId()}]"
value = $property->getValue()->getValueForForm()
label = $property->getTitle()
escape = false
inputClasses = 'js-editor-default' }
{else}
@ -10,6 +11,7 @@
name = "property[{$property->getId()}]"
value = $property->getValue()->getValueForForm()
rows = 10
escape = false
note = $property->getDescription()
label = $property->getTitle()}
{/if}

View file

@ -3,7 +3,7 @@
{$property->getTitle()}
</div>
<strong class="ls-property-list-item-content">
<div class="ls-property-list-item-content">
{$property->getValue()->getValueForDisplay()}
</strong>
</div>
</div>

View file

@ -11,9 +11,9 @@
{* Получатели *}
{component 'user' template='choose'
items = ($recepient) ? [[ 'text' => $recepient->getLogin(), 'value' => $recepient->getId() ]] : false
items = ($recepient) ? [[ 'text' => $recepient->getLogin(), 'value' => $recepient->getId() ]] : false
selectedValue = ($recepient) ? $recepient->getId() : false
form = ($_aRequest['talk_recepient_id']) ? false : $_aRequest
form = ($recepient) ? false : $_aRequest
name = 'talk_users[]'
rules = [ 'required' => true ]
classes = 'js-talk-add-user-choose'
@ -29,7 +29,7 @@
{* Текст сообщения *}
{component 'editor'
sSet = 'light'
sMediaTargetType = 'talk'
mediaTargetType = 'talk'
id = 'talk_text'
name = 'talk_text'
rules = [ 'required' => true, 'length' => '[2,3000]' ]

View file

@ -71,7 +71,7 @@
{* Участники диалога *}
{if $usersCount > 2}
<a href="{router page='talk'}read/{$talk->getId()}/" class="talk-list-item-info-avatar">
<img src="{Config::Get('path.skin.web')}/assets/images/avatars/avatar_male_64x64crop.png" />
<img src="{cfg name='path.skin.web'}/assets/images/avatars/avatar_male_64x64crop.png" />
</a>
{lang name='talk.participants' count=$usersCount plural=true}

View file

@ -45,10 +45,10 @@
{/if}
{/if}
{component 'field' template='select'
{component 'field.autocomplete'
label = $aLang.topic.add.fields.blog.label
name = ''
placeholder = 'Выберите блоги для публикации'
placeholder = $aLang.topic.add.fields.blog.placeholder
inputClasses = 'js-topic-add-blogs'
isMultiple = true
selectedValue = $blogsSelectedId

View file

@ -60,11 +60,11 @@
{capture 'info_private_geo'}
<span itemprop="address" itemscope itemtype="http://data-vocabulary.org/Address">
{if $geoTarget->getCountryId()}
<a href="{router page='people'}country/{$geoTarget->getCountryId()}/" itemprop="country-name">{$user->getProfileCountry()|escape}</a>{if $geoTarget->getCityId()},{/if}
<span itemprop="country-name">{$user->getProfileCountry()|escape}</span>{if $geoTarget->getCityId()},{/if}
{/if}
{if $geoTarget->getCityId()}
<a href="{router page='people'}city/{$geoTarget->getCityId()}/" itemprop="locality">{$user->getProfileCity()|escape}</a>
<span itemprop="locality">{$user->getProfileCity()|escape}</span>
{/if}
</span>
{/capture}

View file

@ -61,7 +61,7 @@
{component 'field' template='date'
name = 'profile_birthday'
inputClasses = 'js-field-date-default'
value = {date_format date=$user->getProfileBirthday() format='j.n.Y'}
value = ($user->getProfileBirthday()) ? {date_format date=$user->getProfileBirthday() format='d.m.Y' notz=true} : ''
label = {lang name='user.settings.profile.fields.birthday.label'}}

View file

@ -17,7 +17,7 @@
</a>
{/capture}
{component 'field' template='select'
{component 'field.autocomplete'
label = $label
name = $name
inputClasses = 'js-user-field-choose-users'

View file

@ -18,9 +18,9 @@
{$createMenu[] = [ 'name' => $type->getCode(), 'text' => $type->getName(), 'url' => $type->getUrlForAdd() ]}
{/foreach}
{$createMenu[] = [ 'name' => 'blog', 'text' => {lang 'modal_create.items.blog'}, 'url' => {router page='blog'} ]}
{$createMenu[] = [ 'name' => 'talk', 'text' => {lang 'modal_create.items.talk'}, 'url' => {router page='talk'} ]}
{$createMenu[] = [ 'name' => 'drafts', 'text' => {lang 'topic.drafts'}, 'url' => "{router page='content'}drafts/", count => $iUserCurrentCountTopicDraft ]}
{$createMenu[] = [ 'name' => 'blog', 'text' => {lang 'modal_create.items.blog'}, 'url' => {router page='blog/add'} ]}
{$createMenu[] = [ 'name' => 'talk', 'text' => {lang 'modal_create.items.talk'}, 'url' => {router page='talk/add'} ]}
{$createMenu[] = [ 'name' => 'drafts', 'text' => {lang 'topic.drafts'}, 'url' => "{router page='content/drafts'}", count => $iUserCurrentCountTopicDraft ]}
{$items = [
[
@ -57,4 +57,4 @@
{component 'search' template='main' mods='light'}
</div>
</div>
</div>

View file

@ -9,6 +9,7 @@
{component_define_params params=[ 'entry', 'type', 'showReply', 'classes' ]}
{component 'comment'
hookPrefix = 'wall_entry'
comment = $entry
showReply = $showReply
useScroll = false

File diff suppressed because it is too large Load diff

View file

@ -24,7 +24,7 @@ return array(
/**
* Голосование
*/
'vote' => array(
'vote' => array(
'up' => 'Нравится',
'down' => 'Не нравится',
'abstain' => 'Воздержаться от голосования и посмотреть рейтинг',
@ -44,7 +44,7 @@ return array(
/**
* Избранное
*/
'favourite' => array(
'favourite' => array(
'favourite' => 'Избранное',
'add' => 'Добавить в избранное',
'remove' => 'Удалить из избранного',
@ -59,7 +59,7 @@ return array(
/**
* Поиск
*/
'search' => array(
'search' => array(
'search' => 'Поиск',
'find' => 'Найти',
'result' => array(
@ -75,7 +75,7 @@ return array(
/**
* Сортировка
*/
'sort' => array(
'sort' => array(
'label' => 'Сортировать',
'by_login' => 'по логину',
'by_name' => 'по имени',
@ -87,7 +87,7 @@ return array(
/**
* Заметка пользователя
*/
'user_note' => array(
'user_note' => array(
'add' => 'Написать заметку',
// Всплывающие сообщения
'notices' => array(
@ -97,7 +97,7 @@ return array(
/**
* Блог
*/
'blog' => array(
'blog' => array(
'blog' => 'Блог',
'blogs' => 'Блоги',
'readers_declension' => 'читатель;читателя;читателей',
@ -135,15 +135,15 @@ return array(
'search' => array(
'placeholder' => 'Поиск по названию',
'result_title' => 'Найден %%count%% блог;Найдено %%count%% блога;Найдено %%count%% блогов',
'form' => array(
'type' => array(
'any' => 'Любой',
'public' => 'Открытый',
'form' => array(
'type' => array(
'any' => 'Любой',
'public' => 'Открытый',
'private' => 'Закрытый'
),
'relation' => array(
'all' => 'Все',
'my' => 'Мои',
'all' => 'Все',
'my' => 'Мои',
'joined' => 'Читаю'
)
)
@ -223,7 +223,7 @@ return array(
'label' => 'Аватар',
'error' => 'Не удалось загрузить аватар',
),
'skip_index' => array(
'skip_index' => array(
'label' => 'Не выводить топики на главную',
'note' => 'Все топики из этого блога не смогут попадать на главную страницу',
),
@ -381,7 +381,7 @@ return array(
/**
* Личные сообщения
*/
'talk' => array(
'talk' => array(
'title' => 'Сообщения',
'participants' => '%%count%% участник;%%count%% участника;%%count%% участников',
'new_messages' => 'У вас есть новые сообщения',
@ -485,7 +485,7 @@ return array(
'title' => 'Участники разговора',
'inactive' => 'Пользователь не участвует в разговоре',
// Сообщения
'notices' => array(
'notices' => array(
'user_not_found' => 'Пользователь <b>%%login%%</b> не участвует в разговоре',
'deleted' => 'Участник <b>%%login%%</b> удалил этот разговор',
)
@ -501,7 +501,7 @@ return array(
/**
* Опросы
*/
'poll' => array(
'poll' => array(
'polls' => 'Опросы',
'vote' => 'Голосовать',
'abstain' => 'Воздержаться',
@ -533,13 +533,22 @@ return array(
),
// Всплывающие сообщения
'notices' => array(
'error_answers_max' => 'Максимально возможное число вариантов ответа %%count%%',
'error_answers_max' => 'Максимально возможное число вариантов ответа %%count%%',
'error_not_allow_vote' => 'В этом опросе уже нельзя голосовать',
'error_not_allow_remove' => 'Этот опрос уже нельзя удалить',
'error_already_vote' => 'Вы уже голосовали',
'error_no_answers' => 'Необходимо выбрать вариант',
'error_answers_max_wrong' => 'Максимальное количество вариантов ответа должно быть больше одного',
'error_answers_count' => 'Необходимо заполнить больше одного варианта ответов',
'error_answer_remove' => 'Нельзя удалить вариант ответа, за который уже голосовали',
'error_target_type' => 'Неверный тип объекта',
'error_target_tmp' => 'Временный идентификатор уже занят',
),
),
/**
* Комментарии
*/
'comments' => array(
'comments' => array(
'comments_declension' => '%%count%% комментарий;%%count%% комментария;%%count%% комментариев',
'no_comments' => 'Нет комментариев',
'count_new' => 'Число новых комментариев',
@ -581,7 +590,7 @@ return array(
/**
* Пополняемый список пользователей
*/
'user_list_add' => array(
'user_list_add' => array(
// Форма добавления
'form' => array(
// Поля
@ -601,7 +610,7 @@ return array(
/**
* Мэйлы
*/
'emails' => array(
'emails' => array(
'common' => array(
'comment_text' => 'Текст комментария',
'regards' => 'С уважением, администрация сайта',
@ -789,7 +798,7 @@ return array(
/**
* Стена
*/
'wall' => array(
'wall' => array(
'title' => 'Стена',
// Форма
'form' => array(
@ -814,7 +823,7 @@ return array(
/**
* Авторизация
*/
'auth' => array(
'auth' => array(
'authorization' => 'Авторизация',
'logout' => 'Выйти',
// Вход
@ -922,14 +931,15 @@ return array(
),
// Сообщения
'notices' => array(
'already_registered' => 'Вы уже зарегистрированы у нас и даже авторизованы!',
'success' => 'Поздравляем! Регистрация прошла успешно',
'success_activate' => 'Поздравляем! Ваш аккаунт успешно активирован.',
'error_login' => 'Неверный логин, допустим от 3 до 30 символов',
'error_login_used' => 'Этот логин уже занят',
'error_mail_used' => 'Этот e-mail уже используется',
'error_reactivate' => 'Ваш аккаунт уже активирован',
'error_code' => 'Неверный код активации!'
'already_registered' => 'Вы уже зарегистрированы у нас и даже авторизованы!',
'success' => 'Поздравляем! Регистрация прошла успешно',
'success_activate' => 'Поздравляем! Ваш аккаунт успешно активирован.',
'error_login' => 'Неверный логин, допустим от 3 до 30 символов',
'error_login_used' => 'Этот логин уже занят',
'error_mail_used' => 'Этот e-mail уже используется',
'error_reactivate' => 'Ваш аккаунт уже активирован',
'error_code' => 'Неверный код активации!',
'error_password_equal' => 'Пароли не совпадают',
),
),
// Общие лэйблы
@ -947,7 +957,7 @@ return array(
/**
* Активность
*/
'activity' => array(
'activity' => array(
'title' => 'Активность',
// Навигация
'nav' => array(
@ -1017,7 +1027,7 @@ return array(
/**
* Лента
*/
'feed' => array(
'feed' => array(
'title' => 'Лента',
// Блоги
'blogs' => array(
@ -1034,7 +1044,7 @@ return array(
/**
* Топик
*/
'topic' => array(
'topic' => array(
'topics' => 'Топики',
'topic_plural' => 'топик;топика;топиков',
'drafts' => 'Черновики',
@ -1048,6 +1058,16 @@ return array(
'drafts' => 'Черновики', // TODO: Remove duplication
'published' => 'Опубликованные'
),
'content_type' => array(
'states' => array(
'active' => 'активен',
'not_active' => 'не активен',
'wrong' => 'неизвестный статус',
),
'notices' => array(
'error_code' => 'Тип с таким кодом уже существует',
),
),
// Форма добавления
'add' => array(
'title' => array(
@ -1058,6 +1078,7 @@ return array(
'fields' => array(
'blog' => array(
'label' => 'В какой блог публикуем?',
'placeholder' => 'Выберите блоги для публикации',
'note' => 'Для того чтобы написать в определенный блог, вы должны, для начала, вступить в него.',
'option_personal' => 'Мой персональный блог',
),
@ -1106,6 +1127,8 @@ return array(
'error_favourite_draft' => 'Топик из черновиков нельзя добавить в избранное',
'time_limit' => 'Вам нельзя создавать топики слишком часто',
'rating_limit' => 'Вам не хватает рейтинга для создания топика',
'update_complete' => 'Обновление прошло успешно',
'create_complete' => 'Добавление прошло успешно',
)
),
// Комментарии
@ -1131,7 +1154,7 @@ return array(
* Пользователь
* !user
*/
'user' => array(
'user' => array(
'user' => 'Пользователь',
'users' => 'Пользователи',
'rating' => '___vote.rating___',
@ -1145,7 +1168,7 @@ return array(
'report' => '___report.report___',
),
// Действия
'choose' => array(
'choose' => array(
'label' => '___user.users___',
'choose' => 'Выбрать из списка друзей',
),
@ -1236,11 +1259,11 @@ return array(
'title' => 'Поиск по пользователям',
'placeholder' => 'Поиск по логину',
'result_title' => 'Найден %%count%% пользователь;Найдено %%count%% пользователя;Найдено %%count%% пользователей',
'form' => array(
'form' => array(
'is_online' => 'Сейчас на сайте',
'gender' => array(
'any' => 'Любой',
'male' => 'Мужской',
'gender' => array(
'any' => 'Любой',
'male' => 'Мужской',
'female' => 'Женский'
)
)
@ -1455,7 +1478,7 @@ return array(
/**
* Поля
*/
'field' => array(
'field' => array(
'email' => array(
'label' => 'E-mail',
'notices' => array(
@ -1474,27 +1497,61 @@ return array(
'label' => 'Категория'
),
),
/**
* Категории
*/
'category' => array(
'notices' => array(
'validate_require' => 'Необходимо выбрать категорию',
'validate_count' => 'Количество категорий должно быть от %%min%% до %%max%%',
'validate_children' => 'Для выбора доступны только конечные категории',
'validate_recursion' => 'Попытка вложить категорию в саму себя',
'validate_parent' => 'Неверная родительская категория',
'validate_wrong' => 'Неверная категория',
),
),
/**
* Кастомные поля
*/
'property' => array(
'video' => array(
'property' => array(
'video' => array(
'preview' => 'Предпросмотр видео',
'watch' => 'Смотреть'
'watch' => 'Смотреть'
),
'image' => array(
'image' => array(
'empty' => 'Изображения нет'
),
'file' => array(
'file' => array(
'forbidden' => 'Для доступа к файлу необходимо авторизоваться',
'downloads' => 'Загрузок',
'empty' => 'Файла нет'
)
'empty' => 'Файла нет'
),
'notices' => array(
'validate_type' => 'Неверный тип поля',
'validate_code' => 'Код поля должен быть уникальным',
'validate_value_date_future' => 'дата не может быть в будущем',
'validate_value_date_past' => 'дата не может быть в прошлом',
'validate_value_file_empty' => 'Необходимо выбрать файл',
'validate_value_file_upload' => 'При загрузке файла возникла ошибка',
'validate_value_file_size_max' => 'Превышен размер файла, максимальный %%size%% Kb',
'validate_value_file_type' => 'Неверный тип файла, допустимы %%types%%',
'validate_value_image_wrong' => 'Файл не является изображением',
'validate_value_image_width_max' => 'Максимальная допустимая ширина изображения %%size%%px',
'validate_value_image_height_max' => 'Максимальная допустимая высота изображения %%size%%px',
'validate_value_select_max' => 'Максимально можно выбрать только %%count%% элемента',
'validate_value_select_min' => 'Минимально можно выбрать только %%count%% элемента',
'validate_value_select_wrong' => 'Проверьте корректность выбранных элементов',
'validate_value_select_only_one' => 'Можно выбрать только один элемент',
'validate_value_video_wrong' => 'Необходимо указать корректную ссылку на видео: YouTube, Vimeo',
'validate_value_wrong' => 'Поле "%%field%%": ',
'validate_value_wrong_base' => 'неверное значение',
'create_error' => 'Возникла ошибка при добавлении поля',
),
),
/**
* Админка
*/
'admin' => array(
'admin' => array(
'title' => 'Админка',
'items' => array(
'plugins' => '___admin.plugins.title___',
@ -1532,7 +1589,7 @@ return array(
/**
* Жалобы
*/
'report' => array(
'report' => array(
'report' => 'Пожаловаться',
'form' => array(
'title' => '___report.report___',
@ -1552,44 +1609,18 @@ return array(
'success' => 'Ваша жалоба отправлена администрации',
)
),
/**
* Загрузкчик файлов
*/
'uploader' => array(
'actions' => array(
'remove' => '___common.remove___'
),
'filter' => array(
'uploaded' => 'Загруженные',
'all' => 'Все'
),
'info' => array(
'empty' => 'Выберите файл',
'types' => array(
'image' => array(
'dimensions' => 'Разрешение',
'title' => 'Описание'
)
)
),
'attach' => array(
'title' => 'Прикрепить файлы',
'upload' => 'Загрузить',
'count' => '%%count%% файл загружен;%%count%% файла загружено;%%count%% файлов загружено',
'empty' => 'Нет загруженных файлов'
)
),
/**
* Загрузка изображений
*/
'media' => array(
'media' => array(
'title' => 'Загрузка медиа-файлов',
'error' => array(
'upload' => 'Не удалось загрузить файл',
'not_image' => 'Файл не является изображением',
'too_large' => 'Превышен максимальный размер файла: %%size%%Кб',
'incorrect_type' => 'Неверный тип файла',
'max_count_files' => 'Превышено максимальное число файлов',
'upload' => 'Не удалось загрузить файл',
'not_image' => 'Файл не является изображением',
'too_large' => 'Превышен максимальный размер файла: %%size%%Кб',
'incorrect_type' => 'Неверный тип файла',
'max_count_files' => 'Превышено максимальное число файлов',
'need_choose_items' => 'Необходимо выбрать элементы',
),
'nav' => array(
'insert' => 'Вставить',
@ -1646,7 +1677,7 @@ return array(
/**
* Теги
*/
'tags' => array(
'tags' => array(
'tags' => 'Теги',
'tag' => 'Тег',
'search' => array(
@ -1673,7 +1704,7 @@ return array(
/**
* Toolbar
*/
'toolbar' => array(
'toolbar' => array(
'scrollup' => array(
'title' => 'Вверх',
),
@ -1685,7 +1716,7 @@ return array(
/**
* Создание
*/
'modal_create' => array(
'modal_create' => array(
'title' => 'Создать',
'items' => array(
'blog' => 'Блог',
@ -1695,13 +1726,13 @@ return array(
/**
* Обрезка изображения
*/
'crop' => array(
'crop' => array(
'title' => 'Обрезка изображения'
),
/**
* Экшнбар
*/
'actionbar' => array(
'actionbar' => array(
'select' => array(
'title' => 'Выбрать',
'menu' => array(
@ -1714,7 +1745,7 @@ return array(
/**
* Управление правами (RBAC)
*/
'rbac' => array(
'rbac' => array(
'permission' => array(
'create_blog' => array(
'title' => 'Создание блога',
@ -1765,5 +1796,14 @@ return array(
'error' => 'У вас нет прав на голосования за топики',
),
),
'notices' => array(
'validate_group_code' => 'Код должен быть уникальным',
'validate_group_wrong' => 'Неверная группа',
'validate_permission_code' => 'Код должен быть уникальным',
'validate_role_code' => 'Код должен быть уникальным',
'validate_role_recursive' => 'Попытка вложить роль в саму себя',
'validate_role_wrong' => 'Неверная роль',
'error_not_allow' => 'У вас нет прав на "%%permission%%"',
),
),
);

View file

@ -31,6 +31,11 @@ $config['head']['template']['css'] = array(
"___path.skin.assets.web___/css/print.css"
);
// Подключение темы
if (Config::Get('view.theme')) {
$config['head']['template']['css'][] = "___path.skin.web___/themes/___view.theme___/style.css";
}
/**
* SEO
*/

View file

@ -7,6 +7,9 @@
*/
/* Основной блок */
.layout {
min-width: 960px;
}
.layout-container {
margin: 0 auto;
padding: 0 50px;

View file

@ -43,9 +43,9 @@
<h3>{lang 'blog.blocks.search.type.title'}</h3>
<div class="ls-field-checkbox-group">
{component 'field' template='radio' inputClasses='js-search-ajax-blog-type' name='blog_search_type' value='' label='Любой' checked=true}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-type' name='blog_search_type' value='open' label='Открытый'}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-type' name='blog_search_type' value='close' label='Закрытый'}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-type' name='blog_search_type' value='' label={lang 'blog.search.form.type.any'} checked=true}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-type' name='blog_search_type' value='open' label={lang 'blog.search.form.type.public'}}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-type' name='blog_search_type' value='close' label={lang 'blog.search.form.type.private'}}
</div>
{* Тип принадлежности блога *}
@ -53,9 +53,9 @@
<h3>{lang 'blog.blocks.search.relation.title'}</h3>
<div class="ls-field-checkbox-group">
{component 'field' template='radio' inputClasses='js-search-ajax-blog-relation' name='blog_search_relation' value='all' label='Все' checked=true}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-relation' name='blog_search_relation' value='my' label='Мои'}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-relation' name='blog_search_relation' value='join' label='Читаю'}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-relation' name='blog_search_relation' value='all' label={lang 'blog.search.form.relation.all'} checked=true}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-relation' name='blog_search_relation' value='my' label={lang 'blog.search.form.relation.my'}}
{component 'field' template='radio' inputClasses='js-search-ajax-blog-relation' name='blog_search_relation' value='join' label={lang 'blog.search.form.relation.joined'}}
</div>
{/if}

View file

@ -17,11 +17,11 @@
{* Название компонента *}
{$component = 'ls-comment'}
{component_define_params params=[ 'dateReadLast', 'showPath', 'showReply', 'authorId', 'comment', 'useFavourite', 'useScroll', 'useVote', 'useEdit', 'mods', 'classes', 'attributes' ]}
{component_define_params params=[ 'hookPrefix', 'dateReadLast', 'showPath', 'showReply', 'authorId', 'comment', 'useFavourite', 'useScroll', 'useVote', 'useEdit', 'mods', 'classes', 'attributes' ]}
{* Переменные *}
{$useEdit = $useEdit|default:true}
{$hookPrefix = $hookPrefix|default:'comment'}
{$isDeleted = $comment->getDelete()}
{$user = $comment->getUser()}
{$commentId = $comment->getId()}
@ -69,7 +69,7 @@
data-parent-id = "{$comment->getPid()}"
{cattr list=$attributes}>
{* @hook Начало комментария *}
{hook run='comment_comment_begin' params=$params}
{hook run="{$hookPrefix}_comment_begin" params=$params}
{* Сворачивание *}
<div class="{$component}-fold js-comment-fold" data-id="{$commentId}">
@ -97,23 +97,23 @@
{* Информация *}
<ul class="{$component}-info ls-clearfix">
{* @hook Начало блока с информацией *}
{hook run='comment_info_begin' params=$params}
{hook run="{$hookPrefix}_info_begin" params=$params}
{* @hook Конец блока с информацией *}
{hook run='comment_info_end' params=$params}
{hook run="{$hookPrefix}_info_end" params=$params}
</ul>
{* Текст комментария *}
<div class="{$component}-content">
{* @hook Начало блока с содержимым комментария *}
{hook run='comment_content_begin' params=$params}
{hook run="{$hookPrefix}_content_begin" params=$params}
<div class="{$component}-text ls-text">
{$comment->getText()}
</div>
{* @hook Конец блока с содержимым комментария *}
{hook run='comment_content_end' params=$params}
{hook run="{$hookPrefix}_content_end" params=$params}
</div>
{* Информация о редактировании *}
@ -134,7 +134,7 @@
{* Действия *}
<ul class="{$component}-actions ls-clearfix">
{* @hook Начало списка экшенов комментария *}
{hook run='comment_actions_begin' params=$params}
{hook run="{$hookPrefix}_actions_begin" params=$params}
{* Автор комментария *}
{component 'comment.info-item'
@ -207,7 +207,7 @@
{/if}
{* @hook Конец списка экшенов комментария *}
{hook run='comment_actions_end' params=$params}
{hook run="{$hookPrefix}_actions_end" params=$params}
</ul>
{* Голосование *}
@ -224,5 +224,5 @@
{/if}
{* @hook Конец комментария *}
{hook run='comment_comment_end' params=$params}
{hook run="{$hookPrefix}_comment_end" params=$params}
</section>

View file

@ -21,6 +21,9 @@
.ls-field-input { width: 100%; }
select[multiple].ls-field-input { max-width: 300px; }
.ls-field--autocomplete select {
display: none;
}
/**
* Horizontal

View file

@ -18,11 +18,16 @@
text-align: center;
margin: 0 10px 20px;
display: block;
color: #bad7ea;
}
.syn-create-item:hover {
color: #608ada;
}
.syn-create-item-image {
width: 115px;
height: 115px;
background-repeat: no-repeat;
font-size: 88px;
}
.syn-create-item-text {
color: #727a90;
@ -32,16 +37,4 @@
.syn-create-item:focus .syn-create-item-text,
.syn-create-item:hover .syn-create-item-text {
color: #275ec2;
}
.syn-create-item .syn-create-item-image { background-image: url(images/topic.png); }
.syn-create-item:hover .syn-create-item-image { background-image: url(images/topic-hover.png); }
.syn-create-item--blog .syn-create-item-image { background-image: url(images/blog.png); }
.syn-create-item--blog:hover .syn-create-item-image { background-image: url(images/blog-hover.png); }
.syn-create-item--message .syn-create-item-image { background-image: url(images/message.png); }
.syn-create-item--message:hover .syn-create-item-image { background-image: url(images/message-hover.png); }
.syn-create-item--draft .syn-create-item-image { background-image: url(images/draft.png); }
.syn-create-item--draft:hover .syn-create-item-image { background-image: url(images/draft-hover.png); }
}

View file

@ -1,23 +1,23 @@
{function syn_create item=null}
<a href="{$item.url}" class="syn-create-item syn-create-item--{$item.name}">
<div class="syn-create-item-image"></div>
<div class="syn-create-item-image {$item.css_icon}"></div>
<div class="syn-create-item-text">{$item.text}</div>
</a>
{/function}
{capture 'syn_create'}
{$_menu = [
[ 'name' => 'blog', 'text' => {lang 'modal_create.items.blog'}, 'url' => {router page='blog/add'} ],
[ 'name' => 'message', 'text' => {lang 'modal_create.items.talk'}, 'url' => "{router page='talk/add'}" ]
[ 'name' => 'blog', 'text' => {lang 'modal_create.items.blog'}, 'url' => {router page='blog/add'}, css_icon => 'fa fa-folder-o' ],
[ 'name' => 'message', 'text' => {lang 'modal_create.items.talk'}, 'url' => "{router page='talk/add'}", css_icon => 'fa fa-envelope-o' ]
]}
<div class="syn-create-items ls-clearfix">
{if $iUserCurrentCountTopicDraft}
{syn_create item=[ 'name' => 'draft', 'text' => {lang 'synio.drafts' count=$iUserCurrentCountTopicDraft plural=true}, 'url' => "{router page='content'}drafts/" ]}
{syn_create item=[ 'name' => 'draft', 'text' => {lang 'synio.drafts' count=$iUserCurrentCountTopicDraft plural=true}, 'url' => "{router page='content'}drafts/", css_icon => 'fa fa-file-o' ]}
{/if}
{foreach $LS->Topic_GetTopicTypes() as $type}
{syn_create item=[ 'name' => $type->getCode(), 'text' => $type->getName(), 'url' => $type->getUrlForAdd() ]}
{syn_create item=[ 'name' => $type->getCode(), 'css_icon' => $type->getParam('css_icon', 'fa fa-file-text-o'), 'text' => $type->getName(), 'url' => $type->getUrlForAdd() ]}
{/foreach}
{foreach $_menu as $item}

View file

@ -71,7 +71,7 @@
{* Участники диалога *}
{if $usersCount > 2}
<a href="{router page='talk'}read/{$talk->getId()}/" class="talk-list-item-info-avatar">
<img src="{Config::Get('path.skin.web')}/assets/images/avatars/group_64x64.png" />
<img src="{cfg name='path.skin.web'}/assets/images/avatars/group_64x64.png" />
</a>
{lang name='talk.participants' count=$usersCount plural=true}

View file

@ -8,7 +8,7 @@
.ls-toolbar {
position: fixed;
z-index: 100;
z-index: 29;
display: inline-block;
}
.ls-toolbar-item {

View file

@ -47,6 +47,10 @@
font-family: 'PT Sans', sans-serif;
font-size: 18px;
}
.ls-topic-blogs .ls-topic-blogs-item {
float: left;
margin-right: 5px;
}
.ls-topic-blogs a {
color: #000;
text-decoration: underline;

View file

@ -55,9 +55,9 @@
{/if}
{if $_blogs}
<ul class="{$component}-blogs">
<ul class="{$component}-blogs ls-clearfix">
{foreach $_blogs as $blog}
<a href="{$blog.url}">{$blog.title}</a>{if ! $blog@last}, {/if}
<li class="{$component}-blogs-item"><a href="{$blog.url}">{$blog.title}</a>{if ! $blog@last}, {/if}</li>
{/foreach}
</ul>
{/if}

View file

@ -68,11 +68,11 @@
{capture 'info_private_geo'}
<span itemprop="address" itemscope itemtype="http://data-vocabulary.org/Address">
{if $geoTarget->getCountryId()}
<a href="{router page='people'}country/{$geoTarget->getCountryId()}/" itemprop="country-name">{$user->getProfileCountry()|escape}</a>{if $geoTarget->getCityId()},{/if}
<span itemprop="country-name">{$user->getProfileCountry()|escape}</span>{if $geoTarget->getCityId()},{/if}
{/if}
{if $geoTarget->getCityId()}
<a href="{router page='people'}city/{$geoTarget->getCityId()}/" itemprop="locality">{$user->getProfileCity()|escape}</a>
<span itemprop="locality">{$user->getProfileCity()|escape}</span>
{/if}
</span>
{/capture}

View file

@ -61,7 +61,7 @@
mods = 'horizontal'
name = 'profile_birthday'
inputClasses = 'js-field-date-default'
value = {date_format date=$user->getProfileBirthday() format='j.n.Y'}
value = ($user->getProfileBirthday()) ? {date_format date=$user->getProfileBirthday() format='d.m.Y' notz=true} : ''
label = {lang name='user.settings.profile.fields.birthday.label'}}

View file

@ -15,7 +15,7 @@
{/block}
{block 'layout_head_styles' append}
<link href="http://fonts.googleapis.com/css?family=PT+Sans:400,700&amp;subset=latin,cyrillic" rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=PT+Sans:400,700&amp;subset=latin,cyrillic" rel="stylesheet" type="text/css">
<link rel="search" type="application/opensearchdescription+xml" href="{router page='search'}opensearch/" title="{Config::Get('view.name')}" />
{/block}
@ -45,6 +45,8 @@
.layout-container { width: {Config::Get('view.grid.fixed_width')}; }
</style>
{/if}
<meta name="viewport" content="">
{/block}
{block 'layout_body'}
@ -73,7 +75,7 @@
{* Первый уровень навигации *}
{if count($layoutNav)}
{component 'nav' hook='main_nav' classes='layout-nav-top' params=$layoutNav[0]}
{component 'nav' classes='layout-nav-top' params=$layoutNav[0]}
{/if}
</div>
</nav>
@ -200,7 +202,7 @@
{hook run='copyright'}
<div class="layout-footer-design-by">
<img src="{cfg name='path.static.skin'}/assets/images/xeoart.png" alt="xeoart" />
<img src="{cfg name='path.skin.assets.web'}/images/xeoart.png" alt="xeoart" />
Design by <a href="http://xeoart.com">xeoart</a>
<div>2012</div>
</div>

View file

@ -6,7 +6,7 @@
{block 'layout_options' append}
{$layoutNav = [[
name => 'settings',
hook => 'settings',
activeItem => $sMenuSubItemSelect,
items => [
[ 'url' => "{router page='settings'}profile/", 'text' => {lang name='user.settings.nav.profile'}, 'name' => 'profile' ],

View file

@ -76,6 +76,11 @@ $config['head']['template']['css'] = array(
"___path.skin.assets.web___/css/print.css"
);
// Подключение темы
if (Config::Get('view.theme')) {
$config['head']['template']['css'][] = "___path.skin.web___/themes/___view.theme___/style.css";
}
/**
* SEO
*/

View file

@ -0,0 +1,21 @@
<?php
return [
'synio' => [
'guest' => 'Guest',
'site_pages' => 'Pages',
'drafts' => '%%count%% draft;%%count%% drafts;%%count%% drafts',
'user_about_empty' => 'No data yet...',
'all_blogs' => 'All blogs'
],
'activity' => [
'block_recent' => [
'all' => 'All activities'
]
],
'user' => [
'search' => [
'title' => 'Search'
]
]
];

View file

@ -0,0 +1,2 @@
Order Deny,Allow
Deny from all

View file

@ -0,0 +1,113 @@
<?php
class InstallConfig
{
static public $sFileConfig = null;
static public $sLastError = null;
static public function save($mName, $mValue = null)
{
if (!self::checkFile()) {
return false;
}
if (is_array($mName)) {
$aValues = $mName;
} else {
$aValues = array($mName => $mValue);
}
$sContent = file_get_contents(self::$sFileConfig);
foreach ($aValues as $sName => $mValue) {
$sContent = self::_writeValue($sName, $mValue, $sContent);
}
file_put_contents(self::$sFileConfig, $sContent);
return true;
}
static public function get($sName, $mDefault = null)
{
if (!self::checkFile(false)) {
return $mDefault;
}
$aConfig = include(self::$sFileConfig);
if (strpos($sName, '.')) {
$sVal = $aConfig;
$aKeys = explode('.', $sName);
foreach ($aKeys as $k) {
if (isset($sVal[$k])) {
$sVal = $sVal[$k];
} else {
return $mDefault;
}
}
} else {
if (isset($aConfig[$sName])) {
$sVal = $aConfig[$sName];
} else {
return $mDefault;
}
}
return $sVal;
}
static public function _writeValue($sName, $mValue, $sContent)
{
$sName = '$config[\'' . implode('\'][\'', explode('.', $sName)) . '\']';
$mValue = self::_convertToConfigValue($mValue);
/**
* Если переменная уже определена в конфиге,
* то меняем значение.
*/
if (substr_count($sContent, $sName)) {
$sContent = preg_replace("~" . preg_quote($sName) . ".+;~Ui", $sName . ' = ' . $mValue . ';', $sContent);
} else {
$sContent = str_replace('return $config;', $sName . ' = ' . $mValue . ';' . PHP_EOL . 'return $config;',
$sContent);
}
return $sContent;
}
static public function _convertToConfigValue($mValue)
{
switch (true) {
case is_string($mValue):
return "'" . addslashes($mValue) . "'";
case is_bool($mValue):
return ($mValue) ? "true" : "false";
case is_array($mValue):
$sArrayString = "";
foreach ($mValue as $sKey => $sValue) {
$sArrayString .= "'{$sKey}'=>" . self::_convertToConfigValue($sValue) . ",";
}
return "array(" . $sArrayString . ")";
case is_numeric($mValue):
return $mValue;
default:
return "'" . (string)$mValue . "'";
}
}
static public function checkFile($bCheckWritable = true)
{
if (is_null(self::$sFileConfig) or !file_exists(self::$sFileConfig)) {
self::$sLastError = InstallCore::getLang('config.errors.file_not_found');
return false;
}
if ($bCheckWritable) {
if (!is_writable(self::$sFileConfig)) {
self::$sLastError = InstallCore::getLang('config.errors.file_not_writable');
return false;
}
}
return true;
}
}

View file

@ -0,0 +1,420 @@
<?php
class InstallCore
{
const COOKIE_NAME = 'install_data';
static public $aGroups = array();
static public $aGroupsParams = array();
static public $oLayout = null;
static public $aLangMsg = array();
static public $aStoredData = array();
public function __construct($aGroups)
{
if (!$aGroups) {
throw new Exception('Empty groups');
}
$this->defineGroups($aGroups);
$this->loadLang();
$this->loadStoredData();
self::$oLayout = new InstallTemplate('layout.tpl.php');
}
protected function defineGroups($aGroups)
{
$aGroupsResult = array();
$aParamsResult = array();
foreach ($aGroups as $sGroup => $aSteps) {
foreach ($aSteps as $sStep => $aParams) {
if (is_int($sStep)) {
$sStep = $aParams;
$aParams = array();
}
$aParamsResult[$sGroup][$sStep] = $aParams;
$aGroupsResult[$sGroup][] = $sStep;
}
}
self::$aGroups = $aGroupsResult;
self::$aGroupsParams = $aParamsResult;
}
/**
* Запускает процесс инсталляции
*/
public function run()
{
if (self::getRequest('reset')) {
self::$aStoredData = array();
self::saveStoredData();
}
/**
* Получаем текущую группу
*/
$sGroup = self::getRequestStr('group');
if ($sGroup) {
return $this->runGroup($sGroup);
}
/**
* Если группа не определена и она только одна - запускаем
*/
if (!$sGroup and count(self::$aGroups) == 1) {
$aGroupNames = array_keys(self::$aGroups);
return $this->runGroup(array_shift($aGroupNames));
}
/**
* Показываем страницу выбора группы
*/
self::setPreviousStepHide();
self::setNextStepHide();
self::setInstallResetHide();
self::render('index.tpl.php', array('groups' => array_keys(self::$aGroups)));
}
public function runGroup($sGroup)
{
if (!isset(self::$aGroups[$sGroup])) {
return self::renderError('Not found group');
}
$aGroup = self::$aGroups[$sGroup];
/**
* Определяем текущий шаг
* Смотрим его в куках, если там нет, то используем первый
* Шаг сквозной для всех групп, поэтому при установке у одной группы - у других он сбрасывается на первый
*/
$sCurrentStep = self::getStoredData('step');
if (!$sCurrentStep or !in_array($sCurrentStep, $aGroup)) {
if (!$sFirst = array_shift($aGroup)) {
return self::renderError('Not found steps');
}
$sCurrentStep = $sFirst;
}
$sNextStep = self::getNextStep($sGroup, $sCurrentStep);
$sPrevousStep = self::getPreviousStep($sGroup, $sCurrentStep);
if (!$sPrevousStep) {
}
if (!$sNextStep) {
self::setNextStepHide();
}
if (isset($_POST['action_previous'])) {
if ($sPrevousStep) {
InstallCore::setStoredData('step', $sPrevousStep);
InstallCore::location($sGroup);
} elseif (count(self::$aGroups) > 1) {
/**
* Перенаправлям на страницу выбора группы
*/
self::location();
}
}
return $this->runStep($sCurrentStep, $sGroup);
}
public function runStep($sStep, $sGroup)
{
$sClass = 'InstallStep' . ucfirst($sStep);
if (!class_exists($sClass)) {
return self::renderError('Not found step ' . $sStep);
}
$aParams = isset(self::$aGroupsParams[$sGroup][$sStep]) ? self::$aGroupsParams[$sGroup][$sStep] : array();
$oStep = new $sClass($sGroup, $aParams);
if (isset($_POST['action_next'])) {
/**
* Сначала обрабатываем шаг
*/
$oStep->_process();
}
$oStep->_show();
}
protected function loadLang()
{
$sLang = 'ru';
$sFilePath = INSTALL_DIR . DIRECTORY_SEPARATOR . 'frontend' . DIRECTORY_SEPARATOR . 'i18n' . DIRECTORY_SEPARATOR . $sLang . '.php';
if (file_exists($sFilePath)) {
self::$aLangMsg = require($sFilePath);
}
}
protected function loadStoredData()
{
$aData = isset($_COOKIE[self::COOKIE_NAME]) ? $_COOKIE[self::COOKIE_NAME] : '';
if (get_magic_quotes_gpc()) {
$this->stripslashes($aData);
}
self::$aStoredData = $aData ? @unserialize($aData) : array();
}
static public function saveStoredData()
{
$sData = serialize(self::$aStoredData);
setcookie(self::COOKIE_NAME, $sData, time() + 60 * 60 * 24);
}
static public function getStoredData($sName, $mDefault = null)
{
return isset(self::$aStoredData[$sName]) ? self::$aStoredData[$sName] : $mDefault;
}
static public function setStoredData($sName, $mValue)
{
self::$aStoredData[$sName] = $mValue;
self::saveStoredData();
}
static public function getDataFilePath($sFile)
{
return dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . $sFile;
}
static public function renderError($sMsg, $sTitle = null)
{
self::render('error.tpl.php', array('msg' => $sMsg, 'title' => $sTitle));
}
static public function render($sTemplate, $aVars = array())
{
if (is_object($sTemplate)) {
$oTemplate = $sTemplate;
self::$oLayout->assign($aVars);
} else {
$oTemplate = new InstallTemplate($sTemplate, $aVars);
}
$oTemplate->setParent(self::$oLayout);
$sContent = $oTemplate->render();
self::$oLayout->assign('content', $sContent);
echo(self::$oLayout->render());
exit();
}
static public function assign($mName, $mValue = null)
{
self::$oLayout->assign($mName, $mValue);
}
static public function getRequest($sName, $mDefault = null)
{
$sName = str_replace('.', '_', $sName);
return isset($_REQUEST[$sName]) ? $_REQUEST[$sName] : $mDefault;
}
static public function getRequestStr($sName, $mDefault = null)
{
$sVal = self::getRequest($sName, $mDefault);
return is_scalar($sVal) ? (string)$sVal : '';
}
static public function getLang($sName)
{
if (strpos($sName, '.')) {
$sLang = self::$aLangMsg;
$aKeys = explode('.', $sName);
foreach ($aKeys as $k) {
if (isset($sLang[$k])) {
$sLang = $sLang[$k];
} else {
return $sName;
}
}
} else {
if (isset(self::$aLangMsg[$sName])) {
$sLang = self::$aLangMsg[$sName];
} else {
return $sName;
}
}
return $sLang;
}
static public function getNextStep($sGroup, $sStep = null)
{
$aGroups = self::$aGroups;
if (isset($aGroups[$sGroup])) {
if (is_null($sStep)) {
return array_shift($aGroups[$sGroup]);
} else {
if (false !== ($iPos = array_search($sStep, $aGroups[$sGroup]))) {
$aNext = array_slice($aGroups[$sGroup], $iPos + 1, 1);
$sNext = current($aNext);
return $sNext !== false ? $sNext : null;
}
}
} else {
return null;
}
}
static public function getPreviousStep($sGroup, $sStep = null)
{
$aGroups = self::$aGroups;
if (isset($aGroups[$sGroup])) {
if (is_null($sStep)) {
return array_shift($aGroups[$sGroup]);
} else {
if ($iPos = array_search($sStep, $aGroups[$sGroup])) {
$aPrev = array_slice($aGroups[$sGroup], $iPos - 1, 1);
$sPrev = current($aPrev);
return $sPrev !== false ? $sPrev : null;
}
}
} else {
return null;
}
}
static public function location($sGroup = '')
{
header('Location: ./' . ($sGroup ? '?group=' . $sGroup : ''));
exit;
}
static public function setInstallResetHide($bHide = true)
{
self::$oLayout->assign('install_reset_hide', $bHide);
}
static public function setNextStepHide($bHide = true)
{
self::$oLayout->assign('next_step_hide', $bHide);
}
static public function setNextStepDisable($bDisable = true)
{
self::$oLayout->assign('next_step_disable', $bDisable);
}
static public function setPreviousStepHide($bHide = true)
{
self::$oLayout->assign('previous_step_hide', $bHide);
}
static public function setPreviousStepDisable($bDisable = true)
{
self::$oLayout->assign('previous_step_disable', $bDisable);
}
protected function stripslashes(&$data)
{
if (is_array($data)) {
foreach ($data as $sKey => $value) {
if (is_array($value)) {
$this->stripslashes($data[$sKey]);
} else {
$data[$sKey] = stripslashes($value);
}
}
} else {
$data = stripslashes($data);
}
}
/**
* Выполняет транслитерацию текста
*
* @param $sText
* @param bool $bLower
* @return mixed|string
*/
static public function transliteration($sText, $bLower = true)
{
$aConverter = array(
'а' => 'a',
'б' => 'b',
'в' => 'v',
'г' => 'g',
'д' => 'd',
'е' => 'e',
'ё' => 'e',
'ж' => 'zh',
'з' => 'z',
'и' => 'i',
'й' => 'y',
'к' => 'k',
'л' => 'l',
'м' => 'm',
'н' => 'n',
'о' => 'o',
'п' => 'p',
'р' => 'r',
'с' => 's',
'т' => 't',
'у' => 'u',
'ф' => 'f',
'х' => 'h',
'ц' => 'c',
'ч' => 'ch',
'ш' => 'sh',
'щ' => 'sch',
'ь' => "'",
'ы' => 'y',
'ъ' => "'",
'э' => 'e',
'ю' => 'yu',
'я' => 'ya',
'А' => 'A',
'Б' => 'B',
'В' => 'V',
'Г' => 'G',
'Д' => 'D',
'Е' => 'E',
'Ё' => 'E',
'Ж' => 'Zh',
'З' => 'Z',
'И' => 'I',
'Й' => 'Y',
'К' => 'K',
'Л' => 'L',
'М' => 'M',
'Н' => 'N',
'О' => 'O',
'П' => 'P',
'Р' => 'R',
'С' => 'S',
'Т' => 'T',
'У' => 'U',
'Ф' => 'F',
'Х' => 'H',
'Ц' => 'C',
'Ч' => 'Ch',
'Ш' => 'Sh',
'Щ' => 'Sch',
'Ь' => "'",
'Ы' => 'Y',
'Ъ' => "'",
'Э' => 'E',
'Ю' => 'Yu',
'Я' => 'Ya',
" " => "-",
"." => "",
"/" => "-",
"_" => "-",
'і' => 'i',
'І' => 'I',
'ї' => 'i',
'Ї' => 'I',
'є' => 'e',
'Є' => 'E',
'ґ' => 'g',
'Ґ' => 'G',
'«' => '',
'»' => '',
);
$sRes = strtr($sText, $aConverter);
if ($sResIconv = @iconv("UTF-8", "ISO-8859-1//IGNORE//TRANSLIT", $sRes)) {
$sRes = $sResIconv;
}
$sRes = preg_replace('/[^A-Za-z0-9\-]/', '', $sRes);
$sRes = preg_replace('/\-{2,}/', '-', $sRes);
if ($bLower) {
$sRes = strtolower($sRes);
}
return $sRes;
}
}

View file

@ -0,0 +1,357 @@
<?php
abstract class InstallStep
{
protected $aParams = array();
protected $oTemplate = null;
protected $sGroup = null;
protected $aErrors = array();
protected $rDbLink = null;
protected $aDbParams = array();
public function __construct($sGroup, $aParams = array())
{
$this->aParams = array_merge($this->aParams, $aParams);
$this->oTemplate = new InstallTemplate($this->getTemplateName());
$this->sGroup = $sGroup;
$this->init();
}
public function init()
{
}
public function getParam($sName, $mDefault = null)
{
return array_key_exists($sName, $this->aParams) ? $this->aParams[$sName] : $mDefault;
}
protected function getTemplateName()
{
return 'steps/' . $this->getName() . '.tpl.php';
}
public function getErrors()
{
return $this->aErrors;
}
protected function addError($sMsg)
{
$this->aErrors[] = $sMsg;
return false;
}
public function getName()
{
$aPath = explode('_', install_func_underscore(get_class($this)));
array_shift($aPath);
array_shift($aPath);
$sName = ucfirst(install_func_camelize(join('_', $aPath)));
$sName{0} = strtolower($sName{0});
return $sName;
}
public function getStepTitle()
{
return InstallCore::getLang('steps.' . $this->getName() . '.title');
}
public function getGroupTitle()
{
return InstallCore::getLang('groups.' . $this->sGroup . '.title');
}
/**
* Выводит шаблон шага
*/
protected function render()
{
InstallCore::assign('currentStep', $this);
$this->oTemplate->assign('currentStep', $this);
InstallCore::render($this->oTemplate);
}
protected function assign($mName, $mValue = null)
{
$this->oTemplate->assign($mName, $mValue);
}
/**
* Запускает отображение шага
*/
public function _show()
{
if ($this->beforeShow()) {
$this->show();
$this->afterShow();
$this->render();
} else {
/**
* todo: нужно изменить - показываем только страницу с ошибкой
*/
return self::renderError('Вернитесь на прошлый шаг');
}
}
/**
* Запускает выполнение шага - когда пользователь жмет "Далее" на текущем шаге
*/
public function _process()
{
if ($this->beforeProcess()) {
if ($this->process()) {
$this->afterProcess();
/**
* Устанавливаем следующий шаг
*/
if ($sNextStep = InstallCore::getNextStep($this->sGroup, $this->getName())) {
InstallCore::setStoredData('step', $sNextStep);
}
/**
* Редиректим
*/
InstallCore::location($this->sGroup);
} else {
/**
* todo: здесь нужно показать сам текущий шаг с сообщением об ошибке
*/
//return InstallCore::renderError('Ошибка при выполнении шага');
}
} else {
/**
* todo: нужно изменить - показываем сам шаг с сообщением об ошибке
*/
//return InstallCore::renderError('Невозможно выполнить шаг');
}
}
protected function getDBConnection($sHost, $iPort, $sUser, $sPasswd, $bGeneral = false)
{
$oDb = @mysqli_connect($sHost, $sUser, $sPasswd, '', $iPort);
if ($oDb) {
/**
* Валидация версии MySQL сервера
*/
if (!version_compare(mysqli_get_server_info($oDb), '5.0.0', '>')) {
return $this->addError(InstallCore::getLang('db.errors.db_version'));
}
mysqli_query($oDb, 'set names utf8');
if ($bGeneral) {
$this->rDbLink = $oDb;
}
return $oDb;
}
return $this->addError(InstallCore::getLang('db.errors.db_connect'));
}
protected function setDbParams($aParams)
{
$this->aDbParams = $aParams;
}
protected function importDumpDB($oDb, $sFile, $aParams = null)
{
$sFileQuery = @file_get_contents($sFile);
if (is_null($aParams)) {
$aParams = $this->aDbParams;
}
if (isset($aParams['prefix'])) {
$sFileQuery = str_replace('prefix_', $aParams['prefix'], $sFileQuery);
}
$aQuery = preg_split("#;(\n|\r)#", $sFileQuery, null, PREG_SPLIT_NO_EMPTY);
/**
* Массив для сбора ошибок
*/
$aErrors = array();
if (isset($aParams['check_table'])) {
/**
* Смотрим, какие таблицы существуют в базе данных
*/
$aDbTables = array();
$aResult = @mysqli_query($oDb, "SHOW TABLES");
if (!$aResult) {
return array(
'result' => false,
'errors' => array($this->addError(InstallCore::getLang('db.errors.db_query')))
);
}
while ($aRow = mysqli_fetch_array($aResult, MYSQLI_NUM)) {
$aDbTables[] = $aRow[0];
}
/**
* Если среди таблиц БД уже есть нужная таблица, то выполнять SQL-дамп не нужно
*/
if (in_array($aParams['prefix'] . $aParams['check_table'], $aDbTables)) {
return array('result' => true, 'errors' => array());
}
}
/**
* Проверка на существование поля
*/
if (isset($aParams['check_table_field'])) {
list($sCheckTable, $sCheckField) = $aParams['check_table_field'];
$sCheckTable = str_replace('prefix_', $aParams['prefix'], $sCheckTable);
$aResult = @mysqli_query($oDb, "SHOW FIELDS FROM `{$sCheckTable}`");
if (!$aResult) {
return array(
'result' => false,
'errors' => array($this->addError(InstallCore::getLang('db.errors.db_query')))
);
}
while ($aRow = mysqli_fetch_assoc($aResult)) {
if ($aRow['Field'] == $sCheckField) {
return array('result' => true, 'errors' => array());
}
}
}
/**
* Выполняем запросы по очереди
*/
foreach ($aQuery as $sQuery) {
$sQuery = trim($sQuery);
/**
* Заменяем движек, если таковой указан в запросе
*/
if (isset($aParams['engine'])) {
$sQuery = str_ireplace('ENGINE=InnoDB', "ENGINE={$aParams['engine']}", $sQuery);
}
if ($sQuery != '') {
$bResult = mysqli_query($oDb, $sQuery);
if (!$bResult) {
$sError = mysqli_error($oDb);
if (isset($aParams['skip_fk_errors']) and $aParams['skip_fk_errors'] and
(stripos($sError, 'errno: 152') !== false or stripos($sError, 'errno: 150') !== false or (stripos($sError, '_fk') !== false and stripos($sError, 'DROP') !== false))
) {
// пропускаем ошибки связанные с внешними ключами
} else {
$aErrors[] = mysqli_error($oDb);
}
}
}
}
return array('result' => count($aErrors) ? false : true, 'errors' => $aErrors);
}
protected function dbCheckTable($sTable)
{
/**
* Смотрим, какие таблицы существуют в базе данных
*/
$aDbTables = array();
$aResult = @mysqli_query($this->rDbLink, "SHOW TABLES");
if (!$aResult) {
return false;
}
while ($aRow = mysqli_fetch_array($aResult, MYSQLI_NUM)) {
$aDbTables[] = $aRow[0];
}
/**
* Ищем необходимую таблицу
*/
$aParams = $this->aDbParams;
if (isset($aParams['prefix'])) {
$sTable = str_replace('prefix_', $aParams['prefix'], $sTable);
}
if (in_array($sTable, $aDbTables)) {
return true;
}
return false;
}
protected function dbQuery($sQuery)
{
$aParams = $this->aDbParams;
if (isset($aParams['prefix'])) {
$sQuery = str_replace('prefix_', $aParams['prefix'], $sQuery);
}
if (isset($aParams['engine'])) {
$sQuery = str_ireplace('ENGINE=InnoDB', "ENGINE={$aParams['engine']}", $sQuery);
}
if ($rResult = mysqli_query($this->rDbLink, $sQuery)) {
return $rResult;
}
$aErrors[] = mysqli_error($this->rDbLink);
return false;
}
protected function dbSelect($sQuery)
{
$aResult = array();
if ($rResult = $this->dbQuery($sQuery)) {
while ($aRow = mysqli_fetch_assoc($rResult)) {
$aResult[] = $aRow;
}
}
return $aResult;
}
protected function dbSelectOne($sQuery)
{
$aResult = $this->dbSelect($sQuery);
if ($aResult) {
$aRow = reset($aResult);
return $aRow;
}
return array();
}
protected function dbInsertQuery($sTable, $aFields, $bRun = true)
{
$aPath = array();
foreach ($aFields as $sFields => $sValue) {
if (is_int($sValue)) {
$aPath[] = "`{$sFields}` = " . $sValue;
} else {
$aPath[] = "`{$sFields}` = '" . mysqli_escape_string($this->rDbLink, $sValue) . "'";
}
}
$sQuery = "INSERT INTO {$sTable} SET " . join(', ', $aPath);
if ($bRun) {
if ($this->dbQuery($sQuery)) {
return mysqli_insert_id($this->rDbLink);
}
return false;
} else {
return $sQuery;
}
}
protected function beforeShow()
{
return true;
}
protected function afterShow()
{
}
protected function beforeProcess()
{
return true;
}
protected function afterProcess()
{
}
public function show()
{
}
public function process()
{
return true;
}
}

View file

@ -0,0 +1,119 @@
<?php
class InstallStepCheckRequirements extends InstallStep
{
public function show()
{
/**
* Проверяем требования
*/
$sAdditionalSolution = '';
$aRequirements = array();
if (!version_compare(PHP_VERSION, '5.5', '>=')) {
$aRequirements[] = array(
'name' => 'php_version',
'current' => PHP_VERSION
);
}
if (!in_array(strtolower(@ini_get('safe_mode')), array('0', 'off', ''))) {
$aRequirements[] = array(
'name' => 'safe_mode',
'current' => InstallCore::getLang('yes')
);
}
if (!@preg_match('//u', '')) {
$aRequirements[] = array(
'name' => 'utf8',
'current' => InstallCore::getLang('no')
);
}
if (!@extension_loaded('mbstring')) {
$aRequirements[] = array(
'name' => 'mbstring',
'current' => InstallCore::getLang('no')
);
}
if (!in_array(strtolower(@ini_get('mbstring.func_overload')), array('0', '4', 'no overload'))) {
$aRequirements[] = array(
'name' => 'mbstring_func_overload',
'current' => InstallCore::getLang('yes')
);
}
if (!@extension_loaded('SimpleXML')) {
$aRequirements[] = array(
'name' => 'xml',
'current' => InstallCore::getLang('no')
);
}
if (@extension_loaded('xdebug')) {
$iLevel = (int)@ini_get('xdebug.max_nesting_level');
if ($iLevel < 1000) {
$aRequirements[] = array(
'name' => 'xdebug',
'current' => InstallCore::getLang('yes') . " ({$iLevel})"
);
}
}
/**
* Права на запись файлов
*/
$bWriteSolutions = false;
$sAppDir = dirname(INSTALL_DIR);
$sDir = dirname($sAppDir) . DIRECTORY_SEPARATOR . 'uploads';
if (!is_dir($sDir) or !is_writable($sDir)) {
$aRequirements[] = array(
'name' => 'dir_uploads',
'current' => InstallCore::getLang('is_not_writable')
);
$bWriteSolutions = true;
}
$sDir = $sAppDir . DIRECTORY_SEPARATOR . 'plugins';
if (!is_dir($sDir) or !is_writable($sDir)) {
$aRequirements[] = array(
'name' => 'dir_plugins',
'current' => InstallCore::getLang('is_not_writable')
);
$bWriteSolutions = true;
}
$sDir = $sAppDir . DIRECTORY_SEPARATOR . 'tmp';
if (!is_dir($sDir) or !is_writable($sDir)) {
$aRequirements[] = array(
'name' => 'dir_tmp',
'current' => InstallCore::getLang('is_not_writable')
);
$bWriteSolutions = true;
}
$sDir = $sAppDir . DIRECTORY_SEPARATOR . 'logs';
if (!is_dir($sDir) or !is_writable($sDir)) {
$aRequirements[] = array(
'name' => 'dir_logs',
'current' => InstallCore::getLang('is_not_writable')
);
$bWriteSolutions = true;
}
$sFile = $sAppDir . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.local.php';
if (!is_file($sFile) or !is_writable($sFile)) {
$aRequirements[] = array(
'name' => 'file_config_local',
'current' => InstallCore::getLang('is_not_writable')
);
$bWriteSolutions = true;
}
if (count($aRequirements)) {
InstallCore::setNextStepDisable();
}
if ($bWriteSolutions) {
$sBuildPath = $sAppDir . DIRECTORY_SEPARATOR . 'install' . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'build.sh';
$sAdditionalSolution .= '<b>' . InstallCore::getLang('steps.checkRequirements.writable_solution') . '</b><br/>';
$sAdditionalSolution .= '<i>chmod 0755 ' . $sBuildPath . '</i><br/>';
$sAdditionalSolution .= '<i>' . $sBuildPath . '</i><br/>';
}
$this->assign('requirements', $aRequirements);
$this->assign('additionalSolution', $sAdditionalSolution);
}
}

View file

@ -0,0 +1,62 @@
<?php
class InstallStepInstallAdmin extends InstallStep
{
/**
* Обработка отправки формы
*
* @return bool
*/
public function process()
{
/**
* Проверяем корректность емайла
*/
$sMail = InstallCore::getRequestStr('admin_mail');
if (!preg_match("/^[\da-z\_\-\.\+]+@[\da-z_\-\.]+\.[a-z]{2,5}$/i", $sMail)) {
return $this->addError(InstallCore::getLang('steps.installAdmin.errors.mail'));
}
/**
* Проверяем корректность пароль
*/
$sPasswd = InstallCore::getRequestStr('admin_passwd');
if (mb_strlen($sPasswd, 'UTF-8') < 3) {
return $this->addError(InstallCore::getLang('steps.installAdmin.errors.passwd'));
}
/**
* Получаем данные коннекта к БД из конфига
*/
InstallConfig::$sFileConfig = dirname(INSTALL_DIR) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.local.php';
/**
* Коннект к серверу БД
*/
if (!$oDb = $this->getDBConnection(InstallConfig::get('db.params.host'), InstallConfig::get('db.params.port'),
InstallConfig::get('db.params.user'), InstallConfig::get('db.params.pass'))
) {
return false;
}
/**
* Выбираем БД
*/
if (!@mysqli_select_db($oDb, InstallConfig::get('db.params.dbname'))) {
return $this->addError(InstallCore::getLang('db.errors.db_query'));
}
/**
* Обновляем пользователя
*/
$sPrefix = InstallConfig::get('db.table.prefix');
$sQuery = "
UPDATE `{$sPrefix}user`
SET
`user_mail` = '{$sMail}',
`user_admin` = '1',
`user_password` = '" . md5($sPasswd) . "'
WHERE `user_id` = 1";
if (!mysqli_query($oDb, $sQuery)) {
return $this->addError(InstallCore::getLang('db.errors.db_query'));
}
return true;
}
}

View file

@ -0,0 +1,23 @@
<?php
class InstallStepInstallComplete extends InstallStep
{
public function init()
{
InstallConfig::$sFileConfig = dirname(INSTALL_DIR) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.local.php';
}
public function show()
{
/**
* Прописываем параметры в конфиг
*/
$aSave = array(
'module.blog.encrypt' => md5(time() . mt_rand()),
'module.talk.encrypt' => md5(time() . mt_rand()),
'module.security.hash' => md5(time() . mt_rand()),
);
InstallConfig::save($aSave);
}
}

View file

@ -0,0 +1,156 @@
<?php
class InstallStepInstallDb extends InstallStep
{
protected $sConfigPath;
public function init()
{
$this->sConfigPath = dirname(INSTALL_DIR) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.local.php';
InstallConfig::$sFileConfig = $this->sConfigPath;
}
/**
* Получаем данные для загрузки на форму
* Возможные источники: реквест, конфиг, дефолтные значения
*
* @param $sName
* @param null $mDefault
* @param bool $bUseHtmlspecialchars
*
* @return mixed|null|string
*/
public function getValue($sName, $mDefault = null, $bUseHtmlspecialchars = true)
{
$mResult = null;
$sNameRequest = str_replace('.', '_', $sName);
if (isset($_REQUEST[$sNameRequest])) {
$mResult = $_REQUEST[$sNameRequest];
} else {
$mResult = InstallConfig::get($sName, $mDefault);
}
return $bUseHtmlspecialchars ? htmlspecialchars($mResult) : $mResult;
}
/**
* Обработка отправки формы
*
* @return bool
*/
public function process()
{
if (!$aRes = $this->processDbCheck()) {
return $aRes;
}
list($oDb, $sEngineDB) = $aRes;
/**
* Запускаем импорт дампов, сначала GEO DB
*/
list($bResult, $aErrors) = array_values($this->importDumpDB($oDb, InstallCore::getDataFilePath('sql/geo.sql'),
array(
'engine' => $sEngineDB,
'prefix' => InstallCore::getRequestStr('db.table.prefix'),
'check_table' => 'geo_city'
)));
if ($bResult) {
/**
* Запускаем основной дамп
*/
list($bResult, $aErrors) = array_values($this->importDumpDB($oDb,
InstallCore::getDataFilePath('sql/dump.sql'), array(
'engine' => $sEngineDB,
'prefix' => InstallCore::getRequestStr('db.table.prefix'),
'check_table' => 'topic'
)));
if ($bResult) {
return true;
}
}
return $this->addError(join('<br/>', $aErrors));
}
protected function processDbCheck()
{
/**
* Коннект к серверу БД
*/
if (!$oDb = $this->getDBConnection(InstallCore::getRequestStr('db.params.host'),
InstallCore::getRequestStr('db.params.port'), InstallCore::getRequestStr('db.params.user'),
InstallCore::getRequestStr('db.params.pass'))
) {
return false;
}
/**
* Выбор БД
*/
$sNameDb = InstallCore::getRequestStr('db.params.dbname');
if (!InstallCore::getRequest('db_create')) {
if (!@mysqli_select_db($oDb, $sNameDb)) {
return $this->addError(InstallCore::getLang('steps.installDb.errors.db_not_found'));
}
} else {
/**
* Пытаемся создать БД
*/
@mysqli_query($oDb,
"CREATE DATABASE IF NOT EXISTS `{$sNameDb}` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci");
if (!@mysqli_select_db($oDb, $sNameDb)) {
return $this->addError(InstallCore::getLang('steps.installDb.errors.db_not_create'));
}
}
/**
* Проверяем корректность префикса таблиц
*/
if (!preg_match('#^[a-z0-9\_]*$#i', InstallCore::getRequestStr('db.table.prefix'))) {
return $this->addError(InstallCore::getLang('steps.installDb.errors.db_table_prefix'));
}
/**
* Определяем поддержку InnoDB
*/
$sEngineDB = 'MyISAM';
if ($aRes = @mysqli_query($oDb, 'SHOW ENGINES')) {
while ($aRow = mysqli_fetch_assoc($aRes)) {
if (strtoupper($aRow['Engine']) == 'INNODB' and in_array(strtoupper($aRow['Support']),
array('DEFAULT', 'YES'))
) {
$sEngineDB = 'InnoDB';
break;
}
}
}
$sPathRootWeb = $this->getPathRootWeb();
$aDirs = array();
$sDirs = trim(str_replace('http://' . $_SERVER['HTTP_HOST'], '', $sPathRootWeb), '/');
if ($sDirs != '') {
$aDirs = explode('/', $sDirs);
}
/**
* Прописываем параметры в конфиг
*/
$aSave = array(
'db.params.host' => InstallCore::getRequestStr('db.params.host'),
'db.params.port' => InstallCore::getRequestStr('db.params.port'),
'db.params.dbname' => InstallCore::getRequestStr('db.params.dbname'),
'db.params.user' => InstallCore::getRequestStr('db.params.user'),
'db.params.pass' => InstallCore::getRequestStr('db.params.pass'),
'db.table.prefix' => InstallCore::getRequestStr('db.table.prefix'),
'db.tables.engine' => $sEngineDB,
'path.root.web' => $sPathRootWeb,
'path.offset_request_url' => count($aDirs),
);
if (!InstallConfig::save($aSave)) {
return $this->addError(InstallConfig::$sLastError);
}
return array($oDb, $sEngineDB);
}
protected function getPathRootWeb()
{
$sPath = rtrim('http://' . $_SERVER['HTTP_HOST'], '/') . str_replace('/install/index.php', '',
$_SERVER['PHP_SELF']);
return preg_replace('#\/application$#', '', $sPath);
}
}

View file

@ -0,0 +1,6 @@
<?php
class InstallStepUpdateComplete extends InstallStepInstallComplete
{
}

View file

@ -0,0 +1,32 @@
<?php
class InstallStepUpdateDb extends InstallStepInstallDb
{
protected function getTemplateName()
{
/**
* Показываем шаблон настроек БД
*/
return 'steps/installDb.tpl.php';
}
public function show()
{
}
/**
* Обработка отправки формы
*
* @return bool
*/
public function process()
{
if (!$aRes = $this->processDbCheck()) {
return $aRes;
}
return true;
}
}

View file

@ -0,0 +1,893 @@
<?php
class InstallStepUpdateVersion extends InstallStep
{
protected $aVersionConvert = array(
'2.0.0',
'1.0.3',
);
public function init()
{
/**
* Получаем данные коннекта к БД из конфига
*/
InstallConfig::$sFileConfig = dirname(INSTALL_DIR) . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.local.php';
}
public function show()
{
$this->assign('from_version', InstallCore::getStoredData('update_from_version'));
$this->assign('convert_versions', $this->aVersionConvert);
}
public function process()
{
set_time_limit(0);
/**
* Коннект к серверу БД
*/
if (!$oDb = $this->getDBConnection(InstallConfig::get('db.params.host'), InstallConfig::get('db.params.port'),
InstallConfig::get('db.params.user'), InstallConfig::get('db.params.pass'), true)
) {
return false;
}
/**
* Выбираем БД
*/
if (!@mysqli_select_db($oDb, InstallConfig::get('db.params.dbname'))) {
return $this->addError(InstallCore::getLang('db.errors.db_query'));
}
$this->setDbParams(array(
'prefix' => InstallConfig::get('db.table.prefix'),
'engine' => InstallConfig::get('db.tables.engine'),
));
$sVersion = InstallCore::getRequestStr('from_version');
/**
* Проверяем наличие конвертора
* Конвертор представляет собой отдельный метод вида converFrom_X1_Y1_Z1_to_X2_Y2_Z2
*/
$sMethod = 'convertFrom_' . str_replace('.', '_', $sVersion) . '_to_' . str_replace('.', '_', VERSION);
if (!method_exists($this, $sMethod)) {
return $this->addError(InstallCore::getLang('steps.updateVersion.errors.not_found_convert'));
}
InstallCore::setStoredData('update_from_version', $sVersion);
/**
* Запускаем конвертор
*/
return call_user_func_array(array($this, $sMethod), array($oDb));
}
/**
* Конвертор версии 2.0.0 в 2.0.1
*
* @param $oDb
*
* @return bool
*/
public function convertFrom_2_0_0_to_2_0_1($oDb)
{
/**
* Запускаем SQL патч
*/
$sFile = 'sql' . DIRECTORY_SEPARATOR . 'patch_2.0.0_to_2.0.1.sql';
list($bResult, $aErrors) = array_values($this->importDumpDB($oDb, InstallCore::getDataFilePath($sFile), array(
'engine' => InstallConfig::get('db.tables.engine'),
'prefix' => InstallConfig::get('db.table.prefix'),
'skip_fk_errors' => true
)));
if ($bResult) {
return true;
}
return $this->addError(join('<br/>', $aErrors));
}
/**
* Конвертор версии 1.0.3 в 2.0.0
*
* @param $oDb
*
* @return bool
*/
public function convertFrom_1_0_3_to_2_0_0($oDb)
{
/**
* Запускаем SQL патч
*/
$sFile = 'sql' . DIRECTORY_SEPARATOR . 'patch_1.0.3_to_2.0.0.sql';
list($bResult, $aErrors) = array_values($this->importDumpDB($oDb, InstallCore::getDataFilePath($sFile), array(
'engine' => InstallConfig::get('db.tables.engine'),
'prefix' => InstallConfig::get('db.table.prefix'),
'check_table' => 'cron_task',
'skip_fk_errors' => true
)));
if ($bResult) {
/**
* Проверяем необходимость конвертировать таблицу плагина Page
*/
if ($this->dbCheckTable("prefix_page")) {
$sFile = 'sql' . DIRECTORY_SEPARATOR . 'patch_page_1.3_to_2.0.sql';
list($bResult, $aErrors) = array_values($this->importDumpDB($oDb, InstallCore::getDataFilePath($sFile),
array(
'engine' => InstallConfig::get('db.tables.engine'),
'prefix' => InstallConfig::get('db.table.prefix'),
'check_table_field' => array('prefix_page', 'id'),
'skip_fk_errors' => true
)));
if (!$bResult) {
return $this->addError(join('<br/>', $aErrors));
}
}
/**
* Конвертируем опросы
* Сначала проверяем необходимость конвертации опросов
*/
if ($this->dbCheckTable("prefix_topic_question_vote")) {
$iPage = 1;
$iLimitCount = 50;
$iLimitStart = 0;
while ($aTopics = $this->dbSelect("SELECT t.*, c.topic_extra FROM prefix_topic as t, prefix_topic_content as c WHERE topic_type = 'question' and t.topic_id = c.topic_id LIMIT {$iLimitStart},{$iLimitCount}")) {
$iPage++;
$iLimitStart = ($iPage - 1) * $iLimitCount;
/**
* Топики
*/
foreach ($aTopics as $aTopic) {
$aPollData = @unserialize($aTopic['topic_extra']);
if (!isset($aPollData['answers'])) {
continue;
}
/**
* Создаем опрос
*/
$aFields = array(
'user_id' => $aTopic['user_id'],
'target_type' => 'topic',
'target_id' => $aTopic['topic_id'],
'title' => htmlspecialchars($aTopic['topic_title']),
'count_answer_max' => 1,
'count_vote' => isset($aPollData['count_vote']) ? $aPollData['count_vote'] : 0,
'count_abstain' => isset($aPollData['count_vote_abstain']) ? $aPollData['count_vote_abstain'] : 0,
'date_create' => $aTopic['topic_date_add'],
);
if ($iPollId = $this->dbInsertQuery('prefix_poll', $aFields)) {
foreach ($aPollData['answers'] as $iAnswerIdOld => $aAnswer) {
/**
* Создаем вариант ответа
*/
$aFields = array(
'poll_id' => $iPollId,
'title' => htmlspecialchars($aAnswer['text']),
'count_vote' => htmlspecialchars($aAnswer['count']),
'date_create' => $aTopic['topic_date_add'],
);
if ($iAnswerId = $this->dbInsertQuery('prefix_poll_answer', $aFields)) {
/**
* Получаем список кто голосовал за этот вариант
*/
if ($aVotes = $this->dbSelect("SELECT * FROM prefix_topic_question_vote WHERE topic_id = '{$aTopic['topic_id']}' AND answer = '{$iAnswerIdOld}' ")) {
foreach ($aVotes as $aVote) {
/**
* Добавляем новый факт голосования за вариант
*/
$aFields = array(
'poll_id' => $iPollId,
'user_id' => $aVote['user_voter_id'],
'answers' => serialize(array($iAnswerId)),
'date_create' => $aTopic['topic_date_add'],
);
$this->dbInsertQuery('prefix_poll_vote', $aFields);
}
}
}
}
/**
* Добавляем факты голосования воздержавшихся
*/
/**
* Получаем список кто голосовал за этот вариант
*/
if ($aVotes = $this->dbSelect("SELECT * FROM prefix_topic_question_vote WHERE topic_id = '{$aTopic['topic_id']}' AND answer = -1 ")) {
foreach ($aVotes as $aVote) {
/**
* Добавляем новый факт воздержания
*/
$aFields = array(
'poll_id' => $iPollId,
'user_id' => $aVote['user_voter_id'],
'answers' => serialize(array()),
'date_create' => $aTopic['topic_date_add'],
);
$this->dbInsertQuery('prefix_poll_vote', $aFields);
}
}
}
/**
* Меняем тип топика
*/
$this->dbQuery("UPDATE prefix_topic SET topic_type = 'topic' WHERE topic_id ='{$aTopic['topic_id']}'");
/**
* Убираем лишние данные из topic_extra
*/
unset($aPollData['answers']);
unset($aPollData['count_vote_abstain']);
unset($aPollData['count_vote']);
$sExtra = mysqli_escape_string($this->rDbLink, serialize($aPollData));
$this->dbQuery("UPDATE prefix_topic_content SET topic_extra = '{$sExtra}' WHERE topic_id ='{$aTopic['topic_id']}'");
}
}
/**
* Удаляем старые таблицы
*/
if (!$this->getErrors()) {
$this->dbQuery('DROP TABLE prefix_topic_question_vote');
}
}
/**
* Конвертируем топик-ссылки
*/
$iPage = 1;
$iLimitCount = 50;
$iLimitStart = 0;
while ($aTopics = $this->dbSelect("SELECT t.*, c.topic_extra, c.topic_text, c.topic_text_short, c.topic_text_source FROM prefix_topic as t, prefix_topic_content as c WHERE topic_type = 'link' and t.topic_id = c.topic_id LIMIT {$iLimitStart},{$iLimitCount}")) {
$iPage++;
$iLimitStart = ($iPage - 1) * $iLimitCount;
/**
* Топики
*/
foreach ($aTopics as $aTopic) {
$aData = @unserialize($aTopic['topic_extra']);
if (!isset($aData['url'])) {
continue;
}
/**
* Переносим ссылку в текст топика
*/
$sUrl = $aData['url'];
if (strpos($sUrl, '://') === false) {
$sUrl = 'http://' . $sUrl;
}
$sUrl = htmlspecialchars($sUrl);
$sTextAdd = "\n<br/><br/><a href=\"{$sUrl}\">{$sUrl}</a>";
$aTopic['topic_text'] .= $sTextAdd;
$aTopic['topic_text_short'] .= $sTextAdd;
$aTopic['topic_text_source'] .= $sTextAdd;
unset($aData['url']);
$sExtra = mysqli_escape_string($this->rDbLink, serialize($aData));
$sText = mysqli_escape_string($this->rDbLink, $aTopic['topic_text']);
$sTextShort = mysqli_escape_string($this->rDbLink, $aTopic['topic_text_short']);
$sTextSource = mysqli_escape_string($this->rDbLink, $aTopic['topic_text_source']);
$this->dbQuery("UPDATE prefix_topic_content SET topic_extra = '{$sExtra}', topic_text = '{$sText}', topic_text_short = '{$sTextShort}', topic_text_source = '{$sTextSource}' WHERE topic_id ='{$aTopic['topic_id']}'");
/**
* Меняем тип топика
*/
$this->dbQuery("UPDATE prefix_topic SET topic_type = 'topic' WHERE topic_id ='{$aTopic['topic_id']}'");
}
}
/**
* Конвертируем топик-фотосеты
*/
if ($this->dbCheckTable("prefix_topic_photo")) {
$iPage = 1;
$iLimitCount = 50;
$iLimitStart = 0;
while ($aTopics = $this->dbSelect("SELECT t.*, c.topic_extra, c.topic_text, c.topic_text_short, c.topic_text_source FROM prefix_topic as t, prefix_topic_content as c WHERE topic_type = 'photoset' and t.topic_id = c.topic_id LIMIT {$iLimitStart},{$iLimitCount}")) {
$iPage++;
$iLimitStart = ($iPage - 1) * $iLimitCount;
/**
* Топики
*/
foreach ($aTopics as $aTopic) {
$aData = @unserialize($aTopic['topic_extra']);
if (!isset($aData['main_photo_id'])) {
continue;
}
/**
* Получаем фото
*/
if ($aPhotos = $this->dbSelect("SELECT * FROM prefix_topic_photo WHERE topic_id = '{$aTopic['topic_id']}' ")) {
$aMediaItems = array();
foreach ($aPhotos as $aPhoto) {
/**
* Необходимо перенести изображение в media и присоеденить к топику
*/
$sFileSource = $this->convertPathWebToServer($aPhoto['path']);
/**
* Формируем список старых изображений для удаления
*/
$sMask = pathinfo($sFileSource,
PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR . pathinfo($sFileSource,
PATHINFO_FILENAME) . '_*';
$aFilesForRemove = array();
if ($aPaths = glob($sMask)) {
foreach ($aPaths as $sPath) {
$aFilesForRemove[$sPath] = $sPath;
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
$iWidth = $oImage->getSize()->getWidth();
$iHeight = $oImage->getSize()->getHeight();
if ($this->resizeImage($oImage, 1000)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_1000x')) {
unset($aFilesForRemove[$sFileSave]);
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->resizeImage($oImage, 500)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_500x')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 100)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_100x100crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 50)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_50x50crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
/**
* Добавляем запись в медиа
*/
$aDataMedia = array(
'image_sizes' => array(
array(
'w' => 1000,
'h' => null,
'crop' => false,
),
array(
'w' => 500,
'h' => null,
'crop' => false,
),
array(
'w' => 100,
'h' => 100,
'crop' => true,
),
array(
'w' => 50,
'h' => 50,
'crop' => true,
),
),
);
if ($aPhoto['description']) {
$aDataMedia['title'] = htmlspecialchars($aPhoto['description']);
}
$aFields = array(
'user_id' => $aTopic['user_id'],
'type' => 1,
'target_type' => 'topic',
'file_path' => '[relative]' . str_replace(dirname(dirname(INSTALL_DIR)), '',
$sFileSource),
'file_name' => pathinfo($sFileSource, PATHINFO_FILENAME),
'file_size' => filesize($sFileSource),
'width' => $iWidth,
'height' => $iHeight,
'date_add' => $aTopic['topic_date_add'],
'data' => serialize($aDataMedia),
);
if ($iMediaId = $this->dbInsertQuery('prefix_media', $aFields)) {
/**
* Добавляем связь медиа с топиком
*/
$aFields = array(
'media_id' => $iMediaId,
'target_id' => $aTopic['topic_id'],
'target_type' => 'topic',
'date_add' => $aTopic['topic_date_add'],
'data' => '',
);
if ($iMediaTargetId = $this->dbInsertQuery('prefix_media_target', $aFields)) {
$sFileWeb = InstallConfig::get('path.root.web') . str_replace(dirname(dirname(INSTALL_DIR)),
'',
$sFileSource);
$aMediaItems[$iMediaId] = $sFileWeb;
}
}
/**
* Удаляем старые
*/
foreach ($aFilesForRemove as $sFileRemove) {
@unlink($sFileRemove);
}
}
}
/**
* Добавляем в начало текста топика вывод фотосета
*/
$sCodeRender = '';
$sCodeSource = '';
if ($aMediaItems) {
$sCodeSource = '<gallery items="' . join(',',
array_keys($aMediaItems)) . '" nav="thumbs" caption="1" />' . "\n";
$sCodeRender = '<div class="fotorama" data-nav="thumbs" >' . "\n";
foreach ($aMediaItems as $iId => $sFileWeb) {
$sCodeRender .= '<img src="' . $sFileWeb . '" />' . "\n";
}
$sCodeRender .= '</div>' . "\n";
}
unset($aData['main_photo_id']);
unset($aData['count_photo']);
$sExtra = mysqli_escape_string($this->rDbLink, serialize($aData));
$sText = mysqli_escape_string($this->rDbLink, $sCodeRender . $aTopic['topic_text']);
$sTextShort = mysqli_escape_string($this->rDbLink,
$sCodeRender . $aTopic['topic_text_short']);
$sTextSource = mysqli_escape_string($this->rDbLink,
$sCodeSource . $aTopic['topic_text_source']);
$this->dbQuery("UPDATE prefix_topic_content SET topic_extra = '{$sExtra}', topic_text = '{$sText}', topic_text_short = '{$sTextShort}', topic_text_source = '{$sTextSource}' WHERE topic_id ='{$aTopic['topic_id']}'");
/**
* Меняем тип топика
*/
$this->dbQuery("UPDATE prefix_topic SET topic_type = 'topic' WHERE topic_id ='{$aTopic['topic_id']}'");
}
}
}
/**
* Удаляем старые таблицы
*/
if (!$this->getErrors()) {
$this->dbQuery('DROP TABLE prefix_topic_photo');
}
}
/**
* Конвертируем урлы топиков к ЧПУ формату
*/
$iPage = 1;
$iLimitCount = 50;
$iLimitStart = 0;
while ($aTopics = $this->dbSelect("SELECT * FROM prefix_topic ORDER BY topic_id asc LIMIT {$iLimitStart},{$iLimitCount}")) {
$iPage++;
$iLimitStart = ($iPage - 1) * $iLimitCount;
/**
* Топики
*/
foreach ($aTopics as $aTopic) {
if ($aTopic['topic_slug']) {
continue;
}
$sSlug = InstallCore::transliteration($aTopic['topic_title']);
$sSlug = $this->GetUniqueTopicSlug($sSlug, $aTopic['topic_id']);
$sSlug = mysqli_escape_string($this->rDbLink, $sSlug);
/**
* Меняем тип топика
*/
$this->dbQuery("UPDATE prefix_topic SET topic_slug = '{$sSlug}' WHERE topic_id ='{$aTopic['topic_id']}'");
}
}
/**
* Конвертируем аватарки блогов
*/
$iPage = 1;
$iLimitCount = 50;
$iLimitStart = 0;
while ($aBlogs = $this->dbSelect("SELECT * FROM prefix_blog WHERE blog_avatar <> '' and blog_avatar <> '0' and blog_avatar IS NOT NULL LIMIT {$iLimitStart},{$iLimitCount}")) {
$iPage++;
$iLimitStart = ($iPage - 1) * $iLimitCount;
foreach ($aBlogs as $aBlog) {
$sAvatar = $aBlog['blog_avatar'];
if (strpos($sAvatar, 'http') === 0) {
$sAvatar = preg_replace('#_\d{1,3}x\d{1,3}(\.\w{3,5})$#i', '\\1', $sAvatar);
$sFileSource = $this->convertPathWebToServer($sAvatar);
/**
* Формируем список старых изображений для удаления
*/
$sMask = pathinfo($sFileSource,
PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR . pathinfo($sFileSource,
PATHINFO_FILENAME) . '_[0-9]*';
$aFilesForRemove = array();
if ($aPaths = glob($sMask)) {
foreach ($aPaths as $sPath) {
$aFilesForRemove[$sPath] = $sPath;
}
}
/**
* Ресайзим к новым размерам
*/
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 500)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_500x500crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 100)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_100x100crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 64)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_64x64crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 48)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_48x48crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 24)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_24x24crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
/**
* Удаляем старые
*/
foreach ($aFilesForRemove as $sFileRemove) {
@unlink($sFileRemove);
}
/**
* Меняем путь до аватара
*/
$sAvatar = '[relative]' . str_replace(dirname(dirname(INSTALL_DIR)), '', $sFileSource);
$sAvatar = mysqli_escape_string($this->rDbLink, $sAvatar);
$this->dbQuery("UPDATE prefix_blog SET blog_avatar = '{$sAvatar}' WHERE blog_id ='{$aBlog['blog_id']}'");
}
}
}
}
/**
* Конвертируем аватарки и фото пользователей
* Дополнительно добавляем роль для прав
*/
/**
* Получаем текущий список админов
*/
$aUserAdmin = array();
if ($this->dbCheckTable("prefix_user_administrator")) {
if ($aAdmins = $this->dbSelect("SELECT * FROM prefix_user_administrator ")) {
foreach ($aAdmins as $aRow) {
$aUserAdmin[] = $aRow['user_id'];
}
}
}
$iPage = 1;
$iLimitCount = 50;
$iLimitStart = 0;
while ($aUsers = $this->dbSelect("SELECT * FROM prefix_user LIMIT {$iLimitStart},{$iLimitCount}")) {
$iPage++;
$iLimitStart = ($iPage - 1) * $iLimitCount;
foreach ($aUsers as $aUser) {
$sAvatar = $aUser['user_profile_avatar'];
$sPhoto = $aUser['user_profile_foto'];
/**
* Аватарки
*/
if (strpos($sAvatar, 'http') === 0) {
$sAvatar = preg_replace('#_\d{1,3}x\d{1,3}(\.\w{3,5})$#i', '\\1', $sAvatar);
$sFileSource = $this->convertPathWebToServer($sAvatar);
/**
* Формируем список старых изображений для удаления
*/
$sMask = pathinfo($sFileSource,
PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR . pathinfo($sFileSource,
PATHINFO_FILENAME) . '_[0-9]*';
$aFilesForRemove = array();
if ($aPaths = glob($sMask)) {
foreach ($aPaths as $sPath) {
$aFilesForRemove[$sPath] = $sPath;
}
}
/**
* Ресайзим к новым размерам
*/
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 100)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_100x100crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 64)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_64x64crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 48)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_48x48crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
if ($oImage = $this->createImageObject($sFileSource)) {
if ($this->cropImage($oImage, 1) and $this->resizeImage($oImage, 24)) {
if ($sFileSave = $this->saveImage($oImage, $sFileSource, '_24x24crop')) {
unset($aFilesForRemove[$sFileSave]);
}
}
}
/**
* Удаляем старые
*/
foreach ($aFilesForRemove as $sFileRemove) {
@unlink($sFileRemove);
}
/**
* Меняем путь до аватара
*/
$sAvatar = '[relative]' . str_replace(dirname(dirname(INSTALL_DIR)), '', $sFileSource);
}
}
/**
* Фото
*/
if (strpos($sPhoto, 'http') === 0) {
$sFileSource = $this->convertPathWebToServer($sPhoto);
/**
* Меняем путь до аватара
*/
$sPhoto = '[relative]' . str_replace(dirname(dirname(INSTALL_DIR)), '', $sFileSource);
}
/**
* Права
*/
if (!$this->dbSelectOne("SELECT * FROM prefix_rbac_role_user WHERE user_id = '{$aUser['user_id']}' and role_id = 2 ")) {
/**
* Добавляем
*/
$aFields = array(
'user_id' => $aUser['user_id'],
'role_id' => 2,
'date_create' => date("Y-m-d H:i:s"),
);
$this->dbInsertQuery('prefix_rbac_role_user', $aFields);
}
/**
* Timezone
*/
$sTzName = null;
if ($aUser['user_settings_timezone']) {
$sTzName = $this->convertTzOffsetToName($aUser['user_settings_timezone']);
}
/**
* Реферальный код
*/
$sReferralCode = $aUser['user_referral_code'];
if (!$sReferralCode) {
$sReferralCode = md5($aUser['user_id'] . '_' . mt_rand());
}
/**
* Админы
*/
$isAdmin = 0;
if (in_array($aUser['user_id'], $aUserAdmin) or $aUser['user_admin']) {
$isAdmin = 1;
}
/**
* Сохраняем в БД
*/
$sAvatar = mysqli_escape_string($this->rDbLink, $sAvatar);
$sPhoto = mysqli_escape_string($this->rDbLink, $sPhoto);
$this->dbQuery("UPDATE prefix_user SET user_admin = '{$isAdmin}' , user_referral_code = '{$sReferralCode}' , user_settings_timezone = " . ($sTzName ? "'{$sTzName}'" : 'null') . " , user_profile_avatar = '{$sAvatar}', user_profile_foto = '{$sPhoto}' WHERE user_id ='{$aUser['user_id']}'");
/**
* Удаляем таблицы
*/
if ($this->dbCheckTable("prefix_user_administrator")) {
$this->dbQuery('DROP TABLE prefix_user_administrator');
}
}
}
if ($this->getErrors()) {
return $this->addError(join('<br/>', $aErrors));
}
return true;
}
return $this->addError(join('<br/>', $aErrors));
}
protected function convertTzOffsetToName($fOffset)
{
$fOffset *= 3600;
$aAbbrarray = DateTimeZone::listAbbreviations();
foreach ($aAbbrarray as $aAbbr) {
foreach ($aAbbr as $aCity) {
if ($aCity['offset'] == $fOffset && $aCity['timezone_id']) {
$oNow = new DateTime(null, new DateTimeZone($aCity['timezone_id']));
if ($oNow->getOffset() == $aCity['offset']) {
return $aCity['timezone_id'];
}
}
}
}
return false;
}
protected function convertPathWebToServer($sFile)
{
/**
* Конвертируем в серверный
*/
if (preg_match('#^http.*(\/uploads\/images\/.*)$#i', $sFile, $aMatch)) {
$sFile = dirname(dirname(INSTALL_DIR)) . str_replace('/', DIRECTORY_SEPARATOR, $aMatch[1]);
}
return $sFile;
}
protected function createImageObject($sFile)
{
try {
$oImagine = new \Imagine\Gd\Imagine;
return $oImagine->open($sFile);
} catch (Exception $e) {
$this->addError($e->getMessage());
return false;
}
}
protected function cropImage($oImage, $fProp, $sPosition = 'center')
{
try {
$oBox = $oImage->getSize();
$iWidth = $oBox->getWidth();
$iHeight = $oBox->getHeight();
/**
* Если высота и ширина уже в нужных пропорциях, то возвращаем изначальный вариант
*/
$iProp = round($fProp, 2);
if (round($iWidth / $iHeight, 2) == $iProp) {
return $this;
}
/**
* Вырезаем прямоугольник из центра
*/
if (round($iWidth / $iHeight, 2) <= $iProp) {
$iNewWidth = $iWidth;
$iNewHeight = round($iNewWidth / $iProp);
} else {
$iNewHeight = $iHeight;
$iNewWidth = $iNewHeight * $iProp;
}
$oBoxCrop = new Imagine\Image\Box($iNewWidth, $iNewHeight);
if ($sPosition == 'center') {
$oPointStart = new Imagine\Image\Point(($iWidth - $iNewWidth) / 2, ($iHeight - $iNewHeight) / 2);
} else {
$oPointStart = new Imagine\Image\Point(0, 0);
}
$oImage->crop($oPointStart, $oBoxCrop);
return true;
} catch (Exception $e) {
$this->addError($e->getMessage());
return false;
}
}
protected function resizeImage($oImage, $iWidthDest, $iHeightDest = null, $bForcedMinSize = true)
{
try {
$oBox = $oImage->getSize();
if ($bForcedMinSize) {
if ($iWidthDest and $iWidthDest > $oBox->getWidth()) {
$iWidthDest = $oBox->getWidth();
}
if ($iHeightDest and $iHeightDest > $oBox->getHeight()) {
$iHeightDest = $oBox->getHeight();
}
}
if (!$iHeightDest) {
/**
* Производим пропорциональное уменьшение по ширине
*/
$oBoxResize = $oBox->widen($iWidthDest);
} elseif (!$iWidthDest) {
/**
* Производим пропорциональное уменьшение по высоте
*/
$oBoxResize = $oBox->heighten($iHeightDest);
} else {
$oBoxResize = new Imagine\Image\Box($iWidthDest, $iHeightDest);
}
$oImage->resize($oBoxResize);
return true;
} catch (Exception $e) {
$this->addError($e->getMessage());
return false;
}
}
protected function saveImage($oImage, $sFileSource, $sFilePostfix)
{
$sDir = pathinfo($sFileSource, PATHINFO_DIRNAME);
$sName = pathinfo($sFileSource, PATHINFO_FILENAME);
$sFormat = pathinfo($sFileSource, PATHINFO_EXTENSION);
$sFile = $sDir . DIRECTORY_SEPARATOR . $sName . $sFilePostfix . '.' . $sFormat;
try {
$oImage->save($sFile, array(
'format' => $sFormat,
'quality' => 95,
));
return $sFile;
} catch (Exception $e) {
$this->addError($e->getMessage());
// TODO: fix exception for Gd driver
if (strpos($e->getFile(), 'Imagine' . DIRECTORY_SEPARATOR . 'Gd')) {
restore_error_handler();
}
return false;
}
}
protected function GetUniqueTopicSlug($sSlug, $iSkipTopicId = null)
{
$iPostfix = 0;
do {
$sUrl = $sSlug . ($iPostfix ? '-' . $iPostfix : '');
$iPostfix++;
} while (($aTopic = $this->getTopicBySlug($sUrl)) and (is_null($iSkipTopicId) or $iSkipTopicId != $aTopic['topic_id']));
return $sUrl;
}
protected function getTopicBySlug($sUrl)
{
$sUrl = mysqli_escape_string($this->rDbLink, $sUrl);
return $this->dbSelectOne("SELECT * FROM prefix_topic WHERE topic_slug = '{$sUrl}' ");
}
}

View file

@ -0,0 +1,64 @@
<?php
class InstallTemplate
{
protected $aVars = array();
protected $sTemplate = null;
protected $oParent = null;
public function __construct($sTemplate, $aVars = array())
{
$this->sTemplate = $sTemplate;
$this->assign($aVars);
}
public function assign($mName, $mValue = null)
{
if (is_array($mName)) {
$this->aVars = array_merge($this->aVars, $mName);
} else {
$this->aVars[$mName] = $mValue;
}
}
public function get($sName = null, $mDefault = null)
{
if (is_null($sName)) {
return $this->aVars;
}
return isset($this->aVars[$sName]) ? $this->aVars[$sName] : $mDefault;
}
public function getFromParent($sName = null, $mDefault = null)
{
if (!$this->oParent) {
return $mDefault;
}
return $this->oParent->get($sName, $mDefault);
}
public function render()
{
ob_start();
include($this->getPathTemplate());
$sResult = ob_get_contents();
ob_end_clean();
return $sResult;
}
public function setParent($oTemplate)
{
$this->oParent = $oTemplate;
}
public function lang($sName)
{
return InstallCore::getLang($sName);
}
protected function getPathTemplate()
{
return INSTALL_DIR . DIRECTORY_SEPARATOR . 'frontend' . DIRECTORY_SEPARATOR . 'template' . DIRECTORY_SEPARATOR . $this->sTemplate;
}
}

View file

@ -0,0 +1,71 @@
<?php
define('INSTALL_DIR', dirname(__FILE__));
define('VERSION', '2.0.1');
function install_func_underscore($sStr)
{
return strtolower(preg_replace('/([^A-Z])([A-Z])/', "$1_$2", $sStr));
}
function install_func_camelize($sStr)
{
$aParts = explode('_', $sStr);
$sCamelized = '';
foreach ($aParts as $sPart) {
$sCamelized .= ucfirst($sPart);
}
return $sCamelized;
}
/**
* Загрузка классов инсталлятора
* пример - InstallCore, InstallStepInit
*
* @param $sClassName
* @return bool
*/
function install_autoload($sClassName)
{
$aPath = explode('_', install_func_underscore($sClassName));
if (count($aPath) >= 2 and $aPath[0] == 'install') {
array_shift($aPath);
if ($aPath[0] == 'step' and count($aPath) > 1) {
array_shift($aPath);
$sDir = 'step';
$sName = ucfirst(install_func_camelize(join('_', $aPath)));
$sName{0} = strtolower($sName{0});
} else {
$sName = array_pop($aPath);
$sDir = join(DIRECTORY_SEPARATOR, $aPath);
}
$sPath = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'backend' . DIRECTORY_SEPARATOR . ($sDir ? $sDir . DIRECTORY_SEPARATOR : '') . $sName . '.php';
if (file_exists($sPath)) {
require_once($sPath);
return true;
}
}
/**
* Проверяем соответствие PSR-0 для библиотек фреймворка
*/
$sClassName = ltrim($sClassName, '\\');
$sFileName = '';
$sNameSpace = '';
if ($iLastNsPos = strrpos($sClassName, '\\')) {
$sNameSpace = substr($sClassName, 0, $iLastNsPos);
$sClassName = substr($sClassName, $iLastNsPos + 1);
$sFileName = str_replace('\\', DIRECTORY_SEPARATOR, $sNameSpace) . DIRECTORY_SEPARATOR;
}
$sFileName .= str_replace('_', DIRECTORY_SEPARATOR, $sClassName) . '.php';
$sFileName = dirname(dirname(INSTALL_DIR)) . DIRECTORY_SEPARATOR . 'framework' . DIRECTORY_SEPARATOR . 'libs' . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . $sFileName;
if (file_exists($sFileName)) {
require_once($sFileName);
return true;
}
return false;
}
/**
* Подключаем загрузкик классов
*/
spl_autoload_register('install_autoload');

View file

@ -0,0 +1,73 @@
<?php
/**
* Консольный запуск шагов инсталляции
* Позволяет выполнить обновление на новую версию через консоль, это актуально при большой БД
* Запускать шаги желательно от имени пользователя под которым работает веб-сервер, это поможет избежать проблем с правами доступа.
*
* Пример запуска обновления с 1.0.3 версии LS до 2.0.0:
* php -f ./console.php run update_version 1.0.3
*/
error_reporting(E_ALL);
ini_set('display_errors', 1);
set_time_limit(0);
require_once('bootstrap.php');
function console_echo($sMsg, $bExit = false)
{
echo("{$sMsg} \n");
if ($bExit) {
exit();
}
}
/**
* Init core
*/
$oInstall = new InstallCore(array('fake' => array()));
/**
* Получаем параметры
*/
$aArgs = isset($_SERVER['argv']) ? $_SERVER['argv'] : array();
if (count($aArgs) == 1) {
console_echo(InstallCore::getLang('console.command_empty'), true);
}
/**
* Ищем команду
*/
$sCommand = strtolower($aArgs[1]);
if ($sCommand == 'run') {
if (!isset($aArgs[2])) {
console_echo(InstallCore::getLang('console.command.run.params_step_empty'), true);
}
$sStep = install_func_camelize($aArgs[2]);
$sClass = 'InstallStep' . ucfirst($sStep);
if (!class_exists($sClass)) {
console_echo(InstallCore::getLang('Not found step ' . $sStep), true);
}
/**
* Хардкодим параметр для шага обновления
* TODO: убрать и переделать на нормальную консольную утилиту
*/
$_REQUEST['from_version'] = isset($aArgs[3]) ? $aArgs[3] : '';
/**
* Создаем объект шага и запускаем его
*/
$oStep = new $sClass('fake', array());
if ($oStep->process()) {
console_echo(InstallCore::getLang('console.command_successful'));
} else {
$aErrors = $oStep->getErrors();
if ($aErrors) {
$sMsgError = join("\n", $aErrors);
} else {
$sMsgError = InstallCore::getLang('console.command_failed');
}
console_echo($sMsgError, true);
}
} else {
console_echo(InstallCore::getLang('console.command_empty'), true);
}

View file

@ -0,0 +1,13 @@
#!/bin/sh
DIRECTORY=$(cd "$(dirname "$0")"; pwd)
if [ ! -e "$DIRECTORY/../../config/config.local.php" ]; then
cp $DIRECTORY/../../config/config.local.php.dist $DIRECTORY/../../config/config.local.php
fi
chmod 777 $DIRECTORY/../../config/config.local.php
chmod 777 $DIRECTORY/../../tmp
chmod 777 $DIRECTORY/../../logs
chmod 777 $DIRECTORY/../../../uploads
chmod 777 $DIRECTORY/../../plugins

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,978 @@
ALTER TABLE `prefix_subscribe` ADD `user_id` INT( 11 ) UNSIGNED NULL DEFAULT NULL AFTER `target_id` ,
ADD INDEX ( `user_id` ) ;
CREATE TABLE IF NOT EXISTS `prefix_blog_category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pid` int(11) DEFAULT NULL,
`title` varchar(200) NOT NULL,
`url` varchar(100) NOT NULL,
`url_full` varchar(200) NOT NULL,
`sort` int(11) NOT NULL DEFAULT '0',
`count_blogs` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `pid` (`pid`),
KEY `count_blogs` (`count_blogs`),
KEY `title` (`title`),
KEY `url` (`url`),
KEY `url_full` (`url_full`),
KEY `sort` (`sort`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `prefix_blog_category`
ADD CONSTRAINT `prefix_blog_category_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `prefix_blog_category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE `prefix_blog` ADD `category_id` INT NULL DEFAULT NULL AFTER `user_owner_id` ,
ADD INDEX ( `category_id` ) ;
ALTER TABLE `prefix_blog` ADD FOREIGN KEY ( `category_id` ) REFERENCES `prefix_blog_category` (
`id`
) ON DELETE CASCADE ON UPDATE CASCADE ;
-- 01-10-2013
--
-- Структура таблицы `prefix_property`
--
CREATE TABLE IF NOT EXISTS `prefix_property` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`target_type` varchar(50) NOT NULL,
`type` enum('int','float','varchar','text','checkbox','select','tags','video_link') NOT NULL DEFAULT 'text',
`code` varchar(50) NOT NULL,
`title` varchar(250) NOT NULL,
`date_create` datetime NOT NULL,
`sort` int(11) NOT NULL,
`validate_rules` varchar(500) DEFAULT NULL,
`params` text,
PRIMARY KEY (`id`),
KEY `target_type` (`target_type`),
KEY `code` (`code`),
KEY `type` (`type`),
KEY `date_create` (`date_create`),
KEY `sort` (`sort`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_property_value`
--
CREATE TABLE IF NOT EXISTS `prefix_property_value` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`property_type` varchar(30) NOT NULL,
`target_type` varchar(50) NOT NULL,
`target_id` int(11) NOT NULL,
`value_int` int(11) DEFAULT NULL,
`value_float` float(11,2) DEFAULT NULL,
`value_varchar` varchar(250) DEFAULT NULL,
`value_text` text,
`data` text,
PRIMARY KEY (`id`),
KEY `property_id` (`property_id`),
KEY `target_type` (`target_type`),
KEY `target_id` (`target_id`),
KEY `value_int` (`value_int`),
KEY `property_type` (`property_type`),
KEY `value_float` (`value_float`),
KEY `value_varchar` (`value_varchar`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_property_value_tag`
--
CREATE TABLE IF NOT EXISTS `prefix_property_value_tag` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`target_type` varchar(50) NOT NULL,
`target_id` int(11) NOT NULL,
`text` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
KEY `target_type` (`target_type`),
KEY `target_id` (`target_id`),
KEY `text` (`text`),
KEY `property_id` (`property_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 29-10-2013
--
-- Структура таблицы `prefix_property_select`
--
CREATE TABLE IF NOT EXISTS `prefix_property_select` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`target_type` varchar(50) NOT NULL,
`value` varchar(250) NOT NULL,
`sort` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `property_id` (`property_id`),
KEY `target_type` (`target_type`),
KEY `sort` (`sort`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_property_value_select`
--
CREATE TABLE IF NOT EXISTS `prefix_property_value_select` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`property_id` int(11) NOT NULL,
`target_type` varchar(50) NOT NULL,
`target_id` int(11) NOT NULL,
`select_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `target_type` (`target_type`),
KEY `target_id` (`target_id`),
KEY `property_id` (`property_id`),
KEY `select_id` (`select_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `prefix_media` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) DEFAULT NULL,
`type` int(11) NOT NULL,
`file_path` varchar(500) NOT NULL,
`file_name` varchar(500) NOT NULL,
`file_size` int(11) NOT NULL,
`width` int(11) NOT NULL,
`height` int(11) NOT NULL,
`date_add` datetime NOT NULL,
`data` text NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `type` (`type`),
KEY `file_size` (`file_size`),
KEY `width` (`width`),
KEY `height` (`height`),
KEY `date_add` (`date_add`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_media_target`
--
CREATE TABLE IF NOT EXISTS `prefix_media_target` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`media_id` int(11) NOT NULL,
`target_id` int(11) DEFAULT NULL,
`target_type` varchar(50) NOT NULL,
`target_tmp` varchar(50) DEFAULT NULL,
`date_add` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `media_id` (`media_id`),
KEY `target_id` (`target_id`),
KEY `target_type` (`target_type`),
KEY `target_tmp` (`target_tmp`),
KEY `date_add` (`date_add`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Ограничения внешнего ключа сохраненных таблиц
--
--
-- Ограничения внешнего ключа таблицы `prefix_media_target`
--
ALTER TABLE `prefix_media_target`
ADD CONSTRAINT `prefix_media_target_ibfk_1` FOREIGN KEY (`media_id`) REFERENCES `prefix_media` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- 10-01-2014
ALTER TABLE `prefix_topic` CHANGE `topic_type` `topic_type` VARCHAR( 50 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'topic';
-- 11-01-2014
CREATE TABLE IF NOT EXISTS `prefix_topic_type` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) NOT NULL,
`name_many` varchar(250) NOT NULL,
`code` varchar(50) NOT NULL,
`allow_remove` tinyint(1) NOT NULL DEFAULT '0',
`date_create` datetime NOT NULL,
`state` tinyint(4) NOT NULL DEFAULT '1',
`params` text,
PRIMARY KEY (`id`),
KEY `code` (`code`),
KEY `state` (`state`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 12.01.2014
ALTER TABLE `prefix_topic_type` ADD `sort` INT NOT NULL DEFAULT '0' AFTER `state` ,
ADD INDEX ( `sort` ) ;
-- 12.01.2014
ALTER TABLE `prefix_property` ADD `description` VARCHAR( 500 ) NOT NULL AFTER `title` ;
-- 23.01.2014
--
-- Структура таблицы `prefix_property_target`
--
CREATE TABLE IF NOT EXISTS `prefix_property_target` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(50) NOT NULL,
`date_create` datetime NOT NULL,
`date_update` datetime DEFAULT NULL,
`state` tinyint(4) NOT NULL DEFAULT '1',
`params` text NOT NULL,
PRIMARY KEY (`id`),
KEY `type` (`type`),
KEY `date_create` (`date_create`),
KEY `date_update` (`date_update`),
KEY `state` (`state`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 25.01.2014
--
-- Структура таблицы `prefix_user_complaint`
--
CREATE TABLE IF NOT EXISTS `prefix_user_complaint` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`target_user_id` int(11) unsigned NOT NULL,
`user_id` int(11) unsigned NOT NULL,
`type` varchar(50) NOT NULL,
`text` text NOT NULL,
`date_add` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `target_user_id` (`target_user_id`),
KEY `type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Ограничения внешнего ключа сохраненных таблиц
--
--
-- Ограничения внешнего ключа таблицы `prefix_user_complaint`
--
ALTER TABLE `prefix_user_complaint`
ADD CONSTRAINT `prefix_user_complaint_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `prefix_user` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `prefix_user_complaint_ibfk_1` FOREIGN KEY (`target_user_id`) REFERENCES `prefix_user` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- 27.01.2014
--
-- Структура таблицы `prefix_rbac_permission`
--
CREATE TABLE IF NOT EXISTS `prefix_rbac_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(50) NOT NULL,
`title` varchar(250) NOT NULL,
`msg_error` varchar(250) NOT NULL,
`date_create` datetime NOT NULL,
`state` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `code` (`code`),
KEY `date_create` (`date_create`),
KEY `state` (`state`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_rbac_role`
--
CREATE TABLE IF NOT EXISTS `prefix_rbac_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pid` int(11) DEFAULT NULL,
`code` varchar(50) NOT NULL,
`title` varchar(250) NOT NULL,
`date_create` datetime NOT NULL,
`state` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `pid` (`pid`),
KEY `state` (`state`),
KEY `date_create` (`date_create`),
KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_rbac_role_permission`
--
CREATE TABLE IF NOT EXISTS `prefix_rbac_role_permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`role_id` int(11) NOT NULL,
`permission_id` int(11) NOT NULL,
`date_create` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `role_id` (`role_id`),
KEY `permission_id` (`permission_id`),
KEY `date_create` (`date_create`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_rbac_user_role`
--
CREATE TABLE IF NOT EXISTS `prefix_rbac_user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) unsigned NOT NULL,
`role_id` int(11) NOT NULL,
`date_create` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `role_id` (`role_id`),
KEY `date_create` (`date_create`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Ограничения внешнего ключа сохраненных таблиц
--
--
-- Ограничения внешнего ключа таблицы `prefix_rbac_role_permission`
--
ALTER TABLE `prefix_rbac_role_permission`
ADD CONSTRAINT `prefix_rbac_role_permission_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `prefix_rbac_role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Ограничения внешнего ключа таблицы `prefix_rbac_user_role`
--
ALTER TABLE `prefix_rbac_user_role`
ADD CONSTRAINT `prefix_rbac_user_role_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `prefix_user` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `prefix_rbac_user_role_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `prefix_rbac_role` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- 28.01.2014
ALTER TABLE `prefix_user_complaint` ADD `state` TINYINT NOT NULL DEFAULT '1',
ADD INDEX ( `state` ) ;
-- 31.01.2014
--
-- Структура таблицы `prefix_storage`
--
CREATE TABLE IF NOT EXISTS `prefix_storage` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`key` varchar(50) NOT NULL,
`value` mediumtext NOT NULL,
`instance` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `key_instance` (`key`,`instance`),
KEY `instance` (`instance`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Дамп данных таблицы `prefix_property_target`
--
INSERT INTO `prefix_property_target` ( `type`, `date_create`, `date_update`, `state`, `params`) VALUES
('topic_topic', '2014-01-31 12:01:34', NULL, 1, 'a:2:{s:6:"entity";s:23:"ModuleTopic_EntityTopic";s:4:"name";s:35:"Топик - Стандартный";}');
-- 04.02.2014
--
-- Структура таблицы `prefix_poll`
--
CREATE TABLE IF NOT EXISTS `prefix_poll` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`target_type` varchar(50) NOT NULL,
`target_id` int(11) DEFAULT NULL,
`target_tmp` varchar(50) DEFAULT NULL,
`title` varchar(500) NOT NULL,
`count_answer_max` tinyint(4) NOT NULL DEFAULT '1',
`count_vote` int(11) NOT NULL DEFAULT '0',
`count_abstain` int(11) NOT NULL DEFAULT '0',
`date_create` datetime NOT NULL,
`date_end` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `target_type_target_id` (`target_type`,`target_id`),
KEY `target_tmp` (`target_tmp`),
KEY `count_vote` (`count_vote`),
KEY `count_abstain` (`count_abstain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_poll_answer`
--
CREATE TABLE IF NOT EXISTS `prefix_poll_answer` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`poll_id` int(11) NOT NULL,
`title` varchar(500) CHARACTER SET utf8 NOT NULL,
`count_vote` int(11) NOT NULL DEFAULT '0',
`date_create` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `poll_id` (`poll_id`),
KEY `count_vote` (`count_vote`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_poll_vote`
--
CREATE TABLE IF NOT EXISTS `prefix_poll_vote` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`poll_id` int(11) NOT NULL,
`answer_id` int(11) DEFAULT NULL,
`user_id` int(11) NOT NULL,
`date_create` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `poll_id` (`poll_id`),
KEY `answer_id` (`answer_id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Ограничения внешнего ключа сохраненных таблиц
--
--
-- Ограничения внешнего ключа таблицы `prefix_poll_answer`
--
ALTER TABLE `prefix_poll_answer`
ADD CONSTRAINT `prefix_poll_answer_ibfk_1` FOREIGN KEY (`poll_id`) REFERENCES `prefix_poll` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
--
-- Ограничения внешнего ключа таблицы `prefix_poll_vote`
--
ALTER TABLE `prefix_poll_vote`
ADD CONSTRAINT `prefix_poll_vote_ibfk_1` FOREIGN KEY (`poll_id`) REFERENCES `prefix_poll` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `prefix_poll_vote_ibfk_2` FOREIGN KEY (`answer_id`) REFERENCES `prefix_poll_answer` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
-- 05.02.2014
ALTER TABLE `prefix_poll_vote` DROP FOREIGN KEY `prefix_poll_vote_ibfk_2` ;
ALTER TABLE `prefix_poll_vote` DROP `answer_id` ;
ALTER TABLE `prefix_poll_vote` ADD `answers` VARCHAR( 500 ) NOT NULL AFTER `user_id` ;
-- 11.02.2014
ALTER TABLE `prefix_property` CHANGE `type` `type` VARCHAR( 50 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'text';
ALTER TABLE `prefix_property_value` ADD `value_date` DATETIME NULL DEFAULT NULL AFTER `value_varchar` ,
ADD INDEX ( `value_date` ) ;
-- 17.02.2014
ALTER TABLE `prefix_media` ADD `target_type` VARCHAR( 50 ) NOT NULL AFTER `type` ,
ADD INDEX ( `target_type` ) ;
-- 21.03.2014
ALTER TABLE `prefix_media_target` ADD `is_preview` TINYINT( 1 ) NOT NULL DEFAULT '0',
ADD INDEX ( `is_preview` ) ;
ALTER TABLE `prefix_media_target` ADD `data` TEXT NOT NULL ;
-- 24.04.2014
ALTER TABLE `prefix_comment` ADD `comment_text_source` TEXT NOT NULL AFTER `comment_text` ;
ALTER TABLE `prefix_comment` ADD `comment_date_edit` DATETIME NULL DEFAULT NULL AFTER `comment_date` ,
ADD INDEX ( `comment_date_edit` ) ;
ALTER TABLE `prefix_comment` ADD `comment_count_edit` INT NOT NULL DEFAULT '0' AFTER `comment_count_favourite` ,
ADD INDEX ( `comment_count_edit` ) ;
-- 29.05.2014
UPDATE `prefix_stream_user_type` set `event_type`='vote_comment_topic' WHERE `event_type`='vote_comment';
UPDATE `prefix_stream_event` set `event_type`='vote_comment_topic' WHERE `event_type`='vote_comment';
-- 26.05.2014
--
-- Структура таблицы `prefix_category`
--
CREATE TABLE IF NOT EXISTS `prefix_category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pid` int(11) DEFAULT NULL,
`type_id` int(11) NOT NULL,
`title` varchar(250) NOT NULL,
`description` text NOT NULL,
`url` varchar(250) NOT NULL,
`url_full` varchar(250) NOT NULL,
`date_create` datetime NOT NULL,
`order` int(11) NOT NULL,
`state` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `pid` (`pid`),
KEY `title` (`title`),
KEY `order` (`order`),
KEY `state` (`state`),
KEY `url` (`url`),
KEY `url_full` (`url_full`),
KEY `type_id` (`type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_category_target`
--
CREATE TABLE IF NOT EXISTS `prefix_category_target` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`category_id` int(11) NOT NULL,
`type_id` int(11) NOT NULL,
`target_type` varchar(50) NOT NULL,
`target_id` int(11) NOT NULL,
`date_create` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `target_type` (`target_type`),
KEY `target_id` (`target_id`),
KEY `category_id` (`category_id`),
KEY `type_id` (`type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Структура таблицы `prefix_category_type`
--
CREATE TABLE IF NOT EXISTS `prefix_category_type` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`target_type` varchar(50) NOT NULL,
`title` varchar(200) NOT NULL,
`state` tinyint(1) NOT NULL DEFAULT '1',
`date_create` datetime NOT NULL,
`date_update` datetime DEFAULT NULL,
`params` text NOT NULL,
PRIMARY KEY (`id`),
KEY `title` (`title`),
KEY `state` (`state`),
KEY `target_type` (`target_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 10.07.2014
ALTER TABLE `prefix_category` ADD `data` VARCHAR( 500 ) NOT NULL ;
ALTER TABLE `prefix_category` ADD `count_target` INT NOT NULL DEFAULT '0' AFTER `state` ,
ADD INDEX ( `count_target` ) ;
ALTER TABLE `prefix_blog_category` DROP FOREIGN KEY `prefix_blog_category_ibfk_1` ;
ALTER TABLE `prefix_blog` DROP FOREIGN KEY `prefix_blog_ibfk_1` ;
ALTER TABLE `prefix_blog` DROP `category_id` ;
DROP TABLE `prefix_blog_category`;
INSERT INTO `prefix_category_type` (
`id` ,
`target_type` ,
`title` ,
`state` ,
`date_create` ,
`date_update` ,
`params`
)
VALUES (
NULL , 'blog', 'Блоги', '1', '2014-07-14 00:00:00', NULL , ''
);
-- 22.07.2014
ALTER TABLE `prefix_topic` ADD `topic_date_edit_content` DATETIME NULL DEFAULT NULL AFTER `topic_date_edit` ,
ADD INDEX ( `topic_date_edit_content` ) ;
-- 23.07.2014
CREATE TABLE IF NOT EXISTS `prefix_cron_task` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(500) NOT NULL,
`method` varchar(500) NOT NULL,
`plugin` varchar(50) NOT NULL,
`state` tinyint(1) NOT NULL DEFAULT '1',
`count_run` int(11) NOT NULL DEFAULT '0',
`period_run` int(11) NOT NULL,
`date_create` datetime NOT NULL,
`date_run_last` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `count_run` (`count_run`),
KEY `state` (`state`),
KEY `plugin` (`plugin`),
KEY `method` (`method`(255)),
KEY `period_run` (`period_run`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 17.08.2014
INSERT INTO `prefix_cron_task` (`id`, `title`, `method`, `plugin`, `state`, `count_run`, `period_run`, `date_create`, `date_run_last`) VALUES (NULL, 'Отложенная отправка емайлов', 'Tools_SystemTaskNotify', '', '1', '0', '2', '2014-08-17 00:00:00', NULL);
INSERT INTO `prefix_cron_task` (`id`, `title`, `method`, `plugin`, `state`, `count_run`, `period_run`, `date_create`, `date_run_last`) VALUES (NULL, 'Удаление старого кеша данных', 'Cache_ClearOldCache', '', '1', '0', '1500', '2014-08-17 00:00:00', NULL);
-- 19.08.2014
ALTER TABLE `prefix_rbac_permission` ADD `plugin` VARCHAR( 50 ) NOT NULL AFTER `code` ,
ADD INDEX ( `plugin` );
CREATE TABLE IF NOT EXISTS `prefix_rbac_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(50) NOT NULL,
`title` varchar(250) NOT NULL,
PRIMARY KEY (`id`),
KEY `code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `prefix_rbac_role_permission` DROP FOREIGN KEY `prefix_rbac_role_permission_ibfk_1` ;
ALTER TABLE `prefix_rbac_user_role` DROP FOREIGN KEY `prefix_rbac_user_role_ibfk_2` ;
ALTER TABLE `prefix_rbac_user_role` DROP FOREIGN KEY `prefix_rbac_user_role_ibfk_1` ;
ALTER TABLE `prefix_rbac_permission` ADD `group_id` INT NULL DEFAULT NULL AFTER `id` ,
ADD INDEX ( `group_id` );
ALTER TABLE `prefix_rbac_group` ADD `date_create` DATETIME NOT NULL ;
RENAME TABLE `prefix_rbac_user_role` TO `prefix_rbac_role_user`;
-- 14.09.2014
CREATE TABLE IF NOT EXISTS `prefix_plugin_migration` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(50) NOT NULL,
`version` varchar(50) NOT NULL,
`date_create` datetime NOT NULL,
`file` varchar(500) NOT NULL,
PRIMARY KEY (`id`),
KEY `file` (`file`(255)),
KEY `code` (`code`),
KEY `version` (`version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `prefix_plugin_version` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`code` varchar(50) NOT NULL,
`version` varchar(50) NOT NULL,
`date_update` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `code` (`code`),
KEY `version` (`version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 07.12.2014
--
-- Дамп данных таблицы `prefix_rbac_group`
--
INSERT INTO `prefix_rbac_group` (`id`, `code`, `title`, `date_create`) VALUES
(1, 'topic', 'Топики', '2014-12-07 07:51:14'),
(2, 'blog', 'Блоги', '2014-12-07 07:51:41'),
(3, 'comment', 'Комментарии', '2014-12-07 07:52:01'),
(4, 'user', 'Пользователи', '2014-12-07 07:52:18');
--
-- Дамп данных таблицы `prefix_rbac_permission`
--
INSERT INTO `prefix_rbac_permission` (`id`, `group_id`, `code`, `plugin`, `title`, `msg_error`, `date_create`, `state`) VALUES
(1, 1, 'create_topic', '', 'rbac.permission.create_topic.title', 'rbac.permission.create_topic.error', '2014-08-31 07:59:56', 1),
(2, 2, 'create_blog', '', 'rbac.permission.create_blog.title', 'rbac.permission.create_blog.error', '2014-10-02 16:08:54', 1),
(3, 1, 'create_topic_comment', '', 'rbac.permission.create_topic_comment.title', 'rbac.permission.create_topic_comment.error', '2014-10-05 11:02:31', 1),
(4, 4, 'create_talk', '', 'rbac.permission.create_talk.title', 'rbac.permission.create_talk.error', '2014-10-05 11:54:22', 1),
(5, 4, 'create_talk_comment', '', 'rbac.permission.create_talk_comment.title', 'rbac.permission.create_talk_comment.error', '2014-10-05 14:08:15', 1),
(6, 3, 'vote_comment', '', 'rbac.permission.vote_comment.title', 'rbac.permission.vote_comment.error', '2014-10-05 14:31:29', 1),
(7, 2, 'vote_blog', '', 'rbac.permission.vote_blog.title', 'rbac.permission.vote_blog.error', '2014-10-05 16:51:53', 1),
(8, 1, 'vote_topic', '', 'rbac.permission.vote_topic.title', 'rbac.permission.vote_topic.error', '2014-10-05 17:22:56', 1),
(9, 4, 'vote_user', '', 'rbac.permission.vote_user.title', 'rbac.permission.vote_user.error', '2014-10-05 17:27:19', 1),
(10, 4, 'create_invite', '', 'rbac.permission.create_invite.title', 'rbac.permission.create_invite.error', '2014-10-05 17:28:46', 1),
(11, 3, 'create_comment_favourite', '', 'rbac.permission.create_comment_favourite.title', 'rbac.permission.create_comment_favourite.error', '2014-10-05 17:56:23', 1),
(12, 1, 'remove_topic', '', 'rbac.permission.remove_topic.title', 'rbac.permission.remove_topic.error', '2014-10-05 18:06:09', 1);
--
-- Дамп данных таблицы `prefix_rbac_role`
--
INSERT INTO `prefix_rbac_role` (`id`, `pid`, `code`, `title`, `date_create`, `state`) VALUES
(1, NULL, 'guest', 'Гость', '2014-08-22 00:00:00', 1),
(2, NULL, 'user', 'Пользователь', '2014-08-22 00:00:00', 1);
--
-- Дамп данных таблицы `prefix_rbac_role_permission`
--
INSERT INTO `prefix_rbac_role_permission` (`id`, `role_id`, `permission_id`, `date_create`) VALUES
(1, 2, 2, '2014-12-07 08:03:38'),
(2, 2, 7, '2014-12-07 08:03:44'),
(3, 2, 11, '2014-12-07 08:03:47'),
(4, 2, 6, '2014-12-07 08:03:49'),
(5, 2, 10, '2014-12-07 08:03:52'),
(6, 2, 4, '2014-12-07 08:03:55'),
(7, 2, 5, '2014-12-07 08:03:59'),
(8, 2, 9, '2014-12-07 08:04:02'),
(9, 2, 1, '2014-12-07 08:04:09'),
(10, 2, 3, '2014-12-07 08:04:11'),
(11, 2, 12, '2014-12-07 08:04:15'),
(12, 2, 8, '2014-12-07 08:04:17');
--
-- Дамп данных таблицы `prefix_rbac_role_user`
--
INSERT INTO `prefix_rbac_role_user` (`id`, `user_id`, `role_id`, `date_create`) VALUES
(1, 1, 2, '2014-12-07 08:06:11');
--
-- Дамп данных таблицы `prefix_topic_type`
--
INSERT INTO `prefix_topic_type` (`id`, `name`, `name_many`, `code`, `allow_remove`, `date_create`, `state`, `sort`, `params`) VALUES
(1, 'Топик', 'Топики', 'topic', 0, '2014-01-11 00:00:00', 1, 0, 'a:3:{s:10:"allow_poll";b:1;s:10:"allow_text";b:1;s:10:"allow_tags";b:1;}');
-- 17.12.2014
ALTER TABLE `prefix_user` CHANGE `user_settings_timezone` `user_settings_timezone` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
ALTER TABLE `prefix_user` ADD `user_admin` TINYINT(1) NOT NULL DEFAULT '0' AFTER `user_mail`, ADD INDEX (`user_admin`) ;
-- 27.12.2014
ALTER TABLE `prefix_session` DROP FOREIGN KEY `prefix_session_fk`;
ALTER TABLE `prefix_session` DROP INDEX user_id;
ALTER TABLE `prefix_session` ADD INDEX(`user_id`);
ALTER TABLE `prefix_session` ADD `session_date_close` DATETIME NULL DEFAULT NULL , ADD INDEX (`session_date_close`) ;
-- 28.12.2014
ALTER TABLE `prefix_blog` CHANGE `blog_type` `blog_type` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'personal';
ALTER TABLE `prefix_comment` CHANGE `target_type` `target_type` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'topic';
ALTER TABLE `prefix_comment_online` CHANGE `target_type` `target_type` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'topic';
ALTER TABLE `prefix_favourite` CHANGE `target_type` `target_type` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'topic';
ALTER TABLE `prefix_favourite_tag` CHANGE `target_type` `target_type` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_user` CHANGE `user_profile_sex` `user_profile_sex` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'other';
ALTER TABLE `prefix_vote` CHANGE `target_type` `target_type` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'topic';
ALTER TABLE `prefix_blog` DROP FOREIGN KEY `prefix_blog_fk`;
ALTER TABLE `prefix_blog_user` DROP FOREIGN KEY `prefix_blog_user_fk`;
ALTER TABLE `prefix_blog_user` DROP FOREIGN KEY `prefix_blog_user_fk1`;
ALTER TABLE `prefix_comment` DROP FOREIGN KEY `prefix_topic_comment_fk`;
ALTER TABLE `prefix_comment` DROP FOREIGN KEY `topic_comment_fk1`;
ALTER TABLE `prefix_comment_online` DROP FOREIGN KEY `prefix_topic_comment_online_fk1`;
ALTER TABLE `prefix_favourite` DROP FOREIGN KEY `prefix_favourite_target_fk`;
ALTER TABLE `prefix_favourite_tag` DROP FOREIGN KEY `prefix_favourite_tag_ibfk_1`;
ALTER TABLE `prefix_friend` DROP FOREIGN KEY `prefix_friend_from_fk`;
ALTER TABLE `prefix_friend` DROP FOREIGN KEY `prefix_friend_to_fk`;
ALTER TABLE `prefix_geo_city` DROP FOREIGN KEY `prefix_geo_city_ibfk_1`;
ALTER TABLE `prefix_geo_city` DROP FOREIGN KEY `prefix_geo_city_ibfk_2`;
ALTER TABLE `prefix_geo_region` DROP FOREIGN KEY `prefix_geo_region_ibfk_1`;
ALTER TABLE `prefix_geo_target` DROP FOREIGN KEY `prefix_geo_target_ibfk_1`;
ALTER TABLE `prefix_geo_target` DROP FOREIGN KEY `prefix_geo_target_ibfk_2`;
ALTER TABLE `prefix_geo_target` DROP FOREIGN KEY `prefix_geo_target_ibfk_3`;
ALTER TABLE `prefix_invite` DROP FOREIGN KEY `prefix_invite_fk`;
ALTER TABLE `prefix_invite` DROP FOREIGN KEY `prefix_invite_fk1`;
ALTER TABLE `prefix_media_target` DROP FOREIGN KEY `prefix_media_target_ibfk_1`;
ALTER TABLE `prefix_poll_answer` DROP FOREIGN KEY `prefix_poll_answer_ibfk_1`;
ALTER TABLE `prefix_poll_vote` DROP FOREIGN KEY `prefix_poll_vote_ibfk_1`;
ALTER TABLE `prefix_reminder` DROP FOREIGN KEY `prefix_reminder_fk`;
ALTER TABLE `prefix_stream_event` DROP FOREIGN KEY `prefix_stream_event_ibfk_1`;
ALTER TABLE `prefix_stream_subscribe` DROP FOREIGN KEY `prefix_stream_subscribe_ibfk_1`;
ALTER TABLE `prefix_stream_user_type` DROP FOREIGN KEY `prefix_stream_user_type_ibfk_1`;
ALTER TABLE `prefix_talk` DROP FOREIGN KEY `prefix_talk_fk`;
ALTER TABLE `prefix_talk_blacklist` DROP FOREIGN KEY `prefix_talk_blacklist_fk_user`;
ALTER TABLE `prefix_talk_blacklist` DROP FOREIGN KEY `prefix_talk_blacklist_fk_target`;
ALTER TABLE `prefix_talk_user` DROP FOREIGN KEY `prefix_talk_user_fk`;
ALTER TABLE `prefix_talk_user` DROP FOREIGN KEY `prefix_talk_user_fk1`;
ALTER TABLE `prefix_topic` DROP FOREIGN KEY `prefix_topic_fk`;
ALTER TABLE `prefix_topic` DROP FOREIGN KEY `prefix_topic_fk1`;
ALTER TABLE `prefix_topic_content` DROP FOREIGN KEY `prefix_topic_content_fk`;
ALTER TABLE `prefix_topic_read` DROP FOREIGN KEY `prefix_topic_read_fk`;
ALTER TABLE `prefix_topic_read` DROP FOREIGN KEY `prefix_topic_read_fk1`;
ALTER TABLE `prefix_topic_tag` DROP FOREIGN KEY `prefix_topic_tag_fk`;
ALTER TABLE `prefix_topic_tag` DROP FOREIGN KEY `prefix_topic_tag_fk1`;
ALTER TABLE `prefix_topic_tag` DROP FOREIGN KEY `prefix_topic_tag_fk2`;
ALTER TABLE `prefix_userfeed_subscribe` DROP FOREIGN KEY `prefix_userfeed_subscribe_ibfk_1`;
ALTER TABLE `prefix_user_changemail` DROP FOREIGN KEY `prefix_user_changemail_ibfk_1`;
ALTER TABLE `prefix_user_complaint` DROP FOREIGN KEY `prefix_user_complaint_ibfk_1`;
ALTER TABLE `prefix_user_complaint` DROP FOREIGN KEY `prefix_user_complaint_ibfk_2`;
ALTER TABLE `prefix_user_field_value` DROP FOREIGN KEY `prefix_user_field_value_ibfk_1`;
ALTER TABLE `prefix_user_field_value` DROP FOREIGN KEY `prefix_user_field_value_ibfk_2`;
ALTER TABLE `prefix_user_note` DROP FOREIGN KEY `prefix_user_note_ibfk_1`;
ALTER TABLE `prefix_user_note` DROP FOREIGN KEY `prefix_user_note_ibfk_2`;
ALTER TABLE `prefix_vote` DROP FOREIGN KEY `prefix_topic_vote_fk1`;
ALTER TABLE `prefix_wall` DROP FOREIGN KEY `prefix_wall_ibfk_1`;
ALTER TABLE `prefix_wall` DROP FOREIGN KEY `prefix_wall_ibfk_2`;
ALTER TABLE `prefix_comment` CHANGE `comment_user_ip` `comment_user_ip` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_session` CHANGE `session_ip_create` `session_ip_create` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_session` CHANGE `session_ip_last` `session_ip_last` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_subscribe` CHANGE `ip` `ip` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_talk` CHANGE `talk_user_ip` `talk_user_ip` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_topic` CHANGE `topic_user_ip` `topic_user_ip` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_user` CHANGE `user_ip_register` `user_ip_register` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_vote` CHANGE `vote_ip` `vote_ip` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '';
ALTER TABLE `prefix_wall` CHANGE `ip` `ip` VARCHAR(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_topic` ADD `topic_skip_index` TINYINT(1) NOT NULL DEFAULT '0' AFTER `topic_publish_index`, ADD INDEX (`topic_skip_index`) ;
-- 30.12.2014
ALTER TABLE `prefix_topic` ADD `blog_id2` INT UNSIGNED NULL DEFAULT NULL AFTER `blog_id`, ADD `blog_id3` INT UNSIGNED NULL DEFAULT NULL AFTER `blog_id2`, ADD `blog_id4` INT UNSIGNED NULL DEFAULT NULL AFTER `blog_id3`, ADD `blog_id5` INT UNSIGNED NULL DEFAULT NULL AFTER `blog_id4`;
ALTER TABLE `prefix_topic` ADD INDEX(`blog_id2`);
ALTER TABLE `prefix_topic` ADD INDEX(`blog_id3`);
ALTER TABLE `prefix_topic` ADD INDEX(`blog_id4`);
ALTER TABLE `prefix_topic` ADD INDEX(`blog_id5`);
-- 10.02.2015
ALTER TABLE `prefix_session` ADD `session_extra` TEXT NULL ;
-- 26.02.2015
ALTER TABLE `prefix_poll` ADD `is_guest_allow` TINYINT(1) NOT NULL DEFAULT '0' AFTER `title`, ADD `is_guest_check_ip` TINYINT(1) NOT NULL DEFAULT '0' AFTER `is_guest_allow`;
ALTER TABLE `prefix_poll_vote` ADD `guest_key` VARCHAR(32) NULL AFTER `user_id`, ADD `ip` VARCHAR(40) NOT NULL AFTER `guest_key`, ADD INDEX (`guest_key`) ;
ALTER TABLE `prefix_poll_vote` ADD INDEX(`ip`);
ALTER TABLE `prefix_poll_vote` CHANGE `user_id` `user_id` INT(11) NULL DEFAULT NULL;
-- 27.02.2015
DROP TABLE `prefix_invite`;
ALTER TABLE `prefix_user` ADD `user_referal_code` VARCHAR(32) NULL DEFAULT NULL AFTER `user_activate_key`, ADD INDEX (`user_referal_code`) ;
CREATE TABLE IF NOT EXISTS `prefix_invite_code` (
`id` int(11) NOT NULL,
`user_id` int(11) DEFAULT NULL,
`code` varchar(32) NOT NULL,
`date_create` datetime NOT NULL,
`date_expired` datetime DEFAULT NULL,
`count_allow_use` int(11) NOT NULL DEFAULT '1',
`count_use` int(11) NOT NULL DEFAULT '0',
`active` tinyint(1) NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `prefix_invite_use` (
`id` int(11) NOT NULL,
`type` tinyint(4) NOT NULL DEFAULT '1',
`code_id` int(11) DEFAULT NULL,
`from_user_id` int(11) DEFAULT NULL,
`to_user_id` int(11) NOT NULL,
`date_create` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
ALTER TABLE `prefix_invite_code`
ADD PRIMARY KEY (`id`), ADD KEY `code` (`code`), ADD KEY `count_allow_use` (`count_allow_use`), ADD KEY `count_use` (`count_use`), ADD KEY `active` (`active`), ADD KEY `date_create` (`date_create`), ADD KEY `user_id` (`user_id`);
ALTER TABLE `prefix_invite_use`
ADD PRIMARY KEY (`id`), ADD KEY `type` (`type`), ADD KEY `code_id` (`code_id`), ADD KEY `from_user_id` (`from_user_id`), ADD KEY `to_user_id` (`to_user_id`);
-- 07.03.2015
ALTER TABLE `prefix_user` CHANGE `user_referal_code` `user_referral_code` VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
-- 17.03.2015
ALTER TABLE `prefix_topic` ADD `topic_slug` VARCHAR(500) NOT NULL DEFAULT '' AFTER `topic_title`, ADD INDEX (`topic_slug`) ;
-- 27.03.2015
ALTER TABLE `prefix_topic` ADD `topic_date_publish` DATETIME NOT NULL AFTER `topic_date_edit_content`, ADD INDEX (`topic_date_publish`) ;
UPDATE `prefix_topic` SET `topic_date_publish` = `topic_date_add`;
-- 09.09.2015
ALTER TABLE `prefix_blog` ADD `blog_skip_index` TINYINT(1) NOT NULL DEFAULT '0' , ADD INDEX (`blog_skip_index`) ;
-- 30.09.2016
ALTER TABLE `prefix_subscribe` CHANGE `target_type` `target_type` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL;
ALTER TABLE `prefix_subscribe` CHANGE `target_id` `target_id` VARCHAR(50) NULL DEFAULT NULL;
ALTER TABLE `prefix_property` CHANGE `sort` `sort` INT(11) NOT NULL DEFAULT '0';
ALTER TABLE `prefix_property` CHANGE `description` `description` VARCHAR(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
ALTER TABLE `prefix_property_target` CHANGE `params` `params` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
ALTER TABLE `prefix_rbac_permission` CHANGE `msg_error` `msg_error` VARCHAR(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
ALTER TABLE `prefix_category` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_category` CHANGE `type_id` `type_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_category` CHANGE `pid` `pid` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_category_target` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_category_target` CHANGE `category_id` `category_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_category_target` CHANGE `type_id` `type_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_category_type` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_cron_task` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_geo_city` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_geo_city` CHANGE `country_id` `country_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_geo_city` CHANGE `region_id` `region_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_geo_country` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_geo_region` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_geo_region` CHANGE `country_id` `country_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_geo_target` CHANGE `geo_id` `geo_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_geo_target` CHANGE `country_id` `country_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_geo_target` CHANGE `region_id` `region_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_geo_target` CHANGE `city_id` `city_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_invite_code` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_invite_code` CHANGE `user_id` `user_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_invite_use` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_invite_use` CHANGE `code_id` `code_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_invite_use` CHANGE `from_user_id` `from_user_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_invite_use` CHANGE `to_user_id` `to_user_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_media` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_media` CHANGE `user_id` `user_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_media_target` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_media_target` CHANGE `media_id` `media_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_plugin_migration` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_plugin_version` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_poll` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_poll` CHANGE `user_id` `user_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_poll_answer` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_poll_answer` CHANGE `poll_id` `poll_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_poll_vote` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_poll_vote` CHANGE `poll_id` `poll_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_poll_vote` CHANGE `user_id` `user_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_property` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_property_select` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_property_select` CHANGE `property_id` `property_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_property_target` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_property_value` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_property_value` CHANGE `property_id` `property_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_property_value_select` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_property_value_select` CHANGE `property_id` `property_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_property_value_select` CHANGE `select_id` `select_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_property_value_tag` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_property_value_tag` CHANGE `property_id` `property_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_rbac_group` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_rbac_permission` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_rbac_permission` CHANGE `group_id` `group_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_rbac_role` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_rbac_role` CHANGE `pid` `pid` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_rbac_role_permission` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_rbac_role_permission` CHANGE `role_id` `role_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_rbac_role_permission` CHANGE `permission_id` `permission_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_rbac_role_user` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_rbac_role_user` CHANGE `role_id` `role_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_storage` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_stream_event` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_stream_subscribe` CHANGE `target_user_id` `target_user_id` INT(11) UNSIGNED NOT NULL;
ALTER TABLE `prefix_subscribe` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_talk_user` CHANGE `comment_id_last` `comment_id_last` INT(11) UNSIGNED NOT NULL DEFAULT '0';
ALTER TABLE `prefix_topic_type` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_user_changemail` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_user_complaint` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_user_field` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_user_field_value` CHANGE `field_id` `field_id` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_user_note` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_wall` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_wall` CHANGE `pid` `pid` INT(11) UNSIGNED NULL DEFAULT NULL;
ALTER TABLE `prefix_invite_code` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `prefix_invite_use` CHANGE `id` `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT;
-- 12.10.2016
ALTER TABLE `prefix_session` CHANGE `session_date_create` `session_date_create` DATETIME NULL DEFAULT NULL;
ALTER TABLE `prefix_reminder` CHANGE `reminder_date_used` `reminder_date_used` DATETIME NULL DEFAULT NULL;
-- 27.01.2017
ALTER TABLE `prefix_notify_task` ADD `notify_text_alt` TEXT NULL DEFAULT NULL AFTER `notify_text`;
-- 28.01.2017
ALTER TABLE `prefix_user` CHANGE `user_mail` `user_mail` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
-- 30.01.2017
ALTER TABLE `prefix_cron_task` ADD `time_start` TIME NULL DEFAULT NULL AFTER `date_run_last`, ADD INDEX (`time_start`);
ALTER TABLE `prefix_cron_task` ADD `time_end` TIME NULL DEFAULT NULL AFTER `time_start`, ADD INDEX (`time_end`);

View file

@ -0,0 +1,2 @@
-- 01.02.2017
ALTER TABLE `prefix_user` CHANGE `user_password` `user_password` VARCHAR(255) NOT NULL;

View file

@ -0,0 +1,16 @@
ALTER TABLE `prefix_page` CHANGE `page_id` `id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT ;
ALTER TABLE `prefix_page` CHANGE `page_pid` `pid` INT( 11 ) UNSIGNED NULL DEFAULT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_url` `url` VARCHAR( 50 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_url_full` `url_full` VARCHAR( 254 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_title` `title` VARCHAR( 200 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_text` `text` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_date_add` `date_add` DATETIME NOT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_date_edit` `date_edit` DATETIME NULL DEFAULT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_seo_keywords` `seo_keywords` VARCHAR( 250 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_seo_description` `seo_description` VARCHAR( 250 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_active` `active` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '1';
ALTER TABLE `prefix_page` CHANGE `page_main` `main` TINYINT( 1 ) UNSIGNED NOT NULL DEFAULT '0';
ALTER TABLE `prefix_page` CHANGE `page_sort` `sort` INT( 11 ) NOT NULL ;
ALTER TABLE `prefix_page` CHANGE `page_auto_br` `auto_br` TINYINT( 1 ) NOT NULL DEFAULT '1';
ALTER TABLE `prefix_page` ADD `text_source` TEXT NULL DEFAULT NULL AFTER `text`;
UPDATE `prefix_page` SET text_source = text;

View file

@ -0,0 +1,159 @@
<?php
return array(
'groups' => array(
'install' => array(
'title' => 'Новая установка',
'description' => '',
),
'update' => array(
'title' => 'Обновление со старой версии',
'description' => '',
),
),
'steps' => array(
'checkRequirements' => array(
'title' => 'Проверка требований для установки',
'writable_solution' => 'Для быстрого исправления ошибки с правами на запись выполните в консоли вашего сервера:',
'requirements' => array(
'php_version' => array(
'title' => 'Версия PHP',
'solution' => 'Минимально допустимая версия PHP 5.5. Обратитесь к хостингу для обновления версии.',
),
'safe_mode' => array(
'title' => 'SAFE MODE',
'solution' => 'Для корректной работы необходимо отключить SAFE MODE. Обратитесь к хостингу.',
),
'utf8' => array(
'title' => 'Поддержка UTF-8',
'solution' => 'Для корректной работы необходима поддержка UTF-8. Обратитесь к хостингу.',
),
'mbstring' => array(
'title' => 'Поддержка многобайтовых строк',
'solution' => 'Для корректной работы необходимо расширение mbstring. Обратитесь к хостингу.',
),
'mbstring_func_overload' => array(
'title' => 'Режим перегрузки строковых функций (func_overload)',
'solution' => 'Для корректной работы необходимо отключить перегрузку строковых функций. Обратитесь к хостингу.',
),
'xml' => array(
'title' => 'Поддержка XML (SimpleXML)',
'solution' => 'Для корректной работы необходимо расширение SimpleXML. Обратитесь к хостингу.',
),
'xdebug' => array(
'title' => 'Использование Xdebug',
'solution' => 'Для корректной работы необходимо отключить Xdebug или повысить значение <b>xdebug.max_nesting_level</b> до 1000. Обратитесь к хостингу.',
),
'dir_uploads' => array(
'title' => 'Каталог /uploads',
'solution' => '',
),
'dir_plugins' => array(
'title' => 'Каталог /application/plugins',
'solution' => '',
),
'dir_tmp' => array(
'title' => 'Каталог /application/tmp',
'solution' => '',
),
'dir_logs' => array(
'title' => 'Каталог /application/logs',
'solution' => '',
),
'file_config_local' => array(
'title' => 'Файл /application/config/config.local.php',
'solution' => 'Необходимо переименовать файл config.local.php.dist в config.local.php и дать ему права на запись',
),
),
),
'installDb' => array(
'title' => 'Настройка базы данных',
'form' => array(
'db_host' => array(
'title' => 'Имя сервера БД'
),
'db_port' => array(
'title' => 'Порт сервера БД'
),
'db_name' => array(
'title' => 'Название БД'
),
'db_create' => array(
'title' => 'Автоматически создать БД'
),
'db_user' => array(
'title' => 'Пользователь БД'
),
'db_passwd' => array(
'title' => 'Пароль от пользователя БД'
),
'db_prefix' => array(
'title' => 'Префикс таблиц в БД'
),
),
'errors' => array(
'db_not_found' => 'Не удалось выбрать необходимую базу данных, проверьте имя базы данных',
'db_not_create' => 'Не удалось создать базу данных, проверьте права доступа к БД',
'db_table_prefix' => 'Неверный формат префикс таблиц, допустимы только латински буквы, цифры и знак "_"',
),
),
'installAdmin' => array(
'title' => 'Данные администратора сайта',
'form' => array(
'mail' => array(
'title' => 'E-mail'
),
'passwd' => array(
'title' => 'Пароль'
),
),
'errors' => array(
'mail' => 'Неверный формат e-mail адреса',
'passwd' => 'Пароль должен быть от 3-х символов',
),
),
'installComplete' => array(
'title' => 'Установка завершена!',
),
'updateVersion' => array(
'title' => 'Выбор текущей версии',
'errors' => array(
'not_found_convert' => 'Для данной версии нет возможности обновления',
),
),
'updateDb' => array(
'title' => 'Настройка базы данных',
),
'updateComplete' => array(
'title' => 'Обновление успешно завершено!',
),
),
'config' => array(
'errors' => array(
'file_not_found' => 'Файл конфига не найден',
'file_not_writable' => 'Файл конфига не доступен для записи',
),
),
'db' => array(
'errors' => array(
'db_connect' => 'Не удалось установить соединение с БД. Проверьте параметры подключения к БД.',
'db_version' => 'Версия сервера БД должна быть от 5.0.0',
'db_query' => 'Не удалось выполнить запрос к БД',
),
),
'console' => array(
'command_empty' => 'Необходимо указать команду. Сейчас поддерживается только команда "run"',
'command_successful' => 'Команда успешно выполнена',
'command_failed' => 'Не удалось выполнить команду',
'command' => array(
'run' => array(
'params_step_empty' => 'Необходимо указать параметр: название шага',
'params_version_empty' => 'Необходимо указать параметр: номер текущей версии',
)
),
),
'install_reset' => 'Начать сначала',
'yes' => 'Да',
'no' => 'Нет',
'is_not_writable' => 'Не доступен для записи',
);

View file

@ -0,0 +1,70 @@
/**
* Уведомления
*
* @module ls/alerts
*
* @license GNU General Public License, version 2
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
* @author Denis Shakhov <denis.shakhov@gmail.com>
*/
.alert {
position: relative;
border: 1px solid #eed3d7;
background-color: #f2dede;
color: #b94a48;
padding: 10px 15px;
margin-bottom: 15px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.alert:last-child {
margin-bottom: 0;
}
.alert li {
margin-bottom: 5px;
}
/* Заголовок */
.alert-title {
margin-bottom: 5px;
font-size: 14px;
font-weight: bold;
}
/**
* @modifier error Ошибка
*/
.alert.alert--error {
background-color: #f2dede;
color: #b94a48;
border-color: #eed3d7;
}
/**
* @modifier success Успешно завершено
*/
.alert.alert--success {
background-color: #dff0d8;
color: #468847;
border-color: #d6e9c6;
}
/**
* @modifier info Информация
*/
.alert.alert--info {
background-color: #d9edf7;
color: #3a87ad;
border-color: #bce8f1;
}
/**
* @modifier empty Пусто
*/
.alert.alert--empty {
background-color: #fafafa;
color: #777;
border-color: #eee;
}

View file

@ -0,0 +1,82 @@
/**
* Buttons
*
* @module ls/button
*
* @license GNU General Public License, version 2
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
* @author Denis Shakhov <denis.shakhov@gmail.com>
*/
.button {
display: inline-block;
padding: 7px 13px;
margin: 0;
border: 1px solid #ddd;
text-align: center;
vertical-align: middle;
text-decoration: none;
font-size: 13px;
line-height: normal;
color: #444;
background: transparent;
font-family: Arial, sans-serif;
cursor: pointer;
position: relative;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
-webkit-transition: background .2s, color .2s;
-moz-transition: background .2s, color .2s;
transition: background .2s, color .2s;
}
.button:hover { text-decoration: none; background: #fafafa; color: #333; }
.button:active {
position: relative;
top: 1px;
}
.button:focus { outline: none; }
.button.active {
background: #eaeaea;
}
.button.pull-right { margin-left: 5px; }
/**
* Button Disabled
*/
.button.disabled,
.button.disabled:hover,
.button[disabled],
.button[disabled]:hover {
border-color: #ccc;
background: #eee;
color: #999;
}
.button.disabled:active,
.button[disabled]:active {
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
/**
* Button Primary
*/
.button--primary { border-color: #74A2FF; color: #777DFF; }
.button--primary:hover { background: #91B6FF; color: #fff; }
.button--primary.active { background: #006DCC; }
/**
* Button Large
*/
.button--large { height: 34px; font-size: 14px; }
a.button--large { padding-top: 8px; }
.button.button--large.button-icon { padding-left: 9px; padding-right: 9px; }

View file

@ -0,0 +1,67 @@
/**
* Forms
*
* @license GNU General Public License, version 2
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
* @author Denis Shakhov <denis.shakhov@gmail.com>
*/
/* Input Text */
select,
input[type="password"],
input[type="text"] {
padding: 7px 8px;
border: 1px solid #ddd;
vertical-align: middle;
border-radius: 3px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
input[type="text"]:focus,
input[type="password"]:focus {
border-color: #4d90fe;
-webkit-box-shadow: 0 2px 4px rgba(0,0,0,.07) inset, 0 0 3px #4d90fe;
box-shadow: 0 2px 4px rgba(0,0,0,.07) inset, 0 0 3px #4d90fe;
outline: none;
}
select,
input[type="password"],
input[type="text"] {
line-height: 18px;
}
/* Checkboxes */
input[type="checkbox"] {
position: relative;
top: 1px;
margin: 0 2px 0 1px;
}
form p {
margin-bottom: 25px;
}
form label {
display: block;
margin-bottom: 4px;
color: #444;
}
/* Note */
.note {
display: block;
margin-top: 3px;
font-size: 12px;
color: #aaa;
}
/* Placeholder */
:-moz-placeholder { color: #afafaf; }
::-moz-placeholder { color: #afafaf; opacity: 1; }
::-webkit-input-placeholder { color: #afafaf; }
:-ms-input-placeholder { color: #afafaf; }

View file

@ -0,0 +1,65 @@
/**
* Helpers
*
* @license GNU General Public License, version 2
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
* @author Denis Shakhov <denis.shakhov@gmail.com>
*/
/* Margins */
.mt-10 { margin-top: 10px !important; }
.mt-15 { margin-top: 15px !important; }
.mt-20 { margin-top: 20px !important; }
.mt-30 { margin-top: 30px !important; }
.mb-10 { margin-bottom: 10px !important; }
.mb-15 { margin-bottom: 15px !important; }
.mb-20 { margin-bottom: 20px !important; }
.mb-30 { margin-bottom: 30px !important; }
.m-0 { margin: 0 !important; }
/* Text Align */
.ta-c { text-align: center !important; }
.ta-r { text-align: right !important; }
/* Floats */
.fl-r, .float-right, .pull-right { float: right !important; }
.fl-l, .float-left, .pull-left { float: left !important; }
/* Clearfix */
.clearfix:before,
.clearfix:after { content: ""; display: table; line-height: 0; }
.clearfix:after { clear: both; }
/* Width */
.width-full { width: 100% !important; }
.width-50 { width: 50px !important; }
.width-100 { width: 100px !important; }
.width-150 { width: 150px !important; }
.width-200 { width: 200px !important; }
.width-250 { width: 250px !important; }
.width-300 { width: 300px !important; }
.width-350 { width: 350px !important; }
.width-400 { width: 400px !important; }
.width-450 { width: 450px !important; }
.width-500 { width: 500px !important; }
.width-550 { width: 550px !important; }
.width-600 { width: 600px !important; }
.width-650 { width: 650px !important; }
/* Loader */
/* TODO: Change gif */
.loading {
height: 100px;
margin-bottom: 20px;
background-image: url(../images/loader.gif);
background-position: 50% 50%;
background-repeat: no-repeat;
}

View file

@ -0,0 +1,88 @@
body {
font: 13px/1.3em Arial,sans-serif;
background: #fafafa;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Open Sans', Arial;
font-weight: 300;
}
a {
color: #1A80DB;
text-decoration: none;
}
a:hover {
color: #058;
}
/**
* Page header
*/
.page-header {
margin-bottom: 20px;
padding-bottom: 4px;
font-size: 18px;
border-bottom: 1px solid #eee;
}
.container {
max-width: 500px;
margin: 40px auto 40px;
padding: 30px;
background: #fff;
box-shadow: 0 1px 5px rgba(0,0,0,.3)
}
/**
* Header
*/
.header {
padding: 10px 20px;
margin-bottom: 30px;
text-align: center;
}
.header h1 {
font-size: 25px;
}
.header h2 {
margin-top: 5px;
font-size: 16px;
color: #777;
}
/**
* Content
*/
.step-buttons {
padding-top: 20px;
}
/**
* Complete
*/
.complete h2, .complete p {
text-align: center;
}
.complete h2 {
font-size: 18px;
margin-bottom: 15px;
}
/**
* Index
*/
.groups {
padding-bottom: 15px;
text-align: center;
}
.groups li {
margin-bottom: 10px;
font-size: 18px;
font-family: 'Open Sans', Arial;
}
.groups li:last-child {
margin-bottom: 0;
}

View file

@ -0,0 +1,397 @@
/* Adapted from git.io/normalize */
/* ==========================================================================
HTML5 display definitions
========================================================================== */
/**
* Correct `block` display not defined in IE 8/9.
*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
hgroup,
nav,
section,
summary {
display: block;
}
/**
* Correct `inline-block` display not defined in IE 8/9.
*/
audio,
canvas,
video {
display: inline-block;
}
/**
* Prevent modern browsers from displaying `audio` without controls.
* Remove excess height in iOS 5 devices.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Address styling not present in IE 8/9.
*/
[hidden] {
display: none;
}
/* ==========================================================================
Base
========================================================================== */
/**
* 1. Set default font family to sans-serif.
* 2. Prevent iOS text size adjust after orientation change, without disabling
* user zoom.
*/
html {
font-family: sans-serif; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
-ms-text-size-adjust: 100%; /* 2 */
}
/**
* Remove default margin.
*/
body {
margin: 0;
}
/* ==========================================================================
Links
========================================================================== */
/**
* Address `outline` inconsistency between Chrome and other browsers.
*/
a:focus {
outline: 0;
}
/**
* Improve readability when focused and also mouse hovered in all browsers.
*/
a:active,
a:hover {
outline: 0;
}
/* ==========================================================================
Typography
========================================================================== */
/**
* Address variable `h1` font size within `section` and `article` contexts in
* Firefox 4+, Safari 5, and Chrome.
*/
h1, h2, h3, h4, h5, h6 {
font-size: 1em;
line-height: 1.6em;
font-weight: normal;
margin: 0;
font-family: sans-serif;
}
p { margin: 0; }
/**
* Address styling not present in IE 8/9, Safari 5, and Chrome.
*/
abbr[title],
acronym[title] {
border-bottom: 1px dotted;
cursor: help;
}
/**
* Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome.
*/
b,
strong {
font-weight: bold;
}
/**
* Address styling not present in Safari 5 and Chrome.
*/
dfn {
font-style: italic;
}
/**
* Address styling not present in IE 8/9.
*/
mark {
background: #ff0;
color: #000;
}
/**
* Correct font family set oddly in Safari 5 and Chrome.
*/
code,
kbd,
pre,
samp {
font-family: monospace, serif;
font-size: 1em;
}
/**
* Improve readability of pre-formatted text in all browsers.
*/
/* pre {
white-space: pre;
white-space: pre-wrap;
word-wrap: break-word;
} */
/**
* Set consistent quote types.
*/
q {
quotes: "\201C" "\201D" "\2018" "\2019";
}
/**
* Address inconsistent and variable font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sup {
top: -0.5em;
}
sub {
bottom: -0.25em;
}
/* =============================================================================
Lists
========================================================================== */
ul, ol, dl, dd, dt { margin: 0; padding: 0; }
ul, ol {
list-style: none;
list-style-image: none;
}
/* ==========================================================================
Embedded content
========================================================================== */
/**
* Remove border when inside `a` element in IE 8/9.
*/
img {
border: 0;
}
/**
* Correct overflow displayed oddly in IE 9.
*/
svg:not(:root) {
overflow: hidden;
}
iframe {
border: 0;
}
/* ==========================================================================
Figures
========================================================================== */
/**
* Address margin not present in IE 8/9 and Safari 5.
*/
figure {
margin: 0;
}
/* ==========================================================================
Forms
========================================================================== */
/**
* Define consistent border, margin, and padding.
*/
fieldset {
border: 0;
margin: 0 2px;
padding: 0;
}
/**
* 1. Correct `color` not being inherited in IE 8/9.
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
*/
legend {
border: 0; /* 1 */
padding: 0; /* 2 */
}
/**
* 1. Correct font family not being inherited in all browsers.
* 2. Correct font size not being inherited in all browsers.
* 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.
*/
button,
input,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 2 */
margin: 0; /* 3 */
}
/**
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
* the UA stylesheet.
*/
button,
input {
line-height: normal;
}
/**
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
* and `video` controls.
* 2. Correct inability to style clickable `input` types in iOS.
* 3. Improve usability and consistency of cursor style between image-type
* `input` and others.
*/
button,
html input[type="button"], /* 1 */
input[type="reset"],
input[type="submit"] {
-webkit-appearance: button; /* 2 */
cursor: pointer; /* 3 */
}
/**
* Re-set default cursor for disabled elements.
*/
button[disabled],
html input[disabled] {
cursor: default;
}
/**
* 1. Address box sizing set to `content-box` in IE 8/9.
* 2. Remove excess padding in IE 8/9.
*/
input[type="checkbox"],
input[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome.
* 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome
* (include `-moz` to future-proof).
*/
input[type="search"] {
-webkit-appearance: textfield; /* 1 */
-moz-box-sizing: content-box;
-webkit-box-sizing: content-box; /* 2 */
box-sizing: content-box;
}
/**
* Remove inner padding and search cancel button in Safari 5 and Chrome
* on OS X.
*/
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* Remove inner padding and border in Firefox 4+.
*/
button::-moz-focus-inner,
input::-moz-focus-inner {
border: 0;
padding: 0;
}
/**
* 1. Remove default vertical scrollbar in IE 8/9.
* 2. Improve readability and alignment in all browsers.
*/
textarea {
overflow: auto; /* 1 */
vertical-align: top; /* 2 */
}
/* ==========================================================================
Tables
========================================================================== */
/**
* Remove most spacing between table cells.
*/
table {
border-collapse: collapse;
border-spacing: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,8 @@
var install = (function ($) {
this.goNextStep = function() {
$('#action_next').click();
};
return this;
}).call(install || {}, jQuery);

Some files were not shown because too many files have changed in this diff Show more