@@ -58,18 +58,9 @@ public function __construct(
5858 parent ::__construct ($ appName , $ request );
5959 }
6060
61- /**
62- * Returns all available TaskProcessing task types
63- *
64- * @return DataResponse<Http::STATUS_OK, array{types: array<string, CoreTaskProcessingTaskType>}, array{}>
65- *
66- * 200: Task types returned
67- */
68- #[NoAdminRequired]
69- #[ApiRoute(verb: 'GET ' , url: '/tasktypes ' , root: '/taskprocessing ' )]
70- public function taskTypes (): DataResponse {
71- /** @var array<string, CoreTaskProcessingTaskType> $taskTypes */
72- $ taskTypes = array_map (function (array $ tt ) {
61+ private function getTaskTypesInternal (): array {
62+ /** @var array<string, CoreTaskProcessingTaskType> */
63+ return array_map (function (array $ tt ) {
7364 $ tt ['inputShape ' ] = array_map (function ($ descriptor ) {
7465 return $ descriptor ->jsonSerialize ();
7566 }, $ tt ['inputShape ' ]);
@@ -134,11 +125,74 @@ public function taskTypes(): DataResponse {
134125 }
135126 return $ tt ;
136127 }, $ this ->taskProcessingManager ->getAvailableTaskTypes ());
128+ }
129+
130+ /**
131+ * Returns all available TaskProcessing task types
132+ *
133+ * @return DataResponse<Http::STATUS_OK, array{types: array<string, CoreTaskProcessingTaskType>}, array{}>
134+ *
135+ * 200: Task types returned
136+ */
137+ #[NoAdminRequired]
138+ #[ApiRoute(verb: 'GET ' , url: '/tasktypes ' , root: '/taskprocessing ' )]
139+ public function taskTypes (): DataResponse {
137140 return new DataResponse ([
138- 'types ' => $ taskTypes ,
141+ 'types ' => $ this -> getTaskTypesInternal () ,
139142 ]);
140143 }
141144
145+ /**
146+ * Returns all available TaskProcessing task types
147+ *
148+ * Endpoint for ExApp usage without user context
149+ *
150+ * @return DataResponse<Http::STATUS_OK, array{types: array<string, CoreTaskProcessingTaskType>}, array{}>
151+ *
152+ * 200: Task types returned
153+ */
154+ #[ExAppRequired]
155+ #[ApiRoute(verb: 'GET ' , url: '/tasks_consumer/tasktypes ' , root: '/taskprocessing ' )]
156+ public function taskTypesExAppEndpoint (): DataResponse {
157+ return new DataResponse ([
158+ 'types ' => $ this ->getTaskTypesInternal (),
159+ ]);
160+ }
161+
162+ /**
163+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_BAD_REQUEST|Http::STATUS_PRECONDITION_FAILED|Http::STATUS_UNAUTHORIZED, array{message: string}, array{}>
164+ */
165+ private function handleScheduleTaskInternal (
166+ array $ input , string $ type , string $ appId , string $ customId = '' ,
167+ ?string $ webhookUri = null , ?string $ webhookMethod = null , bool $ includeWatermark = true ,
168+ ): DataResponse {
169+ $ task = new Task ($ type , $ input , $ appId , $ this ->userId , $ customId );
170+ $ task ->setWebhookUri ($ webhookUri );
171+ $ task ->setWebhookMethod ($ webhookMethod );
172+ $ task ->setIncludeWatermark ($ includeWatermark );
173+ try {
174+ $ this ->taskProcessingManager ->scheduleTask ($ task );
175+
176+ /** @var CoreTaskProcessingTask $json */
177+ $ json = $ task ->jsonSerialize ();
178+
179+ return new DataResponse ([
180+ 'task ' => $ json ,
181+ ]);
182+ } catch (PreConditionNotMetException ) {
183+ return new DataResponse (['message ' => $ this ->l ->t ('The given provider is not available ' )], Http::STATUS_PRECONDITION_FAILED );
184+ } catch (ValidationException $ e ) {
185+ return new DataResponse (['message ' => $ e ->getMessage ()], Http::STATUS_BAD_REQUEST );
186+ } catch (UnauthorizedException ) {
187+ if ($ this ->userId === null ) {
188+ return new DataResponse (['message ' => 'Cannot schedule task with files referenced without user context ' ], Http::STATUS_UNAUTHORIZED );
189+ }
190+ return new DataResponse (['message ' => 'User does not have access to the files mentioned in the task input ' ], Http::STATUS_UNAUTHORIZED );
191+ } catch (Exception ) {
192+ return new DataResponse (['message ' => 'Internal server error ' ], Http::STATUS_INTERNAL_SERVER_ERROR );
193+ }
194+ }
195+
142196 /**
143197 * Schedules a task
144198 *
@@ -163,27 +217,70 @@ public function schedule(
163217 array $ input , string $ type , string $ appId , string $ customId = '' ,
164218 ?string $ webhookUri = null , ?string $ webhookMethod = null , bool $ includeWatermark = true ,
165219 ): DataResponse {
166- $ task = new Task ($ type , $ input , $ appId , $ this ->userId , $ customId );
167- $ task ->setWebhookUri ($ webhookUri );
168- $ task ->setWebhookMethod ($ webhookMethod );
169- $ task ->setIncludeWatermark ($ includeWatermark );
220+ return $ this ->handleScheduleTaskInternal (
221+ $ input ,
222+ $ type ,
223+ $ appId ,
224+ $ customId ,
225+ $ webhookUri ,
226+ $ webhookMethod ,
227+ $ includeWatermark ,
228+ );
229+ }
230+
231+ /**
232+ * Schedules a task
233+ *
234+ * Endpoint for ExApp usage without user context. Files cannot be referenced in this case.
235+ *
236+ * @param array<string, mixed> $input Task's input parameters
237+ * @param string $type Type of the task
238+ * @param string $appId ID of the app that will execute the task
239+ * @param string $customId An arbitrary identifier for the task
240+ * @param string|null $webhookUri URI to be requested when the task finishes
241+ * @param string|null $webhookMethod Method used for the webhook request (HTTP:GET, HTTP:POST, HTTP:PUT, HTTP:DELETE or AppAPI:APP_ID:GET, AppAPI:APP_ID:POST...)
242+ * @param bool $includeWatermark Whether to include a watermark in the output file or not
243+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_BAD_REQUEST|Http::STATUS_PRECONDITION_FAILED|Http::STATUS_UNAUTHORIZED, array{message: string}, array{}>
244+ *
245+ * 200: Task scheduled successfully
246+ * 400: Scheduling task is not possible
247+ * 412: Scheduling task is not possible
248+ * 401: Cannot schedule task because it references files in its input
249+ */
250+ #[ExAppRequired]
251+ #[ApiRoute(verb: 'POST ' , url: '/tasks_consumer/schedule ' , root: '/taskprocessing ' )]
252+ public function scheduleExAppEndpoint (
253+ array $ input , string $ type , string $ appId , string $ customId = '' ,
254+ ?string $ webhookUri = null , ?string $ webhookMethod = null , bool $ includeWatermark = true ,
255+ ): DataResponse {
256+ return $ this ->handleScheduleTaskInternal (
257+ $ input ,
258+ $ type ,
259+ $ appId ,
260+ $ customId ,
261+ $ webhookUri ,
262+ $ webhookMethod ,
263+ $ includeWatermark ,
264+ );
265+ }
266+
267+ /**
268+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
269+ */
270+ private function handleGetTaskInternal (int $ id ): DataResponse {
170271 try {
171- $ this ->taskProcessingManager ->scheduleTask ( $ task );
272+ $ task = $ this ->taskProcessingManager ->getUserTask ( $ id , $ this -> userId );
172273
173274 /** @var CoreTaskProcessingTask $json */
174275 $ json = $ task ->jsonSerialize ();
175276
176277 return new DataResponse ([
177278 'task ' => $ json ,
178279 ]);
179- } catch (PreConditionNotMetException ) {
180- return new DataResponse (['message ' => $ this ->l ->t ('The given provider is not available ' )], Http::STATUS_PRECONDITION_FAILED );
181- } catch (ValidationException $ e ) {
182- return new DataResponse (['message ' => $ e ->getMessage ()], Http::STATUS_BAD_REQUEST );
183- } catch (UnauthorizedException ) {
184- return new DataResponse (['message ' => 'User does not have access to the files mentioned in the task input ' ], Http::STATUS_UNAUTHORIZED );
185- } catch (Exception ) {
186- return new DataResponse (['message ' => 'Internal server error ' ], Http::STATUS_INTERNAL_SERVER_ERROR );
280+ } catch (NotFoundException ) {
281+ return new DataResponse (['message ' => $ this ->l ->t ('Task not found ' )], Http::STATUS_NOT_FOUND );
282+ } catch (RuntimeException ) {
283+ return new DataResponse (['message ' => $ this ->l ->t ('Internal error ' )], Http::STATUS_INTERNAL_SERVER_ERROR );
187284 }
188285 }
189286
@@ -202,18 +299,42 @@ public function schedule(
202299 #[NoAdminRequired]
203300 #[ApiRoute(verb: 'GET ' , url: '/task/{id} ' , root: '/taskprocessing ' )]
204301 public function getTask (int $ id ): DataResponse {
302+ return $ this ->handleGetTaskInternal ($ id );
303+ }
304+
305+ /**
306+ * Gets a task including status and result
307+ *
308+ * Endpoint for ExApp usage without user context
309+ *
310+ * Tasks are removed 1 week after receiving their last update
311+ *
312+ * @param int $id The id of the task
313+ *
314+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
315+ *
316+ * 200: Task returned
317+ * 404: Task not found
318+ */
319+ #[ExAppRequired]
320+ #[ApiRoute(verb: 'GET ' , url: '/tasks_consumer/task/{id} ' , root: '/taskprocessing ' )]
321+ public function getTaskExAppEndpoint (int $ id ): DataResponse {
322+ return $ this ->handleGetTaskInternal ($ id );
323+ }
324+
325+ /**
326+ * @return DataResponse<Http::STATUS_OK, null, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
327+ */
328+ private function handleDeleteTaskInternal (int $ id ): DataResponse {
205329 try {
206330 $ task = $ this ->taskProcessingManager ->getUserTask ($ id , $ this ->userId );
207331
208- /** @var CoreTaskProcessingTask $json */
209- $ json = $ task ->jsonSerialize ();
332+ $ this ->taskProcessingManager ->deleteTask ($ task );
210333
211- return new DataResponse ([
212- 'task ' => $ json ,
213- ]);
334+ return new DataResponse (null );
214335 } catch (NotFoundException ) {
215- return new DataResponse ([ ' message ' => $ this -> l -> t ( ' Task not found ' )], Http:: STATUS_NOT_FOUND );
216- } catch (RuntimeException ) {
336+ return new DataResponse (null );
337+ } catch (Exception ) {
217338 return new DataResponse (['message ' => $ this ->l ->t ('Internal error ' )], Http::STATUS_INTERNAL_SERVER_ERROR );
218339 }
219340 }
@@ -230,17 +351,24 @@ public function getTask(int $id): DataResponse {
230351 #[NoAdminRequired]
231352 #[ApiRoute(verb: 'DELETE ' , url: '/task/{id} ' , root: '/taskprocessing ' )]
232353 public function deleteTask (int $ id ): DataResponse {
233- try {
234- $ task = $ this ->taskProcessingManager ->getUserTask ($ id , $ this ->userId );
235-
236- $ this ->taskProcessingManager ->deleteTask ($ task );
354+ return $ this ->handleDeleteTaskInternal ($ id );
355+ }
237356
238- return new DataResponse (null );
239- } catch (NotFoundException ) {
240- return new DataResponse (null );
241- } catch (Exception ) {
242- return new DataResponse (['message ' => $ this ->l ->t ('Internal error ' )], Http::STATUS_INTERNAL_SERVER_ERROR );
243- }
357+ /**
358+ * Deletes a task
359+ *
360+ * Endpoint for ExApp usage without user context
361+ *
362+ * @param int $id The id of the task
363+ *
364+ * @return DataResponse<Http::STATUS_OK, null, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
365+ *
366+ * 200: Task deleted
367+ */
368+ #[ExAppRequired]
369+ #[ApiRoute(verb: 'DELETE ' , url: '/tasks_consumer/task/{id} ' , root: '/taskprocessing ' )]
370+ public function deleteTaskExAppEndpoint (int $ id ): DataResponse {
371+ return $ this ->handleDeleteTaskInternal ($ id );
244372 }
245373
246374
@@ -490,17 +618,9 @@ public function setResult(int $taskId, ?array $output = null, ?string $errorMess
490618 }
491619
492620 /**
493- * Cancels a task
494- *
495- * @param int $taskId The id of the task
496621 * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
497- *
498- * 200: Task canceled successfully
499- * 404: Task not found
500622 */
501- #[NoAdminRequired]
502- #[ApiRoute(verb: 'POST ' , url: '/tasks/{taskId}/cancel ' , root: '/taskprocessing ' )]
503- public function cancelTask (int $ taskId ): DataResponse {
623+ private function handleCancelTaskInternal (int $ taskId ): DataResponse {
504624 try {
505625 // Check if the current user can access the task
506626 $ this ->taskProcessingManager ->getUserTask ($ taskId , $ this ->userId );
@@ -521,6 +641,38 @@ public function cancelTask(int $taskId): DataResponse {
521641 }
522642 }
523643
644+ /**
645+ * Cancels a task
646+ *
647+ * @param int $taskId The id of the task
648+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
649+ *
650+ * 200: Task canceled successfully
651+ * 404: Task not found
652+ */
653+ #[NoAdminRequired]
654+ #[ApiRoute(verb: 'POST ' , url: '/tasks/{taskId}/cancel ' , root: '/taskprocessing ' )]
655+ public function cancelTask (int $ taskId ): DataResponse {
656+ return $ this ->handleCancelTaskInternal ($ taskId );
657+ }
658+
659+ /**
660+ * Cancels a task
661+ *
662+ * Endpoint for ExApp usage without user context
663+ *
664+ * @param int $taskId The id of the task
665+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
666+ *
667+ * 200: Task canceled successfully
668+ * 404: Task not found
669+ */
670+ #[ExAppRequired]
671+ #[ApiRoute(verb: 'POST ' , url: '/tasks_consumer/tasks/{taskId}/cancel ' , root: '/taskprocessing ' )]
672+ public function cancelTaskExAppEndpoint (int $ taskId ): DataResponse {
673+ return $ this ->handleCancelTaskInternal ($ taskId );
674+ }
675+
524676 /**
525677 * Returns the next scheduled task for the taskTypeId
526678 *
0 commit comments