/**
  * {@inheritdoc}
  */
 public function filter(QueryBuilder $qb, UserInterface $user = null)
 {
     if (!$this->isFilterable($qb)) {
         throw new UserException('Query builder is not filterable.');
     }
     if (empty($user)) {
         $user = $this->getUser();
         if (empty($user)) {
             return;
         }
     }
     $userIds = $this->extendedMetadataFactory->getDoctrineMetadata($user)->getIdentifierValues($user);
     $userId = reset($userIds);
     if (empty($userId)) {
         throw new UserException('User ID is empty.');
     }
     foreach (array_combine($qb->getRootAliases(), $qb->getRootEntities()) as $alias => $entity) {
         $meta = $this->extendedMetadataFactory->getExtendedMetadata($entity)['user'];
         if (empty($meta)) {
             continue;
         }
         $filter = false;
         foreach ($meta['roles'] as $role) {
             if ($this->authorizationChecker->isGranted($role)) {
                 $filter = true;
                 break;
             }
         }
         if (!$filter) {
             continue;
         }
         $key = $meta['property'] . '_id';
         $qb->innerJoin(sprintf('%s.%s', $alias, $meta['property']), $meta['property'])->andWhere(sprintf('%s = :%s', $meta['property'], $key))->setParameter($key, $userId);
     }
 }
 /**
  * @param array    $queriesMap           Queries map
  * @param callable $queryBuilderCallback Callback to process query builder
  *
  * @return array
  * @throws \Darvin\Utils\CustomObject\CustomObjectException
  */
 private function fetchCustomEntities(array $queriesMap, callable $queryBuilderCallback = null)
 {
     foreach ($queriesMap as $customEntityClass => &$initProperties) {
         $customEntityDoctrineMeta = $this->extendedMetadataFactory->getDoctrineMetadata($customEntityClass);
         foreach ($initProperties as $initProperty => &$initPropertyValues) {
             if (!$customEntityDoctrineMeta->hasField($initProperty) && !$customEntityDoctrineMeta->hasAssociation($initProperty)) {
                 throw new CustomObjectException(sprintf('Property "%s::$%s" is not mapped field or association.', $customEntityClass, $initProperty));
             }
             $customEntityRepository = $this->em->getRepository($customEntityClass);
             if (1 === count($initPropertyValues)) {
                 $initPropertyValue = reset($initPropertyValues);
                 $qb = $customEntityRepository->createQueryBuilder('o')->andWhere(sprintf('o.%s = :%1$s', $initProperty))->setParameter($initProperty, $initPropertyValue);
                 if (!empty($queryBuilderCallback)) {
                     $queryBuilderCallback($qb);
                 }
                 try {
                     $customEntity = $qb->getQuery()->getOneOrNullResult();
                 } catch (NonUniqueResultException $ex) {
                     throw new CustomObjectException(sprintf('Unable to fetch custom entity "%s" by %s "%s": entity is not unique.', $customEntityRepository->getClassName(), $initProperty, $initPropertyValue));
                 }
                 if (!empty($customEntity)) {
                     $initPropertyValues[$initPropertyValue] = $customEntity;
                     continue;
                 }
                 unset($initPropertyValues[$initPropertyValue]);
                 continue;
             }
             $qb = $customEntityRepository->createQueryBuilder('o');
             $qb->where($qb->expr()->in('o.' . $initProperty, $initPropertyValues));
             if (!empty($queryBuilderCallback)) {
                 $queryBuilderCallback($qb);
             }
             $customEntities = $qb->getQuery()->getResult();
             /** @var callable $getPropertyValueCallback */
             $getPropertyValueCallback = [$this, 'getPropertyValue'];
             $customEntities = array_combine(array_map(function ($customEntity) use($getPropertyValueCallback, $initProperty) {
                 return $getPropertyValueCallback($customEntity, $initProperty);
             }, $customEntities), $customEntities);
             foreach ($initPropertyValues as &$initPropertyValue) {
                 if (isset($customEntities[$initPropertyValue])) {
                     $initPropertyValue = $customEntities[$initPropertyValue];
                     continue;
                 }
                 unset($initPropertyValues[$initPropertyValue]);
             }
             unset($initPropertyValue);
         }
         unset($initPropertyValues);
     }
     unset($initProperties);
     return $queriesMap;
 }