Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@
class="js-select-submit-on-change"
/>
</fields>
</form>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,8 @@

namespace Joomla\Component\Scheduler\Administrator\Controller;

use Joomla\CMS\Access\Exception\NotAllowed;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Controller\AdminController;
use Joomla\Utilities\ArrayHelper;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
Expand Down Expand Up @@ -46,7 +44,7 @@ class LogsController extends AdminController
*
* @since 5.3.0
*/
public function getModel($name = 'Logs', $prefix = 'Administrator', $config = ['ignore_request' => true])
public function getModel($name = 'Log', $prefix = 'Administrator', $config = ['ignore_request' => true])
{
return parent::getModel($name, $prefix, $config);
}
Expand All @@ -73,39 +71,4 @@ public function purge()

$this->setRedirect('index.php?option=com_scheduler&view=logs', $message);
}

/**
* Removes an item.
*
* Overrides Joomla\CMS\MVC\Controller\FormController::delete to check the core.admin permission.
*
* @return void
*
* @since 5.3.0
*/
public function delete(): void
{
$ids = $this->input->get('cid', [], 'array');

if (!$this->app->getIdentity()->authorise('core.admin', $this->option)) {
throw new NotAllowed(Text::_('JERROR_ALERTNOAUTHOR'), 403);
}

if (empty($ids)) {
$this->setMessage(Text::_('COM_SCHEDULER_NO_LOGS_SELECTED'), 'warning');
$this->setRedirect('index.php?option=com_scheduler&view=logs');
return;
}

// Get the model.
$model = $this->getModel();
$ids = ArrayHelper::toInteger($ids);

// Remove the items.
if ($model->delete($ids)) {
$this->setMessage(Text::plural('COM_SCHEDULER_N_ITEMS_DELETED', \count($ids)));
}

$this->setRedirect('index.php?option=com_scheduler&view=logs');
}
}
60 changes: 60 additions & 0 deletions administrator/components/com_scheduler/src/Model/LogModel.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

/**
* @package Joomla.Administrator
* @subpackage com_scheduler
*
* @copyright (C) 2024 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/

namespace Joomla\Component\Scheduler\Administrator\Model;

use Joomla\CMS\Form\Form;
use Joomla\CMS\MVC\Model\AdminModel;
use Joomla\CMS\Table\Table;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

/**
* MVC Model to interact with the Scheduler logs.
*
* @since __DPELOY_VERSION__
*/
class LogModel extends AdminModel
{
/**
* There is no form for the log.
*
* @param array $data Data that needs to go into the form
* @param bool $loadData Should the form load its data from the DB?
*
* @return Form|boolean A Form object on success, false on failure.
*
* @since __DEPLOY_VERSION__
* @throws \Exception
*/
public function getForm($data = [], $loadData = true)
{
return false;
}

/**
* Method to get a table object, load it if necessary.
*
* @param string $name The table name. Optional.
* @param string $prefix The class prefix. Optional.
* @param array $options Configuration array for model. Optional.
*
* @return Table
*
* @since __DEPLOY_VERSION__
* @throws \Exception
*/
public function getTable($name = 'Log', $prefix = 'Administrator', $options = []): Table
{
return parent::getTable($name, $prefix, $options);
}
}
88 changes: 0 additions & 88 deletions administrator/components/com_scheduler/src/Model/LogsModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
// phpcs:enable PSR1.Files.SideEffects

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Component\Scheduler\Administrator\Helper\SchedulerHelper;
Expand Down Expand Up @@ -185,91 +184,4 @@ protected function getListQuery()

return $query;
}

/**
* Delete rows.
*
* @param array $pks The ids of the items to delete.
*
* @return boolean Returns true on success, false on failure.
*/
public function delete($pks)
{
if ($this->canDelete($pks)) {
// Delete logs from list
$db = $this->getDatabase();
$query = $db->getQuery(true)
->delete($db->quoteName('#__scheduler_logs'))
->whereIn($db->quoteName('id'), $pks);

$db->setQuery($query);
$this->setError((string) $query);

try {
$db->execute();
} catch (\RuntimeException $e) {
$this->setError($e->getMessage());

return false;
}
} else {
Factory::getApplication()->enqueueMessage(Text::_('JERROR_CORE_DELETE_NOT_PERMITTED'), 'error');
}

return true;
}

