Inheritance: extends AppModel
Beispiel #1
0
 /**
  * Split a string into a clean array of keywords
  * @param $text string
  * @param $allowWildcards boolean
  * @return array of keywords
  */
 function &filterKeywords($text, $allowWildcards = false)
 {
     $minLength = Config::getVar('search', 'min_word_length');
     $maxLength = Config::getVar('search', 'max_word_length');
     $stopwords =& SearchIndex::loadStopwords();
     // Remove punctuation
     if (is_array($text)) {
         $text = join("\n", $text);
     }
     $cleanText = String::regexp_replace('/[!"\\#\\$%\'\\(\\)\\.\\?@\\[\\]\\^`\\{\\}~]/', '', $text);
     $cleanText = String::regexp_replace('/[\\+,:;&\\/<=>\\|\\\\]/', ' ', $cleanText);
     $cleanText = String::regexp_replace('/[\\*]/', $allowWildcards ? '%' : ' ', $cleanText);
     $cleanText = String::strtolower($cleanText);
     // Split into words
     $words = String::regexp_split('/\\s+/', $cleanText);
     // FIXME Do not perform further filtering for some fields, e.g., author names?
     // Remove stopwords
     $keywords = array();
     foreach ($words as $k) {
         if (!isset($stopwords[$k]) && String::strlen($k) >= $minLength && !is_numeric($k)) {
             $keywords[] = String::substr($k, 0, $maxLength);
         }
     }
     return $keywords;
 }
 /**
  * Return a instance of SearchIndex.
  * @return SearchIndex Instance of SearchIndex
  */
 public static function getInstance()
 {
     if (self::$oInstance === null) {
         self::$oInstance = new self();
     }
     return self::$oInstance;
 }
Beispiel #3
0
 /**
  * Query parsing helper routine.
  * Returned structure is based on that used by the Search::QueryParser Perl module.
  */
 function _parseQuery($signTokens, $tokens, &$pos, $total)
 {
     $return = array('+' => array(), '' => array(), '-' => array());
     $postBool = $preBool = '';
     $notOperator = String::strtolower(__('search.operator.not'));
     $andOperator = String::strtolower(__('search.operator.and'));
     $orOperator = String::strtolower(__('search.operator.or'));
     while ($pos < $total) {
         if (!empty($signTokens[$pos])) {
             $sign = $signTokens[$pos];
         } else {
             if (empty($sign)) {
                 $sign = '+';
             }
         }
         $token = String::strtolower($tokens[$pos++]);
         switch ($token) {
             case $notOperator:
                 $sign = '-';
                 break;
             case ')':
                 return $return;
             case '(':
                 $token = Search::_parseQuery($signTokens, $tokens, $pos, $total);
             default:
                 $postBool = '';
                 if ($pos < $total) {
                     $peek = String::strtolower($tokens[$pos]);
                     if ($peek == $orOperator) {
                         $postBool = 'or';
                         $pos++;
                     } else {
                         if ($peek == $andOperator) {
                             $postBool = 'and';
                             $pos++;
                         }
                     }
                 }
                 $bool = empty($postBool) ? $preBool : $postBool;
                 $preBool = $postBool;
                 if ($bool == 'or') {
                     $sign = '';
                 }
                 if (is_array($token)) {
                     $k = $token;
                 } else {
                     $k = SearchIndex::filterKeywords($token, true);
                 }
                 if (!empty($k)) {
                     $return[$sign][] = $k;
                 }
                 $sign = '';
                 break;
         }
     }
     return $return;
 }
 public function __actionEdit()
 {
     $synonym = $_POST['synonym'];
     // remove existing instance of hash
     if ($synonym['hash'] != '') {
         unset($this->_synonyms[$synonym['hash']]);
     }
     $this->_synonyms[sha1($synonym['word'])] = array('word' => $synonym['word'], 'synonyms' => $synonym['synonyms']);
     SearchIndex::saveSynonyms($this->_synonyms);
     redirect("{$this->_uri}/synonyms/");
 }
 /**
  * コンテンツメタ情報を更新する
  *
  * @param Model $model
  * @return boolean
  */
 public function updateSearchIndexMeta(Model $model)
 {
     $db = ConnectionManager::getDataSource('default');
     $contentTypes = array();
     $searchIndexes = $this->SearchIndex->find('all', array('fields' => array('SearchIndex.type'), 'group' => array('SearchIndex.type'), 'conditions' => array('SearchIndex.status' => true)));
     foreach ($searchIndexes as $searchIndex) {
         if ($searchIndex['SearchIndex']['type']) {
             $contentTypes[$searchIndex['SearchIndex']['type']] = $searchIndex['SearchIndex']['type'];
         }
     }
     $siteConfigs['SiteConfig']['content_types'] = BcUtil::serialize($contentTypes);
     $SiteConfig = ClassRegistry::init('SiteConfig');
     return $SiteConfig->saveKeyValue($siteConfigs);
 }
