diff --git a/CHANGELOG.md b/CHANGELOG.md index d5694a9e7..f7fd464bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ This project follows [Semantic Versioning](http://semver.org) guidelines. ### Changed * Changed logger to skip reporting stack-traces on PDO exceptions due to sensitive information being contained within. +### Added +* Added support for editing an existing schedule. + ## v0.7.0-rc.1 (Derelict Dermodactylus) ### Fixed * `[beta.4]` — Fixes some bad search and replace action that happened previously and was throwing errors when validating user permissions. diff --git a/app/Http/Controllers/Server/Tasks/TaskManagementController.php b/app/Http/Controllers/Server/Tasks/TaskManagementController.php index 238846258..9805b5cff 100644 --- a/app/Http/Controllers/Server/Tasks/TaskManagementController.php +++ b/app/Http/Controllers/Server/Tasks/TaskManagementController.php @@ -10,6 +10,7 @@ use Prologue\Alerts\AlertsMessageBag; use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Contracts\Extensions\HashidsInterface; use Pterodactyl\Traits\Controllers\JavascriptInjection; +use Pterodactyl\Services\Schedules\ScheduleUpdateService; use Pterodactyl\Services\Schedules\ScheduleCreationService; use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface; use Pterodactyl\Http\Requests\Server\ScheduleCreationFormRequest; @@ -38,24 +39,32 @@ class TaskManagementController extends Controller */ protected $repository; + /** + * @var \Pterodactyl\Services\Schedules\ScheduleUpdateService + */ + private $updateService; + /** * TaskManagementController constructor. * * @param \Prologue\Alerts\AlertsMessageBag $alert * @param \Pterodactyl\Contracts\Extensions\HashidsInterface $hashids * @param \Pterodactyl\Services\Schedules\ScheduleCreationService $creationService + * @param \Pterodactyl\Services\Schedules\ScheduleUpdateService $updateService * @param \Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface $repository */ public function __construct( AlertsMessageBag $alert, HashidsInterface $hashids, ScheduleCreationService $creationService, + ScheduleUpdateService $updateService, ScheduleRepositoryInterface $repository ) { $this->alert = $alert; $this->creationService = $creationService; $this->hashids = $hashids; $this->repository = $repository; + $this->updateService = $updateService; } /** @@ -112,7 +121,7 @@ class TaskManagementController extends Controller $server = $request->attributes->get('server'); $schedule = $this->creationService->handle($server, $request->normalize(), $request->getTasks()); - $this->alert->success(trans('server.schedule.task_created'))->flash(); + $this->alert->success(trans('server.schedule.schedule_created'))->flash(); return redirect()->route('server.schedules.view', [ 'server' => $server->uuidShort, @@ -149,15 +158,18 @@ class TaskManagementController extends Controller * * @param \Pterodactyl\Http\Requests\Server\ScheduleCreationFormRequest $request * @return \Illuminate\Http\RedirectResponse + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + * @throws \Pterodactyl\Exceptions\Service\Schedule\Task\TaskIntervalTooLongException */ public function update(ScheduleCreationFormRequest $request): RedirectResponse { $server = $request->attributes->get('server'); $schedule = $request->attributes->get('schedule'); - $this->alert->warning('Function is not implemented.')->flash(); - // $this->updateService->handle($task, $request->normalize(), $request->getChainedTasks()); - // $this->alert->success(trans('server.schedules.task_updated'))->flash(); + $this->updateService->handle($schedule, $request->normalize(), $request->getTasks()); + $this->alert->success(trans('server.schedule.schedule_updated'))->flash(); return redirect()->route('server.schedules.view', [ 'server' => $server->uuidShort, diff --git a/app/Services/Schedules/ScheduleUpdateService.php b/app/Services/Schedules/ScheduleUpdateService.php new file mode 100644 index 000000000..fd29d9c2d --- /dev/null +++ b/app/Services/Schedules/ScheduleUpdateService.php @@ -0,0 +1,107 @@ +connection = $connection; + $this->repository = $repository; + $this->taskCreationService = $taskCreationService; + $this->taskRepository = $taskRepository; + } + + /** + * Update an existing schedule by deleting all current tasks and re-inserting the + * new values. + * + * @param \Pterodactyl\Models\Schedule $schedule + * @param array $data + * @param array $tasks + * @return \Pterodactyl\Models\Schedule + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + * @throws \Pterodactyl\Exceptions\Service\Schedule\Task\TaskIntervalTooLongException + */ + public function handle(Schedule $schedule, array $data, array $tasks): Schedule + { + $data = array_merge($data, [ + 'next_run_at' => $this->getCronTimestamp($data), + ]); + + $this->connection->beginTransaction(); + + $schedule = $this->repository->update($schedule->id, $data); + $this->taskRepository->deleteWhere([['schedule_id', '=', $schedule->id]]); + + foreach ($tasks as $index => $task) { + $this->taskCreationService->handle($schedule, [ + 'time_interval' => array_get($task, 'time_interval'), + 'time_value' => array_get($task, 'time_value'), + 'sequence_id' => $index + 1, + 'action' => array_get($task, 'action'), + 'payload' => array_get($task, 'payload'), + ], false); + } + + $this->connection->commit(); + + return $schedule; + } + + /** + * Return a DateTime object after parsing the cron data provided. + * + * @param array $data + * @return \DateTime + */ + private function getCronTimestamp(array $data) + { + $formattedCron = sprintf('%s %s %s * %s *', + array_get($data, 'cron_minute', '*'), + array_get($data, 'cron_hour', '*'), + array_get($data, 'cron_day_of_month', '*'), + array_get($data, 'cron_day_of_week', '*') + ); + + return CronExpression::factory($formattedCron)->getNextRunDate(); + } +} diff --git a/app/Services/Schedules/Tasks/TaskCreationService.php b/app/Services/Schedules/Tasks/TaskCreationService.php index 8ed06e5fd..6cf4fc384 100644 --- a/app/Services/Schedules/Tasks/TaskCreationService.php +++ b/app/Services/Schedules/Tasks/TaskCreationService.php @@ -63,7 +63,7 @@ class TaskCreationService 'action' => $data['action'], 'payload' => $data['payload'], 'time_offset' => $delay, - ]); + ], false); return $task; } diff --git a/resources/lang/en/server.php b/resources/lang/en/server.php index 4cb73a0f6..115becd83 100644 --- a/resources/lang/en/server.php +++ b/resources/lang/en/server.php @@ -33,6 +33,7 @@ return [ 'toggle' => 'Toggle Status', 'run_now' => 'Trigger Schedule', 'schedule_created' => 'Successfully created a new schedule for this server.', + 'schedule_updated' => 'Schedule has been updated.', 'unnamed' => 'Unnamed Schedule', 'setup' => 'Schedule Setup', 'day_of_week' => 'Day of Week',