<?php /** * @copyright Copyright (c) 2009-2021 Ryan Demmer. All rights reserved * @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html * JCE is free software. This version may have been modified pursuant * to the GNU General Public License, and as distributed it includes or * is derivative of works licensed under the GNU General Public License or * other free or open source software licenses */ defined('JPATH_PLATFORM') or die; class WFLinkSearchExtension extends WFSearchExtension { private $enabled = array(); /** * Constructor activating the default information of the class. */ public function __construct() { parent::__construct(); $request = WFRequest::getInstance(); $request->setRequest(array($this, 'doSearch')); $request->setRequest(array($this, 'getAreas')); $wf = WFEditorPlugin::getInstance(); // get plugins $plugins = $wf->getParam('search.link.plugins', array()); $default = array('categories', 'contacts', 'content', 'newsfeeds', 'weblinks', 'tags'); // use tested defaults $plugins = empty($plugins) ? $default : $plugins; foreach ($plugins as $plugin) { // plugin must be enabled if (!JPluginHelper::isEnabled('search', $plugin)) { continue; } // create component name from plugin - special case for "contacts" if (in_array($plugin, $default)) { $component = ($plugin == 'contacts') ? 'com_contact' : 'com_' . $plugin; // check for associated component if (!JComponentHelper::isEnabled($component)) { continue; } } // check plugin imports correctly - plugin may have a db entry, but is missing files if (JPluginHelper::importPlugin('search', $plugin)) { $this->enabled[] = $plugin; } } } public function display() { parent::display(); $document = WFDocument::getInstance(); $document->addScript(array('link'), 'extensions.search.js'); $document->addStylesheet(array('link'), 'extensions.search.css'); } public function isEnabled() { $wf = WFEditorPlugin::getInstance(); return (bool) $wf->getParam('search.link.enable', 1) && !empty($this->enabled); } /** * Method to get the search areas. */ public function getAreas() { $app = JFactory::getApplication('site'); $areas = array(); $results = array(); $searchareas = $app->triggerEvent('onContentSearchAreas'); foreach ($searchareas as $area) { if (is_array($area)) { $areas = array_merge($areas, $area); } } foreach ($areas as $k => $v) { $results[$k] = JText::_($v); } return $results; } /* * Render Search fields * This method uses portions of SearchViewSearch::display from components/com_search/views/search/view.html.php * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved. */ public function render() { if (!$this->isEnabled()) { return ''; } // built select lists $orders = array(); $orders[] = JHtml::_('select.option', 'newest', JText::_('WF_SEARCH_NEWEST_FIRST')); $orders[] = JHtml::_('select.option', 'oldest', JText::_('WF_SEARCH_OLDEST_FIRST')); $orders[] = JHtml::_('select.option', 'popular', JText::_('WF_SEARCH_MOST_POPULAR')); $orders[] = JHtml::_('select.option', 'alpha', JText::_('WF_SEARCH_ALPHABETICAL')); $orders[] = JHtml::_('select.option', 'category', JText::_('WF_CATEGORY')); $lists = array(); $lists['ordering'] = JHtml::_('select.genericlist', $orders, 'ordering', 'class="inputbox"', 'value', 'text'); $searchphrases = array(); $searchphrases[] = JHtml::_('select.option', 'all', JText::_('WF_SEARCH_ALL_WORDS')); $searchphrases[] = JHtml::_('select.option', 'any', JText::_('WF_SEARCH_ANY_WORDS')); $searchphrases[] = JHtml::_('select.option', 'exact', JText::_('WF_SEARCH_EXACT_PHRASE')); $lists['searchphrase'] = JHtml::_('select.radiolist', $searchphrases, 'searchphrase', '', 'value', 'text', 'all'); $view = $this->getView(array('name' => 'search', 'layout' => 'search')); $view->searchareas = self::getAreas(); $view->lists = $lists; $view->display(); } private static function getSearchAreaFromUrl($url) { $query = parse_url($url, PHP_URL_QUERY); if (empty($query)) { return ""; } parse_str($query, $values); if (!array_key_exists('option', $values)) { return ""; } $language = JFactory::getLanguage(); $option = $values['option']; // load system language file $language->load($option.'.sys', JPATH_ADMINISTRATOR); $language->load($option, JPATH_ADMINISTRATOR); return JText::_($option); } /** * Process search. * * @param type $query Search query * * @return array Rerach Results * * This method uses portions of SearchController::search from components/com_search/controller.php * * @copyright Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved */ public function doSearch($query) { $wf = WFEditorPlugin::getInstance(); $results = array(); if (empty($query)) { return $results; } // search area $area = null; // available search areas $areas = $this->getAreas(); // query using a specific plugin if (strpos($query, ':') !== false) { preg_match('#^(' . implode('|', $areas) . ')\:(.+)#', $query, $matches); if ($matches) { $area = array($matches[1]); $query = $matches[2]; } } if (!class_exists('JSite')) { // Load JSite class JLoader::register('JSite', JPATH_SITE.'/includes/application.php'); } $app = JFactory::getApplication('site'); $filter = JFilterInput::getInstance(); $router = $app::getRouter('site'); // get SearchHelper require_once JPATH_ADMINISTRATOR.'/components/com_search/helpers/search.php'; // get router mode $sef = (int) $wf->getParam('search.link.sef_url', 0); $limit = (int) $wf->getParam('search.link.limit', 50); // set router off so a raw url is returned by the Search plugin if ($router) { //$router->setMode(0); } // slashes cause errors, <> get stripped anyway later on. # causes problems. $searchword = trim(str_replace(array('#', '>', '<', '\\'), '', $filter->clean($query))); $ordering = null; $searchphrase = 'all'; // if searchword enclosed in double quotes, strip quotes and do exact match if (substr($searchword, 0, 1) == '"' && substr($searchword, -1) == '"') { $searchword = substr($searchword, 1, -1); $searchphrase = 'exact'; } $searchphrase = $app->input->post->getWord('searchphrase', $searchphrase); // get passed through ordering $ordering = $app->input->post->getWord('ordering', $ordering); // get passed through area $area = $app->input->post->getCmd('areas', (array) $area); if (empty($area)) { $area = null; } // trigger search on loaded plugins $searches = $app->triggerEvent('onContentSearch', array( $searchword, $searchphrase, $ordering, $area, )); $rows = array(); foreach ($searches as $search) { $rows = array_merge((array) $rows, (array) $search); } // get first 10 $rows = array_slice($rows, 0, $limit); $areas = array(); for ($i = 0, $count = count($rows); $i < $count; ++$i) { $row = &$rows[$i]; if (empty($row->href) || empty($row->text)) { continue; } $area = self::getSearchAreaFromUrl($row->href); if (!isset($areas[$area])) { $areas[$area] = array(); } $result = new StdClass; if ($searchphrase == 'exact') { $searchwords = array($searchword); $needle = $searchword; } else { $searchworda = preg_replace('#\xE3\x80\x80#s', ' ', $searchword); $searchwords = preg_split("/\s+/u", $searchworda); $needle = $searchwords[0]; } // get anchors if any... $row->anchors = self::getAnchors($row->text); $row->text = SearchHelper::prepareSearchContent($row->text, $needle); // remove base url if (JURI::base(true) && strpos($row->href, JURI::base(true)) !== false) { $row->href = substr_replace($row->href, '', 0, strlen(JURI::base(true)) + 1); } // remove the alias from a link if ((int) $wf->getParam('search.link.remove_alias', 0) && strpos($row->href, ':') !== false) { $row->href = preg_replace('#\:[\w-]+#ui', '', $row->href); } // convert to SEF if ($router && $sef) { $router->setMode(1); $url = str_replace('&', '&', $row->href); $uri = $router->build($url); $url = $uri->toString(); $row->href = str_replace('/administrator/', '/', $url); } $result->title = $row->title; $result->text = $row->text; $result->link = $row->href; if (!empty($row->anchors)) { $result->anchors = $row->anchors; } $areas[$area][] = $result; } if (!empty($areas)) { $results[] = $areas; } return $results; } private static function getAnchors($content) { preg_match_all('#<a([^>]+)(name|id)="([a-z]+[\w\-\:\.]*)"([^>]*)>#i', $content, $matches, PREG_SET_ORDER); $anchors = array(); if (!empty($matches)) { foreach ($matches as $match) { if (strpos($match[0], 'href') === false) { $anchors[] = $match[3]; } } } return $anchors; } }