/**
  * Get ezfSolrDocumentFieldBase instances for all attributes of specified eZContentObjectVersion
  *
  * @param eZContentObjectVersion Instance of eZContentObjectVersion to fetch attributes from.
  *
  * @return array List of ezfSolrDocumentFieldBase instances.
  */
 function getBaseList( eZContentObjectVersion $objectVersion )
 {
     $returnList = array();
     // Get ezfSolrDocumentFieldBase instance for all attributes in related object
     if ( eZContentObject::recursionProtect( $this->ContentObjectAttribute->attribute( 'contentobject_id' ) ) )
     {
         foreach ( $objectVersion->contentObjectAttributes( $this->ContentObjectAttribute->attribute( 'language_code' ) ) as $attribute )
         {
             if ( $attribute->attribute( 'contentclass_attribute' )->attribute( 'is_searchable' ) )
             {
                 $returnList[] = ezfSolrDocumentFieldBase::getInstance( $attribute );
             }
         }
     }
     return $returnList;
 }
Example #2
0
    /**
     * Adds object $contentObject to the search database.
     *
     * @param eZContentObject $contentObject Object to add to search engine
     * @param bool $commit Whether to commit after adding the object.
              If set, run optimize() as well every 1000nd time this function is run.
     * @return bool True if the operation succeed.
     */
    function addObject( $contentObject, $commit = true )
    {
        // 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 = $this->FindINI->variable( 'IndexExclude', 'ClassIdentifierList' );
        if ( $excludeClasses && in_array( $contentObject->attribute( 'class_identifier' ), $excludeClasses ) )
        {
            return true;
        }
        // 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' );
        $mainNodeID = $mainNode->attribute( 'node_id' );
        // 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 = self::getMetaAttributesForObject( $contentObject );

        // Get node attributes.
        $nodeAttributeValues = array();
        foreach ( $contentObject->attribute( 'assigned_nodes' ) as $contentNode )
        {
            $nodeID = $contentNode->attribute( 'node_id' );
            foreach ( eZSolr::nodeAttributes() as $attributeName => $fieldType )
            {
                $nodeAttributeValues[$nodeID][] = array( 'name' => $attributeName,
                                                'value' => $contentNode->attribute( $attributeName ),
                                                'fieldType' => $fieldType );
            }
            $nodePathArray[] = $contentNode->attribute( 'path_array' );

        }

        // Check anonymous user access.
        if ( $this->FindINI->variable( 'SiteSettings', 'IndexPubliclyAvailable' ) == 'enabled' )
        {
            $anonymousUserID = $this->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 = $this->FindINI->variable( "IndexBoost", "MetaField" );
        $boostClasses = $this->FindINI->variable( 'IndexBoost', 'Class' );
        $boostAttributes = $this->FindINI->variable( 'IndexBoost', 'Attribute' );
        $boostDatatypes = $this->FindINI->variable( 'IndexBoost', 'Datatype' );
        $reverseRelatedScale = $this->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' ), $this->guid( $contentObject, $languageCode ) );

            // Set installation identifier
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_id' ), self::installationID() );
            $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( 'installation_url' ),
                            $this->FindINI->variable( 'SiteSettings', 'URLProtocol' ) . $this->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 $nodeID => $metaInfoArray )
            {
                foreach( $metaInfoArray as $metaInfo)
                {
                    $doc->addField( ezfSolrDocumentFieldBase::generateMetaFieldName( $metaInfo['name'] ),
                                ezfSolrDocumentFieldBase::preProcessValue( $metaInfo['value'], $metaInfo['fieldType'] ) );
                }
            }

            // Main node gets single valued fields for sorting, using a dedicated prefix
            foreach ( $nodeAttributeValues[$mainNodeID] as $metaInfo )
            {
                $fieldName = 'main_node_' . ezfSolrDocumentFieldBase::generateMetaFieldName( $metaInfo['name'] );
                $doc->addField( $fieldName,
                                    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 = ( ( $this->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 );
                    $this->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;
        }

        // Since eZFind 2.7: indexhooks
        $generalPlugins = $this->FindINI->variable( 'IndexPlugins', 'General' );
        $classPlugins   = $this->FindINI->variable( 'IndexPlugins', 'Class' );
        if ( !empty( $generalPlugins ) )
        {
            foreach ( $generalPlugins as $pluginClassString )
            {
                if( !class_exists( $pluginClassString ) )
                {
                    eZDebug::writeError( "Unable to find the PHP class '$classname' 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 );
                }
            }
        }

        $optimize = false;
        if ( $this->FindINI->variable( 'IndexOptions', 'DisableDirectCommits' ) === 'true' )
        {
            $commit = false;
        }
        $commitWithin = 0;
        if ( $this->FindINI->variable( 'IndexOptions', 'CommitWithin' ) > 0 )
        {
            $commitWithin = $this->FindINI->variable( 'IndexOptions', 'CommitWithin' );
        }
        if ( $commit && ( $this->FindINI->variable( 'IndexOptions', 'OptimizeOnCommit' ) === 'enabled' ) )
        {
            $optimize = true;
        }

        if ( $this->UseMultiLanguageCores === true)
        {
            $result = true;
            foreach ( $availableLanguages as $languageCode )
            {
                $languageResult = $this->SolrLanguageShards[$languageCode]->addDocs( array( $docList[$languageCode] ), $commit, $optimize, $commitWithin );
                if ( !$languageResult )
                {
                    $result = false;
                }
            }
            return $result;
        }
        else
        {
            return $this->Solr->addDocs( $docList, $commit, $optimize, $commitWithin );
        }


    }
 /**
  * test for getData()
  */
 public function testGetData()
 {
     $providerArray = array();
     #start 1 : the simplest attribute
     $content1 = "Hello world";
     $ezcca1 = new eZContentClassAttribute(array('identifier' => 'title', 'data_type_string' => 'ezstring'));
     $ezcoa1 = new eZContentObjectAttributeTester(array("data_type_string" => 'ezstring', "id" => 100123, "data_text" => $content1, "contentclass_attribute" => $ezcca1));
     $fieldName1 = ezfSolrDocumentFieldBase::getFieldName($ezcca1);
     $expectedData1 = array($fieldName1 => $content1);
     $providerArray[] = array($expectedData1, $ezcoa1);
     #end 1
     #start 2 : attribute with subattributes
     $ezcca2 = new eZContentClassAttribute(array('identifier' => 'dummy', 'data_type_string' => 'dummy_example'));
     $ezcoa2 = new eZContentObjectAttributeTester(array("data_type_string" => 'dummy_example', "id" => 100124, "contentclass_attribute" => $ezcca2));
     $fieldList2 = ezfSolrDocumentFieldBase::getFieldNameList($ezcca2);
     $expectedData2 = array();
     foreach ($fieldList2 as $fieldName) {
         $expectedData2[$fieldName] = 'DATA_FOR_' . $fieldName;
     }
     $fieldName2 = ezfSolrDocumentFieldBase::getFieldName($ezcca2);
     $providerArray[] = array($expectedData2, $ezcoa2);
     #end 2
     #start 3 : object relations
     $expectedData3 = array();
     $tester3 = new ezfSolrDocumentFieldObjectRelationTester(new eZContentObjectAttribute(array()));
     $time3 = time();
     $image3 = new ezpObject("image", 2);
     $image3->name = __METHOD__ . $time3;
     $image3->caption = __METHOD__ . $time3;
     $imageId3 = $image3->publish();
     // $image3->object->clearCache();
     $dataMapImage3 = $image3->dataMap;
     // eZContentObjectAttribute objects, attributes of the related Image
     $imageName3 = $dataMapImage3['name'];
     $imageCaption3 = $dataMapImage3['caption'];
     $article3 = new ezpObject("article", 2);
     $articleId3 = $article3->publish();
     // Create object relation
     $article3->object->addContentObjectRelation($imageId3, $article3->current_version, 154, eZContentObject::RELATION_ATTRIBUTE);
     $dataMapArticle3 = $article3->attribute('data_map');
     $ezcoa3 = $dataMapArticle3['image'];
     $ezcoa3->setAttribute('data_int', $imageId3);
     $ezcoa3->store();
     $ezcca3 = $ezcoa3->attribute('contentclass_attribute');
     $defaultFieldName3 = ezfSolrDocumentFieldBase::generateAttributeFieldName($ezcca3, ezfSolrDocumentFieldObjectRelation::$subattributesDefinition[ezfSolrDocumentFieldObjectRelation::DEFAULT_SUBATTRIBUTE]);
     $expectedData3[$defaultFieldName3] = $tester3->getPlainTextRepresentation($ezcoa3);
     // required to allow another call to metaData()
     // on $ezcoa3 in getPlainTextRepresentation, called from the getData() method :
     eZContentObject::recursionProtectionEnd();
     $fieldNameImageName3 = ezfSolrDocumentFieldBase::generateSubattributeFieldName($ezcca3, $imageName3->attribute('contentclass_attribute_identifier'), ezfSolrDocumentFieldObjectRelation::getClassAttributeType($imageName3->attribute('contentclass_attribute')));
     $expectedData3[$fieldNameImageName3] = trim(implode(' ', array_values(ezfSolrDocumentFieldBase::getInstance($imageName3)->getData())), "\t\r\n ");
     $fieldNameImageCaption3 = ezfSolrDocumentFieldBase::generateSubattributeFieldName($ezcca3, $imageCaption3->attribute('contentclass_attribute_identifier'), ezfSolrDocumentFieldObjectRelation::getClassAttributeType($imageCaption3->attribute('contentclass_attribute')));
     $expectedData3[$fieldNameImageCaption3] = trim(implode(' ', array_values(ezfSolrDocumentFieldBase::getInstance($imageCaption3)->getData())), "\t\r\n ");
     $image3 = eZContentObject::fetch($imageId3);
     $metaAttributeValues = eZSolr::getMetaAttributesForObject($image3);
     foreach ($metaAttributeValues as $metaInfo) {
         $expectedData3[ezfSolrDocumentFieldBase::generateSubmetaFieldName($metaInfo['name'], $ezcca3)] = ezfSolrDocumentFieldBase::preProcessValue($metaInfo['value'], $metaInfo['fieldType']);
     }
     $providerArray[] = array($expectedData3, $ezcoa3);
     #end 3
     // Let's perform the actual testing :
     foreach ($providerArray as $input) {
         $expected = $input[0];
         $contentObjectAttribute = $input[1];
         $instance = ezfSolrDocumentFieldBase::getInstance($contentObjectAttribute);
         self::assertEquals($expected, $instance->getData());
     }
 }
 /**
  * Get ezfSolrDocumentFieldBase instances for all attributes of specified eZContentObjectVersion
  *
  * @param eZContentObjectVersion $objectVersion Instance of eZContentObjectVersion to fetch attributes from.
  * @return ezfSolrDocumentFieldBase[]|ocSolrDocumentFieldObjectRelation[] List of ezfSolrDocumentFieldBase instances.
  */
 function getBaseList(eZContentObjectVersion $objectVersion)
 {
     $returnList = array();
     // Get ezfSolrDocumentFieldBase instance for all attributes in related object
     /** @var eZContentObjectAttribute $attribute */
     foreach ($objectVersion->contentObjectAttributes($this->ContentObjectAttribute->attribute('language_code')) as $attribute) {
         /** @var eZContentClassAttribute $classAttribute */
         $classAttribute = $attribute->attribute('contentclass_attribute');
         if ($classAttribute->attribute('is_searchable')) {
             $returnList[] = ezfSolrDocumentFieldBase::getInstance($attribute);
         }
     }
     return $returnList;
 }
 private static function appendData($indexType, $attribute, $targets, $ngIndexerFieldName, &$data)
 {
     if ($indexType != 'object' && empty($attribute)) {
         return;
     }
     if ($indexType == 'object') {
         $handlerData = array();
         foreach ($targets as $target) {
             foreach ($target->dataMap() as $key => $value) {
                 if ($value->attribute('data_type_string') != 'ngindexer') {
                     $handler = ezfSolrDocumentFieldBase::getInstance($value);
                     $handlerData[$key][] = $handler->getData();
                 }
             }
         }
         foreach ($handlerData as $handlerDataArray) {
             foreach ($handlerDataArray as $dataFields) {
                 self::appendDataFields($dataFields, $ngIndexerFieldName, $data);
             }
         }
     } else {
         if ($indexType == 'object_attribute') {
             foreach ($targets as $target) {
                 $fieldName = self::NGINDEXER_FIELD_PREFIX . $ngIndexerFieldName . '_' . $attribute . '____t';
                 $data[$fieldName][] = $target->object()->attribute($attribute);
             }
         } else {
             if ($indexType == 'node_attribute') {
                 foreach ($targets as $target) {
                     $fieldName = self::NGINDEXER_FIELD_PREFIX . $ngIndexerFieldName . '_' . $attribute . '____t';
                     $data[$fieldName][] = $target->attribute($attribute);
                 }
             } else {
                 if ($indexType == 'data_map_attribute') {
                     $handlerData = array();
                     foreach ($targets as $target) {
                         $dataMap = $target->dataMap();
                         if (isset($dataMap[$attribute]) && $dataMap[$attribute]->attribute('data_type_string') != 'ngindexer') {
                             $handler = ezfSolrDocumentFieldBase::getInstance($dataMap[$attribute]);
                             $handlerData[] = $handler->getData();
                         }
                     }
                     foreach ($handlerData as $dataFields) {
                         self::appendDataFields($dataFields, $ngIndexerFieldName, $data);
                     }
                 }
             }
         }
     }
 }