Fi1osof 02 июля 2013 4 15
Данный топик — ответ вот этому: community.modx-cms.ru/blog/9281.html

Я не буду особо лезть в детали, с какими мы здесь трудностями сталкивается, а хочу только сказать, что даже со средними знаниями php можно обходить многие эти сложности. При этом ваши скрипты будут выполняться гораздо быстрее, и будут они более гибкими в использовании.

Справедливости ради приведу работающий вызов этого сниппета на уровне MODX-синтаксиса.
$output= '[[getImageList?
  &tvname=`afisha`
  &tpl=`Tpl`
  &docid=`338`
  &limit=`3`
  &sort=`[{"sortby":"data","sortdir":"ASC"}]`
  &where=`{"data:>":"[[!today]]"}`
]]';

Заметка автору: [[!today]] в вашем случае должен возвращать полную дату, например 2012-12-18 22:00:00, а не time(). И вам внимательно надо продумать правильное кеширование всего этого.

Самые главные минусу нативного решения:
1) В условие where можно прописать только одно поле.
2) Хоть мы и указываем limit, выборка происходит все равно всех элементов, а потом уже на уровне перебора массива срабатывает limit. Хотя здесь как правило небольшое количество элементов, но этот минус справедлив для многих подобных решений.

А теперь мой скрипт на замену:
<?php
if(!$doc_id) {return '';}
$output = '';

// Получаем TV по ID документа
$q = $modx->newQuery('modTemplateVar');
$q->innerJoin('modTemplateVarResource', 'v', 'v.tmplvarid = modTemplateVar.id');
$q->where(array(
    'v.contentid'  => $doc_id, 
    'modTemplateVar.id'  => $tv_id, 
));
$q->limit(1);
$q->select(array('modTemplateVar.*', 'v.value'));
if(!$tv = $modx->getObject('modTemplateVar', $q)){
   return '';
}

// Получаем его значение
$value =  $tv->get('value');

// Получаем массив из JSON-строки
$array = $modx->fromJSON($value);

// Пробегаемся по всему массиву и фильтруем по дате
$data = array();
$now = time();
$i = 0;
foreach($array as $r){
        $time = strtotime($r['data']);
    if($time < $now){continue;}
        $data[$time] = $r;
    if(++$i == $limit){break;} 
}

// Сортируем массив по ключу (чтобы по дате отсортировать)
ksort($data);

foreach($data as $r){
    $output .= $modx->getChunk($tpl, $r); 
}

return $output;
Да, он чуть сложнее, чем работа на уровне синтаксиса, но если вы освоите API MODX, то вы сможете работать с любыми объектами. Честно скажу, что у меня написание этого сниппета заняло меньше времени, чем изучение сниппета getImageList и выяснение, почему же &where=`[{«data:>»:"[[!today]]"}]` не работает, а &where=`{«data:>»:"[[!today]]"}` работает (пришлось лезть в код модуля и выяснять, что он не умеет принимать массив условий, а только одно условие ключ->значение).

При этом решение на уровне таких сниппетов и более гибкое, и работает быстрее, и кеширование гибкое прописать можно. В общем здесь куча плюсов.
15 комментариев
r
rozhkov 16 января 2014г в 14:58 #
При вызове getImageList в шаблоне вывода процессора web/getdata, путь к изображению выводится одинаковый.
Кто-нибудь сталкивался с таким поведением снипета?
Fi1osof1
Fi1osof 16 января 2014г в 15:38 #
Мы сам getImageList не вызываем. Выкладывайте листинг вашего кода, глянем что там у вас.
r
rozhkov 17 января 2014г в 06:31 #
Для каждого ресурса в шаблоне следующий вызов getImageList.
Путь в источнике файлов задан [[migxResourceMediaPath? &pathTpl=`assets/images/{id}/`]]

{assign var=getImageListParam value=[
    'tvname'    =>  Images,
    'tpl'       =>  '@CODE: <img src="[[+image]]" class="img-thumbnail img-item"/>',
    'limit'     =>  1,
    'randomize' =>  true,
    'docid'     =>  {$object_sale.id}
]}
        
{snippet name='getImageList' assign=image params=$getImageListParam parse=true}

{$image}
Fi1osof1
Fi1osof 17 января 2014г в 14:30 #
1. Вот такой код у меня в консоли выполняется:
<?php
$modx->switchContext('web');
$modx->resource = $modx->getObject('modResource', 4);
 

