/**
     * @return Array
     */
    protected function getSolrArticles()
    {
        $fields = array(
            'attr_headline_t',
            'attr_promo_description_t',
            'attr_'.ClusterTool::clusterIdentifier().'_url_s',
            'attr_category_t',
            'subattr_publisher_folder___source_id____s',
            'attr_date_dt'
        );

        $sort = "attr_headline_t asc";

        $filters[] = 'subattr_publisher_folder___source_id____s:"congress_report_pt"';

        $params = array(
            'indent'        => 'on',
            'q'             => '*:*',
            'fq'            => implode(' AND ' , $filters),
            'start'         => '0',
            'rows'          => '3',
            'fl'            => implode(',', $fields),
            'qt'            => '',
            'explainOther'  => '',
            'hl.fl'         => '',
            'sort'          => $sort,
        );

        $solrResult = SolrTool::rawSearch( $params, 'php', false );

        return $this->formatSolrResponseAttributes($solrResult['response']['docs']);
    }
    /**
     * @param string $query
     * @param int $limit
     * @return array
     */
    public static function search( $query, $limit = 3 )
    {
        if ( !empty( $query ) )
        {
            $params = array(
                'qf' => self::META_APPLICATION_KEYWORD . ' ' . self::HEADLINE_KEYWORD,
                'qt' => 'ezpublish',
                'start' => 0,
                'rows' => $limit,
                'q' => '"' . StringTool::removeAccents( strtolower( $query ) ) . '"',
                'fq' => 'cluster_identifier_s:' . ClusterTool::clusterIdentifier() . ' AND ' . self::META_INSTALLATION_ID_MS_KEY . ':' . self::META_INSTALLATION_ID_MS_VAL,
                'fl' => '*,score',
                'sort' => 'name_s asc'
            );

            $result = SolrTool::rawSearch( $params, 'php', false );
            return $result;
        }
    }
    /**
     * @param array $params
     * @return array
     */
    public static function rawSearch($params)
    {
        $localApplication = CacheApplicationTool::buildLocalizedApplicationByIdentifier(MerckManualShowcase::mainApplicationIdentifier());
        $publishersFilters = $localApplication->getPublishersFilter();
        
        if ( isset($params['fq']) && trim($params['fq']) != '' )
        {
            $params['fq'] .= ' AND ' . $publishersFilters;
        }
        else
        {
            $params['fq'] = $publishersFilters;
        }

        return SolrTool::rawSearch($params);
    }
 /**
  * return all news objects since the date
  *
  * @param $date
  * @return mixed
  */
 private function getLastObjects($date)
 {
     $locales = array('eng-');
     foreach( glob('extension/cluster_*/settings/site.ini*') as $f )
     {
         $ini = eZINI::fetchFromFile( $f );
         foreach( $ini->variable('RegionalSettings', 'SiteLanguageList') as $locale )
         {
             if( !in_array(substr($locale, 0, 4), $locales) )
                 $locales[] = substr($locale, 0, 4);
         }
     }
     
     $filters = array(
         "meta_modified_dt:[$date TO NOW]",
         '('.implode(' OR ', SolrTool::solrLanguageFilter($locales)).')',
         'meta_class_identifier_ms:article',
         'meta_installation_id_ms:'.eZSolr::installationID()
     );
     
     $locale = 'eng';
     
     $continue = true;
     $offset = 0;
     while($continue)
     {
         $params = array(
             'indent'        => 'on',
             'start'         => $offset,
             'rows'          => 2000,
             'q'             => '',
             'fq'            => implode( ' AND ', $filters ),
             'fl'            => 'meta_id_si, meta_name_t, meta_modified_dt',
             'qt'            => 'ezpublish',
             'explainOther'  => '',
             'hl.fl'         => '',
             'sort'          => 'meta_modified_dt asc'
         );
 
         $raw        = SolrTool::rawSearch($params, 'php', false);
         
         $continue = count($raw['response']['docs']);
         $offset += 2000;
         
         foreach($raw['response']['docs'] as $result)
         {
             fputcsv( $this->csvFile(), array($result['meta_id_si'], str_replace( array("\n", "\r"), array(' ', ''), $result['meta_name_t'] )) );
             if(!isset($lastDate) || $result['meta_modified_dt'] > $lastDate)
             {
                 $lastDate = $result['meta_modified_dt'];
             }
         }
     }
     
     // security overlap to to avoid delayed indexing gap
     $overlap = eZINI::instance('merck.ini')->variable( 'AnalyticsExportSettings', 'LastDateOverlap' );
     $d = gmdate( 'Y-m-d\TH:i:s\Z', strtotime( $lastDate ) - $overlap );
     $this->saveNewLastDate($d);
     
     return $raw['response']['numFound'];
 }
    /**
     * @param $publisherFolder PublisherFolder
     * @return string
     */
    public function publisherFolderFilter ( $publisherFolder )
    {
        $languageFilters = array();
        $path = $publisherFolder->attribute('path');

        if ( is_array($publisherFolder->attribute('languages')) )
            $languages = $publisherFolder->attribute('languages');
        else
            $languages = LocaleTool::languageList();

        if ( $publisherFolder->attribute('fallback') )
            $languageFilters = SolrTool::solrLanguageFilter( $languages );
        else
            $languageFilters[] = "meta_language_code_ms:{$languages[0]}";
        
        $publisherFilter = '( subattr_publisher_folder___source_id____s:"'.$path.'"'
                          .' AND ( ' . implode(' OR ', $languageFilters) . ' ) )';
        
        //#48332 - get content for quiz_train_your_brain from 13th August 2015 
        $dateRestrictions = SolrSafeOperatorHelper::clusterIni('MedicalQuizDateRestriction','PublisherFolderDateRestriction','merck.ini');
        if(!empty($dateRestrictions) && array_key_exists($path, $dateRestrictions)){
            if($dateRestrictions[$path]){
                $publisherFilter = '( subattr_publisher_folder___source_id____s:"'.$path.'"'
                          .' AND (attr_online_date_dt:["'.$dateRestrictions[$path].'" TO NOW])'
                          .' AND ( ' . implode(' OR ', $languageFilters) . ' ) )';
            }
        }
        return $publisherFilter;
    }
    /**
     * @return array
     */
    public function stc()
    {
        if( !self::user() ) {
            return false;
        }
        $http = BlockDefault::http();

        //get current user infos
        $serviceUser = ServiceUser::getInstance();
        $parameters = $serviceUser->getFormParameters();
        $userInfos = $serviceUser->callWSHandler( $serviceUser->getEsbInterface( 'read' ), $parameters );

        $appname = $http->hasPostVariable( 'appname' ) ? stripslashes( $http->postVariable( 'appname' ) ) : '';

        $sender = $userInfos['Data']['Params']['Firstname'] . $userInfos['Data']['Params']['Lastname'];
        $senderName = $userInfos['Data']['Params']['Firstname'] . $userInfos['Data']['Params']['Lastname'];
        $senderEmail = $userInfos['Data']['Params']['Email_address'];

        //get comment

        if(!$http->hasPostVariable( 'token' ) || !SecurityTool::isUserTokenValid($http->postVariable( 'token' )))
        {
            return array(
                'Error' =>  'Invalid token',
            );
        }

        $message = $http->hasPostVariable( 'comment' ) ? stripslashes( $http->postVariable( 'comment' ) ) : '';

        //get recipient email
        $recipient = $http->hasPostVariable( 'Recipient_email' ) ? stripslashes( preg_replace( '/\s/', '', $http->postVariable( 'Recipient_email' ) ) ) : '';
        $recipients = array_unique( explode( ';', $recipient ) );

        //get Article nodeID
        $extract = $title = '';
        $articleRemoteID = $http->hasPostVariable( 'remote_id' ) ? $http->postVariable( 'remote_id' ) : null;
        if(!is_null($articleRemoteID))
        {
            $fieldsQuery = array (
                '(meta_remote_id_ms:' . $articleRemoteID . ')',
                '(meta_class_identifier_ms:article)'
            );

            $fields = array (
                'attr_promo_description_t',
                'attr_headline_t',
            );

            //fetch solr
            $params = array(
                'indent'        => 'on',
                'q'             => '*:*',
                'start'         => 0,
                'rows'          => 1,
                'fq'            => implode(' AND ', $fieldsQuery),
                'fl'            => implode(',', $fields),
                'qt'            => '',
                'explainOther'  => '',
                'hl.fl'         => '',
            );

            $raw = SolrTool::rawSearch($params);
            $article = $raw['response']['docs'][0];

            if(strlen($article['attr_promo_description_t']) > 150)
            {
                $extract = mb_substr($article['attr_promo_description_t'], 0, 150, 'utf-8') . '...';
            }
            else
            {
                $extract = $article['attr_promo_description_t'];
            }

            $title = $article['attr_headline_t'];
        }

        $destUrl = $http->hasPostVariable( 'destURL' ) ? stripslashes( filter_var($http->postVariable( 'destURL' ), FILTER_VALIDATE_URL) ) : '';

        $preparedMessage = $this->prepareMessage( $sender, htmlentities( $message ), $extract, $destUrl );

        if( SolrSafeOperatorHelper::featureIsActive( 'ExactTarget' ) && SolrSafeOperatorHelper::featureIsActive( 'UUMP' ) )
        {
            $message = nl2br($message);
            
            foreach( $recipients as $recipient )
            {
                ExactTarget::sendToAColleague(
                    self::user()->attribute( 'uuid' ),
                    $recipient,
                    $message,
                    $appname,
                    $destUrl,
                    $extract,
                    $title
                );
            }
        }
        else
        {
            // Below code is no longer used, since all clusters are using ExactTarget feature.
            $email = new MailTool( $title, $senderName, array(), $preparedMessage, 'sendtocolleague_email.log');
            foreach ( $recipients as $recipient )
            {
                $to = filter_var( $recipient, FILTER_VALIDATE_EMAIL );
                if ( $to === false ) {
                    continue;
                }
                $email->setRecipients( $to );
                $email->sendMail();
            }
        }

        return array(
            'redirect_url' => $this->redirectUrl
        );
    }
    public function suggestedTerms()
    {
        if ( mb_strlen($this->searchQuery, 'UTF-8') < 3 )
        {
            return array();
        }

        eZDebug::accumulatorStart(__CLASS__.'::'.__FUNCTION__, 'Merck' );

        $solrHighlightParams = $this->solrHighlightParams();
        $suggestions         = array();
        $filters             = array();
        $solrFilter          = $this->solrFilter();
        $solrFacetsFiler     = $this->solrFacetsFilter();

        if( $solrFilter )
            $filters[] = $solrFilter;
        if( $solrFacetsFiler )
            $filters[] = $solrFacetsFiler;

        $queries = array();
        $terms   = MMGlobalSearchDictionaryTerm::fetchSolrTerms( $this->searchQuery, null, $this->suggestedTermsLimit() * 3 );

        foreach( $terms as $term )
        {
            $query = array();

            foreach( explode( ' ', $solrHighlightParams['hl.fl'] ) as $field )
                $query[] = $field.':"'.addslashes( $term ).'"';

            $queries[] = implode( ' OR ', $query );
        }

        $params = array(
                'start'	        => 0,
                'rows'	        => 0,
                'q'		        => '*:*',
                'fq'	        => implode(' AND ' , $filters),
                'facet'	        => 'true',
                'facet.query'   => $queries,
        );
        $solrResults = SolrTool::rawSearch( $params );

        $i = 0;
        foreach( $solrResults['facet_counts']['facet_queries'] as $solrTerm => $solrTermCount )
        {
            if( $solrTermCount )
            {
                $term = $terms[$i];
                if( strtolower( trim( $term ) ) != strtolower( trim( $this->searchQuery, ' "' ) ) )
                {
                    $suggestions[] = array(
                        't'	=> $term,
                        'c'	=> $solrTermCount);

                    if( count( $suggestions ) >= $this->suggestedTermsLimit() )
                        break;
                }
            }
            $i++;
        }


        // sort
        usort( $suggestions, function($a, $b){
            return ($a['c'] < $b['c']);
        } );

        eZDebug::accumulatorStop( __CLASS__.'::'.__FUNCTION__ );

        return $suggestions;
    }
