Новости Joomla

SW JProjects v.2.5.0 - компонент каталога цифровых проектов на Joomla

SW JProjects v.2.5.0 - компонент каталога цифровых проектов на Joomla

👩‍💻 SW JProjects v.2.5.0 - компонент каталога цифровых проектов на Joomla.Компонент - менеджер цифровых проектов для Joomla! CMS. Компонент обеспечивает создание каталога цифровых проектов и предоставляет возможность скачивания, в том числе с использованием лицензионных ключей.👩‍💻 v.2.5.0. Что нового?Схемы структур данных для серверов обновлений. Теперь с SW JProjects вы может создавать сервер обновлений не только для расширений Joomla, но и свои собственные. Например, вам нужно, чтобы структура данных сервера обновлений была другая и формат должен быть, например, не XML, а JSON. Формирование структуры данных для сервера обновлений расширений Joomla вынесено в отдельный плагин. Вы можете создать свой собственный плагин и реализовать в нём нужную вам структуру данных, добавив или наоборот исключив отображаемые данные. Сервер обновлений в компоненте по-прежнему отображает информацию о списке проектов и их версиях, о конкретном проекте и его changelog.Можно выбрать схему данных сервера обновлений глобально для всего компонента, выбрать другую схему данных для категории проектов, а так же выбрать схему в каждом проекте.

Разработчикам в качестве образца можно посмотреть плагин схемы данных для Joomla в составе компонента или же плагин-образец JSON-схемы на GitHub.
Группа плагинов swjprojects. Для нужд компонента создана группа плагинов swjprojects. В частности, в этой группе находится плагин структуры данных Joomla расширений для сервера обновлений.Изменение языковых констант. Изменены некоторые языковые константы в панели администратора. Если вы делали переопределение констант - переопределите их снова.👩‍💻 Joomla 6. Внесены изменения для корректной установки и работы компонента на Joomla 6. Компонент успешно протестирован на Joomla 6-beta2.Минимальная версия Joomla - 5. Подняты минимальные системные требования: Joomla 5.0.0 и PHP 8.1.
- Страница расширения👉 Плагин-образец кастомной JSON-схемы данных для сервера обновлений на GitHub.- GitHub расширения- Документация на GitHub- Joomla Extensions Directory#joomla #расширения

Как триггерить события для плагинов на манер Joomla 5+?В Joomla 6 должны удалить метод...

Как триггерить события для плагинов на манер Joomla 5+?В Joomla 6 должны удалить метод...

👩‍💻 Как триггерить события для плагинов на манер Joomla 5+?В Joomla 6 должны удалить метод triggerEvent(), с помощью которого раньше вызывались события для плагинов. Теперь чтобы в своём коде вызвать событие для плагина и получить от него результаты нужно:- создать объект класса события- передать в него параметры

