vendor/elements/process-manager-bundle/src/Controller/MonitoringItemController.php line 45

Open in your IDE?
  1. <?php
  2. /**
  3.  * Elements.at
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  *  @copyright  Copyright (c) elements.at New Media Solutions GmbH (https://www.elements.at)
  12.  *  @license    http://www.pimcore.org/license     GPLv3 and PEL
  13.  */
  14. namespace Elements\Bundle\ProcessManagerBundle\Controller;
  15. use Elements\Bundle\ProcessManagerBundle\Executor\Action\AbstractAction;
  16. use Elements\Bundle\ProcessManagerBundle\Executor\Logger\AbstractLogger;
  17. use Elements\Bundle\ProcessManagerBundle\Executor\Logger\Application;
  18. use Elements\Bundle\ProcessManagerBundle\Executor\Logger\File;
  19. use Elements\Bundle\ProcessManagerBundle\Model\Configuration;
  20. use Elements\Bundle\ProcessManagerBundle\Model\MonitoringItem;
  21. use Pimcore\Bundle\AdminBundle\Controller\AdminController;
  22. use Pimcore\Bundle\AdminBundle\Helper\QueryParams;
  23. use Pimcore\Templating\Model\ViewModel;
  24. use Symfony\Component\HttpFoundation\JsonResponse;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpKernel\Profiler\Profiler;
  27. use Symfony\Component\Routing\Annotation\Route;
  28. use Elements\Bundle\ProcessManagerBundle\ElementsProcessManagerBundle;
  29. use Elements\Bundle\ProcessManagerBundle\Enums;
  30. /**
  31.  * @Route("/admin/elementsprocessmanager/monitoring-item")
  32.  */
  33. class MonitoringItemController extends AdminController
  34. {
  35.     /**
  36.      * @Route("/list")
  37.      *
  38.      * @param Request $request
  39.      *
  40.      * @return JsonResponse
  41.      */
  42.     public function listAction(Request $request)
  43.     {
  44.         $this->checkPermission(Enums\Permissions::VIEW);
  45.         $data = [];
  46.         $list = new MonitoringItem\Listing();
  47.         $list->setOrder('DESC');
  48.         $list->setOrderKey('id');
  49.         $list->setLimit($request->get('limit'25));
  50.         $list->setUser($this->getAdminUser());
  51.         $list->setOffset($request->get('start'));
  52.         $allParams array_merge($request->request->all(), $request->query->all());
  53.         $sortingSettings QueryParams::extractSortingSettings($allParams);
  54.         if ($sortingSettings['orderKey'] && $sortingSettings['order']) {
  55.             $list->setOrderKey($sortingSettings['orderKey']);
  56.             $list->setOrder($sortingSettings['order']);
  57.         }
  58.         $callbacks = [
  59.             'executedByUser' => function ($f) {
  60.                 $db \Pimcore\Db::get();
  61.                 $ids $db->fetchCol('SELECT id FROM users where name LIKE '.$db->quote('%'.$f->value.'%')) ?: [0];
  62.                 return ' executedByUser IN( '.implode(','$ids).') ';
  63.             }
  64.         ];
  65.         if ($filterCondition QueryParams::getFilterCondition(
  66.             $request->get('filter'),
  67.             ['id''o_id''pid'],
  68.             true,
  69.             $callbacks
  70.         )
  71.         ) {
  72.             $list->setCondition($filterCondition);
  73.         }
  74.         $condition $list->getCondition();
  75.         if($filters $request->get('filter')){
  76.             foreach(json_decode($filters,true) as $e){
  77.                 if($e['property'] == 'id'){
  78.                     $condition .= ' OR `parentId` = ' . (int)$e['value'].' ';
  79.                 }
  80.             }
  81.         }
  82.         if (!$request->get('showHidden') || $request->get('showHidden') == 'false') {
  83.             $filterConditionArray =  QueryParams::getFilterCondition($request->get('filter'), ['id''o_id''pid'], false$callbacks);
  84.             if ($filterConditionArray && isset($filterConditionArray['id'])) {
  85.             } else {
  86.                 if ($condition) {
  87.                     $condition .= ' AND published=1';
  88.                 } else {
  89.                     $condition .= ' published=1';
  90.                 }
  91.             }
  92.         }
  93.         $list->setCondition($condition);
  94.         $total $list->getTotalCount();
  95.         foreach ($list->load() as $item) {
  96.             $data[] = $this->getItemData($item);
  97.         }
  98.         return $this->adminJson(['success' => true'total' => $total'data' => $data]);
  99.     }
  100.     /**
  101.      * @Route("/update")
  102.      *
  103.      * @param Request $request
  104.      *
  105.      * @return JsonResponse
  106.      */
  107.     public function update(Request $request){
  108.         $monitoringItem MonitoringItem::getById($request->get('id'));
  109.         $data = [];
  110.         if($monitoringItem){
  111.             if($monitoringItem->getExecutedByUser() == $this->getUser()->getId()){
  112.                 foreach($request->request->all() as $key => $value){
  113.                     $setter "set" ucfirst($key);
  114.                     if(method_exists($monitoringItem,$setter)){
  115.                         $monitoringItem->$setter($value);
  116.                     }
  117.                 }
  118.                 $monitoringItem->save();
  119.             }
  120.             $data $this->getItemData($monitoringItem);
  121.         }
  122.         return $this->json(['success' => true,'data' => $data]);
  123.     }
  124.     /**
  125.      * @return MonitoringItem\Listing
  126.      */
  127.     protected function getProcessesForCurrentUser(){
  128.         $list = new MonitoringItem\Listing();
  129.         $list->setOrder('DESC');
  130.         $list->setOrderKey('id');
  131.         #$list->setLimit(10);
  132.         $list->setCondition('executedByUser = ? and parentId IS NULL AND published = 1 ',[$this->getUser()->getId()]);
  133.         return $list;
  134.     }
  135.     /**
  136.      * @Route("/update-all-user-monitoring-items")
  137.      *
  138.      * @param Request $request
  139.      *
  140.      * @return JsonResponse
  141.      */
  142.     public function updateAllUserMonitoringItems(Request $request){
  143.         $list $this->getProcessesForCurrentUser();
  144.         $params $request->request->all();
  145.         /**
  146.          * @var MonitoringItem $item
  147.          */
  148.         foreach($list->load() as $item){
  149.             $item->setValues($params)->save();
  150.         }
  151.         return $this->adminJson(['success' => true]);
  152.     }
  153.     /**
  154.      * @Route("/list-processes-for-user")
  155.      *
  156.      * @param Request $request
  157.      *
  158.      * @return JsonResponse
  159.      */
  160.     public function listProcessesForUser(Request $request){
  161.         $data = [
  162.             'total' => 0,
  163.             'active' => 0,
  164.             'items' => []
  165.         ];
  166.         try {
  167.             $this->checkPermission(Enums\Permissions::VIEW);
  168.         }catch (\Exception $e){
  169.             return $this->adminJson($data);
  170.         }
  171.         $list $this->getProcessesForCurrentUser();
  172.         $data['total'] = $list->getTotalCount();
  173.         foreach($list->load() as $item){
  174.             $tmp $this->getItemData($item);
  175.             if($tmp['isAlive']){
  176.                 $data['active']++;
  177.             }
  178.             $data['items'][] = $tmp;
  179.         }
  180.         return $this->adminJson($data);
  181.     }
  182.     protected function getItemData(MonitoringItem $item){
  183.         $tmp $item->getObjectVars();
  184.         $tmp['messageShort'] = \Pimcore\Tool\Text::cutStringRespectingWhitespace($tmp['message'],30);
  185.         $tmp['steps'] = '-';
  186.         if ($item->getTotalSteps() > || $item->getCurrentStep()) {
  187.             $tmp['steps'] = $item->getCurrentStep().'/'.$item->getTotalSteps();
  188.         }
  189.         $tmp['duration'] = $item->getDuration() ?: '-';
  190.         $tmp['progress'] = 0;
  191.         if ($tmp['executedByUser']) {
  192.             $user \Pimcore\Model\User::getById($tmp['executedByUser']);
  193.             if ($user) {
  194.                 $tmp['executedByUser'] = $user->getName();
  195.             } else {
  196.                 $tmp['executedByUser'] = 'User id: '.$tmp['executedByUser'];
  197.             }
  198.         } else {
  199.             $tmp['executedByUser'] = 'System';
  200.         }
  201.         $logFile 0;
  202.         $tmp['action'] = '';
  203.         if ($actions $item->getActions()) {
  204.             foreach ($actions as $action) {
  205.                 /**
  206.                  * @var $class AbstractAction
  207.                  */
  208.                 $class = new $action['class'];
  209.                 if ($s $class->getGridActionHtml($item$action)) {
  210.                     $tmp['action'] .= $s;
  211.                 }
  212.             }
  213.         }
  214.         $tmp['actionItems'] = [];
  215.         if($tmp['actions']){
  216.             $actionItems json_decode($tmp['actions'],true);
  217.             foreach($actionItems as $i => $v){
  218.                 if($class $v['class']){
  219.                     if(\Pimcore\Tool::classExists($class)){
  220.                         $o = new $class();
  221.                         $v['dynamicData'] = $o->toJson($item,$v);
  222.                     }
  223.                     $actionItems[$i] = $v;
  224.                 }
  225.             }
  226.             $tmp['actionItems'] = $actionItems;
  227.         }
  228.         $tmp['logger'] = '';
  229.         if ($loggers $item->getLoggers()) {
  230.             foreach ((array)$loggers as $i => $logger) {
  231.                 /**
  232.                  * @var $class AbstractLogger
  233.                  */
  234.                 $class = new $logger['class'];
  235.                 if (\Pimcore\Tool::classExists(get_class($class))) {
  236.                     $logger['index'] = $i;
  237.                     if ($s $class->getGridLoggerHtml($item$logger)) {
  238.                         $tmp['logger'] .= $s;
  239.                     }
  240.                 }
  241.             }
  242.         }
  243.         $tmp['retry'] = 1;
  244.         if ($item->isAlive()) {
  245.             $tmp['retry'] = 0;
  246.         }
  247.         if ($tmp['retry'] == 1) {
  248.             $config Configuration::getById($item->getConfigurationId());
  249.             if ($config) {
  250.                 if ($config->getActive() == 0) {
  251.                     $tmp['retry'] = 0;
  252.                 } else {
  253.                         $uniqueExecution $config->getExecutorClassObject()->getValues()['uniqueExecution'] ?? false;
  254.                         if ($uniqueExecution) {
  255.                         $runningProcesses $config->getRunningProcesses();
  256.                         if (!empty($runningProcesses)) {
  257.                             $tmp['retry'] = 0;
  258.                         }
  259.                     }
  260.                 }
  261.             }
  262.         }
  263.         $tmp['isAlive'] = $item->isAlive();
  264.         $tmp['progress'] = '-';
  265.         if ($item->getCurrentWorkload() && $item->getTotalWorkload()) {
  266.             $progress $item->getProgressPercentage();
  267.             $tmp['progress'] = '<div class="x-progress x-progress-default x-border-box" style="width:100%;"><div class="x-progress-text x-progress-text-back" ></div><div class="x-progress-bar x-progress-bar-default" style="width:'.$progress.'%;min-width: 35px; "><div class="x-progress-text" style="text-align:left;margin-left: 5px;"><div>'.$progress.'%</div></div></div></div>';
  268.         }
  269.         $tmp['progressPercentage'] = (float)$item->getProgressPercentage();
  270.         $tmp['callbackSettingsString'] = json_encode($item->getCallbackSettings());
  271.         $tmp['callbackSettings'] = $item->getCallbackSettingsForGrid();
  272.         return $tmp;
  273.     }
  274.     /**
  275.      * @Route("/log-application-logger")
  276.      *
  277.      * @param Request $request
  278.      *
  279.      * @return JsonResponse
  280.      */
  281.     public function logApplicationLoggerAction(Request $request)
  282.     {
  283.         try {
  284.             $monitoringItem MonitoringItem::getById($request->get('id'));
  285.             if (!$monitoringItem) {
  286.                 throw new \Exception('Monitoring Item with id'.$request->get('id').' not found');
  287.             }
  288.             $loggerIndex $request->get('loggerIndex');
  289.             if ($loggers $monitoringItem->getLoggers()) {
  290.                 foreach ((array)$loggers as $i => $config) {
  291.                     /**
  292.                      * @var $class AbstractLogger
  293.                      * @var $logger Application
  294.                      */
  295.                     $class = new $config['class'];
  296.                     if (\Pimcore\Tool::classExists(get_class($class))) {
  297.                         if ($i == $loggerIndex) {
  298.                             $logger $class;
  299.                             if (!$config['logLevel']) {
  300.                                 $config['logLevel'] = 'DEBUG';
  301.                             }
  302.                             break;
  303.                         }
  304.                     }
  305.                 }
  306.             }
  307.             $result $monitoringItem->getObjectVars();
  308.             $result['logLevel'] = strtolower($config['logLevel']);
  309.             return $this->adminJson(['success' => true'data' => $result]);
  310.         } catch (\Exception $e) {
  311.             return $this->adminJson(['success' => false'message' => $e->getMessage()]);
  312.         }
  313.     }
  314.     /**
  315.      * @Route("/log-file-logger")
  316.      *
  317.      * @param Request $request
  318.      *
  319.      * @return \Symfony\Component\HttpFoundation\Response
  320.      */
  321.     public function logFileLoggerAction(Request $request, ?Profiler $profiler)
  322.     {
  323.         if(null !== $profiler) {
  324.             $profiler->disable();
  325.         }
  326.         $viewData = [];
  327.         $monitoringItem MonitoringItem::getById($request->get('id'));
  328.         $loggerIndex $request->get('loggerIndex');
  329.         if ($loggers $monitoringItem->getLoggers()) {
  330.             foreach ((array)$loggers as $i => $config) {
  331.                 /**
  332.                  * @var $class AbstractLogger
  333.                  * @var $logger File
  334.                  */
  335.                 $class = new $config['class'];
  336.                 if (\Pimcore\Tool::classExists(get_class($class))) {
  337.                     if ($i == $loggerIndex) {
  338.                         $logger $class;
  339.                         $logFile $logger->getLogFile($config$monitoringItem);
  340.                         if (!$config['logLevel']) {
  341.                             $config['logLevel'] = 'DEBUG';
  342.                         }
  343.                         break;
  344.                     }
  345.                 }
  346.             }
  347.         }
  348.         $viewData['logLevel'] = $config['logLevel'];
  349.         $viewData['logFile'] = $logFile;
  350.         if (is_readable($logFile)) {
  351.             $data file_get_contents($logFile);
  352.             if(array_key_exists("disableFileProcessing",$config) && $config['disableFileProcessing']){
  353.                 return new \Symfony\Component\HttpFoundation\Response($data);
  354.             }
  355.             $fileSizeMb round(filesize($logFile) / 1024 1024);
  356.             if ($fileSizeMb 100) {
  357.                 $data file_get_contents($logFile);
  358.                 $data explode("\n"$data);
  359.             } else {
  360.                 $data explode("\n"shell_exec('tail -n 1000 ' $logFile));
  361.                 $warning '<span style="color:#ff131c">The log file is to large to view all contents (' $fileSizeMb.'MB). The last 1000 lines are displayed. File: ' $logFile '</span>';
  362.                 array_unshift($data$warning);
  363.                 array_push($data$warning);
  364.             }
  365.             foreach ($data as $i => $row) {
  366.                 if ($row) {
  367.                     if (strpos($row'.WARNING')) {
  368.                         $data[$i] = '<span style="color:#ffb13b">'.$row.'</span>';
  369.                     }
  370.                     if (strpos($row'.ERROR') || strpos($row'.CRITICAL')) {
  371.                         $data[$i] = '<span style="color:#ff131c">'.$row.'</span>';
  372.                     }
  373.                     if (strpos($row'dev-server > ') === || strpos($row'production-server > ') === 0) {
  374.                         $data[$i] = '<span style="color:#35ad33">'.$row.'</span>';
  375.                     }
  376.                     foreach (['[echo]''[mkdir]''[delete]''[copy]'] as $k) {
  377.                         if (strpos($row$k)) {
  378.                             $data[$i] = '<span style="color:#49b7d4">'.$row.'</span>';
  379.                         }
  380.                     }
  381.                 }
  382.             }
  383.         } else {
  384.             $data = ["Log file doesn't exist. ".$logFile];
  385.         }
  386.         $data implode("\n"$data);
  387.         $viewData['data'] = $data;
  388.         $viewData['monitoringItem'] = $monitoringItem;
  389.         return $this->render('@ElementsProcessManager/MonitoringItem/logFileLogger.html.twig'$viewData);
  390.     }
  391.     /**
  392.      * @Route("/delete")
  393.      *
  394.      * @param Request $request
  395.      *
  396.      * @return JsonResponse
  397.      */
  398.     public function deleteAction(Request $request)
  399.     {
  400.         $this->checkPermission('plugin_pm_permission_delete_monitoring_item');
  401.         $entry MonitoringItem::getById($request->get('id'));
  402.         if ($entry) {
  403.             if($entry->isAlive()){
  404.                 $entry->stopProcess();
  405.             }
  406.             $entry->delete();
  407.             return $this->adminJson(['success' => true]);
  408.         }
  409.         return $this->adminJson(['success' => false'message' => "Couldn't delete entry"]);
  410.     }
  411.     /**
  412.      * @Route("/delete-batch")
  413.      *
  414.      * @param Request $request
  415.      *
  416.      * @return JsonResponse
  417.      */
  418.     public function deleteBatchAction(Request $request)
  419.     {
  420.         $this->checkPermission('plugin_pm_permission_delete_monitoring_item');
  421.         $logLevels array_filter(explode(','$request->get('logLevels')));
  422.         if (!empty($logLevels)) {
  423.             $list = new MonitoringItem\Listing();
  424.             $conditions = [];
  425.             foreach ($logLevels as $loglevel) {
  426.                 $conditions[] = ' status ="'.$loglevel.'" ';
  427.             }
  428.             $condition implode(' OR '$conditions);
  429.             $list->setCondition($condition);
  430.             $items $list->load();
  431.             foreach ($items as $item) {
  432.                 $item->delete();
  433.             }
  434.             return $this->adminJson(['success' => true]);
  435.         } else {
  436.             return $this->adminJson(
  437.                 [
  438.                     'success' => false,
  439.                     'message' => 'No statuses -> didn\'t deleted logs. Please select at least one status',
  440.                 ]
  441.             );
  442.         }
  443.     }
  444.     /**
  445.      * @Route("/cancel")
  446.      *
  447.      * @param Request $request
  448.      *
  449.      * @return JsonResponse
  450.      */
  451.     public function cancelAction(Request $request)
  452.     {
  453.         $monitoringItem MonitoringItem::getById($request->get('id'));
  454.         try {
  455.             $pid $monitoringItem->getPid();
  456.             if ($pid) {
  457.                 $status $monitoringItem->stopProcess();
  458.                 $message 'Process with PID "'.$pid.'" killed by Backend User: '.$this->getUser()->getUser()->getName();
  459.                 $monitoringItem->getLogger()->warning($message);
  460.                 foreach($monitoringItem->getChildProcesses() as $child) {
  461.                     $child->stopProcess();
  462.                 }
  463.                 return $this->adminJson(['success' => $status]);
  464.             }
  465.             return $this->adminJson(['success' => true]);
  466.         } catch (\Exception $e) {
  467.             return $this->adminJson(['success' => false'message' => $e->getMessage()]);
  468.         }
  469.     }
  470.     /**
  471.      * @Route("/restart")
  472.      *
  473.      * @param Request $request
  474.      *
  475.      * @return JsonResponse
  476.      */
  477.     public function restartAction(Request $request)
  478.     {
  479.         try {
  480.             $monitoringItem MonitoringItem::getById($request->get('id'));
  481.             $monitoringItem->deleteLogFile()->resetState()->save();
  482.             putenv(ElementsProcessManagerBundle::MONITORING_ITEM_ENV_VAR '=' $monitoringItem->getId());
  483.             $pid \Pimcore\Tool\Console::execInBackground($monitoringItem->getCommand(), $monitoringItem->getLogFile());
  484.             $monitoringItem->setPid($pid)->save();
  485.             return $this->adminJson(['success' => true,'PID' => $pid]);
  486.         } catch (\Exception $e) {
  487.             return $this->adminJson(['success' => false'message' => $e->getMessage()]);
  488.         }
  489.     }
  490.     /**
  491.      * @Route("/get-by-id")
  492.      *
  493.      * @param Request $request
  494.      *
  495.      * @return JsonResponse
  496.      */
  497.     public function getByIdAction(Request $request){
  498.         $data = [];
  499.         $item MonitoringItem::getById($request->get('id'));
  500.         $data $item->getObjectVars();
  501.         $data['callbackSettings'] = json_decode($data['callbackSettings']);
  502.         $data['executorSettings']['values'] = [];
  503.         return $this->adminJson($data);
  504.     }
  505. }