Как создавать собственные галереи на основе Gallery, я писал здесь. А по поводу возвращаемого JSON-а: изначально modProcessor::outputArray() возвращает JSON-строку. public function outputArray(array $array,$count = false) { if ($count === false) { $count = count($array); } return '{"total":"'.$count.'","results":'.$this->modx->toJSON($array).'}'; } Но так как мы часто пишем метод process сами, и возвращаем в нем $this->success() или $this->failure(), то $this->outputArray() мы и не замечаем. А вот modObjectGetListProcessor в process() именно его и возвращает. public function process() { $beforeQuery = $this->beforeQuery(); if ($beforeQuery !== true) { return $this->failure($beforeQuery); } $data = $this->getData(); $list = $this->iterate($data); return $this->outputArray($list,$data['total']); } Вот поэтому ты на выходе и получаешь JSON. Перегрузи outputArray и все. Можешь в нем $this->success($msg, $array) вернуть, а можешь сразу массив вернуть, как у меня в getdata-процессорах. public function outputArray(array $array, $count = false){ return array( 'success' => true, 'message' => $this->getMessage(), 'count' => count($array), 'total' => $count, 'object' => $array, ); }
Все понятно. Блин, хотелось бы все же с процессорами разобраться. По-моему, mgr/item/getlist в gallery меньше кода гоняет
Кто-нибудь читал о дополнении MyComponents от Боба Рэя: http://bobsguides.com/mycomponent-tutorial.html? Начал разбираться с CMP, наткнулся на него, но из-за плохого английского не могу понять, как с ним работать… Вроде, создаются все нужные файлы и в /core/components/, и в /assets/components/ Создается даже пункт меню в «Компонентах». Но работать отказывается — то ли объекты надо самому прописывать где-то, то ли у меня руки кривые)
Большое спасибо. Это то что я искал.
В продолжение темы работы с xPDO. Я уже довольно долго не использую стандартные сниппеты [[galAlbum]], [[galItem]] и т.п. Блин, реально все заморочено. А кастомный вывод какой-то сделать — это вообще высший пилотаж. Но компонент Gallery использую очень активно, чисто для управления галереями в админке, а вывод галерей пишу сам. Вот сегодня сделал очередную галерейку и хочу показать листинг сниппет. Итак, сниппет: <?php $output = '';
// Получаем все элементы $q = $modx->newQuery('galItem'); $q->join('galAlbumItem', 'AlbumItems'); $q->where(array( 'AlbumItems.album' => $album, )); if(!$items = $modx->getCollection('galItem', $q)){ return; }
// Регистрируем скрипты
$assets_url = $modx->getOption('assets_url', null);
$modx->regClientCSS("{$assets_url}js/lib/colorbox/style/1/colorbox.css");
$modx->regClientStartupScript("{$assets_url}js/lib/colorbox/jquery.colorbox-min.js");
$modx->regClientStartupScript("<script type="text/javascript">
$(document).ready(function(){
//Examples of how to assign the ColorBox event to elements
$('.gallery').colorbox({
rel:'gallery'
,'current': ''
});
});
</script>", true);
// Проходим по каждому элементу и набиваем в шаблоны $x = 0; $inRow = 3; $rowClass = "row flow"; $itemClass = "columns four";
$rowOutput = '';
foreach($items as $item){
$x++;
// print_r($item->toArray());
$item = $modx->getChunk('SiteGalleryItemTpl', array(
'class' => $itemClass,
'title' => $item->get('name'),
'src' => $item->get('absoluteImage'),
));
$rowOutput .= $item;
if($x == $inRow){
$output .= $modx->getChunk('SiteGalleryRowTpl', array(
'class' => $rowClass,
'wrapper' => $rowOutput,
));
$x = 0;
$rowOutput = '';
}
}
return $output;
Чанк SiteGalleryRowTpl
<code><div class="[[+class]]">[[+wrapper]]</div> Чанк SiteGalleryItemTpl <div class="galItem [[+class]]"> <div class="title"><span>[[+title]]</span></div> <a href="[[+src]]" class="gallery" title="[[+title]]"> <img src="/assets/components/site_gallery/connector.php?action=web/image/gallery/small&src=[[+src]]"/> </a>
</div> Как видно, для кастомной галереи не нужно писать много кода.И правда, почему? Я бы сформулировал это так: если вы научитесь понимать xPDO-объекты, их методы и принципы, вы сможете творить в MODX вообще что угодно! Вот еще небольшой пример: мне достался сайт, на котором «галерея» была организована на уровне документов (modResource). То есть один элемент — это один документ, в котором загружена картинка и прописано описание. И это все мне надо перенести в Gallery по альбомам, вместе с описаниями, названиями и файлами. Элементов довольно много, потому я просто написал скриптик и выполнил его через консоль. Скрипт писал минут 30, не больше. Сэкономил себе минимум пару часов, и то потому что элементов не так много было. А мог бы и больше времени сэкономить. Но главное — подобные вещи творить (не в высоком смысле слова) можно часто и где угодно. Используют они стандартные метода. Подробности под катом. Сам скрипт (источник на GistHub: gist.github.com/Fi1osof/70d5197fa7ee3fc74ff7 ): if(!$docs = $modx->getCollection('modResource', array( 'parent' => 26 ))){ return; } $album = 2;
$albumDir = $album.'/'; // Получаем полный путь к директории альбома $targetDir = $modx->call('galAlbum','getFilesPath',array(&$modx)).$albumDir;
// Получаем кеш-менеджер, который к тому же используется и для работы с папками и файлами $cacheManager = $modx->getCacheManager(); // Если нет папки, создаем ее if (!file_exists($targetDir) || !is_dir($targetDir)) { if (!$cacheManager->writeTree($targetDir)) { $modx->log(xPDO::LOG_LEVEL_ERROR,'[Gallery] Could not create directory: '.$targetDir); return $modx->toJSON(array('error' => 'Could not create directory: ' . $targetDir)); } } // Проверяем, чтобы была доступна для записи if (!is_readable($targetDir) || !is_writable($targetDir)) { $modx->log(xPDO::LOG_LEVEL_ERROR,'[Gallery] Could not write to directory: '.$targetDir); return $modx->toJSON(array('error' => 'Could not write to directory: ' . $targetDir)); } $r = 0; // Счетчик ранга элемента
// Проходимся по каждому элементу foreach($docs as $doc){ $r++; $title = $doc->get('pagetitle');
// Пытаемся найти картинку и получить путь
if(!preg_match('/src="(.+?)"/', $doc->content, $match)){
$modx->log(1, "Не было найдено изображение для документа ". $doc->id);
}
$img = $match[1];
$filenm = MODX_BASE_PATH. $img; // Абсолютный путь до картинки-источника
// Описание элемента
$desc = strip_tags($doc->content);
// Создаем новый элемент альбома
$item = $modx->newObject('galItem', array(
'name' => $doc->pagetitle,
));
// Сохраняем его, чтобы получить id (будет использован для формирования имени файла)
$item->save();
// Самый быстрый способ получить расширение файла
$extension = end(explode('.', $img));
$filename = $item->id.'.'.$extension;
$relativePath = $albumDir.$filename;
$absolutePath = $targetDir.$filename;
// Копируем картинку в папку альбома
$cacheManager->copyFile($filenm, $absolutePath );
// Набиваем конечные данные в объект элемента альбома
$item->fromArray(array(
'filename' => $albumDir.$filename,
'description' => $desc,
'active' => 1,
));
// Создаем объект Элемент-Альбом
$ai = $modx->newObject('galAlbumItem', array(
'album' => $album,
'rank' => $r,
));
// Добавляем к нему элемент, чтобы сформировалась связь при сохранении
$ai->addOne($item);
// Сохраняем
$ai->save();
} То есть здесь я на уровне API MODX-а и получил нужные элементы из документов, и скопировал файлы кеш-манагером, и сразу создал все элементы в Gallery. Если кто считает, что это не удобно, хотел бы выслушать возражения. Но главное — практически все компоненты MODX — стандартны. И если вы изучите xPDO, то у вас будет в сотни раз меньше вопросов что и как работает.
Сегодня в одном своем проекте решил пользователю через админку назначить фотку, так, без задней мысли. Полез редактировать пользователя — а там такого нет O_o. Полез в базу данных — колонка photo в таблице user_attributes имеется. Обратно лезу в редактор — нет нифига… А оказалось, что этого механизма в принципе не предусмотрено. Странно, ну да ладно. Сел вот написал небольшой пакетик-плагин. Теперь можно:-) ? Исходник пакета здесь: github.com/Fi1osof/modAvatar Советую всем скачать и и изучить внимательно. Там конечно местами бордак в коде. но в целом пакет не большой, не должны заблудиться. Красота компонента в том, что происходит расширение админки без какого-либо вмешательства в исходный код. Даже контроллеры не переопределяются. Это чистый ExtJS. Кстати, забыл сказать о механизме работы. В целом все очень и очень стандартно. Если фото были раньше чем-то назначены, то компонент их покажет в редакторе профиля, так как нет велосипеда. Колонка photo — стандартная. Туда все и пишется. В дальнейшем можно легко получить значение через API $photo = $modx->getObject('modUser', $id) -> getOne('modUserProfile', 'Profile') ->get('photo');
Добрый день! Никто не сталкивался с процессорами Gallery? У нее очень удобная админская часть, но вот с выводом немного узковато. Хотелось бы вывод картинок сделать по своему сценарию. Решил использовать процессоры и не могу понять, как подступиться.
Запускаю в console код <?php
$response = $modx->runProcessor('mgr/item/getlist',
array(
'album' => '1',
),
array(
'processors_path' => $modx->getOption('core_path') . 'components/gallery/processors/'
));
print_r($response->response); Выдает
?
Насколько я понимаю, это JSON.
пробую вызвать print_r($response->response['results']); и получаю ничего. json_decode тоже не работает. Объясните пожалуйста, в чем проблема, как получить эти results?
Продолжая тему магических операций с xPDO-объектами, рассмотрим новый пример. Дано: две таблицы. Одна содержит данные актуальных данных, вторая содержит исторические записи (когда заявка обновляется, перед сохранением запись переносится в историческую таблицу с сохранением ID на текущую). Это позволяет и всю историю изменений хранить, и не текущую таблицу актуальных данных не перегружать. Структуры таблиц идентичные, только что во второй таблице есть еще колонка orderid, хранящая ключ на первоисточник записи. В результате мы имеем возможность выдернуть и актуальную запись, и всю ее историю. Задача: получить объект заявки и все исторические записи этой заявки одним массивом, и чтобы все объекты были инстансами одного и того же класса. Этот момент разъясню подробней: Класс заявки — JKHOrder. Его таблица orders.
Класс исторических записей — JKHOrderHistory. Таблица — orders_history.
JKHOrderHistory не расширяет класс JKHOrder, так как у него совершенно другая логика, то есть это полностью самостоятельный объект.
Но у меня большая логика в админке завязана на ExtJS, и при выводе одной специфической странице, мне надо, чтобы объект исторической записи вел себя так, как будто это не историческая запись, а именно заявка (нужны специфические методы класса JKHOrder). Вот как раз задача стоит такая: методом $modx->getCollection() из таблицы исторических записей (JKHOrderHistory) получить массив объектов JKHOrder. Для реализации этого запрос будет выглядеть так: // Указываем именно JkhOrderHistory, чтобы xPDO в запросе
использовал как источник именно таблицу исторических записей
$c = $this->modx->newQuery('JkhOrderHistory');
// Устанавливаем алиас
// В случае с подменой объектов обязательно, и должно совпадать с именем получаемых объектов и class_key,
чтобы не возникало xPDO-ошибок и в логи не разрастались.
// Так же этот алиас будет использоваться в конструкциях innerJoin и leftJoin
// Используйте ее сразу после ->newQuery
$c->setClassAlias('JkhOrder');
$c->select(array(
'JkhOrder.*',
// class_key обязательно, так как именно по этой колонке xPDO понимает
// какой именно объект надо вернуть
"'JkhOrder' as class_key",
));
// В конструкции where и т.п. очень советую использовать алиас
// то есть явно указывать принадлежность колонок
// иначе могут возникнуть SQL-ошибки
$c->where(array(
'JkhOrder.orderid' => 45
));
// а вот здесь уже указываем не JkhOrder
$orders = $modx->getCollection('JkhOrder', $c); Вот и все. Получаем массив других объектов.