Понадобилось на одном из сайтов сделать периодическое обновление валют с сайта CBR. Создал процессор в shopkeeper3, в интерфейс запилил кнопку. По кнопке курсы обновляются.
Дополнительно чтобы легко было работать с фильтрацией и сортировкой по ценам написал плагин, который обновляет в товарах цену в скрытом ТВ по курсу выбранному в товаре с пересчётам из цены введённой тем кто заполняет сайт.
Чтобы сразу обновлять цены при обновлении курсов, создал новой системное событие OnSHKAfterSaveSettings, вызвал его в процессоре обновления валют, и подцепил на него плагин.
Всё это прекрасно работает по кнопке(коды процессора и плагина выложу, если кому интересно). Проблемы начинаются, когда нужно как то обновлять это дело автоматом. С кроном связываться не захотелось, не удобно это, да и давно подумывал написать какой-то задачник, чтобы прямо из бэкэнда можно было ставить задачи по типу крона. Написал небольшой компонент с использованием для запуска задач stream_context_create c лимитом 0 и обычный file_get_contents к коннектору запускающему процессор записанный в задаче. Выглядит это так:
Функция в классе компонента запускающая задачу:
public function runTask(modTask $task,$params=array())
{
if(!$task)return false;
$pid = bin2hex(openssl_random_pseudo_bytes(16));
$task->set('pid',$pid);
$task->set('state','process');
$task->set('last_run',time());
$task->save();
$params['pid']=$pid;
$params['tid']=$task->id;
switch($task->type)
{
case 'processor':
{
$params['action']='web/runprocessor';
$http_ctx = stream_context_create(array('http' => array('timeout' => 0 )));
@file_get_contents('http://'.$_SERVER['SERVER_NAME'].$this->config['connector']."?".http_build_query($params), 0, $http_ctx);
return true;
}
case 'snippet':
{
if(empty($params['snippet']))return false;
$snippet = $params['snippet'];
$this->modx->runSnippet($snippet,$params);
return true;
}
case 'event':
{
if(empty($params['event']))return false;
$event = $params['event'];
$this->modx->invokeEvent($event,$params);
return true;
}
default:return false;
}
}
<?php
ignore_user_abort(1);
set_time_limit(120);
require_once dirname(dirname(dirname(dirname(__FILE__)))).'/config.core.php';
require_once MODX_CORE_PATH.'config/'.MODX_CONFIG_KEY.'.inc.php';
define("MODX_REQP",false);
$_REQUEST['ctx']='mgr';
require_once MODX_CONNECTORS_PATH.'index.php';
$_SERVER['HTTP_MODAUTH'] = $modx->site_id;
$_REQUEST['HTTP_MODAUTH'] = $_SERVER['HTTP_MODAUTH'];
$corePath = $modx->getOption('core_path').'components/scheduler/';
$modx->runProcessor($_REQUEST["action"],$_REQUEST,array(
'processors_path' => $corePath . 'processors/'
));
Процессор запускающий процессор задачи:
<?php
class RunProcessorProcessor extends modProcessor
{
public function process()
{
$scriptProperties = $this->getProperties();
$Scheduler = $this->modx->getService('scheduler','Scheduler',$this->modx->getOption('core_path') . 'components/scheduler/model/');
$task = $this->modx->getObject('modTask',(int)$scriptProperties['tid']);
if(!$task)return $this->abort('Задача не найдена');
if($task->type!='processor')return $this->abort('Неверный тип задачи');
if($task->pid!=$scriptProperties['pid'])return $this->abort('Неверный pid');
$params = json_decode($task->params,true);
if(empty($params))return $this->abort('Не задан процессор');
$this->modx->runProcessor
(
$params['processor'],
array_merge($params,$scriptProperties),
array('processors_path' => $params['path'])
);
return array('success'=>true,'message'=>'','object'=>array());
}
public function abort($message)
{
$this->setToLog($message);
return array('success'=>false,'message'=>$message);
}
}
return 'RunProcessorProcessor';
В результате нужный процессор(с обновлением валют) запускается, но вот событие OnSHKAfterSaveSettings не вызывается, точнее даже происходит какая-то ошибка(в логах нет), поскольку запись в лог после вызова $this->modx->invokeEvent('OnSHKAfterSaveSettings ') не проходит, а до вызова появляется.
Нашёл похожую проблему на одном из сайтов там ответом был вызов $modx->getSettings(), но мне он не помог.
Почему ещё может не отрабатывать invokeEvent?