99use Illuminate \Http \JsonResponse ;
1010use Pterodactyl \Facades \Activity ;
1111use Pterodactyl \Models \Permission ;
12+ use Illuminate \Database \ConnectionInterface ;
1213use Pterodactyl \Repositories \Eloquent \TaskRepository ;
1314use Pterodactyl \Exceptions \Http \HttpForbiddenException ;
1415use Pterodactyl \Transformers \Api \Client \TaskTransformer ;
@@ -23,8 +24,10 @@ class ScheduleTaskController extends ClientApiController
2324 /**
2425 * ScheduleTaskController constructor.
2526 */
26- public function __construct (private TaskRepository $ repository )
27- {
27+ public function __construct (
28+ private ConnectionInterface $ connection ,
29+ private TaskRepository $ repository
30+ ) {
2831 parent ::__construct ();
2932 }
3033
@@ -49,14 +52,30 @@ public function store(StoreTaskRequest $request, Server $server, Schedule $sched
4952 $ lastTask = $ schedule ->tasks ()->orderByDesc ('sequence_id ' )->first ();
5053
5154 /** @var \Pterodactyl\Models\Task $task */
52- $ task = $ this ->repository ->create ([
53- 'schedule_id ' => $ schedule ->id ,
54- 'sequence_id ' => ($ lastTask ->sequence_id ?? 0 ) + 1 ,
55- 'action ' => $ request ->input ('action ' ),
56- 'payload ' => $ request ->input ('payload ' ) ?? '' ,
57- 'time_offset ' => $ request ->input ('time_offset ' ),
58- 'continue_on_failure ' => (bool ) $ request ->input ('continue_on_failure ' ),
59- ]);
55+ $ task = $ this ->connection ->transaction (function () use ($ request , $ schedule , $ lastTask ) {
56+ $ sequenceId = ($ lastTask ->sequence_id ?? 0 ) + 1 ;
57+ $ requestSequenceId = $ request ->integer ('sequence_id ' , $ sequenceId );
58+
59+ // If the sequence id from the request is greater than or equal to the next available
60+ // sequence id, we don't need to do anything special. Otherwise, we need to update
61+ // the sequence id of all tasks that are greater than or equal to the request sequence
62+ // id to be one greater than the current value.
63+ if ($ requestSequenceId < $ sequenceId ) {
64+ $ schedule ->tasks ()
65+ ->where ('sequence_id ' , '>= ' , $ requestSequenceId )
66+ ->increment ('sequence_id ' );
67+ $ sequenceId = $ requestSequenceId ;
68+ }
69+
70+ return $ this ->repository ->create ([
71+ 'schedule_id ' => $ schedule ->id ,
72+ 'sequence_id ' => $ sequenceId ,
73+ 'action ' => $ request ->input ('action ' ),
74+ 'payload ' => $ request ->input ('payload ' ) ?? '' ,
75+ 'time_offset ' => $ request ->input ('time_offset ' ),
76+ 'continue_on_failure ' => $ request ->boolean ('continue_on_failure ' ),
77+ ]);
78+ });
6079
6180 Activity::event ('server:task.create ' )
6281 ->subject ($ schedule , $ task )
@@ -84,12 +103,30 @@ public function update(StoreTaskRequest $request, Server $server, Schedule $sche
84103 throw new HttpForbiddenException ("A backup task cannot be created when the server's backup limit is set to 0. " );
85104 }
86105
87- $ this ->repository ->update ($ task ->id , [
88- 'action ' => $ request ->input ('action ' ),
89- 'payload ' => $ request ->input ('payload ' ) ?? '' ,
90- 'time_offset ' => $ request ->input ('time_offset ' ),
91- 'continue_on_failure ' => (bool ) $ request ->input ('continue_on_failure ' ),
92- ]);
106+ $ this ->connection ->transaction (function () use ($ request , $ schedule , $ task ) {
107+ $ sequenceId = $ request ->integer ('sequence_id ' , $ task ->sequence_id );
108+
109+ // Shift all other tasks in the schedule up or down to make room for the new task.
110+ if ($ sequenceId < $ task ->sequence_id ) {
111+ $ schedule ->tasks ()
112+ ->where ('sequence_id ' , '>= ' , $ sequenceId )
113+ ->where ('sequence_id ' , '< ' , $ task ->sequence_id )
114+ ->increment ('sequence_id ' );
115+ } elseif ($ sequenceId > $ task ->sequence_id ) {
116+ $ schedule ->tasks ()
117+ ->where ('sequence_id ' , '> ' , $ task ->sequence_id )
118+ ->where ('sequence_id ' , '<= ' , $ sequenceId )
119+ ->decrement ('sequence_id ' );
120+ }
121+
122+ $ this ->repository ->update ($ task ->id , [
123+ 'sequence_id ' => $ sequenceId ,
124+ 'action ' => $ request ->input ('action ' ),
125+ 'payload ' => $ request ->input ('payload ' ) ?? '' ,
126+ 'time_offset ' => $ request ->input ('time_offset ' ),
127+ 'continue_on_failure ' => $ request ->boolean ('continue_on_failure ' ),
128+ ]);
129+ });
93130
94131 Activity::event ('server:task.update ' )
95132 ->subject ($ schedule , $ task )
@@ -117,10 +154,9 @@ public function delete(ClientApiRequest $request, Server $server, Schedule $sche
117154 throw new HttpForbiddenException ('You do not have permission to perform this action. ' );
118155 }
119156
120- $ schedule ->tasks ()->where ('sequence_id ' , '> ' , $ task ->sequence_id )->update ([
121- 'sequence_id ' => $ schedule ->tasks ()->getConnection ()->raw ('(sequence_id - 1) ' ),
122- ]);
123-
157+ $ schedule ->tasks ()
158+ ->where ('sequence_id ' , '> ' , $ task ->sequence_id )
159+ ->decrement ('sequence_id ' );
124160 $ task ->delete ();
125161
126162 Activity::event ('server:task.delete ' )->subject ($ schedule , $ task )->property ('name ' , $ schedule ->name )->log ();
0 commit comments