Esempio n. 1
0
 /**
  * Create policy limitation query.
  *
  * @param array $limitation Override the limitation of the user. Same format as the return of eZUser::hasAccessTo()
  * @param boolean $ignoreVisibility Set to true for the visibility to be ignored
  * @return string Lucene/Solr query string which can be used as filter query for Solr
  */
 protected function policyLimitationFilterQuery($limitation = null, $ignoreVisibility = null)
 {
     $eZFindIni = eZINI::instance('ezfind.ini');
     $filterQuery = false;
     $policies = array();
     $pathFieldName = $ignoreVisibility ? eZSolr::getMetaFieldName('path') : eZSolr::getMetaFieldName('visible_path');
     if (is_array($limitation)) {
         if (empty($limitation)) {
             $limitation['accessWord'] = 'yes';
         }
     } else {
         $limitation = eZUser::currentUser()->hasAccessTo('content', 'read');
     }
     if (isset($limitation['accessWord'])) {
         switch ($limitation['accessWord']) {
             case 'limited':
                 if (isset($limitation['policies'])) {
                     $policies = $limitation['policies'];
                     break;
                 }
                 // break omitted, "limited" without policies == "no"
             // break omitted, "limited" without policies == "no"
             case 'no':
                 return ' NOT *:* ';
             case 'yes':
                 break;
             default:
                 return false;
         }
     }
     // Add limitations for filter query based on local permissions.
     $limitationHash = array('Class' => eZSolr::getMetaFieldName('contentclass_id'), 'Section' => eZSolr::getMetaFieldName('section_id'), 'User_Section' => eZSolr::getMetaFieldName('section_id'), 'Subtree' => eZSolr::getMetaFieldName('path_string'), 'User_Subtree' => eZSolr::getMetaFieldName('path_string'), 'Node' => eZSolr::getMetaFieldName('main_node_id'), 'Owner' => eZSolr::getMetaFieldName('owner_id'), 'Group' => eZSolr::getMetaFieldName('owner_group_id'), 'ObjectStates' => eZSolr::getMetaFieldName('object_states'));
     $filterQueryPolicies = array();
     // policies are concatenated with OR
     foreach ($policies as $limitationList) {
         // policy limitations are concatenated with AND
         // except for locations policity limitations, concatenated with OR
         $filterQueryPolicyLimitations = array();
         $policyLimitationsOnLocations = array();
         foreach ($limitationList as $limitationType => $limitationValues) {
             // limitation values of one type in a policy are concatenated with OR
             $filterQueryPolicyLimitationParts = array();
             switch ($limitationType) {
                 case 'User_Subtree':
                 case 'Subtree':
                     foreach ($limitationValues as $limitationValue) {
                         $pathString = trim($limitationValue, '/');
                         $pathArray = explode('/', $pathString);
                         // we only take the last node ID in the path identification string
                         $subtreeNodeID = array_pop($pathArray);
                         $policyLimitationsOnLocations[] = $pathFieldName . ':' . $subtreeNodeID;
                         if (isset($this->searchPluginInstance->postSearchProcessingData['subtree_limitations'])) {
                             $this->searchPluginInstance->postSearchProcessingData['subtree_limitations'][] = $subtreeNodeID;
                         } else {
                             $this->searchPluginInstance->postSearchProcessingData['subtree_limitations'] = array($subtreeNodeID);
                         }
                     }
                     break;
                 case 'Node':
                     foreach ($limitationValues as $limitationValue) {
                         $pathString = trim($limitationValue, '/');
                         $pathArray = explode('/', $pathString);
                         // we only take the last node ID in the path identification string
                         $nodeID = array_pop($pathArray);
                         $policyLimitationsOnLocations[] = $limitationHash[$limitationType] . ':' . $nodeID;
                         if (isset($this->searchPluginInstance->postSearchProcessingData['subtree_limitations'])) {
                             $this->searchPluginInstance->postSearchProcessingData['subtree_limitations'][] = $nodeID;
                         } else {
                             $this->searchPluginInstance->postSearchProcessingData['subtree_limitations'] = array($nodeID);
                         }
                     }
                     break;
                 case 'Group':
                     foreach (eZUser::currentUser()->attribute('contentobject')->attribute('parent_nodes') as $groupID) {
                         $filterQueryPolicyLimitationParts[] = $limitationHash[$limitationType] . ':' . $groupID;
                     }
                     break;
                 case 'Owner':
                     $filterQueryPolicyLimitationParts[] = $limitationHash[$limitationType] . ':' . eZUser::currentUser()->attribute('contentobject_id');
                     break;
                 case 'Class':
                 case 'Section':
                 case 'User_Section':
                     foreach ($limitationValues as $limitationValue) {
                         $filterQueryPolicyLimitationParts[] = $limitationHash[$limitationType] . ':' . $limitationValue;
                     }
                     break;
                 default:
                     //hacky, object state limitations reference the state group name in their
                     //limitation
                     //hence the following match on substring
                     if (strpos($limitationType, 'StateGroup') !== false) {
                         foreach ($limitationValues as $limitationValue) {
                             $filterQueryPolicyLimitationParts[] = $limitationHash['ObjectStates'] . ':' . $limitationValue;
                         }
                     } else {
                         eZDebug::writeDebug($limitationType, __METHOD__ . ' unknown limitation type: ' . $limitationType);
                         continue;
                     }
             }
             if (!empty($filterQueryPolicyLimitationParts)) {
                 $filterQueryPolicyLimitations[] = '( ' . implode(' OR ', $filterQueryPolicyLimitationParts) . ' )';
             }
         }
         // Policy limitations on locations (node and/or subtree) need to be concatenated with OR
         // unlike the other types of limitation
         if (!empty($policyLimitationsOnLocations)) {
             $filterQueryPolicyLimitations[] = '( ' . implode(' OR ', $policyLimitationsOnLocations) . ')';
         }
         if (!empty($filterQueryPolicyLimitations)) {
             $filterQueryPolicies[] = '( ' . implode(' AND ', $filterQueryPolicyLimitations) . ')';
         }
     }
     if (!empty($filterQueryPolicies)) {
         $filterQuery = implode(' OR ', $filterQueryPolicies);
     }
     // Add limitations for allowing search of other installations.
     $anonymousPart = '';
     if ($eZFindIni->variable('SiteSettings', 'SearchOtherInstallations') == 'enabled') {
         $anonymousPart = ' OR ' . eZSolr::getMetaFieldName('anon_access') . ':true ';
     }
     if (!empty($filterQuery)) {
         $filterQuery = '((' . eZSolr::getMetaFieldName('installation_id') . ':' . eZSolr::installationID() . ' AND (' . $filterQuery . ')) ' . $anonymousPart . ' )';
     } else {
         $filterQuery = '(' . eZSolr::getMetaFieldName('installation_id') . ':' . eZSolr::installationID() . $anonymousPart . ')';
     }
     // Add ignore visibility condition, either explicitely set to boolean false or not specified
     if ($ignoreVisibility === false || $ignoreVisibility === null) {
         $filterQuery .= ' AND ' . eZSolr::getMetaFieldName('is_invisible') . ':false';
     }
     eZDebugSetting::writeDebug('extension-ezfind-query', $filterQuery, __METHOD__);
     return $filterQuery;
 }
