src/Controller/Pim/ProductController.php line 164

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Pim;
  3. use App\Enum\AssociationTypeEnum;
  4. use App\Enum\AttributeEnum;
  5. use App\Enum\EtimEnum;
  6. use App\Enum\HistoricalEnum;
  7. use App\Enum\PrivilegeEnum;
  8. use App\Enum\RestrictionObjectTypeEnum;
  9. use App\Enum\Workflow\UpdateTypeEnum;
  10. use App\Services\Admin\ContextService;
  11. use App\Services\Admin\CustomerService;
  12. use App\Services\Admin\UserService;
  13. use App\Services\Dam\FormatService;
  14. use App\Services\Main\ExportService;
  15. use App\Services\Main\StatusService;
  16. use App\Services\Pim\AssociationService;
  17. use App\Services\Pim\AttributeService;
  18. use App\Services\Pim\AttributesGroupService;
  19. use App\Services\Pim\CategoryService;
  20. use App\Services\Pim\ChannelService;
  21. use App\Services\Pim\FamilyService;
  22. use App\Services\Pim\ProductService;
  23. use App\Services\Pim\ReferentialService;
  24. use App\Services\Util\JsonService;
  25. use App\Services\Util\UtilService;
  26. use App\Services\Workflow\WorkflowProcessService;
  27. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  28. use Symfony\Component\HttpFoundation\JsonResponse;
  29. use Symfony\Component\HttpFoundation\Request;
  30. use Symfony\Component\HttpFoundation\Response;
  31. use Symfony\Component\HttpFoundation\Session\Session;
  32. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  33. use Symfony\Component\Routing\Annotation\Route;
  34. use Symfony\Component\Serializer\Exception\ExceptionInterface;
  35. use Symfony\Contracts\Translation\TranslatorInterface;
  36. /**
  37.  * Class ProductController.
  38.  *
  39.  * @Route("/product", name="pim.product.")
  40.  */
  41. class ProductController extends AbstractController
  42. {
  43.     /**
  44.      * @Route("/list", name="list", options={"expose" = true})
  45.      *
  46.      * @param Request $request
  47.      * @param ContextService $contextService
  48.      * @param CustomerService $customerService
  49.      * @param ProductService $productService
  50.      * @param AttributeService $attributeService
  51.      * @param AttributesGroupService $attributesGroupService
  52.      * @param ChannelService $channelService
  53.      * @param FamilyService $familyService
  54.      * @param StatusService $statusService
  55.      * @param UserService $userService
  56.      *
  57.      * @throws ExceptionInterface
  58.      *
  59.      * @return Response
  60.      */
  61.     public function index(
  62.         Request $request,
  63.         ContextService $contextService,
  64.         CustomerService $customerService,
  65.         ProductService $productService,
  66.         AttributeService $attributeService,
  67.         AttributesGroupService $attributesGroupService,
  68.         ChannelService $channelService,
  69.         FamilyService $familyService,
  70.         StatusService $statusService,
  71.         UserService $userService,
  72.         UtilService $utilService,
  73.         ExportService $exportService
  74.     ): Response {
  75.         if (!$userService->hasModule('pim') || !$userService->hasPrivilege(PrivilegeEnum::PRODUCTS_LIST)) {
  76.             $utilService->throwCustomException('global.errors.exceptions.pageNotFound');
  77.         }
  78.         $customer $contextService->getCustomer();
  79.         $locale $request->getLocale();
  80.         $listAttributesGroups $attributesGroupService->getList();
  81.         $listAttributes $attributeService->getList();
  82.         $AttributesTypes array_column($listAttributes'type');
  83.         if (!in_array('id'$AttributesTypes)) {
  84.             $utilService->throwCustomException('global.errors.exceptions.noIdAttribute');
  85.         }
  86.         $listChannels $channelService->getList();
  87.         if (empty($listChannels)) {
  88.             $utilService->throwCustomException('global.errors.exceptions.noChannelAvailable');
  89.         }
  90.         $defaultListAttributes $channelService->getAttributesFromChannel($listChannels[0]);
  91.         $listColumns $productService->getListColumns($this->getUser(), $locale$listChannels$defaultListAttributes);
  92.         $listRestrictions $userService->getUserRestrictions();
  93.         $listLanguages $customerService->getListLanguages([], true);
  94.         return $this->render('pim/product/list.html.twig', [
  95.             'listExports' => $exportService->getList(),
  96.             'MULTIPLE_VALUE' => ProductService::MULTIPLE_VALUE,
  97.             'fillingRate' => [
  98.                 'values' => $customerService->getFillingRate($customer),
  99.                 'limitations' => $customer->getCommercialLimitations(),
  100.             ],
  101.             'listChannels' => [
  102.                 'all' => $channelService->serializeListByColumn(
  103.                     $listChannels,
  104.                     'code'
  105.                 ),
  106.                 'listable' => $channelService->serializeListByColumn(
  107.                     $userService->filterListEntityWithRestrictions($listChannels$listRestrictionsRestrictionObjectTypeEnum::RESTRICTION_LISTRestrictionObjectTypeEnum::CHANNEL),
  108.                     'code'
  109.                 ),
  110.             ],
  111.             'listLanguages' => [
  112.                 'all' => array_column($listLanguages'code'),
  113.                 'listable' => array_column($userService->filterListEntityWithRestrictions($listLanguages$listRestrictionsRestrictionObjectTypeEnum::RESTRICTION_LIST), 'code'),
  114.             ],
  115.             'listFamilies' => $familyService->getFlatList(false),
  116.             'listStatus' => $statusService->getList(),
  117.             'listSerializedAttributesGroups' => $attributesGroupService->serializeListWithListAttributes($listAttributesGroups'code'),
  118.             'listColumns' => $listColumns,
  119.             'listColumnsCodes' => array_keys($listColumns),
  120.             'listAttributesGroups' => $listAttributesGroups,
  121.             'listAttributesNames' => $attributeService->getListAttributesNames($listAttributes$locale),
  122.             'listAttributes' => [
  123.                 'all' => $attributeService->serializeListByCode($listAttributes),
  124.                 'listable' => $userService->filterListEntityWithRestrictions($listAttributes$listRestrictionsRestrictionObjectTypeEnum::RESTRICTION_LIST),
  125.                 'typeTable' => array_column(
  126.                     $attributeService->filterListByTypes($listAttributes, [AttributeEnum::TYPE_TABLE]),
  127.                     'code'
  128.                 ),
  129.                 'typeChoices' => $attributeService->serializeListAttributesChoices(
  130.                     $attributeService->filterListByTypes(
  131.                         $listAttributes,
  132.                         [
  133.                             AttributeEnum::TYPE_SELECT,
  134.                             AttributeEnum::TYPE_MULTIPLE,
  135.                         ]
  136.                     )
  137.                 ),
  138.                 'typeId' => $attributeService->filterListByTypes($listAttributes, [AttributeEnum::TYPE_ID])[0] ?? null,
  139.             ],
  140.             'defaultListColumns' => $productService->getDefaultListColumns($locale$defaultListAttributes),
  141.             'listCompleteness' => $channelService->getCompleteness(),
  142.         ]);
  143.     }
  144.     /**
  145.      * @Route(
  146.      *     "/get-list/{json}",
  147.      *     defaults={"json" = false},
  148.      *     name="getList",
  149.      *     options={"expose" = true}
  150.      * )
  151.      *
  152.      * @param Request $request
  153.      * @param ProductService $productService
  154.      * @param bool $json
  155.      *
  156.      * @return Response
  157.      */
  158.     public function list(Request $requestProductService $productServicebool $json false): Response
  159.     {
  160.         $listParameters $request->request->all();
  161.         $context = [
  162.             'channelCode' => $listParameters['channelCode'],
  163.             'languageCode' => $listParameters['languageCode'],
  164.             'listUniqId' => $listParameters['listUniqId'] ?? null,
  165.             'listId' => $listParameters['listId'] ?? null,
  166.             'listIdExcluded' => $listParameters['listIdExcluded'] ?? null,
  167.             'categoryCode' => $listParameters['categoryCode'] ?? null,
  168.             'listCategoriesId' => $listParameters['listCategoriesId'] ?? null,
  169.             'listCategoriesIdExcluded' => $listParameters['listCategoriesIdExcluded'] ?? null,
  170.             'fileCode' => $listParameters['fileCode'] ?? null,
  171.             'listFilters' => json_decode($listParameters['listFilters'] ?? '{}'true),
  172.             'listColumns' => (isset($listParameters['listColumns']))
  173.                 ? array_column($listParameters['listColumns'], 'data')
  174.                 : null,
  175.             'sort' => $listParameters['sort'] ?? null,
  176.             'length' => $listParameters['length'],
  177.             'start' => $listParameters['start'],
  178.         ];
  179.         return ($json)
  180.             ? $this->json($productService->getListByContext($context))
  181.             : new Response(json_encode(
  182.                 $productService->serializeForDatatable(
  183.                     $productService->getListByContext($context),
  184.                     [
  185.                         'channelCode' => $listParameters['channelCode'],
  186.                         'languageCode' => $listParameters['languageCode'],
  187.                         'draw' => $listParameters['draw'],
  188.                         'start' => $listParameters['start'],
  189.                         'length' => $listParameters['length'],
  190.                         'fastResult' => $context['listFilters']['fastResult'] ?? false,
  191.                     ]
  192.                 )
  193.             ), 200, ['Content-Type' => 'text/html']); //For some reaons it's faster return text/html than application/json and ajax/datable handle it correctly
  194.     }
  195.     /**
  196.      * @Route(
  197.      *     "/edit/{id}/{channelCode}/{languageCode}/{origin}",
  198.      *     defaults={"id" = null, "channelCode" = null, "languageCode" = null, "origin" = null},
  199.      *     name="edit",
  200.      *     methods={"GET", "POST"}
  201.      * )
  202.      *
  203.      * Usage examples :
  204.      * "/edit/null/catalog/fr?familyCode=animals" is a new product creation
  205.      * "/edit/[uuid]/catalog/fr" is a simple product edition
  206.      * "/edit/multiple/catalog/fr" is a multiple products edition, listIds are in session or sent in POST request
  207.      * "/edit/multiple/catalog/fr?categoryId=[uuid]" is a multiple products edition from products detail list
  208.      *
  209.      * @param TranslatorInterface $translator
  210.      * @param WorkflowProcessService $workflowProcessService
  211.      * @param ProductService $productService
  212.      * @param FamilyService $familyService
  213.      * @param CustomerService $customerService
  214.      * @param ChannelService $channelService
  215.      * @param CategoryService $categoryService
  216.      * @param StatusService $statusService
  217.      * @param AttributesGroupService $attributesGroupService
  218.      * @param AttributeService $attributeService
  219.      * @param ReferentialService $referentialService
  220.      * @param UserService $userService
  221.      * @param UtilService $utilService
  222.      * @param FormatService $formatService
  223.      * @param Request $request
  224.      * @param null|string $id
  225.      * @param null|string $channelCode
  226.      * @param null|string $languageCode
  227.      * @param null|string $origin
  228.      *
  229.      * @return Response
  230.      */
  231.     public function edit(
  232.         TranslatorInterface $translator,
  233.         WorkflowProcessService $workflowProcessService,
  234.         ProductService $productService,
  235.         FamilyService $familyService,
  236.         CustomerService $customerService,
  237.         ChannelService $channelService,
  238.         CategoryService $categoryService,
  239.         StatusService $statusService,
  240.         AttributesGroupService $attributesGroupService,
  241.         AttributeService $attributeService,
  242.         ReferentialService $referentialService,
  243.         UserService $userService,
  244.         UtilService $utilService,
  245.         FormatService $formatService,
  246.         Request $request,
  247.         ?string $id,
  248.         ?string $channelCode,
  249.         ?string $languageCode,
  250.         ?string $origin null
  251.     ): Response {
  252.         if (!$userService->hasModule('pim') || !$userService->hasPrivilege(PrivilegeEnum::PRODUCTS_LIST)) {
  253.             $utilService->throwCustomException('global.errors.exceptions.pageNotFound');
  254.         }
  255.         $user $this->getUser();
  256.         $categoryId $request->query->get('categoryId');
  257.         $listChannels $channelService->getList(['noRestriction' => true]);
  258.         if (null === $channelCode) {
  259.             $channel $listChannels[0];
  260.             $channelCode $channel['code'];
  261.         } else {
  262.             $channel null;
  263.             foreach ($listChannels as $currentChannel) {
  264.                 if ($currentChannel['code'] === $channelCode) {
  265.                     $channel $currentChannel;
  266.                     break;
  267.                 }
  268.             }
  269.             if (null === $channel) {
  270.                 $channel $listChannels[0];
  271.             }
  272.         }
  273.         $languageCode = (null === $languageCode || !in_array($languageCode$channel['list_languages']))
  274.             ? $channel['list_languages'][0]
  275.             : $languageCode;
  276.         $context = [
  277.             'channelCode' => $channelCode,
  278.             'languageCode' => $languageCode,
  279.         ];
  280.         $listIds null;
  281.         $session = new Session();
  282.         if (isset($categoryId)) {
  283.             $recursive = ('true' === $request->query->get('recursive'));
  284.             $categoryId = ('null' === $categoryId) ? null $categoryId;
  285.             $categoryId str_replace('products-list-'''$categoryId);
  286.             $listFilters $context;
  287.             if (null !== $request->cookies->get('productsFilters')) {
  288.                 $cookieListFilters json_decode($request->cookies->get('productsFilters'), true);
  289.                 $listFilters array_merge(
  290.                     $listFilters,
  291.                     [
  292.                         'includeChildrenCategories' => $cookieListFilters['includeChildrenCategories'] ?? false,
  293.                         'createdDateFrom' => $cookieListFilters['createdDateFrom'] ?? null,
  294.                         'createdDateTo' => $cookieListFilters['createdDateTo'] ?? null,
  295.                         'updatedDateFrom' => $cookieListFilters['updatedDateFrom'] ?? null,
  296.                         'updatedDateTo' => $cookieListFilters['updatedDateTo'] ?? null,
  297.                         'listStatusCodes' => $cookieListFilters['listStatusCodes'] ?? null,
  298.                         'completeness' => $cookieListFilters['completeness'] ?? null,
  299.                         'listFamilyCodes' => $cookieListFilters['listFamilyCodes'] ?? null,
  300.                         'listAttributeFilters' => $cookieListFilters['listAttributes'] ?? null,
  301.                         'search' => $cookieListFilters['search'] ?? null,
  302.                     ]
  303.                 );
  304.             }
  305.             //TODO: ITDB-1495
  306.             $listIds array_column($categoryService->getListProducts($categoryId$recursive$listFilters), 'product_id');
  307.         } elseif (null !== $request->request->get('listIds')) {
  308.             $listIds json_decode($request->request->get('listIds') ?? '');
  309.             $session->set('listIds'$listIds);
  310.             return $this->json($listIds);
  311.         } elseif (null !== $session->get('listIds')) {
  312.             $listIds $session->get('listIds');
  313.         }
  314.         $isMultipleEdition = (null !== $listIds && 'multiple' === $id);
  315.         $multipleEditionData = [];
  316.         if ($isMultipleEdition) {
  317.             $multipleEditionData $productService->getMultipleEditionData($listIds);
  318.             $product $multipleEditionData['commonValues'];
  319.             if (!$multipleEditionData['listProducts']) {
  320.                 throw new NotFoundHttpException($translator->trans('categories.noProductFound', ['productsSingular' => mb_strtolower($translator->trans('products.singular'))]));
  321.             }
  322.             if (=== count($multipleEditionData['listProducts']) && !count($multipleEditionData['listUniqIdsExcluded'])) {
  323.                 $isMultipleEdition false;
  324.                 $id $product['id'][0];
  325.             }
  326.         } elseif ('multiple' === $id) {
  327.             return $this->redirectToRoute('pim.product.list');
  328.         }
  329.         $isNewProduct = !$isMultipleEdition && ('null' === $id);
  330.         $familyCode $request->query->get('familyCode');
  331.         if (!$isMultipleEdition) {
  332.             if ($isNewProduct) {
  333.                 $product $productService->getNewProductDefaultValues($familyCode);
  334.             } else {
  335.                 $productResult $productService->getProductById($id);
  336.                 if ($productResult['error']) {
  337.                     return $this->redirectToRoute('pim.product.list');
  338.                 }
  339.                 $product $productResult['content'];
  340.             }
  341.             if (isset($product['id']) && $userService->hasPrivilege(PrivilegeEnum::COMPLETENESS)) {
  342.                 $product['completeness'] = $productService->getCompleteness($product['id']);
  343.             }
  344.         }
  345.         $template = (null === $origin)
  346.             ? 'pim/product/edit.html.twig'
  347.             'pim/product/edit/edit.html.twig';
  348.         $listAttributes $attributeService->getList(['noRestriction' => true]);
  349.         $listAttributesByCodes $attributeService->serializeListByCode($listAttributes);
  350.         $productSheet $productService->getProductSheet(
  351.             $user->getCustomer(),
  352.             $product,
  353.             $channelCode,
  354.             $languageCode,
  355.             $listAttributesByCodes
  356.         );
  357.         $isEdition = (isset($product['id']));
  358.         $isProcessing false;
  359.         $isProcessingDeletion false;
  360.         if ($isEdition && !$isMultipleEdition) {
  361.             $userId $user->getId();
  362.             $roleId $user->getRole()->getId();
  363.             $context['listAssociations'] = $product['list_associations'] ?? [];
  364.             $isProcessing $workflowProcessService->isObjectProcessing($id);
  365.             $product['workflow']['items'] = [];
  366.             if ($isProcessing) {
  367.                 $isProcessingDeletion $workflowProcessService->isObjectProcessing($id, [UpdateTypeEnum::DELETE]);
  368.                 $product['workflow']['items'] = $productService->getProductWorkflowItems($product$userId$roleId$context);
  369.             }
  370.         }
  371.         $listRestrictions $userService->getUserRestrictions();
  372.         $defaultListAttributes $channelService->getAttributesFromChannel($listChannels[0]);
  373.         $listFamilies $familyService->getFlatList(false);
  374.         $listFamiliesById $familyService->serializeListByColumn($listFamilies'id');
  375.         if (isset($product['family_id'])) {
  376.             $listFamiliesById[$product['family_id']]['family_has_attributes'] = $familyService->getById($product['family_id'])['content']['family_has_attributes'];
  377.         } elseif ($isNewProduct) {
  378.             $family $familyService->getByCode($familyCode)['content'];
  379.             if (null === $family) {
  380.                 return $this->redirectToRoute('pim.product.list');
  381.             }
  382.             $listFamiliesById[$family['id']]['family_has_attributes'] = $family['family_has_attributes'];
  383.         }
  384.         $listLanguages $customerService->getListLanguages([], true);
  385.         $listablesAttributes $attributeService->filterAllowedList($listAttributes$listRestrictionsRestrictionObjectTypeEnum::RESTRICTION_LIST);
  386.         return $this->render($template, [
  387.             'isEdition' => $isEdition || $isMultipleEdition,
  388.             'isMultipleEdition' => $isMultipleEdition,
  389.             'isProcessingDeletion' => $isProcessingDeletion,
  390.             'isProcessing' => $isProcessing,
  391.             'MULTIPLE_VALUE' => ProductService::MULTIPLE_VALUE,
  392.             'channelId' => $channel['id'],
  393.             'channelName' => $channel['name'],
  394.             'channelCode' => $channelCode,
  395.             'languageCode' => $languageCode,
  396.             'product' => $product,
  397.             'listMultipleEdition' => $multipleEditionData,
  398.             'listLanguages' => [
  399.                 'all' => array_column($listLanguages'code'),
  400.                 'listable' => array_column($userService->filterListEntityWithRestrictions($listLanguages$listRestrictionsRestrictionObjectTypeEnum::RESTRICTION_LIST), 'code'),
  401.                 'editable' => array_column($userService->filterListEntityWithRestrictions($listLanguages$listRestrictionsRestrictionObjectTypeEnum::RESTRICTION_EDIT), 'code'),
  402.             ],
  403.             'listChannels' => [
  404.                 'all' => $channelService->serializeListByColumn(
  405.                     $listChannels,
  406.                     'code'
  407.                 ),
  408.                 'listable' => $channelService->serializeListByColumn(
  409.                     $userService->filterListEntityWithRestrictions($listChannels$listRestrictionsRestrictionObjectTypeEnum::RESTRICTION_LISTRestrictionObjectTypeEnum::CHANNEL),
  410.                     'code'
  411.                 ),
  412.                 'editable' => $channelService->serializeListByColumn(
  413.                     $userService->filterListEntityWithRestrictions($listChannels$listRestrictionsRestrictionObjectTypeEnum::RESTRICTION_EDITRestrictionObjectTypeEnum::CHANNEL),
  414.                     'code'
  415.                 ),
  416.             ],
  417.             'listAttributesGroups' => $attributesGroupService->getList(),
  418.             'listAttributes' => [
  419.                 'all' => $listAttributesByCodes,
  420.                 'listable' => $attributeService->serializeListByCode(
  421.                     $listablesAttributes
  422.                 ),
  423.                 'editable' => $attributeService->serializeListByCode(
  424.                     $attributeService->filterAllowedList($listAttributes$listRestrictionsRestrictionObjectTypeEnum::RESTRICTION_EDIT)
  425.                 ),
  426.                 'declinable' => $attributeService->serializeListByCode(
  427.                     $attributeService->filterDeclinableList($listablesAttributes)
  428.                 ),
  429.                 'typeId' => $attributeService->filterListByTypes($listAttributes, [AttributeEnum::TYPE_ID])[0] ?? null,
  430.                 'typeTable' => array_column(
  431.                     $attributeService->filterListByTypes($listAttributes, [AttributeEnum::TYPE_TABLE]),
  432.                     'code'
  433.                 ),
  434.                 'typeChoices' => $attributeService->serializeListAttributesChoices(
  435.                     $attributeService->filterListByTypes(
  436.                         $listAttributes,
  437.                         [
  438.                             AttributeEnum::TYPE_SELECT,
  439.                             AttributeEnum::TYPE_MULTIPLE,
  440.                         ]
  441.                     )
  442.                 ),
  443.             ],
  444.             'listFamilies' => $listFamiliesById,
  445.             'listFamiliesByCode' => $familyService->serializeListByColumn($listFamilies'code'),
  446.             'listReferentials' => $referentialService->getList(),
  447.             'listStatus' => $statusService->serializeListByColumn($statusService->getList(), 'code'),
  448.             'productSheet' => $productSheet,
  449.             'listAssociationsTypes' => AssociationTypeEnum::LIST_TYPES,
  450.             'listColumns' => $productService->getListColumns($user$request->getLocale(), $listChannels$defaultListAttributes),
  451.             'listFormats' => $formatService->getList(),
  452.             'listEtimRelease' => EtimEnum::LIST_ETIM_RELEASE,
  453.         ]);
  454.     }
  455.     /**
  456.      * @Route("/get-common-categories", name="getCommonCategories")
  457.      * 
  458.      * @param Request $request
  459.      * @param ProductService $productService
  460.      * 
  461.      * @return Response
  462.      */
  463.     public function getCommonCategories(Request $requestProductService $productService): Response
  464.     {
  465.         return $this->json($productService->getCommonCategories($request->request->get('listIds')));
  466.     }
  467.     /**
  468.      * @Route("/completeness", name="completeness")
  469.      *
  470.      * @param ProductService $productService
  471.      * @param ChannelService $channelService
  472.      * @param UserService $userService
  473.      *
  474.      * @return Response
  475.      */
  476.     public function completeness(
  477.         ProductService $productService,
  478.         ChannelService $channelService,
  479.         UserService $userService,
  480.         UtilService $utilService
  481.     ): Response {
  482.         if (!$userService->hasModule('pim') || !$userService->hasPrivilege(PrivilegeEnum::COMPLETENESS)) {
  483.             $utilService->throwCustomException('global.errors.exceptions.pageNotFound');
  484.         }
  485.         return $this->render('main/completeness.html.twig', [
  486.             'listChannels' => $channelService->serializeListByColumn($channelService->getList(), 'code'),
  487.             'completeness' => $channelService->getCompleteness(),
  488.         ]);
  489.     }
  490.     /**
  491.      * @Route("/get-categories/{id}", name="getListCategories")
  492.      *
  493.      * @param string $id
  494.      * @param ProductService $productService
  495.      *
  496.      * @return Response
  497.      */
  498.     public function getListCategories(string $idProductService $productService): Response
  499.     {
  500.         return $this->json($productService->getListCategories($id));
  501.     }
  502.     /**
  503.      * @Route(
  504.      *     "/save",
  505.      *     name="save",
  506.      *     methods={"POST"}
  507.      * )
  508.      *
  509.      * @param Request $request
  510.      * @param ContextService $contextService
  511.      * @param JsonService $jsonService
  512.      * @param ProductService $productService
  513.      * @param AttributeService $attributeService
  514.      * @param AssociationService $associationService
  515.      *
  516.      * @return Response
  517.      */
  518.     public function save(
  519.         Request $request,
  520.         ContextService $contextService,
  521.         JsonService $jsonService,
  522.         ProductService $productService,
  523.         AttributeService $attributeService,
  524.         AssociationService $associationService
  525.     ): Response {
  526.         $context $request->request->get('context') ?? [];
  527.         $product $jsonService->decode($request->request->get('product'));
  528.         $listsCustomChoices $jsonService->decode($request->request->get('listsCustomChoices'));
  529.         if (count($listsCustomChoices) > 0) {
  530.             $attributeService->saveListsCustomChoices($listsCustomChoices);
  531.         }
  532.         $listDependenciesToDelete $jsonService->decode($request->request->get('listDependenciesToDelete'));
  533.         if (count($listDependenciesToDelete) > && isset($product['id'])) {
  534.             if (is_array($product['id'])) {
  535.                 foreach ($product['id'] as $productId) {
  536.                     $associationService->delete($listDependenciesToDelete$productIdtrue);
  537.                 }
  538.             } else {
  539.                 $associationService->delete($listDependenciesToDelete$product['id'], true);
  540.             }
  541.         }
  542.         $listProducts $jsonService->decode($request->request->get('listProducts'));
  543.         if (count($listProducts) > 0) {
  544.             $listAssociationsToDelete $jsonService->decode($request->request->get('listAssociationsToDelete'));
  545.             if (count($listAssociationsToDelete) > 0) {
  546.                 foreach ($product['id'] as $productId) {
  547.                     $associationService->delete($listAssociationsToDelete$productId);
  548.                 }
  549.             }
  550.             return $this->json(
  551.                 $productService->saveList(
  552.                     $listProducts,
  553.                     $product,
  554.                     $contextService->getCustomer(),
  555.                     $context
  556.                 )
  557.             );
  558.         }
  559.         $result $productService->save(
  560.             $product,
  561.             $request->request->get('editType') ?? HistoricalEnum::TYPE_EDIT
  562.         );
  563.         if (!$result['error'] && isset($result['content']['product'])) {
  564.             $result['content']['product']['productSheet'] = $productService->getProductSheet(
  565.                 $contextService->getCustomer(),
  566.                 $result['content']['product'],
  567.                 $context['channelCode'],
  568.                 $context['languageCode'],
  569.             );
  570.             $result['content']['product']['completeness'] = $productService->getCompleteness($result['content']['product']['id']);
  571.         }
  572.         return $this->json($result);
  573.     }
  574.     /**
  575.      * @Route(
  576.      *     "/duplicate",
  577.      *     name="duplicate",
  578.      *     methods={"POST"}
  579.      * )
  580.      *
  581.      * @param Request $request
  582.      * @param JsonService $jsonService
  583.      * @param ProductService $productService
  584.      *
  585.      * @return Response
  586.      */
  587.     public function duplicate(Request $requestJsonService $jsonServiceProductService $productService): Response
  588.     {
  589.         return $this->json(
  590.             $productService->duplicate(
  591.                 $request->request->get('productId'),
  592.                 $request->request->get('uniqId'),
  593.                 $request->request->get('originChannelId'),
  594.                 $jsonService->decode($request->request->get('listChannelsCode'))
  595.             )
  596.         );
  597.     }
  598.     /**
  599.      * @Route(
  600.      *     "/delete",
  601.      *     name="delete",
  602.      *     methods={"POST"}
  603.      * )
  604.      *
  605.      * @param Request $request
  606.      * @param ProductService $productService
  607.      *
  608.      * @return Response
  609.      */
  610.     public function delete(Request $requestProductService $productService): Response
  611.     {
  612.         $channelCode $request->request->get('channel-code');
  613.         return $this->json(
  614.             $productService->delete(
  615.                 $request->request->get('products-list'),
  616.                 empty($channelCode) ? null $channelCode
  617.             )
  618.         );
  619.     }
  620.     /**
  621.      * @Route("/id/{id}", name="getById")
  622.      */
  623.     public function getById(
  624.         string $id,
  625.         ProductService $productService,
  626.         ContextService $contextService,
  627.         ChannelService $channelService,
  628.         AssociationService $associationService
  629.     ): Response {
  630.         $channel $channelService->getFirstChannel();
  631.         $channelCode $channel['code'];
  632.         $languageCode $channel['list_languages'][0];
  633.         $productResult $productService->getProductById($id);
  634.         $differentByChannel $associationService->isAssociationDifferentByChannel();
  635.         $listChannels $channelService->getList(['noRestriction' => true]);
  636.         $productResult['content']['listAssociations'] = $associationService->serializeList(
  637.             $productResult['content']['list_associations'] ?? [],
  638.             [
  639.                 'channelCode' => $channelCode,
  640.                 'languageCode' => $languageCode,
  641.             ],
  642.             $differentByChannel,
  643.             $listChannels
  644.         );
  645.         $productResult['content']['listDependencies'] = $associationService->serializeList(
  646.             $productResult['content']['list_dependencies'] ?? [],
  647.             [
  648.                 'channelCode' => $channelCode,
  649.                 'languageCode' => $languageCode,
  650.             ],
  651.             $differentByChannel,
  652.             $listChannels
  653.         );
  654.         $productResult['content']['productSheet'] = $productService->getProductSheet(
  655.             $contextService->getCustomer(),
  656.             $productResult['content'],
  657.             $channelCode,
  658.             $languageCode,
  659.         );
  660.         $productResult['content']['completeness'] = $productService->getCompleteness($productResult['content']['id']);
  661.         return $this->json($productResult);
  662.     }
  663.     /**
  664.      * @Route(
  665.      *     "/search/{string}/{channelCode}/{languageCode}/{codeAttributeImage}/{codeAttributeDescription}",
  666.      *     name="search",
  667.      *     options={"expose" = true}
  668.      * )
  669.      *
  670.      * @return JsonResponse
  671.      */
  672.     public function search(
  673.         string $string,
  674.         string $channelCode,
  675.         string $languageCode,
  676.         string $codeAttributeImage,
  677.         string $codeAttributeDescription,
  678.         ProductService $productService
  679.     ): Response {
  680.         $codeAttributeImage = ('null' === $codeAttributeImage) ? null $codeAttributeImage;
  681.         $codeAttributeDescription = ('null' === $codeAttributeDescription) ? null $codeAttributeDescription;
  682.         return $this->json(
  683.             $productService->search($string$channelCode$languageCode$codeAttributeImage$codeAttributeDescription)
  684.         );
  685.     }
  686.     /**
  687.      * @Route(
  688.      *     "/list/id",
  689.      *     name="getListUniqId"
  690.      * )
  691.      */
  692.     public function getListUniqId(ProductService $productService): Response
  693.     {
  694.         return $this->json(
  695.             $productService->getListUniqId()
  696.         );
  697.     }
  698.     /**
  699.      * @Route(
  700.      *     "/association/format-association-product",
  701.      *     name="formatAssociationProduct",
  702.      *     options={"expose" = true}
  703.      * )
  704.      */
  705.     public function formatAssociationProduct(AssociationService $associationServiceJsonService $jsonServiceRequest $request): Response
  706.     {
  707.         return $this->json(
  708.             $associationService->serializeAssociationDependencies(
  709.                 $jsonService->decode($request->request->get('listAssociations')),
  710.                 $jsonService->decode($request->request->get('listDependencies')),
  711.                 $jsonService->decode($request->request->get('listChannels')),
  712.                 $jsonService->decode($request->request->get('listChannelsAvailable')),
  713.                 $jsonService->decode($request->request->get('context')),
  714.                 'true' === $request->request->get('isMultipleEdition')
  715.             )
  716.         );
  717.     }
  718.     /**
  719.      * @Route(
  720.      *     "/import-list-filter-file",
  721.      *     name="importListFilterFile",
  722.      *     methods={"POST"},
  723.      *     options={"expose" = true}
  724.      * )
  725.      */
  726.     public function importListFilterFile(Request $requestUtilService $utilService): Response
  727.     {
  728.         return $this->json(
  729.             $utilService->getExcelFileValues(
  730.                 $request->files->get('import-list-filter-file'),
  731.                 true
  732.             )
  733.         );
  734.     }
  735. }