private function __construct($rule, $additional, $storeContent) { /*$dom = new DOMDocument (); $dom->preserveWhiteSpace = false; $dom->loadXML ( $rule );*/ //walk through the association rule and index it //$this->_parse ( $rule, 1 ); $quantifiers = $rule->childNodes; foreach ($quantifiers as $quantifier) { if ($quantifier->nodeName == '#text' || $quantifier->nodeValue == '') { continue; } //print $quantifier->nodeName.' : '. trim($quantifier->nodeValue).'<br/>'; $val = trim($quantifier->nodeValue); if (is_numeric($val)) { $val = JuceneHelper::prepareNumber($val); } else { $val = (string) $val; $val = str_replace("-", "", $val); } if ($quantifier->nodeName == 'Text') { $type = 'Unindexed'; } else { $type = 'Text'; } $this->addField(Zend_Search_Lucene_Field::$type($quantifier->nodeName, $val, JUCENE_ENCODING)); } foreach ($additional as $field => $value) { if (is_numeric($value)) { $val = JuceneHelper::prepareNumber($value); } $this->addField(Zend_Search_Lucene_Field::Keyword('service_' . $field, $value, JUCENE_ENCODING)); } }
/** * Information about index */ function getIndexInfo() { require_once JPATH_SITE . DS . 'administrator' . DS . 'components' . DS . 'com_jucene' . DS . 'helpers' . DS . 'jucene.php'; $index = JuceneHelper::getIndex(); $info['infodocs'] = $index->count(); $dir_info = $this->getDirectorySize(JuceneHelper::getIndexPath()); $info['folderSize'] = $dir_info['size']; return $info; }
/** * * @param $article * @param $isNew */ function onIndexContent($article, $isNew = false) { //FIXME move the content type tests and following transformations to the helper global $mainframe; $pk = $article->id; if (!$isNew) { JuceneHelper::removeFromIndex('pk:' . $pk); } $index = JuceneHelper::getIndex(); $xml_field = substr($article->fulltext, 0, 5) != '<?xml' ? $article->introtext : $article->fulltext; if (substr($xml_field, 0, 5) == '<?xml') { $dom = new DOMDocument(); $pmml = true; $xslt = new DOMDocument(); $error = false; //load xslt stylesheet if (!@$xslt->load(JPATH_SITE . DS . 'administrator' . DS . 'components' . DS . 'com_jucene' . DS . 'xslt/jucene.xsl')) { $error = true; $this->raiseMessage("XSLTLOADERROR", 'error'); } $proc = new XSLTProcessor(); if (!$proc->importStylesheet($xslt)) { $error = true; $this->raiseMessage("XSLTIMPORTERROR", 'error'); } unset($artcile->fulltext); unset($record->introtext); if ($dom->loadXML($xml_field) && !$error && $pmml) { //simplify the document - prepare it for the indexation process $xslOutput = $proc->transformToXml($dom); //create new DOM document to preserve output and transform the XML to the indexable one $transXml = new DOMDocument(); $transXml->preserveWhitespace = false; @$transXml->loadXML($xslOutput); //unset unneccessary variables unset($xslOutput); unset($dom); unset($xslt); //index every assoc rule as document with same credentials if (!$error) { $rules = $transXml->getElementsByTagName("AssociationRule"); $rulesCount = $rules->length; if ($rulesCount == 0) { $error = true; $this->raiseMessage('XMLDOCUMENTNORULES', 'error'); } $rule_doc_position = 0; foreach ($rules as $rule) { $additional['rating'] = 0; $additional['position'] = $rule_doc_position; JPluginHelper::importPlugin('content'); $dispatcher =& JDispatcher::getInstance(); $results = $dispatcher->trigger('onIndexPmml', array($rule, $additional)); $rule_doc_position++; } } } } else { $zendDoc = Zend_Search_Lucene_Document_Html::loadHTML($article->fulltext, false, UTF - 8); $index->addDocument($zendDoc); } }
/** * Remove index method */ function remove() { $index = JuceneHelper::removeIndex(); $this->redirect("index.php?option=com_jucene"); }
/** * */ function getFields() { if (empty($this->_fields)) { $index = JuceneHelper::getIndex(); $results = $index->getFieldNames(); $this->_fields = $results; } return $this->_fields; }
function display($tpl = null) { global $mainframe; require_once JPATH_COMPONENT_ADMINISTRATOR . DS . 'helpers' . DS . 'jucene.php'; // Initialize some variables $pathway =& $mainframe->getPathway(); $uri =& JFactory::getURI(); $error = ''; $rows = null; $total = 0; $comParams =& JComponentHelper::getParams('com_jucene'); $displayServiceLink = $comParams->get('service_link', 1); if ($displayServiceLink) { $service_link = 'Powered by Zend Lucene, created by <a href="http://www.drupaler.cz">drupaler.cz</a>, Lukáš Beránek'; } // Get some data from the model $state =& $this->get('state'); $query = $state->get('query'); $params =& $mainframe->getParams(); $menus =& JSite::getMenu(); $menu = $menus->getActive(); // because the application sets a default page title, we need to get it // right from the menu item itself if (is_object($menu)) { $menu_params = new JParameter($menu->params); if (!$menu_params->get('page_title')) { $params->set('page_title', JText::_('Jucene Search')); } } else { $params->set('page_title', JText::_('Jucene Search')); } $document =& JFactory::getDocument(); $document->setTitle($params->get('page_title')); //add search stylesheet and autocomplete jquery library, jquery_lib_min (dependency) $document->addScript('components/com_jucene/js/jquery-1.4.4.min.js'); $document->addScript('components/com_jucene/js/jquery-ui-1.8.10.custom.min.js'); $document->addStyleSheet('components/com_jucene/css/jquery-ui-1.8.10.custom.css'); $document->addStyleSheet('components/com_jucene/css/search.css'); // built select lists //TODO find a solution how to implement query builder or ordering and search areas e.g. search fields $sorting = array(); $sorting[] = JHTML::_('select.option', 'Default', JText::_('SORT_REGULAR ')); $sorting[] = JHTML::_('select.option', 'Numeric', JText::_('SORT_NUMERIC ')); $sorting[] = JHTML::_('select.option', 'String', JText::_('SORT_STRING ')); $ordering = array(); $ordering[] = JHTML::_('select.option', 'Ascending', JText::_('SORT_ASC ')); $ordering[] = JHTML::_('select.option', 'Descending', JText::_('SORT_DESC ')); $lists = array(); //TODO fix sorting problem $lists['sorting'] = JHTML::_('select.genericlist', $sorting, 'sorting', 'class="inputbox"', 'value', 'text', $state->get('sorting')); $lists['ordering'] = JHTML::_('select.genericlist', $ordering, 'ordering', 'class="inputbox"', 'value', 'text', $state->get('ordering')); $searchphrases = array(); $searchphrases[] = JHTML::_('select.option', 'all', JText::_('All words')); $searchphrases[] = JHTML::_('select.option', 'any', JText::_('Any words')); $searchphrases[] = JHTML::_('select.option', 'exact', JText::_('Exact phrase')); $lists['searchphrase'] = JHTML::_('select.radiolist', $searchphrases, 'searchphrase', '', 'value', 'text', $state->get('match')); $fields =& $this->get('fields'); sort($fields); $field_list = ""; foreach ($fields as $field) { $field_list .= '"' . $field . '",'; } $document->addScriptDeclaration(' jQuery.noConflict(); $(function() { var availableTags = [' . $field_list . ']; function split( val ) { return val.split( /:\\s*/ ); } function extractLast( term ) { return split( term ).pop(); } $( "#search_searchword" )// don\'t navigate away from the field on tab when selecting an item .bind( "keydown", function( event ) { if ( event.keyCode === $.ui.keyCode.TAB && $( this ).data( "autocomplete" ).menu.active ) { event.preventDefault(); } }) .autocomplete({ minLength: 0, source: function( request, response ) { // delegate back to autocomplete, but extract the last term response( $.ui.autocomplete.filter( availableTags, extractLast( request.term ) ) ); }, focus: function() { // prevent value inserted on focus return false; }, select: function( event, ui ) { var terms = split( this.value ); // remove the current input terms.pop(); // add the selected item terms.push( ui.item.value ); // add placeholder to get the comma-and-space at the end terms.push( "" ); this.value = terms.join( ": " ); return false; } }); }); '); //TODO refactor this and move into the model and add some security measures - maybe they arent necessary, cause the search is used // by trusted users and Lucene sanitazes the query via the query parser $state->set('query', $query); //prepare query if (JuceneHelper::preprocessQuery($query)) { $error = JText::_('SHORTSTRING'); } if (!$error) { $results =& $this->get('data'); $total =& $this->get('total'); $pagination =& $this->get('pagination'); $count = 0; for ($i = 0; $i < count($results); $i++) { //TODO add Jucene Highlighting here $row =& $results[$i]->title; //TODO add content preparation here - security checks or prepare content for displaying //$row = SearchHelper::prepareSearchContent( $row, 200, $needle ); $result =& $results[$i]; $result->count = $i + 1; } } $this->result = JText::sprintf('JUCENETOTALRESULTSFOUND', $total); $this->assignRef('pagination', $pagination); $this->assignRef('results', $results); $this->assignRef('lists', $lists); $this->assignRef('params', $params); $this->assign('service_link', $service_link); $this->assign('ordering', $state->get('ordering')); $this->assign('sorting', $state->get('sorting')); $this->assign('query', $state->get('query')); $this->assign('field_list', $field_list); $this->assign('total', $total); $this->assign('error', $error); $this->assign('action', $uri->toString()); parent::display($tpl); }
/** * This method is used to generate search results field that are passed to the view * for displaying to the end-user * @param $query * @param $ordering */ function plgSearchJucene($query, $ordering = '') { //import helpers require_once JPATH_SITE . DS . 'administrator' . DS . 'components' . DS . 'com_jucene' . DS . 'helpers' . DS . 'jucene.php'; require_once JPATH_SITE . DS . 'components' . DS . 'com_content' . DS . 'helpers' . DS . 'route.php'; //set up some variables global $mainframe; $user =& JFactory::getUser(); $time = time(); try { //retrieve the Lucene Index if exists $index =& JuceneHelper::getIndex(); } catch (Exception $e) { JFactory::getApplication()->enqueueMessage(JText::_($e->getMessage()), 'error'); } //It is time to define the parameters! First get the right plugin; 'search' (the group), 'nameofplugin'. $plugin =& JPluginHelper::getPlugin('search', 'jucene'); //load the parameters of the plugin $pluginParams = new JParameter($plugin->params); $limit = $pluginParams->def('search_limit', 0); //TODO log search query //Set query try { $query = JuceneHelper::prepareNumber($query); } catch (Exception $e) { } Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding('UTF-8'); try { Zend_Search_Lucene_Search_QueryParser::parse($query); } catch (Exception $e) { JFactory::getApplication()->enqueueMessage(JText::_($e->getMessage()), 'error'); } $query = str_replace('-', ':', $query); if (JDEBUG) { JFactory::getApplication()->enqueueMessage(JText::_($query, 'error')); } //query time $_SESSION['jucene_timer'] = time(); try { $results = $index->find($query, 'score', SORT_NUMERIC, SORT_DESC, 'rating', SORT_NUMERIC, SORT_DESC); } catch (Exception $e) { JFactory::getApplication()->enqueueMessage(JText::_($e->getMessage()), 'error'); } //TODO find better solution to create links, perhaps to create router like it the com_content // Create a user access object for the current user $access = new stdClass(); $access->canEdit = $user->authorize('com_content', 'edit', 'content', 'all'); $access->canEditOwn = $user->authorize('com_content', 'edit', 'content', 'own'); $access->canPublish = $user->authorize('com_content', 'publish', 'content', 'all'); // Check to see if the user has access to view the full article $aid = $user->get('aid'); //pk is the value of the primary key of the record, because we cannot call id - lucene would return id WITHIN index.. not database primary key foreach ($results as $key => $val) { if ($val->access <= $aid) { $results[$key]->href = JRoute::_(ContentHelperRoute::getArticleRoute($val->alias, $val->catid, $val->sectionid)); //ContentHelperRoute::getArticleRoute ( $val->pk ); } else { $params =& JComponentHelper::getParams('com_jucene'); $leave_out = $params->get('leave_out', 1); // Create login URL or leave out private content if ($leave_out == 1) { unset($results[$key]); } else { $uri = JFactory::getURI(); $return = $uri->toString(); $url = 'index.php?option=com_user&view=login'; $url .= '&return=' . base64_encode($return); $results[$key]->href = $url; } } $results[$key]->count = ''; $results[$key]->time = $time; } //Return the search results in an array return $results; }
/** * * @param $conditions * array of conditions in form of fied => value */ function searchKbi(DOMDocument $ar_query, $specific_index = NULL) { if (!JuceneHelper::stringContains($ar_query, "<?xml")) { return ""; } $xslt = new DOMDocument(); if (!@$xslt->load(JPATH_SITE . DS . 'administrator' . DS . 'components' . DS . 'com_jucene' . DS . 'xslt/ARQuery.xsl')) { $error = true; $this->raiseMessage("XSLTLOADERROR", 'error'); } $xslt_proc = new XSLTProcessor(); if (!$xslt_proc->importStylesheet($xslt)) { $error = true; $this->raiseMessage("XSLTIMPORTERROR", 'error'); } $ar_query_dom = new DOMDocument(); if ($ar_query_dom->loadXML($ar_query)) { $query = $xslt_proc->transformToXml($ar_query); } $index = is_null($specific_index) ? JuceneHelper::getIndex() : JuceneHelper::getIndex($specific_index); try { $results = $index->find($query); } catch (Exception $e) { echo $e->getMessage(); } if (count($results) > 0) { //TODO make the results XML $results_xml = new DOMDocument(); $results_xml->formatOutput = true; $search_result = $results_xml->appendChild('SearchResult'); $hits = $search_result->appendChild('Hits'); foreach ($results as $field_name => $value) { $hit = $hits->appendChild('Hit'); $hitValue = $results_xml->createElement($field_name, $value); $hit->appendChild($hitValue); } $xml = $results_xml->saveXML(); } return $xml; }
function sanitizeQueryValue($value) { if (is_numeric($value) || is_float($value) || is_int($value)) { $value = JuceneHelper::prepareNumericValue($value); } else { $value = JuceneHelper::removeCzechSpecialChars($value); } $replace_chars = array(';', '<', '>', '\\', '+', '-', '\\&', '\\|', '!', '(', ')', '{', '}', '[', ']', '\\"'); $value = str_replace($replace_chars, ' ', $value); $replace_dot = array('.'); $value = str_replace($replace_dot, ',', $value); return $value; }