src/Controller/Admin/AdminStoresController.php line 44
<?phpnamespace App\Controller\Admin;use App\Controller\Bootstrap\DefaultSalesHubController;use App\Entity\Cms;use App\Entity\Configuration;use App\Entity\ProductRelation;use App\Entity\Store;use App\Entity\SyncLog;use App\Service\ProductRelationTools;use App\Utils\Breadcrumb;use Doctrine\ORM\EntityManagerInterface;use Doctrine\ORM\Query\Expr\Join;use Symfony\Component\Form\Extension\Core\Type\CheckboxType;use Symfony\Component\Form\Extension\Core\Type\ChoiceType;use Symfony\Component\Form\Extension\Core\Type\IntegerType;use Symfony\Component\Form\Extension\Core\Type\SubmitType;use Symfony\Component\Form\Extension\Core\Type\TextType;use Symfony\Component\HttpFoundation\JsonResponse;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Routing\Annotation\Route;use App\Service\Prestashop\PrestashopProductManager;use App\Service\Wordpress\WordpressProductManager;use App\Service\Shopify\ShopifyProductManager;class AdminStoresController extends DefaultSalesHubController{public string $page_name = 'Stores';public $productRelationTools;public const PRESTASHOP_PRODUCT_PER_PAGE = 500;public const WORDPRESS_PRODUCT_PER_PAGE = 100; //Wordpress max value is 100public const SHOPIFY_PRODUCT_PER_PAGE = 20;public function assignBreadcrumb(){$this->breadcrumb = [(new Breadcrumb('Dashboard', $this->router->generate('dashboard'))),(new Breadcrumb('Stores')),];}#[Route('/admin/stores', name: 'stores')]public function index(EntityManagerInterface $entityManager,Request $request,ProductRelationTools $productRelationTools,PrestashopProductManager $prestashopProductManager,WordpressProductManager $wordpressProductManager,ShopifyProductManager $shopifyProductManager): Response{$this->productRelationTools = $productRelationTools;$this->theme->addJsDef(['ajax_url' => $this->generateUrl('stores', ['ajax' => 1])]);if($request->request->get('ajax') || $request->query->get('ajax')){return $this->handleAjax($entityManager, $request, $prestashopProductManager, $wordpressProductManager, $shopifyProductManager);}if($request->query->has('set_store')){return $this->form($entityManager, $request);}elseif($request->query->has('set_products')){return $this->productsForm($entityManager, $request);}elseif($request->query->has('delete_store')){$this->deleteEntity($entityManager, $request);}return $this->listing($entityManager);}protected function listing(EntityManagerInterface $entityManager){$cms = $entityManager->getRepository(Cms::class)->findAll();$cmsFilter = [];foreach ($cms as $cms_single){$cmsFilter[$cms_single->getId()] = $cms_single->getName();}$datatable = ['name' => 'Stores','selector' => 'stores','columns' => [['display_name' => 'ID', 'data' => 'id', 'name' => 'store.id'],['display_name' => 'Cms', 'data' => 'cms_name', 'name' => 'cms.name'],['display_name' => 'Name', 'data' => 'name', 'name' => 'store.name'],['display_name' => 'Base url', 'data' => 'base_url', 'name' => 'store.base_url'],['display_name' => 'Extra price amount', 'data' => 'extra_price_amount', 'name' => 'store.extra_price_amount'],['display_name' => 'Extra price percentage', 'data' => 'extra_price_percentage', 'name' => 'store.extra_price_percentage'],['display_name' => 'Active', 'data' => 'active', 'name' => 'store.active'],],'column_actions' => [['name' => 'Edit','url' => $this->generateUrl('stores', ['set_store' => 1, 'id_store' => '__the_id__']),],['name' => 'Set Products','url' => $this->generateUrl('stores', ['set_products' => 1, 'id_store' => '__the_id__']),],['name' => 'Delete','url' => $this->generateUrl('stores', ['delete_store' => 1, 'id_store' => '__the_id__']),],],'filter' => ['field' => 'cms.id','options' => $cmsFilter],'columnDefs' => [['targets' => 6,'orderable' => false,'render' => ['val_check' => 'active','if_true' => '<span class="badge py-3 px-4 fs-7 badge-light-success">Active</span>','if_false' => '<span class="badge py-3 px-4 fs-7 badge-light-danger">Inactive</span>',]]]];$this->theme->addJavascriptFile('js/custom/utilities/datatables.js');$this->theme->addJsDef(['datatables' => [$datatable]]);$rendered_datatable = $this->render('partials/datatable.html.twig', ['datatable' => $datatable,])->getContent();return $this->render('pages/stores/index.html.twig', ['rendered_datatable' => $rendered_datatable,'add_product_url' => $this->generateUrl('stores', ['set_store' => 1]),]);}protected function form(EntityManagerInterface $entityManager, Request $request){$this->theme->addJavascriptFile('js/custom/pages/stores/general.js');$cms = $entityManager->getRepository(Cms::class)->findAll();$cms_choices = [];foreach ($cms as $cms_single){$cms_choices[$cms_single->getName()] = $cms_single->getId();}$form = $this->createFormBuilder(null)->add('cms', ChoiceType::class, ['choices' => $cms_choices])->add('name', TextType::class)->add('admin_id_manufacturer', IntegerType::class)->add('admin_id_supplier', IntegerType::class)->add('base_url', TextType::class, ['required' => false,])->add('api_key', TextType::class, ['required' => false,])->add('api_secret', TextType::class, ['required' => false,])->add('extra_price_amount', IntegerType::class)->add('extra_price_percentage', IntegerType::class)->add('active', CheckboxType::class, ['required' => false,])->add('unlimited_stock', CheckboxType::class, ['required' => false,])->add('save', SubmitType::class, ['label' => 'Save'])->getForm();$form->handleRequest($request);if ($form->isSubmitted() && $form->isValid()) {$form_data = $form->getData();$id_store = $request->query->get('id_store');if($id_store){$storeObj = $entityManager->getRepository(Store::class)->findOneBy(['id' => $id_store]);}else{$storeObj = new Store();}$cmsObj = $entityManager->getRepository(Cms::class)->findOneBy(['id' => $form_data['cms']]);$storeObj->setCms($cmsObj);$storeObj->setName($form_data['name']);$storeObj->setAdminIdManufacturer($form_data['admin_id_manufacturer']);$storeObj->setAdminIdSupplier($form_data['admin_id_supplier']);$storeObj->setBaseUrl($form_data['base_url']);$storeObj->setApiKey((string)$form_data['api_key']);$storeObj->setApiSecret((string)$form_data['api_secret']);$storeObj->setExtraPriceAmount($form_data['extra_price_amount']);$storeObj->setExtraPricePercentage($form_data['extra_price_percentage']);$storeObj->setActive($form_data['active']);$storeObj->setUnlimitedStock($form_data['unlimited_stock']);$entityManager->persist($storeObj);$entityManager->flush();}else{$id_store = $request->query->get('id_store');if($id_store){$storeObj = $entityManager->getRepository(Store::class)->findOneBy(['id' => $id_store]);$form->setData(['cms' => ($storeObj->getCms())->getId(),'name' => $storeObj->getName(),'admin_id_manufacturer' => $storeObj->getAdminIdManufacturer(),'admin_id_supplier' => $storeObj->getAdminIdSupplier(),'base_url' => $storeObj->getBaseUrl(),'api_key' => $storeObj->getApiKey(),'api_secret' => $storeObj->getApiSecret(),'extra_price_amount' => $storeObj->getExtraPriceAmount(),'extra_price_percentage' => $storeObj->getExtraPricePercentage(),'active' => $storeObj->isActive(),'unlimited_stock' => $storeObj->isUnlimitedStock(),]);}else{$form->setData(['extra_price_amount' => 0,'extra_price_percentage' => 0,]);}}return $this->render('pages/stores/form.html.twig', ['form' => $form->createView(),]);}protected function productsForm(EntityManagerInterface $entityManager, Request $request){$id_store = $request->query->get('id_store');$storeObj = $entityManager->getRepository(Store::class)->findOneBy(['id' => $id_store]);$this->theme->addJavascriptFile('js/custom/pages/stores/products_wordpress.js');$this->theme->addJsDef(['id_store' => $id_store,'id_cms' => $storeObj->getCms()->getId()]);$datatable = ['name' => 'ProductRelations','selector' => 'product_relations_'.$id_store,'columns' => [['display_name' => 'ID', 'data' => 'id', 'name' => 'product_relation.id'],['display_name' => 'Id product', 'data' => 'id_product', 'name' => 'product_relation.id_product'],['display_name' => 'Name', 'data' => 'name', 'name' => 'product_relation.name'],['display_name' => 'Image', 'data' => 'sample_image_url', 'name' => 'product_relation.sample_image_url'],['display_name' => 'Admin Id product', 'data' => 'admin_id_product', 'name' => 'product_relation.admin_id_product'],],'filter' => [],'columnDefs' => [['targets' => 3,'orderable' => false,'render' => ['handle_function' => 'renderProductImage',]],['targets' => 4,'orderable' => false,'render' => ['handle_function' => 'renderAdminIdProduct',]]]];$this->theme->addJavascriptFile('js/custom/utilities/datatables.js');$this->theme->addJsDef(['datatables' => [$datatable]]);$rendered_datatable = $this->render('partials/datatable.html.twig', ['datatable' => $datatable,])->getContent();return $this->render('pages/stores/productsForm.html.twig', ['rendered_datatable' => $rendered_datatable]);}protected function deleteEntity(EntityManagerInterface $entityManager, Request $request){$id_store = $request->query->get('id_store');if($id_store){$storeObj = $entityManager->getRepository(Store::class)->findOneBy(['id' => $id_store]);$entityManager->remove($storeObj);$entityManager->flush();}}public function handleAjax(EntityManagerInterface $entityManager, Request $request, PrestashopProductManager $prestashopProductManager, WordpressProductManager $wordpressProductManager, ShopifyProductManager $shopifyProductManager): JsonResponse{$ajaxData = json_decode($request->getContent(), true);if($draw = $request->query->get('draw')){$selector = $request->query->get('selector');if($selector && substr($selector, 0, strlen('product_relations')) == 'product_relations'){$id_store = substr($selector, strlen('product_relations_'));return $this->drawProductsForm($entityManager, $request, $id_store);}else{return $this->drawListingTable($entityManager, $request, $draw);}}elseif(isset($ajaxData['ajaxAction']) && $ajaxData['ajaxAction'] == 'loadProducts'){return $this->loadProducts($entityManager, $prestashopProductManager, $wordpressProductManager, $shopifyProductManager, $ajaxData['id_store'], $ajaxData['page'], $ajaxData['total_products'], $ajaxData['after']);}elseif(isset($ajaxData['ajaxAction']) && $ajaxData['ajaxAction'] == 'saveAdminIdProduct'){return $this->saveAdminIdProduct($entityManager, $ajaxData['id_product_relation'], $ajaxData['admin_id_product']);}elseif(isset($ajaxData['ajaxAction']) && $ajaxData['ajaxAction'] == 'checkApi'){return $this->checkApi($prestashopProductManager, $wordpressProductManager, $shopifyProductManager, $ajaxData['id_cms'], $ajaxData['base_url'], $ajaxData['api_key'], $ajaxData['api_secret']);}}protected function drawListingTable(EntityManagerInterface $entityManager, Request $request, $draw) : JsonResponse{$options = $request->query->all();$order_by = 'id';$order_way = 'DESC';$where = null;$limit = (isset($options['length']) ? $options['length'] : 10);$offset = (isset($options['start']) ? $options['start'] : 0);if(isset($options['order']) && isset($options['order'][0])){$order_by = $options['columns'][$options['order'][0]['column']]['name'];$order_way = $options['order'][0]['dir'];}if(isset($options['search']) && isset($options['search']['value']) && $options['search']['value']){$where = $options['search']['value'];}$query = $entityManager->createQueryBuilder()->select('store')->from('App\Entity\Store', 'store')->leftJoin('App\Entity\Cms','cms',Join::WITH,'store.cms = cms.id');if($where){$query->where($where);}$stores = $query->orderBy($order_by, $order_way)->setMaxResults($limit)->setFirstResult($offset)->getQuery()->getResult();$resultTotal = $entityManager->getRepository(Store::class)->count([]);$resultDatatable = [];foreach ($stores as $store){$this_cms = $store->getCms();$this_data = ['id' => $store->getId(),'cms_id' => $this_cms->getId(),'cms_name' => $this_cms->getName(),'name' => $store->getName(),'base_url' => $store->getBaseUrl(),'extra_price_amount' => $store->getExtraPriceAmount(),'extra_price_percentage' => $store->getExtraPricePercentage(),'active' => $store->isActive(),];$resultDatatable[] = $this_data;}return JsonResponse::fromJsonString(json_encode(['draw' => $draw,'recordsTotal' => $resultTotal,'recordsFiltered' => $resultTotal,'data' => $resultDatatable]));}protected function drawProductsForm(EntityManagerInterface $entityManager, Request $request, $id_store) : JsonResponse{$options = $request->query->all();$order_by = 'id';$order_way = 'ASC';$where = null;$limit = (isset($options['length']) ? $options['length'] : 10);$offset = (isset($options['start']) ? $options['start'] : 0);if(isset($options['order']) && isset($options['order'][0])){$order_by = $options['columns'][$options['order'][0]['column']]['name'];$order_way = $options['order'][0]['dir'];}if(isset($options['search']) && isset($options['search']['value']) && $options['search']['value']){$where = $options['search']['value'];}$query = $entityManager->createQueryBuilder()->select('product_relation')->from('App\Entity\ProductRelation', 'product_relation')->where('product_relation.store = '.$id_store.' AND product_relation.deleted = 0');if($where){$query->where($where);}$resultTotal = $entityManager->createQueryBuilder()->select('count(product_relation)')->from('App\Entity\ProductRelation', 'product_relation')->where('product_relation.store = '.$id_store.' AND product_relation.deleted = 0')->getQuery()->getSingleScalarResult();$productRelations = $query->orderBy($order_by, $order_way)->setMaxResults($limit)->setFirstResult($offset)->getQuery()->getResult();$resultDatatable = [];foreach ($productRelations as $productRelation){$this_data = ['id' => $productRelation->getId(),'id_product' => $productRelation->getIdProduct(),'name' => $productRelation->getName(),'sample_image_url' => $productRelation->getSampleImageUrl(),'admin_id_product' => $productRelation->getAdminIdProduct(),];$resultDatatable[] = $this_data;}return JsonResponse::fromJsonString(json_encode(['draw' => $options['draw'],'recordsTotal' => $resultTotal,'recordsFiltered' => $resultTotal,'data' => $resultDatatable]));}protected function loadProducts(EntityManagerInterface $entityManager,PrestashopProductManager $prestashopProductManager,WordpressProductManager $wordpressProductManager,ShopifyProductManager $shopifyProductManager,int $id_store,int $page,$total_products,$after) : JsonResponse{$storeObj = $entityManager->getRepository(Store::class)->findOneBy(['id' => $id_store]);$productRelationRepository = $entityManager->getRepository(ProductRelation::class);$extra_params = [];$products_per_page = 10;switch ($storeObj->getCms()->getId()) {case Cms::PRESTASHOP_ID:$products_per_page = self::PRESTASHOP_PRODUCT_PER_PAGE;$prestashopProductManager->setExternalApiDataByStore($storeObj);$prestashopProductManager->assignExternalApiData();//First time loadedif(!$total_products){$this->productRelationTools->disableAllProducts($id_store);$total_products = count($prestashopProductManager->getAllProducts());}$prestashopProducts = $prestashopProductManager->getProducts(null, $page, $products_per_page);foreach ($prestashopProducts as $product){$productRelation = $productRelationRepository->findOneBy(['id_product' => $product['id'],'store' => $storeObj->getId(),]);if(!$productRelation){$productRelation = new ProductRelation();$productRelation->setStore($storeObj);$productRelation->setIdProduct($product['id']);$productRelation->setName(reset($product['name']));}if(!$productRelation->getSampleImageUrl() && $product['images']){$img_url_parts = explode('/', reset($product['images']));$id_image = end($img_url_parts);$image_url = $storeObj->getBaseUrl().'img/p/' . implode('/', str_split($id_image)) . '/' . $id_image . '.jpg';$productRelation->setSampleImageUrl($image_url);}$productRelation->setDeleted(false);$entityManager->persist($productRelation);}$entityManager->flush();break;case Cms::WORDPRESS_ID:$products_per_page = self::WORDPRESS_PRODUCT_PER_PAGE;try {$wordpressProductManager->setConnectionByStore($storeObj);//First time loadedif(!$total_products){$this->productRelationTools->disableAllProducts($id_store);}$wordpressResponse = $wordpressProductManager->getProducts($page, $products_per_page, true);foreach ($wordpressResponse['products'] as $product){$productRelation = $productRelationRepository->findOneBy(['id_product' => $product['id'],'store' => $storeObj->getId(),]);if(!$productRelation){$productRelation = new ProductRelation();$productRelation->setStore($storeObj);$productRelation->setIdProduct($product['id']);$productRelation->setName($product['name']);}if(!$productRelation->getSampleImageUrl() && $product['images']){$productRelation->setSampleImageUrl($product['images'][0]['src']);}$productRelation->setDeleted(false);$entityManager->persist($productRelation);}$entityManager->flush();$total_products = $wordpressResponse['total_products'];break;}catch (\Exception $e){return JsonResponse::fromJsonString(json_encode(['error' => $e->getMessage(),]));}case Cms::SHOPIFY_ID:$products_per_page = self::SHOPIFY_PRODUCT_PER_PAGE;$shopifyProductManager->setConnectionByStore($storeObj);//First time loadedif(!$total_products){$this->productRelationTools->disableAllProducts($id_store);$total_products = count($shopifyProductManager->getAllProductIds());}$response = $shopifyProductManager->getProducts($products_per_page, $after);foreach ($response['products'] as $product){$productRelation = $productRelationRepository->findOneBy(['id_product' => $product['id'],'store' => $storeObj->getId(),]);if(!$productRelation){$productRelation = new ProductRelation();$productRelation->setStore($storeObj);$productRelation->setIdProduct($product['id']);$productRelation->setName($product['name']);}if(!$productRelation->getSampleImageUrl() && $product['images']){$productRelation->setSampleImageUrl($product['images'][0]);}$productRelation->setDeleted(false);$entityManager->persist($productRelation);}$entityManager->flush();$extra_params['after'] = $response['after'];break;}$pending_products = 'unknown';$percentage_progress = 'unknown';$percentage_progress_formatted = 'unknown';if(is_integer((int)$total_products) && $total_products){$pending_products = $total_products - ($page * $products_per_page);$percentage_progress = ($page * $products_per_page) * 100 / $total_products;if($pending_products <= 0){$pending_products = 0;$percentage_progress = 100;}$percentage_progress = round($percentage_progress, 2);$percentage_progress_formatted = number_format($percentage_progress, 2, ',', '');}return JsonResponse::fromJsonString(json_encode(['total_products' => $total_products,'pending_products' => $pending_products,'percentage_progress' => $percentage_progress,'percentage_progress_formatted' => $percentage_progress_formatted,'id_cms' => $storeObj->getCms()->getId(),'extra_params' => $extra_params]));}protected function saveAdminIdProduct(EntityManagerInterface $entityManager, $id_product_relation, $admin_id_product) : JsonResponse{if($productRelation = $entityManager->getRepository(ProductRelation::class)->findOneBy(['id' => $id_product_relation])) {$productRelation->setAdminIdProduct(($admin_id_product ? $admin_id_product : null));$entityManager->persist($productRelation);$entityManager->flush();}return JsonResponse::fromJsonString(json_encode(['success' => true,]));}protected function checkApi(PrestashopProductManager $prestashopProductManager,WordpressProductManager $wordpressProductManager,ShopifyProductManager $shopifyProductManager,$id_cms,$base_url,$api_key,$api_secret) : JsonResponse{switch ($id_cms) {case Cms::PRESTASHOP_ID:$prestashopProductManager->prestashop_url = $base_url;$prestashopProductManager->prestashop_apikey = $api_key;try {$prestashopProductManager->checkEndpoints();return JsonResponse::fromJsonString(json_encode(['error' => false,]));}catch (\Exception $e){return JsonResponse::fromJsonString(json_encode(['error' => $e->getMessage(),]));}break;case Cms::WORDPRESS_ID:$wordpressProductManager->setUrl($base_url);$wordpressProductManager->setApiKey($api_key);$wordpressProductManager->setApiSecret($api_secret);try {$wordpressProductManager->checkEndpoints();return JsonResponse::fromJsonString(json_encode(['error' => false,]));}catch (\Exception $e){return JsonResponse::fromJsonString(json_encode(['error' => $e->getMessage(),]));}break;case Cms::SHOPIFY_ID:$shopifyProductManager->setUrl($base_url);$shopifyProductManager->setAccessToken($api_key);try {$shopifyProductManager->checkEndpoints();return JsonResponse::fromJsonString(json_encode(['error' => false,]));}catch (\Exception $e){return JsonResponse::fromJsonString(json_encode(['error' => $e->getMessage(),]));}break;}}}