Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/app/Http/Controllers/Api/Client/Servers/ScheduleController.php
10280 views
1
<?php
2
3
namespace Pterodactyl\Http\Controllers\Api\Client\Servers;
4
5
use Carbon\Carbon;
6
use Illuminate\Http\Request;
7
use Illuminate\Http\Response;
8
use Pterodactyl\Models\Server;
9
use Pterodactyl\Models\Schedule;
10
use Illuminate\Http\JsonResponse;
11
use Pterodactyl\Facades\Activity;
12
use Pterodactyl\Helpers\Utilities;
13
use Pterodactyl\Exceptions\DisplayException;
14
use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
15
use Pterodactyl\Services\Schedules\ProcessScheduleService;
16
use Pterodactyl\Transformers\Api\Client\ScheduleTransformer;
17
use Pterodactyl\Http\Controllers\Api\Client\ClientApiController;
18
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
19
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\ViewScheduleRequest;
20
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\StoreScheduleRequest;
21
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\DeleteScheduleRequest;
22
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\UpdateScheduleRequest;
23
use Pterodactyl\Http\Requests\Api\Client\Servers\Schedules\TriggerScheduleRequest;
24
25
class ScheduleController extends ClientApiController
26
{
27
/**
28
* ScheduleController constructor.
29
*/
30
public function __construct(private ScheduleRepository $repository, private ProcessScheduleService $service)
31
{
32
parent::__construct();
33
}
34
35
/**
36
* Returns all the schedules belonging to a given server.
37
*/
38
public function index(ViewScheduleRequest $request, Server $server): array
39
{
40
$schedules = $server->schedules->loadMissing('tasks');
41
42
return $this->fractal->collection($schedules)
43
->transformWith($this->getTransformer(ScheduleTransformer::class))
44
->toArray();
45
}
46
47
/**
48
* Store a new schedule for a server.
49
*
50
* @throws DisplayException
51
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
52
*/
53
public function store(StoreScheduleRequest $request, Server $server): array
54
{
55
/** @var Schedule $model */
56
$model = $this->repository->create([
57
'server_id' => $server->id,
58
'name' => $request->input('name'),
59
'cron_day_of_week' => $request->input('day_of_week'),
60
'cron_month' => $request->input('month'),
61
'cron_day_of_month' => $request->input('day_of_month'),
62
'cron_hour' => $request->input('hour'),
63
'cron_minute' => $request->input('minute'),
64
'is_active' => (bool) $request->input('is_active'),
65
'only_when_online' => (bool) $request->input('only_when_online'),
66
'next_run_at' => $this->getNextRunAt($request),
67
]);
68
69
Activity::event('server:schedule.create')
70
->subject($model)
71
->property('name', $model->name)
72
->log();
73
74
return $this->fractal->item($model)
75
->transformWith($this->getTransformer(ScheduleTransformer::class))
76
->toArray();
77
}
78
79
/**
80
* Returns a specific schedule for the server.
81
*/
82
public function view(ViewScheduleRequest $request, Server $server, Schedule $schedule): array
83
{
84
if ($schedule->server_id !== $server->id) {
85
throw new NotFoundHttpException();
86
}
87
88
$schedule->loadMissing('tasks');
89
90
return $this->fractal->item($schedule)
91
->transformWith($this->getTransformer(ScheduleTransformer::class))
92
->toArray();
93
}
94
95
/**
96
* Updates a given schedule with the new data provided.
97
*
98
* @throws DisplayException
99
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
100
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
101
*/
102
public function update(UpdateScheduleRequest $request, Server $server, Schedule $schedule): array
103
{
104
$active = (bool) $request->input('is_active');
105
106
$data = [
107
'name' => $request->input('name'),
108
'cron_day_of_week' => $request->input('day_of_week'),
109
'cron_month' => $request->input('month'),
110
'cron_day_of_month' => $request->input('day_of_month'),
111
'cron_hour' => $request->input('hour'),
112
'cron_minute' => $request->input('minute'),
113
'is_active' => $active,
114
'only_when_online' => (bool) $request->input('only_when_online'),
115
'next_run_at' => $this->getNextRunAt($request),
116
];
117
118
// Toggle the processing state of the scheduled task when it is enabled or disabled so that an
119
// invalid state can be reset without manual database intervention.
120
//
121
// @see https://github.com/pterodactyl/panel/issues/2425
122
if ($schedule->is_active !== $active) {
123
$data['is_processing'] = false;
124
}
125
126
$this->repository->update($schedule->id, $data);
127
128
Activity::event('server:schedule.update')
129
->subject($schedule)
130
->property(['name' => $schedule->name, 'active' => $active])
131
->log();
132
133
return $this->fractal->item($schedule->refresh())
134
->transformWith($this->getTransformer(ScheduleTransformer::class))
135
->toArray();
136
}
137
138
/**
139
* Executes a given schedule immediately rather than waiting on it's normally scheduled time
140
* to pass. This does not care about the schedule state.
141
*
142
* @throws \Throwable
143
*/
144
public function execute(TriggerScheduleRequest $request, Server $server, Schedule $schedule): JsonResponse
145
{
146
$this->service->handle($schedule, true);
147
148
Activity::event('server:schedule.execute')->subject($schedule)->property('name', $schedule->name)->log();
149
150
return new JsonResponse([], JsonResponse::HTTP_ACCEPTED);
151
}
152
153
/**
154
* Deletes a schedule and it's associated tasks.
155
*/
156
public function delete(DeleteScheduleRequest $request, Server $server, Schedule $schedule): JsonResponse
157
{
158
$this->repository->delete($schedule->id);
159
160
Activity::event('server:schedule.delete')->subject($schedule)->property('name', $schedule->name)->log();
161
162
return new JsonResponse([], Response::HTTP_NO_CONTENT);
163
}
164
165
/**
166
* Get the next run timestamp based on the cron data provided.
167
*
168
* @throws DisplayException
169
*/
170
protected function getNextRunAt(Request $request): Carbon
171
{
172
try {
173
return Utilities::getScheduleNextRunDate(
174
$request->input('minute'),
175
$request->input('hour'),
176
$request->input('day_of_month'),
177
$request->input('month'),
178
$request->input('day_of_week')
179
);
180
} catch (\Exception $exception) {
181
throw new DisplayException('The cron data provided does not evaluate to a valid expression.');
182
}
183
}
184
}
185
186