vendor/uvdesk/automation-bundle/EventListener/WorkflowListener.php line 91

Open in your IDE?
  1. <?php
  2. namespace Webkul\UVDesk\AutomationBundle\EventListener;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use Symfony\Component\DependencyInjection\ContainerInterface;
  5. use Webkul\UVDesk\AutomationBundle\Entity\Workflow;
  6. use Webkul\UVDesk\AutomationBundle\Workflow\Action;
  7. use Webkul\UVDesk\AutomationBundle\Workflow\Event;
  8. use Webkul\UVDesk\AutomationBundle\Workflow\Events as WorkflowEvents;
  9. use Webkul\UVDesk\CoreFrameworkBundle\Entity\Ticket;
  10. use Webkul\UVDesk\CoreFrameworkBundle\Services\TicketService;
  11. use Webkul\UVDesk\CoreFrameworkBundle\Services\UserService;
  12. use UVDesk\CommunityPackages\UVDesk as UVDeskCommunityPackages;
  13. use Webkul\UVDesk\CoreFrameworkBundle\Workflow\Events as CoreWorkflowEvents;
  14. class WorkflowListener
  15. {
  16. private $container;
  17. private $entityManager;
  18. private $ticketService;
  19. private $userService;
  20. private $registeredWorkflowEvents = [];
  21. private $registeredWorkflowActions = [];
  22. public function __construct(ContainerInterface $container, EntityManagerInterface $entityManager, TicketService $ticketService, UserService $userService)
  23. {
  24. $this->container = $container;
  25. $this->entityManager = $entityManager;
  26. $this->ticketService = $ticketService;
  27. $this->userService = $userService;
  28. }
  29. public function registerWorkflowEvent(Event $serviceTag)
  30. {
  31. $this->registeredWorkflowEvents[] = $serviceTag;
  32. }
  33. public function registerWorkflowAction(Action $serviceTag)
  34. {
  35. $this->registeredWorkflowActions[] = $serviceTag;
  36. }
  37. public function getRegisteredWorkflowEvent($eventId)
  38. {
  39. foreach ($this->registeredWorkflowEvents as $workflowDefinition) {
  40. if ($workflowDefinition->getId() == $eventId) {
  41. return $workflowDefinition;
  42. }
  43. }
  44. return null;
  45. }
  46. public function getRegisteredWorkflowEvents()
  47. {
  48. return $this->registeredWorkflowEvents;
  49. }
  50. public function getRegisteredWorkflowActions()
  51. {
  52. return $this->registeredWorkflowActions;
  53. }
  54. public function executeReplyEvent(Event $event) {
  55. if ($this->userService->isFileExists('apps/uvdesk/report')) {
  56. $reportServiceClass = UVDeskCommunityPackages\Report\Services\ReportService::class;
  57. $reportService = new $reportServiceClass($this->entityManager, $this->container, $this->ticketService, $this->userService);
  58. if (($event) instanceof CoreWorkflowEvents\Ticket\Status) {
  59. $reportService->calculateResolveTime($event->getTicket());
  60. } else if (
  61. ($event) instanceof CoreWorkflowEvents\Ticket\AgentReply ||
  62. ($event) instanceof CoreWorkflowEvents\Ticket\CustomerReply ||
  63. ($event) instanceof CoreWorkflowEvents\Ticket\CollaboratorReply
  64. ) {
  65. $thread = $event->getThread();
  66. if (
  67. $thread
  68. && $thread->getThreadType() == 'reply'
  69. && ($thread->getCreatedBy() == 'agent'
  70. || $thread->getCreatedBy() == 'customer')
  71. ) {
  72. $reportService->calculateResponseTime($thread);
  73. }
  74. }
  75. }
  76. }
  77. public function executeWorkflow($event)
  78. {
  79. if (! ($event instanceof Event))
  80. return;
  81. $workflowCollection = $this->entityManager->getRepository(Workflow::class)->getEventWorkflows($event::getId());
  82. if ((
  83. $event instanceof CoreWorkflowEvents\Ticket\Create
  84. || $event instanceof CoreWorkflowEvents\Ticket\Priority
  85. )
  86. && $this->userService->isFileExists('apps/uvdesk/sla')
  87. ) {
  88. $slaServiceClass = UVDeskCommunityPackages\SLA\Services\SlaService::class;
  89. $slaService = new $slaServiceClass($this->container, $this->entityManager );
  90. $slaService->refreshTicketPolicies($event->getTicket());
  91. }
  92. if (($event) instanceof CoreWorkflowEvents\Ticket\Status) {
  93. $this->executeReplyEvent($event);
  94. }
  95. if (empty($workflowCollection) && 'uvdesk.user.forgot_password' == $event::getId()) {
  96. $user = $event->getArgument('entity');
  97. if (
  98. ! empty($user)
  99. && $user instanceof \Webkul\UVDesk\CoreFrameworkBundle\Entity\User
  100. ) {
  101. $agentForgotPasswordWorkflows = $this->entityManager->getRepository(Workflow::class)->getEventWorkflows('uvdesk.agent.forgot_password');
  102. $customerForgotPasswordWorkflows = $this->entityManager->getRepository(Workflow::class)->getEventWorkflows('uvdesk.customer.forgot_password');
  103. if (!empty($agentForgotPasswordWorkflows) || !empty($customerForgotPasswordWorkflows)) {
  104. $agentInstance = $user->getAgentInstance();
  105. $customerInstance = $user->getCustomerInstance();
  106. if (
  107. ! empty($customerForgotPasswordWorkflows)
  108. && !empty($customerInstance)
  109. ) {
  110. // Resort to uvdesk.customer.forgot_password workflows
  111. $workflowCollection = $customerForgotPasswordWorkflows;
  112. } else if (
  113. ! empty($agentForgotPasswordWorkflows)
  114. && !empty($agentInstance)
  115. ) {
  116. // Resort to uvdesk.agent.forgot_password workflows
  117. $workflowCollection = $agentForgotPasswordWorkflows;
  118. }
  119. }
  120. }
  121. }
  122. if (! empty($workflowCollection)) {
  123. foreach ($workflowCollection as $workflow) {
  124. $totalConditions = 0;
  125. $totalEvaluatedConditions = 0;
  126. foreach ($this->evaluateWorkflowConditions($workflow) as $workflowCondition) {
  127. $totalEvaluatedConditions++;
  128. if (isset($workflowCondition['type']) && $this->checkCondition($workflowCondition, $event)) {
  129. $totalConditions++;
  130. }
  131. if (isset($workflowCondition['or'])) {
  132. foreach ($workflowCondition['or'] as $orCondition) {
  133. if ($this->checkCondition($orCondition, $event)) {
  134. $totalConditions++;
  135. }
  136. }
  137. }
  138. }
  139. if ($totalEvaluatedConditions == 0 || $totalConditions >= $totalEvaluatedConditions) {
  140. $this->applyWorkflowActions($workflow, $event);
  141. }
  142. }
  143. }
  144. }
  145. private function evaluateWorkflowConditions(Workflow $workflow)
  146. {
  147. $index = -1;
  148. $workflowConditions = [];
  149. if ($workflow->getConditions() == null) {
  150. return $workflowConditions;
  151. }
  152. foreach ($workflow->getConditions() as $condition) {
  153. if (
  154. ! empty($condition['operation'])
  155. && $condition['operation'] != "&&"
  156. ) {
  157. if (!isset($finalConditions[$index]['or'])) {
  158. $finalConditions[$index]['or'] = [];
  159. }
  160. $workflowConditions[$index]['or'][] = $condition;
  161. } else {
  162. $index++;
  163. $workflowConditions[] = $condition;
  164. }
  165. }
  166. return $workflowConditions;
  167. }
  168. private function applyWorkflowActions(Workflow $workflow, Event $event)
  169. {
  170. foreach ($workflow->getActions() as $attributes) {
  171. if (empty($attributes['type'])) {
  172. continue;
  173. }
  174. foreach ($this->getRegisteredWorkflowActions() as $workflowAction) {
  175. if ($workflowAction->getId() == $attributes['type']) {
  176. $workflowAction->applyAction($this->container, $event, isset($attributes['value']) ? $attributes['value'] : '');
  177. }
  178. }
  179. }
  180. }
  181. public function checkCondition($condition, Event $event)
  182. {
  183. $entity = null;
  184. switch (true) {
  185. case $event instanceof WorkflowEvents\EmailActivity:
  186. $entity = $event->getResolvedEmailHeaders();
  187. break;
  188. case $event instanceof WorkflowEvents\TicketActivity:
  189. $entity = $event->getTicket();
  190. break;
  191. case $event instanceof WorkflowEvents\AgentActivity:
  192. case $event instanceof WorkflowEvents\CustomerActivity:
  193. case $event instanceof WorkflowEvents\UserActivity:
  194. $entity = $event->getUser();
  195. break;
  196. default:
  197. break;
  198. }
  199. if (empty($entity)) {
  200. return false;
  201. }
  202. switch ($condition['type']) {
  203. case 'from_mail':
  204. if (isset($condition['value'])) {
  205. if ($entity instanceof Ticket) {
  206. return $this->match($condition['match'], $entity->getCustomer()->getEmail(), $condition['value']);
  207. } else if (
  208. is_array($entity)
  209. && ! empty($entity['from'])
  210. ) {
  211. return $this->match($condition['match'], $entity['from'], $condition['value']);
  212. }
  213. }
  214. break;
  215. case 'to_mail':
  216. if (
  217. isset($condition['value'])
  218. && $entity instanceof Ticket
  219. && $entity->getMailboxEmail()
  220. ) {
  221. return $this->match($condition['match'], $entity->getMailboxEmail(), $condition['value']);
  222. }
  223. break;
  224. case 'subject':
  225. if (
  226. isset($condition['value'])
  227. && ($entity instanceof Ticket || $entity instanceof Task)
  228. ) {
  229. return $this->match($condition['match'], $entity->getSubject(), $condition['value']);
  230. }
  231. break;
  232. case 'description':
  233. if (
  234. isset($condition['value'])
  235. && $entity instanceof Ticket
  236. ) {
  237. $reply = $entity->createdThread->getMessage();
  238. $reply = rtrim(strip_tags($reply), "\n" );
  239. return $this->match($condition['match'], rtrim($reply), $condition['value']);
  240. }
  241. break;
  242. case 'subject_or_description':
  243. if (
  244. isset($condition['value'])
  245. && $entity instanceof Ticket
  246. ) {
  247. $flag = $this->match($condition['match'], $entity->getSubject(), $condition['value']);
  248. $createThread = $this->container->get('ticket.service')->getCreateReply($entity->getId(),false);
  249. if (! $flag) {
  250. $createThread = $this->container->get('ticket.service')->getCreateReply($entity->getId(),false);
  251. $createThread['reply'] = rtrim(strip_tags($createThread['reply']), "\n" );
  252. $flag = $this->match($condition['match'],$createThread['reply'],$condition['value']);
  253. }
  254. return $flag;
  255. }
  256. break;
  257. case 'TicketPriority':
  258. if (
  259. isset($condition['value'])
  260. && ($entity instanceof Ticket)
  261. ) {
  262. return $this->match($condition['match'], $entity->getPriority()->getId(), $condition['value']);
  263. }
  264. break;
  265. case 'TicketType':
  266. if (
  267. isset($condition['value'])
  268. && $entity instanceof Ticket
  269. ) {
  270. $typeId = $entity->getType() ? $entity->getType()->getId() : 0;
  271. return $this->match($condition['match'], $typeId, $condition['value']);
  272. }
  273. break;
  274. case 'TicketStatus':
  275. if (
  276. isset($condition['value'])
  277. && $entity instanceof Ticket
  278. ) {
  279. return $this->match($condition['match'], $entity->getStatus()->getId(), $condition['value']);
  280. }
  281. break;
  282. case 'stage':
  283. if (
  284. isset($condition['value'])
  285. && $entity instanceof Task
  286. ) {
  287. return $this->match($condition['match'], $entity->getStage()->getId(), $condition['value']);
  288. }
  289. break;
  290. case 'source':
  291. if (
  292. isset($condition['value'])
  293. && $entity instanceof Ticket
  294. ) {
  295. return $this->match($condition['match'], $entity->getSource(), $condition['value']);
  296. }
  297. break;
  298. case 'created':
  299. if (
  300. isset($condition['value'])
  301. && ($entity instanceof Ticket || $entity instanceof Task)
  302. ) {
  303. $date = date_format($entity->getCreatedAt(), "d-m-Y h:ia");
  304. return $this->match($condition['match'], $date, $condition['value']);
  305. }
  306. break;
  307. case 'agent':
  308. if (
  309. isset($condition['value'])
  310. && $entity instanceof Ticket
  311. && $entity->getAgent()
  312. ) {
  313. return $this->match($condition['match'], $entity->getAgent()->getId(), (($condition['value'] == 'actionPerformingAgent') ? ($this->container->get('user.service')->getCurrentUser() ? $this->container->get('user.service')->getCurrentUser()->getId() : 0) : $condition['value']));
  314. }
  315. break;
  316. case 'group':
  317. if (
  318. isset($condition['value'])
  319. && $entity instanceof Ticket
  320. ) {
  321. $groupId = $entity->getSupportGroup() ? $entity->getSupportGroup()->getId() : 0;
  322. return $this->match($condition['match'], $groupId, $condition['value']);
  323. }
  324. break;
  325. case 'team':
  326. if (
  327. isset($condition['value'])
  328. && $entity instanceof Ticket
  329. ) {
  330. $subGroupId = $entity->getSupportTeam() ? $entity->getSupportTeam()->getId() : 0;
  331. return $this->match($condition['match'], $subGroupId, $condition['value']);
  332. }
  333. break;
  334. case 'customer_name':
  335. if (
  336. isset($condition['value'])
  337. && $entity instanceof Ticket
  338. ) {
  339. return $this->match($condition['match'], $entity->getCustomer()->getFullName(), $condition['value']);
  340. }
  341. break;
  342. case 'customer_email':
  343. if (
  344. isset($condition['value'])
  345. && $entity instanceof Ticket
  346. ) {
  347. return $this->match($condition['match'], $entity->getCustomer()->getEmail(), $condition['value']);
  348. }
  349. break;
  350. case strpos($condition['type'], 'customFields') == 0:
  351. $value = null;
  352. $ticketCfValues = $entity->getCustomFieldValues()->getValues();
  353. foreach ($ticketCfValues as $cfValue) {
  354. $mainCf = $cfValue->getTicketCustomFieldsValues();
  355. if ($condition['type'] == 'customFields[' . $mainCf->getId() . ']' ) {
  356. if (in_array($mainCf->getFieldType(), ['select', 'radio', 'checkbox'])) {
  357. $value = json_decode($cfValue->getValue(), true);
  358. } else {
  359. $value = trim($cfValue->getValue(), '"');
  360. }
  361. break;
  362. }
  363. }
  364. if (
  365. isset($condition['value'])
  366. && $entity instanceof Ticket
  367. ) {
  368. return $this->match($condition['match'], !empty($value) ? $value : '', $condition['value']);
  369. }
  370. break;
  371. default:
  372. break;
  373. }
  374. return false;
  375. }
  376. public function match($condition, $haystack, $needle)
  377. {
  378. // Filter tags
  379. if ('string' == gettype($haystack)) {
  380. $haystack = strip_tags($haystack);
  381. }
  382. switch ($condition) {
  383. case 'is':
  384. return is_array($haystack) ? in_array($needle, $haystack) : $haystack == $needle;
  385. case 'isNot':
  386. return is_array($haystack) ? !in_array($needle, $haystack) : $haystack != $needle;
  387. case 'contains':
  388. return strripos($haystack,$needle) !== false ? true : false;
  389. case 'notContains':
  390. return strripos($haystack,$needle) === false ? true : false;
  391. case 'startWith':
  392. return $needle === "" || strripos($haystack, $needle, -strlen($haystack)) !== FALSE;
  393. case 'endWith':
  394. return $needle === "" || (($temp = strlen($haystack) - strlen($needle)) >= 0 && stripos($haystack, $needle, $temp) !== FALSE);
  395. case 'before':
  396. $createdTimeStamp = date('Y-m-d', strtotime($haystack));
  397. $conditionTimeStamp = date('Y-m-d', strtotime($needle . " 23:59:59"));
  398. return $createdTimeStamp < $conditionTimeStamp ? true : false;
  399. case 'beforeOn':
  400. $createdTimeStamp = date('Y-m-d', strtotime($haystack));
  401. $conditionTimeStamp = date('Y-m-d', strtotime($needle . " 23:59:59"));
  402. return ($createdTimeStamp < $conditionTimeStamp || $createdTimeStamp == $conditionTimeStamp) ? true : false;
  403. case 'after':
  404. $createdTimeStamp = date('Y-m-d', strtotime($haystack));
  405. $conditionTimeStamp = date('Y-m-d', strtotime($needle . " 23:59:59"));
  406. return $createdTimeStamp > $conditionTimeStamp ? true : false;
  407. case 'afterOn':
  408. $createdTimeStamp = date('Y-m-d', strtotime($haystack));
  409. $conditionTimeStamp = date('Y-m-d', strtotime($needle . " 23:59:59"));
  410. return $createdTimeStamp > $conditionTimeStamp || $createdTimeStamp == $conditionTimeStamp ? true : false;
  411. case 'beforeDateTime':
  412. $createdTimeStamp = date('Y-m-d h:i:s', strtotime($haystack));
  413. $conditionTimeStamp = date('Y-m-d h:i:s', strtotime($needle));
  414. return $createdTimeStamp < $conditionTimeStamp ? true : false;
  415. case 'beforeDateTimeOn':
  416. $createdTimeStamp = date('Y-m-d h:i:s', strtotime($haystack));
  417. $conditionTimeStamp = date('Y-m-d h:i:s', strtotime($needle));
  418. return ($createdTimeStamp < $conditionTimeStamp || $createdTimeStamp == $conditionTimeStamp) ? true : false;
  419. case 'afterDateTime':
  420. $createdTimeStamp = date('Y-m-d h:i:s', strtotime($haystack));
  421. $conditionTimeStamp = date('Y-m-d h:i:s', strtotime($needle));
  422. return $createdTimeStamp > $conditionTimeStamp ? true : false;
  423. case 'afterDateTimeOn':
  424. $createdTimeStamp = date('Y-m-d h:i:s', strtotime($haystack));
  425. $conditionTimeStamp = date('Y-m-d h:i:s', strtotime($needle));
  426. return $createdTimeStamp > $conditionTimeStamp || $createdTimeStamp == $conditionTimeStamp ? true : false;
  427. case 'beforeTime':
  428. $createdTimeStamp = date('Y-m-d H:i A', strtotime('2017-01-01' . $haystack));
  429. $conditionTimeStamp = date('Y-m-d H:i A', strtotime('2017-01-01' . $needle));
  430. return $createdTimeStamp < $conditionTimeStamp ? true : false;
  431. case 'beforeTimeOn':
  432. $createdTimeStamp = date('Y-m-d H:i A', strtotime('2017-01-01' . $haystack));
  433. $conditionTimeStamp = date('Y-m-d H:i A', strtotime('2017-01-01' . $needle));
  434. return ($createdTimeStamp < $conditionTimeStamp || $createdTimeStamp == $conditionTimeStamp) ? true : false;
  435. case 'afterTime':
  436. $createdTimeStamp = date('Y-m-d H:i A', strtotime('2017-01-01' . $haystack));
  437. $conditionTimeStamp = date('Y-m-d H:i A', strtotime('2017-01-01' . $needle));
  438. return $createdTimeStamp > $conditionTimeStamp ? true : false;
  439. case 'afterTimeOn':
  440. $createdTimeStamp = date('Y-m-d H:i A', strtotime('2017-01-01' . $haystack));
  441. $conditionTimeStamp = date('Y-m-d H:i A', strtotime('2017-01-01' . $needle));
  442. return $createdTimeStamp > $conditionTimeStamp || $createdTimeStamp == $conditionTimeStamp ? true : false;
  443. case 'greaterThan':
  444. return !is_array($haystack) && $needle > $haystack;
  445. case 'lessThan':
  446. return !is_array($haystack) && $needle < $haystack;
  447. default:
  448. break;
  449. }
  450. return false;
  451. }
  452. }