function fetchSolrPublisherFolder ( $publisherNode, $checkModified, $checkLocations, $checkLanguages, $checkHidden, $sleepTime )
{
	$returnArray = array();
	$start = 0;
	$rows = 200;
	$doCheck = $checkModified || $checkLocations || $checkLanguages || $checkHidden;

	$paramArray = array(
			'indent'       => 'on',
			'q'            => '',
			'fq'           => solrFilter($publisherNode),
			'fl'           => 'meta_main_node_id_si',
			'qt'           => 'ezpublish',
			'explainOther' => '',
			'hl.fl'        => '',
	);

	if ($checkModified)
		$paramArray['fl'].= ',meta_modified_dt';
	if ($checkLocations)
		$paramArray['fl'].= ',meta_node_id_si';
	if ($checkLanguages)
		$paramArray['fl'].= ',meta_language_code_ms';
	if ($checkHidden)
		$paramArray['fl'].= ',meta_is_hidden_b';
    
	while ( true )
	{
		$params = $paramArray;
		$params['start'] = $start;
		$params['rows'] = $rows;
		echo "Solr Offset : $start\n";

		$results = SolrTool::rawSearch($params, 'php', false);
		
		if ( $results === false || !count($results['response']['docs']) )
		{
			break;
		}
		
		foreach ( $results['response']['docs'] as $result )
		{
			$nodeId = $result['meta_main_node_id_si'];
			
			if ( $publisherNode != $nodeId )
			{
				if ($doCheck)
				{
					if ( !is_array($returnArray[$nodeId]) )
						$returnArray[$nodeId] = array();
	
					if ($checkModified)
						$returnArray[$nodeId]['modified'] = $result['meta_modified_dt'];
					if ($checkLocations)
						$returnArray[$nodeId]['locations'] = count($result['meta_node_id_si']);
					if ($checkHidden)
                    {
                        $returnArray[$nodeId]['hiddenCount'] = 0;
                        $returnArray[$nodeId]['notHiddenCount'] = 0;

                        foreach ($result['meta_is_hidden_b'] as $isHidden)
                        {
                            if($isHidden)
                                $returnArray[$nodeId]['hiddenCount']+= 1;
                            else
                                $returnArray[$nodeId]['notHiddenCount']+= 1;
                        }
                    }
					if ($checkLanguages)
					{
						if ( !is_array($returnArray[$nodeId]['languages']) )
							$returnArray[$nodeId]['languages'] = array();
	
						$returnArray[$nodeId]['languages'][] = $result['meta_language_code_ms'];
					}
				}
				else 
					$returnArray[$nodeId] = true;
			}
		}
		
		$start+= $rows;
        
        if ( $sleepTime > 0 )
            sleep ($sleepTime);
	}
	
	return $returnArray;
}
    'qt'            => 'ezpublish',
);

foreach ( $clusters as $cluster )
{
    $orFilters[] = "attr_{$cluster}_url_s:full/*";
}
$filters[] = "( " . implode(' OR ', $orFilters ) . " )";

$rawSolrParams['fq'] = implode(' AND ', $filters);