Esempio n. 2
0
 /**
  * Get attribute value
  *
  * @param string Attribute name
  *
  * @return mixed Attribute value. null if attribute does not exist.
  */
 public function attribute($attr)
 {
     switch ($attr) {
         case 'responseHeader':
             return $this->ResultArray['responseHeader'];
             break;
         case 'hasError':
             return !empty($this->ResultArray['error']);
             break;
         case 'error':
             if (!empty($this->ResultArray['error'])) {
                 return $this->ResultArray['error'];
             }
             break;
         case 'facet_queries':
             if (!empty($this->FacetQueries)) {
                 return $this->FacetQueries;
             }
             // If the facets count is empty, an error has occured.
             if (empty($this->ResultArray['facet_counts'])) {
                 return null;
             }
             $facetArray = array();
             foreach ($this->ResultArray['facet_counts']['facet_queries'] as $query => $count) {
                 list($field, $fieldValue) = explode(':', $query);
                 $fieldInfo = array('field' => $field, 'count' => $count, 'queryLimit' => $query, 'fieldValue' => $fieldValue);
                 $facetArray[] = $fieldInfo;
             }
             $this->FacetQueries = $facetArray;
             return $this->FacetQueries;
             break;
         case 'facet_fields':
             if (!empty($this->FacetFields)) {
                 return $this->FacetFields;
             }
             // If the facets count is empty, an error has occured.
             if (empty($this->ResultArray['facet_counts'])) {
                 return null;
             }
             $facetArray = array();
             foreach ($this->ResultArray['facet_counts']['facet_fields'] as $field => $facetField) {
                 switch ($field) {
                     // class facet field
                     case eZSolr::getMetaFieldName('contentclass_id'):
                         $fieldInfo = array('field' => 'class', 'count' => count($facetField), 'nameList' => array(), 'queryLimit' => array(), 'fieldList' => array(), 'countList' => array());
                         foreach ($facetField as $contentClassID => $count) {
                             if ($contentClass = eZContentClass::fetch($contentClassID)) {
                                 $fieldInfo['nameList'][$contentClassID] = $contentClass->attribute('name');
                                 $fieldInfo['queryLimit'][$contentClassID] = 'contentclass_id:' . $contentClassID;
                                 $fieldInfo['countList'][$contentClassID] = $count;
                                 $fieldInfo['fieldList'][$contentClassID] = 'contentclass_id';
                             } else {
                                 eZDebug::writeWarning('Could not fetch eZContentClass: ' . $contentClassID, __METHOD__);
                             }
                         }
                         $facetArray[] = $fieldInfo;
                         break;
                         // instalaltion facet field
                     // instalaltion facet field
                     case eZSolr::getMetaFieldName('installation_id'):
                         $findINI = eZINI::instance('ezfind.ini');
                         $siteNameMapList = $findINI->variable('FacetSettings', 'SiteNameList');
                         $fieldInfo = array('field' => 'installation', 'count' => count($facetField), 'nameList' => array(), 'queryLimit' => array(), 'fieldList' => array(), 'countList' => array());
                         foreach ($facetField as $installationID => $count) {
                             $fieldInfo['nameList'][$installationID] = isset($siteNameMapList[$installationID]) ? $siteNameMapList[$installationID] : $installationID;
                             $fieldInfo['queryLimit'][$installationID] = 'installation_id:' . $installationID;
                             $fieldInfo['countList'][$installationID] = $count;
                             $fieldInfo['fieldList'][$installationID] = 'installation_id';
                         }
                         $facetArray[] = $fieldInfo;
                         break;
                         // author facet field
                     // author facet field
                     case eZSolr::getMetaFieldName('owner_id'):
                         $fieldInfo = array('field' => 'author', 'count' => count($facetField), 'nameList' => array(), 'queryLimit' => array(), 'fieldList' => array(), 'countList' => array());
                         foreach ($facetField as $ownerID => $count) {
                             if ($owner = eZContentObject::fetch($ownerID)) {
                                 $fieldInfo['nameList'][$ownerID] = $owner->attribute('name');
                                 $fieldInfo['queryLimit'][$ownerID] = 'owner_id:' . $ownerID;
                                 $fieldInfo['countList'][$ownerID] = $count;
                                 $fieldInfo['fieldList'][$ownerID] = 'owner_id';
                             } else {
                                 eZDebug::writeWarning('Could not fetch owner ( eZContentObject ): ' . $ownerID, __METHOD__);
                             }
                         }
                         $facetArray[] = $fieldInfo;
                         break;
                         // translation facet field
                     // translation facet field
                     case eZSolr::getMetaFieldName('language_code'):
                         $fieldInfo = array('field' => 'translation', 'count' => count($facetField), 'nameList' => array(), 'queryLimit' => array(), 'fieldList' => array(), 'countList' => array());
                         foreach ($facetField as $languageCode => $count) {
                             $fieldInfo['nameList'][$languageCode] = $languageCode;
                             $fieldInfo['queryLimit'][$languageCode] = 'language_code:' . $languageCode;
                             $fieldInfo['fieldList'][$languageCode] = 'language_code';
                             $fieldInfo['countList'][$languageCode] = $count;
                         }
                         $facetArray[] = $fieldInfo;
                         break;
                     default:
                         $fieldInfo = array('field' => $attr, 'count' => count($facetField), 'queryLimit' => array(), 'fieldList' => array(), 'nameList' => array(), 'countList' => array());
                         foreach ($facetField as $value => $count) {
                             $fieldInfo['nameList'][$value] = $value;
                             $fieldInfo['fieldList'][$value] = $field;
                             $fieldInfo['queryLimit'][$value] = $field . ':' . $value;
                             $fieldInfo['countList'][$value] = $count;
                         }
                         $facetArray[] = $fieldInfo;
                         break;
                 }
             }
             $this->FacetFields = $facetArray;
             return $this->FacetFields;
             break;
         case 'engine':
             return eZSolr::engineText();
             break;
             //may or may not be active, so returns false if not present
         //may or may not be active, so returns false if not present
         case 'spellcheck':
             if (isset($this->ResultArray['spellcheck']) && $this->ResultArray['spellcheck']['suggestions'] > 0) {
                 return $this->ResultArray['spellcheck']['suggestions'];
             } else {
                 return false;
             }
             break;
         case 'spellcheck_collation':
             if (isset($this->ResultArray['spellcheck']['suggestions']['collation'])) {
                 // work around border case if 'collation' is searched for but does not exist in the spell check index
                 // the collation string is the last element of the suggestions array
                 return end($this->ResultArray['spellcheck']['suggestions']);
             } else {
                 return false;
             }
             break;
             //only relevant for MoreLikeThis queries
         //only relevant for MoreLikeThis queries
         case 'interestingTerms':
             if (isset($this->ResultArray['interestingTerms'])) {
                 return $this->ResultArray['interestingTerms'];
             } else {
                 return false;
             }
             break;
         case 'facet_dates':
             if (isset($this->ResultArray['facet_dates'])) {
                 return $this->ResultArray['facet_dates'];
             } else {
                 return false;
             }
             break;
         case 'facet_ranges':
             if (isset($this->ResultArray['facet_counts']['facet_ranges'])) {
                 return $this->ResultArray['facet_counts']['facet_ranges'];
             } else {
                 return false;
             }
             break;
         case 'clusters':
             if (isset($this->ResultArray['clusters'])) {
                 return $this->ResultArray['clusters'];
             } else {
                 return false;
             }
             break;
         default:
             break;
     }
     return null;
 }
 public function buildFetch(OCClassSearchFormFetcher $fetcher, $requestValue, &$filters)
 {
     $bounds = OCClassSearchFormPublishedFieldBounds::fromString($this->attributes['value']);
     $filters[] = eZSolr::getMetaFieldName('published') . ':[' . $bounds->attribute('start_solr') . ' TO ' . $bounds->attribute('end_solr') . ']';
     $fetcher->addFetchField(array('name' => $this->attributes['label'], 'value' => $bounds->humanString(), 'remove_view_parameters' => $fetcher->getViewParametersString(array('publish_date'))));
 }