$s = $modx->runSnippet('getImageList', array(
    'tvname'    =>  'gallery',
    'tpl'       =>  '@CODE: <img src="[[+image]]" class="img-thumbnail img-item"/>',
    'limit'     =>  1,
    'randomize' =>  true,
    'docid'     =>  4

));

print $s;

То есть выводится рандомная картинка. 4 — это id документа с мигх-картинками. Собственно это ваш код, поэтому все должно работать.

2. Я, как обычно, формирую пути в процессоре. А потом просто использую массив картинок $object.gallery

путь к изображению выводится одинаковый.
То есть картинка выводится, но не работает рандом или что?
r
rozhkov 20 января 2014г в 07:16 #
То есть картинка выводится, но не работает рандом или что?
Картинка выводится та, но путь к ней не тот. Выводит так:

<img src="/assets/images/14/Oryx Antelope.jpg"/>
<img src="/assets/images/14/52bef16f8b102.jpg"/>
<img src="/assets/images/14/Humpback Whale.jpg"/>

А должен так:

<img src="/assets/images/14/Oryx Antelope.jpg"/>
<img src="/assets/images/15/52bef16f8b102.jpg"/>
<img src="/assets/images/16/Humpback Whale.jpg"/>


Ваш код, у меня в консоли, выдает ошибку:
Call to a member function getSource() on a non-object in Z:\domains\phoenix\core\cache\includes\elements\modsnippet\3.include.cache.php

