Tramp1357 20 декабря 2014 1 1
Давно подумывал о замене стандартных компонентов breadcrumbs, процессоры MODX привлекают меня гораздо больше, да и когда работаешь в одном окружении (smarty), необходимость переключаться на другой синтаксис слегка нервирует.
И вот это случилось. Представляю на ваш суд процессор для вывода цепочки родителей.

Процессор breadcrumbs.class.php я кинул в папку (modxsite)site/web
<?php

class modSiteWebBreadcrumbsProcessor extends modProcessor{

	public function initialize(){
		$this->setDefaultProperties(array(
			'startId'       => 0,
			'excludeDocs'   => array(),
			'showHidden'    => true,
			'showUnpub'     => false,
			'showDeleted'   => false
		));
		return parent::initialize();
	}

	public function process() {
		$bc_path = array();
		$resource = $this->modx->resource;

		//стоим в голове, нечего выводить
		if($resource->get('id')==$this->getProperty('startId')){
			return array(
				'success'   => true,
				'message'   => '',
				'object'    => array()
			);
		}

		//соберем цепочку родителей
		$r=$resource->toArray();
		unset($r['content']);
		$bc_path[]=$r;

	    while($resource = $resource->getOne('Parent')) {
		    if (in_array($resource->id, $this->getProperty('excludeDocs'))
			    || !$this->getProperty('showHidden') && $resource->hidemenu
			    || !$this->getProperty('showUnpub') && !$resource->published
			    || !$this->getProperty('showDeleted') && $resource->deleted
		    ){
			    continue;
			}

		    $r=$resource->toArray();
		    unset($r['content']);
		    array_unshift($bc_path,$r);

		    if($resource->id==$this->getProperty('startId'))
				break;
		}
		return array(
			'success'   => true,
			'message'   => '',
			'object'    => $bc_path,
		);
	}
}
return 'modSiteWebBreadcrumbsProcessor';

для вывода использовал шаблон
{$params=['startId'=>37]} {* это голова нужной ветки *}
{processor action='site/web/breadcrumbs' ns=modxsite params=$params assign=result}

<div class="breadcrumbs">
	{$total = count($result['object'])}
	{$counter = 0}
	{foreach $result.object as $object}
		{$counter=$counter+1}
		{if $counter<$total}
			<span itemscope="itemscope" itemtype="http://data-vocabulary.org/Breadcrumb">
				<a itemprop="url" rel="{$object.pagetitle}" href="{$object.uri}">
					<span itemprop="title">{$object.pagetitle}</span></a></span>
			/
		{else}
			<span itemscope="itemscope">{$object.pagetitle}</span>
		{/if}
	{/foreach}
</div>

Буду благодарен любым советам по доработке.
1 комментарий
Fi1osof1
Fi1osof 20 декабря 2014г в 15:30 #
Саша, привет!

Прежде всего: не стоит использовать для этого getdata-процессор, правильней просто расширить modProcessor и написать свой метод process.

2. Сорри, что докапываюсь до синтаксиса, но
$modx=$this->modx;
$resource = $modx->resource;
Просто чтобы один раз вызвать $modx, создавать для нее переменную? Чем не нравится просто $this->modx?
И, хотя это объекты и все равно между ними будут ссылки, но все-таки хотя бы для наглядности не забываем про амперсанты. $modx = & $this->modx; $resource = & $modx->resource;

3. Посмотри микроразметку, которую формирует родной Breadcrumbs, там не все так просто. Есть стандарты, и лучше их придерживаться, а то СЕОшники помидорами закидают.
Tramp13571
Tramp1357 20 декабря 2014г в 15:42 #
$modx=$this->modx;
$resource = $modx->resource;
исправил, но при добавлении ссылки
$modx= & $this->modx->resource;

перестает выводиться сам ресурс (пустой контент)
Посмотри микроразметку
спасибо за информацию, сейчас посмотрю
Fi1osof1
Fi1osof 20 декабря 2014г в 16:01 #
перестает выводиться сам ресурс (пустой контент)
Кстати да :) Ведь ты ниже перетираешь в цикле переменную $resource :)
Поэтому $modx = & $this->modx — оправдано, а вот с $resource здесь не оправдано. Но где логика позволяет, лучше конечно использовать, так как нагрузку снижает, не делает копию инстанса.
Tramp13571
Tramp1357 20 декабря 2014г в 17:49 #
Подправил разметку.
Fi1osof1
Fi1osof 20 декабря 2014г в 18:13 #
ОК. Ты бы это сразу куда-нибудь на гист выложил, чтобы всегда актуальный код был и можно было ПРы слать.
Tramp13571
Tramp1357 20 декабря 2014г в 18:24 #
Fi1osof1
Fi1osof 20 декабря 2014г в 18:28 #
Круть! При случае обязательно погоняю. Но процессор все равно подумай на счет перевода на обычный modProcessor.
Tramp13571
Tramp1357 20 декабря 2014г в 19:15 #
подумай на счет перевода на обычный modProcessor
Да я так и думал сначала, но потом решил, что зачем велосипед изобретать — есть процессор, который собирает все данные ресурсов.
Кто знает — может, понадобится когда картинками из TV крошки отрисовать? :)
Fi1osof1
Fi1osof 20 декабря 2014г в 19:31 #
getdata-процессор рассчитан только на выборку документов за раз, он не рассчитан на выборку внутри него циклами. То есть его общий механизм тут не применим, а вставить список id-шников в prepareQueryBeforeCount здесь не годится, так как в какой-то момент ты получишь не тот результат просто из-за сортировки. Ты же не можешь гарантировать, что крошки все будут иметь id по порядку, или заголовки или типа того. Тебе надо просто получить их данные в цикле и набить в массив, и это делается за раз в одной функции.

И тв-шки добавить не сложно.
Tramp13571
Tramp1357 20 декабря 2014г в 19:35 #
получишь не тот результат просто из-за сортировки
ну, для этого я и переопределил afterIteration. Возможно, и кривовато, но данных немного…

А в целом я согласен, переделаю. Просто это-первое, что пришло в голову :)
Tramp13571
Tramp1357 20 декабря 2014г в 20:11 #
переделал процессор. Действительно проще получилось :)
Fi1osof1
Fi1osof 20 декабря 2014г в 20:24 #
Вот видишь :)

Я переписал немного твой код (к слову, сорри за микс табов и пробелов) gist.github.com/Fi1osof/c2087b988a679bd699c3
Глянь, наверняка мысли мои уловишь.
Tramp13571
Tramp1357 20 декабря 2014г в 20:56 #
Да, так лучше и нагляднее. Я пока такие мелочи упускаю.
Но в любом случае, думаю, польза от него будет. По крайней мере, вывод теперь полностью под контролем :)
Fi1osof1
Fi1osof 20 декабря 2014г в 21:04 #
Все так :)
Авторизуйтесь или зарегистрируйтесь (можно через соцсети ), чтобы оставлять комментарии.