Дата публикации
21 Апреля 2020
Дата изменения
5 Июля 2020
Уникальных просмотров
3.006

Оглавление

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

Пролог

Одна из моих первых рабочих задач на MODx, заключалась в написании скрипта парсинга, который должен был по определенному URL считывать информацию и обновлять её на сайте. Тогда я решил свою задачу с помощью PDO или xPDO. Получал объект обновляемого ресурса через $modx->getObject, изменял необходимые поля с помощью метода set(), и сохранял ресурс методом save().

Фактически, этого было достаточно на тот момент. Но для более грамотного управления ресурсами (да и практически всей динамикой в MODx), умные дядьки написали процессоры. Это php скрипты, в которых выполняются определенные функции. Когда вы через менеджер MODx создаете, удаляете, публикуете, изменяете или делайте еще много других процедур с ресурсами, срабатывают те самые — процессоры.

Есть очень важное отличие в использовании процессоров при управлении любыми объектами в MODx, нежели чем использовать PDO, xPDO или вообще писать свои SQL запросы. В процессорах с помощью метода modX.invokeEvent, активируются системные события, это позволит скриптам правильно отрабатывать при взаимодействии с объектами в MODx. Вы сможете смело писать плагины, не переживая что, то или иное событие может не запуститься.

В MODx есть система «Прав доступа». Она нужна для проверок, имеет ли пользователь право  проводить определённые операции с объектами системы. Так что, если вы используете процессоры, будет произведена проверка на ту или иную проводимую пользователем операцию. Всегда логируйте результат работы процессоров:

if ($response->isError()) {
    return print_r($modx->error->failure($response->getMessage()));
}

Получаем данные ресурса через процессор get

Так как мы изменяем данные уже существующего ресурса, нам нужно их для начала получить. И для этого тоже есть процессор. Я буду работать в очень крутом дополнении MODx — modalConsole, которую написал Сергей Шлоков. Пишем следующий код:

$id = 1;

// Получаем поля ресурса с идентификатором 1
$properties = ['id' => $id];
$response = $modx->runProcessor('resource/get', $properties);
if ($response->isError()) {
    return print_r($modx->error->failure($response->getMessage()));
}

$data = $response->response['object'];

print_r($data);

В этом коде, мы с помощью метода runProcessor, запустили процессор ресурса — get, передали в него свойства в виде идентификатора искомого ресурса, проверили что в ответе нет ошибок и в переменную $data записали массив полей ресурса:

Array
(
    [id] => 1
    [type] => document
    [contentType] => text/html
    [pagetitle] => Главная
    [longtitle] => 
    [description] => 
    [alias] => glavnaya
    [alias_visible] => 1
    [link_attributes] => 
    [published] => 1
    [pub_date] => 
    [unpub_date] => 
    [parent] => 0
    [isfolder] => 
    [introtext] => 
    [content] => 
    [richtext] => 1
    [template] => 2
    [menuindex] => 0
    [searchable] => 1
    [cacheable] => 1
    [createdby] => 1
    [createdon] => 2020-04-13 21:07:42
    [editedby] => 1
    [editedon] => 2020-04-21 15:43:45
    [deleted] => 
    [deletedon] => 0
    [deletedby] => 0
    [publishedon] => 2020-04-21 1:15 pm
    [publishedby] => 1
    [menutitle] => 
    [donthit] => 
    [privateweb] => 
    [privatemgr] => 
    [content_dispo] => 0
    [hidemenu] => 
    [class_key] => modDocument
    [context_key] => web
    [content_type] => 1
    [uri] => glavnaya
    [uri_override] => 0
    [hide_children_in_tree] => 0
    [show_in_tree] => 1
    [properties] => 
    [canpublish] => 1
)

Изменяем данные ресурса через процессор update

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

// Обновляем поля ресурса
$response = $modx->runProcessor('resource/update', [
    'id' => $data['id'],
    'content' => 'Тест',
]);

И при попытке выполнить код, изменение ресурса не произойдет, а мы получим ошибки. Дело в том, что процессор update, требует обязательно указать контекст ресурса, в котором происходят изменения. Сделаем это:

$response = $modx->runProcessor('resource/update', [
    // Указываем обязательное поле context_key для обновления ресурса
    'id' => $data['id'],
    'context_key' => $data['context_key'],
    // Меняем нужные нам поля
    'content' => 'Тест',
]);

