repository = $em->getRepository(ThirdParty::class); } public function findThirdpartiesWithContacts(string $lang): iterable { $sql = " SELECT parent.id AS Id, CASE WHEN parent.kind = 'company' THEN 'Personne morale' ELSE 'Personne physique' END AS kind, parent_civility.name->>? AS civility, parent.firstname AS firstname, parent.name AS name, parent.profession AS profession, parent.telephone AS telephone, parent.telephone2 AS telephone2, parent.email AS email, CONCAT_WS(' ', parent_address.street, parent_address.streetnumber, parent_postal.code, parent_postal.label) AS address, parent.comment AS comment, parent.parent_id AS parent, parent.name_company AS name_company, parent.acronym AS acronym, CASE WHEN parent.active THEN 'X' ELSE '' END AS active, -- Contact (child third-party) details contact.id AS contact_id, contact.name AS contact_name, contact.firstname AS contact_firstname, contact.telephone AS contact_phone, contact.telephone2 AS contact_phone2, contact.email AS contact_email, contact.profession AS contact_profession, CONCAT_WS(' ', contact_address.street, contact_address.streetnumber, contact_postal.code, contact_postal.label) AS contact_address FROM chill_3party.third_party parent LEFT JOIN chill_main_civility parent_civility ON parent.civility_id = parent_civility.id LEFT JOIN chill_main_address parent_address ON parent.address_id = parent_address.id LEFT JOIN chill_main_postal_code parent_postal ON parent_address.postcode_id = parent_postal.id -- Join contacts (child third parties) LEFT JOIN chill_3party.third_party contact ON contact.parent_id = parent.id LEFT JOIN chill_main_address contact_address ON contact.address_id = contact_address.id LEFT JOIN chill_main_postal_code contact_postal ON contact_address.postcode_id = contact_postal.id -- Exclude contacts from appearing as standalone rows WHERE parent.parent_id IS NULL -- Sorting order ORDER BY parent.name ASC, parent.name_company ASC, parent.id ASC, contact.name ASC, contact.firstname ASC, contact.id ASC "; return $this->connection->iterateAssociative($sql, [$lang]); } /** * count amongst parties associated to $centers, with $terms parameters. */ public function countByMemberOfCenters(array $centers, array $terms = []): int { $qb = $this->buildQuery($centers, $terms); $qb->select('COUNT(tp)'); return $qb->getQuery()->getSingleScalarResult(); } public function createQueryBuilder(string $alias, ?string $indexBy = null): QueryBuilder { return $this->repository->createQueryBuilder($alias, $indexBy); } public function find($id): ?ThirdParty { return $this->repository->find($id); } /** * @return array|ThirdParty[] */ public function findAll(): array { return $this->repository->findAll(); } /** * @param null $limit * @param null $offset * * @return array|ThirdParty[] */ public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array { return $this->repository->findBy($criteria, $orderBy, $limit, $offset); } /** * Search amongst parties associated to $centers, with $terms parameters. * * Different format for return: * - ['entity']: return the entity hydrated as objects * - ['array', [ DQL ]: return objects hydrated as entity, with * an array describing the fields as DQL. * * supported terms: * * - name or _default: containing the name (name LIKE %string%) * - is_active: is active = true / false * - types: an array of types * * @param int $firstResult * @param int $maxResults * @param array $terms * @param string[] $returnFormat a format for returning */ public function findByMemberOfCenters(array $centers, $firstResult = 0, $maxResults = 20, $terms = [], $returnFormat = ['entity']): array { $qb = $this->buildQuery($centers, $terms); switch ($returnFormat[0]) { case 'entity': $qb->select('tp'); $hydrate = Query::HYDRATE_OBJECT; break; case 'array': $hydrate = Query::HYDRATE_ARRAY; $first = true; foreach ($returnFormat[1] as $dql) { if ($first) { $qb->select($dql); $first = false; } else { $qb->addSelect($dql); } } break; default: throw new \DomainException('This return format is invalid'); } $qb->setFirstResult($firstResult) ->setMaxResults($maxResults); return $qb->getQuery()->getResult(); } public function findOneBy(array $criteria): ?ThirdParty { return $this->repository->findOneBy($criteria); } public function getClassName(): string { return ThirdParty::class; } private function buildQuery($centers, $terms): QueryBuilder { $qb = $this->createMemberOfCentersQuery($centers); $this->setNameCondition($qb, $terms); $this->setTypesCondition($qb, $terms); $this->setIsActiveCondition($qb, $terms); return $qb; } private function createMemberOfCentersQuery($centers): QueryBuilder { $qb = $this->createQueryBuilder('tp'); $or = $qb->expr()->orX(); foreach ($centers as $center) { $or->add($qb->expr()->isMemberOf(':center_'.$center->getId(), 'tp.centers')); $qb->setParameter('center_'.$center->getId(), $center); } $qb->where($or); return $qb; } private function setIsActiveCondition(QueryBuilder $qb, array $terms) { if (\array_key_exists('is_active', $terms)) { $qb->andWhere( $terms['is_active'] ? $qb->expr()->eq('tp.active', "'TRUE'") : $qb->expr()->eq('tp.active', "'FALSE'") ); } } /** * Add parameters to filter by containing $terms["name"] or * $terms["_default"]. */ private function setNameCondition(QueryBuilder $qb, array $terms) { if (\array_key_exists('name', $terms) || \array_key_exists('_default', $terms)) { $term = $terms['name'] ?? $terms['_default']; if (null === $term || '' === $term) { return; } $qb->andWhere($qb->expr()->like('UNACCENT(LOWER(tp.name))', 'UNACCENT(LOWER(:name))')); $qb->setParameter('name', '%'.$term.'%'); } } private function setTypesCondition(QueryBuilder $qb, array $terms) { if (\array_key_exists('types', $terms)) { $orx = $qb->expr()->orX(); foreach ($terms['types'] as $type) { $orx->add('JSONB_EXISTS_IN_ARRAY(tp.type, :type_'.$type.') = \'TRUE\''); $qb->setParameter('type_'.$type, $type); } $qb->andWhere($orx); } } }