Что делает: каждому материалу можно присвоить несколько категорий. При просмотре материала будут показаны все категории, в которых содержится материал (хотя это уже на ваше усмотрение, можете и не показывать). При просмотре категорий дубликатов, естественно, никаких нет.
Хак требует изменения как базы данных так и нескольких файлов самой Joomla, так что перед тем как редактировать файлы, сделайте их копии.
Шаг 1 - Выполнить скрипт для БД, где # - префикс таблиц в вашей БД. Лучше всего это делать через phpMyAdmin.
ALTER TABLE `#_content` ADD `catid2` INT ( 11 ) NOT NULL DEFAULT '0' AFTER `catid` ;
ALTER TABLE `#_content` ADD `catid3` INT ( 11 ) NOT NULL DEFAULT '0' AFTER `catid2` ;
ALTER TABLE `#_content` ADD INDEX ( `catid2` );
ALTER TABLE `#_content` ADD INDEX ( `catid3` );
Шаг 2 - Добавляем в админке возможность при создании/редактировании материала указывать несколько категорий
Редактируем файл administrator\components\com_content\views\article\tmpl\edit.php
Ищем
<?php echo $this->form->getInput('catid'); ?>
Добавляем после
<?php echo $this->form->getInput('catid2'); ?><?php echo $this->form->getInput('catid3'); ?>
Редактируем файл administrator\components\com_content\models\forms\article.xml
Ищем
<field name="catid" type="categoryedit"
label="JCATEGORY" description="JFIELD_CATEGORY_DESC"
class="inputbox" required="true"
>
</field>
Добавляем после
<field name="catid2" type="categoryedit"
label="JCATEGORY" description="JFIELD_CATEGORY_DESC"
class="inputbox" required="false" default="0"
><option value="0">
Select Category</option>
</field>
<field name="catid3" type="categoryedit"
label="JCATEGORY" description="JFIELD_CATEGORY_DESC"
class="inputbox" required="false" default="0"
><option value="0">
Select Category</option>
</field>
Шаг 3 - делаем возможность в админке для материалов привязанных к нескольким категориям в столбце Категория показывать все категории, к которым привязан материал
Редактируем файл administrator\components\com_content\views\articles\tmpl\default.php
Ищем
<?php echo $this->escape($item->category_title); ?>
и заменяем на
<?php echo $this->escape($item->category_title);
if ($item->category_title2) echo '<hr />'.$this->escape($item->category_title2);
if ($item->category_title3) echo '<hr />'.$this->escape($item->category_title3);
?>
В описанном варианте выводится список категорий просто в столбик. Разделение сделано горизонтальной линией для удобства. Удобно для небольшого колличества категорий, не более 3х.
Редактируем файл administrator\components\com_content\models\articles.php
Ищем
// Join over the categories.
$query->select('c.title AS category_title');
$query->join('LEFT', '#__categories AS c ON c.id = a.catid');
и добавляем после :
// Join over the categories to get other category titles
$query->select('sister2.title AS category_title2');
$query->join('LEFT', '#__categories AS sister2 ON sister2.id = a.catid2');
$query->select('sister3.title AS category_title3');
$query->join('LEFT', '#__categories AS sister3 ON sister3.id = a.catid3');
Ищем
$query->where('c.lft >= '.(int) $lft);
$query->where('c.rgt <= '.(int) $rgt);
и заменяем на
$query->where('(c.lft >= '.(int) $lft.' AND c.rgt <= '.(int) $rgt.') OR (sister2.lft >= '.(int) $lft.' AND sister2.rgt <= '.(int) $rgt.') OR (sister3.lft >= '.(int) $lft.' AND sister3.rgt <= '.(int) $rgt.')');
Шаг 4 - Учим Joomla показывать при просмотре материала все категории, за которыми закреплен данный материал.
Редактируем файл components\com_content\models\article.php
Ищем
$query->select($this->getState(
'item.select', 'a.id, a.asset_id, a.title, a.alias, a.title_alias, a.introtext, a.fulltext, ' .
// If badcats is not null, this means that the article is inside an unpublished category
// In this case, the state is set to 0 to indicate Unpublished (even if the article state is Published)
'CASE WHEN badcats.id is null THEN a.state ELSE 0 END AS state, ' .
'a.mask, a.catid, a.created, a.created_by, a.created_by_alias, ' .
// use created if modified is 0
Заменяем на
$query->select($this->getState(
'item.select', 'a.id, a.asset_id, a.title, a.alias, a.title_alias, a.introtext, a.fulltext, ' .
// If badcats is not null, this means that the article is inside an unpublished category
// In this case, the state is set to 0 to indicate Unpublished (even if the article state is Published)
'CASE WHEN badcats.id is null THEN a.state ELSE 0 END AS state, ' .
'a.mask, a.catid, a.catid2, a.catid3, a.created, a.created_by, a.created_by_alias, ' .
// use created if modified is 0
Ищем
// Join on category table.
$query->select('c.title AS category_title, c.alias AS category_alias, c.access AS category_access');
$query->join('LEFT', '#__categories AS c on c.id = a.catid');
Добавляем после
// Join over the categories to get other category titles
$query->select('sister2.title as category_title2');
$query->join('LEFT', '#__categories as sister2 ON sister2.id = a.catid2');
$query->select('sister3.title as category_title3');
$query->join('LEFT', '#__categories as sister3 ON sister3.id = a.catid3');
Редактируем файл components\com_content\views\article\tmpl\default.php
Ищем
$url = '<a href="'.JRoute::_(ContentHelperRoute::getCategoryRoute($this->item->catslug)).'">'.$title.'</a>';?>
<?php if ($params->get('link_category') and $this->item->catslug) : ?>
<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $url); ?>
<?php else : ?>
<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $title); ?>
Заменяем на
$title2 = $this->escape($this->item->category_title2);
$title3 = $this->escape($this->item->category_title3);
$url = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($this->item->catid)) . '">' . $title . '</a>';
$url2 = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($this->item->catid2)) . '">' . $title2 . '</a>';
$url3 = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($this->item->catid3)) . '">' . $title3 . '</a>';
?>
<?php if ($params->get('link_category')) : ?>
<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $url);
if ($this->item->category_title2) echo ', '.$url2;
if ($this->item->category_title3) echo ', '.$url3;
?>
<?php else : ?>
<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $title);
if ($this->item->category_title2) echo ', '.$title2;
if ($this->item->category_title3) echo ', '.$title3;
?>
Примечание: эту же операцию с файлом default.php необходимо проделать и с используемыми вами шаблонами, если в них есть этот файл. Например его содержит шаблон beez5\html\com_content\article\default.php
Шаг 5 - Учим Joomla показывать при просмотре категории все категории, за которыми закреплены материалы.
Редактируем файл components\com_content\models\articles.php
найти
// Select the required fields from the table.
$query->select(
$this->getState(
'list.select',
'a.id, a.title, a.alias, a.title_alias, a.introtext, ' .
'a.checked_out, a.checked_out_time, ' .
'a.catid, a.created, a.created_by, a.created_by_alias, ' .
Заменяем на
// Select the required fields from the table.
$query->select(
$this->getState(
'list.select',
'a.id, a.title, a.alias, a.title_alias, a.introtext, ' .
'a.checked_out, a.checked_out_time, ' .
'a.catid, a.catid2, a.catid3, a.created, a.created_by, a.created_by_alias, ' .
ищем
// Join over the categories to get parent category titles
$query->select('parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias');
$query->join('LEFT', '#__categories as parent ON parent.id = c.parent_id');
Добавляем после
// Join over the categories to get other category titles
$query->select('sister2.title as category_title2');
$query->join('LEFT', '#__categories as sister2 ON sister2.id = a.catid2');
$query->select('sister3.title as category_title3');
$query->join('LEFT', '#__categories as sister3 ON sister3.id = a.catid3');
ищем
$categoryEquals = 'a.catid '.$type.(int) $categoryId;
Заменяем на
$categoryEquals = 'a.catid '.$type.(int) $categoryId.' OR a.catid2 '.$type.(int) $categoryId.' OR a.catid3 '.$type.(int) $categoryId;
Следующзее изменение добавлено 20.03.2015
ищем
$query->where('a.catid '.$type.' ('.$categoryId.')');
заменяем на
$query->where('a.catid '.$type.' ('.$categoryId.') OR a.catid2 '.$type.' ('.$categoryId.') OR a.catid3 '.$type.' ('.$categoryId.')');Редактируем файл components\com_content\views\category\tmpl\blog_item.php
найти
$url = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($this->item->catid)) . '">' . $title . '</a>'; ?>
<?php if ($params->get('link_category')) : ?>
<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $url); ?>
<?php else : ?>
<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $title); ?>
Заменить на
$title2 = $this->escape($this->item->category_title2);
$title3 = $this->escape($this->item->category_title3);
$url = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($this->item->catid)) . '">' . $title . '</a>';
$url2 = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($this->item->catid2)) . '">' . $title2 . '</a>';
$url3 = '<a href="' . JRoute::_(ContentHelperRoute::getCategoryRoute($this->item->catid3)) . '">' . $title3 . '</a>';
?>
<?php if ($params->get('link_category')) : ?>
<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $url);
if ($this->item->category_title2) echo JText::sprintf('COM_CONTENT_CATEGORY', $url2);
if ($this->item->category_title3) echo JText::sprintf('COM_CONTENT_CATEGORY', $url3);
?>
<?php else : ?>
<?php echo JText::sprintf('COM_CONTENT_CATEGORY', $title);
if ($this->item->category_title2) echo JText::sprintf('COM_CONTENT_CATEGORY', $title2);
if ($this->item->category_title3) echo JText::sprintf('COM_CONTENT_CATEGORY', $title3);
?>
Примечание: эту же операцию с файлами blog_item.php необходимо проделать и с используемыми вами шаблонами, если в них есть этот файл. Например его содержит шаблон beez5\html\com_content\category\blog_item.php
Шаг 6 - добавляем возможность указания нескольких категорий в fronted редакторе (если нужно)
Редактируем файл components\com_content\models\forms\article.xml
Ищем
<field
id="catid"
name="catid"
type="categoryedit"
extension="com_content"
label="JCATEGORY"
description="JFIELD_CATEGORY_DESC"
class="inputbox"
required="true">
</field>
Добавляем после
<field
id="catid2"
name="catid2"
type="categoryedit"
extension="com_content"
label="JCATEGORY"
description="JFIELD_CATEGORY_DESC"
class="inputbox"
default="0"
required="false">
<option value="0">Select Category</option>
</field>
<field
id="catid3"
name="catid3"
type="categoryedit"
extension="com_content"
label="JCATEGORY"
description="JFIELD_CATEGORY_DESC"
class="inputbox"
default="0"
required="false">
<option value="0">Select Category</option>
</field>
Редактируем файл components\com_content\views\form\tmpl\edit.php
найти
<?php echo $this->form->getInput('catid'); ?>
заменить на
<?php echo $this->form->getInput('catid'); ?><?php echo $this->form->getInput('catid2'); ?><?php echo $this->form->getInput('catid3'); ?>Всё, теперь можно работать.