芝麻web文件管理V1.00
编辑当前文件:/home/mgatv524/public_html/shimoda/lib/Controller/Task.php
setCommonDependencies($log, $sanitizerService, $state, $user, $help, $date, $config); $this->taskFactory = $taskFactory; $this->store = $store; $this->userGroupFactory = $userGroupFactory; $this->pool = $pool; $this->userFactory = $userFactory; $this->layoutFactory = $layoutFactory; $this->displayFactory = $displayFactory; $this->upgradeFactory = $upgradeFactory; $this->mediaFactory = $mediaFactory; $this->notificationFactory = $notificationFactory; $this->userNotificationFactory = $userNotificationFactory; } /** * Display Page */ public function displayPage() { $this->getState()->template = 'task-page'; } /** * Grid */ public function grid() { $tasks = $this->taskFactory->query($this->gridRenderSort(), $this->gridRenderFilter()); foreach ($tasks as $task) { /** @var \Xibo\Entity\Task $task */ $task->nextRunDt = $task->nextRunDate(); if ($this->isApi()) continue; $task->includeProperty('buttons'); $task->buttons[] = array( 'id' => 'task_button_run.now', 'url' => $this->urlFor('task.runNow.form', ['id' => $task->taskId]), 'text' => __('Run Now') ); // Don't show any edit buttons if the config is locked. if ($this->getConfig()->GetSetting('TASK_CONFIG_LOCKED_CHECKB') == 'Checked') continue; // Edit Button $task->buttons[] = array( 'id' => 'task_button_edit', 'url' => $this->urlFor('task.edit.form', ['id' => $task->taskId]), 'text' => __('Edit') ); // Delete Button $task->buttons[] = array( 'id' => 'task_button_delete', 'url' => $this->urlFor('task.delete.form', ['id' => $task->taskId]), 'text' => __('Delete') ); } $this->getState()->template = 'grid'; $this->getState()->recordsTotal = $this->taskFactory->countLast(); $this->getState()->setData($tasks); } /** * Add form */ public function addForm() { // Provide a list of possible task classes by searching for .task file in /tasks and /custom $data = ['tasksAvailable' => []]; // Do we have any modules to install?! if ($this->getConfig()->GetSetting('TASK_CONFIG_LOCKED_CHECKB') != 'Checked') { // Get a list of matching files in the modules folder $files = array_merge(glob(PROJECT_ROOT . '/tasks/*.task'), glob(PROJECT_ROOT . '/custom/*.task')); // Add to the list of available tasks foreach ($files as $file) { $config = json_decode(file_get_contents($file)); $config->file = str_replace_first(PROJECT_ROOT, '', $file); $data['tasksAvailable'][] = $config; } } $this->getState()->template = 'task-form-add'; $this->getState()->setData($data); } /** * Add */ public function add() { $task = $this->taskFactory->create(); $task->name = $this->getSanitizer()->getString('name'); $task->configFile = $this->getSanitizer()->getString('file'); $task->schedule = $this->getSanitizer()->getString('schedule'); $task->status = \Xibo\Entity\Task::$STATUS_IDLE; $task->lastRunStatus = 0; $task->isActive = 0; $task->runNow = 0; $task->setClassAndOptions(); $task->save(); // Return $this->getState()->hydrate([ 'httpStatus' => 201, 'message' => sprintf(__('Added %s'), $task->name), 'id' => $task->taskId, 'data' => $task ]); } /** * Edit Form * @param $taskId */ public function editForm($taskId) { $task = $this->taskFactory->getById($taskId); $task->setClassAndOptions(); $this->getState()->template = 'task-form-edit'; $this->getState()->setData([ 'task' => $task ]); } /** * @param $taskId */ public function edit($taskId) { $task = $this->taskFactory->getById($taskId); $task->setClassAndOptions(); $task->name = $this->getSanitizer()->getString('name'); $task->schedule = $this->getSanitizer()->getString('schedule'); $task->isActive = $this->getSanitizer()->getCheckbox('isActive'); // Loop through each option and see if a new value is provided foreach ($task->options as $option => $value) { $provided = $this->getSanitizer()->getString($option); if ($provided !== null) { $this->getLog()->debug('Setting ' . $option . ' to ' . $provided); $task->options[$option] = $provided; } } $this->getLog()->debug('New options = ' . var_export($task->options, true)); $task->save(); // Return $this->getState()->hydrate([ 'httpStatus' => 200, 'message' => sprintf(__('Edited %s'), $task->name), 'id' => $task->taskId, 'data' => $task ]); } /** * Delete Form * @param $taskId */ public function deleteForm($taskId) { $task = $this->taskFactory->getById($taskId); $this->getState()->template = 'task-form-delete'; $this->getState()->setData([ 'task' => $task ]); } /** * @param $taskId */ public function delete($taskId) { $task = $this->taskFactory->getById($taskId); $task->delete(); // Return $this->getState()->hydrate([ 'httpStatus' => 204, 'message' => sprintf(__('Deleted %s'), $task->name) ]); } /** * Delete Form * @param $taskId */ public function runNowForm($taskId) { $task = $this->taskFactory->getById($taskId); $this->getState()->template = 'task-form-run-now'; $this->getState()->setData([ 'task' => $task ]); } /** * @param $taskId */ public function runNow($taskId) { $task = $this->taskFactory->getById($taskId); $task->runNow = 1; $task->save(); // Return $this->getState()->hydrate([ 'httpStatus' => 204, 'message' => sprintf(__('Run Now set on %s'), $task->name) ]); } /** * @param $taskId * @throws \Exception */ public function run($taskId) { // Handle cases where we arrive from older versions of the application. // that is versions without tasks if (DBVERSION < 128) { // We need to manually create and run task 1 so that we trigger an upgrade. $task = new MaintenanceDailyTask(); $task->setApp($this->getApp()) ->setSanitizer($this->getSanitizer()) ->setUser($this->getUser()) ->setConfig($this->getConfig()) ->setLogger($this->getLog()) ->setDate($this->getDate()) ->setPool($this->pool) ->setStore($this->store) ->setFactories( $this->userFactory, $this->userGroupFactory, $this->layoutFactory, $this->displayFactory, $this->upgradeFactory, $this->mediaFactory, $this->notificationFactory, $this->userNotificationFactory ) ->setTask($task) ->run(); if ($taskId == 1) return; } // Get this task $task = $this->taskFactory->getById($taskId); // Set to running $this->getLog()->debug('Running Task ' . $task->name . ' [' . $task->taskId . ']'); // Run try { // Instantiate if (!class_exists($task->class)) throw new NotFoundException(); /** @var TaskInterface $taskClass */ $taskClass = new $task->class(); // Record the start time $start = time(); $taskClass ->setApp($this->getApp()) ->setSanitizer($this->getSanitizer()) ->setUser($this->getUser()) ->setConfig($this->getConfig()) ->setLogger($this->getLog()) ->setDate($this->getDate()) ->setPool($this->pool) ->setStore($this->store) ->setFactories( $this->userFactory, $this->userGroupFactory, $this->layoutFactory, $this->displayFactory, $this->upgradeFactory, $this->mediaFactory, $this->notificationFactory, $this->userNotificationFactory ) ->setTask($task) ->run(); // We should commit anything this task has done $this->store->commitIfNecessary(); // Collect results $task->lastRunDuration = time() - $start; $task->lastRunMessage = $taskClass->getRunMessage(); $task->lastRunStatus = \Xibo\Entity\Task::$STATUS_SUCCESS; } catch (\Exception $e) { $this->getLog()->error($e->getMessage()); $this->getLog()->debug($e->getTraceAsString()); // We should rollback anything we've done so far if ($this->store->getConnection()->inTransaction()) $this->store->getConnection()->rollBack(); // Set the results to error $task->lastRunMessage = $e->getMessage(); $task->lastRunStatus = \Xibo\Entity\Task::$STATUS_ERROR; } $task->lastRunDt = $this->getDate()->getLocalDate(null, 'U'); $task->runNow = 0; // Save (on the XTR connection) $task->save(['connection' => 'xtr', 'validate' => false]); $this->getLog()->debug('Finished Task ' . $task->name . ' [' . $task->taskId . '] Run Dt: ' . $this->getDate()->getLocalDate()); // No output $this->setNoOutput(true); } /** * Poll for tasks to run * continue polling until there aren't any more to run * allow for multiple polls to run at the same time */ public function poll() { $this->getLog()->debug('XTR poll started'); $this->pollProcessTimeouts(); // The getting/updating of tasks runs in a separate DB connection // Query for a list of tasks to run. $db = $this->store->getConnection('xtr'); // This queries for all enabled tasks, because we need to assess the schedule in code $pollSth = $db->prepare('SELECT taskId, `schedule`, runNow, lastRunDt FROM `task` WHERE isActive = 1 AND `status` <> :status ORDER BY lastRunDuration'); // Update statements $updateSth = $db->prepare('UPDATE `task` SET status = :status WHERE taskId = :taskId'); if (DBVERSION < 133) $updateStartSth = null; else $updateStartSth = $db->prepare('UPDATE `task` SET status = :status, lastRunStartDt = :lastRunStartDt WHERE taskId = :taskId'); $updateFatalErrorSth = $db->prepare('UPDATE `task` SET status = :status, isActive = :isActive, lastRunMessage = :lastRunMessage WHERE taskId = :taskId'); // We loop until we have gone through without running a task // we select new tasks each time while (true) { // Get tasks that aren't running currently $pollSth->execute(['status' => \Xibo\Entity\Task::$STATUS_RUNNING]); $this->store->incrementStat('xtr', 'select'); $tasks = $pollSth->fetchAll(\PDO::FETCH_ASSOC); // Assume we wont run anything $taskRun = false; foreach ($tasks as $task) { /** @var \Xibo\Entity\Task $task */ $taskId = $task['taskId']; $cron = \Cron\CronExpression::factory($task['schedule']); // Is the next run date of this event earlier than now, or is the task set to runNow $nextRunDt = $cron->getNextRunDate(\DateTime::createFromFormat('U', $task['lastRunDt']))->format('U'); if ($task['runNow'] == 1 || $nextRunDt < time()) { $this->getLog()->info('Running Task ' . $taskId); // Set to running if (DBVERSION < 133) { $updateSth->execute([ 'taskId' => $taskId, 'status' => \Xibo\Entity\Task::$STATUS_RUNNING ]); } else { $updateStartSth->execute([ 'taskId' => $taskId, 'status' => \Xibo\Entity\Task::$STATUS_RUNNING, 'lastRunStartDt' => $this->getDate()->getLocalDate(null, 'U') ]); } $this->store->incrementStat('xtr', 'update'); // Pass to run. try { // Run is isolated $this->run($taskId); // Set to idle $updateSth->execute(['taskId' => $taskId, 'status' => \Xibo\Entity\Task::$STATUS_IDLE]); $this->store->incrementStat('xtr', 'update'); } catch (\Exception $exception) { // This is a completely unexpected exception, and we should disable the task $this->getLog()->error('Task run error for taskId ' . $taskId . '. E = ' . $exception->getMessage()); // Set to error $updateFatalErrorSth->execute([ 'taskId' => $taskId, 'status' => \Xibo\Entity\Task::$STATUS_ERROR, 'isActive' => 0, 'lastRunMessage' => 'Fatal Error' ]); $this->store->incrementStat('xtr', 'update'); } // We have run a task $taskRun = true; break; } } // If we haven't run a task, then stop if (!$taskRun) break; } $this->getLog()->debug('XTR poll stopped'); } private function pollProcessTimeouts() { $db = $this->store->getConnection('xtr'); // Not available before 133 (1.8.2) if (DBVERSION < 133) return; // Get timed out tasks and deal with them $command = $db->prepare(' SELECT taskId, lastRunStartDt FROM `task` WHERE isActive = 1 AND `status` = :status AND lastRunStartDt < :timeout '); $updateFatalErrorSth = $db->prepare('UPDATE `task` SET `status` = :status WHERE taskId = :taskId'); $command->execute([ 'status' => \Xibo\Entity\Task::$STATUS_RUNNING, 'timeout' => $this->getDate()->parse()->subHours(12)->format('U') ]); foreach ($command->fetchAll(\PDO::FETCH_ASSOC) as $task) { $this->getLog()->error('Timed out task detected, marking as timed out. TaskId: ' . $task['taskId']); $updateFatalErrorSth->execute([ 'taskId' => intval($task['taskId']), 'status' => \Xibo\Entity\Task::$STATUS_TIMEOUT ]); } } }