@@ -59,17 +59,10 @@ public function __construct(
5959 }
6060
6161 /**
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
62+ * @return array<string, CoreTaskProcessingTaskType>
6763 */
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 ) {
64+ private function getTaskTypesInternal (): array {
65+ return array_map (function (array $ tt ) {
7366 $ tt ['inputShape ' ] = array_map (function ($ descriptor ) {
7467 return $ descriptor ->jsonSerialize ();
7568 }, $ tt ['inputShape ' ]);
@@ -134,11 +127,74 @@ public function taskTypes(): DataResponse {
134127 }
135128 return $ tt ;
136129 }, $ this ->taskProcessingManager ->getAvailableTaskTypes ());
130+ }
131+
132+ /**
133+ * Returns all available TaskProcessing task types
134+ *
135+ * @return DataResponse<Http::STATUS_OK, array{types: array<string, CoreTaskProcessingTaskType>}, array{}>
136+ *
137+ * 200: Task types returned
138+ */
139+ #[NoAdminRequired]
140+ #[ApiRoute(verb: 'GET ' , url: '/tasktypes ' , root: '/taskprocessing ' )]
141+ public function taskTypes (): DataResponse {
137142 return new DataResponse ([
138- 'types ' => $ taskTypes ,
143+ 'types ' => $ this -> getTaskTypesInternal () ,
139144 ]);
140145 }
141146
147+ /**
148+ * Returns all available TaskProcessing task types
149+ *
150+ * Endpoint for ExApp usage without user context
151+ *
152+ * @return DataResponse<Http::STATUS_OK, array{types: array<string, CoreTaskProcessingTaskType>}, array{}>
153+ *
154+ * 200: Task types returned
155+ */
156+ #[ExAppRequired]
157+ #[ApiRoute(verb: 'GET ' , url: '/tasks_consumer/tasktypes ' , root: '/taskprocessing ' )]
158+ public function taskTypesExAppEndpoint (): DataResponse {
159+ return new DataResponse ([
160+ 'types ' => $ this ->getTaskTypesInternal (),
161+ ]);
162+ }
163+
164+ /**
165+ * @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{}>
166+ */
167+ private function handleScheduleTaskInternal (
168+ array $ input , string $ type , string $ appId , string $ customId = '' ,
169+ ?string $ webhookUri = null , ?string $ webhookMethod = null , bool $ includeWatermark = true ,
170+ ): DataResponse {
171+ $ task = new Task ($ type , $ input , $ appId , $ this ->userId , $ customId );
172+ $ task ->setWebhookUri ($ webhookUri );
173+ $ task ->setWebhookMethod ($ webhookMethod );
174+ $ task ->setIncludeWatermark ($ includeWatermark );
175+ try {
176+ $ this ->taskProcessingManager ->scheduleTask ($ task );
177+
178+ /** @var CoreTaskProcessingTask $json */
179+ $ json = $ task ->jsonSerialize ();
180+
181+ return new DataResponse ([
182+ 'task ' => $ json ,
183+ ]);
184+ } catch (PreConditionNotMetException ) {
185+ return new DataResponse (['message ' => $ this ->l ->t ('The given provider is not available ' )], Http::STATUS_PRECONDITION_FAILED );
186+ } catch (ValidationException $ e ) {
187+ return new DataResponse (['message ' => $ e ->getMessage ()], Http::STATUS_BAD_REQUEST );
188+ } catch (UnauthorizedException ) {
189+ if ($ this ->userId === null ) {
190+ return new DataResponse (['message ' => 'Cannot schedule task with files referenced without user context ' ], Http::STATUS_UNAUTHORIZED );
191+ }
192+ return new DataResponse (['message ' => 'User does not have access to the files mentioned in the task input ' ], Http::STATUS_UNAUTHORIZED );
193+ } catch (Exception ) {
194+ return new DataResponse (['message ' => 'Internal server error ' ], Http::STATUS_INTERNAL_SERVER_ERROR );
195+ }
196+ }
197+
142198 /**
143199 * Schedules a task
144200 *
@@ -163,27 +219,70 @@ public function schedule(
163219 array $ input , string $ type , string $ appId , string $ customId = '' ,
164220 ?string $ webhookUri = null , ?string $ webhookMethod = null , bool $ includeWatermark = true ,
165221 ): DataResponse {
166- $ task = new Task ($ type , $ input , $ appId , $ this ->userId , $ customId );
167- $ task ->setWebhookUri ($ webhookUri );
168- $ task ->setWebhookMethod ($ webhookMethod );
169- $ task ->setIncludeWatermark ($ includeWatermark );
222+ return $ this ->handleScheduleTaskInternal (
223+ $ input ,
224+ $ type ,
225+ $ appId ,
226+ $ customId ,
227+ $ webhookUri ,
228+ $ webhookMethod ,
229+ $ includeWatermark ,
230+ );
231+ }
232+
233+ /**
234+ * Schedules a task
235+ *
236+ * Endpoint for ExApp usage without user context. Files cannot be referenced in this case.
237+ *
238+ * @param array<string, mixed> $input Task's input parameters
239+ * @param string $type Type of the task
240+ * @param string $appId ID of the app that will execute the task
241+ * @param string $customId An arbitrary identifier for the task
242+ * @param string|null $webhookUri URI to be requested when the task finishes
243+ * @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...)
244+ * @param bool $includeWatermark Whether to include a watermark in the output file or not
245+ * @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{}>
246+ *
247+ * 200: Task scheduled successfully
248+ * 400: Scheduling task is not possible
249+ * 412: Scheduling task is not possible
250+ * 401: Cannot schedule task because it references files in its input
251+ */
252+ #[ExAppRequired]
253+ #[ApiRoute(verb: 'POST ' , url: '/tasks_consumer/schedule ' , root: '/taskprocessing ' )]
254+ public function scheduleExAppEndpoint (
255+ array $ input , string $ type , string $ appId , string $ customId = '' ,
256+ ?string $ webhookUri = null , ?string $ webhookMethod = null , bool $ includeWatermark = true ,
257+ ): DataResponse {
258+ return $ this ->handleScheduleTaskInternal (
259+ $ input ,
260+ $ type ,
261+ $ appId ,
262+ $ customId ,
263+ $ webhookUri ,
264+ $ webhookMethod ,
265+ $ includeWatermark ,
266+ );
267+ }
268+
269+ /**
270+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
271+ */
272+ private function handleGetTaskInternal (int $ id ): DataResponse {
170273 try {
171- $ this ->taskProcessingManager ->scheduleTask ( $ task );
274+ $ task = $ this ->taskProcessingManager ->getUserTask ( $ id , $ this -> userId );
172275
173276 /** @var CoreTaskProcessingTask $json */
174277 $ json = $ task ->jsonSerialize ();
175278
176279 return new DataResponse ([
177280 'task ' => $ json ,
178281 ]);
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 );
282+ } catch (NotFoundException ) {
283+ return new DataResponse (['message ' => $ this ->l ->t ('Task not found ' )], Http::STATUS_NOT_FOUND );
284+ } catch (RuntimeException ) {
285+ return new DataResponse (['message ' => $ this ->l ->t ('Internal error ' )], Http::STATUS_INTERNAL_SERVER_ERROR );
187286 }
188287 }
189288
@@ -202,18 +301,42 @@ public function schedule(
202301 #[NoAdminRequired]
203302 #[ApiRoute(verb: 'GET ' , url: '/task/{id} ' , root: '/taskprocessing ' )]
204303 public function getTask (int $ id ): DataResponse {
304+ return $ this ->handleGetTaskInternal ($ id );
305+ }
306+
307+ /**
308+ * Gets a task including status and result
309+ *
310+ * Endpoint for ExApp usage without user context
311+ *
312+ * Tasks are removed 1 week after receiving their last update
313+ *
314+ * @param int $id The id of the task
315+ *
316+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
317+ *
318+ * 200: Task returned
319+ * 404: Task not found
320+ */
321+ #[ExAppRequired]
322+ #[ApiRoute(verb: 'GET ' , url: '/tasks_consumer/task/{id} ' , root: '/taskprocessing ' )]
323+ public function getTaskExAppEndpoint (int $ id ): DataResponse {
324+ return $ this ->handleGetTaskInternal ($ id );
325+ }
326+
327+ /**
328+ * @return DataResponse<Http::STATUS_OK, null, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
329+ */
330+ private function handleDeleteTaskInternal (int $ id ): DataResponse {
205331 try {
206332 $ task = $ this ->taskProcessingManager ->getUserTask ($ id , $ this ->userId );
207333
208- /** @var CoreTaskProcessingTask $json */
209- $ json = $ task ->jsonSerialize ();
334+ $ this ->taskProcessingManager ->deleteTask ($ task );
210335
211- return new DataResponse ([
212- 'task ' => $ json ,
213- ]);
336+ return new DataResponse (null );
214337 } catch (NotFoundException ) {
215- return new DataResponse ([ ' message ' => $ this -> l -> t ( ' Task not found ' )], Http:: STATUS_NOT_FOUND );
216- } catch (RuntimeException ) {
338+ return new DataResponse (null );
339+ } catch (Exception ) {
217340 return new DataResponse (['message ' => $ this ->l ->t ('Internal error ' )], Http::STATUS_INTERNAL_SERVER_ERROR );
218341 }
219342 }
@@ -230,17 +353,24 @@ public function getTask(int $id): DataResponse {
230353 #[NoAdminRequired]
231354 #[ApiRoute(verb: 'DELETE ' , url: '/task/{id} ' , root: '/taskprocessing ' )]
232355 public function deleteTask (int $ id ): DataResponse {
233- try {
234- $ task = $ this ->taskProcessingManager ->getUserTask ($ id , $ this ->userId );
235-
236- $ this ->taskProcessingManager ->deleteTask ($ task );
356+ return $ this ->handleDeleteTaskInternal ($ id );
357+ }
237358
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- }
359+ /**
360+ * Deletes a task
361+ *
362+ * Endpoint for ExApp usage without user context
363+ *
364+ * @param int $id The id of the task
365+ *
366+ * @return DataResponse<Http::STATUS_OK, null, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR, array{message: string}, array{}>
367+ *
368+ * 200: Task deleted
369+ */
370+ #[ExAppRequired]
371+ #[ApiRoute(verb: 'DELETE ' , url: '/tasks_consumer/task/{id} ' , root: '/taskprocessing ' )]
372+ public function deleteTaskExAppEndpoint (int $ id ): DataResponse {
373+ return $ this ->handleDeleteTaskInternal ($ id );
244374 }
245375
246376
@@ -490,17 +620,9 @@ public function setResult(int $taskId, ?array $output = null, ?string $errorMess
490620 }
491621
492622 /**
493- * Cancels a task
494- *
495- * @param int $taskId The id of the task
496623 * @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
500624 */
501- #[NoAdminRequired]
502- #[ApiRoute(verb: 'POST ' , url: '/tasks/{taskId}/cancel ' , root: '/taskprocessing ' )]
503- public function cancelTask (int $ taskId ): DataResponse {
625+ private function handleCancelTaskInternal (int $ taskId ): DataResponse {
504626 try {
505627 // Check if the current user can access the task
506628 $ this ->taskProcessingManager ->getUserTask ($ taskId , $ this ->userId );
@@ -521,6 +643,38 @@ public function cancelTask(int $taskId): DataResponse {
521643 }
522644 }
523645
646+ /**
647+ * Cancels a task
648+ *
649+ * @param int $taskId The id of the task
650+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
651+ *
652+ * 200: Task canceled successfully
653+ * 404: Task not found
654+ */
655+ #[NoAdminRequired]
656+ #[ApiRoute(verb: 'POST ' , url: '/tasks/{taskId}/cancel ' , root: '/taskprocessing ' )]
657+ public function cancelTask (int $ taskId ): DataResponse {
658+ return $ this ->handleCancelTaskInternal ($ taskId );
659+ }
660+
661+ /**
662+ * Cancels a task
663+ *
664+ * Endpoint for ExApp usage without user context
665+ *
666+ * @param int $taskId The id of the task
667+ * @return DataResponse<Http::STATUS_OK, array{task: CoreTaskProcessingTask}, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
668+ *
669+ * 200: Task canceled successfully
670+ * 404: Task not found
671+ */
672+ #[ExAppRequired]
673+ #[ApiRoute(verb: 'POST ' , url: '/tasks_consumer/tasks/{taskId}/cancel ' , root: '/taskprocessing ' )]
674+ public function cancelTaskExAppInternal (int $ taskId ): DataResponse {
675+ return $ this ->handleCancelTaskInternal ($ taskId );
676+ }
677+
524678 /**
525679 * Returns the next scheduled task for the taskTypeId
526680 *
0 commit comments