Категории в Вопросах и ответах

Обещаный пример пример адаптации категорий.

Добавляем категории к плагину Вопросы и ответы (далее Qa :). Данный пример реализован тут.

Сразу к делу.

Для начала нужно добавить в таблицы prefix_category и prefix_category_relation полю target_type новый тип qa, выполняем запросы:

ALTER TABLE `prefix_category` CHANGE `target_type` `target_type` ENUM( 'topic', 'qa' ) DEFAULT 'topic'
ALTER TABLE `prefix_category_relation` CHANGE `target_type` `target_type` ENUM( 'topic', 'qa' ) DEFAULT 'topic'

Добавляем префикс для определение хуком экшена. В plugins\category\config\config.php находим
'blog'=>array('title'=>'Топики','prefix'=>'topic'),

и добавляем
'qa'=>array('title'=>'Вопросы и ответы','prefix'=>'qa'),

Находим
Config::Set('router.page.category_topic', 'PluginCategory_ActionTopic');

И добавляем экшен для категорий QA
Config::Set('router.page.category_qa', 'PluginCategory_ActionQa');

Добавляем блоки для Qa

Config::Set('block.rule_index_blog', array(
	'action'  => array(
  'index','blog','topic'
	),
	'blocks'  => array(
		'right' => array(
      'stream'=>array('priority'=>100),
      'Category'=>array('params'=>array('plugin'=>'category'),'priority'=>150),
      'tags'=>array('priority'=>50),
      'blogs'=>array('params'=>array(),'priority'=>1),
 		)
	),
	'clear' => false,
));

