diff --git a/phpunit/web/APIRestTest.php b/phpunit/web/APIRestTest.php index 0839f708f8a..208a4821075 100644 --- a/phpunit/web/APIRestTest.php +++ b/phpunit/web/APIRestTest.php @@ -3356,4 +3356,68 @@ public function testUndisclosedNotificationContent() $this->assertEquals('********', $notification['13']); // 13 = body_text } } + + public static function getHelpdeskFormsDetailsWithPaginationProvider(): iterable + { + $request_form = [ + 'id' => 2, + 'name' => "Request a service", + 'description' => "Ask for a service to be provided by our team.", + 'logo_url' => "/lib/glpi-project/illustrations/glpi-illustrations-icons.svg#request-service", + 'category' => "", + ]; + $incident_form = [ + 'id' => 1, + 'name' => "Report an issue", + 'description' => "Ask for support from our helpdesk team.", + 'logo_url' => "/lib/glpi-project/illustrations/glpi-illustrations-icons.svg#report-issue", + 'category' => "", + ]; + + yield 'no pagination' => [ + 'query' => [], + 'expected_totalcount' => 2, + 'expected_items' => [$request_form, $incident_form], + 'expected_return_code' => 200, + ]; + + yield 'with pagination, first item' => [ + 'query' => [ + 'page' => 1, + 'page_size' => 1, + ], + 'expected_totalcount' => 2, + 'expected_items' => [$request_form], + 'expected_return_code' => 206, + ]; + + yield 'with pagination, second item' => [ + 'query' => [ + 'page' => 2, + 'page_size' => 1, + ], + 'expected_totalcount' => 2, + 'expected_items' => [$incident_form], + 'expected_return_code' => 206, + ]; + } + + #[DataProvider('getHelpdeskFormsDetailsWithPaginationProvider')] + public function testGetHelpdeskFormsDetailsWithPagination( + array $query, + int $expected_totalcount, + array $expected_items, + int $expected_return_code, + ): void { + $this->initSessionCredentials(); + $data = $this->query('getHelpdeskFormsDetails', [ + 'headers' => [ + 'Session-Token' => $this->session_token, + ], + 'query' => $query, + ], $expected_return_code); + + $this->assertEquals($expected_totalcount, $data['totalcount']); + $this->assertEquals($expected_items, $data['items']); + } } diff --git a/src/Glpi/Api/APIRest.php b/src/Glpi/Api/APIRest.php index acc821aec1d..215575df481 100644 --- a/src/Glpi/Api/APIRest.php +++ b/src/Glpi/Api/APIRest.php @@ -40,7 +40,16 @@ namespace Glpi\Api; use AllAssets; +use Glpi\Form\AccessControl\FormAccessParameters; +use Glpi\Form\Category; +use Glpi\Form\Form; +use Glpi\Form\ServiceCatalog\ItemRequest; +use Glpi\Form\ServiceCatalog\Provider\FormProvider; +use Glpi\Form\ServiceCatalog\ServiceCatalogManager; +use Glpi\UI\IllustrationManager; use GLPIUploadHandler; +use RuntimeException; +use Session; use stdClass; use Toolbox; @@ -267,6 +276,8 @@ public function call() ); } elseif (preg_match('%user/(\d+)/picture%i', $path_info, $matches)) { $this->userPicture($matches[1]); + } elseif ($resource == 'getHelpdeskFormsDetails') { + $this->getHelpdeskFormsDetails(); } else { // commonDBTM manipulation $itemtype = $this->getItemtype(0); @@ -680,4 +691,52 @@ public function inlineDocumentation($file = "apirest.md") } exit(); } + + private function getHelpdeskFormsDetails(): void + { + // Get services + $catalog_manager = new ServiceCatalogManager([new FormProvider()]); + $illustration_manager = new IllustrationManager(); + + // Set range params + $page = $this->parameters['page'] ?? 1; + $page_size = $this->parameters['page_size'] ?? ServiceCatalogManager::ITEMS_PER_PAGE; + + // Fetch items + $item_request = new ItemRequest( + access_parameters: new FormAccessParameters( + session_info: Session::getCurrentSessionInfo(), + ), + page: $page, + items_per_page: $page_size, + ); + $service_catalog_items = $catalog_manager->getItems($item_request); + + // Build response + $response = [ + 'items' => [], + 'totalcount' => $service_catalog_items['total'], + ]; + foreach ($service_catalog_items['items'] as $form) { + if (!$form instanceof Form) { + throw new RuntimeException(); + } + + $category_id = $form->fields['forms_categories_id']; + $category = $category_id ? Category::getById($category_id) : null; + $response['items'][] = [ + 'id' => $form->getId(), + 'name' => $form->getServiceCatalogItemTitle(), + 'description' => $form->getServiceCatalogItemDescription(), + 'logo_url' => $illustration_manager->getIconPath( + $form->getServiceCatalogItemIllustration(), + ), + 'category' => $category ? $category->getServiceCatalogItemTitle() : "", + ]; + } + + $is_partial_response = $service_catalog_items['total'] > count($service_catalog_items['items']); + + $this->returnResponse($response, $is_partial_response ? 206 : 200); + } } diff --git a/src/Glpi/Form/ServiceCatalog/ServiceCatalogManager.php b/src/Glpi/Form/ServiceCatalog/ServiceCatalogManager.php index 2da25766a71..8ed58e24b64 100644 --- a/src/Glpi/Form/ServiceCatalog/ServiceCatalogManager.php +++ b/src/Glpi/Form/ServiceCatalog/ServiceCatalogManager.php @@ -50,13 +50,18 @@ final class ServiceCatalogManager /** @var \Glpi\Form\ServiceCatalog\Provider\ItemProviderInterface[] */ private array $providers; - public function __construct() + public function __construct(array $providers = []) { - $this->providers = [ - new FormProvider(), - new CategoryProvider(), - new KnowbaseItemProvider(), - ]; + if (empty($providers)) { + // Default providers + $this->providers = [ + new FormProvider(), + new CategoryProvider(), + new KnowbaseItemProvider(), + ]; + } else { + $this->providers = $providers; + } } /** diff --git a/src/Glpi/UI/IllustrationManager.php b/src/Glpi/UI/IllustrationManager.php index 9c6c4534505..219de950389 100644 --- a/src/Glpi/UI/IllustrationManager.php +++ b/src/Glpi/UI/IllustrationManager.php @@ -35,6 +35,7 @@ namespace Glpi\UI; use Glpi\Application\View\TemplateRenderer; +use Html; use RuntimeException; final class IllustrationManager @@ -102,6 +103,21 @@ public function renderIcon(string $icon_id, ?int $size = null): string } } + public function getIconPath(string $icon_id): string + { + $custom_icon_prefix = self::CUSTOM_ILLUSTRATION_PREFIX; + $is_custom = str_starts_with($icon_id, $custom_icon_prefix); + if ($is_custom) { + // Remove custom prefix to get real icon id + $icon_id = substr($icon_id, strlen($custom_icon_prefix)); + $path = "/UI/Illustration/CustomIllustration/$icon_id"; + } else { + $path = $this->icons_sprites_path . "#$icon_id"; + } + + return Html::getPrefixedUrl($path); + } + /** * @param int|null $height Height (px). Will be set to 100% if null. * @param int|null $width Width (px). Will be set to 100% if null.