/** * Clean up search index for current installation. * @return bool true if cleanup was successful * @todo: handle multicore configs (need a parameter for it) for return values **/ function cleanup( $allInstallations = false, $optimize = false ) { if ( $allInstallations === true ) { $optimize = true; $deleteQuery = '*:*'; } else { $deleteQuery = ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_id' ) . ':' . self::installationID(); } if ( $this->UseMultiLanguageCores == true ) { foreach ( $this->SolrLanguageShards as $shard ) { $shard->deleteDocs( array(), $deleteQuery, true, $optimize ); } return true; } else { return $this->Solr->deleteDocs( array(), $deleteQuery, true ); } }
/** * Translates a solr response into result objects or a slightly modified array. * The $asObjects parameter controls which of the 2 return formats get send back. * @see eZSolrBase::search * @see eZSolrBase::moreLikeThis */ protected function buildResultObjects($resultArray, &$searchCount, $asObjects = true, $fieldsToReturn = array()) { $objectRes = array(); $highLights = array(); if (!empty($resultArray['highlighting'])) { foreach ($resultArray['highlighting'] as $id => $highlight) { $highLightStrings = array(); //implode apparently does not work on associative arrays that contain arrays //$element being an array as well foreach ($highlight as $key => $element) { $highLightStrings[] = implode(' ', $element); } $highLights[$id] = implode(' ... ', $highLightStrings); } } if (!empty($resultArray)) { $result = $resultArray['response']; $maxScore = $result['maxScore']; $docs = $result['docs']; $localNodeIDList = array(); $nodeRowList = array(); // Loop through result, and get eZContentObjectTreeNode ID foreach ($docs as $idx => $doc) { if ($doc[ezfSolrDocumentFieldBase::generateMetaFieldName('installation_id')] == self::installationID()) { $localNodeIDList[] = $this->getNodeID($doc); } } if (!empty($localNodeIDList)) { $tmpNodeRowList = eZContentObjectTreeNode::fetch($localNodeIDList, false, false); // Workaround for eZContentObjectTreeNode::fetch behaviour if (count($localNodeIDList) === 1) { $tmpNodeRowList = array($tmpNodeRowList); } if ($tmpNodeRowList) { foreach ($tmpNodeRowList as $nodeRow) { $nodeRowList[$nodeRow['node_id']] = $nodeRow; } } unset($tmpNodeRowList); } //need refactoring from the moment Solr has globbing in fl parameter foreach ($docs as $idx => $doc) { if (!$asObjects) { $emit = array(); foreach ($doc as $fieldName => $fieldValue) { // check if field is not in the explicit field list, to keep explode from generating notices. if (strpos($fieldName, '_') !== false) { list($prefix, $rest) = explode('_', $fieldName, 2); // get the identifier for meta, binary fields $inner = implode('_', explode('_', $rest, -1)); if ($prefix === 'meta') { $emit[$inner] = $fieldValue; } elseif ($prefix === 'as') { $emit['data_map'][$inner] = ezfSolrStorage::unserializeData($fieldValue); } } elseif (in_array($fieldName, $fieldsToReturn)) { $emit['fields'][$fieldName] = $fieldValue; } } $emit['highlight'] = isset($highLights[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName('guid')]]) ? $highLights[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName('guid')]] : null; $objectRes[] = $emit; unset($emit); continue; } elseif ($doc[ezfSolrDocumentFieldBase::generateMetaFieldName('installation_id')] == self::installationID()) { // Search result document is from current installation $nodeID = $this->getNodeID($doc); // Invalid $nodeID // This can happen if a content has been deleted while Solr was not running, provoking desynchronization if (!isset($nodeRowList[$nodeID])) { $searchCount--; eZDebug::writeError("Node #{$nodeID} (/{$doc[ezfSolrDocumentFieldBase::generateMetaFieldName('main_url_alias')]}) returned by Solr cannot be found in the database. Please consider reindexing your content", __METHOD__); continue; } $resultTree = new eZFindResultNode($nodeRowList[$nodeID]); $node = $nodeRowList[$nodeID]; $resultTree->setContentObject(new eZContentObject(array("id" => $node["id"], "section_id" => $node["section_id"], "owner_id" => $node["owner_id"], "contentclass_id" => $node["contentclass_id"], "name" => $node["name"], "published" => $node["published"], "modified" => $node["modified"], "current_version" => $node["current_version"], "status" => $node["status"], "remote_id" => $node["object_remote_id"], "language_mask" => $node["language_mask"], "initial_language_id" => $node["initial_language_id"], "class_identifier" => $node["class_identifier"], "serialized_name_list" => $node["class_serialized_name_list"]))); $resultTree->setAttribute('is_local_installation', true); // can_read permission must be checked as they could be out of sync in Solr, however, when called from template with: // limitation, hash( 'accessWord', ... ) this check should not be performed as it has precedence. // See: http://issues.ez.no/15978 if (!isset($params['Limitation'], $params['Limitation']['accessWord']) && !$resultTree->attribute('object')->attribute('can_read')) { $searchCount--; eZDebug::writeNotice('Access denied for eZ Find result, node_id: ' . $nodeID, __METHOD__); continue; } $urlAlias = $this->getUrlAlias($doc); $globalURL = $urlAlias . '/(language)/' . $doc[ezfSolrDocumentFieldBase::generateMetaFieldName('language_code')]; eZURI::transformURI($globalURL); } else { $resultTree = new eZFindResultNode(); $resultTree->setAttribute('is_local_installation', false); $globalURL = $doc[ezfSolrDocumentFieldBase::generateMetaFieldName('installation_url')] . $doc[ezfSolrDocumentFieldBase::generateMetaFieldName('main_url_alias')] . '/(language)/' . $doc[ezfSolrDocumentFieldBase::generateMetaFieldName('language_code')]; } $resultTree->setAttribute('name', $doc[ezfSolrDocumentFieldBase::generateMetaFieldName('name')]); $resultTree->setAttribute('published', $doc[ezfSolrDocumentFieldBase::generateMetaFieldName('published')]); $resultTree->setAttribute('global_url_alias', $globalURL); $resultTree->setAttribute('highlight', isset($highLights[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName('guid')]]) ? $highLights[$doc[ezfSolrDocumentFieldBase::generateMetaFieldName('guid')]] : null); /** * $maxScore may be equal to 0 when the QueryElevationComponent is used. * It returns as first results the elevated documents, with a score equal to 0. In case no * other document than the elevated ones are returned, maxScore is then 0 and the * division below raises a warning. If maxScore is equal to zero, we can safely assume * that only elevated documents were returned. The latter have an articifial relevancy of 100%, * which must be reflected in the 'score_percent' attribute of the result node. */ $maxScore != 0 ? $resultTree->setAttribute('score_percent', (int) ($doc['score'] / $maxScore * 100)) : $resultTree->setAttribute('score_percent', 100); $resultTree->setAttribute('language_code', $doc[ezfSolrDocumentFieldBase::generateMetaFieldName('language_code')]); $objectRes[] = $resultTree; } } return $objectRes; }
/** * test for generateMetaFieldName() */ public function testGenerateMetaFieldName() { $baseName = "main_url_alias"; // type : 'string' $expected = ezfSolrDocumentFieldBase::META_FIELD_PREFIX . $baseName . '_s'; self::assertEquals($expected, ezfSolrDocumentFieldBase::generateMetaFieldName($baseName)); }
function fakeAddObject($contentObject) { $eZSolr = new eZSolr(); // Add all translations to the document list $docList = array(); // Check if we need to index this object after all // Exclude if class identifier is in the exclude list for classes $excludeClasses = $eZSolr->FindINI->variable('IndexExclude', 'ClassIdentifierList'); if ($excludeClasses && in_array($contentObject->attribute('class_identifier'), $excludeClasses)) { return false; } // Get global object values $mainNode = $contentObject->attribute('main_node'); if (!$mainNode) { eZDebug::writeError('Unable to fetch main node for object: ' . $contentObject->attribute('id'), __METHOD__); return false; } $mainNodePathArray = $mainNode->attribute('path_array'); // initialize array of parent node path ids, needed for multivalued path field and subtree filters $nodePathArray = array(); //included in $nodePathArray //$pathArray = $mainNode->attribute( 'path_array' ); $currentVersion = $contentObject->currentVersion(); // Get object meta attributes. $metaAttributeValues = eZSolr::getMetaAttributesForObject($contentObject); // Get node attributes. $nodeAttributeValues = array(); foreach ($contentObject->attribute('assigned_nodes') as $contentNode) { foreach (eZSolr::nodeAttributes() as $attributeName => $fieldType) { $nodeAttributeValues[] = array('name' => $attributeName, 'value' => $contentNode->attribute($attributeName), 'fieldType' => $fieldType); } $nodePathArray[] = $contentNode->attribute('path_array'); } // Check anonymous user access. if ($eZSolr->FindINI->variable('SiteSettings', 'IndexPubliclyAvailable') == 'enabled') { $anonymousUserID = $eZSolr->SiteINI->variable('UserSettings', 'AnonymousUserID'); $currentUserID = eZUser::currentUserID(); $user = eZUser::instance($anonymousUserID); eZUser::setCurrentlyLoggedInUser($user, $anonymousUserID); $anonymousAccess = $contentObject->attribute('can_read'); $user = eZUser::instance($currentUserID); eZUser::setCurrentlyLoggedInUser($user, $currentUserID); $anonymousAccess = $anonymousAccess ? 'true' : 'false'; } else { $anonymousAccess = 'false'; } // Load index time boost factors if any //$boostMetaFields = $eZSolr->FindINI->variable( "IndexBoost", "MetaField" ); $boostClasses = $eZSolr->FindINI->variable('IndexBoost', 'Class'); $boostAttributes = $eZSolr->FindINI->variable('IndexBoost', 'Attribute'); $boostDatatypes = $eZSolr->FindINI->variable('IndexBoost', 'Datatype'); $reverseRelatedScale = $eZSolr->FindINI->variable('IndexBoost', 'ReverseRelatedScale'); // Initialise default doc boost $docBoost = 1.0; $contentClassIdentifier = $contentObject->attribute('class_identifier'); // Just test if the boost factor is defined by checking if it has a numeric value if (isset($boostClasses[$contentClassIdentifier]) && is_numeric($boostClasses[$contentClassIdentifier])) { $docBoost += $boostClasses[$contentClassIdentifier]; } // Google like boosting, using eZ Publish reverseRelatedObjectCount $reverseRelatedObjectCount = $contentObject->reverseRelatedObjectCount(); $docBoost += $reverseRelatedScale * $reverseRelatedObjectCount; // Create the list of available languages for this version : $availableLanguages = $currentVersion->translationList(false, false); // Loop over each language version and create an eZSolrDoc for it foreach ($availableLanguages as $languageCode) { $doc = new eZSolrDoc($docBoost); // Set global unique object ID $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('guid'), $eZSolr->guid($contentObject, $languageCode)); // Set installation identifier $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('installation_id'), eZSolr::installationID()); $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('installation_url'), $eZSolr->FindINI->variable('SiteSettings', 'URLProtocol') . $eZSolr->SiteINI->variable('SiteSettings', 'SiteURL') . '/'); // Set Object attributes $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('name'), $contentObject->name(false, $languageCode)); // Also add value to the "sort_name" field as "name" is unsortable, due to Solr limitation (tokenized field) $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('sort_name'), $contentObject->name(false, $languageCode)); $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('anon_access'), $anonymousAccess); $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('language_code'), $languageCode); $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('available_language_codes'), $availableLanguages); if ($owner = $contentObject->attribute('owner')) { // Set owner name $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('owner_name'), $owner->name(false, $languageCode)); // Set owner group ID foreach ($owner->attribute('parent_nodes') as $groupID) { $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('owner_group_id'), $groupID); } } // from eZ Publish 4.1 only: object states // so let's check if the content object has it if (method_exists($contentObject, 'stateIDArray')) { $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('object_states'), $contentObject->stateIDArray()); } // Set content object meta attribute values. foreach ($metaAttributeValues as $metaInfo) { $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName($metaInfo['name']), ezfSolrDocumentFieldBase::preProcessValue($metaInfo['value'], $metaInfo['fieldType'])); } // Set content node meta attribute values. foreach ($nodeAttributeValues as $metaInfo) { $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName($metaInfo['name']), ezfSolrDocumentFieldBase::preProcessValue($metaInfo['value'], $metaInfo['fieldType'])); } // Add main url_alias $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('main_url_alias'), $mainNode->attribute('url_alias')); // Add main path_string $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('main_path_string'), $mainNode->attribute('path_string')); // add nodeid of all parent nodes path elements foreach ($nodePathArray as $pathArray) { foreach ($pathArray as $pathNodeID) { $doc->addField(ezfSolrDocumentFieldBase::generateMetaFieldName('path'), $pathNodeID); } } // Since eZ Fnd 2.3 // cannot call metafield field bame constructor as we are creating multiple fields foreach ($mainNodePathArray as $key => $pathNodeID) { $doc->addField('meta_main_path_element_' . $key . '_si', $pathNodeID); } eZContentObject::recursionProtectionStart(); // Loop through all eZContentObjectAttributes and add them to the Solr document. // @since eZ Find 2.3: look for the attribute storage setting $doAttributeStorage = $eZSolr->FindINI->variable('IndexOptions', 'EnableSolrAttributeStorage') === 'true' ? true : false; if ($doAttributeStorage) { $allAttributeData = array(); } foreach ($currentVersion->contentObjectAttributes($languageCode) as $attribute) { $metaDataText = ''; $classAttribute = $attribute->contentClassAttribute(); $attributeIdentifier = $classAttribute->attribute('identifier'); $combinedIdentifier = $contentClassIdentifier . '/' . $attributeIdentifier; $boostAttribute = false; if (isset($boostAttributes[$attributeIdentifier]) && is_numeric($boostAttributes[$attributeIdentifier])) { $boostAttribute = $boostAttributes[$attributeIdentifier]; } if (isset($boostAttributes[$combinedIdentifier]) && is_numeric($boostAttributes[$combinedIdentifier])) { $boostAttribute += $boostAttributes[$combinedIdentifier]; } if ($classAttribute->attribute('is_searchable') == 1) { $documentFieldBase = ezfSolrDocumentFieldBase::getInstance($attribute); $eZSolr->addFieldBaseToDoc($documentFieldBase, $doc, $boostAttribute); } if ($doAttributeStorage) { $storageFieldName = ezfSolrStorage::getSolrStorageFieldName($attributeIdentifier); $attributeData = ezfSolrStorage::getAttributeData($attribute); $allAttributeData['data_map'][$attributeIdentifier] = $attributeData; $doc->addField($storageFieldName, ezfSolrStorage::serializeData($attributeData)); } } eZContentObject::recursionProtectionEnd(); if ($doAttributeStorage) { $doc->addField('as_all_bst', ezfSolrStorage::serializeData($allAttributeData)); } $docList[$languageCode] = $doc; $generalPlugins = (array) eZINI::instance('ezfind.ini')->variable('IndexPlugins', 'General'); $classPlugins = (array) eZINI::instance('ezfind.ini')->variable('IndexPlugins', 'Class'); if (!empty($generalPlugins)) { foreach ($generalPlugins as $pluginClassString) { if (!class_exists($pluginClassString)) { eZDebug::writeError("Unable to find the PHP class '{$pluginClassString}' defined for index time plugins for eZ Find", __METHOD__); continue; } $plugin = new $pluginClassString(); if ($plugin instanceof ezfIndexPlugin) { $plugin->modify($contentObject, $docList); } } } if (array_key_exists($contentObject->attribute('class_identifier'), $classPlugins)) { $pluginClassString = $classPlugins[$contentObject->attribute('class_identifier')]; if (class_exists($pluginClassString)) { $plugin = new $pluginClassString(); if ($plugin instanceof ezfIndexPlugin) { $plugin->modify($contentObject, $docList); } } } } return $docList; }
$subtreeArray = explode(',', $ParentNodes); $defaultFilters = $DefaultFilters !== null ? explode(',', $DefaultFilters) : array(); $fieldsToReturn = $fields; $iDisplayStart = $http->hasGetVariable('iDisplayStart') ? $http->getVariable('iDisplayStart') : 10; $iDisplayLength = $http->hasGetVariable('iDisplayLength') ? $http->getVariable('iDisplayLength') : 100; /* * Ordering */ $sortBy = array(ezfSolrDocumentFieldBase::generateMetaFieldName('sort_name') => 'asc'); if ($http->hasGetVariable('iSortCol_0')) { for ($i = 0; $i < intval($http->getVariable('iSortingCols')); $i++) { $sortBy = array(); if ($http->getVariable('bSortable_' . intval($http->getVariable('iSortCol_' . $i))) == "true") { $sortKey = $fields[intval($http->getVariable('iSortCol_' . $i))]; if ($sortKey == 'name_t' || $sortKey == 'name') { $sortKey = ezfSolrDocumentFieldBase::generateMetaFieldName('sort_name'); } $sortBy[] = array($sortKey, $http->getVariable('sSortDir_' . $i)); } } } $query = ''; if ($http->getVariable('sSearch') != "") { $query = str_replace(' ', ' AND ', $http->getVariable('sSearch')) . '*'; } /* * Individual column filtering */ $filters = array(); if (!empty($defaultFilters)) { if ($DefaultFilters > 1) {