Выполняем код и он опять не сработает. В логах, php нам любезно сообщит что нужно указать поля ресурса pagetitle, parent, и class_key. Я, если честно, не вникал зачем MODx требует указывать и эти поля, но у нас ведь никаких проблем с этим нет. Мы получили все поля ресурса и можем их же и указать при обновлении ресурса:

$response = $modx->runProcessor('resource/update', [
    // Указываем обязательные поля
    'id' => $data['id'],
    'parent' => $data['parent'],
    'class_key' => $data['class_key'],
    'context_key' => $data['context_key'],
    'pagetitle' => $data['pagetitle'],
    // Меняем нужные нам поля
    'content' => 'тест',
]);

if ($response->isError()) {
    return print_r($modx->error->failure($response->getMessage()));
}

И вот теперь при выполнении кода, значение поля контент уже изменится на — «Тест». Изменится оно в базе, изменится в менеджере MODx, но на фронте — нет. Потому что нужно почистить кэш. Но не будем же мы чистить весь кэш сайта? Я покажу как чистить кэш чуть более оптимизировано. Дописываем в скрипт следующий код:

// Очищаем только кэш ресурса с идентификатором 1
$options = [
    'objects' => null,
    'extensions' => [
        $id . '.cache.php'
    ]
];

// Очищаем только файлы кэша которые расположены по пути указанном ниже
$paths = [
    'resource/web/resources/',
];

// Чистим кэш по настройкам выше
$modx->cacheManager->clearCache($paths, $options);

Ну и теперь кэш ресурса который мы редактируем очистится автоматически, а при обращении к страничке на фронте сгенерируется новый. Вот теперь база для написания парсинга готова!

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

 Пишем парсер

Это удивительно конечно, но фактически парсер мы уже написали. Теперь нам осталось придумать откуда и как цеплять контент и подставлять его в нужные нам поля ресурса. Я воспользуюсь самым обычным способ парсинга, через функцию php — file_get_contents:

// Формируем данные для парсинга
$url = 'https://www.php.net/';
$content = file_get_contents($url);
$getBlock = explode('<div class="download">', $content);
$html = explode('</div>', $getBlock [1]);

Я парсю главную страницу сайта php.net и вырезаю блок «Download», который и буду сохранять у себя на сайте. 

Финальный код парсера

Полный код нашего мини-парсера:

$id = 1;

$properties = ['id' => $id];
$response = $modx->runProcessor('resource/get', $properties);
if ($response->isError()) {
    return print_r($modx->error->failure($response->getMessage()));
}

$data = $response->response['object'];

// Формируем данные для парсинга
$url = 'https://www.php.net/';
$content = file_get_contents($url);
$getBlock = explode('<div class="download">', $content);
$html = explode('</div>', $getBlock[1]);

$response = $modx->runProcessor('resource/update', [
    'id' => $data['id'],
    'parent' => $data['parent'],
    'class_key' => $data['class_key'],
    'context_key' => $data['context_key'],
    'alias' => $data['alias'],
    'pagetitle' => $data['pagetitle'],
    // Меняем нужные нам поля
    'content' => $html[0],
]);

if ($response->isError()) {
    return print_r($modx->error->failure($response->getMessage()));
}

$options = [
    'objects' => null,
    'extensions' => [
        $id . '.cache.php'
    ]
];

$paths = [
    'resource/web/resources/',
];

$modx->cacheManager->clearCache($paths, $options);

Если сайт php.net еще не изменил разметку, можете попробовать запустить этот скрипт на своем тестовом сайте и в ресурсе с идентификатором 1 появится информация с сайта php.net.

Эпилог

Этот пример дает вам практически полную базу знаний в использовании процессоров для обновления ресурсов. При определённых знаниях в PHP или взаимодействиями с некоторыми библиотеками, можно создать хороший парсер, который будет складывать информацию в нужные вам ресурсы, в нужные поля, очищать кэш либо у указанных ресурсов, либо у всех. Все зависит от настроек, которые вы выставите. Ну, а скрипт выше — это база с которой стоит начинать редактирование ресурсов через процессоры MODx.

Благодарность автору

Если по какой-либо причине вы хотите поблагодарить автора данного ресурса, вы можете это сделать одним из удобных для вас способов ниже.

Один из самых популярных способов поблагодарить автора, воспользоваться сервисом Яндекс.Деньги.

Время работы: 0,1189 s
Время запросов: 0,1189 s
Количество запросов: 28
Источник: cache