vendor/shopware/core/Framework/Api/Controller/InfoController.php line 121

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\Api\Controller;
  3. use OpenApi\Annotations as OA;
  4. use Shopware\Core\Content\Flow\Api\FlowActionCollector;
  5. use Shopware\Core\Framework\Api\ApiDefinition\DefinitionService;
  6. use Shopware\Core\Framework\Api\ApiDefinition\Generator\EntitySchemaGenerator;
  7. use Shopware\Core\Framework\Api\ApiDefinition\Generator\OpenApi3Generator;
  8. use Shopware\Core\Framework\App\AppCollection;
  9. use Shopware\Core\Framework\App\AppEntity;
  10. use Shopware\Core\Framework\Bundle;
  11. use Shopware\Core\Framework\Context;
  12. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
  17. use Shopware\Core\Framework\Event\BusinessEventCollector;
  18. use Shopware\Core\Framework\Feature;
  19. use Shopware\Core\Framework\Increment\Exception\IncrementGatewayNotFoundException;
  20. use Shopware\Core\Framework\Increment\IncrementGatewayRegistry;
  21. use Shopware\Core\Framework\Plugin;
  22. use Shopware\Core\Framework\Routing\Annotation\Since;
  23. use Shopware\Core\Kernel;
  24. use Shopware\Core\PlatformRequest;
  25. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  26. use Symfony\Component\Asset\PackageInterface;
  27. use Symfony\Component\Asset\Packages;
  28. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  29. use Symfony\Component\HttpFoundation\JsonResponse;
  30. use Symfony\Component\HttpFoundation\Request;
  31. use Symfony\Component\HttpFoundation\Response;
  32. use Symfony\Component\Routing\Annotation\Route;
  33. /**
  34.  * @Route(defaults={"_routeScope"={"api"}})
  35.  */
  36. class InfoController extends AbstractController
  37. {
  38.     private DefinitionService $definitionService;
  39.     private ParameterBagInterface $params;
  40.     private Packages $packages;
  41.     private Kernel $kernel;
  42.     private bool $enableUrlFeature;
  43.     private array $cspTemplates;
  44.     private BusinessEventCollector $eventCollector;
  45.     private ?FlowActionCollector $flowActionCollector;
  46.     private IncrementGatewayRegistry $incrementGatewayRegistry;
  47.     private EntityRepositoryInterface $appRepository;
  48.     /**
  49.      * @internal
  50.      */
  51.     public function __construct(
  52.         DefinitionService $definitionService,
  53.         ParameterBagInterface $params,
  54.         Kernel $kernel,
  55.         Packages $packages,
  56.         BusinessEventCollector $eventCollector,
  57.         IncrementGatewayRegistry $incrementGatewayRegistry,
  58.         EntityRepositoryInterface $appRepository,
  59.         ?FlowActionCollector $flowActionCollector null,
  60.         bool $enableUrlFeature true,
  61.         array $cspTemplates = []
  62.     ) {
  63.         $this->definitionService $definitionService;
  64.         $this->params $params;
  65.         $this->packages $packages;
  66.         $this->kernel $kernel;
  67.         $this->enableUrlFeature $enableUrlFeature;
  68.         $this->flowActionCollector $flowActionCollector;
  69.         $this->cspTemplates $cspTemplates;
  70.         $this->eventCollector $eventCollector;
  71.         $this->incrementGatewayRegistry $incrementGatewayRegistry;
  72.         $this->appRepository $appRepository;
  73.     }
  74.     /**
  75.      * @Since("6.0.0.0")
  76.      * @OA\Get(
  77.      *     path="/_info/openapi3.json",
  78.      *     summary="Get OpenAPI Specification",
  79.      *     description="Get information about the API in OpenAPI format.",
  80.      *     operationId="api-info",
  81.      *     tags={"Admin API", "System Info & Healthcheck"},
  82.      *     @OA\Parameter(
  83.      *         name="type",
  84.      *         description="Type of the api",
  85.      *         @OA\Schema(type="string", enum={"jsonapi", "json"}),
  86.      *         in="query"
  87.      *     ),
  88.      *     @OA\Response(
  89.      *         response="200",
  90.      *         description="Returns information about the API."
  91.      *     )
  92.      * )
  93.      * @Route("/api/_info/openapi3.json", defaults={"auth_required"="%shopware.api.api_browser.auth_required_str%"}, name="api.info.openapi3", methods={"GET"})
  94.      */
  95.     public function info(Request $request): JsonResponse
  96.     {
  97.         $apiType $request->query->getAlpha('type'DefinitionService::TypeJsonApi);
  98.         $data $this->definitionService->generate(OpenApi3Generator::FORMATDefinitionService::API$apiType);
  99.         return new JsonResponse($data);
  100.     }
  101.     /**
  102.      * @Since("6.4.6.0")
  103.      * @Route("/api/_info/queue.json", name="api.info.queue", methods={"GET"})
  104.      */
  105.     public function queue(): JsonResponse
  106.     {
  107.         try {
  108.             $gateway $this->incrementGatewayRegistry->get(IncrementGatewayRegistry::MESSAGE_QUEUE_POOL);
  109.         } catch (IncrementGatewayNotFoundException $exception) {
  110.             // In case message_queue pool is disabled
  111.             return new JsonResponse([]);
  112.         }
  113.         // Fetch unlimited message_queue_stats
  114.         $entries $gateway->list('message_queue_stats', -1);
  115.         return new JsonResponse(array_map(function (array $entry) {
  116.             return [
  117.                 'name' => $entry['key'],
  118.                 'size' => (int) $entry['count'],
  119.             ];
  120.         }, array_values($entries)));
  121.     }
  122.     /**
  123.      * @Since("6.0.0.0")
  124.      * @Route("/api/_info/open-api-schema.json", defaults={"auth_required"="%shopware.api.api_browser.auth_required_str%"}, name="api.info.open-api-schema", methods={"GET"})
  125.      */
  126.     public function openApiSchema(): JsonResponse
  127.     {
  128.         $data $this->definitionService->getSchema(OpenApi3Generator::FORMATDefinitionService::API);
  129.         return new JsonResponse($data);
  130.     }
  131.     /**
  132.      * @Since("6.0.0.0")
  133.      * @Route("/api/_info/entity-schema.json", name="api.info.entity-schema", methods={"GET"})
  134.      */
  135.     public function entitySchema(): JsonResponse
  136.     {
  137.         $data $this->definitionService->getSchema(EntitySchemaGenerator::FORMATDefinitionService::API);
  138.         return new JsonResponse($data);
  139.     }
  140.     /**
  141.      * @Since("6.3.2.0")
  142.      * @OA\Get(
  143.      *     path="/_info/events.json",
  144.      *     summary="Get Business events",
  145.      *     description="Get a list of about the business events.",
  146.      *     operationId="business-events",
  147.      *     tags={"Admin API", "System Info & Healthcheck"},
  148.      *     @OA\Response(
  149.      *         response="200",
  150.      *         description="Returns a list of about the business events.",
  151.      *         @OA\JsonContent(ref="#/components/schemas/businessEventsResponse")
  152.      *     )
  153.      * )
  154.      * @Route("/api/_info/events.json", name="api.info.business-events", methods={"GET"})
  155.      */
  156.     public function businessEvents(Context $context): JsonResponse
  157.     {
  158.         $events $this->eventCollector->collect($context);
  159.         return $this->json($events);
  160.     }
  161.     /**
  162.      * @Since("6.0.0.0")
  163.      * @Route("/api/_info/swagger.html", defaults={"auth_required"="%shopware.api.api_browser.auth_required_str%"}, name="api.info.swagger", methods={"GET"})
  164.      */
  165.     public function infoHtml(Request $request): Response
  166.     {
  167.         $nonce $request->attributes->get(PlatformRequest::ATTRIBUTE_CSP_NONCE);
  168.         $apiType $request->query->getAlpha('type'DefinitionService::TypeJson);
  169.         $response $this->render(
  170.             '@Framework/swagger.html.twig',
  171.             [
  172.                 'schemaUrl' => 'api.info.openapi3',
  173.                 'cspNonce' => $nonce,
  174.                 'apiType' => $apiType,
  175.             ]
  176.         );
  177.         $cspTemplate $this->cspTemplates['administration'] ?? '';
  178.         $cspTemplate trim($cspTemplate);
  179.         if ($cspTemplate !== '') {
  180.             $csp str_replace('%nonce%'$nonce$cspTemplate);
  181.             $csp str_replace(["\n""\r"], ' '$csp);
  182.             $response->headers->set('Content-Security-Policy'$csp);
  183.         }
  184.         return $response;
  185.     }
  186.     /**
  187.      * @Since("6.0.0.0")
  188.      * @OA\Get(
  189.      *     path="/_info/config",
  190.      *     summary="Get API information",
  191.      *     description="Get information about the API",
  192.      *     operationId="config",
  193.      *     tags={"Admin API", "System Info & Healthcheck"},
  194.      *     @OA\Response(
  195.      *         response="200",
  196.      *         description="Returns information about the API.",
  197.      *         @OA\JsonContent(ref="#/components/schemas/infoConfigResponse")
  198.      *     )
  199.      * )
  200.      * @Route("/api/_info/config", name="api.info.config", methods={"GET"})
  201.      *
  202.      * @deprecated tag:v6.5.0 $context param will be required
  203.      */
  204.     public function config(?Context $context null): JsonResponse
  205.     {
  206.         if (!$context) {
  207.             Feature::triggerDeprecationOrThrow(
  208.                 'v6.5.0.0',
  209.                 'First parameter `$context` will be required in method `config()` in `InfoController` in v6.5.0.0'
  210.             );
  211.             $context Context::createDefaultContext();
  212.         }
  213.         return new JsonResponse([
  214.             'version' => $this->params->get('kernel.shopware_version'),
  215.             'versionRevision' => $this->params->get('kernel.shopware_version_revision'),
  216.             'adminWorker' => [
  217.                 'enableAdminWorker' => $this->params->get('shopware.admin_worker.enable_admin_worker'),
  218.                 'transports' => $this->params->get('shopware.admin_worker.transports'),
  219.             ],
  220.             'bundles' => $this->getBundles($context),
  221.             'settings' => [
  222.                 'enableUrlFeature' => $this->enableUrlFeature,
  223.             ],
  224.         ]);
  225.     }
  226.     /**
  227.      * @Since("6.3.5.0")
  228.      * @OA\Get(
  229.      *     path="/_info/version",
  230.      *     summary="Get the Shopware version",
  231.      *     description="Get the version of the Shopware instance",
  232.      *     operationId="infoShopwareVersion",
  233.      *     tags={"Admin API", "System Info & Healthcheck"},
  234.      *     @OA\Response(
  235.      *         response="200",
  236.      *         description="Returns the version of the Shopware instance.",
  237.      *         @OA\JsonContent(
  238.      *              @OA\Property(
  239.      *                  property="version",
  240.      *                  description="The Shopware version.",
  241.      *                  type="string"
  242.      *              )
  243.      *          )
  244.      *     )
  245.      * )
  246.      * @Route("/api/_info/version", name="api.info.shopware.version", methods={"GET"})
  247.      * @Route("/api/v1/_info/version", name="api.info.shopware.version_old_version", methods={"GET"})
  248.      */
  249.     public function infoShopwareVersion(): JsonResponse
  250.     {
  251.         return new JsonResponse([
  252.             'version' => $this->params->get('kernel.shopware_version'),
  253.         ]);
  254.     }
  255.     /**
  256.      * @Since("6.4.5.0")
  257.      * @OA\Get(
  258.      *     path="/_info/flow-actions.json",
  259.      *     summary="Get actions for flow builder",
  260.      *     description="Get a list of action for flow builder.",
  261.      *     operationId="flow-actions",
  262.      *     tags={"Admin API", "System Info & Healthcheck"},
  263.      *     @OA\Response(
  264.      *         response="200",
  265.      *         description="Returns a list of action for flow builder.",
  266.      *         @OA\JsonContent(ref="#/components/schemas/flowBulderActionsResponse")
  267.      *     )
  268.      * )
  269.      * @Route("/api/_info/flow-actions.json", name="api.info.actions", methods={"GET"})
  270.      */
  271.     public function flowActions(Context $context): JsonResponse
  272.     {
  273.         if (!$this->flowActionCollector) {
  274.             return $this->json([]);
  275.         }
  276.         $events $this->flowActionCollector->collect($context);
  277.         return $this->json($events);
  278.     }
  279.     private function getBundles(Context $context): array
  280.     {
  281.         $assets = [];
  282.         $package $this->packages->getPackage('asset');
  283.         foreach ($this->kernel->getBundles() as $bundle) {
  284.             if (!$bundle instanceof Bundle) {
  285.                 continue;
  286.             }
  287.             $bundleDirectoryName preg_replace('/bundle$/'''mb_strtolower($bundle->getName()));
  288.             if ($bundleDirectoryName === null) {
  289.                 throw new \RuntimeException(sprintf('Unable to generate bundle directory for bundle "%s"'$bundle->getName()));
  290.             }
  291.             $styles array_map(static function (string $filename) use ($package$bundleDirectoryName) {
  292.                 $url 'bundles/' $bundleDirectoryName '/' $filename;
  293.                 return $package->getUrl($url);
  294.             }, $this->getAdministrationStyles($bundle));
  295.             $scripts array_map(static function (string $filename) use ($package$bundleDirectoryName) {
  296.                 $url 'bundles/' $bundleDirectoryName '/' $filename;
  297.                 return $package->getUrl($url);
  298.             }, $this->getAdministrationScripts($bundle));
  299.             $baseUrl $this->getBaseUrl($bundle$package$bundleDirectoryName);
  300.             if (empty($styles) && empty($scripts)) {
  301.                 if ($baseUrl === null) {
  302.                     continue;
  303.                 }
  304.             }
  305.             $assets[$bundle->getName()] = [
  306.                 'css' => $styles,
  307.                 'js' => $scripts,
  308.                 'baseUrl' => $baseUrl,
  309.                 'type' => 'plugin',
  310.             ];
  311.         }
  312.         /** @var AppEntity $app */
  313.         foreach ($this->getActiveApps($context) as $app) {
  314.             $assets[$app->getName()] = [
  315.                 'active' => $app->isActive(),
  316.                 'integrationId' => $app->getIntegrationId(),
  317.                 'type' => 'app',
  318.                 'baseUrl' => $app->getBaseAppUrl(),
  319.                 'permissions' => $this->fetchAppPermissions($app),
  320.                 'version' => $app->getVersion(),
  321.             ];
  322.         }
  323.         return $assets;
  324.     }
  325.     private function fetchAppPermissions(AppEntity $app): array
  326.     {
  327.         $privileges = [];
  328.         $aclRole $app->getAclRole();
  329.         if ($aclRole === null) {
  330.             return $privileges;
  331.         }
  332.         foreach ($aclRole->getPrivileges() as $privilege) {
  333.             if (substr_count($privilege':') !== 1) {
  334.                 $privileges['additional'][] = $privilege;
  335.                 continue;
  336.             }
  337.             [ $entity$key ] = \explode(':'$privilege);
  338.             $privileges[$key][] = $entity;
  339.         }
  340.         return $privileges;
  341.     }
  342.     private function getAdministrationStyles(Bundle $bundle): array
  343.     {
  344.         $path 'administration/css/' str_replace('_''-'$bundle->getContainerPrefix()) . '.css';
  345.         $bundlePath $bundle->getPath();
  346.         if (!file_exists($bundlePath '/Resources/public/' $path)) {
  347.             return [];
  348.         }
  349.         return [$path];
  350.     }
  351.     private function getAdministrationScripts(Bundle $bundle): array
  352.     {
  353.         $path 'administration/js/' str_replace('_''-'$bundle->getContainerPrefix()) . '.js';
  354.         $bundlePath $bundle->getPath();
  355.         if (!file_exists($bundlePath '/Resources/public/' $path)) {
  356.             return [];
  357.         }
  358.         return [$path];
  359.     }
  360.     private function getBaseUrl(Bundle $bundlePackageInterface $packagestring $bundleDirectoryName): ?string
  361.     {
  362.         if (!$bundle instanceof Plugin) {
  363.             return null;
  364.         }
  365.         if ($bundle->getAdminBaseUrl()) {
  366.             return $bundle->getAdminBaseUrl();
  367.         }
  368.         $defaultEntryFile 'administration/index.html';
  369.         $bundlePath $bundle->getPath();
  370.         if (!file_exists($bundlePath '/Resources/public/' $defaultEntryFile)) {
  371.             return null;
  372.         }
  373.         $url 'bundles/' $bundleDirectoryName '/' $defaultEntryFile;
  374.         return $package->getUrl($url);
  375.     }
  376.     private function getActiveApps(Context $context): AppCollection
  377.     {
  378.         $criteria = new Criteria();
  379.         $criteria->addAssociation('aclRole');
  380.         $criteria->addFilter(
  381.             new MultiFilter(
  382.                 MultiFilter::CONNECTION_AND,
  383.                 [
  384.                     new EqualsFilter('active'true),
  385.                     new NotFilter(MultiFilter::CONNECTION_AND, [new EqualsFilter('baseAppUrl'null)]),
  386.                 ]
  387.             )
  388.         );
  389.         /** @var AppCollection $apps */
  390.         $apps $this->appRepository->search(new Criteria(), $context)->getEntities();
  391.         return $apps;
  392.     }
  393. }