Esempio n. 4
0
    /**
     * Get solr field name, from base name. The base name may either be a
     * meta-data name, or an eZ Publish content class attribute, specified by
     * <class identifier>/<attribute identifier>[/<option>]
     *
     * @param string $baseName Base field name.
     * @param boolean $includingClassID conditions the structure of the answer. See return value explanation.
     * @param $context is introduced in ez find 2.2 to allow for more optimal sorting, faceting, filtering
     *
     * @return mixed Internal base name. Returns null if no valid base name was provided.
     *               If $includingClassID is true, an associative array will be returned, as shown below :
     *               <code>
     *               array( 'fieldName'      => 'attr_title_t',
     *                      'contentClassId' => 16 );
     *               </code>
     */
    static function getFieldName( $baseName, $includingClassID = false, $context = 'search' )
    {
        // If the base name is a meta field, get the correct field name.
        if ( eZSolr::hasMetaAttributeType( $baseName, $context ) )
        {
            return eZSolr::getMetaFieldName( $baseName, $context );
        }
        else
        {
            // Get class and attribute identifiers + optional option.
            $subattribute = null;
            $fieldDef = explode( '/', $baseName );
            // Check if content class attribute ID is provided.
            if ( is_numeric( $fieldDef[0] ) )
            {
                if ( count( $fieldDef ) == 1 )
                {
                    $contentClassAttributeID = $fieldDef[0];
                }
                else if ( count( $fieldDef ) == 2 )
                {
                    list( $contentClassAttributeID, $subattribute ) = $fieldDef;
                }
            }
            else
            {
                switch( count( $fieldDef ) )
                {
                    case 1:
                    {
                        // Return fieldname as is.
                        return $baseName;
                    } break;

                    case 2:
                    {
                        // Field def contains class indentifier and class attribute identifier.
                        list( $classIdentifier, $attributeIdentifier ) = $fieldDef;
                    } break;

                    case 3:
                    {
                        // Field def contains class indentifier, class attribute identifier and optional specification.
                        list( $classIdentifier, $attributeIdentifier, $subattribute ) = $fieldDef;
                    } break;
                }
                $contentClassAttributeID = eZContentObjectTreeNode::classAttributeIDByIdentifier( $classIdentifier . '/' . $attributeIdentifier );
            }
            if ( !$contentClassAttributeID )
            {
                eZDebug::writeNotice( 'Could not get content class from base name: ' . $baseName, __METHOD__ );
                return null;
            }
            $contentClassAttribute = eZContentClassAttribute::fetch( $contentClassAttributeID );
            $fieldName = ezfSolrDocumentFieldBase::getFieldName( $contentClassAttribute, $subattribute, $context );

            if ( $includingClassID )
            {
                return array( 'fieldName'      => $fieldName,
                              'contentClassId' => $contentClassAttribute->attribute( 'contentclass_id' ) );
            }
            else
                return $fieldName;
        }
    }
 /**
  * Returns autocomplete suggestions for given params
  *
  * @param mixed $args
  * @return array
  */
 public static function autocomplete($args)
 {
     $result = array();
     $findINI = eZINI::instance('ezfind.ini');
     // Only make calls if explicitely enabled
     if ($findINI->hasVariable('AutoCompleteSettings', 'AutoComplete') && $findINI->variable('AutoCompleteSettings', 'AutoComplete') === 'enabled') {
         $solrINI = eZINI::instance('solr.ini');
         $siteINI = eZINI::instance();
         $currentLanguage = $siteINI->variable('RegionalSettings', 'ContentObjectLocale');
         $input = isset($args[0]) ? mb_strtolower($args[0], 'UTF-8') : null;
         $limit = isset($args[1]) ? (int) $args[1] : (int) $findINI->variable('AutoCompleteSettings', 'Limit');
         $facetField = $findINI->variable('AutoCompleteSettings', 'FacetField');
         $facetMethod = $findINI->variable('AutoCompleteSettings', 'FacetMethod');
         $params = array('q' => '*:*', 'rows' => 0, 'json.nl' => 'arrarr', 'facet' => 'true', 'facet.field' => $facetField, 'facet.prefix' => $input, 'facet.limit' => $limit, 'facet.method' => $facetMethod, 'facet.mincount' => 1);
         if ($findINI->variable('LanguageSearch', 'MultiCore') == 'enabled') {
             $languageMapping = $findINI->variable('LanguageSearch', 'LanguagesCoresMap');
             $shardMapping = $solrINI->variable('SolrBase', 'Shards');
             $fullSolrURI = $shardMapping[$languageMapping[$currentLanguage]];
         } else {
             $fullSolrURI = $solrINI->variable('SolrBase', 'SearchServerURI');
             // Autocomplete search should be done in current language and fallback languages
             $validLanguages = array_unique(array_merge($siteINI->variable('RegionalSettings', 'SiteLanguageList'), array($currentLanguage)));
             $params['fq'] = 'meta_language_code_ms:(' . implode(' OR ', $validLanguages) . ')';
         }
         //build the query part for the subtree limitation
         if (isset($args[2]) && (int) $args[2]) {
             if (isset($params['fq']) && $params['fq']) {
                 $params['fq'] .= ' AND ';
             }
             $params['fq'] .= eZSolr::getMetaFieldName('path') . ':' . (int) $args[2];
         }
         //build the query part for the class limitation
         if (isset($args[3]) && $args[3]) {
             if (isset($params['fq']) && $params['fq']) {
                 $params['fq'] .= ' AND ';
             }
             $classes = explode(',', $args[3]);
             $classQueryParts = array();
             foreach ($classes as $class) {
                 if (!is_numeric($class)) {
                     if ($class = eZContentClass::fetchByIdentifier($class)) {
                         $classQueryParts[] = eZSolr::getMetaFieldName('contentclass_id') . ':' . $class->attribute('id');
                     }
                 } else {
                     $classQueryParts[] = eZSolr::getMetaFieldName('contentclass_id') . ':' . $class;
                 }
             }
             $classQueryParts = implode(' OR ', $classQueryParts);
             $params['fq'] .= '(' . $classQueryParts . ')';
         }
         $solrBase = new eZSolrBase($fullSolrURI);
         $result = $solrBase->rawSolrRequest('/select', $params, 'json');
         return $result['facet_counts']['facet_fields'][$facetField];
     } else {
         // not enabled, just return an empty array
         return array();
     }
 }