src/App/Doctrine/Repository/System/SchoolRepository.php line 42

Open in your IDE?
  1. <?php
  2. namespace App\Doctrine\Repository\System;
  3. use App\Doctrine\Repository\SearchableRepositoryInterface;
  4. use App\Doctrine\Repository\SearchableRepositoryTrait;
  5. use App\Entity\System\School;
  6. use App\Model\Searching\AbstractSearch;
  7. use App\Model\Searching\SchoolSearch;
  8. use App\Util\Querying;
  9. use Cms\TenantBundle\Entity\Tenant;
  10. use Doctrine\ORM\EntityRepository;
  11. use Doctrine\ORM\QueryBuilder;
  12. use JsonException;
  13. /**
  14.  * @method School|null find($id, $lockMode = null, $lockVersion = null)
  15.  * @method School|null findOneBy(array $criteria, array $orderBy = null)
  16.  * @method array|School[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
  17.  */
  18. class SchoolRepository extends EntityRepository implements SearchableRepositoryInterface
  19. {
  20.     use SearchableRepositoryTrait;
  21.     /**
  22.      * @param string|null $ulid
  23.      * @return School|null
  24.      */
  25.     public function findOneByUlid(?string $ulid): ?School
  26.     {
  27.         return $ulid $this->findOneBy([
  28.             'ulid' => $ulid,
  29.         ]) : null;
  30.     }
  31.     /**
  32.      * {@inheritDoc}
  33.      * @return array|School[]
  34.      */
  35.     public function findAll(): array
  36.     {
  37.         return $this->findBy(
  38.             [],
  39.             [
  40.                 'type' => 'ASC',
  41.                 'name' => 'ASC',
  42.             ]
  43.         );
  44.     }
  45.     /**
  46.      * @param Tenant $tenant
  47.      * @param int $schoolTypes
  48.      * @return School[]
  49.      */
  50.     public function findAllForTenantAndSchoolTypes(Tenant $tenantint $schoolTypes): array
  51.     {
  52.         return $this->createQueryBuilder('schools')
  53.             ->andWhere('schools.tenant = :tenant')
  54.             ->setParameter('tenant'$tenant)
  55.             ->andWhere('BIT_AND(:types, schools.type) > 0')
  56.             ->setParameter('types'$schoolTypes)
  57.             ->getQuery()
  58.             ->getResult();
  59.     }
  60.     /**
  61.      * @return array|School[]
  62.      */
  63.     public function findAllForApp(bool $district true): array
  64.     {
  65.         $qb $this
  66.             ->createQueryBuilder('schools')
  67.             ->andWhere('schools.department IS NOT NULL');
  68.         if ($district) {
  69.             $qb
  70.                 ->addSelect('CASE WHEN schools.type = :type THEN 0 ELSE 1 END AS HIDDEN _sorting')
  71.                 ->addOrderBy('_sorting''ASC');
  72.         } else {
  73.             $qb->andWhere('schools.type != :type');
  74.         }
  75.         return $qb
  76.             ->setParameter('type'School::TYPES__DISTRICT)
  77.             ->addOrderBy('schools.name''ASC')
  78.             ->getQuery()
  79.             ->getResult();
  80.     }
  81.     /**
  82.      * @param array|string[] $schools
  83.      * @param bool $district
  84.      * @return array|School[]
  85.      */
  86.     public function findAllForSchools(array $schools, ?bool $district null): array
  87.     {
  88.         // init builder
  89.         $qb $this
  90.             ->createQueryBuilder('schools')
  91.             ->andWhere('schools.department IS NOT NULL');
  92.         // custom sorting, district first, then by name no matter the type
  93.         $qb
  94.             ->addSelect('CASE WHEN schools.type = :typesDistrict THEN 0 ELSE 1 END AS HIDDEN _sorting')
  95.             ->setParameter('typesDistrict'School::TYPES__DISTRICT);
  96.         // handle district option
  97.         switch (true) {
  98.             // we don't care if the district naturally falls in the profiles list of schools
  99.             // i.e. the user may be directly associated with the district, such as a superintendent, etc.
  100.             case $district === null:
  101.                 $qb
  102.                     ->andWhere('schools.oneRosterOrg IN (:schools)')
  103.                     ->setParameter('schools'$schools);
  104.                 break;
  105.             // we want to ensure that the district is not in the results, no matter of direct associations or not
  106.             case $district === false:
  107.                 $qb
  108.                     ->andWhere('schools.type != :type')
  109.                     ->setParameter('type'School::TYPES__DISTRICT)
  110.                     ->andWhere('schools.oneRosterOrg IN (:schools)')
  111.                     ->setParameter('schools'$schools);
  112.                 break;
  113.             // we want to ensure that the district appears in the list of schools for the user
  114.             case $district === true:
  115.                 $qb
  116.                     ->andWhere(
  117.                         $qb->expr()->orX(
  118.                             'schools.type = :type',
  119.                             'schools.oneRosterOrg IN (:schools)',
  120.                         )
  121.                     )
  122.                     ->setParameter('type'School::TYPES__DISTRICT)
  123.                     ->setParameter('schools'$schools);
  124.                 break;
  125.         }
  126.         // sort and return results
  127.         return $qb
  128.             ->addOrderBy('_sorting''ASC')
  129.             ->addOrderBy('schools.name''ASC')
  130.             ->getQuery()
  131.             ->getResult();
  132.     }
  133.     /**
  134.      * {@inheritDoc}
  135.      * @param SchoolSearch $search
  136.      */
  137.     public function qbBySearch(
  138.         AbstractSearch $search,
  139.         ?QueryBuilder $qb null
  140.     ): QueryBuilder
  141.     {
  142.         if ( ! $search instanceof SchoolSearch) {
  143.             throw new \Exception();
  144.         }
  145.         $qb $qb ?: $this->createQueryBuilder('schools');
  146.         switch ($search->getSort()) {
  147.             case SchoolSearch::SORTS__NAME:
  148.                 $qb->addOrderBy('schools.name'$search->getDirection());
  149.                 break;
  150.             case SchoolSearch::SORTS__TYPE:
  151.                 $qb
  152.                     ->addOrderBy('schools.type'Querying::dirFlip($search->getDirection()))
  153.                     ->addOrderBy('schools.name''ASC');
  154.                 break;
  155.             case SchoolSearch::SORTS__TIMESTAMP:
  156.                 $qb
  157.                     ->addOrderBy('schools.touchedAt'$search->getDirection())
  158.                     ->addOrderBy('schools.name''ASC');
  159.                 break;
  160.         }
  161.         return $qb;
  162.     }
  163.     /**
  164.      * @param School ...$schools
  165.      * @return string
  166.      * @throws JsonException
  167.      */
  168.     public static function getSchoolsOneRosterOrgsJson(School ...$schools): string
  169.     {
  170.         return json_encode(
  171.             array_map(
  172.                 static function (School $school) {
  173.                     return $school->getOneRosterOrg();
  174.                 },
  175.                 $schools
  176.             ),
  177.             JSON_THROW_ON_ERROR
  178.         );
  179.     }
  180. }