mirror of
https://github.com/Oreolek/ifhub.club.git
synced 2024-06-26 03:30:48 +03:00
Поддержка ЧПУ для топиков fix #636
This commit is contained in:
parent
13b2e46f12
commit
8abbcb779e
|
@ -116,6 +116,7 @@ class ActionBlog extends Action
|
|||
'ajaxbloginfo',
|
||||
'ajaxblogjoin',
|
||||
'ajax',
|
||||
'_show_topic_url',
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -184,8 +185,8 @@ class ActionBlog extends Action
|
|||
$this->AddEventPreg('/^ajax$/i', '/^remove-avatar$/i', '/^$/i', 'EventAjaxRemoveAvatar');
|
||||
$this->AddEventPreg('/^ajax$/i', '/^modal-crop-avatar$/i', '/^$/i', 'EventAjaxModalCropAvatar');
|
||||
|
||||
$this->AddEventPreg('/^_show_topic_url$/i', '/^$/i', 'EventInternalShowTopicByUrl');
|
||||
$this->AddEventPreg('/^(\d+)\.html$/i', '/^$/i', array('EventShowTopic', 'topic'));
|
||||
$this->AddEventPreg('/^[\w\-\_]+$/i', '/^(\d+)\.html$/i', array('EventShowTopic', 'topic'));
|
||||
|
||||
$this->AddEventPreg('/^[\w\-\_]+$/i', '/^(page([1-9]\d{0,5}))?$/i', array('EventShowBlog', 'blog'));
|
||||
$this->AddEventPreg('/^[\w\-\_]+$/i', '/^bad$/i', '/^(page([1-9]\d{0,5}))?$/i', array('EventShowBlog', 'blog'));
|
||||
|
@ -714,23 +715,85 @@ class ActionBlog extends Action
|
|||
$this->SetTemplateAction('index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Обработка ЧПУ топика
|
||||
*/
|
||||
protected function EventInternalShowTopicByUrl()
|
||||
{
|
||||
$sTopicUrl = Config::Get('module.topic._router_topic_original_url');
|
||||
$sSecurityHash = Config::Get('module.topic._router_topic_security_hash');
|
||||
/**
|
||||
* Проверяем ключ
|
||||
*/
|
||||
if ($sSecurityHash != Config::Get('module.security.hash')) {
|
||||
return $this->EventErrorDebug();
|
||||
}
|
||||
/**
|
||||
* Проверяем корректность URL топика
|
||||
* Сначала нужно получить сам топик по ID или уникальному полю Slug (транслитерированный заголовок)
|
||||
* Смотрим наличие ID или Slug в маске топика
|
||||
*/
|
||||
$sUrlEscape = preg_quote(trim(Config::Get('module.topic.url'), '/ '));
|
||||
$aMask = array_map(function ($sItem) {
|
||||
return "({$sItem})";
|
||||
}, Config::Get('module.topic.url_preg'));
|
||||
$sPreg = strtr($sUrlEscape, $aMask);
|
||||
if (preg_match('@^' . $sPreg . '$@iu', $sTopicUrl, $aMatch)) {
|
||||
$aRuleRequire = array();
|
||||
if (preg_match_all('#%(\w+)%#', $sUrlEscape, $aMatch2)) {
|
||||
foreach ($aMatch2[1] as $k => $sFind) {
|
||||
if (in_array($sFind, array('id', 'title'))) {
|
||||
if (isset($aMatch[$k + 1])) {
|
||||
$aRuleRequire[$sFind] = $aMatch[$k + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Не удалось найти обязательные поля - запускаем обработку дальше по цепочке
|
||||
*/
|
||||
if (!$aRuleRequire) {
|
||||
return Router::Action($sTopicUrl);
|
||||
}
|
||||
|
||||
$oTopic = null;
|
||||
/**
|
||||
* Ищем топик
|
||||
*/
|
||||
if (isset($aRuleRequire['id'])) {
|
||||
$oTopic = $this->Topic_GetTopicById($aRuleRequire['id']);
|
||||
} elseif (isset($aRuleRequire['title'])) {
|
||||
$oTopic = $this->Topic_GetTopicBySlug($aRuleRequire['title']);
|
||||
}
|
||||
if (!$oTopic) {
|
||||
return Router::Action($sTopicUrl);
|
||||
}
|
||||
/**
|
||||
* Проверяем корректность URL топика
|
||||
*/
|
||||
if ($oTopic->getUrl(false) != $sTopicUrl) {
|
||||
Router::Location($oTopic->getUrl());
|
||||
}
|
||||
/**
|
||||
* Направляем на стандартную обработку топика
|
||||
*/
|
||||
return Router::Action('blog', "{$oTopic->getId()}.html");
|
||||
}
|
||||
/**
|
||||
* Запускаем обработку дальше по цепочке
|
||||
*/
|
||||
return Router::Action($sTopicUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Показ топика
|
||||
*
|
||||
*/
|
||||
protected function EventShowTopic()
|
||||
{
|
||||
$sBlogUrl = '';
|
||||
if ($this->GetParamEventMatch(0, 1)) {
|
||||
// из коллективного блога
|
||||
$sBlogUrl = $this->sCurrentEvent;
|
||||
$iTopicId = $this->GetParamEventMatch(0, 1);
|
||||
$this->sMenuItemSelect = 'blog';
|
||||
} else {
|
||||
// из персонального блога
|
||||
$iTopicId = $this->GetEventMatch(1);
|
||||
$this->sMenuItemSelect = 'log';
|
||||
}
|
||||
$iTopicId = $this->GetEventMatch(1);
|
||||
$this->sMenuItemSelect = 'blog';
|
||||
$this->sMenuSubItemSelect = '';
|
||||
/**
|
||||
* Проверяем есть ли такой топик
|
||||
|
@ -744,24 +807,6 @@ class ActionBlog extends Action
|
|||
if (!$this->ACL_IsAllowShowTopic($oTopic, $this->oUserCurrent)) {
|
||||
return parent::EventNotFound();
|
||||
}
|
||||
/**
|
||||
* Если запросили топик из персонального блога то перенаправляем на страницу вывода коллективного топика
|
||||
*/
|
||||
if ($sBlogUrl != '' and $oTopic->getBlog()->getType() == 'personal') {
|
||||
Router::Location($oTopic->getUrl());
|
||||
}
|
||||
/**
|
||||
* Если запросили не персональный топик то перенаправляем на страницу для вывода коллективного топика
|
||||
*/
|
||||
if ($sBlogUrl == '' and $oTopic->getBlog()->getType() != 'personal') {
|
||||
Router::Location($oTopic->getUrl());
|
||||
}
|
||||
/**
|
||||
* Если номер топика правильный но УРЛ блога косяный то корректируем его и перенаправляем на нужный адрес
|
||||
*/
|
||||
if ($sBlogUrl != '' and $oTopic->getBlog()->getUrl() != $sBlogUrl) {
|
||||
Router::Location($oTopic->getUrl());
|
||||
}
|
||||
/**
|
||||
* Достаём комменты к топику
|
||||
*/
|
||||
|
|
|
@ -479,6 +479,24 @@ class ModuleTopic extends Module
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить топик по url/slug
|
||||
*
|
||||
* @param string $sSlug url/slug топика
|
||||
* @return ModuleTopic_EntityTopic|null
|
||||
*/
|
||||
public function GetTopicBySlug($sSlug)
|
||||
{
|
||||
if (!is_scalar($sSlug)) {
|
||||
return null;
|
||||
}
|
||||
$aTopics = $this->GetTopicsByFilter(array('topic_slug' => $sSlug), 1, 1);
|
||||
if ($aTopics['collection']) {
|
||||
return reset($aTopics['collection']);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить список топиков по списку айдишников
|
||||
*
|
||||
|
@ -1829,4 +1847,91 @@ class ModuleTopic extends Module
|
|||
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array("topic_update"));
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует и возвращает полный ЧПУ URL для топика
|
||||
*
|
||||
* @param ModuleTopic_EntityTopic $oTopic
|
||||
* @param bool $bAbsolute При false вернет относительный УРЛ
|
||||
* @return string
|
||||
*/
|
||||
public function BuildUrlForTopic($oTopic, $bAbsolute = true)
|
||||
{
|
||||
$sUrlMask = Config::Get('module.topic.url');
|
||||
$iDateCreate = strtotime($oTopic->getDateAdd());
|
||||
$aReplace = array(
|
||||
'%year%' => date("Y", $iDateCreate),
|
||||
'%month%' => date("m", $iDateCreate),
|
||||
'%day%' => date("d", $iDateCreate),
|
||||
'%hour%' => date("H", $iDateCreate),
|
||||
'%minute%' => date("i", $iDateCreate),
|
||||
'%second%' => date("s", $iDateCreate),
|
||||
'%login%' => '',
|
||||
'%blog%' => '',
|
||||
'%id%' => $oTopic->getId(),
|
||||
'%title%' => $oTopic->getSlug(),
|
||||
'%type%' => $oTopic->getType(),
|
||||
);
|
||||
|
||||
/**
|
||||
* Получаем связанные данные только если в этом есть необходимость
|
||||
*/
|
||||
if (strpos($sUrlMask, '%blog%') !== false) {
|
||||
if (!($oBlog = $oTopic->GetBlog())) {
|
||||
$oBlog = $this->Blog_GetBlogById($oTopic->getBlogId());
|
||||
}
|
||||
if ($oBlog) {
|
||||
if ($oBlog->getType() == 'personal') {
|
||||
$sUrlMask = str_replace('%blog%', '%login%', $sUrlMask);
|
||||
} else {
|
||||
$aReplace['%blog%'] = $oBlog->getUrl();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strpos($sUrlMask, '%login%') !== false) {
|
||||
if (!($oUser = $oTopic->GetUser())) {
|
||||
$oUser = $this->User_GetUserById($oTopic->getUserId());
|
||||
}
|
||||
if ($oUser) {
|
||||
$aReplace['%login%'] = $oUser->getLogin();
|
||||
}
|
||||
}
|
||||
$sUrl = strtr($sUrlMask, $aReplace);
|
||||
return $bAbsolute ? Router::GetPathRootWeb() . '/' . $sUrl : $sUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Формирует из строки url
|
||||
*
|
||||
* @param string $sText
|
||||
* @return string
|
||||
*/
|
||||
public function MakeSlug($sText)
|
||||
{
|
||||
return $this->Text_Transliteration($sText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL с учетом уникалькости по всем топикам
|
||||
*
|
||||
* @param string$sSlug
|
||||
* @param int|null $iSkipTopicId
|
||||
* @return string
|
||||
*/
|
||||
public function GetUniqueSlug($sSlug, $iSkipTopicId = null)
|
||||
{
|
||||
$iPostfix = 0;
|
||||
do {
|
||||
$oTopic = $this->GetTopicBySlug($sSlug . ($iPostfix ? '-' . $iPostfix : ''));
|
||||
if ($oTopic and (is_null($iSkipTopicId) or $iSkipTopicId != $oTopic->getId())) {
|
||||
$iPostfix++;
|
||||
$bNeedNext = true;
|
||||
} else {
|
||||
$bNeedNext = false;
|
||||
}
|
||||
} while ($bNeedNext);
|
||||
|
||||
return $sSlug . ($iPostfix ? '-' . $iPostfix : '');
|
||||
}
|
||||
}
|
|
@ -59,6 +59,12 @@ class ModuleTopic_EntityTopic extends Entity
|
|||
'allowEmpty' => Config::Get('module.topic.title_allow_empty'),
|
||||
'label' => $this->Lang_Get('topic.add.fields.title.label')
|
||||
);
|
||||
$this->aValidateRules[] = array(
|
||||
'topic_slug_raw',
|
||||
'regexp',
|
||||
'allowEmpty' => true,
|
||||
'pattern' => '#^[a-z0-9\-]{1,500}$#i'
|
||||
);
|
||||
$this->aValidateRules[] = array(
|
||||
'topic_text_source',
|
||||
'string',
|
||||
|
@ -79,6 +85,7 @@ class ModuleTopic_EntityTopic extends Entity
|
|||
|
||||
$this->aValidateRules[] = array('blogs_id_raw', 'blogs');
|
||||
$this->aValidateRules[] = array('topic_text_source', 'topic_unique');
|
||||
$this->aValidateRules[] = array('topic_slug_raw', 'slug_check');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -124,6 +131,49 @@ class ModuleTopic_EntityTopic extends Entity
|
|||
return $this->Lang_Get('topic.add.notices.error_type');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка URL топика
|
||||
*
|
||||
* @param string $sValue Проверяемое значение
|
||||
* @param array $aParams Параметры
|
||||
* @return bool|string
|
||||
*/
|
||||
public function ValidateSlugCheck($sValue, $aParams)
|
||||
{
|
||||
if (!$this->User_GetIsAdmin()) {
|
||||
/**
|
||||
* Простому пользователю разрешаем менять url только в течении X времени после создания топика
|
||||
* Причем не прямую смену url, а через транлитерацию заголовка топика
|
||||
*/
|
||||
if ($this->getId()) {
|
||||
if (strtotime($this->getDateAdd()) < time() - 60 * 60 * 1) {
|
||||
/**
|
||||
* Не меняем url
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Для нового топика всегда формируем url
|
||||
*/
|
||||
$this->setSlugRaw('');
|
||||
}
|
||||
|
||||
if ($this->getSlugRaw()) {
|
||||
$this->setSlug($this->Topic_GetUniqueSlug($this->getSlugRaw(), $this->getId()));
|
||||
} elseif ($this->getTitle()) {
|
||||
if ($sUrl = $this->Topic_MakeSlug($this->getTitle())) {
|
||||
/**
|
||||
* Получаем уникальный URL
|
||||
*/
|
||||
$this->setSlug($this->Topic_GetUniqueSlug($sUrl, $this->getId()));
|
||||
} else {
|
||||
return $this->Lang_Get('topic.add.notices.error_slug');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка топика на уникальность
|
||||
*
|
||||
|
@ -295,6 +345,16 @@ class ModuleTopic_EntityTopic extends Entity
|
|||
return $this->_getDataOne('topic_title');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает url топика
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getSlug()
|
||||
{
|
||||
return $this->_getDataOne('topic_slug');
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает текст топика
|
||||
*
|
||||
|
@ -613,15 +673,12 @@ class ModuleTopic_EntityTopic extends Entity
|
|||
/**
|
||||
* Возвращает полный URL до топика
|
||||
*
|
||||
* @param bool $bAbsolute При false вернет относительный УРЛ
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl()
|
||||
public function getUrl($bAbsolute = true)
|
||||
{
|
||||
if ($this->getBlog()->getType() == 'personal') {
|
||||
return Router::GetPath('blog') . $this->getId() . '.html';
|
||||
} else {
|
||||
return Router::GetPath('blog') . $this->getBlog()->getUrl() . '/' . $this->getId() . '.html';
|
||||
}
|
||||
return $this->Topic_BuildUrlForTopic($this, $bAbsolute);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -963,6 +1020,16 @@ class ModuleTopic_EntityTopic extends Entity
|
|||
$this->_aData['topic_title'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает url топика
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function setSlug($data)
|
||||
{
|
||||
$this->_aData['topic_slug'] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает текст топика
|
||||
*
|
||||
|
|
|
@ -44,6 +44,7 @@ class ModuleTopic_MapperTopic extends Mapper
|
|||
user_id,
|
||||
topic_type,
|
||||
topic_title,
|
||||
topic_slug,
|
||||
topic_tags,
|
||||
topic_date_add,
|
||||
topic_user_ip,
|
||||
|
@ -55,10 +56,10 @@ class ModuleTopic_MapperTopic extends Mapper
|
|||
topic_forbid_comment,
|
||||
topic_text_hash
|
||||
)
|
||||
VALUES(?d, ?d, ?d, ?d, ?d, ?d, ?, ?, ?, ?, ?, ?d, ?d, ?d, ?d, ?, ?, ?)
|
||||
VALUES(?d, ?d, ?d, ?d, ?d, ?d, ?, ?, ?, ?, ?, ?, ?d, ?d, ?d, ?d, ?, ?, ?)
|
||||
";
|
||||
if ($iId = $this->oDb->query($sql, $oTopic->getBlogId(), $oTopic->getBlogId2(), $oTopic->getBlogId3(),
|
||||
$oTopic->getBlogId4(), $oTopic->getBlogId5(), $oTopic->getUserId(), $oTopic->getType(), $oTopic->getTitle(),
|
||||
$oTopic->getBlogId4(), $oTopic->getBlogId5(), $oTopic->getUserId(), $oTopic->getType(), $oTopic->getTitle(), $oTopic->getSlug(),
|
||||
$oTopic->getTags(), $oTopic->getDateAdd(), $oTopic->getUserIp(), $oTopic->getPublish(),
|
||||
$oTopic->getPublishDraft(), $oTopic->getPublishIndex(), $oTopic->getSkipIndex(), $oTopic->getCutText(),
|
||||
$oTopic->getForbidComment(), $oTopic->getTextHash())
|
||||
|
@ -518,6 +519,7 @@ class ModuleTopic_MapperTopic extends Mapper
|
|||
blog_id4= ?d,
|
||||
blog_id5= ?d,
|
||||
topic_title= ?,
|
||||
topic_slug= ?,
|
||||
topic_tags= ?,
|
||||
topic_date_add = ?,
|
||||
topic_date_edit = ?,
|
||||
|
@ -542,7 +544,7 @@ class ModuleTopic_MapperTopic extends Mapper
|
|||
topic_id = ?d
|
||||
";
|
||||
$res = $this->oDb->query($sql, $oTopic->getBlogId(), $oTopic->getBlogId2(), $oTopic->getBlogId3(),
|
||||
$oTopic->getBlogId4(), $oTopic->getBlogId5(), $oTopic->getTitle(), $oTopic->getTags(),
|
||||
$oTopic->getBlogId4(), $oTopic->getBlogId5(), $oTopic->getTitle(), $oTopic->getSlug(), $oTopic->getTags(),
|
||||
$oTopic->getDateAdd(), $oTopic->getDateEdit(), $oTopic->getDateEditContent(), $oTopic->getUserIp(),
|
||||
$oTopic->getPublish(), $oTopic->getPublishDraft(), $oTopic->getPublishIndex(), $oTopic->getSkipIndex(),
|
||||
$oTopic->getRating(), $oTopic->getCountVote(), $oTopic->getCountVoteUp(), $oTopic->getCountVoteDown(),
|
||||
|
@ -590,6 +592,9 @@ class ModuleTopic_MapperTopic extends Mapper
|
|||
if (isset($aFilter['topic_date_more'])) {
|
||||
$sWhere .= " AND t.topic_date_add > " . $this->oDb->escape($aFilter['topic_date_more']);
|
||||
}
|
||||
if (isset($aFilter['topic_slug'])) {
|
||||
$sWhere .= " AND t.topic_slug = " . $this->oDb->escape($aFilter['topic_slug']);
|
||||
}
|
||||
if (isset($aFilter['topic_publish'])) {
|
||||
$sWhere .= " AND t.topic_publish = " . (int)$aFilter['topic_publish'];
|
||||
}
|
||||
|
|
|
@ -149,6 +149,43 @@ $config['module']['topic']['default_period_discussed'] = 1; // Дефолтны
|
|||
$config['module']['topic']['max_blog_count'] = 3; // Количество блогов, которые можно задать топику. Максимальное значение 5.
|
||||
$config['module']['topic']['max_rss_count'] = 20; // Максимальное количество топиков в RSS потоке
|
||||
$config['module']['topic']['default_preview_size'] = '900x300crop'; // Дефолтный размер превью для топика (все размеры задаются в конфиге media), который будет использоваться, например, для Open Graph
|
||||
/**
|
||||
* Настройка ЧПУ URL топиков
|
||||
* Допустимы шаблоны:
|
||||
* %year% - год топика (2010)
|
||||
* %month% - месяц (08)
|
||||
* %day% - день (24)
|
||||
* %hour% - час (17)
|
||||
* %minute% - минуты (06)
|
||||
* %second% - секунды (54)
|
||||
* %login% - логин автора топика (admin)
|
||||
* %blog% - url основного блога (report), если топик без блога, то этот параметр заменится на логин автора топика
|
||||
* %id% - id топика (325)
|
||||
* %title% - заголовок топика в транслите (moy_topic)
|
||||
* %type% - тип топика (news)
|
||||
*
|
||||
* В шаблоне обязательно должен быть %id% или %title%, это необходимо для точной идентификации топика
|
||||
*/
|
||||
$config['module']['topic']['url'] = '%year%/%month%/%day%/%id%.html';
|
||||
/**
|
||||
* Список регулярных выражений для частей URL топика
|
||||
* Без необходмых навыков лучше этот параметр не менять
|
||||
*/
|
||||
$config['module']['topic']['url_preg'] = array(
|
||||
'%year%' => '\d{4}',
|
||||
'%month%' => '\d{2}',
|
||||
'%day%' => '\d{2}',
|
||||
'%hour%' => '\d{2}',
|
||||
'%minute%' => '\d{2}',
|
||||
'%second%' => '\d{2}',
|
||||
'%login%' => '[\w\-\_]+',
|
||||
'%blog%' => '[\w\-\_]+',
|
||||
'%id%' => '\d+',
|
||||
'%title%' => '[\w\-\_]+',
|
||||
'%type%' => '[\w\-\_]+',
|
||||
);
|
||||
|
||||
|
||||
// Модуль User
|
||||
$config['module']['user']['per_page'] = 15; // Число юзеров на страницу на странице статистики и в профиле пользователя
|
||||
$config['module']['user']['friend_on_profile'] = 15; // Ограничение на вывод числа друзей пользователя на странице его профиля
|
||||
|
|
|
@ -73,6 +73,15 @@
|
|||
entity = 'ModuleTopic_EntityTopic'
|
||||
label = $aLang.topic.add.fields.title.label}
|
||||
|
||||
{* URL топика *}
|
||||
{if $oUserCurrent->isAdministrator()}
|
||||
{component 'field' template='text'
|
||||
name = 'topic[topic_slug_raw]'
|
||||
value = {(( $topic ) ? $topic->getSlug() : '')|escape}
|
||||
note = {lang 'topic.add.fields.slug.note'}
|
||||
label = {lang 'topic.add.fields.slug.label'}}
|
||||
{/if}
|
||||
|
||||
{block 'add_topic_form_text_before'}{/block}
|
||||
|
||||
|
||||
|
|
|
@ -1080,6 +1080,10 @@ return array(
|
|||
'title' => array(
|
||||
'label' => 'Заголовок'
|
||||
),
|
||||
'slug' => array(
|
||||
'label' => 'URL',
|
||||
'note' => 'Формируется автоматически из названия топика, но вы можете задать свое значение'
|
||||
),
|
||||
'text' => array(
|
||||
'label' => 'Текст'
|
||||
),
|
||||
|
@ -1114,6 +1118,7 @@ return array(
|
|||
'error_blog_not_allowed' => 'Вы не можете писать в этот блог',
|
||||
'error_text_unique' => 'Вы уже писали топик с таким содержанием',
|
||||
'error_type' => 'Неверный тип топика', // TODO: Remove?
|
||||
'error_slug' => 'Необходимо указать URL топика',
|
||||
'error_favourite_draft' => 'Топик из черновиков нельзя добавить в избранное',
|
||||
'time_limit' => 'Вам нельзя создавать топики слишком часто',
|
||||
'rating_limit' => 'Вам не хватает рейтинга для создания топика',
|
||||
|
|
|
@ -872,3 +872,6 @@ ALTER TABLE `prefix_invite_use`
|
|||
|
||||
-- 07.03.2015
|
||||
ALTER TABLE `prefix_user` CHANGE `user_referal_code` `user_referral_code` VARCHAR(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
|
||||
|
||||
-- 17.03.2015
|
||||
ALTER TABLE `prefix_topic` ADD `topic_slug` VARCHAR(500) NOT NULL DEFAULT '' AFTER `topic_title`, ADD INDEX (`topic_slug`) ;
|
||||
|
|
|
@ -61,15 +61,55 @@ require_once($sPathToFramework . '/config/loader.php');
|
|||
/**
|
||||
* Определяем дополнительные параметры роутинга
|
||||
*/
|
||||
$aRouterParams = array(/*
|
||||
'callback_after_parse_url' => function() {
|
||||
$aRouterParams = array(
|
||||
'callback_after_parse_url' => array(
|
||||
function () {
|
||||
/**
|
||||
* Логика по ЧПУ топиков
|
||||
* Если URL соответствует шаблону ЧПУ топика, перенаправляем обработку на экшен/евент /blog/_show_topic_url/
|
||||
* Через свои параметры конфига передаем исходный URL и ключ из конфига 'module.security.hash', ключ нужен для проверки валидности запроса.
|
||||
* Если ключ верный, то 100% это внутренняя обработка, а не произвольное внешнее обращение к URL
|
||||
* Суть обработки _show_topic_url в том, чтобы определить ID топика и корректность его URL, если он некорректен, то произвести его корректировку через внешний редирект на правильный URL
|
||||
* Если удалось определить топик и URL корректный, то происходит внутренний редирект на стандартный евент отображения топика по ID (/blog/12345.html)
|
||||
*/
|
||||
|
||||
}
|
||||
*/
|
||||
$sUrlRequest = '';
|
||||
if (Router::GetAction()) {
|
||||
$sUrlRequest .= Router::GetAction();
|
||||
}
|
||||
if (Router::GetActionEvent()) {
|
||||
$sUrlRequest .= '/' . Router::GetActionEvent();
|
||||
}
|
||||
if (Router::GetParams()) {
|
||||
$sUrlRequest .= '/' . join('/', Router::GetParams());
|
||||
}
|
||||
/**
|
||||
* Функция для формирования регулярного выражения по маске URL топика
|
||||
*
|
||||
* @param string $sUrl
|
||||
* @return string
|
||||
*/
|
||||
$funcMakePreg = function ($sUrl) {
|
||||
$sUrl = preg_quote(trim($sUrl, '/ '));
|
||||
return strtr($sUrl, Config::Get('module.topic.url_preg'));
|
||||
};
|
||||
$sPreg = $funcMakePreg(Config::Get('module.topic.url'));
|
||||
if (preg_match('@^' . $sPreg . '$@iu', $sUrlRequest)) {
|
||||
Router::SetAction('blog');
|
||||
Router::SetActionEvent('_show_topic_url');
|
||||
Router::SetParams(array());
|
||||
/**
|
||||
* Хак - через конфиг передаем нужные параметры в обработчик эвента
|
||||
* Модуль кеша здесь нельзя использовать, т.к. еще не произошло инициализации ядра
|
||||
*/
|
||||
Config::Set('module.topic._router_topic_original_url', $sUrlRequest);
|
||||
Config::Set('module.topic._router_topic_security_hash', Config::Get('module.security.hash'));
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Проверяем наличие директории install
|
||||
*/
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit ea1a9ac4c47041e76c8d2665dc0f95cc4f48dfe1
|
||||
Subproject commit ae7dfb5d8bb201af9937d7040bcbab4d2f23b8d3
|
Loading…
Reference in a new issue