/** * @param StaticSegment $staticSegment * * {@inheritdoc} */ protected function createSubordinateIterator($staticSegment) { $this->assertRequiredDependencies(); if (!$staticSegment->getExtendedMergeVars()) { return new \EmptyIterator(); } $qb = $this->getIteratorQueryBuilder($staticSegment); $marketingList = $staticSegment->getMarketingList(); $memberIdentifier = MarketingListQueryBuilderAdapter::MEMBER_ALIAS . '.id'; $fieldExpr = $this->fieldHelper->getFieldExpr($marketingList->getEntity(), $qb, $this->doctrineHelper->getSingleEntityIdentifierFieldName($marketingList->getEntity())); $qb->addSelect($fieldExpr . ' AS entity_id'); $qb->addSelect($memberIdentifier . ' AS member_id'); $qb->andWhere($qb->expr()->andX($qb->expr()->isNotNull($memberIdentifier))); $bufferedIterator = new BufferedQueryResultIterator($qb); $bufferedIterator->setHydrationMode(AbstractQuery::HYDRATE_ARRAY)->setReverse(true); $uniqueMembers =& $this->uniqueMembers; return new \CallbackFilterIterator($bufferedIterator, function (&$current) use($staticSegment, &$uniqueMembers) { if (is_array($current)) { if (!empty($current['member_id']) && in_array($current['member_id'], $uniqueMembers, true)) { return false; } $current['subscribersList_id'] = $staticSegment->getSubscribersList()->getId(); $current['static_segment_id'] = $staticSegment->getId(); $uniqueMembers[] = $current['member_id']; unset($current['id']); } return true; }); }
/** * @param object $entity * @return object|null */ public function discoverSimilar($entity) { if (!$this->configuration) { return null; } $idName = $this->doctrineHelper->getSingleEntityIdentifierFieldName($this->discoveryEntityClass); $idFieldName = self::ROOT_ALIAS . '.' . $idName; /** @var EntityRepository $repository */ $repository = $this->doctrineHelper->getEntityRepository($this->discoveryEntityClass); $qb = $repository->createQueryBuilder(self::ROOT_ALIAS)->select(self::ROOT_ALIAS); // Apply search strategies $this->applyStrategies($qb, $entity); // Apply matcher strategy if ($this->configuration[Configuration::DISCOVERY_OPTIONS_KEY][Configuration::DISCOVERY_MATCH_KEY] === Configuration::DISCOVERY_MATCH_LATEST) { $qb->orderBy($idFieldName, Criteria::DESC); } // Skip current entity $id = $this->doctrineHelper->getSingleEntityIdentifier($entity); if (!empty($id)) { $idParameter = ':' . $idName; $qb->andWhere($qb->expr()->neq($idFieldName, $idParameter))->setParameter($idParameter, $id); } // Add organization limits $organizationField = $this->ownershipMetadata->getMetadata(ClassUtils::getClass($entity))->getOrganizationFieldName(); if ($organizationField) { $propertyAccessor = PropertyAccess::createPropertyAccessor(); $organization = $propertyAccessor->getValue($entity, $organizationField); $qb->andWhere(sprintf('%s.%s = :organization', self::ROOT_ALIAS, $organizationField))->setParameter('organization', $organization); } // Get only 1 match $qb->setMaxResults(1); return $qb->getQuery()->getOneOrNullResult(); }
/** * {@inheritdoc} */ public function batchUpdate(MassActionInterface $massAction, IterableResultInterface $results, array $data) { $this->entityName = $massAction->getOptions()->offsetGet('entityName'); $this->fieldName = empty($data['mass_edit_field']) ? null : $data['mass_edit_field']; if (empty($this->fieldName)) { throw new \RuntimeException("Field name was not specified with option 'mass_edit_field'"); } $this->identifierName = $this->doctrineHelper->getSingleEntityIdentifierFieldName($this->entityName); $value = $data[$this->fieldName]; $selectedIds = []; $entitiesCount = 0; $iteration = 0; $this->entityManager = $this->doctrineHelper->getEntityManager($this->entityName); $this->entityManager->beginTransaction(); try { set_time_limit(0); foreach ($results as $result) { /** @var $result ResultRecordInterface */ $selectedIds[] = $result->getValue($this->identifierName); $iteration++; if ($iteration % $this->batchSize == 0) { $entitiesCount += $this->finishBatch($selectedIds, $value); } } if ($iteration % $this->batchSize > 0) { $entitiesCount += $this->finishBatch($selectedIds, $value); } $this->entityManager->commit(); } catch (\Exception $e) { $this->entityManager->rollback(); throw $e; } return $entitiesCount; }
/** * @param MarketingList $marketingList * @param array $result * @return MarketingListItem */ public function contactResultRow(MarketingList $marketingList, array $result) { $idName = $this->doctrineHelper->getSingleEntityIdentifierFieldName($marketingList->getEntity()); if (empty($result[$idName])) { throw new \InvalidArgumentException('Result row must contain identifier field'); } return $this->contact($marketingList, $result[$idName]); }
/** * {@inheritdoc} */ public function onBuildBefore(BuildBefore $event) { $datagrid = $event->getDatagrid(); list($entityName, $alias) = $this->getEntityNameWithAlias($datagrid); $alias = $alias ?: 'e'; if (!$this->isApplicable($event, $entityName)) { return; } // configure mass action $event->getConfig()->offsetSetByPath(sprintf(self::ACTION_CONFIGURATION_KEY, MassUpdateActionHandler::ACTION_NAME), ['type' => 'window', 'frontend_type' => 'update-mass', 'route' => 'oro_datagrid_mass_action', 'dialogWindowOptions' => ['route' => 'trustify_mass_update', 'route_parameters' => ['entityName' => str_replace('\\', '_', $entityName)]], 'data_identifier' => $alias . '.' . $this->doctrineHelper->getSingleEntityIdentifierFieldName($entityName), 'handler' => MassUpdateActionHandler::SERVICE_ID, 'label' => 'trustify.mass_update.dialog.title', 'success_message' => 'trustify.mass_update.success_message', 'error_message' => 'trustify.mass_update.error_message']); }
/** * {@inheritdoc} */ protected function getSerializationConfig() { $config = ['fields' => ['owner' => ['fields' => 'id'], 'organization' => ['fields' => 'name'], 'file' => ['fields' => 'id']], 'post_serialize' => function (array &$result) { $this->postSerializeAttachment($result); }]; $attachmentTargets = $this->getAttachmentTargets(); foreach ($attachmentTargets as $targetClass => $fieldName) { $config['fields'][$fieldName] = ['fields' => $this->doctrineHelper->getSingleEntityIdentifierFieldName($targetClass)]; } return $config; }
/** * @param array $item * @return QueryBuilder */ protected function createQueryBuilder(array $item) { $em = $this->doctrineHelper->getEntityManager($this->entityName); $identifierFieldName = $this->doctrineHelper->getSingleEntityIdentifierFieldName($this->entityName); $qb = $em->createQueryBuilder(); $qb->select('COUNT(e.' . $identifierFieldName . ') as itemsCount')->from($this->entityName, 'e'); if (array_key_exists($this->field, $item)) { $qb->andWhere($qb->expr()->notIn('e.' . $this->field, ':items'))->setParameter('items', (array) $item[$this->field]); } // Workaround to limit by channel. Channel is not available in second step context. if (array_key_exists('channel', $item)) { $qb->andWhere($qb->expr()->eq('e.channel', ':channel'))->setParameter('channel', $item['channel']); } return $qb; }
/** * Adds filter by $entity DQL to the given query builder * * @param QueryBuilder $qb The query builder that is used to get the list of activities * @param string $entityClass The target entity class * @param mixed $entityId The target entity id * @param string|null $activityEntityClass This parameter should be specified * if the query has more than one root entity * * @throws \RuntimeException */ public function addFilterByTargetEntity(QueryBuilder $qb, $entityClass, $entityId, $activityEntityClass = null) { $activityEntityAlias = null; $rootEntities = $qb->getRootEntities(); if (empty($rootEntities)) { throw new \RuntimeException('The query must have at least one root entity.'); } if (empty($activityEntityClass)) { if (count($rootEntities) > 1) { throw new \RuntimeException('The $activityEntityClass must be specified if the query has several root entities.'); } $activityEntityClass = $rootEntities[0]; $activityEntityAlias = $qb->getRootAliases()[0]; } else { $normalizedActivityEntityClass = ClassUtils::getRealClass($this->entityClassResolver->getEntityClass($activityEntityClass)); foreach ($rootEntities as $i => $className) { $className = $this->entityClassResolver->getEntityClass($className); if ($className === $normalizedActivityEntityClass) { $activityEntityAlias = $qb->getRootAliases()[$i]; break; } } if (empty($activityEntityAlias)) { throw new \RuntimeException(sprintf('The "%s" must be the root entity.', $activityEntityClass)); } } $activityIdentifierFieldName = $this->doctrineHelper->getSingleEntityIdentifierFieldName($activityEntityClass); $targetIdentifierFieldName = $this->doctrineHelper->getSingleEntityIdentifierFieldName($entityClass); $filterQuery = $qb->getEntityManager()->createQueryBuilder()->select(sprintf('filterActivityEntity.%s', $activityIdentifierFieldName))->from($activityEntityClass, 'filterActivityEntity')->innerJoin(sprintf('filterActivityEntity.%s', ExtendHelper::buildAssociationName($entityClass, ActivityScope::ASSOCIATION_KIND)), 'filterTargetEntity')->where(sprintf('filterTargetEntity.%s = :targetEntityId', $targetIdentifierFieldName))->getQuery(); $qb->andWhere($qb->expr()->in(sprintf('%s.%s', $activityEntityAlias, $activityIdentifierFieldName), $filterQuery->getDQL()))->setParameter('targetEntityId', $entityId); }
/** * @param DatagridConfiguration $config * * @return string */ protected function getDataIdentifier(DatagridConfiguration $config) { $entity = $this->getEntity($config); $identifier = $this->doctrineHelper->getSingleEntityIdentifierFieldName($entity); $rootAlias = $this->gridConfigurationHelper->getEntityRootAlias($config); return sprintf('%s.%s', $rootAlias, $identifier); }
/** * @expectedException \Oro\Bundle\EntityBundle\Exception\InvalidEntityException * @expectedExceptionMessage Can't get single identifier field name for the entity */ public function testGetSingleEntityIdentifierIncorrectIdentifierFieldName() { $identifiers = array('key1' => 'value1', 'key2' => 'value2'); $entity = new ItemStubProxy(); $class = 'ItemStubProxy'; $this->classMetadata->expects($this->any())->method('getIdentifierFieldNames')->will($this->returnValue(array_keys($identifiers))); $this->em->expects($this->once())->method('getClassMetadata')->with($class)->will($this->returnValue($this->classMetadata)); $this->registry->expects($this->once())->method('getManagerForClass')->with($class)->will($this->returnValue($this->em)); $this->doctrineHelper->getSingleEntityIdentifierFieldName($entity); }
/** * @param OrmDatasource $dataSource * @param string $scope * @return array */ protected function getAllEntityIds(OrmDatasource $dataSource, $scope) { $permission = EntityPaginationManager::getPermission($scope); $entityName = $this->getEntityName($dataSource); $entityIdentifier = $this->doctrineHelper->getSingleEntityIdentifierFieldName($entityName); $queryBuilder = $dataSource->getQueryBuilder(); $queryBuilder->setFirstResult(0); $queryBuilder->setMaxResults($this->getEntitiesLimit()); $query = $this->aclHelper->apply($queryBuilder, $permission); $results = $query->execute(); $entityIds = []; foreach ($results as $result) { $record = new ResultRecord($result); $entityIds[] = $record->getValue($entityIdentifier); } return $entityIds; }
/** * Returns a query builder that could be used for fetching the list of entities * associated with $associationOwnerClass entities found by $filters and $joins * * @param string $associationTargetClass The FQCN of the entity that is the owning side of the association * @param mixed|null $filters Criteria is used to filter entities which are association owners * e.g. ['age' => 20, ...] or \Doctrine\Common\Collections\Criteria * @param array|null $joins Additional associations required to filter owning side entities * @param array $associationOwners The list of fields responsible to store associations between * the given target and association owners * Array format: [owner_entity_class => field_name] * @param int $limit The maximum number of items per page * @param int $page The page number * @param string|null $orderBy The ordering expression for the result * * @return SqlQueryBuilder */ public function getMultiAssociationOwnersQueryBuilder($associationTargetClass, $filters, $joins, $associationOwners, $limit = null, $page = null, $orderBy = null) { $em = $this->doctrineHelper->getEntityManager($associationTargetClass); $criteria = $this->doctrineHelper->normalizeCriteria($filters); $selectStmt = null; $subQueries = []; $targetIdFieldName = $this->doctrineHelper->getSingleEntityIdentifierFieldName($associationTargetClass); foreach ($associationOwners as $ownerClass => $fieldName) { // dispatch oro_api.request.get_list.before event $event = new GetListBefore($this->cloneCriteria($criteria), $associationTargetClass); $this->eventDispatcher->dispatch(GetListBefore::NAME, $event); $subCriteria = $event->getCriteria(); $nameExpr = $this->entityNameResolver->getNameDQL($ownerClass, 'e'); $subQb = $em->getRepository($ownerClass)->createQueryBuilder('e')->select(sprintf('target.%s AS id, e.id AS entityId, \'%s\' AS entityClass, ' . ($nameExpr ?: '\'\'') . ' AS entityTitle', $targetIdFieldName, str_replace('\'', '\'\'', $ownerClass)))->innerJoin('e.' . $fieldName, 'target'); $this->doctrineHelper->applyJoins($subQb, $joins); // fix of doctrine error with Same Field, Multiple Values, Criteria and QueryBuilder // http://www.doctrine-project.org/jira/browse/DDC-2798 // TODO revert changes when doctrine version >= 2.5 in scope of BAP-5577 QueryBuilderHelper::addCriteria($subQb, $subCriteria); // $subQb->addCriteria($criteria); $subQuery = $subQb->getQuery(); $subQueries[] = QueryUtils::getExecutableSql($subQuery); if (empty($selectStmt)) { $mapping = QueryUtils::parseQuery($subQuery)->getResultSetMapping(); $selectStmt = sprintf('entity.%s AS id, entity.%s AS entity, entity.%s AS title', QueryUtils::getColumnNameByAlias($mapping, 'entityId'), QueryUtils::getColumnNameByAlias($mapping, 'entityClass'), QueryUtils::getColumnNameByAlias($mapping, 'entityTitle')); } } $rsm = new ResultSetMapping(); $rsm->addScalarResult('id', 'id', Type::INTEGER)->addScalarResult('entity', 'entity')->addScalarResult('title', 'title'); $qb = new SqlQueryBuilder($em, $rsm); $qb->select($selectStmt)->from('(' . implode(' UNION ALL ', $subQueries) . ')', 'entity'); if (null !== $limit) { $qb->setMaxResults($limit); if (null !== $page) { $qb->setFirstResult($this->doctrineHelper->getPageOffset($page, $limit)); } } if ($orderBy) { $qb->orderBy($orderBy); } return $qb; }
/** * @param Channel $channel * @param array $ids * @return \ArrayIterator|BufferedQueryResultIterator */ protected function getEntityIdsByChannel(Channel $channel, array $ids = []) { $entityFQCN = $channel->getCustomerIdentity(); $qb = $this->doctrineHelper->getEntityRepository($entityFQCN)->createQueryBuilder('e'); $metadata = $this->doctrineHelper->getEntityMetadataForClass($entityFQCN); $metrics = []; foreach ($this->providers as $provider) { if ($provider->supports($channel) && $metadata->hasField($provider->getType())) { $metrics[] = $provider->getType(); } } if (count($metrics) === 0) { return new \ArrayIterator(); } $idField = sprintf('e.%s', $this->doctrineHelper->getSingleEntityIdentifierFieldName($entityFQCN)); $qb->select(preg_filter('/^/', 'e.', $metrics))->addSelect($idField . ' as id')->where('e.dataChannel = :dataChannel')->orderBy($qb->expr()->asc($idField))->setParameter('dataChannel', $channel); if (count($ids) !== 0) { $qb->andWhere($qb->expr()->in($idField, ':ids'))->setParameter('ids', $ids); } return (new BufferedQueryResultIterator($qb))->setBufferSize(self::BATCH_SIZE); }
/** * Returns a query builder that could be used for fetching the list of owner side entities * the specified $associationTargetClass associated with. * The $filters and $joins could be used to filter entities * * The resulting query would be something like this: * <code> * SELECT entity.entityId AS id, entity.entityClass AS entity, entity.entityTitle AS title FROM ( * SELECT [DISTINCT] * target.id AS id, * e.id AS entityId, * {first_owner_entity_class} AS entityClass, * {first_owner_title} AS entityTitle * FROM {first_owner_entity_class} AS e * INNER JOIN e.{target_field_name_for_first_owner} AS target * {joins} * WHERE {filters} * UNION ALL * SELECT [DISTINCT] * target.id AS id, * e.id AS entityId, * {second_owner_entity_class} AS entityClass, * {second_owner_title} AS entityTitle * FROM {second_owner_entity_class} AS e * INNER JOIN e.{target_field_name_for_second_owner} AS target * {joins} * WHERE {filters} * UNION ALL * ... select statements for other owners * ) entity * ORDER BY {orderBy} * LIMIT {limit} OFFSET {(page - 1) * limit} * </code> * * @param string $associationTargetClass The FQCN of the entity that is the target side of the association * @param mixed|null $filters Criteria is used to filter entities which are association owners * e.g. ['age' => 20, ...] or \Doctrine\Common\Collections\Criteria * @param array|null $joins Additional associations required to filter owning side entities * @param array $associationOwners The list of fields responsible to store associations between * the given target and association owners * Array format: [owner_entity_class => field_name] * @param int|null $limit The maximum number of items per page * @param int|null $page The page number * @param string|null $orderBy The ordering expression for the result * @param callable|null $callback A callback function which can be used to modify child queries * function (QueryBuilder $qb, $ownerEntityClass) * * @return SqlQueryBuilder */ public function getMultiAssociationOwnersQueryBuilder($associationTargetClass, $filters, $joins, $associationOwners, $limit = null, $page = null, $orderBy = null, $callback = null) { $em = $this->doctrineHelper->getEntityManager($associationTargetClass); $criteria = QueryUtils::normalizeCriteria($filters); $selectStmt = null; $subQueries = []; $targetIdFieldName = $this->doctrineHelper->getSingleEntityIdentifierFieldName($associationTargetClass); foreach ($associationOwners as $ownerClass => $fieldName) { $nameExpr = $this->entityNameResolver->getNameDQL($ownerClass, 'e'); $subQb = $em->getRepository($ownerClass)->createQueryBuilder('e')->select(sprintf('target.%s AS id, e.id AS entityId, \'%s\' AS entityClass, ' . ($nameExpr ?: '\'\'') . ' AS entityTitle', $targetIdFieldName, str_replace('\'', '\'\'', $ownerClass)))->innerJoin('e.' . $fieldName, 'target'); QueryUtils::applyJoins($subQb, $joins); $subQb->addCriteria($criteria); if (null !== $callback && is_callable($callback)) { call_user_func($callback, $subQb, $ownerClass); } $subQuery = $this->getAclHelper()->apply($subQb); $subQueries[] = QueryUtils::getExecutableSql($subQuery); if (empty($selectStmt)) { $mapping = QueryUtils::parseQuery($subQuery)->getResultSetMapping(); $selectStmt = sprintf('entity.%s AS id, entity.%s AS entity, entity.%s AS title', QueryUtils::getColumnNameByAlias($mapping, 'entityId'), QueryUtils::getColumnNameByAlias($mapping, 'entityClass'), QueryUtils::getColumnNameByAlias($mapping, 'entityTitle')); } } $rsm = new ResultSetMapping(); $rsm->addScalarResult('id', 'id', Type::INTEGER)->addScalarResult('entity', 'entity')->addScalarResult('title', 'title'); $qb = new SqlQueryBuilder($em, $rsm); $qb->select($selectStmt)->from('(' . implode(' UNION ALL ', $subQueries) . ')', 'entity'); if (null !== $limit) { $qb->setMaxResults($limit); if (null !== $page) { $qb->setFirstResult(QueryUtils::getPageOffset($page, $limit)); } } if ($orderBy) { $qb->orderBy($orderBy); } return $qb; }
/** * {@inheritdoc} */ public function getVirtualFieldQuery($className, $fieldName) { return ['select' => ['expr' => 'entity.' . $this->doctrineHelper->getSingleEntityIdentifierFieldName($className), 'label' => 'oro.tag.entity_plural_label', 'return_type' => 'tag', 'related_entity_name' => 'Oro\\Bundle\\TagBundle\\Entity\\Tag']]; }
/** * @param string $className * * @return array */ protected function getRelationDefinition($className) { return ['label' => 'oro.tag.entity_plural_label', 'relation_type' => 'ManyToMany', 'related_entity_name' => 'Oro\\Bundle\\TagBundle\\Entity\\Tag', 'target_join_alias' => self::TARGET_ALIAS, 'query' => ['join' => ['left' => [['join' => 'Oro\\Bundle\\TagBundle\\Entity\\Tagging', 'alias' => 'virtualTagging', 'conditionType' => Join::WITH, 'condition' => sprintf('(virtualTagging.entityName = \'%s\' and virtualTagging.recordId = entity.%s)', $className, $this->doctrineHelper->getSingleEntityIdentifierFieldName($className))], ['join' => 'virtualTagging.tag', 'alias' => self::TARGET_ALIAS]]]]]; }
/** * @param string $entityName * @return string */ public function getIdentifierFieldName($entityName) { return $this->doctrineHelper->getSingleEntityIdentifierFieldName($entityName); }
/** * Returns query builder that could be used for fetching entity by its id * * @param mixed $id The id of an entity * * @return QueryBuilder */ public function getItemQueryBuilder($id) { return $this->getRepository()->createQueryBuilder('e')->where(sprintf('e.%s = :id', $this->doctrineHelper->getSingleEntityIdentifierFieldName($this->class)))->setParameter('id', $id); }
/** * @param string $className * @return array */ public function getRelationDefinition($className) { $idField = $this->doctrineHelper->getSingleEntityIdentifierFieldName($className); return ['label' => 'orocrm.marketinglist.entity_label', 'relation_type' => 'oneToMany', 'related_entity_name' => 'OroCRM\\Bundle\\MarketingListBundle\\Entity\\MarketingList', 'query' => ['join' => ['left' => [['join' => 'OroCRMMarketingListBundle:MarketingList', 'alias' => self::RELATION_NAME, 'conditionType' => Join::WITH, 'condition' => self::RELATION_NAME . ".entity = '{$className}'"], ['join' => 'OroCRMMarketingListBundle:MarketingListItem', 'alias' => self::MARKETING_LIST_ITEM_RELATION_NAME, 'conditionType' => Join::WITH, 'condition' => self::MARKETING_LIST_ITEM_RELATION_NAME . '.marketingList = ' . self::RELATION_NAME . ' AND entity.' . $idField . ' = ' . self::MARKETING_LIST_ITEM_RELATION_NAME . '.entityId']]]]]; }