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