Похожие статьи

[Hack] Один материал в нескольких категориях для Joomla 2.5 (мультикатегории)

Обратились ко мне в очередной раз помощью на тему мультикатегорий для Joomla 2.5, также как и в случае с мультикатегориями для Joomla 1.5, только заказчик...

[Hack] Сортировка материалов по их рейтингу в Joomla 2.5

Задача - сделать возможность сортировки по рейтингу материала. Система рейтингов в стандартной конфигурации Joomla 2.5 уже присутствует, но вот возможности сортировать материалы по этим рейтингам почему то нет. Следующими изменениями мы исправим эту досадную оплошность.

Проблема Opera с Joomla и файла mootools-more.js

После последних обновлений Opera 12 возникли проблемы с работой сайтов на движке Joomla, а если быть более точным, то перестала работать библиотека mootools и все что с ней связано соответственно. Проблема связана с сжатием файла mootools-more.js из-за содержания в нем локальных символов. Соответственно...

Последние обновления

Монтируем EXT2, EXT3, EXT4 в Mac OS

Mac OS самостоятельно работать с файловой системой Linux, таких как EXT2, EXT3, EXT4, не может. Для решения этой проблемы есть платное решение extFS от Paragon, но есть и бесплатный вариант для тех кто не боится командной строки. Для этого нам понадобиться приложение fuse-ext2.

Установка Windows 11 без интернета или без учетной записи Microsoft

Windows 11 при первичном запуске требует подключения интернета и учётной записи Microsoft, но на практике бывают ситуации когда нет интернета или нет желания использовать учетную запись Microsoft. Например, в моём случае при подключении WiFi выдавало сообщение "oops you've lost internet connection".

Автоматизация получения бесплатных SSL сертификатов на хостинге RUCENTER

Можно долго ругаться на RUCENTER за нежелание дать клиентам виртуального хостинга бесплатные SSL сертификаты, но воз и ныне  там. В связи с этим пользователям остается либо уходить на другой хостинг, либо оставаться без HTTPS протокола и наблюдать неприятные пометки о небезопасности...

[Hack] Один материал в нескольких категориях для Joomla 1.5 (мультикатегории)

Делал я как то сайт для одной компании, среди условий было использование движка Joomla и возможность размещения одной статьи в нескольких категориях, они почему то были уверены что в Joomla это есть. Для меня же это было первое знакомство с Joomla, поэтому не возражал, но практика показала что ничего стоящего для размещения статей в нескольких категориях не оказалось, единственное что оказалось более менее близко - это компонент ZOO. Но его реализация страдала на обе ноги, меня это абсолютно не устраивало. Так что собравшись мыслями и терпением стал изучать движок с целью его допиливания до наших нужд.  Данная реализация не имеет никаких проблем с SEO или SEF.

Что делает: каждому материалу можно присвоить несколько категорий, но в пределах одного раздела. При просмотре материала будут показаны все категории, в которых содержится материал (хотя это уже на ваше усмотрение, можете и не показывать). При просмотре раздела, дубликатов, естественно, никаких нет.

Хак требует изменения как базы данных так и нескольких файлов самой Joomla, так что перед тем как редактировать файлы, сделайте их копии.

Приступим: Описание сделано для возможности указания категорий, если нужно больше делайте по аналогии, принцип понять несложно.

Шаг 1 - Выполнить скрипт для БД, где # - префикс таблиц в вашей БД. Лучше всего это делать через phpMyAdmin.

ALTER TABLE `#_content` ADD `catid2` INT ( 11 ) NOT NULL DEFAULT '-1' AFTER `catid` ;
ALTER TABLE `#_content` ADD `catid3` INT ( 11 ) NOT NULL DEFAULT '-1' AFTER `catid2` ;
ALTER TABLE `#_content` ADD INDEX ( `catid2` );
ALTER TABLE `#_content` ADD INDEX ( `catid3` );

Шаг 2 - Обьясняем Joomla, что у нас в таблице content появились новые поля.

Редактируем файл libraries\joomla\database\table\content.php

Ищем

var $catid= null;

Добавляем после

var $catid2= null;
var $catid3= null;

Шаг 3 - Добавляем в админке возможность при создании/редактировании материала указывать несколько категорий
Редактируем файл administrator\components\com_content\admin.content.html.php
Ищем

<?php echo $lists['catid']; ?>

Добавляем после

                </br><?php echo $lists['catid2']; ?>
                </br><?php echo $lists['catid3']; ?>

Редактируем файл administrator\components\com_content\controller.php
Ищем