/**
* Determine whether a record may be deleted taking into consideration
* the user's permissions over the record.
*
* @param object $record The database row/record in question
*
* @return boolean True if the record may be deleted
*
* @since 5.3.0
* @throws \Exception
*/
protected function canDelete($record): bool
{
// Record doesn't exist, can't delete
if (empty($record)) {
return false;
}

return Factory::getApplication()->getIdentity()->authorise('core.delete', 'com_scheduler');
}

/**
* @param array $data The task execution data.
*
* @return void
*
* @since 5.3.0
* @throws Exception
*/
public function logTask(array $data): void
{
$model = Factory::getApplication()->bootComponent('com_scheduler')
->getMVCFactory()->createModel('Task', 'Administrator', ['ignore_request' => true]);
$taskInfo = $model->getItem($data['TASK_ID']);
$taskOptions = SchedulerHelper::getTaskOptions();
$safeTypeTitle = $taskOptions->findOption($taskInfo->type)->title ?? '';
$duration = ($data['TASK_DURATION'] ?? 0);
$created = Factory::getDate()->toSql();

/** @var \Joomla\Component\Schduler\Administrator\Table\LogsTable $table */
$logsTable = $this->getTable();
$logsTable->tasktype = $safeTypeTitle;
$logsTable->taskname = $data['TASK_TITLE'];
$logsTable->duration = $duration;
$logsTable->jobid = $data['TASK_ID'];
$logsTable->exitcode = $data['EXIT_CODE'];
$logsTable->taskid = $data['TASK_TIMES'];
$logsTable->lastdate = $created;
$logsTable->nextdate = $taskInfo->next_execution;

// Log the execution of the task.
$logsTable->store();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ protected function populateState(): void
* @since 4.1.0
* @throws \Exception
*/
public function getTable($name = 'Task', $prefix = 'Table', $options = []): Table
public function getTable($name = 'Task', $prefix = 'Administrator', $options = []): Table
{
return parent::getTable($name, $prefix, $options);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
*
* @since 5.3.0
*/
class LogsTable extends Table
class LogTable extends Table
{
/**
* Constructor
Expand Down
3 changes: 2 additions & 1 deletion administrator/language/en-GB/com_scheduler.ini
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ COM_SCHEDULER_LAST_RUN_ASC="Last Run ascending"
COM_SCHEDULER_LAST_RUN_DATE="Last Run Date"
COM_SCHEDULER_LAST_RUN_DESC="Last Run descending"
COM_SCHEDULER_LOGS_CLEAR="All execution history logs have been deleted."
COM_SCHEDULER_LOGS_N_ITEMS_DELETED="%d logs deleted."
COM_SCHEDULER_LOGS_N_ITEMS_DELETED_1="Log deleted."
COM_SCHEDULER_MANAGER_TASKS="Scheduled Tasks"
COM_SCHEDULER_MANAGER_TASK_EDIT="Edit Task"
COM_SCHEDULER_MANAGER_TASK_NEW="New Task"
Expand All @@ -119,7 +121,6 @@ COM_SCHEDULER_N_ITEMS_UNPUBLISHED="%d tasks disabled."
COM_SCHEDULER_N_ITEMS_UNPUBLISHED_1="Task disabled."
COM_SCHEDULER_N_ITEMS_UNLOCKED="%d tasks unlocked."
COM_SCHEDULER_N_ITEMS_UNLOCKED_1="Task unlocked."
COM_SCHEDULER_NO_LOGS_SELECTED="No execution history logs selected."
COM_SCHEDULER_OPTION_EXECUTION_MANUAL_LABEL="Manual Execution"
COM_SCHEDULER_OPTION_ORPHANED_HIDE="Hide Orphaned"
COM_SCHEDULER_OPTION_ORPHANED_ONLY="Only Orphaned"
Expand Down
58 changes: 39 additions & 19 deletions plugins/system/tasknotification/src/Extension/TaskNotification.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@

use Joomla\CMS\Event\Model;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Mail\MailTemplate;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\User\UserFactoryAwareTrait;
use Joomla\Component\Scheduler\Administrator\Helper\SchedulerHelper;
use Joomla\Component\Scheduler\Administrator\Task\Status;
use Joomla\Component\Scheduler\Administrator\Task\Task;
use Joomla\Database\DatabaseAwareTrait;
Expand Down Expand Up @@ -125,13 +125,8 @@ public function notifyFailure(Event $event): void
{
/** @var Task $task */
$task = $event->getArgument('subject');

// @todo safety checks, multiple files [?]
$outFile = $event->getArgument('subject')->snapshot['output_file'] ?? '';
$data = $this->getDataFromTask($event->getArgument('subject'));
$model = $this->getApplication()->bootComponent('com_scheduler')
->getMVCFactory()->createModel('Task', 'Administrator', ['ignore_request' => true]);
$model->logTask($data);
$data = $this->getDataFromTask($event->getArgument('subject'));
$this->saveLog($data);

if (!(int) $task->get('params.notifications.failure_mail', 1)) {
return;
Expand All @@ -140,6 +135,8 @@ public function notifyFailure(Event $event): void
// Load translations
$this->loadLanguage();

// @todo safety checks, multiple files [?]
$outFile = $event->getArgument('subject')->snapshot['output_file'] ?? '';
$this->sendMail('plg_system_tasknotification.failure_mail', $data, $outFile);
}

Expand Down Expand Up @@ -185,20 +182,18 @@ public function notifySuccess(Event $event): void
{
/** @var Task $task */
$task = $event->getArgument('subject');

// @todo safety checks, multiple files [?]
$outFile = $event->getArgument('subject')->snapshot['output_file'] ?? '';
$data = $this->getDataFromTask($event->getArgument('subject'));
$model = $this->getApplication()->bootComponent('com_scheduler')
->getMVCFactory()->createModel('Logs', 'Administrator', ['ignore_request' => true]);
$model->logTask($data);
$data = $this->getDataFromTask($event->getArgument('subject'));
$this->saveLog($data);

if (!(int) $task->get('params.notifications.success_mail', 0)) {
return;
}

// Load translations
$this->loadLanguage();

// @todo safety checks, multiple files [?]
$outFile = $event->getArgument('subject')->snapshot['output_file'] ?? '';
$this->sendMail('plg_system_tasknotification.success_mail', $data, $outFile);
}

Expand All @@ -214,10 +209,7 @@ public function notifySuccess(Event $event): void
*/
public function notifyWillResume(Event $event): void
{
$data = $this->getDataFromTask($event->getArgument('subject'));
$model = $this->getApplication()->bootComponent('com_scheduler')
->getMVCFactory()->createModel('Logs', 'Administrator', ['ignore_request' => true]);
$model->logTask($data);
$this->saveLog($this->getDataFromTask($event->getArgument('subject')));
}

/**
Expand Down Expand Up @@ -341,4 +333,32 @@ private function sendMail(string $template, array $data, string $attachment = ''
Log::add($this->getApplication()->getLanguage()->_('PLG_SYSTEM_TASK_NOTIFICATION_NO_MAIL_SENT'), Log::WARNING);
}
}

/**
* @param array $data The form data
*
* @return void
*
* @since __DEPLOY_VERSION__
* @throws \Exception
*/
private function saveLog(array $data): void
{
$model = $this->getApplication()->bootComponent('com_scheduler')->getMVCFactory()->createModel('Task', 'Administrator', ['ignore_request' => true]);
$taskInfo = $model->getItem($data['TASK_ID']);

$obj = new \stdClass();
$obj->tasktype = SchedulerHelper::getTaskOptions()->findOption($taskInfo->type)->title ?? '';
$obj->taskname = $data['TASK_TITLE'];
$obj->duration = $data['TASK_DURATION'] ?? 0;
$obj->jobid = $data['TASK_ID'];
$obj->exitcode = $data['EXIT_CODE'];
$obj->taskid = $data['TASK_TIMES'];
$obj->lastdate = Factory::getDate()->toSql();
$obj->nextdate = $taskInfo->next_execution;

$model = $this->getApplication()->bootComponent('com_scheduler')
->getMVCFactory()->createModel('Log', 'Administrator', ['ignore_request' => true]);
$model->save((array)$obj);
}
}