Beispiel #6
0
 /**
  * @method POST
  */
 function get()
 {
     parse_str($this->request->data, $request);
     // parse request
     $term = $request['term'];
     $language = $request['language'];
     $siteUniqId = SITE_UNIQ_ID;
     $site = Site::GetBySiteUniqId($siteUniqId);
     $showSecure = false;
     if (isset($_SESSION[$site['FriendlyId'] . '.UserId'])) {
         $showSecure = true;
     }
     $results = SearchIndex::Search($siteUniqId, $language, $term, $showSecure);
     // return a json response
     $response = new Tonic\Response(Tonic\Response::OK);
     $response->contentType = 'application/json';
     $response->body = json_encode($results);
     return $response;
 }
 public function __viewIndex()
 {
     // create a DS and filter on System ID of the current entry to build the entry's XML
     $ds = new ReindexDataSource(Administration::instance(), NULL, FALSE);
     $ds->dsSource = (string) $_GET['section'];
     $ds->dsParamFILTERS = $this->_index['filters'];
     $param_pool = array();
     $grab_xml = $ds->grab($param_pool);
     $xml = $grab_xml->generate();
     $dom = new DomDocument();
     $dom->loadXML($xml);
     $xpath = new DomXPath($dom);
     foreach ($xpath->query("//entry") as $entry) {
         $context = (object) array('section' => $this->_section, 'entry' => reset($this->_entryManager->fetch($entry->getAttribute('id'))));
         SearchIndex::indexEntry($context->entry, $context->section);
     }
     header('Content-type: text/xml');
     echo $xml;
     exit;
 }
 /**
  * Resets all references to other model objects or collections of model objects.
  *
  * This method is a user-space workaround for PHP's inability to garbage collect
  * objects with circular references (even in PHP 5.3). This is currently necessary
  * when using Propel in certain daemon or large-volume/high-memory operations.
  *
  * @param boolean $deep Whether to also clear the references on all referrer objects.
  */
 public function clearAllReferences($deep = false)
 {
     if ($deep && !$this->alreadyInClearAllReferencesDeep) {
         $this->alreadyInClearAllReferencesDeep = true;
         if ($this->aSearchIndex instanceof Persistent) {
             $this->aSearchIndex->clearAllReferences($deep);
         }
         if ($this->aUserRelatedByCreatedBy instanceof Persistent) {
             $this->aUserRelatedByCreatedBy->clearAllReferences($deep);
         }
         if ($this->aUserRelatedByUpdatedBy instanceof Persistent) {
             $this->aUserRelatedByUpdatedBy->clearAllReferences($deep);
         }
         $this->alreadyInClearAllReferencesDeep = false;
     }
     // if ($deep)
     $this->aSearchIndex = null;
     $this->aUserRelatedByCreatedBy = null;
     $this->aUserRelatedByUpdatedBy = null;
 }
 public function __viewIndex()
 {
     // create a DS and filter on System ID of the current entry to build the entry's XML
     $ds = new ReindexDataSource(NULL, FALSE);
     $ds->dsSource = (string) $_GET['section'];
     $ds->dsParamFILTERS = $this->_index['filters'];
     $param_pool = array();
     $grab_xml = $ds->grab($param_pool);
     $xml = $grab_xml->generate();
     $dom = new DomDocument();
     $dom->loadXML($xml);
     $xpath = new DomXPath($dom);
     $entry_ids = array();
     foreach ($xpath->query("//entry") as $entry) {
         $entry_ids[] = $entry->getAttribute('id');
     }
     SearchIndex::indexEntry($entry_ids, $ds->dsSource, FALSE);
     header('Content-type: text/xml');
     echo $xml;
     exit;
 }
 /**
  * Delete this entry's search index
  *
  * @param object $context
  */
 public function deleteEntryIndex($context)
 {
     SearchIndex::deleteIndexByEntry($context['entry_id']);
 }
 /**
  * Parse the indexable content for an entry
  *
  * @param int $entry
  * @param int $section
  */
 public function indexEntry($entry, $section, $check_filters = TRUE)
 {
     self::assert();
     if (is_object($entry)) {
         $entry = $entry->get('id');
     }
     if (is_object($section)) {
         $section = $section->get('id');
     }
     // get a list of sections that have indexing enabled
     $indexed_sections = self::getIndexes();
     // go no further if this section isn't being indexed
     if (!isset($indexed_sections[$section])) {
         return;
     }
     // delete existing index for this entry
     self::deleteIndexByEntry($entry);
     // get the current section index config
     $section_index = $indexed_sections[$section];
     // only pass entries through filters if we need to. If entry is being sent
     // from the Re-Index AJAX it has already gone through filtering, so no need here
     if ($check_filters === TRUE) {
         if (self::$_where == NULL || self::$_joins == NULL) {
             // modified from class.datasource.php
             // create filters and build SQL required for each
             if (is_array($section_index['filters']) && !empty($section_index['filters'])) {
                 foreach ($section_index['filters'] as $field_id => $filter) {
                     if (is_array($filter) && empty($filter) || trim($filter) == '') {
                         continue;
                     }
                     if (!is_array($filter)) {
                         $filter_type = DataSource::__determineFilterType($filter);
                         $value = preg_split('/' . ($filter_type == DS_FILTER_AND ? '\\+' : ',') . '\\s*/', $filter, -1, PREG_SPLIT_NO_EMPTY);
                         $value = array_map('trim', $value);
                     } else {
                         $value = $filter;
                     }
                     $field = self::$_entry_manager->fieldManager->fetch($field_id);
                     $field->buildDSRetrivalSQL($value, $joins, $where, $filter_type == DS_FILTER_AND ? TRUE : FALSE);
                 }
             }
             self::$_where = $where;
             self::$_joins = $joins;
         }
         // run entry though filters
         $entry_prefilter = self::$_entry_manager->fetch($entry, $section, 1, 0, self::$_where, self::$_joins, FALSE, FALSE);
         // if no entry found, it didn't pass the pre-filtering
         if (empty($entry_prefilter)) {
             return;
         }
         // if entry passes filtering, pass entry_id as a DS filter to the EntryXMLDataSource DS
         $entry = reset($entry_prefilter);
         $entry = $entry['id'];
     }
     if (!is_array($entry)) {
         $entry = array($entry);
     }
     // create a DS and filter on System ID of the current entry to build the entry's XML
     #$ds = new EntryXMLDataSource(Administration::instance(), NULL, FALSE);
     self::$_entry_xml_datasource->dsParamINCLUDEDELEMENTS = $indexed_sections[$section]['fields'];
     self::$_entry_xml_datasource->dsParamFILTERS['id'] = implode(',', $entry);
     self::$_entry_xml_datasource->dsSource = (string) $section;
     $param_pool = array();
     $entry_xml = self::$_entry_xml_datasource->grab($param_pool);
     require_once TOOLKIT . '/class.xsltprocess.php';
     $xml = simplexml_load_string($entry_xml->generate());
     /* MULTILANGUAGE SUPPORT: */
     require_once TOOLKIT . '/class.extensionmanager.php';
     require_once TOOLKIT . '/class.fieldmanager.php';
     $fieldManager = new FieldManager($this);
     $extensionManager = new ExtensionManager($this);
     $status = $extensionManager->fetchStatus('multilanguage');
     $multilingualFields = array();
     $languages = array();
     if ($status == EXTENSION_ENABLED) {
         // Check if this section has multilingual fields:
         $results = Symphony::Database()->fetch('SELECT `element_name` FROM `tbl_fields` WHERE `parent_section` = ' . $section . ' AND `multilanguage` = 1;');
         foreach ($results as $result) {
             $multilingualFields[] = $result['element_name'];
         }
         $languages = explode(',', file_get_contents(MANIFEST . '/multilanguage-languages'));
     }
     foreach ($xml->xpath("//entry") as $entry_xml) {
         // get text value of the entry (default behaviour)
         $proc = new XsltProcess();
         $data = $proc->process($entry_xml->asXML(), file_get_contents(EXTENSIONS . '/search_index/lib/parse-entry.xsl'));
         $dataLanguages = array();
         foreach ($languages as $language) {
             foreach ($entry_xml->children() as $child) {
                 $name = $child->getName();
                 if (in_array($name, $multilingualFields)) {
                     // Bingo!
                     // Get the correct value for this item:
                     $field_id = $fieldManager->fetchFieldIDFromElementName($name);
                     $entry_id = $entry_xml->attributes()->id;
                     $values = Symphony::Database()->fetch('SELECT * FROM `tbl_multilanguage_values` WHERE `id_entry` = ' . $entry_id . ' AND `id_field` = ' . $field_id . ' AND `language` = \'' . $language . '\';');
                     if (count($values) >= 1) {
                         // Value found:
                         foreach ($values as $value) {
                             switch ($value['field_name']) {
                                 case 'value':
                                     $entry_xml->{$name} = $value['value'];
                                     break;
                             }
                         }
                     }
                 }
             }
             // Store it:
             $proc = new XsltProcess();
             $dataLanguages[$language] = $proc->process($entry_xml->asXML(), file_get_contents(EXTENSIONS . '/search_index/lib/parse-entry.xsl'));
         }
         self::saveEntryIndex((int) $entry_xml->attributes()->id, $section, $data, $dataLanguages);
         /* END MULTILANGUAGE SUPPORT */
     }
 }
 public function execute(array &$param_pool = null)
 {
     $result = new XMLElement($this->dsParamROOTELEMENT);
     $config = (object) Symphony::Configuration()->get('search_index');
     // Setup
     /*-----------------------------------------------------------------------*/
     // look for key in GET array if it's specified
     if (!empty($config->{'get-param-prefix'})) {
         if ($config->{'get-param-prefix'} == 'param_pool') {
             $_GET = $this->_env['param'];
         } else {
             $_GET = $_GET[$config->{'get-param-prefix'}];
         }
     }
     // get input parameters from GET request
     $param_keywords = isset($_GET[$config->{'get-param-keywords'}]) ? trim($_GET[$config->{'get-param-keywords'}]) : '';
     $param_sort = isset($_GET[$config->{'get-param-sort'}]) ? $_GET[$config->{'get-param-sort'}] : $config->{'default-sort'};
     $param_direction = isset($_GET[$config->{'get-param-direction'}]) ? strtolower($_GET[$config->{'get-param-direction'}]) : $config->{'default-direction'};
     // set pagination on the data source
     $this->dsParamSTARTPAGE = isset($_GET[$config->{'get-param-page'}]) ? (int) $_GET[$config->{'get-param-page'}] : $this->dsParamSTARTPAGE;
     $this->dsParamLIMIT = isset($_GET[$config->{'get-param-per-page'}]) && (int) $_GET[$config->{'get-param-per-page'}] > 0 ? (int) $_GET[$config->{'get-param-per-page'}] : $config->{'default-per-page'};
     // build ORDER BY statement for later
     switch ($param_sort) {
         case 'date':
             $sql_order_by = "e.creation_date {$param_direction}";
             break;
         case 'id':
             $sql_order_by = "e.id {$param_direction}";
             break;
         default:
             $sql_order_by = "score {$param_direction}";
             break;
     }
     // Find valid sections to query
     /*-----------------------------------------------------------------------*/
     if (isset($_GET[$config->{'get-param-sections'}]) && !empty($_GET[$config->{'get-param-sections'}])) {
         $param_sections = $_GET[$config->{'get-param-sections'}];
         // allow sections to be sent as an array if the user wishes (multi-select or checkboxes)
         if (is_array($param_sections)) {
             implode(',', $param_sections);
         }
     } elseif (!empty($config->{'default-sections'})) {
         $param_sections = $config->{'default-sections'};
     } else {
         $param_sections = '';
     }
     $sections = array();
     foreach (array_map('trim', explode(',', $param_sections)) as $handle) {
         $section = Symphony::Database()->fetchRow(0, sprintf("SELECT `id`, `name` FROM `tbl_sections` WHERE handle = '%s' LIMIT 1", Symphony::Database()->cleanValue($handle)));
         if ($section) {
             $sections[$section['id']] = array('handle' => $handle, 'name' => $section['name']);
         }
     }
     if (count($sections) == 0) {
         return $this->errorXML('Invalid search sections');
     }
     // Set up and manipulate keywords
     /*-----------------------------------------------------------------------*/
     // should we apply word stemming?
     $do_stemming = $config->{'stem-words'} == 'yes' ? TRUE : FALSE;
     // replace synonyms
     $keywords = SearchIndex::applySynonyms($param_keywords);
     $keywords_boolean = SearchIndex::parseKeywordString($keywords, $do_stemming);
     $keywords_highlight = trim(implode(' ', $keywords_boolean['highlight']), '"');
     // Set up weighting
     /*-----------------------------------------------------------------------*/
     $sql_weighting = '';
     foreach (SearchIndex::getIndexes() as $section_id => $index) {
         $weight = isset($index['weighting']) ? $index['weighting'] : 2;
         switch ($weight) {
             case 0:
                 $weight = 4;
                 break;
                 // highest
             // highest
             case 1:
                 $weight = 2;
                 break;
                 // high
             // high
             case 2:
                 $weight = 1;
                 break;
                 // none
             // none
             case 3:
                 $weight = 0.5;
                 break;
                 // low
             // low
             case 4:
                 $weight = 0.25;
                 break;
                 // lowest
         }
         $sql_weighting .= sprintf("WHEN e.section_id = %d THEN %d \n", $section_id, $weight);
     }
     // Build search SQL
     /*-----------------------------------------------------------------------*/
     $mode = !is_null($config->{'mode'}) ? $config->{'mode'} : 'like';
     $mode = strtoupper($mode);
     switch ($mode) {
         case 'FULLTEXT':
             $sql = sprintf("SELECT\n\t\t\t\t\t\t\tSQL_CALC_FOUND_ROWS\n\t\t\t\t\t\t\te.id as `entry_id`,\n\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\te.section_id as `section_id`,\n\t\t\t\t\t\t\tUNIX_TIMESTAMP(e.creation_date) AS `creation_date`,\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\tMATCH(index.data) AGAINST ('%1\$s') *\n\t\t\t\t\t\t\t\tCASE\n\t\t\t\t\t\t\t\t\t%2\$s\n\t\t\t\t\t\t\t\t\tELSE 1\n\t\t\t\t\t\t\t\tEND\n\t\t\t\t\t\t\t\t%3\$s\n\t\t\t\t\t\t\t) AS `score`\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\ttbl_search_index as `index`\n\t\t\t\t\t\t\tJOIN tbl_entries as `e` ON (index.entry_id = e.id)\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\tMATCH(index.data) AGAINST ('%4\$s' IN BOOLEAN MODE)\n\t\t\t\t\t\t\tAND e.section_id IN ('%5\$s')\n\t\t\t\t\t\tORDER BY\n\t\t\t\t\t\t\t%6\$s\n\t\t\t\t\t\tLIMIT %7\$d, %8\$d", Symphony::Database()->cleanValue($keywords), $sql_weighting, $param_sort == 'score-recency' ? '/ SQRT(GREATEST(1, DATEDIFF(NOW(), creation_date)))' : '', Symphony::Database()->cleanValue($keywords), implode("','", array_keys($sections)), Symphony::Database()->cleanValue($sql_order_by), max(0, ($this->dsParamSTARTPAGE - 1) * $this->dsParamLIMIT), (int) $this->dsParamLIMIT);
             break;
         case 'LIKE':
         case 'REGEXP':
             $sql_locate = '';
             $sql_replace = '';
             $sql_where = '';
             // by default, no wildcard separators
             $prefix = '';
             $suffix = '';
             // append wildcard for LIKE
             if ($mode == 'LIKE') {
                 $prefix = $suffix = '%';
             }
             // apply word boundary separator
             if ($mode == 'REGEXP') {
                 $prefix = '[[:<:]]';
                 $suffix = '[[:>:]]';
             }
             // all words to include in the query (single words and phrases)
             foreach ($keywords_boolean['include-words-all'] as $keyword) {
                 $keyword_stem = NULL;
                 $keyword = Symphony::Database()->cleanValue($keyword);
                 if ($do_stemming) {
                     $keyword_stem = Symphony::Database()->cleanValue(PorterStemmer::Stem($keyword));
                 }
                 // if the word can be stemmed, look for the word or the stem version
                 if ($do_stemming && $keyword_stem != $keyword) {
                     $sql_where .= "(index.data {$mode} '{$prefix}{$keyword}{$suffix}' OR index.data {$mode} '{$prefix}{$keyword}{$suffix}') AND ";
                 } else {
                     $sql_where .= "index.data {$mode} '{$prefix}{$keyword}{$suffix}' AND ";
                 }
                 // if this keyword exists in the entry contents, add 1 to "keywords_matched"
                 // which represents number of unique keywords in the search string that are found
                 $sql_locate .= "IF(LOCATE('{$keyword}', LOWER(`data`)) > 0, 1, 0) + ";
                 // see how many times this word is found in the entry contents by removing it from
                 // the column text then compare length to see how many times it was removed
                 $sql_replace .= "(LENGTH(`data`) - LENGTH(REPLACE(LOWER(`data`),LOWER('{$keyword}'),''))) / LENGTH('{$keyword}') + ";
             }
             // all words or phrases that we do not want
             foreach ($keywords_boolean['exclude-words-all'] as $keyword) {
                 $keyword = Symphony::Database()->cleanValue($keyword);
                 $sql_where .= "index.data NOT {$mode} '{$prefix}{$keyword}{$suffix}' AND ";
             }
             // append to complete SQL
             $sql_locate = $sql_locate == '' ? $sql_locate = '1' : ($sql_locate .= '0');
             $sql_replace = $sql_replace == '' ? $sql_replace = '1' : ($sql_replace .= '0');
             $sql_where = $sql_where == '' ? $sql_where = 'NOT 1' : $sql_where;
             // trim unnecessary boolean conditions from SQL
             $sql_where = preg_replace("/ OR \$/", "", $sql_where);
             $sql_where = preg_replace("/ AND \$/", "", $sql_where);
             // if ordering by score, use a function of the two columns
             // we are calculating rather than just "score"
             if (preg_match("/^score/", $sql_order_by)) {
                 $sql_order_by = preg_replace("/^score/", "(keywords_matched * score)", $sql_order_by);
             }
             $sql = sprintf("SELECT\n\t\t\t\t\t\t\tSQL_CALC_FOUND_ROWS\n\t\t\t\t\t\t\te.id as `entry_id`,\n\t\t\t\t\t\t\tdata,\n\t\t\t\t\t\t\te.section_id as `section_id`,\n\t\t\t\t\t\t\tUNIX_TIMESTAMP(e.creation_date) AS `creation_date`,\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t%1\$s\n\t\t\t\t\t\t\t) AS keywords_matched,\n\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t(%2\$s)\n\t\t\t\t\t\t\t\t*\n\t\t\t\t\t\t\t\tCASE\n\t\t\t\t\t\t\t\t\t%3\$s\n\t\t\t\t\t\t\t\t\tELSE 1\n\t\t\t\t\t\t\t\tEND\n\t\t\t\t\t\t\t\t%4\$s\n\t\t\t\t\t\t\t) AS score\n\t\t\t\t\t\tFROM\n\t\t\t\t\t\t\ttbl_search_index as `index`\n\t\t\t\t\t\t\tJOIN tbl_entries as `e` ON (index.entry_id = e.id)\n\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t%5\$s\n\t\t\t\t\t\t\tAND e.section_id IN ('%6\$s')\n\t\t\t\t\t\tORDER BY\n\t\t\t\t\t\t\t%7\$s\n\t\t\t\t\t\tLIMIT\n\t\t\t\t\t\t\t%8\$d, %9\$d", $sql_locate, $sql_replace, $sql_weighting, $param_sort == 'score-recency' ? '/ SQRT(GREATEST(1, DATEDIFF(NOW(), creation_date)))' : '', $sql_where, implode("','", array_keys($sections)), Symphony::Database()->cleanValue($sql_order_by), max(0, ($this->dsParamSTARTPAGE - 1) * $this->dsParamLIMIT), (int) $this->dsParamLIMIT);
             //echo $sql;die;
             break;
     }
     // Add soundalikes ("did you mean?") to XML
     /*-----------------------------------------------------------------------*/
     // we have search words, check for soundalikes
     if (count($keywords_boolean['include-words-all']) > 0) {
         $sounds_like = array();
         foreach ($keywords_boolean['include-words-all'] as $word) {
             $soundalikes = Symphony::Database()->fetchCol('keyword', sprintf("SELECT keyword FROM tbl_search_index_keywords WHERE SOUNDEX(keyword) = SOUNDEX('%s')", Symphony::Database()->cleanValue($word)));
             foreach ($soundalikes as $i => &$soundalike) {
                 if ($soundalike == $word) {
                     unset($soundalikes[$i]);
                     continue;
                 }
                 $soundalike = array('word' => $soundalike, 'distance' => levenshtein($soundalike, $word));
             }
             usort($soundalikes, array('datasourcesearch', 'sortWordDistance'));
             $sounds_like[$word] = $soundalikes[0]['word'];
         }
         // add words to XML
         if (count($sounds_like) > 0) {
             $alternative_spelling = new XMLElement('alternative-keywords');
             foreach ($sounds_like as $word => $soundalike) {
                 $alternative_spelling->appendChild(new XMLElement('keyword', NULL, array('original' => $word, 'alternative' => $soundalike, 'distance' => levenshtein($soundalike, $word))));
             }
             $result->appendChild($alternative_spelling);
         }
     }
     // Run search SQL!
     /*-----------------------------------------------------------------------*/
     // get our entries, returns entry IDs
     $entries = Symphony::Database()->fetch($sql);
     $total_entries = Symphony::Database()->fetchVar('total', 0, 'SELECT FOUND_ROWS() AS `total`');
     // append input values
     $result->setAttributeArray(array('keywords' => General::sanitize($keywords), 'sort' => General::sanitize($param_sort), 'direction' => General::sanitize($param_direction)));
     // append pagination
     $result->appendChild(General::buildPaginationElement($total_entries, ceil($total_entries * (1 / $this->dsParamLIMIT)), $this->dsParamLIMIT, $this->dsParamSTARTPAGE));
     // append list of sections
     $sections_xml = new XMLElement('sections');
     foreach ($sections as $id => $section) {
         $sections_xml->appendChild(new XMLElement('section', General::sanitize($section['name']), array('id' => $id, 'handle' => $section['handle'])));
     }
     $result->appendChild($sections_xml);
     // Append entries to XML, build if desired
     /*-----------------------------------------------------------------------*/
     // if true then the entire entry will be appended to the XML. If not, only
     // a "stub" of the entry ID is provided, allowing other data sources to
     // supplement with the necessary fields
     $build_entries = $config->{'build-entries'} == 'yes' ? TRUE : FALSE;
     if ($build_entries) {
         $field_pool = array();
     }
     // container for entry ID output parameter
     $param_output = array();
     foreach ($entries as $entry) {
         $param_output[] = $entry['entry_id'];
         $entry_xml = new XMLElement('entry', NULL, array('id' => $entry['entry_id'], 'section' => $sections[$entry['section_id']]['handle']));
         // add excerpt with highlighted search terms
         $excerpt = SearchIndex::parseExcerpt($keywords_highlight, $entry['data']);
         $excerpt = $this->fixEncoding($excerpt);
         $entry_xml->appendChild(new XMLElement('excerpt', $excerpt));
         // build and append entry data
         if ($build_entries) {
             $e = reset(EntryManager::fetch($entry['entry_id']));
             $data = $e->getData();
             foreach ($data as $field_id => $values) {
                 if (!isset($field_pool[$field_id]) || !is_object($field_pool[$field_id])) {
                     $field_pool[$field_id] = FieldManager::fetch($field_id);
                 }
                 $field_pool[$field_id]->appendFormattedElement($entry_xml, $values, FALSE, !empty($values['value_formatted']) ? 'formatted' : null, $e->get('id'));
             }
         }
         $result->appendChild($entry_xml);
     }
     // send entry IDs as Output Parameterss
     $param_pool['ds-' . $this->dsParamROOTELEMENT . '.id'] = $param_output;
     $param_pool['ds-' . $this->dsParamROOTELEMENT] = $param_output;
     // Log query
     /*-----------------------------------------------------------------------*/
     if ($config->{'log-keywords'} == 'yes' && trim($keywords)) {
         $section_handles = array_map('reset', array_values($sections));
         // has this search (keywords+sections) already been logged this session?
         $already_logged = Symphony::Database()->fetch(sprintf("SELECT * FROM `tbl_search_index_logs` WHERE keywords='%s' AND sections='%s' AND session_id='%s'", Symphony::Database()->cleanValue($param_keywords), Symphony::Database()->cleanValue(implode(',', $section_handles)), session_id()));
         $log_sql = sprintf("INSERT INTO `tbl_search_index_logs`\n\t\t\t\t\t(date, keywords, keywords_manipulated, sections, page, results, session_id)\n\t\t\t\t\tVALUES('%s', '%s', '%s', '%s', %d, %d, '%s')", date('Y-m-d H:i:s', time()), Symphony::Database()->cleanValue($param_keywords), Symphony::Database()->cleanValue($keywords), Symphony::Database()->cleanValue(implode(',', $section_handles)), $this->dsParamSTARTPAGE, $total_entries, session_id());
         Symphony::Database()->query($log_sql);
     }
     return $result;
 }