while (true)
{
    $rawSolrParams['start'] = $solrStart;

    $results = SolrTool::rawSearch($rawSolrParams, 'php', false);

    $cli->output( "[Step 1/2] Bad url search in progress : {$solrStart} / {$results['response']['numFound']}" );

    if ( count($results['response']['docs']) === 0 )
        break;

    $objectIds = array();

    foreach( $results['response']['docs'] as $result )
        $objectIds[] = $result["meta_id_si"];

    unset($results);

    $globalObjectIds = array_merge( $globalObjectIds, $objectIds );
 public function fetchNewestArticle()
 {
     $params = array(
         'indent'        => 'on',
         'q'             => '',
         'start'         => 0,
         'rows'          => 1,
         'fq'            => "subattr_publisher_folder___source_id____s: \"bbc_feed\"",
         'fl'            => "attr_headline_t,attr_date_dt",
         'qt'            => 'ezpublish',
         'explainOther'  => '',
         'hl.fl'         => '',
         'sort'          => 'attr_date_dt desc'
     );
     $result = SolrTool::rawSearch($params);
     if (isset($result['response']) && isset($result['response']['docs']) && isset($result['response']['docs'][0]))
     {
         return $result['response']['docs'][0];
     }
     return false;
 }
    public function getEvrikaCityAndSpecialty()
    {
        $fields = array(
            'attr_evrika_address_city_s',
            'subattr_evrika_specialty____s',
        );

        $filters = $this->solrFilter(false, filter_var($_GET['year'], FILTER_VALIDATE_INT), filter_var($_GET['month'], FILTER_VALIDATE_INT), filter_var($_GET['events'], FILTER_SANITIZE_STRING),filter_var($_GET['specialty'], FILTER_VALIDATE_FLOAT));

        $params = array(
            'indent'        => 'on',
            'q'             => '',
            'start'         => 0,
            'rows'          => 1,
            'fq'            => $filters,
            'fl'            => implode(',', array_values($fields)),
            'qt'            => 'ezpublish',
            'explainOther'  => '',
            'hl.fl'         => '',
            'facet' => 'on',
            'facet.field' => array(
                'attr_evrika_address_city_s',
                'subattr_evrika_specialty____s',
            )
        );


        $result = SolrTool::rawSearch($params, 'php');

        $cities = $result['facet_counts']['facet_fields']['attr_evrika_address_city_s'];

        $specialties = $result['facet_counts']['facet_fields']['subattr_evrika_specialty____s'];

        return array(
            'cities' => $cities,
            'specialties' => $specialties,
        );
    }
    /**
     * @param eZTemplate $tpl
     * @param string $operatorName
     * @param array $operatorParameters
     * @param string $rootNamespace
     * @param string $currentNamespace
     * @param mixed $operatorValue
     * @param array $namedParameters
     */
    function modify($tpl, $operatorName, $operatorParameters, $rootNamespace, $currentNamespace, &$operatorValue, $namedParameters)
    {
        switch ($operatorName)
        {
            /*******************************************************************************/
            /*                             Solr Safe Operators                             */
            /*******************************************************************************/

            case 'ezfind_raw_fetch':
                $operatorValue = SolrSafeOperatorHelper::ezfindRawFetch(
                    $namedParameters['params'],
                    $namedParameters['nodeIdsOnly']
                );
                break;
            case 'getUrlSolr':
                $operatorValue = SolrSafeOperatorHelper::getUrlSolr($namedParameters['solrdata']);
                break;
            case 'getDatesPDFavailable':
                $operatorValue = SolrSafeOperatorHelper::getDatesPDFavailable(
                    $namedParameters['onlineDate'],
                    $namedParameters['daysAvailable']
                );
                break;
            case 'getViewCounter':
                $operatorValue = SolrSafeOperatorHelper::getViewCounter(
                    $namedParameters['remoteId'],
                    $namedParameters['clusterIdentifier']
                );
                break;
            case 'getRatings':
                $operatorValue = SolrSafeOperatorHelper::getRatings(
                    $namedParameters['remoteId'],
                    $namedParameters['clusterIdentifier']
                );
                break;
            case 'getJavascriptFiles':
                $operatorValue = SolrSafeOperatorHelper::getJavascriptFiles(
                    $namedParameters['application_name'],
                    $namedParameters['type'],
                    $namedParameters['isConsult']
                );
                break;
            case 'getLessFiles':
                $operatorValue = SolrSafeOperatorHelper::getLessFiles(
                    $namedParameters['application_name'],
                    $namedParameters['application'],
                    $namedParameters['isConsult']
                );
                break;
            case 'getInfosApp':
                $operatorValue = SolrSafeOperatorHelper::getInfosApp($namedParameters['application_identifier']);
                break;
            case 'getHostNameFromURL':
                $operatorValue = SolrSafeOperatorHelper::getHostNameFromURL($namedParameters['url']);
                break;
            case 'context':
                $operatorValue = SolrSafeOperatorHelper::context($namedParameters['url']);
                break;
            case 'getMetas':
                $operatorValue = SolrSafeOperatorHelper::getMetas($namedParameters['applicationName']);
                break;
            case 'getSolrData':
                $operatorValue = SolrSafeOperatorHelper::getSolrData(
                    $namedParameters['remoteId'],
                    $namedParameters['clusterIdentifier'],
                    $namedParameters['extended_fields']
                );
                break;
            case 'getCustomParameter':
                $operatorValue = SolrSafeOperatorHelper::getCustomParameter(
                    $namedParameters['application'],
                    $namedParameters['parameter_name'],
                    $namedParameters['context']
                );
                break;
            case 'getAppIdentifierForIcon':
                $operatorValue = SolrSafeOperatorHelper::getAppIdentifierForIcon($namedParameters['application']);
                break;
            case 'getApplicationUrl':
                $operatorValue = SolrSafeOperatorHelper::getApplicationUrl($namedParameters['identifier']);
                break;
            case 'mappingNameSpe':
                $operatorValue = SolrSafeOperatorHelper::mappingNameSpe($namedParameters['specialtie']);
                break;
            case 'getMappingSpe':
                $operatorValue = SolrSafeOperatorHelper::getMappingSpe();
                break;
            case 'getCustomerTypes':
                $operatorValue = SolrSafeOperatorHelper::getCustomerTypes();
                break;
            case 'getMainSpecialities':
                $operatorValue = SolrSafeOperatorHelper::getMainSpecialities();
                break;
            case 'getUserSpecialities':
                $operatorValue = SolrSafeOperatorHelper::getUserSpecialities();
                break;
            case 'noSeoLink':
                $operatorValue = SolrSafeOperatorHelper::noSeoLink($operatorValue);
                break;
            case 'getTaxoTranslation':
                $operatorValue = SolrSafeOperatorHelper::getTaxoTranslation(
                    $namedParameters['identifier'],
                    $namedParameters['remote_id']
                );
                break;
            case 'cluster_ini':
                $operatorValue = SolrSafeOperatorHelper::clusterIni(
                    $namedParameters['section'],
                    $namedParameters['variable'],
                    $namedParameters['ini_file']
                );
                break;
            case 'truncateContentRelated':
                $operatorValue = SolrSafeOperatorHelper::truncateContentRelated($namedParameters['text']);
                break;
            case 'myCertificatesEnabled':
                $operatorValue = SolrSafeOperatorHelper::featureIsActive("MyCertificates");
                break;
            case 'appHasSpeciality':
                $operatorValue = SolrSafeOperatorHelper::appHasSpeciality();
                break;
            case 'setClusterIdentifier':
                // No $operatorValue modification is normal
                SolrSafeOperatorHelper::setClusterIdentifier($namedParameters['clusterIdentifier']);
                break;
            case 'featureIsActive':
                $operatorValue = SolrSafeOperatorHelper::featureIsActive($namedParameters['featureCode']);
                break;
            case 'feature':
                $operatorValue = SolrSafeOperatorHelper::feature(
                    $namedParameters['featureCode'],
                    $namedParameters['value']
                );
                break;
            case 'alphabet':
                $operatorValue = SolrSafeOperatorHelper::alphabet();
                break;
            case 'generateIso6391':
                $operatorValue = SolrSafeOperatorHelper::generateIso6391($namedParameters['regionalSettingsLocale']);
                break;
            case 'staticfile':
                $operatorValue = SolrSafeOperatorHelper::staticFile(
                    $operatorValue,
                    $namedParameters['quote'],
                    $namedParameters['skip_slash']
                );
                break;
            case 'showHelpDeskPhoneInHeader':
                $operatorValue = !(SolrSafeOperatorHelper::feature('HelpDeskSettings', 'HidePhoneNumberInHeader'));
                break;
            case 'showHelpDeskPhoneOnPage':
                $operatorValue = !(SolrSafeOperatorHelper::feature('HelpDeskSettings', 'HidePhoneNumberOnPage'));
                break;
            case 'getFooterHTML':
                $operatorValue = SolrSafeOperatorHelper::getFooterHTML($namedParameters['footerBlockIdentifier']);
                break;
            case 'getLocaleBySystemCode':
                $operatorValue = SolrSafeOperatorHelper::getLocaleBySystemCode($namedParameters['systemCode']);
                break;
            case 'buildExitUrl':
                $operatorValue = SolrSafeOperatorHelper::buildExitUrl($namedParameters['url']);
                break;
            case 'getUserToken':
                $operatorValue = SolrSafeOperatorHelper::getUserToken();
                break;
            case 'clusterHasFeaturedChannel':
                $operatorValue = SolrSafeOperatorHelper::clusterHasFeaturedChannel();
                break;
            case 'aliasDimensions':
                $operatorValue = SolrSafeOperatorHelper::aliasDimensions($namedParameters['alias']);
                break;
            case 'hasImageArticleFromSolr':
                $operatorValue = SolrSafeOperatorHelper::hasImageArticleFromSolr(
                    $namedParameters['solrdata'],
                    $namedParameters['media_case']
                );
                break;
            case 'getImageArticleUrl':
                $operatorValue = SolrSafeOperatorHelper::getImageArticleUrl(
                    $namedParameters['media_case'],
                    $namedParameters['object_id'],
                    $namedParameters['language'],
                    $namedParameters['alias']
                );
                break;
            case 'getImageArticleUrlFromSolr':
                $operatorValue = SolrSafeOperatorHelper::getImageArticleUrl(
                    $namedParameters['media_case'],
                    $namedParameters['solrdata']['object_id'],
                    $namedParameters['solrdata']['language'],
                    $namedParameters['alias']
                );
                break;
            case 'isHidden':
                $operatorValue = SolrSafeOperatorHelper::isHidden($namedParameters['contentobject_id']);
                break;
            case 'isObjectGloballyVisible':
                $operatorValue = SolrSafeOperatorHelper::isObjectGloballyVisible($namedParameters['contentobject_id']);
                break;
            case 'getClusterVisibilities':
                $operatorValue = SolrSafeOperatorHelper::getClusterVisibilities($namedParameters['contentobject_id']);
                break;
            case 'parseTranslationTagParams':
                $operatorValue = SolrSafeOperatorHelper::parseTranslationTagParams($namedParameters['params']);
                break;
            case 'isSendToColleagueDisabled':
                $operatorValue = SolrSafeOperatorHelper::featureIsActive('DisableSendToColleague')
                    ? SolrSafeOperatorHelper::feature('DisableSendToColleague', 'IsDisabled')
                    : false;
                break;
            case 'getListOfValueOptions':
                $operatorValue = SolrSafeOperatorHelper::getListOfValueOptions( $namedParameters['business_name'], $namedParameters['filter'] );
                break;
            case 'getListOfValues':
                $operatorValue = SolrSafeOperatorHelper::getListOfValues( $namedParameters['business_name'], $namedParameters['filter'] );
                break;
            case 'solrDateToStamp':
                $operatorValue = strtotime($namedParameters['date']) > 3600*24*2 ? SolrTool::getTimestampFromSolr($namedParameters['date']) : 0;
                break;
            case 'getSeoParam':
                $operatorValue = SolrSafeOperatorHelper::getSeoParam($namedParameters['applicationLocalized'], $namedParameters['name'], $namedParameters['params']);
                break;
            case 'applicationHasSeoSpeciality':
                $operatorValue = SolrSafeOperatorHelper::applicationHasSeoSpeciality($namedParameters['applicationIdentifier']);
                break;
            case 'seoIsEnabled':
                $operatorValue = SolrSafeOperatorHelper::seoIsEnabled($namedParameters['applicationIdentifier']);
                break;
            case 'includeEsi':
                $operatorValue = SolrSafeOperatorHelper::includeEsi( $namedParameters['src'], $namedParameters['debug'] );
                break;
            case 'imageDecHash':
                $operatorValue = SolrSafeOperatorHelper::imageDecHash( $operatorValue );
                break;
            case 'bannerDecHash':
                $operatorValue = SolrSafeOperatorHelper::bannerDecHash( $operatorValue );
                break;
            case 'getAndStoreGPNotebookHS':
                $operatorValue = self::getAndStoreGPNotebookHS( );
                break;
            case 'isPromoTaxonomyVisible':
                $operatorValue = SolrSafeOperatorHelper::isPromoTaxonomyVisible( $namedParameters['values'] );
                break;
            case 'translateTaxonomy':
                $operatorValue = SolrSafeOperatorHelper::translateTaxonomy( $namedParameters['code'] );
                break;
            case 'getPublisherArticleUrl':
                $operatorValue = SolrSafeOperatorHelper::getPublisherArticleUrl( $namedParameters['publisher'], $namedParameters['articleId'] );
                break;
        }
    }
    public function getTrial($trialId)
    {
        $detailsField = "attr_clinical_trials_details_s";
        $clusterIdentifier = ClusterTool::clusterIdentifier();
        $fields = array(
            'details' => $detailsField,
            'headline' => 'attr_headline_s',
            'online_date' => 'attr_date_dt',
            'recruitment_status' => 'subattr_recruitment_status___source_id____s',
            'conditions' => 'attr_clinical_trials_conditions_s',
            'gender' => 'subattr_gender___source_id____s',
            'min_age' => 'attr_clinical_trials_min_age_i',
            'max_age' => 'attr_clinical_trials_max_age_i',
            'country' => "attr_clinical_trials_country____s",
            'online_date_stamp' => 'attr_online_date_dt',
            'guid' => 'meta_guid_ms',
        );

        $fq = array(
            "attr_{$clusterIdentifier}_url_s: \"{$trialId}\"",
        );
        $params = array(
            'indent'        => 'on',
            'q'             => '*:*',
            'fq'            => implode(' AND ', $fq),
            'start'         => $this->offset,
            'rows'          => 1,
            'fl'            => implode(',',$fields),
            'qt'            => 'ezpublish',
            'explainOther'  => '',
            'hl.fl'         => '',
            'sort'          => "attr_online_date_dt desc",
        );

        $result =  SolrTool::rawSearch( $params, 'php', true, false );

        if ($result['response']['numFound'] <= 0)
        {
            return null;
        }

        $result = $result['response']['docs'][0];

        $doc = array();
        foreach ($fields as $mapping => $value)
        {
            $doc[$mapping] = $result[$value];
        }

        $doc['online_date'] = strtotime($doc['online_date']) > 3600*24*2 ? SolrTool::getTimestampFromSolr($doc['online_date']) : 0;
        $doc['details'] = json_decode($doc['details'], true);
        $doc['country'] = implode(', ', $doc['country']);
        foreach (array('update_date', 'register_date', 'enrollement_date') as $dateField)
        {
            $doc['details'][$dateField] = strtotime($doc['details'][$dateField]) > 3600*24*2 ? SolrTool::getTimestampFromSolr($doc['details'][$dateField]) : 0;
        }
        $doc['details']['secondary_outcome'] = implode(', ', $doc['details']['secondary_outcome']);
        $doc['details']['secondary_id'] = implode(', ', $doc['details']['secondary_id']);
        $doc['details']['secondary_sponsor'] = implode(', ', $doc['details']['secondary_sponsor']);

        $doc['id'] = $trialId;
        return $doc;

    }
    public function getChildOnly($node)
    {
        $fields = array_values(array_merge($this->mappingFieldsSolr, $this->additionnalTaxonomyFields));
        $n_id= $node->NodeID;

        $params = array(
            'indent'        => 'on',
            'q'             => '*:*',
            'fq'            => "meta_main_parent_node_id_si: {$n_id} AND attr_relative_depth_i: 1",
            'start'         => $this->offset,
            'rows'          => 4,
            'fl'            => implode(',',$fields),
            'qt'            => 'ezpublish',
            'explainOther'  => '',
            'hl.fl'         => '',
            'sort'          => "attr_online_date_dt desc",
        );

        $result = SolrTool::rawSearch($params);
        $result = $this->articleResult($result, array());

        return $result;
    }
    /**
     * @return array
     */
    public function getResponseSolr()
    {
        $applicationDictionaryRows = $this->prepareConfig();

        $forbiddenWords = NodeVisibilityCheck::getForbiddenWordsArray( $this->_cluster_identifier );
        $queryTerm = count($forbiddenWords) ? implode(' ', $forbiddenWords) : '*:*';

        foreach ( $applicationDictionaryRows as $applicationDictionaryRow )
        {
            // Get application node_id
            $applicationId = $applicationDictionaryRow['application_id'];

            /** @var ApplicationLocalized[] $_localApplication */
            $this->_localApplications[$applicationId] = CacheApplicationTool::buildLocalizedApplicationByApplication( $applicationId );

            $appLocalizedIsProper = ( $this->_localApplications[$applicationId] instanceof ApplicationLocalized );

            if ( !$appLocalizedIsProper )
            {
                eZDebug::writeError( sprintf( 'Cannot fetch localized application %s for cluster %s', $applicationId, $this->_cluster_identifier ), __FILE__ . '::' . __LINE__ );
                continue;
            }

            /* @type $validLanguages array */
            $newsletterStyle = $applicationDictionaryRow['newsletter_style'];
            $clusterSiteIni  = eZINI::fetchFromFile( "extension/{$this->_cluster_identifier}/settings/site.ini.append.php" );
            $validLanguages  = $clusterSiteIni->variable( 'RegionalSettings', 'SiteLanguageList' );

            // Common
            $fq = array(
                'meta_class_identifier_ms:"article"',
                '(attr_archive_date_dt:"1970-01-01T01:00:00Z" OR attr_archive_date_dt:[NOW TO *])',
                'meta_installation_id_ms:'.eZSolr::installationID(),
                'attr_is_invisible_' . $this->_cluster_identifier . '_b:false',
                'meta_language_code_ms:(' . implode( ' OR ', $validLanguages ) . ')',
            );
            
            $taxonomyList = json_decode( $applicationDictionaryRow['taxonomy_filter'], true );

            if(count($taxonomyList) > 0){
                foreach ($taxonomyList as $row) {
                    foreach($row as $taxonomyCategory => $taxonomies){
                        $taxonomies = array_map(function($value) { return '"' . $value . '"'; }, $taxonomies);
                        $fq[] = "subattr_{$taxonomyCategory}___source_id____s: (" . implode(',', $taxonomies) . ')';
                    }
                }
            }

            // NO SDK
            $publisherNodeIds = $this->_localApplications[$applicationId]->publisherNodeIds();
            if(count($publisherNodeIds) == 1 )
            {
                $newsletterStyle = $applicationDictionaryRow['newsletter_style'];

                $fq = array_merge($fq, array(
                    'meta_path_si:' . $publisherNodeIds[0],
                ));
            }
            elseif (count($publisherNodeIds) > 1 )
            {
                $publisherFilter = implode(' OR ', $publisherNodeIds);
                $newsletterStyle = $applicationDictionaryRow['newsletter_style'];

                $fq = array_merge($fq, array(
                        "meta_path_si:($publisherFilter)",
                    ));
            }
            /**
             * SDK Specific treatment; dead code for now
             *
                if ( $this->_localApplications[$applicationId] instanceof SDKApplication )
                {
                    // SDK application
                    $fq = array_merge($fq, array(
                        'subattr_local_application___source_id____s:' . $applicationId,
                        'is_sdk_b:true AND is_newsletter_b:true'
                    ));
                }
             *
             */

            // Solr query parameters
            $rows = 100000;
            $queryParams = array(
                'indent' => 'on',
                'q' => $queryTerm,
                'start' => 0,
                'rows' => $rows,
                'fq' => $fq,
                'fl' => array(
                    'attr_has_image_' . $this->_cluster_identifier . '_bst',
                    'meta_remote_id_ms',
                    'meta_node_id_si',
                    'meta_main_node_id_si',
                    'attr_featured_content_b',
                    'attr_date_dt',
                    'meta_path_string_ms',
                    'meta_language_code_ms',
                    'attr_view_counter_' . $this->_cluster_identifier . '_i',
                    'subattr_speciality___source_id____s',
                    'subattr_customer_type___source_id____s',
                    'meta_current_version_si',
                    'attr_promo_description_t',
                    'attr_author_t',
                    'attr_source_t',
                    'attr_online_date_dt',
                    'attr_headline_s',
                    'subattr_publisher_folder___source_id____s',
                    'attr_promo_headline_s',
                    'attr_'.$this->_cluster_identifier.'_remote_s',
                    'attr_'.$this->_cluster_identifier.'_node_remote_s',
                    //'attr_media_content_image_'.$this->_cluster_identifier.'____ms',
                    //'attr_promo_image_'.$this->_cluster_identifier.'_s',
                    'is_sdk_b',
                    'meta_url_alias_ms',
                    'attr_promo_headline_t',
                    'subattr_publisher_folder___source_id____s',
                    'meta_id_si',
                    'attr_media_content_types_' . ClusterTool::clusterIdentifier() . '_bst',
                    'attr_' . ClusterTool::clusterIdentifier() . '_url_s',
                    'attr_core_content_t',
                    'subattr_download_ressource___expiration_date____dt',
                    'attr_node_remote_s',
                    'attr_media_content_quiz_replies_' . $this->_cluster_identifier . '____ms',
                    'attr_media_content_quiz_points_' . $this->_cluster_identifier . '_i',
                    'attr_media_content_quiz_question_' . $this->_cluster_identifier . '_ms',
                ),
                'qt' => '',
                'explainOther' => '',
                'hl.fl' => '',
                'sort' => $this->_configuration['sort']
            );
            $publisherFilters = $this->_localApplications[$applicationId]->getPublishersFilter();
            if ( $publisherFilters )
            {
                $queryParams['fq'][] = $publisherFilters;
            }

            if ( !empty($this->_customerType) )
            {
                $customerTypeCondition = implode(',', $this->stringArrayToFilterQueryParam($this->_customerType));
                $queryParams['fq'][] = sprintf( 'subattr_customer_type___source_id____s:(%s)', $customerTypeCondition );
            }
            if ( !empty($this->_specialty) )
            {
                $specialtyCondition = implode(',', $this->stringArrayToFilterQueryParam($this->_specialty));
                $queryParams['fq'][] = sprintf( 'subattr_speciality___source_id____s:(%s)', $specialtyCondition );
            }
            if ( $applicationDictionaryRow["publisher"] )
            {
                $queryParams['fq'][] = sprintf( 'subattr_publisher_folder___source_id____s:(%s)', $applicationDictionaryRow["publisher"] );
            }

            if ( $newsletterStyle == 'PICL' )
            {
                $queryParams['fq'][] = 'subattr_media_type___source_id____s:107.2';
            }

            //taxonomies
            $taxonomies = $this->getApplicationTaxonomies($applicationDictionaryRow['feed_id']);
            $firstCategory = reset(array_keys($taxonomies));
            $queryTaxonomies = '';
            foreach($taxonomies as $categorie=>$taxonomie)
            {
                if($categorie != $firstCategory)
                {
                    $queryTaxonomies .= ' AND ';
                }
                $queryTaxonomies .= 'subattr_' . $categorie . '___source_id____s:(' . $taxonomie . ')';
            }

            if($queryTaxonomies != '')
            {
                $queryParams['fq'][] = $queryTaxonomies;
            }

            $queryParamsFqFallback = $queryParams['fq'];
            $rowValueKey           = '';

            // different sort and filters by mechanism
            switch ($applicationDictionaryRow["mechanism"]) {
                case 1:
                    $rowValueKey = 'number_article_list';
                    $queryParams['sort'] = implode( ', ', $queryParams['sort'] );

                    //if begin/end date is set
                    if(!empty($this->_beginDate) && !empty($this->_endDate))
                    {
                        $queryParams['fq'][] = 'attr_online_date_dt:[' . $this->_beginDate . ' TO ' . $this->_endDate . ']';
                    }
                    else
                    {
                        $queryParams['fq'][] = sprintf( 'attr_online_date_dt:[NOW-%sDAY TO *]', $this->_configuration['days'] );
                    }
                    break;
                case 2:
                    $rowValueKey = 'number_article_random';
                    $oneHourRandom = floor(time() / 3600);
                    $queryParams['sort'] = 'attr_' . $oneHourRandom . '_random asc';
                    break;
                case 4:
                    $rowValueKey = 'number_article_last_x';
                    $queryParams['sort'] = "attr_online_date_dt desc";
                    $queryParams['fq'][] = 'attr_online_date_dt:[NOW-7DAY TO *]';

                    //if begin/end date is set
                    if(!empty($this->_beginDate) && !empty($this->_endDate))
                    {
                        $queryParams['fq'][] = 'attr_online_date_dt:[' . $this->_beginDate . ' TO ' . $this->_endDate . ']';
                    }
                    else
                    {
                        $queryParams['fq'][] = sprintf( 'attr_online_date_dt:[NOW-%sDAY TO *]', $this->_configuration['days'] );
                    }
                    break;
                case 5:
                    $rowValueKey = 'number_article_list';
                    if(!empty($this->_beginDate) && !empty($this->_endDate))
                    {
                        $queryParams['fq'][] = 'attr_online_date_dt:[' . $this->_beginDate . ' TO ' . $this->_endDate . ']';
                    }
                    $queryParams['sort'] = implode( ', ', $queryParams['sort'] );
                    if( $applicationDictionaryRow['number_article_ns'] )
                    {  
                        $queryParams['rows'] = (int)$applicationDictionaryRow['number_article_ns'];
                    }
                    else
                    {
                         $queryParams['rows'] = 100;
                    }
                    break;
            }

            if ( (int) $applicationDictionaryRow[$rowValueKey] >= 0 )
            {
                $queryParams['rows'] = (int) $applicationDictionaryRow[$rowValueKey];
            }

            $queryParams['fl'] = implode( ',', $queryParams['fl'] );
            $queryParams['fq'] = implode( ' AND ', $queryParams['fq'] );

            // main fetch solr
            $result = SolrTool::rawSearch( $queryParams, 'php', false );
            if ( !isset( $result['response']['docs'] ) )
            {
                eZDebug::writeError( 'Error from Solr for query : ' . $result['params']['fq'], __FILE__ . '::' . __LINE__ );
                if( php_sapi_name() != 'cli' )
                {
                    header( 'HTTP/1.x 500 Internal Server Error' );
                    eZExecution::cleanExit();
                }
            }
            if ( count($result['response']['docs']) == 0 && $applicationDictionaryRow['mechanism'] == 5)
            {
                $queryParams['fq'] = $queryParamsFqFallback;
                $queryParams['sort'] = array(
                    'attr_featured_content_b desc',
                    'attr_online_date_dt desc',
                );

                $queryParams['sort'] = implode( ', ', $queryParams['sort'] );

                //if begin/end date is set
                if(!empty($this->_beginDate) && !empty($this->_endDate))
                {
                    $queryParams['fq'][] = 'attr_online_date_dt:[' . $this->_beginDate . ' TO ' . $this->_endDate . ']';
                }
                $queryParams['fq'] = implode( ' AND ', $queryParams['fq'] );
                $result = SolrTool::rawSearch( $queryParams, 'php', false );
            }

            // if no result fallback for mechanism 3
            if ( count( $result['response']['docs'] ) == 0 && $applicationDictionaryRow["mechanism"] == 3 )
            {
                $queryParams['fq'] = $queryParamsFqFallback;
                $queryParams['fq'] = implode( ' AND ', $queryParams['fq'] );
                if ( (int) $applicationDictionaryRow['number_article_random'] >= 0 )
                {
                    $queryParams['rows'] = (int) $applicationDictionaryRow['number_article_random'];
                }
                else
                {
                    $queryParams['rows'] = $rows;
                }
                $oneHourRandom = floor(time() / 3600);
                $queryParams['sort'] = 'attr_' . $oneHourRandom . '_random asc';

                $result = SolrTool::rawSearch( $queryParams, 'php', false );
                if ( !isset( $result['response']['docs'] ) )
                {
                    eZDebug::writeError( 'Error from Solr for query : ' . $result['params']['fq'], __FILE__ . '::' . __LINE__ );
                    if( php_sapi_name() != 'cli' )
                    {
                        header( 'HTTP/1.x 500 Internal Server Error' );
                        eZExecution::cleanExit();
                    }
                }
            }

            $articles = $result['response']['docs'];

            // if mechanism 4, we need to have articles also from previous week
            if($applicationDictionaryRow["mechanism"] == 4)
            {
                $queryParams['fq'] = $queryParamsFqFallback;
                $queryParams['fq'][] = 'attr_online_date_dt:[NOW-14DAY TO NOW-7DAY]';
                $oneHourRandom = floor(time());
                $queryParams['sort'] = 'attr_' . $oneHourRandom . '_random asc';

                $queryParams['fq'] = implode( ' AND ', $queryParams['fq'] );
                $queryParams['rows'] = (int) $applicationDictionaryRow['number_article_random_y'];

                $resultRandom = SolrTool::rawSearch( $queryParams, 'php', false );
                if ( !isset( $resultRandom['response']['docs'] ) )
                {
                    eZDebug::writeError( 'Error from Solr for query : ' . $result['params']['fq'], __FILE__ . '::' . __LINE__ );
                    if( php_sapi_name() != 'cli' )
                    {
                        header( 'HTTP/1.x 500 Internal Server Error' );
                        eZExecution::cleanExit();
                    }
                }

                if(count($resultRandom['response']['docs'])) {
                    $articles = array_merge($articles, $resultRandom['response']['docs']);
                }
            }

            $this->_applicationsData[$applicationId][] = array(
                'articles'                    => $articles,
                'applicationDictionaryRow'    => $applicationDictionaryRow
            );
        }

        return $this->_applicationsData;
    }
    /**
     * @param int $remoteId
     * @return array
     */
    protected function getPreviousAndNextQuizzes( $remoteId )
    {
        $filters = array();

        $this->initResultHandler();

        $quizSolrData = SolrSafeOperatorHelper::getSolrData(
            $remoteId,
            ClusterTool::clusterIdentifier(),
            array(
                'online-date' => 'attr_online_date_dt',
                'node-ids'    => 'meta_node_id_si'
            )
        );

        $filters['default']  = $this->resultHandler->solrFilter();
        $filters['date']     = 'attr_online_date_dt:[' . $quizSolrData['online-date'] . ' TO NOW]';
        $filters['exclNIDs'] = '-meta_node_id_si:(' . implode( ' OR ', $quizSolrData['node-ids'] ) . ')';

        $params = array(
            'indent'        => 'on',
            'q'             => '',
            'fq'            => implode( ' AND ', $filters ),
            'start'         => 0,
            'rows'          => 1,
            'fl'            => implode( ',', array_values( array_merge( $this->resultHandler->mappingFieldsSolr, $this->resultHandler->additionnalTaxonomyFields ) ) ),
            'qt'            => 'ezpublish',
            'explainOther'  => '',
            'hl.fl'         => '',
            'sort'          => 'attr_online_date_dt asc',
        );

        $nextResult = $this->resultHandler->articleResult( SolrTool::rawSearch( $params ), array() );

        $filters['date'] = 'attr_online_date_dt:[' . $quizSolrData['online-date'] . '-1YEAR TO ' . $quizSolrData['online-date'] . ']';
        $params['fq']    = implode( ' AND ', $filters );
        $params['sort']  = 'attr_online_date_dt desc';

        $prevResult = $this->resultHandler->articleResult( SolrTool::rawSearch( $params ), array() );

        return array(
            'next'     => $nextResult['article_informations']['articles_solrdata'][$nextResult['article_informations']['articles'][0]]['url'],
            'previous' => $prevResult['article_informations']['articles_solrdata'][$prevResult['article_informations']['articles'][0]]['url']
        );
    }
    /**
     * @param array|string $applications
     * @param int $offset
     * @param string|bool $template
     * @param bool $ordered
     * @return array
     */
    protected function fetchUserSelection( $applications = null, $offset = null, $template = false, $ordered = false )
    {
        header("Cache-Control: no-cache, must-revalidate");

        if( is_null( $applications ) && isset( $_POST['applications'] ) && $_POST['applications'] != 'null' )
        {
            $applications =  $_POST['applications'];
        }

        //TODO white liste to templates ?
        if( isset( $_POST['template'] ) )
        {
            $template = $_POST['template'];
        }

        if( isset( $_POST['ordered'] ) )
        {
            $ordered = $_POST['ordered'];
        }

        $elearningStatuses = isset( $_POST['st'] ) ? $_POST['st'] : null;

        if( !is_null($elearningStatuses) )
        {
            if( !is_array($applications) )
                $applications = array( 'e-learning' );
            else
                $applications[] = 'e-learning';
        }

        if(in_array("-1", $applications))
            $applications = null;

        if( is_null( $offset ) )
            $offset = isset( $_POST['offset'] ) ? $_POST['offset'] : 0;

        $managedResults = $this->manageResults( MMSelections::fetchUserSelectionByApps( null, null, $applications, $elearningStatuses, $ordered ), $offset );
        $articles       = array();
        $fields         = array(
            'headline'          => 'attr_headline_s',
            'object_id'         => 'meta_id_si',
            'language'          => 'meta_language_code_ms',
            'has_image'         => 'attr_has_image_'.ClusterTool::clusterIdentifier().'_bst',
            'url'               => 'attr_' .  ClusterTool::clusterIdentifier() . '_url_s',
            'publisher_path'    => 'subattr_publisher_folder___source_id____s',
            'app_identifiers'   => 'subattr_parent_application___identifier____s'
        );

        /** @var String[][] $applicationUrls */
        $applicationsUrl = array();

        /** @var MMSelections $item */
        foreach($managedResults["items"] as $item)
        {
            $remote  = $item->attribute("remote_id");
            $locale  = LocaleTool::mainLanguage();
            $cluster = $item->attribute("cluster_identifier");

            $article = array(
                "description"        => $item->attribute("description"),
                "remote_id"          => $remote,
                "cluster_identifier" => $cluster,
                "application"        => $item->attribute("application"),
                "add_date"           => $item->attribute("add_date"),
                "is_visible"         => $item->attribute('is_visible'),
            );

            $fqPrimaryLanguage = implode(" AND ", array(
                "meta_remote_id_ms:".$remote,
                "meta_language_code_ms:".$locale
            ));

            $fqSecondaryLanguages = implode(" AND ", array(
                "meta_remote_id_ms:".$remote,
                "-meta_language_code_ms:".$locale,
                "-meta_available_language_codes_ms:".$locale,
            ));

            $params = array(
                'indent'        => 'on',
                'q'             => '',
                'start'         => 0,
                'rows'          => 1,
                'fq'            => "(($fqPrimaryLanguage) OR ($fqSecondaryLanguages))",
                'fl'            => implode(',', array_values($fields)),
                'qt'            => 'ezpublish',
                'explainOther'  => '',
                'hl.fl'         => '',
            );
            $raw = SolrTool::rawSearch($params);

            if(isset($raw["response"]["docs"][0]))
            {
                $rawArticle = $raw["response"]["docs"][0];

                $applicationIdentifier  = $item->attribute("application");
                $publisherPath          = $rawArticle[$fields["publisher_path"]][0];
                $publisherInfo          = PublisherFolderTool::getPathToIDMapping($publisherPath);
                $publisherFolderId      = $publisherInfo['pfid'];

                if( !in_array($applicationIdentifier, $applicationsUrl))
                {
                    $application = CacheApplicationTool::buildLocalizedApplicationByIdentifier( $applicationIdentifier );
                    
                    if ( $application instanceof ApplicationLocalized )
                    {
                        $applicationObject = $application->applicationObject();

                        $applicationsUrl[$applicationIdentifier]["url"] = $application->attribute('url_alias');
                        $applicationsUrl[$applicationIdentifier]["type"] = $applicationObject->applicationType()->attribute('type_identifier');
                    }
                    else
                    {
                        continue;
                    }
                }

                // since publisher refactor, we don't use the url in mm_selection_remote anymore, we use the url from solr instead
                $url = $rawArticle[$fields["url"]];

                switch ( $applicationsUrl[$applicationIdentifier]["type"] ) {
                    case 'evrika-calendar':
                    case 'clinical-trials':
                        $url = $applicationsUrl[$applicationIdentifier]["url"] . '/' . $url;
                        break;
                    case 'first-child':
                        $url = $applicationsUrl[$applicationIdentifier]["url"];
                        break;
                    default:
                        $url = $applicationsUrl[$applicationIdentifier]["url"] . '/' . $publisherFolderId . '/' . $url;
                }
                $additionnalFields = array(
                    "name"      => $rawArticle[$fields["headline"]],
                    "url"       => $url,
                    "object_id" => $rawArticle[$fields["object_id"]],
                    "language"  => $rawArticle[$fields["language"]],
                    "has_image" => json_decode( base64_decode($rawArticle[$fields["has_image"]]) ),
                );

                $article = array_merge($additionnalFields, $article);
            }

            $articles[] = $article;
        }

        $tpl = $this->tpl();
        $tpl->setVariable( 'my_selection_list', array( 'items' => $articles ) );
        $tpl->setVariable( 'facets', $managedResults['facets'] );

        if(!$template)
        {
            return array(
                'content' => array(
                    'articles'    => $tpl->fetch( 'design:esibuild/app_content/my-selection/line.tpl' ),
                    'articles_nb' => count($articles),
                    'num_found'   => $managedResults['total'],
                    'f'           => $tpl->fetch( 'design:esibuild/app_content/my-selection/facet_line.tpl' )
                )
            );
        }
        else
        {
            return array(
                'content' => array(
                    'articles'    => $tpl->fetch( 'design:esibuild/app_content/my-selection/' . $template . '_line.tpl' ),
                    'articles_nb' => count($managedResults['items']),
                    'num_found'   => $managedResults['total'],
                    'f'           => $tpl->fetch( 'design:esibuild/app_content/my-selection/facet_line.tpl' )
                )
            );
        }
    }
    /**
     * @param eZContentObjectTreenode $node
     * @param array $row
     * @return array
     */
    protected static function nodeHasForbiddenWords( &$node, &$row )
    {
        /* @type $clustersToHide array */
        $clustersToHide = eZINI::instance( 'merck.ini' )->variable( 'PublishSettings', 'clustersToHide' );
        $returnArray    = array();
        
        foreach ($clustersToHide as $cluster)
        {
            /* @type $languageList array */
            $clusterIni = eZINI::fetchFromFile( "./extension/$cluster/settings/site.ini" );
            $languageList = $clusterIni->variable('RegionalSettings', 'SiteLanguageList');
        
            foreach( $languageList as $locale )
            {
                /* @type $nodeDatamap eZContentObjectAttribute[] */
                $nodeDatamap = $node->object()->fetchDataMap(false, $locale);

                if( !$nodeDatamap )
                    continue;

                if( $nodeDatamap['forbidden_article']->attribute('data_int') == 1 )
                {
                    // node is marked from publisher as containing some forbidden words = we hide
                    $returnArray[$cluster] = array(
                        'toHide'   => true,
                        'toDelete' => true,
                        'comment'  => 'marked by publisher',
                    );
                    break;
                }
                
                $forbiddenWordsArray = self::getForbiddenWordsArray($cluster);

                if(empty($forbiddenWordsArray))
                {
                    $returnArray[$cluster] = array(
                        'toHide'   => false,
                        'toDelete' => true,
                        'comment'  => 'no forbidden words on cluster',
                    );
                    continue;
                }

                $lgExplode      = explode('-', $locale);
                $languageFilter = $lgExplode[0] . '-*';

                $params = array(
                            'indent'   => 'on',
                            'qt'       => 'standard',
                            'q'        => '*:*',
                            'start'    => 0,
                            'stop'     => 0,
                            'fq'       => implode(' AND ', array(
                                'meta_node_id_si:'.$node->attribute('node_id'),
                                'meta_language_code_ms:'.$languageFilter,
                                'meta_installation_id_ms:'.eZSolr::installationID()
                    )),
                );

                $isInSolrResult = SolrTool::rawSearch($params, 'php', false);

                if( !$isInSolrResult['response']['numFound'] )
                {
                    // the node is not in solr. We postpone its check
                    if( $row['created'] < time() - 3600 * 4 )
                    {
                        // the node was added more than 4 hours ago. It should be in solr. We ask for a reindex
                        eZSearch::addObject( $node->object() );

                        $returnArray[$cluster] = array(    
                            'toHide'   => true,
                            'toDelete' => false,
                            'comment'  => 'not indexed in solr yet',
                        );
                        break;
                    }

                    if( $row['created'] < time() - 3600 * 48 )
                    {
                        eZLog::write( sprintf( "%s\t Node %s still not in solr after 48h", date('Y-m-d H:i:s'), $node->attribute('node_id') ), 'updatevisibility.log' );
                        $returnArray[$cluster] = array(
                            'toHide'   => true,
                            'toDelete' => true,
                            'comment'  => 'node is taking too long to be indexed',
                        );
                        break;
                    }
                }

                $params['q'] = implode(' ', $forbiddenWordsArray);
                $solrResults = SolrTool::rawSearch($params, 'php', false);

                if( !$solrResults['response']['numFound'] )
                {
                    // content has forbidden words => we hide
                    $returnArray[$cluster] = array(
                        'toHide'   => true,
                        'toDelete' => true,
                        'comment'  => 'has forbidden words',
                    );
                    break;
                }            
            }

            if ( !isset($returnArray[$cluster]) )
            {
                $returnArray[$cluster] = array(
                    'toHide'   => false,
                    'toDelete' => true,
                    'comment'  => 'default case'
                );
            }
        }
        
        return $returnArray;
    }
 protected function searchInFront()
 {
     $filters = array(
         '(attr_archive_date_dt:"1970-01-01T01:00:00Z" OR attr_archive_date_dt:[NOW TO *])',
         'meta_class_identifier_ms:article',
         'meta_installation_id_ms:' . eZSolr::installationID(),
         'attr_is_invisible_' . ClusterTool::clusterIdentifier() . '_b:false'
     );
     $results = SolrTool::rawSearch( array(
         'indent'       => 'on',
         'q'            => $this->keyword,
         'fq'           => implode( ' AND ', $filters ),
         'start'        => 0,
         'rows'         => 10,
         'fl'           => 'attr_headline_s',
         'qt'           => 'ezpublish',
         'explainOther' => '',
         'hl.fl'        => '',
         'sort'         => "score desc"
     ) );
     if( $results['response']['numFound'] > 0 )
     {
         foreach( $results['response']['docs'] as $doc )
         {
             if( trim( $doc['attr_headline_s'] ) == $this->keyword )
             {
                 $this->article->setAttribute( 'date_front', time() );
                 if( !is_null( $this->article->attribute( 'date_newsletter' ) ) )
                 {
                     $this->article->setAttribute( 'new_relic_report', 1 );
                     $this->reportToNewRelic( $this->newRelicMetricName, 0 );
                 }
                 $this->article->store();
                 break;
             }
         }
     }
 }
    private function getArticleHierarchyWithoutTaxonomy($nodeID)
    {
        $hierarchy = array(
            "title" => ezpI18n::tr("merck", "TABLE OF CONTENTS"),
            "articles" => array()
        );

        $node = eZContentObjectTreeNode::fetch($nodeID);

        $parent = $this->getArticleParent($node);
        if(!$parent->isMain())
        {
            $parent = eZContentObjectTreeNode::fetch($parent->attribute("main_node_id"));
        }

        if(!$parent)
        {
            return $hierarchy;
        }

        $solrFilter = $this->_application->getResultHandler()->solrFilter(false, false);
        if( $solrFilter )
            $filters[] = $solrFilter;

        $filters[] = sprintf('main_node_meta_path_string_ms:%s*', $parent->attribute("path_string"));

        $params = array(
            'indent'        => 'on',
            'q'             => '',
            'start'         => 0,
            'rows'          => 100,
            'fq'            => implode(' AND ' , $filters),
            'fl'            => 'attr_'.ClusterTool::clusterIdentifier().'_url_s,attr_headline_s,meta_main_node_id_si,main_node_meta_path_string_ms,attr_relative_depth_i,subattr_publisher_folder___source_id____s',
            'qt'            => 'ezpublish',
            'sort'          => 'main_node_meta_priority_si asc',
            'explainOther'  => '',
            'hl.fl'         => '',
        );

        return $this->parseSolrResponse(SolrTool::rawSearch( $params ), $hierarchy);
    }
    public static function getPublisherArticleUrl($publisher, $articleId)
    {
        $fields = array(
            'apps' => 'subattr_local_application___source_mixed____s',
            'url'  => 'attr_'.ClusterTool::clusterIdentifier().'_url_s',
            'publisher_path' => 'subattr_publisher_folder___source_id____s',
        );

        $fq = array(
            "subattr_publisher_folder___source_id____s: \"{$publisher}\"",
            "attr_publisher_internal_id_s: \"{$articleId}\"",
        );

        $params = array(
            'indent'        => 'on',
            'q'             => '',
            'start'         => 0,
            'rows'          => 1,
            'fq'            => implode(' AND ', $fq),
            'fl'            => implode(',', array_values($fields)),
            'qt'            => 'ezpublish',
            'explainOther'  => '',
            'hl.fl'         => '',
        );

        $raw = SolrTool::rawSearch($params);
        if ($raw['response']['numFound'] == 0)
        {
            return null;
        }
        $row = $raw['response']['docs'][0];

        $solrApplicationIndexes = $row[$fields['apps']];
        $solrApplicationIdentifiers = array();
        $solrApplicationNames = array();

        foreach( $solrApplicationIndexes as $applicationIndex )
        {
            list ( $cluster, /* unused */, $applicationId ) = explode( '##', $applicationIndex );

            if ( $cluster == ClusterTool::clusterIdentifier() )
            {
                $app = CacheApplicationTool::buildLocalizedApplicationByApplication( $applicationId );

                if ( !($app instanceof ApplicationLocalized) )
                    continue;

                $solrApplicationNames[] = $app->attribute('name');
                $solrApplicationIdentifiers[] = $app->applicationObject()->attribute('identifier');
            }
        }

        if (empty($solrApplicationIdentifiers))
        {
            return;
        }
        $applicationIdentifier = $solrApplicationIdentifiers[0];
        $application = CacheApplicationTool::buildLocalizedApplicationByIdentifier( $applicationIdentifier );
        $applicationObject = $application->applicationObject();
        $applicationType = $applicationObject->applicationType()->attribute('type_identifier');
        $publisherPath = $row[$fields['publisher_path']][0];
        $publisherInfo = PublisherFolderTool::getPathToIDMapping($publisherPath);
        $publisherFolderId = $publisherInfo['pfid'];

        $url = isset( $row[$fields['url']] ) ? $row[$fields['url']] : null;

        $url = ($applicationType == 'first-child')
            ? $application->attribute('url_alias')
            : $application->attribute('url_alias') . '/' . $publisherFolderId . '/' . $url;

        return $url;
    }
 /**
  * @param array $params
  * @param bool $includeSynonmys
  * @return array
  */
 protected static function fetchFromSolr( $params, $includeSynonmys = true )
 {
     $solrResult = SolrTool::rawSearch( $params, 'php', false );
     
     $results = array();
     $conceptIds = array();
     
     foreach( $solrResult['response']['docs'] as $row )
     {
         $results[$row['attr_term_t']] = $row['attr_id_l'];
         $conceptIds[$row['attr_concept_id_l']] = true;
     }
     
     if( empty( $conceptIds) || empty( $results ) )
         return array();
     
     if( $includeSynonmys )
     {
         // we include the synonmys
         foreach( self::fetchObjectList(
                     self::definition(),
                     null,
                     array( 'concept_id' => array( array_keys( $conceptIds ) ) ),
                     null,
                     null,
                     false,
                     null,
                     null,
                     null,
                     " AND id NOT IN (".implode( ', ', $results ).")" ) as $row 
         ){
             $results[$row['term']] = $row['id'];
         }
     }
     
     return array_keys( $results );
 }
    /**
     * i18n operator works like : source|context([argument1, argument2 ...])
     * Arguments are optional and are comma separated
     *
     * @return Callable[]
     *
     * Examples :
     *
     * Simple without argument:
     * {{# i18n }}
     *   MORE|merck()
     * {{/ i18n }}
     *
     * Or with argument:
     * {{# i18n }}
     *   %nb RESULTS|merck(3)
     * {{/ i18n }}
     */
    private static function getHelpers($application = null)
    {
        return array(
            'i18n' => function($text) {
                preg_match("#(?<source>[^\|]+)\|(?<context>[^(]+)\((?<params>[^\)]+)?\)#", $text, $m);
                if($m && $m["source"] && $m["context"])
                {
                    $arguments = array();
                    if($m["params"])
                    {
                        $params = explode(",", $m["params"]);
                        preg_match_all("#(?<arguments>%\w+)#", $m["source"], $mParams);
                        if($mParams && $mParams["arguments"])
                        {
                            for($i = 0; $i < count($mParams["arguments"]); $i++)
                            {
                                $arguments[$mParams["arguments"][$i]] = $params[$i];
                            }
                        }
                    }

                    return ezpI18n::tr($m["context"], $m["source"], null, $arguments);
                }
                return $text;
            },
            'taxonomies_filter' => function($text) use ($application) {
                $filterTaxonomies = $application->getCustomParameter('TaxonomiesFilter');

                $html = '';
                foreach($filterTaxonomies as $category)
                {
                    $taxonomies = FacetFilteringTool::getTaxonomyTranslationsByCategory($category);
                    $tpl = eZTemplate::factory();

                    $tpl->setVariable('taxonomies', $taxonomies);
                    $tpl->setVariable('category', $category);
                    $html .= $tpl->fetch( 'design:esibuild/app_content/channel/filter.tpl' );
                }
                return $html;
            },
            'editors_choice_content' => function($text) use ($application) {
                $taxonomyCategory = $application->getCustomParameter('EditorsChoiceFilter');
                $taxonomyValue = $application->getCustomParameter('EditorsChoiceValue');
                $limit = $application->getCustomParameter('EditorsChoiceLimit');
                $html = '';
                $language = eZINI::instance('site.ini')->variable('RegionalSettings', 'ContentObjectLocale');

                $fields = array(
                    'node_id'              => 'meta_node_id_si',
                    'object_id'            => 'meta_id_si',
                    'language'             => 'meta_language_code_ms',
                    'url'                  => 'attr_'.ClusterTool::clusterIdentifier().'_url_s',
                    'headline'             => 'attr_headline_s',
                    'promo_description'    => 'attr_promo_description_t',
                    'rating'               => 'attr_content_rating_'.ClusterTool::clusterIdentifier().'_f',
                    'views'                => 'attr_view_counter_'.ClusterTool::clusterIdentifier().'_i',
                    'app_identifiers'      => 'subattr_parent_application___identifier____s',
                    'apps'                 => 'subattr_local_application___source_mixed____s',
                    'app_id'               => 'subattr_local_application___source_id____s',
                    'online_date'          => 'attr_online_date_dt',
                    'score'                => 'score',
                    'publisher_path'       => 'subattr_publisher_folder___source_id____s',
                    'has_image'            => 'attr_has_image_'.ClusterTool::clusterIdentifier().'_bst',
                    'media_types'          => 'attr_media_content_types_'.ClusterTool::clusterIdentifier().'_bst',
                    'internal_id'          => 'attr_publisher_internal_id_s',
                    'link_url'             => 'attr_media_content_link_'.ClusterTool::clusterIdentifier().'____ms'
                );
                $filters = array(
                    "subattr_{$taxonomyCategory[0]}___source_id____s: \"{$taxonomyValue[0]}\"",
                    "meta_language_code_ms: \"{$language}\""
                );
                    
                $params = array(
                    'indent'        => 'on',
                    'q'             => '*:*',
                    'fq'            => implode(' AND ' , $filters),
                    'start'         => '0',
                    'rows'          => $limit,
                    'fl'            => implode(',',$fields),
                    'qt'            => 'ezpublish',
                    'explainOther'  => '',
                    'hl.fl'         => '',
                    'sort'          => "attr_online_date_dt desc",
                );
                
                $result = SolrTool::rawSearch($params);
                foreach ($result[response][docs] as $key => $value) {
                    
                    $result[response][docs][$key]['headline'] = $value['attr_headline_s'];
                    $result[response][docs][$key]['node_id'] = $value['meta_node_id_si'];
                    $result[response][docs][$key]['object_id'] = $value['meta_id_si'];
                    $result[response][docs][$key]['language'] = $value['meta_language_code_ms'];
                    $result[response][docs][$key]['promo_description'] = $value['attr_promo_description_t'];
                    
                    $app = CacheApplicationTool::buildLocalizedApplicationByApplication( $value['subattr_local_application___source_id____s'][0] );
                    $applicationObject = $app->applicationObject();
                    $applicationType   = $applicationObject->applicationType()->attribute('type_identifier');
                    $result[response][docs][$key]['application_name'] = $app->attribute('url_alias');
                    
                    $publisherPath = $value['subattr_publisher_folder___source_id____s'][0];
                    $publisher = PublisherFolder::getPublisherFromPath($publisherPath);
                    $publisherFolderId = $publisher->getTranslation()->attribute('publisher_folder_id');
                    $publisherName = $publisher->getTranslation()->attribute('name');
                    $result[response][docs][$key]['publisher_name'] = $publisherName;
                                  
                    $url = $value['attr_'.ClusterTool::clusterIdentifier().'_url_s'];
                    $url = ($applicationType == 'first-child')
                        ? $app->attribute('url_alias')
                        : $app->attribute('url_alias') . '/' . $publisherFolderId . '/' . $url;
                    $result[response][docs][$key]['url'] = $url;
                    $result[response][docs][$key]['online_date'] = solrTool::getDateFromSolr($value['attr_online_date_dt']);
                    $result[response][docs][$key]['publisher_name'] = $publisherName;
                    
                    $result[response][docs][$key]['has_image'] = json_decode( base64_decode($value['attr_has_image_'.ClusterTool::clusterIdentifier().'_bst']), true );
                    $mediaCase = ImageArticleTool::NEWS_APPLICATION_CASE;
                    $hasImage = $result[response][docs][$key]['has_image'][$mediaCase];
                    if ($hasImage) {
                        $result[response][docs][$key]["dt_url"] = SolrSafeOperatorHelper::getImageArticleUrl($mediaCase, $result[response][docs][$key]['object_id'], $result[response][docs][$key]['language'], 'dt_full');
                        $result[response][docs][$key]["mb_url"] = SolrSafeOperatorHelper::getImageArticleUrl($mediaCase, $result[response][docs][$key]['object_id'], $result[response][docs][$key]['language'], 'm_full');
                    }

                }
                
                $tpl = eZTemplate::factory();
                $tpl->setVariable('editorsChoice', $result);
                $html .= $tpl->fetch( 'design:esibuild/app_content/channel/editors_choice.tpl' );
                
                return $html;
            }
        );
    }
    /**
     * @param bool $force
     * @return array
     */
    public function contentResultMain( $force = false )
    {
        $filters            = array();
        $solrFilter         = $this->solrFilter();
        $solrFacetsFiler    = $this->solrFacetsFilter();

        if( $solrFilter )
            $filters[] = $solrFilter;

        if( $solrFacetsFiler )
            $filters[] = $solrFacetsFiler;

        $headlineSortKey = SolrSafeOperatorHelper::clusterIni( 'ContentListApplicationSettings' , 'HeadlineSortKey', 'merck.ini' );
        $headlineSortKey = empty( $headlineSortKey ) ? 'attr_headline_lc_s' : $headlineSortKey;
        $sort            = '';
        // TODO: check if this check is needed:
        $rootNodeIds = $this->rootNodeIds;
        if ( isset( $this->rootNodeIds[0] ) && is_array( $this->rootNodeIds[0] ) ) {
            $rootNodeIds = $this->rootNodeIds[0];
        }

        switch ( $this->sortBy )
        {
            case self::SORT_BEST_MATCH:
                if ( trim($this->searchQuery) != '' )
                    $sort = "score desc, {$headlineSortKey} asc";
                break;
            case self::SORT_MOST_POPULAR:
                header( 'x-ez-most-popular-node: ' . 'P' . implode('PP', $rootNodeIds) . 'P' );
                $sort = 'attr_content_rating_'.ClusterTool::clusterIdentifier()."_f desc, {$headlineSortKey} asc";
                break;
            case self::SORT_MOST_VIEWED:
                header( 'x-ez-most-view-node: ' . 'P' . implode('PP', $rootNodeIds) . 'P' );
                $sort = 'attr_view_counter_'.ClusterTool::clusterIdentifier()."_i desc, {$headlineSortKey} asc";
                break;
            case self::SORT_ALPHABETICAL:
                $sort = "{$headlineSortKey} asc";
                break;
            case self::SORT_MOST_RECENT:
                // default sort
            default:
                // no sort provided - we default to most recent
                $sort = "attr_date_dt desc, {$headlineSortKey} asc";
                break;
        }

        $fields = array(
            'attr_headline_t',
            'attr_promo_description_t',
            'attr_'.ClusterTool::clusterIdentifier().'_url_s',
            'subattr_local_application___source_id____s',
            'subattr_local_application___source_mixed____s',
            'subattr_publisher_folder___source_id____s',
            'attr_trip_speciality_s',
            'attr_trip_publication_t',
            'attr_trip_external_url_s',
            'attr_date_dt'
        );

        $searchQuery = isset( $_REQUEST['q'] ) ? strip_tags( $_REQUEST['q'] ) : '*:*';

        $params = array(
            'indent'        => 'on',
            'q'             => $searchQuery,
            'fq'            => implode(' AND ' , $filters),
            'start'         => $this->offset,
            'rows'          => $this->limit,
            'fl'            => implode(',', $fields),
            'qt'            => '',
            'explainOther'  => '',
            'hl.fl'         => '',
            'sort'          => $sort,
        );

        if( trim($this->searchQuery) != '' )
            $params = array_merge( $params, $this->solrHighlightParams() );

        if ( $this->withFacets )
            $params = array_merge( $params, $this->unfilteredFacetsParams() );

        if ($this->isSolrJsonDebug() )
            $this->contentList->pushResult( 'params', $params, true);

        return SolrTool::rawSearch( $params );
    }