Я уже весь мозг себе сломал ((
r
rozhkov 20 января 2014г в 09:02 #
Выяснил вот какую особенность. Поставил modx. Установил только Console, MIGX.
Создал TV параметр MIGX.
Следующий код выполнился успешно:
<?php
$modx->switchContext('web');
$modx->resource = $modx->getObject('modResource', 1);
 

$s = $modx->runSnippet('getImageList', array(
    'tvname'    =>  'gallery',
    'tpl'       =>  '@CODE: <img src="[[+image]]" class="img-thumbnail img-item"/>',
    'limit'     =>  1,
    'randomize' =>  true,
    'docid'     =>  1

));

print $s;


Затем поставил modxSite, modxSmarty. И вышеприведенный код перестал работать.
Удаление установленных пакетов не повлияло на работоспособность кода. Он просто перестал работать и все.
Fi1osof1
Fi1osof 20 января 2014г в 09:21 #
Ваш код, у меня в консоли, выдает ошибку:
Call to a member function getSource() on a non-object in Z:\domains\phoenix\core\cache\includes\elements\modsnippet\3.include.cache.php
Здесь два варианта:
1. Вы не меняли id документа, и документа с id 4 просто нет. $modx->resource = $modx->getObject('modResource', 4);
2. Нет указанного медиасурса.

Затем поставил modxSite, modxSmarty. И вышеприведенный код перестал работать.
Удаление установленных пакетов не повлияло на работоспособность кода. Он просто перестал работать и все.
Великие сомнения на счет того, что эти пакеты при установке на что-то могли повлиять. Они просто не цепляют ядра. Тем не менее пришлите в личку доступ к админке, где установлены эти пакеты и этот код не работает. Я посмотрю.
r
rozhkov 20 января 2014г в 15:12 #
Прошу прощения. Действительно имя TV параметра указал неверный.
Fi1osof1
Fi1osof 20 января 2014г в 15:25 #
В итоге что, вопрос полностью решился или как?
r
rozhkov 21 января 2014г в 09:30 #
Не совсем.

{processor action="web/getdata" ns="shopmodx" assign=value}
    {foreach $value.object as $obj}
        [[!getImageList?docid=`{$obj.id}`&tpl=`@CODE: <img src="[[+image]]" class="img-thumbnail img-item"/>`&limit=`1`&randomize=`true`&tvname=`gallery`]]
    {/foreach}

Пути некорректно выводит. Как будто id ресурса не меняется при каждом вызове getImageList. При этом имя изображения правильное.
В консоли выводит как положено, при изменении id ресурса выводит путь тот который должен быть.

Ваш код я уверен что будет работать, т.к. в одном проекте я делал похожим образом и путь формировался корректно.
Написал свой процессор с логикой как у getImageList. Но если вызывать его по id ресурса, так же некорректно выводит путь. При этом имена файлов правильные.
Fi1osof1
Fi1osof 21 января 2014г в 14:15 #
Сорри, но больше ничем не помогу. Придется вам копать сам сниппет getImageList, проверяя где какие значения проходят.
Но если вызывать его по id ресурса, так же некорректно выводит путь.
Он скорее всего плейсхолдер берет не переданного значения id, а id текущего документа.
r
rozhkov 22 января 2014г в 09:02 #
В конце концов разобрался. И все стало работать.
Необходимо путь в источнике файлов делать некешируемым [[!migxResourceMediaPath? &pathTpl=`assets/images/{id}/`]]

Код процессора который я написал для себя:

<?php

require_once MODX_CORE_PATH .'components/migx/model/migx/migx.class.php';

class GetDataMIGxProcessor extends modProcessor{
    
    public function initialize(){
        
        $this->setDefaultProperties(array(
            'tvname'        =>  '',
            'id'            =>  0, //id ресурса
            'randomize'     =>  0,
            'limit'         =>  0,
            'nameMS'	    => 	'' //имя MediaSource
        ));
        
        return parent::initialize();
    }
    
    private function GetPath(){
	$this->modx->setPlaceholder('docid', $this->getProperty('id'));
        $source = $this->modx->getObject('modMediaSource', array('name'=>$this->getProperty('nameMS')));
        
        $this->modx->resource = $this->modx->getObject('modResource', $this->getProperty('id'));
	
        $source->initialize(); 
        $value = $source->getBaseUrl();
        
        //unset($source);
        return  $value;
        
        
    }
    
    private function FindFields(xPDOObject $object)
    {   
        
        $migx = new MIGX($this->modx);

        $config_r = $object->get('input_properties');
        $config = $config_r['configs'];
        //

        $q = $this->modx->getObject('migxConfig', array('name'=>$config));
        $data = $this->modx->fromJSON(trim($q->get('formtabs'),  '[]'));

        $res_field = array();

        foreach($data['fields'] as $field){
            if ($field['inputTVtype'] == 'image' || $field['inputTVtype'] == 'file')
                $res_field = $res_field + array($field['field']);
            }
        
        
        unset($migx);
        
        return $res_field;
    }
    
    private function GetTVValue($path){
        $q = $this->modx->newQuery('modTemplateVar');
        $q->innerJoin('modTemplateVarResource', 'v', 'v.tmplvarid = modTemplateVar.id');
        $q->where(array('modTemplateVar.name'=> $this->getProperty('tvname'), 'v.contentid' => $this->getProperty('id')));
        $q->select(array('v.*, modTemplateVar.input_properties'));
            
        $q->prepare();

        $tv = $this->modx->getObject('modTemplateVar', $q);
	
        $keys = $this->FindFields($tv);
        $object = $this->modx->fromJSON($tv->get('value'));
        
        $list = array();
        $index = 0;
        
        if ($this->getProperty('randomize') != 0)
            shuffle($object);
        
        foreach ($object as $tv){

            for ($i = 0; count($keys) > $i; $i++){
                if(array_key_exists($keys[$i], $tv)){
                
                    $tv[$keys[$i]] = implode("", array($path, $tv[$keys[$i]]));
                }
            }
            array_push($list, $tv);
            $index++;
            
            if ($this->getProperty('limit') != 0 && $this->getProperty('limit') == $index)
                break;
        }
        
        //$list['count'] = $index; 

        return array("count" => $index, "object" => $list);
    }
    
    public function process(){
        $path = $this->GetPath();
        $tv_objects = $this->GetTVValue($path);
        
        return $tv_objects;
    }
}

return 'GetDataMIGxProcessor';
Fi1osof1
Fi1osof 22 января 2014г в 10:15 #
Необходимо путь в источнике файлов делать некешируемым [[!migxResourceMediaPath? &pathTpl=`assets/images/{id}/`]]
Да уж, обычный случай для MODX :)
P
Peter Griffin 14 июля 2015г в 19:57 #
Спасибо тебе мужик!
Дай свой кошелек, я тебе на пиво скину!
Три дня боролся с этой проблемой, почитал твой ответ и подумал «НЕЕЕЕ, У МЕНЯ ВСЕ ГУД, ЭТО Я ТОЧНО НЕ ЗАБЫЛ СДЕЛАТЬ!» =)
Эта мелочь мне изрядно попортила пару ночей, но теперь все гуд), еще раз спасибо)
Fi1osof1
Fi1osof 14 июля 2015г в 20:00 #
Всегда пожалуйста!

Внизу форма для донейтов. Туда ОК :)
Авторизуйтесь или зарегистрируйтесь (можно через соцсети ), чтобы оставлять комментарии.