Initial commit - monorepo
This commit is contained in:
commit
6ee031045b
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
application/config/config.local.php
|
||||
application/logs
|
||||
uploads
|
||||
application/tmp
|
||||
application/plugins/admin
|
||||
application/plugins/
|
||||
application/install
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "framework"]
|
||||
path = framework
|
||||
url = https://github.com/livestreet/livestreet-framework.git
|
48
.travis.yml
Normal file
48
.travis.yml
Normal file
|
@ -0,0 +1,48 @@
|
|||
language: php
|
||||
|
||||
php:
|
||||
- 5.3
|
||||
- 5.4
|
||||
|
||||
before_script:
|
||||
# export virtual display
|
||||
- export DISPLAY=:99
|
||||
|
||||
# change application working folders for write access
|
||||
- chmod -R 0777 ./tmp
|
||||
- chmod -R 0777 ./uploads
|
||||
- chmod -R 0777 ./templates/cache/
|
||||
- chmod -R 0777 ./templates/compiled/
|
||||
- cp ./install/*.sql tests/fixtures/sql/
|
||||
- rm -rf ./install
|
||||
|
||||
# install required PHP stuff
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install php5 php5-cli php5-mysql php5-mcrypt php5-xsl php5-xdebug php-apc php5-gd php5-curl php5-intl mysql-server mysql-client
|
||||
|
||||
# launch apache, MySQL and PHPUnit Selenium installers
|
||||
- ./tests/travis/apache_setup.sh
|
||||
- ./tests/travis/mysql_setup.sh
|
||||
- mysql -u root -e "USE social_test; SHOW TABLES;" | wc -l
|
||||
- cp ./config/config.test.php.dist config/config.test.php
|
||||
- cp ./config/config.test.php.dist config/config.local.php
|
||||
- sudo sed -i s/sql-mode/#sql-mode/ /etc/mysql/my.cnf
|
||||
- sudo /etc/init.d/mysql restart
|
||||
- sleep 5
|
||||
|
||||
# get HTML of main page (for debug)
|
||||
|
||||
- firefox --version
|
||||
- wget -S http://livestreet.test -O /dev/null
|
||||
|
||||
# start virtual display
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- sleep 5
|
||||
|
||||
# download and launch Selenium
|
||||
- wget -O /tmp/selenium-server-standalone.jar http://selenium.dev.stfalcon.com/selenium-server-standalone-latest.jar
|
||||
- java -jar /tmp/selenium-server-standalone.jar > /dev/null &
|
||||
- sleep 5
|
||||
|
||||
|
||||
script: HTTP_APP_ENV=test php tests/behat/behat.phar -c tests/behat/behat.yml
|
15
README.md
Normal file
15
README.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
Исходный код ifhub.ru
|
||||
|
||||
На основе [LiveStreet CMS](http://livestreetcms.ru) 2.0.1.dev
|
||||
|
||||
### Лицензия
|
||||
|
||||
LiveStreet - open-source проект под лицензией [GPL-2.0](http://opensource.org/licenses/GPL-2.0).
|
||||
|
||||
|
||||
|
||||
Readme
|
||||
-------------
|
||||
|
||||
* [English README](https://github.com/livestreet/livestreet/blob/master/Readme.EN.txt)
|
||||
* [Russian README](https://github.com/livestreet/livestreet/blob/master/Readme.RU.txt)
|
2
application/classes/.htaccess
Normal file
2
application/classes/.htaccess
Normal file
|
@ -0,0 +1,2 @@
|
|||
Order Deny,Allow
|
||||
Deny from all
|
171
application/classes/actions/ActionAdmin.class.php
Normal file
171
application/classes/actions/ActionAdmin.class.php
Normal file
|
@ -0,0 +1,171 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки УРЛа вида /admin/
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionAdmin extends Action
|
||||
{
|
||||
/**
|
||||
* Текущий пользователь
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent = null;
|
||||
/**
|
||||
* Главное меню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuHeadItemSelect = 'admin';
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Если нет прав доступа - перекидываем на 404 страницу
|
||||
*/
|
||||
if (!$this->User_IsAuthorization() or !$oUserCurrent = $this->User_GetUserCurrent() or !$oUserCurrent->isAdministrator()) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
$this->SetDefaultEvent('index');
|
||||
|
||||
$this->oUserCurrent = $oUserCurrent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('index', 'EventIndex');
|
||||
$this->AddEvent('plugins', 'EventPlugins');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Отображение главной страницы админки
|
||||
*/
|
||||
protected function EventIndex()
|
||||
{
|
||||
/**
|
||||
* Определяем доступность установки расширенной админ-панели
|
||||
*/
|
||||
$aPluginsAll = func_list_plugins(true);
|
||||
if (in_array('admin', $aPluginsAll)) {
|
||||
$this->Viewer_Assign('availableAdminPlugin', true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Страница со списком плагинов
|
||||
*
|
||||
*/
|
||||
protected function EventPlugins()
|
||||
{
|
||||
$this->sMenuHeadItemSelect = 'plugins';
|
||||
/**
|
||||
* Получаем название плагина и действие
|
||||
*/
|
||||
if ($sPlugin = getRequestStr('plugin', null, 'get') and $sAction = getRequestStr('action', null, 'get')) {
|
||||
return $this->SubmitManagePlugin($sPlugin, $sAction);
|
||||
}
|
||||
/**
|
||||
* Получаем список блогов
|
||||
*/
|
||||
$aPlugins = $this->PluginManager_GetPluginsItems(array('order' => 'name'));
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('plugins', $aPlugins);
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('admin.plugins.title'));
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->SetTemplateAction('plugins');
|
||||
}
|
||||
|
||||
/**
|
||||
* Активация\деактивация плагина
|
||||
*
|
||||
* @param string $sPlugin Имя плагина
|
||||
* @param string $sAction Действие
|
||||
*/
|
||||
protected function SubmitManagePlugin($sPlugin, $sAction)
|
||||
{
|
||||
$this->Security_ValidateSendForm();
|
||||
if (!in_array($sAction, array('activate', 'deactivate', 'remove', 'apply_update'))) {
|
||||
$this->Message_AddError($this->Lang_Get('admin.plugins.notices.unknown_action'), $this->Lang_Get('common.error.error'),
|
||||
true);
|
||||
Router::Location(Router::GetPath('admin/plugins'));
|
||||
}
|
||||
$bResult = false;
|
||||
/**
|
||||
* Активируем\деактивируем плагин
|
||||
*/
|
||||
if ($sAction == 'activate') {
|
||||
$bResult = $this->PluginManager_ActivatePlugin($sPlugin);
|
||||
} elseif ($sAction == 'deactivate') {
|
||||
$bResult = $this->PluginManager_DeactivatePlugin($sPlugin);
|
||||
} elseif ($sAction == 'remove') {
|
||||
$bResult = $this->PluginManager_RemovePlugin($sPlugin);
|
||||
} elseif ($sAction == 'apply_update') {
|
||||
$this->PluginManager_ApplyPluginUpdate($sPlugin);
|
||||
$bResult = true;
|
||||
}
|
||||
if ($bResult) {
|
||||
$this->Message_AddNotice($this->Lang_Get('admin.plugins.notices.action_ok'), $this->Lang_Get('common.attention'),
|
||||
true);
|
||||
} else {
|
||||
if (!($aMessages = $this->Message_GetErrorSession()) or !count($aMessages)) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'), true);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Возвращаем на страницу управления плагинами
|
||||
*/
|
||||
Router::Location(Router::GetPath('admin') . 'plugins/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется при завершении работы экшена
|
||||
*
|
||||
*/
|
||||
public function EventShutdown()
|
||||
{
|
||||
/**
|
||||
* Загружаем в шаблон необходимые переменные
|
||||
*/
|
||||
$this->Viewer_Assign('sMenuHeadItemSelect', $this->sMenuHeadItemSelect);
|
||||
}
|
||||
}
|
2122
application/classes/actions/ActionAjax.class.php
Normal file
2122
application/classes/actions/ActionAjax.class.php
Normal file
File diff suppressed because it is too large
Load diff
55
application/classes/actions/ActionArchive.class.php
Normal file
55
application/classes/actions/ActionArchive.class.php
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
* Страницы с архивами
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionArchive extends Action
|
||||
{
|
||||
/**
|
||||
* Инициализация экшена
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем дефолтный евент
|
||||
*/
|
||||
$this->SetDefaultEvent('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем евенты
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('index', 'EventIndex');
|
||||
$this->AddEvent('wiki', 'EventIfwiki');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод списка архивов
|
||||
*
|
||||
*/
|
||||
protected function EventIndex()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle('Архивы');
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Архивы вики
|
||||
*/
|
||||
protected function EventIfwiki()
|
||||
{
|
||||
$this->Viewer_AddHtmlTitle('Архивы IFWiki');
|
||||
$files = array_slice(scandir('./wikidump'), 2);
|
||||
$this->SetTemplateAction('archive');
|
||||
$this->Viewer_Assign('files', $files);
|
||||
}
|
||||
}
|
624
application/classes/actions/ActionAuth.class.php
Normal file
624
application/classes/actions/ActionAuth.class.php
Normal file
|
@ -0,0 +1,624 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обрабатывает авторизацию/регистрацию
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionAuth extends Action
|
||||
{
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Если включены инвайты то перенаправляем на страницу регистрации по инвайтам
|
||||
*/
|
||||
if (!$this->User_IsAuthorization() and Config::Get('general.reg.invite') and in_array(Router::GetActionEvent(),
|
||||
array('register', 'ajax-register')) and !$this->CheckInviteRegister()
|
||||
) {
|
||||
return Router::Action('auth', 'invite');
|
||||
}
|
||||
/**
|
||||
* Устанавливаем дефолтный евент
|
||||
*/
|
||||
$this->SetDefaultEvent('login');
|
||||
/**
|
||||
* Отключаем отображение статистики выполнения
|
||||
*/
|
||||
Router::SetIsShowStats(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем евенты
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('login', 'EventLogin');
|
||||
$this->AddEvent('logout', 'EventLogout');
|
||||
$this->AddEvent('password-reset', 'EventPasswordReset');
|
||||
$this->AddEvent('register', 'EventRegister');
|
||||
$this->AddEvent('register-confirm', 'EventRegisterConfirm');
|
||||
$this->AddEvent('activate', 'EventActivate');
|
||||
$this->AddEvent('reactivation', 'EventReactivation');
|
||||
$this->AddEvent('invite', 'EventInvite');
|
||||
$this->AddEventPreg('/^referral$/i', '/^[\w\-\_]{1,200}$/i', 'EventReferral');
|
||||
|
||||
$this->AddEvent('ajax-login', 'EventAjaxLogin');
|
||||
$this->AddEvent('ajax-password-reset', 'EventAjaxPasswordReset');
|
||||
$this->AddEvent('ajax-validate-fields', 'EventAjaxValidateFields');
|
||||
$this->AddEvent('ajax-validate-login', 'EventAjaxValidateLogin');
|
||||
$this->AddEvent('ajax-validate-email', 'EventAjaxValidateEmail');
|
||||
$this->AddEvent('ajax-register', 'EventAjaxRegister');
|
||||
$this->AddEvent('ajax-reactivation', 'EventAjaxReactivation');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax авторизация
|
||||
*/
|
||||
protected function EventAjaxLogin()
|
||||
{
|
||||
/**
|
||||
* Устанвливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Логин и пароль являются строками?
|
||||
*/
|
||||
if (!is_string(getRequest('login')) or !is_string(getRequest('password'))) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.base'));
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Проверяем есть ли такой юзер по логину
|
||||
*/
|
||||
if ((func_check(getRequest('login'),
|
||||
'mail') and $oUser = $this->User_GetUserByMail(getRequest('login'))) or $oUser = $this->User_GetUserByLogin(getRequest('login'))
|
||||
) {
|
||||
/**
|
||||
* Выбираем сценарий валидации
|
||||
*/
|
||||
$oUser->_setValidateScenario('signIn');
|
||||
/**
|
||||
* Заполняем поля (данные)
|
||||
*/
|
||||
$oUser->setCaptcha(getRequestStr('captcha'));
|
||||
/**
|
||||
* Запускаем валидацию
|
||||
*/
|
||||
if ($oUser->_Validate()) {
|
||||
/**
|
||||
* Сверяем хеши паролей и проверяем активен ли юзер
|
||||
*/
|
||||
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'))));
|
||||
return;
|
||||
}
|
||||
$bRemember = getRequest('remember', false) ? true : false;
|
||||
/**
|
||||
* Убиваем каптчу
|
||||
*/
|
||||
$this->Session_Drop('captcha_keystring_user_auth');
|
||||
/**
|
||||
* Авторизуем
|
||||
*/
|
||||
$this->User_Authorization($oUser, $bRemember);
|
||||
/**
|
||||
* Определяем редирект
|
||||
*/
|
||||
$sUrl = Config::Get('module.user.redirect_after_login');
|
||||
if (getRequestStr('return-path')) {
|
||||
$sUrl = getRequestStr('return-path');
|
||||
}
|
||||
$this->Viewer_AssignAjax('sUrlRedirect', $sUrl ? $sUrl : Router::GetPath('/'));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Получаем ошибки
|
||||
*/
|
||||
$this->Viewer_AssignAjax('errors', $oUser->_getValidateErrors());
|
||||
$this->Message_AddErrorSingle(null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('auth.login.notices.error_login'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Обрабатываем процесс залогинивания
|
||||
* По факту только отображение шаблона, дальше вступает в дело Ajax
|
||||
*
|
||||
*/
|
||||
protected function EventLogin()
|
||||
{
|
||||
/**
|
||||
* Если уже авторизирован
|
||||
*/
|
||||
if ($this->User_IsAuthorization()) {
|
||||
Router::Location(Router::GetPath('/'));
|
||||
}
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('auth.login.title'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Обрабатываем процесс разлогинивания
|
||||
*
|
||||
*/
|
||||
protected function EventLogout()
|
||||
{
|
||||
$this->Security_ValidateSendForm();
|
||||
if ($this->User_GetUserCurrent()) {
|
||||
$this->User_Logout();
|
||||
}
|
||||
Router::LocationAction('/');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax запрос на восстановление пароля
|
||||
*/
|
||||
protected function EventAjaxPasswordReset()
|
||||
{
|
||||
/**
|
||||
* Устанвливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Пользователь с таким емайлом существует?
|
||||
*/
|
||||
if ((func_check(getRequestStr('mail'), 'mail') and $oUser = $this->User_GetUserByMail(getRequestStr('mail')))) {
|
||||
/**
|
||||
* Формируем и отправляем ссылку на смену пароля
|
||||
*/
|
||||
$oReminder = Engine::GetEntity('User_Reminder');
|
||||
$oReminder->setCode(func_generator(32));
|
||||
$oReminder->setDateAdd(date("Y-m-d H:i:s"));
|
||||
$oReminder->setDateExpire(date("Y-m-d H:i:s", time() + 60 * 60 * 24 * 7));
|
||||
$oReminder->setDateUsed(null);
|
||||
$oReminder->setIsUsed(0);
|
||||
$oReminder->setUserId($oUser->getId());
|
||||
if ($this->User_AddReminder($oReminder)) {
|
||||
$this->Message_AddNotice($this->Lang_Get('auth.reset.notices.success_send_link'));
|
||||
$this->User_SendNotifyReminderCode($oUser, $oReminder);
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->Message_AddError($this->Lang_Get('auth.notices.error_bad_email'), $this->Lang_Get('common.error.error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка напоминания пароля, подтверждение смены пароля
|
||||
*
|
||||
*/
|
||||
protected function EventPasswordReset()
|
||||
{
|
||||
if ($this->User_IsAuthorization()) {
|
||||
Router::LocationAction('/');
|
||||
}
|
||||
$this->SetTemplateAction('reset');
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('auth.reset.title'));
|
||||
/**
|
||||
* Проверка кода на восстановление пароля и генерация нового пароля
|
||||
*/
|
||||
if (func_check($this->GetParam(0), 'md5')) {
|
||||
/**
|
||||
* Проверка кода подтверждения
|
||||
*/
|
||||
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($this->User_MakeHashPassword($sNewPassword));
|
||||
if ($this->User_Update($oUser)) {
|
||||
$oReminder->setDateUsed(date("Y-m-d H:i:s"));
|
||||
$oReminder->setIsUsed(1);
|
||||
$this->User_UpdateReminder($oReminder);
|
||||
$this->User_SendNotifyReminderPassword($oUser, $sNewPassword);
|
||||
$this->SetTemplateAction('reset_confirm');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('auth.reset.alerts.error_bad_code'),
|
||||
$this->Lang_Get('common.error.error'));
|
||||
return Router::Action('error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax валидация форму регистрации
|
||||
*/
|
||||
protected function EventAjaxValidateFields()
|
||||
{
|
||||
$this->ValidateFields(getRequest('fields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax валидация логина
|
||||
*/
|
||||
protected function EventAjaxValidateLogin()
|
||||
{
|
||||
$this->ValidateFields(array(array('field' => 'login', 'value' => getRequest('login'))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax валидация емэйла
|
||||
*/
|
||||
protected function EventAjaxValidateEmail()
|
||||
{
|
||||
$this->ValidateFields(array(array('field' => 'mail', 'value' => getRequest('mail'))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax валидация форму регистрации
|
||||
*/
|
||||
protected function ValidateFields($aFields)
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Создаем объект пользователя и устанавливаем сценарий валидации
|
||||
*/
|
||||
$oUser = Engine::GetEntity('ModuleUser_EntityUser');
|
||||
$oUser->_setValidateScenario('registration');
|
||||
/**
|
||||
* Пробегаем по переданным полям/значениям и валидируем их каждое в отдельности
|
||||
*/
|
||||
if (is_array($aFields)) {
|
||||
foreach ($aFields as $aField) {
|
||||
if (isset($aField['field']) and isset($aField['value'])) {
|
||||
$this->Hook_Run('registration_validate_field', array('aField' => &$aField, 'oUser' => $oUser));
|
||||
|
||||
$sField = $aField['field'];
|
||||
$sValue = $aField['value'];
|
||||
/**
|
||||
* Список полей для валидации
|
||||
*/
|
||||
switch ($sField) {
|
||||
case 'login':
|
||||
$oUser->setLogin($sValue);
|
||||
break;
|
||||
case 'mail':
|
||||
$oUser->setMail($sValue);
|
||||
break;
|
||||
case 'captcha':
|
||||
$oUser->setCaptcha($sValue);
|
||||
break;
|
||||
case 'password':
|
||||
$oUser->setPassword($sValue);
|
||||
break;
|
||||
case 'password_confirm':
|
||||
$oUser->setPasswordConfirm($sValue);
|
||||
$oUser->setPassword(isset($aField['params']['password']) ? $aField['params']['password'] : null);
|
||||
break;
|
||||
default:
|
||||
continue 2;
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* Валидируем поле
|
||||
*/
|
||||
$oUser->_Validate(array($sField), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Возникли ошибки?
|
||||
*/
|
||||
if ($oUser->_hasValidateErrors()) {
|
||||
/**
|
||||
* Получаем ошибки
|
||||
*/
|
||||
$this->Viewer_AssignAjax('errors', $oUser->_getValidateErrors());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка Ajax регистрации
|
||||
*/
|
||||
protected function EventAjaxRegister()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Создаем объект пользователя и устанавливаем сценарий валидации
|
||||
*/
|
||||
$oUser = Engine::GetEntity('ModuleUser_EntityUser');
|
||||
$oUser->_setValidateScenario('registration');
|
||||
/**
|
||||
* Заполняем поля (данные)
|
||||
*/
|
||||
$oUser->setLogin(getRequestStr('login'));
|
||||
$oUser->setMail(getRequestStr('mail'));
|
||||
$oUser->setPassword(getRequestStr('password'));
|
||||
$oUser->setPasswordConfirm(getRequestStr('password_confirm'));
|
||||
$oUser->setCaptcha(getRequestStr('captcha'));
|
||||
$oUser->setDateRegister(date("Y-m-d H:i:s"));
|
||||
$oUser->setIpRegister(func_getIp());
|
||||
/**
|
||||
* Если используется активация, то генерим код активации
|
||||
*/
|
||||
if (Config::Get('general.reg.activation')) {
|
||||
$oUser->setActivate(0);
|
||||
$oUser->setActivateKey(md5(func_generator() . time()));
|
||||
} else {
|
||||
$oUser->setActivate(1);
|
||||
$oUser->setActivateKey(null);
|
||||
}
|
||||
$this->Hook_Run('registration_validate_before', array('oUser' => $oUser));
|
||||
/**
|
||||
* Запускаем валидацию
|
||||
*/
|
||||
if ($oUser->_Validate()) {
|
||||
$this->Hook_Run('registration_validate_after', array('oUser' => $oUser));
|
||||
$oUser->setPassword($this->User_MakeHashPassword($oUser->getPassword()));
|
||||
if ($this->User_Add($oUser)) {
|
||||
$this->Hook_Run('registration_after', array('oUser' => $oUser));
|
||||
/**
|
||||
* Убиваем каптчу
|
||||
*/
|
||||
$this->Session_Drop('captcha_keystring_user_signup');
|
||||
/**
|
||||
* Подписываем пользователя на дефолтные события в ленте активности
|
||||
*/
|
||||
$this->Stream_switchUserEventDefaultTypes($oUser->getId());
|
||||
/**
|
||||
* Если юзер зарегистрировался по приглашению то обновляем инвайт
|
||||
*/
|
||||
if ($sCode = $this->GetInviteRegister()) {
|
||||
$this->Invite_UseCode($sCode, $oUser);
|
||||
}
|
||||
/**
|
||||
* Если стоит регистрация с активацией то проводим её
|
||||
*/
|
||||
if (Config::Get('general.reg.activation')) {
|
||||
/**
|
||||
* Отправляем на мыло письмо о подтверждении регистрации
|
||||
*/
|
||||
$this->User_SendNotifyRegistrationActivate($oUser, getRequestStr('password'));
|
||||
$this->Viewer_AssignAjax('sUrlRedirect', Router::GetPath('auth/register-confirm'));
|
||||
} else {
|
||||
$this->User_SendNotifyRegistration($oUser, getRequestStr('password'));
|
||||
$oUser = $this->User_GetUserById($oUser->getId());
|
||||
/**
|
||||
* Сразу авторизуем
|
||||
*/
|
||||
$this->User_Authorization($oUser, false);
|
||||
$this->DropInviteRegister();
|
||||
/**
|
||||
* Определяем URL для редиректа после авторизации
|
||||
*/
|
||||
$sUrl = Config::Get('module.user.redirect_after_registration');
|
||||
if (getRequestStr('return-path')) {
|
||||
$sUrl = getRequestStr('return-path');
|
||||
}
|
||||
$this->Viewer_AssignAjax('sUrlRedirect', $sUrl ? $sUrl : Router::GetPath('/'));
|
||||
$this->Message_AddNoticeSingle($this->Lang_Get('auth.registration.notices.success'));
|
||||
}
|
||||
} else {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.base'));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Получаем ошибки
|
||||
*/
|
||||
$this->Viewer_AssignAjax('errors', $oUser->_getValidateErrors());
|
||||
$this->Message_AddErrorSingle(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Показывает страничку регистрации
|
||||
* Просто вывод шаблона
|
||||
*/
|
||||
protected function EventRegister()
|
||||
{
|
||||
if ($this->User_IsAuthorization()) {
|
||||
Router::LocationAction('/');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка реферального кода
|
||||
*/
|
||||
protected function EventReferral()
|
||||
{
|
||||
if ($this->User_IsAuthorization()) {
|
||||
Router::LocationAction('/');
|
||||
}
|
||||
/**
|
||||
* Смотрим наличие реферального кода и сохраняем его в сессию
|
||||
*/
|
||||
if ($sCode = $this->GetParam(0)) {
|
||||
if ($iType = $this->Invite_GetInviteTypeByCode($sCode)) {
|
||||
if (!Config::Get('general.reg.invite') or $iType != ModuleInvite::INVITE_TYPE_REFERRAL) {
|
||||
$this->Session_Set('invite_code', $sCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
Router::LocationAction('auth/register');
|
||||
}
|
||||
|
||||
/**
|
||||
* Обрабатывает активацию аккаунта
|
||||
*/
|
||||
protected function EventActivate()
|
||||
{
|
||||
if ($this->User_IsAuthorization()) {
|
||||
Router::LocationAction('/');
|
||||
}
|
||||
$bError = false;
|
||||
/**
|
||||
* Проверяет передан ли код активации
|
||||
*/
|
||||
$sActivateKey = $this->GetParam(0);
|
||||
if (!func_check($sActivateKey, 'md5')) {
|
||||
$bError = true;
|
||||
}
|
||||
/**
|
||||
* Проверяет верный ли код активации
|
||||
*/
|
||||
if (!($oUser = $this->User_GetUserByActivateKey($sActivateKey))) {
|
||||
$bError = true;
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
if ($oUser and $oUser->getActivate()) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('auth.registration.notices.error_reactivate'),
|
||||
$this->Lang_Get('common.error.error'));
|
||||
return Router::Action('error');
|
||||
}
|
||||
/**
|
||||
* Если что то не то
|
||||
*/
|
||||
if ($bError) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('auth.registration.notices.error_code'),
|
||||
$this->Lang_Get('common.error.error'));
|
||||
return Router::Action('error');
|
||||
}
|
||||
/**
|
||||
* Активируем
|
||||
*/
|
||||
$oUser->setActivate(1);
|
||||
$oUser->setDateActivate(date("Y-m-d H:i:s"));
|
||||
/**
|
||||
* Сохраняем юзера
|
||||
*/
|
||||
if ($this->User_Update($oUser)) {
|
||||
$this->User_Authorization($oUser, false);
|
||||
$this->DropInviteRegister();
|
||||
return;
|
||||
} else {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.base'));
|
||||
return Router::Action('error');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Повторный запрос активации
|
||||
*/
|
||||
protected function EventReactivation()
|
||||
{
|
||||
if ($this->User_IsAuthorization()) {
|
||||
Router::LocationAction('/');
|
||||
}
|
||||
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('auth.reactivation.title'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax повторной активации
|
||||
*/
|
||||
protected function EventAjaxReactivation()
|
||||
{
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
|
||||
if ((func_check(getRequestStr('mail'), 'mail') and $oUser = $this->User_GetUserByMail(getRequestStr('mail')))) {
|
||||
if ($oUser->getActivate()) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('auth.registration.notices.error_reactivate'));
|
||||
return;
|
||||
} else {
|
||||
$oUser->setActivateKey(md5(func_generator() . time()));
|
||||
if ($this->User_Update($oUser)) {
|
||||
$this->Message_AddNotice($this->Lang_Get('auth.reactivation.notices.success'));
|
||||
$this->User_SendNotifyReactivationCode($oUser);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('auth.notices.error_bad_email'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Просто выводит шаблон для подтверждения регистрации
|
||||
*
|
||||
*/
|
||||
protected function EventRegisterConfirm()
|
||||
{
|
||||
$this->SetTemplateAction('confirm');
|
||||
}
|
||||
|
||||
protected function EventInvite()
|
||||
{
|
||||
if ($this->User_IsAuthorization()) {
|
||||
Router::LocationAction('/');
|
||||
}
|
||||
$this->SetTemplateAction('invite');
|
||||
|
||||
if (isPost()) {
|
||||
/**
|
||||
* Проверяем валидность кода
|
||||
*/
|
||||
if ($this->Invite_CheckCode(getRequestStr('invite_code'), ModuleInvite::INVITE_TYPE_CODE)) {
|
||||
Router::Location($this->Invite_GetReferralLink(null, getRequestStr('invite_code')));
|
||||
} else {
|
||||
$this->Message_AddError($this->Lang_Get('auth.invite.alerts.error_code'), $this->Lang_Get('common.error.error'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Пытается ли юзер зарегистрироваться с помощью кода приглашения
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function CheckInviteRegister()
|
||||
{
|
||||
if ($this->GetInviteRegister()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Вожвращает код приглашения из сессии
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function GetInviteRegister()
|
||||
{
|
||||
return $this->Session_Get('invite_code');
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет код приглашения из сессии
|
||||
*/
|
||||
protected function DropInviteRegister()
|
||||
{
|
||||
$this->Session_Drop('invite_code');
|
||||
}
|
||||
}
|
2246
application/classes/actions/ActionBlog.class.php
Normal file
2246
application/classes/actions/ActionBlog.class.php
Normal file
File diff suppressed because it is too large
Load diff
189
application/classes/actions/ActionBlogs.class.php
Normal file
189
application/classes/actions/ActionBlogs.class.php
Normal file
|
@ -0,0 +1,189 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки УРЛа вида /comments/
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionBlogs extends Action
|
||||
{
|
||||
/**
|
||||
* Текущий пользователь
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent = null;
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Загружаем в шаблон JS текстовки
|
||||
*/
|
||||
$this->Lang_AddLangJs(array(
|
||||
'blog.join.join',
|
||||
'blog.join.leave'
|
||||
));
|
||||
/**
|
||||
* Получаем текущего пользователя
|
||||
*/
|
||||
$this->oUserCurrent = $this->User_GetUserCurrent();
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('blog.menu.all_list'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем евенты
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEventPreg('/^(page([1-9]\d{0,5}))?$/i', 'EventShowBlogs');
|
||||
$this->AddEventPreg('/^ajax-search$/i', 'EventAjaxSearch');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Поиск блогов по названию
|
||||
*/
|
||||
protected function EventAjaxSearch()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Фильтр
|
||||
*/
|
||||
$aFilter = array(
|
||||
'exclude_type' => 'personal',
|
||||
);
|
||||
$sOrderWay = in_array(getRequestStr('order'), array('desc', 'asc')) ? getRequestStr('order') : 'desc';
|
||||
$sOrderField = in_array(getRequestStr('sort_by'), array(
|
||||
'blog_id',
|
||||
'blog_title',
|
||||
'blog_count_user',
|
||||
'blog_count_topic'
|
||||
)) ? getRequestStr('sort_by') : 'blog_count_user';
|
||||
if (is_numeric(getRequestStr('next_page')) and getRequestStr('next_page') > 0) {
|
||||
$iPage = getRequestStr('next_page');
|
||||
} else {
|
||||
$iPage = 1;
|
||||
}
|
||||
/**
|
||||
* Получаем из реквеста первые буквы блога
|
||||
*/
|
||||
if ($sTitle = getRequestStr('sText')) {
|
||||
$sTitle = str_replace('%', '', $sTitle);
|
||||
} else {
|
||||
$sTitle = '';
|
||||
}
|
||||
if ($sTitle) {
|
||||
$aFilter['title'] = "%{$sTitle}%";
|
||||
}
|
||||
/**
|
||||
* Категории
|
||||
*/
|
||||
if (getRequestStr('category') and $oCategory = $this->Category_GetCategoryById(getRequestStr('category'))) {
|
||||
/**
|
||||
* Получаем ID всех блогов
|
||||
* По сути это костыль, но т.к. блогов обычно не много, то норм
|
||||
*/
|
||||
$aBlogIds = $this->Blog_GetTargetIdsByCategory($oCategory, 1, 1000, true);
|
||||
$aFilter['id'] = $aBlogIds ? $aBlogIds : array(0);
|
||||
}
|
||||
/**
|
||||
* Тип
|
||||
*/
|
||||
if (in_array(getRequestStr('type'), array('open', 'close'))) {
|
||||
$aFilter['type'] = getRequestStr('type');
|
||||
}
|
||||
/**
|
||||
* Принадлежность
|
||||
*/
|
||||
if ($this->oUserCurrent) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Ищем блоги
|
||||
*/
|
||||
$aResult = $this->Blog_GetBlogsByFilter($aFilter, array($sOrderField => $sOrderWay), $iPage,
|
||||
Config::Get('module.blog.per_page'));
|
||||
$bHideMore = $iPage * Config::Get('module.blog.per_page') >= $aResult['count'];
|
||||
/**
|
||||
* Формируем и возвращает ответ
|
||||
*/
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
$oViewer->Assign('blogs', $aResult['collection'], true);
|
||||
$oViewer->Assign('oUserCurrent', $this->User_GetUserCurrent());
|
||||
$this->Viewer_AssignAjax('html', $oViewer->Fetch("component@blog.list-loop"));
|
||||
/**
|
||||
* Для подгрузки
|
||||
*/
|
||||
$this->Viewer_AssignAjax('count_loaded', count($aResult['collection']));
|
||||
$this->Viewer_AssignAjax('next_page', count($aResult['collection']) > 0 ? $iPage + 1 : $iPage);
|
||||
$this->Viewer_AssignAjax('searchCount', (int)$aResult['count']);
|
||||
$this->Viewer_AssignAjax('hide', $bHideMore or !$aResult['count'] or !count($aResult['collection']));
|
||||
$this->Viewer_AssignAjax('textEmpty', $this->Lang_Get('search.alerts.empty'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Отображение списка блогов
|
||||
*/
|
||||
protected function EventShowBlogs()
|
||||
{
|
||||
/**
|
||||
* Фильтр поиска блогов
|
||||
*/
|
||||
$aFilter = array(
|
||||
'exclude_type' => 'personal'
|
||||
);
|
||||
/**
|
||||
* Получаем список блогов
|
||||
*/
|
||||
$aResult = $this->Blog_GetBlogsByFilter($aFilter, array('blog_count_user' => 'desc'), 1,
|
||||
Config::Get('module.blog.per_page'));
|
||||
$aBlogs = $aResult['collection'];
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('blogs', $aBlogs);
|
||||
$this->Viewer_Assign('searchCount', $aResult['count']);
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
}
|
108
application/classes/actions/ActionComments.class.php
Normal file
108
application/classes/actions/ActionComments.class.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки УРЛа вида /comments/
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionComments extends Action
|
||||
{
|
||||
/**
|
||||
* Текущий юзер
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent = null;
|
||||
/**
|
||||
* Главное меню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuHeadItemSelect = 'blog';
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
$this->oUserCurrent = $this->User_GetUserCurrent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEventPreg('/^\d+$/i', 'EventShowComment');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обрабатывает ссылку на конкретный комментарий, определят к какому топику он относится и перенаправляет на него
|
||||
* Актуально при использовании постраничности комментариев
|
||||
*/
|
||||
protected function EventShowComment()
|
||||
{
|
||||
$iCommentId = $this->sCurrentEvent;
|
||||
/**
|
||||
* Проверяем к чему относится комментарий
|
||||
*/
|
||||
if (!($oComment = $this->Comment_GetCommentById($iCommentId))) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
if ($oComment->getTargetType() != 'topic' or !($oTopic = $oComment->getTarget())) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
/**
|
||||
* Определяем необходимую страницу для отображения комментария
|
||||
*/
|
||||
if (!Config::Get('module.comment.use_nested') or !Config::Get('module.comment.nested_per_page')) {
|
||||
Router::Location($oTopic->getUrl() . '#comment' . $oComment->getId());
|
||||
}
|
||||
$iPage = $this->Comment_GetPageCommentByTargetId($oComment->getTargetId(), $oComment->getTargetType(),
|
||||
$oComment);
|
||||
if ($iPage == 1) {
|
||||
Router::Location($oTopic->getUrl() . '#comment' . $oComment->getId());
|
||||
} else {
|
||||
Router::Location($oTopic->getUrl() . "?cmtpage={$iPage}#comment" . $oComment->getId());
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется при завершении работы экшена
|
||||
*
|
||||
*/
|
||||
public function EventShutdown()
|
||||
{
|
||||
/**
|
||||
* Загружаем в шаблон необходимые переменные
|
||||
*/
|
||||
$this->Viewer_Assign('sMenuHeadItemSelect', $this->sMenuHeadItemSelect);
|
||||
}
|
||||
}
|
745
application/classes/actions/ActionContent.class.php
Normal file
745
application/classes/actions/ActionContent.class.php
Normal file
|
@ -0,0 +1,745 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки УРЛа вида /content/ - управление своими топиками
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 2.0
|
||||
*/
|
||||
class ActionContent extends Action
|
||||
{
|
||||
/**
|
||||
* Главное меню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuHeadItemSelect = 'blog';
|
||||
/**
|
||||
* Меню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuItemSelect = 'topic';
|
||||
/**
|
||||
* СубМеню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuSubItemSelect = 'topic';
|
||||
/**
|
||||
* Текущий юзер
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent = null;
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Проверяем авторизован ли юзер
|
||||
*/
|
||||
if (!$this->User_IsAuthorization()) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
$this->oUserCurrent = $this->User_GetUserCurrent();
|
||||
/**
|
||||
* Усанавливаем дефолтный евент
|
||||
*/
|
||||
$this->SetDefaultEvent('add');
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('topic.topics'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем евенты
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEventPreg('/^add$/i', '/^[a-z_0-9]{1,50}$/i', '/^$/i', 'EventAdd');
|
||||
$this->AddEventPreg('/^edit$/i', '/^\d{1,10}$/i', '/^$/i', 'EventEdit');
|
||||
$this->AddEventPreg('/^delete$/i', '/^\d{1,10}$/i', '/^$/i', 'EventDelete');
|
||||
|
||||
$this->AddEventPreg('/^published$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventShowTopics');
|
||||
$this->AddEventPreg('/^drafts$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventShowTopics');
|
||||
$this->AddEventPreg('/^deferred$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventShowTopics');
|
||||
|
||||
$this->AddEventPreg('/^ajax$/i', '/^add$/i', '/^$/i', 'EventAjaxAdd');
|
||||
$this->AddEventPreg('/^ajax$/i', '/^edit$/i', '/^$/i', 'EventAjaxEdit');
|
||||
$this->AddEventPreg('/^ajax$/i', '/^preview$/i', '/^$/i', 'EventAjaxPreview');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Выводит список топиков
|
||||
*
|
||||
*/
|
||||
protected function EventShowTopics()
|
||||
{
|
||||
/**
|
||||
* Меню
|
||||
*/
|
||||
$this->sMenuSubItemSelect = $this->sCurrentEvent;
|
||||
/**
|
||||
* Передан ли номер страницы
|
||||
*/
|
||||
$iPage = $this->GetParamEventMatch(0, 2) ? $this->GetParamEventMatch(0, 2) : 1;
|
||||
/**
|
||||
* Получаем список топиков
|
||||
*/
|
||||
if ($this->sCurrentEvent == 'deferred') {
|
||||
$aResult = $this->Topic_GetTopicsPersonalDeferredByUser($this->oUserCurrent->getId(), $iPage, Config::Get('module.topic.per_page'));
|
||||
$this->SetTemplateAction('drafts');
|
||||
} else {
|
||||
$aResult = $this->Topic_GetTopicsPersonalByUser($this->oUserCurrent->getId(),
|
||||
$this->sCurrentEvent == 'published' ? 1 : 0, $iPage, Config::Get('module.topic.per_page'));
|
||||
}
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('module.topic.per_page'),
|
||||
Config::Get('pagination.pages.count'), Router::GetPath('content') . $this->sCurrentEvent);
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
$this->Viewer_Assign('topics', $aTopics);
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('topic.nav.' . $this->sCurrentEvent));
|
||||
}
|
||||
|
||||
protected function EventDelete()
|
||||
{
|
||||
$this->Security_ValidateSendForm();
|
||||
/**
|
||||
* Получаем номер топика из УРЛ и проверяем существует ли он
|
||||
*/
|
||||
$sTopicId = $this->GetParam(0);
|
||||
if (!($oTopic = $this->Topic_GetTopicById($sTopicId))) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
/**
|
||||
* проверяем есть ли право на удаление топика
|
||||
*/
|
||||
if (!$this->ACL_IsAllowDeleteTopic($oTopic, $this->oUserCurrent)) {
|
||||
$this->Message_AddErrorSingle($this->Rbac_GetMsgLast());
|
||||
return Router::Action('error');
|
||||
}
|
||||
/**
|
||||
* Удаляем топик
|
||||
*/
|
||||
$this->Hook_Run('topic_delete_before', array('oTopic' => $oTopic));
|
||||
$this->Topic_DeleteTopic($oTopic);
|
||||
$this->Hook_Run('topic_delete_after', array('oTopic' => $oTopic));
|
||||
/**
|
||||
* Перенаправляем на страницу со списком топиков из блога этого топика
|
||||
*/
|
||||
Router::Location($oTopic->getBlog()->getUrlFull());
|
||||
}
|
||||
|
||||
protected function EventEdit()
|
||||
{
|
||||
/**
|
||||
* Получаем номер топика из УРЛ и проверяем существует ли он
|
||||
*/
|
||||
$sTopicId = $this->GetParam(0);
|
||||
if (!($oTopic = $this->Topic_GetTopicById($sTopicId))) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
/**
|
||||
* Проверяем тип топика
|
||||
*/
|
||||
if (!$oTopicType = $this->Topic_GetTopicType($oTopic->getType())) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
/**
|
||||
* Если права на редактирование
|
||||
*/
|
||||
if (!$this->ACL_IsAllowEditTopic($oTopic, $this->oUserCurrent)) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
|
||||
/**
|
||||
* Получаем доступные блоги по типам
|
||||
*/
|
||||
$aBlogs = array();
|
||||
$aBlogs['open'] = $this->Blog_GetBlogsByType('open');
|
||||
/**
|
||||
* Убираем из списка блоги в которые не доступен постинг
|
||||
*/
|
||||
$aBlogsCurrent = $oTopic->getBlogIds();
|
||||
foreach ($aBlogs['open'] as $k => $oBlogOpen) {
|
||||
if (!$this->ACL_IsAllowBlog($oBlogOpen, $this->oUserCurrent) and !in_array($oBlogOpen->getId(), $aBlogsCurrent)) {
|
||||
unset($aBlogs['open'][$k]);
|
||||
}
|
||||
}
|
||||
if ($this->oUserCurrent->isAdministrator()) {
|
||||
$aBlogs['close'] = $this->Blog_GetBlogsByType('close');
|
||||
} else {
|
||||
$aBlogs['close'] = $this->Blog_GetBlogsByTypeAndUserId('close', $this->oUserCurrent->getId());
|
||||
}
|
||||
/**
|
||||
* Вызов хуков
|
||||
*/
|
||||
$this->Hook_Run('topic_edit_show', array('oTopic' => $oTopic, 'aBlogs' => &$aBlogs));
|
||||
|
||||
/**
|
||||
* Дополнительно загружам превью
|
||||
*/
|
||||
$aFilter = array(
|
||||
'target_type' => 'topic',
|
||||
'is_preview' => 1,
|
||||
'target_id' => $sTopicId
|
||||
);
|
||||
$aTargetItems = $this->Media_GetTargetItemsByFilter($aFilter);
|
||||
$this->Viewer_Assign('imagePreviewItems', $aTargetItems);
|
||||
|
||||
/**
|
||||
* Проверяем на отсутствие блогов
|
||||
*/
|
||||
$bSkipBlogs = true;
|
||||
foreach ($aBlogs as $aBlogsType) {
|
||||
if ($aBlogsType) {
|
||||
$bSkipBlogs = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('blogsAllow', $aBlogs);
|
||||
$this->Viewer_Assign('skipBlogs', $bSkipBlogs);
|
||||
$this->Viewer_Assign('topicType', $oTopicType);
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('topic.add.title.edit'));
|
||||
|
||||
$this->Viewer_Assign('topicEdit', $oTopic);
|
||||
$this->SetTemplateAction('add');
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавление топика
|
||||
*
|
||||
*/
|
||||
protected function EventAdd()
|
||||
{
|
||||
$sTopicType = $this->GetParam(0);
|
||||
$iBlogId = (int)getRequest('blog_id');
|
||||
|
||||
if (!$oTopicType = $this->Topic_GetTopicType($sTopicType)) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
/**
|
||||
* Проверяем права на создание топика
|
||||
*/
|
||||
if (!$this->ACL_CanAddTopic($this->oUserCurrent, $oTopicType)) {
|
||||
$this->Message_AddErrorSingle($this->Rbac_GetMsgLast());
|
||||
return Router::Action('error');
|
||||
}
|
||||
$this->sMenuSubItemSelect = $sTopicType;
|
||||
/**
|
||||
* Получаем доступные блоги по типам
|
||||
*/
|
||||
$aBlogs = array();
|
||||
$aBlogs['open'] = $this->Blog_GetBlogsByType('open');
|
||||
/**
|
||||
* Убираем из списка блоги в которые не доступен постинг
|
||||
*/
|
||||
foreach ($aBlogs['open'] as $k => $oBlogOpen) {
|
||||
if (!$this->ACL_IsAllowBlog($oBlogOpen, $this->oUserCurrent)) {
|
||||
unset($aBlogs['open'][$k]);
|
||||
}
|
||||
}
|
||||
if ($this->oUserCurrent->isAdministrator()) {
|
||||
$aBlogs['close'] = $this->Blog_GetBlogsByType('close');
|
||||
} else {
|
||||
$aBlogs['close'] = $this->Blog_GetBlogsByTypeAndUserId('close', $this->oUserCurrent->getId());
|
||||
}
|
||||
/**
|
||||
* Вызов хуков
|
||||
*/
|
||||
$this->Hook_Run('topic_add_show', array('aBlogs' => &$aBlogs));
|
||||
/**
|
||||
* Проверяем на отсутствие блогов
|
||||
*/
|
||||
$bSkipBlogs = true;
|
||||
foreach ($aBlogs as $aBlogsType) {
|
||||
if ($aBlogsType) {
|
||||
$bSkipBlogs = false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('topicType', $oTopicType);
|
||||
$this->Viewer_Assign('blogsAllow', $aBlogs);
|
||||
$this->Viewer_Assign('skipBlogs', $bSkipBlogs);
|
||||
$this->Viewer_Assign('blogId', $iBlogId);
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('topic.add.title.add'));
|
||||
$this->SetTemplateAction('add');
|
||||
}
|
||||
|
||||
protected function EventAjaxEdit()
|
||||
{
|
||||
$this->Viewer_SetResponseAjax();
|
||||
|
||||
$aTopicRequest = getRequest('topic');
|
||||
if (!(isset($aTopicRequest['id']) and $oTopic = $this->Topic_GetTopicById($aTopicRequest['id']))) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
if (!$this->Topic_IsAllowTopicType($oTopic->getType())) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Проверяем разрешено ли постить топик по времени
|
||||
*/
|
||||
if (!isPost('is_draft') and !$oTopic->getPublishDraft() and !$this->ACL_CanPostTopicTime($this->oUserCurrent)) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('topic.add.notices.time_limit'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Если права на редактирование
|
||||
*/
|
||||
if (!$this->ACL_IsAllowEditTopic($oTopic, $this->oUserCurrent)) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Сохраняем старое значение идентификатора основного блога и всех блогов
|
||||
*/
|
||||
$sBlogIdOld = $oTopic->getBlogId();
|
||||
$aBlogsIdOld = $oTopic->getBlogsId();
|
||||
|
||||
$oTopic->_setDataSafe(getRequest('topic'));
|
||||
$oTopic->setProperties(getRequest('property'));
|
||||
$oTopic->setUserCreator($this->oUserCurrent);
|
||||
$oTopic->setUserIp(func_getIp());
|
||||
if (!$oTopic->getTags() or !$oTopic->getTypeObject()->getParam('allow_tags')) {
|
||||
$oTopic->setTags('');
|
||||
}
|
||||
/**
|
||||
* Принудительный вывод на главную
|
||||
*/
|
||||
if ($this->ACL_IsAllowTopicPublishIndex($this->oUserCurrent)) {
|
||||
if (isset($_REQUEST['topic']['topic_publish_index'])) {
|
||||
$oTopic->setPublishIndex(1);
|
||||
} else {
|
||||
$oTopic->setPublishIndex(0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Принудительный запрет вывода на главную
|
||||
*/
|
||||
if ($this->ACL_IsAllowTopicSkipIndex($this->oUserCurrent)) {
|
||||
if (isset($_REQUEST['topic']['topic_skip_index'])) {
|
||||
$oTopic->setSkipIndex(1);
|
||||
} else {
|
||||
$oTopic->setSkipIndex(0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Запрет на комментарии к топику
|
||||
*/
|
||||
$oTopic->setForbidComment(0);
|
||||
if (isset($_REQUEST['topic']['topic_forbid_comment'])) {
|
||||
$oTopic->setForbidComment(1);
|
||||
}
|
||||
/**
|
||||
* Дата редактирования контента
|
||||
*/
|
||||
$oTopic->setDateEditContent(date('Y-m-d H:i:s'));
|
||||
|
||||
$this->Hook_Run('topic_edit_validate_before', array('oTopic' => $oTopic));
|
||||
if ($oTopic->_Validate()) {
|
||||
/**
|
||||
* Публикуем или сохраняем в черновиках
|
||||
*/
|
||||
$bSendNotify = false;
|
||||
if (!isset($_REQUEST['is_draft'])) {
|
||||
$oTopic->setPublish(1);
|
||||
if ($oTopic->getPublishDraft() == 0) {
|
||||
$oTopic->setPublishDraft(1);
|
||||
$oTopic->setDatePublish(date("Y-m-d H:i:s"));
|
||||
$bSendNotify = true;
|
||||
}
|
||||
} else {
|
||||
$oTopic->setPublish(0);
|
||||
}
|
||||
/**
|
||||
* Отложенная публикация
|
||||
*/
|
||||
if ($oTopic->getPublishDateRaw()) {
|
||||
$oTopic->setDatePublish(date("Y-m-d H:i:s", $oTopic->getPublishDateRaw()));
|
||||
$bSendNotify = false;
|
||||
} else {
|
||||
/**
|
||||
* Снятие даты публикации, только при условии, что была установлена дата в будущем
|
||||
*/
|
||||
if ($oTopic->getDatePublish() and strtotime($oTopic->getDatePublish()) > time()) {
|
||||
$oTopic->setDatePublish(date("Y-m-d H:i:s"));
|
||||
/**
|
||||
* Если сохраняем отложенный в черновик, то считаем, что он еще ниразу не публиковался
|
||||
*/
|
||||
if (isset($_REQUEST['is_draft'])) {
|
||||
$oTopic->setPublishDraft(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
$oBlog = $oTopic->getBlog();
|
||||
/**
|
||||
* Получаемый и устанавливаем разрезанный текст по тегу <cut>
|
||||
*/
|
||||
if ($oTopic->getTypeObject()->getParam('allow_text')) {
|
||||
list($sTextShort, $sTextNew, $sTextCut) = $this->Text_Cut($oTopic->getTextSource());
|
||||
$oTopic->setCutText($sTextCut);
|
||||
// TODO: передача параметров в Topic_Parser пока не используется - нужно заменить на этот вызов все места с парсингом топика
|
||||
$oTopic->setText($this->Topic_Parser($sTextNew, $oTopic));
|
||||
if ($sTextShort != $sTextNew) {
|
||||
$oTopic->setTextShort($this->Topic_Parser($sTextShort, $oTopic));
|
||||
} else {
|
||||
$oTopic->setTextShort('');
|
||||
}
|
||||
} else {
|
||||
$oTopic->setCutText('');
|
||||
$oTopic->setText('');
|
||||
$oTopic->setTextShort('');
|
||||
$oTopic->setTextSource('');
|
||||
}
|
||||
$this->Hook_Run('topic_edit_before', array('oTopic' => $oTopic, 'oBlog' => $oBlog));
|
||||
/**
|
||||
* Сохраняем топик
|
||||
*/
|
||||
if ($this->Topic_UpdateTopic($oTopic)) {
|
||||
$this->Hook_Run('topic_edit_after',
|
||||
array('oTopic' => $oTopic, 'oBlog' => $oBlog, 'bSendNotify' => &$bSendNotify));
|
||||
/**
|
||||
* Обновляем данные в комментариях, если топик был перенесен в новый блог
|
||||
*/
|
||||
if ($sBlogIdOld != $oTopic->getBlogId()) {
|
||||
$this->Comment_UpdateTargetParentByTargetId($oTopic->getBlogId(), 'topic', $oTopic->getId());
|
||||
$this->Comment_UpdateTargetParentByTargetIdOnline($oTopic->getBlogId(), 'topic', $oTopic->getId());
|
||||
}
|
||||
/**
|
||||
* Обновляем количество топиков в блоге
|
||||
*/
|
||||
if ($aBlogsIdOld != $oTopic->getBlogsId()) {
|
||||
$this->Blog_RecalculateCountTopicByBlogId($aBlogsIdOld);
|
||||
}
|
||||
$this->Blog_RecalculateCountTopicByBlogId($oTopic->getBlogsId());
|
||||
/**
|
||||
* Добавляем событие в ленту
|
||||
*/
|
||||
$this->Stream_write($oTopic->getUserId(), 'add_topic', $oTopic->getId(),
|
||||
$oTopic->getPublish() && $oBlog->getType() != 'close', $oTopic->getDatePublish());
|
||||
/**
|
||||
* Рассылаем о новом топике подписчикам блога
|
||||
*/
|
||||
if ($bSendNotify) {
|
||||
$this->Topic_SendNotifyTopicNew($oTopic, $oTopic->getUser());
|
||||
}
|
||||
if (!$oTopic->getPublish() and !$this->oUserCurrent->isAdministrator() and $this->oUserCurrent->getId() != $oTopic->getUserId()) {
|
||||
$sUrlRedirect = $oBlog->getUrlFull();
|
||||
} else {
|
||||
$sUrlRedirect = $oTopic->getUrl();
|
||||
}
|
||||
|
||||
$this->Viewer_AssignAjax('sUrlRedirect', $sUrlRedirect);
|
||||
$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'));
|
||||
}
|
||||
} else {
|
||||
$this->Message_AddError($oTopic->_getValidateError(), $this->Lang_Get('common.error.error'));
|
||||
}
|
||||
}
|
||||
|
||||
protected function EventAjaxAdd()
|
||||
{
|
||||
$this->Viewer_SetResponseAjax();
|
||||
/**
|
||||
* Проверяем тип топика
|
||||
*/
|
||||
$sTopicType = getRequestStr('topic_type');
|
||||
if (!$oTopicType = $this->Topic_GetTopicType($sTopicType)) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Проверяем права на создание топика
|
||||
*/
|
||||
if (!$this->ACL_CanAddTopic($this->oUserCurrent, $oTopicType)) {
|
||||
$this->Message_AddErrorSingle($this->Rbac_GetMsgLast());
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Создаем топик
|
||||
*/
|
||||
$oTopic = Engine::GetEntity('Topic');
|
||||
$oTopic->_setDataSafe(getRequest('topic'));
|
||||
|
||||
$oTopic->setProperties(getRequest('property'));
|
||||
$oTopic->setUserCreator($this->oUserCurrent);
|
||||
$oTopic->setUserId($this->oUserCurrent->getId());
|
||||
$oTopic->setDateAdd(date("Y-m-d H:i:s"));
|
||||
$oTopic->setUserIp(func_getIp());
|
||||
$oTopic->setTopicType($sTopicType);
|
||||
if (!$oTopic->getTags() or !$oTopic->getTypeObject()->getParam('allow_tags')) {
|
||||
$oTopic->setTags('');
|
||||
}
|
||||
/**
|
||||
* Публикуем или сохраняем
|
||||
*/
|
||||
if (!isset($_REQUEST['is_draft'])) {
|
||||
$oTopic->setPublish(1);
|
||||
$oTopic->setPublishDraft(1);
|
||||
} else {
|
||||
$oTopic->setPublish(0);
|
||||
$oTopic->setPublishDraft(0);
|
||||
}
|
||||
/**
|
||||
* Принудительный вывод на главную
|
||||
*/
|
||||
$oTopic->setPublishIndex(0);
|
||||
if ($this->ACL_IsAllowTopicPublishIndex($this->oUserCurrent)) {
|
||||
if (isset($_REQUEST['topic']['topic_publish_index'])) {
|
||||
$oTopic->setPublishIndex(1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Принудительный запрет вывода на главную
|
||||
*/
|
||||
$oTopic->setSkipIndex(0);
|
||||
if ($this->ACL_IsAllowTopicSkipIndex($this->oUserCurrent)) {
|
||||
if (isset($_REQUEST['topic']['topic_skip_index'])) {
|
||||
$oTopic->setSkipIndex(1);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Запрет на комментарии к топику
|
||||
*/
|
||||
$oTopic->setForbidComment(0);
|
||||
if (isset($_REQUEST['topic']['topic_forbid_comment'])) {
|
||||
$oTopic->setForbidComment(1);
|
||||
}
|
||||
|
||||
$this->Hook_Run('topic_add_validate_before', array('oTopic' => $oTopic));
|
||||
if ($oTopic->_Validate()) {
|
||||
if ($oTopic->getPublishDateRaw()) {
|
||||
$oTopic->setDatePublish(date("Y-m-d H:i:s", $oTopic->getPublishDateRaw()));
|
||||
}
|
||||
$oBlog = $oTopic->getBlog();
|
||||
/**
|
||||
* Получаем и устанавливаем разрезанный текст по тегу <cut>
|
||||
*/
|
||||
if ($oTopic->getTypeObject()->getParam('allow_text')) {
|
||||
list($sTextShort, $sTextNew, $sTextCut) = $this->Text_Cut($oTopic->getTextSource());
|
||||
$oTopic->setCutText($sTextCut);
|
||||
$oTopic->setText($this->Topic_Parser($sTextNew, $oTopic));
|
||||
if ($sTextShort != $sTextNew) {
|
||||
$oTopic->setTextShort($this->Topic_Parser($sTextShort, $oTopic));
|
||||
} else {
|
||||
$oTopic->setTextShort('');
|
||||
}
|
||||
} else {
|
||||
$oTopic->setCutText('');
|
||||
$oTopic->setText('');
|
||||
$oTopic->setTextShort('');
|
||||
$oTopic->setTextSource('');
|
||||
}
|
||||
|
||||
$this->Hook_Run('topic_add_before', array('oTopic' => $oTopic, 'oBlog' => $oBlog));
|
||||
if ($this->Topic_AddTopic($oTopic)) {
|
||||
$this->Hook_Run('topic_add_after', array('oTopic' => $oTopic, 'oBlog' => $oBlog));
|
||||
/**
|
||||
* Получаем топик, чтоб подцепить связанные данные
|
||||
*/
|
||||
$oTopic = $this->Topic_GetTopicById($oTopic->getId());
|
||||
/**
|
||||
* Обновляем количество топиков в блогах
|
||||
*/
|
||||
$this->Blog_RecalculateCountTopicByBlogId($oTopic->getBlogsId());
|
||||
/**
|
||||
* Фиксируем ID у media файлов топика
|
||||
*/
|
||||
$this->Media_ReplaceTargetTmpById('topic', $oTopic->getId());
|
||||
/**
|
||||
* Фиксируем ID у опросов
|
||||
*/
|
||||
if ($oTopicType->getParam('allow_poll')) {
|
||||
$this->Poll_ReplaceTargetTmpById('topic', $oTopic->getId());
|
||||
}
|
||||
/**
|
||||
* Добавляем автора топика в подписчики на новые комментарии к этому топику
|
||||
*/
|
||||
$oUser = $oTopic->getUser();
|
||||
if ($oUser) {
|
||||
$this->Subscribe_AddSubscribeSimple('topic_new_comment', $oTopic->getId(), $oUser->getMail(),
|
||||
$oUser->getId());
|
||||
}
|
||||
/**
|
||||
* Делаем рассылку спама всем, кто состоит в этом блоге
|
||||
*/
|
||||
if ($oTopic->getPublish() == 1 and $oBlog->getType() != 'personal' and strtotime($oTopic->getDatePublish()) <= time()) {
|
||||
$this->Topic_SendNotifyTopicNew($oTopic, $oUser);
|
||||
}
|
||||
/**
|
||||
* Добавляем событие в ленту
|
||||
*/
|
||||
$this->Stream_write($oTopic->getUserId(), 'add_topic', $oTopic->getId(),
|
||||
$oTopic->getPublish() && $oBlog->getType() != 'close', $oTopic->getDatePublish());
|
||||
|
||||
$this->Viewer_AssignAjax('sUrlRedirect', $oTopic->getUrl());
|
||||
$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'));
|
||||
}
|
||||
} else {
|
||||
$this->Message_AddError($oTopic->_getValidateError(), $this->Lang_Get('common.error.error'));
|
||||
}
|
||||
}
|
||||
|
||||
public function EventAjaxPreview()
|
||||
{
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Пользователь авторизован?
|
||||
*/
|
||||
if (!$this->oUserCurrent) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.need_authorization'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Допустимый тип топика?
|
||||
*/
|
||||
if (!$this->Topic_IsAllowTopicType($sType = getRequestStr('topic_type'))) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('topic.add.notices.error_type'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
$aTopicRequest = getRequest('topic');
|
||||
/**
|
||||
* Проверка на ID при редактировании топика
|
||||
*/
|
||||
$iId = isset($aTopicRequest['id']) ? (int)$aTopicRequest['id'] : null;
|
||||
if ($iId and !($oTopicOriginal = $this->Topic_GetTopicById($iId))) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Если права на редактирование
|
||||
*/
|
||||
if ($iId and !$this->ACL_IsAllowEditTopic($oTopicOriginal, $this->oUserCurrent)) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
/**
|
||||
* Создаем объект топика для валидации данных
|
||||
*/
|
||||
$oTopic = Engine::GetEntity('ModuleTopic_EntityTopic');
|
||||
$oTopic->setTitle(isset($aTopicRequest['topic_title']) ? strip_tags($aTopicRequest['topic_title']) : '');
|
||||
$oTopic->setTextSource(isset($aTopicRequest['topic_text_source']) ? $aTopicRequest['topic_text_source'] : '');
|
||||
$oTopic->setTags(isset($aTopicRequest['topic_tags']) ? $aTopicRequest['topic_tags'] : '');
|
||||
$oTopic->setDateAdd(date("Y-m-d H:i:s"));
|
||||
$oTopic->setDatePublish(date("Y-m-d H:i:s"));
|
||||
$oTopic->setUserId($this->oUserCurrent->getId());
|
||||
$oTopic->setType($sType);
|
||||
$oTopic->setPublish(1);
|
||||
$oTopic->setProperties(getRequest('property'));
|
||||
/**
|
||||
* Перед валидацией аттачим существующие свойста
|
||||
*/
|
||||
if ($iId) {
|
||||
$oTopic->setId($iId);
|
||||
$a = $oTopic->getPropertyList();
|
||||
}
|
||||
/**
|
||||
* Валидируем необходимые поля топика
|
||||
*/
|
||||
$oTopic->_Validate(array('topic_title', 'topic_text', 'topic_tags', 'topic_type', 'properties'), false);
|
||||
if ($oTopic->_hasValidateErrors()) {
|
||||
$this->Message_AddErrorSingle($oTopic->_getValidateError());
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Аттачим опросы
|
||||
*/
|
||||
if (!$oTopic->getId()) {
|
||||
$aPolls = array();
|
||||
if ($sPollTargetTmp = $this->Session_GetCookie('poll_target_tmp_topic')) {
|
||||
$aPolls = $this->Poll_GetPollItemsByFilter(array(
|
||||
'target_type' => 'topic',
|
||||
'target_tmp' => $sPollTargetTmp,
|
||||
'#order' => array('id' => 'asc')
|
||||
));
|
||||
}
|
||||
$oTopic->setPolls($aPolls);
|
||||
}
|
||||
/**
|
||||
* Аттачим дополнительные поля к топику
|
||||
*/
|
||||
$this->Property_AttachPropertiesForTarget($oTopic, $oTopic->getPropertiesObject());
|
||||
/**
|
||||
* Формируем текст топика
|
||||
*/
|
||||
list($sTextShort, $sTextNew, $sTextCut) = $this->Text_Cut($oTopic->getTextSource());
|
||||
$oTopic->setCutText($sTextCut);
|
||||
$oTopic->setText($this->Topic_Parser($sTextNew, $oTopic));
|
||||
$oTopic->setTextShort($this->Topic_Parser($sTextShort, $oTopic));
|
||||
/**
|
||||
* Рендерим шаблон для предпросмотра топика
|
||||
*/
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
$aParams = array(
|
||||
'isPreview' => true,
|
||||
'topic' => $oTopic,
|
||||
);
|
||||
foreach ($aParams as $sName => $mValue) {
|
||||
$oViewer->Assign($sName, $mValue, true);
|
||||
}
|
||||
$oViewer->Assign('params', $aParams); // fix для корректной работы подключения внутренних шаблонов компонента
|
||||
|
||||
$sTemplate = 'component@topic.type';
|
||||
$sTextResult = $oViewer->Fetch($sTemplate);
|
||||
/**
|
||||
* Передаем результат в ajax ответ
|
||||
*/
|
||||
$this->Viewer_AssignAjax('sText', $sTextResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* При завершении экшена загружаем необходимые переменные
|
||||
*
|
||||
*/
|
||||
public function EventShutdown()
|
||||
{
|
||||
$this->Viewer_Assign('sMenuHeadItemSelect', $this->sMenuHeadItemSelect);
|
||||
$this->Viewer_Assign('sMenuItemSelect', $this->sMenuItemSelect);
|
||||
$this->Viewer_Assign('sMenuSubItemSelect', $this->sMenuSubItemSelect);
|
||||
}
|
||||
}
|
43
application/classes/actions/ActionDonate.class.php
Normal file
43
application/classes/actions/ActionDonate.class.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* Статическая страница доната
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionDonate extends Action
|
||||
{
|
||||
/**
|
||||
* Инициализация экшена
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем дефолтный евент
|
||||
*/
|
||||
$this->SetDefaultEvent('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем евенты
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('index', 'EventIndex');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод правил
|
||||
*
|
||||
*/
|
||||
protected function EventIndex()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle('Поддержать IFHub');
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
}
|
103
application/classes/actions/ActionError.class.php
Normal file
103
application/classes/actions/ActionError.class.php
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки УРЛа вида /error/ т.е. ошибок
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionError extends Action
|
||||
{
|
||||
/**
|
||||
* Список специфических HTTP ошибок для которых необходимо отдавать header
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aHttpErrors = array(
|
||||
'404' => array(
|
||||
'header' => '404 Not Found',
|
||||
),
|
||||
'403' => array(
|
||||
'header' => '403 Forbidden',
|
||||
),
|
||||
'500' => array(
|
||||
'header' => '500 Internal Server Error',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Инициализация экшена
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем дефолтный евент
|
||||
*/
|
||||
$this->SetDefaultEvent('index');
|
||||
/**
|
||||
* Запрешаем отображать статистику выполнения
|
||||
*/
|
||||
Router::SetIsShowStats(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем евенты
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('index', 'EventError');
|
||||
$this->AddEventPreg('/^\d{3}$/i', 'EventError');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод ошибки
|
||||
*
|
||||
*/
|
||||
protected function EventError()
|
||||
{
|
||||
/**
|
||||
* Если евент равен одной из ошибок из $aHttpErrors, то шлем браузеру специфичный header
|
||||
* Например, для 404 в хидере будет послан браузеру заголовок HTTP/1.1 404 Not Found
|
||||
*/
|
||||
if (array_key_exists($this->sCurrentEvent, $this->aHttpErrors)) {
|
||||
/**
|
||||
* Смотрим есть ли сообщения об ошибках
|
||||
*/
|
||||
if (!$this->Message_GetError()) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.code.' . $this->sCurrentEvent),
|
||||
$this->sCurrentEvent);
|
||||
}
|
||||
$aHttpError = $this->aHttpErrors[$this->sCurrentEvent];
|
||||
if (isset($aHttpError['header'])) {
|
||||
$sProtocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
|
||||
header("{$sProtocol} {$aHttpError['header']}");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('common.error.error'));
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
}
|
372
application/classes/actions/ActionIndex.class.php
Normal file
372
application/classes/actions/ActionIndex.class.php
Normal file
|
@ -0,0 +1,372 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обработка главной страницы, т.е. УРЛа вида /index/
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionIndex extends Action
|
||||
{
|
||||
/**
|
||||
* Главное меню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuHeadItemSelect = 'blog';
|
||||
/**
|
||||
* Меню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuItemSelect = 'index';
|
||||
/**
|
||||
* Субменю
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuSubItemSelect = 'good';
|
||||
/**
|
||||
* Число новых топиков
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $iCountTopicsNew = 0;
|
||||
/**
|
||||
* Число новых топиков в коллективных блогах
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $iCountTopicsCollectiveNew = 0;
|
||||
/**
|
||||
* Число новых топиков в персональных блогах
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $iCountTopicsPersonalNew = 0;
|
||||
/**
|
||||
* URL-префикс для навигации по топикам
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sNavTopicsSubUrl = '';
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Подсчитываем новые топики
|
||||
*/
|
||||
$this->iCountTopicsCollectiveNew = $this->Topic_GetCountTopicsCollectiveNew();
|
||||
$this->iCountTopicsPersonalNew = $this->Topic_GetCountTopicsPersonalNew();
|
||||
$this->iCountTopicsNew = $this->iCountTopicsCollectiveNew + $this->iCountTopicsPersonalNew;
|
||||
$this->sNavTopicsSubUrl = Router::GetPath('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEventPreg('/^(page([1-9]\d{0,5}))?$/i', 'EventIndex');
|
||||
$this->AddEventPreg('/^new$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventNew');
|
||||
$this->AddEventPreg('/^newall$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventNewAll');
|
||||
$this->AddEventPreg('/^discussed$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventDiscussed');
|
||||
$this->AddEventPreg('/^top$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventTop');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Вывод рейтинговых топиков
|
||||
*/
|
||||
protected function EventTop()
|
||||
{
|
||||
$sPeriod = Config::Get('module.topic.default_period_top');
|
||||
if (in_array(getRequestStr('period'), array(1, 7, 30, 'all'))) {
|
||||
$sPeriod = getRequestStr('period');
|
||||
}
|
||||
if (!$sPeriod) {
|
||||
$sPeriod = 1;
|
||||
}
|
||||
/**
|
||||
* Меню
|
||||
*/
|
||||
$this->sMenuSubItemSelect = 'top';
|
||||
/**
|
||||
* Передан ли номер страницы
|
||||
*/
|
||||
$iPage = $this->GetParamEventMatch(0, 2) ? $this->GetParamEventMatch(0, 2) : 1;
|
||||
if ($iPage == 1 and !getRequest('period')) {
|
||||
$this->Viewer_SetHtmlCanonical(Router::GetPath('index') . 'top/');
|
||||
}
|
||||
/**
|
||||
* Получаем список топиков
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsTop($iPage, Config::Get('module.topic.per_page'),
|
||||
$sPeriod == 'all' ? null : $sPeriod * 60 * 60 * 24);
|
||||
/**
|
||||
* Если нет топиков за 1 день, то показываем за неделю (7)
|
||||
*/
|
||||
if (!$aResult['count'] and $iPage == 1 and !getRequest('period')) {
|
||||
$sPeriod = 7;
|
||||
$aResult = $this->Topic_GetTopicsTop($iPage, Config::Get('module.topic.per_page'),
|
||||
$sPeriod == 'all' ? null : $sPeriod * 60 * 60 * 24);
|
||||
}
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Вызов хуков
|
||||
*/
|
||||
$this->Hook_Run('topics_list_show', array('aTopics' => &$aTopics));
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('module.topic.per_page'),
|
||||
Config::Get('pagination.pages.count'), Router::GetPath('index') . 'top', array('period' => $sPeriod));
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('topics', $aTopics);
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
$this->Viewer_Assign('periodSelectCurrent', $sPeriod);
|
||||
$this->Viewer_Assign('periodSelectCurrentTitle', $this->Lang_Get('blog.menu.top_period_' . $sPeriod));
|
||||
$this->Viewer_Assign('periodSelectRoot', Router::GetPath('index') . 'top/');
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->SetTemplateAction('index');
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('blog.menu.all_top'));
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('blog.menu.top_period_' . $sPeriod));
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод обсуждаемых топиков
|
||||
*/
|
||||
protected function EventDiscussed()
|
||||
{
|
||||
$sPeriod = Config::Get('module.topic.default_period_discussed');
|
||||
if (in_array(getRequestStr('period'), array(1, 7, 30, 'all'))) {
|
||||
$sPeriod = getRequestStr('period');
|
||||
}
|
||||
if (!$sPeriod) {
|
||||
$sPeriod = 1;
|
||||
}
|
||||
/**
|
||||
* Меню
|
||||
*/
|
||||
$this->sMenuSubItemSelect = 'discussed';
|
||||
/**
|
||||
* Передан ли номер страницы
|
||||
*/
|
||||
$iPage = $this->GetParamEventMatch(0, 2) ? $this->GetParamEventMatch(0, 2) : 1;
|
||||
if ($iPage == 1 and !getRequest('period')) {
|
||||
$this->Viewer_SetHtmlCanonical(Router::GetPath('index') . 'discussed/');
|
||||
}
|
||||
/**
|
||||
* Получаем список топиков
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsDiscussed($iPage, Config::Get('module.topic.per_page'),
|
||||
$sPeriod == 'all' ? null : $sPeriod * 60 * 60 * 24);
|
||||
/**
|
||||
* Если нет топиков за 1 день, то показываем за неделю (7)
|
||||
*/
|
||||
if (!$aResult['count'] and $iPage == 1 and !getRequest('period')) {
|
||||
$sPeriod = 7;
|
||||
$aResult = $this->Topic_GetTopicsDiscussed($iPage, Config::Get('module.topic.per_page'),
|
||||
$sPeriod == 'all' ? null : $sPeriod * 60 * 60 * 24);
|
||||
}
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Вызов хуков
|
||||
*/
|
||||
$this->Hook_Run('topics_list_show', array('aTopics' => &$aTopics));
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('module.topic.per_page'),
|
||||
Config::Get('pagination.pages.count'), Router::GetPath('index') . 'discussed', array('period' => $sPeriod));
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('topics', $aTopics);
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
$this->Viewer_Assign('periodSelectCurrent', $sPeriod);
|
||||
$this->Viewer_Assign('periodSelectCurrentTitle', $this->Lang_Get('blog.menu.top_period_' . $sPeriod));
|
||||
$this->Viewer_Assign('periodSelectRoot', Router::GetPath('index') . 'discussed/');
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->SetTemplateAction('index');
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('blog.menu.all_discussed'));
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('blog.menu.top_period_' . $sPeriod));
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод новых топиков
|
||||
*/
|
||||
protected function EventNew()
|
||||
{
|
||||
$this->Viewer_SetHtmlRssAlternate(Router::GetPath('rss') . 'new/', Config::Get('view.name'));
|
||||
/**
|
||||
* Меню
|
||||
*/
|
||||
$this->sMenuSubItemSelect = 'new';
|
||||
/**
|
||||
* Передан ли номер страницы
|
||||
*/
|
||||
$iPage = $this->GetParamEventMatch(0, 2) ? $this->GetParamEventMatch(0, 2) : 1;
|
||||
/**
|
||||
* Получаем список топиков
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsNew($iPage, Config::Get('module.topic.per_page'));
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Вызов хуков
|
||||
*/
|
||||
$this->Hook_Run('topics_list_show', array('aTopics' => &$aTopics));
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('module.topic.per_page'),
|
||||
Config::Get('pagination.pages.count'), Router::GetPath('index') . 'new');
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('topics', $aTopics);
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->SetTemplateAction('index');
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('blog.menu.all_new'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод ВСЕХ новых топиков
|
||||
*/
|
||||
protected function EventNewAll()
|
||||
{
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('blog.menu.all'));
|
||||
$this->Viewer_SetHtmlRssAlternate(Router::GetPath('rss') . 'new/', Config::Get('view.name'));
|
||||
/**
|
||||
* Меню
|
||||
*/
|
||||
$this->sMenuSubItemSelect = 'new';
|
||||
/**
|
||||
* Передан ли номер страницы
|
||||
*/
|
||||
$iPage = $this->GetParamEventMatch(0, 2) ? $this->GetParamEventMatch(0, 2) : 1;
|
||||
/**
|
||||
* Получаем список топиков
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsNewAll($iPage, Config::Get('module.topic.per_page'));
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Вызов хуков
|
||||
*/
|
||||
$this->Hook_Run('topics_list_show', array('aTopics' => &$aTopics));
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('module.topic.per_page'),
|
||||
Config::Get('pagination.pages.count'), Router::GetPath('index') . 'newall');
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('topics', $aTopics);
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод интересных на главную
|
||||
*
|
||||
*/
|
||||
protected function EventIndex()
|
||||
{
|
||||
$this->Viewer_SetHtmlRssAlternate(Router::GetPath('rss') . 'index/', Config::Get('view.name'));
|
||||
/**
|
||||
* Меню
|
||||
*/
|
||||
$this->sMenuSubItemSelect = 'good';
|
||||
/**
|
||||
* Передан ли номер страницы
|
||||
*/
|
||||
$iPage = $this->GetEventMatch(2) ? $this->GetEventMatch(2) : 1;
|
||||
/**
|
||||
* Устанавливаем основной URL для поисковиков
|
||||
*/
|
||||
if ($iPage == 1) {
|
||||
$this->Viewer_SetHtmlCanonical(Router::GetPath('/'));
|
||||
}
|
||||
/**
|
||||
* Получаем список топиков
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsGood($iPage, Config::Get('module.topic.per_page'));
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Вызов хуков
|
||||
*/
|
||||
$this->Hook_Run('topics_list_show', array('aTopics' => &$aTopics));
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('module.topic.per_page'),
|
||||
Config::Get('pagination.pages.count'), Router::GetPath('index'));
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('topics', $aTopics);
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* При завершении экшена загружаем переменные в шаблон
|
||||
*
|
||||
*/
|
||||
public function EventShutdown()
|
||||
{
|
||||
$this->Viewer_Assign('sMenuHeadItemSelect', $this->sMenuHeadItemSelect);
|
||||
$this->Viewer_Assign('sMenuItemSelect', $this->sMenuItemSelect);
|
||||
$this->Viewer_Assign('sMenuSubItemSelect', $this->sMenuSubItemSelect);
|
||||
$this->Viewer_Assign('iCountTopicsNew', $this->iCountTopicsNew);
|
||||
$this->Viewer_Assign('iCountTopicsCollectiveNew', $this->iCountTopicsCollectiveNew);
|
||||
$this->Viewer_Assign('iCountTopicsPersonalNew', $this->iCountTopicsPersonalNew);
|
||||
$this->Viewer_Assign('iCountTopicsSubNew', $this->iCountTopicsNew);
|
||||
$this->Viewer_Assign('sNavTopicsSubUrl', $this->sNavTopicsSubUrl);
|
||||
}
|
||||
}
|
236
application/classes/actions/ActionPeople.class.php
Normal file
236
application/classes/actions/ActionPeople.class.php
Normal file
|
@ -0,0 +1,236 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки статистики юзеров, т.е. УРЛа вида /people/
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionPeople extends Action
|
||||
{
|
||||
/**
|
||||
* Главное меню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuHeadItemSelect = 'people';
|
||||
/**
|
||||
* Меню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuItemSelect = 'all';
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('user.users'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем евенты
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEventPreg('/^(index)?$/i', '/^(page([1-9]\d{0,5}))?$/i', '/^$/i', 'EventIndex');
|
||||
$this->AddEventPreg('/^ajax-search$/i', 'EventAjaxSearch');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Поиск пользователей по логину
|
||||
*/
|
||||
protected function EventAjaxSearch()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Формируем фильтр
|
||||
*/
|
||||
$aFilter = array(
|
||||
'activate' => 1
|
||||
);
|
||||
$sOrderWay = in_array(getRequestStr('order'), array('desc', 'asc')) ? getRequestStr('order') : 'desc';
|
||||
$sOrderField = in_array(getRequestStr('sort_by'), array(
|
||||
'user_rating',
|
||||
'user_date_register',
|
||||
'user_login',
|
||||
'user_profile_name'
|
||||
)) ? getRequestStr('sort_by') : 'user_rating';
|
||||
if (is_numeric(getRequestStr('next_page')) and getRequestStr('next_page') > 0) {
|
||||
$iPage = getRequestStr('next_page');
|
||||
} else {
|
||||
$iPage = 1;
|
||||
}
|
||||
/**
|
||||
* Получаем из реквеста первые буквы для поиска пользователей по логину
|
||||
*/
|
||||
$sTitle = getRequest('sText');
|
||||
if (is_string($sTitle) and mb_strlen($sTitle, 'utf-8')) {
|
||||
$sTitle = str_replace(array('_', '%'), array('\_', '\%'), $sTitle);
|
||||
} else {
|
||||
$sTitle = '';
|
||||
}
|
||||
/**
|
||||
* Как именно искать: совпадение в любой части логина, или только начало или конец логина
|
||||
*/
|
||||
if ($sTitle) {
|
||||
if (getRequest('isPrefix')) {
|
||||
$sTitle .= '%';
|
||||
} elseif (getRequest('isPostfix')) {
|
||||
$sTitle = '%' . $sTitle;
|
||||
} else {
|
||||
$sTitle = '%' . $sTitle . '%';
|
||||
}
|
||||
}
|
||||
if ($sTitle) {
|
||||
$aFilter['name'] = $sTitle;
|
||||
}
|
||||
/**
|
||||
* Пол
|
||||
*/
|
||||
if (in_array(getRequestStr('sex'), array('man', 'woman', 'other'))) {
|
||||
$aFilter['profile_sex'] = getRequestStr('sex');
|
||||
}
|
||||
/**
|
||||
* Онлайн
|
||||
* date_last
|
||||
*/
|
||||
if (getRequest('is_online')) {
|
||||
$aFilter['date_last_more'] = date('Y-m-d H:i:s', time() - Config::Get('module.user.time_onlive'));
|
||||
}
|
||||
/**
|
||||
* Geo привязка
|
||||
*/
|
||||
if (getRequestStr('city')) {
|
||||
$aFilter['geo_city'] = getRequestStr('city');
|
||||
} elseif (getRequestStr('region')) {
|
||||
$aFilter['geo_region'] = getRequestStr('region');
|
||||
} elseif (getRequestStr('country')) {
|
||||
$aFilter['geo_country'] = getRequestStr('country');
|
||||
}
|
||||
/**
|
||||
* Ищем пользователей
|
||||
*/
|
||||
$aResult = $this->User_GetUsersByFilter($aFilter, array($sOrderField => $sOrderWay), $iPage,
|
||||
Config::Get('module.user.per_page'));
|
||||
$bHideMore = $iPage * Config::Get('module.user.per_page') >= $aResult['count'];
|
||||
/**
|
||||
* Формируем ответ
|
||||
*/
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
$oViewer->Assign('users', $aResult['collection'], true);
|
||||
$oViewer->Assign('oUserCurrent', $this->User_GetUserCurrent());
|
||||
$this->Viewer_AssignAjax('html', $oViewer->Fetch("component@user.list-loop"));
|
||||
/**
|
||||
* Для подгрузки
|
||||
*/
|
||||
$this->Viewer_AssignAjax('count_loaded', count($aResult['collection']));
|
||||
$this->Viewer_AssignAjax('next_page', count($aResult['collection']) > 0 ? $iPage + 1 : $iPage);
|
||||
$this->Viewer_AssignAjax('hide', $bHideMore or !$aResult['count'] or !count($aResult['collection']));
|
||||
$this->Viewer_AssignAjax('searchCount', (int)$aResult['count']);
|
||||
$this->Viewer_AssignAjax('count_left', (int)($aResult['count'] - ($iPage - 1) * Config::Get('module.user.per_page') - count($aResult['collection'])));
|
||||
$this->Viewer_AssignAjax('textEmpty', $this->Lang_Get('search.alerts.empty'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Показываем юзеров
|
||||
*
|
||||
*/
|
||||
protected function EventIndex()
|
||||
{
|
||||
/**
|
||||
* Получаем статистику
|
||||
*/
|
||||
$this->GetStats();
|
||||
$aFilter = array(
|
||||
'activate' => 1
|
||||
);
|
||||
/**
|
||||
* Получаем список юзеров
|
||||
*/
|
||||
$aResult = $this->User_GetUsersByFilter($aFilter, array('user_rating' => 'desc'), 1,
|
||||
Config::Get('module.user.per_page'));
|
||||
/**
|
||||
* Получаем алфавитный указатель на список пользователей
|
||||
*/
|
||||
$aPrefixUser = $this->User_GetGroupPrefixUser(1);
|
||||
/**
|
||||
* Список используемых стран
|
||||
*/
|
||||
$aCountriesUsed = $this->Geo_GetCountriesUsedByTargetType('user');
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('users', $aResult['collection']);
|
||||
$this->Viewer_Assign('searchCount', $aResult['count']);
|
||||
$this->Viewer_Assign('prefixUser', $aPrefixUser);
|
||||
$this->Viewer_Assign('countriesUsed', $aCountriesUsed);
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение статистики
|
||||
*
|
||||
*/
|
||||
protected function GetStats()
|
||||
{
|
||||
/**
|
||||
* Статистика кто, где и т.п.
|
||||
*/
|
||||
$aStat = $this->User_GetStatUsers();
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('usersStat', $aStat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется при завершении работы экшена
|
||||
*
|
||||
*/
|
||||
public function EventShutdown()
|
||||
{
|
||||
/**
|
||||
* Загружаем в шаблон необходимые переменные
|
||||
*/
|
||||
$this->Viewer_Assign('sMenuHeadItemSelect', $this->sMenuHeadItemSelect);
|
||||
$this->Viewer_Assign('sMenuItemSelect', $this->sMenuItemSelect);
|
||||
}
|
||||
}
|
1292
application/classes/actions/ActionProfile.class.php
Normal file
1292
application/classes/actions/ActionProfile.class.php
Normal file
File diff suppressed because it is too large
Load diff
123
application/classes/actions/ActionProperty.class.php
Normal file
123
application/classes/actions/ActionProperty.class.php
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки УРЛа вида /property/
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 2.0
|
||||
*/
|
||||
class ActionProperty extends Action
|
||||
{
|
||||
/**
|
||||
* Текущий пользователь
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent = null;
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Достаём текущего пользователя
|
||||
*/
|
||||
$this->oUserCurrent = $this->User_GetUserCurrent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем евенты
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEventPreg('/^download$/i', '/^[\w]{10,32}$/i', '/^$/i', 'EventDownloadFile');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Загрузка файла
|
||||
*/
|
||||
protected function EventDownloadFile()
|
||||
{
|
||||
$sKey = $this->GetParam(0);
|
||||
/**
|
||||
* Выполняем проверки
|
||||
*/
|
||||
if (!$oValue = $this->Property_GetValueByValueVarchar($sKey)) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
if (!$oProperty = $oValue->getProperty()) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
if ($oProperty->getType() != ModuleProperty::PROPERTY_TYPE_FILE) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
if (!$oTargetRel = $this->Property_GetTargetByType($oValue->getTargetType())) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
if ($oTargetRel->getState() != ModuleProperty::TARGET_STATE_ACTIVE) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
|
||||
$bAllowDownload = false;
|
||||
if (!$this->oUserCurrent) {
|
||||
if ($oProperty->getParam('access_only_auth')) {
|
||||
return Router::Action('error', '403');
|
||||
} else {
|
||||
$bAllowDownload = true;
|
||||
}
|
||||
}
|
||||
if (!$bAllowDownload) {
|
||||
/**
|
||||
* Проверяем доступ пользователя к объекту, которому принадлежит свойство
|
||||
*/
|
||||
if ($this->Property_CheckAllowTargetObject($oValue->getTargetType(), $oValue->getTargetId(),
|
||||
array('user' => $this->oUserCurrent))
|
||||
) {
|
||||
$bAllowDownload = true;
|
||||
}
|
||||
}
|
||||
if ($bAllowDownload) {
|
||||
/**
|
||||
* Увеличиваем количество загрузок
|
||||
*/
|
||||
$aStats = $oValue->getDataOne('stats');
|
||||
$aStats['count_download'] = (isset($aStats['count_download']) ? $aStats['count_download'] : 0) + 1;
|
||||
$oValue->setDataOne('stats', $aStats);
|
||||
$oValue->Update();
|
||||
$oValueType = $oValue->getValueTypeObject();
|
||||
if (!$oValueType->DownloadFile()) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
} else {
|
||||
return Router::Action('error', '403');
|
||||
}
|
||||
|
||||
$this->SetTemplate(false);
|
||||
}
|
||||
}
|
460
application/classes/actions/ActionRss.class.php
Normal file
460
application/classes/actions/ActionRss.class.php
Normal file
|
@ -0,0 +1,460 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен бработки RSS
|
||||
* Автор класса vovazol(http://livestreet.ru/profile/vovazol/)
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionRss extends Action
|
||||
{
|
||||
/**
|
||||
* Инициализация
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
$this->SetDefaultEvent('index');
|
||||
Router::SetIsShowStats(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Указывает браузеру правильный content type в случае вывода RSS-ленты
|
||||
*/
|
||||
protected function InitRss()
|
||||
{
|
||||
header('Content-Type: application/rss+xml; charset=utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('index', 'RssGood');
|
||||
$this->AddEvent('full', 'RssFull');
|
||||
$this->AddEvent('new', 'RssNew');
|
||||
$this->AddEvent('allcomments', 'RssComments');
|
||||
$this->AddEvent('comments', 'RssTopicComments');
|
||||
$this->AddEvent('tag', 'RssTag');
|
||||
$this->AddEvent('blog', 'RssColectiveBlog');
|
||||
$this->AddEvent('personal_blog', 'RssPersonalBlog');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод RSS интересных топиков
|
||||
*/
|
||||
protected function RssGood()
|
||||
{
|
||||
/**
|
||||
* Получаем топики
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsGood(1, Config::Get('module.topic.max_rss_count'), false);
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Формируем данные канала RSS
|
||||
*/
|
||||
$aChannel['title'] = Config::Get('view.name');
|
||||
$aChannel['link'] = Router::GetPath('/');
|
||||
$aChannel['description'] = Config::Get('view.name') . ' / RSS channel';
|
||||
$aChannel['language'] = 'ru';
|
||||
$aChannel['managingEditor'] = Config::Get('general.rss_editor_mail');
|
||||
$aChannel['generator'] = Config::Get('view.name');
|
||||
/**
|
||||
* Формируем записи RSS
|
||||
*/
|
||||
$topics = array();
|
||||
foreach ($aTopics as $oTopic) {
|
||||
$item['title'] = $oTopic->getTitle();
|
||||
$item['guid'] = $oTopic->getUrl();
|
||||
$item['link'] = $oTopic->getUrl();
|
||||
$item['description'] = $this->getTopicText($oTopic);
|
||||
$item['pubDate'] = $oTopic->getDatePublish();
|
||||
$item['author'] = $oTopic->getUser()->getLogin();
|
||||
$item['category'] = htmlspecialchars($oTopic->getTags());
|
||||
$topics[] = $item;
|
||||
}
|
||||
/**
|
||||
* Формируем ответ
|
||||
*/
|
||||
$this->InitRss();
|
||||
$this->Viewer_Assign('aChannel', $aChannel);
|
||||
$this->Viewer_Assign('aItems', $topics);
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод RSS новых топиков
|
||||
*/
|
||||
protected function RssNew()
|
||||
{
|
||||
/**
|
||||
* Получаем топики
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsNew(1, Config::Get('module.topic.max_rss_count'), false);
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Формируем данные канала RSS
|
||||
*/
|
||||
$aChannel['title'] = Config::Get('view.name');
|
||||
$aChannel['link'] = Router::GetPath('/');
|
||||
$aChannel['description'] = Router::GetPath('/') . ' / RSS channel';
|
||||
$aChannel['language'] = 'ru';
|
||||
$aChannel['managingEditor'] = Config::Get('general.rss_editor_mail');
|
||||
$aChannel['generator'] = Router::GetPath('/');
|
||||
/**
|
||||
* Формируем записи RSS
|
||||
*/
|
||||
$topics = array();
|
||||
foreach ($aTopics as $oTopic) {
|
||||
$item['title'] = $oTopic->getTitle();
|
||||
$item['guid'] = $oTopic->getUrl();
|
||||
$item['link'] = $oTopic->getUrl();
|
||||
$item['description'] = $this->getTopicText($oTopic);
|
||||
$item['pubDate'] = $oTopic->getDatePublish();
|
||||
$item['author'] = $oTopic->getUser()->getLogin();
|
||||
$item['category'] = htmlspecialchars($oTopic->getTags());
|
||||
$topics[] = $item;
|
||||
}
|
||||
/**
|
||||
* Формируем ответ
|
||||
*/
|
||||
$this->InitRss();
|
||||
$this->Viewer_Assign('aChannel', $aChannel);
|
||||
$this->Viewer_Assign('aItems', $topics);
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод полнотекстового RSS интересных топиков
|
||||
*/
|
||||
protected function RssFull()
|
||||
{
|
||||
/**
|
||||
* Получаем топики
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsNew(1, Config::Get('module.topic.max_rss_count'), false);
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Формируем данные канала RSS
|
||||
*/
|
||||
$aChannel['title'] = Config::Get('view.name');
|
||||
$aChannel['link'] = Router::GetPath('/');
|
||||
$aChannel['description'] = Config::Get('view.name') . ' / RSS channel';
|
||||
$aChannel['language'] = 'ru';
|
||||
$aChannel['managingEditor'] = Config::Get('general.rss_editor_mail');
|
||||
$aChannel['generator'] = Config::Get('view.name');
|
||||
/**
|
||||
* Формируем записи RSS
|
||||
*/
|
||||
$topics = array();
|
||||
foreach ($aTopics as $oTopic) {
|
||||
$item['title'] = $oTopic->getTitle();
|
||||
$item['guid'] = $oTopic->getUrl();
|
||||
$item['link'] = $oTopic->getUrl();
|
||||
$item['description'] = $this->getTopicFullText($oTopic);
|
||||
$item['pubDate'] = $oTopic->getDatePublish();
|
||||
$item['author'] = $oTopic->getUser()->getLogin();
|
||||
$item['category'] = htmlspecialchars($oTopic->getTags());
|
||||
$topics[] = $item;
|
||||
}
|
||||
/**
|
||||
* Формируем ответ
|
||||
*/
|
||||
$this->InitRss();
|
||||
$this->Viewer_Assign('aChannel', $aChannel);
|
||||
$this->Viewer_Assign('aItems', $topics);
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод RSS последних комментариев
|
||||
*/
|
||||
protected function RssComments()
|
||||
{
|
||||
/**
|
||||
* Получаем закрытые блоги, чтобы исключить их из выдачи
|
||||
*/
|
||||
$aCloseBlogs = $this->Blog_GetInaccessibleBlogsByUser();
|
||||
/**
|
||||
* Получаем комментарии
|
||||
*/
|
||||
$aResult = $this->Comment_GetCommentsAll('topic', 1, Config::Get('module.comment.max_rss_count'), array(),
|
||||
$aCloseBlogs);
|
||||
$aComments = $aResult['collection'];
|
||||
/**
|
||||
* Формируем данные канала RSS
|
||||
*/
|
||||
$aChannel['title'] = Config::Get('view.name');
|
||||
$aChannel['link'] = Router::GetPath('/');
|
||||
$aChannel['description'] = Router::GetPath('/') . ' / RSS channel';
|
||||
$aChannel['language'] = 'ru';
|
||||
$aChannel['managingEditor'] = Config::Get('general.rss_editor_mail');
|
||||
$aChannel['generator'] = Router::GetPath('/');
|
||||
/**
|
||||
* Формируем записи RSS
|
||||
*/
|
||||
$comments = array();
|
||||
foreach ($aComments as $oComment) {
|
||||
$item['title'] = 'Comments: ' . $oComment->getTarget()->getTitle();
|
||||
$item['guid'] = $oComment->getTarget()->getUrl() . '#comment' . $oComment->getId();
|
||||
$item['link'] = $oComment->getTarget()->getUrl() . '#comment' . $oComment->getId();
|
||||
$item['description'] = $oComment->getText();
|
||||
$item['pubDate'] = $oComment->getDate();
|
||||
$item['author'] = $oComment->getUser()->getLogin();
|
||||
$item['category'] = 'comments';
|
||||
$comments[] = $item;
|
||||
}
|
||||
/**
|
||||
* Формируем ответ
|
||||
*/
|
||||
$this->InitRss();
|
||||
$this->Viewer_Assign('aChannel', $aChannel);
|
||||
$this->Viewer_Assign('aItems', $comments);
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод RSS комментариев конкретного топика
|
||||
*/
|
||||
protected function RssTopicComments()
|
||||
{
|
||||
$sTopicId = $this->GetParam(0);
|
||||
/**
|
||||
* Топик существует?
|
||||
*/
|
||||
if (!($oTopic = $this->Topic_GetTopicById($sTopicId)) or !$oTopic->getPublish() or $oTopic->getBlog()->getType() == 'close') {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
/**
|
||||
* Получаем комментарии
|
||||
*/
|
||||
$aResult = $this->Comment_GetCommentsByFilter(array('target_id' => $oTopic->getId(),
|
||||
'target_type' => 'topic',
|
||||
'delete' => 0
|
||||
), array('comment_id' => 'desc'), 1, 100);
|
||||
$aComments = $aResult['collection'];
|
||||
/**
|
||||
* Формируем данные канала RSS
|
||||
*/
|
||||
$aChannel['title'] = Config::Get('view.name');
|
||||
$aChannel['link'] = Router::GetPath('/');
|
||||
$aChannel['description'] = Router::GetPath('/') . ' / RSS channel';
|
||||
$aChannel['language'] = 'ru';
|
||||
$aChannel['managingEditor'] = Config::Get('general.rss_editor_mail');
|
||||
$aChannel['generator'] = Router::GetPath('/');
|
||||
/**
|
||||
* Формируем записи RSS
|
||||
*/
|
||||
$comments = array();
|
||||
foreach ($aComments as $oComment) {
|
||||
$item['title'] = 'Comments: ' . $oTopic->getTitle();
|
||||
$item['guid'] = $oTopic->getUrl() . '#comment' . $oComment->getId();
|
||||
$item['link'] = $oTopic->getUrl() . '#comment' . $oComment->getId();
|
||||
$item['description'] = $oComment->getText();
|
||||
$item['pubDate'] = $oComment->getDate();
|
||||
$item['author'] = $oComment->getUser()->getLogin();
|
||||
$item['category'] = 'comments';
|
||||
$comments[] = $item;
|
||||
}
|
||||
/**
|
||||
* Формируем ответ
|
||||
*/
|
||||
$this->InitRss();
|
||||
$this->Viewer_Assign('aChannel', $aChannel);
|
||||
$this->Viewer_Assign('aItems', $comments);
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод RSS топиков по определенному тегу
|
||||
*/
|
||||
protected function RssTag()
|
||||
{
|
||||
$sTag = urldecode($this->GetParam(0));
|
||||
/**
|
||||
* Получаем топики
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsByTag($sTag, 1, Config::Get('module.topic.max_rss_count'), false);
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Формируем данные канала RSS
|
||||
*/
|
||||
$aChannel['title'] = Config::Get('view.name');
|
||||
$aChannel['link'] = Router::GetPath('/');
|
||||
$aChannel['description'] = Router::GetPath('/') . ' / RSS channel';
|
||||
$aChannel['language'] = 'ru';
|
||||
$aChannel['managingEditor'] = Config::Get('general.rss_editor_mail');
|
||||
$aChannel['generator'] = Router::GetPath('/');
|
||||
/**
|
||||
* Формируем записи RSS
|
||||
*/
|
||||
$topics = array();
|
||||
foreach ($aTopics as $oTopic) {
|
||||
$item['title'] = $oTopic->getTitle();
|
||||
$item['guid'] = $oTopic->getUrl();
|
||||
$item['link'] = $oTopic->getUrl();
|
||||
$item['description'] = $this->getTopicText($oTopic);
|
||||
$item['pubDate'] = $oTopic->getDatePublish();
|
||||
$item['author'] = $oTopic->getUser()->getLogin();
|
||||
$item['category'] = htmlspecialchars($oTopic->getTags());
|
||||
$topics[] = $item;
|
||||
}
|
||||
/**
|
||||
* Формируем ответ
|
||||
*/
|
||||
$this->InitRss();
|
||||
$this->Viewer_Assign('aChannel', $aChannel);
|
||||
$this->Viewer_Assign('aItems', $topics);
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод RSS топиков из коллективного блога
|
||||
*/
|
||||
protected function RssColectiveBlog()
|
||||
{
|
||||
$sBlogUrl = $this->GetParam(0);
|
||||
/**
|
||||
* Если блог существует, то получаем записи
|
||||
*/
|
||||
if (!$sBlogUrl or !($oBlog = $this->Blog_GetBlogByUrl($sBlogUrl)) or $oBlog->getType() == "close") {
|
||||
return parent::EventNotFound();
|
||||
} else {
|
||||
$aResult = $this->Topic_GetTopicsByBlog($oBlog, 1, Config::Get('module.topic.max_rss_count'), 'good');
|
||||
}
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Формируем данные канала RSS
|
||||
*/
|
||||
$aChannel['title'] = Config::Get('view.name');
|
||||
$aChannel['link'] = Router::GetPath('/');
|
||||
$aChannel['description'] = Router::GetPath('/') . ' / ' . $oBlog->getTitle() . ' / RSS channel';
|
||||
$aChannel['language'] = 'ru';
|
||||
$aChannel['managingEditor'] = Config::Get('general.rss_editor_mail');
|
||||
$aChannel['generator'] = Router::GetPath('/');
|
||||
/**
|
||||
* Формируем записи RSS
|
||||
*/
|
||||
$topics = array();
|
||||
foreach ($aTopics as $oTopic) {
|
||||
$item['title'] = $oTopic->getTitle();
|
||||
$item['guid'] = $oTopic->getUrl();
|
||||
$item['link'] = $oTopic->getUrl();
|
||||
$item['description'] = $this->getTopicText($oTopic);
|
||||
$item['pubDate'] = $oTopic->getDatePublish();
|
||||
$item['author'] = $oTopic->getUser()->getLogin();
|
||||
$item['category'] = htmlspecialchars($oTopic->getTags());
|
||||
$topics[] = $item;
|
||||
}
|
||||
/**
|
||||
* Формируем ответ
|
||||
*/
|
||||
$this->InitRss();
|
||||
$this->Viewer_Assign('aChannel', $aChannel);
|
||||
$this->Viewer_Assign('aItems', $topics);
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод RSS топиков из персонального блога или всех персональных
|
||||
*/
|
||||
protected function RssPersonalBlog()
|
||||
{
|
||||
$this->sUserLogin = $this->GetParam(0);
|
||||
if (!$this->sUserLogin) {
|
||||
/**
|
||||
* RSS-лента всех записей из персональных блогов
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsPersonal(1, Config::Get('module.topic.max_rss_count'));
|
||||
} elseif (!$oUser = $this->User_GetUserByLogin($this->sUserLogin)) {
|
||||
return parent::EventNotFound();
|
||||
} else {
|
||||
/**
|
||||
* RSS-лента записей персонального блога указанного пользователя
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsPersonalByUser($oUser->getId(), 1, 1,
|
||||
Config::Get('module.topic.max_rss_count'));
|
||||
}
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Формируем данные канала RSS
|
||||
*/
|
||||
$aChannel['title'] = Config::Get('view.name');
|
||||
$aChannel['link'] = Router::GetPath('/');
|
||||
$aChannel['description'] = ($this->sUserLogin)
|
||||
? Router::GetPath('/') . ' / ' . $oUser->getLogin() . ' / RSS channel'
|
||||
: Router::GetPath('/') . ' / RSS channel';
|
||||
$aChannel['language'] = 'ru';
|
||||
$aChannel['managingEditor'] = Config::Get('general.rss_editor_mail');
|
||||
$aChannel['generator'] = Router::GetPath('/');
|
||||
/**
|
||||
* Формируем записи RSS
|
||||
*/
|
||||
$topics = array();
|
||||
foreach ($aTopics as $oTopic) {
|
||||
$item['title'] = $oTopic->getTitle();
|
||||
$item['guid'] = $oTopic->getUrl();
|
||||
$item['link'] = $oTopic->getUrl();
|
||||
$item['description'] = $this->getTopicText($oTopic);
|
||||
$item['pubDate'] = $oTopic->getDatePublish();
|
||||
$item['author'] = $oTopic->getUser()->getLogin();
|
||||
$item['category'] = htmlspecialchars($oTopic->getTags());
|
||||
$topics[] = $item;
|
||||
}
|
||||
/**
|
||||
* Формируем ответ
|
||||
*/
|
||||
$this->InitRss();
|
||||
$this->Viewer_Assign('aChannel', $aChannel);
|
||||
$this->Viewer_Assign('aItems', $topics);
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует текст топика для RSS
|
||||
*
|
||||
*/
|
||||
protected function getTopicText($oTopic)
|
||||
{
|
||||
$sText = $oTopic->getTextShort();
|
||||
if ($oTopic->getTextShort() != $oTopic->getText()) {
|
||||
$sText .= "<br><a href=\"{$oTopic->getUrl()}#cut\" title=\"{$this->Lang_Get('topic.read_more')}\">";
|
||||
if ($oTopic->getCutText()) {
|
||||
$sText .= htmlspecialchars($oTopic->getCutText());
|
||||
} else {
|
||||
$sText .= $this->Lang_Get('topic.read_more');
|
||||
}
|
||||
$sText .= "</a>";
|
||||
}
|
||||
return $sText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует полный текст топика (без ката) для RSS
|
||||
*
|
||||
*/
|
||||
protected function getTopicFullText($oTopic)
|
||||
{
|
||||
return $oTopic->getText();
|
||||
}
|
||||
}
|
43
application/classes/actions/ActionRules.class.php
Normal file
43
application/classes/actions/ActionRules.class.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
/**
|
||||
* Статическая страница правил
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionRules extends Action
|
||||
{
|
||||
/**
|
||||
* Инициализация экшена
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем дефолтный евент
|
||||
*/
|
||||
$this->SetDefaultEvent('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрируем евенты
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('index', 'EventIndex');
|
||||
}
|
||||
|
||||
/**
|
||||
* Вывод правил
|
||||
*
|
||||
*/
|
||||
protected function EventIndex()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle('Правила Ифхаба');
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
}
|
172
application/classes/actions/ActionSearch.class.php
Normal file
172
application/classes/actions/ActionSearch.class.php
Normal file
|
@ -0,0 +1,172 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обработка основного поиска
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionSearch extends Action
|
||||
{
|
||||
|
||||
public function Init()
|
||||
{
|
||||
$this->SetDefaultEvent('index');
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('search.search'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('index', 'EventIndex');
|
||||
$this->AddEventPreg('/^topics$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventTopics');
|
||||
$this->AddEventPreg('/^comments$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventComments');
|
||||
$this->AddEvent('opensearch', 'EventOpenSearch');
|
||||
}
|
||||
|
||||
/**
|
||||
* Главная страница поиска
|
||||
*/
|
||||
protected function EventIndex()
|
||||
{
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка стандарта для браузеров Open Search
|
||||
*/
|
||||
function EventOpenSearch()
|
||||
{
|
||||
Router::SetIsShowStats(false);
|
||||
header('Content-type: text/xml; charset=utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка поиска топиков
|
||||
*/
|
||||
protected function EventTopics()
|
||||
{
|
||||
$this->SetTemplateAction('index');
|
||||
$sSearchType = $this->sCurrentEvent;
|
||||
$iPage = $this->GetParamEventMatch(0, 2) ? $this->GetParamEventMatch(0, 2) : 1;
|
||||
/**
|
||||
* Получаем список слов для поиска
|
||||
*/
|
||||
$aWords = $this->Search_GetWordsForSearch(mb_strtolower(getRequestStr('q'),"utf-8"));
|
||||
if (!$aWords) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('search.alerts.query_incorrect'));
|
||||
return;
|
||||
}
|
||||
$sQuery = join(' ', $aWords);
|
||||
/**
|
||||
* Формируем регулярное выражение для поиска
|
||||
*/
|
||||
$sRegexp = $this->Search_GetRegexpForWords($aWords);
|
||||
/**
|
||||
* Выполняем поиск
|
||||
*/
|
||||
$aResult = $this->Search_SearchTopics($sRegexp, $iPage, Config::Get('module.topic.per_page'));
|
||||
$aResultItems = $aResult['collection'];
|
||||
/**
|
||||
* Конфигурируем парсер jevix
|
||||
*/
|
||||
$this->Text_LoadJevixConfig('search');
|
||||
/**
|
||||
* Делаем сниппеты
|
||||
*/
|
||||
foreach ($aResultItems AS $oItem) {
|
||||
/**
|
||||
* Т.к. текст в сниппетах небольшой, то можно прогнать через парсер
|
||||
*/
|
||||
$oItem->setTextShort($this->Text_JevixParser($this->Search_BuildExcerpts($oItem->getText(), $aWords)));
|
||||
}
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('module.topic.per_page'),
|
||||
Config::Get('pagination.pages.count'), Router::GetPath('search') . $sSearchType, array('q' => $sQuery));
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('resultItems', $aResultItems);
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
$this->Viewer_Assign('searchType', $sSearchType);
|
||||
$this->Viewer_Assign('query', $sQuery);
|
||||
$this->Viewer_Assign('typeCounts', array($sSearchType => $aResult['count']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка поиска комментариев
|
||||
*/
|
||||
protected function EventComments()
|
||||
{
|
||||
$this->SetTemplateAction('index');
|
||||
$sSearchType = $this->sCurrentEvent;
|
||||
$iPage = $this->GetParamEventMatch(0, 2) ? $this->GetParamEventMatch(0, 2) : 1;
|
||||
/**
|
||||
* Получаем список слов для поиска
|
||||
*/
|
||||
$aWords = $this->Search_GetWordsForSearch(mb_strtolower(getRequestStr('q'),"utf-8"));
|
||||
if (!$aWords) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('search.alerts.query_incorrect'));
|
||||
return;
|
||||
}
|
||||
$sQuery = join(' ', $aWords);
|
||||
/**
|
||||
* Формируем регулярное выражение для поиска
|
||||
*/
|
||||
$sRegexp = $this->Search_GetRegexpForWords($aWords);
|
||||
/**
|
||||
* Выполняем поиск
|
||||
*/
|
||||
$aResult = $this->Search_SearchComments($sRegexp, $iPage, 4, 'topic');
|
||||
$aResultItems = $aResult['collection'];
|
||||
/**
|
||||
* Конфигурируем парсер jevix
|
||||
*/
|
||||
$this->Text_LoadJevixConfig('search');
|
||||
/**
|
||||
* Делаем сниппеты
|
||||
*/
|
||||
foreach ($aResultItems AS $oItem) {
|
||||
/**
|
||||
* Т.к. текст в сниппетах небольшой, то можно прогнать через парсер
|
||||
*/
|
||||
$oItem->setText($this->Text_JevixParser($this->Search_BuildExcerpts($oItem->getText(), $aWords)));
|
||||
}
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, 4, Config::Get('pagination.pages.count'),
|
||||
Router::GetPath('search') . $sSearchType, array('q' => $sQuery));
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('resultItems', $aResultItems);
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
$this->Viewer_Assign('searchType', $sSearchType);
|
||||
$this->Viewer_Assign('query', $sQuery);
|
||||
$this->Viewer_Assign('typeCounts', array($sSearchType => $aResult['count']));
|
||||
}
|
||||
}
|
731
application/classes/actions/ActionSettings.class.php
Normal file
731
application/classes/actions/ActionSettings.class.php
Normal file
|
@ -0,0 +1,731 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обрабтки настроек профиля юзера (/settings/)
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionSettings extends Action
|
||||
{
|
||||
/**
|
||||
* Какое меню активно
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuItemSelect = 'settings';
|
||||
/**
|
||||
* Меню профиля пользователя
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuProfileItemSelect = 'settings';
|
||||
/**
|
||||
* Какое подменю активно
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuSubItemSelect = 'profile';
|
||||
/**
|
||||
* Текущий юзер
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent = null;
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Проверяем авторизован ли юзер
|
||||
*/
|
||||
if (!$this->User_IsAuthorization()) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.not_access'), $this->Lang_Get('common.error.error'));
|
||||
return Router::Action('error');
|
||||
}
|
||||
/**
|
||||
* Получаем текущего юзера
|
||||
*/
|
||||
$this->oUserCurrent = $this->User_GetUserCurrent();
|
||||
$this->SetDefaultEvent('profile');
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('user.settings.title'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('profile', 'EventProfile');
|
||||
$this->AddEvent('invite', 'EventInvite');
|
||||
$this->AddEvent('tuning', 'EventTuning');
|
||||
$this->AddEvent('account', 'EventAccount');
|
||||
|
||||
$this->AddEventPreg('/^ajax-upload-photo$/i', '/^$/i', 'EventAjaxUploadPhoto');
|
||||
$this->AddEventPreg('/^ajax-crop-photo$/i', '/^$/i', 'EventAjaxCropPhoto');
|
||||
$this->AddEventPreg('/^ajax-crop-cancel-photo$/i', '/^$/i', 'EventAjaxCropCancelPhoto');
|
||||
$this->AddEventPreg('/^ajax-remove-photo$/i', '/^$/i', 'EventAjaxRemovePhoto');
|
||||
$this->AddEventPreg('/^ajax-change-avatar$/i', '/^$/i', 'EventAjaxChangeAvatar');
|
||||
$this->AddEventPreg('/^ajax-modal-crop-photo$/i', '/^$/i', 'EventAjaxModalCropPhoto');
|
||||
$this->AddEventPreg('/^ajax-modal-crop-avatar$/i', '/^$/i', 'EventAjaxModalCropAvatar');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Загрузка фотографии в профиль пользователя
|
||||
*/
|
||||
protected function EventAjaxUploadPhoto()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
if (!isset($_FILES['photo']['tmp_name'])) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
|
||||
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
if (!$oUser->isAllowEdit()) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Копируем загруженный файл
|
||||
*/
|
||||
$sFileTmp = Config::Get('sys.cache.dir') . func_generator();
|
||||
if (!move_uploaded_file($_FILES['photo']['tmp_name'], $sFileTmp)) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Если объект изображения не создан, возвращаем ошибку
|
||||
*/
|
||||
if (!$oImage = $this->Image_Open($sFileTmp)) {
|
||||
$this->Fs_RemoveFileLocal($sFileTmp);
|
||||
$this->Message_AddError($this->Image_GetLastError());
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Ресайзим и сохраняем именьшенную копию
|
||||
* Храним две копии - мелкую для показа пользователю и крупную в качестве исходной для ресайза
|
||||
*/
|
||||
$sDir = Config::Get('path.uploads.images') . "/tmp/userphoto/{$oUser->getId()}";
|
||||
$aPhotoSizes = $this->Media_ParsedImageSize(Config::Get('module.user.profile_photo_size'));
|
||||
$sSaveWidth = $aPhotoSizes['w'] > 1000 ? $aPhotoSizes['w'] : 1000;
|
||||
if ($sFileOriginal = $oImage->resize($sSaveWidth, null)->saveSmart($sDir, 'original', array('skip_watermark' => true))) {
|
||||
if ($sFilePreview = $oImage->resize(350, null)->saveSmart($sDir, 'preview', array('skip_watermark' => true))) {
|
||||
list($iOriginalWidth, $iOriginalHeight) = @getimagesize($this->Fs_GetPathServer($sFileOriginal));
|
||||
list($iWidth, $iHeight) = @getimagesize($this->Fs_GetPathServer($sFilePreview));
|
||||
/**
|
||||
* Сохраняем в сессии временный файл с изображением
|
||||
*/
|
||||
$this->Session_Set('sPhotoFileTmp', $sFileOriginal);
|
||||
$this->Session_Set('sPhotoFilePreviewTmp', $sFilePreview);
|
||||
$this->Viewer_AssignAjax('path', $this->Fs_GetPathWeb($sFilePreview));
|
||||
$this->Viewer_AssignAjax('original_width', $iOriginalWidth);
|
||||
$this->Viewer_AssignAjax('original_height', $iOriginalHeight);
|
||||
$this->Viewer_AssignAjax('width', $iWidth);
|
||||
$this->Viewer_AssignAjax('height', $iHeight);
|
||||
$this->Fs_RemoveFileLocal($sFileTmp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
$this->Message_AddError($this->Image_GetLastError());
|
||||
$this->Fs_RemoveFileLocal($sFileTmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обрезка фотографии в профиль пользователя
|
||||
*/
|
||||
protected function EventAjaxCropPhoto()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
|
||||
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
if (!$oUser->isAllowEdit()) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
|
||||
$sFile = $this->Session_Get('sPhotoFileTmp');
|
||||
$sFilePreview = $this->Session_Get('sPhotoFilePreviewTmp');
|
||||
if (!$this->Image_IsExistsFile($sFile)) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.base'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (true === ($res = $this->User_CreateProfilePhoto($sFile, $oUser, getRequest('size'),
|
||||
getRequestStr('canvas_width')))
|
||||
) {
|
||||
$this->Image_RemoveFile($sFile);
|
||||
$this->Image_RemoveFile($sFilePreview);
|
||||
$this->Session_Drop('sPhotoFileTmp');
|
||||
$this->Session_Drop('sPhotoFilePreviewTmp');
|
||||
/**
|
||||
* Создаем аватар на основе фото
|
||||
*/
|
||||
$this->User_CreateProfileAvatar($oUser->getProfileFoto(), $oUser);
|
||||
|
||||
$this->Viewer_AssignAjax('upload_text', $this->Lang_Get('user.photo.actions.change_photo'));
|
||||
$this->Viewer_AssignAjax('photo', $oUser->getProfileFotoPath());
|
||||
} else {
|
||||
$this->Message_AddError(is_string($res) ? $res : $this->Lang_Get('common.error.error'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Показывает модальное окно с кропом фото
|
||||
*/
|
||||
protected function EventAjaxModalCropPhoto()
|
||||
{
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
|
||||
$oViewer->Assign('image', getRequestStr('path'), true);
|
||||
$oViewer->Assign('originalWidth', (int)getRequest('original_width'), true);
|
||||
$oViewer->Assign('originalHeight', (int)getRequest('original_height'), true);
|
||||
$oViewer->Assign('width', (int)getRequest('width'), true);
|
||||
$oViewer->Assign('height', (int)getRequest('height'), true);
|
||||
|
||||
$this->Viewer_AssignAjax('sText', $oViewer->Fetch("component@photo.modal-photo"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Показывает модальное окно с кропом аватарки
|
||||
*/
|
||||
protected function EventAjaxModalCropAvatar()
|
||||
{
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
|
||||
$oViewer->Assign('image', getRequestStr('path'), true);
|
||||
$oViewer->Assign('originalWidth', (int)getRequest('original_width'), true);
|
||||
$oViewer->Assign('originalHeight', (int)getRequest('original_height'), true);
|
||||
$oViewer->Assign('width', (int)getRequest('width'), true);
|
||||
$oViewer->Assign('height', (int)getRequest('height'), true);
|
||||
$oViewer->Assign('usePreview', true, true);
|
||||
|
||||
$this->Viewer_AssignAjax('sText', $oViewer->Fetch("component@photo.modal-avatar"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет временные файлы кропа фото
|
||||
*/
|
||||
protected function EventAjaxCropCancelPhoto()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
|
||||
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
if (!$oUser->isAllowEdit()) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
|
||||
$sFile = $this->Session_Get('sPhotoFileTmp');
|
||||
$sFilePreview = $this->Session_Get('sPhotoFilePreviewTmp');
|
||||
|
||||
$this->Image_RemoveFile($sFile);
|
||||
$this->Image_RemoveFile($sFilePreview);
|
||||
$this->Session_Drop('sPhotoFileTmp');
|
||||
$this->Session_Drop('sPhotoFilePreviewTmp');
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление фотографии профиля
|
||||
*/
|
||||
protected function EventAjaxRemovePhoto()
|
||||
{
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
|
||||
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
if (!$oUser->isAllowEdit()) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
|
||||
$this->User_DeleteProfilePhoto($oUser);
|
||||
$this->User_DeleteProfileAvatar($oUser);
|
||||
$this->User_Update($oUser);
|
||||
|
||||
$this->Viewer_AssignAjax('upload_text', $this->Lang_Get('user.photo.actions.upload_photo'));
|
||||
$this->Viewer_AssignAjax('photo', $oUser->getProfileFotoPath());
|
||||
$this->Viewer_AssignAjax('avatars', $oUser->GetProfileAvatarsPath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновление аватара на основе фото профиля
|
||||
*/
|
||||
protected function EventAjaxChangeAvatar()
|
||||
{
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
|
||||
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
if (!$oUser->isAllowEdit()) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
|
||||
if (true === ($res = $this->User_CreateProfileAvatar($oUser->getProfileFoto(), $oUser, getRequest('size'),
|
||||
getRequestStr('canvas_width')))
|
||||
) {
|
||||
// Формируем массив с путями до аватаров
|
||||
$this->Viewer_AssignAjax('avatars', $oUser->GetProfileAvatarsPath());
|
||||
} else {
|
||||
$this->Message_AddError(is_string($res) ? $res : $this->Lang_Get('common.error.error'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительные настройки сайта
|
||||
*/
|
||||
protected function EventTuning()
|
||||
{
|
||||
$this->sMenuItemSelect = 'settings';
|
||||
$this->sMenuSubItemSelect = 'tuning';
|
||||
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('user.settings.nav.tuning'));
|
||||
$aTimezoneList = DateTimeZone::listIdentifiers();
|
||||
$this->Viewer_Assign('aTimezoneList', $aTimezoneList);
|
||||
/**
|
||||
* Если отправили форму с настройками - сохраняем
|
||||
*/
|
||||
if (isPost()) {
|
||||
$this->Security_ValidateSendForm();
|
||||
|
||||
if (in_array(getRequestStr('settings_general_timezone'), $aTimezoneList)) {
|
||||
$this->oUserCurrent->setSettingsTimezone(getRequestStr('settings_general_timezone'));
|
||||
}
|
||||
|
||||
$this->oUserCurrent->setSettingsNoticeNewTopic(getRequest('settings_notice_new_topic') ? 1 : 0);
|
||||
$this->oUserCurrent->setSettingsNoticeNewComment(getRequest('settings_notice_new_comment') ? 1 : 0);
|
||||
$this->oUserCurrent->setSettingsNoticeNewTalk(getRequest('settings_notice_new_talk') ? 1 : 0);
|
||||
$this->oUserCurrent->setSettingsNoticeReplyComment(getRequest('settings_notice_reply_comment') ? 1 : 0);
|
||||
$this->oUserCurrent->setSettingsNoticeNewFriend(getRequest('settings_notice_new_friend') ? 1 : 0);
|
||||
$this->oUserCurrent->setProfileDate(date("Y-m-d H:i:s"));
|
||||
/**
|
||||
* Запускаем выполнение хуков
|
||||
*/
|
||||
$this->Hook_Run('settings_tuning_save_before', array('oUser' => $this->oUserCurrent));
|
||||
if ($this->User_Update($this->oUserCurrent)) {
|
||||
$this->Message_AddNoticeSingle($this->Lang_Get('common.success.save'));
|
||||
$this->Hook_Run('settings_tuning_save_after', array('oUser' => $this->oUserCurrent));
|
||||
} else {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.base'));
|
||||
}
|
||||
} else {
|
||||
if (is_null($this->oUserCurrent->getSettingsTimezone())) {
|
||||
$_REQUEST['settings_general_timezone'] = date_default_timezone_get();
|
||||
} else {
|
||||
$_REQUEST['settings_general_timezone'] = $this->oUserCurrent->getSettingsTimezone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Показ и обработка формы приглаешний
|
||||
*
|
||||
*/
|
||||
protected function EventInvite()
|
||||
{
|
||||
$this->sMenuSubItemSelect = 'invite';
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('user.settings.nav.invites'));
|
||||
|
||||
$this->Viewer_Assign('iCountInviteAvailable', $this->Invite_GetCountInviteAvailable($this->oUserCurrent));
|
||||
$this->Viewer_Assign('iCountInviteUsed', $this->Invite_GetCountInviteUsed($this->oUserCurrent->getId()));
|
||||
$this->Viewer_Assign('sReferralLink', $this->Invite_GetReferralLink($this->oUserCurrent));
|
||||
/**
|
||||
* Если отправили форму
|
||||
*/
|
||||
if (isPost()) {
|
||||
$this->Security_ValidateSendForm();
|
||||
|
||||
$bError = false;
|
||||
/**
|
||||
* Есть права на отправку инвайтов?
|
||||
*/
|
||||
if (!$this->ACL_CanSendInvite($this->oUserCurrent)) {
|
||||
$this->Message_AddErrorSingle($this->Rbac_GetMsgLast());
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Емайл корректен?
|
||||
*/
|
||||
if (!$this->Validate_Validate('email', getRequestStr('invite_mail'), array('allowEmpty' => false))) {
|
||||
$this->Message_AddError($this->Validate_GetErrorLast());
|
||||
return;
|
||||
}
|
||||
|
||||
if (Config::Get('general.reg.invite')) {
|
||||
if (!($oInvite = $this->Invite_GenerateInvite($this->oUserCurrent))) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
$sRefCode = $oInvite->getCode();
|
||||
} else {
|
||||
if (!($sRefCode = $this->Invite_GetReferralCode($this->oUserCurrent))) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Если нет ошибок, то отправляем инвайт
|
||||
*/
|
||||
if (!$bError) {
|
||||
/**
|
||||
* Запускаем выполнение хуков
|
||||
*/
|
||||
$this->Hook_Run('settings_invite_send_before', array('oUser' => $this->oUserCurrent, 'sRefCode' => $sRefCode));
|
||||
|
||||
$this->Invite_SendNotifyInvite($this->oUserCurrent, getRequestStr('invite_mail'), $sRefCode);
|
||||
$this->Message_AddNoticeSingle($this->Lang_Get('user.settings.invites.notices.success'));
|
||||
$this->Hook_Run('settings_invite_send_after', array('oUser' => $this->oUserCurrent, 'sRefCode' => $sRefCode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Форма смены пароля, емайла
|
||||
*/
|
||||
protected function EventAccount()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('user.settings.nav.account'));
|
||||
$this->sMenuSubItemSelect = 'account';
|
||||
/**
|
||||
* Если нажали кнопку "Сохранить"
|
||||
*/
|
||||
if (isPost()) {
|
||||
$this->Security_ValidateSendForm();
|
||||
|
||||
$bError = false;
|
||||
/**
|
||||
* Проверка мыла
|
||||
*/
|
||||
if (func_check(getRequestStr('mail'), 'mail')) {
|
||||
if ($oUserMail = $this->User_GetUserByMail(getRequestStr('mail')) and $oUserMail->getId() != $this->oUserCurrent->getId()) {
|
||||
$this->Message_AddError($this->Lang_Get('user.settings.account.fields.email.notices.error_used'),
|
||||
$this->Lang_Get('common.error.error'));
|
||||
$bError = true;
|
||||
}
|
||||
} else {
|
||||
$this->Message_AddError($this->Lang_Get('fields.email.notices.error'), $this->Lang_Get('common.error.error'));
|
||||
$bError = true;
|
||||
}
|
||||
/**
|
||||
* Проверка на смену пароля
|
||||
*/
|
||||
if (getRequestStr('password', '') != '') {
|
||||
if (func_check(getRequestStr('password'), 'password', 5)) {
|
||||
if (getRequestStr('password') == getRequestStr('password_confirm')) {
|
||||
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'),
|
||||
$this->Lang_Get('common.error.error'));
|
||||
}
|
||||
} else {
|
||||
$bError = true;
|
||||
$this->Message_AddError($this->Lang_Get('user.settings.account.fields.password_confirm.notices.error'),
|
||||
$this->Lang_Get('common.error.error'));
|
||||
}
|
||||
} else {
|
||||
$bError = true;
|
||||
$this->Message_AddError($this->Lang_Get('user.settings.account.fields.password_new.notices.error'),
|
||||
$this->Lang_Get('common.error.error'));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Ставим дату последнего изменения
|
||||
*/
|
||||
$this->oUserCurrent->setProfileDate(date("Y-m-d H:i:s"));
|
||||
/**
|
||||
* Запускаем выполнение хуков
|
||||
*/
|
||||
$this->Hook_Run('settings_account_save_before',
|
||||
array('oUser' => $this->oUserCurrent, 'bError' => &$bError));
|
||||
/**
|
||||
* Сохраняем изменения
|
||||
*/
|
||||
if (!$bError) {
|
||||
if ($this->User_Update($this->oUserCurrent)) {
|
||||
$this->Message_AddNoticeSingle($this->Lang_Get('common.success.save'));
|
||||
/**
|
||||
* Подтверждение смены емайла
|
||||
*/
|
||||
if (getRequestStr('mail') and getRequestStr('mail') != $this->oUserCurrent->getMail()) {
|
||||
if ($oChangemail = $this->User_MakeUserChangemail($this->oUserCurrent, getRequestStr('mail'))) {
|
||||
if ($oChangemail->getMailFrom()) {
|
||||
$this->Message_AddNotice($this->Lang_Get('user.settings.account.fields.email.notices.change_from_notice'));
|
||||
} else {
|
||||
$this->Message_AddNotice($this->Lang_Get('user.settings.account.fields.email.notices.change_to_notice'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->Hook_Run('settings_account_save_after', array('oUser' => $this->oUserCurrent));
|
||||
} else {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.base'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Выводит форму для редактирования профиля и обрабатывает её
|
||||
*
|
||||
*/
|
||||
protected function EventProfile()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем title страницы
|
||||
*/
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('user.settings.nav.profile'));
|
||||
$this->Viewer_Assign('aUserFields', $this->User_getUserFields(''));
|
||||
$this->Viewer_Assign('aUserFieldsContact', $this->User_getUserFields(array('contact', 'social')));
|
||||
/**
|
||||
* Загружаем в шаблон JS текстовки
|
||||
*/
|
||||
$this->Lang_AddLangJs(array(
|
||||
'user.settings.profile.notices.error_max_userfields'
|
||||
));
|
||||
/**
|
||||
* Если нажали кнопку "Сохранить"
|
||||
*/
|
||||
if (isPost()) {
|
||||
$this->Security_ValidateSendForm();
|
||||
|
||||
$bError = false;
|
||||
/**
|
||||
* Заполняем профиль из полей формы
|
||||
*/
|
||||
/**
|
||||
* Определяем гео-объект
|
||||
*/
|
||||
$aGeo = getRequest('geo');
|
||||
|
||||
if (isset($aGeo['city']) && $aGeo['city']) {
|
||||
$oGeoObject = $this->Geo_GetGeoObject('city', (int)$aGeo['city']);
|
||||
} elseif (isset($aGeo['region']) && $aGeo['region']) {
|
||||
$oGeoObject = $this->Geo_GetGeoObject('region', (int)$aGeo['region']);
|
||||
} elseif (isset($aGeo['country']) && $aGeo['country']) {
|
||||
$oGeoObject = $this->Geo_GetGeoObject('country', (int)$aGeo['country']);
|
||||
} else {
|
||||
$oGeoObject = null;
|
||||
}
|
||||
/**
|
||||
* Проверяем имя
|
||||
*/
|
||||
if (func_check(getRequestStr('profile_name'), 'text', 2, Config::Get('module.user.name_max'))) {
|
||||
$this->oUserCurrent->setProfileName(getRequestStr('profile_name'));
|
||||
} else {
|
||||
$this->oUserCurrent->setProfileName(null);
|
||||
}
|
||||
/**
|
||||
* Проверяем пол
|
||||
*/
|
||||
if (in_array(getRequestStr('profile_sex'), array('man', 'woman', 'other'))) {
|
||||
$this->oUserCurrent->setProfileSex(getRequestStr('profile_sex'));
|
||||
} else {
|
||||
$this->oUserCurrent->setProfileSex('other');
|
||||
}
|
||||
/**
|
||||
* Проверяем дату рождения
|
||||
*/
|
||||
$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));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Проверяем информацию о себе
|
||||
*/
|
||||
if (func_check(getRequestStr('profile_about'), 'text', 1, 3000)) {
|
||||
$this->oUserCurrent->setProfileAbout($this->Text_Parser(getRequestStr('profile_about')));
|
||||
} else {
|
||||
$this->oUserCurrent->setProfileAbout(null);
|
||||
}
|
||||
/**
|
||||
* Ставим дату последнего изменения профиля
|
||||
*/
|
||||
$this->oUserCurrent->setProfileDate(date("Y-m-d H:i:s"));
|
||||
/**
|
||||
* Запускаем выполнение хуков
|
||||
*/
|
||||
$this->Hook_Run('settings_profile_save_before',
|
||||
array('oUser' => $this->oUserCurrent, 'bError' => &$bError));
|
||||
/**
|
||||
* Сохраняем изменения профиля
|
||||
*/
|
||||
if (!$bError) {
|
||||
if ($this->User_Update($this->oUserCurrent)) {
|
||||
/**
|
||||
* Создаем связь с гео-объектом
|
||||
*/
|
||||
if ($oGeoObject) {
|
||||
$this->Geo_CreateTarget($oGeoObject, 'user', $this->oUserCurrent->getId());
|
||||
if ($oCountry = $oGeoObject->getCountry()) {
|
||||
$this->oUserCurrent->setProfileCountry($oCountry->getName());
|
||||
} else {
|
||||
$this->oUserCurrent->setProfileCountry(null);
|
||||
}
|
||||
if ($oRegion = $oGeoObject->getRegion()) {
|
||||
$this->oUserCurrent->setProfileRegion($oRegion->getName());
|
||||
} else {
|
||||
$this->oUserCurrent->setProfileRegion(null);
|
||||
}
|
||||
if ($oCity = $oGeoObject->getCity()) {
|
||||
$this->oUserCurrent->setProfileCity($oCity->getName());
|
||||
} else {
|
||||
$this->oUserCurrent->setProfileCity(null);
|
||||
}
|
||||
} else {
|
||||
$this->Geo_DeleteTargetsByTarget('user', $this->oUserCurrent->getId());
|
||||
$this->oUserCurrent->setProfileCountry(null);
|
||||
$this->oUserCurrent->setProfileRegion(null);
|
||||
$this->oUserCurrent->setProfileCity(null);
|
||||
}
|
||||
$this->User_Update($this->oUserCurrent);
|
||||
|
||||
/**
|
||||
* Обрабатываем дополнительные поля, type = ''
|
||||
*/
|
||||
$aFields = $this->User_getUserFields('');
|
||||
$aData = array();
|
||||
foreach ($aFields as $iId => $aField) {
|
||||
if (isset($_REQUEST['profile_user_field_' . $iId])) {
|
||||
$aData[$iId] = getRequestStr('profile_user_field_' . $iId);
|
||||
}
|
||||
}
|
||||
$this->User_setUserFieldsValues($this->oUserCurrent->getId(), $aData);
|
||||
/**
|
||||
* Динамические поля контактов, type = array('contact','social')
|
||||
*/
|
||||
$aType = array('contact', 'social');
|
||||
$aFields = $this->User_getUserFields($aType);
|
||||
/**
|
||||
* Удаляем все поля с этим типом
|
||||
*/
|
||||
$this->User_DeleteUserFieldValues($this->oUserCurrent->getId(), $aType);
|
||||
$aFieldsContactType = getRequest('profile_user_field_type');
|
||||
$aFieldsContactValue = getRequest('profile_user_field_value');
|
||||
if (is_array($aFieldsContactType)) {
|
||||
foreach ($aFieldsContactType as $k => $v) {
|
||||
$v = (string)$v;
|
||||
if (isset($aFields[$v]) and isset($aFieldsContactValue[$k]) and is_string($aFieldsContactValue[$k])) {
|
||||
$this->User_setUserFieldsValues($this->oUserCurrent->getId(),
|
||||
array($v => $aFieldsContactValue[$k]),
|
||||
Config::Get('module.user.userfield_max_identical'));
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->Message_AddNoticeSingle($this->Lang_Get('common.success.save'));
|
||||
$this->Hook_Run('settings_profile_save_after', array('oUser' => $this->oUserCurrent));
|
||||
} else {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.system.base'));
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Загружаем гео-объект привязки
|
||||
*/
|
||||
$oGeoTarget = $this->Geo_GetTargetByTarget('user', $this->oUserCurrent->getId());
|
||||
$this->Viewer_Assign('oGeoTarget', $oGeoTarget);
|
||||
/**
|
||||
* Загружаем в шаблон список стран, регионов, городов
|
||||
*/
|
||||
$aCountries = $this->Geo_GetCountries(array(), array('sort' => 'asc'), 1, 300);
|
||||
$this->Viewer_Assign('aGeoCountries', $aCountries['collection']);
|
||||
if ($oGeoTarget) {
|
||||
if ($oGeoTarget->getCountryId()) {
|
||||
$aRegions = $this->Geo_GetRegions(array('country_id' => $oGeoTarget->getCountryId()),
|
||||
array('sort' => 'asc'), 1, 500);
|
||||
$this->Viewer_Assign('aGeoRegions', $aRegions['collection']);
|
||||
}
|
||||
if ($oGeoTarget->getRegionId()) {
|
||||
$aCities = $this->Geo_GetCities(array('region_id' => $oGeoTarget->getRegionId()),
|
||||
array('sort' => 'asc'), 1, 500);
|
||||
$this->Viewer_Assign('aGeoCities', $aCities['collection']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется при завершении работы экшена
|
||||
*
|
||||
*/
|
||||
public function EventShutdown()
|
||||
{
|
||||
$iCountTopicFavourite = $this->Topic_GetCountTopicsFavouriteByUserId($this->oUserCurrent->getId());
|
||||
$iCountTopicUser = $this->Topic_GetCountTopicsPersonalByUser($this->oUserCurrent->getId(), 1);
|
||||
$iCountCommentUser = $this->Comment_GetCountCommentsByUserId($this->oUserCurrent->getId(), 'topic');
|
||||
$iCountCommentFavourite = $this->Comment_GetCountCommentsFavouriteByUserId($this->oUserCurrent->getId());
|
||||
$iCountNoteUser = $this->User_GetCountUserNotesByUserId($this->oUserCurrent->getId());
|
||||
|
||||
$this->Viewer_Assign('oUserProfile', $this->oUserCurrent);
|
||||
$this->Viewer_Assign('iCountWallUser',
|
||||
$this->Wall_GetCountWall(array('wall_user_id' => $this->oUserCurrent->getId(), 'pid' => null)));
|
||||
/**
|
||||
* Общее число публикация и избранного
|
||||
*/
|
||||
$this->Viewer_Assign('iCountCreated', $iCountNoteUser + $iCountTopicUser + $iCountCommentUser);
|
||||
$this->Viewer_Assign('iCountFavourite', $iCountCommentFavourite + $iCountTopicFavourite);
|
||||
$this->Viewer_Assign('iCountFriendsUser', $this->User_GetCountUsersFriend($this->oUserCurrent->getId()));
|
||||
|
||||
/**
|
||||
* Загружаем в шаблон необходимые переменные
|
||||
*/
|
||||
$this->Viewer_Assign('sMenuItemSelect', $this->sMenuItemSelect);
|
||||
$this->Viewer_Assign('sMenuProfileItemSelect', $this->sMenuProfileItemSelect);
|
||||
$this->Viewer_Assign('sMenuSubItemSelect', $this->sMenuSubItemSelect);
|
||||
|
||||
$this->Hook_Run('action_shutdown_settings');
|
||||
}
|
||||
}
|
356
application/classes/actions/ActionStream.class.php
Normal file
356
application/classes/actions/ActionStream.class.php
Normal file
|
@ -0,0 +1,356 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки ленты активности
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionStream extends Action
|
||||
{
|
||||
/**
|
||||
* Текущий пользователь
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent;
|
||||
|
||||
/**
|
||||
* Какое меню активно
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuItemSelect = 'user';
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
$this->oUserCurrent = $this->User_getUserCurrent();
|
||||
|
||||
// Личная лента доступна только для авторизованных, гостям показываем общую ленту
|
||||
if ($this->oUserCurrent) {
|
||||
$this->SetDefaultEvent('personal');
|
||||
} else {
|
||||
$this->SetDefaultEvent('all');
|
||||
}
|
||||
|
||||
$this->Viewer_Assign('sMenuHeadItemSelect', 'stream');
|
||||
|
||||
/**
|
||||
* Загружаем в шаблон JS текстовки
|
||||
*/
|
||||
$this->Lang_AddLangJs(array(
|
||||
'activity.notices.error_already_subscribed',
|
||||
'error'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEvent('personal', 'EventPersonal');
|
||||
$this->AddEvent('all', 'EventAll');
|
||||
|
||||
$this->AddEvent('subscribe', 'EventSubscribe'); // TODO: возможно нужно удалить
|
||||
$this->AddEvent('ajaxadduser', 'EventAjaxAddUser');
|
||||
$this->AddEvent('ajaxremoveuser', 'EventAjaxRemoveUser');
|
||||
$this->AddEvent('switchEventType', 'EventSwitchEventType');
|
||||
|
||||
$this->AddEvent('get_more_all', 'EventGetMoreAll');
|
||||
$this->AddEvent('get_more_personal', 'EventGetMore');
|
||||
$this->AddEvent('get_more_user', 'EventGetMoreUser');
|
||||
}
|
||||
|
||||
/**
|
||||
* Персональная активность
|
||||
*/
|
||||
protected function EventPersonal()
|
||||
{
|
||||
if (!$this->oUserCurrent) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
|
||||
$this->Viewer_AddBlock('right', 'activitySettings');
|
||||
$this->Viewer_AddBlock('right', 'activityUsers');
|
||||
|
||||
$this->Viewer_Assign('activityEvents', $this->Stream_Read());
|
||||
$this->Viewer_Assign('activityEventsAllCount', $this->Stream_GetCountByReaderId($this->oUserCurrent->getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Общая активность
|
||||
*/
|
||||
protected function EventAll()
|
||||
{
|
||||
$this->sMenuItemSelect = 'all';
|
||||
|
||||
$this->Viewer_Assign('activityEvents', $this->Stream_ReadAll());
|
||||
$this->Viewer_Assign('activityEventsAllCount', $this->Stream_GetCountAll());
|
||||
}
|
||||
|
||||
/**
|
||||
* Активаци/деактивация типа события
|
||||
*/
|
||||
protected function EventSwitchEventType()
|
||||
{
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
|
||||
if (!$this->oUserCurrent) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
|
||||
if (!getRequest('type')) {
|
||||
$this->Message_AddError($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Активируем/деактивируем тип
|
||||
*/
|
||||
$this->Stream_switchUserEventType($this->oUserCurrent->getId(), getRequestStr('type'));
|
||||
$this->Message_AddNotice($this->Lang_Get('common.success.save'), $this->Lang_Get('common.attention'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Подгрузка событий (замена постраничности)
|
||||
*/
|
||||
protected function EventGetMore()
|
||||
{
|
||||
if (!$this->oUserCurrent) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
|
||||
$_this = $this;
|
||||
$this->GetMore(function ($lastId) use ($_this) {
|
||||
return $_this->Stream_Read(null, $lastId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Подгрузка событий для всего сайта
|
||||
*/
|
||||
protected function EventGetMoreAll()
|
||||
{
|
||||
$_this = $this;
|
||||
$this->GetMore(function ($lastId) use ($_this) {
|
||||
return $_this->Stream_ReadAll(null, $lastId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Подгрузка событий для пользователя
|
||||
*/
|
||||
protected function EventGetMoreUser()
|
||||
{
|
||||
$_this = $this;
|
||||
$this->GetMore(function ($lastId) use ($_this) {
|
||||
if (!($oUser = $_this->User_GetUserById(getRequestStr('target_id')))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $_this->Stream_ReadByUserId($oUser->getId(), null, $lastId);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Общий метод подгрузки событий
|
||||
*
|
||||
* @param callback $getEvents Метод возвращающий список событий
|
||||
*/
|
||||
protected function GetMore($getEvents)
|
||||
{
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
|
||||
// Необходимо передать последний просмотренный ID событий
|
||||
$iLastId = getRequestStr('last_id');
|
||||
|
||||
if (!$iLastId) {
|
||||
$this->Message_AddError($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Получаем события
|
||||
$aEvents = $getEvents($iLastId);
|
||||
|
||||
if ($aEvents === false) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
|
||||
$oViewer->Assign('events', $aEvents, 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);
|
||||
}
|
||||
|
||||
$this->Viewer_AssignAjax('count_loaded', count($aEvents));
|
||||
$this->Viewer_AssignAjax('html', $oViewer->Fetch('component@activity.event-list'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Подписка на пользователя по ID
|
||||
*
|
||||
*/
|
||||
protected function EventSubscribe()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Пользователь авторизован?
|
||||
*/
|
||||
if (!$this->oUserCurrent) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
/**
|
||||
* Проверяем существование пользователя
|
||||
*/
|
||||
if (!$this->User_getUserById(getRequestStr('id'))) {
|
||||
$this->Message_AddError($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'));
|
||||
}
|
||||
if ($this->oUserCurrent->getId() == getRequestStr('id')) {
|
||||
$this->Message_AddError($this->Lang_Get('user_list_add.notices.error_self'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Подписываем на пользователя
|
||||
*/
|
||||
$this->Stream_subscribeUser($this->oUserCurrent->getId(), getRequestStr('id'));
|
||||
$this->Message_AddNotice($this->Lang_Get('stream_subscribes_updated'), $this->Lang_Get('common.attention'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Подписка на пользователя по логину
|
||||
*/
|
||||
protected function EventAjaxAddUser()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
$aUsers = getRequest('users', null, 'post');
|
||||
|
||||
/**
|
||||
* Валидация
|
||||
*/
|
||||
if (!is_array($aUsers)) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
|
||||
/**
|
||||
* Если пользователь не авторизирован, возвращаем ошибку
|
||||
*/
|
||||
if (!$this->User_IsAuthorization()) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.need_authorization'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
|
||||
$aResult = array();
|
||||
/**
|
||||
* Обрабатываем добавление по каждому из переданных логинов
|
||||
*/
|
||||
foreach ($aUsers as $iUserId) {
|
||||
$iUserId = (int)$iUserId;
|
||||
|
||||
if (!$iUserId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Если пользователь не найден или неактивен, возвращаем ошибку
|
||||
*/
|
||||
if ($oUser = $this->User_GetUserById($iUserId) and $oUser->getActivate() == 1) {
|
||||
$this->Stream_subscribeUser($this->oUserCurrent->getId(), $oUser->getId());
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
$oViewer->Assign('user', $oUser, true);
|
||||
$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")
|
||||
);
|
||||
} else {
|
||||
$aResult[] = array(
|
||||
'bStateError' => true,
|
||||
'sMsgTitle' => $this->Lang_Get('common.error.error'),
|
||||
'sMsg' => $this->Lang_Get('user.notices.not_found_by_id', array('id' => $iUserId))
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Передаем во вьевер массив с результатами обработки по каждому пользователю
|
||||
*/
|
||||
$this->Viewer_AssignAjax('users', $aResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Отписка от пользователя
|
||||
*/
|
||||
protected function EventAjaxRemoveUser()
|
||||
{
|
||||
$iUserId = (int)getRequestStr('user_id');
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Пользователь авторизован?
|
||||
*/
|
||||
if (!$this->oUserCurrent) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Пользователь с таким ID существует?
|
||||
*/
|
||||
if (!$this->User_GetUserById($iUserId)) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Отписываем
|
||||
*/
|
||||
$this->Stream_unsubscribeUser($this->oUserCurrent->getId(), $iUserId);
|
||||
$this->Message_AddNotice($this->Lang_Get('common.success.remove'), $this->Lang_Get('common.attention'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется при завершении работы экшена
|
||||
*/
|
||||
public function EventShutdown()
|
||||
{
|
||||
/**
|
||||
* Загружаем в шаблон необходимые переменные
|
||||
*/
|
||||
$this->Viewer_Assign('sMenuItemSelect', $this->sMenuItemSelect);
|
||||
}
|
||||
}
|
147
application/classes/actions/ActionSubscribe.class.php
Normal file
147
application/classes/actions/ActionSubscribe.class.php
Normal file
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки подписок пользователей
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionSubscribe extends Action
|
||||
{
|
||||
/**
|
||||
* Текущий пользователь
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent = null;
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
$this->oUserCurrent = $this->User_GetUserCurrent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEventPreg('/^unsubscribe$/i', '/^\w{32}$/i', 'EventUnsubscribe');
|
||||
$this->AddEvent('ajax-subscribe-toggle', 'EventAjaxSubscribeToggle');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Отписка от подписки
|
||||
*/
|
||||
protected function EventUnsubscribe()
|
||||
{
|
||||
/**
|
||||
* Получаем подписку по ключу
|
||||
*/
|
||||
if ($oSubscribe = $this->Subscribe_GetSubscribeByKey($this->getParam(0)) and $oSubscribe->getStatus() == 1) {
|
||||
/**
|
||||
* Отписываем пользователя
|
||||
*/
|
||||
$oSubscribe->setStatus(0);
|
||||
$oSubscribe->setDateRemove(date("Y-m-d H:i:s"));
|
||||
$this->Subscribe_UpdateSubscribe($oSubscribe);
|
||||
|
||||
$this->Message_AddNotice($this->Lang_Get('common.success.save'), null, true);
|
||||
}
|
||||
/**
|
||||
* Получаем URL для редиректа
|
||||
*/
|
||||
if ((!$sUrl = $this->Subscribe_GetUrlTarget($oSubscribe->getTargetType(), $oSubscribe->getTargetId()))) {
|
||||
$sUrl = Router::GetPath('index');
|
||||
}
|
||||
Router::Location($sUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Изменение состояния подписки
|
||||
*/
|
||||
protected function EventAjaxSubscribeToggle()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Получаем емайл подписки и проверяем его на валидность
|
||||
*/
|
||||
$sMail = getRequestStr('mail');
|
||||
if ($this->oUserCurrent) {
|
||||
$sMail = $this->oUserCurrent->getMail();
|
||||
}
|
||||
if (!func_check($sMail, 'mail')) {
|
||||
$this->Message_AddError($this->Lang_Get('field.email.notices.error'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Получаем тип объекта подписки
|
||||
*/
|
||||
$sTargetType = getRequestStr('target_type');
|
||||
if (!$this->Subscribe_IsAllowTargetType($sTargetType)) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
$sTargetId = getRequestStr('target_id') ? getRequestStr('target_id') : null;
|
||||
$iValue = getRequest('value') ? 1 : 0;
|
||||
|
||||
$oSubscribe = null;
|
||||
/**
|
||||
* Есть ли доступ к подписке гостям?
|
||||
*/
|
||||
if (!$this->oUserCurrent and !$this->Subscribe_IsAllowTargetForGuest($sTargetType)) {
|
||||
$this->Message_AddError($this->Lang_Get('common.error.need_authorization'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Проверка объекта подписки
|
||||
*/
|
||||
if (!$this->Subscribe_CheckTarget($sTargetType, $sTargetId, $iValue)) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Если подписка еще не существовала, то создаем её
|
||||
*/
|
||||
if ($oSubscribe = $this->Subscribe_AddSubscribeSimple($sTargetType, $sTargetId, $sMail,
|
||||
$this->oUserCurrent ? $this->oUserCurrent->getId() : null)
|
||||
) {
|
||||
$oSubscribe->setStatus($iValue);
|
||||
$this->Subscribe_UpdateSubscribe($oSubscribe);
|
||||
$this->Message_AddNotice($this->Lang_Get('common.success.save'), $this->Lang_Get('common.attention'));
|
||||
return;
|
||||
}
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
}
|
119
application/classes/actions/ActionTag.class.php
Normal file
119
application/classes/actions/ActionTag.class.php
Normal file
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Экшен обработки поиска по тегам
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionTag extends Action
|
||||
{
|
||||
/**
|
||||
* Главное меню
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $sMenuHeadItemSelect = 'blog';
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEventPreg('/^.+$/i', '/^(page([1-9]\d{0,5}))?$/i', 'EventTags');
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************************
|
||||
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
|
||||
**********************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Отображение топиков
|
||||
*
|
||||
*/
|
||||
protected function EventTags()
|
||||
{
|
||||
/**
|
||||
* Получаем тег из УРЛа
|
||||
*/
|
||||
$sTag = $this->sCurrentEvent;
|
||||
/**
|
||||
* Передан ли номер страницы
|
||||
*/
|
||||
$iPage = $this->GetParamEventMatch(0, 2) ? $this->GetParamEventMatch(0, 2) : 1;
|
||||
/**
|
||||
* Получаем список топиков
|
||||
*/
|
||||
$aResult = $this->Topic_GetTopicsByTag($sTag, $iPage, Config::Get('module.topic.per_page'));
|
||||
$aTopics = $aResult['collection'];
|
||||
/**
|
||||
* Вызов хуков
|
||||
*/
|
||||
$this->Hook_Run('topics_list_show', array('aTopics' => $aTopics));
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('module.topic.per_page'),
|
||||
Config::Get('pagination.pages.count'), Router::GetPath('tag') . htmlspecialchars($sTag));
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
$this->Viewer_Assign('topics', $aTopics);
|
||||
$this->Viewer_Assign('tag', $sTag);
|
||||
$this->Viewer_AddHtmlTitle($this->Lang_Get('tag_title'));
|
||||
$this->Viewer_AddHtmlTitle($sTag);
|
||||
$this->Viewer_SetHtmlRssAlternate(Router::GetPath('rss') . 'tag/' . $sTag . '/', $sTag);
|
||||
/**
|
||||
* Если не удалось найти топиков, то ыставляем 404 заголовок
|
||||
*/
|
||||
if (!count($aTopics)) {
|
||||
header("HTTP/1.1 404 Not Found");
|
||||
}
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется при завершении работы экшена
|
||||
*
|
||||
*/
|
||||
public function EventShutdown()
|
||||
{
|
||||
/**
|
||||
* Загружаем в шаблон необходимые переменные
|
||||
*/
|
||||
$this->Viewer_Assign('sMenuHeadItemSelect', $this->sMenuHeadItemSelect);
|
||||
}
|
||||
}
|
1303
application/classes/actions/ActionTalk.class.php
Normal file
1303
application/classes/actions/ActionTalk.class.php
Normal file
File diff suppressed because it is too large
Load diff
281
application/classes/actions/ActionUserfeed.class.php
Normal file
281
application/classes/actions/ActionUserfeed.class.php
Normal file
|
@ -0,0 +1,281 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обрабатывает пользовательские ленты контента
|
||||
*
|
||||
* @package application.actions
|
||||
* @since 1.0
|
||||
*/
|
||||
class ActionUserfeed extends Action
|
||||
{
|
||||
/**
|
||||
* Текущий пользователь
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent;
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
/**
|
||||
* Доступ только у авторизованных пользователей
|
||||
*/
|
||||
$this->oUserCurrent = $this->User_getUserCurrent();
|
||||
if (!$this->oUserCurrent) {
|
||||
parent::EventNotFound();
|
||||
}
|
||||
$this->Viewer_Assign('sMenuItemSelect', 'feed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрация евентов
|
||||
*
|
||||
*/
|
||||
protected function RegisterEvent()
|
||||
{
|
||||
$this->AddEventPreg('/^(page([1-9]\d{0,5}))?$/i', 'EventIndex');
|
||||
$this->AddEvent('subscribe', 'EventSubscribe');
|
||||
$this->AddEvent('ajaxadduser', 'EventAjaxAddUser');
|
||||
$this->AddEvent('unsubscribe', 'EventUnSubscribe');
|
||||
}
|
||||
|
||||
/**
|
||||
* Выводит ленту контента(топики) для пользователя
|
||||
*
|
||||
*/
|
||||
protected function EventIndex()
|
||||
{
|
||||
/**
|
||||
* Передан ли номер страницы
|
||||
*/
|
||||
$iPage = $this->GetEventMatch(2) ? $this->GetEventMatch(2) : 1;
|
||||
|
||||
$aResult = $this->Userfeed_read($this->oUserCurrent->getId(),$iPage,Config::Get('module.topic.per_page'));
|
||||
$aTopics = $aResult['collection'];
|
||||
|
||||
// Вызов хуков
|
||||
$this->Hook_Run('topics_list_show', array('aTopics' => $aTopics));
|
||||
/**
|
||||
* Формируем постраничность
|
||||
*/
|
||||
$aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('module.topic.per_page'),
|
||||
Config::Get('pagination.pages.count'), Router::GetPath('feed'));
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('topics', $aTopics);
|
||||
$this->Viewer_Assign('paging', $aPaging);
|
||||
|
||||
$this->SetTemplateAction('list');
|
||||
}
|
||||
|
||||
/**
|
||||
* Подписка на контент блога или пользователя
|
||||
*
|
||||
*/
|
||||
protected function EventSubscribe()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
/**
|
||||
* Проверяем наличие ID блога или пользователя
|
||||
*/
|
||||
if (!getRequest('id')) {
|
||||
$this->Message_AddError($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'));
|
||||
}
|
||||
$sType = getRequestStr('type');
|
||||
$iType = null;
|
||||
/**
|
||||
* Определяем тип подписки
|
||||
*/
|
||||
switch ($sType) {
|
||||
case 'blogs':
|
||||
$iType = ModuleUserfeed::SUBSCRIBE_TYPE_BLOG;
|
||||
/**
|
||||
* Проверяем существование блога
|
||||
*/
|
||||
if (!($oBlog=$this->Blog_GetBlogById(getRequestStr('id'))) or !$this->ACL_IsAllowShowBlog($oBlog,$this->oUserCurrent)) {
|
||||
$this->Message_AddError($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 'users':
|
||||
$iType = ModuleUserfeed::SUBSCRIBE_TYPE_USER;
|
||||
/**
|
||||
* Проверяем существование пользователя
|
||||
*/
|
||||
if (!$this->User_GetUserById(getRequestStr('id'))) {
|
||||
$this->Message_AddError($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
if ($this->oUserCurrent->getId() == getRequestStr('id')) {
|
||||
$this->Message_AddError($this->Lang_Get('user_list_add.notices.error_self'),
|
||||
$this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->Message_AddError($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Подписываем
|
||||
*/
|
||||
$this->Userfeed_subscribeUser($this->oUserCurrent->getId(), $iType, getRequestStr('id'));
|
||||
$this->Message_AddNotice($this->Lang_Get('common.success.save'), $this->Lang_Get('common.attention'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Подписка на пользвователя по логину
|
||||
*
|
||||
*/
|
||||
protected function EventAjaxAddUser()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
$aUsers = getRequest('users', null, 'post');
|
||||
/**
|
||||
* Валидация
|
||||
*/
|
||||
if (!is_array($aUsers)) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Если пользователь не авторизирован, возвращаем ошибку
|
||||
*/
|
||||
if (!$this->User_IsAuthorization()) {
|
||||
$this->Message_AddErrorSingle($this->Lang_Get('common.error.need_authorization'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
|
||||
$aResult = array();
|
||||
/**
|
||||
* Обрабатываем добавление по каждому из переданных логинов
|
||||
*/
|
||||
foreach ($aUsers as $iUserId) {
|
||||
$iUserId = (int) $iUserId;
|
||||
|
||||
if (!$iUserId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Если пользователь не найден или неактивен, возвращаем ошибку
|
||||
*/
|
||||
if ($oUser = $this->User_GetUserById($iUserId) and $oUser->getActivate() == 1) {
|
||||
$this->Userfeed_subscribeUser($this->oUserCurrent->getId(), ModuleUserfeed::SUBSCRIBE_TYPE_USER,
|
||||
$oUser->getId());
|
||||
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
$oViewer->Assign('user', $oUser, true);
|
||||
$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")
|
||||
);
|
||||
} else {
|
||||
$aResult[] = array(
|
||||
'bStateError' => true,
|
||||
'sMsgTitle' => $this->Lang_Get('common.error.error'),
|
||||
'sMsg' => $this->Lang_Get('user.notices.not_found_by_id', array('id' => $iUserId))
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Передаем во вьевер массив с результатами обработки по каждому пользователю
|
||||
*/
|
||||
$this->Viewer_AssignAjax('users', $aResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Отписка от блога или пользователя
|
||||
*
|
||||
*/
|
||||
protected function EventUnsubscribe()
|
||||
{
|
||||
/**
|
||||
* Устанавливаем формат Ajax ответа
|
||||
*/
|
||||
$this->Viewer_SetResponseAjax('json');
|
||||
$sId = getRequestStr('id');
|
||||
|
||||
$sType = getRequestStr('type');
|
||||
$iType = null;
|
||||
/**
|
||||
* Определяем от чего отписываемся
|
||||
*/
|
||||
switch ($sType) {
|
||||
case 'blogs':
|
||||
$iType = ModuleUserfeed::SUBSCRIBE_TYPE_BLOG;
|
||||
break;
|
||||
case 'users':
|
||||
$iType = ModuleUserfeed::SUBSCRIBE_TYPE_USER;
|
||||
$sId = getRequestStr('user_id');
|
||||
break;
|
||||
default:
|
||||
$this->Message_AddError($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
if (!$sId) {
|
||||
$this->Message_AddError($this->Lang_Get('common.error.system.base'), $this->Lang_Get('common.error.error'));
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Отписываем пользователя
|
||||
*/
|
||||
$this->Userfeed_unsubscribeUser($this->oUserCurrent->getId(), $iType, $sId);
|
||||
$this->Message_AddNotice($this->Lang_Get('common.success.remove'), $this->Lang_Get('common.attention'));
|
||||
}
|
||||
|
||||
/**
|
||||
* При завершении экшена загружаем в шаблон необходимые переменные
|
||||
*
|
||||
*/
|
||||
public function EventShutdown()
|
||||
{
|
||||
/**
|
||||
* Подсчитываем новые топики
|
||||
*/
|
||||
$iCountTopicsCollectiveNew = $this->Topic_GetCountTopicsCollectiveNew();
|
||||
$iCountTopicsPersonalNew = $this->Topic_GetCountTopicsPersonalNew();
|
||||
$iCountTopicsNew = $iCountTopicsCollectiveNew + $iCountTopicsPersonalNew;
|
||||
/**
|
||||
* Загружаем переменные в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('iCountTopicsCollectiveNew', $iCountTopicsCollectiveNew);
|
||||
$this->Viewer_Assign('iCountTopicsPersonalNew', $iCountTopicsPersonalNew);
|
||||
$this->Viewer_Assign('iCountTopicsNew', $iCountTopicsNew);
|
||||
}
|
||||
}
|
47
application/classes/blocks/BlockActivityRecent.class.php
Normal file
47
application/classes/blocks/BlockActivityRecent.class.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обработка блока с топиками (прямой эфир)
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 1.0
|
||||
*/
|
||||
class BlockActivityRecent extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
/**
|
||||
* Получаем топики
|
||||
*/
|
||||
if ($oTopics = $this->Topic_GetTopicsLast(Config::Get('block.stream.row'))) {
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
$oViewer->Assign('topics', $oTopics, true);
|
||||
$sTextResult = $oViewer->Fetch("component@activity.recent-topics");
|
||||
$this->Viewer_Assign('content', $sTextResult, true);
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@activity.block.recent');
|
||||
}
|
||||
}
|
45
application/classes/blocks/BlockActivitySettings.class.php
Normal file
45
application/classes/blocks/BlockActivitySettings.class.php
Normal file
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Блок настройки ленты активности
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 1.0
|
||||
*/
|
||||
class BlockActivitySettings extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
/**
|
||||
* пользователь авторизован?
|
||||
*/
|
||||
if ($oUserCurrent = $this->User_getUserCurrent()) {
|
||||
$this->Viewer_Assign('types', $this->Stream_getEventTypes());
|
||||
$this->Viewer_Assign('typesActive', $this->Stream_getTypesList($oUserCurrent->getId()));
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@activity.block.settings');
|
||||
}
|
||||
}
|
44
application/classes/blocks/BlockActivityUsers.class.php
Normal file
44
application/classes/blocks/BlockActivityUsers.class.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Блок выбора пользователей для чтения в ленте активности
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 1.0
|
||||
*/
|
||||
class BlockActivityUsers extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
/**
|
||||
* пользователь авторизован?
|
||||
*/
|
||||
if ($oUserCurrent = $this->User_getUserCurrent()) {
|
||||
$this->Viewer_Assign('users', $this->Stream_getUserSubscribes($oUserCurrent->getId()));
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@activity.block.users');
|
||||
}
|
||||
}
|
51
application/classes/blocks/BlockBlogs.class.php
Normal file
51
application/classes/blocks/BlockBlogs.class.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обработка блока с рейтингом блогов
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 1.0
|
||||
*/
|
||||
class BlockBlogs extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
/**
|
||||
* Получаем список блогов
|
||||
*/
|
||||
if ($aResult = $this->Blog_GetBlogsRating(1, Config::Get('block.blogs.row'))) {
|
||||
$aBlogs = $aResult['collection'];
|
||||
$oViewer = $this->Viewer_GetLocalViewer();
|
||||
$oViewer->Assign('aBlogs', $aBlogs);
|
||||
/**
|
||||
* Формируем результат в виде шаблона и возвращаем
|
||||
*/
|
||||
$sTextResult = $oViewer->Fetch("component@blog.top");
|
||||
$this->Viewer_Assign('sBlogsTop', $sTextResult);
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@blog.block.blogs');
|
||||
}
|
||||
}
|
44
application/classes/blocks/BlockBlogsSearch.class.php
Normal file
44
application/classes/blocks/BlockBlogsSearch.class.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обрабатывает блок категорий для блогов
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 2.0
|
||||
*/
|
||||
class BlockBlogsSearch extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
if (!Config::Get('module.blog.category_allow')) {
|
||||
return;
|
||||
}
|
||||
$aCategories = $this->Blog_GetCategoriesTree();
|
||||
$aBlogsAll = $this->Blog_GetBlogsByFilter(array('exclude_type' => 'personal'), array(), 1, 1, array());
|
||||
$this->Viewer_Assign('aBlogCategories', $aCategories);
|
||||
$this->Viewer_Assign('iCountBlogsAll', $aBlogsAll['count']);
|
||||
$this->SetTemplate('component@blog.block.search');
|
||||
}
|
||||
}
|
72
application/classes/blocks/BlockFieldCategory.class.php
Normal file
72
application/classes/blocks/BlockFieldCategory.class.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обработка блока с редактированием категорий объекта
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 2.0
|
||||
*/
|
||||
class BlockFieldCategory extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
$sEntity = $this->GetParam('entity');
|
||||
$oTarget = $this->GetParam('target');
|
||||
$sTargetType = $this->GetParam('target_type');
|
||||
|
||||
if (!$oTarget) {
|
||||
$oTarget = Engine::GetEntity($sEntity);
|
||||
}
|
||||
|
||||
$aBehaviors = $oTarget->GetBehaviors();
|
||||
foreach ($aBehaviors as $oBehavior) {
|
||||
if ($oBehavior instanceof ModuleCategory_BehaviorEntity) {
|
||||
/**
|
||||
* Если в параметрах был тип, то переопределяем значение. Это необходимо для корректной работы, когда тип динамический.
|
||||
*/
|
||||
if ($sTargetType) {
|
||||
$oBehavior->setParam('target_type', $sTargetType);
|
||||
}
|
||||
/**
|
||||
* Нужное нам поведение - получаем список текущих категорий
|
||||
*/
|
||||
$this->Viewer_Assign('categoriesSelected', $oBehavior->getCategories(), true);
|
||||
/**
|
||||
* Загружаем параметры
|
||||
*/
|
||||
$aParams = $oBehavior->getParams();
|
||||
$this->Viewer_Assign('params', $aParams, true);
|
||||
/**
|
||||
* Загружаем список доступных категорий
|
||||
*/
|
||||
$this->Viewer_Assign('categories',
|
||||
$this->Category_GetCategoriesTreeByTargetType($oBehavior->getCategoryTargetType()), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@field.category');
|
||||
}
|
||||
}
|
72
application/classes/blocks/BlockMenu.class.php
Normal file
72
application/classes/blocks/BlockMenu.class.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2018 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Oleg Demodov <boxmilo@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description of BlockMenu
|
||||
*
|
||||
* @author oleg
|
||||
*/
|
||||
class BlockMenu extends Block {
|
||||
|
||||
public function Exec() {
|
||||
$sNameMenu = $this->GetParam('name');
|
||||
|
||||
if(!$oMenu = $this->Menu_Get($sNameMenu)){
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->Hook_Run('menu_before_prepare', ['menu' => &$oMenu]);
|
||||
|
||||
$ItemsTree = $this->prepareItems($oMenu->getItems());
|
||||
|
||||
$this->Hook_Run('menu_after_prepare', ['items' => &$ItemsTree['items']]);
|
||||
|
||||
$this->Viewer_Assign('activeItem', $this->GetParam('activeItem', null), true);
|
||||
$this->Viewer_Assign('mods', $this->GetParam('mods', null), true);
|
||||
$this->Viewer_Assign('classes', $this->GetParam('classes', null), true);
|
||||
$this->Viewer_Assign('template', $this->GetParam('template', $sNameMenu), true);
|
||||
$this->Viewer_Assign('params', $ItemsTree);
|
||||
|
||||
$this->SetTemplate("component@menu");
|
||||
}
|
||||
|
||||
public function prepareItems($ItemsTree) {
|
||||
if( !is_array($ItemsTree) or !count($ItemsTree) ){
|
||||
return null;
|
||||
}
|
||||
$aItemsNav = [];
|
||||
|
||||
foreach ($ItemsTree as $ItemTree) {
|
||||
$aChildrens = $ItemTree->getChildren();
|
||||
$aItemsNav[] = [
|
||||
'url' => Router::GetPath( $ItemTree->getUrl() ),
|
||||
'name' => $ItemTree->getName(),
|
||||
'text' => $this->Lang_Get($ItemTree->getTitle()),
|
||||
'count' => $ItemTree->getCount(),
|
||||
'is_enabled' => $ItemTree->getEnable(),
|
||||
'menu' => $this->prepareItems( $aChildrens )
|
||||
];
|
||||
}
|
||||
return [ 'items' => $aItemsNav];
|
||||
}
|
||||
|
||||
}
|
59
application/classes/blocks/BlockPollFormItems.class.php
Normal file
59
application/classes/blocks/BlockPollFormItems.class.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Используется для вывода списка опросов в форме редактирования объекта
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 2.0
|
||||
*/
|
||||
class BlockPollFormItems extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
$this->SetTemplate('component@poll.manage.list');
|
||||
|
||||
$sTargetType = $this->GetParam('target_type');
|
||||
$sTargetId = $this->GetParam('target_id');
|
||||
$sTargetTmp = $this->Session_GetCookie('poll_target_tmp_' . $sTargetType) ? $this->Session_GetCookie('poll_target_tmp_' . $sTargetType) : $this->GetParam('target_tmp');
|
||||
|
||||
$aFilter = array('target_type' => $sTargetType, '#order' => array('id' => 'asc'));
|
||||
if ($sTargetId) {
|
||||
$sTargetTmp = null;
|
||||
if (!$this->Poll_CheckTarget($sTargetType, $sTargetId)) {
|
||||
return false;
|
||||
}
|
||||
$aFilter['target_id'] = $sTargetId;
|
||||
} else {
|
||||
$sTargetId = null;
|
||||
if (!$sTargetTmp or !$this->Poll_IsAllowTargetType($sTargetType)) {
|
||||
return true; // показываем список, но пустой
|
||||
}
|
||||
$aFilter['target_tmp'] = $sTargetTmp;
|
||||
}
|
||||
$aPollItems = $this->Poll_GetPollItemsByFilter($aFilter);
|
||||
|
||||
$this->Viewer_Assign('aPollItems', $aPollItems);
|
||||
}
|
||||
}
|
64
application/classes/blocks/BlockPropertyUpdate.class.php
Normal file
64
application/classes/blocks/BlockPropertyUpdate.class.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обработка блока с редактированием свойств объекта
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 2.0
|
||||
*/
|
||||
class BlockPropertyUpdate extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
$sEntity = $this->GetParam('entity');
|
||||
$oTarget = $this->GetParam('target');
|
||||
$sTargetType = $this->GetParam('target_type');
|
||||
|
||||
if (!$oTarget) {
|
||||
$oTarget = Engine::GetEntity($sEntity);
|
||||
}
|
||||
|
||||
$aBehaviors = $oTarget->GetBehaviors();
|
||||
foreach ($aBehaviors as $oBehavior) {
|
||||
/**
|
||||
* Определяем нужное нам поведение
|
||||
*/
|
||||
if ($oBehavior instanceof ModuleProperty_BehaviorEntity) {
|
||||
/**
|
||||
* Если в параметрах был тип, то переопределяем значение. Это необходимо для корректной работы, когда тип динамический.
|
||||
*/
|
||||
if ($sTargetType) {
|
||||
$oBehavior->setParam('target_type', $sTargetType);
|
||||
}
|
||||
$aProperties = $this->Property_GetPropertiesForUpdate($oBehavior->getPropertyTargetType(),
|
||||
$oTarget->getId());
|
||||
$this->Viewer_Assign('properties', $aProperties, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@property.input.list');
|
||||
}
|
||||
}
|
60
application/classes/blocks/BlockTagsPersonalTopic.class.php
Normal file
60
application/classes/blocks/BlockTagsPersonalTopic.class.php
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обрабатывает блок облака тегов для избранного
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 1.0
|
||||
*/
|
||||
class BlockTagsPersonalTopic extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
/**
|
||||
* Пользователь авторизован?
|
||||
*/
|
||||
if ($oUserCurrent = $this->User_getUserCurrent()) {
|
||||
if (!($oUser = $this->getParam('user'))) {
|
||||
$oUser = $oUserCurrent;
|
||||
}
|
||||
/**
|
||||
* Получаем список тегов пользователя
|
||||
*/
|
||||
$aTags = $this->Favourite_GetGroupTags($oUser->getId(), 'topic', true, 70);
|
||||
/**
|
||||
* Расчитываем логарифмическое облако тегов
|
||||
*/
|
||||
$this->Tools_MakeCloud($aTags);
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->Viewer_Assign('tags', $aTags, true);
|
||||
$this->Viewer_Assign('user', $oUser, true);
|
||||
$this->Viewer_Assign('activeTag', $this->getParam('activeTag'), true);
|
||||
|
||||
$this->SetTemplate('component@tags-personal.cloud');
|
||||
}
|
||||
}
|
||||
}
|
69
application/classes/blocks/BlockTopicsTags.class.php
Normal file
69
application/classes/blocks/BlockTopicsTags.class.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Обрабатывает блок облака тегов
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 1.0
|
||||
*/
|
||||
class BlockTopicsTags extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
/**
|
||||
* Получаем список тегов
|
||||
*/
|
||||
$aTags = $this->Topic_GetOpenTopicTags(Config::Get('block.tags.tags_count'));
|
||||
/**
|
||||
* Расчитываем логарифмическое облако тегов
|
||||
*/
|
||||
if ($aTags) {
|
||||
$this->Tools_MakeCloud($aTags);
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->Viewer_Assign('tags', $aTags, true);
|
||||
}
|
||||
/**
|
||||
* Теги пользователя
|
||||
*/
|
||||
if ($oUserCurrent = $this->User_getUserCurrent()) {
|
||||
$aTags = $this->Topic_GetOpenTopicTags(Config::Get('block.tags.personal_tags_count'),
|
||||
$oUserCurrent->getId());
|
||||
/**
|
||||
* Расчитываем логарифмическое облако тегов
|
||||
*/
|
||||
if ($aTags) {
|
||||
$this->Tools_MakeCloud($aTags);
|
||||
/**
|
||||
* Устанавливаем шаблон вывода
|
||||
*/
|
||||
$this->Viewer_Assign('tagsUser', $aTags, true);
|
||||
}
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@topic.block.tags');
|
||||
}
|
||||
}
|
65
application/classes/blocks/BlockUserfeedBlogs.class.php
Normal file
65
application/classes/blocks/BlockUserfeedBlogs.class.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Блок настройки списка блогов в ленте
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 1.0
|
||||
*/
|
||||
class BlockUserfeedBlogs extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
/**
|
||||
* Пользователь авторизован?
|
||||
*/
|
||||
if ($oUserCurrent = $this->User_getUserCurrent()) {
|
||||
$aUserSubscribes = $this->Userfeed_getUserSubscribes($oUserCurrent->getId());
|
||||
/**
|
||||
* Получаем список ID блогов, в которых состоит пользователь
|
||||
*/
|
||||
$aBlogsId = $this->Blog_GetBlogUsersByUserId($oUserCurrent->getId(), array(
|
||||
ModuleBlog::BLOG_USER_ROLE_USER,
|
||||
ModuleBlog::BLOG_USER_ROLE_MODERATOR,
|
||||
ModuleBlog::BLOG_USER_ROLE_ADMINISTRATOR
|
||||
), true);
|
||||
/**
|
||||
* Получаем список ID блогов, которые создал пользователь
|
||||
*/
|
||||
$aBlogsOwnerId = $this->Blog_GetBlogsByOwnerId($oUserCurrent->getId(), true);
|
||||
$aBlogsId = array_merge($aBlogsId, $aBlogsOwnerId);
|
||||
|
||||
$aBlogs = $this->Blog_GetBlogsAdditionalData($aBlogsId, array('owner' => array()),
|
||||
array('blog_title' => 'asc'));
|
||||
/**
|
||||
* Выводим в шаблон
|
||||
*/
|
||||
$this->Viewer_Assign('blogsSubscribed', $aUserSubscribes['blogs']);
|
||||
$this->Viewer_Assign('blogsJoined', $aBlogs);
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@feed.block.blogs');
|
||||
}
|
||||
}
|
48
application/classes/blocks/BlockUserfeedUsers.class.php
Normal file
48
application/classes/blocks/BlockUserfeedUsers.class.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Блок настройки списка пользователей в ленте
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 1.0
|
||||
*/
|
||||
class BlockUserfeedUsers extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
/**
|
||||
* Пользователь авторизован?
|
||||
*/
|
||||
if ($oUserCurrent = $this->User_getUserCurrent()) {
|
||||
/**
|
||||
* Получаем необходимые переменные и прогружаем в шаблон
|
||||
*/
|
||||
$aResult = $this->Userfeed_getUserSubscribes($oUserCurrent->getId());
|
||||
$this->Viewer_Assign('users', $aResult['users']);
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@feed.block.users');
|
||||
}
|
||||
}
|
51
application/classes/blocks/BlockWall.class.php
Normal file
51
application/classes/blocks/BlockWall.class.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Стена
|
||||
*
|
||||
* @package application.blocks
|
||||
* @since 2.0
|
||||
*/
|
||||
class BlockWall extends Block
|
||||
{
|
||||
/**
|
||||
* Запуск обработки
|
||||
*/
|
||||
public function Exec()
|
||||
{
|
||||
$wall = $this->Wall_GetWall(array('wall_user_id' => (int)$this->GetParam('user_id'), 'pid' => null),
|
||||
array('id' => 'desc'), 1, Config::Get('module.wall.per_page'));
|
||||
$posts = $wall['collection'];
|
||||
|
||||
$this->Viewer_Assign('posts', $posts, true);
|
||||
$this->Viewer_Assign('count', $wall['count'], true);
|
||||
$this->Viewer_Assign('classes', $this->GetParam('classes'), true);
|
||||
$this->Viewer_Assign('attributes', $this->GetParam('attributes'), true);
|
||||
$this->Viewer_Assign('mods', $this->GetParam('mods'), true);
|
||||
|
||||
if (count($posts)) {
|
||||
$this->Viewer_Assign('lastId', end($posts)->getId(), true);
|
||||
}
|
||||
|
||||
$this->SetTemplate('component@wall.wall');
|
||||
}
|
||||
}
|
47
application/classes/hooks/HookCopyright.class.php
Normal file
47
application/classes/hooks/HookCopyright.class.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Регистрация хука для вывода ссылки копирайта
|
||||
*
|
||||
* @package application.hooks
|
||||
* @since 1.0
|
||||
*/
|
||||
class HookCopyright extends Hook
|
||||
{
|
||||
/**
|
||||
* Регистрируем хуки
|
||||
*/
|
||||
public function RegisterHook()
|
||||
{
|
||||
$this->AddHook('template_copyright', 'CopyrightLink', __CLASS__, -100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка хука копирайта
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function CopyrightLink()
|
||||
{
|
||||
return '© Powered by <a href="https://catalog.livestreetcms.com">LiveStreet CMS</a>';
|
||||
}
|
||||
}
|
150
application/classes/hooks/HookMain.class.php
Normal file
150
application/classes/hooks/HookMain.class.php
Normal file
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Регистрация основных хуков
|
||||
*
|
||||
* @package application.hooks
|
||||
* @since 1.0
|
||||
*/
|
||||
class HookMain extends Hook
|
||||
{
|
||||
/**
|
||||
* Регистрируем хуки
|
||||
*/
|
||||
public function RegisterHook()
|
||||
{
|
||||
$this->AddHook('init_action', 'InitAction', __CLASS__, 1000);
|
||||
$this->AddHook('start_action', 'StartAction', __CLASS__, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка хука инициализации экшенов
|
||||
* Может выполняться несколько раз, например, при использовании внутренних реврайтов
|
||||
*/
|
||||
public function InitAction()
|
||||
{
|
||||
/**
|
||||
* Проверка на закрытый режим
|
||||
*/
|
||||
$oUserCurrent = $this->User_GetUserCurrent();
|
||||
if (!$oUserCurrent and Config::Get('general.close') and !Router::CheckIsCurrentAction((array)Config::Get('general.close_exceptions'))) {
|
||||
Router::Action('auth/login');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка запуска экшена
|
||||
* Выполняется всегда только один раз
|
||||
*/
|
||||
public function StartAction()
|
||||
{
|
||||
$this->LoadDefaultJsVarAndLang();
|
||||
/**
|
||||
* Обработка сайтмапа
|
||||
*/
|
||||
$this->Sitemap_AddTargetType('general', array(
|
||||
'callback_counters' => function () {
|
||||
return 1;
|
||||
},
|
||||
'callback_data' => function () {
|
||||
return array(
|
||||
$this->Sitemap_GetDataForSitemapRow(Router::GetPath('/'), time(), Config::Get('module.sitemap.index.priority'),
|
||||
Config::Get('module.sitemap.index.changefreq')),
|
||||
$this->Sitemap_GetDataForSitemapRow(Router::GetPath('stream/all'), time(), Config::Get('module.sitemap.stream.priority'),
|
||||
Config::Get('module.sitemap.stream.changefreq')),
|
||||
);
|
||||
}
|
||||
));
|
||||
$this->Topic_RegisterSitemap();
|
||||
$this->Blog_RegisterSitemap();
|
||||
$this->User_RegisterSitemap();
|
||||
/**
|
||||
* Запуск обработки сборщика
|
||||
*/
|
||||
$this->Ls_SenderRun();
|
||||
}
|
||||
|
||||
/**
|
||||
* Загрузка необходимых переменных и текстовок в шаблон
|
||||
*/
|
||||
public function LoadDefaultJsVarAndLang()
|
||||
{
|
||||
/**
|
||||
* Загружаем JS переменные
|
||||
*/
|
||||
$this->Viewer_AssignJs(
|
||||
array(
|
||||
'recaptcha.site_key' => Config::Get('module.validate.recaptcha.site_key'),
|
||||
'comment_max_tree' => Config::Get('module.comment.max_tree'),
|
||||
'comment_show_form' => Config::Get('module.comment.show_form'),
|
||||
'comment_use_paging' => Config::Get('module.comment.use_nested'),
|
||||
'topic_max_blog_count' => Config::Get('module.topic.max_blog_count'),
|
||||
'block_stream_show_tip' => Config::Get('block.stream.show_tip'),
|
||||
'poll_max_answers' => Config::Get('module.poll.max_answers'),
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Загрузка языковых текстовок
|
||||
*/
|
||||
$this->Lang_AddLangJs(array(
|
||||
'comments.comments_declension',
|
||||
'comments.unsubscribe',
|
||||
'comments.subscribe',
|
||||
'comments.folding.unfold',
|
||||
'comments.folding.fold',
|
||||
'comments.folding.unfold_all',
|
||||
'comments.folding.fold_all',
|
||||
'poll.notices.error_answers_max',
|
||||
'favourite.add',
|
||||
'favourite.remove',
|
||||
'field.geo.select_city',
|
||||
'field.geo.select_region',
|
||||
'blog.blog',
|
||||
'blog.add.fields.type.note_open',
|
||||
'blog.add.fields.type.note_close',
|
||||
'blog.search.result_title',
|
||||
'blog.blocks.navigator.blog',
|
||||
'common.success.add',
|
||||
'common.success.remove',
|
||||
'common.remove_confirm',
|
||||
'pagination.notices.first',
|
||||
'pagination.notices.last',
|
||||
'user.actions.unfollow',
|
||||
'user.actions.follow',
|
||||
'user.friends.status.added',
|
||||
'user.friends.status.notfriends',
|
||||
'user.friends.status.pending',
|
||||
'user.friends.status.rejected',
|
||||
'user.friends.status.sent',
|
||||
'user.friends.status.linked',
|
||||
'user.settings.profile.notices.error_max_userfields',
|
||||
'user.search.result_title',
|
||||
'more.text',
|
||||
'more.text_count',
|
||||
'more.empty',
|
||||
'validate.tags.count',
|
||||
'uploader.attach.count',
|
||||
'uploader.attach.empty'
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Регистрация хука для вывода статистики производительности
|
||||
*
|
||||
* @package application.hooks
|
||||
* @since 1.0
|
||||
*/
|
||||
class HookStatisticsPerformance extends Hook
|
||||
{
|
||||
/**
|
||||
* Регистрируем хуки
|
||||
*/
|
||||
public function RegisterHook()
|
||||
{
|
||||
$this->AddHook('template_body_end', 'Statistics', __CLASS__, -1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка хука перед закрывающим тегом body
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function Statistics()
|
||||
{
|
||||
if (!$this->User_GetIsAdmin()) {
|
||||
return '';
|
||||
}
|
||||
$oEngine = Engine::getInstance();
|
||||
/**
|
||||
* Подсчитываем время выполнения
|
||||
*/
|
||||
$iTimeInit = $oEngine->GetTimeInit();
|
||||
$iTimeFull = round(microtime(true) - $iTimeInit, 3);
|
||||
$this->Viewer_Assign('timeFullPerformance', $iTimeFull, true);
|
||||
/**
|
||||
* Получаем статистику по кешу и БД
|
||||
*/
|
||||
$aStats = $oEngine->getStats();
|
||||
$aStats['cache']['time'] = round($aStats['cache']['time'], 5);
|
||||
$this->Viewer_Assign('stats', $aStats, true);
|
||||
$this->Viewer_Assign('bIsShowStatsPerformance', Router::GetIsShowStats());
|
||||
/**
|
||||
* В ответ рендерим шаблон статистики
|
||||
*/
|
||||
return $this->Viewer_Fetch('component@performance.performance');
|
||||
}
|
||||
}
|
826
application/classes/modules/acl/ACL.class.php
Normal file
826
application/classes/modules/acl/ACL.class.php
Normal file
|
@ -0,0 +1,826 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* ACL(Access Control List)
|
||||
* Модуль для разруливания ограничений по карме/рейтингу юзера
|
||||
*
|
||||
* @package application.modules.acl
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleACL extends Module
|
||||
{
|
||||
/**
|
||||
* Коды механизма удаления блога
|
||||
*/
|
||||
const CAN_DELETE_BLOG_EMPTY_ONLY = 1;
|
||||
const CAN_DELETE_BLOG_WITH_TOPICS = 2;
|
||||
|
||||
/**
|
||||
* Инициализация модуля
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь создавать блоги
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function CanCreateBlog($oUser)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'create_blog', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
if (!$oUser->isAllowCreateBlog()) {
|
||||
return $that->Lang_Get('blog.add.alerts.acl');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь создавать топики
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @param ModuleTopic_EntityTopicType $oTopicType Объект типа топика
|
||||
* @return bool
|
||||
*/
|
||||
public function CanAddTopic($oUser, $oTopicType)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'create_topic', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Проверяем хватает ли рейтинга юзеру чтоб создать топик
|
||||
*/
|
||||
if ($oUser->getRating() <= Config::Get('acl.create.topic.limit_rating')) {
|
||||
return $that->Lang_Get('topic.add.notices.rating_limit');
|
||||
}
|
||||
/**
|
||||
* Проверяем лимит по времени
|
||||
*/
|
||||
if (!$that->CanPostTopicTime($oUser)) {
|
||||
return $that->Lang_Get('topic.add.notices.time_limit');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь создавать комментарии
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @param ModuleTopic_EntityTopic|null $oTopic Топик
|
||||
* @return bool
|
||||
*/
|
||||
public function CanPostComment($oUser, $oTopic = null)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'create_topic_comment', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that, $oTopic) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Проверяем на закрытый блог
|
||||
*/
|
||||
if ($oTopic and !$that->IsAllowShowBlog($oTopic->getBlog(), $oUser)) {
|
||||
return $that->Lang_Get('topic.comments.notices.acl');
|
||||
}
|
||||
/**
|
||||
* Ограничение на рейтинг
|
||||
*/
|
||||
if ($oUser->getRating() < Config::Get('acl.create.comment.rating')) {
|
||||
return $that->Lang_Get('topic.comments.notices.acl');
|
||||
}
|
||||
/**
|
||||
* Ограничение по времени
|
||||
*/
|
||||
if (Config::Get('acl.create.comment.limit_time') > 0 and $oUser->getDateCommentLast()) {
|
||||
$sDateCommentLast = strtotime($oUser->getDateCommentLast());
|
||||
if ($oUser->getRating() < Config::Get('acl.create.comment.limit_time_rating') and ((time() - $sDateCommentLast) < Config::Get('acl.create.comment.limit_time'))) {
|
||||
return $that->Lang_Get('topic.comments.notices.limit');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь создавать топик по времени
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function CanPostTopicTime($oUser)
|
||||
{
|
||||
// Для администраторов ограничение по времени не действует
|
||||
if ($oUser->isAdministrator()
|
||||
or Config::Get('acl.create.topic.limit_time') == 0
|
||||
or $oUser->getRating() >= Config::Get('acl.create.topic.limit_time_rating')
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяем, если топик опубликованный меньше чем acl.create.topic.limit_time секунд назад
|
||||
*/
|
||||
$aTopics = $this->Topic_GetLastTopicsByUserId($oUser->getId(), Config::Get('acl.create.topic.limit_time'));
|
||||
if (isset($aTopics['count']) and $aTopics['count'] > 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет возможность отправки личного сообщения
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function CanAddTalk($oUser)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'create_talk', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
if (!$that->CanSendTalkTime($oUser)) {
|
||||
return $that->Lang_Get('talk.notices.time_limit');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь отправить инбокс по времени
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function CanSendTalkTime($oUser)
|
||||
{
|
||||
// Для администраторов ограничение по времени не действует
|
||||
if ($oUser->isAdministrator()
|
||||
or Config::Get('acl.create.talk.limit_time') == 0
|
||||
or $oUser->getRating() >= Config::Get('acl.create.talk.limit_time_rating')
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяем, если топик опубликованный меньше чем acl.create.topic.limit_time секунд назад
|
||||
*/
|
||||
$aTalks = $this->Talk_GetLastTalksByUserId($oUser->getId(), Config::Get('acl.create.talk.limit_time'));
|
||||
if (isset($aTalks['count']) and $aTalks['count'] > 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь создавать комментарии к личным сообщениям
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function CanPostTalkComment($oUser)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'create_talk_comment', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
$aTalkComments = $that->Comment_GetCommentsByUserId($oUser->getId(), 'talk', 1, 1);
|
||||
/**
|
||||
* Если комментариев не было
|
||||
*/
|
||||
if (!is_array($aTalkComments) or $aTalkComments['count'] == 0) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Достаем последний комментарий
|
||||
*/
|
||||
$oComment = array_shift($aTalkComments['collection']);
|
||||
$sDate = strtotime($oComment->getDate());
|
||||
|
||||
if ($sDate and ((time() - $sDate) < Config::Get('acl.create.talk_comment.limit_time'))) {
|
||||
return $that->Lang_Get('talk.add.notices.time_limit');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь голосовать за конкретный комментарий
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @param ModuleComment_EntityComment $oComment Комментарий
|
||||
* @return bool
|
||||
*/
|
||||
public function CanVoteComment($oUser, $oComment)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'vote_comment', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that, $oComment) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Голосует автор комментария?
|
||||
*/
|
||||
if ($oComment->getUserId() == $oUser->getId()) {
|
||||
return $that->Lang_Get('vote.notices.error_self');
|
||||
}
|
||||
/**
|
||||
* Пользователь уже голосовал?
|
||||
*/
|
||||
if ($oTopicCommentVote = $that->Vote_GetVote($oComment->getId(), 'comment', $oUser->getId())) {
|
||||
return $that->Lang_Get('vote.notices.error_already_voted');
|
||||
}
|
||||
/**
|
||||
* Разрешаем админу
|
||||
*/
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Ограничение по рейтингу
|
||||
*/
|
||||
if ($oUser->getRating() < Config::Get('acl.vote.comment.rating')) {
|
||||
return $that->Lang_Get('vote.notices.error_acl');
|
||||
}
|
||||
/**
|
||||
* Время голосования истекло?
|
||||
*/
|
||||
if (strtotime($oComment->getDate()) <= time() - Config::Get('acl.vote.comment.limit_time')) {
|
||||
return $that->Lang_Get('vote.notices.error_time');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь голосовать за конкретный топик
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @param ModuleTopic_EntityTopic $oTopic Топик
|
||||
* @param int $iValue Направление голосования
|
||||
* @return bool
|
||||
*/
|
||||
public function CanVoteTopic($oUser, $oTopic, $iValue)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'vote_topic', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that, $oTopic, $iValue) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Голосует автор топика?
|
||||
*/
|
||||
if ($oTopic->getUserId() == $oUser->getId()) {
|
||||
return $that->Lang_Get('vote.notices.error_self');
|
||||
}
|
||||
/**
|
||||
* Пользователь уже голосовал?
|
||||
*/
|
||||
if ($oTopicVote = $that->Vote_GetVote($oTopic->getId(), 'topic', $oUser->getId())) {
|
||||
return $that->Lang_Get('vote.notices.error_already_voted');
|
||||
}
|
||||
/**
|
||||
* Разрешаем админу
|
||||
*/
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Время голосования истекло?
|
||||
*/
|
||||
if (strtotime($oTopic->getDatePublish()) <= time() - Config::Get('acl.vote.topic.limit_time')) {
|
||||
return $that->Lang_Get('vote.notices.error_time');
|
||||
}
|
||||
/**
|
||||
* Ограничение по рейтингу
|
||||
*/
|
||||
if ($iValue != 0 and $oUser->getRating() < Config::Get('acl.vote.topic.rating')) {
|
||||
return $that->Lang_Get('vote.notices.error_acl');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет можно ли юзеру слать инвайты
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function CanSendInvite($oUser)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'create_invite', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
if (!Config::Get('general.reg.invite')) {
|
||||
// разрешаем приглашения всем, когда сайт открыт
|
||||
return true;
|
||||
}
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
if ($that->Invite_GetCountInviteAvailable($oUser) == 0) {
|
||||
return $that->Lang_Get('user.settings.invites.available_no');
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет можно или нет юзеру постить в данный блог
|
||||
*
|
||||
* @param ModuleBlog_EntityBlog $oBlog Блог
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowBlog($oBlog, $oUser)
|
||||
{
|
||||
if (!$oBlog || !$oUser) {
|
||||
return false;
|
||||
}
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
if ($oBlog->getOwnerId() == $oUser->getId()) {
|
||||
return true;
|
||||
}
|
||||
if ($oBlog->getType() == 'close') {
|
||||
/**
|
||||
* Для закрытых блогов проверяем среди подписчиков
|
||||
*/
|
||||
if ($oBlogUser = $this->Blog_GetBlogUserByBlogIdAndUserId($oBlog->getId(), $oUser->getId())) {
|
||||
if ($oUser->getRating() >= $oBlog->getLimitRatingTopic() or $oBlogUser->getIsAdministrator() or $oBlogUser->getIsModerator()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Иначе смотрим ограничение на рейтинг
|
||||
*/
|
||||
if ($oUser->getRating() >= $oBlog->getLimitRatingTopic()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет можно или нет юзеру просматривать блог
|
||||
*
|
||||
* @param ModuleBlog_EntityBlog $oBlog Блог
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowShowBlog($oBlog, $oUser)
|
||||
{
|
||||
if ($oBlog->getType() != 'close') {
|
||||
return true;
|
||||
}
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
if ($oBlog->getOwnerId() == $oUser->getId()) {
|
||||
return true;
|
||||
}
|
||||
if ($oBlogUser = $this->Blog_GetBlogUserByBlogIdAndUserId($oBlog->getId(),
|
||||
$oUser->getId()) and $oBlogUser->getUserRole() > ModuleBlog::BLOG_USER_ROLE_GUEST
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет можно или нет пользователю редактировать данный топик
|
||||
*
|
||||
* @param ModuleTopic_EntityTopic $oTopic Топик
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowEditTopic($oTopic, $oUser)
|
||||
{
|
||||
/**
|
||||
* Разрешаем если это админ сайта или автор топика
|
||||
*/
|
||||
if ($oTopic->getUserId() == $oUser->getId() or $oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Если автор(смотритель) блога
|
||||
*/
|
||||
if ($oTopic->getBlog()->getOwnerId() == $oUser->getId()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Если модер или админ блога
|
||||
*/
|
||||
if ($this->User_GetUserCurrent() and $this->User_GetUserCurrent()->getId() == $oUser->getId()) {
|
||||
/**
|
||||
* Для авторизованного пользователя данный код будет работать быстрее
|
||||
*/
|
||||
if ($oTopic->getBlog()->getUserIsAdministrator() or $oTopic->getBlog()->getUserIsModerator()) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$oBlogUser = $this->Blog_GetBlogUserByBlogIdAndUserId($oTopic->getBlogId(), $oUser->getId());
|
||||
if ($oBlogUser and ($oBlogUser->getIsModerator() or $oBlogUser->getIsAdministrator())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на редактирование комментария
|
||||
*
|
||||
* @param ModuleComment_EntityComment $oComment
|
||||
* @param ModuleUser_EntityUser $oUser
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowEditComment($oComment, $oUser)
|
||||
{
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
if (!in_array($oComment->getTargetType(), (array)Config::Get('module.comment.edit_target_allow'))) {
|
||||
return false;
|
||||
}
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
if ($oComment->getUserId() == $oUser->getId() and $oUser->getRating() >= Config::Get('acl.update.comment.rating')) {
|
||||
/**
|
||||
* Проверяем на лимит времени
|
||||
*/
|
||||
if (!Config::Get('acl.update.comment.limit_time') or (time() - strtotime($oComment->getDate()) <= Config::Get('acl.update.comment.limit_time'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на возможность добавления комментария в избранное
|
||||
*
|
||||
* @param $oComment
|
||||
* @param $oUser
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowFavouriteComment($oComment, $oUser)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'create_comment_favourite', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that, $oComment) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
if (!in_array($oComment->getTargetType(), array('topic'))) {
|
||||
return false;
|
||||
}
|
||||
if (!$oTarget = $oComment->getTarget()) {
|
||||
return false;
|
||||
}
|
||||
if ($oComment->getTargetType() == 'topic') {
|
||||
/**
|
||||
* Проверяем права на просмотр топика
|
||||
*/
|
||||
if (!$that->IsAllowShowTopic($oTarget, $oUser)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на удаление комментария
|
||||
*
|
||||
* @param ModuleComment_EntityComment $oComment
|
||||
* @param ModuleUser_EntityUser $oUser
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowDeleteComment($oComment, $oUser)
|
||||
{
|
||||
/**
|
||||
* Разрешаем если это админ сайта
|
||||
*/
|
||||
if ($oUser and $oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет можно или нет пользователю удалять данный топик
|
||||
*
|
||||
* @param ModuleTopic_EntityTopic $oTopic Топик
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowDeleteTopic($oTopic, $oUser)
|
||||
{
|
||||
$that = $this; // fix for PHP < 5.4
|
||||
return $this->Rbac_IsAllowUser($oUser, 'remove_topic', array(
|
||||
'callback' => function ($oUser, $aParams) use ($that, $oTopic) {
|
||||
if (!$oUser) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Разрешаем если это админ сайта или автор топика
|
||||
*/
|
||||
if ($oTopic->getUserId() == $oUser->getId() or $oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Если автор(смотритель) блога
|
||||
*/
|
||||
if ($oTopic->getBlog()->getOwnerId() == $oUser->getId()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Если модер или админ блога
|
||||
*/
|
||||
if ($that->User_GetUserCurrent() and $that->User_GetUserCurrent()->getId() == $oUser->getId()) {
|
||||
/**
|
||||
* Для авторизованного пользователя данный код будет работать быстрее
|
||||
*/
|
||||
if ($oTopic->getBlog()->getUserIsAdministrator() or $oTopic->getBlog()->getUserIsModerator()) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$oBlogUser = $that->Blog_GetBlogUserByBlogIdAndUserId($oTopic->getBlogId(), $oUser->getId());
|
||||
if ($oBlogUser and ($oBlogUser->getIsModerator() or $oBlogUser->getIsAdministrator())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на возможность просмотра топика
|
||||
*
|
||||
* @param $oTopic
|
||||
* @param $oUser
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowShowTopic($oTopic, $oUser)
|
||||
{
|
||||
if (!$oTopic) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Проверяем права на просмотр топика
|
||||
*/
|
||||
if ((!$oTopic->getPublish() or $oTopic->getDatePublish() > date('Y-m-d H:i:s'))
|
||||
and (!$oUser or ($oUser->getId() != $oTopic->getUserId() and !$oUser->isAdministrator()))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Определяем права на отображение записи из закрытого блога
|
||||
*/
|
||||
if (!$this->IsAllowShowBlog($oTopic->getBlog(), $oUser)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет можно или нет пользователю удалять данный блог
|
||||
*
|
||||
* @param ModuleBlog_EntityBlog $oBlog Блог
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowDeleteBlog($oBlog, $oUser)
|
||||
{
|
||||
/**
|
||||
* Разрешаем если это админ сайта или автор блога
|
||||
*/
|
||||
if ($oUser->isAdministrator()) {
|
||||
return self::CAN_DELETE_BLOG_WITH_TOPICS;
|
||||
}
|
||||
/**
|
||||
* Разрешаем удалять администраторам блога и автору, но только пустой
|
||||
*/
|
||||
if ($oBlog->getOwnerId() == $oUser->getId()) {
|
||||
return self::CAN_DELETE_BLOG_EMPTY_ONLY;
|
||||
}
|
||||
|
||||
$oBlogUser = $this->Blog_GetBlogUserByBlogIdAndUserId($oBlog->getId(), $oUser->getId());
|
||||
if ($oBlogUser and $oBlogUser->getIsAdministrator()) {
|
||||
return self::CAN_DELETE_BLOG_EMPTY_ONLY;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь удалить комментарий
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function CanDeleteComment($oUser)
|
||||
{
|
||||
if (!$oUser || !$oUser->isAdministrator()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь публиковать на главной
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowTopicPublishIndex(ModuleUser_EntityUser $oUser)
|
||||
{
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет может ли пользователь блокировать топик на главной
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowTopicSkipIndex(ModuleUser_EntityUser $oUser)
|
||||
{
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет можно или нет пользователю редактировать данный блог
|
||||
*
|
||||
* @param ModuleBlog_EntityBlog $oBlog Блог
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowEditBlog($oBlog, $oUser)
|
||||
{
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Разрешаем если это создатель блога
|
||||
*/
|
||||
if ($oBlog->getOwnerId() == $oUser->getId()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Явлется ли авторизованный пользователь администратором блога
|
||||
*/
|
||||
$oBlogUser = $this->Blog_GetBlogUserByBlogIdAndUserId($oBlog->getId(), $oUser->getId());
|
||||
|
||||
if ($oBlogUser && $oBlogUser->getIsAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет можно или нет пользователю управлять пользователями блога
|
||||
*
|
||||
* @param ModuleBlog_EntityBlog $oBlog Блог
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowAdminBlog($oBlog, $oUser)
|
||||
{
|
||||
if ($oUser->isAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Разрешаем если это создатель блога
|
||||
*/
|
||||
if ($oBlog->getOwnerId() == $oUser->getId()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Явлется ли авторизованный пользователь администратором блога
|
||||
*/
|
||||
$oBlogUser = $this->Blog_GetBlogUserByBlogIdAndUserId($oBlog->getId(), $oUser->getId());
|
||||
if ($oBlogUser && $oBlogUser->getIsAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на ограничение по времени на постинг на стене
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser Пользователь
|
||||
* @param ModuleWall_EntityWall $oWall Объект сообщения на стене
|
||||
* @return bool
|
||||
*/
|
||||
public function CanAddWallTime($oUser, $oWall)
|
||||
{
|
||||
/**
|
||||
* Для администраторов ограничение по времени не действует
|
||||
*/
|
||||
if ($oUser->isAdministrator()
|
||||
or Config::Get('acl.create.wall.limit_time') == 0
|
||||
or $oUser->getRating() >= Config::Get('acl.create.wall.limit_time_rating')
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
if ($oWall->getUserId() == $oWall->getWallUserId()) {
|
||||
return true;
|
||||
}
|
||||
/**
|
||||
* Получаем последнее сообщение
|
||||
*/
|
||||
$aWall = $this->Wall_GetWall(array('user_id' => $oWall->getUserId()), array('id' => 'desc'), 1, 1, array());
|
||||
/**
|
||||
* Если сообщений нет
|
||||
*/
|
||||
if ($aWall['count'] == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$oWallLast = array_shift($aWall['collection']);
|
||||
$sDate = strtotime($oWallLast->getDateAdd());
|
||||
if ($sDate and ((time() - $sDate) < Config::Get('acl.create.wall.limit_time'))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
1229
application/classes/modules/blog/Blog.class.php
Normal file
1229
application/classes/modules/blog/Blog.class.php
Normal file
File diff suppressed because it is too large
Load diff
517
application/classes/modules/blog/entity/Blog.entity.class.php
Normal file
517
application/classes/modules/blog/entity/Blog.entity.class.php
Normal file
|
@ -0,0 +1,517 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность блога
|
||||
*
|
||||
* @package application.modules.blog
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleBlog_EntityBlog extends Entity
|
||||
{
|
||||
|
||||
protected $sPrimaryKey = 'blog_id';
|
||||
/**
|
||||
* Список поведений
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aBehaviors = array(
|
||||
// Категории
|
||||
'category' => array(
|
||||
'class' => 'ModuleCategory_BehaviorEntity',
|
||||
'target_type' => 'blog',
|
||||
'form_field' => 'category',
|
||||
'multiple' => false,
|
||||
'validate_require' => false,
|
||||
'validate_only_without_children' => true,
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
parent::Init();
|
||||
$this->aBehaviors['category']['validate_require'] = !Config::Get('module.blog.category_allow_empty');
|
||||
$this->aBehaviors['category']['validate_only_without_children'] = Config::Get('module.blog.category_only_without_children');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ID блога
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->_getDataOne('blog_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ID хозяина блога
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getOwnerId()
|
||||
{
|
||||
return $this->_getDataOne('user_owner_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает название блога
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->_getDataOne('blog_title');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает описание блога
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->_getDataOne('blog_description');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает тип блога
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->_getDataOne('blog_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает дату создания блога
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDateAdd()
|
||||
{
|
||||
return $this->_getDataOne('blog_date_add');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает дату редактирования блога
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDateEdit()
|
||||
{
|
||||
return $this->_getDataOne('blog_date_edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возврщает количество проголосовавших за блог
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCountVote()
|
||||
{
|
||||
return $this->_getDataOne('blog_count_vote');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество пользователей в блоге
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCountUser()
|
||||
{
|
||||
return $this->_getDataOne('blog_count_user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество топиков в блоге
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCountTopic()
|
||||
{
|
||||
return $this->_getDataOne('blog_count_topic');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ограничение по рейтингу для постинга в блог
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getLimitRatingTopic()
|
||||
{
|
||||
return $this->_getDataOne('blog_limit_rating_topic');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL блога
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
return $this->_getDataOne('blog_url');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает флаг пропуска топиков на главной
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getSkipIndex()
|
||||
{
|
||||
return $this->_getDataOne('blog_skip_index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает полный серверный путь до аватара блога
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getAvatar()
|
||||
{
|
||||
return $this->_getDataOne('blog_avatar');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает расширения аватра блога
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getAvatarType()
|
||||
{
|
||||
return ($sPath = $this->getAvatarPath()) ? pathinfo($sPath, PATHINFO_EXTENSION) : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает объект пользователя хозяина блога
|
||||
*
|
||||
* @return ModuleUser_EntityUser|null
|
||||
*/
|
||||
public function getOwner()
|
||||
{
|
||||
return $this->_getDataOne('owner');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект голосования за блог
|
||||
*
|
||||
* @return ModuleVote_EntityVote|null
|
||||
*/
|
||||
public function getVote()
|
||||
{
|
||||
return $this->_getDataOne('vote');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает полный серверный путь до аватара блога определенного размера
|
||||
*
|
||||
* @param int $iSize Размер аватара
|
||||
* @return string
|
||||
*/
|
||||
public function getAvatarPath($iSize = 48)
|
||||
{
|
||||
if (is_numeric($iSize)) {
|
||||
$iSize .= 'crop';
|
||||
}
|
||||
if ($sPath = $this->getAvatar()) {
|
||||
return $this->Media_GetImageWebPath($sPath, $iSize);
|
||||
} else {
|
||||
return $this->Media_GetImagePathBySize(Router::GetFixPathWeb(Config::Get('path.skin.assets.web')) . '/images/avatars/avatar_blog.png', $iSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает путь до большого аватара блога
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAvatarBig()
|
||||
{
|
||||
return $this->getAvatarPath(Config::Get('module.blog.avatar_size_big'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует массив с путями до аватаров
|
||||
*
|
||||
* @return array Массив с путями до аватаров
|
||||
*/
|
||||
public function getAvatarsPath()
|
||||
{
|
||||
$aAvatars = array();
|
||||
|
||||
foreach (Config::Get('module.blog.avatar_size') as $sSize) {
|
||||
$aAvatars[$sSize] = $this->getAvatarPath($sSize);
|
||||
}
|
||||
|
||||
return $aAvatars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает факт присоединения пользователя к блогу
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function getUserIsJoin()
|
||||
{
|
||||
return $this->_getDataOne('user_is_join');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет является ли пользователь администратором блога
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function getUserIsAdministrator()
|
||||
{
|
||||
return $this->_getDataOne('user_is_administrator');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет является ли пользователь модератором блога
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function getUserIsModerator()
|
||||
{
|
||||
return $this->_getDataOne('user_is_moderator');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает полный URL блога
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlFull()
|
||||
{
|
||||
if ($this->getType() == 'personal') {
|
||||
return $this->getOwner()->getUserWebPath() . 'created/topics/';
|
||||
} else {
|
||||
return Router::GetPath('blog') . $this->getUrl() . '/';
|
||||
}
|
||||
}
|
||||
|
||||
public function isAllowEdit()
|
||||
{
|
||||
if ($oUser = $this->User_GetUserCurrent()) {
|
||||
if ($oUser->getId() == $this->getOwnerId() or $oUser->isAdministrator() or $this->getUserIsAdministrator()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID блога
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setId($data)
|
||||
{
|
||||
$this->_aData['blog_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID хозяина блога
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setOwnerId($data)
|
||||
{
|
||||
$this->_aData['user_owner_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает заголовок блога
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setTitle($data)
|
||||
{
|
||||
$this->_aData['blog_title'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает описание блога
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setDescription($data)
|
||||
{
|
||||
$this->_aData['blog_description'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает тип блога
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setType($data)
|
||||
{
|
||||
$this->_aData['blog_type'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает дату создания блога
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setDateAdd($data)
|
||||
{
|
||||
$this->_aData['blog_date_add'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает дату редактирования топика
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setDateEdit($data)
|
||||
{
|
||||
$this->_aData['blog_date_edit'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устаналивает количество проголосовавших
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setCountVote($data)
|
||||
{
|
||||
$this->_aData['blog_count_vote'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает количество пользователей блога
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setCountUser($data)
|
||||
{
|
||||
$this->_aData['blog_count_user'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает количество топиков в блоге
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setCountTopic($data)
|
||||
{
|
||||
$this->_aData['blog_count_topic'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ограничение на постинг в блог
|
||||
*
|
||||
* @param float $data
|
||||
*/
|
||||
public function setLimitRatingTopic($data)
|
||||
{
|
||||
$this->_aData['blog_limit_rating_topic'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает URL блога
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setUrl($data)
|
||||
{
|
||||
$this->_aData['blog_url'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает флаг пропуска топиков на главной
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setSkipIndex($data)
|
||||
{
|
||||
$this->_aData['blog_skip_index'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает полный серверный путь до аватара блога
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setAvatar($data)
|
||||
{
|
||||
$this->_aData['blog_avatar'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает автора блога
|
||||
*
|
||||
* @param ModuleUser_EntityUser $data
|
||||
*/
|
||||
public function setOwner($data)
|
||||
{
|
||||
$this->_aData['owner'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает статус администратора блога для текущего пользователя
|
||||
*
|
||||
* @param bool $data
|
||||
*/
|
||||
public function setUserIsAdministrator($data)
|
||||
{
|
||||
$this->_aData['user_is_administrator'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает статус модератора блога для текущего пользователя
|
||||
*
|
||||
* @param bool $data
|
||||
*/
|
||||
public function setUserIsModerator($data)
|
||||
{
|
||||
$this->_aData['user_is_moderator'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устаналивает статус присоединения польователя к блогу
|
||||
*
|
||||
* @param bool $data
|
||||
*/
|
||||
public function setUserIsJoin($data)
|
||||
{
|
||||
$this->_aData['user_is_join'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает объект голосования за блог
|
||||
*
|
||||
* @param ModuleVote_EntityVote $data
|
||||
*/
|
||||
public function setVote($data)
|
||||
{
|
||||
$this->_aData['vote'] = $data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,190 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность связи пользователя и блога
|
||||
*
|
||||
* @package application.modules.blog
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleBlog_EntityBlogUser extends Entity
|
||||
{
|
||||
/**
|
||||
* Возвращает ID блога
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getBlogId()
|
||||
{
|
||||
return $this->_getDataOne('blog_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ID пользователя
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->_getDataOne('user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает статус модератор пользователь или нет
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsModerator()
|
||||
{
|
||||
return ($this->getUserRole() == ModuleBlog::BLOG_USER_ROLE_MODERATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает статус администратор пользователь или нет
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsAdministrator()
|
||||
{
|
||||
return ($this->getUserRole() == ModuleBlog::BLOG_USER_ROLE_ADMINISTRATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает статус бана пользователя
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getIsBanned()
|
||||
{
|
||||
return ($this->getUserRole() == ModuleBlog::BLOG_USER_ROLE_BAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает текущую роль пользователя в блоге
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getUserRole()
|
||||
{
|
||||
return $this->_getDataOne('user_role');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект блога
|
||||
*
|
||||
* @return ModuleBlog_EntityBlog|null
|
||||
*/
|
||||
public function getBlog()
|
||||
{
|
||||
return $this->_getDataOne('blog');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект пользователя
|
||||
*
|
||||
* @return ModuleUser_EntityUser|null
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->_getDataOne('user');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает ID блога
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setBlogId($data)
|
||||
{
|
||||
$this->_aData['blog_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID пользователя
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setUserId($data)
|
||||
{
|
||||
$this->_aData['user_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает статус модератора блога
|
||||
*
|
||||
* @param bool $data
|
||||
*/
|
||||
public function setIsModerator($data)
|
||||
{
|
||||
if ($data && !$this->getIsModerator()) {
|
||||
/**
|
||||
* Повышаем статус до модератора
|
||||
*/
|
||||
$this->setUserRole(ModuleBlog::BLOG_USER_ROLE_MODERATOR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает статус администратора блога
|
||||
*
|
||||
* @param bool $data
|
||||
*/
|
||||
public function setIsAdministrator($data)
|
||||
{
|
||||
if ($data && !$this->getIsAdministrator()) {
|
||||
/**
|
||||
* Повышаем статус до администратора
|
||||
*/
|
||||
$this->setUserRole(ModuleBlog::BLOG_USER_ROLE_ADMINISTRATOR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает роль пользователя
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setUserRole($data)
|
||||
{
|
||||
$this->_aData['user_role'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает блог
|
||||
*
|
||||
* @param ModuleBlog_EntityBlog $data
|
||||
*/
|
||||
public function setBlog($data)
|
||||
{
|
||||
$this->_aData['blog'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливаем пользователя
|
||||
*
|
||||
* @param ModuleUser_EntityUser $data
|
||||
*/
|
||||
public function setUser($data)
|
||||
{
|
||||
$this->_aData['user'] = $data;
|
||||
}
|
||||
}
|
641
application/classes/modules/blog/mapper/Blog.mapper.class.php
Normal file
641
application/classes/modules/blog/mapper/Blog.mapper.class.php
Normal file
|
@ -0,0 +1,641 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Маппер для работы с БД по части блогов
|
||||
*
|
||||
* @package application.modules.blog
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleBlog_MapperBlog extends Mapper
|
||||
{
|
||||
/**
|
||||
* Добавляет блог в БД
|
||||
*
|
||||
* @param ModuleBlog_EntityBlog $oBlog Объект блога
|
||||
* @return int|bool
|
||||
*/
|
||||
public function AddBlog(ModuleBlog_EntityBlog $oBlog)
|
||||
{
|
||||
$sql = "INSERT INTO " . Config::Get('db.table.blog') . "
|
||||
(user_owner_id,
|
||||
blog_title,
|
||||
blog_description,
|
||||
blog_type,
|
||||
blog_date_add,
|
||||
blog_limit_rating_topic,
|
||||
blog_url,
|
||||
blog_skip_index,
|
||||
blog_avatar
|
||||
)
|
||||
VALUES(?d, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
";
|
||||
if ($iId = $this->oDb->query($sql, $oBlog->getOwnerId(), $oBlog->getTitle(), $oBlog->getDescription(),
|
||||
$oBlog->getType(), $oBlog->getDateAdd(), $oBlog->getLimitRatingTopic(), $oBlog->getUrl(),
|
||||
$oBlog->getSkipIndex(), $oBlog->getAvatar())
|
||||
) {
|
||||
return $iId;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет блог в БД
|
||||
*
|
||||
* @param ModuleBlog_EntityBlog $oBlog Объект блога
|
||||
* @return bool
|
||||
*/
|
||||
public function UpdateBlog(ModuleBlog_EntityBlog $oBlog)
|
||||
{
|
||||
$sql = "UPDATE " . Config::Get('db.table.blog') . "
|
||||
SET
|
||||
blog_title= ?,
|
||||
blog_description= ?,
|
||||
blog_type= ?,
|
||||
blog_date_edit= ?,
|
||||
blog_count_vote = ?d,
|
||||
blog_count_user= ?d,
|
||||
blog_count_topic= ?d,
|
||||
blog_limit_rating_topic= ?f ,
|
||||
blog_url= ?,
|
||||
blog_skip_index= ?d,
|
||||
blog_avatar= ?
|
||||
WHERE
|
||||
blog_id = ?d
|
||||
";
|
||||
$res = $this->oDb->query($sql, $oBlog->getTitle(), $oBlog->getDescription(), $oBlog->getType(),
|
||||
$oBlog->getDateEdit(), $oBlog->getCountVote(), $oBlog->getCountUser(),
|
||||
$oBlog->getCountTopic(), $oBlog->getLimitRatingTopic(), $oBlog->getUrl(), $oBlog->getSkipIndex(), $oBlog->getAvatar(),
|
||||
$oBlog->getId());
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список блогов по ID
|
||||
*
|
||||
* @param array $aArrayId Список ID блогов
|
||||
* @param array|null $aOrder Сортировка блогов
|
||||
* @return array
|
||||
*/
|
||||
public function GetBlogsByArrayId($aArrayId, $aOrder = null)
|
||||
{
|
||||
if (!is_array($aArrayId) or count($aArrayId) == 0) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (!is_array($aOrder)) {
|
||||
$aOrder = array($aOrder);
|
||||
}
|
||||
$sOrder = '';
|
||||
foreach ($aOrder as $key => $value) {
|
||||
$value = (string)$value;
|
||||
if (!in_array($key,
|
||||
array('blog_id', 'blog_title', 'blog_type', 'blog_count_user', 'blog_date_add'))
|
||||
) {
|
||||
unset($aOrder[$key]);
|
||||
} elseif (in_array($value, array('asc', 'desc'))) {
|
||||
$sOrder .= " {$key} {$value},";
|
||||
}
|
||||
}
|
||||
$sOrder = trim($sOrder, ',');
|
||||
|
||||
$sql = "SELECT
|
||||
*
|
||||
FROM
|
||||
" . Config::Get('db.table.blog') . "
|
||||
WHERE
|
||||
blog_id IN(?a)
|
||||
ORDER BY
|
||||
{ FIELD(blog_id,?a) } ";
|
||||
if ($sOrder != '') {
|
||||
$sql .= $sOrder;
|
||||
}
|
||||
|
||||
$aBlogs = array();
|
||||
if ($aRows = $this->oDb->select($sql, $aArrayId, $sOrder == '' ? $aArrayId : DBSIMPLE_SKIP)) {
|
||||
foreach ($aRows as $aBlog) {
|
||||
$aBlogs[] = Engine::GetEntity('Blog', $aBlog);
|
||||
}
|
||||
}
|
||||
return $aBlogs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет связь пользователя с блогом в БД
|
||||
*
|
||||
* @param ModuleBlog_EntityBlogUser $oBlogUser Объект отношения пользователя с блогом
|
||||
* @return bool
|
||||
*/
|
||||
public function AddRelationBlogUser(ModuleBlog_EntityBlogUser $oBlogUser)
|
||||
{
|
||||
$sql = "INSERT INTO " . Config::Get('db.table.blog_user') . "
|
||||
(blog_id,
|
||||
user_id,
|
||||
user_role
|
||||
)
|
||||
VALUES(?d, ?d, ?d)
|
||||
";
|
||||
if ($this->oDb->query($sql, $oBlogUser->getBlogId(), $oBlogUser->getUserId(), $oBlogUser->getUserRole()) === 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет отношение пользователя с блогом
|
||||
*
|
||||
* @param ModuleBlog_EntityBlogUser $oBlogUser Объект отношения пользователя с блогом
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteRelationBlogUser(ModuleBlog_EntityBlogUser $oBlogUser)
|
||||
{
|
||||
$sql = "DELETE FROM " . Config::Get('db.table.blog_user') . "
|
||||
WHERE
|
||||
blog_id = ?d
|
||||
AND
|
||||
user_id = ?d
|
||||
";
|
||||
$res = $this->oDb->query($sql, $oBlogUser->getBlogId(), $oBlogUser->getUserId());
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет отношение пользователя с блогом
|
||||
*
|
||||
* @param ModuleBlog_EntityBlogUser $oBlogUser Объект отношения пользователя с блогом
|
||||
* @return bool
|
||||
*/
|
||||
public function UpdateRelationBlogUser(ModuleBlog_EntityBlogUser $oBlogUser)
|
||||
{
|
||||
$sql = "UPDATE " . Config::Get('db.table.blog_user') . "
|
||||
SET
|
||||
user_role = ?d
|
||||
WHERE
|
||||
blog_id = ?d
|
||||
AND
|
||||
user_id = ?d
|
||||
";
|
||||
$res = $this->oDb->query($sql, $oBlogUser->getUserRole(), $oBlogUser->getBlogId(), $oBlogUser->getUserId());
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список отношений пользователей с блогами
|
||||
*
|
||||
* @param array $aFilter Фильтр поиска отношений
|
||||
* @param int $iCount Возвращает общее количество элементов
|
||||
* @param int $iCurrPage Номер текущейс страницы
|
||||
* @param int $iPerPage Количество элементов на одну страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetBlogUsers($aFilter, &$iCount = null, $iCurrPage = null, $iPerPage = null)
|
||||
{
|
||||
|
||||
if (isset($aFilter['blog_id']) and !is_array($aFilter['blog_id'])) {
|
||||
$aFilter['blog_id']=array($aFilter['blog_id']);
|
||||
}
|
||||
if (isset($aFilter['user_role']) and !is_array($aFilter['user_role'])) {
|
||||
$aFilter['user_role']=array($aFilter['user_role']);
|
||||
}
|
||||
|
||||
if (is_null($iCurrPage)) {
|
||||
$iCurrPage=1;
|
||||
}
|
||||
if (is_null($iPerPage)) {
|
||||
$iPerPage=1000;
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
bu.*
|
||||
FROM
|
||||
" . Config::Get('db.table.blog_user') . " as bu
|
||||
WHERE
|
||||
1=1
|
||||
{ AND bu.blog_id IN (?a) }
|
||||
{ AND bu.user_id = ?d }
|
||||
{ AND bu.user_role IN (?a) }
|
||||
{ AND bu.user_role > ?d }
|
||||
|
||||
LIMIT ?d, ?d
|
||||
";
|
||||
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->selectPage($iCount, $sql,
|
||||
(isset($aFilter['blog_id']) and count($aFilter['blog_id'])) ? $aFilter['blog_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['user_id']) ? $aFilter['user_id'] : DBSIMPLE_SKIP,
|
||||
(isset($aFilter['user_role']) and count($aFilter['user_role'])) ? $aFilter['user_role'] : DBSIMPLE_SKIP,
|
||||
!isset($aFilter['user_role']) ? ModuleBlog::BLOG_USER_ROLE_GUEST : DBSIMPLE_SKIP,
|
||||
($iCurrPage - 1) * $iPerPage, $iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('Blog_BlogUser', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список отношений пользователя к блогам
|
||||
*
|
||||
* @param array $aArrayId Список ID блогов
|
||||
* @param int $sUserId ID блогов
|
||||
* @return array
|
||||
*/
|
||||
public function GetBlogUsersByArrayBlog($aArrayId, $sUserId)
|
||||
{
|
||||
if (!is_array($aArrayId) or count($aArrayId) == 0) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
bu.*
|
||||
FROM
|
||||
" . Config::Get('db.table.blog_user') . " as bu
|
||||
WHERE
|
||||
bu.blog_id IN(?a)
|
||||
AND
|
||||
bu.user_id = ?d ";
|
||||
$aBlogUsers = array();
|
||||
if ($aRows = $this->oDb->select($sql, $aArrayId, $sUserId)) {
|
||||
foreach ($aRows as $aUser) {
|
||||
$aBlogUsers[] = Engine::GetEntity('Blog_BlogUser', $aUser);
|
||||
}
|
||||
}
|
||||
return $aBlogUsers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает ID персонального блога пользователя
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @return int|null
|
||||
*/
|
||||
public function GetPersonalBlogByUserId($sUserId)
|
||||
{
|
||||
$sql = "SELECT blog_id FROM " . Config::Get('db.table.blog') . " WHERE user_owner_id = ?d and blog_type='personal'";
|
||||
if ($aRow = $this->oDb->selectRow($sql, $sUserId)) {
|
||||
return $aRow['blog_id'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает блог по названию
|
||||
*
|
||||
* @param string $sTitle Нащвание блога
|
||||
* @return ModuleBlog_EntityBlog|null
|
||||
*/
|
||||
public function GetBlogByTitle($sTitle)
|
||||
{
|
||||
$sql = "SELECT blog_id FROM " . Config::Get('db.table.blog') . " WHERE blog_title = ? ";
|
||||
if ($aRow = $this->oDb->selectRow($sql, $sTitle)) {
|
||||
return $aRow['blog_id'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает блог по URL
|
||||
*
|
||||
* @param string $sUrl URL блога
|
||||
* @return ModuleBlog_EntityBlog|null
|
||||
*/
|
||||
public function GetBlogByUrl($sUrl)
|
||||
{
|
||||
$sql = "SELECT
|
||||
b.blog_id
|
||||
FROM
|
||||
" . Config::Get('db.table.blog') . " as b
|
||||
WHERE
|
||||
b.blog_url = ?
|
||||
";
|
||||
if ($aRow = $this->oDb->selectRow($sql, $sUrl)) {
|
||||
return $aRow['blog_id'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить список блогов по хозяину
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @return array
|
||||
*/
|
||||
public function GetBlogsByOwnerId($sUserId)
|
||||
{
|
||||
$sql = "SELECT
|
||||
b.blog_id
|
||||
FROM
|
||||
" . Config::Get('db.table.blog') . " as b
|
||||
WHERE
|
||||
b.user_owner_id = ?
|
||||
AND
|
||||
b.blog_type<>'personal'
|
||||
";
|
||||
$aBlogs = array();
|
||||
if ($aRows = $this->oDb->select($sql, $sUserId)) {
|
||||
foreach ($aRows as $aBlog) {
|
||||
$aBlogs[] = $aBlog['blog_id'];
|
||||
}
|
||||
}
|
||||
return $aBlogs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список всех не персональных блогов
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetBlogs()
|
||||
{
|
||||
$sql = "SELECT
|
||||
b.blog_id
|
||||
FROM
|
||||
" . Config::Get('db.table.blog') . " as b
|
||||
WHERE
|
||||
b.blog_type<>'personal'
|
||||
";
|
||||
$aBlogs = array();
|
||||
if ($aRows = $this->oDb->select($sql)) {
|
||||
foreach ($aRows as $aBlog) {
|
||||
$aBlogs[] = $aBlog['blog_id'];
|
||||
}
|
||||
}
|
||||
return $aBlogs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список не персональных блогов с сортировкой по рейтингу
|
||||
*
|
||||
* @param int $iCount Возвращает общее количество элементов
|
||||
* @param int $iCurrPage Номер текущей страницы
|
||||
* @param int $iPerPage Количество элементов на одну страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetBlogsRating(&$iCount, $iCurrPage, $iPerPage)
|
||||
{
|
||||
$sql = "SELECT
|
||||
b.blog_id
|
||||
FROM
|
||||
" . Config::Get('db.table.blog') . " as b
|
||||
WHERE
|
||||
b.blog_type<>'personal'
|
||||
ORDER by b.blog_count_user desc
|
||||
LIMIT ?d, ?d ";
|
||||
$aReturn = array();
|
||||
if ($aRows = $this->oDb->selectPage($iCount, $sql, ($iCurrPage - 1) * $iPerPage, $iPerPage)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aReturn[] = $aRow['blog_id'];
|
||||
}
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список блогов в которых состоит пользователь
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param int $iLimit Ограничение на выборку элементов
|
||||
* @return array
|
||||
*/
|
||||
public function GetBlogsRatingJoin($sUserId, $iLimit)
|
||||
{
|
||||
$sql = "SELECT
|
||||
b.*
|
||||
FROM
|
||||
" . Config::Get('db.table.blog_user') . " as bu,
|
||||
" . Config::Get('db.table.blog') . " as b
|
||||
WHERE
|
||||
bu.user_id = ?d
|
||||
AND
|
||||
bu.blog_id = b.blog_id
|
||||
AND
|
||||
b.blog_type<>'personal'
|
||||
ORDER by b.blog_count_user desc
|
||||
LIMIT 0, ?d
|
||||
;
|
||||
";
|
||||
$aReturn = array();
|
||||
if ($aRows = $this->oDb->select($sql, $sUserId, $iLimit)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aReturn[] = Engine::GetEntity('Blog', $aRow);
|
||||
}
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список блогов, которые создал пользователь
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param int $iLimit Ограничение на выборку элементов
|
||||
* @return array
|
||||
*/
|
||||
public function GetBlogsRatingSelf($sUserId, $iLimit)
|
||||
{
|
||||
$sql = "SELECT
|
||||
b.*
|
||||
FROM
|
||||
" . Config::Get('db.table.blog') . " as b
|
||||
WHERE
|
||||
b.user_owner_id = ?d
|
||||
AND
|
||||
b.blog_type<>'personal'
|
||||
ORDER by b.blog_count_user desc
|
||||
LIMIT 0, ?d
|
||||
;";
|
||||
$aReturn = array();
|
||||
if ($aRows = $this->oDb->select($sql, $sUserId, $iLimit)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aReturn[] = Engine::GetEntity('Blog', $aRow);
|
||||
}
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает полный список закрытых блогов
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetCloseBlogs()
|
||||
{
|
||||
$sql = "SELECT b.blog_id
|
||||
FROM " . Config::Get('db.table.blog') . " as b
|
||||
WHERE b.blog_type='close'
|
||||
;";
|
||||
$aReturn = array();
|
||||
if ($aRows = $this->oDb->select($sql)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aReturn[] = $aRow['blog_id'];
|
||||
}
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление блога из базы данных
|
||||
*
|
||||
* @param int $iBlogId ID блога
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteBlog($iBlogId)
|
||||
{
|
||||
$sql = "
|
||||
DELETE FROM " . Config::Get('db.table.blog') . "
|
||||
WHERE blog_id = ?d
|
||||
";
|
||||
$res = $this->oDb->query($sql, $iBlogId);
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удалить пользователей блога по идентификатору блога
|
||||
*
|
||||
* @param int $iBlogId ID блога
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteBlogUsersByBlogId($iBlogId)
|
||||
{
|
||||
$sql = "
|
||||
DELETE FROM " . Config::Get('db.table.blog_user') . "
|
||||
WHERE blog_id = ?d
|
||||
";
|
||||
$res = $this->oDb->query($sql, $iBlogId);
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Пересчитывает число топиков в блогах
|
||||
*
|
||||
* @param int|null $iBlogId ID блога
|
||||
* @return bool
|
||||
*/
|
||||
public function RecalculateCountTopic($iBlogId = null)
|
||||
{
|
||||
$sql = "
|
||||
UPDATE " . Config::Get('db.table.blog') . " b
|
||||
SET b.blog_count_topic = (
|
||||
SELECT count(*)
|
||||
FROM " . Config::Get('db.table.topic') . " t
|
||||
WHERE
|
||||
(
|
||||
t.blog_id = b.blog_id OR
|
||||
t.blog_id2 = b.blog_id OR
|
||||
t.blog_id3 = b.blog_id OR
|
||||
t.blog_id4 = b.blog_id OR
|
||||
t.blog_id5 = b.blog_id
|
||||
)
|
||||
AND
|
||||
t.topic_publish = 1
|
||||
)
|
||||
WHERE 1=1
|
||||
{ and b.blog_id = ?d }
|
||||
";
|
||||
$res = $this->oDb->query($sql, is_null($iBlogId) ? DBSIMPLE_SKIP : $iBlogId);
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список блогов по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр выборки
|
||||
* @param array $aOrder Сортировка
|
||||
* @param int $iCount Возвращает общее количество элментов
|
||||
* @param int $iCurrPage Номер текущей страницы
|
||||
* @param int $iPerPage Количество элементов на одну страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetBlogsByFilter($aFilter, $aOrder, &$iCount, $iCurrPage, $iPerPage)
|
||||
{
|
||||
$aOrderAllow = array('blog_id', 'blog_title', 'blog_count_user', 'blog_count_topic');
|
||||
$sOrder = '';
|
||||
foreach ($aOrder as $key => $value) {
|
||||
if (!in_array($key, $aOrderAllow)) {
|
||||
unset($aOrder[$key]);
|
||||
} elseif (in_array($value, array('asc', 'desc'))) {
|
||||
$sOrder .= " b.{$key} {$value},";
|
||||
}
|
||||
}
|
||||
$sOrder = trim($sOrder, ',');
|
||||
if ($sOrder == '') {
|
||||
$sOrder = ' b.blog_id desc ';
|
||||
}
|
||||
|
||||
if (isset($aFilter['exclude_type']) and !is_array($aFilter['exclude_type'])) {
|
||||
$aFilter['exclude_type'] = array($aFilter['exclude_type']);
|
||||
}
|
||||
if (isset($aFilter['type']) and !is_array($aFilter['type'])) {
|
||||
$aFilter['type'] = array($aFilter['type']);
|
||||
}
|
||||
if (isset($aFilter['id']) and !is_array($aFilter['id'])) {
|
||||
$aFilter['id'] = array($aFilter['id']);
|
||||
}
|
||||
|
||||
$iUserCurrentId=0;
|
||||
if (isset($aFilter['roles_user_id'])) {
|
||||
$iUserCurrentId=$aFilter['roles_user_id'];
|
||||
} elseif ($oUserCurrent=$this->User_GetUserCurrent()) {
|
||||
$iUserCurrentId=$oUserCurrent->getId();
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
b.blog_id
|
||||
FROM
|
||||
" . Config::Get('db.table.blog') . " as b
|
||||
{
|
||||
JOIN " . Config::Get('db.table.blog_user') . " as bu
|
||||
ON ( bu.blog_id = b.blog_id and bu.user_id = '{$iUserCurrentId}'
|
||||
and bu.user_role in (?a)
|
||||
)
|
||||
}
|
||||
WHERE
|
||||
1 = 1
|
||||
{ AND b.blog_id IN (?a) }
|
||||
{ AND b.user_owner_id = ?d }
|
||||
{ AND b.blog_type IN (?a) }
|
||||
{ AND b.blog_type not IN (?a) }
|
||||
{ AND b.blog_url = ? }
|
||||
{ AND b.blog_title LIKE ? }
|
||||
ORDER by {$sOrder}
|
||||
LIMIT ?d, ?d ;
|
||||
";
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->selectPage($iCount, $sql,
|
||||
(isset($aFilter['roles']) and count($aFilter['roles'])) ? $aFilter['roles'] : DBSIMPLE_SKIP,
|
||||
(isset($aFilter['id']) and count($aFilter['id'])) ? $aFilter['id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['user_owner_id']) ? $aFilter['user_owner_id'] : DBSIMPLE_SKIP,
|
||||
(isset($aFilter['type']) and count($aFilter['type'])) ? $aFilter['type'] : DBSIMPLE_SKIP,
|
||||
(isset($aFilter['exclude_type']) and count($aFilter['exclude_type'])) ? $aFilter['exclude_type'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['url']) ? $aFilter['url'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['title']) ? $aFilter['title'] : DBSIMPLE_SKIP,
|
||||
($iCurrPage - 1) * $iPerPage, $iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = $aRow['blog_id'];
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
}
|
577
application/classes/modules/category/Category.class.php
Normal file
577
application/classes/modules/category/Category.class.php
Normal file
|
@ -0,0 +1,577 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Модуль управления универсальными категориями
|
||||
*
|
||||
* @package application.modules.category
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleCategory extends ModuleORM
|
||||
{
|
||||
/**
|
||||
* Список состояний типов объектов
|
||||
*/
|
||||
const TARGET_STATE_ACTIVE = 1;
|
||||
const TARGET_STATE_NOT_ACTIVE = 2;
|
||||
const TARGET_STATE_REMOVE = 3;
|
||||
|
||||
/**
|
||||
* Возвращает список категорий сущности
|
||||
*
|
||||
* @param $oTarget
|
||||
* @param $sTargetType
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetEntityCategories($oTarget, $sTargetType)
|
||||
{
|
||||
$aCategories = $oTarget->_getDataOne('_categories');
|
||||
if (is_null($aCategories)) {
|
||||
$this->AttachCategoriesForTargetItems($oTarget, $sTargetType);
|
||||
return $oTarget->_getDataOne('_categories');
|
||||
}
|
||||
return $aCategories;
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка фильтра ORM запросов
|
||||
*
|
||||
* @param array $aFilter
|
||||
* @param array $sEntityFull
|
||||
* @param string $sTargetType
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function RewriteFilter($aFilter, $sEntityFull, $sTargetType)
|
||||
{
|
||||
$oEntitySample = Engine::GetEntity($sEntityFull);
|
||||
|
||||
if (!isset($aFilter['#join'])) {
|
||||
$aFilter['#join'] = array();
|
||||
}
|
||||
|
||||
if (!isset($aFilter['#select'])) {
|
||||
$aFilter['#select'] = array();
|
||||
}
|
||||
|
||||
if (array_key_exists('#category', $aFilter)) {
|
||||
$aCategoryId = $aFilter['#category'];
|
||||
if (!is_array($aCategoryId)) {
|
||||
$aCategoryId = array($aCategoryId);
|
||||
}
|
||||
$sJoin = "JOIN " . Config::Get('db.table.category_target') . " category ON
|
||||
t.`{$oEntitySample->_getPrimaryKey()}` = category.target_id and
|
||||
category.target_type = '{$sTargetType}' and
|
||||
category.category_id IN ( ?a ) ";
|
||||
$aFilter['#join'][$sJoin] = array($aCategoryId);
|
||||
if (count($aFilter['#select'])) {
|
||||
$aFilter['#select'][] = "distinct t.`{$oEntitySample->_getPrimaryKey()}`";
|
||||
} else {
|
||||
$aFilter['#select'][] = "distinct t.`{$oEntitySample->_getPrimaryKey()}`";
|
||||
$aFilter['#select'][] = 't.*';
|
||||
}
|
||||
}
|
||||
return $aFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Переопределяем метод для возможности цеплять свои кастомные данные при ORM запросах - свойства
|
||||
*
|
||||
* @param array $aResult
|
||||
* @param array $aFilter
|
||||
* @param string $sTargetType
|
||||
*/
|
||||
public function RewriteGetItemsByFilter($aResult, $aFilter, $sTargetType)
|
||||
{
|
||||
if (!$aResult) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Список на входе может быть двух видов:
|
||||
* 1 - одномерный массив
|
||||
* 2 - двумерный, если применялась группировка (использование '#index-group')
|
||||
*
|
||||
* Поэтому сначала сформируем линейный список
|
||||
*/
|
||||
if (isset($aFilter['#index-group']) and $aFilter['#index-group']) {
|
||||
$aEntitiesWork = array();
|
||||
foreach ($aResult as $aItems) {
|
||||
foreach ($aItems as $oItem) {
|
||||
$aEntitiesWork[] = $oItem;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$aEntitiesWork = $aResult;
|
||||
}
|
||||
|
||||
if (!$aEntitiesWork) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Проверяем необходимость цеплять категории
|
||||
*/
|
||||
if (isset($aFilter['#with']['#category'])) {
|
||||
$this->AttachCategoriesForTargetItems($aEntitiesWork, $sTargetType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Цепляет для списка объектов категории
|
||||
*
|
||||
* @param array $aEntityItems
|
||||
* @param string $sTargetType
|
||||
*/
|
||||
public function AttachCategoriesForTargetItems($aEntityItems, $sTargetType)
|
||||
{
|
||||
if (!is_array($aEntityItems)) {
|
||||
$aEntityItems = array($aEntityItems);
|
||||
}
|
||||
$aEntitiesId = array();
|
||||
foreach ($aEntityItems as $oEntity) {
|
||||
$aEntitiesId[] = $oEntity->getId();
|
||||
}
|
||||
/**
|
||||
* Получаем категории для всех объектов
|
||||
*/
|
||||
$sEntityCategory = $this->_NormalizeEntityRootName('Category');
|
||||
$sEntityTarget = $this->_NormalizeEntityRootName('Target');
|
||||
$aCategories = $this->GetCategoryItemsByFilter(array(
|
||||
'#join' => array(
|
||||
"JOIN " . Config::Get('db.table.category_target') . " category_target ON
|
||||
t.id = category_target.category_id and
|
||||
category_target.target_type = '{$sTargetType}' and
|
||||
category_target.target_id IN ( ?a )
|
||||
" => array($aEntitiesId)
|
||||
),
|
||||
'#select' => array(
|
||||
't.*',
|
||||
'category_target.target_id'
|
||||
),
|
||||
'#index-group' => 'target_id',
|
||||
'#cache' => array(
|
||||
null,
|
||||
array(
|
||||
$sEntityCategory . '_save',
|
||||
$sEntityCategory . '_delete',
|
||||
$sEntityTarget . '_save',
|
||||
$sEntityTarget . '_delete'
|
||||
)
|
||||
)
|
||||
));
|
||||
/**
|
||||
* Собираем данные
|
||||
*/
|
||||
foreach ($aEntityItems as $oEntity) {
|
||||
if (isset($aCategories[$oEntity->_getPrimaryKeyValue()])) {
|
||||
$oEntity->_setData(array('_categories' => $aCategories[$oEntity->_getPrimaryKeyValue()]));
|
||||
} else {
|
||||
$oEntity->_setData(array('_categories' => array()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает дерево категорий
|
||||
*
|
||||
* @param int $sId Type ID
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetCategoriesTreeByType($sId)
|
||||
{
|
||||
$aCategories = $this->LoadTreeOfCategory(array('type_id' => $sId));
|
||||
return ModuleORM::buildTree($aCategories);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает дерево категорий
|
||||
*
|
||||
* @param string $sCode Type code
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetCategoriesTreeByTargetType($sCode)
|
||||
{
|
||||
if ($oType = $this->GetTypeByTargetType($sCode)) {
|
||||
return $this->GetCategoriesTreeByType($oType->getId());
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Валидирует список категория
|
||||
*
|
||||
* @param array $aCategoryId
|
||||
* @param int $iType
|
||||
* @param bool $bReturnObjects
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public function ValidateCategoryArray($aCategoryId, $iType, $bReturnObjects = false)
|
||||
{
|
||||
if (!is_array($aCategoryId)) {
|
||||
return false;
|
||||
}
|
||||
$aIds = array();
|
||||
foreach ($aCategoryId as $iId) {
|
||||
$aIds[] = (int)$iId;
|
||||
}
|
||||
if ($aIds and $aCategories = $this->GetCategoryItemsByFilter(array(
|
||||
'id in' => $aIds,
|
||||
'type_id' => $iType,
|
||||
'#index-from-primary'
|
||||
))
|
||||
) {
|
||||
if ($bReturnObjects) {
|
||||
return $aCategories;
|
||||
} else {
|
||||
return array_keys($aCategories);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохраняет категории для объекта
|
||||
*
|
||||
* @param $oTarget
|
||||
* @param $sTargetType
|
||||
* @param $mCallbackCountTarget
|
||||
*/
|
||||
public function SaveCategories($oTarget, $sTargetType, $mCallbackCountTarget = null)
|
||||
{
|
||||
$aCategoriesId = $oTarget->_getDataOne('_categories_for_save');
|
||||
if (!is_array($aCategoriesId)) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Удаляем текущие связи
|
||||
*/
|
||||
$aCategoryIdChanged = $this->RemoveRelation($oTarget->_getPrimaryKeyValue(), $sTargetType);
|
||||
/**
|
||||
* Создаем
|
||||
*/
|
||||
$this->CreateRelation($aCategoriesId, $oTarget->_getPrimaryKeyValue(), $sTargetType);
|
||||
/**
|
||||
* Полный список категорий, которые затронули изменения
|
||||
*/
|
||||
$aCategoryIdChanged = array_merge($aCategoryIdChanged, $aCategoriesId);
|
||||
/**
|
||||
* Подсчитываем количество новое элементов для каждой категории
|
||||
*/
|
||||
$this->UpdateCountTarget($aCategoryIdChanged, $sTargetType, $mCallbackCountTarget);
|
||||
|
||||
$oTarget->_setData(array('_categories_for_save' => null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет количество элементов у категорий (поле count_target в таблице категорий)
|
||||
*
|
||||
* @param $aCategoryId
|
||||
* @param $sTargetType
|
||||
* @param null $mCallback
|
||||
*/
|
||||
protected function UpdateCountTarget($aCategoryId, $sTargetType, $mCallback = null)
|
||||
{
|
||||
if (!is_array($aCategoryId)) {
|
||||
$aCategoryId = array($aCategoryId);
|
||||
}
|
||||
if (!count($aCategoryId)) {
|
||||
return;
|
||||
}
|
||||
$aCategories = $this->GetCategoryItemsByArrayId($aCategoryId);
|
||||
foreach ($aCategories as $oCategory) {
|
||||
if ($mCallback) {
|
||||
if (is_string($mCallback)) {
|
||||
$mCallback = array($this, $mCallback);
|
||||
}
|
||||
$iCount = call_user_func_array($mCallback, array($oCategory, $sTargetType));
|
||||
} else {
|
||||
$iCount = $this->GetCountItemsByFilter(array('category_id' => $oCategory->getId()),
|
||||
'ModuleCategory_EntityTarget');
|
||||
}
|
||||
$oCategory->setCountTarget($iCount);
|
||||
$oCategory->Update();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет категории у объекта
|
||||
*
|
||||
* @param $oTarget
|
||||
* @param $sTargetType
|
||||
* @param $mCallbackCountTarget
|
||||
*/
|
||||
public function RemoveCategories($oTarget, $sTargetType, $mCallbackCountTarget = null)
|
||||
{
|
||||
$aCategoryIdChanged = $this->RemoveRelation($oTarget->_getPrimaryKeyValue(), $sTargetType);
|
||||
/**
|
||||
* Подсчитываем количество новое элементов для каждой категории
|
||||
*/
|
||||
$this->UpdateCountTarget($aCategoryIdChanged, $sTargetType, $mCallbackCountTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает новую связь конкретного объекта с категориями
|
||||
*
|
||||
* @param array $aCategoryId
|
||||
* @param int $iTargetId
|
||||
* @param int|string $iType type_id или target_type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function CreateRelation($aCategoryId, $iTargetId, $iType)
|
||||
{
|
||||
if (!$aCategoryId or (is_array($aCategoryId) and !count($aCategoryId))) {
|
||||
return false;
|
||||
}
|
||||
if (!is_array($aCategoryId)) {
|
||||
$aCategoryId = array($aCategoryId);
|
||||
}
|
||||
if (is_numeric($iType)) {
|
||||
$oType = $this->GetTypeById($iType);
|
||||
} else {
|
||||
$oType = $this->GetTypeByTargetType($iType);
|
||||
}
|
||||
if (!$oType) {
|
||||
return false;
|
||||
}
|
||||
foreach ($aCategoryId as $iCategoryId) {
|
||||
if (!$this->GetTargetByCategoryIdAndTargetIdAndTypeId($iCategoryId, $iTargetId, $oType->getId())) {
|
||||
$oTarget = Engine::GetEntity('ModuleCategory_EntityTarget');
|
||||
$oTarget->setCategoryId($iCategoryId);
|
||||
$oTarget->setTargetId($iTargetId);
|
||||
$oTarget->setTargetType($oType->getTargetType());
|
||||
$oTarget->setTypeId($oType->getId());
|
||||
$oTarget->Add();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет связь конкретного объекта с категориями
|
||||
*
|
||||
* @param int $iTargetId
|
||||
* @param int|string $iType type_id или target_type
|
||||
*
|
||||
* @return bool|array
|
||||
*/
|
||||
public function RemoveRelation($iTargetId, $iType)
|
||||
{
|
||||
if (!is_numeric($iType)) {
|
||||
if ($oType = $this->GetTypeByTargetType($iType)) {
|
||||
$iType = $oType->getId();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$aRemovedCategory = array();
|
||||
$aTargets = $this->GetTargetItemsByTargetIdAndTypeId($iTargetId, $iType);
|
||||
foreach ($aTargets as $oTarget) {
|
||||
$oTarget->Delete();
|
||||
$aRemovedCategory[] = $oTarget->getCategoryId();
|
||||
}
|
||||
return $aRemovedCategory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список категорий по категории
|
||||
*
|
||||
* @param $oCategory
|
||||
* @param bool $bIncludeChild Возвращать все дочернии категории
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function GetCategoriesIdByCategory($oCategory, $bIncludeChild = false)
|
||||
{
|
||||
if (is_object($oCategory)) {
|
||||
$iCategoryId = $oCategory->getId();
|
||||
} else {
|
||||
$iCategoryId = $oCategory;
|
||||
}
|
||||
$aCategoryId = array($iCategoryId);
|
||||
if ($bIncludeChild) {
|
||||
/**
|
||||
* Сначала получаем полный список категорий текущего типа
|
||||
*/
|
||||
if (!is_object($oCategory)) {
|
||||
$oCategory = $this->GetCategoryById($iCategoryId);
|
||||
}
|
||||
if ($oCategory) {
|
||||
if ($aChildren = $oCategory->getDescendants()) {
|
||||
foreach ($aChildren as $oCategoryChild) {
|
||||
$aCategoryId[] = $oCategoryChild->getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aCategoryId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Пересобирает полные URL дочерних категорий
|
||||
*
|
||||
* @param $oCategoryStart
|
||||
* @param bool $bStart
|
||||
*/
|
||||
public function RebuildCategoryUrlFull($oCategoryStart, $bStart = true)
|
||||
{
|
||||
static $aRebuildIds;
|
||||
if ($bStart) {
|
||||
$aRebuildIds = array();
|
||||
}
|
||||
|
||||
if (is_null($oCategoryStart->getId())) {
|
||||
$aCategories = $this->GetCategoryItemsByFilter(array(
|
||||
'#where' => array('pid is null' => array()),
|
||||
'type_id' => $oCategoryStart->getTypeId()
|
||||
));
|
||||
} else {
|
||||
$aCategories = $this->GetCategoryItemsByFilter(array(
|
||||
'pid' => $oCategoryStart->getId(),
|
||||
'type_id' => $oCategoryStart->getTypeId()
|
||||
));
|
||||
}
|
||||
|
||||
foreach ($aCategories as $oCategory) {
|
||||
if ($oCategory->getId() == $oCategoryStart->getId()) {
|
||||
continue;
|
||||
}
|
||||
if (in_array($oCategory->getId(), $aRebuildIds)) {
|
||||
continue;
|
||||
}
|
||||
$aRebuildIds[] = $oCategory->getId();
|
||||
$oCategory->setUrlFull($oCategoryStart->getUrlFull() . '/' . $oCategory->getUrl());
|
||||
$oCategory->Update();
|
||||
$this->RebuildCategoryUrlFull($oCategory, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список ID таргетов по списку категорий
|
||||
*
|
||||
* @param $aCategoryId
|
||||
* @param $sTargetType
|
||||
* @param $iPage
|
||||
* @param $iPerPage
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetTargetIdsByCategoriesId($aCategoryId, $sTargetType, $iPage, $iPerPage)
|
||||
{
|
||||
if (!is_array($aCategoryId)) {
|
||||
$aCategoryId = array($aCategoryId);
|
||||
}
|
||||
if (!count($aCategoryId)) {
|
||||
return array();
|
||||
}
|
||||
$aTargetItems = $this->GetTargetItemsByFilter(array(
|
||||
'category_id in' => $aCategoryId,
|
||||
'target_type' => $sTargetType,
|
||||
'#page' => array($iPage, $iPerPage),
|
||||
'#index-from' => 'target_id'
|
||||
));
|
||||
return array_keys($aTargetItems['collection']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список ID таргетов по категории
|
||||
*
|
||||
* @param $oCategory
|
||||
* @param $sTargetType
|
||||
* @param $iPage
|
||||
* @param $iPerPage
|
||||
* @param bool $bIncludeChild
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetTargetIdsByCategory($oCategory, $sTargetType, $iPage, $iPerPage, $bIncludeChild = false)
|
||||
{
|
||||
$aCategoryId = $this->GetCategoriesIdByCategory($oCategory, $bIncludeChild);
|
||||
|
||||
return $this->GetTargetIdsByCategoriesId($aCategoryId, $sTargetType, $iPage, $iPerPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает новый тип объекта в БД для категорий
|
||||
*
|
||||
* @param string $sType
|
||||
* @param string $sTitle
|
||||
* @param array $aParams
|
||||
* @param bool $bRewrite
|
||||
*
|
||||
* @return bool|ModuleCategory_EntityType
|
||||
*/
|
||||
public function CreateTargetType($sType, $sTitle, $aParams = array(), $bRewrite = false)
|
||||
{
|
||||
/**
|
||||
* Проверяем есть ли уже такой тип
|
||||
*/
|
||||
if ($oType = $this->GetTypeByTargetType($sType)) {
|
||||
if (!$bRewrite) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$oType = Engine::GetEntity('ModuleCategory_EntityType');
|
||||
$oType->setTargetType($sType);
|
||||
}
|
||||
$oType->setState(self::TARGET_STATE_ACTIVE);
|
||||
$oType->setTitle(htmlspecialchars($sTitle));
|
||||
$oType->setParams($aParams);
|
||||
if ($oType->Save()) {
|
||||
return $oType;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отключает тип объекта для категорий
|
||||
*
|
||||
* @param string $sType
|
||||
* @param int $iState self::TARGET_STATE_NOT_ACTIVE или self::TARGET_STATE_REMOVE
|
||||
*/
|
||||
public function RemoveTargetType($sType, $iState = self::TARGET_STATE_NOT_ACTIVE)
|
||||
{
|
||||
if ($oType = $this->GetTypeByTargetType($sType)) {
|
||||
$oType->setState($iState);
|
||||
$oType->Save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Парсинг текста с учетом конкретной категории
|
||||
*
|
||||
* @param string $sText
|
||||
* @param ModuleCategory_EntityCategory $oCategory
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ParserText($sText, $oCategory)
|
||||
{
|
||||
$this->Text_AddParams(array('oCategory' => $oCategory));
|
||||
$sResult = $this->Text_Parser($sText);
|
||||
$this->Text_RemoveParams(array('oCategory'));
|
||||
return $sResult;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,237 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Поведение, которое необходимо добавлять к сущности (entity) у которой добавляются категории
|
||||
*
|
||||
* @package application.modules.category
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleCategory_BehaviorEntity extends Behavior
|
||||
{
|
||||
/**
|
||||
* Дефолтные параметры
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aParams = array(
|
||||
// Уникальный код
|
||||
'target_type' => '',
|
||||
// Имя инпута (select) на форме, который содержит список категорий
|
||||
'form_field' => 'categories',
|
||||
// Автоматически брать текущую категорию из реквеста
|
||||
'form_fill_current_from_request' => true,
|
||||
// Возможность выбирать несколько категорий
|
||||
'multiple' => false,
|
||||
// Автоматическая валидация категорий (актуально при ORM)
|
||||
'validate_enable' => true,
|
||||
// Поле сущности, в котором хранятся категории. Если null, то используется имя из form_field
|
||||
'validate_field' => null,
|
||||
// Обязательное заполнение категории
|
||||
'validate_require' => false,
|
||||
// Получать значение валидации не из сущности, а из реквеста (используется поле form_field)
|
||||
'validate_from_request' => false,
|
||||
// Минимальное количество категорий, доступное для выбора
|
||||
'validate_min' => 1,
|
||||
// Максимальное количество категорий, доступное для выбора
|
||||
'validate_max' => 5,
|
||||
// Возможность выбрать только те категории, у которых нет дочерних
|
||||
'validate_only_without_children' => false,
|
||||
// Колбек для подсчета количества объектов у категории. Необходим, например, если необходимо учитывать объекты только с определенным статусом (доступен для публикации).
|
||||
// Указывать можно строкой с полным вызовом метода модуля, например, "PluginArticle_Main_GetCountArticle"
|
||||
// В качестве параметров передается список ID категорий и тип
|
||||
'callback_count_target' => null,
|
||||
);
|
||||
/**
|
||||
* Список хуков
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aHooks = array(
|
||||
'validate_after' => 'CallbackValidateAfter',
|
||||
'after_save' => 'CallbackAfterSave',
|
||||
'after_delete' => 'CallbackAfterDelete',
|
||||
);
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*/
|
||||
protected function Init()
|
||||
{
|
||||
parent::Init();
|
||||
if (!$this->getParam('validate_field')) {
|
||||
$this->aParams['validate_field'] = $this->getParam('form_field');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Коллбэк
|
||||
* Выполняется при инициализации сущности
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function CallbackValidateAfter($aParams)
|
||||
{
|
||||
if ($aParams['bResult'] and $this->getParam('validate_enable')) {
|
||||
$aFields = $aParams['aFields'];
|
||||
if (is_null($aFields) or in_array($this->getParam('validate_field'), $aFields)) {
|
||||
$oValidator = $this->Validate_CreateValidator('categories_check', $this,
|
||||
$this->getParam('validate_field'));
|
||||
$oValidator->validateEntity($this->oObject, $aFields);
|
||||
$aParams['bResult'] = !$this->oObject->_hasValidateErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Коллбэк
|
||||
* Выполняется после сохранения сущности
|
||||
*/
|
||||
public function CallbackAfterSave()
|
||||
{
|
||||
$this->Category_SaveCategories($this->oObject, $this->getParam('target_type'),
|
||||
$this->getParam('callback_count_target'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Коллбэк
|
||||
* Выполняется после удаления сущности
|
||||
*/
|
||||
public function CallbackAfterDelete()
|
||||
{
|
||||
$this->Category_RemoveCategories($this->oObject, $this->getParam('target_type'),
|
||||
$this->getParam('callback_count_target'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительный метод для сущности
|
||||
* Запускает валидацию дополнительных полей
|
||||
*
|
||||
* @param $mValue
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function ValidateCategoriesCheck($mValue)
|
||||
{
|
||||
/**
|
||||
* Проверяем тип категрий
|
||||
*/
|
||||
if (!$oTypeCategory = $this->Category_GetTypeByTargetType($this->getParam('target_type'))) {
|
||||
return 'Неверный тип категорий';
|
||||
}
|
||||
|
||||
if ($this->getParam('validate_from_request')) {
|
||||
$mValue = getRequest($this->getParam('form_field'));
|
||||
}
|
||||
/**
|
||||
* Значение может быть числом, массивом, строкой с разделением через запятую
|
||||
*/
|
||||
if (!is_array($mValue)) {
|
||||
if ($this->getParam('multiple')) {
|
||||
$mValue = explode(',', $mValue);
|
||||
} else {
|
||||
$mValue = array($mValue);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Проверяем наличие категорий в БД
|
||||
*/
|
||||
$aCategories = $this->Category_ValidateCategoryArray($mValue, $oTypeCategory->getId(), true);
|
||||
if (!$aCategories) {
|
||||
$aCategories = array();
|
||||
}
|
||||
|
||||
if ($this->getParam('validate_require') and !$aCategories) {
|
||||
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->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 $this->Lang_Get('category.notices.validate_children');
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Сохраняем необходимый список категорий для последующего сохранения в БД
|
||||
*/
|
||||
$this->oObject->_setData(array('_categories_for_save' => array_keys($aCategories)));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список категорий сущности
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCategories()
|
||||
{
|
||||
return $this->Category_GetEntityCategories($this->oObject, $this->getCategoryTargetType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество категорий
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCountCategories()
|
||||
{
|
||||
return count($this->getCategories());
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает одну категорию сущности
|
||||
* Если объект может иметь несколько категорий, то вернется первая
|
||||
*
|
||||
* @return ModuleCategory_EntityCategory|null
|
||||
*/
|
||||
public function getCategory()
|
||||
{
|
||||
$aCategories = $this->getCategories();
|
||||
$oCategory = reset($aCategories);
|
||||
return $oCategory ? $oCategory : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает тип объекта для категорий
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCategoryTargetType()
|
||||
{
|
||||
if ($sType = $this->getParam('target_type')) {
|
||||
return $sType;
|
||||
}
|
||||
/**
|
||||
* Иначе дополнительно смотрим на наличие данного метода у сущности
|
||||
* Это необходимо, если тип вычисляется динамически по какой-то своей логике
|
||||
*/
|
||||
if (func_method_exists($this->oObject, 'getCategoryTargetType', 'public')) {
|
||||
return call_user_func(array($this->oObject, 'getCategoryTargetType'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Поведение, которое необходимо добавлять к ORM модулю сущности у которой добавляются категории
|
||||
*
|
||||
* @package application.modules.category
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleCategory_BehaviorModule extends Behavior
|
||||
{
|
||||
/**
|
||||
* Дефолтные параметры
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aParams = array(
|
||||
'target_type' => '',
|
||||
);
|
||||
/**
|
||||
* Список хуков
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aHooks = array(
|
||||
'module_orm_GetItemsByFilter_after' => array(
|
||||
'CallbackGetItemsByFilterAfter',
|
||||
1000
|
||||
),
|
||||
'module_orm_GetItemsByFilter_before' => array(
|
||||
'CallbackGetItemsByFilterBefore',
|
||||
1000
|
||||
),
|
||||
'module_orm_GetByFilter_before' => array(
|
||||
'CallbackGetItemsByFilterBefore',
|
||||
1000
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Модифицирует фильтр в ORM запросе
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function CallbackGetItemsByFilterAfter($aParams)
|
||||
{
|
||||
$aEntities = $aParams['aEntities'];
|
||||
$aFilter = $aParams['aFilter'];
|
||||
$this->Category_RewriteGetItemsByFilter($aEntities, $aFilter, $this->getParam('target_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Модифицирует результат ORM запроса
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function CallbackGetItemsByFilterBefore($aParams)
|
||||
{
|
||||
$aFilter = $this->Category_RewriteFilter($aParams['aFilter'], $aParams['sEntityFull'],
|
||||
$this->getParam('target_type'));
|
||||
$aParams['aFilter'] = $aFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает дерево категорий
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetCategoriesTree()
|
||||
{
|
||||
return $this->Category_GetCategoriesTreeByTargetType($this->getParam('target_type'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список ID объектов (элементов), которые принадлежат категории
|
||||
*
|
||||
* @param $oCategory
|
||||
* @param $iPage
|
||||
* @param $iPerPage
|
||||
* @param bool $bIncludeChild
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetTargetIdsByCategory($oCategory, $iPage, $iPerPage, $bIncludeChild = false)
|
||||
{
|
||||
return $this->Category_GetTargetIdsByCategory($oCategory, $this->getParam('target_type'), $iPage, $iPerPage,
|
||||
$bIncludeChild);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность категории
|
||||
*
|
||||
* @package application.modules.category
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleCategory_EntityCategory extends EntityORM
|
||||
{
|
||||
|
||||
/**
|
||||
* Определяем правила валидации
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aValidateRules = array(
|
||||
array('title', 'string', 'max' => 200, 'min' => 1, 'allowEmpty' => false),
|
||||
array('description', 'string', 'max' => 5000, 'min' => 1, 'allowEmpty' => true),
|
||||
array('url', 'regexp', 'pattern' => '/^[\w\-_]+$/i', 'allowEmpty' => false),
|
||||
array('order', 'number', 'integerOnly' => true),
|
||||
array('pid', 'parent_category'),
|
||||
array('order', 'order_check'),
|
||||
);
|
||||
|
||||
protected $aRelations = array(
|
||||
'type' => array(self::RELATION_TYPE_BELONGS_TO, 'ModuleCategory_EntityType', 'type_id'),
|
||||
self::RELATION_TYPE_TREE
|
||||
);
|
||||
|
||||
/**
|
||||
* Проверка родительской категории
|
||||
*
|
||||
* @param string $sValue Валидируемое значение
|
||||
* @param array $aParams Параметры
|
||||
* @return bool
|
||||
*/
|
||||
public function ValidateParentCategory($sValue, $aParams)
|
||||
{
|
||||
if ($this->getPid()) {
|
||||
if ($oCategory = $this->Category_GetCategoryById($this->getPid())) {
|
||||
if ($oCategory->getId() == $this->getId()) {
|
||||
return $this->Lang_Get('category.notices.validate_recursion');
|
||||
}
|
||||
if ($oCategory->getTypeId() != $this->getTypeId()) {
|
||||
return $this->Lang_Get('category.notices.validate_parent');
|
||||
}
|
||||
$this->setUrlFull($oCategory->getUrlFull() . '/' . $this->getUrl());
|
||||
} else {
|
||||
return $this->Lang_Get('category.notices.validate_wrong');
|
||||
}
|
||||
} else {
|
||||
$this->setPid(null);
|
||||
$this->setUrlFull($this->getUrl());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Установка дефолтной сортировки
|
||||
*
|
||||
* @param string $sValue Валидируемое значение
|
||||
* @param array $aParams Параметры
|
||||
* @return bool
|
||||
*/
|
||||
public function ValidateOrderCheck($sValue, $aParams)
|
||||
{
|
||||
if (!$this->getSort()) {
|
||||
$this->setSort(100);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется перед удалением
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function beforeDelete()
|
||||
{
|
||||
if ($bResult = parent::beforeDelete()) {
|
||||
/**
|
||||
* Запускаем удаление дочерних категорий
|
||||
*/
|
||||
if ($aCildren = $this->getChildren()) {
|
||||
foreach ($aCildren as $oChildren) {
|
||||
$oChildren->Delete();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Удаляем связь с таргетом
|
||||
*/
|
||||
if ($aTargets = $this->Category_GetTargetItemsByCategoryId($this->getId())) {
|
||||
foreach ($aTargets as $oTarget) {
|
||||
$oTarget->Delete();
|
||||
/**
|
||||
* TODO: Нужно запустить хук, что мы удалили такую-то связь
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Переопределяем имя поля с родителем
|
||||
* Т.к. по дефолту в деревьях используется поле parent_id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function _getTreeParentKey()
|
||||
{
|
||||
return 'pid';
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется перед сохранением
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL категории
|
||||
* Этот метод необходимо переопределить из плагина и возвращать свой URL для нужного типа категорий
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getWebUrl()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект типа категории с использованием кеширования на время сессии
|
||||
*
|
||||
* @return ModuleCategory_EntityType
|
||||
*/
|
||||
public function getTypeByCacheLife()
|
||||
{
|
||||
$sKey = 'category_type_' . (string)$this->getTypeId();
|
||||
if (false === ($oType = $this->Cache_GetLife($sKey))) {
|
||||
$oType = $this->getType();
|
||||
$this->Cache_SetLife($oType, $sKey);
|
||||
}
|
||||
return $oType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL админки для редактирования
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlAdminUpdate()
|
||||
{
|
||||
return Router::GetPath('admin/categories/' . $this->getTypeByCacheLife()->getTargetType() . '/update/' . $this->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL админки для удаления
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlAdminRemove()
|
||||
{
|
||||
return Router::GetPath('admin/categories/' . $this->getTypeByCacheLife()->getTargetType() . '/remove/' . $this->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список дополнительных данных
|
||||
*
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
$aData = @unserialize($this->_getDataOne('data'));
|
||||
if (!$aData) {
|
||||
$aData = array();
|
||||
}
|
||||
return $aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает список дополнительня данных
|
||||
*
|
||||
* @param $aRules
|
||||
*/
|
||||
public function setData($aRules)
|
||||
{
|
||||
$this->_aData['data'] = @serialize($aRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает данные по конкретному ключу
|
||||
*
|
||||
* @param $sKey
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getDataOne($sKey)
|
||||
{
|
||||
$aData = $this->getData();
|
||||
if (isset($aData[$sKey])) {
|
||||
return $aData[$sKey];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанваливает данные для конкретного ключа
|
||||
*
|
||||
* @param $sKey
|
||||
* @param $mValue
|
||||
*/
|
||||
public function setDataOne($sKey, $mValue)
|
||||
{
|
||||
$aData = $this->getData();
|
||||
$aData[$sKey] = $mValue;
|
||||
$this->setData($aData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает сумму значений по ключу для всех потомков, включая себя
|
||||
*
|
||||
* @param $sKey
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getDataOneSumDescendants($sKey)
|
||||
{
|
||||
$iResult = $this->getDataOne($sKey);
|
||||
$aChildren = $this->getDescendants();
|
||||
foreach ($aChildren as $oItem) {
|
||||
$iResult += $oItem->getDataOne($sKey);
|
||||
}
|
||||
return $iResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество таргетов (объектов) для всех потомков, включая себя
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCountTargetOfDescendants()
|
||||
{
|
||||
$iCount = $this->getCountTarget();
|
||||
$aChildren = $this->getDescendants();
|
||||
foreach ($aChildren as $oItem) {
|
||||
$iCount += $oItem->getCountTarget();
|
||||
}
|
||||
return $iCount;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность связи категории с объектами
|
||||
*
|
||||
* @package application.modules.category
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleCategory_EntityTarget extends EntityORM
|
||||
{
|
||||
|
||||
protected $aRelations = array();
|
||||
|
||||
/**
|
||||
* Выполняется перед сохранением
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность типа категории
|
||||
*
|
||||
* @package application.modules.category
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleCategory_EntityType extends EntityORM
|
||||
{
|
||||
|
||||
protected $aRelations = array();
|
||||
|
||||
/**
|
||||
* Выполняется перед сохранением
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
} else {
|
||||
$this->setDateUpdate(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список дополнительных параметров
|
||||
*
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getParams()
|
||||
{
|
||||
$aData = @unserialize($this->_getDataOne('params'));
|
||||
if (!$aData) {
|
||||
$aData = array();
|
||||
}
|
||||
return $aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает список дополнительных параметров
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function setParams($aParams)
|
||||
{
|
||||
$this->_aData['params'] = @serialize($aParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает конкретный параметр
|
||||
*
|
||||
* @param $sName
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getParam($sName)
|
||||
{
|
||||
$aParams = $this->getParams();
|
||||
return isset($aParams[$sName]) ? $aParams[$sName] : null;
|
||||
}
|
||||
}
|
1128
application/classes/modules/comment/Comment.class.php
Normal file
1128
application/classes/modules/comment/Comment.class.php
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,578 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект сущности комментариев
|
||||
*
|
||||
* @package application.modules.comment
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleComment_EntityComment extends Entity
|
||||
{
|
||||
/**
|
||||
* Возвращает ID коммента
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->_getDataOne('comment_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ID родительского коммента
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getPid()
|
||||
{
|
||||
return $this->_getDataOne('comment_pid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает значение left для дерева nested set
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getLeft()
|
||||
{
|
||||
return $this->_getDataOne('comment_left');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает значение right для дерева nested set
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getRight()
|
||||
{
|
||||
return $this->_getDataOne('comment_right');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ID владельца
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getTargetId()
|
||||
{
|
||||
return $this->_getDataOne('target_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает тип владельца
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTargetType()
|
||||
{
|
||||
return $this->_getDataOne('target_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращет ID родителя владельца
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getTargetParentId()
|
||||
{
|
||||
return $this->_getDataOne('target_parent_id') ? $this->_getDataOne('target_parent_id') : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ID пользователя, автора комментария
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->_getDataOne('user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает текст комментария
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getText()
|
||||
{
|
||||
return $this->_getDataOne('comment_text');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает исходный текст комментария
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTextSource()
|
||||
{
|
||||
return $this->_getDataOne('comment_text_source') ? $this->_getDataOne('comment_text_source') : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает дату комментария
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDate()
|
||||
{
|
||||
return $this->_getDataOne('comment_date');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает дату последнего редактирования комментария
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getDateEdit()
|
||||
{
|
||||
return $this->_getDataOne('comment_date_edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает IP пользователя
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getUserIp()
|
||||
{
|
||||
return $this->_getDataOne('comment_user_ip');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает рейтинг комментария
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRating()
|
||||
{
|
||||
return number_format(round($this->_getDataOne('comment_rating'), 2), 0, '.', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество проголосовавших
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCountVote()
|
||||
{
|
||||
return $this->_getDataOne('comment_count_vote');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество редактирований комментария
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCountEdit()
|
||||
{
|
||||
return $this->_getDataOne('comment_count_edit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает флаг удаленного комментария
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getDelete()
|
||||
{
|
||||
return $this->_getDataOne('comment_delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает флаг опубликованного комментария
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPublish()
|
||||
{
|
||||
return $this->_getDataOne('comment_publish') ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает хеш комментария
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTextHash()
|
||||
{
|
||||
return $this->_getDataOne('comment_text_hash');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает уровень вложенности комментария
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getLevel()
|
||||
{
|
||||
return $this->_getDataOne('comment_level');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет является ли комментарий плохим
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isBad()
|
||||
{
|
||||
if ($this->getRating() <= Config::Get('module.comment.bad')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект пользователя
|
||||
*
|
||||
* @return ModuleUser_EntityUser|null
|
||||
*/
|
||||
public function getUser()
|
||||
{
|
||||
return $this->_getDataOne('user');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект владельца
|
||||
*
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getTarget()
|
||||
{
|
||||
return $this->_getDataOne('target');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект голосования
|
||||
*
|
||||
* @return ModuleVote_EntityVote|null
|
||||
*/
|
||||
public function getVote()
|
||||
{
|
||||
return $this->_getDataOne('vote');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет является ли комментарий избранным у текущего пользователя
|
||||
*
|
||||
* @return bool|null
|
||||
*/
|
||||
public function getIsFavourite()
|
||||
{
|
||||
return $this->_getDataOne('comment_is_favourite');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество избранного
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCountFavourite()
|
||||
{
|
||||
return $this->_getDataOne('comment_count_favourite');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на разрешение редактировать комментарий
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function isAllowEdit()
|
||||
{
|
||||
return $this->ACL_IsAllowEditComment($this, $this->User_GetUserCurrent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество секунд в течении которых возможно редактирование
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getEditTimeRemaining()
|
||||
{
|
||||
$oUser = $this->User_GetUserCurrent();
|
||||
if (($oUser and $oUser->isAdministrator()) or !Config::Get('acl.update.comment.limit_time')) {
|
||||
return 0;
|
||||
}
|
||||
$iTime = Config::Get('acl.update.comment.limit_time') - (time() - strtotime($this->getDate()));
|
||||
return $iTime > 0 ? $iTime : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на разрешение удалить комментарий
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function isAllowDelete()
|
||||
{
|
||||
return $this->ACL_IsAllowDeleteComment($this, $this->User_GetUserCurrent());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает ID комментария
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setId($data)
|
||||
{
|
||||
$this->_aData['comment_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID родительского комментария
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setPid($data)
|
||||
{
|
||||
$this->_aData['comment_pid'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает значени left для дерева nested set
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setLeft($data)
|
||||
{
|
||||
$this->_aData['comment_left'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает значени right для дерева nested set
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setRight($data)
|
||||
{
|
||||
$this->_aData['comment_right'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID владельца
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setTargetId($data)
|
||||
{
|
||||
$this->_aData['target_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает тип владельца
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setTargetType($data)
|
||||
{
|
||||
$this->_aData['target_type'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID родителя владельца
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setTargetParentId($data)
|
||||
{
|
||||
$this->_aData['target_parent_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID пользователя
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setUserId($data)
|
||||
{
|
||||
$this->_aData['user_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает текст комментария
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setText($data)
|
||||
{
|
||||
$this->_aData['comment_text'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает исходный текст комментария
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setTextSource($data)
|
||||
{
|
||||
$this->_aData['comment_text_source'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает дату комментария
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setDate($data)
|
||||
{
|
||||
$this->_aData['comment_date'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает дату последнего редактирования комментария
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setDateEdit($data)
|
||||
{
|
||||
$this->_aData['comment_date_edit'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает IP пользователя
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setUserIp($data)
|
||||
{
|
||||
$this->_aData['comment_user_ip'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает рейтинг комментария
|
||||
*
|
||||
* @param float $data
|
||||
*/
|
||||
public function setRating($data)
|
||||
{
|
||||
$this->_aData['comment_rating'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает количество проголосавших
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setCountVote($data)
|
||||
{
|
||||
$this->_aData['comment_count_vote'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает количество редактирований комментария
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setCountEdit($data)
|
||||
{
|
||||
$this->_aData['comment_count_edit'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает флаг удаленности комментария
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setDelete($data)
|
||||
{
|
||||
$this->_aData['comment_delete'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает флаг публикации
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setPublish($data)
|
||||
{
|
||||
$this->_aData['comment_publish'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает хеш комментария
|
||||
*
|
||||
* @param strign $data
|
||||
*/
|
||||
public function setTextHash($data)
|
||||
{
|
||||
$this->_aData['comment_text_hash'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает уровень вложенности комментария
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setLevel($data)
|
||||
{
|
||||
$this->_aData['comment_level'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устаналвает объект пользователя
|
||||
*
|
||||
* @param ModuleUser_EntityUser $data
|
||||
*/
|
||||
public function setUser($data)
|
||||
{
|
||||
$this->_aData['user'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает объект владельца
|
||||
*
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function setTarget($data)
|
||||
{
|
||||
$this->_aData['target'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает объект голосования
|
||||
*
|
||||
* @param ModuleVote_EntityVote $data
|
||||
*/
|
||||
public function setVote($data)
|
||||
{
|
||||
$this->_aData['vote'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает факт нахождения комментария в избранном у текущего пользователя
|
||||
*
|
||||
* @param bool $data
|
||||
*/
|
||||
public function setIsFavourite($data)
|
||||
{
|
||||
$this->_aData['comment_is_favourite'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает количество избранного
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setCountFavourite($data)
|
||||
{
|
||||
$this->_aData['comment_count_favourite'] = $data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект сущности прямого эфира
|
||||
*
|
||||
* @package application.modules.comment
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleComment_EntityCommentOnline extends Entity
|
||||
{
|
||||
/**
|
||||
* Возвращает ID владельца
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getTargetId()
|
||||
{
|
||||
return $this->_getDataOne('target_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает тип владельца
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTargetType()
|
||||
{
|
||||
return $this->_getDataOne('target_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ID комментария
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getCommentId()
|
||||
{
|
||||
return $this->_getDataOne('comment_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ID родителя владельца
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getTargetParentId()
|
||||
{
|
||||
return $this->_getDataOne('target_parent_id') ? $this->_getDataOne('target_parent_id') : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID владельца
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setTargetId($data)
|
||||
{
|
||||
$this->_aData['target_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает тип владельца
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setTargetType($data)
|
||||
{
|
||||
$this->_aData['target_type'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID комментария
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setCommentId($data)
|
||||
{
|
||||
$this->_aData['comment_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID родителя владельца
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setTargetParentId($data)
|
||||
{
|
||||
$this->_aData['target_parent_id'] = $data;
|
||||
}
|
||||
}
|
1031
application/classes/modules/comment/mapper/Comment.mapper.class.php
Normal file
1031
application/classes/modules/comment/mapper/Comment.mapper.class.php
Normal file
File diff suppressed because it is too large
Load diff
534
application/classes/modules/favourite/Favourite.class.php
Normal file
534
application/classes/modules/favourite/Favourite.class.php
Normal file
|
@ -0,0 +1,534 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Модуль для работы с избранным
|
||||
*
|
||||
* @package application.modules.favourite
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleFavourite extends Module
|
||||
{
|
||||
/**
|
||||
* Объект маппера
|
||||
*
|
||||
* @var ModuleFavourite_MapperFavourite
|
||||
*/
|
||||
protected $oMapper;
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
$this->oMapper = Engine::GetMapper(__CLASS__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает информацию о том, найден ли таргет в избранном или нет
|
||||
*
|
||||
* @param int $sTargetId ID владельца
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $sUserId ID пользователя
|
||||
* @return ModuleFavourite_EntityFavourite|null
|
||||
*/
|
||||
public function GetFavourite($sTargetId, $sTargetType, $sUserId)
|
||||
{
|
||||
if (!is_numeric($sTargetId) or !is_string($sTargetType)) {
|
||||
return null;
|
||||
}
|
||||
$data = $this->GetFavouritesByArray($sTargetId, $sTargetType, $sUserId);
|
||||
return (isset($data[$sTargetId]))
|
||||
? $data[$sTargetId]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить список избранного по списку айдишников
|
||||
*
|
||||
* @param array $aTargetId Список ID владельцев
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $sUserId ID пользователя
|
||||
* @return array
|
||||
*/
|
||||
public function GetFavouritesByArray($aTargetId, $sTargetType, $sUserId)
|
||||
{
|
||||
if (!$aTargetId) {
|
||||
return array();
|
||||
}
|
||||
if (Config::Get('sys.cache.solid')) {
|
||||
return $this->GetFavouritesByArraySolid($aTargetId, $sTargetType, $sUserId);
|
||||
}
|
||||
if (!is_array($aTargetId)) {
|
||||
$aTargetId = array($aTargetId);
|
||||
}
|
||||
$aTargetId = array_unique($aTargetId);
|
||||
$aFavourite = array();
|
||||
$aIdNotNeedQuery = array();
|
||||
/**
|
||||
* Делаем мульти-запрос к кешу
|
||||
*/
|
||||
$aCacheKeys = func_build_cache_keys($aTargetId, "favourite_{$sTargetType}_", '_' . $sUserId);
|
||||
if (false !== ($data = $this->Cache_Get($aCacheKeys))) {
|
||||
/**
|
||||
* проверяем что досталось из кеша
|
||||
*/
|
||||
foreach ($aCacheKeys as $sValue => $sKey) {
|
||||
if (array_key_exists($sKey, $data)) {
|
||||
if ($data[$sKey]) {
|
||||
$aFavourite[$data[$sKey]->getTargetId()] = $data[$sKey];
|
||||
} else {
|
||||
$aIdNotNeedQuery[] = $sValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Смотрим чего не было в кеше и делаем запрос в БД
|
||||
*/
|
||||
$aIdNeedQuery = array_diff($aTargetId, array_keys($aFavourite));
|
||||
$aIdNeedQuery = array_diff($aIdNeedQuery, $aIdNotNeedQuery);
|
||||
$aIdNeedStore = $aIdNeedQuery;
|
||||
if ($data = $this->oMapper->GetFavouritesByArray($aIdNeedQuery, $sTargetType, $sUserId)) {
|
||||
foreach ($data as $oFavourite) {
|
||||
/**
|
||||
* Добавляем к результату и сохраняем в кеш
|
||||
*/
|
||||
$aFavourite[$oFavourite->getTargetId()] = $oFavourite;
|
||||
$this->Cache_Set($oFavourite,
|
||||
"favourite_{$oFavourite->getTargetType()}_{$oFavourite->getTargetId()}_{$sUserId}", array(),
|
||||
60 * 60 * 24 * 7);
|
||||
$aIdNeedStore = array_diff($aIdNeedStore, array($oFavourite->getTargetId()));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Сохраняем в кеш запросы не вернувшие результата
|
||||
*/
|
||||
foreach ($aIdNeedStore as $sId) {
|
||||
$this->Cache_Set(null, "favourite_{$sTargetType}_{$sId}_{$sUserId}", array(), 60 * 60 * 24 * 7);
|
||||
}
|
||||
/**
|
||||
* Сортируем результат согласно входящему массиву
|
||||
*/
|
||||
$aFavourite = func_array_sort_by_keys($aFavourite, $aTargetId);
|
||||
return $aFavourite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить список избранного по списку айдишников, но используя единый кеш
|
||||
*
|
||||
* @param array $aTargetId Список ID владельцев
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $sUserId ID пользователя
|
||||
* @return array
|
||||
*/
|
||||
public function GetFavouritesByArraySolid($aTargetId, $sTargetType, $sUserId)
|
||||
{
|
||||
if (!is_array($aTargetId)) {
|
||||
$aTargetId = array($aTargetId);
|
||||
}
|
||||
$aTargetId = array_unique($aTargetId);
|
||||
$aFavourites = array();
|
||||
$s = join(',', $aTargetId);
|
||||
if (false === ($data = $this->Cache_Get("favourite_{$sTargetType}_{$sUserId}_id_{$s}"))) {
|
||||
$data = $this->oMapper->GetFavouritesByArray($aTargetId, $sTargetType, $sUserId);
|
||||
foreach ($data as $oFavourite) {
|
||||
$aFavourites[$oFavourite->getTargetId()] = $oFavourite;
|
||||
}
|
||||
$this->Cache_Set($aFavourites, "favourite_{$sTargetType}_{$sUserId}_id_{$s}",
|
||||
array("favourite_{$sTargetType}_change_user_{$sUserId}"), 60 * 60 * 24 * 1);
|
||||
return $aFavourites;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список таргетов из избранного
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @param array $aExcludeTarget Список ID владельцев для исклчения
|
||||
* @return array
|
||||
*/
|
||||
public function GetFavouritesByUserId($sUserId, $sTargetType, $iCurrPage, $iPerPage, $aExcludeTarget = array())
|
||||
{
|
||||
$s = serialize($aExcludeTarget);
|
||||
if (false === ($data = $this->Cache_Get("{$sTargetType}_favourite_user_{$sUserId}_{$iCurrPage}_{$iPerPage}_{$s}"))) {
|
||||
$data = array(
|
||||
'collection' => $this->oMapper->GetFavouritesByUserId($sUserId, $sTargetType, $iCount, $iCurrPage,
|
||||
$iPerPage, $aExcludeTarget),
|
||||
'count' => $iCount
|
||||
);
|
||||
$this->Cache_Set(
|
||||
$data,
|
||||
"{$sTargetType}_favourite_user_{$sUserId}_{$iCurrPage}_{$iPerPage}_{$s}",
|
||||
array(
|
||||
"favourite_{$sTargetType}_change",
|
||||
"favourite_{$sTargetType}_change_user_{$sUserId}"
|
||||
),
|
||||
60 * 60 * 24 * 1
|
||||
);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает число таргетов определенного типа в избранном по ID пользователя
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param array $aExcludeTarget Список ID владельцев для исклчения
|
||||
* @return array
|
||||
*/
|
||||
public function GetCountFavouritesByUserId($sUserId, $sTargetType, $aExcludeTarget = array())
|
||||
{
|
||||
$s = serialize($aExcludeTarget);
|
||||
if (false === ($data = $this->Cache_Get("{$sTargetType}_count_favourite_user_{$sUserId}_{$s}"))) {
|
||||
$data = $this->oMapper->GetCountFavouritesByUserId($sUserId, $sTargetType, $aExcludeTarget);
|
||||
$this->Cache_Set(
|
||||
$data,
|
||||
"{$sTargetType}_count_favourite_user_{$sUserId}_{$s}",
|
||||
array(
|
||||
"favourite_{$sTargetType}_change",
|
||||
"favourite_{$sTargetType}_change_user_{$sUserId}"
|
||||
),
|
||||
60 * 60 * 24 * 1
|
||||
);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список комментариев к записям открытых блогов
|
||||
* из избранного указанного пользователя
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetFavouriteOpenCommentsByUserId($sUserId, $iCurrPage, $iPerPage)
|
||||
{
|
||||
if (false === ($data = $this->Cache_Get("comment_favourite_user_{$sUserId}_{$iCurrPage}_{$iPerPage}_open"))) {
|
||||
$data = array(
|
||||
'collection' => $this->oMapper->GetFavouriteOpenCommentsByUserId($sUserId, $iCount, $iCurrPage,
|
||||
$iPerPage),
|
||||
'count' => $iCount
|
||||
);
|
||||
$this->Cache_Set(
|
||||
$data,
|
||||
"comment_favourite_user_{$sUserId}_{$iCurrPage}_{$iPerPage}_open",
|
||||
array(
|
||||
"favourite_comment_change",
|
||||
"favourite_comment_change_user_{$sUserId}"
|
||||
),
|
||||
60 * 60 * 24 * 1
|
||||
);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает число комментариев к открытым блогам в избранном по ID пользователя
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @return array
|
||||
*/
|
||||
public function GetCountFavouriteOpenCommentsByUserId($sUserId)
|
||||
{
|
||||
if (false === ($data = $this->Cache_Get("comment_count_favourite_user_{$sUserId}_open"))) {
|
||||
$data = $this->oMapper->GetCountFavouriteOpenCommentsByUserId($sUserId);
|
||||
$this->Cache_Set(
|
||||
$data,
|
||||
"comment_count_favourite_user_{$sUserId}_open",
|
||||
array(
|
||||
"favourite_comment_change",
|
||||
"favourite_comment_change_user_{$sUserId}"
|
||||
),
|
||||
60 * 60 * 24 * 1
|
||||
);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список топиков из открытых блогов
|
||||
* из избранного указанного пользователя
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetFavouriteOpenTopicsByUserId($sUserId, $iCurrPage, $iPerPage)
|
||||
{
|
||||
if (false === ($data = $this->Cache_Get("topic_favourite_user_{$sUserId}_{$iCurrPage}_{$iPerPage}_open"))) {
|
||||
$data = array(
|
||||
'collection' => $this->oMapper->GetFavouriteOpenTopicsByUserId($sUserId, $iCount, $iCurrPage,
|
||||
$iPerPage),
|
||||
'count' => $iCount
|
||||
);
|
||||
$this->Cache_Set(
|
||||
$data,
|
||||
"topic_favourite_user_{$sUserId}_{$iCurrPage}_{$iPerPage}_open",
|
||||
array(
|
||||
"favourite_topic_change",
|
||||
"favourite_topic_change_user_{$sUserId}"
|
||||
),
|
||||
60 * 60 * 24 * 1
|
||||
);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает число топиков в открытых блогах из избранного по ID пользователя
|
||||
*
|
||||
* @param string $sUserId ID пользователя
|
||||
* @return array
|
||||
*/
|
||||
public function GetCountFavouriteOpenTopicsByUserId($sUserId)
|
||||
{
|
||||
if (false === ($data = $this->Cache_Get("topic_count_favourite_user_{$sUserId}_open"))) {
|
||||
$data = $this->oMapper->GetCountFavouriteOpenTopicsByUserId($sUserId);
|
||||
$this->Cache_Set(
|
||||
$data,
|
||||
"topic_count_favourite_user_{$sUserId}_open",
|
||||
array(
|
||||
"favourite_topic_change",
|
||||
"favourite_topic_change_user_{$sUserId}"
|
||||
),
|
||||
60 * 60 * 24 * 1
|
||||
);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет таргет в избранное
|
||||
*
|
||||
* @param ModuleFavourite_EntityFavourite $oFavourite Объект избранного
|
||||
* @return bool
|
||||
*/
|
||||
public function AddFavourite(ModuleFavourite_EntityFavourite $oFavourite)
|
||||
{
|
||||
if (!$oFavourite->getTags()) {
|
||||
$oFavourite->setTags('');
|
||||
}
|
||||
$this->SetFavouriteTags($oFavourite);
|
||||
//чистим зависимые кеши
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG,
|
||||
array("favourite_{$oFavourite->getTargetType()}_change_user_{$oFavourite->getUserId()}"));
|
||||
$this->Cache_Delete("favourite_{$oFavourite->getTargetType()}_{$oFavourite->getTargetId()}_{$oFavourite->getUserId()}");
|
||||
return $this->oMapper->AddFavourite($oFavourite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет запись об избранном
|
||||
*
|
||||
* @param ModuleFavourite_EntityFavourite $oFavourite Объект избранного
|
||||
* @return bool
|
||||
*/
|
||||
public function UpdateFavourite(ModuleFavourite_EntityFavourite $oFavourite)
|
||||
{
|
||||
if (!$oFavourite->getTags()) {
|
||||
$oFavourite->setTags('');
|
||||
}
|
||||
$this->SetFavouriteTags($oFavourite);
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG,
|
||||
array("favourite_{$oFavourite->getTargetType()}_change_user_{$oFavourite->getUserId()}"));
|
||||
$this->Cache_Delete("favourite_{$oFavourite->getTargetType()}_{$oFavourite->getTargetId()}_{$oFavourite->getUserId()}");
|
||||
return $this->oMapper->UpdateFavourite($oFavourite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает список тегов для избранного
|
||||
*
|
||||
* @param ModuleFavourite_EntityFavourite $oFavourite Объект избранного
|
||||
* @param bool $bAddNew Добавлять новые теги или нет
|
||||
*/
|
||||
public function SetFavouriteTags($oFavourite, $bAddNew = true)
|
||||
{
|
||||
/**
|
||||
* Удаляем все теги
|
||||
*/
|
||||
$this->oMapper->DeleteTags($oFavourite);
|
||||
/**
|
||||
* Добавляем новые
|
||||
*/
|
||||
if ($bAddNew) {
|
||||
/**
|
||||
* Добавляем теги объекта избранного, если есть
|
||||
*/
|
||||
if ($aTags = $this->GetTagsTarget($oFavourite->getTargetType(), $oFavourite->getTargetId())) {
|
||||
foreach ($aTags as $sTag) {
|
||||
$oTag = Engine::GetEntity('ModuleFavourite_EntityTag', $oFavourite->_getData());
|
||||
$oTag->setText(htmlspecialchars($sTag));
|
||||
$oTag->setIsUser(0);
|
||||
$this->oMapper->AddTag($oTag);
|
||||
}
|
||||
}
|
||||
if ($oFavourite->getTags()) {
|
||||
/**
|
||||
* Добавляем пользовательские теги
|
||||
*/
|
||||
$aTags = $oFavourite->getTagsArray();
|
||||
foreach ($aTags as $sTag) {
|
||||
$oTag = Engine::GetEntity('ModuleFavourite_EntityTag', $oFavourite->_getData());
|
||||
$oTag->setText($sTag); // htmlspecialchars уже используется при установке тегов
|
||||
$oTag->setIsUser(1);
|
||||
$this->oMapper->AddTag($oTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет таргет из избранного
|
||||
*
|
||||
* @param ModuleFavourite_EntityFavourite $oFavourite Объект избранного
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteFavourite(ModuleFavourite_EntityFavourite $oFavourite)
|
||||
{
|
||||
$this->SetFavouriteTags($oFavourite, false);
|
||||
//чистим зависимые кеши
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG,
|
||||
array("favourite_{$oFavourite->getTargetType()}_change_user_{$oFavourite->getUserId()}"));
|
||||
$this->Cache_Delete("favourite_{$oFavourite->getTargetType()}_{$oFavourite->getTargetId()}_{$oFavourite->getUserId()}");
|
||||
return $this->oMapper->DeleteFavourite($oFavourite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Меняет параметры публикации у таргета
|
||||
*
|
||||
* @param array|int $aTargetId Список ID владельцев
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iPublish Флаг публикации
|
||||
* @return bool
|
||||
*/
|
||||
public function SetFavouriteTargetPublish($aTargetId, $sTargetType, $iPublish)
|
||||
{
|
||||
if (!is_array($aTargetId)) {
|
||||
$aTargetId = array($aTargetId);
|
||||
}
|
||||
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array("favourite_{$sTargetType}_change"));
|
||||
return $this->oMapper->SetFavouriteTargetPublish($aTargetId, $sTargetType, $iPublish);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет избранное по списку идентификаторов таргетов
|
||||
*
|
||||
* @param array|int $aTargetId Список ID владельцев
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteFavouriteByTargetId($aTargetId, $sTargetType)
|
||||
{
|
||||
if (!is_array($aTargetId)) {
|
||||
$aTargetId = array($aTargetId);
|
||||
}
|
||||
/**
|
||||
* Чистим зависимые кеши
|
||||
*/
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array("favourite_{$sTargetType}_change"));
|
||||
$this->DeleteTagByTarget($aTargetId, $sTargetType);
|
||||
return $this->oMapper->DeleteFavouriteByTargetId($aTargetId, $sTargetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление тегов по таргету
|
||||
*
|
||||
* @param array $aTargetId Список ID владельцев
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteTagByTarget($aTargetId, $sTargetType)
|
||||
{
|
||||
return $this->oMapper->DeleteTagByTarget($aTargetId, $sTargetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список тегов для объекта избранного
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return bool|array
|
||||
*/
|
||||
public function GetTagsTarget($sTargetType, $iTargetId)
|
||||
{
|
||||
$sMethod = 'GetTagsTarget' . func_camelize($sTargetType);
|
||||
if (method_exists($this, $sMethod)) {
|
||||
return $this->$sMethod($iTargetId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает наиболее часто используемые теги
|
||||
*
|
||||
* @param int $iUserId ID пользователя
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param bool $bIsUser Возвращает все теги ли только пользовательские
|
||||
* @param int $iLimit Количество элементов
|
||||
* @return array
|
||||
*/
|
||||
public function GetGroupTags($iUserId, $sTargetType, $bIsUser, $iLimit)
|
||||
{
|
||||
return $this->oMapper->GetGroupTags($iUserId, $sTargetType, $bIsUser, $iLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список тегов по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param array $aOrder Сортировка
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array('collection'=>array,'count'=>int)
|
||||
*/
|
||||
public function GetTags($aFilter, $aOrder, $iCurrPage, $iPerPage)
|
||||
{
|
||||
return array(
|
||||
'collection' => $this->oMapper->GetTags($aFilter, $aOrder, $iCount, $iCurrPage, $iPerPage),
|
||||
'count' => $iCount
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список тегов для топика, название метода формируется автоматически из GetTagsTarget()
|
||||
* @see GetTagsTarget
|
||||
*
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return bool|array
|
||||
*/
|
||||
public function GetTagsTargetTopic($iTargetId)
|
||||
{
|
||||
if ($oTopic = $this->Topic_GetTopicById($iTargetId)) {
|
||||
return $oTopic->getTagsArray();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект сущности избрнного
|
||||
*
|
||||
* @package application.modules.favourite
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleFavourite_EntityFavourite extends Entity
|
||||
{
|
||||
/**
|
||||
* Возвращает ID владельца
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getTargetId()
|
||||
{
|
||||
return $this->_getDataOne('target_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает ID пользователя
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getUserId()
|
||||
{
|
||||
return $this->_getDataOne('user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает флаг публикации владельца
|
||||
*
|
||||
* @return int|null
|
||||
*/
|
||||
public function getTargetPublish()
|
||||
{
|
||||
return $this->_getDataOne('target_publish');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает тип владельца
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getTargetType()
|
||||
{
|
||||
return $this->_getDataOne('target_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возващает список тегов
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTagsArray()
|
||||
{
|
||||
if ($this->getTags()) {
|
||||
return explode(',', $this->getTags());
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает массив тегов в виде объектов
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getTagsObjects()
|
||||
{
|
||||
$aReturn = array();
|
||||
if ($aTags = $this->getTagsArray()) {
|
||||
foreach ($aTags as $sTag) {
|
||||
if ($sTag) {
|
||||
$aReturn[] = Engine::GetEntity('ModuleFavourite_EntityTag', array(
|
||||
'target_type' => $this->getTargetType(),
|
||||
'target_id' => $this->getTargetId(),
|
||||
'user_id' => $this->getUserId(),
|
||||
'text' => $sTag,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID владельца
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setTargetId($data)
|
||||
{
|
||||
$this->_aData['target_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ID пользователя
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setUserId($data)
|
||||
{
|
||||
$this->_aData['user_id'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает статус публикации для владельца
|
||||
*
|
||||
* @param int $data
|
||||
*/
|
||||
public function setTargetPublish($data)
|
||||
{
|
||||
$this->_aData['target_publish'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает тип владельца
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setTargetType($data)
|
||||
{
|
||||
$this->_aData['target_type'] = $data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект сущности тега для избранного
|
||||
*
|
||||
* @package application.modules.favourite
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleFavourite_EntityTag extends Entity
|
||||
{
|
||||
/**
|
||||
* Возвращает URL страницы тега
|
||||
* todo: на странице списка топиков получение пользователя может стать узким местом
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
$_this = $this;
|
||||
$oUser = $this->Cache_Remember("favourite_tag_user_{$this->getUserId()}",
|
||||
function () use ($_this) {
|
||||
return $_this->User_GetUserById($_this->getUserId());
|
||||
}, false, array(), 'life', true);
|
||||
|
||||
if ($oUser) {
|
||||
return $oUser->getUserWebPath() . 'favourites/topics/tag/' . urlencode($this->getText()) . '/';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,596 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект маппера для работы с БД
|
||||
*
|
||||
* @package application.modules.favourite
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleFavourite_MapperFavourite extends Mapper
|
||||
{
|
||||
/**
|
||||
* Добавляет таргет в избранное
|
||||
*
|
||||
* @param ModuleFavourite_EntityFavourite $oFavourite Объект избранного
|
||||
* @return bool
|
||||
*/
|
||||
public function AddFavourite(ModuleFavourite_EntityFavourite $oFavourite)
|
||||
{
|
||||
$sql = "
|
||||
INSERT INTO " . Config::Get('db.table.favourite') . "
|
||||
( target_id, target_type, user_id, tags )
|
||||
VALUES
|
||||
(?d, ?, ?d, ?)
|
||||
";
|
||||
if ($this->oDb->query(
|
||||
$sql,
|
||||
$oFavourite->getTargetId(),
|
||||
$oFavourite->getTargetType(),
|
||||
$oFavourite->getUserId(),
|
||||
$oFavourite->getTags()
|
||||
) === 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновляет запись об избранном
|
||||
*
|
||||
* @param ModuleFavourite_EntityFavourite $oFavourite Объект избранного
|
||||
* @return bool
|
||||
*/
|
||||
public function UpdateFavourite(ModuleFavourite_EntityFavourite $oFavourite)
|
||||
{
|
||||
$sql = "
|
||||
UPDATE " . Config::Get('db.table.favourite') . "
|
||||
SET tags = ? WHERE user_id = ?d and target_id = ?d and target_type = ?
|
||||
";
|
||||
if ($this->oDb->query(
|
||||
$sql,
|
||||
$oFavourite->getTags(),
|
||||
$oFavourite->getUserId(),
|
||||
$oFavourite->getTargetId(),
|
||||
$oFavourite->getTargetType()
|
||||
) !== false
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить список избранного по списку айдишников
|
||||
*
|
||||
* @param array $aArrayId Список ID владельцев
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $sUserId ID пользователя
|
||||
* @return array
|
||||
*/
|
||||
public function GetFavouritesByArray($aArrayId, $sTargetType, $sUserId)
|
||||
{
|
||||
if (!is_array($aArrayId) or count($aArrayId) == 0) {
|
||||
return array();
|
||||
}
|
||||
$sql = "SELECT *
|
||||
FROM " . Config::Get('db.table.favourite') . "
|
||||
WHERE
|
||||
user_id = ?d
|
||||
AND
|
||||
target_id IN(?a)
|
||||
AND
|
||||
target_type = ? ";
|
||||
$aFavourites = array();
|
||||
if ($aRows = $this->oDb->select($sql, $sUserId, $aArrayId, $sTargetType)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aFavourites[] = Engine::GetEntity('Favourite', $aRow);
|
||||
}
|
||||
}
|
||||
return $aFavourites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет таргет из избранного
|
||||
*
|
||||
* @param ModuleFavourite_EntityFavourite $oFavourite Объект избранного
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteFavourite(ModuleFavourite_EntityFavourite $oFavourite)
|
||||
{
|
||||
$sql = "
|
||||
DELETE FROM " . Config::Get('db.table.favourite') . "
|
||||
WHERE
|
||||
user_id = ?d
|
||||
AND
|
||||
target_id = ?d
|
||||
AND
|
||||
target_type = ?
|
||||
";
|
||||
$res = $this->oDb->query(
|
||||
$sql,
|
||||
$oFavourite->getUserId(),
|
||||
$oFavourite->getTargetId(),
|
||||
$oFavourite->getTargetType()
|
||||
);
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет теги
|
||||
*
|
||||
* @param ModuleFavourite_EntityFavourite $oFavourite Объект избранного
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteTags($oFavourite)
|
||||
{
|
||||
$sql = "
|
||||
DELETE FROM " . Config::Get('db.table.favourite_tag') . "
|
||||
WHERE
|
||||
user_id = ?d
|
||||
AND
|
||||
target_type = ?
|
||||
AND
|
||||
target_id = ?d
|
||||
";
|
||||
$res = $this->oDb->query(
|
||||
$sql,
|
||||
$oFavourite->getUserId(),
|
||||
$oFavourite->getTargetType(),
|
||||
$oFavourite->getTargetId()
|
||||
);
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет тег
|
||||
*
|
||||
* @param ModuleFavourite_EntityTag $oTag Объект тега
|
||||
* @return bool
|
||||
*/
|
||||
public function AddTag($oTag)
|
||||
{
|
||||
$sql = "
|
||||
INSERT INTO " . Config::Get('db.table.favourite_tag') . "
|
||||
SET target_id = ?d, target_type = ?, user_id = ?d, is_user = ?d, text =?
|
||||
";
|
||||
if ($this->oDb->query(
|
||||
$sql,
|
||||
$oTag->getTargetId(),
|
||||
$oTag->getTargetType(),
|
||||
$oTag->getUserId(),
|
||||
$oTag->getIsUser(),
|
||||
$oTag->getText()
|
||||
) === 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Меняет параметры публикации у таргета
|
||||
*
|
||||
* @param array|int $aTargetId Список ID владельцев
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iPublish Флаг публикации
|
||||
* @return bool
|
||||
*/
|
||||
public function SetFavouriteTargetPublish($aTargetId, $sTargetType, $iPublish)
|
||||
{
|
||||
$sql = "
|
||||
UPDATE " . Config::Get('db.table.favourite') . "
|
||||
SET
|
||||
target_publish = ?d
|
||||
WHERE
|
||||
target_id IN(?a)
|
||||
AND
|
||||
target_type = ?
|
||||
";
|
||||
$res = $this->oDb->query($sql, $iPublish, $aTargetId, $sTargetType);
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список таргетов из избранного
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iCount Возвращает количество элементов
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @param array $aExcludeTarget Список ID владельцев для исклчения
|
||||
* @return array
|
||||
*/
|
||||
public function GetFavouritesByUserId(
|
||||
$sUserId,
|
||||
$sTargetType,
|
||||
&$iCount,
|
||||
$iCurrPage,
|
||||
$iPerPage,
|
||||
$aExcludeTarget = array()
|
||||
) {
|
||||
$sql = "
|
||||
SELECT target_id
|
||||
FROM " . Config::Get('db.table.favourite') . "
|
||||
WHERE
|
||||
user_id = ?
|
||||
AND
|
||||
target_publish = 1
|
||||
AND
|
||||
target_type = ?
|
||||
{ AND target_id NOT IN (?a) }
|
||||
ORDER BY target_id DESC
|
||||
LIMIT ?d, ?d ";
|
||||
|
||||
$aFavourites = array();
|
||||
if ($aRows = $this->oDb->selectPage(
|
||||
$iCount,
|
||||
$sql,
|
||||
$sUserId,
|
||||
$sTargetType,
|
||||
(count($aExcludeTarget) ? $aExcludeTarget : DBSIMPLE_SKIP),
|
||||
($iCurrPage - 1) * $iPerPage,
|
||||
$iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aFavourite) {
|
||||
$aFavourites[] = $aFavourite['target_id'];
|
||||
}
|
||||
}
|
||||
return $aFavourites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает число таргетов определенного типа в избранном по ID пользователя
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param array $aExcludeTarget Список ID владельцев для исклчения
|
||||
* @return array
|
||||
*/
|
||||
public function GetCountFavouritesByUserId($sUserId, $sTargetType, $aExcludeTarget)
|
||||
{
|
||||
$sql = "SELECT
|
||||
count(target_id) as count
|
||||
FROM
|
||||
" . Config::Get('db.table.favourite') . "
|
||||
WHERE
|
||||
user_id = ?
|
||||
AND
|
||||
target_publish = 1
|
||||
AND
|
||||
target_type = ?
|
||||
{ AND target_id NOT IN (?a) }
|
||||
;";
|
||||
return ($aRow = $this->oDb->selectRow(
|
||||
$sql, $sUserId,
|
||||
$sTargetType,
|
||||
(count($aExcludeTarget) ? $aExcludeTarget : DBSIMPLE_SKIP)
|
||||
)
|
||||
)
|
||||
? $aRow['count']
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список комментариев к записям открытых блогов
|
||||
* из избранного указанного пользователя
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param int $iCount Возвращает количество элементов
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetFavouriteOpenCommentsByUserId($sUserId, &$iCount, $iCurrPage, $iPerPage)
|
||||
{
|
||||
$sql = "
|
||||
SELECT f.target_id
|
||||
FROM
|
||||
" . Config::Get('db.table.favourite') . " AS f,
|
||||
" . Config::Get('db.table.comment') . " AS c,
|
||||
" . Config::Get('db.table.topic') . " AS t,
|
||||
" . Config::Get('db.table.blog') . " AS b
|
||||
WHERE
|
||||
f.user_id = ?d
|
||||
AND
|
||||
f.target_publish = 1
|
||||
AND
|
||||
f.target_type = 'comment'
|
||||
AND
|
||||
f.target_id = c.comment_id
|
||||
AND
|
||||
c.target_id = t.topic_id
|
||||
AND
|
||||
t.blog_id = b.blog_id
|
||||
AND
|
||||
b.blog_type IN ('open', 'personal')
|
||||
ORDER BY target_id DESC
|
||||
LIMIT ?d, ?d ";
|
||||
|
||||
$aFavourites = array();
|
||||
if ($aRows = $this->oDb->selectPage(
|
||||
$iCount, $sql, $sUserId,
|
||||
($iCurrPage - 1) * $iPerPage, $iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aFavourite) {
|
||||
$aFavourites[] = $aFavourite['target_id'];
|
||||
}
|
||||
}
|
||||
return $aFavourites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает число комментариев к открытым блогам в избранном по ID пользователя
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @return array
|
||||
*/
|
||||
public function GetCountFavouriteOpenCommentsByUserId($sUserId)
|
||||
{
|
||||
$sql = "SELECT
|
||||
count(f.target_id) as count
|
||||
FROM
|
||||
" . Config::Get('db.table.favourite') . " AS f,
|
||||
" . Config::Get('db.table.comment') . " AS c,
|
||||
" . Config::Get('db.table.topic') . " AS t,
|
||||
" . Config::Get('db.table.blog') . " AS b
|
||||
WHERE
|
||||
f.user_id = ?d
|
||||
AND
|
||||
f.target_publish = 1
|
||||
AND
|
||||
f.target_type = 'comment'
|
||||
AND
|
||||
f.target_id = c.comment_id
|
||||
AND
|
||||
c.target_id = t.topic_id
|
||||
AND
|
||||
t.blog_id = b.blog_id
|
||||
AND
|
||||
b.blog_type IN ('open', 'personal')
|
||||
;";
|
||||
return ($aRow = $this->oDb->selectRow($sql, $sUserId))
|
||||
? $aRow['count']
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает список топиков из открытых блогов
|
||||
* из избранного указанного пользователя
|
||||
*
|
||||
* @param int $sUserId ID пользователя
|
||||
* @param int $iCount Возвращает количество элементов
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetFavouriteOpenTopicsByUserId($sUserId, &$iCount, $iCurrPage, $iPerPage)
|
||||
{
|
||||
$sql = "
|
||||
SELECT f.target_id
|
||||
FROM
|
||||
" . Config::Get('db.table.favourite') . " AS f,
|
||||
" . Config::Get('db.table.topic') . " AS t,
|
||||
" . Config::Get('db.table.blog') . " AS b
|
||||
WHERE
|
||||
f.user_id = ?d
|
||||
AND
|
||||
f.target_publish = 1
|
||||
AND
|
||||
f.target_type = 'topic'
|
||||
AND
|
||||
f.target_id = t.topic_id
|
||||
AND
|
||||
t.blog_id = b.blog_id
|
||||
AND
|
||||
b.blog_type IN ('open', 'personal')
|
||||
ORDER BY target_id DESC
|
||||
LIMIT ?d, ?d ";
|
||||
|
||||
$aFavourites = array();
|
||||
if ($aRows = $this->oDb->selectPage(
|
||||
$iCount, $sql, $sUserId,
|
||||
($iCurrPage - 1) * $iPerPage, $iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aFavourite) {
|
||||
$aFavourites[] = $aFavourite['target_id'];
|
||||
}
|
||||
}
|
||||
return $aFavourites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает число топиков в открытых блогах из избранного по ID пользователя
|
||||
*
|
||||
* @param string $sUserId ID пользователя
|
||||
* @return array
|
||||
*/
|
||||
public function GetCountFavouriteOpenTopicsByUserId($sUserId)
|
||||
{
|
||||
$sql = "SELECT
|
||||
count(f.target_id) as count
|
||||
FROM
|
||||
" . Config::Get('db.table.favourite') . " AS f,
|
||||
" . Config::Get('db.table.topic') . " AS t,
|
||||
" . Config::Get('db.table.blog') . " AS b
|
||||
WHERE
|
||||
f.user_id = ?d
|
||||
AND
|
||||
f.target_publish = 1
|
||||
AND
|
||||
f.target_type = 'topic'
|
||||
AND
|
||||
f.target_id = t.topic_id
|
||||
AND
|
||||
t.blog_id = b.blog_id
|
||||
AND
|
||||
b.blog_type IN ('open', 'personal')
|
||||
;";
|
||||
return ($aRow = $this->oDb->selectRow($sql, $sUserId))
|
||||
? $aRow['count']
|
||||
: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет избранное по списку идентификаторов таргетов
|
||||
*
|
||||
* @param array|int $aTargetId Список ID владельцев
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteFavouriteByTargetId($aTargetId, $sTargetType)
|
||||
{
|
||||
$sql = "
|
||||
DELETE FROM " . Config::Get('db.table.favourite') . "
|
||||
WHERE
|
||||
target_id IN(?a)
|
||||
AND
|
||||
target_type = ? ";
|
||||
$res = $this->oDb->query($sql, $aTargetId, $sTargetType);
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление тегов по таргету
|
||||
*
|
||||
* @param array $aTargetId Список ID владельцев
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function DeleteTagByTarget($aTargetId, $sTargetType)
|
||||
{
|
||||
$sql = "
|
||||
DELETE FROM " . Config::Get('db.table.favourite_tag') . "
|
||||
WHERE
|
||||
target_type = ?
|
||||
AND
|
||||
target_id IN(?a)
|
||||
";
|
||||
$res = $this->oDb->query($sql, $sTargetType, $aTargetId);
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает наиболее часто используемые теги
|
||||
*
|
||||
* @param int $iUserId ID пользователя
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param bool $bIsUser Возвращает все теги ли только пользовательские
|
||||
* @param int $iLimit Количество элементов
|
||||
* @return array
|
||||
*/
|
||||
public function GetGroupTags($iUserId, $sTargetType, $bIsUser, $iLimit)
|
||||
{
|
||||
$sql = "SELECT
|
||||
text,
|
||||
user_id,
|
||||
count(text) as count
|
||||
FROM
|
||||
" . Config::Get('db.table.favourite_tag') . "
|
||||
WHERE
|
||||
1=1
|
||||
{AND user_id = ?d }
|
||||
{AND target_type = ? }
|
||||
{AND is_user = ?d }
|
||||
GROUP BY
|
||||
text
|
||||
ORDER BY
|
||||
count desc
|
||||
LIMIT 0, ?d
|
||||
";
|
||||
$aReturn = array();
|
||||
$aReturnSort = array();
|
||||
if ($aRows = $this->oDb->select($sql, $iUserId, $sTargetType, is_null($bIsUser) ? DBSIMPLE_SKIP : $bIsUser,
|
||||
$iLimit)
|
||||
) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aReturn[mb_strtolower($aRow['text'], 'UTF-8')] = $aRow;
|
||||
}
|
||||
ksort($aReturn);
|
||||
foreach ($aReturn as $aRow) {
|
||||
$aReturnSort[] = Engine::GetEntity('ModuleFavourite_EntityTag', $aRow);
|
||||
}
|
||||
}
|
||||
return $aReturnSort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список тегов по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param array $aOrder Сортировка
|
||||
* @param int $iCount Возвращает количество элементов
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetTags($aFilter, $aOrder, &$iCount, $iCurrPage, $iPerPage)
|
||||
{
|
||||
$aOrderAllow = array('target_id', 'user_id', 'is_user');
|
||||
$sOrder = '';
|
||||
foreach ($aOrder as $key => $value) {
|
||||
if (!in_array($key, $aOrderAllow)) {
|
||||
unset($aOrder[$key]);
|
||||
} elseif (in_array($value, array('asc', 'desc'))) {
|
||||
$sOrder .= " {$key} {$value},";
|
||||
}
|
||||
}
|
||||
$sOrder = trim($sOrder, ',');
|
||||
if ($sOrder == '') {
|
||||
$sOrder = ' target_id desc ';
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
*
|
||||
FROM
|
||||
" . Config::Get('db.table.favourite_tag') . "
|
||||
WHERE
|
||||
1 = 1
|
||||
{ AND user_id = ?d }
|
||||
{ AND target_type = ? }
|
||||
{ AND target_id = ?d }
|
||||
{ AND is_user = ?d }
|
||||
{ AND text = ? }
|
||||
ORDER by {$sOrder}
|
||||
LIMIT ?d, ?d ;
|
||||
";
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->selectPage($iCount, $sql,
|
||||
isset($aFilter['user_id']) ? $aFilter['user_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['target_type']) ? $aFilter['target_type'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['target_id']) ? $aFilter['target_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['is_user']) ? $aFilter['is_user'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['text']) ? $aFilter['text'] : DBSIMPLE_SKIP,
|
||||
($iCurrPage - 1) * $iPerPage, $iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleFavourite_EntityTag', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
}
|
547
application/classes/modules/geo/Geo.class.php
Normal file
547
application/classes/modules/geo/Geo.class.php
Normal file
|
@ -0,0 +1,547 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Модуль Geo - привязка объектов к географии (страна/регион/город)
|
||||
* Терминология:
|
||||
* объект - который привязываем к гео-объекту
|
||||
* гео-объект - географический объект(страна/регион/город)
|
||||
*
|
||||
* @package application.modules.geo
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleGeo extends Module
|
||||
{
|
||||
/**
|
||||
* Объект маппера
|
||||
*
|
||||
* @var ModuleGeo_MapperGeo
|
||||
*/
|
||||
protected $oMapper;
|
||||
/**
|
||||
* Список доступных типов объектов
|
||||
* На данный момент доступен параметр allow_multi=>1 - указывает на возможность создавать несколько связей для одного объекта
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aTargetTypes = array(
|
||||
'user' => array(),
|
||||
);
|
||||
/**
|
||||
* Список доступных типов гео-объектов
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aGeoTypes = array(
|
||||
'country',
|
||||
'region',
|
||||
'city',
|
||||
);
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
$this->oMapper = Engine::GetMapper(__CLASS__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список типов объектов
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetTargetTypes()
|
||||
{
|
||||
return $this->aTargetTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет в разрешенные новый тип
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param array $aParams Параметры
|
||||
* @return bool
|
||||
*/
|
||||
public function AddTargetType($sTargetType, $aParams = array())
|
||||
{
|
||||
if (!array_key_exists($sTargetType, $this->aTargetTypes)) {
|
||||
$this->aTargetTypes[$sTargetType] = $aParams;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет разрешен ли данный тип
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowTargetType($sTargetType)
|
||||
{
|
||||
return in_array($sTargetType, array_keys($this->aTargetTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет разрешен ли данный гео-тип
|
||||
*
|
||||
* @param string $sGeoType Тип владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowGeoType($sGeoType)
|
||||
{
|
||||
return in_array($sGeoType, $this->aGeoTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка объекта
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function CheckTarget($sTargetType, $iTargetId)
|
||||
{
|
||||
if (!$this->IsAllowTargetType($sTargetType)) {
|
||||
return false;
|
||||
}
|
||||
$sMethod = 'CheckTarget' . func_camelize($sTargetType);
|
||||
if (method_exists($this, $sMethod)) {
|
||||
return $this->$sMethod($iTargetId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на возможность нескольких связей
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowTargetMulti($sTargetType)
|
||||
{
|
||||
if ($this->IsAllowTargetType($sTargetType)) {
|
||||
if (isset($this->aTargetTypes[$sTargetType]['allow_multi']) and $this->aTargetTypes[$sTargetType]['allow_multi']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет связь объекта с гео-объектом в БД
|
||||
*
|
||||
* @param ModuleGeo_EntityTarget $oTarget Объект связи с владельцем
|
||||
* @return ModuleGeo_EntityTarget|bool
|
||||
*/
|
||||
public function AddTarget($oTarget)
|
||||
{
|
||||
if ($this->oMapper->AddTarget($oTarget)) {
|
||||
return $oTarget;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Создание связи
|
||||
*
|
||||
* @param ModuleGeo_EntityGeo $oGeoObject
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return bool|ModuleGeo_EntityTarget
|
||||
*/
|
||||
public function CreateTarget($oGeoObject, $sTargetType, $iTargetId)
|
||||
{
|
||||
/**
|
||||
* Проверяем объект на валидность
|
||||
*/
|
||||
if (!$this->CheckTarget($sTargetType, $iTargetId)) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Проверяем есть ли уже у этого объекта другие связи
|
||||
*/
|
||||
$aTargets = $this->GetTargets(array('target_type' => $sTargetType, 'target_id' => $iTargetId), 1, 1);
|
||||
if ($aTargets['count']) {
|
||||
if ($this->IsAllowTargetMulti($sTargetType)) {
|
||||
/**
|
||||
* Разрешено несколько связей
|
||||
* Проверяем есть ли уже связь с данным гео-объектом, если есть то возвращаем его
|
||||
*/
|
||||
$aTargetSelf = $this->GetTargets(array(
|
||||
'target_type' => $sTargetType,
|
||||
'target_id' => $iTargetId,
|
||||
'geo_type' => $oGeoObject->getType(),
|
||||
'geo_id' => $oGeoObject->getId()
|
||||
), 1, 1);
|
||||
if ($oTargetSelf = array_shift($aTargetSelf['collection'])) {
|
||||
return $oTargetSelf;
|
||||
}
|
||||
} else {
|
||||
/**
|
||||
* Есть другие связи и несколько связей запрещено - удаляем имеющиеся связи
|
||||
*/
|
||||
$this->DeleteTargets(array('target_type' => $sTargetType, 'target_id' => $iTargetId));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Создаем связь
|
||||
*/
|
||||
$oTarget = Engine::GetEntity('ModuleGeo_EntityTarget');
|
||||
$oTarget->setGeoType($oGeoObject->getType());
|
||||
$oTarget->setGeoId($oGeoObject->getId());
|
||||
$oTarget->setTargetType($sTargetType);
|
||||
$oTarget->setTargetId($iTargetId);
|
||||
if ($oGeoObject->getType() == 'city') {
|
||||
$oTarget->setCountryId($oGeoObject->getCountryId());
|
||||
$oTarget->setRegionId($oGeoObject->getRegionId());
|
||||
$oTarget->setCityId($oGeoObject->getId());
|
||||
} elseif ($oGeoObject->getType() == 'region') {
|
||||
$oTarget->setCountryId($oGeoObject->getCountryId());
|
||||
$oTarget->setRegionId($oGeoObject->getId());
|
||||
} elseif ($oGeoObject->getType() == 'country') {
|
||||
$oTarget->setCountryId($oGeoObject->getId());
|
||||
}
|
||||
return $this->AddTarget($oTarget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список связей по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array('collection'=>array,'count'=>int)
|
||||
*/
|
||||
public function GetTargets($aFilter, $iCurrPage, $iPerPage)
|
||||
{
|
||||
return array(
|
||||
'collection' => $this->oMapper->GetTargets($aFilter, $iCount, $iCurrPage, $iPerPage),
|
||||
'count' => $iCount
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает первый объект связи по объекту
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return null|ModuleGeo_EntityTarget
|
||||
*/
|
||||
public function GetTargetByTarget($sTargetType, $iTargetId)
|
||||
{
|
||||
$aTargets = $this->GetTargets(array('target_type' => $sTargetType, 'target_id' => $iTargetId), 1, 1);
|
||||
if ($oTarget = array_shift($aTargets['collection'])) {
|
||||
return $oTarget;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список связей для списка объектов одного типа.
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param array $aTargetId Список ID владельцев
|
||||
* @return array В качестве ключей используется ID объекта, в качестве значений массив связей этого объекта
|
||||
*/
|
||||
public function GetTargetsByTargetArray($sTargetType, $aTargetId)
|
||||
{
|
||||
if (!is_array($aTargetId)) {
|
||||
$aTargetId = array($aTargetId);
|
||||
}
|
||||
if (!count($aTargetId)) {
|
||||
return array();
|
||||
}
|
||||
$aResult = array();
|
||||
$aTargets = $this->GetTargets(array('target_type' => $sTargetType, 'target_id' => $aTargetId), 1,
|
||||
count($aTargetId));
|
||||
if ($aTargets['count']) {
|
||||
foreach ($aTargets['collection'] as $oTarget) {
|
||||
$aResult[$oTarget->getTargetId()][] = $oTarget;
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет связи по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @return bool|int
|
||||
*/
|
||||
public function DeleteTargets($aFilter)
|
||||
{
|
||||
return $this->oMapper->DeleteTargets($aFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление всех связей объекта
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return bool|int
|
||||
*/
|
||||
public function DeleteTargetsByTarget($sTargetType, $iTargetId)
|
||||
{
|
||||
return $this->DeleteTargets(array('target_type' => $sTargetType, 'target_id' => $iTargetId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список стран по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param array $aOrder Сортировка
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array('collection'=>array,'count'=>int)
|
||||
*/
|
||||
public function GetCountries($aFilter, $aOrder, $iCurrPage, $iPerPage)
|
||||
{
|
||||
return array(
|
||||
'collection' => $this->oMapper->GetCountries($aFilter, $aOrder, $iCount, $iCurrPage, $iPerPage),
|
||||
'count' => $iCount
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список регионов по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param array $aOrder Сортировка
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array('collection'=>array,'count'=>int)
|
||||
*/
|
||||
public function GetRegions($aFilter, $aOrder, $iCurrPage, $iPerPage)
|
||||
{
|
||||
return array(
|
||||
'collection' => $this->oMapper->GetRegions($aFilter, $aOrder, $iCount, $iCurrPage, $iPerPage),
|
||||
'count' => $iCount
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список городов по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param array $aOrder Сортировка
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array('collection'=>array,'count'=>int)
|
||||
*/
|
||||
public function GetCities($aFilter, $aOrder, $iCurrPage, $iPerPage)
|
||||
{
|
||||
return array(
|
||||
'collection' => $this->oMapper->GetCities($aFilter, $aOrder, $iCount, $iCurrPage, $iPerPage),
|
||||
'count' => $iCount
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает страну по ID
|
||||
*
|
||||
* @param int $iId ID страны
|
||||
* @return ModuleGeo_EntityCountry|null
|
||||
*/
|
||||
public function GetCountryById($iId)
|
||||
{
|
||||
$aRes = $this->GetCountries(array('id' => $iId), array(), 1, 1);
|
||||
if ($oCountry = array_shift($aRes['collection'])) {
|
||||
return $oCountry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает регион по ID
|
||||
*
|
||||
* @param int $iId ID региона
|
||||
* @return ModuleGeo_EntityRegion|null
|
||||
*/
|
||||
public function GetRegionById($iId)
|
||||
{
|
||||
$aRes = $this->GetRegions(array('id' => $iId), array(), 1, 1);
|
||||
if ($oRegion = array_shift($aRes['collection'])) {
|
||||
return $oRegion;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает регион по ID
|
||||
*
|
||||
* @param int $iId ID города
|
||||
* @return ModuleGeo_EntityCity|null
|
||||
*/
|
||||
public function GetCityById($iId)
|
||||
{
|
||||
$aRes = $this->GetCities(array('id' => $iId), array(), 1, 1);
|
||||
if ($oCity = array_shift($aRes['collection'])) {
|
||||
return $oCity;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает гео-объект
|
||||
*
|
||||
* @param string $sType Тип гео-объекта
|
||||
* @param int $iId ID гео-объекта
|
||||
* @return ModuleGeo_EntityGeo|null
|
||||
*/
|
||||
public function GetGeoObject($sType, $iId)
|
||||
{
|
||||
$sType = strtolower($sType);
|
||||
if (!$this->IsAllowGeoType($sType)) {
|
||||
return null;
|
||||
}
|
||||
switch ($sType) {
|
||||
case 'country':
|
||||
return $this->GetCountryById($iId);
|
||||
break;
|
||||
case 'region':
|
||||
return $this->GetRegionById($iId);
|
||||
break;
|
||||
case 'city':
|
||||
return $this->GetCityById($iId);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает первый гео-объект для объекта
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return ModuleGeo_EntityCity|ModuleGeo_EntityCountry|ModuleGeo_EntityRegion|null
|
||||
*/
|
||||
public function GetGeoObjectByTarget($sTargetType, $iTargetId)
|
||||
{
|
||||
$aTargets = $this->GetTargets(array('target_type' => $sTargetType, 'target_id' => $iTargetId), 1, 1);
|
||||
if ($oTarget = array_shift($aTargets['collection']) ) {
|
||||
$oTarget = $oTarget;
|
||||
return $this->GetGeoObject($oTarget->getGeoType(), $oTarget->getGeoId());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список стран сгруппированных по количеству использований в данном типе объектов
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iLimit Количество элементов
|
||||
* @return array
|
||||
*/
|
||||
public function GetGroupCountriesByTargetType($sTargetType, $iLimit)
|
||||
{
|
||||
return $this->oMapper->GetGroupCountriesByTargetType($sTargetType, $iLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список городов сгруппированных по количеству использований в данном типе объектов
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iLimit Количество элементов
|
||||
* @return array
|
||||
*/
|
||||
public function GetGroupCitiesByTargetType($sTargetType, $iLimit)
|
||||
{
|
||||
return $this->oMapper->GetGroupCitiesByTargetType($sTargetType, $iLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список использованых стран для типа
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @return array
|
||||
*/
|
||||
public function GetCountriesUsedByTargetType($sTargetType)
|
||||
{
|
||||
return $this->oMapper->GetCountriesUsedByTargetType($sTargetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список использованых регионов для типа
|
||||
*
|
||||
* @param int $iCountryId
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @return array
|
||||
*/
|
||||
public function GetRegionsUsedByTargetType($iCountryId, $sTargetType)
|
||||
{
|
||||
return $this->oMapper->GetRegionsUsedByTargetType($iCountryId, $sTargetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список использованых городов для типа
|
||||
*
|
||||
* @param int $iRegionId
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @return array
|
||||
*/
|
||||
public function GetCitiesUsedByTargetType($iRegionId, $sTargetType)
|
||||
{
|
||||
return $this->oMapper->GetCitiesUsedByTargetType($iRegionId, $sTargetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка объекта с типом "user"
|
||||
* Название метода формируется автоматически
|
||||
*
|
||||
* @param int $iTargetId ID пользователя
|
||||
* @return bool
|
||||
*/
|
||||
public function CheckTargetUser($iTargetId)
|
||||
{
|
||||
if ($oUser = $this->User_GetUserById($iTargetId)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение всех обьектов по таргетам (для загрузки в шаблон)
|
||||
*
|
||||
* @param arr $aTargets массив таргетов
|
||||
* @return arr
|
||||
*/
|
||||
public function GetGeoObjectsByTargets($aTargets)
|
||||
{
|
||||
$aGeoCountryIds = [];
|
||||
$aGeoRegoinIds = [];
|
||||
$aGeoCityIds = [];
|
||||
|
||||
foreach ($aTargets as $oTarget) {
|
||||
$aGeoCountryIds[] = $oTarget->getCountryId();
|
||||
$aGeoRegoinIds[] = $oTarget->getRegionId();
|
||||
$aGeoCityIds[] = $oTarget->getCityId();
|
||||
}
|
||||
|
||||
return [
|
||||
'countries' => $this->GetCountries(['id' => $aGeoCountryIds], [], 1, 1000)['collection'],
|
||||
'regions' => $this->GetRegions(['id' => $aGeoRegoinIds], [], 1, 1000)['collection'],
|
||||
'cities' => $this->GetCities(['id' => $aGeoCityIds], [], 1, 1000)['collection']
|
||||
];
|
||||
}
|
||||
}
|
31
application/classes/modules/geo/entity/City.entity.class.php
Normal file
31
application/classes/modules/geo/entity/City.entity.class.php
Normal file
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект сущности города
|
||||
*
|
||||
* @package application.modules.geo
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleGeo_EntityCity extends ModuleGeo_EntityGeo
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект сущности страны
|
||||
*
|
||||
* @package application.modules.geo
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleGeo_EntityCountry extends ModuleGeo_EntityGeo
|
||||
{
|
||||
|
||||
}
|
131
application/classes/modules/geo/entity/Geo.entity.class.php
Normal file
131
application/classes/modules/geo/entity/Geo.entity.class.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект сущности гео-объекта
|
||||
*
|
||||
* @package application.modules.geo
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleGeo_EntityGeo extends Entity
|
||||
{
|
||||
|
||||
/**
|
||||
* Возвращает имя гео-объекта в зависимости от языка
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
$sName = '';
|
||||
$sLangDef = Config::get('lang.default');
|
||||
if ($sLangDef == 'ru') {
|
||||
$sName = $this->getNameRu();
|
||||
} elseif ($sLangDef == 'en') {
|
||||
$sName = $this->getNameEn();
|
||||
}
|
||||
|
||||
$sLang = Config::get('lang.current');
|
||||
if ($sLang == 'ru' and $this->getNameRu()) {
|
||||
$sName = $this->getNameRu();
|
||||
} elseif ($sLang == 'en' and $this->getNameEn()) {
|
||||
$sName = $this->getNameEn();
|
||||
}
|
||||
return $sName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает тип гео-объекта
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
if ($this instanceof ModuleGeo_EntityCity) {
|
||||
return 'city';
|
||||
} elseif ($this instanceof ModuleGeo_EntityRegion) {
|
||||
return 'region';
|
||||
} elseif ($this instanceof ModuleGeo_EntityCountry) {
|
||||
return 'country';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает гео-объект страны
|
||||
*
|
||||
* @return ModuleGeo_EntityGeo|null
|
||||
*/
|
||||
public function getCountry()
|
||||
{
|
||||
if ($this->getType() == 'country') {
|
||||
return $this;
|
||||
}
|
||||
if ($oCountry = $this->_getDataOne('country')) {
|
||||
return $oCountry;
|
||||
}
|
||||
if ($this->getCountryId()) {
|
||||
$oCountry = $this->Geo_GetCountryById($this->getCountryId());
|
||||
return $this->_aData['country'] = $oCountry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает гео-объект региона
|
||||
*
|
||||
* @return ModuleGeo_EntityGeo|null
|
||||
*/
|
||||
public function getRegion()
|
||||
{
|
||||
if ($this->getType() == 'region') {
|
||||
return $this;
|
||||
}
|
||||
if ($oRegion = $this->_getDataOne('region')) {
|
||||
return $oRegion;
|
||||
}
|
||||
if ($this->getRegionId()) {
|
||||
$oRegion = $this->Geo_GetRegionById($this->getRegionId());
|
||||
return $this->_aData['region'] = $oRegion;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает гео-объект города
|
||||
*
|
||||
* @return ModuleGeo_EntityGeo|null
|
||||
*/
|
||||
public function getCity()
|
||||
{
|
||||
if ($this->getType() == 'city') {
|
||||
return $this;
|
||||
}
|
||||
if ($oCity = $this->_getDataOne('city')) {
|
||||
return $oCity;
|
||||
}
|
||||
if ($this->getCityId()) {
|
||||
$oCity = $this->Geo_GetCityById($this->getCityId());
|
||||
return $this->_aData['city'] = $oCity;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект сущности региона
|
||||
*
|
||||
* @package application.modules.geo
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleGeo_EntityRegion extends ModuleGeo_EntityGeo
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект связи гео-объекта с владельцем
|
||||
*
|
||||
* @package application.modules.geo
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleGeo_EntityTarget extends Entity
|
||||
{
|
||||
|
||||
}
|
467
application/classes/modules/geo/mapper/Geo.mapper.class.php
Normal file
467
application/classes/modules/geo/mapper/Geo.mapper.class.php
Normal file
|
@ -0,0 +1,467 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект маппера для работы с БД
|
||||
*
|
||||
* @package application.modules.geo
|
||||
* @since 1.0
|
||||
*/
|
||||
class ModuleGeo_MapperGeo extends Mapper
|
||||
{
|
||||
/**
|
||||
* Добавляет связь объекта с гео-объектом в БД
|
||||
*
|
||||
* @param ModuleGeo_EntityTarget $oTarget Объект связи с владельцем
|
||||
* @return ModuleGeo_EntityTarget|bool
|
||||
*/
|
||||
public function AddTarget($oTarget)
|
||||
{
|
||||
$sql = "INSERT INTO " . Config::Get('db.table.geo_target') . " SET ?a ";
|
||||
if ($this->oDb->query($sql, $oTarget->_getData())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список связей по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param int $iCount Возвращает количество элементов
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetTargets($aFilter, &$iCount, $iCurrPage, $iPerPage)
|
||||
{
|
||||
if (isset($aFilter['target_id']) and !is_array($aFilter['target_id'])) {
|
||||
$aFilter['target_id'] = array($aFilter['target_id']);
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
*
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_target') . "
|
||||
WHERE
|
||||
1 = 1
|
||||
{ AND geo_type = ? }
|
||||
{ AND geo_id = ?d }
|
||||
{ AND target_type = ? }
|
||||
{ AND target_id IN ( ?a ) }
|
||||
{ AND country_id = ?d }
|
||||
{ AND region_id = ?d }
|
||||
{ AND city_id = ?d }
|
||||
ORDER BY target_id DESC
|
||||
LIMIT ?d, ?d ;
|
||||
";
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->selectPage($iCount, $sql,
|
||||
isset($aFilter['geo_type']) ? $aFilter['geo_type'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['geo_id']) ? $aFilter['geo_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['target_type']) ? $aFilter['target_type'] : DBSIMPLE_SKIP,
|
||||
(isset($aFilter['target_id']) and count($aFilter['target_id'])) ? $aFilter['target_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['country_id']) ? $aFilter['country_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['region_id']) ? $aFilter['region_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['city_id']) ? $aFilter['city_id'] : DBSIMPLE_SKIP,
|
||||
|
||||
($iCurrPage - 1) * $iPerPage, $iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleGeo_EntityTarget', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список стран сгруппированных по количеству использований в данном типе объектов
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iLimit Количество элементов
|
||||
* @return array
|
||||
*/
|
||||
public function GetGroupCountriesByTargetType($sTargetType, $iLimit)
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
t.count,
|
||||
g.*
|
||||
FROM (
|
||||
SELECT
|
||||
count(*) as count,
|
||||
country_id
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_target') . "
|
||||
WHERE target_type = ? and country_id IS NOT NULL
|
||||
GROUP BY country_id ORDER BY count DESC LIMIT 0, ?d
|
||||
) as t
|
||||
JOIN " . Config::Get('db.table.geo_country') . " as g on t.country_id=g.id
|
||||
ORDER BY g.name_ru
|
||||
";
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->select($sql, $sTargetType, $iLimit)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleGeo_EntityCountry', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список городов сгруппированных по количеству использований в данном типе объектов
|
||||
*
|
||||
* @param string $sTargetType Тип владельца
|
||||
* @param int $iLimit Количество элементов
|
||||
* @return array
|
||||
*/
|
||||
public function GetGroupCitiesByTargetType($sTargetType, $iLimit)
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
t.count,
|
||||
g.*
|
||||
FROM (
|
||||
SELECT
|
||||
count(*) as count,
|
||||
city_id
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_target') . "
|
||||
WHERE target_type = ? and city_id IS NOT NULL
|
||||
GROUP BY city_id ORDER BY count DESC LIMIT 0, ?d
|
||||
) as t
|
||||
JOIN " . Config::Get('db.table.geo_city') . " as g on t.city_id=g.id
|
||||
ORDER BY g.name_ru
|
||||
";
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->select($sql, $sTargetType, $iLimit)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleGeo_EntityCity', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет связи по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @return bool|int
|
||||
*/
|
||||
public function DeleteTargets($aFilter)
|
||||
{
|
||||
if (!$aFilter) {
|
||||
return false;
|
||||
}
|
||||
$sql = "DELETE
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_target') . "
|
||||
WHERE
|
||||
1 = 1
|
||||
{ AND geo_type = ? }
|
||||
{ AND geo_id = ?d }
|
||||
{ AND target_type = ? }
|
||||
{ AND target_id = ?d }
|
||||
{ AND country_id = ?d }
|
||||
{ AND region_id = ?d }
|
||||
{ AND city_id = ?d }
|
||||
";
|
||||
$res = $this->oDb->query($sql,
|
||||
isset($aFilter['geo_type']) ? $aFilter['geo_type'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['geo_id']) ? $aFilter['geo_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['target_type']) ? $aFilter['target_type'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['target_id']) ? $aFilter['target_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['country_id']) ? $aFilter['country_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['region_id']) ? $aFilter['region_id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['city_id']) ? $aFilter['city_id'] : DBSIMPLE_SKIP
|
||||
);
|
||||
return $this->IsSuccessful($res);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список стран по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param array $aOrder Сортировка
|
||||
* @param int $iCount Возвращает количество элементов
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetCountries($aFilter, $aOrder, &$iCount, $iCurrPage, $iPerPage)
|
||||
{
|
||||
$aOrderAllow = array('id', 'name_ru', 'name_en', 'sort');
|
||||
$sOrder = '';
|
||||
foreach ($aOrder as $key => $value) {
|
||||
if (!in_array($key, $aOrderAllow)) {
|
||||
unset($aOrder[$key]);
|
||||
} elseif (in_array($value, array('asc', 'desc'))) {
|
||||
$sOrder .= " {$key} {$value},";
|
||||
}
|
||||
}
|
||||
$sOrder = trim($sOrder, ',');
|
||||
if ($sOrder == '') {
|
||||
$sOrder = ' id desc ';
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
*
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_country') . "
|
||||
WHERE
|
||||
1 = 1
|
||||
{ AND id = ?d }
|
||||
{ AND name_ru = ? }
|
||||
{ AND name_ru LIKE ? }
|
||||
{ AND name_en = ? }
|
||||
{ AND name_en LIKE ? }
|
||||
{ AND code = ? }
|
||||
|
||||
ORDER by {$sOrder}
|
||||
LIMIT ?d, ?d ;
|
||||
";
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->selectPage($iCount, $sql,
|
||||
isset($aFilter['id']) ? $aFilter['id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_ru']) ? $aFilter['name_ru'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_ru_like']) ? $aFilter['name_ru_like'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_en']) ? $aFilter['name_en'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_en_like']) ? $aFilter['name_en_like'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['code']) ? $aFilter['code'] : DBSIMPLE_SKIP,
|
||||
($iCurrPage - 1) * $iPerPage, $iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleGeo_EntityCountry', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список регионов по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param array $aOrder Сортировка
|
||||
* @param int $iCount Возвращает количество элементов
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetRegions($aFilter, $aOrder, &$iCount, $iCurrPage, $iPerPage)
|
||||
{
|
||||
$aOrderAllow = array('id', 'name_ru', 'name_en', 'sort', 'country_id');
|
||||
$sOrder = '';
|
||||
foreach ($aOrder as $key => $value) {
|
||||
if (!in_array($key, $aOrderAllow)) {
|
||||
unset($aOrder[$key]);
|
||||
} elseif (in_array($value, array('asc', 'desc'))) {
|
||||
$sOrder .= " {$key} {$value},";
|
||||
}
|
||||
}
|
||||
$sOrder = trim($sOrder, ',');
|
||||
if ($sOrder == '') {
|
||||
$sOrder = ' id desc ';
|
||||
}
|
||||
|
||||
if (isset($aFilter['country_id']) and !is_array($aFilter['country_id'])) {
|
||||
$aFilter['country_id'] = array($aFilter['country_id']);
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
*
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_region') . "
|
||||
WHERE
|
||||
1 = 1
|
||||
{ AND id = ?d }
|
||||
{ AND name_ru = ? }
|
||||
{ AND name_ru LIKE ? }
|
||||
{ AND name_en = ? }
|
||||
{ AND name_en LIKE ? }
|
||||
{ AND country_id IN ( ?a ) }
|
||||
|
||||
ORDER by {$sOrder}
|
||||
LIMIT ?d, ?d ;
|
||||
";
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->selectPage($iCount, $sql,
|
||||
isset($aFilter['id']) ? $aFilter['id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_ru']) ? $aFilter['name_ru'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_ru_like']) ? $aFilter['name_ru_like'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_en']) ? $aFilter['name_en'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_en_like']) ? $aFilter['name_en_like'] : DBSIMPLE_SKIP,
|
||||
(isset($aFilter['country_id']) && count($aFilter['country_id'])) ? $aFilter['country_id'] : DBSIMPLE_SKIP,
|
||||
($iCurrPage - 1) * $iPerPage, $iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleGeo_EntityRegion', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список городов по фильтру
|
||||
*
|
||||
* @param array $aFilter Фильтр
|
||||
* @param array $aOrder Сортировка
|
||||
* @param int $iCount Возвращает количество элементов
|
||||
* @param int $iCurrPage Номер страницы
|
||||
* @param int $iPerPage Количество элементов на страницу
|
||||
* @return array
|
||||
*/
|
||||
public function GetCities($aFilter, $aOrder, &$iCount, $iCurrPage, $iPerPage)
|
||||
{
|
||||
$aOrderAllow = array('id', 'name_ru', 'name_en', 'sort', 'country_id', 'region_id');
|
||||
$sOrder = '';
|
||||
foreach ($aOrder as $key => $value) {
|
||||
if (!in_array($key, $aOrderAllow)) {
|
||||
unset($aOrder[$key]);
|
||||
} elseif (in_array($value, array('asc', 'desc'))) {
|
||||
$sOrder .= " {$key} {$value},";
|
||||
}
|
||||
}
|
||||
$sOrder = trim($sOrder, ',');
|
||||
if ($sOrder == '') {
|
||||
$sOrder = ' id desc ';
|
||||
}
|
||||
|
||||
if (isset($aFilter['country_id']) and !is_array($aFilter['country_id'])) {
|
||||
$aFilter['country_id'] = array($aFilter['country_id']);
|
||||
}
|
||||
if (isset($aFilter['region_id']) and !is_array($aFilter['region_id'])) {
|
||||
$aFilter['region_id'] = array($aFilter['region_id']);
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
*
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_city') . "
|
||||
WHERE
|
||||
1 = 1
|
||||
{ AND id = ?d }
|
||||
{ AND name_ru = ? }
|
||||
{ AND name_ru LIKE ? }
|
||||
{ AND name_en = ? }
|
||||
{ AND name_en LIKE ? }
|
||||
{ AND country_id IN ( ?a ) }
|
||||
{ AND region_id IN ( ?a ) }
|
||||
|
||||
ORDER by {$sOrder}
|
||||
LIMIT ?d, ?d ;
|
||||
";
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->selectPage($iCount, $sql,
|
||||
isset($aFilter['id']) ? $aFilter['id'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_ru']) ? $aFilter['name_ru'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_ru_like']) ? $aFilter['name_ru_like'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_en']) ? $aFilter['name_en'] : DBSIMPLE_SKIP,
|
||||
isset($aFilter['name_en_like']) ? $aFilter['name_en_like'] : DBSIMPLE_SKIP,
|
||||
(isset($aFilter['country_id']) && count($aFilter['country_id'])) ? $aFilter['country_id'] : DBSIMPLE_SKIP,
|
||||
(isset($aFilter['region_id']) && count($aFilter['region_id'])) ? $aFilter['region_id'] : DBSIMPLE_SKIP,
|
||||
($iCurrPage - 1) * $iPerPage, $iPerPage
|
||||
)
|
||||
) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleGeo_EntityCity', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function GetCountriesUsedByTargetType($sTargetType)
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
c.*
|
||||
FROM (
|
||||
SELECT
|
||||
DISTINCT country_id
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_target') . "
|
||||
WHERE target_type = ? and country_id IS NOT NULL
|
||||
) as t
|
||||
JOIN " . Config::Get('db.table.geo_country') . " as c on t.country_id=c.id
|
||||
ORDER BY c.name_ru
|
||||
";
|
||||
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->select($sql, $sTargetType)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleGeo_EntityCountry', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function GetRegionsUsedByTargetType($iCountryId,$sTargetType)
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
c.*
|
||||
FROM (
|
||||
SELECT
|
||||
DISTINCT region_id
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_target') . "
|
||||
WHERE target_type = ? and region_id IS NOT NULL
|
||||
) as t
|
||||
JOIN " . Config::Get('db.table.geo_region') . " as c on ( t.region_id=c.id and c.country_id = ? )
|
||||
ORDER BY c.name_ru
|
||||
";
|
||||
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->select($sql, $sTargetType, $iCountryId)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleGeo_EntityRegion', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function GetCitiesUsedByTargetType($iRegionId,$sTargetType)
|
||||
{
|
||||
$sql = "
|
||||
SELECT
|
||||
c.*
|
||||
FROM (
|
||||
SELECT
|
||||
DISTINCT city_id
|
||||
FROM
|
||||
" . Config::Get('db.table.geo_target') . "
|
||||
WHERE target_type = ? and city_id IS NOT NULL
|
||||
) as t
|
||||
JOIN " . Config::Get('db.table.geo_city') . " as c on ( t.city_id=c.id and c.region_id = ? )
|
||||
ORDER BY c.name_ru
|
||||
";
|
||||
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->select($sql, $sTargetType, $iRegionId)) {
|
||||
foreach ($aRows as $aRow) {
|
||||
$aResult[] = Engine::GetEntity('ModuleGeo_EntityCity', $aRow);
|
||||
}
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
}
|
68
application/classes/modules/ifhub/Ifhub.class.php
Normal file
68
application/classes/modules/ifhub/Ifhub.class.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
/**
|
||||
* Модуль для функций Ифхаба
|
||||
*
|
||||
* @license GPLv2
|
||||
* @package application.modules.ifhub
|
||||
* @author Alexander Yakovlev
|
||||
*/
|
||||
class ModuleIfhub extends Module
|
||||
{
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка тега spoiler в тексте
|
||||
* <pre>
|
||||
* <spoiler title="Заголовок">Текст спойлера</spoiler>
|
||||
* </pre>
|
||||
*
|
||||
* @param string $sTag Тег на котором сработал колбэк
|
||||
* @param array $aParams Список параметров тега
|
||||
* @return string
|
||||
*/
|
||||
public function CallbackParserTagSpoiler($sTag, $aParams, $sText)
|
||||
{
|
||||
$sTitle = "Спойлер";
|
||||
if (isset($aParams['title'])) {
|
||||
$sTitle = $aParams['title'];
|
||||
}
|
||||
|
||||
return '<details class="newspoiler">'.
|
||||
'<summary class="newspoiler-title">'.$sTitle.'</summary>'.
|
||||
$sText.'</details>';
|
||||
}
|
||||
/**
|
||||
* Обработка тега aside в тексте
|
||||
* <pre>
|
||||
* <aside>Текст врезки</aside>
|
||||
* </pre>
|
||||
*
|
||||
* @param string $sTag Тег на котором сработал колбэк
|
||||
* @param array $aParams Список параметров тега
|
||||
* @return string
|
||||
*/
|
||||
public function CallbackParserTagAside($sTag, $aParams, $sText)
|
||||
{
|
||||
return '<div class="aside">'.$sText.'</div>';
|
||||
}
|
||||
/**
|
||||
* Обработка тега incut в тексте
|
||||
* <pre>
|
||||
* <incut>Текст врезки</incut>
|
||||
* </pre>
|
||||
*
|
||||
* @param string $sTag Тег на котором сработал колбэк
|
||||
* @param array $aParams Список параметров тега
|
||||
* @return string
|
||||
*/
|
||||
public function CallbackParserTagIncut($sTag, $aParams, $sText)
|
||||
{
|
||||
return '<div class="incut">'.$sText.'</div>';
|
||||
}
|
||||
}
|
279
application/classes/modules/invite/Invite.class.php
Normal file
279
application/classes/modules/invite/Invite.class.php
Normal file
|
@ -0,0 +1,279 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Модуль управления инвайтами
|
||||
*
|
||||
* @package application.modules.invite
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleInvite extends ModuleORM
|
||||
{
|
||||
/**
|
||||
* Тип реферального инвайта, когда пользователь приглашает по своему реферальному коду
|
||||
*/
|
||||
const INVITE_TYPE_REFERRAL = 1;
|
||||
/**
|
||||
* Тип инвайта по сгенерированному коду, когда пользователь генерирует для приглашения отдельный код (доступен в закрытом режиме сайта)
|
||||
*/
|
||||
const INVITE_TYPE_CODE = 2;
|
||||
|
||||
/**
|
||||
* Генерирует новый код инвайта
|
||||
*
|
||||
* @param int $iUserId
|
||||
* @param string|null $sCode
|
||||
* @param int $iCountAllowUse
|
||||
* @param int|string|null $sDateExpired
|
||||
* @return bool|ModuleInvite_EntityCode
|
||||
*/
|
||||
public function GenerateInvite($iUserId, $sCode = null, $iCountAllowUse = 1, $sDateExpired = null)
|
||||
{
|
||||
$iUserId = is_scalar($iUserId) ? (int)$iUserId : $iUserId->getId();
|
||||
$sDateExpired = is_int($sDateExpired) ? date('Y-m-d H:i:s', time() + $sDateExpired) : $sDateExpired;
|
||||
|
||||
$oInviteCode = Engine::GetEntity('ModuleInvite_EntityCode');
|
||||
$oInviteCode->setUserId($iUserId);
|
||||
$oInviteCode->setCode(is_null($sCode) ? $this->GenerateRandomCode() : $sCode);
|
||||
$oInviteCode->setCountAllowUse($iCountAllowUse);
|
||||
$oInviteCode->setDateExpired($sDateExpired);
|
||||
$oInviteCode->setActive(1);
|
||||
if ($oInviteCode->Add()) {
|
||||
return $oInviteCode;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Фиксирует факт использования кода инвайта
|
||||
*
|
||||
* @param string $sCode
|
||||
* @param int $iUserId
|
||||
* @return bool
|
||||
*/
|
||||
public function UseCode($sCode, $iUserId)
|
||||
{
|
||||
$iUserId = is_scalar($iUserId) ? (int)$iUserId : $iUserId->getId();
|
||||
$iType = $this->GetInviteTypeByCode($sCode);
|
||||
|
||||
$oUse = Engine::GetEntity('ModuleInvite_EntityUse');
|
||||
$oUse->setType($iType);
|
||||
$oUse->setToUserId($iUserId);
|
||||
|
||||
if ($iType == self::INVITE_TYPE_CODE) {
|
||||
$oCode = $this->GetCodeByCode($sCode);
|
||||
$oCode->setCountUse($oCode->getCountUse() + 1);
|
||||
$oCode->Update();
|
||||
|
||||
$oUse->setCodeId($oCode->getId());
|
||||
$oUse->setFromUserId($oCode->getUserId());
|
||||
} elseif ($iType == self::INVITE_TYPE_REFERRAL) {
|
||||
$oUser = $this->User_GetUserByReferralCode($sCode);
|
||||
$oUse->setFromUserId($oUser->getId());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return $oUse->Add();
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет корректность кода инвайта с учетом его типа
|
||||
*
|
||||
* @param string $sCode
|
||||
* @param int $iType Тип инвайта, смотри self::INVITE_TYPE_*
|
||||
* @return bool
|
||||
*/
|
||||
public function CheckCode($sCode, $iType = self::INVITE_TYPE_CODE)
|
||||
{
|
||||
if ($iType == self::INVITE_TYPE_CODE) {
|
||||
if ($oCode = $this->GetCodeByCode($sCode)) {
|
||||
if ($oCode->getActive()
|
||||
and $oCode->getCountUse() < $oCode->getCountAllowUse()
|
||||
and (!$oCode->getDateExpired() or strtotime($oCode->getDateExpired()) < time())
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} elseif ($iType == self::INVITE_TYPE_REFERRAL) {
|
||||
if ($oUser = $this->User_GetUserByReferralCode($sCode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает тип инвайта по его коду
|
||||
*
|
||||
* @param string $sCode
|
||||
* @return bool|int
|
||||
*/
|
||||
public function GetInviteTypeByCode($sCode)
|
||||
{
|
||||
/**
|
||||
* Приоритет отдаем сгенерированному коду
|
||||
*/
|
||||
if ($this->CheckCode($sCode, self::INVITE_TYPE_CODE)) {
|
||||
return self::INVITE_TYPE_CODE;
|
||||
}
|
||||
if ($this->CheckCode($sCode, self::INVITE_TYPE_REFERRAL)) {
|
||||
return self::INVITE_TYPE_REFERRAL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает персональный реферальный код пользователя
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser
|
||||
* @return string|null
|
||||
*/
|
||||
public function GetReferralCode($oUser)
|
||||
{
|
||||
if (is_scalar($oUser)) {
|
||||
$oUser = $this->User_GetUserById($oUser);
|
||||
}
|
||||
if (is_object($oUser)) {
|
||||
return $oUser->getReferralCode();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает полную ссылку с реферальным кодом
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser
|
||||
* @param string|null $sCode
|
||||
* @return null|string
|
||||
*/
|
||||
public function GetReferralLink($oUser, $sCode = null)
|
||||
{
|
||||
if ($sCode or $sCode = $this->GetReferralCode($oUser)) {
|
||||
return Router::GetPath('auth/referral') . urlencode($sCode) . '/';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерирует случайный код
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function GenerateRandomCode()
|
||||
{
|
||||
return func_generator(10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество доступных инвайтов для пользователя в данный момент
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUser
|
||||
* @return int
|
||||
*/
|
||||
public function GetCountInviteAvailable($oUser)
|
||||
{
|
||||
if (is_scalar($oUser)) {
|
||||
$oUser = $this->User_GetUserById($oUser);
|
||||
}
|
||||
/**
|
||||
* Период в днях, за который выдаем инвайты
|
||||
*/
|
||||
$sDay = 7;
|
||||
/**
|
||||
* Количество выданных инвайтов за эти дни
|
||||
*/
|
||||
$iCountUsed = $this->GetCountFromCodeByFilter(array(
|
||||
'user_id' => $oUser->getId(),
|
||||
'date_create >' => date("Y-m-d 00:00:00", mktime(0, 0, 0, date("m"), date("d") - $sDay, date("Y")))
|
||||
));
|
||||
/**
|
||||
* Доступное число инвайтов период = рейтингу пользователя
|
||||
*/
|
||||
$iCountAllAvailable = round($oUser->getRating());
|
||||
$iCountAllAvailable = $iCountAllAvailable < 0 ? 0 : $iCountAllAvailable;
|
||||
$iCountAvailable = $iCountAllAvailable - $iCountUsed;
|
||||
$iCountAvailable = $iCountAvailable < 0 ? 0 : $iCountAvailable;
|
||||
return $iCountAvailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает количество приглашенных пользователей (число использованных инвайтов)
|
||||
*
|
||||
* @param int $iUserId
|
||||
* @return int
|
||||
*/
|
||||
public function GetCountInviteUsed($iUserId)
|
||||
{
|
||||
$iUserId = is_scalar($iUserId) ? (int)$iUserId : $iUserId->getId();
|
||||
|
||||
return $this->GetCountFromUseByFilter(array('from_user_id' => $iUserId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает пользователя, который пригласил текущего
|
||||
*
|
||||
* @param $iUserId
|
||||
* @return ModuleUser_EntityUser|null
|
||||
*/
|
||||
public function GetUserInviteFrom($iUserId)
|
||||
{
|
||||
if ($oUse = $this->GetUseByToUserId($iUserId) and $iUserFrom = $oUse->getFromUserId()) {
|
||||
return $this->User_GetUserById($iUserFrom);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список приглашенных пользователей
|
||||
*
|
||||
* @param int $iUserId
|
||||
* @return array
|
||||
*/
|
||||
public function GetUsersInvite($iUserId)
|
||||
{
|
||||
if ($aUseItems = $this->GetUseItemsByFilter(array('from_user_id' => $iUserId, '#index-from' => 'to_user_id', '#limit' => 100))) {
|
||||
return $this->User_GetUsersAdditionalData(array_keys($aUseItems));
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправляет инвайт
|
||||
*
|
||||
* @param ModuleUser_EntityUser $oUserFrom Пароль пользователя, который отправляет инвайт
|
||||
* @param string $sMailTo Емайл на который отправляем инвайт
|
||||
* @param string $sRefCode Код приглашения
|
||||
*/
|
||||
public function SendNotifyInvite(ModuleUser_EntityUser $oUserFrom, $sMailTo, $sRefCode)
|
||||
{
|
||||
$this->Notify_Send(
|
||||
$sMailTo,
|
||||
'invite.tpl',
|
||||
$this->Lang_Get('emails.invite.subject'),
|
||||
array(
|
||||
'sMailTo' => $sMailTo,
|
||||
'oUserFrom' => $oUserFrom,
|
||||
'sRefCode' => $sRefCode,
|
||||
'sRefLink' => $this->GetReferralLink($oUserFrom, $sRefCode),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность инвайта
|
||||
*
|
||||
* @package application.modules.invite
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleInvite_EntityCode extends EntityORM
|
||||
{
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность факта использования инвайта
|
||||
*
|
||||
* @package application.modules.invite
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleInvite_EntityUse extends EntityORM
|
||||
{
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
}
|
1518
application/classes/modules/media/Media.class.php
Normal file
1518
application/classes/modules/media/Media.class.php
Normal file
File diff suppressed because it is too large
Load diff
115
application/classes/modules/media/entity/Media.entity.class.php
Normal file
115
application/classes/modules/media/entity/Media.entity.class.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность медиа данных (изображение, видео и т.п.)
|
||||
*
|
||||
* @package application.modules.media
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleMedia_EntityMedia extends EntityORM
|
||||
{
|
||||
|
||||
protected $aValidateRules = array();
|
||||
|
||||
protected $aRelations = array(
|
||||
'targets' => array(self::RELATION_TYPE_HAS_MANY, 'ModuleMedia_EntityTarget', 'media_id'),
|
||||
);
|
||||
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateAdd(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
protected function beforeDelete()
|
||||
{
|
||||
if ($bResult = parent::beforeDelete()) {
|
||||
/**
|
||||
* Удаляем все связи
|
||||
*/
|
||||
$aTargets = $this->getTargets();
|
||||
foreach ($aTargets as $oTarget) {
|
||||
$oTarget->Delete();
|
||||
}
|
||||
/**
|
||||
* Удаляем все файлы медиа
|
||||
*/
|
||||
$this->Media_DeleteFiles($this);
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL до файла нужного размера, в основном используется для изображений
|
||||
*
|
||||
* @param null $sSize
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getFileWebPath($sSize = null)
|
||||
{
|
||||
if ($this->getFilePath()) {
|
||||
return $this->Media_GetFileWebPath($this, $sSize);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
$aData = @unserialize($this->_getDataOne('data'));
|
||||
if (!$aData) {
|
||||
$aData = array();
|
||||
}
|
||||
return $aData;
|
||||
}
|
||||
|
||||
public function setData($aRules)
|
||||
{
|
||||
$this->_aData['data'] = @serialize($aRules);
|
||||
}
|
||||
|
||||
public function getDataOne($sKey)
|
||||
{
|
||||
$aData = $this->getData();
|
||||
if (isset($aData[$sKey])) {
|
||||
return $aData[$sKey];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setDataOne($sKey, $mValue)
|
||||
{
|
||||
$aData = $this->getData();
|
||||
$aData[$sKey] = $mValue;
|
||||
$this->setData($aData);
|
||||
}
|
||||
|
||||
public function getRelationTarget()
|
||||
{
|
||||
return $this->_getDataOne('_relation_entity');
|
||||
}
|
||||
}
|
102
application/classes/modules/media/entity/Target.entity.class.php
Normal file
102
application/classes/modules/media/entity/Target.entity.class.php
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность связи медиа данных с объектами
|
||||
*
|
||||
* @package application.modules.media
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleMedia_EntityTarget extends EntityORM
|
||||
{
|
||||
|
||||
protected $aValidateRules = array();
|
||||
|
||||
protected $aRelations = array(
|
||||
'media' => array(self::RELATION_TYPE_BELONGS_TO, 'ModuleMedia_EntityMedia', 'media_id'),
|
||||
);
|
||||
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateAdd(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
protected function beforeDelete()
|
||||
{
|
||||
if ($bResult = parent::beforeDelete()) {
|
||||
/**
|
||||
* Удаляем превью
|
||||
*/
|
||||
if ($this->getIsPreview() and $oMedia = $this->getMedia()) {
|
||||
$this->Media_RemoveFilePreview($oMedia, $this);
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
$aData = @unserialize($this->_getDataOne('data'));
|
||||
if (!$aData) {
|
||||
$aData = array();
|
||||
}
|
||||
return $aData;
|
||||
}
|
||||
|
||||
public function setData($aRules)
|
||||
{
|
||||
$this->_aData['data'] = @serialize($aRules);
|
||||
}
|
||||
|
||||
public function getDataOne($sKey)
|
||||
{
|
||||
$aData = $this->getData();
|
||||
if (isset($aData[$sKey])) {
|
||||
return $aData[$sKey];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setDataOne($sKey, $mValue)
|
||||
{
|
||||
$aData = $this->getData();
|
||||
$aData[$sKey] = $mValue;
|
||||
$this->setData($aData);
|
||||
}
|
||||
|
||||
public function getPreviewImageItemsWebPath()
|
||||
{
|
||||
$aPreviewItems = array();
|
||||
$sPathbase = $this->getDataOne('image_preview');
|
||||
$aSizes = $this->getDataOne('image_preview_sizes');
|
||||
if ($sPathbase and $aSizes) {
|
||||
foreach ($aSizes as $aSize) {
|
||||
$aPreviewItems[] = $this->Media_GetImageWebPath($sPathbase, $aSize);
|
||||
}
|
||||
}
|
||||
return $aPreviewItems;
|
||||
}
|
||||
}
|
129
application/classes/modules/media/mapper/Media.mapper.class.php
Normal file
129
application/classes/modules/media/mapper/Media.mapper.class.php
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Маппер для работы с БД
|
||||
*
|
||||
* @package application.modules.media
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleMedia_MapperMedia extends Mapper
|
||||
{
|
||||
|
||||
public function GetMediaByTarget($sTargetType, $iTargetId, $iUserId = null)
|
||||
{
|
||||
$sFieldsJoinReturn = $this->GetFieldsRelationTarget();
|
||||
$sql = "SELECT
|
||||
{$sFieldsJoinReturn},
|
||||
m.*
|
||||
FROM " . Config::Get('db.table.media_target') . " AS t
|
||||
JOIN " . Config::Get('db.table.media') . " as m on ( m.id=t.media_id { and m.user_id = ?d } )
|
||||
WHERE
|
||||
t.target_id = ?d
|
||||
AND
|
||||
t.target_type = ?
|
||||
ORDER BY
|
||||
m.id desc
|
||||
limit 0,500";
|
||||
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->select($sql, $iUserId ? $iUserId : DBSIMPLE_SKIP, $iTargetId, $sTargetType)) {
|
||||
$aResult = $this->PrepareResultTarget($aRows);
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function GetMediaByTargetTmp($sTargetTmp, $iUserId = null)
|
||||
{
|
||||
$sFieldsJoinReturn = $this->GetFieldsRelationTarget();
|
||||
$sql = "SELECT
|
||||
{$sFieldsJoinReturn},
|
||||
m.*
|
||||
FROM " . Config::Get('db.table.media_target') . " AS t
|
||||
JOIN " . Config::Get('db.table.media') . " as m on ( m.id=t.media_id { and m.user_id = ?d } )
|
||||
WHERE
|
||||
t.target_tmp = ?
|
||||
ORDER BY
|
||||
m.id desc
|
||||
limit 0,500";
|
||||
|
||||
$aResult = array();
|
||||
if ($aRows = $this->oDb->select($sql, $iUserId ? $iUserId : DBSIMPLE_SKIP, $sTargetTmp)) {
|
||||
$aResult = $this->PrepareResultTarget($aRows);
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
|
||||
public function RemoveTargetByTypeAndId($sTargetType, $iTargetId)
|
||||
{
|
||||
$sql = "DELETE
|
||||
FROM " . Config::Get('db.table.media_target') . "
|
||||
WHERE
|
||||
target_id = ?d
|
||||
AND
|
||||
target_type = ?
|
||||
";
|
||||
if ($this->oDb->query($sql, $iTargetId, $sTargetType) !== false) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function GetFieldsRelationTarget()
|
||||
{
|
||||
$oEntityJoinSample = Engine::GetEntity('ModuleMedia_EntityTarget');
|
||||
/**
|
||||
* Формируем список полей для возврата у таблице связей
|
||||
*/
|
||||
$aFieldsJoinReturn = $oEntityJoinSample->_getFields();
|
||||
foreach ($aFieldsJoinReturn as $k => $sField) {
|
||||
if (!is_numeric($k)) {
|
||||
// Удаляем служебные (примари) поля
|
||||
unset($aFieldsJoinReturn[$k]);
|
||||
continue;
|
||||
}
|
||||
$aFieldsJoinReturn[$k] = "t.`{$sField}` as t_join_{$sField}";
|
||||
}
|
||||
$sFieldsJoinReturn = join(', ', $aFieldsJoinReturn);
|
||||
return $sFieldsJoinReturn;
|
||||
}
|
||||
|
||||
protected function PrepareResultTarget($aRows)
|
||||
{
|
||||
$aResult = array();
|
||||
foreach ($aRows as $aRow) {
|
||||
$aData = array();
|
||||
$aDataRelation = array();
|
||||
foreach ($aRow as $k => $v) {
|
||||
if (strpos($k, 't_join_') === 0) {
|
||||
$aDataRelation[str_replace('t_join_', '', $k)] = $v;
|
||||
} else {
|
||||
$aData[$k] = $v;
|
||||
}
|
||||
}
|
||||
$aData['_relation_entity'] = Engine::GetEntity('ModuleMedia_EntityTarget', $aDataRelation);
|
||||
$oEntity = Engine::GetEntity('ModuleMedia_EntityMedia', $aData);
|
||||
$oEntity->_SetIsNew(false);
|
||||
$aResult[] = $oEntity;
|
||||
}
|
||||
return $aResult;
|
||||
}
|
||||
}
|
79
application/classes/modules/menu/Menu.class.php
Normal file
79
application/classes/modules/menu/Menu.class.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2018 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Oleg Demodov <boxmilo@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description of Menu
|
||||
*
|
||||
* @author oleg
|
||||
*/
|
||||
class ModuleMenu extends ModuleORM {
|
||||
|
||||
const STATE_ITEM_ENABLE = 1;
|
||||
const STATE_ITEM_DISABLE = 0;
|
||||
const STATE_ITEM_ACTIVE = 2;
|
||||
|
||||
private $aMenus = [];
|
||||
|
||||
public function Init() {
|
||||
parent::Init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает дерево пунктов
|
||||
*
|
||||
* @param int $sId MenuId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetItemsTreeByMenuId($sId)
|
||||
{
|
||||
$aItems = $this->LoadTreeOfItem(array('menu_id' => $sId));
|
||||
return ModuleORM::buildTree($aItems);
|
||||
}
|
||||
|
||||
public function Get($sName) {
|
||||
if( !isset($this->aMenus[$sName]) ){
|
||||
$this->aMenus[$sName] = $this->GetMenuByName($sName);
|
||||
}
|
||||
|
||||
return $this->aMenus[$sName];
|
||||
}
|
||||
|
||||
public function GetMenuByName($sName) {
|
||||
if(!$oMenu = $this->GetMenuByFilter(['name' => $sName])){
|
||||
return null;
|
||||
}
|
||||
$aItemsTree = $this->LoadTreeOfItem([
|
||||
'menu_id' => $oMenu->getId(),
|
||||
'#order' => ['priority' => 'asc']
|
||||
]);
|
||||
|
||||
if(is_array($aItemsTree)){
|
||||
foreach ($aItemsTree as $oItem) {
|
||||
$oItem->setParent($oMenu);
|
||||
}
|
||||
}
|
||||
|
||||
$oMenu->setChildren($aItemsTree);
|
||||
return $oMenu;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2018 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Oleg Demodov <boxmilo@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description of Item
|
||||
*
|
||||
* @author oleg
|
||||
*/
|
||||
class ModuleMenu_EntityAbstractItem extends EntityORM{
|
||||
|
||||
|
||||
public function find($sName) {
|
||||
return $this->recursiveSearch($sName, $this->getChildren());
|
||||
}
|
||||
|
||||
public function recursiveSearch($sName, $aItems) {
|
||||
if(!is_array($aItems)){
|
||||
return null;
|
||||
}
|
||||
foreach ($aItems as $oItem) {
|
||||
if($oItem->getName() == $sName){
|
||||
return $oItem;
|
||||
}
|
||||
if($mResult = $this->recursiveSearch($sName, $oItem->getChildren())){
|
||||
return $mResult;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private function findIndex($aItems, $sName){
|
||||
if(!is_array($aItems)){
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($aItems as $key => $oItem) {
|
||||
if($oItem->getName() == $sName){
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function after($oItem) {
|
||||
if(!is_array($oItem)){
|
||||
$oItem = [$oItem];
|
||||
}
|
||||
|
||||
if(get_class($this) == "ModuleMenu_EntityMenu"){
|
||||
return $this;
|
||||
}
|
||||
|
||||
if(!$oParent = $this->getParent()){
|
||||
return $this;
|
||||
}
|
||||
|
||||
$oParent->spliceChild($this->getName(), 1, $oItem);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function before($oItem) {
|
||||
if(get_class($this) == "ModuleMenu_EntityMenu"){
|
||||
return $this;
|
||||
}
|
||||
|
||||
if(!is_array($oItem)){
|
||||
$oItem = [$oItem];
|
||||
}
|
||||
|
||||
if(!$oParent = $this->getParent()){
|
||||
return $this;
|
||||
}
|
||||
|
||||
$oParent->spliceChild($this->getName(), 0, $oItem);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function remove() {
|
||||
if(get_class($this) == "ModuleMenu_EntityMenu"){
|
||||
return $this;
|
||||
}
|
||||
|
||||
if(!$oParent = $this->getParent()){
|
||||
return $this;
|
||||
}
|
||||
|
||||
$oParent->spliceChild($this->getName(), 0, [], 1);
|
||||
}
|
||||
|
||||
public function spliceChild($sName, $iOffset, $aItems, $iRemove=0){
|
||||
|
||||
$aChildrens = $this->getChildren();
|
||||
|
||||
if(!is_array($aChildrens)){
|
||||
return $this;
|
||||
}
|
||||
|
||||
if(($iKey = $this->findIndex($aChildrens, $sName)) === false){
|
||||
return $this;
|
||||
}
|
||||
|
||||
array_splice($aChildrens, $iKey?($iKey+$iOffset):$iKey, $iRemove, $aItems);
|
||||
|
||||
$this->setChildren($aChildrens);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function appendChild($oItem) {
|
||||
$aItems = $this->getChildren();
|
||||
|
||||
if(!is_array($aItems)){
|
||||
$aItems= [];
|
||||
}
|
||||
|
||||
$aItems[] = $oItem;
|
||||
$this->setChildren($aItems);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function prependChild($oItem) {
|
||||
$aItems = $this->getChildren();
|
||||
|
||||
if(!is_array($aItems)){
|
||||
$aItems= [];
|
||||
}
|
||||
|
||||
array_unshift($aItems, $oItem);
|
||||
$this->setChildren($aItems);
|
||||
return $this;
|
||||
}
|
||||
}
|
128
application/classes/modules/menu/entity/Item.entity.class.php
Normal file
128
application/classes/modules/menu/entity/Item.entity.class.php
Normal file
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2018 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Oleg Demodov <boxmilo@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description of Item
|
||||
*
|
||||
* @author oleg
|
||||
*/
|
||||
class ModuleMenu_EntityItem extends ModuleMenu_EntityAbstractItem{
|
||||
|
||||
protected $aRelations = [
|
||||
'menu' => [self::RELATION_TYPE_BELONGS_TO, "ModuleMenu_EntityMenu", 'menu_id'],
|
||||
self::RELATION_TYPE_TREE
|
||||
];
|
||||
|
||||
public function __construct($aData) {
|
||||
parent::__construct($aData);
|
||||
$this->setState(ModuleMenu::STATE_ITEM_ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Определяем правила валидации
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $aValidateRules = array(
|
||||
array('title', 'string', 'max' => 250, 'min' => 1, 'allowEmpty' => false),
|
||||
array('name', 'string', 'max' => 30, 'min' => 1, 'allowEmpty' => true),
|
||||
array('url', 'string', 'max' => 1000, 'min' => 1, 'allowEmpty' => false),
|
||||
array('enable', 'number'),
|
||||
array('active', 'number'),
|
||||
array('pid', 'parent_item'),
|
||||
array('priority', 'number'),
|
||||
array('menu_id', 'menu_id'),
|
||||
);
|
||||
|
||||
public function _getTreeParentKey()
|
||||
{
|
||||
return 'pid';
|
||||
}
|
||||
|
||||
public function beforeSave()
|
||||
{
|
||||
if(!parent::beforeSave()){
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!$this->_getDataOne('enable')){
|
||||
$this->setState(ModuleMenu::STATE_ITEM_DISABLE);
|
||||
return true;
|
||||
}
|
||||
$this->setState(ModuleMenu::STATE_ITEM_ENABLE);
|
||||
|
||||
if($this->_getDataOne('active')){
|
||||
$this->setState(ModuleMenu::STATE_ITEM_ACTIVE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function afterDelete() {
|
||||
parent::afterDelete();
|
||||
|
||||
$aChildrenItems = $this->getChildren();
|
||||
foreach ($aChildrenItems as $oItem) {
|
||||
$oItem->setState(ModuleMenu::STATE_ITEM_DISABLE);
|
||||
$oItem->setPid(null);
|
||||
$oItem->Save();
|
||||
}
|
||||
}
|
||||
|
||||
public function ValidateParentItem($sValue, $aParams)
|
||||
{
|
||||
if(!$sValue){
|
||||
return true;
|
||||
}
|
||||
if (!$oItem = $this->Menu_GetItemById($this->getPid())) {
|
||||
return $this->Lang_Get('menu.message.no_find_parent_item');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function ValidateMenuId($sValue, $aParams)
|
||||
{
|
||||
|
||||
if (!$oMenu = $this->Menu_GetMenuById($this->getMenuId())) {
|
||||
return $this->Lang_Get('menu.message.no_find_menu');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getEnable() {
|
||||
if($this->getState()){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getActive() {
|
||||
if($this->getState() == ModuleMenu::STATE_ITEM_ACTIVE){
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2018 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Oleg Demodov <boxmilo@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description of Menu
|
||||
*
|
||||
* @author oleg
|
||||
*/
|
||||
class ModuleMenu_EntityMenu extends ModuleMenu_EntityAbstractItem {
|
||||
|
||||
public function getItems() {
|
||||
return $this->getChildren();
|
||||
}
|
||||
|
||||
}
|
287
application/classes/modules/poll/Poll.class.php
Normal file
287
application/classes/modules/poll/Poll.class.php
Normal file
|
@ -0,0 +1,287 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Модуль опросов
|
||||
*
|
||||
* @package application.modules.poll
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModulePoll extends ModuleORM
|
||||
{
|
||||
|
||||
/**
|
||||
* Объект текущего пользователя
|
||||
*
|
||||
* @var ModuleUser_EntityUser|null
|
||||
*/
|
||||
protected $oUserCurrent;
|
||||
|
||||
protected $aTargetTypes = array(
|
||||
'topic' => array(),
|
||||
);
|
||||
|
||||
/**
|
||||
* Инициализация
|
||||
*
|
||||
*/
|
||||
public function Init()
|
||||
{
|
||||
parent::Init();
|
||||
$this->oUserCurrent = $this->User_GetUserCurrent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список типов объектов
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetTargetTypes()
|
||||
{
|
||||
return $this->aTargetTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет в разрешенные новый тип
|
||||
*
|
||||
* @param string $sTargetType Тип
|
||||
* @param array $aParams Параметры
|
||||
* @return bool
|
||||
*/
|
||||
public function AddTargetType($sTargetType, $aParams = array())
|
||||
{
|
||||
if (!array_key_exists($sTargetType, $this->aTargetTypes)) {
|
||||
$this->aTargetTypes[$sTargetType] = $aParams;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет разрешен ли данный тип
|
||||
*
|
||||
* @param string $sTargetType Тип
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowTargetType($sTargetType)
|
||||
{
|
||||
return in_array($sTargetType, array_keys($this->aTargetTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает парметры нужного типа
|
||||
*
|
||||
* @param string $sTargetType
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetTargetTypeParams($sTargetType)
|
||||
{
|
||||
if ($this->IsAllowTargetType($sTargetType)) {
|
||||
return $this->aTargetTypes[$sTargetType];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка объекта target - владелец медиа
|
||||
*
|
||||
* @param string $sTargetType Тип
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function CheckTarget($sTargetType, $iTargetId)
|
||||
{
|
||||
if (!$this->IsAllowTargetType($sTargetType)) {
|
||||
return false;
|
||||
}
|
||||
$sMethod = 'CheckTarget' . func_camelize($sTargetType);
|
||||
if (method_exists($this, $sMethod)) {
|
||||
return $this->$sMethod($iTargetId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Заменяет временный идентификатор на необходимый ID объекта
|
||||
*
|
||||
* @param string $sTargetType
|
||||
* @param string $sTargetId
|
||||
* @param null|string $sTargetTmp Если не задан, то берется их куки "poll_target_tmp_{$sTargetType}"
|
||||
*/
|
||||
public function ReplaceTargetTmpById($sTargetType, $sTargetId, $sTargetTmp = null)
|
||||
{
|
||||
$sCookieKey = 'poll_target_tmp_' . $sTargetType;
|
||||
if (is_null($sTargetTmp) and $this->Session_GetCookie($sCookieKey)) {
|
||||
$sTargetTmp = $this->Session_GetCookie($sCookieKey);
|
||||
$this->Session_DropCookie($sCookieKey);
|
||||
}
|
||||
if (is_string($sTargetTmp)) {
|
||||
$aPollItems = $this->Poll_GetPollItemsByTargetTmpAndTargetType($sTargetTmp, $sTargetType);
|
||||
foreach ($aPollItems as $oPoll) {
|
||||
$oPoll->setTargetTmp(null);
|
||||
$oPoll->setTargetId($sTargetId);
|
||||
$oPoll->Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список опросов для объекта
|
||||
*
|
||||
* @param string $sTargetType
|
||||
* @param string $sTargetId
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetPollItemsByTarget($sTargetType, $sTargetId)
|
||||
{
|
||||
$aFilter = array(
|
||||
'target_type' => $sTargetType,
|
||||
'target_id' => $sTargetId,
|
||||
'#with' => array('answers')
|
||||
);
|
||||
if ($this->oUserCurrent) {
|
||||
$aFilter['#with']['vote_current'] = array(
|
||||
'user_id' => $this->oUserCurrent->getId(),
|
||||
'#value-default' => false
|
||||
);
|
||||
} else {
|
||||
$_this = $this;
|
||||
$aFilter['#with']['vote_current'] = array(
|
||||
'#value-default' => false,
|
||||
'#callback-filter' => function ($aPollItems, &$aRelationFilter) use ($_this) {
|
||||
$aWhere = array();
|
||||
$aWhereBind = array();
|
||||
foreach ($aPollItems as $oPoll) {
|
||||
/**
|
||||
* Смотрим по IP
|
||||
*/
|
||||
if($oPoll->getIsGuestCheckIp()) {
|
||||
$aWhere[] = ' ( t.poll_id = ?d and t.ip = ? ) ';
|
||||
$aWhereBind[] = $oPoll->getId();
|
||||
$aWhereBind[] = func_getIp();
|
||||
}
|
||||
/**
|
||||
* Смотрим в куках
|
||||
*/
|
||||
if ($sKey = $_this->Session_GetCookie($_this->GetCookieVoteName($oPoll->getId()))) {
|
||||
$aWhere[] = ' ( t.poll_id = ?d and t.guest_key = ? ) ';
|
||||
$aWhereBind[] = $oPoll->getId();
|
||||
$aWhereBind[] = $sKey;
|
||||
}
|
||||
}
|
||||
if ($aWhere) {
|
||||
$aRelationFilter['#where'] = array(
|
||||
' ( ' . join(' or ', $aWhere) . ' ) ' => $aWhereBind
|
||||
);
|
||||
} else {
|
||||
$aRelationFilter['#value-set'] = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
$aPollItems = $this->Poll_GetPollItemsByFilter($aFilter);
|
||||
return $aPollItems;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Проверка владельца с типом "topic"
|
||||
* Название метода формируется автоматически
|
||||
*
|
||||
* @param int $iTargetId ID владельца
|
||||
* @return bool
|
||||
*/
|
||||
public function CheckTargetTopic($iTargetId)
|
||||
{
|
||||
if ($oTopic = $this->Topic_GetTopicById($iTargetId)) {
|
||||
if (!$oTopicType = $this->Topic_GetTopicType($oTopic->getType()) or !$oTopicType->getParam('allow_poll')) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Проверяем права на редактирование топика
|
||||
*/
|
||||
if ($this->ACL_IsAllowEditTopic($oTopic, $this->oUserCurrent)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Голосовал ли пользователь в опросе
|
||||
*
|
||||
* @param ModulePoll_EntityPoll $oPoll
|
||||
* @param int|null $iUserId Если null, то проверяется для гостя
|
||||
* @return bool
|
||||
*/
|
||||
public function CheckUserAlreadyVote($oPoll, $iUserId)
|
||||
{
|
||||
return $this->GetVoteByUser($oPoll, $iUserId) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект голосования текущего пользователя за конкретный опрос
|
||||
*
|
||||
* @param ModulePoll_EntityPoll $oPoll
|
||||
* @param int|null $iUserId Если null, то проверяется для гостя
|
||||
* @return ModulePoll_EntityVote
|
||||
*/
|
||||
public function GetVoteByUser($oPoll, $iUserId)
|
||||
{
|
||||
$iUserId = is_object($iUserId) ? $iUserId->getId() : $iUserId;
|
||||
if (is_null($iUserId)) {
|
||||
/**
|
||||
* Для гостя
|
||||
* Два варианта - проверка по IP и по кукам
|
||||
*/
|
||||
if ($oPoll->getIsGuestCheckIp()) {
|
||||
if ($oVote = $this->Poll_GetVoteByIpAndPollId(func_getIp(), $oPoll->getId())) {
|
||||
return $oVote;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* По кукам
|
||||
*/
|
||||
if ($sKey = $this->Session_GetCookie($this->GetCookieVoteName($oPoll))) {
|
||||
return $this->Poll_GetVoteByGuestKeyAndPollId($sKey, $oPoll->getId());
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
/**
|
||||
* Для авторизованного
|
||||
*/
|
||||
return $this->Poll_GetVoteByUserIdAndPollId($iUserId, $oPoll->getId());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает название куки для хранения факта голосования
|
||||
*
|
||||
* @param $oPoll
|
||||
* @return string
|
||||
*/
|
||||
public function GetCookieVoteName($oPoll)
|
||||
{
|
||||
$iPollId = is_object($oPoll) ? $oPoll->getId() : $oPoll;
|
||||
return "poll-vote-{$iPollId}";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность ответа в опросе
|
||||
*
|
||||
* @package application.modules.poll
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModulePoll_EntityAnswer extends EntityORM
|
||||
{
|
||||
|
||||
protected $aValidateRules = array(
|
||||
array('title', 'string', 'allowEmpty' => false, 'min' => 1, 'max' => 250),
|
||||
array('title', 'check_title'),
|
||||
);
|
||||
|
||||
protected $aRelations = array(
|
||||
'poll' => array(self::RELATION_TYPE_BELONGS_TO, 'ModulePoll_EntityPoll', 'poll_id'),
|
||||
);
|
||||
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
public function ValidateCheckTitle()
|
||||
{
|
||||
$this->setTitle(htmlspecialchars($this->getTitle()));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
296
application/classes/modules/poll/entity/Poll.entity.class.php
Normal file
296
application/classes/modules/poll/entity/Poll.entity.class.php
Normal file
|
@ -0,0 +1,296 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность опроса
|
||||
*
|
||||
* @package application.modules.poll
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModulePoll_EntityPoll extends EntityORM
|
||||
{
|
||||
|
||||
protected $aValidateRules = array(
|
||||
array('title', 'string', 'allowEmpty' => false, 'min' => 3, 'max' => 250, 'on' => array('create', 'update')),
|
||||
array(
|
||||
'count_answer_max',
|
||||
'number',
|
||||
'allowEmpty' => true,
|
||||
'integerOnly' => true,
|
||||
'min' => 0,
|
||||
'on' => array('create', 'update')
|
||||
),
|
||||
array('type', 'check_type', 'on' => array('create', 'update')),
|
||||
array('answers_raw', 'check_answers_raw', 'on' => array('create', 'update')),
|
||||
array('target_raw', 'check_target_raw', 'on' => array('create')),
|
||||
array('title', 'check_title', 'on' => array('create', 'update')),
|
||||
array('is_guest_allow', 'check_is_guest_allow', 'on' => array('create', 'update')),
|
||||
array('is_guest_check_ip', 'check_is_guest_check_ip', 'on' => array('create', 'update')),
|
||||
);
|
||||
|
||||
protected $aRelations = array(
|
||||
'answers' => array(self::RELATION_TYPE_HAS_MANY, 'ModulePoll_EntityAnswer', 'poll_id'),
|
||||
'vote_current' => array(self::RELATION_TYPE_HAS_ONE, 'ModulePoll_EntityVote', 'poll_id'),
|
||||
);
|
||||
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
protected function afterSave()
|
||||
{
|
||||
parent::afterSave();
|
||||
/**
|
||||
* Сохраняем варианты
|
||||
*/
|
||||
if ($aAnswers = $this->getAnswersObject()) {
|
||||
foreach ($aAnswers as $oAnswer) {
|
||||
$oAnswer->setPollId($this->getId());
|
||||
$oAnswer->Save();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Удаляем варианты
|
||||
*/
|
||||
if ($aAnswers = $this->getAnswersObjectForRemove()) {
|
||||
foreach ($aAnswers as $oAnswer) {
|
||||
$oAnswer->Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function afterDelete()
|
||||
{
|
||||
parent::afterDelete();
|
||||
/**
|
||||
* Удаляем варианты ответов
|
||||
*/
|
||||
$aAnswerItems = $this->Poll_GetAnswerItemsByPollId($this->getId());
|
||||
foreach ($aAnswerItems as $oAnswer) {
|
||||
$oAnswer->Delete();
|
||||
}
|
||||
/**
|
||||
* Удаляем голосования
|
||||
*/
|
||||
$aVoteItems = $this->Poll_GetVoteItemsByPollId($this->getId());
|
||||
foreach ($aVoteItems as $oVote) {
|
||||
$oVote->Delete();
|
||||
}
|
||||
}
|
||||
|
||||
public function ValidateCheckTitle()
|
||||
{
|
||||
$this->setTitle(htmlspecialchars($this->getTitle()));
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ValidateCheckIsGuestAllow()
|
||||
{
|
||||
$this->setIsGuestAllow($this->getIsGuestAllow() ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ValidateCheckIsGuestCheckIp()
|
||||
{
|
||||
$this->setIsGuestCheckIp($this->getIsGuestCheckIp() ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ValidateCheckType()
|
||||
{
|
||||
if (!$this->_isNew() and $this->getCountVote()) {
|
||||
/**
|
||||
* Запрещаем смену типа
|
||||
*/
|
||||
$this->setCountAnswerMax($this->_getOriginalDataOne('count_answer_max'));
|
||||
return true;
|
||||
}
|
||||
$iCount = $this->getCountAnswerMax();
|
||||
if ($this->getType() == 'one') {
|
||||
$this->setCountAnswerMax(1);
|
||||
return true;
|
||||
} else {
|
||||
if ($iCount < 2) {
|
||||
return $this->Lang_Get('poll.notices.error_answers_max_wrong');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ValidateCheckAnswersRaw()
|
||||
{
|
||||
if (!$this->_isNew() and !$this->isAllowUpdate()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$aAnswersRaw = $this->getAnswersRaw();
|
||||
if (!is_array($aAnswersRaw) or count($aAnswersRaw) < 2) {
|
||||
return $this->Lang_Get('poll.notices.error_answers_count');
|
||||
}
|
||||
/**
|
||||
* Здесь может быть два варианта - создание опроса или редактирование, при редактирование могут передаваться ID ответов
|
||||
*/
|
||||
if (!$this->_isNew()) {
|
||||
$aAnswersOld = $this->Poll_GetAnswerItemsByFilter(array(
|
||||
'poll_id' => $this->getId(),
|
||||
'#index-from-primary'
|
||||
));
|
||||
} else {
|
||||
$aAnswersOld = array();
|
||||
}
|
||||
$aAnswers = array();
|
||||
foreach ($aAnswersRaw as $aAnswer) {
|
||||
if ($this->_isNew() or !(isset($aAnswer['id']) and isset($aAnswersOld[$aAnswer['id']]) and $oAnswer = $aAnswersOld[$aAnswer['id']])) {
|
||||
$oAnswer = Engine::GetEntity('ModulePoll_EntityAnswer');
|
||||
}
|
||||
if ($oAnswer->getId()) {
|
||||
/**
|
||||
* Фильтруем список старых ответов для будущего удаления оставшихся
|
||||
*/
|
||||
unset($aAnswersOld[$oAnswer->getId()]);
|
||||
}
|
||||
$oAnswer->setTitle(isset($aAnswer['title']) ? $aAnswer['title'] : '');
|
||||
if (!$oAnswer->_Validate()) {
|
||||
return $oAnswer->_getValidateError();
|
||||
}
|
||||
$aAnswers[] = $oAnswer;
|
||||
}
|
||||
$this->setAnswersObject($aAnswers);
|
||||
|
||||
foreach ($aAnswersOld as $oAnswer) {
|
||||
if ($oAnswer->getCountVote()) {
|
||||
return $this->Lang_Get('poll.notices.error_answer_remove');
|
||||
}
|
||||
}
|
||||
|
||||
$this->setAnswersObjectForRemove($aAnswersOld);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ValidateCheckTargetRaw()
|
||||
{
|
||||
$aTarget = $this->getTargetRaw();
|
||||
|
||||
$sTargetType = isset($aTarget['type']) ? $aTarget['type'] : '';
|
||||
$sTargetId = isset($aTarget['id']) ? $aTarget['id'] : '';
|
||||
$sTargetTmp = isset($aTarget['tmp']) ? $aTarget['tmp'] : '';
|
||||
|
||||
if ($sTargetId) {
|
||||
$sTargetTmp = null;
|
||||
if (!$this->Poll_CheckTarget($sTargetType, $sTargetId)) {
|
||||
return $this->Lang_Get('poll.notices.error_target_type');
|
||||
}
|
||||
} else {
|
||||
$sTargetId = null;
|
||||
if (!$sTargetTmp or !$this->Poll_IsAllowTargetType($sTargetType)) {
|
||||
return $this->Lang_Get('poll.notices.error_target_type');
|
||||
}
|
||||
if ($this->Poll_GetPollByFilter(array('target_tmp' => $sTargetTmp, 'target_type <>' => $sTargetType))) {
|
||||
return $this->Lang_Get('poll.notices.error_target_tmp');
|
||||
}
|
||||
}
|
||||
|
||||
$this->setTargetType($sTargetType);
|
||||
$this->setTargetId($sTargetId);
|
||||
$this->setTargetTmp($sTargetTmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет доступность опроса для изменения
|
||||
* Важно понимать, что здесь нет проверки на права доступа
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowUpdate()
|
||||
{
|
||||
$iTime = $this->getDateCreate();
|
||||
if ((time() - strtotime($iTime)) > Config::Get('module.poll.time_limit_update')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет возможность удаления опроса, не пользователем, а в принципе
|
||||
* Важно понимать, что здесь нет проверки на права доступа
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowRemove()
|
||||
{
|
||||
if ($this->getCountVote() || $this->getCountAbstain()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет возможность голосования в опросе, не пользователем, а в принципе
|
||||
* Важно понимать, что здесь нет проверки на права доступа
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowVote()
|
||||
{
|
||||
$sDateEnd = $this->getDateEnd();
|
||||
if ($sDateEnd and (time() - strtotime($sDateEnd)) > 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getAnswerPercent($oAnswer)
|
||||
{
|
||||
$iCountAll = $this->getCountVote();
|
||||
if ($iCountAll == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return number_format(round($oAnswer->getCountVote() * 100 / $iCountAll, 1), 1, '.', '');
|
||||
}
|
||||
}
|
||||
|
||||
public function getCountVoteAnswerMax()
|
||||
{
|
||||
$iMax = 0;
|
||||
$aAnswers = $this->getAnswers();
|
||||
foreach ($aAnswers as $oAnswer) {
|
||||
if ($oAnswer->getCountVote() > $iMax) {
|
||||
$iMax = $oAnswer->getCountVote();
|
||||
}
|
||||
}
|
||||
return $iMax;
|
||||
}
|
||||
|
||||
public function getVoteCurrent()
|
||||
{
|
||||
if (array_key_exists('vote_current', $this->aRelationsData)) {
|
||||
return $this->aRelationsData['vote_current'];
|
||||
}
|
||||
return $this->Poll_GetVoteByUser($this, $this->User_GetUserCurrent());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность голосования в опросе
|
||||
*
|
||||
* @package application.modules.poll
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModulePoll_EntityVote extends EntityORM
|
||||
{
|
||||
|
||||
protected $aValidateRules = array();
|
||||
|
||||
protected $aRelations = array(
|
||||
'poll' => array(self::RELATION_TYPE_BELONGS_TO, 'ModulePoll_EntityPoll', 'poll_id'),
|
||||
);
|
||||
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
$this->setIp(func_getIp());
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
protected function afterSave()
|
||||
{
|
||||
parent::afterSave();
|
||||
if ($this->_isNew()) {
|
||||
/**
|
||||
* Отмечаем факт голосования в опросе и вариантах
|
||||
*/
|
||||
$oPoll = $this->getPoll();
|
||||
$aAnswerItems = $this->getAnswersObject();
|
||||
if ($aAnswerItems) {
|
||||
foreach ($aAnswerItems as $oAnswer) {
|
||||
$oAnswer->setCountVote($oAnswer->getCountVote() + 1);
|
||||
$oAnswer->Update();
|
||||
}
|
||||
$oPoll->setCountVote($oPoll->getCountVote() + 1);
|
||||
} else {
|
||||
$oPoll->setCountAbstain($oPoll->getCountAbstain() + 1);
|
||||
}
|
||||
$oPoll->Update(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список вариантов, за которые голосовали
|
||||
*
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getAnswers()
|
||||
{
|
||||
$aData = @unserialize($this->_getDataOne('answers'));
|
||||
if (!$aData) {
|
||||
$aData = array();
|
||||
}
|
||||
return $aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает список вариантов, за которые голосовали
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function setAnswers($aParams)
|
||||
{
|
||||
$this->_aData['answers'] = @serialize($aParams);
|
||||
}
|
||||
}
|
971
application/classes/modules/property/Property.class.php
Normal file
971
application/classes/modules/property/Property.class.php
Normal file
|
@ -0,0 +1,971 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Модуль управления дополнительными полями
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty extends ModuleORM
|
||||
{
|
||||
/**
|
||||
* Список возможных типов свойств/полей
|
||||
*/
|
||||
const PROPERTY_TYPE_INT = 'int';
|
||||
const PROPERTY_TYPE_FLOAT = 'float';
|
||||
const PROPERTY_TYPE_VARCHAR = 'varchar';
|
||||
const PROPERTY_TYPE_TEXT = 'text';
|
||||
const PROPERTY_TYPE_CHECKBOX = 'checkbox';
|
||||
const PROPERTY_TYPE_TAGS = 'tags';
|
||||
const PROPERTY_TYPE_VIDEO_LINK = 'video_link';
|
||||
const PROPERTY_TYPE_SELECT = 'select';
|
||||
const PROPERTY_TYPE_DATE = 'date';
|
||||
const PROPERTY_TYPE_FILE = 'file';
|
||||
const PROPERTY_TYPE_IMAGE = 'image';
|
||||
const PROPERTY_TYPE_IMAGESET = 'imageset';
|
||||
/**
|
||||
* Список состояний типов объектов
|
||||
*/
|
||||
const TARGET_STATE_ACTIVE = 1;
|
||||
const TARGET_STATE_NOT_ACTIVE = 2;
|
||||
const TARGET_STATE_REMOVE = 3;
|
||||
|
||||
protected $oMapper = null;
|
||||
/**
|
||||
* Список доступных типов полей
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aPropertyTypes = array(
|
||||
self::PROPERTY_TYPE_INT,
|
||||
self::PROPERTY_TYPE_FLOAT,
|
||||
self::PROPERTY_TYPE_VARCHAR,
|
||||
self::PROPERTY_TYPE_TEXT,
|
||||
self::PROPERTY_TYPE_CHECKBOX,
|
||||
self::PROPERTY_TYPE_TAGS,
|
||||
self::PROPERTY_TYPE_VIDEO_LINK,
|
||||
self::PROPERTY_TYPE_SELECT,
|
||||
self::PROPERTY_TYPE_DATE,
|
||||
self::PROPERTY_TYPE_FILE,
|
||||
self::PROPERTY_TYPE_IMAGE,
|
||||
self::PROPERTY_TYPE_IMAGESET
|
||||
);
|
||||
/**
|
||||
* Список разрешенных типов
|
||||
* На данный момент допустимы параметры entity=>ModuleTest_EntityTest - указывает на класс сущности
|
||||
* name=>Статьи
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aTargetTypes = array();
|
||||
|
||||
public function Init()
|
||||
{
|
||||
parent::Init();
|
||||
$this->oMapper = Engine::GetMapper(__CLASS__);
|
||||
|
||||
/**
|
||||
* Получаем типы из БД и активируем их
|
||||
*/
|
||||
if ($aTargetItems = $this->GetTargetItemsByFilter(array('state' => self::TARGET_STATE_ACTIVE))) {
|
||||
foreach ($aTargetItems as $oTarget) {
|
||||
$this->Property_AddTargetType($oTarget->getType(), $oTarget->getParams());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список типов объектов
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetTargetTypes()
|
||||
{
|
||||
return $this->aTargetTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Добавляет в разрешенные новый тип
|
||||
*
|
||||
* @param string $sTargetType Тип
|
||||
* @param array $aParams Параметры
|
||||
* @return bool
|
||||
*/
|
||||
public function AddTargetType($sTargetType, $aParams = array())
|
||||
{
|
||||
if (!array_key_exists($sTargetType, $this->aTargetTypes)) {
|
||||
$this->aTargetTypes[$sTargetType] = $aParams;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет разрешен ли данный тип
|
||||
*
|
||||
* @param string $sTargetType Тип
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowTargetType($sTargetType)
|
||||
{
|
||||
return in_array($sTargetType, array_keys($this->aTargetTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает парметры нужного типа
|
||||
*
|
||||
* @param string $sTargetType
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetTargetTypeParams($sTargetType)
|
||||
{
|
||||
if ($this->IsAllowTargetType($sTargetType)) {
|
||||
return $this->aTargetTypes[$sTargetType];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет разрешен ли тип поля
|
||||
*
|
||||
* @param string $sType
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function IsAllowPropertyType($sType)
|
||||
{
|
||||
return in_array($sType, $this->aPropertyTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Для каждого из свойств получает значение
|
||||
*
|
||||
* @param array $aProperties Список свойств
|
||||
* @param string $sTargetType Тип объекта
|
||||
* @param int $iTargetId ID объекта
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function AttachValueForProperties($aProperties, $sTargetType, $iTargetId)
|
||||
{
|
||||
if (!$aProperties) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Формируем список ID свойств
|
||||
*/
|
||||
$aPropertyIds = array();
|
||||
foreach ($aProperties as $oProperty) {
|
||||
$aPropertyIds[] = $oProperty->getId();
|
||||
}
|
||||
/**
|
||||
* Получаем список значений
|
||||
*/
|
||||
$aValues = $this->Property_GetValueItemsByFilter(array(
|
||||
'target_id' => $iTargetId,
|
||||
'target_type' => $sTargetType,
|
||||
'property_id in' => $aPropertyIds,
|
||||
'#index-from' => 'property_id'
|
||||
));
|
||||
/**
|
||||
* Аттачим значения к свойствам
|
||||
*/
|
||||
foreach ($aProperties as $oProperty) {
|
||||
if (isset($aValues[$oProperty->getId()])) {
|
||||
$oProperty->setValue($aValues[$oProperty->getId()]);
|
||||
} else {
|
||||
$oProperty->setValue(Engine::GetEntity('ModuleProperty_EntityValue', array(
|
||||
'property_id' => $oProperty->getId(),
|
||||
'property_type' => $oProperty->getType(),
|
||||
'target_type' => $sTargetType,
|
||||
'target_id' => $iTargetId
|
||||
)));
|
||||
}
|
||||
$oProperty->getValue()->setProperty($oProperty);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохраняет текущие значения свойств
|
||||
*
|
||||
* @param array $aProperties
|
||||
* @param Entity|int $oTarget Объект сущности или ID сущности
|
||||
*/
|
||||
public function UpdatePropertiesValue($aProperties, $oTarget)
|
||||
{
|
||||
if ($aProperties) {
|
||||
foreach ($aProperties as $oProperty) {
|
||||
$oValue = $oProperty->getValue();
|
||||
$oValue->setTargetId(is_object($oTarget) ? $oTarget->getId() : $oTarget);
|
||||
$oValue->setPropertyType($oProperty->getType());
|
||||
$oValue->Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаление всех свойств у конкретного объекта/сущности
|
||||
*
|
||||
* @param Entity $oTarget
|
||||
*/
|
||||
public function RemovePropertiesValue($oTarget)
|
||||
{
|
||||
$aProperties = $this->Property_GetPropertyItemsByFilter(array('target_type' => $oTarget->property->getPropertyTargetType()));
|
||||
if ($aProperties) {
|
||||
$this->AttachValueForProperties($aProperties, $oTarget->property->getPropertyTargetType(),
|
||||
$oTarget->getId());
|
||||
foreach ($aProperties as $oProperty) {
|
||||
$oValue = $oProperty->getValue();
|
||||
if ($oValue and $oValue->getId()) {
|
||||
$oValueType = $oValue->getValueTypeObject();
|
||||
/**
|
||||
* Кастомное удаление
|
||||
*/
|
||||
$oValueType->removeValue();
|
||||
/**
|
||||
* Удаляем основные данные
|
||||
*/
|
||||
$oValue->Delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Валидирует значение свойств у объекта
|
||||
*
|
||||
* @param Entity $oTarget
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
public function ValidateEntityPropertiesCheck($oTarget)
|
||||
{
|
||||
/**
|
||||
* Пробуем получить свойства из реквеста
|
||||
*/
|
||||
$oTarget->setProperties($oTarget->getProperties() ? $oTarget->getProperties() : getRequest('property'));
|
||||
$aPropertiesValue = $oTarget->getProperties();
|
||||
$aPropertiesResult = array();
|
||||
/**
|
||||
* Получаем весь список свойств у объекта
|
||||
*/
|
||||
$aPropertiesObject = $this->Property_GetPropertyItemsByFilter(array('target_type' => $oTarget->property->getPropertyTargetType()));
|
||||
$this->Property_AttachValueForProperties($aPropertiesObject, $oTarget->property->getPropertyTargetType(),
|
||||
$oTarget->getId());
|
||||
foreach ($aPropertiesObject as $oProperty) {
|
||||
$oValue = $oProperty->getValue();
|
||||
$sValue = isset($aPropertiesValue[$oProperty->getId()]) ? $aPropertiesValue[$oProperty->getId()] : null;
|
||||
/**
|
||||
* Валидируем значение
|
||||
*/
|
||||
$oValueType = $oValue->getValueTypeObject();
|
||||
$oValueType->setValueForValidate($sValue);
|
||||
if (true === ($sRes = $oValueType->validate())) {
|
||||
$oValueType->setValue($oValueType->getValueForValidate());
|
||||
$aPropertiesResult[$oProperty->getId()] = $oProperty;
|
||||
} else {
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает значение свойсва у объекта
|
||||
*
|
||||
* @param Entity $oTarget Объект сущности
|
||||
* @param int $sPropertyId ID свойства
|
||||
*
|
||||
* @return null|mixed
|
||||
*/
|
||||
public function GetEntityPropertyValue($oTarget, $sPropertyId)
|
||||
{
|
||||
if ($oProperty = $this->GetEntityPropertyValueObject($oTarget, $sPropertyId)) {
|
||||
return $oProperty->getValue()->getValueForDisplay();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект свойства сущности
|
||||
*
|
||||
* @param Entity $oTarget Объект сущности
|
||||
* @param int $sPropertyId ID свойства
|
||||
*
|
||||
* @return null|ModuleProperty_EntityProperty
|
||||
*/
|
||||
public function GetEntityProperty($oTarget, $sPropertyId)
|
||||
{
|
||||
if ($oProperty = $this->GetEntityPropertyValueObject($oTarget, $sPropertyId)) {
|
||||
return $oProperty;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список свойств сущности
|
||||
*
|
||||
* @param Entity $oTarget Объект сущности
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetEntityPropertyList($oTarget)
|
||||
{
|
||||
$sTargetType = $oTarget->property->getPropertyTargetType();
|
||||
/**
|
||||
* Проверяем зарегистрирован ли такой тип
|
||||
*/
|
||||
if (!$this->IsAllowTargetType($sTargetType)) {
|
||||
return array();
|
||||
}
|
||||
if (!$oTarget->getPropertyIsLoadAll()) {
|
||||
$aProperties = $this->oMapper->GetPropertiesValueByTarget($oTarget->property->getPropertyTargetType(),
|
||||
$oTarget->getId());
|
||||
$this->AttachPropertiesForTarget($oTarget, $aProperties);
|
||||
}
|
||||
return $oTarget->_getDataOne('property_list');
|
||||
}
|
||||
|
||||
/**
|
||||
* Служебный метод для аттача свойст к сущности
|
||||
*
|
||||
* @param Entity $oTarget Объект сущности
|
||||
* @param array $aProperties Список свойств
|
||||
*/
|
||||
public function AttachPropertiesForTarget($oTarget, $aProperties)
|
||||
{
|
||||
$oTarget->setPropertyList($aProperties);
|
||||
$oTarget->setPropertyIsLoadAll(true);
|
||||
$aMapperCode = array();
|
||||
foreach ($aProperties as $oProperty) {
|
||||
$aMapperCode[$oProperty->getCode()] = $oProperty->getId();
|
||||
}
|
||||
$oTarget->setPropertyMapperCode($aMapperCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект свойства
|
||||
*
|
||||
* @param Entity $oTarget Объект сущности
|
||||
* @param array $sPropertyId ID свойства
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function GetEntityPropertyValueObject($oTarget, $sPropertyId)
|
||||
{
|
||||
if (!$oTarget->getPropertyIsLoadAll()) {
|
||||
/**
|
||||
* Загружаем все свойства
|
||||
*/
|
||||
$aProperties = $this->oMapper->GetPropertiesValueByTarget($oTarget->property->getPropertyTargetType(),
|
||||
$oTarget->getId());
|
||||
$this->AttachPropertiesForTarget($oTarget, $aProperties);
|
||||
}
|
||||
|
||||
if (!is_numeric($sPropertyId)) {
|
||||
$aMapperCode = $oTarget->getPropertyMapperCode();
|
||||
if (isset($aMapperCode[$sPropertyId])) {
|
||||
$sPropertyId = $aMapperCode[$sPropertyId];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
$aProperties = $oTarget->property->getPropertyList();
|
||||
if (isset($aProperties[$sPropertyId])) {
|
||||
return $aProperties[$sPropertyId];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Переопределяем метод для возможности цеплять свои кастомные данные при ORM запросах - свойства
|
||||
*
|
||||
* @param array $aResult
|
||||
* @param array $aFilter
|
||||
* @param null|string $sEntityFull
|
||||
*/
|
||||
public function RewriteGetItemsByFilter($aResult, $aFilter = array(), $sEntityFull = null)
|
||||
{
|
||||
if (!$aResult) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Список на входе может быть двух видом:
|
||||
* 1 - одномерный массив
|
||||
* 2 - двумерный, если применялась группировка (использование '#index-group')
|
||||
*
|
||||
* Поэтому сначала сформируем линейный список
|
||||
*/
|
||||
if (isset($aFilter['#index-group']) and $aFilter['#index-group']) {
|
||||
$aEntitiesWork = array();
|
||||
foreach ($aResult as $aItems) {
|
||||
foreach ($aItems as $oItem) {
|
||||
$aEntitiesWork[] = $oItem;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$aEntitiesWork = $aResult;
|
||||
}
|
||||
|
||||
if (!$aEntitiesWork) {
|
||||
return;
|
||||
}
|
||||
$oEntityFirst = reset($aEntitiesWork);
|
||||
if (!$oEntityFirst->property) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Проверяем необходимость цеплять свойства
|
||||
*/
|
||||
if (isset($aFilter['#properties']) and $aFilter['#properties']) {
|
||||
$aEntitiesId = array();
|
||||
$aTargetTypes = array();
|
||||
foreach ($aEntitiesWork as $oEntity) {
|
||||
$sTargetType = $oEntity->property->getPropertyTargetType();
|
||||
if ($this->IsAllowTargetType($sTargetType)) {
|
||||
$aEntitiesId[] = $oEntity->getId();
|
||||
$aTargetTypes[] = $sTargetType;
|
||||
}
|
||||
}
|
||||
$aTargetTypes = array_unique($aTargetTypes);
|
||||
/**
|
||||
* Получаем все свойства со значениями для всех объектов
|
||||
*/
|
||||
$aResult = $this->oMapper->GetPropertiesValueByTargetArray($aTargetTypes, $aEntitiesId);
|
||||
if ($aResult) {
|
||||
/**
|
||||
* Формируем список свойств и значений
|
||||
*/
|
||||
$aProperties = array();
|
||||
$aValues = array();
|
||||
foreach ($aResult as $aRow) {
|
||||
$aPropertyData = array();
|
||||
$aValueData = array();
|
||||
foreach ($aRow as $k => $v) {
|
||||
if (strpos($k, 'prop_') === 0) {
|
||||
$aPropertyData[str_replace('prop_', '', $k)] = $v;
|
||||
} else {
|
||||
$aValueData[$k] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($aProperties[$aRow['prop_id']])) {
|
||||
$oProperty = Engine::GetEntity('ModuleProperty_EntityProperty', $aPropertyData);
|
||||
$aProperties[$aRow['prop_id']] = $oProperty;
|
||||
}
|
||||
if ($aRow['target_id']) {
|
||||
$sKey = $aRow['property_id'] . '_' . $aRow['target_id'];
|
||||
$aValues[$sKey] = Engine::GetEntity('ModuleProperty_EntityValue', $aValueData);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Собираем данные
|
||||
*/
|
||||
foreach ($aEntitiesWork as $oEntity) {
|
||||
$aPropertiesClone = array();
|
||||
foreach ($aProperties as $oProperty) {
|
||||
if ($oEntity->property->getPropertyTargetType() != $oProperty->getTargetType()) {
|
||||
continue;
|
||||
}
|
||||
$oPropertyNew = clone $oProperty;
|
||||
$sKey = $oProperty->getId() . '_' . $oEntity->getId();
|
||||
if (isset($aValues[$sKey])) {
|
||||
$oValue = $aValues[$sKey];
|
||||
} else {
|
||||
$oValue = Engine::GetEntity('ModuleProperty_EntityValue', array(
|
||||
'property_type' => $oProperty->getType(),
|
||||
'property_id' => $oProperty->getId(),
|
||||
'target_type' => $oProperty->getTargetType(),
|
||||
'target_id' => $oEntity->getId()
|
||||
));
|
||||
}
|
||||
$oPropertyNew->setValue($oValue);
|
||||
$oValue->setProperty($oPropertyNew);
|
||||
$aPropertiesClone[$oPropertyNew->getId()] = $oPropertyNew;
|
||||
}
|
||||
$this->AttachPropertiesForTarget($oEntity, $aPropertiesClone);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка фильтра ORM запросов
|
||||
*
|
||||
* @param array $aFilter
|
||||
* @param array $sEntityFull
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function RewriteFilter($aFilter, $sEntityFull)
|
||||
{
|
||||
$oEntitySample = Engine::GetEntity($sEntityFull);
|
||||
if (!$oEntitySample->property) {
|
||||
return $aFilter;
|
||||
}
|
||||
|
||||
if (!isset($aFilter['#join'])) {
|
||||
$aFilter['#join'] = array();
|
||||
}
|
||||
$aPropFields = array();
|
||||
foreach ($aFilter as $k => $v) {
|
||||
if (preg_match('@^#prop:(.+)$@i', $k, $aMatch)) {
|
||||
/**
|
||||
* Сначала формируем список полей с операндами
|
||||
*/
|
||||
$aK = explode(' ', trim($aMatch[1]), 2);
|
||||
$sPropCurrent = $aK[0];
|
||||
$sConditionCurrent = ' = ';
|
||||
if (count($aK) > 1) {
|
||||
$sConditionCurrent = strtolower($aK[1]);
|
||||
}
|
||||
$aPropFields[$sPropCurrent] = array('value' => $v, 'condition' => $sConditionCurrent);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Проверяем на наличие сортировки по полям
|
||||
*/
|
||||
$aOrders = array();
|
||||
if (isset($aFilter['#order'])) {
|
||||
if (!is_array($aFilter['#order'])) {
|
||||
$aFilter['#order'] = array($aFilter['#order']);
|
||||
}
|
||||
foreach ($aFilter['#order'] as $key => $value) {
|
||||
$aKeys = explode(':', $key);
|
||||
if (count($aKeys) == 2 and strtolower($aKeys[0]) == 'prop') {
|
||||
$aOrders[$aKeys[1]] = array('way' => $value, 'replace' => $key);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Получаем данные по полям
|
||||
*/
|
||||
if ($aPropFields) {
|
||||
$sTargetType = $oEntitySample->property->getPropertyTargetType();
|
||||
$aProperties = $this->Property_GetPropertyItemsByFilter(array(
|
||||
'code in' => array_keys($aPropFields),
|
||||
'target_type' => $sTargetType
|
||||
));
|
||||
$iPropNum = 0;
|
||||
foreach ($aProperties as $oProperty) {
|
||||
/**
|
||||
* По каждому полю строим JOIN запрос
|
||||
*/
|
||||
$sCondition = $aPropFields[$oProperty->getCode()]['condition'];
|
||||
$bIsArray = in_array(strtolower($sCondition), array('in', 'not in')) ? true : false;
|
||||
if (in_array($oProperty->getType(),
|
||||
array(ModuleProperty::PROPERTY_TYPE_INT, ModuleProperty::PROPERTY_TYPE_CHECKBOX))) {
|
||||
$sFieldValue = "value_int";
|
||||
$sConditionFull = $sCondition . ($bIsArray ? ' (?a) ' : ' ?d ');
|
||||
} elseif ($oProperty->getType() == ModuleProperty::PROPERTY_TYPE_FLOAT) {
|
||||
$sFieldValue = "value_float";
|
||||
$sConditionFull = $sCondition . ($bIsArray ? ' (?a) ' : ' ?f ');
|
||||
} elseif (in_array($oProperty->getType(), array(
|
||||
ModuleProperty::PROPERTY_TYPE_VARCHAR,
|
||||
ModuleProperty::PROPERTY_TYPE_TAGS,
|
||||
ModuleProperty::PROPERTY_TYPE_VIDEO_LINK
|
||||
))) {
|
||||
$sFieldValue = "value_varchar";
|
||||
$sConditionFull = $sCondition . ($bIsArray ? ' (?a) ' : ' ? ');
|
||||
} elseif ($oProperty->getType() == ModuleProperty::PROPERTY_TYPE_TEXT) {
|
||||
$sFieldValue = "value_text";
|
||||
$sConditionFull = $sCondition . ($bIsArray ? ' (?a) ' : ' ? ');
|
||||
} else {
|
||||
$sFieldValue = "value_varchar";
|
||||
$sConditionFull = $sCondition . ($bIsArray ? ' (?a) ' : ' ? ');
|
||||
}
|
||||
$iPropNum++;
|
||||
$sJoin = "JOIN " . Config::Get('db.table.property_value') . " propv{$iPropNum} ON
|
||||
t.`{$oEntitySample->_getPrimaryKey()}` = propv{$iPropNum}.target_id and
|
||||
propv{$iPropNum}.target_type = '{$sTargetType}' and
|
||||
propv{$iPropNum}.property_id = {$oProperty->getId()} and
|
||||
propv{$iPropNum}.{$sFieldValue} {$sConditionFull}";
|
||||
$aFilter['#join'][$sJoin] = array($aPropFields[$oProperty->getCode()]['value']);
|
||||
/**
|
||||
* Проверяем на сортировку по текущему полю
|
||||
*/
|
||||
if (isset($aOrders[$oProperty->getCode()])) {
|
||||
$aOrders[$oProperty->getCode()]['field'] = "propv{$iPropNum}.{$sFieldValue}";
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Подменяем сортировку
|
||||
*/
|
||||
foreach ($aOrders as $aItem) {
|
||||
if (isset($aFilter['#order'][$aItem['replace']])) {
|
||||
$aFilter['#order'] = $this->ArrayReplaceKey($aFilter['#order'], $aItem['replace'], $aItem['field']);
|
||||
}
|
||||
}
|
||||
return $aFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Служебный метод для замены ключа в массиве
|
||||
*
|
||||
* @param array $aArray
|
||||
* @param string $sKeyOld
|
||||
* @param string $sKeyNew
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
protected function ArrayReplaceKey($aArray, $sKeyOld, $sKeyNew)
|
||||
{
|
||||
$aKeys = array_keys($aArray);
|
||||
if (false === $iIndex = array_search($sKeyOld, $aKeys)) {
|
||||
return false;
|
||||
}
|
||||
$aKeys[$iIndex] = $sKeyNew;
|
||||
return array_combine($aKeys, array_values($aArray));
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет теги свойства у сущности
|
||||
*
|
||||
* @param string $sTargetType Тип объекта сущности
|
||||
* @param int $iTargetId ID объекта сущности
|
||||
* @param int $iPropertyId ID свойства
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function RemoveValueTagsByTarget($sTargetType, $iTargetId, $iPropertyId)
|
||||
{
|
||||
// сбрасываем кеш
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('ModuleProperty_EntityValueTag_delete'));
|
||||
return $this->oMapper->RemoveValueTagsByTarget($sTargetType, $iTargetId, $iPropertyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет значения типа select
|
||||
*
|
||||
* @param string $sTargetType Тип объекта сущности
|
||||
* @param int $iTargetId ID объекта сущности
|
||||
* @param int $iPropertyId ID свойства
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function RemoveValueSelectsByTarget($sTargetType, $iTargetId, $iPropertyId)
|
||||
{
|
||||
// сбрасываем кеш
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('ModuleProperty_EntityValueSelect_delete'));
|
||||
return $this->oMapper->RemoveValueSelectsByTarget($sTargetType, $iTargetId, $iPropertyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список тегов/знаяений свойства. Используется для авкомплиттера тегов.
|
||||
*
|
||||
* @param string $sTag
|
||||
* @param int $iPropertyId
|
||||
* @param int $iLimit
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetPropertyTagsByLike($sTag, $iPropertyId, $iLimit)
|
||||
{
|
||||
return $this->oMapper->GetPropertyTagsByLike($sTag, $iPropertyId, $iLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращет список группированных тегов с их количеством для необходимого свойства
|
||||
*
|
||||
* @param int $iPropertyId
|
||||
* @param int $iLimit
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetPropertyTagsGroup($iPropertyId, $iLimit)
|
||||
{
|
||||
return $this->oMapper->GetPropertyTagsGroup($iPropertyId, $iLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует и возвращает облако тегов необходимого свойства
|
||||
*
|
||||
* @param int $iPropertyId
|
||||
* @param int $iLimit
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetPropertyTagsCloud($iPropertyId, $iLimit)
|
||||
{
|
||||
$aTags = $this->Property_GetPropertyTagsGroup($iPropertyId, $iLimit);
|
||||
if ($aTags) {
|
||||
$this->Tools_MakeCloud($aTags);
|
||||
}
|
||||
return $aTags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Список ID сущностей по тегу конкретного свойства
|
||||
*
|
||||
* @param int $iPropertyId
|
||||
* @param string $sTag
|
||||
* @param int $iCurrPage
|
||||
* @param int $iPerPage
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function GetTargetsByTag($iPropertyId, $sTag, $iCurrPage, $iPerPage)
|
||||
{
|
||||
return array(
|
||||
'collection' => $this->oMapper->GetTargetsByTag($iPropertyId, $sTag, $iCount, $iCurrPage, $iPerPage),
|
||||
'count' => $iCount
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Производит изменение названия типа объекта, например "article" меняем на "news"
|
||||
*
|
||||
* @param $sType
|
||||
* @param $sTypeNew
|
||||
*/
|
||||
public function ChangeTargetType($sType, $sTypeNew)
|
||||
{
|
||||
$this->oMapper->UpdatePropertyByTargetType($sType, $sTypeNew);
|
||||
$this->oMapper->UpdatePropertyTargetByTargetType($sType, $sTypeNew);
|
||||
$this->oMapper->UpdatePropertySelectByTargetType($sType, $sTypeNew);
|
||||
$this->oMapper->UpdatePropertyValueByTargetType($sType, $sTypeNew);
|
||||
$this->oMapper->UpdatePropertyValueSelectByTargetType($sType, $sTypeNew);
|
||||
$this->oMapper->UpdatePropertyValueTagByTargetType($sType, $sTypeNew);
|
||||
/**
|
||||
* Сбрасываем кеши
|
||||
*/
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array(
|
||||
'ModuleProperty_EntityProperty_save',
|
||||
'ModuleProperty_EntityTarget_save',
|
||||
'ModuleProperty_EntitySelect_save',
|
||||
'ModuleProperty_EntityValue_save',
|
||||
'ModuleProperty_EntityValueSelect_save',
|
||||
'ModuleProperty_EntityValueTag_save',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Создает новый тип объекта в БД для дополнительных полей
|
||||
*
|
||||
* @param string $sType
|
||||
* @param array $aParams
|
||||
* @param bool $bRewrite
|
||||
*
|
||||
* @return bool|ModuleProperty_EntityTarget
|
||||
*/
|
||||
public function CreateTargetType($sType, $aParams, $bRewrite = false)
|
||||
{
|
||||
/**
|
||||
* Проверяем есть ли уже такой тип
|
||||
*/
|
||||
if ($oTarget = $this->GetTargetByType($sType)) {
|
||||
if (!$bRewrite) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$oTarget = Engine::GetEntity('ModuleProperty_EntityTarget');
|
||||
$oTarget->setType($sType);
|
||||
}
|
||||
$oTarget->setState(self::TARGET_STATE_ACTIVE);
|
||||
$oTarget->setParams($aParams);
|
||||
if ($oTarget->Save()) {
|
||||
return $oTarget;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отключает тип объекта для дополнительных полей
|
||||
*
|
||||
* @param string $sType
|
||||
* @param int $iState self::TARGET_STATE_NOT_ACTIVE или self::TARGET_STATE_REMOVE
|
||||
*/
|
||||
public function RemoveTargetType($sType, $iState = self::TARGET_STATE_NOT_ACTIVE)
|
||||
{
|
||||
if ($oTarget = $this->GetTargetByType($sType)) {
|
||||
$oTarget->setState($iState);
|
||||
$oTarget->Save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает набор полей/свойств для показа их на форме редактирования
|
||||
*
|
||||
* @param $sTargetType
|
||||
* @param $iTargetId
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function GetPropertiesForUpdate($sTargetType, $iTargetId)
|
||||
{
|
||||
/**
|
||||
* Проверяем зарегистрирован ли такой тип
|
||||
*/
|
||||
if (!$this->IsAllowTargetType($sTargetType)) {
|
||||
return array();
|
||||
}
|
||||
/**
|
||||
* Получаем набор свойств
|
||||
*/
|
||||
$aProperties = $this->Property_GetPropertyItemsByFilter(array(
|
||||
'target_type' => $sTargetType,
|
||||
'#order' => array('sort' => 'desc')
|
||||
));
|
||||
$this->Property_AttachValueForProperties($aProperties, $sTargetType, $iTargetId);
|
||||
return $aProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Автоматическое создание дополнительного поля
|
||||
* TODO: учитывать $aAdditional для создание вариантов в типе select
|
||||
*
|
||||
* @param string $sTargetType Тип объекта дял которого добавляем поле
|
||||
* @param array $aData Данные поля: array('type'=>'int','title'=>'Название','code'=>'newfield','description'=>'Описание поля','sort'=>100);
|
||||
* @param bool $bSkipErrorUniqueCode Пропускать ошибку при дублировании кода поля (такое поле уже существует)
|
||||
* @param array $aValidateRules Данные валидатора поля, зависят от конкретного типа поля: array('allowEmpty'=>true,'max'=>1000)
|
||||
* @param array $aParams Дополнительные параметры поля, зависят от типа поля
|
||||
* @param array $aAdditional Дополнительные данные, которые нужно учитывать при создании поля, зависят от типа поля
|
||||
*
|
||||
* @return bool|ModuleProperty_EntityProperty
|
||||
*/
|
||||
public function CreateTargetProperty(
|
||||
$sTargetType,
|
||||
$aData,
|
||||
$bSkipErrorUniqueCode = true,
|
||||
$aValidateRules = array(),
|
||||
$aParams = array(),
|
||||
$aAdditional = array()
|
||||
) {
|
||||
/**
|
||||
* Если необходимо и поле уже существует, то пропускаем создание
|
||||
*/
|
||||
if ($bSkipErrorUniqueCode and isset($aData['code']) and $this->GetPropertyByTargetTypeAndCode($sTargetType,
|
||||
$aData['code'])
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$oProperty = Engine::GetEntity('ModuleProperty_EntityProperty');
|
||||
$oProperty->_setValidateScenario('auto');
|
||||
$oProperty->_setDataSafe($aData);
|
||||
$oProperty->setValidateRulesRaw($aValidateRules);
|
||||
$oProperty->setParamsRaw($aParams);
|
||||
$oProperty->setTargetType($sTargetType);
|
||||
if ($oProperty->_Validate()) {
|
||||
if ($oProperty->Add()) {
|
||||
return $oProperty;
|
||||
} else {
|
||||
return $this->Lang_Get('property.notices.create_error');
|
||||
}
|
||||
} else {
|
||||
return $oProperty->_getValidateError();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Используется для создания дефолтных дополнительных полей при активации плагина
|
||||
*
|
||||
* @param array $aProperties Список полей
|
||||
* <pre>
|
||||
* array(
|
||||
* array(
|
||||
* 'data'=>array(
|
||||
* 'type'=>ModuleProperty::PROPERTY_TYPE_INT,
|
||||
* 'title'=>'Номер',
|
||||
* 'code'=>'number',
|
||||
* 'sort'=>100
|
||||
* ),
|
||||
* 'validate_rule'=>array(
|
||||
* 'min'=>10
|
||||
* ),
|
||||
* 'params'=>array(),
|
||||
* 'additional'=>array()
|
||||
* )
|
||||
* );
|
||||
* </pre>
|
||||
* @param string $sTargetType Тип объекта
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function CreateDefaultTargetPropertyFromPlugin($aProperties, $sTargetType)
|
||||
{
|
||||
foreach ($aProperties as $aProperty) {
|
||||
$sResultMsg = $this->CreateTargetProperty($sTargetType, $aProperty['data'], true,
|
||||
$aProperty['validate_rule'], $aProperty['params'], $aProperty['additional']);
|
||||
if ($sResultMsg !== true and !is_object($sResultMsg)) {
|
||||
if (is_string($sResultMsg)) {
|
||||
$this->Message_AddErrorSingle($sResultMsg, $this->Lang_Get('common.error.error'), true);
|
||||
}
|
||||
/**
|
||||
* Отменяем добавление типа
|
||||
*/
|
||||
$this->RemoveTargetType($sTargetType, ModuleProperty::TARGET_STATE_NOT_ACTIVE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function RemoveValueByPropertyId($iPropertyId)
|
||||
{
|
||||
$bRes = $this->oMapper->RemoveValueByPropertyId($iPropertyId);
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('ModuleProperty_EntityValue_delete'));
|
||||
return $bRes;
|
||||
}
|
||||
|
||||
public function RemoveValueTagByPropertyId($iPropertyId)
|
||||
{
|
||||
$bRes = $this->oMapper->RemoveValueTagByPropertyId($iPropertyId);
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('ModuleProperty_EntityValueTag_delete'));
|
||||
return $bRes;
|
||||
}
|
||||
|
||||
public function RemoveValueSelectByPropertyId($iPropertyId)
|
||||
{
|
||||
$bRes = $this->oMapper->RemoveValueSelectByPropertyId($iPropertyId);
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('ModuleProperty_EntityValueSelect_delete'));
|
||||
return $bRes;
|
||||
}
|
||||
|
||||
public function RemoveSelectByPropertyId($iPropertyId)
|
||||
{
|
||||
$bRes = $this->oMapper->RemoveSelectByPropertyId($iPropertyId);
|
||||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('ModuleProperty_EntitySelect_delete'));
|
||||
return $bRes;
|
||||
}
|
||||
|
||||
public function CheckAllowTargetObject($sTargetType, $iTargetId, $aParams = array())
|
||||
{
|
||||
$sMethod = 'CheckAllowTargetObject' . func_camelize($sTargetType);
|
||||
if (method_exists($this, $sMethod)) {
|
||||
if (!array_key_exists('user', $aParams)) {
|
||||
$aParams['user'] = $this->oUserCurrent;
|
||||
}
|
||||
return $this->$sMethod($iTargetId, $aParams);
|
||||
}
|
||||
/**
|
||||
* По умолчанию считаем доступ разрешен
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Поведение для подключения функционала дополнительных полей к сущностям
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_BehaviorEntity extends Behavior
|
||||
{
|
||||
/**
|
||||
* Дефолтные параметры
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aParams = array(
|
||||
'target_type' => '',
|
||||
);
|
||||
/**
|
||||
* Список хуков
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aHooks = array(
|
||||
'validate_after' => 'CallbackValidateAfter',
|
||||
'after_save' => 'CallbackAfterSave',
|
||||
'after_delete' => 'CallbackAfterDelete',
|
||||
);
|
||||
|
||||
/**
|
||||
* Коллбэк
|
||||
* Выполняется при инициализации сущности
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function CallbackValidateAfter($aParams)
|
||||
{
|
||||
if ($aParams['bResult']) {
|
||||
$aFields = $aParams['aFields'];
|
||||
if (is_null($aFields) or in_array('properties', $aFields)) {
|
||||
$oValidator = $this->Validate_CreateValidator('properties_check', $this, 'properties');
|
||||
$oValidator->validateEntity($this->oObject, $aFields);
|
||||
$aParams['bResult'] = !$this->oObject->_hasValidateErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Коллбэк
|
||||
* Выполняется после сохранения сущности
|
||||
*/
|
||||
public function CallbackAfterSave()
|
||||
{
|
||||
$this->Property_UpdatePropertiesValue($this->oObject->getPropertiesObject(), $this->oObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Коллбэк
|
||||
* Выполняется после удаления сущности
|
||||
*/
|
||||
public function CallbackAfterDelete()
|
||||
{
|
||||
$this->Property_RemovePropertiesValue($this->oObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительный метод для сущности
|
||||
* Запускает валидацию дополнительных полей
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function ValidatePropertiesCheck()
|
||||
{
|
||||
return $this->Property_ValidateEntityPropertiesCheck($this->oObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает полный список свойств сущности
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPropertyList()
|
||||
{
|
||||
return $this->Property_GetEntityPropertyList($this->oObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает значение конкретного свойства
|
||||
* @see ModuleProperty_EntityValue::getValueForDisplay
|
||||
*
|
||||
* @param int|string $sPropertyId ID или код свойства
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPropertyValue($sPropertyId)
|
||||
{
|
||||
return $this->Property_GetEntityPropertyValue($this->oObject, $sPropertyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект конкретного свойства сущности
|
||||
*
|
||||
* @param int|string $sPropertyId ID или код свойства
|
||||
*
|
||||
* @return ModuleProperty_EntityProperty|null
|
||||
*/
|
||||
public function getProperty($sPropertyId)
|
||||
{
|
||||
return $this->Property_GetEntityProperty($this->oObject, $sPropertyId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает тип объекта для дополнительных полей
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPropertyTargetType()
|
||||
{
|
||||
if ($sType = $this->getParam('target_type')) {
|
||||
return $sType;
|
||||
}
|
||||
/**
|
||||
* Иначе дополнительно смотрим на наличие данного метода у сущности
|
||||
* Это необходимо, если тип вычисляется динамически по какой-то своей логике
|
||||
*/
|
||||
if (func_method_exists($this->oObject, 'getPropertyTargetType', 'public')) {
|
||||
return call_user_func(array($this->oObject, 'getPropertyTargetType'));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Поведение для подключения функционала дополнительных полей к модулям
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_BehaviorModule extends Behavior
|
||||
{
|
||||
/**
|
||||
* Список хуков
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $aHooks = array(
|
||||
'module_orm_GetItemsByFilter_after' => array(
|
||||
'CallbackGetItemsByFilterAfter',
|
||||
1000
|
||||
),
|
||||
'module_orm_GetItemsByFilter_before' => array(
|
||||
'CallbackGetItemsByFilterBefore',
|
||||
1000
|
||||
),
|
||||
'module_orm_GetByFilter_before' => array(
|
||||
'CallbackGetItemsByFilterBefore',
|
||||
1000
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Модифицирует фильтр в ORM запросе
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function CallbackGetItemsByFilterAfter($aParams)
|
||||
{
|
||||
$aEntities = $aParams['aEntities'];
|
||||
$aFilter = $aParams['aFilter'];
|
||||
$this->Property_RewriteGetItemsByFilter($aEntities, $aFilter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Модифицирует результат ORM запроса
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function CallbackGetItemsByFilterBefore($aParams)
|
||||
{
|
||||
$aFilter = $this->Property_RewriteFilter($aParams['aFilter'], $aParams['sEntityFull']);
|
||||
$aParams['aFilter'] = $aFilter;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,345 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность дополнительного поля
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntityProperty extends EntityORM
|
||||
{
|
||||
|
||||
protected $aValidateRules = array(
|
||||
array('type', 'check_type', 'on' => array('create', 'auto')),
|
||||
array(
|
||||
'code',
|
||||
'regexp',
|
||||
'allowEmpty' => false,
|
||||
'pattern' => '#^[a-z0-9\_]+$#i',
|
||||
'on' => array('create', 'update', 'auto')
|
||||
),
|
||||
array(
|
||||
'title',
|
||||
'string',
|
||||
'allowEmpty' => false,
|
||||
'min' => 1,
|
||||
'max' => 250,
|
||||
'on' => array('create', 'update', 'auto')
|
||||
),
|
||||
array('description', 'string', 'allowEmpty' => true, 'max' => 500, 'on' => array('update', 'auto')),
|
||||
array('sort', 'number', 'allowEmpty' => false, 'integerOnly' => true, 'min' => 0, 'on' => array('auto')),
|
||||
array('validate_rules_raw', 'check_validate_rules_raw', 'on' => array('create', 'update', 'auto')),
|
||||
array('params_raw', 'check_params_raw', 'on' => array('update', 'auto')),
|
||||
array('code', 'check_code', 'on' => array('create', 'update', 'auto')),
|
||||
array('title', 'check_title', 'on' => array('create', 'update', 'auto')),
|
||||
array('description', 'check_description', 'on' => array('update', 'auto')),
|
||||
);
|
||||
|
||||
protected $aRelations = array(
|
||||
'selects' => array(
|
||||
self::RELATION_TYPE_HAS_MANY,
|
||||
'ModuleProperty_EntitySelect',
|
||||
'property_id',
|
||||
array('#order' => array('sort' => 'desc'))
|
||||
),
|
||||
);
|
||||
|
||||
public function ValidateCheckType()
|
||||
{
|
||||
if ($this->Property_IsAllowPropertyType($this->getType())) {
|
||||
return true;
|
||||
}
|
||||
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 $this->Lang_Get('property.notices.validate_code');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ValidateCheckTitle()
|
||||
{
|
||||
$this->setTitle(htmlspecialchars($this->getTitle()));
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ValidateCheckDescription()
|
||||
{
|
||||
$this->setDescription(htmlspecialchars($this->getDescription()));
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ValidateCheckValidateRulesRaw()
|
||||
{
|
||||
$aRulesRaw = $this->getValidateRulesRaw();
|
||||
/**
|
||||
* Валидация зависит от типа
|
||||
*/
|
||||
$oValue = Engine::GetEntity('ModuleProperty_EntityValue', array(
|
||||
'property_type' => $this->getType(),
|
||||
'property_id' => $this->getId(),
|
||||
'target_type' => $this->getTargetType(),
|
||||
'target_id' => $this->getId()
|
||||
));
|
||||
$oValueType = $oValue->getValueTypeObject();
|
||||
$aRules = $oValueType->prepareValidateRulesRaw($aRulesRaw);
|
||||
$this->setValidateRules($aRules);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function ValidateCheckParamsRaw()
|
||||
{
|
||||
$aParamsRaw = $this->getParamsRaw();
|
||||
/**
|
||||
* Валидация зависит от типа
|
||||
*/
|
||||
$oValue = Engine::GetEntity('ModuleProperty_EntityValue', array(
|
||||
'property_type' => $this->getType(),
|
||||
'property_id' => $this->getId(),
|
||||
'target_type' => $this->getTargetType(),
|
||||
'target_id' => $this->getId()
|
||||
));
|
||||
$oValueType = $oValue->getValueTypeObject();
|
||||
$aParams = $oValueType->prepareParamsRaw($aParamsRaw);
|
||||
$this->setParams($aParams);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется перед сохранением сущности
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
|
||||
$oValue = Engine::GetEntity('ModuleProperty_EntityValue', array(
|
||||
'property_type' => $this->getType(),
|
||||
'property_id' => $this->getId(),
|
||||
'target_type' => $this->getTargetType(),
|
||||
'target_id' => $this->getId()
|
||||
));
|
||||
$oValueType = $oValue->getValueTypeObject();
|
||||
/**
|
||||
* Выставляем дефолтные значения параметров
|
||||
*/
|
||||
$this->setParams($oValueType->getParamsDefault());
|
||||
/**
|
||||
* Выставляем дефолтные значения параметров валидации
|
||||
*/
|
||||
$this->setValidateRules($oValueType->getValidateRulesDefault());
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняется перед удалением сущности
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function beforeDelete()
|
||||
{
|
||||
if ($bResult = parent::beforeDelete()) {
|
||||
/**
|
||||
* Сначала удаляем стандартные значения
|
||||
*/
|
||||
$this->Property_RemoveValueByPropertyId($this->getId());
|
||||
/**
|
||||
* Удаляем значения тегов
|
||||
*/
|
||||
$this->Property_RemoveValueTagByPropertyId($this->getId());
|
||||
/**
|
||||
* Удаляем значения селектов
|
||||
*/
|
||||
$this->Property_RemoveValueSelectByPropertyId($this->getId());
|
||||
/**
|
||||
* Удаляем сами варианты селектов
|
||||
*/
|
||||
$this->Property_RemoveSelectByPropertyId($this->getId());
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает правила валидации поля
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getValidateRules()
|
||||
{
|
||||
$aData = @unserialize($this->_getDataOne('validate_rules'));
|
||||
if (!$aData) {
|
||||
$aData = array();
|
||||
}
|
||||
return $aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает экранированный список правил валидации
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getValidateRulesEscape()
|
||||
{
|
||||
$aRules = $this->getValidateRules();
|
||||
func_htmlspecialchars($aRules);
|
||||
return $aRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает конкретное правило валидации
|
||||
*
|
||||
* @param string $sRule
|
||||
*
|
||||
* @return null|mixed
|
||||
*/
|
||||
public function getValidateRuleOne($sRule)
|
||||
{
|
||||
$aData = $this->getValidateRules();
|
||||
if (isset($aData[$sRule])) {
|
||||
return $aData[$sRule];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает правила валидации поля
|
||||
*
|
||||
* @param array $aRules
|
||||
*/
|
||||
public function setValidateRules($aRules)
|
||||
{
|
||||
$this->_aData['validate_rules'] = @serialize($aRules);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список дополнительных параметров поля
|
||||
*
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getParams()
|
||||
{
|
||||
$aData = @unserialize($this->_getDataOne('params'));
|
||||
if (!$aData) {
|
||||
$aData = array();
|
||||
}
|
||||
return $aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает экранированный список параметров
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getParamsEscape()
|
||||
{
|
||||
$aParams = $this->getParams();
|
||||
func_htmlspecialchars($aParams);
|
||||
return $aParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает список дополнительных параметров поля
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function setParams($aParams)
|
||||
{
|
||||
$this->_aData['params'] = @serialize($aParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает конкретный параметр поля
|
||||
*
|
||||
* @param $sName
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getParam($sName)
|
||||
{
|
||||
$aParams = $this->getParams();
|
||||
return isset($aParams[$sName]) ? $aParams[$sName] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL админки для редактирования поля
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlAdminUpdate()
|
||||
{
|
||||
return Router::GetPath('admin/properties/' . $this->getTargetType() . '/update/' . $this->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL админки для редактирования поля
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlAdminRemove()
|
||||
{
|
||||
return Router::GetPath('admin/properties/' . $this->getTargetType() . '/remove/' . $this->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает описание типа поля
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getTypeTitle()
|
||||
{
|
||||
/**
|
||||
* TODO: использовать текстовку из языкового
|
||||
*/
|
||||
return $this->getType();
|
||||
}
|
||||
|
||||
public function getSaveFileDir($sPostfix = '')
|
||||
{
|
||||
$sPostfix = trim($sPostfix, '/');
|
||||
return Config::Get('path.uploads.base') . '/property/' . $this->getTargetType() . '/' . $this->getType() . '/' . date('Y/m/d/H/') . ($sPostfix ? "{$sPostfix}/" : '');
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
if (!$oValue = $this->getValue()) {
|
||||
return true;
|
||||
}
|
||||
return $oValue->isEmpty();
|
||||
}
|
||||
|
||||
public function getValueTypeObject()
|
||||
{
|
||||
if ($oValue = $this->getValue()) {
|
||||
return $oValue->getValueTypeObject();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность дополнительного поля
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntitySelect extends EntityORM
|
||||
{
|
||||
|
||||
protected $aValidateRules = array();
|
||||
|
||||
protected $aRelations = array();
|
||||
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность связи поля с объектом
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntityTarget extends EntityORM
|
||||
{
|
||||
|
||||
protected $aValidateRules = array();
|
||||
|
||||
protected $aRelations = array();
|
||||
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
if ($this->_isNew()) {
|
||||
$this->setDateCreate(date("Y-m-d H:i:s"));
|
||||
} else {
|
||||
$this->setDateUpdate(date("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает список дополнительных параметров
|
||||
*
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getParams()
|
||||
{
|
||||
$aData = @unserialize($this->_getDataOne('params'));
|
||||
if (!$aData) {
|
||||
$aData = array();
|
||||
}
|
||||
return $aData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает список дополнительных параметров
|
||||
*
|
||||
* @param $aParams
|
||||
*/
|
||||
public function setParams($aParams)
|
||||
{
|
||||
$this->_aData['params'] = @serialize($aParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает конкретный параметр
|
||||
*
|
||||
* @param $sName
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function getParam($sName)
|
||||
{
|
||||
$aParams = $this->getParams();
|
||||
return isset($aParams[$sName]) ? $aParams[$sName] : null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность значения поля
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntityValue extends EntityORM
|
||||
{
|
||||
|
||||
protected $aRelations = array(
|
||||
'property' => array(self::RELATION_TYPE_BELONGS_TO, 'ModuleProperty_EntityProperty', 'property_id'),
|
||||
);
|
||||
|
||||
protected function beforeSave()
|
||||
{
|
||||
if ($bResult = parent::beforeSave()) {
|
||||
$oValueType = $this->getValueTypeObject();
|
||||
$oValueType->beforeSaveValue();
|
||||
}
|
||||
return $bResult;
|
||||
}
|
||||
|
||||
public function getValueForDisplay()
|
||||
{
|
||||
$oValueType = $this->getValueTypeObject();
|
||||
return $oValueType->getValueForDisplay();
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
$oValueType = $this->getValueTypeObject();
|
||||
return $oValueType->isEmpty();
|
||||
}
|
||||
|
||||
public function getValueForForm()
|
||||
{
|
||||
$oValueType = $this->getValueTypeObject();
|
||||
return $oValueType->getValueForForm();
|
||||
}
|
||||
|
||||
public function getValueTypeObject()
|
||||
{
|
||||
if (!$this->_getDataOne('value_type_object')) {
|
||||
$oObject = Engine::GetEntity('ModuleProperty_EntityValueType' . func_camelize($this->getPropertyType()));
|
||||
$oObject->setValueObject($this);
|
||||
$this->setValueTypeObject($oObject);
|
||||
}
|
||||
return $this->_getDataOne('value_type_object');
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
$aData = @unserialize($this->_getDataOne('data'));
|
||||
if (!$aData) {
|
||||
$aData = array();
|
||||
}
|
||||
return $aData;
|
||||
}
|
||||
|
||||
public function setData($aRules)
|
||||
{
|
||||
$this->_aData['data'] = @serialize($aRules);
|
||||
}
|
||||
|
||||
public function getDataOne($sKey)
|
||||
{
|
||||
$aData = $this->getData();
|
||||
if (isset($aData[$sKey])) {
|
||||
return $aData[$sKey];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function setDataOne($sKey, $mValue)
|
||||
{
|
||||
$aData = $this->getData();
|
||||
$aData[$sKey] = $mValue;
|
||||
$this->setData($aData);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность значений поля типа Select
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntityValueSelect extends EntityORM
|
||||
{
|
||||
|
||||
protected $aRelations = array();
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Сущность значений поля типа Tag
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntityValueTag extends EntityORM
|
||||
{
|
||||
|
||||
protected $aRelations = array();
|
||||
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Базовый объект значения поля
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntityValueType extends Entity
|
||||
{
|
||||
|
||||
protected $oValue = null;
|
||||
|
||||
public function getValueForDisplay()
|
||||
{
|
||||
// TODO: getValue() всегда вернет null
|
||||
return $this->getValueObject()->getValue();
|
||||
}
|
||||
|
||||
public function getValueForForm()
|
||||
{
|
||||
return htmlspecialchars($this->getValueObject()->getValue());
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->getValueObject()->getValueVarchar() ? false : true;
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
return 'Неверное значение';
|
||||
}
|
||||
|
||||
protected function validateStandart(
|
||||
$sTypeValidator,
|
||||
$aParamsAdditional = array(),
|
||||
$sFieldForValidate = 'value_for_validate'
|
||||
) {
|
||||
$oProperty = $this->getValueObject()->getProperty();
|
||||
/**
|
||||
* Получаем параметры валидации
|
||||
*/
|
||||
$aParams = $oProperty->getValidateRules();
|
||||
if (!isset($aParams['label'])) {
|
||||
$aParams['label'] = '';
|
||||
}
|
||||
$aParams = array_merge($aParams, $aParamsAdditional);
|
||||
|
||||
$oValidator = $this->Validate_CreateValidator($sTypeValidator, $this, null, $aParams);
|
||||
$oValidator->fields = array($sFieldForValidate);
|
||||
$oValidator->validateEntity($this);
|
||||
if ($this->_hasValidateErrors()) {
|
||||
return $this->_getValidateError();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function setValue($mValue)
|
||||
{
|
||||
$this->resetAllValue();
|
||||
}
|
||||
|
||||
public function setValueObject($oValue)
|
||||
{
|
||||
$this->oValue = $oValue;
|
||||
}
|
||||
|
||||
public function getValueObject()
|
||||
{
|
||||
return $this->oValue;
|
||||
}
|
||||
|
||||
public function resetAllValue()
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
$oValue->setValueInt(null);
|
||||
$oValue->setValueFloat(null);
|
||||
$oValue->setValueVarchar(null);
|
||||
$oValue->setValueText(null);
|
||||
$oValue->setValueDate(null);
|
||||
$oValue->setData(null);
|
||||
/**
|
||||
* Удаляем из таблицы тегов
|
||||
*/
|
||||
$this->Property_RemoveValueTagsByTarget($oValue->getTargetType(), $oValue->getTargetId(),
|
||||
$oValue->getPropertyId());
|
||||
/**
|
||||
* Удаляем из таблицы селектов
|
||||
*/
|
||||
$this->Property_RemoveValueSelectsByTarget($oValue->getTargetType(), $oValue->getTargetId(),
|
||||
$oValue->getPropertyId());
|
||||
}
|
||||
|
||||
public function prepareValidateRulesRaw($aRulesRaw)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getValidateRulesDefault()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function prepareParamsRaw($aParamsRaw)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getParamsDefault()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function beforeSaveValue()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function removeValue()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект управления типом checkbox
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntityValueTypeCheckbox extends ModuleProperty_EntityValueType
|
||||
{
|
||||
|
||||
public function getValueForDisplay()
|
||||
{
|
||||
return $this->getValueObject()->getValueInt() ? 'да' : 'нет';
|
||||
}
|
||||
|
||||
public function getValueForForm()
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
$oProperty = $oValue->getProperty();
|
||||
return $oValue->_isNew() ? $oProperty->getParam('default') : $oValue->getValueInt();
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
$sValue = $this->getValueForValidate();
|
||||
$this->setValueForValidate($sValue ? 1 : 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setValue($mValue)
|
||||
{
|
||||
$this->resetAllValue();
|
||||
$oValue = $this->getValueObject();
|
||||
$oProperty = $oValue->getProperty();
|
||||
$oValue->setValueInt($mValue ? $oProperty->getParam('default_value') : 0);
|
||||
}
|
||||
|
||||
public function prepareParamsRaw($aParamsRaw)
|
||||
{
|
||||
$aParams = array();
|
||||
|
||||
$aParams['default'] = isset($aParamsRaw['default']) ? true : false;
|
||||
if (isset($aParamsRaw['default_value'])) {
|
||||
$aParams['default_value'] = htmlspecialchars($aParamsRaw['default_value']);
|
||||
}
|
||||
|
||||
return $aParams;
|
||||
}
|
||||
|
||||
public function getParamsDefault()
|
||||
{
|
||||
return array(
|
||||
'default_value' => 1,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект управления типом date
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntityValueTypeDate extends ModuleProperty_EntityValueType
|
||||
{
|
||||
|
||||
protected $sFormatDateInput = 'dd.MM.yyyy';
|
||||
protected $sFormatDateTimeInput = 'dd.MM.yyyy HH:mm';
|
||||
|
||||
public function getValueForDisplay()
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
$oProperty = $oValue->getProperty();
|
||||
|
||||
return $oValue->getValueDate() ? $this->Viewer_GetDateFormat(strtotime($oValue->getValueDate()), $oProperty->getParam('format_out')) : '';
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->getValueObject()->getValueDate() ? false : true;
|
||||
}
|
||||
|
||||
public function getValueForForm()
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
$sDate = $oValue->getValueDate();
|
||||
$iTime = strtotime($sDate);
|
||||
// TODO: нужен конвертор формата дат вида Y в yyyy для учета $this->sFormatDateInput
|
||||
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' => '..' )
|
||||
*/
|
||||
$aValue = $this->getValueForValidate();
|
||||
$oValueObject = $this->getValueObject();
|
||||
$oProperty = $oValueObject->getProperty();
|
||||
$this->setValueForValidateDate(isset($aValue['date']) ? $aValue['date'] : '');
|
||||
/**
|
||||
* Формируем формат для валидации даты
|
||||
* В инпуте дата идет в формате d.m.Y и плюс H:i если используется время
|
||||
*/
|
||||
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) {
|
||||
/**
|
||||
* Формируем полную дату
|
||||
*/
|
||||
if ($this->getValueForValidateDate()) {
|
||||
$sTimeFull = strtotime($this->getValueForValidateDate());
|
||||
/**
|
||||
* Проверка на ограничение даты
|
||||
*/
|
||||
if ($oProperty->getValidateRuleOne('disallowFuture')) {
|
||||
if ($sTimeFull > time()) {
|
||||
return "{$oProperty->getTitle()}: " . $this->Lang_Get('property.notices.validate_value_date_future');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Проверка на ограничения только если это новая запись, либо старая с изменениями
|
||||
*/
|
||||
if ($oValueObject->_isNew() or strtotime($oValueObject->getValueDate()) != $sTimeFull) {
|
||||
if ($oProperty->getValidateRuleOne('disallowPast')) {
|
||||
if ($sTimeFull < time()) {
|
||||
return "{$oProperty->getTitle()}: " . $this->Lang_Get('property.notices.validate_value_date_past');
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$sTimeFull = null;
|
||||
}
|
||||
/**
|
||||
* Переопределяем результирующее значение
|
||||
*/
|
||||
$this->setValueForValidate($sTimeFull ? date('Y-m-d H:i:00', $sTimeFull) : null);
|
||||
return true;
|
||||
} else {
|
||||
return $mRes;
|
||||
}
|
||||
}
|
||||
|
||||
public function setValue($mValue)
|
||||
{
|
||||
$this->resetAllValue();
|
||||
$oValue = $this->getValueObject();
|
||||
$oValue->setValueDate($mValue ? $mValue : null);
|
||||
}
|
||||
|
||||
public function prepareValidateRulesRaw($aRulesRaw)
|
||||
{
|
||||
$aRules = array();
|
||||
$aRules['allowEmpty'] = isset($aRulesRaw['allowEmpty']) ? false : true;
|
||||
$aRules['disallowFuture'] = isset($aRulesRaw['disallowFuture']) ? true : false;
|
||||
$aRules['disallowPast'] = isset($aRulesRaw['disallowPast']) ? true : false;
|
||||
|
||||
return $aRules;
|
||||
}
|
||||
|
||||
public function prepareParamsRaw($aParamsRaw)
|
||||
{
|
||||
$aParams = array();
|
||||
$aParams['use_time'] = isset($aParamsRaw['use_time']) ? true : false;
|
||||
|
||||
if (isset($aParamsRaw['format_out'])) {
|
||||
$aParams['format_out'] = $aParamsRaw['format_out'];
|
||||
}
|
||||
|
||||
return $aParams;
|
||||
}
|
||||
|
||||
public function getParamsDefault()
|
||||
{
|
||||
return array(
|
||||
'format_out' => 'Y-m-d H:i',
|
||||
'use_time' => true,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
<?php
|
||||
/*
|
||||
* LiveStreet CMS
|
||||
* Copyright © 2013 OOO "ЛС-СОФТ"
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* Official site: www.livestreetcms.com
|
||||
* Contact e-mail: office@livestreetcms.com
|
||||
*
|
||||
* GNU General Public License, version 2:
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
*
|
||||
* ------------------------------------------------------
|
||||
*
|
||||
* @link http://www.livestreetcms.com
|
||||
* @copyright 2013 OOO "ЛС-СОФТ"
|
||||
* @author Maxim Mzhelskiy <rus.engine@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Объект управления типом file
|
||||
*
|
||||
* @package application.modules.property
|
||||
* @since 2.0
|
||||
*/
|
||||
class ModuleProperty_EntityValueTypeFile extends ModuleProperty_EntityValueType
|
||||
{
|
||||
|
||||
public function getValueForDisplay()
|
||||
{
|
||||
return $this->getFileFullName();
|
||||
}
|
||||
|
||||
public function isEmpty()
|
||||
{
|
||||
return $this->getFileFullName() ? false : true;
|
||||
}
|
||||
|
||||
public function validate()
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
$oProperty = $oValue->getProperty();
|
||||
$iPropertyId = $oProperty->getId();
|
||||
|
||||
$bNeedRemove = false;
|
||||
$mValue = $this->getValueForValidate();
|
||||
if (isset($mValue['remove']) and $mValue['remove']) {
|
||||
$bNeedRemove = true;
|
||||
$this->setValueForValidate(array('remove' => true));
|
||||
}
|
||||
|
||||
$sFileName = $this->_getValueFromFiles($iPropertyId, 'name');
|
||||
$sFileTmpName = $this->_getValueFromFiles($iPropertyId, 'tmp_name');
|
||||
$sFileError = $this->_getValueFromFiles($iPropertyId, 'error');
|
||||
$sFileSize = $this->_getValueFromFiles($iPropertyId, 'size');
|
||||
|
||||
if (!$sFileTmpName) {
|
||||
if ($oProperty->getValidateRuleOne('allowEmpty')) {
|
||||
return true;
|
||||
} elseif ($aFilePrev = $oValue->getDataOne('file') and isset($aFilePrev['path']) and !$bNeedRemove) {
|
||||
return true;
|
||||
} else {
|
||||
return $this->Lang_Get('property.notices.validate_value_file_empty');
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Проверяем на ошибки
|
||||
*/
|
||||
if ($sFileError and $sFileError != UPLOAD_ERR_NO_FILE) {
|
||||
return $this->Lang_Get('property.notices.validate_value_file_upload') . " - {$sFileError}";
|
||||
}
|
||||
/**
|
||||
* На корректность загрузки
|
||||
*/
|
||||
if (!$sFileName or !$sFileTmpName) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* На ограничение по размеру файла
|
||||
*/
|
||||
if ($iSizeKb = $oProperty->getValidateRuleOne('size_max') and $iSizeKb * 1024 < $sFileSize) {
|
||||
return $this->Lang_Get('property.notices.validate_value_file_size_max', array('size' => $iSizeKb));
|
||||
}
|
||||
/**
|
||||
* На допустимые типы файлов
|
||||
*/
|
||||
$aPath = pathinfo($sFileName);
|
||||
if (!isset($aPath['extension']) or !$aPath['extension']) {
|
||||
return false;
|
||||
}
|
||||
if ($aTypes = $oProperty->getParam('types') and !in_array($aPath['extension'], $aTypes)) {
|
||||
return $this->Lang_Get('property.notices.validate_value_file_type', array('types' => join(', ', $aTypes)));
|
||||
}
|
||||
/**
|
||||
* Пробрасываем данные по файлу
|
||||
*/
|
||||
$this->setValueForValidate(array(
|
||||
'name' => $sFileName,
|
||||
'tmp_name' => $sFileTmpName,
|
||||
'error' => $sFileError,
|
||||
'size' => $sFileSize,
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function _getValueFromFiles($iId, $sName)
|
||||
{
|
||||
if (isset($_FILES['property'][$sName][$iId]['file'])) {
|
||||
return $_FILES['property'][$sName][$iId]['file'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает значение после валидации конкретного поля, а не всех полей
|
||||
* Поэтому здесь нельзя сохранять файл, это нужно делать в beforeSaveValue()
|
||||
*
|
||||
* @param $aValue
|
||||
*/
|
||||
public function setValue($aValue)
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
/**
|
||||
* Просто пробрасываем данные
|
||||
*/
|
||||
if ($aValue) {
|
||||
$oValue->setDataOne('file_raw', $aValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Дополнительная обработка перед сохранением значения
|
||||
* Здесь нужно выполнять основную загрузку файла
|
||||
*/
|
||||
public function beforeSaveValue()
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
$oProperty = $oValue->getProperty();
|
||||
if (!$aFile = $oValue->getDataOne('file_raw')) {
|
||||
return true;
|
||||
}
|
||||
$oValue->setDataOne('file_raw', null);
|
||||
/**
|
||||
* Удаляем предыдущий файл
|
||||
*/
|
||||
if (isset($aFile['remove']) or isset($aFile['name'])) {
|
||||
if ($aFilePrev = $oValue->getDataOne('file')) {
|
||||
$this->RemoveFile($aFilePrev['path']);
|
||||
$oValue->setDataOne('file', array());
|
||||
$oValue->setValueVarchar(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($aFile['name'])) {
|
||||
/**
|
||||
* Выполняем загрузку файла
|
||||
*/
|
||||
$aPathInfo = pathinfo($aFile['name']);
|
||||
$sExtension = isset($aPathInfo['extension']) ? $aPathInfo['extension'] : 'unknown';
|
||||
$sFileName = func_generator(20) . '.' . $sExtension;
|
||||
/**
|
||||
* Копируем загруженный файл
|
||||
*/
|
||||
$sDirTmp = Config::Get('path.tmp.server') . '/property/';
|
||||
if (!is_dir($sDirTmp)) {
|
||||
@mkdir($sDirTmp, 0777, true);
|
||||
}
|
||||
$sFileTmp = $sDirTmp . $sFileName;
|
||||
|
||||
if (move_uploaded_file($aFile['tmp_name'], $sFileTmp)) {
|
||||
$sDirSave = Config::Get('path.root.server') . $oProperty->getSaveFileDir();
|
||||
if (!is_dir($sDirSave)) {
|
||||
@mkdir($sDirSave, 0777, true);
|
||||
}
|
||||
$sFilePath = $sDirSave . $sFileName;
|
||||
/**
|
||||
* Сохраняем файл
|
||||
*/
|
||||
if ($sFilePathNew = $this->SaveFile($sFileTmp, $sFilePath, null, true)) {
|
||||
/**
|
||||
* Сохраняем данные о файле
|
||||
*/
|
||||
$oValue->setDataOne('file', array(
|
||||
'path' => $sFilePathNew,
|
||||
'size' => filesize($sFilePath),
|
||||
'name' => htmlspecialchars($aPathInfo['filename']),
|
||||
'extension' => htmlspecialchars($aPathInfo['extension']),
|
||||
));
|
||||
/**
|
||||
* Сохраняем уникальный ключ для доступа к файлу
|
||||
*/
|
||||
$oValue->setValueVarchar(func_generator(32));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function prepareValidateRulesRaw($aRulesRaw)
|
||||
{
|
||||
$aRules = array();
|
||||
$aRules['allowEmpty'] = isset($aRulesRaw['allowEmpty']) ? false : true;
|
||||
|
||||
if (isset($aRulesRaw['size_max']) and is_numeric($aRulesRaw['size_max'])) {
|
||||
$aRules['size_max'] = (int)$aRulesRaw['size_max'];
|
||||
}
|
||||
return $aRules;
|
||||
}
|
||||
|
||||
public function prepareParamsRaw($aParamsRaw)
|
||||
{
|
||||
$aParams = array();
|
||||
|
||||
$aParams['types'] = array();
|
||||
if (isset($aParamsRaw['types']) and is_array($aParamsRaw['types'])) {
|
||||
foreach ($aParamsRaw['types'] as $sType) {
|
||||
if ($sType) {
|
||||
$aParams['types'][] = htmlspecialchars($sType);
|
||||
}
|
||||
}
|
||||
}
|
||||
$aParams['access_only_auth'] = isset($aParamsRaw['access_only_auth']) ? true : false;
|
||||
|
||||
return $aParams;
|
||||
}
|
||||
|
||||
public function getParamsDefault()
|
||||
{
|
||||
return array(
|
||||
'types' => array(
|
||||
'zip'
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function removeValue()
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
/**
|
||||
* Удаляем файл
|
||||
*/
|
||||
if ($aFilePrev = $oValue->getDataOne('file')) {
|
||||
$this->RemoveFile($aFilePrev['path']);
|
||||
}
|
||||
}
|
||||
|
||||
public function getFileFullName()
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
if ($aFilePrev = $oValue->getDataOne('file')) {
|
||||
return $aFilePrev['name'] . '.' . $aFilePrev['extension'];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getCountDownloads()
|
||||
{
|
||||
$aStats = $this->oValue->getDataOne('stats');
|
||||
return isset($aStats['count_download']) ? $aStats['count_download'] : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохраняет(копирует) файл на сервер
|
||||
* Если переопределить данный метод, то можно сохранять файл, например, на Amazon S3
|
||||
*
|
||||
* @param string $sFileSource Полный путь до исходного файла
|
||||
* @param string $sFileDest Полный путь до файла для сохранения с типом, например, [server]/home/var/site.ru/book.pdf
|
||||
* @param int|null $iMode Права chmod для файла, например, 0777
|
||||
* @param bool $bRemoveSource Удалять исходный файл или нет
|
||||
* @return bool | string При успешном сохранении возвращает относительный путь до файла с типом, например, [relative]/image.jpg
|
||||
*/
|
||||
protected function SaveFile($sFileSource, $sFileDest, $iMode = null, $bRemoveSource = false)
|
||||
{
|
||||
if ($this->Fs_SaveFileLocal($sFileSource, $this->Fs_GetPathServer($sFileDest), $iMode, $bRemoveSource)) {
|
||||
return $this->Fs_MakePath($this->Fs_GetPathRelativeFromServer($sFileDest), ModuleFs::PATH_TYPE_RELATIVE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Удаляет файл
|
||||
* Если переопределить данный метод, то можно удалять файл, например, с Amazon S3
|
||||
*
|
||||
* @param string $sPathFile Полный путь до файла с типом, например, [relative]/book.pdf
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function RemoveFile($sPathFile)
|
||||
{
|
||||
$sPathFile = $this->Fs_GetPathServer($sPathFile);
|
||||
return $this->Fs_RemoveFileLocal($sPathFile);
|
||||
}
|
||||
|
||||
public function DownloadFile()
|
||||
{
|
||||
$oValue = $this->getValueObject();
|
||||
if ($aFilePrev = $oValue->getDataOne('file')) {
|
||||
$this->Tools_DownloadFile($this->Fs_GetPathServer($aFilePrev['path']),
|
||||
$aFilePrev['name'] . '.' . $aFilePrev['extension'], $aFilePrev['size']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue