src/Controller/HomepageController.php line 627

  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Blog;
  4. use App\Entity\Partner;
  5. use App\Entity\Vehicle;
  6. use App\Repository\BlogKindRepository;
  7. use App\Repository\BlogRepository;
  8. use App\Repository\AutanetPartnerRepository;
  9. use App\Repository\DealerOpenHourRepository;
  10. use App\Repository\DealerRepository;
  11. use App\Repository\DistrictRepository;
  12. use App\Repository\PageRepository;
  13. use App\Repository\PartnerRepository;
  14. use App\Repository\RegionRepository;
  15. use App\Repository\VehicleBodyRepository;
  16. use App\Repository\VehicleCategoryRepository;
  17. use App\Repository\VehicleFuelRepository;
  18. use App\Repository\VehicleKindRepository;
  19. use App\Repository\VehicleManufacturerRepository;
  20. use App\Repository\VehicleModelRepository;
  21. use App\Repository\VehiclePartKindRepository;
  22. use App\Repository\VehicleRepository;
  23. use App\Repository\VehicleTipRepository;
  24. use App\Service\VehicleSeoService;
  25. use App\Service\VehicleUrlGenerator;
  26. use DateTime;
  27. use DateTimeImmutable;
  28. use DateTimeZone;
  29. use Knp\Component\Pager\PaginatorInterface;
  30. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  31. use Symfony\Component\HttpFoundation\Request;
  32. use Symfony\Component\HttpFoundation\Response;
  33. use Symfony\Component\Routing\Annotation\Route;
  34. use Symfony\Contracts\Cache\CacheInterface;
  35. use Symfony\Contracts\Cache\ItemInterface;
  36. /**
  37.  * @phpstan-type PlaceValue array{name: string, url: string}
  38.  */
  39. class HomepageController extends AbstractController
  40. {
  41.     private const RECOMMENDED_VEHICLES_COUNT 12;
  42.     private const HOMEPAGE_KIND_URLS = [
  43.         'osobni-vozidla',
  44.         'uzitkova-vozidla',
  45.         'nakladni-vozidla',
  46.         'obytna-vozidla',
  47.         'motorky-skutry',
  48.     ];
  49.     #[Route('/{idAutanet}/auto-{idTipCars}/{urlName}.html'name'page_vehicle_detail_redirect'methods: ['GET'])]
  50.     public function vehicleDetailRedirect(int $idAutanetint $idTipCarsstring $urlNameVehicleRepository $vehicleRepositoryVehicleUrlGenerator $vehicleUrlGenerator): Response
  51.     {
  52.         $vehicle $vehicleRepository->findOneBy(['idImport' => $idTipCars]);
  53.         if ($vehicle) {
  54.             return $this->redirect($vehicleUrlGenerator->path($vehicle), 301);
  55.         } else {
  56.             throw $this->createNotFoundException('Page old url vehicle no exist');
  57.         }
  58.     }
  59.     #[Route('/models'name'app_models'methods: ['GET'])]
  60.     public function getModels(Request $requestVehicleModelRepository $vehicleModelRepositoryVehicleManufacturerRepository $manufacturerRepository): Response
  61.     {
  62.         $models = [];
  63.         $manufacturerId $request->get('idManufacturer');
  64.         if ($manufacturerId) {
  65.             $manufacturer $manufacturerRepository->find($manufacturerId);
  66.             if ($manufacturer) {
  67.                 foreach ($vehicleModelRepository->findActive($manufacturer) as $model) {
  68.                     $models[] = [
  69.                         'id' => $model->getId(),
  70.                         'name' => $model->getName(),
  71.                         'url' => $model->getUrl(),
  72.                     ];
  73.                 }
  74.             }
  75.         }
  76.         return $this->json(compact('models'));
  77.     }
  78.     #[Route('/autobazary/{urlPlace}'name'page_dealer'defaults: ['urlPlace' => false], methods: ['GET'])]
  79.     public function dealers(string             $urlPlaceRequest $requestPaginatorInterface $paginator,
  80.                             DealerRepository   $dealerRepository,
  81.                             VehicleRepository  $vehicleRepository,
  82.                             DistrictRepository $districtRepository,
  83.                             RegionRepository   $regionRepository,
  84.                             AutanetPartnerRepository $autanetPartnerRepository): Response
  85.     {
  86.         $parameters = [
  87.             'visible' => '1',
  88.             'excludeBasic' => true,
  89.         ];
  90.         $activePlace false;
  91.         if ($urlPlace) {
  92.             $dealer $dealerRepository->findOneBy(['url' => $urlPlace]);
  93.             if ($dealer) {
  94.                 return $this->redirectToRoute('page_dealer_detail', ['url' => $urlPlace], Response::HTTP_MOVED_PERMANENTLY);
  95.             }
  96.             if ('praha' === $urlPlace) {
  97.                 $urlPlace 'hlavni-mesto-praha';
  98.             }
  99.             if ('ostrava' === $urlPlace) {
  100.                 $urlPlace 'ostrava-mesto';
  101.             }
  102.             if ('brno' === $urlPlace) {
  103.                 $urlPlace = ['brno-mesto''brno-venkov'];
  104.             }
  105.             if ('plzen' === $urlPlace) {
  106.                 $urlPlace = ['plzen-mesto''plzen-jih''plzen-sever'];
  107.             }
  108.             if (!is_array($urlPlace) && $regionRepository->findOneBy(['url' => $urlPlace])) {
  109.                 $parameters['region'] = $urlPlace;
  110.                 $activePlace $regionRepository->findOneBy(['url' => $urlPlace]);
  111.             } else {
  112.                 $parameters['district'] = $urlPlace;
  113.                 if (is_array($urlPlace)) {
  114.                     $urlPlace $urlPlace[0];
  115.                 }
  116.                 $activePlace $districtRepository->findOneBy(['url' => $urlPlace]);
  117.             }
  118.             if (!$activePlace) {
  119.                 throw $this->createNotFoundException('The place does not exist');
  120.             }
  121.         }
  122.         if ($request->query->all()) {
  123.             $parameters += $request->query->all();
  124.         }
  125.         $pagination $paginator->paginate(
  126.             $dealerRepository->findQuery($parameters), /* query NOT result */
  127.             $request->query->getInt('page'1), /*page number*/
  128.             10 /*limit per page*/
  129.         );
  130.         $date = new DateTime('now', new DateTimeZone('Europe/Prague'));
  131.         $activeAutanetPartners = [];
  132.         foreach ($pagination->getItems() as $dealer) {
  133.             $autanetPartner $autanetPartnerRepository->findActiveByDealer($dealer$date);
  134.             if ($autanetPartner && $autanetPartner->getId() !== null) {
  135.                 $activeAutanetPartners[$dealer->getId()] = $autanetPartner->getId();
  136.             }
  137.         }
  138.         $dealerMap = [];
  139.         foreach ($dealerRepository->findBy(['visible' => '1'], ['name' => 'ASC']) as $dealer) {
  140.             if ($dealer->isBasicAdvertising()) {
  141.                 continue;
  142.             }
  143.             $dealerMap[] = [
  144.                 'id' => $dealer->getId(),
  145.                 'lat' => $dealer->getLat(),
  146.                 'lng' => $dealer->getLng(),
  147.                 'street' => $dealer->getStreet(),
  148.                 'city' => $dealer->getCity(),
  149.                 'link' => $this->generateUrl('page_dealer_detail', ['url' => $dealer->getUrl()]),
  150.                 'name' => $dealer->getName(),
  151.                 'region' => $dealer->getDistrict()?->getRegion()?->getName() ?? '',
  152.                 'countVehicle' => $vehicleRepository->count(['dealer' => $dealer'visible' => '1']),
  153.             ];
  154.         }
  155.         return $this->render('homepage/dealer.html.twig', [
  156.             'dealers' => $pagination,
  157.             'activeAutanetPartners' => $activeAutanetPartners,
  158.             'urlPlace' => $urlPlace,
  159.             'dealerMap' => $dealerMap,
  160.             'selectPlaceValues' => $this->getSelectPlaceValues($regionRepository$districtRepository),
  161.             'activePlace' => $activePlace,
  162.         ]);
  163.     }
  164.     /**
  165.      * @param RegionRepository $regionRepository
  166.      * @param DistrictRepository $districtRepository
  167.      * @return array<int, PlaceValue>
  168.      */
  169.     private function getSelectPlaceValues(RegionRepository $regionRepositoryDistrictRepository $districtRepository): array
  170.     {
  171.         $selectPlaceValues = [];
  172.         foreach ($regionRepository->findBy([], ['name' => 'ASC']) as $region) {
  173.             if (strpos($region->getName(), 'Praha') !== false) {
  174.                 $selectPlaceValues[] = [
  175.                     'name' => 'Praha',
  176.                     'url' => 'praha'
  177.                 ];
  178.                 continue;
  179.             }
  180.             $selectPlaceValues[] = [
  181.                 'name' => $region->getName(),
  182.                 'url' => $region->getUrl()
  183.             ];
  184.         }
  185.         foreach ($districtRepository->findBy([], ['name' => 'ASC']) as $district) {
  186.             //if in name praha
  187.             if (strpos($district->getName(), 'Praha') !== false) {
  188.                 continue;
  189.             }
  190.             if (strpos($district->getName(), 'Ostrava') !== false) {
  191.                 $selectPlaceValues[] = [
  192.                     'name' => 'Ostrava',
  193.                     'url' => 'ostrava'
  194.                 ];
  195.                 continue;
  196.             }
  197.             if (strpos($district->getName(), 'Brno-venkov') !== false) {
  198.                 continue;
  199.             }
  200.             if (strpos($district->getName(), 'území Hlavního města Prahy') !== false) {
  201.                 continue;
  202.             }
  203.             if (strpos($district->getName(), 'Brno-město') !== false) {
  204.                 $selectPlaceValues[] = [
  205.                     'name' => 'Brno',
  206.                     'url' => 'brno'
  207.                 ];
  208.                 continue;
  209.             }
  210.             if (strpos($district->getName(), 'Plzeň-jih') !== false
  211.                 || strpos($district->getName(), 'Plzeň-sever') !== false) {
  212.                 continue;
  213.             }
  214.             if (strpos($district->getName(), 'Plzeň-město') !== false) {
  215.                 $selectPlaceValues[] = [
  216.                     'name' => 'Plzeň',
  217.                     'url' => 'plzen'
  218.                 ];
  219.                 continue;
  220.             }
  221.             $selectPlaceValues[] = [
  222.                 'name' => $district->getName(),
  223.                 'url' => $district->getUrl()
  224.             ];
  225.         }
  226.         return $selectPlaceValues;
  227.     }
  228.     #[Route(
  229.         path: [
  230.             '/autobazary/{url}/kontakt',
  231.             '/autobazary/{url}/kontakty',
  232.         ], name'page_dealer_detail_redirect_contact'methods: ['GET'])]
  233.     public function dealerDetailRedirectContact(string $url): Response
  234.     {
  235.         return $this->redirectToRoute('page_dealer_detail', ['url' => $url], Response::HTTP_MOVED_PERMANENTLY);
  236.     }
  237.     #[Route('/autobazary/{url}/vozidla'name'redirect_autobazary_vozidla'methods: ['GET'], priority10)]
  238.     public function redirectAutobazaryVozidla(string $url): Response
  239.     {
  240.         return $this->redirect(sprintf("/autobazar/%s/vozidla"$url), Response::HTTP_MOVED_PERMANENTLY);
  241.     }
  242.     #[Route(
  243.         path: [
  244.             '/autobazary/{url}/{urlManufacturer}',
  245.         ], name'page_dealer_detail_redirect'methods: ['GET'])]
  246.     public function dealerDetailRedirect(string $urlstring $urlManufacturer): Response
  247.     {
  248.         //http://127.0.0.1:8000/autobazary/ald-automotive/audi
  249.         $url '/autobazar/' $url '/vozidla/' $urlManufacturer;
  250.         return $this->redirect($urlResponse::HTTP_MOVED_PERMANENTLY);
  251.     }
  252.     #[Route('/autobazar/{url}'name'page_dealer_detail'methods: ['GET'])]
  253.     public function dealerDetail(string                   $url,
  254.                                  VehicleRepository        $vehicleRepository,
  255.                                  DealerOpenHourRepository $dealerOpenHourRepository,
  256.                                  DealerRepository         $dealerRepository,
  257.                                  VehicleTipRepository     $vehicleTipRepository,
  258.                                  AutanetPartnerRepository $autanetPartnerRepository
  259.     ): Response
  260.     {
  261.         $dealer $dealerRepository->findOneBy(['url' => $url]);
  262.         if (!$dealer) {
  263.             throw $this->createNotFoundException('The dealer does not exist');
  264.         }
  265.         $date = new DateTime('now', new DateTimeZone('Europe/Prague'));
  266.         $openTime $dealerOpenHourRepository->findBy(['dealer' => $dealer'summer' => $date->format('I')]);
  267.         $autanetPartner $autanetPartnerRepository->findActiveByDealer($dealer$date);
  268.         $hasVehicleImport $dealer->getNameImportVehicle() !== null && !empty($dealer->getIdImportVehicle());
  269.         if (!$hasVehicleImport) {
  270.             $vehicles = [];
  271.             $vehicleTips $vehicleTipRepository->findRandVisible(6);
  272.         } else {
  273.             $vehicles $vehicleRepository->findBy(['dealer' => $dealer'visible' => true], ['createAt' => 'DESC'], 5);
  274.             $vehicleTips = [];
  275.         }
  276.         $dealerType $dealer->isAuthSeller() ? 'autosalon' 'autobazar';
  277.         $seoTitle sprintf('%s %s %s | Autanet.cz'$dealer->getName(), $dealerType$dealer->getCity());
  278.         if (!$hasVehicleImport) {
  279.             $seoDescription sprintf('%s %s %s – profil prodejce vozidel s kontaktními údaji, mapou, odkazem na webové stránky a provozní dobou.',
  280.                 $dealer->getName(), $dealerType$dealer->getCity());
  281.         } else {
  282.             $seoDescription sprintf('%s %s %s - novinky z nabídky inzerce, kontakty, mapa, provozní doba.',
  283.                 $dealer->getName(), $dealerType$dealer->getCity());
  284.         }
  285.         return $this->render('homepage/detailDealer.html.twig', [
  286.             'dealer' => $dealer,
  287.             'openTime' => $openTime,
  288.             'vehicles' => $vehicles,
  289.             'vehicleTips' => $vehicleTips,
  290.             'hasVehicleImport' => $hasVehicleImport,
  291.             'isBasicDealer' => $dealer->isBasicAdvertising(),
  292.             'autanetPartner' => $autanetPartner,
  293.             'seoTitle' => $seoTitle,
  294.             'seoDescription' => $seoDescription,
  295.         ]);
  296.     }
  297.     #[Route('clanky/{urlKind}/{urlManufacturer}'name'page_blog_universal'requirements: ['urlManufacturer' => '[a-z0-9\-]+'], methods: ['GET'], priority1)]
  298.     public function blogUniversal(string                        $urlKind,
  299.                                   string                        $urlManufacturer,
  300.                                   BlogKindRepository            $blogKindRepository,
  301.                                   BlogRepository                $blogRepository,
  302.                                   VehicleManufacturerRepository $manufacturerRepository,
  303.                                   VehicleModelRepository        $modelRepository,
  304.                                   Request                       $request,
  305.                                   PaginatorInterface            $paginator
  306.     ): Response
  307.     {
  308.         $blogKind $blogKindRepository->findOneBy(['url' => $urlKind]);
  309.         if (!$blogKind) {
  310.             throw $this->createNotFoundException('The blog kind does not exist');
  311.         }
  312.         if (str_contains($urlManufacturer'-')) {
  313.             [$manufacturerUrl$modelUrl] = $this->parseManufacturerAndModel($urlManufacturer$manufacturerRepository$blogKindRepository);
  314.         } else {
  315.             $manufacturerUrl $urlManufacturer;
  316.             $modelUrl null;
  317.         }
  318.         $manufacturer $manufacturerUrl $manufacturerRepository->findOneBy(['url' => $manufacturerUrl]) : null;
  319.         $model = ($modelUrl && $manufacturer) ? $modelRepository->findOneBy(['url' => $modelUrl'vehicleManufacturer' => $manufacturer]) : null;
  320.         $isTestyAut $blogKind->getUrl() === 'testy-aut';
  321.         $baseParameters = ['visible' => '1''urlKind' => $urlKind];
  322.         $notFoundMessage null;
  323.         $activeManufacturer null;
  324.         $activeModel null;
  325.         if (!$isTestyAut || !$manufacturer) {
  326.             $pagination $paginator->paginate(
  327.                 $blogRepository->findQuery($baseParameters),
  328.                 $request->query->getInt('page'1), 20
  329.             );
  330.             if (!$manufacturer) {
  331.                 $notFoundMessage "Testy pro požadovanou značku nebyly nalezeny. Zobrazujeme všechny testy aut.";
  332.             }
  333.         } else {
  334.             $manufacturerParameters array_merge($baseParameters, ['manufacturer' => $manufacturer->getId()]);
  335.             $manufacturerResults $blogRepository->findQueryWithManufacturer($manufacturerParameters);
  336.             if (empty($manufacturerResults)) {
  337.                 $pagination $paginator->paginate(
  338.                     $blogRepository->findQuery($baseParameters),
  339.                     $request->query->getInt('page'1), 20
  340.                 );
  341.                 $notFoundMessage "Testy pro požadovanou značku nebyly nalezeny. Zobrazujeme všechny testy aut.";
  342.             } else {
  343.                 $activeManufacturer $manufacturer;
  344.                 $paginateResults $manufacturerResults;
  345.                 $notFoundMessage $modelUrl "Testy pro hledaný model nebyly nalezeny. Zobrazujeme všechny testy této značky." null;
  346.                 if ($model) {
  347.                     $modelParameters array_merge($manufacturerParameters, ['model' => $model->getId()]);
  348.                     $modelResults $blogRepository->findQueryWithManufacturerAndModel($modelParameters);
  349.                     if (!empty($modelResults)) {
  350.                         $activeModel $model;
  351.                         $paginateResults $modelResults;
  352.                         $notFoundMessage null;
  353.                     }
  354.                 }
  355.                 $pagination $paginator->paginate($paginateResults$request->query->getInt('page'1), 20);
  356.             }
  357.         }
  358.         $manufacturers $manufacturerRepository->findByBlogKind($blogKind);
  359.         $models $manufacturer $modelRepository->findByManufacturerAndBlogKind($manufacturer$blogKind) : [];
  360.         $data = [
  361.             'blogs' => $pagination,
  362.             'blogKind' => $blogKind,
  363.             'manufacturers' => $manufacturers,
  364.             'models' => $models,
  365.             'activeManufacturer' => $activeManufacturer,
  366.             'activeModel' => $activeModel,
  367.             'notFoundMessage' => $notFoundMessage,
  368.         ];
  369.         return $this->render('homepage/blog.html.twig'$data);
  370.     }
  371.     #[Route('clanky/{urlKind}'name'page_blog'methods: ['GET'], priority0)]
  372.     public function blog(string         $urlKindBlogKindRepository $blogKindRepository,
  373.                          BlogRepository $blogRepositoryVehicleManufacturerRepository $manufacturerRepository,
  374.                          Request        $requestPaginatorInterface $paginator): Response
  375.     {
  376.         if ($urlKind == 'vsechny-clanky') {
  377.             $parameters = [
  378.                 'visible' => '1',
  379.                 'urlKind' => '',
  380.             ];
  381.             $blogKind false;
  382.         } else {
  383.             $parameters = [
  384.                 'visible' => '1',
  385.                 'urlKind' => $urlKind,
  386.             ];
  387.             $blogKind $blogKindRepository->findOneBy(['url' => $urlKind]);
  388.             if (!$blogKind) {
  389.                 throw $this->createNotFoundException('The blog kind does not exist');
  390.             }
  391.         }
  392.         $pagination $paginator->paginate(
  393.             $blogRepository->findQuery($parameters), /* query NOT result */
  394.             $request->query->getInt('page'1), /*page number*/
  395.             20 /*limit per page*/
  396.         );
  397.         $manufacturers = [];
  398.         $models = [];
  399.         if ($blogKind && $blogKind->getUrl() === 'testy-aut') {
  400.             $manufacturers $manufacturerRepository->findByBlogKind($blogKind);
  401.         }
  402.         return $this->render('homepage/blog.html.twig', [
  403.             'blogs' => $pagination,
  404.             'blogKind' => $blogKind,
  405.             'manufacturers' => $manufacturers,
  406.             'models' => $models,
  407.             'activeManufacturer' => null,
  408.             'activeModel' => null,
  409.             'notFoundMessage' => null,
  410.         ]);
  411.     }
  412.     #[Route(
  413.         path: [
  414.             '/autobazar/{url}/vozidla',
  415.             '/autobazar/{url}/vozidla/{urlManufacturer}',
  416.             '/autobazar/{url}/vozidla/{urlManufacturer}/{urlModel}'
  417.         ]
  418.         , name'page_dealer_vehicle'defaults: ['urlManufacturer' => null'urlModel' => null], methods: ['GET'])]
  419.     public function dealerVehicles(string                        $url,
  420.                                    string|null                   $urlManufacturer,
  421.                                    string|null                   $urlModel,
  422.                                    Request                       $request,
  423.                                    PaginatorInterface            $paginator,
  424.                                    VehicleRepository             $vehicleRepository,
  425.                                    VehicleManufacturerRepository $manufacturerRepository,
  426.                                    VehicleModelRepository        $vehicleModelRepository,
  427.                                    DealerRepository              $dealerRepository
  428.     ): Response
  429.     {
  430.         $dealer $dealerRepository->findOneBy(['url' => $url]);
  431.         if (!$dealer) {
  432.             throw $this->createNotFoundException('The dealer does not exist');
  433.         }
  434.         $parameters = [
  435.             'visible' => '1',
  436.             'dealer' => (string)$dealer->getId(),
  437.         ];
  438.         $manufacturer null;
  439.         if ($urlManufacturer) {
  440.             $manufacturer $manufacturerRepository->findOneBy(['url' => $urlManufacturer]);
  441.             if (!$manufacturer) {
  442.                 throw $this->createNotFoundException('The manufacturer does not exist');
  443.             }
  444.             $manufacturerId $parameters['manufacturer'] = $manufacturer->getId();
  445.         }
  446.         $model null;
  447.         if ($urlModel) {
  448.             $model $vehicleModelRepository->findOneBy(['url' => $urlModel]);
  449.             if (!$model) {
  450.                 throw $this->createNotFoundException('The model does not exist');
  451.             }
  452.             $parameters['model'] = $model->getId();
  453.         }
  454.         $pagination $paginator->paginate(
  455.             $vehicleRepository->findQuery($parameters), /* query NOT result */
  456.             $request->query->getInt('page'1), /*page number*/
  457.             10 /*limit per page*/
  458.         );
  459.         $dealerType $dealer->isAuthSeller() ? 'autosalon' 'autobazar';
  460.         $vehicleCount $pagination->getTotalItemCount();
  461.         if ($manufacturer && $model) {
  462.             $seoTitle sprintf('%s %s - nabídka vozidel %s %s | Autanet.cz',
  463.                 $dealer->getName(), $dealer->getCity(), $manufacturer->getName(), $model->getName());
  464.             $seoDescription sprintf('Nabídka %d vozidel %s %s z %su %s %s. Vybírejte z nabídky vozidel značky %s %s a dalších modelů.',
  465.                 $vehicleCount$manufacturer->getName(), $model->getName(), $dealerType$dealer->getName(), $dealer->getCity(),
  466.                 $manufacturer->getName(), $model->getName());
  467.         } elseif ($manufacturer) {
  468.             $seoTitle sprintf('%s %s - nabídka vozidel %s | Autanet.cz',
  469.                 $dealer->getName(), $dealer->getCity(), $manufacturer->getName());
  470.             $seoDescription sprintf('Nabídka %d vozidel %s z %su %s %s. Vybírejte z nabídky vozidel značky %s a dalších.',
  471.                 $vehicleCount$manufacturer->getName(), $dealerType$dealer->getName(), $dealer->getCity(), $manufacturer->getName());
  472.         } else {
  473.             $seoTitle sprintf('%s %s - nabídka vozidel | Autanet.cz'$dealer->getName(), $dealer->getCity());
  474.             $topManufacturers $manufacturerRepository->findByDealerActive($dealer);
  475.             $manufacturerNames array_slice(array_map(fn($m) => $m->getName(), $topManufacturers), 05);
  476.             $manufacturerList implode(', '$manufacturerNames);
  477.             $seoDescription sprintf('Nabídka %d vozidel z %su %s %s. Vybírejte z vozidel značek %s a dalších.',
  478.                 $vehicleCount$dealerType$dealer->getName(), $dealer->getCity(), $manufacturerList);
  479.         }
  480.         if ($manufacturer && $model) {
  481.             $seoH1 sprintf('Nabídka vozidel %s %s %s'$manufacturer->getName(), $model->getName(), $dealer->getName());
  482.         } elseif ($manufacturer) {
  483.             $seoH1 sprintf('Nabídka vozidel %s %s'$manufacturer->getName(), $dealer->getName());
  484.         } else {
  485.             $seoH1 sprintf('Nabídka vozidel %s'$dealer->getName());
  486.         }
  487.         return $this->render('homepage/vehicleDealer.html.twig', [
  488.             'dealer' => $dealer,
  489.             'activeManufacturer' => $manufacturer,
  490.             'activeModel' => $model,
  491.             'manufacturer' => $manufacturerRepository->findByDealerActive($dealer),
  492.             'model' => $vehicleModelRepository->findByDealerActive($dealer$manufacturer?->getId()),
  493.             'vehicles' => $pagination,
  494.             'seoTitle' => $seoTitle,
  495.             'seoDescription' => $seoDescription,
  496.             'seoH1' => $seoH1,
  497.         ]);
  498.     }
  499.     #[Route(path: [
  500.         '/nova/{urlKind}',
  501.         '/nova/{urlKind}/{urlManufacturer}',
  502.         '/nova/{urlKind}/{urlManufacturer}/{urlModel}',
  503.     ], name'app_search_redirect'defaults: ['urlManufacturer' => null'urlModel' => null], methods: ['GET'])]
  504.     public function redirectSearch(string $urlKindstring|null $urlManufacturerstring|null $urlModel): Response
  505.     {
  506.         if ($urlManufacturer and $urlModel) {
  507.             return $this->redirectToRoute('page_vehicle_search'compact('urlKind''urlManufacturer''urlModel'), Response::HTTP_MOVED_PERMANENTLY);
  508.         } elseif ($urlManufacturer) {
  509.             return $this->redirectToRoute('page_vehicle_search'compact('urlKind''urlManufacturer'), Response::HTTP_MOVED_PERMANENTLY);
  510.         } else {
  511.             return $this->redirectToRoute('page_vehicle_search'compact('urlKind'), Response::HTTP_MOVED_PERMANENTLY);
  512.         }
  513.     }
  514.     #[Route(path: [
  515.         '/{urlKind}',
  516.         '/{urlKind}/{urlManufacturer}',
  517.         '/{urlKind}/{urlManufacturer}/{urlModel}',
  518.     ], name'page_vehicle_search'defaults: ['urlManufacturer' => null'urlModel' => null], methods: ['GET'])]
  519.     public function vehicleSearch(string                        $urlKindstring|null $urlManufacturerstring|null $urlModelRequest $requestPaginatorInterface $paginator,
  520.                                   VehicleRepository             $vehicleRepository,
  521.                                   VehicleKindRepository         $vehicleKindRepository,
  522.                                   VehicleCategoryRepository     $vehicleCategoryRepository,
  523.                                   VehicleManufacturerRepository $manufacturerRepository,
  524.                                   VehicleModelRepository        $vehicleModelRepository,
  525.                                   VehicleBodyRepository         $vehicleBodyRepository,
  526.                                   VehicleFuelRepository         $vehicleFuelRepository,
  527.                                   RegionRepository              $regionRepository,
  528.                                   DistrictRepository            $districtRepository,
  529.                                   VehiclePartKindRepository     $vehiclePartKindRepository,
  530.                                   AutanetPartnerRepository      $autanetPartnerRepository): Response
  531.     {
  532.         $parameters = [
  533.             'visible' => '1',
  534.         ];
  535.         $vehicleKind null;
  536.         $models = [];
  537.         $vehicleCategory null;
  538.         $manufacturer null;
  539.         $mileageValues = [
  540.             '0-10000' => 'do 10000 km',
  541.             '10000-30000' => '10 000 - 30 000 km',
  542.             '30000-50000' => '30 000 - 50 000 km',
  543.             '50000-100000' => '50 000 - 100 000 km',
  544.             '100000-150000' => '100 000 - 150 000 km',
  545.             '150000-200000' => '150 000 - 200 000 km',
  546.             '200000-300000' => '200 000 - 300 000 km',
  547.             '300000-10000000' => '300 000 a více km',
  548.         ];
  549.         $powerValues = [
  550.             '0-40' => 'do 40 kW',
  551.             '40-60' => '40 - 60 kW',
  552.             '60-80' => '60 - 80 kW',
  553.             '80-100' => '80 - 100 kW',
  554.             '100-125' => '100 - 125 kW',
  555.             '125-150' => '120 - 150 kW',
  556.             '150-200' => '150 - 200 kW',
  557.             '200-300' => '200 - 300 kW',
  558.             '300-2000' => 'nad 300 kW',
  559.         ];
  560.         $vehiclePartKindValues = [];
  561.         if ($urlKind) {
  562.             if ($urlKind == 'obytna-vozidla') {
  563.                 $powerValues = [
  564.                     '0-60' => 'do 60 kW',
  565.                     '60-80' => '60 - 80 kW',
  566.                     '80-100' => '80 - 100 kW',
  567.                     '100-125' => '100 - 125 kW',
  568.                     '125-150' => '125 - 150 kW',
  569.                     '150-200' => '150 - 200 kW',
  570.                     '200-300' => '200 - 300 kW',
  571.                     '300-2000' => 'nad 300 kW',
  572.                 ];
  573.             }
  574.             if ($urlKind == 'nakladni-vozidla') {
  575.                 $powerValues = [
  576.                     '0-100' => 'do 100 kW',
  577.                     '100-150' => '100 - 150 kW',
  578.                     '150-200' => '150 - 200 kW',
  579.                     '200-300' => '200 - 300 kW',
  580.                     '300-400' => '300 - 400 kW',
  581.                     '400-2000' => 'nad 400 kW',
  582.                 ];
  583.             }
  584.             if ($urlKind == 'motorky-skutry') {
  585.                 $mileageValues = [
  586.                     '0-10000' => 'do 10000 km',
  587.                     '10000-30000' => '10 000 - 30 000 km',
  588.                     '30000-50000' => '30 000 - 50 000 km',
  589.                     '50000-100000' => '50 000 - 100 000 km',
  590.                     '100000-150000' => '100 000 - 150 000 km',
  591.                     '150000-1000000' => '150 000 a více km',
  592.                 ];
  593.                 $powerValues = [
  594.                     '0-25' => 'do 25 kW',
  595.                     '25-50' => '25 - 50 kW',
  596.                     '50-75' => '50 - 75 kW',
  597.                     '75-100' => '75 - 100 kW',
  598.                     '100-125' => '100 - 125 kW',
  599.                     '125-150' => '125 - 150 kW',
  600.                     '150-2000' => 'nad 150 kW',
  601.                 ];
  602.             }
  603.             if ($urlKind == 'nahradni-dily' || $urlKind == 'prislusenstvi') {
  604.                 $vehicleCategory $vehicleCategoryRepository->findOneBy(['url' => $urlKind]);
  605.                 if ($vehicleCategory) {
  606.                     $parameters['category'] = $vehicleCategory->getId();
  607.                 } else {
  608.                     return $this->forward('App\Controller\HomepageController::blogDetail', ['url' => $urlKind,]);
  609.                 }
  610.                 $vehiclePartKindValues $vehiclePartKindRepository->findActiveCategory($vehicleCategory);
  611.             } else {
  612.                 $vehicleKind $vehicleKindRepository->findOneBy(['url' => $urlKind]);
  613.                 if ($vehicleKind) {
  614.                     $parameters['kind'] = $vehicleKind->getId();
  615.                 } else {
  616.                     return $this->forward('App\Controller\HomepageController::blogDetail', ['url' => $urlKind,]);
  617.                 }
  618.             }
  619.         }
  620.         if ($urlManufacturer) {
  621.             $manufacturer $manufacturerRepository->findOneBy(['url' => $urlManufacturer]);
  622.             if ($manufacturer) {
  623.                 $parameters['manufacturer'] = $manufacturer->getId();
  624.                 $models $vehicleModelRepository->findActive($manufacturer$vehicleCategory$vehicleKind);
  625.             } else {
  626.                 return $this->forward('App\Controller\HomepageController::page', ['url' => $urlKind,]);
  627.             }
  628.         }
  629.         $activeModel null;
  630.         if ($urlModel) {
  631.             $activeModel $vehicleModelRepository->findOneBy(['url' => $urlModel]);
  632.             if ($activeModel) {
  633.                 $parameters['model'] = $activeModel->getId();
  634.             } else {
  635.                 return $this->forward('App\Controller\HomepageController::page', ['url' => $urlKind,]);
  636.             }
  637.         }
  638.         $urlPlace $request->get('place');
  639.         if ($urlPlace) {
  640.             if ('praha' === $urlPlace) {
  641.                 $urlPlace 'hlavni-mesto-praha';
  642.             }
  643.             if ('ostrava' === $urlPlace) {
  644.                 $urlPlace 'ostrava-mesto';
  645.             }
  646.             if ('brno' === $urlPlace) {
  647.                 $urlPlace = ['brno-mesto''brno-venkov'];
  648.             }
  649.             if ('plzen' === $urlPlace) {
  650.                 $urlPlace = ['plzen-mesto''plzen-jih''plzen-sever'];
  651.             }
  652.             if (!is_array($urlPlace) && $regionRepository->findOneBy(['url' => $urlPlace])) {
  653.                 $parameters['region'] = $urlPlace;
  654.             } else {
  655.                 $parameters['district'] = $urlPlace;
  656.             }
  657.         }
  658.         if ($request->query->all()) {
  659.             $parameters += $request->query->all();
  660.         }
  661.         $pagination $paginator->paginate(
  662.             $vehicleRepository->findQuery($parameters), /* query NOT result */
  663.             $request->query->getInt('page'1), /*page number*/
  664.             20 /*limit per page*/
  665.         );
  666.         $date = new DateTime('now', new DateTimeZone('Europe/Prague'));
  667.         $activeAutanetPartners = [];
  668.         $checkedDealerIds = [];
  669.         foreach ($pagination->getItems() as $vehicle) {
  670.             $dealer $vehicle->getDealer();
  671.             if (!$dealer || isset($checkedDealerIds[$dealer->getId()])) {
  672.                 continue;
  673.             }
  674.             $checkedDealerIds[$dealer->getId()] = true;
  675.             $autanetPartner $autanetPartnerRepository->findActiveByDealer($dealer$date);
  676.             if ($autanetPartner && $autanetPartner->getId() !== null) {
  677.                 $activeAutanetPartners[$dealer->getId()] = $autanetPartner->getId();
  678.             }
  679.         }
  680.         return $this->render('homepage/search.html.twig', [
  681.             'vehicles' => $pagination,
  682.             'activeAutanetPartners' => $activeAutanetPartners,
  683.             'activeKind' => $vehicleKind,
  684.             'baseUrl' => $vehicleCategory $vehicleCategory->getUrl() : $vehicleKind->getUrl(),
  685.             'activeCategory' => $vehicleCategory,
  686.             'activeManufacturer' => isset($parameters['manufacturer']) ? $manufacturerRepository->find($parameters['manufacturer']) : null,
  687.             'activeModel' => $activeModel,
  688.             'categories' => $vehicleCategoryRepository->findActive(),
  689.             'manufacturers' => $manufacturerRepository->findActive($vehicleKind$vehicleCategory),
  690.             'models' => $models,
  691.             'bodies' => $vehicleBodyRepository->findActive($vehicleKind$manufacturer$activeModel),
  692.             'fuels' => $vehicleFuelRepository->findActive(),
  693.             'gearbox' => $vehicleRepository->findActiveGearBox(),
  694.             'selectPlaceValues' => $this->getSelectPlaceValues($regionRepository$districtRepository),
  695.             'vehicleKind' => $vehicleKind,
  696.             'mileageValues' => $mileageValues,
  697.             'powerValues' => $powerValues,
  698.             'vehiclePartKindValues' => $vehiclePartKindValues
  699.         ]);
  700.     }
  701.     #[Route('/detail/{seoSlug}-{id}'name'page_vehicle_detail_seo'methods: ['GET'], requirements: ['seoSlug' => '.+''id' => '[0-9]+'], priority10)]
  702.     public function vehicleDetailSeo(string            $seoSlugint $idVehicleRepository $vehicleRepository,
  703.                                      VehicleSeoService $vehicleSeoServiceDealerOpenHourRepository $dealerOpenHourRepository,
  704.                                      AutanetPartnerRepository $autanetPartnerRepository): Response
  705.     {
  706.         $vehicle $vehicleRepository->find($id);
  707.         if (!$vehicle) {
  708.             throw $this->createNotFoundException('Vehicle not found');
  709.         }
  710.         if (!$vehicle->getSeoSlug()) {
  711.             $vehicleSeoService->generateSeoData($vehicle);
  712.         }
  713.         if ($vehicle->getSeoSlug() && $seoSlug !== $vehicle->getSeoSlug()) {
  714.             return $this->redirectToRoute('page_vehicle_detail_seo', [
  715.                 'seoSlug' => $vehicle->getSeoSlug(),
  716.                 'id' => $id
  717.             ], 301);
  718.         }
  719.         if (!$vehicle->isVisible()) {
  720.             $response $this->render('homepage/detailVehicleDisable.html.twig'compact('vehicle'));
  721.             $response->setStatusCode(404);
  722.             return $response;
  723.         }
  724.         $date = new DateTime('now', new DateTimeZone('Europe/Prague'));
  725.         $openTime $dealerOpenHourRepository->findBy(['dealer' => $vehicle->getDealer(), 'summer' => $date->format('I')]);
  726.         $vehicleOthers $vehicleRepository->findOtherDealerBody($vehicle4);
  727.         $autanetPartner $autanetPartnerRepository->findActiveByDealer($vehicle->getDealer(), $date);
  728.         return $this->render('homepage/detailVehicle.html.twig'compact('vehicle''openTime''vehicleOthers''autanetPartner'));
  729.     }
  730.     #[Route(
  731.         [
  732.             '/detail/{urlManufacturer}/{urlModel}/{id}',
  733.         ], name'page_vehicle_detail'defaults: ['urlModel' => null], methods: ['GET'])]
  734.     public function vehicleDetail(string                        $urlManufacturerstring $urlModelint $idVehicleRepository $vehicleRepository,
  735.                                   VehicleManufacturerRepository $vehicleManufacturerRepository,
  736.                                   VehicleModelRepository        $vehicleModelRepositoryDealerOpenHourRepository $dealerOpenHourRepository,
  737.                                   VehicleSeoService             $vehicleSeoService,
  738.                                   AutanetPartnerRepository      $autanetPartnerRepository): Response
  739.     {
  740.         if ($urlModel) {
  741.             $vehicleModel $vehicleModelRepository->findOneBy(['url' => $urlModel]);
  742.         }
  743.         $manufacturer $vehicleManufacturerRepository->findOneBy(['url' => $urlManufacturer]);
  744.         if ($urlModel) {
  745.             $vehicle $vehicleRepository->findOneBy(['id' => $id'visible' => true'manufacturer' => $manufacturer'model' => $vehicleModel]);
  746.         } else {
  747.             $vehicle $vehicleRepository->findOneBy(['id' => $id'visible' => true'manufacturer' => $manufacturer]);
  748.         }
  749.         if ($urlModel) {
  750.             $disableVehicle $vehicleRepository->findOneBy(['id' => $id'visible' => false'manufacturer' => $manufacturer'model' => $vehicleModel]);
  751.         } else {
  752.             $disableVehicle $vehicleRepository->findOneBy(['id' => $id'visible' => false'manufacturer' => $manufacturer]);
  753.         }
  754.         if ($disableVehicle) {
  755.             $response $this->render('homepage/detailVehicleDisable.html.twig', [
  756.                 'vehicle' => $disableVehicle,
  757.             ]);
  758.             $response->setStatusCode(404);
  759.             return $response;
  760.         }
  761.         if (!$vehicle) {
  762.             throw $this->createNotFoundException('The vehicle does not exist');
  763.         }
  764.         if (!$vehicle->getSeoSlug()) {
  765.             $vehicleSeoService->generateSeoData($vehicle);
  766.         }
  767.         if ($vehicleSeoService->shouldRedirectToSeo($vehicle) && $vehicle->getSeoSlug()) {
  768.             return $this->redirectToRoute('page_vehicle_detail_seo', [
  769.                 'seoSlug' => $vehicle->getSeoSlug(),
  770.                 'id' => $id
  771.             ], 301);
  772.         }
  773.         $date = new DateTime('now', new DateTimeZone('Europe/Prague'));
  774.         $openTime $dealerOpenHourRepository->findBy(['dealer' => $vehicle->getDealer(), 'summer' => $date->format('I')]);
  775.         $vehicleOthers $vehicleRepository->findOtherDealerBody($vehicle4);
  776.         $autanetPartner $autanetPartnerRepository->findActiveByDealer($vehicle->getDealer(), $date);
  777.         return $this->render('homepage/detailVehicle.html.twig', [
  778.             'vehicle' => $vehicle,
  779.             'openTime' => $openTime,
  780.             'vehicleOthers' => $vehicleOthers,
  781.             'autanetPartner' => $autanetPartner,
  782.         ]);
  783.     }
  784.     #[Route('/{url}'name'page'methods: ['GET'], priority: -2)]
  785.     public function page(string $urlPageRepository $pageRepository): Response
  786.     {
  787.         $page $pageRepository->findPage($url);
  788.         if (!$page) {
  789.             throw $this->createNotFoundException('Page no exist');
  790.         }
  791.         return $this->render('homepage/page.html.twig', [
  792.             'page' => $page,
  793.         ]);
  794.     }
  795.     #[Route('/{url}'name'page_blog_detail'methods: ['GET'], priority: -1)]
  796.     public function blogDetail(string $urlBlogRepository $blogRepositoryVehicleRepository $vehicleRepository): Response
  797.     {
  798.         $blog $blogRepository->findOneVisibleUrl($url);
  799.         if (!$blog) {
  800.             return $this->forward('App\Controller\HomepageController::page', [
  801.                 'url' => $url,
  802.             ]);
  803.         }
  804.         $vehicles $vehicleRepository->findRandActive($blog->getVehicleManufacturer(), $blog->getVehicleModel(), 3);
  805.         if (!$vehicles) {
  806.             $vehicles $vehicleRepository->findRandActive($blog->getVehicleManufacturer(), null3);
  807.             $isVehicleModel false;
  808.         } else {
  809.             $isVehicleModel true;
  810.         }
  811.         $blogOtherManufacturer $blogRepository->findRandActive($blog->getVehicleManufacturer(), $blog->getVehicleModel(), $blog->getId(), 3);
  812.         return $this->render('homepage/blogDetail.html.twig', [
  813.             'blog' => $blog,
  814.             'vehicles' => $vehicles,
  815.             'isVehicleModel' => $isVehicleModel,
  816.             'blogOtherManufacturer' => $blogOtherManufacturer,
  817.             'blogNew' => $blogRepository->findNewActive(3)
  818.         ]);
  819.     }
  820.     #[Route('/'name'app_homepage'methods: ['GET'])]
  821.     public function index(BlogRepository       $blogRepository,
  822.                           VehicleTipRepository $vehicleTipRepository,
  823.                           PartnerRepository    $partnerRepository,
  824.                           VehicleRepository    $vehicleRepository,
  825.                           DealerRepository     $dealerRepository,
  826.                           CacheInterface       $cache): Response
  827.     {
  828.         $blogsTests $blogRepository->findLatestByKindUrl('testy-aut'3);
  829.         $excludeIds array_map(static fn(Blog $blog): int => (int)$blog->getId(), $blogsTests);
  830.         [$recommendedVehicles$tipVehicleIds$tipAutanetPartnerIds] = $this->getRecommendedVehicles($vehicleTipRepository$vehicleRepository);
  831.         return $this->render('homepage/index.html.twig', [
  832.             'partners' => $this->getPartners($partnerRepository),
  833.             'blogsTests' => $blogsTests,
  834.             'blogsLatest' => $blogRepository->findLatestExcluding(3$excludeIds),
  835.             'recommendedVehicles' => $recommendedVehicles,
  836.             'tipVehicleIds' => $tipVehicleIds,
  837.             'tipAutanetPartnerIds' => $tipAutanetPartnerIds,
  838.             'stats' => $this->getHomepageStats($vehicleRepository$dealerRepository$cache),
  839.         ]);
  840.     }
  841.     /**
  842.      * @return array{0: Vehicle[], 1: int[], 2: array<int, int>}
  843.      */
  844.     private function getRecommendedVehicles(VehicleTipRepository $vehicleTipRepositoryVehicleRepository $vehicleRepository): array
  845.     {
  846.         $vehicles = [];
  847.         $tipVehicleIds = [];
  848.         $tipAutanetPartnerIds = [];
  849.         foreach ($vehicleTipRepository->findHomepageActive(self::RECOMMENDED_VEHICLES_COUNT) as $tip) {
  850.             $vehicle $tip->getVehicle();
  851.             if ($vehicle === null) {
  852.                 continue;
  853.             }
  854.             $vehicleId = (int)$vehicle->getId();
  855.             $vehicles[] = $vehicle;
  856.             $tipVehicleIds[] = $vehicleId;
  857.             $autanetPartner $tip->getAutanetPartner();
  858.             if ($autanetPartner !== null && $autanetPartner->getId() !== null) {
  859.                 $tipAutanetPartnerIds[$vehicleId] = (int)$autanetPartner->getId();
  860.             }
  861.         }
  862.         $missing self::RECOMMENDED_VEHICLES_COUNT count($vehicles);
  863.         if ($missing 0) {
  864.             $vehicles array_merge($vehicles$vehicleRepository->findRandomVisibleWithImages($missing$tipVehicleIds));
  865.         }
  866.         return [$vehicles$tipVehicleIds$tipAutanetPartnerIds];
  867.     }
  868.     /**
  869.      * @return Partner[]
  870.      */
  871.     private function getPartners(PartnerRepository $partnerRepository): array
  872.     {
  873.         $partners $partnerRepository->findActiveAutanetPartners(new DateTimeImmutable());
  874.         shuffle($partners);
  875.         return $partners;
  876.     }
  877.     /**
  878.      * @return array{total: int, today: int, week: int, dealers: int}
  879.      */
  880.     private function getHomepageStats(VehicleRepository $vehicleRepository,
  881.                                       DealerRepository  $dealerRepository,
  882.                                       CacheInterface    $cache): array
  883.     {
  884.         return $cache->get('homepage_stats', function (ItemInterface $item) use ($vehicleRepository$dealerRepository): array {
  885.             $item->expiresAfter(300);
  886.             $storageTimezone = new DateTimeZone(date_default_timezone_get());
  887.             $todayStart = new DateTimeImmutable('today', new DateTimeZone('Europe/Prague'));
  888.             return [
  889.                 'total' => $vehicleRepository->countVisibleByKindUrls(self::HOMEPAGE_KIND_URLS),
  890.                 'today' => $vehicleRepository->countFirstSeenSince($todayStart->setTimezone($storageTimezone), self::HOMEPAGE_KIND_URLS),
  891.                 'week' => $vehicleRepository->countFirstSeenSince($todayStart->modify('-6 days')->setTimezone($storageTimezone), self::HOMEPAGE_KIND_URLS),
  892.                 'dealers' => $dealerRepository->countActiveProfiles(),
  893.             ];
  894.         });
  895.     }
  896.     /**
  897.      * Rozdělí URL typu "bmw-rada-3" na výrobce "bmw" a model "rada-3"
  898.      * Použije přístup: najít všechny možné kandidáty na výrobce a vybrat nejdelší shodu
  899.      */
  900.     private function parseManufacturerAndModel(string $manufacturerAndModelVehicleManufacturerRepository $manufacturerRepositoryBlogKindRepository $blogKindRepository): array
  901.     {
  902.         $testyAutKind $blogKindRepository->findOneBy(['url' => 'testy-aut']);
  903.         if (!$testyAutKind) {
  904.             return [nullnull];
  905.         }
  906.         $manufacturers $manufacturerRepository->findByBlogKind($testyAutKind);
  907.         $manufacturerUrls array_map(fn($m) => $m->getUrl(), $manufacturers);
  908.         $candidates = [];
  909.         $urlParts explode('-'$manufacturerAndModel);
  910.         $countParts count($urlParts);
  911.         for ($i 1$i <= $countParts$i++) {
  912.             $candidateManufacturer implode('-'array_slice($urlParts0$i));
  913.             if (in_array($candidateManufacturer$manufacturerUrls)) {
  914.                 $candidates[] = $candidateManufacturer;
  915.             }
  916.         }
  917.         if (empty($candidates)) {
  918.             return [nullnull];
  919.         }
  920.         usort($candidates, fn($a$b) => strlen($b) <=> strlen($a));
  921.         $manufacturerUrl $candidates[0];
  922.         if ($manufacturerUrl === $manufacturerAndModel) {
  923.             return [$manufacturerUrlnull];
  924.         }
  925.         $modelUrl substr($manufacturerAndModelstrlen($manufacturerUrl) + 1);
  926.         return [$manufacturerUrl$modelUrl];
  927.     }
  928. }