public function mapFields(Content $content, $languageCode) { $fields = []; $contentType = $this->contentTypeHandler->load($content->versionInfo->contentInfo->contentTypeId); foreach ($content->fields as $field) { if ($field->languageCode !== $languageCode) { continue; } foreach ($contentType->fieldDefinitions as $fieldDefinition) { if ($fieldDefinition->id !== $field->fieldDefinitionId) { continue; } $fieldType = $this->fieldRegistry->getType($field->type); $indexFields = $fieldType->getIndexData($field, $fieldDefinition); foreach ($indexFields as $indexField) { if ($indexField->value === null) { continue; } $documentField = new Field($name = $this->fieldNameGenerator->getName($indexField->name, $fieldDefinition->identifier, $contentType->identifier), $indexField->value, $indexField->type); $this->appendField($fields, $fieldDefinition, $documentField); } } } return $fields; }
/** * @covers \Netgen\TagsBundle\Core\Search\Solr\Query\Content\CriterionVisitor\Tags\TagKeyword::visit * @covers \Netgen\TagsBundle\Core\Search\Solr\Query\Content\CriterionVisitor\Tags::getTargetFieldNames */ public function testVisitWithoutTarget() { $criterion = new Criterion\TagKeyword(Operator::IN, array('tag1', 'tag2')); $this->contentTypeHandler->expects($this->once())->method('getSearchableFieldMap')->will($this->returnValue(array('news' => array('tags_field' => array('field_type_identifier' => 'eztags')), 'article' => array('tags_field2' => array('field_type_identifier' => 'eztags'))))); $this->fieldNameResolver->expects($this->at(0))->method('getFieldNames')->with($this->equalTo($criterion), $this->equalTo('tags_field'), 'eztags', 'tag_keywords')->will($this->returnValue(array('news_tags_field_s'))); $this->fieldNameResolver->expects($this->at(1))->method('getFieldNames')->with($this->equalTo($criterion), $this->equalTo('tags_field2'), 'eztags', 'tag_keywords')->will($this->returnValue(array('article_tags_field2_s'))); $this->assertEquals('(news_tags_field_s:"tag1" OR article_tags_field2_s:"tag1" OR news_tags_field_s:"tag2" OR article_tags_field2_s:"tag2")', $this->visitor->visit($criterion)); }
/** * Generate query expression for a Criterion this handler accepts. * * accept() must be called before calling this method. * * @param \eZ\Publish\Core\Search\Legacy\Content\Common\Gateway\CriteriaConverter $converter * @param \eZ\Publish\Core\Persistence\Database\SelectQuery $query * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion * * @return \eZ\Publish\Core\Persistence\Database\Expression */ public function handle(CriteriaConverter $converter, SelectQuery $query, Criterion $criterion) { $idList = array(); foreach ($criterion->value as $identifier) { $idList[] = $this->contentTypeHandler->loadByIdentifier($identifier)->id; } return $query->expr->in($this->dbHandler->quoteColumn('contentclass_id', 'ezcontentobject'), $idList); }
public function mapFields(Content $content) { $versionInfo = $content->versionInfo; $contentInfo = $content->versionInfo->contentInfo; // UserGroups and Users are Content, but permissions cascade is achieved through // Locations hierarchy. We index all ancestor Location Content ids of all // Locations of an owner. $ancestorLocationsContentIds = $this->getAncestorLocationsContentIds($contentInfo->ownerId); // Add owner user id as it can also be considered as user group. $ancestorLocationsContentIds[] = $contentInfo->ownerId; $section = $this->sectionHandler->load($contentInfo->sectionId); return [new Field('content_id', $contentInfo->id, new FieldType\IdentifierField()), new Field('content_type_id', $contentInfo->contentTypeId, new FieldType\IdentifierField()), new Field('content_version_no', $versionInfo->versionNo, new FieldType\IntegerField()), new Field('content_version_status', $versionInfo->status, new FieldType\IdentifierField()), new Field('content_name', $contentInfo->name, new FieldType\StringField()), new Field('content_version_creator_user_id', $versionInfo->creatorId, new FieldType\IdentifierField()), new Field('content_owner_user_id', $contentInfo->ownerId, new FieldType\IdentifierField()), new Field('content_section_id', $contentInfo->sectionId, new FieldType\IdentifierField()), new Field('content_remote_id', $contentInfo->remoteId, new FieldType\IdentifierField()), new Field('content_modification_date', $contentInfo->modificationDate, new FieldType\DateField()), new Field('content_publication_date', $contentInfo->publicationDate, new FieldType\DateField()), new Field('content_language_codes', array_keys($versionInfo->names), new FieldType\MultipleStringField()), new Field('content_main_language_code', $contentInfo->mainLanguageCode, new FieldType\StringField()), new Field('content_always_available', $contentInfo->alwaysAvailable, new FieldType\BooleanField()), new Field('content_owner_user_group_ids', $ancestorLocationsContentIds, new FieldType\MultipleIdentifierField()), new Field('content_section_identifier', $section->identifier, new FieldType\IdentifierField()), new Field('content_section_name', $section->name, new FieldType\StringField()), new Field('content_type_group_ids', $this->contentTypeHandler->load($contentInfo->contentTypeId)->groupIds, new FieldType\MultipleIdentifierField()), new Field('content_object_state_ids', $this->getObjectStateIds($contentInfo->id), new FieldType\MultipleIdentifierField())]; }
/** * Map field value to a proper Elasticsearch filter representation. * * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion * @param \eZ\Publish\Core\Search\Elasticsearch\Content\CriterionVisitorDispatcher $dispatcher * @param array $languageFilter * * @return mixed */ public function visitFilter(Criterion $criterion, Dispatcher $dispatcher, array $languageFilter) { if (count($criterion->value) > 1) { $idList = array(); foreach ($criterion->value as $identifier) { $idList[] = $this->contentTypeHandler->loadByIdentifier($identifier)->id; } $filter = array('terms' => array('type_id' => $idList)); } else { $filter = array('term' => array('type_id' => $this->contentTypeHandler->loadByIdentifier($criterion->value[0])->id)); } return $filter; }
/** * Rollback transaction. * * Rollback transaction, or throw exceptions if no transactions has been started. * * @throws \RuntimeException If no transaction has been started */ public function rollback() { try { $this->dbHandler->rollback(); // Clear all caches after rollback if ($this->contentTypeHandler instanceof CachingContentTypeHandler) { $this->contentTypeHandler->clearCache(); } if ($this->languageHandler instanceof CachingLanguageHandler) { $this->languageHandler->clearCache(); } } catch (Exception $e) { throw new RuntimeException($e->getMessage(), 0, $e); } }
/** * Get field type information * * Returns an array in the form: * * <code> * array( * "content-type-identifier" => array( * "field-definition-identifier" => "field-type-identifier", * … * ), * … * ) * </code> * * @return array */ protected function getFieldMap() { $fieldTypes = []; foreach ($this->contentTypeHandler->loadAllGroups() as $group) { foreach ($this->contentTypeHandler->loadContentTypes($group->id) as $contentType) { foreach ($contentType->fieldDefinitions as $fieldDefinition) { if (!$fieldDefinition->isSearchable) { continue; } $fieldTypes[$contentType->identifier][$fieldDefinition->identifier] = $fieldDefinition->fieldType; } } } return $fieldTypes; }
protected function mapLocationFields(Location $location, Content $content, Section $section) { $fields = array(new Field('location', $location->id, new FieldType\IdentifierField()), new Field('document_type', self::DOCUMENT_TYPE_IDENTIFIER_LOCATION, new FieldType\IdentifierField()), new Field('priority', $location->priority, new FieldType\IntegerField()), new Field('hidden', $location->hidden, new FieldType\BooleanField()), new Field('invisible', $location->invisible, new FieldType\BooleanField()), new Field('remote_id', $location->remoteId, new FieldType\IdentifierField()), new Field('parent_id', $location->parentId, new FieldType\IdentifierField()), new Field('path_string', $location->pathString, new FieldType\IdentifierField()), new Field('depth', $location->depth, new FieldType\IntegerField()), new Field('sort_field', $location->sortField, new FieldType\IdentifierField()), new Field('sort_order', $location->sortOrder, new FieldType\IdentifierField()), new Field('is_main_location', $location->id == $content->versionInfo->contentInfo->mainLocationId, new FieldType\BooleanField())); // UserGroups and Users are Content, but permissions cascade is achieved through // Locations hierarchy. We index all ancestor Location Content ids of all // Locations of an owner. $ancestorLocationsContentIds = $this->getAncestorLocationsContentIds($content->versionInfo->contentInfo->ownerId); // Add owner user id as it can also be considered as user group. $ancestorLocationsContentIds[] = $content->versionInfo->contentInfo->ownerId; $fields[] = new Field('content_owner_user_group', $ancestorLocationsContentIds, new FieldType\MultipleIdentifierField()); $fields[] = new Field('content_id', $content->versionInfo->contentInfo->id, new FieldType\IdentifierField()); $fields[] = new Field('content_type', $content->versionInfo->contentInfo->contentTypeId, new FieldType\IdentifierField()); $fields[] = new Field('content_version_no', $content->versionInfo->versionNo, new FieldType\IntegerField()); $fields[] = new Field('content_status', $content->versionInfo->status, new FieldType\IdentifierField()); $fields[] = new Field('content_name', $content->versionInfo->contentInfo->name, new FieldType\StringField()); $fields[] = new Field('content_creator', $content->versionInfo->creatorId, new FieldType\IdentifierField()); $fields[] = new Field('content_owner', $content->versionInfo->contentInfo->ownerId, new FieldType\IdentifierField()); $fields[] = new Field('content_section', $content->versionInfo->contentInfo->sectionId, new FieldType\IdentifierField()); $fields[] = new Field('content_section_identifier', $section->identifier, new FieldType\IdentifierField()); $fields[] = new Field('content_section_name', $section->name, new FieldType\StringField()); $fields[] = new Field('content_remote_id', $content->versionInfo->contentInfo->remoteId, new FieldType\IdentifierField()); $fields[] = new Field('content_modified', $content->versionInfo->contentInfo->modificationDate, new FieldType\DateField()); $fields[] = new Field('content_published', $content->versionInfo->contentInfo->publicationDate, new FieldType\DateField()); $fields[] = new Field('language_code', array_keys($content->versionInfo->names), new FieldType\MultipleStringField()); $fields[] = new Field('content_always_available', $content->versionInfo->contentInfo->alwaysAvailable, new FieldType\BooleanField()); $fields[] = new Field('content_group', $this->contentTypeHandler->load($content->versionInfo->contentInfo->contentTypeId)->groupIds, new FieldType\MultipleIdentifierField()); $fields[] = new Field('content_object_state', $this->getObjectStateIds($content->versionInfo->contentInfo->id), new FieldType\MultipleIdentifierField()); return $fields; }
/** * Returns an array of FullTextValue object containing searchable values of content object * fields for the given $content. * * @param \eZ\Publish\SPI\Persistence\Content $content * * @return \eZ\Publish\Core\Search\Legacy\Content\FullTextValue[] */ protected function getFullTextValues(Content $content) { $fullTextValues = []; foreach ($content->fields as $field) { $fieldDefinition = $this->contentTypeHandler->getFieldDefinition($field->fieldDefinitionId, Content\Type::STATUS_DEFINED); if (!$fieldDefinition->isSearchable) { continue; } $value = $this->getFullTextFieldValue($field, $fieldDefinition); if (empty($value)) { continue; } $fullTextValues[] = new FullTextValue(['id' => $field->id, 'fieldDefinitionId' => $field->fieldDefinitionId, 'fieldDefinitionIdentifier' => $fieldDefinition->identifier, 'languageCode' => $field->languageCode, 'value' => !is_array($value) ? $value : implode(' ', $value)]); } return $fullTextValues; }
/** * @see \eZ\Publish\SPI\Persistence\Content\Type\Handler::getSearchableFieldMap */ public function getSearchableFieldMap() { if ($this->searchableFieldMap !== null) { return $this->searchableFieldMap; } return $this->searchableFieldMap = $this->innerHandler->getSearchableFieldMap(); }
/** * Copy Content with Fields and Versions from $contentId in $version. * * Copies all fields from $contentId in $versionNo (or all versions if null) * to a new object which is returned. Version numbers are maintained. * * @todo Should relations be copied? Which ones? * * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If content or version is not found * * @param mixed $contentId * @param mixed|null $versionNo Copy all versions if left null * * @return \eZ\Publish\SPI\Persistence\Content */ public function copy($contentId, $versionNo = null) { $currentVersionNo = isset($versionNo) ? $versionNo : $this->loadContentInfo($contentId)->currentVersionNo; // Copy content in given version or current version $createStruct = $this->mapper->createCreateStructFromContent($this->load($contentId, $currentVersionNo)); $content = $this->internalCreate($createStruct, $currentVersionNo); $contentType = $this->contentTypeHandler->load($createStruct->typeId); // If version was not passed also copy other versions if (!isset($versionNo)) { foreach ($this->listVersions($contentId) as $versionInfo) { if ($versionInfo->versionNo === $currentVersionNo) { continue; } $versionContent = $this->load($contentId, $versionInfo->versionNo); $versionContent->versionInfo->contentInfo->id = $content->versionInfo->contentInfo->id; $versionContent->versionInfo->modificationDate = $createStruct->modified; $versionContent->versionInfo->creationDate = $createStruct->modified; $versionContent->versionInfo->id = $this->contentGateway->insertVersion($versionContent->versionInfo, $versionContent->fields); $this->fieldHandler->createNewFields($versionContent, $contentType); // Create names foreach ($versionContent->versionInfo->names as $language => $name) { $this->contentGateway->setName($content->versionInfo->contentInfo->id, $versionInfo->versionNo, $name, $language); } } } return $content; }
/** * Get field type information for sort clause * * TODO: handle custom field * TODO: caching (see above) * * @param string $contentTypeIdentifier * @param string $fieldDefinitionIdentifier * @param string $languageCode * * @return array */ public function getSortFieldTypes($contentTypeIdentifier, $fieldDefinitionIdentifier, $languageCode) { $types = array(); foreach ($this->contentTypeHandler->loadAllGroups() as $group) { foreach ($this->contentTypeHandler->loadContentTypes($group->id) as $contentType) { if ($contentType->identifier !== $contentTypeIdentifier) { continue; } foreach ($contentType->fieldDefinitions as $fieldDefinition) { if ($fieldDefinition->identifier !== $fieldDefinitionIdentifier) { continue; } // TODO: find a better way to handle non-translatable fields? if ($languageCode === null || $fieldDefinition->isTranslatable) { $fieldType = $this->fieldRegistry->getType($fieldDefinition->fieldType); foreach ($fieldType->getIndexDefinition() as $name => $type) { $types[$type->type] = $this->nameGenerator->getTypedName($this->nameGenerator->getName($name, $fieldDefinition->identifier, $contentType->identifier), $type); } } break 3; } } } return $types; }
/** * Publish the content type and update content objects. * * This method updates content objects, depending on the changed field definitions. * * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException If the content type has no draft * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the content type has no field definitions * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to publish a content type * * @param \eZ\Publish\API\Repository\Values\ContentType\ContentTypeDraft $contentTypeDraft */ public function publishContentTypeDraft(APIContentTypeDraft $contentTypeDraft) { if ($this->repository->hasAccess('class', 'update') !== true) { throw new UnauthorizedException('ContentType', 'update'); } try { $loadedContentTypeDraft = $this->loadContentTypeDraft($contentTypeDraft->id); } catch (APINotFoundException $e) { throw new BadStateException("\$contentTypeDraft", "The content type does not have a draft.", $e); } if (count($loadedContentTypeDraft->getFieldDefinitions()) === 0) { throw new InvalidArgumentException("\$contentTypeDraft", "The content type draft should have at least one field definition."); } $this->repository->beginTransaction(); try { if (empty($loadedContentTypeDraft->nameSchema)) { $fieldDefinitions = $loadedContentTypeDraft->getFieldDefinitions(); $this->contentTypeHandler->update($contentTypeDraft->id, $contentTypeDraft->status, $this->buildSPIContentTypeUpdateStruct($loadedContentTypeDraft, new ContentTypeUpdateStruct(array("nameSchema" => "<" . $fieldDefinitions[0]->identifier . ">")))); } $this->contentTypeHandler->publish($loadedContentTypeDraft->id); $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } }
/** * Map content to document. * * A document is an array of fields * * @param \eZ\Publish\SPI\Persistence\Content $content * * @return array */ protected function mapContent(Content $content) { $locations = $this->locationHandler->loadLocationsByContent($content->versionInfo->contentInfo->id); $mainLocation = null; foreach ($locations as $location) { if ($location->id == $content->versionInfo->contentInfo->mainLocationId) { $mainLocation = $location; } } $section = $this->sectionHandler->load($content->versionInfo->contentInfo->sectionId); // UserGroups and Users are Content, but permissions cascade is achieved through // Locations hierarchy. We index all ancestor Location Content ids of all // Locations of an owner. $ancestorLocationsContentIds = $this->getAncestorLocationsContentIds($content->versionInfo->contentInfo->ownerId); // Add owner user id as it can also be considered as user group. $ancestorLocationsContentIds[] = $content->versionInfo->contentInfo->ownerId; $document = array(new Field('id', $content->versionInfo->contentInfo->id, new FieldType\IdentifierField()), new Field('type', $content->versionInfo->contentInfo->contentTypeId, new FieldType\IdentifierField()), new Field('version', $content->versionInfo->versionNo, new FieldType\IdentifierField()), new Field('status', $content->versionInfo->status, new FieldType\IdentifierField()), new Field('name', $content->versionInfo->contentInfo->name, new FieldType\StringField()), new Field('creator', $content->versionInfo->creatorId, new FieldType\IdentifierField()), new Field('owner', $content->versionInfo->contentInfo->ownerId, new FieldType\IdentifierField()), new Field('owner_user_group', $ancestorLocationsContentIds, new FieldType\MultipleIdentifierField()), new Field('section', $content->versionInfo->contentInfo->sectionId, new FieldType\IdentifierField()), new Field('section_identifier', $section->identifier, new FieldType\IdentifierField()), new Field('section_name', $section->name, new FieldType\StringField()), new Field('remote_id', $content->versionInfo->contentInfo->remoteId, new FieldType\IdentifierField()), new Field('modified', $content->versionInfo->contentInfo->modificationDate, new FieldType\DateField()), new Field('published', $content->versionInfo->contentInfo->publicationDate, new FieldType\DateField()), new Field('path', array_map(function ($location) { return $location->pathString; }, $locations), new FieldType\MultipleIdentifierField()), new Field('location', array_map(function ($location) { return $location->id; }, $locations), new FieldType\MultipleIdentifierField()), new Field('depth', array_map(function ($location) { return $location->depth; }, $locations), new FieldType\IntegerField()), new Field('priority', array_map(function ($location) { return $location->priority; }, $locations), new FieldType\IntegerField()), new Field('location_parent', array_map(function ($location) { return $location->parentId; }, $locations), new FieldType\MultipleIdentifierField()), new Field('location_remote_id', array_map(function ($location) { return $location->remoteId; }, $locations), new FieldType\MultipleIdentifierField()), new Field('language_code', array_keys($content->versionInfo->names), new FieldType\MultipleStringField()), new Field('main_language_code', $content->versionInfo->contentInfo->mainLanguageCode, new FieldType\StringField()), new Field('invisible', array_map(function ($location) { return $location->invisible; }, $locations), new FieldType\MultipleBooleanField()), new Field('always_available', $content->versionInfo->contentInfo->alwaysAvailable, new FieldType\BooleanField())); if ($mainLocation !== null) { $document[] = new Field('main_location', $mainLocation->id, new FieldType\IdentifierField()); $document[] = new Field('main_location_parent', $mainLocation->parentId, new FieldType\IdentifierField()); $document[] = new Field('main_location_remote_id', $mainLocation->remoteId, new FieldType\IdentifierField()); $document[] = new Field('main_path', $mainLocation->pathString, new FieldType\IdentifierField()); $document[] = new Field('main_depth', $mainLocation->depth, new FieldType\IntegerField()); $document[] = new Field('main_priority', $mainLocation->priority, new FieldType\IntegerField()); } $contentType = $this->contentTypeHandler->load($content->versionInfo->contentInfo->contentTypeId); $document[] = new Field('group', $contentType->groupIds, new FieldType\MultipleIdentifierField()); foreach ($content->fields as $field) { foreach ($contentType->fieldDefinitions as $fieldDefinition) { if ($fieldDefinition->id !== $field->fieldDefinitionId) { continue; } $fieldType = $this->fieldRegistry->getType($field->type); foreach ($fieldType->getIndexData($field) as $indexField) { $document[] = new Field($this->fieldNameGenerator->getName($indexField->name, $fieldDefinition->identifier, $contentType->identifier), $indexField->value, $indexField->type); } } } $objectStateIds = array(); foreach ($this->objectStateHandler->loadAllGroups() as $objectStateGroup) { $objectStateIds[] = $this->objectStateHandler->getContentState($content->versionInfo->contentInfo->id, $objectStateGroup->id)->id; } $document[] = new Field('object_state', $objectStateIds, new FieldType\MultipleIdentifierField()); return $document; }
/** * Convenience method for resolving name schema. * * @param \eZ\Publish\API\Repository\Values\Content\Content $content * @param array $fieldMap * @param array $languageCodes * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType|null $contentType * * @return array */ public function resolveNameSchema(Content $content, array $fieldMap = array(), array $languageCodes = array(), ContentType $contentType = null) { if ($contentType === null) { $contentType = $this->contentTypeHandler->load($content->contentInfo->contentTypeId); } $languageCodes = $languageCodes ?: $content->versionInfo->languageCodes; return $this->resolve($contentType->nameSchema, $contentType, $this->mergeFieldMap($content, $fieldMap, $languageCodes), $languageCodes); }
/** * Resolves the targeted fields for this criterion. * * @param \eZ\Publish\API\Repository\Values\Content\Query\Criterion $criterion * * @return array */ protected function getTargetFieldNames(Criterion $criterion) { if ($criterion->target != null) { return $this->fieldNameResolver->getFieldNames($criterion, $criterion->target, $this->fieldTypeIdentifier, $this->fieldName); } $targetFieldNames = array(); foreach ($this->contentTypeHandler->getSearchableFieldMap() as $fieldDefinitions) { foreach ($fieldDefinitions as $fieldIdentifier => $fieldDefinition) { if (!isset($fieldDefinition['field_type_identifier'])) { continue; } if ($fieldDefinition['field_type_identifier'] != $this->fieldTypeIdentifier) { continue; } $solrFieldNames = $this->fieldNameResolver->getFieldNames($criterion, $fieldIdentifier, $this->fieldTypeIdentifier, $this->fieldName); $targetFieldNames = array_merge($targetFieldNames, $solrFieldNames); } } return array_values(array_unique($targetFieldNames)); }
/** * Applies joins to the query, required to fetch sort data. * * @param \eZ\Publish\Core\Persistence\Database\SelectQuery $query * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause $sortClause * @param int $number * @param array $languageSettings */ public function applyJoin(SelectQuery $query, SortClause $sortClause, $number, array $languageSettings) { /** @var \eZ\Publish\API\Repository\Values\Content\Query\SortClause\Target\FieldTarget $fieldTarget */ $fieldTarget = $sortClause->targetData; $fieldMap = $this->contentTypeHandler->getSearchableFieldMap(); if (!isset($fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]['field_definition_id'])) { throw new InvalidArgumentException('$sortClause->targetData', 'No searchable fields found for the given sort clause target ' . "'{$fieldTarget->fieldIdentifier}' on '{$fieldTarget->typeIdentifier}'."); } $fieldDefinitionId = $fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]['field_definition_id']; $table = $this->getSortTableName($number); $query->leftJoin($query->alias($this->dbHandler->quoteTable('ezcontentobject_attribute'), $this->dbHandler->quoteIdentifier($table)), $query->expr->lAnd($query->expr->eq($query->bindValue($fieldDefinitionId, null, PDO::PARAM_INT), $this->dbHandler->quoteColumn('contentclassattribute_id', $table)), $query->expr->eq($this->dbHandler->quoteColumn('contentobject_id', $table), $this->dbHandler->quoteColumn('id', 'ezcontentobject')), $query->expr->eq($this->dbHandler->quoteColumn('version', $table), $this->dbHandler->quoteColumn('current_version', 'ezcontentobject')), $this->getFieldCondition($query, $languageSettings, $table))); }
/** * Get field type information * * Returns an array in the form: * * <code> * array( * "field-identifier" => array( * "solr_field_name", * … * ), * … * ) * </code> * * @param \eZ\Publish\API\Repository\Values\Content\Query\CustomFieldInterface $criterion * * @return array */ public function getFieldTypes(CustomFieldInterface $criterion) { // @TODO: temp fixed by disabling caching, see https://jira.ez.no/browse/EZP-22834 $this->fieldTypes = array(); foreach ($this->contentTypeHandler->loadAllGroups() as $group) { foreach ($this->contentTypeHandler->loadContentTypes($group->id) as $contentType) { foreach ($contentType->fieldDefinitions as $fieldDefinition) { if (!$fieldDefinition->isSearchable) { continue; } if ($customField = $criterion->getCustomField($contentType->identifier, $fieldDefinition->identifier)) { $this->fieldTypes[$fieldDefinition->identifier]["custom"][] = $customField; continue; } $fieldType = $this->fieldRegistry->getType($fieldDefinition->fieldType); foreach ($fieldType->getIndexDefinition() as $name => $type) { $this->fieldTypes[$fieldDefinition->identifier][$type->type][] = $this->nameGenerator->getTypedName($this->nameGenerator->getName($name, $fieldDefinition->identifier, $contentType->identifier), $type); } } } } return $this->fieldTypes; }
/** * Builds API Relation object from provided SPI Relation object. * * @param \eZ\Publish\SPI\Persistence\Content\Relation $spiRelation * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $sourceContentInfo * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $destinationContentInfo * * @return \eZ\Publish\API\Repository\Values\Content\Relation */ public function buildRelationDomainObject(SPIRelation $spiRelation, ContentInfo $sourceContentInfo, ContentInfo $destinationContentInfo) { $sourceFieldDefinitionIdentifier = null; if ($spiRelation->sourceFieldDefinitionId !== null) { $contentType = $this->contentTypeHandler->load($sourceContentInfo->contentTypeId); foreach ($contentType->fieldDefinitions as $fieldDefinition) { if ($fieldDefinition->id !== $spiRelation->sourceFieldDefinitionId) { continue; } $sourceFieldDefinitionIdentifier = $fieldDefinition->identifier; break; } } return new Relation(array('id' => $spiRelation->id, 'sourceFieldDefinitionIdentifier' => $sourceFieldDefinitionIdentifier, 'type' => $spiRelation->type, 'sourceContentInfo' => $sourceContentInfo, 'destinationContentInfo' => $destinationContentInfo)); }
/** * @dataProvider providerForTestValidateError * * @param \eZ\Publish\API\Repository\Values\User\Limitation\ParentContentTypeLimitation $limitation * @param int $errorCount */ public function testValidateError(ParentContentTypeLimitation $limitation, $errorCount) { if (!empty($limitation->limitationValues)) { $this->getPersistenceMock()->expects($this->any())->method("contentTypeHandler")->will($this->returnValue($this->contentTypeHandlerMock)); foreach ($limitation->limitationValues as $key => $value) { $this->contentTypeHandlerMock->expects($this->at($key))->method("load")->with($value)->will($this->throwException(new NotFoundException('location', $value))); } } else { $this->getPersistenceMock()->expects($this->never())->method($this->anything()); } // Need to create inline instead of depending on testConstruct() to get correct mock instance $limitationType = $this->testConstruct(); $validationErrors = $limitationType->validate($limitation); self::assertCount($errorCount, $validationErrors); }
/** * Applies joins to the query, required to fetch sort data * * @param \eZ\Publish\Core\Persistence\Database\SelectQuery $query * @param \eZ\Publish\API\Repository\Values\Content\Query\SortClause $sortClause * @param int $number * * @return void */ public function applyJoin(SelectQuery $query, SortClause $sortClause, $number) { /** @var \eZ\Publish\API\Repository\Values\Content\Query\SortClause\Target\FieldTarget $fieldTarget */ $fieldTarget = $sortClause->targetData; $fieldMap = $this->contentTypeHandler->getSearchableFieldMap(); if (!isset($fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]["field_definition_id"])) { throw new InvalidArgumentException("\$sortClause->targetData", "No searchable fields found for the given sort clause target " . "'{$fieldTarget->fieldIdentifier}' on '{$fieldTarget->typeIdentifier}'."); } $fieldDefinitionId = $fieldMap[$fieldTarget->typeIdentifier][$fieldTarget->fieldIdentifier]["field_definition_id"]; $table = $this->getSortTableName($number); if ($fieldTarget->languageCode === null) { $languageExpression = $query->expr->gt($query->expr->bitAnd($query->expr->bitAnd($this->dbHandler->quoteColumn("language_id", $table), ~1), $this->dbHandler->quoteColumn("initial_language_id", "ezcontentobject")), 0); } else { $languageExpression = $query->expr->gt($query->expr->bitAnd($query->expr->bitAnd($this->dbHandler->quoteColumn("language_id", $table), ~1), $query->bindValue($this->languageHandler->loadByLanguageCode($fieldTarget->languageCode)->id, null, \PDO::PARAM_INT)), 0); } $query->leftJoin($query->alias($this->dbHandler->quoteTable("ezcontentobject_attribute"), $this->dbHandler->quoteIdentifier($table)), $query->expr->lAnd($query->expr->eq($query->bindValue($fieldDefinitionId, null, PDO::PARAM_INT), $this->dbHandler->quoteColumn("contentclassattribute_id", $table)), $query->expr->eq($this->dbHandler->quoteColumn("contentobject_id", $table), $this->dbHandler->quoteColumn("id", "ezcontentobject")), $query->expr->eq($this->dbHandler->quoteColumn("version", $table), $this->dbHandler->quoteColumn("current_version", "ezcontentobject")), $languageExpression)); }
public function mapLocation(Location $location) { $contentInfo = $this->contentHandler->loadContentInfo($location->contentId); $content = $this->contentHandler->load($location->contentId, $contentInfo->currentVersionNo); $section = $this->sectionHandler->load($content->versionInfo->contentInfo->sectionId); $fields = array(new Field('location', $location->id, new FieldType\IdentifierField()), new Field('document_type', 'location', new FieldType\IdentifierField()), new Field('priority', $location->priority, new FieldType\IntegerField()), new Field('hidden', $location->hidden, new FieldType\BooleanField()), new Field('invisible', $location->invisible, new FieldType\BooleanField()), new Field('remote_id', $location->remoteId, new FieldType\IdentifierField()), new Field('parent_id', $location->parentId, new FieldType\IdentifierField()), new Field('path_string', $location->pathString, new FieldType\IdentifierField()), new Field('depth', $location->depth, new FieldType\IntegerField()), new Field('sort_field', $location->sortField, new FieldType\IdentifierField()), new Field('sort_order', $location->sortOrder, new FieldType\IdentifierField()), new Field('is_main_location', $location->id == $content->versionInfo->contentInfo->mainLocationId, new FieldType\BooleanField())); // UserGroups and Users are Content, but permissions cascade is achieved through // Locations hierarchy. We index all ancestor Location Content ids of all // Locations of an owner. $ancestorLocationsContentIds = $this->getAncestorLocationsContentIds($contentInfo->ownerId); // Add owner user id as it can also be considered as user group. $ancestorLocationsContentIds[] = $contentInfo->ownerId; $fields[] = new Field('content_owner_user_group', $ancestorLocationsContentIds, new FieldType\MultipleIdentifierField()); $fields[] = new Field('content_id', $content->versionInfo->contentInfo->id, new FieldType\IdentifierField()); $fields[] = new Field('content_type', $content->versionInfo->contentInfo->contentTypeId, new FieldType\IdentifierField()); $fields[] = new Field('content_version', $content->versionInfo->versionNo, new FieldType\IdentifierField()); $fields[] = new Field('content_status', $content->versionInfo->status, new FieldType\IdentifierField()); $fields[] = new Field('content_name', $content->versionInfo->contentInfo->name, new FieldType\StringField()); $fields[] = new Field('content_creator', $content->versionInfo->creatorId, new FieldType\IdentifierField()); $fields[] = new Field('content_owner', $content->versionInfo->contentInfo->ownerId, new FieldType\IdentifierField()); $fields[] = new Field('content_section', $content->versionInfo->contentInfo->sectionId, new FieldType\IdentifierField()); $fields[] = new Field('content_section_identifier', $section->identifier, new FieldType\IdentifierField()); $fields[] = new Field('content_section_name', $section->name, new FieldType\StringField()); $fields[] = new Field('content_remote_id', $content->versionInfo->contentInfo->remoteId, new FieldType\IdentifierField()); $fields[] = new Field('content_modified', $content->versionInfo->contentInfo->modificationDate, new FieldType\DateField()); $fields[] = new Field('content_published', $content->versionInfo->contentInfo->publicationDate, new FieldType\DateField()); $fields[] = new Field('language_code', array_keys($content->versionInfo->names), new FieldType\MultipleStringField()); $fields[] = new Field('content_always_available', $content->versionInfo->contentInfo->alwaysAvailable, new FieldType\BooleanField()); $fields[] = new Field('content_group', $this->contentTypeHandler->load($content->versionInfo->contentInfo->contentTypeId)->groupIds, new FieldType\MultipleIdentifierField()); $fields[] = new Field('content_object_state', $this->getObjectStateIds($content->versionInfo->contentInfo->id), new FieldType\MultipleIdentifierField()); $contentType = $this->contentTypeHandler->load($content->versionInfo->contentInfo->contentTypeId); $fieldSets = $this->mapContentFields($content, $contentType, false); $documents = array(); foreach ($fieldSets as $languageCode => $translationFields) { $translationFields[] = new Field('meta_indexed_language_code', $languageCode, new FieldType\StringField()); $translationFields[] = new Field('meta_indexed_is_main_translation', $languageCode === $content->versionInfo->contentInfo->mainLanguageCode, new FieldType\BooleanField()); $translationFields[] = new Field('meta_indexed_is_main_translation_and_always_available', $languageCode === $content->versionInfo->contentInfo->mainLanguageCode && $content->versionInfo->contentInfo->alwaysAvailable, new FieldType\BooleanField()); $isMainTranslation = $content->versionInfo->contentInfo->mainLanguageCode === $languageCode; $alwaysAvailable = $isMainTranslation && $content->versionInfo->contentInfo->alwaysAvailable; $documents[] = new Document(array("id" => $this->generateLocationDocumentId($location, $languageCode), "languageCode" => $languageCode, "alwaysAvailable" => $alwaysAvailable, "isMainTranslation" => $isMainTranslation, "fields" => array_merge($fields, $translationFields))); } return $documents; }
/** * Maps given Location to a Document. * * Returned Document represents a "parent" Location document searchable with Location Search. * * @param \eZ\Publish\SPI\Persistence\Content\Location $location * * @return \eZ\Publish\Core\Search\Elasticsearch\Content\Document */ public function mapLocation(Location $location) { $contentInfo = $this->contentHandler->loadContentInfo($location->contentId); $content = $this->contentHandler->load($location->contentId, $contentInfo->currentVersionNo); $section = $this->sectionHandler->load($content->versionInfo->contentInfo->sectionId); $document = $this->mapContentLocation($location, $content); $document->id = $location->id; $document->type = "location"; $document->fields[] = new Field('is_main_location', $location->id == $content->versionInfo->contentInfo->mainLocationId, new FieldType\BooleanField()); // UserGroups and Users are Content, but permissions cascade is achieved through // Locations hierarchy. We index all ancestor Location Content ids of all // Locations of an owner. $ancestorLocationsContentIds = $this->getAncestorLocationsContentIds($contentInfo->ownerId); // Add owner user id as it can also be considered as user group. $ancestorLocationsContentIds[] = $contentInfo->ownerId; $document->fields[] = new Field('content_owner_user_group', $ancestorLocationsContentIds, new FieldType\MultipleIdentifierField()); $document->fields[] = new Field('content_id', $content->versionInfo->contentInfo->id, new FieldType\IdentifierField()); $document->fields[] = new Field('content_type', $content->versionInfo->contentInfo->contentTypeId, new FieldType\IdentifierField()); $document->fields[] = new Field('content_version', $content->versionInfo->versionNo, new FieldType\IdentifierField()); $document->fields[] = new Field('content_status', $content->versionInfo->status, new FieldType\IdentifierField()); $document->fields[] = new Field('content_name', $content->versionInfo->contentInfo->name, new FieldType\StringField()); $document->fields[] = new Field('content_creator', $content->versionInfo->creatorId, new FieldType\IdentifierField()); $document->fields[] = new Field('content_owner', $content->versionInfo->contentInfo->ownerId, new FieldType\IdentifierField()); $document->fields[] = new Field('content_section', $content->versionInfo->contentInfo->sectionId, new FieldType\IdentifierField()); $document->fields[] = new Field('content_section_identifier', $section->identifier, new FieldType\IdentifierField()); $document->fields[] = new Field('content_section_name', $section->name, new FieldType\StringField()); $document->fields[] = new Field('content_remote_id', $content->versionInfo->contentInfo->remoteId, new FieldType\IdentifierField()); $document->fields[] = new Field('content_modified', $content->versionInfo->contentInfo->modificationDate, new FieldType\DateField()); $document->fields[] = new Field('content_published', $content->versionInfo->contentInfo->publicationDate, new FieldType\DateField()); $document->fields[] = new Field('content_language_code', array_keys($content->versionInfo->names), new FieldType\MultipleStringField()); $document->fields[] = new Field('content_always_available', $content->versionInfo->contentInfo->alwaysAvailable, new FieldType\BooleanField()); $contentType = $this->contentTypeHandler->load($content->versionInfo->contentInfo->contentTypeId); $document->fields[] = new Field('content_group', $contentType->groupIds, new FieldType\MultipleIdentifierField()); $document->fields[] = new Field('content_object_state', $this->getObjectStateIds($content->versionInfo->contentInfo->id), new FieldType\MultipleIdentifierField()); return $document; }
/** * Update content objects * * Updates content objects, depending on the changed field definitions. * * A content type has a state which tells if its content objects yet have * been adapted. * * Flags the content type as updated. * * @param mixed $contentTypeId * @return void */ public function publish($contentTypeId) { $this->clearCache(); return $this->innerHandler->publish($contentTypeId); }
/** * Returns true if the given content type $contentType has content instances. * * @since 6.0.1 * * @param \eZ\Publish\API\Repository\Values\ContentType\ContentType $contentType * * @return bool */ public function isContentTypeUsed(APIContentType $contentType) { return $this->contentTypeHandler->getContentCount($contentType->id) > 0; }
/** * Get content type, field definition and field type mapping information * * Returns an array in the form: * * <code> * array( * "<ContentType identifier>" => array( * "<FieldDefinition identifier>" => array( * "field_definition_id" => "<FieldDefinition id>", * "field_type_identifier" => "<FieldType identifier>", * ), * ... * ), * ... * ) * </code> * * @return array */ protected function getSearchableFieldMap() { return $this->contentTypeHandler->getSearchableFieldMap(); }