| 1 |
<?php |
| 2 |
|
| 3 |
namespace AcyMailing\Controllers\Scenarios; |
| 4 |
|
| 5 |
use AcyMailing\Classes\ScenarioClass; |
| 6 |
use AcyMailing\Classes\ScenarioHistoryLineClass; |
| 7 |
use AcyMailing\Classes\ScenarioProcessClass; |
| 8 |
use AcyMailing\Classes\ScenarioQueueClass; |
| 9 |
use AcyMailing\Classes\ScenarioStepClass; |
| 10 |
use AcyMailing\Classes\UserClass; |
| 11 |
use AcyMailing\Helpers\PaginationHelper; |
| 12 |
use AcyMailing\Helpers\ScenarioHelper; |
| 13 |
use AcyMailing\Helpers\WorkflowHelper; |
| 14 |
|
| 15 |
trait Performance |
| 16 |
{ |
| 17 |
public function performances(): void |
| 18 |
{ |
| 19 |
acym_setVar('layout', 'performances'); |
| 20 |
acym_setVar('step', 'performances'); |
| 21 |
|
| 22 |
$data = []; |
| 23 |
|
| 24 |
$data['isPerformance'] = true; |
| 25 |
$data['workflowHelper'] = new WorkflowHelper(); |
| 26 |
$data['scenarioId'] = acym_getVar('int', 'scenarioId', 0); |
| 27 |
|
| 28 |
$this->prepareScenarioPerformance($data); |
| 29 |
|
| 30 |
if (empty($data['scenario'])) { |
| 31 |
$this->listing(); |
| 32 |
|
| 33 |
return; |
| 34 |
} |
| 35 |
|
| 36 |
$this->prepareStepsPerformance($data); |
| 37 |
|
| 38 |
$this->breadcrumb[$data['scenario']->name] = acym_completeLink('scenarios&task=edit&step=editScenario&scenarioId='.$data['scenario']->id); |
| 39 |
|
| 40 |
parent::display($data); |
| 41 |
} |
| 42 |
|
| 43 |
private function prepareScenarioPerformance(array &$data): void |
| 44 |
{ |
| 45 |
if (empty($data['scenarioId'])) { |
| 46 |
return; |
| 47 |
} |
| 48 |
|
| 49 |
$scenarioClass = new ScenarioClass(); |
| 50 |
$data['scenario'] = $scenarioClass->getOneById($data['scenarioId']); |
| 51 |
} |
| 52 |
|
| 53 |
private function prepareStepsPerformance(array &$data): void |
| 54 |
{ |
| 55 |
$scenarioStepClass = new ScenarioStepClass(); |
| 56 |
$scenarioProcessClass = new ScenarioProcessClass(); |
| 57 |
|
| 58 |
$steps = $scenarioStepClass->getAllByScenarioId($data['scenario']->id); |
| 59 |
$numberOfTrigger = $scenarioProcessClass->getNumberOfTriggerByScenarioId($data['scenario']->id); |
| 60 |
$numberOfProcessByStep = $scenarioStepClass->getNumberOfProcessByStepByScenarioId($data['scenario']->id); |
| 61 |
|
| 62 |
|
| 63 |
if (empty($steps)) { |
| 64 |
return; |
| 65 |
} |
| 66 |
|
| 67 |
$triggerNames = $this->getTriggerNames(); |
| 68 |
$conditionNames = $this->getConditionNames(); |
| 69 |
$actionsNames = $this->getActionNames(); |
| 70 |
|
| 71 |
$triggerName = ucfirst($triggerNames[$data['scenario']->trigger]); |
| 72 |
$chartNodes = [ |
| 73 |
$data['scenario']->id => [ |
| 74 |
'id' => $data['scenario']->id, |
| 75 |
'name' => 'Trigger '.$triggerNames[$data['scenario']->trigger], |
| 76 |
'value' => $this->createTooltip($triggerName), |
| 77 |
'scenarioId' => $data['scenario']->id, |
| 78 |
'type' => 'trigger', |
| 79 |
'stepId' => '', |
| 80 |
], |
| 81 |
]; |
| 82 |
$chartData = []; |
| 83 |
|
| 84 |
$scenarioHelper = new ScenarioHelper(); |
| 85 |
|
| 86 |
foreach ($steps as $step) { |
| 87 |
switch ($step->type) { |
| 88 |
case ScenarioClass::TYPE_CONDITION: |
| 89 |
$name = ucfirst($conditionNames[$scenarioHelper->getConditionValue($step)]); |
| 90 |
break; |
| 91 |
case ScenarioClass::TYPE_ACTION: |
| 92 |
$name = ucfirst($actionsNames[$scenarioHelper->getActionValue($step)]); |
| 93 |
break; |
| 94 |
case ScenarioClass::TYPE_DELAY: |
| 95 |
$name = acym_translation('ACYM_DELAY'); |
| 96 |
break; |
| 97 |
default: |
| 98 |
$name = ''; |
| 99 |
} |
| 100 |
|
| 101 |
$chartNodes[$step->id] = [ |
| 102 |
'id' => $step->id, |
| 103 |
'name' => $name, |
| 104 |
'value' => $this->createTooltip($name), |
| 105 |
'scenarioId' => $step->scenario_id, |
| 106 |
'type' => $step->type, |
| 107 |
'stepId' => $step->id, |
| 108 |
]; |
| 109 |
|
| 110 |
if (empty($step->previous_id)) { |
| 111 |
$from = $data['scenario']->id; |
| 112 |
$value = intval($numberOfTrigger); |
| 113 |
} else { |
| 114 |
$from = $step->previous_id; |
| 115 |
$value = empty($numberOfProcessByStep[$step->id]) ? 0 : intval($numberOfProcessByStep[$step->id]->count); |
| 116 |
} |
| 117 |
|
| 118 |
$chartData[] = [ |
| 119 |
'source' => $from, |
| 120 |
'target' => $step->id, |
| 121 |
'value' => $value, |
| 122 |
]; |
| 123 |
} |
| 124 |
|
| 125 |
$data['numberOfTrigger'] = $numberOfTrigger; |
| 126 |
$data['chartNodes'] = $chartNodes; |
| 127 |
$data['chartData'] = $chartData; |
| 128 |
} |
| 129 |
|
| 130 |
private function getTriggerNames(): array |
| 131 |
{ |
| 132 |
$defaultValues = []; |
| 133 |
$triggers = ['classic' => [], 'user' => []]; |
| 134 |
acym_trigger('onAcymDeclareTriggers', [&$triggers, &$defaultValues]); |
| 135 |
|
| 136 |
$triggerNames = []; |
| 137 |
foreach ($triggers['user'] as $key => $trigger) { |
| 138 |
$triggerNames[$key] = strtolower(acym_stripTags($trigger->name)); |
| 139 |
} |
| 140 |
|
| 141 |
return $triggerNames; |
| 142 |
} |
| 143 |
|
| 144 |
private function getConditionNames(): array |
| 145 |
{ |
| 146 |
$conditions = ['user' => [], 'classic' => []]; |
| 147 |
acym_trigger('onAcymDeclareConditions', [&$conditions]); |
| 148 |
|
| 149 |
$conditionNames = []; |
| 150 |
foreach ($conditions['user'] as $key => $condition) { |
| 151 |
$conditionNames[$key] = strtolower(acym_stripTags($condition->name)); |
| 152 |
} |
| 153 |
|
| 154 |
return $conditionNames; |
| 155 |
} |
| 156 |
|
| 157 |
private function getActionNames(): array |
| 158 |
{ |
| 159 |
$actions = []; |
| 160 |
acym_trigger('onAcymDeclareActionsScenario', [&$actions]); |
| 161 |
|
| 162 |
$actionNames = []; |
| 163 |
foreach ($actions as $key => $action) { |
| 164 |
$actionNames[$key] = strtolower(acym_stripTags($action->name)); |
| 165 |
} |
| 166 |
|
| 167 |
return $actionNames; |
| 168 |
} |
| 169 |
|
| 170 |
private function createTooltip(string $name): string |
| 171 |
{ |
| 172 |
ob_start(); |
| 173 |
include acym_getPartial('scenarios', 'performances_tooltip'); |
| 174 |
|
| 175 |
return ob_get_clean(); |
| 176 |
} |
| 177 |
|
| 178 |
public function getStepStats(): void |
| 179 |
{ |
| 180 |
$scenarioId = acym_getVar('int', 'scenarioId', 0); |
| 181 |
$stepId = acym_getVar('string', 'stepId', ''); |
| 182 |
$type = acym_getVar('string', 'type', ''); |
| 183 |
|
| 184 |
if (empty($scenarioId) || empty($type) || ($type !== 'trigger' && empty($stepId))) { |
| 185 |
acym_sendAjaxResponse(acym_translation('ACYM_AN_ERROR_OCCURRED'), [], false); |
| 186 |
} |
| 187 |
|
| 188 |
$scenarioClass = new ScenarioClass(); |
| 189 |
$scenario = $scenarioClass->getOneById($scenarioId); |
| 190 |
|
| 191 |
if (empty($scenario)) { |
| 192 |
acym_sendAjaxResponse(acym_translation('ACYM_AN_ERROR_OCCURRED'), [], false); |
| 193 |
} |
| 194 |
|
| 195 |
switch ($type) { |
| 196 |
case 'trigger': |
| 197 |
$html = $this->getTriggerHtml($scenarioId); |
| 198 |
break; |
| 199 |
case ScenarioClass::TYPE_CONDITION: |
| 200 |
case ScenarioClass::TYPE_ACTION: |
| 201 |
case ScenarioClass::TYPE_DELAY: |
| 202 |
$html = $this->getStepHtml($stepId, $type); |
| 203 |
break; |
| 204 |
default: |
| 205 |
$html = []; |
| 206 |
} |
| 207 |
|
| 208 |
if (empty($html)) { |
| 209 |
acym_sendAjaxResponse(acym_translation('ACYM_AN_ERROR_OCCURRED'), [], false); |
| 210 |
} |
| 211 |
|
| 212 |
acym_sendAjaxResponse('', ['content' => $html]); |
| 213 |
} |
| 214 |
|
| 215 |
private function getTriggerHtml(int $scenarioId): string |
| 216 |
{ |
| 217 |
$page = acym_getVar('int', 'page', 1); |
| 218 |
$search = acym_getVar('string', 'search', ''); |
| 219 |
$scenarioProcessClass = new ScenarioProcessClass(); |
| 220 |
|
| 221 |
$pagination = new PaginationHelper(); |
| 222 |
$elementsPerPage = $pagination->getListLimit(); |
| 223 |
|
| 224 |
$listingSettings = [ |
| 225 |
'scenarioId' => $scenarioId, |
| 226 |
'search' => $search, |
| 227 |
'offset' => ($page - 1) * $elementsPerPage, |
| 228 |
'elementsPerPage' => $elementsPerPage, |
| 229 |
]; |
| 230 |
|
| 231 |
$matchingElements = $scenarioProcessClass->getMatchingElements($listingSettings); |
| 232 |
|
| 233 |
$pagination->setStatus((int)$matchingElements['total']->total, $page, $listingSettings['elementsPerPage']); |
| 234 |
|
| 235 |
$data = [ |
| 236 |
'numberOfTrigger' => $scenarioProcessClass->getNumberOfTriggerByScenarioId($scenarioId), |
| 237 |
'usersProcess' => $matchingElements['elements'], |
| 238 |
'pagination' => $pagination, |
| 239 |
'search' => $search, |
| 240 |
'isEmpty' => empty($matchingElements['totalOverall']), |
| 241 |
'title' => acym_translation('ACYM_NUMBER_OF_TRIGGER'), |
| 242 |
]; |
| 243 |
|
| 244 |
ob_start(); |
| 245 |
include acym_getPartial('scenarios', 'performances_trigger'); |
| 246 |
|
| 247 |
return ob_get_clean(); |
| 248 |
} |
| 249 |
|
| 250 |
private function getStepHtml(string $stepId, string $type): string |
| 251 |
{ |
| 252 |
$page = acym_getVar('int', 'page', 1); |
| 253 |
$search = acym_getVar('string', 'search', ''); |
| 254 |
$pagination = new PaginationHelper(); |
| 255 |
$elementsPerPage = $pagination->getListLimit(); |
| 256 |
|
| 257 |
$listingSettings = [ |
| 258 |
'stepId' => $stepId, |
| 259 |
'search' => $search, |
| 260 |
'offset' => ($page - 1) * $elementsPerPage, |
| 261 |
'elementsPerPage' => $elementsPerPage, |
| 262 |
]; |
| 263 |
|
| 264 |
$scenarioHistoryLineClass = new ScenarioHistoryLineClass(); |
| 265 |
$matchingElements = $scenarioHistoryLineClass->getMatchingElements($listingSettings); |
| 266 |
|
| 267 |
$pagination->setStatus((int)$matchingElements['total']->total, $page, $listingSettings['elementsPerPage']); |
| 268 |
|
| 269 |
$data = [ |
| 270 |
'historyLines' => $matchingElements['elements'], |
| 271 |
'pagination' => $pagination, |
| 272 |
'search' => $search, |
| 273 |
'isEmpty' => empty($matchingElements['totalOverall']), |
| 274 |
'numberOfTrigger' => $matchingElements['totalOverall'], |
| 275 |
'title' => acym_translation('ACYM_TOTAL_USERS_PROCESSED'), |
| 276 |
]; |
| 277 |
|
| 278 |
ob_start(); |
| 279 |
include acym_getPartial('scenarios', 'performances_step'); |
| 280 |
|
| 281 |
return ob_get_clean(); |
| 282 |
} |
| 283 |
|
| 284 |
public function getUserInfo(): void |
| 285 |
{ |
| 286 |
$userId = acym_getVar('int', 'userId', 0); |
| 287 |
$processId = acym_getVar('int', 'processId', 0); |
| 288 |
|
| 289 |
if (empty($userId) || empty($processId)) { |
| 290 |
acym_sendAjaxResponse(acym_translation('ACYM_AN_ERROR_OCCURRED'), [], false); |
| 291 |
} |
| 292 |
|
| 293 |
$userClass = new UserClass(); |
| 294 |
$user = $userClass->getOneById($userId); |
| 295 |
|
| 296 |
if (empty($user)) { |
| 297 |
acym_sendAjaxResponse(acym_translation('ACYM_AN_ERROR_OCCURRED'), [], false); |
| 298 |
} |
| 299 |
|
| 300 |
$scenarioProcessClass = new ScenarioProcessClass(); |
| 301 |
$process = $scenarioProcessClass->getOneById($processId); |
| 302 |
|
| 303 |
if (empty($process)) { |
| 304 |
acym_sendAjaxResponse(acym_translation('ACYM_AN_ERROR_OCCURRED'), [], false); |
| 305 |
} |
| 306 |
|
| 307 |
$scenarioHistoryLineClass = new ScenarioHistoryLineClass(); |
| 308 |
$scenarioHistoryLines = $scenarioHistoryLineClass->getAllByProcessId($processId); |
| 309 |
|
| 310 |
$scenarioQueueClass = new ScenarioQueueClass(); |
| 311 |
$upcomingStep = $scenarioQueueClass->getByProcessId($processId); |
| 312 |
|
| 313 |
$data = [ |
| 314 |
'user' => $user, |
| 315 |
'process' => $process, |
| 316 |
'historyLines' => $scenarioHistoryLines, |
| 317 |
'upcomingStep' => $upcomingStep, |
| 318 |
]; |
| 319 |
|
| 320 |
ob_start(); |
| 321 |
include acym_getPartial('scenarios', 'performances_user'); |
| 322 |
|
| 323 |
acym_sendAjaxResponse('', ['content' => ob_get_clean()]); |
| 324 |
} |
| 325 |
} |
| 326 |
|