<?php
/**
* This file implements the UI controller for browsing the automations.
*
* This file is part of the b2evolution/evocms project - {@link http://b2evolution.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.' );
load_funcs( 'automations/model/_automation.funcs.php' );
load_class( 'automations/model/_automation.class.php', 'Automation' );
load_class( 'automations/model/_automationstep.class.php', 'AutomationStep' );
// Check permission:
check_user_perm( 'admin', 'normal', true );
check_user_perm( 'options', 'view', true );
param_action( '', true );
param( 'display_mode', 'string', 'normal' );
param( 'tab', 'string', 'settings', true );
if( param( 'autm_ID', 'integer', '', true ) )
{ // Load Automation object:
$AutomationCache = & get_AutomationCache();
if( ( $edited_Automation = & $AutomationCache->get_by_ID( $autm_ID, false ) ) === false )
{ // We could not find the automation to edit:
unset( $edited_Automation );
forget_param( 'autm_ID' );
$action = '';
$Messages->add( sprintf( TB_('Requested «%s» object does not exist any longer.'), TB_('Automation') ), 'error' );
}
}
if( param( 'step_ID', 'integer', '', true ) )
{ // Load AutomationStep object:
$AutomationStepCache = & get_AutomationStepCache();
if( ( $edited_AutomationStep = & $AutomationStepCache->get_by_ID( $step_ID, false ) ) === false )
{ // We could not find the automation step to edit:
unset( $edited_AutomationStep );
forget_param( 'autm_ID' );
$action = '';
$Messages->add( sprintf( TB_('Requested «%s» object does not exist any longer.'), TB_('Automation step') ), 'error' );
}
}
switch( $action )
{
case 'new':
// New Automation form:
// Check permission:
check_user_perm( 'options', 'edit', true );
// Create object of new Automation:
$edited_Automation = new Automation();
break;
case 'edit':
case 'edit_step':
case 'copy_step':
// Edit Automation/Step forms:
// Check permission:
check_user_perm( 'options', 'edit', true );
if( $action == 'copy_step' )
{ // Clear an order of the duplicating step in order to set this automatically right below current one:
$edited_AutomationStep->set( 'order', '' );
}
if( ( $action == 'edit_step' || $action == 'copy_step' ) && ! $edited_AutomationStep->can_be_modified() )
{ // If step cannot be modified currently
$Messages->add( TB_('You must pause the automation before changing step.'), 'warning' );
}
break;
case 'new_step':
// New Automation Step form:
// Check permission:
check_user_perm( 'options', 'edit', true );
// Create object of new Automation:
$edited_AutomationStep = new AutomationStep();
$edited_AutomationStep->set( 'autm_ID', $autm_ID );
if( ! $edited_AutomationStep->can_be_modified() )
{ // If step cannot be modified currently
$Messages->add( TB_('You must pause the automation before creating new step.'), 'warning' );
}
break;
case 'create':
// Create new Automation:
$edited_Automation = new Automation();
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automation' );
// Check that current user has permission to create automations:
check_user_perm( 'options', 'edit', true );
// load data from request
if( $edited_Automation->load_from_Request() )
{ // We could load data from form without errors:
// Insert in DB:
if( $edited_Automation->dbinsert() )
{
$Messages->add( TB_('New automation has been created.'), 'success' );
// Create default step automatically:
$default_AutomationStep = new AutomationStep();
$default_AutomationStep->set( 'autm_ID', $edited_Automation->ID );
$default_AutomationStep->set( 'order', '1' );
$default_AutomationStep->set( 'type', 'notify_owner' );
$default_AutomationStep->set( 'info', '$login$ has ENTERED automation $automation_name$ (ID: $automation_ID$)'."\n\n".'Step $step_number$ (ID: $step_ID$)' );
$default_AutomationStep->set( 'yes_next_step_ID', 0 ); // Continue
$default_AutomationStep->set( 'yes_next_step_delay', 86400 ); // 1 day
$default_AutomationStep->set( 'error_next_step_ID', 1 ); // Loop
$default_AutomationStep->set( 'error_next_step_delay', 14400 ); // 4 hours
$default_AutomationStep->set_label();
$default_AutomationStep->dbinsert( false/* Insert step even when automation is not paused */ );
}
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations', 303 ); // Will EXIT
// We have EXITed already at this point!!
}
$action = 'new';
break;
case 'update':
// Update Automation:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automation' );
// Check that current user has permission to edit automations:
check_user_perm( 'options', 'edit', true );
// Make sure we got an autm_ID:
param( 'autm_ID', 'integer', true );
// load data from request:
if( $edited_Automation->load_from_Request() )
{ // We could load data from form without errors:
// Update automation in DB:
$edited_Automation->dbupdate();
$Messages->add( TB_('Automation has been updated.'), 'success' );
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations', 303 ); // Will EXIT
// We have EXITed already at this point!!
}
$action = 'edit';
break;
case 'delete':
// Delete Automation:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automation' );
// Check permission:
check_user_perm( 'options', 'edit', true );
// Make sure we got an autm_ID:
param( 'autm_ID', 'integer', true );
if( param( 'confirm', 'integer', 0 ) )
{ // Delete from DB if confirmed:
$msg = sprintf( TB_('The automation "%s" has been deleted.'), $edited_Automation->dget( 'name' ) );
$edited_Automation->dbdelete();
unset( $edited_Automation );
forget_param( 'autm_ID' );
$Messages->add( $msg, 'success' );
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations', 303 ); // Will EXIT
// We have EXITed already at this point!!
}
else
{ // Check for restrictions if not confirmed yet:
if( ! $edited_Automation->check_delete( sprintf( TB_('Cannot delete automation "%s"'), $edited_Automation->dget( 'name' ) ) ) )
{ // There are restrictions:
$action = 'view';
}
}
break;
case 'status_paused':
case 'status_active':
// Toggle Automation status:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automation' );
// Check that current user has permission to edit automations:
check_user_perm( 'options', 'edit', true );
// Make sure we got an autm_ID:
param( 'autm_ID', 'integer', true );
param( 'enlt_ID', 'integer', NULL );
// Change automation status depending on action:
$edited_Automation->set( 'status', ( $action == 'status_paused' ? 'paused' : 'active' ) );
// Update automation in DB:
if( $edited_Automation->dbupdate() )
{
$Messages->add( ( $action == 'status_paused'
? TB_('Automation has been paused.')
: TB_('Automation has been activated.')
), 'success' );
// We want to highlight the moved Step on next list display:
$Session->set( 'fadeout_array', array( 'autm_ID' => array( $edited_Automation->ID ) ) );
}
// Set a redirect to page back where the status has been changes:
if( $enlt_ID > 0 )
{ // A list of automations on the edited List page:
$redirect_to = $admin_url.'?ctrl=newsletters&tab=automations&action=edit&enlt_ID='.$enlt_ID;
}
elseif( $tab == 'steps' || $tab == 'diagram' )
{ // Tab "Steps" of the edited Automation page:
$redirect_to = $admin_url.'?ctrl=automations&action=edit&tab='.$tab.'&autm_ID='.$edited_Automation->ID;
}
else
{ // A list of all automations:
$redirect_to = $admin_url.'?ctrl=automations';
}
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $redirect_to, 303 ); // Will EXIT
// We have EXITed already at this point!!
break;
case 'requeue':
// Requeue Automation for finished steps:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automation' );
// Check that current user has permission to edit automations:
check_user_perm( 'options', 'edit', true );
// Make sure we got IDs:
param( 'autm_ID', 'integer', true );
param( 'target_step_ID', 'integer', true );
// Additional options to requeue a specific step or user:
param( 'source_step_ID', 'integer', NULL );
param( 'source_user_ID', 'integer', NULL );
if( $source_user_ID > 0 )
{ // Requeue only one specific user:
$requeue_sql_where = 'aust_user_ID = '.$DB->quote( $source_user_ID );
}
elseif( $source_step_ID > 0 )
{ // Requeue a specific step:
$requeue_sql_where = 'aust_next_step_ID = '.$DB->quote( $source_step_ID );
}
else
{ // Requeue all finished steps:
$requeue_sql_where = 'aust_next_step_ID IS NULL';
}
$requeued_users_num = intval( $DB->query( 'UPDATE T_automation__user_state
SET aust_next_step_ID = '.$DB->quote( $target_step_ID ).',
aust_next_exec_ts = '.$DB->quote( date2mysql( $servertimenow ) ).'
WHERE aust_autm_ID = '.$edited_Automation->ID.'
AND '.$requeue_sql_where ) );
if( $requeued_users_num )
{
$Messages->add( sprintf( TB_('Automation has been requeued for %d users.'), $requeued_users_num ), 'success' );
// We want to highlight the reduced Step on list display:
$Session->set( 'fadeout_array', array( 'aust_user_ID' => array( $source_user_ID ) ) );
}
// Redirect so that a reload doesn't write to the DB twice:
if( $source_step_ID > 0 && $source_user_ID > 0 )
{ // Redirect to an edit page of the requeued step:
header_redirect( $admin_url.'?ctrl=automations&action=edit_step&step_ID='.$target_step_ID, 303 ); // Will EXIT
}
elseif( $source_user_ID > 0 )
{ // Redirect to a page of Automation users:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab=users&autm_ID='.$edited_Automation->ID, 303 ); // Will EXIT
}
else
{ // Redirect to a page of Automation steps:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab=steps&autm_ID='.$edited_Automation->ID, 303 ); // Will EXIT
}
// We have EXITed already at this point!!
break;
case 'move_step_up':
case 'move_step_down':
// Move up/down Automation Step:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automationstep' );
// Check that current user has permission to create automation steps:
check_user_perm( 'options', 'edit', true );
if( ! $edited_AutomationStep->can_be_modified() )
{ // If step cannot be modified currently
$Messages->add( TB_('You must pause the automation before changing step.'), 'error' );
$action = 'edit'; // To keep same opened page
// We want to highlight the Step:
$Session->set( 'fadeout_array', array( 'step_ID' => array( $edited_AutomationStep->ID ) ) );
break;
}
// Make sure we got an step_ID:
param( 'step_ID', 'integer', true );
if( $action == 'move_step_up' )
{ // Set variables for "move up" action
$order_condition = '<';
$order_direction = 'DESC';
}
else
{ // move down
$order_condition = '>';
$order_direction = 'ASC';
}
$DB->begin( 'SERIALIZABLE' );
// Get near step, We should swap the order with this step:
$SQL = new SQL( 'Get near Step to reorder it with moved Step #'.$edited_AutomationStep->ID );
$SQL->SELECT( 'step_ID, step_order' );
$SQL->FROM( 'T_automation__step' );
$SQL->WHERE( 'step_autm_ID = '.$edited_AutomationStep->get( 'autm_ID' ) );
$SQL->WHERE_and( 'step_order '.$order_condition.' '.$edited_AutomationStep->get( 'order' ) );
$SQL->ORDER_BY( 'step_order '.$order_direction );
$SQL->LIMIT( 1 );
$swaped_step = $DB->get_row( $SQL );
if( empty( $swaped_step ) )
{ // Current step is first or last in group, no change ordering:
$DB->commit(); // This is required only to not leave open transaction
$action = 'edit'; // To keep same opened page
break;
}
// Switch orders of the steps:
$result = true;
for( $i = 0; $i < 2; $i++ )
{ // We can swap orders only in two SQL queries to avoid error of duplicate entry because of step_order is unique index per Automation:
// By first SQL query we update the step orders to reserved values which cannot be assigned on edit form by user:
$step_order_1 = ( $i == 0 ? -2147483647 : $swaped_step->step_order );
$step_order_2 = ( $i == 0 ? -2147483648 : $edited_AutomationStep->get( 'order' ) );
$result = ( $result !== false ) && $DB->query( 'UPDATE T_automation__step
SET step_order = CASE
WHEN step_ID = '.$edited_AutomationStep->ID.' THEN '.$step_order_1.'
WHEN step_ID = '.$swaped_step->step_ID.' THEN '.$step_order_2.'
ELSE step_order
END
WHERE step_ID IN ( '.$edited_AutomationStep->ID.', '.$swaped_step->step_ID.' )' );
}
if( $result !== false )
{ // Update was successful:
$DB->commit();
$Messages->add( TB_('Order has been changed.'), 'success' );
// We want to highlight the moved Step on next list display:
$Session->set( 'fadeout_array', array( 'step_ID' => array( $edited_AutomationStep->ID ) ) );
}
else
{ // Couldn't update successfully, probably because of concurrent modification
// Note: In this case we may try again to execute the same queries.
$DB->rollback();
// The message is not localized because it may appear very rarely
$Messages->add( 'Order could not be changed. Please try again.', 'error' );
}
$action = 'edit'; // To keep same opened page
break;
case 'create_step':
// Create new Automation Step:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automationstep' );
// Check that current user has permission to create automation steps:
check_user_perm( 'options', 'edit', true );
$edited_AutomationStep = new AutomationStep();
$entered_step_order = param( 'step_order', 'integer', NULL );
// load data from request
if( $edited_AutomationStep->load_from_Request() &&
$edited_AutomationStep->pause_automation() )
{ // We could load data from form without errors and automation can be paused:
// Insert in DB:
$edited_AutomationStep->dbinsert();
$Messages->add( TB_('New automation step has been created.'), 'success' );
// We want to highlight the moved Step on next list display:
$Session->set( 'fadeout_array', array( 'step_ID' => array( $edited_AutomationStep->ID ) ) );
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab='.$tab.'&autm_ID='.$edited_AutomationStep->get( 'autm_ID' ), 303 ); // Will EXIT
// We have EXITed already at this point!!
}
$action = 'new_step';
$edited_AutomationStep->set( 'order', $entered_step_order );
break;
case 'duplicate_step':
// Duplicate Automation Step:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automationstep' );
// Check that current user has permission to create automation steps:
check_user_perm( 'options', 'edit', true );
$duplicated_step_ID = $edited_AutomationStep->ID;
$duplicated_step_order = $edited_AutomationStep->get( 'order' );
$edited_AutomationStep = new AutomationStep();
$entered_step_order = param( 'step_order', 'integer', NULL );
// Load data from request:
if( $edited_AutomationStep->load_from_Request() &&
$edited_AutomationStep->pause_automation() )
{ // We could load data from form without errors and automation can be paused:
// Insert in DB:
$edited_AutomationStep->dbinsert();
if( empty( $entered_step_order ) )
{ // Move the new created step right after the duplicated step:
$SQL = new SQL( 'Get steps of automation #'.$edited_AutomationStep->get( 'autm_ID' ).' before insert new step right below duplicated one' );
$SQL->SELECT( 'step_order' );
$SQL->FROM( 'T_automation__step' );
$SQL->WHERE( 'step_autm_ID = '.$DB->quote( $edited_AutomationStep->get( 'autm_ID' ) ) );
$SQL->WHERE_and( 'step_order > '.$DB->quote( $duplicated_step_order ) );
$SQL->ORDER_BY( 'step_order' );
$steps = $DB->get_col( $SQL );
if( ! empty( $steps ) && $steps[0] == $duplicated_step_order + 1 )
{ // If the duplicated step is NOT last AND the next order number is NOT free
// then we should shift all next steps down and use next order for new created step:
$DB->query( 'UPDATE T_automation__step
SET step_order = step_order + 1
WHERE step_autm_ID = '.$DB->quote( $edited_AutomationStep->get( 'autm_ID' ) ).'
AND step_order > '.$DB->quote( $duplicated_step_order ).'
ORDER BY step_order DESC' );
$DB->query( 'UPDATE T_automation__step
SET step_order = '.( $duplicated_step_order + 1 ).'
WHERE step_ID = '.$DB->quote( $edited_AutomationStep->ID ) );
}
}
$Messages->add( TB_('Automation step has been duplicated.'), 'success' );
// We want to highlight the moved Step on next list display:
$Session->set( 'fadeout_array', array( 'step_ID' => array( $edited_AutomationStep->ID ) ) );
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab=steps&autm_ID='.$edited_AutomationStep->get( 'autm_ID' ), 303 ); // Will EXIT
// We have EXITed already at this point!!
}
// If errors, Display the step form again to fix them:
$action = 'copy_step';
$edited_AutomationStep->ID = $duplicated_step_ID;
$edited_AutomationStep->set( 'order', $entered_step_order );
break;
case 'update_step':
// Update Automation Step:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automationstep' );
// Check that current user has permission to edit automation steps:
check_user_perm( 'options', 'edit', true );
// Make sure we got an step_ID:
param( 'step_ID', 'integer', true );
// load data from request:
if( $edited_AutomationStep->load_from_Request() &&
$edited_AutomationStep->pause_automation() )
{ // We could load data from form without errors and automation can be paused:
// Update automation step in DB:
$edited_AutomationStep->dbupdate();
$Messages->add( TB_('Automation step has been updated.'), 'success' );
if( $tab != 'diagram' )
{ // We want to highlight the moved Step on next list display:
$Session->set( 'fadeout_array', array( 'step_ID' => array( $edited_AutomationStep->ID ) ) );
}
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab='.$tab.'&autm_ID='.$edited_AutomationStep->get( 'autm_ID' ), 303 ); // Will EXIT
// We have EXITed already at this point!!
}
$action = 'edit_step';
break;
case 'update_step_position':
// Update step position on automation diagram:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automationstep' );
// Check permission:
check_user_perm( 'options', 'edit', true );
param( 'pos', 'array:integer' );
if( count( $pos ) != 2 )
{ // Position array must contains 2 values: row|x and column|y:
debug_die( 'Wrong step position!' );
}
// Update step position:
$edited_AutomationStep->set( 'diagram', implode( ':', $pos ) );
$edited_AutomationStep->dbupdate();
// Exit here because we don't need UI for this AJAX action:
exit;
case 'update_step_connection':
// Update steps connection on automation diagram:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automationstep' );
// Check permission:
check_user_perm( 'options', 'edit', true );
param( 'connection_type', 'string', true );
if( ! in_array( $connection_type, array( 'yes', 'no', 'error' ) ) )
{ // Wrong connection type:
debug_die( 'Wrong step connection type!' );
}
// Set correct ID for next/target Step:
param( 'target_step_ID', 'integer' );
if( $target_step_ID > 0 )
{ // If step has been connected with target Step:
$target_AutomationStep = & $AutomationStepCache->get_by_ID( $target_step_ID );
if( $edited_AutomationStep->get_next_ordered_step_ID() == $target_AutomationStep->ID )
{ // If target Step is the next ordered Step we should use an option "Continue":
$target_step_ID = 0;
}
else
{ // Some other next target Step:
$target_step_ID = $target_AutomationStep->ID;
}
}
else
{ // if step has been disconnected:
$target_step_ID = -1;
}
// Update step connection or disconnection between the requested Steps:
$edited_AutomationStep->set( $connection_type.'_next_step_ID', $target_step_ID, true );
$edited_AutomationStep->dbupdate();
// Exit here because we don't need UI for this AJAX action:
exit;
case 'reset_diagram':
// Reset steps positions on automation diagram to default positions:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automationstep' );
// Check permission:
check_user_perm( 'options', 'edit', true );
// Reset positions of all steps of the edited Automation:
$DB->query( 'UPDATE T_automation__step
SET step_diagram = NULL
WHERE step_autm_ID = '.$DB->quote( $edited_Automation->ID ) );
$Messages->add( TB_('Diagram layout has been reset.'), 'success' );
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab=diagram&autm_ID='.$edited_Automation->ID, 303 ); // Will EXIT
// We have EXITed already at this point!!
break;
case 'delete_step':
// Delete Automation Step:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automationstep' );
// Check permission:
check_user_perm( 'options', 'edit', true );
// Make sure we got an autm_ID:
param( 'autm_ID', 'integer', true );
if( ! $edited_AutomationStep->can_be_modified() )
{ // If step cannot be modified currently
$Messages->add( TB_('You must pause the automation before deleting step.'), 'error' );
}
elseif( $edited_AutomationStep->dbdelete() )
{
$Messages->add( TB_('Automation step has been deleted.'), 'success' );
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab=steps&autm_ID='.$edited_AutomationStep->get( 'autm_ID' ), 303 ); // Will EXIT
// We have EXITed already at this point!!
}
// Display the same edit automation page with steps list because step cannot be deleted by some restriciton:
$action = 'edit';
// We want to highlight the Step which cannot be deleted on next list display:
$Session->set( 'fadeout_array', array( 'step_ID' => array( $edited_AutomationStep->ID ) ) );
break;
case 'reduce_step_delay':
// Reduce step delay for a specific user:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automation' );
// Check permission:
check_user_perm( 'options', 'edit', true );
param( 'user_ID', 'integer', true );
$UserCache = & get_UserCache();
$step_User = & $UserCache->get_by_ID( $user_ID );
// Change execution time to NOW:
$r = $DB->query( 'UPDATE T_automation__user_state
SET aust_next_exec_ts = '.$DB->quote( date2mysql( $servertimenow ) ).'
WHERE aust_autm_ID = '.$edited_Automation->ID.'
AND aust_user_ID = '.$step_User->ID.'
AND aust_next_step_ID IS NOT NULL' ); // exclude finished steps
if( $r )
{ // Display a result message if user really has been affected:
$Messages->add( sprintf( TB_('Execution time has been changed to now for user %s.'), '"'.$step_User->dget( 'login' ).'"' ), 'success' );
// We want to highlight the reduced Step on list display:
$Session->set( 'fadeout_array', array( 'aust_user_ID' => array( $step_User->ID ) ) );
}
// Redirect so that a reload doesn't write to the DB twice:
if( isset( $edited_AutomationStep ) )
{ // Redirect to a page of Step edit form:
header_redirect( $admin_url.'?ctrl=automations&action=edit_step&step_ID='.$edited_AutomationStep->ID, 303 ); // Will EXIT
}
else
{ // Redirect to a page of Automation users:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab=users&autm_ID='.$edited_Automation->ID, 303 ); // Will EXIT
}
// We have EXITed already at this point!!
break;
case 'stop_user':
// Stop automation for a specific user:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automation' );
// Check permission:
check_user_perm( 'options', 'edit', true );
param( 'user_ID', 'integer', true );
$UserCache = & get_UserCache();
$step_User = & $UserCache->get_by_ID( $user_ID );
// Change execution time to NOW:
$r = $DB->query( 'UPDATE T_automation__user_state
SET aust_next_step_ID = NULL,
aust_next_exec_ts = NULL
WHERE aust_autm_ID = '.$edited_Automation->ID.'
AND aust_user_ID = '.$step_User->ID );
if( $r )
{ // Display a result message if user really has been affected:
$Messages->add( sprintf( TB_('Automation has been stopped for user %s.'), '"'.$step_User->dget( 'login' ).'"' ), 'success' );
// We want to highlight the reduced Step on list display:
$Session->set( 'fadeout_array', array( 'aust_user_ID' => array( $step_User->ID ) ) );
}
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab=users&autm_ID='.$edited_Automation->ID, 303 ); // Will EXIT
// We have EXITed already at this point!!
break;
case 'remove_user':
// Remove a specific user from automation:
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'automation' );
// Check permission:
check_user_perm( 'options', 'edit', true );
param( 'user_ID', 'integer', true );
$UserCache = & get_UserCache();
$step_User = & $UserCache->get_by_ID( $user_ID );
// Change execution time to NOW:
$r = $DB->query( 'DELETE FROM T_automation__user_state
WHERE aust_autm_ID = '.$edited_Automation->ID.'
AND aust_user_ID = '.$step_User->ID );
if( $r )
{ // Display a result message if user really has been affected:
$Messages->add( sprintf( TB_('User %s has been removed from this automation.'), '"'.$step_User->dget( 'login' ).'"' ), 'success' );
}
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( $admin_url.'?ctrl=automations&action=edit&tab=users&autm_ID='.$edited_Automation->ID, 303 ); // Will EXIT
// We have EXITed already at this point!!
break;
}
$AdminUI->breadcrumbpath_init( false );
$AdminUI->breadcrumbpath_add( TB_('Emails'), $admin_url.'?ctrl=campaigns' );
$AdminUI->breadcrumbpath_add( TB_('Automations'), $admin_url.'?ctrl=automations' );
$AdminUI->display_breadcrumbpath_init();
$AdminUI->set_path( 'email', 'automations' );
// Set an url for manual page:
switch( $action )
{
case 'new':
case 'edit':
case 'delete':
case 'new_step':
case 'edit_step':
case 'copy_step':
$AdminUI->display_breadcrumbpath_add( TB_('Automations'), $admin_url.'?ctrl=automations' );
if( $action != 'new' )
{ // Add menu level 3 entries:
if( empty( $edited_Automation ) )
{ // Get Automation of the edited Step:
$edited_Automation = & $edited_AutomationStep->get_Automation();
set_param( 'tab', $display_mode == 'js' ? 'diagram' : 'steps' );
}
$AdminUI->add_menu_entries( array( 'email', 'automations' ), array(
'settings' => array(
'text' => TB_('Settings'),
'href' => $admin_url.'?ctrl=automations&action=edit&tab=settings&autm_ID='.$edited_Automation->ID ),
'steps' => array(
'text' => TB_('Steps'),
'href' => $admin_url.'?ctrl=automations&action=edit&tab=steps&autm_ID='.$edited_Automation->ID ),
'diagram' => array(
'text' => TB_('Diagram view'),
'href' => $admin_url.'?ctrl=automations&action=edit&tab=diagram&autm_ID='.$edited_Automation->ID ),
'users' => array(
'text' => TB_('Users'),
'href' => $admin_url.'?ctrl=automations&action=edit&tab=users&autm_ID='.$edited_Automation->ID ),
) );
if( in_array( $action, array( 'edit', 'delete' ) ) )
{
$AdminUI->display_breadcrumbpath_add( $edited_Automation->dget( 'name' ) );
}
}
else
{ // Don't add level 3 entries for new creating automation, and force tab only for settings:
set_param( 'tab', 'settings' );
$AdminUI->display_breadcrumbpath_add( TB_('New automation') );
}
switch( $tab )
{
case 'steps':
$AdminUI->set_page_manual_link( in_array( $action, array( 'new_step', 'edit_step', 'copy_step' ) ) ? 'automation-step-details' : 'automation-steps' );
$AdminUI->set_path( 'email', 'automations', 'steps' );
break;
case 'users':
$AdminUI->set_page_manual_link( 'automation-users-queued' );
$AdminUI->set_path( 'email', 'automations', 'users' );
break;
case 'diagram':
$AdminUI->set_page_manual_link( 'automation-diagram-view' );
$AdminUI->set_path( 'email', 'automations', 'diagram' );
// Load files to draw diagram by plugin jsPlumb:
require_js_defer( 'ext:jquery/jsplumb/js/jsplumb.min.js', 'rsc_url' );
require_css( 'ext:jquery/jsplumb/css/jsplumbtoolkit-defaults.css', 'rsc_url' );
require_css( 'ext:jquery/jsplumb/css/jsplumbtoolkit-b2evo.css', 'rsc_url' );
require_js_defer( 'ext:jquery/panzoom/js/jquery.panzoom.min.js', 'rsc_url' );
break;
default:
case 'settings':
$AdminUI->set_page_manual_link( 'automation-form-settings' );
$AdminUI->set_path( 'email', 'automations', 'settings' );
// Init JS to autcomplete the user logins
init_autocomplete_login_js( 'rsc_url', $AdminUI->get_template( 'autocomplete_plugin' ) );
}
if( $action == 'edit' )
{ // Initialize Hotkeys
init_hotkeys_js();
}
break;
default:
$AdminUI->display_breadcrumbpath_add( TB_('Automations') );
$AdminUI->set_page_manual_link( 'automations-list' );
break;
}
if( in_array( $action, array( 'new_step', 'edit_step', 'copy_step' ) ) )
{ // Load jQuery QueryBuilder plugin files:
$step_Automation = & $edited_AutomationStep->get_Automation();
init_querybuilder_js( 'rsc_url' );
// Initialize Hotkeys:
init_hotkeys_js();
$AdminUI->display_breadcrumbpath_add( $edited_Automation->dget( 'name' ), $admin_url.'?ctrl=automations&action=edit&autm_ID='.$step_Automation->ID );
if( $action == 'new_step' )
{
$AdminUI->display_breadcrumbpath_add( TB_('New step') );
}
elseif( $action == 'copy_step' )
{
$AdminUI->display_breadcrumbpath_add( TB_('Duplicate step').' #'.get_param( 'step_ID' ) );
}
else
{
$AdminUI->display_breadcrumbpath_add( TB_('Step').' #'.$edited_AutomationStep->dget( 'order' ) );
}
}
if( $tab == 'diagram' )
{ // Load jQuery QueryBuilder plugin files for edit step form in modal window:
init_querybuilder_js( 'rsc_url' );
}
if( $display_mode != 'js' )
{
// Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)
$AdminUI->disp_html_head();
// Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)
$AdminUI->disp_body_top();
// Begin payload block:
$AdminUI->disp_payload_begin();
evo_flush();
}
switch( $action )
{
case 'delete':
// We need to ask for confirmation:
$edited_Automation->confirm_delete(
sprintf( TB_('Delete automation "%s"?'), $edited_Automation->dget( 'name' ) ),
'automation', $action, get_memorized( 'action' ) );
/* no break */
case 'new':
case 'edit':
// Display a form of automation:
switch( $tab )
{
case 'steps':
$AdminUI->disp_view( 'automations/views/_automation_steps.view.php' );
break;
case 'users':
$AdminUI->disp_view( 'automations/views/_automation_users.view.php' );
break;
case 'diagram':
$AdminUI->disp_view( 'automations/views/_automation_diagram.view.php' );
break;
case 'settings':
default:
$AdminUI->disp_view( 'automations/views/_automation.form.php' );
}
break;
case 'requeue_form':
// Display a form to requeue automation:
$AdminUI->disp_view( 'automations/views/_automation_requeue.form.php' );
// Do not append Debuglog & Debug JSlog to response!
$debug = false;
$debug_jslog = false;
break;
case 'new_step':
case 'edit_step':
case 'copy_step':
// Display a form of automation step:
$AdminUI->disp_view( 'automations/views/_automation_step.form.php' );
break;
default:
// Display a list of automations:
$AdminUI->disp_view( 'automations/views/_automations.view.php' );
break;
}
if( $display_mode != 'js' )
{
// End payload block:
$AdminUI->disp_payload_end();
// Display body bottom, debug info and close </html>:
$AdminUI->disp_global_footer();
}
?>