use Joomla\CMS\Event\AbstractEvent;use Joomla\CMS\Factory;use Joomla\CMS\Plugin\PluginHelper;// Грузим плагины нужных группPluginHelper::importPlugin('system');// Создаём объект события$event = AbstractEvent::create('onAfterInitUniverse', [    'subject' => $this,    'data'    => $data, // какие-то данные    'article' => $article, // ещё материал вдовесок    'product' => $product, // и товаров подвезли]);// Триггерим событиеFactory::getApplication()->getDispatcher()->dispatch(    $event->getName(), // Тут можно строку передать 'onAfterInitUniverse'    $event);// Получаем результаты// В случае с AbstractEvent это может быть не 'result',// а что-то ещё - куда сами отдадите данные.// 2-й аргумент - значение по умолчанию, // если не получены результаты$results = $event->getArgument('result', []);
Плюсы такого подхода - вам не нужно запоминать порядок аргументов и проверять их наличие. Если вы написали свой класс события, то в плагине можно получать аргументы с помощью методов $event->getArticle(), $event->getData(), $event->getProduct() и подобными - реализуете сами под свои нужды. Если такой класс события написали, то создаёте экземпляр своего класса события и укажите его явно в аргументе eventClass
use Joomla\Component\MyComponent\Administrator\Event\MyCoolEvent;$event = MyCoolEvent::create('onAfterInitUniverse', [    'subject'    => $this,    'eventClass' => MyCoolEvent::class, // ваш класс события    'data'       => $data, // какие-то данные    'article'    => $article, // ещё материал вдовесок    'product'    => $product, // и товаров подвезли]);
Ожидаемо, что класс вашего события будет расширять AbsractEvent или другие классы событий Joomla.🙁 Есть неприятный нюанс - нельзя просто так вызывать событие и ничего не передать в аргументы. Аргумент subject обязательный. Но если вы всё-таки не хотите туда ничего передавать - передайте туда пустой stdClass или объект Joomla\registry\Registry.
@joomlafeed#joomla #php #webdev

0 Пользователей и 1 Гость просматривают эту тему.
  • 8 Ответов
  • 3836 Просмотров
*

xchesh

  • Захожу иногда
  • 277
  • 10 / 1
Если кто-то не в теме опишу конкретней.
Задача стоит в реализации региональности на сайте. При чем только на главной странице сайта. На ней выводится различный контент, в зависимости от региона, не стандартным компонентом(т.е. самописным).
Написан плагин, который запрашивает регион с сервиса ipgeobase и записывает его в кукисы.
Код
<?php
/**
 * Joomla! 2.5 component Geo
 *
 * @version $Id: Geo.php 2010-10-06 9:32:30 svn $
 * @author xchesh
 * @package Joomla
 * @subpackage geo
 * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 *
 */
// запрет прямого доступа
defined( '_JEXEC' ) or die( 'Restricted access' );

// Импортируем зависимую библиотеку
//jimport('joomla.plugin.plugin');

class plgSystemGeo extends JPlugin
{
    public function __construct(&$subject, $config)
    {
        parent::__construct( $subject, $config);
        if(!isset($_COOKIE['geobase']))
        {
            $this->get_value('utf-8');
        }
    }
        public function get_value($charset = false, $ip = false)
        {
            $key = $this->params->get('what_show');
            if(!isset($ip) OR !$this->is_valid_ip($ip))
            $this->ip = $this->get_ip();
                elseif($this->is_valid_ip($ip))          
            $this->ip = $ip;
            // кодировка
                if(isset($charset) && $charset && $charset!='windows-1251')
            $this->charset = $charset;
            $key_array = array('inetnum', 'country', 'city', 'region', 'district', 'lat', 'lng');
            if(!in_array($key, $key_array)){
                $key = false;
            }
            $data = $this->get_geobase_data();
            $alias = 'rus';
            if($data[$key]){
                $db = JFactory::getDbo();
                $query = $db->setQuery($db->getQuery(true)
                        ->select('alias')
                        ->from('#__region')
                        ->where('name='.$data[$key])
                );
                $alias = $db->loadResult();
                setcookie('geobase', $alias, time()+3600*24*7); //устанавливаем куки на неделю
            }else{
                setcookie('geobase', $alias, time()+3600*24*7); //устанавливаем куки на неделю
            }
        }
        /**
         * функция получает данные по IP.
         * @return array - возвращает массив с данными
         */
        public function get_geobase_data()
        {
            // получаем данные по ip
            $link = 'ipgeobase.ru:7020/geo?ip='.$this->ip;
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $link);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_TIMEOUT, 3);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
            $string = curl_exec($ch);    
            
            // если указана кодировка отличная от windows-1251, изменяем кодировку
            if($this->charset)      
                $string = iconv('windows-1251', $this->charset, $string);      
            $data = $this->parse_string($string);
                
            return $data;
        }
        
        /**
         * функция парсит полученные в XML данные в случае, если на сервере не установлено расширение Simplexml
         * @return array - возвращает массив с данными
         */
        
        public function parse_string($string)
        {
            $pa['inetnum'] = '/<inetnum>(.*)<\/inetnum>/';
            $pa['country'] = '/<country>(.*)<\/country>/';
            $pa['city'] = '/<city>(.*)<\/city>/';
            $pa['region'] = '/<region>(.*)<\/region>/';
            $pa['district'] = '/<district>(.*)<\/district>/';
            $pa['lat'] = '/<lat>(.*)<\/lat>/';
            $pa['lng'] = '/<lng>(.*)<\/lng>/';
            $data = array();
            foreach($pa as $key => $pattern)
            {
                preg_match($pattern, $string, $out);
                if(isset($out[1]) && $out[1])
                $data[$key] = trim($out[1]);
            }
            return $data;
        }
        
        /**
         * функция определяет IP адрес по глобальному массиву $_SERVER
         * IP адреса проверяются начиная с приоритетного, для определения возможного использования прокси
         * @return ip-адрес
         */
        public function get_ip()
        {
            $ip = false;
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
                $ipa[] = trim(strtok($_SERVER['HTTP_X_FORWARDED_FOR'], ','));
            
            if (isset($_SERVER['HTTP_CLIENT_IP']))
                $ipa[] = $_SERVER['HTTP_CLIENT_IP'];      
            
            if (isset($_SERVER['REMOTE_ADDR']))
                $ipa[] = $_SERVER['REMOTE_ADDR'];
            
            if (isset($_SERVER['HTTP_X_REAL_IP']))
                $ipa[] = $_SERVER['HTTP_X_REAL_IP'];
            
            // проверяем ip-адреса на валидность начиная с приоритетного.
            foreach($ipa as $ips)
            {
                //  если IP валидный обрываем цикл, назначаем IP адрес и возвращаем его
                if($this->is_valid_ip($ips))
                {                    
                    $ip = $ips;
                    break;
                }
            }
            return $ip;
            
        }
        
        /**
         * функция для проверки валидности IP адреса
         * @param IP адрес в формате 1.2.3.4
         * @return bolean : true - если IP валидный, иначе false
         */
        public function is_valid_ip($ip=null)
        {
            if(preg_match("#^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$#", $ip))
                return true; // если ip-адрес попадает под регулярное выражение, возвращаем true
            
            return false; // иначе возвращаем false
        }  
}

