/**
     *
     * Returns the Node from which the Source attribute is gotten
     * @param eZContentObject $object
     * @return string
     */
    public static function getSourceString($object)
    {
        $mainNode = $object->mainNode();
        $continue = true;
        $parent   = null;

        if(!$mainNode)
            return false;

        while($continue)
        {
            /* @type $mainNode eZContentObjectTreeNode */
            /* @type $parent eZContentObjectTreeNode */
            $parent = is_null($parent) ? $mainNode->fetchParent() : $parent->fetchParent();
            if($parent->ClassIdentifier == 'publisher_folder')
            {
                /* @var $parentDatamap eZContentObjectAttribute[] */
                $parentDatamap = $parent->dataMap();

                $publisherAttribute = $parentDatamap['publisher'];
                if($publisherAttribute->hasContent())
                {
                    /* @var $publisherUser eZContentObject */
                    /* @var $publisherDatamap eZContentObjectAttribute[] */
                    $publisherUser      = $publisherAttribute->content();
                    $publisherDatamap   = $publisherUser->dataMap();
                    $publisherFirstName = '';
                    $publisherLastName  = '';

                    if($publisherDatamap['first_name']->hasContent())
                        $publisherFirstName = $publisherDatamap['first_name']->content();
                    if($publisherDatamap['last_name']->hasContent())
                        $publisherLastName = $publisherDatamap['last_name']->content();
                    if($publisherDatamap['user_account']->hasContent())
                    {
                        /* @var $publisherUser eZUser */
                        $publisherUser = $publisherDatamap['user_account']->content();
                        $publisherUsername = $publisherUser->attribute('login');
                    }

                    if( empty($publisherFirstName) && empty($publisherLastName))
                        $publisherString = $publisherUsername;
                    else
                        $publisherString = implode(' ', array($publisherFirstName, $publisherLastName));

                    return $publisherString;
                }
            }

            $continue = count($parent->pathArray()) > 2;
        }

        return false;
    }
 /**
  * Generate result data for a node view
  *
  * @param eZTemplate $tpl
  * @param eZContentObjectTreeNode $node
  * @param eZContentObject $object
  * @param bool|string $languageCode
  * @param string $viewMode
  * @param int $offset
  * @param array $viewParameters
  * @param bool|array $collectionAttributes
  * @param bool $validation
  * @return array Result array for view
  */
 static function generateNodeViewData(eZTemplate $tpl, eZContentObjectTreeNode $node, eZContentObject $object, $languageCode, $viewMode, $offset, array $viewParameters = array('offset' => 0, 'year' => false, 'month' => false, 'day' => false), $collectionAttributes = false, $validation = false)
 {
     $section = eZSection::fetch($object->attribute('section_id'));
     if ($section) {
         $navigationPartIdentifier = $section->attribute('navigation_part_identifier');
         $sectionIdentifier = $section->attribute('identifier');
     } else {
         $navigationPartIdentifier = null;
         $sectionIdentifier = null;
     }
     $keyArray = array(array('object', $object->attribute('id')), array('node', $node->attribute('node_id')), array('parent_node', $node->attribute('parent_node_id')), array('class', $object->attribute('contentclass_id')), array('class_identifier', $node->attribute('class_identifier')), array('view_offset', $offset), array('viewmode', $viewMode), array('remote_id', $object->attribute('remote_id')), array('node_remote_id', $node->attribute('remote_id')), array('navigation_part_identifier', $navigationPartIdentifier), array('depth', $node->attribute('depth')), array('url_alias', $node->attribute('url_alias')), array('class_group', $object->attribute('match_ingroup_id_list')), array('state', $object->attribute('state_id_array')), array('state_identifier', $object->attribute('state_identifier_array')), array('section', $object->attribute('section_id')), array('section_identifier', $sectionIdentifier));
     $parentClassID = false;
     $parentClassIdentifier = false;
     $parentNodeRemoteID = false;
     $parentObjectRemoteID = false;
     $parentNode = $node->attribute('parent');
     if (is_object($parentNode)) {
         $parentNodeRemoteID = $parentNode->attribute('remote_id');
         $keyArray[] = array('parent_node_remote_id', $parentNodeRemoteID);
         $parentObject = $parentNode->attribute('object');
         if (is_object($parentObject)) {
             $parentObjectRemoteID = $parentObject->attribute('remote_id');
             $keyArray[] = array('parent_object_remote_id', $parentObjectRemoteID);
             $parentClass = $parentObject->contentClass();
             if (is_object($parentClass)) {
                 $parentClassID = $parentClass->attribute('id');
                 $parentClassIdentifier = $parentClass->attribute('identifier');
                 $keyArray[] = array('parent_class', $parentClassID);
                 $keyArray[] = array('parent_class_identifier', $parentClassIdentifier);
             }
         }
     }
     $res = eZTemplateDesignResource::instance();
     $res->setKeys($keyArray);
     if ($languageCode) {
         $oldLanguageCode = $node->currentLanguage();
         $node->setCurrentLanguage($languageCode);
     }
     $tpl->setVariable('node', $node);
     $tpl->setVariable('viewmode', $viewMode);
     $tpl->setVariable('language_code', $languageCode);
     if (isset($viewParameters['_custom'])) {
         foreach ($viewParameters['_custom'] as $customVarName => $customValue) {
             $tpl->setVariable($customVarName, $customValue);
         }
         unset($viewParameters['_custom']);
     }
     $tpl->setVariable('view_parameters', $viewParameters);
     $tpl->setVariable('collection_attributes', $collectionAttributes);
     $tpl->setVariable('validation', $validation);
     $tpl->setVariable('persistent_variable', false);
     $parents = $node->attribute('path');
     $path = array();
     $titlePath = array();
     foreach ($parents as $parent) {
         $path[] = array('text' => $parent->attribute('name'), 'url' => '/content/view/full/' . $parent->attribute('node_id'), 'url_alias' => $parent->attribute('url_alias'), 'node_id' => $parent->attribute('node_id'));
     }
     $titlePath = $path;
     $path[] = array('text' => $object->attribute('name'), 'url' => false, 'url_alias' => false, 'node_id' => $node->attribute('node_id'));
     $titlePath[] = array('text' => $object->attribute('name'), 'url' => false, 'url_alias' => false);
     $tpl->setVariable('node_path', $path);
     $event = ezpEvent::getInstance();
     $event->notify('content/pre_rendering', array($node, $tpl, $viewMode));
     $Result = array();
     $Result['content'] = $tpl->fetch('design:node/view/' . $viewMode . '.tpl');
     $Result['view_parameters'] = $viewParameters;
     $Result['path'] = $path;
     $Result['title_path'] = $titlePath;
     $Result['section_id'] = $object->attribute('section_id');
     $Result['node_id'] = $node->attribute('node_id');
     $Result['navigation_part'] = $navigationPartIdentifier;
     $contentInfoArray = array();
     $contentInfoArray['object_id'] = $object->attribute('id');
     $contentInfoArray['node_id'] = $node->attribute('node_id');
     $contentInfoArray['parent_node_id'] = $node->attribute('parent_node_id');
     $contentInfoArray['class_id'] = $object->attribute('contentclass_id');
     $contentInfoArray['class_identifier'] = $node->attribute('class_identifier');
     $contentInfoArray['remote_id'] = $object->attribute('remote_id');
     $contentInfoArray['node_remote_id'] = $node->attribute('remote_id');
     $contentInfoArray['offset'] = $offset;
     $contentInfoArray['viewmode'] = $viewMode;
     $contentInfoArray['navigation_part_identifier'] = $navigationPartIdentifier;
     $contentInfoArray['node_depth'] = $node->attribute('depth');
     $contentInfoArray['url_alias'] = $node->attribute('url_alias');
     $contentInfoArray['current_language'] = $object->attribute('current_language');
     $contentInfoArray['language_mask'] = $object->attribute('language_mask');
     $contentInfoArray['main_node_id'] = $node->attribute('main_node_id');
     $contentInfoArray['main_node_url_alias'] = false;
     // Add url alias for main node if it is not current node and user has access to it
     if (!$node->isMain()) {
         $mainNode = $object->mainNode();
         if ($mainNode->canRead()) {
             $contentInfoArray['main_node_url_alias'] = $mainNode->attribute('url_alias');
         }
     }
     $contentInfoArray['persistent_variable'] = false;
     if ($tpl->variable('persistent_variable') !== false) {
         $contentInfoArray['persistent_variable'] = $tpl->variable('persistent_variable');
         $keyArray[] = array('persistent_variable', $contentInfoArray['persistent_variable']);
         $res->setKeys($keyArray);
     }
     $contentInfoArray['class_group'] = $object->attribute('match_ingroup_id_list');
     $contentInfoArray['state'] = $object->attribute('state_id_array');
     $contentInfoArray['state_identifier'] = $object->attribute('state_identifier_array');
     $contentInfoArray['parent_class_id'] = $parentClassID;
     $contentInfoArray['parent_class_identifier'] = $parentClassIdentifier;
     $contentInfoArray['parent_node_remote_id'] = $parentNodeRemoteID;
     $contentInfoArray['parent_object_remote_id'] = $parentObjectRemoteID;
     $Result['content_info'] = $contentInfoArray;
     // Store which templates were used to make this cache.
     $Result['template_list'] = $tpl->templateFetchList();
     // Check if time to live is set in template
     if ($tpl->hasVariable('cache_ttl')) {
         $cacheTTL = $tpl->variable('cache_ttl');
     }
     if (!isset($cacheTTL)) {
         $cacheTTL = -1;
     }
     $Result['cache_ttl'] = $cacheTTL;
     // if cache_ttl is set to 0 from the template, we need to add a no-cache advice
     // to the node's data. That way, the retrieve callback on the next calls
     // will be able to determine earlier that no cache generation should be started
     // for this node
     if ($cacheTTL == 0) {
         $Result['no_cache'] = true;
     }
     if ($languageCode) {
         $node->setCurrentLanguage($oldLanguageCode);
     }
     return $Result;
 }
