Exemple #1
0
 /**
  * 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;
 }
    /**
     * Search on the Solr search server
     * @todo: add functionality not to call the DB to recreate objects : $asObjects == false
     *
     * @param string search term
     * @param array parameters. @see ezfeZPSolrQueryBuilder::buildSearch()
     * @see ezfeZPSolrQueryBuilder::buildSearch()
     * @param array search types. Reserved.
     *
     * @return array List of eZFindResultNode objects.
     */
    function search( $searchText, $params = array(), $searchTypes = array() )
    {
        eZDebug::createAccumulator( 'Search', 'eZ Find' );
        eZDebug::accumulatorStart( 'Search' );
        $error = 'Server not running';
        $searchCount = 0;

        $asObjects = isset( $params['AsObjects'] ) ? $params['AsObjects'] : true;

        //distributed search: fields to return can be specified in 2 parameters
        $fieldsToReturn = isset( $params['FieldsToReturn'] ) ? $params['FieldsToReturn'] : array();
        if ( isset( $params['DistributedSearch']['returnfields'] ) )
        {
            $fieldsToReturn = array_merge( $fieldsToReturn, $params['DistributedSearch']['returnfields'] );

        }



        $coreToUse = null;
        $shardQueryPart = null;
        if ( $this->UseMultiLanguageCores === true )
        {
            $languages = $this->SiteINI->variable( 'RegionalSettings', 'SiteLanguageList' );
            if ( array_key_exists ( $languages[0], $this->SolrLanguageShards ) )
            {
                $coreToUse = $this->SolrLanguageShards[$languages[0]];
                if ( $this->FindINI->variable( 'LanguageSearch', 'SearchMainLanguageOnly' ) <> 'enabled' )
                {
                    $shardQueryPart = array( 'shards' => implode( ',', $this->SolrLanguageShardURIs ) );
                }
            }
            //eZDebug::writeNotice( $languages, __METHOD__ . ' languages' );
            eZDebug::writeNotice( $shardQueryPart, __METHOD__ . ' shards' );
            //eZDebug::writeNotice( $this->SolrLanguageShardURIs, __METHOD__ . ' this languagesharduris' );
        }
        else
        {
            $coreToUse = $this->Solr;
        }


        if ( $this->SiteINI->variable( 'SearchSettings', 'AllowEmptySearch' ) == 'disabled' &&
             trim( $searchText ) == '' )
        {
            $error = 'Empty search is not allowed.';
            eZDebug::writeNotice( $error, __METHOD__ );
            $resultArray = null;
        }

        else
        {
            eZDebug::createAccumulator( 'Query build', 'eZ Find' );
            eZDebug::accumulatorStart( 'Query build' );
            $queryBuilder = new ezfeZPSolrQueryBuilder( $this );
            $queryParams = $queryBuilder->buildSearch( $searchText, $params, $searchTypes );
            if ( !$shardQueryPart == null )
            {
                $queryParams = array_merge( $shardQueryPart, $queryParams );
            }
            eZDebug::accumulatorStop( 'Query build' );
            eZDebug::writeDebug( $queryParams, 'Final query parameters sent to Solr backend' );

            eZDebug::createAccumulator( 'Engine time', 'eZ Find' );
            eZDebug::accumulatorStart( 'Engine time' );
            $resultArray = $coreToUse->rawSearch( $queryParams );
            eZDebug::accumulatorStop( 'Engine time' );
        }

        if ( !$resultArray )
        {
            eZDebug::accumulatorStop( 'Search' );
            return array(
                'SearchResult' => false,
                'SearchCount' => 0,
                'StopWordArray' => array(),
                'SearchExtras' => new ezfSearchResultInfo( array( 'error' => ezpI18n::tr( 'ezfind', $error ) ) ) );
        }

        $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'];
            $searchCount = $result['numFound'];
            $maxScore = $result['maxScore'];
            $docs = $result['docs'];
            $localNodeIDList = array();
            $objectRes = 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 )
                    {
                        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 );
                        }
                        // it may be a field originating from the explicit fieldlist to return, so it should be added for template consumption
                        // note that the fieldname will be kept verbatim in a substructure 'fields'
                        elseif( in_array( $fieldName, $fieldsToReturn ) )
                        {
                            $emit['fields'][$fieldName] = $fieldValue;
                        }

                    }
                    $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] );
                    $resultTree->setContentObject( new eZContentObject( $nodeRowList[$nodeID] ) );
                    $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;
            }
        }

        $stopWordArray = array();

        eZDebug::accumulatorStop( 'Search' );
        return array(
            'SearchResult' => $objectRes,
            'SearchCount' => $searchCount,
            'StopWordArray' => $stopWordArray,
            'SearchExtras' => new ezfSearchResultInfo( $resultArray ) );
    }
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;
}