$javascript = "onchange=\"changeDynaList ( 'catid', sectioncategories, document.adminForm.sectionid.options[document.adminForm.sectionid.selectedIndex].value, 0, 0);\"";

Заменяем на

$javascript = "onchange=\"changeDynaList ( 'catid', sectioncategories, document.adminForm.sectionid.options[document.adminForm.sectionid.selectedIndex].value, 0, 0);changeDynaList ( 'catid2', sectioncategories, document.adminForm.sectionid.options[document.adminForm.sectionid.selectedIndex].value, 0, 0);changeDynaList ( 'catid3', sectioncategories, document.adminForm.sectionid.options[document.adminForm.sectionid.selectedIndex].value, 0, 0);\"";

Ищем

foreach ($cat_list as $cat)
{
if ($cat->section == $section->id) {
$rows2[] = $cat;
}
}

Добавляем после

$sectioncategories[$section->id][] = JHTML::_('select.option', '-1', JText::_( 'Select Category' ), 'id', 'title');

Ищем

$lists['catid'] = JHTML::_('select.genericlist',  $categories, 'catid', 'class="inputbox" size="1"', 'id', 'title', intval ($row->catid));

Добавляем после

$lists['catid2'] = JHTML::_('select.genericlist',  $categories, 'catid2', 'class="inputbox" size="1"', 'id', 'title', intval ($row->catid2));
$lists['catid3'] = JHTML::_('select.genericlist',  $categories, 'catid3', 'class="inputbox" size="1"', 'id', 'title', intval ($row->catid3));

Шаг 4 - Учим Joomla показывать материалы, в которых указано несколько категорий
Редактируем файл components\com_content\models\category.php
Ищем

$where .= ' AND a.catid = '.(int) $this->_id;

Заменяем на

$where .= ' AND (a.catid = '.(int) $this->_id.' OR a.catid2 = '.(int) $this->_id.' OR a.catid3 = '.(int) $this->_id.')';

Шаг 5 - Учим Joomla показывать при просмотре материала все категории, за которыми закреплен данный материал.
Редактируем файл components\com_content\models\article.php
Ищем

$this->_article = $this->_db->loadObject ();

Добавляем после

if ($this->_article->catid2 != -1) {
$query = 'SELECT title'.
' FROM #__categories' .
' WHERE id = '.$this->_article->catid2;
$this->_db->setQuery ($query);
$this->_cat2 = $this->_db->loadObject ();
$this->_article->category2= $this->_cat2->title;
}

if ($this->_article->catid3 != -1) {
$query = 'SELECT title'.
' FROM #__categories' .
' WHERE id = '.$this->_article->catid3;
$this->_db->setQuery ($query);
$this->_cat3 = $this->_db->loadObject ();
$this->_article->category3= $this->_cat3->title;
}

Редактируем файл components\com_content\views\article\tmpl\default.php
Ищем

<?php if ($this->params->get ('link_category')) : ?>
<?php echo '<a href="'.JRoute::_(ContentHelperRoute::getCategoryRoute ($this->article->catslug, $this->article->sectionid)).'">'; ?>
<?php endif; ?>
<?php echo $this->escape ($this->article->category); ?>
<?php if ($this->params->get ('link_category')) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>

Добавляем после

             <?php if ($this->params->get ('link_category') && $this->article->category2) : ?>
<?php echo ',
<a href="'.JRoute::_(ContentHelperRoute::getCategoryRoute ($this->article->catid2, $this->article->sectionid)).'">'; ?>
<?php endif; ?>
<?php echo $this->escape ($this->article->category2); ?>
<?php if ($this->params->get ('link_category') && $this->article->category2) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>
            <?php if ($this->params->get ('link_category') && $this->article->category3) : ?>
<?php echo ',
<a href="'.JRoute::_(ContentHelperRoute::getCategoryRoute ($this->article->catid3, $this->article->sectionid)).'">'; ?>
<?php endif; ?>
<?php echo $this->escape ($this->article->category3); ?>
<?php if ($this->params->get ('link_category') && $this->article->category3) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>

Примечание: эту же операцию необходимо проделать и с используемыми вами шаблонами, если в них есть этот файл. Например его содержит шаблон ja_purity/html/com_content/article/default.php


Шаг 6 - Ну и наконец знакомим другие модули Joomla с нашим хаком (например модули mainmenu и breadcrumbs)
Редактируем файл components\com_content\views\category\view.html.php
Ищем