/**
 * Aligns articles published under given publisher folder
 * @param eZContentObject $publisherObject
 */
function alignArticle( $publisherObject, $checkModified = false, $checkLocations = false, $checkLanguages = false, $checkHidden = false, $timingDelay = 0, $forceLast = 0, $sleepTime = 1 )
{
	echo "Starting treatment of publisher folder : " . $publisherObject->name() . "\n";
	echo "Fetching solr informations\n";
	$eZSolr        = eZSearch::getEngine();
	$offset        = 0;
    $forced        = 0;
	$limit         = 200;
	$publisherNode = $publisherObject->mainNode();
	$doCheck       = $checkModified || $checkLocations || $checkLanguages || $checkHidden;
	$solrInfos     = fetchSolrPublisherFolder ( $publisherNode, $checkModified, $checkLocations, $checkLanguages, $checkHidden, $sleepTime );
	
	echo "Solr count : " . count($solrInfos) . "\n";

	while ( true )
	{
		$params = array(
				'Offset'           => $offset,
				'Limit'            => $limit,
				'ClassFilterType'  => 'include',
				'ClassFilterArray' => array( 'article' ),
				'LoadDataMap'      => false,
				'AsObject'         => false,
				'MainNodeOnly'     => true,
		);
        
        if ($forceLast > 0)
            $params['SortBy'] = array ( array('published', false ) );

		$nodeList = $publisherNode->subtree( $params );
		echo "\neZ Offset : $offset\n";

		if ( count( $nodeList ) == 0 )
		{
			break;
		}
	
		foreach ( $nodeList as $mainNode )
		{
			$nodeId = $mainNode['node_id'];
			$objectId = $mainNode['contentobject_id'];
			$toUpdate = false;

            if ( $forceLast > 0 && $forced < $forceLast )
                $toUpdate = true;
			elseif ( isset($solrInfos[$nodeId]) )
			{
				if ( $doCheck )
				{
					if ( $checkLanguages )
					{
						$eZLanguages = eZContentObject::fetch($objectId)->languages();
						$toUpdate = compareLanguages( array_keys($eZLanguages), $solrInfos[$nodeId]['languages'] );
						
						showInvalidTranslations(array_keys($eZLanguages), $solrInfos[$nodeId]['languages'], $objectId);
					}

					if (!$toUpdate && $checkModified)
						$toUpdate = compareDates($mainNode['modified'], $solrInfos[$nodeId]['modified'], $timingDelay);

					if (!$toUpdate && $checkLocations)
						$toUpdate = compareLocations($objectId, $solrInfos[$nodeId]['locations']);

                    if (!$toUpdate && $checkHidden)
                        $toUpdate = compareHidden($objectId, $solrInfos[$nodeId]['hiddenCount'], $solrInfos[$nodeId]['notHiddenCount']);
				}

				unset($solrInfos[$nodeId]);
			}
			else
				$toUpdate = true;

			if ( $toUpdate )
			{
				$return = $eZSolr->addObject( eZContentObject::fetch($objectId), false );

				echo ( !$return ? '!' . $objectId . '!' : '+' );
			}
			else
				echo '-';
            
            $forced++;
		}
	
		$offset += $limit;

		eZContentObject::clearCache();
        
        if ( $sleepTime > 0 )
            sleep ($sleepTime);
	}
	
	echo "\nArticles in solr but unknown from eZPublish : " . count($solrInfos) . " articles\n";
}
    /**
     * @param eZContentObject $contentObject
     * @param bool|null $parentIsInvisible Only defined as boolean true|false if we are recursively going in a child
     */
    public static function updateGlobalLimitation ( $contentObject, $parentIsInvisible = null )
    {
        /* @type $contentMainNode eZContentObjectTreeNode */
        $db              = eZDB::instance();
        $contentObjectID = $contentObject->attribute('id');
        $contentMainNode = $contentObject->mainNode();

        if ( !($contentMainNode instanceof eZContentObjectTreeNode) )
            return;

        /* @type $dm eZContentObjectAttribute[] */
        $contentDepth         = $contentMainNode->attribute('depth');
        $merckINI             = eZINI::instance('merck.ini');
        $onlineDateAttribute  = $merckINI->variable("ArticleVisibility","OnlineDate");
        $offlineDateAttribute = $merckINI->variable("ArticleVisibility","OfflineDate");
        $dm                   = $contentObject->attribute("data_map");

        if ( !is_array($dm) )
            return;

        /* @type $onlineDateContent eZDateTime */
        /* @type $offlineDateContent eZDateTime */
        $onlineDateContent    = $dm[$onlineDateAttribute]->content();
        $onlineDate           = $onlineDateContent->timeStamp();
        $offlineDateContent   = $dm[$offlineDateAttribute]->content();
        $offlineDate          = $offlineDateContent->timeStamp();
        $visibility           = MMEventManager::visibilityDates($contentObject);
        $isInvisible          = !$visibility;

        // We have a parent article, we check its visibility
        if ( !$isInvisible && $parentIsInvisible === null && $contentDepth > 4 )
        {
            $parentNode  = $contentMainNode->fetchParent();
            $isInvisible = self::isGloballyLimited( $parentNode->attribute('contentobject_id') );
        }
        elseif ( !$isInvisible )
        {
            if ( $parentIsInvisible !== null && $parentIsInvisible === true )
                $isInvisible = true;
        }

        $db->beginQuery();

        $visibilityChange = self::updateGlobalLimitationEntry( $contentObjectID, $offlineDate, $onlineDate, $visibility, $isInvisible);

        if ( $visibilityChange && $visibility && !$isInvisible )
        {
            eZSearch::updateNodeVisibility($contentObject->mainNodeID(), 'show');
        }
        elseif ( $visibilityChange && ( !$visibility || $isInvisible ) )
        {
            eZSearch::updateNodeVisibility($contentObject->mainNodeID(), 'hide');
        }

        if ( $visibilityChange )
            self::spreadGlobalLimitationChange( $contentMainNode, $isInvisible );

        $db->commitQuery();
    }
