<?php
/**
* This file implements the UI view for the general settings.
*
* This file is part of the evoCore framework - {@link http://evocore.net/}
* See also {@link https://github.com/b2evolution/b2evolution}.
*
* @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
*
* @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}
*
* @package admin
*/
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
// Get filters:
global $ctst_pending, $ctst_started, $ctst_warning, $ctst_timeout, $ctst_error, $ctst_imap_error, $ctst_finished, $cjob_type;
global $datestartinput, $datestart, $timestart, $datestopinput, $datestop, $timestop;
// We want to remember these params from page to page:
$ctst_status = param( 'ctst_status', 'array:string', NULL, true );
$cjob_type = param( 'cjob_type', 'string', NULL, true );
param( 'results_crontab_order', 'string', '-D', true );
param( 'results_crontab_page', 'integer', 1, true );
// Name filter:
$s = param( 's', 'string', '', true );
// Date/time filters:
if( param_date( 'datestartinput', T_('Invalid date'), false, NULL ) !== NULL )
{ // We have a user provided localized date:
memorize_param( 'datestart', 'string', NULL, trim( form_date( $datestartinput ) ) );
memorize_param( 'datestartinput', 'string', NULL, empty( $datestartinput ) ? NULL : date( locale_datefmt(), strtotime( $datestartinput ) ) );
param_time( 'timestart', '00:00:00', true, false, true, true );
}
else
{ // We may have an automated param transmission date:
param( 'datestart', 'string', '', true );
}
if( param_date( 'datestopinput', T_('Invalid date'), false, NULL ) !== NULL )
{ // We have a user provided localized date:
memorize_param( 'datestop', 'string', NULL, trim( form_date( $datestopinput ) ) );
memorize_param( 'datestopinput', 'string', NULL, empty( $datestopinput ) ? NULL : date( locale_datefmt(), strtotime( $datestopinput ) ) );
param_time( 'timestop', '23:59:59', true, false, true, true );
}
else
{ // We may have an automated param transmission date:
param( 'datestop', 'string', '', true );
}
global $Session;
$cronjob_filters = $Session->get( 'cronjob_filters' );
if( empty( $cronjob_filters ) )
{ // No saved filter yet
$cronjob_filters = array();
}
if( $ctst_status === NULL )
{ // Get a param values from Session
foreach( cron_statuses() as $status_key => $status_title )
{
${'ctst_'.$status_key} = empty( $cronjob_filters[ $status_key ] ) ? 0 : 1;
}
}
else
{ // Save new values to Session
foreach( cron_statuses() as $status_key => $status_title )
{
$cronjob_filters[ $status_key ] = ${'ctst_'.$status_key} = intval( in_array( $status_key, $ctst_status ) );
}
}
if( $cjob_type === NULL )
{ // Get a param values from Session
$cjob_type = empty( $cronjob_filters['type'] ) ? '' : $cronjob_filters['type'];
}
else
{ // Save new values to Session
$cronjob_filters['type'] = $cjob_type;
}
// Save new filters
$Session->set( 'cronjob_filters', $cronjob_filters );
$Session->dbsave();
if( !$ctst_pending && !$ctst_started && !$ctst_warning && !$ctst_timeout && !$ctst_error && !$ctst_imap_error && !$ctst_finished )
{ // Set default status filters:
$ctst_pending = 1;
$ctst_started = 1;
$ctst_warning = 1;
$ctst_timeout = 1;
$ctst_error = 1;
$ctst_imap_error = 1;
}
// Create cron job names SELECT query from crong_jobs_config array
$cron_job_name_query = cron_job_sql_query();
/*
* Create result set :
*/
$SQL = new SQL();
$SQL->SELECT( 'ctsk_ID, ctsk_start_datetime, ctsk_key, ctsk_name, ctsk_params, ctsk_repeat_after, ctsk_repeat_variation, clog_actions_num,
IFNULL( clog_status, "pending" ) as status,
IF( clog_realstop_datetime IS NULL, -1, UNIX_TIMESTAMP( clog_realstop_datetime ) - UNIX_TIMESTAMP( clog_realstart_datetime ) ) as duration,
IFNULL( ctsk_name, task_name ) as final_name' );
$SQL->FROM( 'T_cron__task LEFT JOIN T_cron__log ON ctsk_ID = clog_ctsk_ID' );
if( !empty( $cron_job_name_query ) )
{ // left join with the predefined cron job names, to be able to order correctly after the after the localized Name fields
$SQL->FROM_add( 'LEFT JOIN ( '.$cron_job_name_query. ' ) AS temp ON ctsk_key = temp.task_key');
}
if( ! empty( $cjob_type ) )
{ // Filter by job type:
$SQL->WHERE( 'ctsk_key = '.$DB->quote( $cjob_type ) );
}
if( $ctst_started )
{ // Started
$clog_statuses[] = 'started';
}
if( $ctst_warning )
{ // Warning
$clog_statuses[] = 'warning';
}
if( $ctst_timeout )
{ // Timed out
$clog_statuses[] = 'timeout';
}
if( $ctst_error )
{ // Error
$clog_statuses[] = 'error';
}
if( $ctst_imap_error )
{ // IMAP Error
$clog_statuses[] = 'imap_error';
}
if( $ctst_finished )
{ // Finished
$clog_statuses[] = 'finished';
}
if( $ctst_pending || ! empty( $clog_statuses ) )
{ // Filter by statuses:
$clog_statuses = empty( $clog_statuses ) ? array() : array( 'clog_status IN ( "'.implode( '", "', $clog_statuses ).'" )' );
if( $ctst_pending )
{ // Pending
$clog_statuses[] = 'clog_status IS NULL';
}
$SQL->WHERE_and( implode( ' OR ', $clog_statuses ) );
}
if( ! empty( $s ) )
{ // Filter by name
$SQL->WHERE_and( '( ( ctsk_name IS NULL AND task_name LIKE '.$DB->quote( '%'.$s.'%' ).' )
OR ( ctsk_name IS NOT NULL AND ctsk_name LIKE '.$DB->quote( '%'.$s.'%' ).' ) )' );
}
if( ! empty( $datestart ) )
{ // Filter by start date
$timestart_value = empty( $timestart ) ? '00:00:00' : $timestart;
$SQL->WHERE_and( '( ctsk_start_datetime >= '.$DB->quote( $datestart.' '.$timestart_value ).'
OR clog_realstart_datetime >= '.$DB->quote( $datestart.' '.$timestart_value ).' )' );
}
if( ! empty( $datestop ) )
{ // Filter by end date
$timestop_value = empty( $timestop ) ? '23:59:59' : $timestop;
$SQL->WHERE_and( '( ctsk_start_datetime <= '.$DB->quote( $datestop.' '.$timestop_value ).'
OR clog_realstop_datetime <= '.$DB->quote( $datestop.' '.$timestop_value ).' )' );
}
$SQL->ORDER_BY( '*, ctsk_ID' );
$Results = new Results( $SQL->get(), 'crontab_', '-D' );
$Results->title = T_('Scheduled jobs').get_manual_link('scheduled-jobs-list');
$Results->global_icon( T_('Refresh'), 'refresh', regenerate_url(), T_('Refresh'), 3, 4 );
if( check_user_perm( 'options', 'edit', false, NULL ) )
{ // Permission to edit settings:
$Results->global_icon( T_('Create a new scheduled job...'), 'new', regenerate_url( 'action,cjob_ID', 'action=new' ), T_('New job').' »', 3, 4, array( 'class' => 'action_icon btn-primary' ) );
}
/**
* Callback to add filters on top of the result set
*
* @param Form
*/
function filter_crontab( & $Form )
{
global $ctst_pending, $ctst_started, $ctst_warning, $ctst_timeout, $ctst_error, $ctst_imap_error, $ctst_finished, $cjob_type;
global $datestart, $timestart, $datestop, $timestop;
// Job statuses:
foreach( cron_statuses() as $status_key => $status_title )
{
$Form->checkbox( 'ctst_status[]', ${'ctst_'.$status_key}, $status_title, '', '', $status_key );
}
// Job types:
$cron_jobs_names = array_merge( array(
'' => T_('All') ),
get_cron_jobs_config( 'name' )
);
$Form->select_input_array( 'cjob_type', $cjob_type, $cron_jobs_names, T_('Job type') );
// New line separator
echo '<div class="clear"></div>';
// Search:
$Form->text( 's', get_param( 's' ), 20, T_('Search'), '', 255 );
// Date/time filters:
$Form->date_input( 'datestartinput', $datestart, T_('Start Date'), array( 'add_date_format_note' => true ) );
echo T_('at').' ';
$Form->time_input( 'timestart', ' '.$timestart, '' );
$Form->date_input( 'datestopinput', $datestop, T_('End Date'), array( 'add_date_format_note' => true ) );
echo T_('at').' ';
$Form->time_input( 'timestop', ' '.$timestop, '' );
}
$Results->filter_area = array(
'callback' => 'filter_crontab',
'url_ignore' => 'results_crontab_page,ctst_pending,ctst_started,ctst_timeout,ctst_error,ctst_finished', // ignor epage param and checkboxes
);
$Results->register_filter_preset( 'all', T_('All'), '?ctrl=crontab&ctst_status[]=pending&ctst_status[]=started&ctst_status[]=warning&ctst_status[]=timeout&ctst_status[]=error&ctst_status[]=imap_error&ctst_status[]=finished&cjob_type=' );
$Results->register_filter_preset( 'schedule', T_('Schedule'), '?ctrl=crontab&ctst_status[]=pending&ctst_status[]=started&ctst_status[]=warning&ctst_status[]=timeout&ctst_status[]=error&ctst_status[]=imap_error&cjob_type=' );
$Results->register_filter_preset( 'finished', T_('Finished'), '?ctrl=crontab&ctst_status[]=finished&cjob_type=' );
$Results->register_filter_preset( 'attention', T_('Attention'), '?ctrl=crontab&ctst_status[]=warning&ctst_status[]=timeout&ctst_status[]=error&ctst_status[]=imap_error&cjob_type=' );
$Results->cols[] = array(
'th' => T_('ID'),
'order' => 'ctsk_ID',
'th_class' => 'shrinkwrap',
'td_class' => 'shrinkwrap',
'td' => '$ctsk_ID$'
);
$Results->cols[] = array(
'th' => T_('Planned at'),
'order' => 'ctsk_start_datetime',
'td_class' => 'shrinkwrap',
'td' => '%mysql2localedatetime_spans( #ctsk_start_datetime# )%',
);
$Results->cols[] = array(
'th' => T_('Name'),
'order' => 'final_name',
'td' => '<a href="%regenerate_url(\'action,cjob_ID\',\'action=view&cjob_ID=$ctsk_ID$\')%">%cron_job_name( #ctsk_key#, #ctsk_name#, #ctsk_params# )%</a>%cron_job_manual_link( #ctsk_key# )%',
);
$Results->cols[] = array(
'th' => T_('# of actions'),
'order' => 'clog_actions_num',
'td' => '$clog_actions_num$',
'default_dir' => 'D',
'th_class' => 'shrinkwrap',
'td_class' => 'right',
);
$Results->cols[] = array(
'th' => T_('Status'),
'order' => 'status',
'td_class' => 'shrinkwrap',
'td' => '%cron_status_title( "#status#" )%',
'extra' => array ( 'style' => 'background-color: %cron_status_color( "#status#" )%;', 'format_to_output' => false )
);
/**
* Get a title for cron execution time
*
* @param integer Seconds
* @return string
*/
function crontab_duration( $seconds )
{
if( $seconds == -1 )
{ // This crontab is pending or timed out, No duration time is available
return T_('none');
}
else
{ // Inform about duration in seconds
return sprintf( T_('%s seconds'), $seconds );
}
}
$Results->cols[] = array(
'th' => T_('Duration'),
'order' => 'duration',
'default_dir' => 'D',
'th_class' => 'shrinkwrap',
'td_class' => 'right nowrap',
'td' => '%crontab_duration( #duration# )%',
);
/**
* Get a title for cron execution time
*
* @param integer Repeat every X seconds
* @param integer Variation in seconds
* @return string
*/
function crontab_repeat( $ctsk_repeat_after, $ctsk_repeat_variation, $ctsk_key )
{
if( $ctsk_repeat_after > 0 )
{ // Display a repeat period with variation:
return seconds_to_period( $ctsk_repeat_after ).' ± '
.( $ctsk_key == 'poll-antispam-blacklist'
? T_('Auto')
: seconds_to_period( $ctsk_repeat_variation ) );
}
else
{ // If cron job is not repeated:
return '-';
}
}
$Results->cols[] = array(
'th' => T_('Repeat'),
'order' => 'ctsk_repeat_after',
'td_class' => 'shrinkwrap',
'td' => '%crontab_repeat( #ctsk_repeat_after#, #ctsk_repeat_variation#, #ctsk_key# )%',
);
function crontab_actions( $ctsk_ID, $status )
{
global $admin_url;
$col = '';
if( check_user_perm( 'options', 'edit', false, NULL ) )
{ // User can edit options:
if( $status == 'pending' )
{ // Icon for edit action
$col .= action_icon( T_('Edit this job'), 'edit', $admin_url.'?ctrl=crontab&action=edit&ctsk_ID='.$ctsk_ID );
}
elseif( $status == 'error' )
{ // Icon for copy action
$col .= action_icon( T_('Duplicate this job'), 'copy', $admin_url.'?ctrl=crontab&action=copy&ctsk_ID='.$ctsk_ID );
}
if( $status != 'started' )
{ // Icon for delete action
$col .= action_icon( T_('Delete this job!'), 'delete',
regenerate_url( 'action', 'ctsk_ID='.$ctsk_ID.'&action=delete&'.url_crumb('crontask') ) );
}
}
return $col;
}
$Results->cols[] = array(
'th' => T_('Actions'),
'td_class' => 'shrinkwrap',
'td' => '%crontab_actions( #ctsk_ID#, #status# )%',
);
// Display results :
$Results->display();
global $cron_url;
echo '<p>[<a href="'.$cron_url.'cron_exec.php" onclick="return pop_up_window( \''.$cron_url.'cron_exec.php\', \'evo_cron\' )" target="evo_cron">'.T_('Execute pending jobs in a popup window now!').'</a>]</p>';
?>