if (($item->params->get ('show_readmore') && @ $item->readmore) || $item->params->get ('link_titles'))
{

Добавляем после него

$itemid = JRequest::getInt ('id',0);

Далее ищем 

$item->readmore_link = JRoute::_(ContentHelperRoute::getArticleRoute ($item->slug, $item->catslug, $item->sectionid));

Заменяем на

$item->readmore_link = JRoute::_(ContentHelperRoute::getArticleRoute ($item->slug, $itemid, $item->sectionid));

Ищем 

$returnURL = JRoute::_(ContentHelperRoute::getArticleRoute ($item->slug, $item->catslug, $item->sectionid),false);

и заменяем на

$returnURL = JRoute::_(ContentHelperRoute::getArticleRoute ($item->slug, $itemid, $item->sectionid),false);

Шаг 7 - учим админку показывать при фильтрации по категории материалы привязанные к нескольким категориям
Редактируем файл administrator\components\com_content\controller.php
Найти   

$where[] = 'c.catid = ' . (int) $catid;

и заменить на

$where[] = '(c.catid = ' . (int) $catid .' OR c.catid2 = ' . (int) $catid .' OR c.catid3 = '. (int) $catid .')';

Шаг 8 - делаем возможность для материалов привязанных к нескольким категориям в столбце Категория показывать все категории, к которым привязан материал.
Редактируем файл administrator\components\com_content\controller.php
Ищем

// Get the articles
$query = 'SELECT c.*, g.name AS groupname, cc.title AS name, u.name AS editor, f.content_id AS frontpage, s.title AS section_name, v.name AS author' .
' FROM #__content AS c' .
' LEFT JOIN #__categories AS cc ON cc.id = c.catid' .
' LEFT JOIN #__sections AS s ON s.id = c.sectionid' .
' LEFT JOIN #__groups AS g ON g.id = c.access' .
' LEFT JOIN #__users AS u ON u.id = c.checked_out' .
' LEFT JOIN #__users AS v ON v.id = c.created_by' .
' LEFT JOIN #__content_frontpage AS f ON f.content_id = c.id' .
$where .
$order;

и заменяем на      

// Get the articles
$query = 'SELECT c.*, g.name AS groupname, cc.title AS name, cc2.title AS name2, cc3.title AS name3, u.name AS editor, f.content_id AS frontpage, s.title AS section_name, v.name AS author' .
' FROM #__content AS c' .
' LEFT JOIN #__categories AS cc ON cc.id = c.catid' .
' LEFT JOIN #__categories AS cc2 ON cc2.id = c.catid2' .
' LEFT JOIN #__categories AS cc3 ON cc3.id = c.catid3' .
' LEFT JOIN #__sections AS s ON s.id = c.sectionid' .
' LEFT JOIN #__groups AS g ON g.id = c.access' .
' LEFT JOIN #__users AS u ON u.id = c.checked_out' .
' LEFT JOIN #__users AS v ON v.id = c.created_by' .
' LEFT JOIN #__content_frontpage AS f ON f.content_id = c.id' .
$where .
$order;

Редактируем файл administrator\components\com_content\admin.content.html.php

Если хотите вывести список категорий просто в столбик, то делаем следующее. Разделение сделано горизонтальной линией для удобства. Удобно для небольшого колличества категорий, не более 3х.

Ищем (найдется две строки, сделать для обоих)

$row->cat_link = JRoute::_( 'index.php?option=com_categories&task=edit&cid[]='. $row->catid );

и добавляем после :         

$row->cat_link2 = JRoute::_( 'index.php?option=com_categories&task=edit&cid[]='. $row->catid2 );
$row->cat_link3 = JRoute::_( 'index.php?option=com_categories&task=edit&cid[]='. $row->catid3 );

Ищем (найдется две строки, сделать для обоих)      

<a href="/<?php echo $row->cat_link; ?>" title="<?php echo JText::_( 'Edit Category' ); ?>">
<?php echo $row->name; ?></a>

и добавить после них

                        <?php if ($row->catid2 && $row->catid2!=-1) : ?>
<hr><a href="/<?php echo $row->cat_link2; ?>" title="<?php echo JText::_( 'Edit Category' ); ?>">
<?php echo $row->name2; ?></a>
<?php endif; ?>
                        <?php if ($row->catid3 && $row->catid3!=-1) : ?>
<hr><a href="/<?php echo $row->cat_link3; ?>" title="<?php echo JText::_( 'Edit Category' ); ?>">
<?php echo $row->name3; ?></a>
<?php endif; ?>

Если хотите сделать в виде выпадающего списка по нажатию кнопки, то делаем следующее.

Ищем

<a href="/<?php echo $row->cat_link; ?>" title="<?php echo JText::_( 'Edit Category' ); ?>">
<?php echo $row->name; ?></a>

Заменяем на

<?php if (($row->catid2 && $row->catid2!=-1) || ($row->catid3 && $row->catid3!=-1)) : ?>
                    <div class="jpane-toggler"><span><?php echo JText::_( 'SELECT FROM LIST' ); ?></span></div>
                    <div class="jpane-slider">
<a href="/<?php echo $row->cat_link; ?>" title="<?php echo JText::_( 'Edit Category' ); ?>">
<?php echo $row->name; ?></a>
                        <?php if ($row->catid2 && $row->catid2!=-1) : ?>
<hr><a href="/<?php echo $row->cat_link2; ?>" title="<?php echo JText::_( 'Edit Category' ); ?>">
<?php echo $row->name2; ?></a>
<?php endif; ?>
                        <?php if ($row->catid3 && $row->catid3!=-1) : ?>
<hr><a href="/<?php echo $row->cat_link3; ?>" title="<?php echo JText::_( 'Edit Category' ); ?>">
<?php echo $row->name3; ?></a>
<?php endif; ?>
                        </div>
                        <?php else : ?>
                        <a href="/<?php echo $row->cat_link; ?>" title="<?php echo JText::_( 'Edit Category' ); ?>">
<?php echo $row->name; ?></a>
                    <?php endif; ?>

Ищем

<form action="index.php?option=com_content" method="post" name="adminForm">

Добавляем после 

  <script type="text/javascript">
window.addEvent('domready', function(){ new Accordion($$('div.jpane-toggler'), $$('div.jpane-slider'), {onActive: function(toggler, i) { toggler.addClass('jpane-toggler-down'); toggler.removeClass('jpane-toggler'); },onBackground: function(toggler, i) { toggler.addClass('jpane-toggler'); toggler.removeClass('jpane-toggler-down'); },duration: 300,opacity: false,alwaysHide: true}); });
  </script>

Если вы используете нестандартный шаблон админки, вам придется самостоятельно дорабатывать используемые стили jpane-toggler.

Шаг 9 - добавляем возможность указания нескольких категорий в fronted редакторе
Редактируем файл components\com_content\views\article\view.html.php
Ищем

$lists['catid'] = JHTML::_('select.genericlist',  $categories, 'catid', 'class="inputbox" size="1"', 'id', 'title', intval($article->catid));

Добавляем после 

$lists['catid2'] = JHTML::_('select.genericlist',  $categories, 'catid2', 'class="inputbox" size="1"', 'id', 'title', intval($article->catid2));
$lists['catid3'] = JHTML::_('select.genericlist',  $categories, 'catid3', 'class="inputbox" size="1"', 'id', 'title', intval($article->catid3));

найти

$javascript = "onchange=\"changeDynaList( 'catid', sectioncategories, document.adminForm.sectionid.options[document.adminForm.sectionid.selectedIndex].value, 0, 0);\"";

заменить на

$javascript = "onchange=\"changeDynaList ( 'catid', sectioncategories, document.adminForm.sectionid.options[document.adminForm.sectionid.selectedIndex].value, 0, 0);changeDynaList ( 'catid2', sectioncategories, document.adminForm.sectionid.options[document.adminForm.sectionid.selectedIndex].value, 0, 0);changeDynaList ( 'catid3', sectioncategories, document.adminForm.sectionid.options[document.adminForm.sectionid.selectedIndex].value, 0, 0);\"";

найти

foreach ($cat_list as $cat)
{
if ($cat->section == $section->id) {
$rows2[] = $cat;
}
}

Добавляем после

$sectioncategories[$section->id][] = JHTML::_('select.option', '-1', JText::_( 'Select Category' ), 'id', 'title');

Редактируем файл components\com_content\views\article\tmpl\form.php
Ищем

<?php echo $this->lists['catid']; ?>

Добавляем после

        </br><?php echo $this->lists['catid2']; ?>
        </br><?php echo $this->lists['catid3']; ?>

Шаг 10 - Учим Joomla показывать при просмотре раздела или категории все категории, за которыми закреплены материалы.
Редактируем файл components\com_content\models\section.php
найти

$limit= JRequest::getVar('limit', 0, '', 'int');
$limitstart= JRequest::getVar('limitstart', 0, '', 'int');

Добавляем после

$query = 'SELECT id, title'.
' FROM #__categories'.
' WHERE section = '.(int) $this->_id;
$this->_db->setQuery($query);
$this->_cat = $this->_db->loadObjectList();
foreach ($this->_cat as $data)
{
$cati[$data->id] = $data->title;
}

немного ниже найти

// check to determine if section or category has proper access rights
$rows[$i] = $row;

Добавляем после

if ($rows[$i]->catid2 != -1) $rows[$i]->category2= $cati[$rows[$i]->catid2];
if ($rows[$i]->catid3 != -1) $rows[$i]->category3= $cati[$rows[$i]->catid3];

найти

$query = 'SELECT a.id, a.title, a.alias, a.title_alias, a.introtext, a.fulltext, a.sectionid, a.state, a.catid, a.created, a.created_by, a.created_by_alias, a.modified, a.modified_by,' .
' a.checked_out, a.checked_out_time, a.publish_up, a.publish_down, a.attribs, a.hits, a.images, a.urls, a.ordering, a.metakey, a.metadesc, a.access,' .

заменить на

$query = 'SELECT a.*,' .

Редактируем файл components\com_content\models\category.php
найти

$limit= JRequest::getVar('limit', 0, '', 'int');
$limitstart= JRequest::getVar('limitstart', 0, '', 'int');

Добавляем после

$query = 'SELECT id, title'.
' FROM #__categories'.
' WHERE section = '.(int) $this->_category->section;
$this->_db->setQuery($query);
$this->_cat = $this->_db->loadObjectList();
foreach ($this->_cat as $data)
{
$cati[$data->id] = $data->title;
}

найти

// check to determine if section or category has proper access rights
$rows[$i] = $row;

Добавляем после

$rows[$i]->category1= $cati[$rows[$i]->catid];
if ($rows[$i]->catid2 != -1) $rows[$i]->category2= $cati[$rows[$i]->catid2];
if ($rows[$i]->catid3 != -1) $rows[$i]->category3= $cati[$rows[$i]->catid3];

найти

$query = 'SELECT cc.title AS category, a.id, a.title, a.alias, a.title_alias, a.introtext, a.fulltext, a.sectionid, a.state, a.catid, a.created, a.created_by, a.created_by_alias, a.modified, a.modified_by,' .
' a.checked_out, a.checked_out_time, a.publish_up, a.publish_down, a.attribs, a.hits, a.images, a.urls, a.ordering, a.metakey, a.metadesc, a.access,' .

заменить на

$query = 'SELECT cc.title AS category, a.*,' .

Редактируем файл components\com_content\views\section\tmpl\blog_item.php
найти

<?php if ($this->item->params->get('link_category')) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>

Добавляем после

            <?php if ($this->item->params->get ('link_category') && $this->item->category2) : ?>
<?php echo ',
<a href="'.JRoute::_(ContentHelperRoute::getCategoryRoute ($this->item->catid2, $this->item->sectionid)).'">'; ?>
<?php endif; ?>
<?php echo $this->escape ($this->item->category2); ?>
<?php if ($this->item->params->get ('link_category') && $this->item->category2) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>
            <?php if ($this->item->params->get ('link_category') && $this->item->category3) : ?>
<?php echo ',
<a href="'.JRoute::_(ContentHelperRoute::getCategoryRoute ($this->item->catid3, $this->item->sectionid)).'">'; ?>
<?php endif; ?>
<?php echo $this->escape ($this->item->category3); ?>
<?php if ($this->item->params->get ('link_category') && $this->item->category3) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>

Редактируем файл components\com_content\views\category\tmpl\blog_item.php
найти

<?php echo $this->escape($this->item->category); ?>
<?php if ($this->item->params->get('link_category')) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>

Заменить на

<?php echo $this->escape($this->item->category1); ?>
<?php if ($this->item->params->get('link_category')) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>
            <?php if ($this->item->params->get ('link_category') && $this->item->category2) : ?>
<?php echo ',
<a href="'.JRoute::_(ContentHelperRoute::getCategoryRoute ($this->item->catid2, $this->item->sectionid)).'">'; ?>
<?php endif; ?>
<?php echo $this->escape ($this->item->category2); ?>
<?php if ($this->item->params->get ('link_category') && $this->item->category2) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>
            <?php if ($this->item->params->get ('link_category') && $this->item->category3) : ?>
<?php echo ',
<a href="'.JRoute::_(ContentHelperRoute::getCategoryRoute ($this->item->catid3, $this->item->sectionid)).'">'; ?>
<?php endif; ?>
<?php echo $this->escape ($this->item->category3); ?>
<?php if ($this->item->params->get ('link_category') && $this->item->category3) : ?>
<?php echo '</a>'; ?>
<?php endif; ?>

Примечание: эту же операцию с файлами blog_item.php необходимо проделать и с используемыми вами шаблонами, если в них есть этот файл. Например его содержит шаблон ja_purity (ja_purity\html\com_content\section\blog_item.php и ja_purity\html\com_content\category\blog_item.php)

Всё, теперь можете идти в админку и смотреть результат.