Beispiel #13
0
				<h1>Cross References</h1>
				<ul>';
    foreach ($law->references as $reference) {
        $sidebar .= '<li><span class="identifier">' . SECTION_SYMBOL . '&nbsp;<a href="' . $reference->url . '" class="law">' . $reference->section_number . '</a></span>
			<span class="title">' . $reference->catch_line . '</li>';
    }
    $sidebar .= '</ul>
			</section>';
}
/*
 * If we have a list of related laws, list them.
 * Note that Solr < 4.6 will probably die horribly trying this.
 * We catch any exceptions as a result and go about our business.
 */
try {
    $search_client = new SearchIndex(array('config' => json_decode(SEARCH_CONFIG, TRUE)));
    $related_laws = $search_client->find_related($law, 3);
    if ($related_laws && count($related_laws->get_results()) > 0) {
        $sidebar .= '
				<section class="related-group grid-box" id="related-links">
					<h1>Related Laws</h1>
					<ul id="related">';
        $related_law = new Law();
        foreach ($related_laws->get_results() as $result) {
            $related_law->law_id = $result->law_id;
            $related_law->get_law();
            $related_law->permalink = $related_law->get_url($result->law_id);
            $sidebar .= '<li>' . SECTION_SYMBOL . '&nbsp;<a href="' . $related_law->permalink->url . '">' . $related_law->section_number . '</a> ' . $related_law->catch_line . '</li>';
        }
        $sidebar .= '
					</ul>
 /**
  * Filter the query by a related SearchIndex object
  *
  * @param   SearchIndex|PropelObjectCollection $searchIndex The related object(s) to use as filter
  * @param     string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
  *
  * @return                 SearchIndexWordQuery The current query, for fluid interface
  * @throws PropelException - if the provided filter is invalid.
  */
 public function filterBySearchIndex($searchIndex, $comparison = null)
 {
     if ($searchIndex instanceof SearchIndex) {
         return $this->addUsingAlias(SearchIndexWordPeer::SEARCH_INDEX_ID, $searchIndex->getId(), $comparison);
     } elseif ($searchIndex instanceof PropelObjectCollection) {
         if (null === $comparison) {
             $comparison = Criteria::IN;
         }
         return $this->addUsingAlias(SearchIndexWordPeer::SEARCH_INDEX_ID, $searchIndex->toKeyValue('Id', 'Id'), $comparison);
     } else {
         throw new PropelException('filterBySearchIndex() only accepts arguments of type SearchIndex or PropelCollection');
     }
 }
 private function index(array $aPath)
 {
     $oNavigationItem = $this->oRootNavigationItem;
     PageNavigationItem::clearCache();
     while (count($aPath) > 0) {
         $oNavigationItem = $oNavigationItem->namedChild(array_shift($aPath), $this->sLanguageId, true, true);
     }
     FilterModule::getFilters()->handleNavigationPathFound($this->oRootNavigationItem, $oNavigationItem);
     FrontendManager::$CURRENT_NAVIGATION_ITEM = $oNavigationItem;
     $oPageNavigationItem = $oNavigationItem;
     while (!$oPageNavigationItem instanceof PageNavigationItem) {
         $oPageNavigationItem = $oPageNavigationItem->getParent();
     }
     FrontendManager::$CURRENT_PAGE = $oPageNavigationItem->getMe();
     $oPage = FrontendManager::$CURRENT_PAGE;
     $bIsNotFound = false;
     FilterModule::getFilters()->handlePageHasBeenSet($oPage, $bIsNotFound, $oNavigationItem);
     FilterModule::getFilters()->handleRequestStarted();
     FilterModule::getFilters()->handlePageNotFoundDetectionComplete($bIsNotFound, $oPage, $oNavigationItem, array(&$bIsNotFound));
     if ($bIsNotFound) {
         return false;
     }
     $sDescription = $oNavigationItem->getDescription($this->sLanguageId);
     if ($sDescription === null) {
         $sDescription = $oPage->getDescription($this->sLanguageId);
     }
     $aKeywords = array();
     foreach ($oPage->getConsolidatedKeywords($this->sLanguageId, true) as $sKeyword) {
         $aKeywords = array_merge($aKeywords, StringUtil::getWords($sKeyword));
     }
     $sTitle = $oNavigationItem->getTitle($this->sLanguageId);
     $sLinkText = $oNavigationItem->getLinkText($this->sLanguageId);
     if (!$sLinkText) {
         $sLinkText = $sTitle;
     }
     $sName = $oNavigationItem->getName();
     // Page type can prevent indexing
     if (!self::doIndex($oPage->getPageType(), $oNavigationItem)) {
         return false;
     }
     $oPageType = PageTypeModule::getModuleInstance($oPage->getPageType(), $oPage, $oNavigationItem);
     $aWords = $oPageType->getWords();
     $aWords = array_merge($aWords, StringUtil::getWords($sDescription), $aKeywords, StringUtil::getWords($sTitle), StringUtil::getWords($sLinkText), array($sName));
     $aPagePath = $oPage->getLink();
     $aNavigationItemPath = $oNavigationItem->getLink();
     $sPath = implode('/', array_diff($aNavigationItemPath, $aPagePath));
     $oSearchIndex = new SearchIndex();
     $oSearchIndex->setPageId($oPage->getId());
     $oSearchIndex->setPath($sPath);
     $oSearchIndex->setLinkText($sLinkText);
     $oSearchIndex->setPageTitle($sTitle);
     $oSearchIndex->setLanguageId($this->sLanguageId);
     $oSearchIndex->save();
     foreach ($aWords as $sWord) {
         $sWord = Synonyms::rootFor($sWord, $this->sLanguageId);
         $oSearchIndexWord = SearchIndexWordQuery::create()->filterBySearchIndex($oSearchIndex)->filterByWord($sWord)->findOne();
         if ($oSearchIndexWord === null) {
             $oSearchIndexWord = new SearchIndexWord();
             $oSearchIndexWord->setSearchIndex($oSearchIndex);
             $oSearchIndexWord->setWord($sWord);
         } else {
             $oSearchIndexWord->incrementCount();
         }
         $oSearchIndexWord->save();
     }
     return true;
 }
 function insertRecordCallback($hookName, $args)
 {
     // Handle the record.
     $record =& $args[0];
     $schemaPlugin =& $record->getSchemaPlugin();
     $schemaPluginName = $schemaPlugin->getName();
     $fieldDao =& DAORegistry::getDAO('FieldDAO');
     foreach ($schemaPlugin->getFieldList() as $fieldName) {
         $field =& $fieldDao->buildField($fieldName, $schemaPluginName);
         $fieldValue = $schemaPlugin->getFieldValue($record, $fieldName, SORT_ORDER_TYPE_STRING);
         SearchIndex::updateTextIndex($record->getRecordId(), $field->getFieldId(), $fieldValue);
     }
     return false;
 }
Beispiel #17
0
 public static function BuildSearchIndex($site, $page, $root = '../')
 {
     // get content from published fragment
     $content = '';
     $fragment = $root . 'sites/' . $site['FriendlyId'] . '/fragments/publish/' . $page['PageUniqId'] . '.html';
     if (file_exists($fragment)) {
         $content = file_get_contents($fragment);
     }
     // remove existing index
     SearchIndex::Remove($page['PageUniqId']);
     // build the search index for the page in the default language
     $isDefaultLanguage = true;
     Utilities::BuildSearchIndex($site, $page, $site['Language'], $isDefaultLanguage, $content, $root);
     // get a list of other languages
     $rootPrefix = $root . 'sites/' . $site['FriendlyId'] . '/';
     // build index for non-default languages
     $languages = Utilities::GetSupportedLanguages($rootPrefix);
     $isDefaultLanguage = false;
     foreach ($languages as $language) {
         if ($language != $site['Language']) {
             Utilities::BuildSearchIndex($site, $page, $language, $isDefaultLanguage, $content, $root);
         }
     }
 }
 public function __viewIndex()
 {
     $this->setPageType('table');
     $this->setTitle(__('Symphony') . ' &ndash; ' . __('Search Indexes'));
     $page = @(int) $_GET['pg'] > 1 ? (int) $_GET['pg'] : 1;
     $page_size = (int) Symphony::Configuration()->get('pagination_maximum_rows', 'symphony');
     $sort_column = 'date';
     $sort_order = 'desc';
     $filter_keywords = '';
     $filter_view = '';
     if (isset($_GET['sort'])) {
         $sort_column = $_GET['sort'];
     }
     if (isset($_GET['order'])) {
         $sort_order = $_GET['order'];
     }
     if (isset($_GET['keywords'])) {
         $filter_keywords = $_GET['keywords'];
     }
     if (isset($_GET['view'])) {
         $filter_view = $_GET['view'];
     }
     $logs = SearchIndex::getLogs($sort_column, $sort_order, $filter_view == 'export' ? NULL : $page, $filter_keywords);
     if ($filter_view == 'export') {
         $file_path = sprintf('%s/search-index.log.%d.csv', TMP, time());
         $csv = fopen($file_path, 'w');
         fputcsv($csv, array(__('Date'), __('Keywords'), __('Adjusted Keywords'), __('Results'), __('Depth'), __('Session ID')), ',', '"');
         foreach ($logs as $log) {
             fputcsv($csv, array($log['date'], $log['keywords'], $log['keywords_manipulated'], $log['results'], $log['depth'], $log['session_id']), ',', '"');
         }
         fclose($csv);
         header('Content-type: application/csv');
         header('Content-Disposition: attachment; filename="' . end(explode('/', $file_path)) . '"');
         readfile($file_path);
         unlink($file_path);
         exit;
     }
     $start = max(1, ($page - 1) * $page_size);
     $end = $start == 1 ? $page_size : $start + count($logs);
     $total = SearchIndex::countLogs($filter_keywords);
     $pages = ceil($total / $page_size);
     $filter_form = Widget::Form($this->_uri . '/logs/', 'get');
     $filters = new XMLElement('div', NULL, array('class' => 'search-index-log-filters'));
     $label = new XMLElement('label', __('Filter searches containing the keywords %s', array(Widget::Input('keywords', $filter_keywords)->generate())));
     $filters->appendChild($label);
     $filters->appendChild(new XMLElement('input', NULL, array('type' => 'submit', 'value' => __('Filter'), 'class' => 'create button')));
     $filters->appendChild(Widget::Anchor(__('Clear'), $this->_uri . '/logs/', NULL, 'button clear'));
     $filter_form->appendChild($filters);
     $this->insertDrawer(Widget::Drawer('search_index', __('Filter Logs'), $filter_form, 'opened'), 'horizontal');
     $this->appendSubheading(__('Logs'), Widget::Anchor(__('Export CSV'), $this->_uri . '/logs/?view=export&amp;sort=' . $sort_column . '&amp;order=' . $sort_order . '&amp;keywords=' . $filter_keywords, NULL, 'button'));
     $stats = array('unique-users' => SearchIndex::getStatsCount('unique-users', $filter_keywords), 'unique-searches' => SearchIndex::getStatsCount('unique-searches', $filter_keywords), 'unique-terms' => SearchIndex::getStatsCount('unique-terms', $filter_keywords), 'average-results' => SearchIndex::getStatsCount('average-results', $filter_keywords));
     $this->addStylesheetToHead(URL . '/extensions/search_index/assets/search_index.css', 'screen', 100);
     $this->Form->appendChild(new XMLElement('p', sprintf(__('<strong>%s</strong> unique searches from <strong>%s</strong> unique users via <strong>%s</strong> distinct search terms. Each search yielded an average of <strong>%s</strong> results.', array($stats['unique-searches'], $stats['unique-users'], $stats['unique-terms'], $stats['average-results']))), array('class' => 'intro')));
     $tableHead = array();
     $tableBody = array();
     $tableHead = array(array(Widget::Anchor(__('Date'), Administration::instance()->getCurrentPageURL() . '?pg=1&amp;sort=date&amp;order=' . ($sort_column == 'date' && $sort_order == 'desc' ? 'asc' : 'desc') . '&amp;keywords=' . $filter_keywords, '', $sort_column == 'date' ? 'active' : ''), 'col'), array(Widget::Anchor(__('Keywords'), Administration::instance()->getCurrentPageURL() . '?pg=1&amp;sort=keywords&amp;order=' . ($sort_column == 'keywords' && $sort_order == 'asc' ? 'desc' : 'asc') . '&amp;keywords=' . $filter_keywords, '', $sort_column == 'keywords' ? 'active' : ''), 'col'), array(__('Adjusted Keywords'), 'col'), array(Widget::Anchor(__('Results'), Administration::instance()->getCurrentPageURL() . '?pg=1&amp;sort=results&amp;order=' . ($sort_column == 'results' && $sort_order == 'desc' ? 'asc' : 'desc') . '&amp;keywords=' . $filter_keywords, '', $sort_column == 'results' ? 'active' : ''), 'col'), array(Widget::Anchor(__('Depth'), Administration::instance()->getCurrentPageURL() . '?pg=1&amp;sort=depth&amp;order=' . ($sort_column == 'depth' && $sort_order == 'desc' ? 'asc' : 'desc') . '&amp;keywords=' . $filter_keywords, '', $sort_column == 'depth' ? 'active' : ''), 'col'), array(__('Session ID'), 'col'));
     if (!is_array($logs) or empty($logs)) {
         $tableBody = array(Widget::TableRow(array(Widget::TableData(__('None Found.'), 'inactive', null, count($tableHead)))));
     } else {
         foreach ($logs as $hash => $log) {
             $row = array();
             $row[] = Widget::TableData(DateTimeObj::get(__SYM_DATETIME_FORMAT__, strtotime($log['date'])));
             $keywords = $log['keywords'];
             $keywords_class = '';
             if ($keywords == '') {
                 $keywords = __('None');
                 $keywords_class = 'inactive';
             }
             $row[] = Widget::TableData(htmlentities($keywords, ENT_QUOTES), $keywords_class);
             $adjusted = $log['keywords_manipulated'];
             $adjusted_class = '';
             if ($log['keywords_manipulated'] == '' || strtolower(trim($log['keywords'])) == strtolower(trim($log['keywords_manipulated']))) {
                 $adjusted = __('None');
                 $adjusted_class = 'inactive';
             }
             $row[] = Widget::TableData(htmlentities($adjusted, ENT_QUOTES), $adjusted_class);
             $row[] = Widget::TableData($log['results']);
             $row[] = Widget::TableData($log['depth']);
             $row[] = Widget::TableData($log['session_id']);
             //$row[] = Widget::TableData($log['session_id'] . Widget::Input("items[{$log['id']}]", null, 'checkbox')->generate());
             $tableBody[] = Widget::TableRow($row);
         }
     }
     $table = Widget::Table(Widget::TableHead($tableHead), null, Widget::TableBody($tableBody));
     $this->Form->appendChild($table);
     $div = new XMLElement('div');
     $div->setAttribute('class', 'actions');
     $this->Form->appendChild($div);
     // Pagination:
     if ($pages > 1) {
         $ul = new XMLElement('ul');
         $ul->setAttribute('class', 'page');
         ## First
         $li = new XMLElement('li');
         if ($page > 1) {
             $li->appendChild(Widget::Anchor(__('First'), Administration::instance()->getCurrentPageURL() . '?pg=1&amp;sort=' . $sort_column . '&amp;order=' . $sort_order . '&amp;keywords=' . $filter_keywords));
         } else {
             $li->setValue(__('First'));
         }
         $ul->appendChild($li);
         ## Previous
         $li = new XMLElement('li');
         if ($page > 1) {
             $li->appendChild(Widget::Anchor(__('&larr; Previous'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($page - 1) . '&amp;sort=' . $sort_column . '&amp;order=' . $sort_order . '&amp;keywords=' . $filter_keywords));
         } else {
             $li->setValue('&larr; ' . __('Previous'));
         }
         $ul->appendChild($li);
         ## Summary
         $li = new XMLElement('li');
         $li->setAttribute('title', __('Viewing %1$s - %2$s of %3$s entries', array($start, $end, $total)));
         $pgform = Widget::Form(Administration::instance()->getCurrentPageURL(), 'get', 'paginationform');
         $pgmax = max($page, $pages);
         $pgform->appendChild(Widget::Input('pg', NULL, 'text', array('data-active' => __('Go to page …'), 'data-inactive' => __('Page %1$s of %2$s', array((string) $page, $pgmax)), 'data-max' => $pgmax)));
         $li->appendChild($pgform);
         $ul->appendChild($li);
         ## Next
         $li = new XMLElement('li');
         if ($page < $pages) {
             $li->appendChild(Widget::Anchor(__('Next &rarr;'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($page + 1) . '&amp;sort=' . $sort_column . '&amp;order=' . $sort_order . '&amp;keywords=' . $filter_keywords));
         } else {
             $li->setValue(__('Next') . ' &rarr;');
         }
         $ul->appendChild($li);
         ## Last
         $li = new XMLElement('li');
         if ($page < $pages) {
             $li->appendChild(Widget::Anchor(__('Last'), Administration::instance()->getCurrentPageURL() . '?pg=' . $pages . '&amp;sort=' . $sort_column . '&amp;order=' . $sort_order . '&amp;keywords=' . $filter_keywords));
         } else {
             $li->setValue(__('Last'));
         }
         $ul->appendChild($li);
         $this->Contents->appendChild($ul);
     }
 }
	/**
	* Set up static members
	*/
	private function assert() {
		if (self::$_entry_manager == NULL) self::$_entry_manager = new EntryManager(Administration::instance());
	}
 /**
  * Exclude object from result
  *
  * @param   SearchIndex $searchIndex Object to remove from the list of results
  *
  * @return SearchIndexQuery The current query, for fluid interface
  */
 public function prune($searchIndex = null)
 {
     if ($searchIndex) {
         $this->addCond('pruneCond0', $this->getAliasedColName(SearchIndexPeer::ID), $searchIndex->getId(), Criteria::NOT_EQUAL);
         $this->addCond('pruneCond1', $this->getAliasedColName(SearchIndexPeer::LANGUAGE_ID), $searchIndex->getLanguageId(), Criteria::NOT_EQUAL);
         $this->combine(array('pruneCond0', 'pruneCond1'), Criteria::LOGICAL_OR);
     }
     return $this;
 }
 public function index_laws($args)
 {
     if (!isset($this->edition)) {
         $edition_obj = new Edition(array('db' => $this->db));
         $this->edition = $edition_obj->current();
     }
     if (!isset($this->edition)) {
         throw new Exception('No edition, cannot index laws.');
     }
     if ($this->edition->current != '1') {
         $this->logger->message('The edition is not current, skipping the update of the search ' . ' index', 9);
         return;
     }
     if (!defined('SEARCH_CONFIG')) {
         $this->logger->message('Solr is not in use, skipping index', 9);
         return;
     } else {
         /*
          * Index the laws.
          */
         $this->logger->message('Updating search index', 5);
         $this->logger->message('Indexing laws', 6);
         $search_index = new SearchIndex(array('config' => json_decode(SEARCH_CONFIG, TRUE)));
         $law_obj = new Law(array('db' => $this->db));
         $result = $law_obj->get_all_laws($this->edition->id, true);
         $search_index->start_update();
         while ($law = $result->fetch()) {
             // Get the full data of the actual law.
             $document = new Law(array('db' => $this->db));
             $document->law_id = $law['id'];
             $document->config->get_all = TRUE;
             $document->get_law();
             // Bring over our edition info.
             $document->edition = $this->edition;
             try {
                 $search_index->add_document($document);
             } catch (Exception $error) {
                 $this->logger->message('Search index error "' . $error->getStatusMessage() . '"', 10);
                 return FALSE;
             }
         }
         $search_index->commit();
         // $this->logger->message('Indexing structures', 6);
         ### TODO: Index structures
         $this->logger->message('Laws were indexed', 5);
         return TRUE;
     }
 }
Beispiel #22
0
 private function deleteSearchIndex($intId)
 {
     $strSql = sprintf("SELECT * FROM pcms_search_index WHERE elementId = '%s'", quote_smart($intId));
     $objSearchIndexes = SearchIndex::select($strSql);
     foreach ($objSearchIndexes as $objSearchIndex) {
         $objSearchIndex->delete();
     }
 }
 public function __actionEdit()
 {
     $fields = $_POST['fields'];
     $is_new = !isset($this->_indexes[$this->_section->get('id')]);
     $this->_indexes[$this->_section->get('id')]['fields'] = $fields['included_elements'];
     $this->_indexes[$this->_section->get('id')]['weighting'] = $fields['weighting'];
     if (!is_array($fields['filter'])) {
         $fields['filter'] = array($fields['filter']);
     }
     $filters = array();
     foreach ($fields['filter'] as $filter) {
         if (is_null($filter)) {
             continue;
         }
         $filters[key($filter)] = $filter[key($filter)];
     }
     $this->_indexes[$this->_section->get('id')]['filters'] = $filters;
     SearchIndex::saveIndexes($this->_indexes);
     redirect("{$this->_uri}/indexes/");
 }
Beispiel #24
0
 public static function BuildSearchIndex($site, $page, $language, $isDefaultLanguage, $content, $root = '../')
 {
     $html = str_get_html($content, true, true, DEFAULT_TARGET_CHARSET, false, DEFAULT_BR_TEXT);
     $url = $page['FriendlyId'];
     $isSecure = 0;
     $image = $page['Image'];
     if ($page['PageTypeId'] != -1) {
         $pageType = PageType::GetByPageTypeId($page['PageTypeId']);
         $url = $pageType['FriendlyId'] . '/' . $page['FriendlyId'];
         if ($pageType['IsSecure'] == 1) {
             $isSecure = 1;
         }
     }
     if ($isDefaultLanguage == false) {
         // set language to the domain for the site
         $domain = $root . 'sites/' . $site['FriendlyId'] . '/locale';
         // set the language
         Utilities::SetLanguage($language, $domain);
     }
     $name = $page['Name'];
     $text = '';
     $h1s = '';
     $h2s = '';
     $h3s = '';
     $description = $page['Description'];
     if ($isDefaultLanguage == false) {
         $name = _($name);
         // get translated version
         $description = _($description);
     }
     if ($html == null) {
         return '';
     }
     // setup gettext blockquote, h1, h2, h3, p, td, th, li, meta tags for multi-lingual support
     foreach ($html->find('blockquote') as $el) {
         if ($isDefaultLanguage == false) {
             $text .= _($el->innertext) . ' ';
             // get translated version
         } else {
             $text .= $el->innertext . ' ';
         }
     }
     foreach ($html->find('h1') as $el) {
         if ($isDefaultLanguage == false) {
             $h1s .= _($el->innertext) . ' ';
             // get translated version
         } else {
             $h1s .= $el->innertext . ' ';
         }
     }
     foreach ($html->find('h2') as $el) {
         if ($isDefaultLanguage == false) {
             $h2s .= _($el->innertext) . ' ';
             // get translated version
         } else {
             $h2s .= $el->innertext . ' ';
         }
     }
     foreach ($html->find('h3') as $el) {
         if ($isDefaultLanguage == false) {
             $h3s .= _($el->innertext) . ' ';
             // get translated version
         } else {
             $h3s .= $el->innertext . ' ';
         }
     }
     foreach ($html->find('p') as $el) {
         if ($isDefaultLanguage == false) {
             $text .= _($el->innertext) . ' ';
             // get translated version
         } else {
             $text .= $el->innertext . ' ';
         }
     }
     foreach ($html->find('td') as $el) {
         if ($isDefaultLanguage == false) {
             $text .= _($el->innertext) . ' ';
             // get translated version
         } else {
             $text .= $el->innertext . ' ';
         }
     }
     foreach ($html->find('th') as $el) {
         if ($isDefaultLanguage == false) {
             $text .= _($el->innertext) . ' ';
             // get translated version
         } else {
             $text .= $el->innertext . ' ';
         }
     }
     foreach ($html->find('li') as $el) {
         if ($isDefaultLanguage == false) {
             $text .= _($el->innertext) . ' ';
             // get translated version
         } else {
             $text .= $el->innertext . ' ';
         }
     }
     foreach ($html->find('meta[name=description]') as $el) {
         if ($isDefaultLanguage == false) {
             $description = _($el->innertext);
             // get translated version
         } else {
             $description = $el->innertext;
         }
     }
     // strip any html
     $h1s = strip_tags($h1s);
     $h2s = strip_tags($h2s);
     $h3s = strip_tags($h3s);
     $description = strip_tags($description);
     $text = strip_tags($text);
     // add to search index
     SearchIndex::Add($page['PageUniqId'], $site['SiteUniqId'], $language, $url, $name, $image, $isSecure, $h1s, $h2s, $h3s, $description, $text);
 }
 /**
  * Build SQL for Data Source filter
  *
  * @param array $data
  * @param string $joins
  * @param string $where
  * @param boolean $andOperation
  */
 function buildDSRetrivalSQL($data, &$joins, &$where, $andOperation = FALSE)
 {
     $field_id = $this->get('id');
     if (!is_array($data)) {
         $data = array($data);
     }
     foreach ($data as &$value) {
         $value = SearchIndex::wildcardSearchKeywords($this->cleanValue($value));
     }
     $this->_key++;
     $data = implode("', '", $data);
     $joins .= " LEFT JOIN `tbl_search_index` AS search_index ON (e.id = search_index.entry_id) ";
     $where .= " AND MATCH(search_index.data) AGAINST ('{$data}' IN BOOLEAN MODE) ";
     return TRUE;
 }
 public function fieldData($field, $forceType = null, $extraOptions = array())
 {
     // Ensure that 'boost' is recorded here without being captured by solr
     $boost = null;
     if (array_key_exists('boost', $extraOptions)) {
         $boost = $extraOptions['boost'];
         unset($extraOptions['boost']);
     }
     $data = parent::fieldData($field, $forceType, $extraOptions);
     // Boost all fields with this name
     if (isset($boost)) {
         foreach ($data as $fieldName => $fieldInfo) {
             $this->boostedFields[$fieldName] = $boost;
         }
     }
     return $data;
 }
Beispiel #27
0
 private function deleteSearchIndex($intId)
 {
     $strSql = sprintf("DELETE FROM pcms_search_index WHERE elementId = '%s'", self::quote($intId));
     SearchIndex::select($strSql);
 }
 public function renderPanel($context)
 {
     $config = $context['config'];
     switch ($context['type']) {
         case 'search_index':
             $logs = SearchIndex::getLogs('date', 'desc', 1);
             $thead = array(array(__('Date'), 'col'), array(__('Keywords'), 'col'), array(__('Results'), 'col'));
             $tbody = array();
             if (!is_array($logs) or empty($logs)) {
                 $tbody = array(Widget::TableRow(array(Widget::TableData(__('No data available.'), 'inactive', null, count($thead)))));
             } else {
                 foreach ($logs as $log) {
                     $tbody[] = Widget::TableRow(array(Widget::TableData(DateTimeObj::get(__SYM_DATETIME_FORMAT__, strtotime($log['date']))), Widget::TableData($log['keywords']), Widget::TableData($log['results'])));
                 }
             }
             $table = Widget::Table(Widget::TableHead($thead), null, Widget::TableBody($tbody), null);
             $table->setAttribute('class', 'skinny');
             $context['panel']->appendChild($table);
             $context['panel']->appendChild(new XMLElement('p', '<a href="' . (SYMPHONY_URL . '/extension/search_index/logs/') . '">' . __('View full search logs') . ' &#8594;</a>', array('style' => 'margin:0.7em;text-align:right;')));
             break;
     }
 }
 /**
  * Adds an object to the instance pool.
  *
  * Propel keeps cached copies of objects in an instance pool when they are retrieved
  * from the database.  In some cases -- especially when you override doSelect*()
  * methods in your stub classes -- you may need to explicitly add objects
  * to the cache in order to ensure that the same objects are always returned by doSelect*()
  * and retrieveByPK*() calls.
  *
  * @param SearchIndex $obj A SearchIndex object.
  * @param      string $key (optional) key to use for instance map (for performance boost if key was already calculated externally).
  */
 public static function addInstanceToPool($obj, $key = null)
 {
     if (Propel::isInstancePoolingEnabled()) {
         if ($key === null) {
             $key = serialize(array((string) $obj->getId(), (string) $obj->getLanguageId()));
         }
         // if key === null
         SearchIndexPeer::$instances[$key] = $obj;
     }
 }
 public function __viewIndex()
 {
     $this->setPageType('table');
     $this->setTitle(__('Symphony') . ' &ndash; ' . __('Search Indexes'));
     $this->appendSubheading(__('Indexes'));
     $this->Form->appendChild(new XMLElement('p', __('Configure how each of your sections are indexed. Choose which field text values to index, which entries to index, and the weighting of the section in search results.'), array('class' => 'intro')));
     $this->addElementToHead(new XMLElement('script', "Symphony.Context.add('search_index', " . json_encode(Symphony::Configuration()->get('search_index')) . ")", array('type' => 'text/javascript')), 99);
     $this->addStylesheetToHead(URL . '/extensions/search_index/assets/search_index.css', 'screen', 100);
     $this->addScriptToHead(URL . '/extensions/search_index/assets/search_index.js', 101);
     $tableHead = array();
     $tableBody = array();
     $tableHead[] = array(__('Section'), 'col');
     $tableHead[] = array(__('Fields'), 'col');
     $tableHead[] = array(__('Weighting'), 'col');
     $tableHead[] = array(__('Index Size'), 'col');
     if (!is_array($this->_sections) or empty($this->_sections)) {
         $tableBody = array(Widget::TableRow(array(Widget::TableData(__('None Found.'), 'inactive', null, count($tableHead)))));
     } else {
         $re_index = explode(',', $_GET['section']);
         foreach ($this->_sections as $section) {
             $index = NULL;
             if (isset($this->_indexes[$section->get('id')])) {
                 $index = $this->_indexes[$section->get('id')];
             }
             $col_name = Widget::TableData(Widget::Anchor($section->get('name'), "{$this->_uri}/indexes/edit/{$section->get('id')}/"));
             if ($index) {
                 $col_name->appendChild(Widget::Input("items[{$section->get('id')}]", null, 'checkbox'));
             }
             if ($index && isset($index['fields']) && count($index['fields'] > 0)) {
                 $section_fields = $section->fetchFields();
                 $fields = $this->_indexes[$section->get('id')]['fields'];
                 $fields_list = '';
                 foreach ($section_fields as $section_field) {
                     if (in_array($section_field->get('element_name'), array_values($fields))) {
                         $fields_list .= $section_field->get('label') . ', ';
                     }
                 }
                 $fields_list = trim($fields_list, ', ');
                 $col_fields = Widget::TableData($fields_list);
             } else {
                 $col_fields = Widget::TableData(__('None'), 'inactive');
             }
             if ($index) {
                 if ($index['weighting'] == '') {
                     $index['weighting'] = 2;
                 }
                 $col_weighting = Widget::TableData($this->_weightings[$index['weighting']]);
             } else {
                 $col_weighting = Widget::TableData(__('None'), 'inactive');
             }
             $count_data = null;
             $count_class = null;
             if (isset($_GET['section']) && in_array($section->get('id'), $re_index) && in_array($section->get('id'), array_keys($this->_indexes))) {
                 SearchIndex::deleteIndexBySection($section->get('id'));
                 $count_data = '<span class="to-re-index" id="section-' . $section->get('id') . '">' . __('Waiting to re-index...') . '</span>';
             } else {
                 if (isset($this->_indexes[$section->get('id')])) {
                     $count = Symphony::Database()->fetchCol('count', sprintf("SELECT COUNT(entry_id) as `count` FROM tbl_search_index WHERE `section_id`='%d'", $section->get('id')));
                     $count_data = $count[0] . ' ' . ((int) $count[0] == 1 ? __('entry') : __('entries'));
                 } else {
                     $count_data = __('No index');
                     $count_class = 'inactive';
                 }
             }
             $col_count = Widget::TableData($count_data, $count_class . ' count-column');
             $tableBody[] = Widget::TableRow(array($col_name, $col_fields, $col_weighting, $col_count), 'section-' . $section->get('id'));
         }
     }
     $table = Widget::Table(Widget::TableHead($tableHead), NULL, Widget::TableBody($tableBody), 'selectable', null, array('role' => 'directory', 'aria-labelledby' => 'symphony-subheading', 'data-interactive' => 'data-interactive'));
     $this->Form->appendChild($table);
     $actions = new XMLElement('div');
     $actions->setAttribute('class', 'actions');
     $options = array(array(null, false, __('With Selected...')), array('re-index', false, __('Re-index Entries')), array('delete', false, __('Delete')));
     $actions->appendChild(Widget::Apply($options));
     $this->Form->appendChild($actions);
 }