classes/Gems/Default/CommJobAction.php
<?php
/**
*
* @package Gems
* @subpackage Default
* @author Matijs de Jong <mjong@magnafacta.nl>
* @copyright Copyright (c) 2011 Erasmus MC
* @license New BSD License
*/
/**
*
*
* @package Gems
* @subpackage Default
* @copyright Copyright (c) 2011 Erasmus MC
* @license New BSD License
* @since Class available since version 1.6.2
*/
class Gems_Default_CommJobAction extends \Gems_Controller_ModelSnippetActionAbstract
{
protected $autofilterParameters = array(
'extraSort' => array('gcj_id_order' => SORT_ASC),
'searchFields' => 'getSearchFields'
);
/**
* The snippets used for the create and edit actions.
*
* @var mixed String or array of snippets name
*/
protected $createEditSnippets = 'ModelFormVariableFieldSnippet';
/**
*
* @var \Gems_User_User
*/
public $currentUser;
/**
*
* @var \Zend_Db_Adapter_Abstract
*/
public $db;
/**
* The snippets used for the index action, before those in autofilter
*
* @var mixed String or array of snippets name
*/
protected $indexStartSnippets = array('Generic\\ContentTitleSnippet', 'Agenda\\AutosearchFormSnippet');
protected $monitorParameters = array(
'monitorJob' => 'getMailMonitorJob'
);
protected $monitorSnippets = 'MonitorSnippet';
/**
*
* @var \Gems_Project_ProjectSettings
*/
public $project;
/**
* Query to get the round descriptions for options
* @var string
*/
protected $roundDescQuery = "SELECT gro_round_description, gro_round_description FROM gems__rounds WHERE gro_id_track = ? GROUP BY gro_round_description";
/**
* The snippets used for the show action
*
* @var mixed String or array of snippets name
*/
protected $showSnippets = ['Generic\\ContentTitleSnippet', 'Mail\\CommJobShowSnippet'];
/**
* The automatically filtered result
*
* @param $resetMvc When true only the filtered resulsts
*/
public function autofilterAction($resetMvc = true)
{
parent::autofilterAction($resetMvc);
//If allowed, add the sort action
if ($this->menu->findAllowedController($this->getRequest()->getControllerName(), 'sort')) {
$buttons = $this->_helper->SortableTable('sort', 'id');
// First element is the wrapper
$this->html[0]->append($buttons);
}
}
/**
* Creates a model for getModel(). Called only for each new $action.
*
* The parameters allow you to easily adapt the model to the current action. The $detailed
* parameter was added, because the most common use of action is a split between detailed
* and summarized actions.
*
* @param boolean $detailed True when the current action is not in $summarizedActions.
* @param string $action The current action.
* @return \MUtil_Model_ModelAbstract
*/
protected function createModel($detailed, $action)
{
$dbLookup = $this->util->getDbLookup();
$dbTracks = $this->util->getTrackData();
$commUtil = $this->util->getCommJobsUtil();
$unselected = array('' => '');
$model = new \MUtil_Model_TableModel('gems__comm_jobs');
// START START START START START START START START START START START START START START START START START
\Gems_Model::setChangeFieldsByPrefix($model, 'gcj');
$model->set('gcj_id_order', 'label', $this->_('Execution order'),
'description', $this->_('Execution order of the communication jobs, lower numbers are executed first.'),
'required', true
);
if ($detailed) {
$model->set('gcj_id_order', 'validator', $model->createUniqueValidator('gcj_id_order'));
if ($action == 'create') {
// Set the default round order
$newOrder = $this->db->fetchOne("SELECT MAX(gcj_id_order) FROM gems__comm_jobs");
if ($newOrder) {
$model->set('gcj_id_order', 'default', $newOrder + 10);
}
}
}
$model->set('gcj_id_communication_messenger',
[
'label' => $this->_('Communication method'),
'description' => $this->_('The communication method the message should be sent as. E.g. mail, sms'),
'required' => true,
'multiOptions' => $commUtil->getCommunicationMessengers(),
]
);
$model->set('gcj_id_message', 'label', $this->_('Template'),
'multiOptions', $unselected + $dbLookup->getCommTemplates('token')
);
// EXECUTION EXECUTION EXECUTION EXECUTION EXECUTION EXECUTION EXECUTION EXECUTION EXECUTION EXECUTION
if ($detailed) {
$html = \MUtil_Html::create()->h4($this->_('Execution'));
$model->set('execution',
'default', $html,
'label', ' ',
'elementClass', 'html',
'value', $html
);
}
$model->set('gcj_active', 'label', $this->_('Execution method'),
'multiOptions', $commUtil->getActiveOptions(),
'required', true,
'description', $this->_('Manual jobs run only manually, but not during automatic jobs. Disabled jobs not even then. ')
);
if ($detailed) {
$bulkProcessOptions = $commUtil->getBulkProcessOptions();
} else {
$bulkProcessOptions = $commUtil->getBulkProcessOptionsShort();
}
$model->set('gcj_process_method', 'label', $this->_('Processing Method'),
'default', 'O',
'description', $this->_('Only for advanced users'),
'multiOptions', $bulkProcessOptions
);
$model->set('gcj_filter_mode', 'label', $this->_('Filter for'),
'multiOptions', $unselected + $commUtil->getBulkFilterOptions()
);
if ($detailed) {
// Only show reminder fields when needed
$switches = array(
'R' => array(
'gcj_filter_days_between' => array('elementClass' => 'Text', 'label' => $this->_('Days between reminders'),'description', $this->_('1 day means the reminder is send the next day')),
'gcj_filter_max_reminders' => array('elementClass' => 'Text', 'label' => $this->_('Maximum reminders'))
),
'B' => array(
'gcj_filter_days_between' => array('elementClass' => 'Text', 'label' => $this->_('Days before expiration'), 'description', ''),
),
'E' => array(
'gcj_filter_days_between' => array('elementClass' => 'Text', 'label' => $this->_('Days before expiration'), 'description', ''),
),
'N' => [],
);
$model->addDependency(array('ValueSwitchDependency', $switches), 'gcj_filter_mode');
$model->set('gcj_filter_days_between', 'label', '',
'elementClass', 'Hidden',
'required', true,
'validators[]', 'Digits'
);
$model->set('gcj_filter_max_reminders','label', '',
'elementClass', 'Hidden',
'description', $this->_('1 means only one reminder will be send'),
'required', true,
'validators[]', 'Digits'
);
}
// SENDER SENDER SENDER SENDER SENDER SENDER SENDER SENDER SENDER SENDER SENDER SENDER SENDER SENDER SENDER
if ($detailed) {
$html = \MUtil_Html::create()->h4($this->_('Sender'));
$model->set('send_from',
'default', $html,
'label', ' ',
'elementClass', 'html',
'value', $html
);
}
$model->set('gcj_id_user_as', 'label', $this->_('By staff member'),
'multiOptions', $unselected + $dbLookup->getActiveStaff(),
'default', $this->currentUser->getUserId(),
'description', $this->_('Used for logging and possibly from address.'))
;
$fromMethods = $unselected + $commUtil->getBulkFromOptions();
$model->set('gcj_from_method', 'label', $this->_('From address used'),
'multiOptions', $fromMethods
);
if ($detailed) {
// Show other field only when last $fromMethod is select
$switches = [
'F' => ['gcj_from_fixed' => ['elementClass' => 'Text', 'label' => $this->_('From other')]],
'O' => [],
'S' => [],
'U' => [],
];
$model->addDependency(array('ValueSwitchDependency', $switches), 'gcj_from_method');
$model->set('gcj_from_fixed', 'label', '',
'elementClass', 'Hidden',
'validators[mail]', 'SimpleEmail'
);
}
// RECEIVER RECEIVER RECEIVER RECEIVER RECEIVER RECEIVER RECEIVER RECEIVER RECEIVER RECEIVER RECEIVER RECEIVER
if ($detailed) {
$html = \MUtil_Html::create()->h4($this->_('Receiver'));
$model->set('send_to',
'default', $html,
'label', ' ',
'elementClass', 'html',
'value', $html
);
}
$model->set('gcj_target', 'label', $this->_('Filler'),
'default', 0,
'multiOptions', $commUtil->getBulkTargetOptions()
);
if ($detailed) {
$model->set('gcj_to_method', 'multiOptions', $commUtil->getBulkToOptions());
$model->set('gcj_fallback_method', 'multiOptions', $fromMethods);
$model->set('gcj_fallback_fixed', 'validators[mail]', 'SimpleEmail');
$model->addDependency('CommJob\\Senderdependency');
}
if ($model->has('gcj_target_group')) {
$anyGroup[''] = $this->_('(all groups)');
$model->set('gcj_target_group', 'label', $this->_('Group'),
'multiOptions', $anyGroup + $commUtil->getAllGroups(),
'onchange', 'this.form.submit();'
);
}
// SURVEY SELECTION SURVEY SELECTION SURVEY SELECTION SURVEY SELECTION SURVEY SELECTION SURVEY SELECTION
if ($detailed) {
$html = \MUtil_Html::create()->h4($this->_('Survey selection'));
$model->set('selection',
'default', $html,
'label', ' ',
'elementClass', 'html',
'value', $html
);
}
$anyTrack[''] = $this->_('(all tracks)');
$model->set('gcj_id_track', 'label', $this->_('Track'),
'multiOptions', $anyTrack + $dbTracks->getAllTracks(),
'onchange', 'this.form.submit();'
);
$anyRound[''] = $this->_('(all rounds)');
$defaultRounds = $anyRound + $dbTracks->getAllRoundDescriptions();
$model->set('gcj_round_description', 'label', $this->_('Round'),
'multiOptions', $defaultRounds,
'variableSelect', array(
'source' => 'gcj_id_track',
'baseQuery' => $this->roundDescQuery,
'ajax' => array('controller' => 'comm-job', 'action' => 'roundselect'),
'firstValue' => $anyRound,
'defaultValues' => $defaultRounds,
));
$anySurvey[''] = $this->_('(all surveys)');
$model->set('gcj_id_survey', 'label', $this->_('Survey'),
'multiOptions', $anySurvey + $dbTracks->getAllSurveys(true)
);
$organizations = $dbLookup->getOrganizations();
$anyOrganization[''] = $this->_('(all organizations)');
$model->set('gcj_id_organization',
'multiOptions', $anyOrganization + $organizations);
if ($detailed || count($organizations) > 1) {
$model->set('gcj_id_organization', 'label', $this->_('Organization'));
}
return $model;
}
/**
* Execute a single mail job
*/
public function executeAction($preview = false)
{
$jobId = intval($this->getParam(\MUtil_Model::REQUEST_ID));
$batch = $this->loader->getTaskRunnerBatch('commjob-execute-' . $jobId);
$batch->setMessageLogFile($this->project->getCronLogfile());
$batch->minimalStepDurationMs = 3000; // 3 seconds max before sending feedback
if (!$batch->isLoaded() && !is_null(($jobId))) {
$batch->addMessage(sprintf(
$this->_('Starting single %s message job %s'),
$this->project->getName(),
$jobId
));
// Check for unprocessed tokens
$tracker = $this->loader->getTracker();
$tracker->loadCompletedTokensBatch($batch, null, $this->currentUser->getUserId());
// We could skip this, but a check before starting the batch is better
$sql = $this->db->select()->from('gems__comm_jobs', array('gcj_id_job'))
->where('gcj_active > 0')
->where('gcj_id_job = ?', $jobId);
$job = $this->db->fetchOne($sql);
if (!empty($job)) {
$batch->addTask('Comm\\ExecuteCommJobTask', $job, null, null, $preview);
} else {
$batch->reset();
$this->addMessage($this->_("Messagejob is inactive and won't be executed"), 'danger');
}
if ($preview === true) {
$batch->autoStart = true;
}
}
if ($batch->isFinished()) {
// Add the messages to the view and forward
$messages = $batch->getMessages(true);
if (count($messages)) {
$this->addMessage($messages, 'info');
}
$echo = array_filter(array_map('trim', preg_split('/<[^>]+>/', \MUtil_Echo::out())));
if ($echo) {
echo "\n\n================================================================\nECHO OUTPUT:\n\n";
echo implode("\n", $echo);
}
$this->accesslog->logChange($this->getRequest(), $messages, $echo);
$this->_reroute(array('action'=>'show'));
}
if ($preview === true) {
$title = sprintf($this->_('Preview single message job %s'), $jobId);
} else {
$title = sprintf($this->_('Executing single message job %s'), $jobId);
}
$this->_helper->BatchRunner($batch, $title, $this->accesslog);
}
/**
* Execute all message jobs
*/
public function executeAllAction()
{
$this->_helper->BatchRunner(
$this->loader->getMailLoader()->getCronBatch('commjob-execute-all'),
$this->_('Execute all message jobs'),
$this->accesslog
);
}
/**
* Helper function to get the title for the index action.
*
* @return $string
*/
public function getIndexTitle()
{
return $this->_('Automatic message jobs');
}
public function getMailMonitorJob()
{
return $this->loader->getUtil()->getMonitor()->getCronMailMonitor();
}
/**
* Returns the fields for autosearch with
*
* @return array
*/
public function getSearchFields()
{
return [
'gcj_active' => $this->_('(all execution methods)')
];
}
/**
* Helper function to allow generalized statements about the items in the model.
*
* @param int $count
* @return $string
*/
public function getTopic($count = 1)
{
return $this->plural('automatic messaging job', 'automatic messaging jobs', $count);
}
/**
* Action for showing a browse page
*/
public function indexAction()
{
$lock = $this->util->getCronJobLock();
if ($lock->isLocked()) {
$this->addMessage(sprintf($this->_('Automatic messaging have been turned off since %s.'), $lock->getLockTime()));
if ($menuItem = $this->menu->findController('cron', 'cron-lock')) {
$menuItem->set('label', $this->_('Turn Automatic Messaging Jobs ON'));
}
}
parent::indexAction();
$this->html->pInfo($this->_('With automatic messaging jobs and a cron job on the server, messages can be sent without manual user action.'));
}
public function monitorAction() {
if ($this->monitorSnippets) {
$params = $this->_processParameters($this->monitorParameters);
$this->addSnippets($this->monitorSnippets, $params);
}
}
/**
* Execute a single message job
*/
public function previewAction() {
$this->executeAction(true);
}
/**
* Ajax return function for round selection
*/
public function roundselectAction()
{
\Zend_Layout::resetMvcInstance();
$trackId = $this->getRequest()->getParam('sourceValue');
$rounds = $this->db->fetchPairs($this->roundDescQuery, $trackId);
echo json_encode($rounds);
}
/**
* Action for showing an item page with title
*/
public function showAction()
{
parent::showAction();
$jobId = $this->getRequest()->getParam('id');
if (!is_null($jobId)) {
$jobId = (int) $jobId;
$job = $this->db->fetchRow("SELECT * FROM gems__comm_jobs WHERE gcj_id_job = ?", $jobId);
// Show a different color when not active,
switch ($job['gcj_active']) {
case 0:
$class = ' disabled';
$caption = $this->_('Message job inactive, can not be sent');
break;
case 2:
$class = ' manual';
$caption = $this->_('Message job manual, can only be sent using run');
break;
// gcj_active = 1
default:
$class = '';
$caption = $this->_('Message job automatic, can be sent using run or run all');
break;
}
$model = $this->loader->getTracker()->getTokenModel();
$filter = $this->loader->getUtil()->getCommJobsUtil()->getJobFilter($job);
// Clone request and unset the id parameter to prevent filtering
$cleanReq = clone $this->getRequest();
$cleanReq->setParam(\MUtil_Model::REQUEST_ID, null);
$params = [
'request' => $cleanReq,
'model' => $model,
'filter' => $filter,
'showActionLinks' => false,
'class' => 'browser table mailjob' . $class,
'caption' => $caption,
'onEmpty' => $this->_('No tokens found to message'),
'extraSort' => ['gto_valid_from' => SORT_ASC, 'gto_round_order' => SORT_ASC]
];
$this->addSnippet('TokenPlanTableSnippet', $params);
}
}
public function sortAction()
{
$this->_helper->getHelper('SortableTable')->ajaxAction('gems__comm_jobs','gcj_id_job', 'gcj_id_order');
}
}