При создании сайта встала задача фильтровать статьи по нескольким тегам.
Покопавшись в интерне склонялся к мысли что придется это делать через TagManager2. что вызывало определенные неудобства при добавлении тегов:
- Сделать теги фиксированными через checkbox или select с множественным выбором (не подходило, т.к. неизвестно заранее, какие теги нужны)
- Сделать теги — ресурсы и так же для checkbox выбирать их запросом select (неудобно, т.к. сначала нужно добавить ресурс с тегом, а потом привязать его к статье)
Т.к изначально вывод тегов был организован через tagLister, при пришло решение доработать его и использовать совместно с pdoResources.
Выборка статей через tagLister
<ul class="list-inline list-tags">
[[!tagLister? &target=`6` &tv=`tags` &tpl=`articles.tagLister.tmpl` &cls=`` &activeCls=`active` ]]
</ul>Шаблон articles.tagLister.tmpl
<li class="[[+cls]]"><a href="[[+url]]">[[+tag]]</a></li>Доработка tagLister
Доработка выделения нескольких активных тегов
После получения параметров сниппета добавляем
if ($activeTag!='') {
$activeTag_arr=explode(',', $activeTag);
} else {
$activeTag_arr=array();
}Строку:
if (!empty($activeCls) && $tag==$activeTag && (empty($activeKey) || $tv==$activeKey)) $tagCls .= ' '.$activeCls;Заменяем на:
if (!empty($activeCls) && in_array($tag, $activeTag_arr) && (empty($activeKey) || $tv==$activeKey)) $tagCls .= ' '.$activeCls;Доработка формирования ссылки тега.
Анализируем строку GET запроса. Если тег присутствует в запросе — убираем его из ссылки, если нет, то добавляем, сохраняя другие
Строку:
/* handle weighting for css */
if (!empty($weights) && !empty($weightCls)) $tagCls .= ' '.$weightCls.ceil($count / (max($tagList) / $weights));Заменяем на:
/* handle weighting for css */
if (!empty($weights) && !empty($weightCls)) $tagCls .= ' '.$weightCls.ceil($count / (max($tagList) / $weights));
$tag_arr = $activeTag_arr;
if(($id = array_search($tag, $tag_arr)) !== false) {
unset($tag_arr[$id]);
} else {
array_unshift($tag_arr, $tag);
}Строку:
$tagParams[$tagVar] = $tag;Заменяем на:
$tagParams[$tagVar] = implode(",", $tag_arr);Выборка статей pdoResource c разбивкой на страницы
[[!pdoPage:empty=`<p>Статей, удовлетворяющих условиям не найдено</p>`?
&parents=`[[*id]]`
&tpl=`@INLINE <p><a href="/[[+uri]]">[[+pagetitle]]</a></p>`
&limit=`4`
&sortby=`publishedon`
&sortdir=`ASC`
&includeTVs=`image,tags`
&tvFilters=`[[!getTags]]`
]]Сниппет getTags формирования строки для фильтра по TV параметрам
Создаем новый сниппет getTags
Вставляем в него код. который разбивает GET строку на теги и формирует строку для фильтра по TV параметрам
<?php
$filterVar = $modx->getOption('filterVar',$scriptProperties,'tags');
$getVar = $modx->getOption('getVar',$scriptProperties,'tag');
$getValue = isset($_REQUEST[$getVar]) ? $modx->stripTags(urldecode($_REQUEST[$getVar])) : '';
if ($getValue=='') return '';
$tags=explode(',', $getValue);
foreach ($tags as $key => $val) {
$tags[$key]=$filterVar.'==%'.$val.'%';
}
return implode(',', $tags);Результат можно можно посмотреть на сайте
Комментарии приветствуются, Может кто зарелизит это в основной tagLister
Полный код модифицированного tagLister
<?php
/**
* tagLister
*
* Copyright 2010 by Shaun McCormick <shaun@modxcms.com>
*
* This file is part of tagLister, a simple tag listing snippet for MODx
* Revolution.
*
* tagLister is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option) any later
* version.
*
* tagLister is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* tagLister; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*
* @package taglister
*/
/**
* tagLister snippet
*
* @var modX $modx
* @var TagLister $tagLister
* @var array $scriptProperties
*
* @package taglister
*/
$tagLister = $modx->getService('taglister','TagLister',$modx->getOption('taglister.core_path',null,$modx->getOption('core_path').'components/taglister/').'model/taglister/',$scriptProperties);
if (!($tagLister instanceof TagLister)) return '';
$modx->lexicon->load('taglister:default');
/* setup default properties */
$tpl = $modx->getOption('tpl',$scriptProperties,'tag');
$tv = $modx->getOption('tv',$scriptProperties,'tags');
$tvDelimiter = $modx->getOption('tvDelimiter',$scriptProperties,',');
$target = $modx->getOption('target',$scriptProperties,1);
$tagVar = $modx->getOption('tagVar',$scriptProperties,'tag');
$tagKeyVar = $modx->getOption('tagKeyVar',$scriptProperties,'key');
$limit = $modx->getOption('limit',$scriptProperties,10);
$sortBy = strtolower($modx->getOption('sortBy',$scriptProperties,'count'));
$sortDir = strtoupper($modx->getOption('sortDir',$scriptProperties,'ASC'));
$cls = $modx->getOption('cls',$scriptProperties,'');
$altCls = $modx->getOption('altCls',$scriptProperties,'');
$firstCls = $modx->getOption('firstCls',$scriptProperties,'');
$lastCls = $modx->getOption('lastCls',$scriptProperties,'');
$activeCls = $modx->getOption('activeCls',$scriptProperties,'');
$activeTag = isset($_REQUEST[$tagVar]) ? $modx->stripTags(urldecode($_REQUEST[$tagVar])) : '';
$activeKey = isset($_REQUEST[$tagKeyVar]) ? $modx->stripTags(urldecode($_REQUEST[$tagKeyVar])) : '';
$all = $modx->getOption('all',$scriptProperties,false);
$toLower = $modx->getOption('toLower',$scriptProperties,false);
$weights = $modx->getOption('weights',$scriptProperties,0);
$weightCls = $modx->getOption('weightCls',$scriptProperties,'');
$useTagFurl = $modx->getOption('useTagFurl',$scriptProperties,false);
$furlKey = $modx->getOption('furlKey',$scriptProperties,'tags');
// add =================
if ($activeTag!='') {
$activeTag_arr=explode(',', $activeTag);
} else {
$activeTag_arr=array();
}
/* get TV values */
$c = $modx->newQuery('modTemplateVarResource');
$c->innerJoin('modTemplateVar','TemplateVar');
$c->innerJoin('modResource','Resource');
$c->leftJoin('modUser','CreatedBy','CreatedBy.id = Resource.createdby');
$c->leftJoin('modUser','PublishedBy','PublishedBy.id = Resource.publishedby');
$c->leftJoin('modUser','EditedBy','EditedBy.id = Resource.editedby');
$tvPk = (int)$tv;
if (!empty($tvPk)) {
$c->where(array('TemplateVar.id' => $tvPk));
} else {
$c->where(array('TemplateVar.name' => $tv));
}
/* parents support */
$parents = isset($parents) ? explode(',', $parents) : array();
if (!empty($parents)) {
$depth = isset($depth) ? (integer) $depth : 10;
$children = array();
foreach ($parents as $parent) {
$kids = $modx->getChildIds($parent,$depth);
if (!empty($kids)) {
$children = array_merge($children,$kids);
}
}
if (!empty($children)) {
$children = array_unique($children);
$parents = array_merge($parents,$children);
}
$parents = array_unique($parents);
if (!empty($parents)) {
$c->where(array(
'Resource.id:IN' => $parents,
));
}
}
if (!$modx->getOption('includeDeleted',$scriptProperties,false)) {
$c->where(array('Resource.deleted' => 0));
}
if (!$modx->getOption('includeUnpublished',$scriptProperties,false)) {
$c->where(array('Resource.published' => 1));
}
/* json where support */
$where = $modx->getOption('where',$scriptProperties,'');
if (!empty($where)) {
$where = $modx->fromJSON($where);
if (is_array($where) && !empty($where)) {
$c->where($where);
}
}
if ($sortBy == 'publishedon') {
$c->sortby('Resource.publishedon',$sortDir);
} else if (in_array($sortBy,array('rand','random','rand()'))) {
$c->sortby('RAND()','');
}
$tags = $modx->getCollection('modTemplateVarResource',$c);
/* parse TV values */
$output = array();
$tagList = array();
$encoding = $modx->getOption('modx_charset',$scriptProperties,'UTF-8');
$useMultibyte = $modx->getOption('use_multibyte',$scriptProperties,false);
/** @var modTemplateVarResource $tag */
foreach ($tags as $tag) {
$v = $tag->get('value');
$vs = explode($tvDelimiter,$v);
foreach ($vs as $key) {
$key = trim($key);
if (empty($key)) continue;
if ($toLower) { /* allow for case-insensitive filtering */
$key = $useMultibyte ? mb_strtolower($key,$encoding) : strtolower($key);
}
/* increment tag count */
if (empty($tagList[$key])) {
$tagList[$key] = 1;
} else { $tagList[$key]++; }
}
}
/* sort */
switch ($sortBy.'-'.$sortDir) {
case 'publishedon-DESC': case 'publishedon-ASC': break;
case 'tag-ASC': ksort($tagList); break;
case 'tag-DESC': krsort($tagList); break;
case 'count-DESC': asort($tagList); break;
case 'count-ASC': default: arsort($tagList); break;
case 'rand-ASC': case 'random-ASC': case 'rand()-asc': $tagList = $tagLister->ashuffle($tagList); break;
}
/* iterate */
$totalTags = 0;
$i = $all ? 1 : 0;
foreach ($tagList as $tag => $count) {
if ($i >= $limit) break;
$tagCls = $cls.((!empty($altCls) && $i % 2)? ' '.$altCls : '');
if (!empty($firstCls) && $i == 0) $tagCls .= ' '.$firstCls;
if (!empty($lastCls) && ($i+1 >= $limit || $i == $count)) $tagCls .= ' '.$lastCls;
/* if tag is currently being viewed, mark as active */
//if (!empty($activeCls) && $tag==$activeTag && (empty($activeKey) || $tv==$activeKey)) $tagCls .= ' '.$activeCls;
if (!empty($activeCls) && in_array($tag, $activeTag_arr) && (empty($activeKey) || $tv==$activeKey)) $tagCls .= ' '.$activeCls;
/* handle weighting for css */
if (!empty($weights) && !empty($weightCls)) $tagCls .= ' '.$weightCls.ceil($count / (max($tagList) / $weights));
$tag_arr = $activeTag_arr;
if(($id = array_search($tag, $tag_arr)) !== false) {
unset($tag_arr[$id]);
} else {
array_unshift($tag_arr, $tag);
}
$tagArray = array(
'tag' => $tag,
'tagVar' => $tagVar,
'tagKey' => $tv,
'tagKeyVar' => $tagKeyVar,
'count' => $count,
'target' => $target,
'cls' => $tagCls,
'idx' => $i,
);
$tagParams = array();
if (empty($useTagFurl)) {
// $tagParams[$tagVar] = $tag;
$tagParams[$tagVar] = implode(",", $tag_arr);;
$tagParams[$tagKeyVar] = $tv;
}
$tagArray['url'] = $modx->makeUrl($target,'',$tagParams);
if (!empty($useTagFurl)) {
$tagArray['url'] = rtrim($tagArray['url'],'/').'/'.(!empty($furlKey) ? $furlKey : $tv).'/'.urlencode($tag);
}
$output[] = $tagLister->getChunk($tpl,$tagArray);
$totalTags += $count;
$i++;
}
if ($all) {
$allTpl = $modx->getOption('allTpl',$scriptProperties,'all');
$allChunk = $tagLister->getChunk($allTpl,array(
'tag' => !empty($scriptProperties['allText']) ? $scriptProperties['allText'] : $modx->lexicon('all_tags'),
'tagVar' => $tagVar,
'tagKey' => $tv,
'tagKeyVar' => $tagKeyVar,
'count' => $totalTags,
'target' => $target,
'cls' => $cls,
'url' => $useTagFurl ? $modx->makeUrl($target).$tv.'/' : $modx->makeUrl($target,'',array(
$tagVar => '',
$tagKeyVar => $tv,
)),
));
if ($modx->getOption('allPosition',$scriptProperties,'B') == 'T') {
array_unshift($output,$allChunk);
} else {
array_push($output,$allChunk);
}
}
/* output */
$outputSeparator = $modx->getOption('outputSeparator',$scriptProperties,"\n");
$output = implode($outputSeparator,$output);
$toPlaceholder = $modx->getOption('toPlaceholder',$scriptProperties,false);
if (!empty($toPlaceholder)) {
$modx->setPlaceholder($toPlaceholder,$output);
return '';
}
return $output;
Комментарии (0)