Path: blob/1.0-develop/app/Http/Controllers/Api/Client/Servers/ScheduleController.php
10280 views
<?php12namespace Pterodactyl\Http\Controllers\Api\Client\Servers;34use Carbon\Carbon;5use Illuminate\Http\Request;6use Illuminate\Http\Response;7use Pterodactyl\Models\Server;8use Pterodactyl\Models\Schedule;9use Illuminate\Http\JsonResponse;10use Pterodactyl\Facades\Activity;11use Pterodactyl\Helpers\Utilities;12use Pterodactyl\Exceptions\DisplayException;13use Pterodactyl\Repositories\Eloquent\ScheduleRepository;14use Pterodactyl\Services\Schedules\ProcessScheduleService;15use Pterodactyl\Transformers\Api\Client\ScheduleTransformer;16use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;17use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;18use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\ViewScheduleRequest;19use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\StoreScheduleRequest;20use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\DeleteScheduleRequest;21use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\UpdateScheduleRequest;22use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\TriggerScheduleRequest;2324class ScheduleController extends ClientApiController25{26/**27* ScheduleController constructor.28*/29public function __construct(private ScheduleRepository $repository, private ProcessScheduleService $service)30{31parent::__construct();32}3334/**35* Returns all the schedules belonging to a given server.36*/37public function index(ViewScheduleRequest $request, Server $server): array38{39$schedules = $server->schedules->loadMissing('tasks');4041return $this->fractal->collection($schedules)42->transformWith($this->getTransformer(ScheduleTransformer::class))43->toArray();44}4546/**47* Store a new schedule for a server.48*49* @throws DisplayException50* @throws \Pterodactyl\Exceptions\Model\DataValidationException51*/52public function store(StoreScheduleRequest $request, Server $server): array53{54/** @var Schedule $model */55$model = $this->repository->create([56'server_id' => $server->id,57'name' => $request->input('name'),58'cron_day_of_week' => $request->input('day_of_week'),59'cron_month' => $request->input('month'),60'cron_day_of_month' => $request->input('day_of_month'),61'cron_hour' => $request->input('hour'),62'cron_minute' => $request->input('minute'),63'is_active' => (bool) $request->input('is_active'),64'only_when_online' => (bool) $request->input('only_when_online'),65'next_run_at' => $this->getNextRunAt($request),66]);6768Activity::event('server:schedule.create')69->subject($model)70->property('name', $model->name)71->log();7273return $this->fractal->item($model)74->transformWith($this->getTransformer(ScheduleTransformer::class))75->toArray();76}7778/**79* Returns a specific schedule for the server.80*/81public function view(ViewScheduleRequest $request, Server $server, Schedule $schedule): array82{83if ($schedule->server_id !== $server->id) {84throw new NotFoundHttpException();85}8687$schedule->loadMissing('tasks');8889return $this->fractal->item($schedule)90->transformWith($this->getTransformer(ScheduleTransformer::class))91->toArray();92}9394/**95* Updates a given schedule with the new data provided.96*97* @throws DisplayException98* @throws \Pterodactyl\Exceptions\Model\DataValidationException99* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException100*/101public function update(UpdateScheduleRequest $request, Server $server, Schedule $schedule): array102{103$active = (bool) $request->input('is_active');104105$data = [106'name' => $request->input('name'),107'cron_day_of_week' => $request->input('day_of_week'),108'cron_month' => $request->input('month'),109'cron_day_of_month' => $request->input('day_of_month'),110'cron_hour' => $request->input('hour'),111'cron_minute' => $request->input('minute'),112'is_active' => $active,113'only_when_online' => (bool) $request->input('only_when_online'),114'next_run_at' => $this->getNextRunAt($request),115];116117// Toggle the processing state of the scheduled task when it is enabled or disabled so that an118// invalid state can be reset without manual database intervention.119//120// @see https://github.com/pterodactyl/panel/issues/2425121if ($schedule->is_active !== $active) {122$data['is_processing'] = false;123}124125$this->repository->update($schedule->id, $data);126127Activity::event('server:schedule.update')128->subject($schedule)129->property(['name' => $schedule->name, 'active' => $active])130->log();131132return $this->fractal->item($schedule->refresh())133->transformWith($this->getTransformer(ScheduleTransformer::class))134->toArray();135}136137/**138* Executes a given schedule immediately rather than waiting on it's normally scheduled time139* to pass. This does not care about the schedule state.140*141* @throws \Throwable142*/143public function execute(TriggerScheduleRequest $request, Server $server, Schedule $schedule): JsonResponse144{145$this->service->handle($schedule, true);146147Activity::event('server:schedule.execute')->subject($schedule)->property('name', $schedule->name)->log();148149return new JsonResponse([], JsonResponse::HTTP_ACCEPTED);150}151152/**153* Deletes a schedule and it's associated tasks.154*/155public function delete(DeleteScheduleRequest $request, Server $server, Schedule $schedule): JsonResponse156{157$this->repository->delete($schedule->id);158159Activity::event('server:schedule.delete')->subject($schedule)->property('name', $schedule->name)->log();160161return new JsonResponse([], Response::HTTP_NO_CONTENT);162}163164/**165* Get the next run timestamp based on the cron data provided.166*167* @throws DisplayException168*/169protected function getNextRunAt(Request $request): Carbon170{171try {172return Utilities::getScheduleNextRunDate(173$request->input('minute'),174$request->input('hour'),175$request->input('day_of_month'),176$request->input('month'),177$request->input('day_of_week')178);179} catch (\Exception $exception) {180throw new DisplayException('The cron data provided does not evaluate to a valid expression.');181}182}183}184185186