src/Service/ProfileList.php line 94

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use App\Bridge\Porpaginas\Doctrine\ORM\FakeORMQueryPage;
  4. use App\Entity\Location\City;
  5. use App\Entity\Profile\Genders;
  6. use App\Entity\Profile\Profile;
  7. use App\Event\PaginatorPageTakenEvent;
  8. use App\Repository\ProfileRepository;
  9. use App\Repository\ReadModel\ProfileListingReadModel;
  10. use App\Specification\Profile\ICountIdSpec;
  11. use App\Specification\Profile\ISelectIdListSpec;
  12. use App\Specification\Profile\ProfileHasOneOfGenders;
  13. use App\Specification\Profile\ProfileIdINOrderedByINValues;
  14. use App\Specification\Profile\ProfileIdNotIn;
  15. use App\Specification\Profile\ProfileIsActive;
  16. use App\Specification\Profile\ProfileIsArchived;
  17. use App\Specification\Profile\ProfileIsLocatedInCountry;
  18. use App\Specification\Profile\ProfileIsLocated;
  19. use App\Specification\Profile\ProfileIsMasseur;
  20. use App\Specification\Profile\ProfileIsModerationPassed;
  21. use App\Specification\Profile\ProfileIsNotMasseur;
  22. use App\Specification\QueryModifier\FreeProfilesFeatureArchivedProfileOrder;
  23. use App\Specification\QueryModifier\FreeProfilesFeatureProfileOrder;
  24. use App\Specification\Profile\ProfileIsHidden;
  25. use App\Specification\Profile\ProfileIsNotHidden;
  26. use App\Specification\QueryModifier\LimitResult;
  27. use App\Specification\QueryModifier\ProfileOrderedByCreated;
  28. use App\Specification\QueryModifier\ProfileOrderedByInactivated;
  29. use App\Specification\QueryModifier\ProfileOrderedByRandom;
  30. use App\Specification\QueryModifier\ProfileOrderedByUpdated;
  31. use App\Specification\QueryModifier\ProfileOrderedByStatus;
  32. use App\Specification\QueryModifier\ProfilePlacementHiding;
  33. use Doctrine\ORM\EntityManagerInterface;
  34. use Happyr\DoctrineSpecification\Filter\Filter;
  35. use Happyr\DoctrineSpecification\Logic\AndX;
  36. use Happyr\DoctrineSpecification\Spec;
  37. use Happyr\DoctrineSpecification\Specification\Specification;
  38. use Porpaginas\Page;
  39. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  40. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  41. use Symfony\Component\HttpFoundation\Request;
  42. use Symfony\Component\HttpFoundation\RequestStack;
  43. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  44. class ProfileList
  45. {
  46.     public const ORDER_BY_STATUS = 'status';
  47.     public const ORDER_BY_UPDATED = 'updated';
  48.     public const ORDER_NONE = 'none';
  49.     private ?Request $request;
  50.     private int $perPageDefault;
  51.     private int $perPage;
  52.     private array $executedCountQueryData;
  53.     private bool $withTopPlacementForPagination = false;
  54.     public function __construct(
  55.         private ProfileRepository $profileRepository,
  56.         RequestStack $requestStack,
  57.         private Features $features,
  58.         ParameterBagInterface $parameterBag,
  59.         private EventDispatcherInterface $eventDispatcher,
  60.         private EntityManagerInterface $entityManager,
  61.         private ProfileTopBoard $profileTopBoard,
  62.         private SplitFirstPagePagination $splitFirstPagePagination,
  63.     )
  64.     {
  65.         $this->request = $requestStack->getCurrentRequest();
  66.         $this->perPageDefault = intval($parameterBag->get('profile_list.per_page'));
  67.         $this->perPage = $this->perPageDefault;
  68.     }
  69.     public function listActiveWithinCityOrderedByStatusWithSpecAvoidingTopPlacement(
  70.         City $city, ?Filter $spec, array $additionalSpecs = null, array $genders = [Genders::FEMALE]
  71.     ): array|Page
  72.     {
  73.         return $this->listActiveWithinCityOrderedByStatusWithSpec($city, $spec, $additionalSpecs, $genders, true);
  74.     }
  75.     public function listActiveWithinCityOrderedByStatusWithSpec(
  76.         City $city, ?Filter $spec, array $additionalSpecs = null, array $genders = [Genders::FEMALE], bool $avoidTopPlacement = false
  77.     ): array|Page
  78.     {
  79.         return $this->list($city, null, $spec, $additionalSpecs, true, null, self::ORDER_BY_STATUS,
  80.             null, true, null, $genders, $avoidTopPlacement);
  81.     }
  82.     public function listActiveWithinCityOrderedByStatusWithSpecLimited(
  83.         City $city, ?Filter $spec, array $additionalSpecs = null, array $genders = [Genders::FEMALE], bool $avoidTopPlacement = false, int $limit = 0,
  84.     ): array|Page
  85.     {
  86.         return $this->list($city, null, $spec, $additionalSpecs, true, null, self::ORDER_BY_STATUS,
  87.             $limit, false, null, $genders, $avoidTopPlacement);
  88.     }
  89.     public function listActiveNotMasseurWithinCityOrderedByStatusWithSpec(
  90.         City $city, ?Filter $spec, array $additionalSpecs = null, array $genders = [Genders::FEMALE]
  91.     ): array|Page
  92.     {
  93.         return $this->list($city, null, $spec, $additionalSpecs, true, false, self::ORDER_BY_STATUS,
  94.             null, true, null, $genders);
  95.     }
  96.     public function listActiveOrderedByStatusWithSpec(
  97.         ?Filter $spec,
  98.         ?array $additionalSpecs = null,
  99.         array $genders = [Genders::FEMALE]
  100.     ): array|Page
  101.     {
  102.         $this->perPage = $this->perPageDefault;
  103.         $criteria = Spec::andX(
  104.             $this->getActiveSpecByFlag(true),
  105.             $this->getModerationSpecByFlag(),
  106.             new ProfileHasOneOfGenders($genders)
  107.         );
  108.         $criteriaForIdList = clone $criteria;
  109.         $countProfiles = $this->countOfCriteriaWithCustomSpec($criteria, $spec, $additionalSpecs);
  110.         if (0 === $countProfiles) {
  111.             $profiles = $this->takeFakePage($countProfiles, []);
  112.             $this->restorePerPageToDefault();
  113.             return $profiles;
  114.         }
  115.         $criteriaForIdList->andX($this->getOrderSpecByFlags(self::ORDER_BY_STATUS, true));
  116.         $idList = $this->listIdOfCriteriaWithCustomSpec($criteriaForIdList, $spec, $additionalSpecs, true);
  117.         $profiles = [];
  118.         if (!empty($idList)) {
  119.             $profiles = $this->profileRepository->fetchListingByIds(new ProfileIdINOrderedByINValues($idList));
  120.         }
  121.         $profiles = $this->takeFakePage($countProfiles, $profiles);
  122.         $this->restorePerPageToDefault();
  123.         return $profiles;
  124.     }
  125.     public function countActiveWithinCityWithSpec(
  126.         City $city, ?Filter $spec, array $additionalSpecs = null, array $genders = [Genders::FEMALE]
  127.     ): int
  128.     {
  129.         $criteria = Spec::andX(
  130.             ProfileIsLocated::withinCity($city),
  131.             $this->getActiveSpecByFlag(true)
  132.         );
  133.         $criteria->andX($this->getModerationSpecByFlag());
  134.         $criteria->andX(new ProfileHasOneOfGenders($genders));
  135.         return $this->countOfCriteriaWithCustomSpec($criteria, $spec, $additionalSpecs);
  136.     }
  137.     /**
  138.      * @param Profile|bool|null $avoidOrTopPlacement Принимает bool для обратной совместимости с старым кодом
  139.      */
  140.     public function list(
  141.         City $city, ?string $country, ?Filter $spec, ?array $additionalSpecs, bool $active, ?bool $masseur = false,
  142.         ?string $order = self::ORDER_BY_STATUS, ?int $limit = null, bool $paged = true, ?callable $fetchByIdMethod = null,
  143.         array $genders = [Genders::FEMALE], Profile|null|bool $avoidOrTopPlacement = false
  144.     ): array|Page
  145.     {
  146. //        $this->perPage = $limit ?? $this->perPageDefault;
  147.         $this->perPage = $this->perPageDefault;
  148.         $countProfiles = 0;
  149.         $returnProfiles = [];
  150.         $topPlacementToAvoidId = null;
  151.         if (/*null === $limit && */true === $avoidOrTopPlacement) {
  152.             $profileTopPlacement = $this->profileTopBoard->topPlacementSatisfiedBy($city, $spec);
  153.             if (null !== $profileTopPlacement) {
  154.                 $topPlacementToAvoidId = $profileTopPlacement->getId();
  155.                 $countProfiles = 1;
  156.                 $returnProfiles[] = $profileTopPlacement;
  157.             }
  158.         } elseif ($avoidOrTopPlacement instanceof Profile) {
  159.             $topPlacementToAvoidId = $avoidOrTopPlacement->getId();
  160.             $countProfiles = 1;
  161.             $returnProfiles[] = $avoidOrTopPlacement;
  162.         }
  163.         $this->withTopPlacementForPagination = null !== $topPlacementToAvoidId;
  164.         if ($this->withTopPlacementForPagination && !$this->splitFirstPagePagination->isActive()) {
  165.             //на тесте часто ставят 1 на страницу, что ломает логику, т.к. после декремента становится 0 на страницу,
  166.             //за тем и условие
  167.             if ($this->perPage > 1) {
  168.                 $this->perPage--;
  169.             }
  170.         }
  171.         $order = $this->getOrderSpecByFlags($order, $active);
  172.         $masseurSpec = $this->getMasseurSpecByFlag($masseur);
  173.         $activeSpec = $this->getActiveSpecByFlag($active);
  174.         $excludeTopProfileSpec = null !== $topPlacementToAvoidId ? new ProfileIdNotIn([$topPlacementToAvoidId]) : null;
  175.         $criteria = Spec::andX(
  176.             $country ? ProfileIsLocatedInCountry::withCountryCode($city->getCountryCode()) : ProfileIsLocated::withinCity($city),
  177.             $activeSpec
  178.         );
  179.         if ($masseurSpec) {
  180.             $criteria->andX($masseurSpec);
  181.         }
  182.         if (null !== $excludeTopProfileSpec) {
  183.             $criteria->andX($excludeTopProfileSpec);
  184.         }
  185.         $criteria->andX($this->getModerationSpecByFlag());
  186.         $criteria->andX(new ProfileHasOneOfGenders($genders));
  187.         $criteriaForIdList = clone $criteria;
  188.         if ($paged) {
  189.             $pagedCount = $this->countOfCriteriaWithCustomSpec($criteria, $spec, $additionalSpecs);
  190.             $countProfiles += $pagedCount;
  191.             if (0 === $pagedCount) {
  192.                 return $this->takeFakePage($countProfiles, $returnProfiles);
  193.             }
  194.         }
  195.         if ($order) {
  196.             $criteriaForIdList->andX($order);
  197.         }
  198.         $idList = $this->listIdOfCriteriaWithCustomSpec($criteriaForIdList, $spec, $additionalSpecs, $paged, $limit);
  199.         $profiles = [];
  200.         if(!empty($idList)) {
  201.             // $profiles = $this->profileRepository->matchingSpecRaw(new ProfileIdINOrderedByINValues($idList), null, true, array($this->profileRepository, 'hydrateProfileRow'));
  202.             $profiles = null === $fetchByIdMethod
  203.                 ? $this->profileRepository->fetchListingByIds(new ProfileIdINOrderedByINValues($idList))
  204.                 : $fetchByIdMethod(new ProfileIdINOrderedByINValues($idList));
  205.         }
  206.         $returnProfiles = array_merge($returnProfiles, $profiles);
  207.         if ($paged) {
  208.             $returnProfiles = $this->takeFakePage($countProfiles, $returnProfiles);
  209.         }
  210.         $this->restorePerPageToDefault();
  211.         return $returnProfiles;
  212.     }
  213.     public function listForMap(
  214.         City $city, ?string $country, ?Filter $spec, ?array $additionalSpecs, bool $active, ?bool $masseur = false,
  215.         ?string $order = self::ORDER_BY_STATUS, array $genders = [Genders::FEMALE], int $coordsRoundPrecision = 3,
  216.     ): array|Page
  217.     {
  218.         $order = $this->getOrderSpecByFlags($order, $active);
  219.         $masseurSpec = $this->getMasseurSpecByFlag($masseur);
  220.         $activeSpec = $this->getActiveSpecByFlag($active);
  221.         $criteria = Spec::andX(
  222.             $country ? ProfileIsLocatedInCountry::withCountryCode($city->getCountryCode()) : ProfileIsLocated::withinCity($city),
  223.             //$activeSpec
  224.         );
  225.         if($masseurSpec)
  226.             $criteria->andX($masseurSpec);
  227.         $criteria->andX($this->getModerationSpecByFlag());
  228.         $criteria->andX(new ProfileHasOneOfGenders($genders));
  229.         if(null == $additionalSpecs)
  230.             $additionalSpecs = [];
  231.         array_unshift($additionalSpecs, $spec);
  232.         array_walk($additionalSpecs, function($spec) use ($criteria): void {
  233.             $criteria->andX($spec);
  234.         });
  235.         $profiles = $this->profileRepository->listForMapMatchingSpec($criteria, $coordsRoundPrecision);
  236.         return $profiles;
  237.     }
  238.     protected function countOfCriteriaWithCustomSpec(AndX $criteria, ?Filter $spec, array $additionalSpecs = null): int
  239.     {
  240.         if(null == $additionalSpecs)
  241.             $additionalSpecs = [];
  242.         array_unshift($additionalSpecs, $spec);
  243.         array_walk($additionalSpecs, function($spec) use ($criteria): void {
  244.             $criteria->andX($spec);
  245.             if($spec instanceof ICountIdSpec)
  246.                 $criteria->andX($spec->getCountIdSpec());
  247.         });
  248.         $defaultStack = $this->entityManager->getConnection()->getConfiguration()->getSQLLogger();
  249.         $stack = new \Doctrine\DBAL\Logging\DebugStack();
  250.         $this->entityManager->getConnection()->getConfiguration()->setSQLLogger($stack);
  251.         $result = $this->profileRepository->countMatchingSpec($criteria);
  252.         //$this->executedCountQueryData = ['sql' => 'SELECT count( p0_.id ) AS sclr_0 FROM `profiles` p0_ INNER JOIN profile_adboard_placements p1_ ON p0_.id = p1_.profile_id  WHERE ( p0_.deleted_at IS NULL )', 'params' => [], 'types' => []];//
  253.         $this->executedCountQueryData = $stack->queries[count($stack->queries)];
  254.         $this->entityManager->getConnection()->getConfiguration()->setSQLLogger($defaultStack);
  255.         return $result;
  256.     }
  257.     protected function listIdOfCriteriaWithCustomSpec(AndX $criteria, ?Filter $spec, array $additionalSpecs = null, bool $paged = true, ?int $limit = null): array
  258.     {
  259.         if(null == $additionalSpecs)
  260.             $additionalSpecs = [];
  261.         array_unshift($additionalSpecs, $spec);
  262.         array_walk($additionalSpecs, function($spec) use ($criteria): void {
  263.             $criteria->andX($spec);
  264.             if($spec instanceof ISelectIdListSpec)
  265.                 $criteria->andX($spec->getIdListSpec());
  266.         });
  267.         return $this->profileRepository->listIdMatchingSpec(
  268.             $criteria,
  269.             $paged ? $this->getOffset() : 0,
  270.             $paged ? $this->getPerPageForQuery() : $limit
  271. //            $limit ?: $this->perPage
  272.         );
  273.     }
  274.     protected function getPage(): int
  275.     {
  276.         $page = (int)$this->request->get('page');
  277.         if ($page < 1)
  278.             $page = 1;
  279.         return $page;
  280.     }
  281.     protected function getOffset(): float|int
  282.     {
  283.         if ($this->splitFirstPagePagination->isActive()) {
  284.             return $this->splitFirstPagePagination->getOffsetForPage(
  285.                 $this->getPage(),
  286.                 $this->withTopPlacementForPagination
  287.             );
  288.         }
  289.         return ($this->getPage() - 1) * $this->perPage;
  290.     }
  291.     private function getPerPageForQuery(): int
  292.     {
  293.         if ($this->splitFirstPagePagination->isActive()) {
  294.             return $this->splitFirstPagePagination->getLimitForPage(
  295.                 $this->getPage(),
  296.                 $this->withTopPlacementForPagination
  297.             );
  298.         }
  299.         return $this->perPage;
  300.     }
  301.     protected function takeFakePage(int $totalResults, array $profiles): Page
  302.     {
  303.         if ($this->splitFirstPagePagination->isActive()) {
  304.             if ($this->splitFirstPagePagination->isPageOutOfRange($this->getPage(), $totalResults)) {
  305.                 throw new NotFoundHttpException('Page number doesn\'t exist');
  306.             }
  307.             $this->eventDispatcher->dispatch(new PaginatorPageTakenEvent($profiles), PaginatorPageTakenEvent::NAME);
  308.             return new FakeORMQueryPage(
  309.                 $this->splitFirstPagePagination->getDisplayOffset($this->getPage()),
  310.                 $this->getPage(),
  311.                 $this->splitFirstPagePagination->getDisplayLimit($this->getPage()),
  312.                 $totalResults,
  313.                 $profiles
  314.             );
  315.         }
  316.         //если передана страница, которой нет в основной выборке
  317.         //if($totalResults != 0 && $this->getPage() > ceil($totalResults / $this->perPage))
  318.         if ($totalResults > 0 && $this->getPage() !== 1 && $this->getOffset() > $totalResults - 1) {
  319.             throw new NotFoundHttpException('Page number doesn\'t exist');
  320.         }
  321.         //$profileIds = array_map(function(ProfileListingReadModel $profileListingReadModel): int {
  322.         //    return $profileListingReadModel->id;
  323.         //}, $profiles);
  324.         $this->eventDispatcher->dispatch(new PaginatorPageTakenEvent($profiles), PaginatorPageTakenEvent::NAME);
  325.         return new FakeORMQueryPage($this->getOffset(), $this->getPage(), $this->perPage, $totalResults, $profiles);
  326.     }
  327.     public function listRandom(
  328.         City $city, ?string $country, ?Filter $spec, ?array $additionalSpecs, bool $active, ?bool $masseur = false,
  329.         array $genders = [Genders::FEMALE], bool $paged = true, ?int $limit = null
  330.     ): array|Page
  331.     {
  332.         $masseurSpec = $this->getMasseurSpecByFlag($masseur);
  333.         $activeSpec = $this->getActiveSpecByFlag($active);
  334.         $criteria = Spec::andX(
  335.             $country ? ProfileIsLocatedInCountry::withCountryCode($city->getCountryCode()) : ProfileIsLocated::withinCity($city),
  336.             $activeSpec
  337.         );
  338.         if($masseurSpec)
  339.             $criteria->andX($masseurSpec);
  340.         $criteria->andX($this->getModerationSpecByFlag());
  341.         $criteria->andX(new ProfileHasOneOfGenders($genders));
  342.         $criteria->andX(new ProfileOrderedByRandom());
  343.         $idList = $this->listIdOfCriteriaWithCustomSpec($criteria, $spec, $additionalSpecs, $paged, $limit);
  344.         $profiles = [];
  345.         if(!empty($idList)) {
  346.             $profiles = $this->profileRepository->fetchListingByIds(new ProfileIdINOrderedByINValues($idList));
  347.         }
  348.         if($paged) {
  349.             $profiles = $this->takeFakePage(count($profiles)/*$this->perPage*/, $profiles);
  350.         }
  351.         return $profiles;
  352.     }
  353.     public function listRecent(City $city, int $count, array $genders = [Genders::FEMALE]): array
  354.     {
  355.         $criteria = Spec::andX(
  356.             //new ProfileAdBoardPlacement(),
  357.             new ProfileIsActive(),
  358.             new ProfilePlacementHiding(),
  359.             new \App\Specification\QueryModifier\ProfileAvatar(),
  360.             // убрано чтобы не было мало записей на маленьких городах
  361.             // new ProfileIsNew(),
  362.             ProfileIsLocated::withinCity($city),
  363.             new ProfileOrderedByCreated(),
  364.             new LimitResult($count)
  365.         );
  366.         $criteria->andX($this->getActiveSpecByFlag(true));
  367.         $criteria->andX($this->getModerationSpecByFlag());
  368.         $criteria->andX(new ProfileHasOneOfGenders($genders));
  369.         $result = $this->profileRepository->matchingSpecRaw($criteria, null, false);
  370.         return $result;
  371.     }
  372.     public function listLatestCreated(City $city, int $limit, array $genders = [Genders::FEMALE]): Page
  373.     {
  374.         $criteria = Spec::andX(
  375.             ProfileIsLocated::withinCity($city),
  376.             $this->getActiveSpecByFlag(true),
  377.             $this->getModerationSpecByFlag(),
  378.             new ProfileHasOneOfGenders($genders),
  379.             new ProfileOrderedByCreated()
  380.         );
  381.         $idList = $this->profileRepository->listIdMatchingSpec($criteria, 0, $limit);
  382.         $pageIds = array_slice($idList, (int)$this->getOffset(), $this->getPerPageForQuery());
  383.         $profiles = [];
  384.         if (!empty($pageIds)) {
  385.             $profiles = $this->profileRepository->fetchListingByIds(new ProfileIdINOrderedByINValues($pageIds));
  386.         }
  387.         $result = $this->takeFakePage(count($idList), $profiles);
  388.         $this->restorePerPageToDefault();
  389.         return $result;
  390.     }
  391.     public function listBySpec(?Filter $spec, ?array $additionalSpecs = null, ?int $limit = null, bool $paged = true, ?callable $fetchByIdMethod = null): array|Page
  392.     {
  393.         $this->perPage = $limit ?? $this->perPageDefault;
  394.         $criteria = Spec::andX(
  395.             $spec
  396.         );
  397.         $criteriaForIdList = clone $criteria;
  398.         if($paged) {
  399.             $count = $this->countOfCriteriaWithCustomSpec($criteria, $spec, $additionalSpecs);
  400.             if(0 == $count)
  401.                 return $this->takeFakePage($count, []);
  402.         }
  403.         $idList = $this->listIdOfCriteriaWithCustomSpec($criteriaForIdList, $spec, $additionalSpecs, $paged);
  404.         $profiles = [];
  405.         if(!empty($idList)) {
  406.             # $fetchByIdMethod передается если нужно, чтобы результат был не в виде ProfileListingReadModel, например.
  407.             # Как вариант - [$profileRepository, 'findByIds']
  408.             $profiles = null == $fetchByIdMethod
  409.                 ? $this->profileRepository->fetchListingByIds(new ProfileIdINOrderedByINValues($idList))
  410.                 : $fetchByIdMethod($idList);
  411.         }
  412.         if($paged) {
  413.             $profiles = $this->takeFakePage($count, $profiles);
  414.         }
  415.         $this->restorePerPageToDefault();
  416.         return $profiles;
  417.     }
  418.     protected function getMasseurSpecByFlag(?bool $masseur): ?Specification
  419.     {
  420.         if(true === $masseur) {
  421.             $masseurSpec = new ProfileIsMasseur();
  422.         } else if(false === $masseur) {
  423.             $masseurSpec = new ProfileIsNotMasseur();
  424.         } else {
  425.             $masseurSpec = null;
  426.         }
  427.         return $masseurSpec;
  428.     }
  429.     public function getActiveSpecByFlag(bool $active): ProfileIsHidden|ProfileIsArchived|ProfileIsNotHidden|ProfileIsActive
  430.     {
  431.         if($active) {
  432.             $activeSpec = $this->features->free_profiles() ? new ProfileIsNotHidden() : new ProfileIsActive();
  433.         } else {
  434.             $activeSpec = $this->features->free_profiles() ? new ProfileIsHidden() : new ProfileIsArchived();
  435.         }
  436.         return $activeSpec;
  437.     }
  438.     public function getModerationSpecByFlag(): ProfileIsModerationPassed
  439.     {
  440.         return new ProfileIsModerationPassed();
  441.     }
  442.     protected function getOrderSpecByFlags(string $order, bool $active): string|ProfileOrderedByStatus|ProfileOrderedByUpdated|ProfileOrderedByInactivated|FreeProfilesFeatureProfileOrder|FreeProfilesFeatureArchivedProfileOrder
  443.     {
  444.         switch($order) {
  445.             case self::ORDER_BY_UPDATED:
  446.                 $defaultOrder = new ProfileOrderedByUpdated();
  447.                 break;
  448.             case self::ORDER_NONE:
  449.                 $defaultOrder = null;
  450.                 break;
  451.             case self::ORDER_BY_STATUS:
  452.             default:
  453.                 $defaultOrder = new ProfileOrderedByStatus();
  454.                 break;
  455.         }
  456.         if(null != $defaultOrder) {
  457.             if ($this->features->free_profiles()) {
  458.                 $order = $active ? new FreeProfilesFeatureProfileOrder($this->features->consider_approved_priority()) : new FreeProfilesFeatureArchivedProfileOrder();
  459.             } else {
  460.                 $order = $active ? $defaultOrder : new ProfileOrderedByInactivated();
  461.             }
  462.         }
  463.         return $order;
  464.     }
  465.     public function executedCountQueryData(): array
  466.     {
  467.         return $this->executedCountQueryData;
  468.     }
  469.     protected function restorePerPageToDefault(): void
  470.     {
  471.         $this->perPage = $this->perPageDefault;
  472.         $this->withTopPlacementForPagination = false;
  473.     }
  474.   
  475.     public function getProfilesByIdsInOrder(array $ids): array
  476.     {
  477.         if (empty($ids)) {
  478.             return [];
  479.         }
  480.         return $this->profileRepository->fetchListingByIds(new \App\Specification\Profile\ProfileIdINOrderedByINValues($ids));
  481.     }
  482.     public function getActiveProfilesByIdsInOrderWithinCityAndSpec(
  483.         City $city,
  484.         array $ids,
  485.         ?Filter $spec,
  486.         ?array $additionalSpecs = null,
  487.         array $genders = [Genders::FEMALE],
  488.     ): array {
  489.         if (empty($ids)) {
  490.             return [];
  491.         }
  492.         $additionalSpecs ??= [];
  493.         $additionalSpecs[] = new ProfileIdINOrderedByINValues($ids);
  494.         return $this->list(
  495.             $city,
  496.             null,
  497.             $spec,
  498.             $additionalSpecs,
  499.             true,
  500.             null,
  501.             self::ORDER_NONE,
  502.             count($ids),
  503.             false,
  504.             null,
  505.             $genders,
  506.         );
  507.     }
  508.    
  509.     public function createFakePageFromProfiles(int $totalResults, array $profiles): Page
  510.     {
  511.         return $this->takeFakePage($totalResults, $profiles);
  512.     }
  513. }