Так же написан роутер для своего компонента
Код
<?php
/**
 * @package Joomla.Site
 * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
 * @license GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.application.categories');

/**
 * Build the route for the com_content component
 *
 * @param array An array of URL arguments
 * @return array The URL arguments to use to assemble the subsequent URL.
 * @since 1.5
 */
function XbanerBuildRoute(&$query)
{
    // $query должно иметь вид index.php?option=com_xbaner&view=xbaner&catid=ид_категории, т.е никаких
    // няшек и рюшек типа ид_категории:алиас. Алиас получаем в самом роутере.
        $app = JFactory::getApplication();
$menu = $app->getMenu();
        $segments = array();
        if(isset($query['region'])){
            die('yes!');
        }
        $menuItem = $menu->getItems('link','index.php?option=com_xbaner&view=xbaner&catid='.$query['catid'], true); // получаем первый пункт меню по catid
        if(!$menuItem){//если пункта с таким catid не существует - будем делать свой.
            $menuItem = $menu->getActive();//вот это самая геморная часть. Если не получить активный пункт меню, модуль меню не будет работать.
            $categories = JCategories::getInstance('xbaner');
            $category = $categories->get($query['catid']);//получаем эту самую категорию по catid
            if (!$category) {//если её нету, то извините :)
                return $segments;
            }
            $path = $category->getPath();//получаем путь категории вида Array([0]=>ид_категории:алиас [1]=>ид_категории:алиас и т.д.). Массив, потому что получаем полный путь категории начиная от корневого пункта меню.
            $segments = array_merge((array)$segments, (array)$path);//добавляем этот путь в результирующий массив $segments
        }
        $itemid = $menuItem->id; //важный момент! получаем Id пункта меню. В любом случае он будет, либо активного, либо полученного вначале.  
        if (empty($query['Itemid'])){//устанавливаем Itemid
            $query['Itemid']=$itemid;
        }
        elseif($menuItem->query['catid']==$query['catid']){//без этого условия модуль меню не будет работать
                $query['Itemid']=$itemid;//условие проверяет сопоставление catid. В модуле меню они не равны
        }
        unset($query['catid']);
        if(isset($query['id']))//т.к. итемам не присваивают пункты меню, алиас будем для них формировать всегда
{
            if (strpos($query['id'], ':') === false) {//эту проверку можно исключить, но на всякий случай :)
                $db =&JFactory::getDBO();
                $DBload = 'SELECT alias FROM #__xbaner WHERE id='.(int)$query['id'];
                $db->setQuery($DBload);
                $alias = $db->loadResult();//этот запрос получает алиас из БД
                $query['id'] = $query['id'].':'.$alias;//устанавливаем $query['id'] равным ид_итема:алиас
            }
            $segments[] = $query['id'];
            unset($query['id']);
};
        unset($query['view']);//мне не нужен в строке вид, если хотите, можете и его передать.
        return $segments;
}
/**
 * Parse the segments of a URL.
 *
 * @param array The segments of the URL to parse.
 *
 * @return array The URL attributes to be used by the application.
 * @since 1.5
 */
