src/Reader/Vacancy/DoctrineReader.php line 350

Open in your IDE?
  1. <?php
  2. namespace App\Reader\Vacancy;
  3. use App\Component\Attributes\AttributeManager;
  4. use App\Component\Attributes\AttributeManagerFactory;
  5. use App\Component\Configuration\Util\Config;
  6. use App\Decorator\VacancyDecorator;
  7. use App\Decorator\VacancyOptionDecorator;
  8. use App\Entity\Asset;
  9. use App\Entity\Gallery;
  10. use App\Entity\Option;
  11. use App\Entity\OptionValue;
  12. use App\Entity\Recruiter;
  13. use App\Entity\RecruiterAttribute;
  14. use App\Entity\Repository\VacancyRepository;
  15. use App\Entity\Vacancy;
  16. use App\Entity\VacancyAttribute;
  17. use App\EventListener\FeatureFlagListener;
  18. use App\FilterSet\VacancyFilterSet;
  19. use App\Form\Setting\MultiSiteSettingType;
  20. use App\Form\Setting\VacancySettingType;
  21. use App\Manager\MultiMediaManager;
  22. use App\Manager\VacancyDomainManager;
  23. use App\Model\Vacancy\SearchResultSet;
  24. use App\Model\Vacancy\SearchResultSetMeta;
  25. use App\Model\Vacancy\VacancyDomainCollection;
  26. use App\Service\SiteService;
  27. use App\Service\VacancyService;
  28. use App\Util\AssetUtil;
  29. use App\Util\PhoneNumberUtil;
  30. use App\Util\VacancyImage;
  31. use App\Util\VacancyUtil;
  32. use App\Vacancy\Sort\SortFactory;
  33. use Doctrine\ORM\EntityManagerInterface;
  34. use Doctrine\ORM\NonUniqueResultException;
  35. use Doctrine\ORM\NoResultException;
  36. use Flagception\Manager\FeatureManager;
  37. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  38. use Symfony\Component\HttpFoundation\Request;
  39. use Traversable;
  40. class DoctrineReader extends AbstractVacancyReader
  41. {
  42.     protected ?Recruiter $defaultRecruiter null;
  43.     protected array $optionRecruiters = [];
  44.     protected ?Gallery $defaultGallery null;
  45.     protected array $optionGalleries = [];
  46.     protected array $companyGalleries = [];
  47.     protected AttributeManager $vacancyAttributeManager;
  48.     protected AttributeManager $recruiterAttributeManager;
  49.     public function __construct(
  50.         protected EntityManagerInterface $entityManager,
  51.         protected ParameterBagInterface $parameterBag,
  52.         protected VacancyDecorator $vacancyDecorator,
  53.         protected SiteService $siteService,
  54.         protected VacancyService $vacancyService,
  55.         protected VacancyOptionDecorator $vacancyOptionDecorator,
  56.         protected VacancyFilterSet $filterSet,
  57.         protected AssetUtil $assetUtil,
  58.         protected VacancyDomainManager $vacancyDomainManager,
  59.         protected FeatureManager $featureManager,
  60.         protected MultiMediaManager $multiMediaManager,
  61.         protected Config $config,
  62.         protected VacancyImage $vacancyImage,
  63.         AttributeManagerFactory $attributeManagerFactory,
  64.         protected SortFactory $vacancySortFactory
  65.     ) {
  66.         $this->vacancyAttributeManager $attributeManagerFactory->create(VacancyAttribute::class);
  67.         $this->recruiterAttributeManager $attributeManagerFactory->create(RecruiterAttribute::class);
  68.     }
  69.     /**
  70.      * @param string|int $id
  71.      */
  72.     public function get($id): Vacancy
  73.     {
  74.         return $this->getRepository()->find($id);
  75.     }
  76.     /**
  77.      * @return Vacancy[]|array
  78.      */
  79.     public function getAll(): array
  80.     {
  81.         return $this->getRepository()->findAll();
  82.     }
  83.     /**
  84.      * @throws NonUniqueResultException|NoResultException
  85.      */
  86.     public function getSearchResultSetByRequest(Request $request): SearchResultSet
  87.     {
  88.         $domainCollection $this->getVacancyDomainCollection($request);
  89.         $vacancyRepository $this->getRepository();
  90.         $hostSite null;
  91.         if ($host $request->query->get('host')) {
  92.             $hostSite $this->siteService->getSiteFromHost($host);
  93.         }
  94.         $offset 0;
  95.         if ($request->query->getInt('pageNumber') > 1) {
  96.             $offset $request->get(
  97.                 'pageSize',
  98.                 $this->config->get('site_vacancy_limit_per_page')
  99.             ) * ($request->query->getInt('pageNumber'1) -
  100.                     1);
  101.         }
  102.         /** @var array<string, mixed> $preFilters */
  103.         $preFilters $this->parameterBag->get('site_vacancy_overview_prefilter');
  104.         $filters $this->vacancyService->fetchFilters($request$preFilters);
  105.         $options $this->vacancyService->getOptionsFromRequest($request$preFilters);
  106.         $sort $this->vacancySortFactory->create();
  107.         $vacancies $vacancyRepository->findByOptionsWithFilterSet(
  108.             $options,
  109.             $this->filterSet,
  110.             $request->get('sort'$sort->getField()),
  111.             $request->get('sortDir'$sort->getDirection()),
  112.             $offset,
  113.             $request->query->getInt('pageSize'\intval($this->config->get('site_vacancy_limit_per_page'))),
  114.             $this->config->get('site_vacancy_show_internal_vacancy_on_overview'),
  115.             $hostSite ?? $this->siteService->getSite(),
  116.             $domainCollection
  117.         );
  118.         $vacancyCount $vacancyRepository->findByOptionsWithFilterSetCount(
  119.             $options,
  120.             $this->filterSet,
  121.             $this->config->get('site_vacancy_show_internal_vacancy_on_overview'),
  122.             $hostSite ?? $this->siteService->getSite(),
  123.             $domainCollection
  124.         );
  125.         $facets $this->vacancyService->getFacets(
  126.             $options,
  127.             $filters,
  128.             $this->filterSet,
  129.             $this->config->get('site_vacancy_show_internal_vacancy_on_overview'),
  130.             $hostSite ?? $this->siteService->getSite(),
  131.             $domainCollection
  132.         );
  133.         $this->vacancyDecorator->decorate($vacanciesfalsefalse);
  134.         $this->vacancyOptionDecorator->decorate($vacancies);
  135.         $objectMultiMedia = [];
  136.         if ($this->featureManager->isActive(FeatureFlagListener::FEATURE_MULTI_MEDIA)) {
  137.             $objectMultiMedia $this->multiMediaManager->getFeaturedObjectMultiMediaByClass(Vacancy::class);
  138.         }
  139.         $maxPaginationItems 2;
  140.         $totalPageCount ceil($vacancyCount $this->config->get('site_vacancy_limit_per_page'));
  141.         if ($totalPageCount $maxPaginationItems) {
  142.             $maxPaginationItems $totalPageCount;
  143.         }
  144.         $vacancyOutput = [];
  145.         /** @var Vacancy $vacancy */
  146.         foreach ($vacancies as $vacancy) {
  147.             $data $this->transformVacancy($vacancy$objectMultiMedia);
  148.             $vacancyOutput[] = $data;
  149.         }
  150.         $seoSnippet $this->vacancyService->getSeoSnippetsFromFacets($facets$this->siteService->getSite());
  151.         unset($seoSnippet['optionValues']);
  152.         $maxSalaryRangeOptions $options;
  153.         $maxSalaryRangeOptions['filters'] = array_filter($options['filters'], fn ($filter) => 'salary_filter' !== $filter['name']);
  154.         $maxSalaryRange $this->featureManager->isActive(FeatureFlagListener::FEATURE_VACANCY_SALARY_RANGE_FILTER)
  155.             ? \intval($vacancyRepository->findMaxSalaryAmount(
  156.                 $maxSalaryRangeOptions,
  157.                 $this->filterSet,
  158.                 (bool) $this->config->get('site_vacancy_show_internal_vacancy_on_overview'),
  159.                 $domainCollection,
  160.             ) / 100)
  161.             : null;
  162.         return new SearchResultSet(
  163.             $vacancyOutput,
  164.             $facets,
  165.             new SearchResultSetMeta(
  166.                 $vacancyCount,
  167.                 $request->query->getInt('pageNumber'1),
  168.                 $this->config->get('site_vacancy_limit_per_page'),
  169.                 $totalPageCount,
  170.                 $maxPaginationItems,
  171.                 $seoSnippet,
  172.                 $this->featureManager->isActive(FeatureFlagListener::FEATURE_TEALIUM) ?
  173.                     $this->getTealiumData($request$vacancyCount)->toArray() : [],
  174.                 $maxSalaryRange
  175.             )
  176.         );
  177.     }
  178.     /**
  179.      * @throws NonUniqueResultException|NoResultException
  180.      */
  181.     public function getMapSearchResultSetByRequest(Request $request): SearchResultSet
  182.     {
  183.         $domainCollection $this->getVacancyDomainCollection($request);
  184.         $vacancyRepository $this->getRepository();
  185.         $hostSite null;
  186.         if ($host $request->query->get('host')) {
  187.             $hostSite $this->siteService->getSiteFromHost($host);
  188.         }
  189.         $offset 0;
  190.         /** @var array $preFilters */
  191.         $preFilters $this->parameterBag->get('site_vacancy_overview_prefilter');
  192.         $filters $this->vacancyService->fetchFilters($request$preFilters);
  193.         $options $this->vacancyService->getOptionsFromRequest($request$preFilters);
  194.         $sort $this->vacancySortFactory->create();
  195.         /** @var Vacancy[] $vacancies */
  196.         $vacancies $vacancyRepository->findMapByOptionsWithFilterSet(
  197.             $options,
  198.             $this->filterSet,
  199.             $request->get('sort'$sort->getField()),
  200.             $request->get('sortDir'$sort->getDirection()),
  201.             $offset,
  202.             9999,
  203.             $this->config->get('site_vacancy_show_internal_vacancy_on_overview'),
  204.             $hostSite ?? $this->siteService->getSite(),
  205.             $domainCollection
  206.         );
  207.         $facets = [];
  208.         $seoSnippet = [];
  209.         return new SearchResultSet(
  210.             $vacancies,
  211.             $facets,
  212.             new SearchResultSetMeta(
  213.                 9,
  214.                 1,
  215.                 1,
  216.                 1,
  217.                 0,
  218.                 $seoSnippet,
  219.                 []
  220.             )
  221.         );
  222.     }
  223.     public function transformVacancy(Vacancy $vacancy, array $objectMultiMedia): array
  224.     {
  225.         $company $vacancy->getCompany();
  226.         $featuredMultiMedia $this->getFeaturedMultiMedia($objectMultiMedia$vacancy->getId());
  227.         $data = [
  228.             'id' => $vacancy->getId(),
  229.             'external_id' => $vacancy->getExternalId(),
  230.             'external_reference' => md5($vacancy->getExternalReference() ?? ''),
  231.             'displayable_external_id' => $vacancy->getDisplayableExternalId(),
  232.             'created' => $vacancy->getCreated(),
  233.             'updated' => $vacancy->getUpdated(),
  234.             'slug' => $vacancy->getSlug(),
  235.             'title' => $vacancy->getTitle(),
  236.             'subtitle' => $vacancy->getSubTitle(),
  237.             'city' => $vacancy->getCity(),
  238.             'salary' => $vacancy->getSalary(),
  239.             'min_salary' => $vacancy->getMinSalary(),
  240.             'max_salary' => $vacancy->getMaxSalary(),
  241.             'salary_unit' => $vacancy->getSalaryUnit(),
  242.             'zipcode' => $vacancy->getZipcode(),
  243.             'intro' => $vacancy->getIntro(),
  244.             'option_values' => $this->parseOptionValues($vacancy->getOptionValues()),
  245.             'main_icon' => [
  246.                 'font_awesome_icon' => $vacancy->getMainIcon() ? $vacancy->getMainIcon()->getFontAwesomeIcon() : '',
  247.             ],
  248.             'vacancy_usp_values' => [],
  249.             'usps' => [],
  250.             'featured' => $vacancy->isFeatured(),
  251.             'internal_vacancy' => $vacancy->isInternalVacancy(),
  252.             'new' => $vacancy->isNew(),
  253.             'address' => $vacancy->getAddress(),
  254.             'latitude' => $vacancy->getLatitude(),
  255.             'longitude' => $vacancy->getLongitude(),
  256.             'overview_images' => array_map(
  257.                 fn (Asset $asset) => $this->assetUtil->getAssetUrlsForFilters($asset),
  258.                 $vacancy->getOverviewImages()
  259.             ),
  260.             'featured_multi_media' => $featuredMultiMedia,
  261.             'custom_salary' => $this->config->get('site_vacancy_show_custom_salary_in_overview') ? $vacancy->getCustomSalary() : null,
  262.             'show_city' => $this->config->get('site_vacancy_show_location'),
  263.             'analytics_data' => [
  264.                 'favorite' => json_encode([
  265.                     'elementAction' => 'favorite',
  266.                     'jobId' => $vacancyAnalyticsData['job_id'] ?? $vacancy->getExternalId(),
  267.                     'jobName' => $vacancyAnalyticsData['job_name'] ?? $vacancy->getTitle(),
  268.                     'jobField' => $vacancyAnalyticsData['job_field'] ?? '',
  269.                     'jobEntity' => $vacancyAnalyticsData['job_entity'] ?? '',
  270.                     'jobCountry' => $vacancyAnalyticsData['job_country'] ?? $vacancy->getCountry(),
  271.                     'jobCity' => $vacancyAnalyticsData['job_city'] ?? $vacancy->getCity(),
  272.                 ]),
  273.             ],
  274.             'gallery' => $this->getVacancyGallery($vacancy),
  275.             'labels' => $vacancy->getLabels(),
  276.             'job_start_date' => $vacancy->getJobStartDate(),
  277.             'attribute_values' => $this->vacancyAttributeManager->getNormalizedValues($vacancy),
  278.         ];
  279.         if ($this->config->get('site_vacancy_recruiter_in_overview')) {
  280.             if ($vacancy->getRecruiter()) {
  281.                 $data['recruiter'] = $this->transformRecruiter($vacancy->getRecruiter());
  282.             }
  283.             if (empty($data['recruiter']) && $recruiter $this->getVacancyRecruiter($vacancy)) {
  284.                 $data['recruiter'] = $this->transformRecruiter($recruiter);
  285.             }
  286.         }
  287.         if ($company) {
  288.             $data['company'] = [
  289.                 'id' => $company->getId(),
  290.                 'slug' => $company->getSlug(),
  291.                 'name' => $vacancy->getCompanyName() ?? $company->getName(),
  292.                 'zipcode' => $company->getZipcode(),
  293.                 'city' => $company->getCity(),
  294.                 'website' => $company->getWebsite(),
  295.                 'email' => $company->getEmail(),
  296.                 'option_values' => [],
  297.                 'address' => $company->getAddress(),
  298.                 'latitude' => $company->getLatitude(),
  299.                 'longitude' => $company->getLongitude(),
  300.                 'logo' => $company->getLogo() ?
  301.                     $this->assetUtil->getAssetUrlsForFilters($company->getLogo()) : null,
  302.             ];
  303.         }
  304.         return $data;
  305.     }
  306.     protected function getRepository(): VacancyRepository
  307.     {
  308.         return $this->entityManager->getRepository(Vacancy::class);
  309.     }
  310.     public function isCacheAble(): bool
  311.     {
  312.         return true;
  313.     }
  314.     public function getRelatedVacancies(Request $requestVacancy $vacancy, ?int $limit null): array
  315.     {
  316.         $site null;
  317.         $host $request->query->get('host');
  318.         if (\is_string($host)) {
  319.             $site $this->siteService->getSiteFromHost($host);
  320.         }
  321.         if (!$site) {
  322.             $site $this->siteService->getSite();
  323.         }
  324.         $vacancyRepository $this->entityManager->getRepository(Vacancy::class);
  325.         switch ($this->config->get('site_vacancy_related_vacancy_type')) {
  326.             case 'featured':
  327.                 $relatedVacancies $vacancy->isFeatured() ?
  328.                     $vacancyRepository->findTopVacanciesOfCompany(
  329.                         $vacancy->getCompany(),
  330.                         [$vacancy],
  331.                         $limit,
  332.                         $site
  333.                     ) :
  334.                     $vacancyRepository->findTopVacancies([$vacancy], $limit$site);
  335.                 break;
  336.             case 'options':
  337.                 $relatedVacancyOptions $this->config->get('site_vacancy_related_vacancy_options');
  338.                 $relatedVacancyOptionsIds array_map(static fn (Option $option) => $option->getId(), $relatedVacancyOptions->toArray());
  339.                 $relatedVacanciesOptionValues $vacancy->getOptionValues()->filter(function (
  340.                     OptionValue $optionValue
  341.                 ) use ($relatedVacancyOptionsIds) {
  342.                     return \in_array($optionValue->getOption()->getId(), $relatedVacancyOptionsIdstrue);
  343.                 });
  344.                 $relatedVacancies $vacancyRepository->findRelatedVacanciesByOptionValues(
  345.                     $relatedVacanciesOptionValues->toArray(),
  346.                     $limit,
  347.                     $vacancy,
  348.                     $site,
  349.                     $this->config->get('site_vacancy_restricted_related_vacancies_to_company') ? $vacancy->getCompany() : null,
  350.                 );
  351.                 break;
  352.             case 'primary_discipline':
  353.                 $relatedVacancies $vacancyRepository->findRelatedByPrimaryDiscipline(
  354.                     $vacancy,
  355.                     $limit,
  356.                     $site
  357.                 );
  358.                 break;
  359.             case 'primary_secundary_discipline':
  360.                 $relatedVacancies $vacancyRepository->findRelatedByPrimaryOrSecundaryDiscipline(
  361.                     $vacancy,
  362.                     $limit,
  363.                     $site
  364.                 );
  365.                 break;
  366.             case 'location':
  367.                 $relatedVacancies $vacancyRepository->findRelatedByLocation(
  368.                     $vacancy,
  369.                     $limit,
  370.                     $site
  371.                 );
  372.                 break;
  373.             default:
  374.                 $relatedVacancies = [];
  375.                 break;
  376.         }
  377.         return $relatedVacancies;
  378.     }
  379.     public function getVacancyCount(Request $request): int
  380.     {
  381.         $hostSite null;
  382.         if ($host $request->getHost()) {
  383.             $hostSite $this->siteService->getSiteFromHost($host);
  384.         }
  385.         /** @var VacancyRepository $vacancyRepository */
  386.         $vacancyRepository $this->entityManager->getRepository(Vacancy::class);
  387.         /** @var array<string, mixed> $preFilters */
  388.         $preFilters $this->parameterBag->get('site_vacancy_overview_prefilter');
  389.         $options $this->vacancyService->getOptionsFromRequest($request$preFilters);
  390.         try {
  391.             return $vacancyRepository->findByOptionsWithFilterSetCount(
  392.                 $options,
  393.                 $this->filterSet,
  394.                 true,
  395.                 $hostSite
  396.             );
  397.         } catch (NonUniqueResultException|NoResultException) {
  398.             return 0;
  399.         }
  400.     }
  401.     public function getFeaturedVacancies(?int $limit null, ?string $sort null): array
  402.     {
  403.         if (
  404.             MultiSiteSettingType::MULTI_SITE_VACANCY_FILTER_MULTIPLE_SITES === $this->parameterBag->get('site_vacancy_filter_strategy')
  405.         ) {
  406.             return $this->getRepository()->findTopVacanciesFindableOnSites([], $limit$this->siteService->getSite(), $sort);
  407.         }
  408.         return $this->getRepository()->findTopVacancies([], $limit$this->siteService->getSite(), $sort);
  409.     }
  410.     public function getVacanciesByIds(array $ids): array
  411.     {
  412.         $vacancies $this->getRepository()
  413.             ->findVacanciesByIds($ids)
  414.         ;
  415.         return [
  416.             'vacancies' => $vacancies,
  417.             'companyLogos' => [],
  418.         ];
  419.     }
  420.     protected function getVacancyDomainCollection(Request $request): VacancyDomainCollection
  421.     {
  422.         $domains explode(';'$request->get('domains''public'));
  423.         $isPublicDomain \in_array('public'$domainstrue);
  424.         $isPrivateDomain \in_array('private'$domainstrue);
  425.         return $this->vacancyDomainManager->calculateVacancyDomains($isPublicDomain$isPrivateDomain);
  426.     }
  427.     protected function getFeaturedMultiMedia(array $objectMultiMediaint $vacancyId): array
  428.     {
  429.         return $this->vacancyService->getFeaturedMultiMedia($objectMultiMedia$vacancyId);
  430.     }
  431.     protected function parseOptionValues(Traversable $optionValueCollection): array
  432.     {
  433.         $optionValues = [];
  434.         /** @var OptionValue $optionValue */
  435.         foreach ($optionValueCollection as $optionValue) {
  436.             $formattedOptionValue = [
  437.                 'id' => $optionValue->getId(),
  438.                 'value' => $optionValue->getValue(),
  439.                 'sub_title' => $optionValue->getSubTitle(),
  440.                 'slug' => $optionValue->getSlug(),
  441.                 'font_awesome_icon' => $optionValue->getFontAwesomeIcon(),
  442.                 'content' => $optionValue->getContent(),
  443.                 'hasDetailPage' => $optionValue->hasDetailPage(),
  444.                 'attributes' => $optionValue->getAttributes(),
  445.                 'vacancy_images' => array_map(function ($image) {return $this->assetUtil->getAssetUrlsForFilters($image); }, $optionValue->getVacancyImages()->toArray()),
  446.             ];
  447.             if (($option $optionValue->getOption()) instanceof Option) {
  448.                 $formattedOptionValue['option'] = [
  449.                     'id' => $option->getId(),
  450.                     'title' => $option->getTitle(),
  451.                     'slug' => $option->getSlug(),
  452.                     'font_awesome_icon' => $option->getFontAwesomeIcon(),
  453.                     'expanded_by_default' => $option->isExpandedByDefault(),
  454.                     'strategy_on_overview' => $option->getStrategyOnOverview(),
  455.                     'visible_in_detail' => $option->isVisibleInDetail(),
  456.                     'values' => [],
  457.                     'position' => $option->getPosition(),
  458.                     'internal_name' => $option->getInternalName(),
  459.                     'display_type' => $option->getDisplayType(),
  460.                 ];
  461.             }
  462.             $optionValues[] = $formattedOptionValue;
  463.         }
  464.         return $optionValues;
  465.     }
  466.     protected function transformRecruiter(Recruiter $recruiter): array
  467.     {
  468.         return [
  469.             'name' => $recruiter->getName(),
  470.             'first_name' => $recruiter->getFirstName(),
  471.             'last_name_prefix' => $recruiter->getLastNamePrefix(),
  472.             'last_name' => $recruiter->getLastName(),
  473.             'email' => $recruiter->getEmail(),
  474.             'phone' => [
  475.                 'e164' => PhoneNumberUtil::formatPhoneE164($recruiter->getPhone()),
  476.                 'regular' => PhoneNumberUtil::formatPhoneNational($recruiter->getPhone()),
  477.             ],
  478.             'picture' => $this->assetUtil->getFilteredUrlsForObject(
  479.                 $recruiter,
  480.                 'picture',
  481.                 [
  482.                     'avatar_48',
  483.                     'avatar_64',
  484.                     'avatar_96',
  485.                 ]
  486.             ),
  487.             'attribute_values' => $this->recruiterAttributeManager->getNormalizedValues($recruiter),
  488.         ];
  489.     }
  490.     private function getDefaultRecruiter(): ?Recruiter
  491.     {
  492.         if (!$this->defaultRecruiter) {
  493.             $recruiterFallback $this->config->get('site_vacancy_detail_recruiter_fallback');
  494.             if ($recruiterFallback) {
  495.                 $this->defaultRecruiter $this->entityManager
  496.                     ->getRepository(Recruiter::class)
  497.                     ->find($recruiterFallback->getId());
  498.             }
  499.         }
  500.         return $this->defaultRecruiter;
  501.     }
  502.     private function getOptionRecruiter(Vacancy $vacancy): ?Recruiter
  503.     {
  504.         $recruiterOption $this->config->get('site_vacancy_detail_recruiter_option');
  505.         if (!$recruiterOption) {
  506.             return null;
  507.         }
  508.         if (empty($this->optionRecruiters[$recruiterOption->getId()])) {
  509.             $this->optionRecruiters[$recruiterOption->getId()] = null;
  510.             $recruiterOptionOptionValues VacancyUtil::getOptionValuesByOptionId($vacancy$recruiterOption->getId());
  511.             $recruiterOptionOptionValue $recruiterOptionOptionValues->first();
  512.             if ($recruiterOptionOptionValue) {
  513.                 $this->optionRecruiters[$recruiterOption->getId()] = $recruiterOptionOptionValue->getRecruiter();
  514.             }
  515.         }
  516.         return $this->optionRecruiters[$recruiterOption->getId()];
  517.     }
  518.     protected function getVacancyRecruiter(Vacancy $vacancy): ?Recruiter
  519.     {
  520.         return match ($this->config->get('site_vacancy_detail_recruiter_strategy')) {
  521.             VacancySettingType::VACANCY_DETAIL_RECRUITER_STRATEGY_OPTION => $this->getOptionRecruiter($vacancy),
  522.             VacancySettingType::VACANCY_DETAIL_RECRUITER_STRATEGY_FALLBACK => $this->getDefaultRecruiter(),
  523.             default => null,
  524.         };
  525.     }
  526.     private function getDefaultGallery(): ?Gallery
  527.     {
  528.         if (!$this->defaultGallery) {
  529.             $galleryFallback $this->config->get('site_vacancy_detail_gallery_fallback');
  530.             if ($galleryFallback) {
  531.                 $this->defaultGallery $this->entityManager
  532.                     ->getRepository(Gallery::class)
  533.                     ->find($galleryFallback->getId());
  534.             }
  535.         }
  536.         return $this->defaultGallery;
  537.     }
  538.     private function getOptionGallery(Vacancy $vacancy): ?Gallery
  539.     {
  540.         $galleryOption $this->config->get('site_vacancy_detail_gallery_option');
  541.         if (!$galleryOption) {
  542.             return null;
  543.         }
  544.         if (empty($this->optionGalleries[$galleryOption->getId()])) {
  545.             $this->optionGalleries[$galleryOption->getId()] = null;
  546.             $galleryOptionOptionValues VacancyUtil::getOptionValuesByOptionId($vacancy$galleryOption->getId());
  547.             $galleryOptionOptionValue $galleryOptionOptionValues->first();
  548.             if ($galleryOptionOptionValue) {
  549.                 $this->optionGalleries[$galleryOption->getId()] = $galleryOptionOptionValue->getGallery();
  550.             }
  551.         }
  552.         return $this->optionGalleries[$galleryOption->getId()];
  553.     }
  554.     private function getCompanyGallery(Vacancy $vacancy): ?Gallery
  555.     {
  556.         $galleryCompany $vacancy->getCompany();
  557.         if (!$galleryCompany) {
  558.             return null;
  559.         }
  560.         if (empty($this->companyGalleries[$galleryCompany->getId()])) {
  561.             $this->companyGalleries[$galleryCompany->getId()] = $galleryCompany->getGallery();
  562.         }
  563.         return $this->companyGalleries[$galleryCompany->getId()];
  564.     }
  565.     protected function getVacancyGallery(Vacancy $vacancy): ?Gallery
  566.     {
  567.         switch ($this->config->get('site_vacancy_detail_gallery_strategy')) {
  568.             case VacancySettingType::VACANCY_DETAIL_GALLERY_STRATEGY_NONE:
  569.             default:
  570.                 return null;
  571.             case VacancySettingType::VACANCY_DETAIL_GALLERY_STRATEGY_COMPANY:
  572.                 return $this->getCompanyGallery($vacancy);
  573.             case VacancySettingType::VACANCY_DETAIL_GALLERY_STRATEGY_OPTION:
  574.                 return $this->getOptionGallery($vacancy);
  575.             case VacancySettingType::VACANCY_DETAIL_GALLERY_STRATEGY_FALLBACK:
  576.                 return $this->getDefaultGallery();
  577.         }
  578.     }
  579. }