Кастомная галерея by Gallery

В продолжение темы работы с xPDO. Я уже довольно долго не использую стандартные сниппеты [[galAlbum]], [[galItem]] и т.п. Блин, реально все заморочено. А кастомный вывод какой-то сделать — это вообще высший пилотаж. Но компонент Gallery использую очень активно, чисто для управления галереями в админке, а вывод галерей пишу сам. Вот сегодня сделал очередную галерейку и хочу показать листинг сниппет.

Итак, сниппет:

$output = '';

// Получаем все элементы
$q = $modx->newQuery('galItem');
$q->join('galAlbumItem', 'AlbumItems');
$q->where(array(
    'AlbumItems.album' => $album,
));
if(!$items = $modx->getCollection('galItem', $q)){
    return;
}

// Регистрируем скрипты
$assets_url = $modx->getOption('assets_url', null);
$modx->regClientCSS("{$assets_url}js/lib/colorbox/style/1/colorbox.css");
$modx->regClientStartupScript("{$assets_url}js/lib/colorbox/jquery.colorbox-min.js");
$modx->regClientStartupScript("<script type=\"text/javascript\">
$(document).ready(function(){
    //Examples of how to assign the ColorBox event to elements
        $('.gallery').colorbox({
        rel:'gallery'
        ,'current': ''
        });
});     
</script>", true);

// Проходим по каждому элементу и набиваем в шаблоны
$x = 0;
$inRow = 3;
$rowClass = "row flow";
$itemClass = "columns four";

$rowOutput = '';
foreach($items as $item){
    $x++;
    // print_r($item->toArray());   
    $item = $modx->getChunk('SiteGalleryItemTpl', array(
        'class'     => $itemClass,
        'title'     => $item->get('name'),
        'src'       => $item->get('absoluteImage'),
    ));
    
    $rowOutput  .= $item;
    
    if($x == $inRow){
        $output .= $modx->getChunk('SiteGalleryRowTpl', array(
            'class'     => $rowClass,
            'wrapper'   => $rowOutput,
        ));
        $x = 0;
        $rowOutput = '';
    }
}

return $output;

Чанк SiteGalleryRowTpl

<div class="[[+class]]">[[+wrapper]]</div>

Чанк SiteGalleryItemTpl

<div class="galItem [[+class]]">
    <div class="title"><span>[[+title]]</span></div>
    <a href="[[+src]]" class="gallery" title="[[+title]]">
        <img src="/assets/components/site_gallery/connector.php?action=web/image/gallery/small&src=[[+src]]"/>
    </a>
</div>

Как видно, для кастомной галереи не нужно писать много кода.

Comments

Все понятно. Блин, хотелось бы все же с процессорами разобраться. По-моему, mgr/item/getlist в gallery меньше кода гоняет

вот что получилось:

require_once(MODX_CORE_PATH.'components/gallery/processors/mgr/item/getlist.class.php');

class modSiteGalleryProcessor extends GalleryItemGetListProcessor{

public function outputArray(array $array, $count = false){
        return array(
            'success' => true,
            'message' => $this->getMessage(),
            'count'   => count($array),
            'total'   => $count,
            'object'  => $array,
        );
}
}
return 'modSiteGalleryProcessor';

вызываю из консоли

$response = $modx->runProcessor('gallery/getlist', 
array(
    'album' => 1,
), 
array(
    'processors_path' => $modx->getOption('core_path') . 'site/processors/'
));
print_r($response->response);

ничего не выдает, только Loading крутится. Что-то я еще не сделал?

  1. В начале кода в консоли пропиши ini_set('display_errors', 1); Чтобы php тебе выводил ошибки.
  2. Поставь FireBug или типа того, чтобы видеть Ajax-овые запросы и т.п.
  3. Ошибка у тебя 99,999% из-за $this->getMessage(). Это моя функция в моем процессоре, и в процессорах MODX-а ее нет. Поэтому у тебя скрипт и разваливается с критической ошибкой.

И еще:

'processors_path' => $modx->getOption('core_path'). 'site/processors/'

А что это ты из core_path процессор пытаешься дернуть? У тебя по идее как минимум в core_path. components должно лежать. Пути в общем проверь.

А все-таки, что экономичнее на твой взгляд — getCollection или все-таки процессор? Я так понял, процессор превьюшки генерит (у него возвращаются их адреса)? Они-то как раз и не нужны.

Крайне неудачное решение. Используй MODX_CORE_PATH .'components/site/processors/' и все. А экономия с путями тебе сразу несколько минусов дает:

  1. Компонент — это не только процессоры. Это еще контроллеры для админки, модели и т.п.
  2. Папка core не попадает в снимки сайта, так что Vapor-ом уже не сможешь перенести свой сайт. И еще куча минусов, включая «элементарно забыть про что-то там в core».

что экономичнее на твой взгляд — getCollection или все-таки процессор?

Ты путаешь довольно разные вещи. getCollection — это конкретный метод xPDO для получения массива объектов. При этом это не только запросы к базе данных, но и набивка результатов в конечные объекты. Чтобы это лучше понимать, прочитай эти статьи: modxclub.ru/blog/200.html modxclub.ru/blog/166.html

А процессор — это процессор. И в нем логика может быть какая угодно. Так вот, классический modObjectGetlistprocessor использует в том числе и метод xPDO::getCollection(). Просто помимо этого он имеет ряд методов для проверки прав, формирования запроса, подсчета общего числа элементов, обработки вывода и т.п. Конечно же он по определению тяжелее, чем просто getCollection(). Но если брать те же getlist-процессоры из shopModx-а, то там не используется метод getCollection, а используется чистое PDO/xPDO. Те процессоры в итоге легче гораздо.

Но в случае с Gallery работать с объектами конечно же лучше как минимум по двум причинам:

  1. получаемые galItem-объекты имеют все необходимые методы для работы с этими картинками, а так же формирования путей, самбов и т.п.
  2. как правило элементов не много, так что нагрузкой можно пренебречь.

Ну, примерно так:

<?php
/**
 * Smarty plugin
 *
 * @package Smarty
 * @subpackage PluginsFunction
 */


function smarty_function_galAlbum($params, & $smarty)
{
    if(!isset($params['album']) OR !$album = $params['album']){return;}

	$output = '';
    if(!$rowTpl = $params['rowTpl']){
		$output = array();
	}

    if(!empty($params['assign'])){
        $assign = (string)$params['assign'];
    }
    
    $modx = & $smarty->modx;

	// Получаем все элементы
	$q = $modx->newQuery('galItem');
	$q->join('galAlbumItem', 'AlbumItems');
	$q->where(array(
	    'AlbumItems.album' => $album,
	));

	if($items=$modx->getCollection('galItem', $q)){
		foreach($items as $item){
		    $item = array(
		        'name'			=>$item->get('name'),
                'description'	=>$item->get('description'),
//                'filename'	=>$item->get('filename'),
//                'mediatype'	=>$item->get('mediatype'),
//                'url'			=>$item->get('url'),
		        'relativeImage'	=> $item->get('relativeImage'),
//                'thumbnail'	=>$item->get('thumbnail'),
//                'image'	=>$item->get('image'),
//                'absoluteImage'	=>$item->get('absoluteImage'),
//                'filesize'	=>$item->get('filesize'),
//                'image_path'	=>$item->get('image_path'),
		    );
			if($rowTpl){
	            $smarty->assign('item',$item);
				$output.=$smarty->fetch($rowTpl);
			}
			else{
				$output[]=$item;
			}
		}
	}
    return !empty($assign) ? $smarty->assign($assign, $output) : $output;
}

Да, подобные решения очень нужны. Планирую выпустить серьезно обновленную сборку, в котором будет больше готовых модулей на процессорах+Smarty, включая менюшку на процессорах и т.п. Но вот оформлению в виде Smarty-плагинов предпочитаю именно процессоры. Есть ряд причин:

  1. Smarty-плагины — это не формат MODX-а, и они не особо укладываются в модель пакетов для него. А даже если их включать в пакеты, то для подключения их надо указывать Smarty дополнительную директорию расширений (через плагин). Все это очень не удобно.
  2. Smarty-плагины подходят только для самого Smarty. Отдельно их не вызовешь. А вот MODX-процессоры можно вызвать где угодно — хоть в Smarty, хоть в плагиных, хоть в сниппетах, хоть в других плагинах. К тому же процессоры можно использовать и в других системах шаблонизации (ведь все еще витают идеи прикрутить Twig и т.п.).
  3. Smarty-плагины — это просто функции, а значит их расширить или переопределить нельзя. С процессорами все гораздо интересней, потому что это классы.

В общем, я стараюсь Smarty не обвешивать особенно.

согласен. В принципе, я вчера и процессор испытал — все удобно. И полностью согласен с тобой в плане процессоров. Просто я пока во всем этом новичок, все интересно, да и опыта набираюсь потихоньку.

Не, поиграться и попробовать различные способы — это и полезно, и интересно. Всяко поддерживаю.

Здравствуйте, использую ваш код, ссылка /assets/components/gallery/connector.php?action=web/image/gallery/small&src=/assets/gallery/1/2.jpg выдает сообщение {"success":false,"message":"Доступ закрыт.","total":0,"data":[],"object":{"code":401}}. Как это можно исправить?