Открываем plugins\category\classes\hooks\HookCategory.class.php и регистрируем хуки в public function RegisterHook() {, добвляем строчки:
$this->AddHook('template_form_add_qa_begin','CategorySelect');
      $this->AddHook('qa_add_after','TopicEditAfter');
      $this->AddHook('qa_edit_show','TopicEditAfter');
      $this->AddHook('qa_edit_after','TopicEditAfter');

Создаем экшен для категорий Qa файл plugins\category\classes\actions\ActionQa.class.php с содержимым
<?php

class PluginCategory_ActionQa extends ActionPlugin {

  protected $sMenuItemSelect='qa';
  protected $oUserCurrent=null;

  public function Init() {
    $this->oUserCurrent=$this->User_GetUserCurrent();
    $this->SetDefaultEvent('last');
  }
	
  protected function RegisterEvent() {
    $this->AddEventPreg('/^([\w\-\_]+)$/i','EventCategory');
    $this->AddEventPreg('/^([\w\-\_]+)$/i','/^(page(\d+))?$/i','EventCategory');
  }

  protected function EventCategory() {

    $sCategoryUrl=$this->sCurrentEvent;
    if (!($oCategory=$this->PluginCategory_Category_GetCategoryByUrl($sCategoryUrl))){
      return Router::Action('error');
    }

    $sPage=$this->GetParam(0);
    if (preg_match("/^page(\d+)$/i",$sPage,$aMatch)) {$iPage=$aMatch[1];} else {$iPage=1;}

    $aResult = $this->PluginCategory_Qatopic_GetTopicsAll($iPage, Config::Get('plugin.qa.per_page'),$oCategory);
    $aTopics = $aResult['collection'];
    $aId=array();
    if (!empty($aTopics)){
      foreach ($aTopics as $oTopic){
        $aId[]=$oTopic->getId();
      }
    }
    $aPaging = $this->Viewer_MakePaging($aResult['count'], $iPage, Config::Get('plugin.qa.per_page'), 4, Router::GetPath('qa') . $sCategoryUrl);

    $this->Viewer_Assign('aTopics', $aTopics);
    $this->Viewer_Assign('aPaging', $aPaging);
    $this->Viewer_Assign('oCategory', $oCategory);

    $this->AddBlock($aId);

    $this->SetTemplateAction('index');
    
  }

  public function AddBlock($aId) {
    $this->Viewer_ClearBlocks('right');
    $this->Viewer_AddBlock('right','Category',array('plugin'=>'category'),100);
    $this->Viewer_AddBlock('right','qacommentsonline',array('plugin'=>'qa'),50);
    $this->Viewer_AddBlock('right','qatags',array('plugin'=>'qa','topics_id'=>$aId),1000);
  }
  
  public function EventShutdown() {
    $this->Viewer_Assign('sMenuItemSelect',$this->sMenuItemSelect);
    $this->Viewer_Assign('sTemplateCategoryPath',rtrim(Plugin::GetTemplatePath('category'),'/'));
    $this->Viewer_Assign('sTemplateQaPath',rtrim(Plugin::GetTemplatePath('qa'),'/'));
    $this->Viewer_Assign('sTemplateCategoryWebPathPlugin',rtrim(Plugin::GetTemplateWebPath(__CLASS__),'/'));
  }
}
?>

Добавляем файл шаблона для экшена. Создаем plugins\category\templates\skin\default\actions\ActionQa\ в него копируем index.tpl из plugins\qa\templates\skin\default\actions\ActionQa\.

Создаем папки модуля plugins\category\classes\modules\qatopic\ и мапера plugins\category\classes\modules\qatopic\mapper. Создаем фай модуля plugins\category\classes\modules\qatopic\Qatopic.class.php c содержмым:
<?php
class PluginCategory_ModuleQatopic extends Module {
    protected $oMapperTopic;
    protected $oUserCurrent = null;

    public function Init() {
        $this->oMapperTopic = Engine::GetMapper(__CLASS__);
        $this->oUserCurrent = $this->User_GetUserCurrent();
    }

    public function GetTopicsAll($iPage, $iPerPage, $oCategory) {

        $aArrayId=array();
        $aArrayId[]=$oCategory->getId();

        $aArrayId=$this->PluginCategory_Category_GetCategoryArrayIdTree($oCategory->getType(),$oCategory->getId(),$aArrayId);

        $data = $this->oMapperTopic->GetArrayQaTopicsByCetegory($iPage, $iPerPage, $aArrayId, $oCategory->getType());
        if (!empty($data['collection'])){
          $data['collection'] = $this->PluginQa_Qatopic_GetTopicsAdditionalData($data['collection']);
          foreach ($data['collection'] as $oTopic){
            $oTopic->setCategory($oCategory);
          }
        }
        return $data;
  }
}
?>

Создаем файл мапера plugins\category\classes\modules\qatopic\mapper\Qatopic.mapper.class.php с содержимым
<?php
class PluginCategory_ModuleQatopic_MapperQatopic extends Mapper {

    public function GetArrayQaTopicsByCetegory($iPage, $iPerPage, $aArrayId, $sShowType) {
        $aReturn=array();
        $aReturn['collection'] = null;
        $aReturn['count'] = 0;
        if (!is_array($aArrayId) or count($aArrayId) == 0) {
            return $aReturn;
        }

        $sql = "SELECT
          count(*) as count
				FROM
					".Config::Get('plugin.category.table.category_relation')."
				WHERE
					category_id IN(?a) AND target_type = ?";
        $iCount = 0;
        if ($aRow = $this->oDb->selectRow($sql, $aArrayId, $sShowType)) {
          $iCount=$aRow['count'];
        }

        $sql = "SELECT
					t.topic_id,
          cr.target_id, cr.category_id
				FROM 
					".Config::Get('db.table.qa_topic')." as t
					JOIN  ".Config::Get('plugin.category.table.category_relation')." AS cr ON cr.target_id=t.topic_id
				WHERE
					cr.category_id IN(?a) AND cr.target_type = ?
				ORDER BY t.topic_date_add DESC LIMIT ?d, ?d";
        $aTopics = array();
        if ($aRows = $this->oDb->select($sql, $aArrayId, $sShowType, ($iPage - 1) * $iPerPage, $iPerPage)) {
            foreach ($aRows as $aRow) {
                $aTopics[] = $aRow['topic_id'];
            }
        }
        $aReturn['collection'] = $aTopics;
        $aReturn['count'] = $iCount;
        return $aReturn;
    }

}

?>

далее осталось добаить хуки в экшен и шаблон add.tpl плагина Qa. Открываем экшен плагина Qa plugins\qa\classes\actions\ActionQa.class.php и добавляем хуки.
Находим строчку
if ($this->PluginQa_Qatopic_AddTopic($oTopic)) {

и после нее добавляем
$this->Hook_Run('qa_add_after', array('oTopic'=>$oTopic));

Находим строчку
if (!$this->ACL_IsAllowEditTopic($oTopic, $this->oUserCurrent)) {

и перед ней добавляем
$this->Hook_Run('qa_edit_show',array('oTopic'=>$oTopic));

Нахдим строчку
if ($this->PluginQa_Qatopic_UpdateTopic($oTopic)) {

и добавляем
$this->Hook_Run('qa_edit_after', array('oTopic'=>$oTopic));

Открываем plugins\qa\templates\skin\default\actions\ActionQa\add.tpl находим
<form action="" method="POST" enctype="multipart/form-data">

И добавляем
{hook run='form_add_qa_begin'}


Все.

19 комментариев

avatar
Хм, я до такого не дошел в своё время, и просто обозвал теги «категориями», а поле ввода тегов сделал выпадающим, с выбором из имеющихся в базе, чтобы нельзя было выбрать несколько, а только один, как будто это категория.
avatar
а как это реализовать, подскажите. Хочу так же сделать, для меня идеальное решение.
avatar
Все зашибись, но первый же апгрейд плагина запросто может похерить все эти «вкусности». В общем, я бы настоятельно советовал подчеркивать, что подобные штуки рекомендуются только тем, кто все обновления делает с «напильником» в руках.
avatar
в Qa все изменения — это добавление хуков, да и написано что это пример использования категорий с другими плагинами.
avatar
Спасибо, замечательный пример, работает. Если не сложно, подскажите условие, как сделать чтобы пользователь, не выбрав категорию, не смог создать вопрос? Сейчас такая возможность есть.
  • Mitya
  • 0
avatar
Уважаемый автор плагина категории огромная просьба подскажите пож почему при переходе по ссылке из блока категорий выдается ошибка 404 ls 0.5 от ошибок которые были при установке я избавился путями озвученными в комментариях побывал на 2 разных серверах и на локальном ни чего не помогает (все остальные функции работают) пробывал на чистом ls
avatar
как и почему я знать не могу, ибо какой код вы написали или скопировали я невижу
возможный вариант решения livestreet.ru/blog/FreeModules/8397.html#comment124925
avatar
livestreet.ru/blog/FreeModules/7803.html#comment114767 все эти решения я к моему сожалению испробывал — безуспешно. Именно поэтому пишу (плагин я не видоизменял единственно буквы в конфигах поправил как рекомендовали )
avatar
ну так а этот топик причем? возможный вариант решения livestreet.ru/blog/FreeModules/8397.html#comment124925
avatar
возможно у Вас чтото в настройках сервера и отсутствуетс переменная $_SERVER['REDIRECT_URL'], попробуйте в
\plugins\category\classes\hooks\HookCategory.class.php изменить
$aUrl = explode('/', trim(@$_SERVER['REDIRECT_URL'], '/'));
на
$aUrl = explode('/', trim(@$_SERVER['REQUEST_URI'], '/'));
85 строчка
Вы это имели в виду это? Пробывал без результата
avatar
будьте добры пишите туда где Ваш вопрос будет в тему.
по вопросу, незнаю — не сталкивался, бросайте в личку доступы как будет время посмотрю в чем может быть проблема
avatar
Все разобрался уровень вложенности увеличил до 5 в config/config.local.php на 3 не работало
avatar
Только теперь в админку не могу попасть)))
avatar
Не заметил ничего в примере, он не актуален? А инструкция подойдет для последней версии QA? =)
avatar
проверили актуальность для текущей версии?
avatar
Нет, не проверял.
avatar
А как сделать категории для блогов?
avatar
Остановились на самом интересном вопросе.
avatar
Продолжение здесь
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.