function XbanerParseRoute($segments)
{
        $vars = array();
        $count = count($segments);
        list($id, $alias) = explode(':', $segments[$count-1], 2);//берем последний элемент массива и разбиваем связку ид:алиас
        $category = JCategories::getInstance('xbaner')->get($id);//подгружаем по ID категорию
        if ($category && $category->alias==$alias){//если категория существует и алиасы совпадают
            $vars['view']='xbaner';//устанавливаем нужный вид
            $vars['catid']=$id;//и ид категории
            return $vars;//на этом все! больше ничего не требуется
        }else{//если категории не существет, то это итем
            $vars['view'] = 'xbaner_one';//ставим вид нужный
            $vars['id'] = (int)$id;//и ид_итема
            return $vars;//делаем "давай дасвидания!"
        }
        return $vars;
}

который формирует отличную ссылку.

Сейчас стоит вопрос в совмещении этих двух вещей для реализации региональности. Нужно получать красивую ссылку http://мой_сайт.рф/москва и различный контент.

Создание категорий или пунктов меню сразу же отпадает. Никто не захочет 98 регионов реализовывать подобным способом.
« Последнее редактирование: 06.11.2012, 13:06:11 от xchesh »
*

xchesh

  • Захожу иногда
  • 277
  • 10 / 1
и так допишите ручками к адресу вашего сайта /москва

далее парсинг:
Код: php
function XbanerParseRoute( $segments )
{
print_r( $segments );
die();
и видим что у нас в $segments:
Array ( 0 => москва )

Дальше дело за малым
Код: php
if(count($segments ) == 1 && is_string($segments[0] ){
            $vars['view'] = 'regiion_view'
            $vars['region'] = $segments[0];
}
...

Общий принцип приблизительно такой )
Тогда в плагине поставить redirect на мой_сайт/москва
*

xchesh

  • Захожу иногда
  • 277
  • 10 / 1
мм? какой редирект?)
Ладно. Сейчас делаю выложу код.
*

xchesh

  • Захожу иногда
  • 277
  • 10 / 1
Я просто с плагином что то провтыкал.. что он вообще делает и куда редиректит и зачем?)
Плагин определяет регион. А редирект на страницу региона.
*

xchesh

  • Захожу иногда
  • 277
  • 10 / 1
Вот мне ещё интересно, как определить, главная ли это страница? JFactory::getApplication()->get()?
*

xchesh

  • Захожу иногда
  • 277
  • 10 / 1
Компонент с региональностью готов. Сразу оговорюсь - задача стоит сделать региональность только для одной(главной) страницы.
В плагине, который получает регион, ничего не менялось.
Код модели главной страницы:
Код
protected function getListQuery()
{
            $region = JRequest::getVar('region');
            if (!$region){
                JFactory::getApplication()->redirect(JRoute::_('index.php?option=com_xbaner&view=xbaner_index&region=rus'));
            }else{
//            $this->setRedirect(JRoute::_('index.php?com_xbaner&view=xbaner_index&region='.$region));
                $this->_db->setQuery($this->_db->getQuery(true)
                        ->from("#__xbaner")
                        ->select("*")
                        ->where("published=1 AND type=4 AND region LIKE '%rus%'"));
                $array = $this->_db->loadAssocList();
                if (empty($array)) {
                    return JError::raiseError(404, JText::_('ERROR! BANER NOT FOUND!'));
                }
                return $array;
            }
}
Как можете заметить, сейчас я получаю только поля содержащие "rus", это потому что на локальном хостинге(кстати загадка почему) не достются кукисы.
Здесь все просто, проверяем есть ли region, если нет, то перенаправляем на страницу региона, если да, то выполняется запрос к бд.

