[tvSuperSelect] 1.2.2 Кастомайз по полной программе!


Новый функционал позволяет навесить свой процессор на получение значений для любого ТВ с типом tvSuperSelect. Теперь мы можем вывести абсолютно любые значения в этом ТВ, которые передадим через наш процессор. Предлагаю рассмотреть подробнее, как это делается и что это нам даст.

Что это даёт


  • Можно выдавать любые значения на выбор. Например, список ресурсов или опции miniShop2.
  • Можно ограничить пользователя только значениями из нашего списка, не давая добавить ничего нового.

Кейс


Допустим, нам нужно вывести список ресурсов в ТВ поле, чтобы менеджер мог выбрать несколько из них. Выглядеть это дело у нас будет вот так:


Шаг 1
Создаём ТВ поле с типом tvSuperSelect и указываем такие настройки:
  • Connector URL
    /assets/custom/tvssconnector.php
  • Процессор
    tvss/getresources
Шаг 2
Создаём файл-коннектор, в котором будет происходить запуск процессора и получение наших значений.
<?php
require_once dirname(dirname(dirname(__FILE__))) . '/config.core.php';
require_once MODX_CORE_PATH . 'config/' . MODX_CONFIG_KEY . '.inc.php';
require_once MODX_CONNECTORS_PATH . 'index.php';
$modx->request->handleRequest(array(
    'processors_path' => MODX_CORE_PATH . 'custom/processors/',
    'location' => '',
));
Местонахождение: /assets/custom/tvssconnector.php

Шаг 3
Создаём процессор, в котором будет происходить вся магия выборка ресурсов и формирование массива для отображения в списке ComboBox.
<?php
class customTvssComboGetResourcesProcessor extends modObjectGetListProcessor
{
    public $classKey = 'modResource';
    public $languageTopics = array('resource');
    public $defaultSortField = 'menuindex';
    public $defaultSortDirection = 'ASC';

    /**
     * @param xPDOQuery $c
     *
     * @return xPDOQuery
     */
    public function prepareQueryBeforeCount(xPDOQuery $c)
    {
        if ($context_key = $this->getProperty('context_key')) {
            $c->where(array('context_key' => $context_key));
        }
        if ($resource_id = (int)$this->getProperty('resource_id', 0)) {
            $c->where(array('id:!=' => $resource_id));
        }
        if ($query = trim($this->getProperty('query'))) {
            $c->where(array(
                'id:LIKE' => "{$query}%",
                'OR:pagetitle:LIKE' => "%{$query}%",
                'OR:longtitle:LIKE' => "%{$query}%",
            ));
        }

        return $c;
    }

    /**
     * @param xPDOObject $obj
     *
     * @return array
     */
    public function prepareRow(xPDOObject $obj)
    {
        $array = $obj->toArray();
        $array['parents'] = array();
        $parents = $this->modx->getParentIds($array['id'], 4, array('context' => $array['context_key']));
        if ($parents[count($parents) - 1] == 0) {
            unset($parents[count($parents) - 1]);
        }
        if (!empty($parents) && is_array($parents)) {
            $q = $this->modx->newQuery($this->classKey, array('id:IN' => $parents));
            $q->select('id,pagetitle');
            if ($q->prepare() && $q->stmt->execute()) {
                while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
                    $key = array_search($row['id'], $parents);
                    if ($key !== false) {
                        $parents[$key] = $row['pagetitle'];
                    }
                }
            }
            $array['parents'] = array_reverse($parents);
        }
        unset($parents, $q, $row, $key);
        
        $data = array(
            'display' => "<div><small>({$array['id']})</small> <b>{$array['pagetitle']}</b></div>",
            'value' => $array['id'],
        );
        if (!empty($array['parents'])) {
            $data['display'] = '<div class="parents"><small>' . join(' / ', $array['parents']) . '</small></div>' . $data['display'];
        }

        return $data;
    }
}

return 'customTvssComboGetResourcesProcessor';
Местонахождение: /core/custom/processors/tvss/getresources.class.php

Итого
Вот и всё! На фронте у нас будет список ресурсов в виде JSON массива, который мы сможем декодировать и делать с ними всё, что угодно!
{var $resources = ($_modx->resource['our_tv'] | fromJSON)}
{foreach $resources as $v}
    {$v | resource : 'pagetitle'}
{/foreach}
Павел Гвоздь
13 сентября 2018, 10:54
16
271
+23

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

Aleksandr Huz
13 сентября 2018, 13:00
+1
Очень круто.
Отдельное спасибо за примеры.
Сергей Лелеко
13 сентября 2018, 15:33
+1
Очень крутое обновление! Спасибо большое!
Хоть я только недавно познакомился с этим компонентом, но очень нравится. А тут еще и обновление такое! Еще раз спасибо Павел!
Pavel Zarubin
15 сентября 2018, 14:49
+1
А чем это отличается от @EVAL $modx->runSnippet в обычном множественном выборе тв? Я не ерничаю, просто интересно
    Павел Гвоздь
    15 сентября 2018, 15:38
    0
    Не знаю, я его не использовал. Вообще не знал о существовании оного. :)
    У меня tvSuperSelect много где используется, поэтому реализовал этот функционал для него.
    Aleksandr Huz
    15 сентября 2018, 15:42
    0
    я вижу только одно отличие, что можно еще добавлять свои произвольные значения на ходу.

    но, если
    Можно ограничить пользователя только значениями из нашего списка, не давая добавить ничего нового
    то тогда нет отличий.
      Pavel Zarubin
      15 сентября 2018, 18:06
      +1
      Понятно, спасибо!
      Илья Уткин
      16 сентября 2018, 11:31
      +2
      Блин, как так нет отличий — даже обидно за автора такого полезного дополнения.

      Основное преимущество tvSuperSelect в том, что теги хранятся в отдельной таблице — при выборке не нужно использовать LIKE и городить всякие велосипеды.

    Алексей Бгатов
    15 сентября 2018, 18:16
    +1
    отличие в способе хранения данных, и это важное отличие на мой взгляд. в обычном тв строка с разделителями, а тут json-массив
    Алексей Бгатов
    15 сентября 2018, 18:18
    0
    ну и плюс @EVAL это 1. костыль и 2. небезопасно. а тут всё по феншую, через коннектор
    Aleksandr Huz
    16 сентября 2018, 11:20
    +1
    Кстати, в MODX3 @EVAL будет удален, поэтому tvSuperSelect будет более востребован.