Женим mFilter2 и tvSuperSelect

Понадобилось однажды сделать фильтры по диапазону. То есть, например, в поселке Один участки площадью 10-15 соток, а в поселке Два — 13-20 соток. Фильтровать нужно поселки по по площади участка. В итоге я пришел к тому, чтобы в tvSuperSelectпоселку писать крайние значения (10, 15), а на фронтенде — стандартные ui-slider от mFilter2
И тут выяснилось, что mFilter не знаком с суперселектом)


Поковырялся и сделал следующее:

1. Создаем по инструкции от Василия расширяющий класс для фильтра. Я его обозвал SuperSelectFilter. В нем переопределяем функцию getTvValues. Код почти весь оставляем прежним, только там, где создается переменная $tmp (массив значений для фильтра) добавляем условие для типа tvSuperSelect.
if ($row['type'] == 'tvSuperSelect') {
					$tmp = json_decode($row['value']);
				} else {
					$tmp = strpos($row['value'], '||') !== false ? explode('||', $row['value']) : array($row['value']);
				}
В принципе, этот же костыль должен сработать с любым json-значением, например migx, но я не пробовал. Вот получившийся класс:
<?php
class SuperSelectFilter extends mse2FiltersHandler {
	
	public function getTvValues(array $tvs, array $ids) {
		$filters = array();
		$q = $this->modx->newQuery('modResource', array('modResource.id:IN' => $ids));
		$q->leftJoin('modTemplateVarTemplate', 'TemplateVarTemplate',
			'TemplateVarTemplate.tmplvarid IN (SELECT id FROM ' . $this->modx->getTableName('modTemplateVar') . ' WHERE name IN ("' . implode('","', $tvs) . '") )
			AND modResource.template = TemplateVarTemplate.templateid'
		);
		$q->leftJoin('modTemplateVar', 'TemplateVar', 'TemplateVarTemplate.tmplvarid = TemplateVar.id');
		$q->leftJoin('modTemplateVarResource', 'TemplateVarResource', 'TemplateVarResource.tmplvarid = TemplateVar.id AND TemplateVarResource.contentid = modResource.id');
		$q->select('TemplateVar.name, TemplateVarResource.contentid as id, TemplateVarResource.value, TemplateVar.type, TemplateVar.default_text');
		$tstart = microtime(true);
		if ($q->prepare() && $q->stmt->execute()) {
			$this->modx->queryTime += microtime(true) - $tstart;
			$this->modx->executedQueries++;
			while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
				if (empty($row['id'])) {
					continue;
				}
				elseif (is_null($row['value']) || trim($row['value']) == '') {
					$row['value'] = $row['default_text'];
				}
				if ($row['type'] == 'tag' || $row['type'] == 'autotag') {
					$row['value'] = str_replace(',', '||', $row['value']);
				}
				if ($row['type'] == 'tvSuperSelect') {
					$tmp = json_decode($row['value']);
				} else {
					$tmp = strpos($row['value'], '||') !== false ? explode('||', $row['value']) : array($row['value']);
				}
				foreach ($tmp as $v) {
					$v = str_replace('"', '"', trim($v));
					if ($v == '') {
						continue;
					}
					$name = strtolower($row['name']);
					if (isset($filters[$name][$v])) {
						$filters[$name][$v][$row['id']] = $row['id'];
					}
					else {
						$filters[$name][$v] = array($row['id'] => $row['id']);
					}
				}
			}
		}
		else {
			$this->modx->log(modX::LOG_LEVEL_ERROR, "[mSearch2] Error on get filter params.\nQuery: ".$q->toSQL()."\nResponse: ".print_r($q->stmt->errorInfo(),1));
		}

		return $filters;
	}

}
2. Переопределил системную настройку «mse2_filters_handler_class» — вписал туда название своего класса.
Работает без нареканий. Ура, товарищи.

P. S. Если есть какие другие идеи, как подобную фильтрацию сделать — делитесь…
mngatoff
01 июля 2016, 19:01
modx.pro
19
3 537
+7

Комментарии: 5

Андрей Сухомозгий
02 июля 2016, 12:23
+1
А есть живой пример?
    mngatoff
    08 июля 2016, 17:39
    0
    есть, angeldela.ru
    Evgeny Tarasov
    19 августа 2016, 12:03
    0
    не, ну Ваще круто работает!
      Андрей
      05 января 2017, 15:23
      0
      А сам вывод mfilter не подскажете?
        Владимир Ребров
        22 октября 2019, 12:05
        0
        Огромное спасибо!
          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
          5