Дальше приведу код роутера.
Код
function XbanerBuildRoute(&$query)
{
    // $query должно иметь вид index.php?option=com_xbaner&view=xbaner&catid=ид_категории, т.е никаких
    // няшек и рюшек типа ид_категории:алиас. Алиас получаем в самом роутере.
        $app = JFactory::getApplication();
$menu = $app->getMenu();
        $segments = array();
        $menuItem = $menu->getItems('link','index.php?option=com_xbaner&view=xbaner&catid='.$query['catid'], true); // получаем первый пункт меню по catid
        if(!$menuItem){//если пункта с таким catid не существует - будем делать свой.
            $menuItem = $menu->getActive();//вот это самая геморная часть. Если не получить активный пункт меню, модуль меню не будет работать.
            $categories = JCategories::getInstance('xbaner');
            $category = $categories->get($query['catid']);//получаем эту самую категорию по catid
            if (!$category) {//если её нету, то извините :)
                return $segments;
            }
            if(isset($query['region'])){
                $segments[]=$query['region'];
                unset($query['region']);
            }else{
                $path = $category->getPath();//получаем путь категории вида Array([0]=>ид_категории:алиас [1]=>ид_категории:алиас и т.д.). Массив, потому что получаем полный путь категории начиная от корневого пункта меню.
                $segments = array_merge((array)$segments, (array)$path);//добавляем этот путь в результирующий массив $segments
            }
        }
        $itemid = $menuItem->id; //важный момент! получаем Id пункта меню. В любом случае он будет, либо активного, либо полученного вначале.  
        if (empty($query['Itemid'])){//устанавливаем Itemid
            $query['Itemid']=$itemid;
        }
        elseif($menuItem->query['catid']==$query['catid']){//без этого условия модуль меню не будет работать
                $query['Itemid']=$itemid;//условие проверяет сопоставление catid. В модуле меню они не равны
        }
        unset($query['catid']);
        if(isset($query['id']))//т.к. итемам не присваивают пункты меню, алиас будем для них формировать всегда
{
            if (strpos($query['id'], ':') === false) {//эту проверку можно исключить, но на всякий случай :)
                $db =&JFactory::getDBO();
                $DBload = 'SELECT alias FROM #__xbaner WHERE id='.(int)$query['id'];
                $db->setQuery($DBload);
                $alias = $db->loadResult();//этот запрос получает алиас из БД
                $query['id'] = $query['id'].':'.$alias;//устанавливаем $query['id'] равным ид_итема:алиас
            }
            $segments[] = $query['id'];
            unset($query['id']);
};
        unset($query['view']);//мне не нужен в строке вид, если хотите, можете и его передать.
        return $segments;
}
/**
 * Parse the segments of a URL.
 *
 * @param array The segments of the URL to parse.
 *
 * @return array The URL attributes to be used by the application.
 * @since 1.5
 */
function XbanerParseRoute($segments)
{
        $vars = array();
        $count = count($segments);
        list($id, $alias) = explode(':', $segments[$count-1], 2);//берем последний элемент массива и разбиваем связку ид:алиас
        $category = JCategories::getInstance('xbaner')->get($id);//подгружаем по ID категорию
        if((strpos($segments[$count-1], ':') === false) && $count==1){
            $vars['view']='xbaner_index';
            $vars['region']='rus';
            return $vars;
        }elseif ($category && $category->alias==$alias){//если категория существует и алиасы совпадают
            $vars['view']='xbaner';//устанавливаем нужный вид
            $vars['catid']=$id;//и ид категории
            return $vars;//на этом все! больше ничего не требуется
        }else{//если категории не существет, то это итем
            $vars['view'] = 'xbaner_one';//ставим вид нужный
            $vars['id'] = (int)$id;//и ид_итема
            return $vars;//делаем "давай дасвидания!"
        }
        return $vars;
}
Тут изменилось немногое. Добавилось условие на проверку наличия $query['region'] в build.
В parse я ничего более логичного не смог придумать, ибо $count может равняться 1, если это корневая категория. Вот и решил, что регион все равно не будет передаваться с id.
Пока что все работает. Буду проверять на ошибки, но суть не изменится, как мне кажется.
*

xchesh

  • Захожу иногда
  • 277
  • 10 / 1
Итак, в ходе долгих раздумий, рассмотрении плюсов и минусов реализации региональности, было принято решение разворачивать регионы на поддоменах.
Собственно решение обоснованное, с учетом трудозатрат, понимания, расширяемости и т.п.
Т.к. это решение пришло после реализации региональности в компоненте, то естественно хороший или не очень код отправляется в комментарии.
Приведу сразу же код роутера и модели, м.б. кому-нибудь поможет.
Сначала router.php
Код
<?php
/**
 * @package Joomla.Site
 * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
 * @license GNU General Public License version 2 or later; see LICENSE.txt
 */

defined('_JEXEC') or die;

jimport('joomla.application.categories');

/**
 * Build the route for the com_content component
 *
 * @param array An array of URL arguments
 * @return array The URL arguments to use to assemble the subsequent URL.
 * @since 1.5
 */