/**
 * Aligns location of the articles published under given publisher folder
 * @param eZContentObject $publisherObject
 */
function alignArticleLocation( $publisherObject, $offset = 0 )
{
    $limit = 200;
    $continue = true;
    $publisherNode = $publisherObject->mainNode();
    $globalVarName = 'contentServiceMainNodeID';

    if ( !isset( $GLOBALS[$globalVarName] ) )
    {
        $GLOBALS[$globalVarName] = array();
    }

    echo "Starting treatment of publisher folder : " . $publisherObject->name() . "\n";

    while ( true )
    {
        $params = array(
            'Offset' => $offset,
            'Limit' => $limit,
            'ClassFilterType' => 'include',
            'ClassFilterArray' => array(
                'article'
            ),
            'LoadDataMap' => false,
            'AsObject' => false,
            'MainNodeOnly' => true,
        );

        $nodeList = $publisherNode->subtree( $params );
        echo " // Offset : $offset // ";

        if ( count( $nodeList ) == 0 )
        {
            break;
        }

        foreach ( $nodeList as $mainNode )
        {
            $object = eZContentObject::fetch( $mainNode["contentobject_id"] );

            deploymentType::addListNodesIdToAddLocation($object);
        }

        $offset += $limit;

        eZContentObject::clearCache();
    }
}
    /**
     * The modify method gets the current content object AND the list of
     * Solr Docs (for each available language version).
     *
     * @param eZContentObject $contentObject
     * @param eZSolrDoc[] $docList
     */
    public function modify( eZContentObject $contentObject, &$docList )
    {
        /* @var eZContentObjectTreeNode $contentMainNode */
        $contentMainNode        = $contentObject->mainNode();
        $contentObjectLanguages = $contentObject->allLanguages();
        $articleLanguageArray   = array_keys($contentObjectLanguages);
        $publisherFolderNodeId  = PublisherFolderTool::getPublisherNodeIdFromArticleNode($contentMainNode);
        $isMerckManualShowcase  = false;
        // Depth : 0 => father article, 1+ => child article
        $articleRelativeDepth   = $contentMainNode->attribute('depth') - 4;

        if ( is_null($publisherFolderNodeId) )
            return;

        $publisherFolderInfos = PublisherFolderTool::getPublisherFolderInfosFromNodeId($publisherFolderNodeId);
        
        if ( !$publisherFolderInfos )
            return;

        $publisherFolderRelations = PublisherFolderTool::getPublisherFolderRelations($publisherFolderInfos['path']);

        if ( !$publisherFolderRelations || count($publisherFolderRelations['clusters']) === 0 )
            return;

        // node remote
        $remote = $contentMainNode->attribute("remote_id");
        $this->addValueToDoc( $docList, 'attr_node_remote_s', $remote);
        $this->addValueToDoc( $docList, 'attr_relative_depth_i', $articleRelativeDepth);

        foreach ( $publisherFolderRelations['clusters'] as $cluster => $applications )
        {
            ClusterTool::setCurrentCluster( $cluster );
            
            $applicationIdentifier = $applications[0];

            /* @var $applicationLocalized ApplicationLocalized */
            $applicationLocalized = CacheApplicationTool::buildLocalizedApplicationByIdentifier( $applicationIdentifier );

            if ( !($applicationLocalized instanceof ApplicationLocalized) )
            {
                if (count($applications) == 1)
                {
                    unset($publisherFolderRelations['clusters'][$cluster]);
                    continue;
                }

                $applicationIdentifier = $applications[1];
                $applicationLocalized = CacheApplicationTool::buildLocalizedApplicationByIdentifier( $applicationIdentifier );

                if ( !($applicationLocalized instanceof ApplicationLocalized) )
                {
                    unset($publisherFolderRelations['clusters'][$cluster]);
                    continue;
                }
                
                $publisherFolderRelations['clusters'][$cluster] = array ($applicationIdentifier);
            }

            // visibility per cluster
            $isVisible = ObjectVisibilityManager::isVisible($contentMainNode->attribute('contentobject_id'), $cluster);

            $this->addValueToDoc( $docList, 'attr_is_invisible_' . $cluster . '_b', !$isVisible );

            if (!isset(self::$_applicationIdentifierToId[$applicationIdentifier]))
                self::$_applicationIdentifierToId[$applicationIdentifier] = $applicationLocalized->applicationObject()->attribute ('id');

            $publisherFolder              = $applicationLocalized->getPublisherFolderFromPath($publisherFolderInfos['path']);
            $publisherLanguages           = $publisherFolder->getLanguages();
            $publisherAndArticleLanguages = array_intersect($publisherLanguages, $articleLanguageArray);

            if ( count($publisherAndArticleLanguages) == 0 )
                continue;

            $primaryLanguage = reset($publisherAndArticleLanguages);
            $contentMainNode->setCurrentLanguage($primaryLanguage);

            // publisher folder languages
            $languageKey       = 'subattr_language_' . $cluster . '____s';
            $formatedLanguages = array_map(
                array('kezfSolrArticleIndex', 'languageCode') ,
                $publisherAndArticleLanguages
            );

            $indexLanguages = array_unique( $formatedLanguages );

            $this->addValueToDoc( $docList, $languageKey, $indexLanguages, true, false );
            
            // Meck manual sections
            if( $applicationIdentifier == MerckManualShowcase::mainApplicationIdentifier() )
                $isMerckManualShowcase = true;

            // url computation
            /* @var eZContentObjectAttribute[] $dataMap */
            $dataMap = $contentMainNode->dataMap();

            ClusterTool::setCurrentCluster( $cluster );

            if( $applicationIdentifier == MerckManualShowcase::mainApplicationIdentifier() )
            {
                $urlContent = preg_replace(
                    '#^([^/]+/){2}#',
                    '',
                    MerckManualFunctionCollection::getMerckManualNodeUrl(
                        $applicationIdentifier,
                        $contentMainNode,
                        $primaryLanguage
                    )
                );
            }
            else
                $urlContent = preg_replace( '#^([^/]+/){2}#', '', $contentMainNode->urlAlias() );

            $this->addValueToDoc( $docList, 'attr_' . $cluster . '_url_s', $urlContent);

            $hasImage = array();

            for ( $mediaCase = 0; $mediaCase<=2; $mediaCase++ )
            {
                $hasImage[$mediaCase] = NodeOperatorHelper::hasImageArticle($contentMainNode, $mediaCase);
            }

            self::addValueToDoc( $docList, 'attr_has_image_' . $cluster . '_bst', base64_encode(json_encode($hasImage)) );

            $db = MMDB::instance();

            // index rating
            $row = $db->arrayQuery(sprintf("SELECT * FROM mm_rating_remote WHERE cluster_identifier = '%s' AND remote_id = '%s'", $cluster, $contentObject->remoteID()));
            if(count($row) && $row[0]["counter"] > 5 )
            {
                self::addValueToDoc( $docList, 'attr_content_rating_'.$cluster.'_f', $row[0]["total"]/$row[0]["counter"] );
                //update to_reindex
                $db->query(sprintf("UPDATE mm_rating_remote SET to_reindex=0 WHERE cluster_identifier = '%s' AND remote_id = '%s'", $cluster, $contentObject->remoteID()));
            }

            // index views
            $row = $db->arrayQuery(sprintf("SELECT * FROM mm_readcount_remote WHERE cluster_identifier = '%s' AND remote_id = '%s'", $cluster, $contentObject->remoteID()));
            if(count($row) && $row[0]["count"] > 0 )
            {
                self::addValueToDoc( $docList, 'attr_view_counter_'.$cluster.'_i', $row[0]["count"] );
                //update to_reindex
                $db->query(sprintf("UPDATE mm_readcount_remote SET to_reindex=0 WHERE cluster_identifier = '%s' AND remote_id = '%s'", $cluster, $contentObject->remoteID()));
            }

            if( $dataMap && $dataMap['media_content']->hasContent() )
            {
                $mediaContent      = $dataMap['media_content']->content();
                $mediaRelationList = $mediaContent['relation_list'];
                $entries           = array();
                $firstLink         = true;
                $totalQuizzes      = 0;

                foreach ( $mediaRelationList as $mediaRelation )
                {
                    $mediaObjectId = $mediaRelation['contentobject_id'];
                    $mediaClass = $mediaRelation['contentclass_identifier'];

                    /*******************************************************************************
                     * TODO : Adapt after PF Refactor
                     *******************************************************************************/
                    if ( !in_array($mediaClass, array('image', 'quiz', 'link')) )
                        continue;

                    
                    if ( $mediaClass === 'image' )
                    {
                        if ( count( $entries ) >= 3 )
                            continue;

                        // Language is DEPRECATED, Fake Language instead
                        $entries[] = $mediaObjectId . ";dep-DP";
                        /*******************************************************************************
                         * TODO : End : Adapt after PF Refactor
                         *******************************************************************************/
                    }
                    elseif ( ( $mediaClass === 'link' && $firstLink ) || $mediaClass === 'quiz' )
                    {
                        $mediaObject = eZContentObject::fetch( $mediaObjectId );

                        if ( !$mediaObject )
                            continue;

                        /* @var eZContentObjectAttribute[] $mediaDatamap */
                        $mediaDatamap = $mediaObject->dataMap();

                        if ( !is_array($mediaDatamap) )
                            continue;

                        if ( $mediaClass === 'link' )
                        {
                            if (!$mediaDatamap['url']->hasContent())
                                continue;

                            $firstLink = false;

                            self::addValueToDoc( $docList, 'attr_media_content_link_' . $cluster . '____ms', $mediaDatamap['url']->content(), false );
                        }
                        elseif ( $mediaClass === 'quiz' )
                        {
                            if ( $mediaDatamap['replies']->hasContent() )
                            {
                                $quizReplies = $mediaDatamap['replies']->content();
                                $quizReplies = $quizReplies->attribute('columns');
                                $quizReplies = $quizReplies['sequential'][1]['rows'];

                                if ( count($quizReplies) > 0 )
                                    self::addValueToDoc( $docList, 'attr_media_content_quiz_replies_' . $cluster . '____ms', $quizReplies, true);
                            }

                            if ( !empty($mediaDatamap['question']->DataText) )
                            {
                                self::addValueToDoc( $docList, 'attr_media_content_quiz_question_' . $cluster . '_ms', trim(strip_tags($mediaDatamap['question']->DataText)), false );
                            }

                            if ( !$mediaDatamap['points']->hasContent() )
                                continue;

                            $totalQuizzes+= $mediaDatamap['points']->content();
                        }
                    }
                }

                $withMediaDuration    = true;
                $typeMedias           = NodeOperatorHelper::getPictosMedia( $contentMainNode, $withMediaDuration );
                $typeMediasSerialized = base64_encode( json_encode($typeMedias) );

                // getPictosMedia as solr field
                self::addValueToDoc( $docList, 'attr_media_content_types_' . $cluster . '_bst', $typeMediasSerialized, false );

                // getMediaCount as solr field
                $mediaCount = NodeOperatorHelper::getMediaCount($contentMainNode);
                self::addValueToDoc( $docList, 'attr_media_content_count_' . $cluster . '_i', $mediaCount, false );

                // Used only for Quizz
                if ( $totalQuizzes > 0 )
                    self::addValueToDoc( $docList, 'attr_media_content_quiz_points_' . $cluster . '_i', $totalQuizzes, false );
            }
            
            unset($isHidden);
        }

        ClusterTool::resetCurrentCluster();

        $concernedNode = $contentMainNode;
        $concernedNode->setCurrentLanguage($articleLanguageArray[0]);

        if ( $contentMainNode->attribute('depth') > 4 )
        {
            $concernedNode = $contentMainNode->fetchParent();
            $concernedNode->setCurrentLanguage($articleLanguageArray[0]);
        }

        /* @type $concernedDM eZContentObjectAttribute[] */
        $concernedDM = $concernedNode->dataMap();
        $tags        = $concernedDM['tags'];

        $MerckManualAboutSectionId = eZIni::instance('merck.ini')->variable('MerckManualAboutSettings', 'SectionSourceId');
        $taxonomiesAttribute       = $concernedDM['serialized_taxonomies'];

        if( $taxonomiesAttribute instanceof eZContentObjectAttribute && $taxonomiesAttribute->hasContent() )
        {
            $taxonomies = $taxonomiesAttribute->content();

            foreach( array_keys($publisherFolderRelations['clusters']) as $cluster )
            {
                self::addValueToDoc(
                    $docList,
                    "attr_exclude_from_search_{$cluster}_b",
                    $MerckManualAboutSectionId && in_array($MerckManualAboutSectionId, $taxonomies['section']),
                    false
                );
            }
        }

        if( $tags instanceof eZContentObjectAttribute && $tags->hasContent() )
            self::addValueToDoc( $docList, 'subattr_tags____ms', explode("|", $tags->content()) );

        if ( $isMerckManualShowcase )
            $this->processSpecificMerckManual($docList, $concernedNode, $concernedDM, $publisherFolderRelations);

        foreach ( $publisherFolderRelations['clusters'] as $cluster => $applications )
        {
            ClusterTool::setCurrentCluster( $cluster );

            foreach( $applications as $key => $applicationIdentifier )
            {
                if ( !isset(self::$_applicationIdentifierToId[$applicationIdentifier]) )
                {
                    $applicationLocalized = CacheApplicationTool::buildLocalizedApplicationByIdentifier( $applicationIdentifier );

                    if( !($applicationLocalized instanceof ApplicationLocalized) )
                    {
                        eZDebug::writeError(
                            sprintf('Cluster: %s; Identifier: %s; ObjectId: %s', $cluster, $applicationIdentifier, $contentObject->attribute('id') ),
                            'Error getting application localized' );
                        unset( $publisherFolderRelations['clusters'][$cluster][$key] );
                    }
                    else
                        self::$_applicationIdentifierToId[$applicationIdentifier] = $applicationLocalized->applicationObject()->attribute('id');
                }
            }
        }

        ClusterTool::resetCurrentCluster();
        
        $applicationIds = array();

        foreach ( $publisherFolderRelations['clusters'] as $cluster => $applications )
            foreach( $applications as $applicationIdentifier )
                $applicationIds[] = self::$_applicationIdentifierToId[$applicationIdentifier];

        $uniqueApplicationIds = array_unique($applicationIds);

        foreach( $docList as $languageCode => $doc )
        {
            $dataMap               = $contentObject->fetchDataMap(false, $languageCode);
            $headline              = $dataMap['headline']->content();
            $headlineLowerCase     = mb_strtolower( StringTool::removeAccents($headline, 'utf-8', false), 'utf-8' );
            $unaccentedFirstLetter = mb_substr($headlineLowerCase, 0, 1, 'utf-8');

            $doc->addField( 'attr_headline_first_letter_lc_s', $unaccentedFirstLetter );
            $doc->addField( 'attr_headline_lc_s', $headlineLowerCase );

            foreach( $uniqueApplicationIds as $id )
            {
                $doc->addField( 'subattr_local_application___source_id____s', $id );
            }

            foreach( $publisherFolderRelations['clusters'] as $cluster => $applications )
            {
                foreach( $applications as $applicationIdentifier )
                {
                    $doc->addField('subattr_local_application___source_mixed____s', $cluster . '##unused##' . self::$_applicationIdentifierToId[$applicationIdentifier]);
                }
            }
        }
    }