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

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