function XbanerBuildRoute(&$query)
{
    // $query должно иметь вид index.php?option=com_xbaner&view=xbaner&catid=ид_категории, т.е никаких
    // няшек и рюшек типа ид_категории:алиас. Алиас получаем в самом роутере.
        $app = JFactory::getApplication();
$menu = $app->getMenu();
        $segments = array();
        $menuItem = $menu->getItems('link','index.php?option=com_xbaner&view=xbaner&catid='.$query['catid'], true); // получаем первый пункт меню по catid
        if(!$menuItem){//если пункта с таким catid не существует - будем делать свой.
            $menuItem = $menu->getActive();//вот это самая геморная часть. Если не получить активный пункт меню, модуль меню не будет работать.
            $categories = JCategories::getInstance('xbaner');
            $category = $categories->get($query['catid']);//получаем эту самую категорию по catid
            if (!$category) {//если её нету, то извините :)
                return $segments;
            }
            if(isset($query['region'])){
                $db =&JFactory::getDBO();
                $DBload = 'SELECT alias FROM #__region WHERE id='.(int)$query['region'];
                $db->setQuery($DBload);
                $alias = $db->loadResult();//этот запрос получает алиас из БД
                $query['region'] = $alias;//устанавливаем $query['id'] равным ид_итема:алиас
                $segments[] = $query['region'];
                unset($query['region']);
            }else{
                $path = $category->getPath();//получаем путь категории вида Array([0]=>ид_категории:алиас [1]=>ид_категории:алиас и т.д.). Массив, потому что получаем полный путь категории начиная от корневого пункта меню.
                $segments = array_merge((array)$segments, (array)$path);//добавляем этот путь в результирующий массив $segments
            }
        }
        $itemid = $menuItem->id; //важный момент! получаем Id пункта меню. В любом случае он будет, либо активного, либо полученного вначале. 
        if (empty($query['Itemid'])){//устанавливаем Itemid
            $query['Itemid']=$itemid;
        }
        elseif($menuItem->query['catid']==$query['catid']){//без этого условия модуль меню не будет работать
                $query['Itemid']=$itemid;//условие проверяет сопоставление catid. В модуле меню они не равны
        }
        unset($query['catid']);
        if(isset($query['id']))//т.к. итемам не присваивают пункты меню, алиас будем для них формировать всегда
{
            if (strpos($query['id'], ':') === false) {//эту проверку можно исключить, но на всякий случай :)
                $db =&JFactory::getDBO();
                $DBload = 'SELECT alias FROM #__xbaner WHERE id='.(int)$query['id'];
                $db->setQuery($DBload);
                $alias = $db->loadResult();//этот запрос получает алиас из БД
                $query['id'] = $query['id'].':'.$alias;//устанавливаем $query['id'] равным ид_итема:алиас
            }
            $segments[] = $query['id'];
            unset($query['id']);
};
        unset($query['view']);//мне не нужен в строке вид, если хотите, можете и его передать.
        return $segments;
}
/**
 * Parse the segments of a URL.
 *
 * @param array The segments of the URL to parse.
 *
 * @return array The URL attributes to be used by the application.
 * @since 1.5
 */
function XbanerParseRoute($segments)
{
        $vars = array();
        $count = count($segments);
        list($id, $alias) = explode(':', $segments[$count-1], 2);//берем последний элемент массива и разбиваем связку ид:алиас
        $category = JCategories::getInstance('xbaner')->get($id);//подгружаем по ID категорию
        if((strpos($segments[$count-1], ':') === false) && $count==1){
            $vars['view']='xbaner_index';
            $vars['region']= $_COOKIE['geobase'];
            return $vars;
        }elseif ($category && $category->alias==$alias){//если категория существует и алиасы совпадают
            $vars['view']='xbaner';//устанавливаем нужный вид
            $vars['catid']=$id;//и ид категории
            return $vars;//на этом все! больше ничего не требуется
        }else{//если категории не существет, то это итем
            $db =&JFactory::getDBO();
            $DBload = 'SELECT alias FROM #__xbaner WHERE id='.(int)$id;
            $db->setQuery($DBload);
            $alias_db = $db->loadResult();//этот запрос получает алиас из БД
            if ($alias==$alias_db){
                $vars['view'] = 'xbaner_one';//ставим вид нужный
                $vars['id'] = (int)$id;//и ид_итема
                return $vars;//делаем "давай дасвидания!"
            }
        }
        return $vars;
}

Сейчас могут опять же возникнуть некоторые недоразумения, например, зачем проверять алиас? Решение это обосновано тем, что если не сделать проверку, то можно написать любой алиас с нужным id и итем все равно отобразиться верно, что не есть хорошо. Было мнение, что нужно проверять алиас в модели, но я предпочел данный метод, он гораздо проще.

А вот это модель главной страницы.
Код
<?php
// No direct access to this file
defined('_JEXEC') or die('Restricted access');
// import Joomla modelitem library
jimport('joomla.application.component.modelitem');
 
/**
 * Xbaner_index Model
 */
class XbanerModelXbaner_index extends JModelItem
{
/**
* @var object item
*/
protected $item;
        protected $maker;
        protected $stage;
 
/**
* Returns a reference to the a Table object, always creating it.
*
* @param type The table type to instantiate
* @param string A prefix for the table class name. Optional.
* @param array Configuration array for model. Optional.
* @return JTable A database object
* @since 2.5
*/
public function getTable($type = 'Xbaner', $prefix = 'XbanerTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
/**
* Get the message
* @return object The message to be displayed to the user
*/
        protected function getListQuery()
{
            $region = JRequest::getVar('region');
            $url = JURI::current();
            $baseurl = JURI::base();
            if ((!$region || $url==$baseurl) && isset($_COOKIE['region'])){
                JFactory::getApplication()->redirect(JRoute::_('index.php?option=com_xbaner&view=xbaner_index&region='.$_COOKIE['region']));
            }else{
                if (!$region){
                    $plugin = JPluginHelper::getPlugin('system', 'geo');
                    $pluginParams = new JRegistry();
                    $pluginParams->loadString($plugin->params);
                    $param = $pluginParams->get('home_item');
                    JFactory::getApplication()->redirect(JRoute::_('index.php?option=com_xbaner&view=xbaner_index&region='.$param));
                }
                $db = JFactory::getDBO();
                $query = $db->getQuery(true);
                // Select some fields
                $query->select('#__xbaner.*, #__categories.lft');
                $query->from('#__xbaner');
                $query->where("#__xbaner.published=1 AND #__xbaner.type=1 AND #__xbaner.region LIKE '%$region,%' or region LIKE '$region,%' or region LIKE '%,$region' or region=$region");
                $query->join('', '#__categories ON #__xbaner.catid = #__categories.id');
                $query->order('#__categories.lft');
                $db->setQuery($query);
                $array = $db->loadAssocList();
                if (empty($array)) {
                    return JError::raiseError(404, JText::_('ERROR! BANER NOT FOUND!'));
                }
                return $array;
            }
}
        protected function getListOld(){
$this->_db->setQuery($this->_db->getQuery(true)
                            ->from('#__maker')
                            ->select('*')
                            ->where('published=1 ORDER BY id'));
                $array = $this->_db->loadAssocList('id');
return $array;
}
public function getItem()
{
if (!isset($this->item))
{
                    $this->item = $this->getListQuery();
}
return $this->item;
}
        public function getMaker()
{
if (!isset($this->maker))
{
$this->maker = $this->getListOld();
}
return $this->maker;
}
}

Тут нас интересует getListQuery(), как видите, сделаны всяческие проверки, дабы исключить ошибки.
Думаю некоторые заметят, что подгружается плагин geo. Это системный плагин, который записывает id региона в кукисы, регион определяется сервисом ipgeobase.ru.
Получается, что для реализации региональности, в купе идут 2 компонента(компонент регионов и компонент каталога) и плагин. Региональность новостей ещё не готова. Только плагин-кнопка.
Вообще привожу код здесь только для тех, кто когда-нибудь в своем компоненте захочет реализовать нечто подобное.
*

xchesh

  • Захожу иногда
  • 277
  • 10 / 1
Возобновляю тему. Появились интересные моменты.
Если в components\com_компонент\views\tmp\default.xml не указать любой, хоть абсолютно неиспользуемый параметр, то.... роутер не работает.
Если я нахожусь не в своем компоненте, то.... роутер не работает.
Если я выведу меню не в своем компоненте, то... роутер не работает.
XbanerBuildRoute - в нем засос.
Код: php
function XbanerBuildRoute(&$query)
{
    // $query должно иметь вид index.php?option=com_xbaner&view=xbaner&catid=ид_категории, т.е никаких
    // няшек и рюшек типа ид_категории:алиас. Алиас получаем в самом роутере.
        $app = JFactory::getApplication();
$menu = $app->getMenu();
        $segments = array();
        $menuItem = $menu->getItems('link','index.php?option=com_xbaner&view=xbaner&catid='.$query['catid'], true); // получаем первый пункт меню по catid
        if(!$menuItem){//если пункта с таким catid не существует - будем делать свой.
            $menuItem = $menu->getActive();//вот это самая геморная часть. Если не получить активный пункт меню, модуль меню не будет работать.
            $categories = JCategories::getInstance('xbaner');
            $category = $categories->get($query['catid']);//получаем эту самую категорию по catid
            if (!$category) {//если её нету, то извините :)
                return $segments;
            }
//            if(isset($query['region'])){
//                $db =&JFactory::getDBO();
//                $DBload = 'SELECT alias FROM #__region WHERE id='.(int)$query['region'];
//                $db->setQuery($DBload);
//                $alias = $db->loadResult();//этот запрос получает алиас из БД
//                $query['region'] = $alias;//устанавливаем $query['id'] равным ид_итема:алиас
//                $segments[] = $query['region'];
//                unset($query['region']);
//            }else{
//                $path = $category->getPath();//получаем путь категории вида Array([0]=>ид_категории:алиас [1]=>ид_категории:алиас и т.д.). Массив, потому что получаем полный путь категории начиная от корневого пункта меню.
//                $segments = array_merge((array)$segments, (array)$path);//добавляем этот путь в результирующий массив $segments
//            }
        }
        $itemid = $menuItem->id; //важный момент! получаем Id пункта меню. В любом случае он будет, либо активного, либо полученного вначале. 
        if (empty($query['Itemid'])){//устанавливаем Itemid
            $query['Itemid']=$itemid;
        }
        else
        if($menuItem->query['catid']==$query['catid']){//без этого условия модуль меню не будет работать
                $query['Itemid']=$itemid;//условие проверяет сопоставление catid. В модуле меню они не равны
        }
        unset($query['catid']);
        if(isset($query['id']))//т.к. итемам не присваивают пункты меню, алиас будем для них формировать всегда
{
            if (strpos($query['id'], ':') === false) {//эту проверку можно исключить, но на всякий случай :)
                $db =&JFactory::getDBO();
                $DBload = 'SELECT alias FROM #__xbaner WHERE id='.(int)$query['id'];
                $db->setQuery($DBload);
                $alias = $db->loadResult();//этот запрос получает алиас из БД
                $query['id'] = $query['id'].':'.$alias;//устанавливаем $query['id'] равным ид_итема:алиас
            }
            $segments[] = $query['id'];
            unset($query['id']);
};
        unset($query['region']);
        unset($query['fromFilial']);
        unset($query['view']);//мне не нужен в строке вид, если хотите, можете и его передать.
        return $segments;
}
*

xchesh

  • Захожу иногда
  • 277
  • 10 / 1
Вот эти строки не очень хороши.
Код: php
$itemid = $menuItem->id; //важный момент! получаем Id пункта меню. В любом случае он будет, либо активного, либо полученного вначале.  
        if (empty($query['Itemid'])){//устанавливаем Itemid
            $query['Itemid']=$itemid;
        }
        else
        if($menuItem->query['catid']==$query['catid']){//без этого условия модуль меню не будет работать
                $query['Itemid']=$itemid;//условие проверяет сопоставление catid. В модуле меню они не равны
        }
Чтобы оставить сообщение,
Вам необходимо Войти или Зарегистрироваться
 

Как и чем можно обращаться с запросами из Joomla к GraphQL?

Автор bmf1982

Ответов: 0
Просмотров: 904
Последний ответ 03.10.2019, 15:46:00
от bmf1982
Jroute компонента альбомов

Автор Koot

Ответов: 2
Просмотров: 904
Последний ответ 03.08.2019, 10:21:04
от Aleks.Denezh
Joomla как система авторизации

Автор kav

Ответов: 23
Просмотров: 2731
Последний ответ 29.04.2018, 11:10:30
от Aleks.Denezh
Нужна помощь в доработке модуля под Joomla 3

Автор kik84

Ответов: 5
Просмотров: 2686
Последний ответ 30.01.2018, 22:40:30
от Елeна
Как отучить Joomla стартовать session для гостей?

Автор commeta

Ответов: 8
Просмотров: 3398
Последний ответ 20.08.2015, 14:06:38
от acyp