Файловый менеджер - Редактировать - /home/wuectly/www/03cbe/helpers.tar
Назад
protect.php 0000604 00000014604 15245535622 0006747 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\Document as RL_Document; use RegularLabs\Library\Protect as RL_Protect; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLProtect { public static function isProtectedPage($extension_alias = '', $hastags = false, $exclude_formats = ['pdf']) { if ( ! class_exists('RegularLabs\Library\Protect')) { return true; } if (RL_Protect::isDisabledByUrl($extension_alias)) { return true; } return class_exists('RegularLabs\Library\Protect') && RL_Protect::isRestrictedPage($hastags, $exclude_formats); } public static function isAdmin($block_login = false) { return class_exists('RegularLabs\Library\Document') && RL_Document::isAdmin($block_login); } public static function isEditPage() { return class_exists('RegularLabs\Library\Document') && RL_Document::isEditPage(); } public static function isRestrictedComponent($restricted_components, $area = 'component') { return class_exists('RegularLabs\Library\Protect') && RL_Protect::isRestrictedComponent($restricted_components, $area); } public static function isComponentInstalled($extension_alias) { return class_exists('RegularLabs\Library\Protect') && RL_Protect::isComponentInstalled($extension_alias); } public static function isSystemPluginInstalled($extension_alias) { return class_exists('RegularLabs\Library\Protect') && RL_Protect::isSystemPluginInstalled($extension_alias); } public static function getFormRegex($regex_format = false) { return class_exists('RegularLabs\Library\Protect') && RL_Protect::getFormRegex($regex_format); } public static function protectFields(&$string, $search_strings = []) { class_exists('RegularLabs\Library\Protect') && RL_Protect::protectFields($string, $search_strings); } public static function protectScripts(&$string) { class_exists('RegularLabs\Library\Protect') && RL_Protect::protectScripts($string); } public static function protectHtmlTags(&$string) { class_exists('RegularLabs\Library\Protect') && RL_Protect::protectHtmlTags($string); } public static function protectByRegex(&$string, $regex) { class_exists('RegularLabs\Library\Protect') && RL_Protect::protectByRegex($string, $regex); } public static function protectTags(&$string, $tags = [], $include_closing_tags = true) { class_exists('RegularLabs\Library\Protect') && RL_Protect::protectTags($string, $tags, $include_closing_tags); } public static function unprotectTags(&$string, $tags = [], $include_closing_tags = true) { class_exists('RegularLabs\Library\Protect') && RL_Protect::unprotectTags($string, $tags, $include_closing_tags); } public static function protectInString(&$string, $unprotected = [], $protected = []) { class_exists('RegularLabs\Library\Protect') && RL_Protect::protectInString($string, $unprotected, $protected); } public static function unprotectInString(&$string, $unprotected = [], $protected = []) { class_exists('RegularLabs\Library\Protect') && RL_Protect::unprotectInString($string, $unprotected, $protected); } public static function protectSourcerer(&$string) { class_exists('RegularLabs\Library\Protect') && RL_Protect::protectSourcerer($string); } public static function protectForm(&$string, $tags = [], $include_closing_tags = true) { class_exists('RegularLabs\Library\Protect') && RL_Protect::protectForm($string, $tags, $include_closing_tags); } public static function unprotect(&$string) { class_exists('RegularLabs\Library\Protect') && RL_Protect::unprotect($string); } public static function convertProtectionToHtmlSafe(&$string) { class_exists('RegularLabs\Library\Protect') && RL_Protect::convertProtectionToHtmlSafe($string); } public static function unprotectHtmlSafe(&$string) { class_exists('RegularLabs\Library\Protect') && RL_Protect::unprotectHtmlSafe($string); } public static function protectString($string, $is_tag = false) { return class_exists('RegularLabs\Library\Protect') && RL_Protect::protectString($string, $is_tag); } public static function unprotectString($string, $is_tag = false) { return class_exists('RegularLabs\Library\Protect') && RL_Protect::unprotectString($string, $is_tag); } public static function protectTag($string) { return class_exists('RegularLabs\Library\Protect') && RL_Protect::protectTag($string); } public static function protectArray($array, $is_tag = false) { return class_exists('RegularLabs\Library\Protect') && RL_Protect::protectArray($array, $is_tag); } public static function unprotectArray($array, $is_tag = false) { return class_exists('RegularLabs\Library\Protect') && RL_Protect::unprotectArray($array, $is_tag); } public static function unprotectForm(&$string, $tags = []) { class_exists('RegularLabs\Library\Protect') && RL_Protect::unprotectForm($string, $tags); } public static function removeInlineComments(&$string, $name) { class_exists('RegularLabs\Library\Protect') && RL_Protect::removeInlineComments($string, $name); } public static function removePluginTags(&$string, $tags, $character_start = '{', $character_end = '{', $keep_content = true) { class_exists('RegularLabs\Library\Protect') && RL_Protect::removePluginTags($string, $tags, $character_start, $character_end, $keep_content); } public static function removeFromHtmlTagContent(&$string, $tags, $include_closing_tags = true, $html_tags = ['title']) { class_exists('RegularLabs\Library\Protect') && RL_Protect::removeFromHtmlTagContent($string, $tags, $include_closing_tags, $html_tags); } public static function removeFromHtmlTagAttributes(&$string, $tags, $attributes = 'ALL', $include_closing_tags = true) { class_exists('RegularLabs\Library\Protect') && RL_Protect::removeFromHtmlTagAttributes($string, $tags, $attributes, $include_closing_tags); } public static function articlePassesSecurity(&$article, $securtiy_levels = []) { return class_exists('RegularLabs\Library\Protect') && RL_Protect::articlePassesSecurity($article, $securtiy_levels); } public static function isJoomla3() { return true; } } functions.php 0000604 00000010562 15245535622 0007276 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\Document as RL_Document; use RegularLabs\Library\Extension as RL_Extension; use RegularLabs\Library\File as RL_File; use RegularLabs\Library\Http as RL_Http; use RegularLabs\Library\Language as RL_Language; use RegularLabs\Library\Xml as RL_Xml; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } /** * Framework Functions */ class RLFunctions { public static function getContents($url, $timeout = 20) { return ! class_exists('RegularLabs\Library\Http') ? '' : RL_Http::get($url, $timeout); } public static function getByUrl($url, $timeout = 20) { return ! class_exists('RegularLabs\Library\Http') ? '' : RL_Http::getFromServer($url, $timeout); } public static function isFeed() { return class_exists('RegularLabs\Library\Document') && RL_Document::isFeed(); } public static function script($file, $version = '') { class_exists('RegularLabs\Library\Document') && RL_Document::script($file, $version); } public static function stylesheet($file, $version = '') { class_exists('RegularLabs\Library\Document') && RL_Document::stylesheet($file, $version); } public static function addScriptVersion($url) { jimport('joomla.filesystem.file'); $version = ''; if (file_exists(JPATH_SITE . $url)) { $version = filemtime(JPATH_SITE . $url); } self::script($url, $version); } public static function addStyleSheetVersion($url) { jimport('joomla.filesystem.file'); $version = ''; if (file_exists(JPATH_SITE . $url)) { $version = filemtime(JPATH_SITE . $url); } self::stylesheet($url, $version); } protected static function getFileByFolder($folder, $file) { return ! class_exists('RegularLabs\Library\File') ? '' : RL_File::getMediaFile($folder, $file); } public static function getComponentBuffer() { return ! class_exists('RegularLabs\Library\Document') ? '' : RL_Document::getBuffer(); } public static function getAliasAndElement(&$name) { return ! class_exists('RegularLabs\Library\Extension') ? '' : RL_Extension::getAliasAndElement($name); } public static function getNameByAlias($alias) { return ! class_exists('RegularLabs\Library\Extension') ? '' : RL_Extension::getNameByAlias($alias); } public static function getAliasByName($name) { return ! class_exists('RegularLabs\Library\Extension') ? '' : RL_Extension::getAliasByName($name); } public static function getElementByAlias($alias) { return ! class_exists('RegularLabs\Library\Extension') ? '' : RL_Extension::getElementByAlias($alias); } public static function getXMLValue($key, $alias, $type = 'component', $folder = 'system') { return ! class_exists('RegularLabs\Library\Extension') ? '' : RL_Extension::getXMLValue($key, $alias, $type, $folder); } public static function getXML($alias, $type = 'component', $folder = 'system') { return ! class_exists('RegularLabs\Library\Extension') ? '' : RL_Extension::getXML($alias, $type, $folder); } public static function getXMLFile($alias, $type = 'component', $folder = 'system') { return ! class_exists('RegularLabs\Library\Extension') ? '' : RL_Extension::getXMLFile($alias, $type, $folder); } public static function extensionInstalled($extension, $type = 'component', $folder = 'system') { return ! class_exists('RegularLabs\Library\Extension') ? '' : RL_Extension::isInstalled($extension, $type, $folder); } public static function getExtensionPath($extension = 'plg_system_regularlabs', $basePath = JPATH_ADMINISTRATOR, $check_folder = '') { return ! class_exists('RegularLabs\Library\Extension') ? '' : RL_Extension::getPath($extension, $basePath, $check_folder); } public static function loadLanguage($extension = 'plg_system_regularlabs', $basePath = '', $reload = false) { return class_exists('RegularLabs\Library\Language') && RL_Language::load($extension, $basePath, $reload); } public static function xmlToObject($url, $root = '') { return ! class_exists('RegularLabs\Library\Xml') ? '' : RL_Xml::toObject($url, $root); } } assignments.php 0000604 00000002132 15245535622 0007613 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\Conditions as RL_Conditions; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLAssignmentsHelper { function passAll($assignments, $matching_method = 'all', $item = 0) { return RL_Conditions::pass($assignments, $matching_method, $item); } public function getAssignmentsFromParams(&$params) { return RL_Conditions::getConditionsFromParams($params); } public function getAssignmentsFromTagAttributes(&$params, $types = []) { return RL_Conditions::getConditionsFromTagAttributes($params, $types); } public function hasAssignments(&$assignments) { return RL_Conditions::hasConditions($assignments); } } text.php 0000604 00000011417 15245535622 0006252 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\Alias as RL_Alias; use RegularLabs\Library\ArrayHelper as RL_Array; use RegularLabs\Library\Date as RL_Date; use RegularLabs\Library\Form as RL_Form; use RegularLabs\Library\Html as RL_Html; use RegularLabs\Library\HtmlTag as RL_HtmlTag; use RegularLabs\Library\PluginTag as RL_PluginTag; use RegularLabs\Library\RegEx as RL_RegEx; use RegularLabs\Library\StringHelper as RL_String; use RegularLabs\Library\Title as RL_Title; use RegularLabs\Library\Uri as RL_Uri; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLText { /* Date functions */ public static function fixDate(&$date) { $date = RL_Date::fix($date); } public static function fixDateOffset(&$date) { RL_Date::applyTimezone($date); } public static function dateToDateFormat($dateFormat) { return RL_Date::strftimeToDateFormat($dateFormat); } public static function dateToStrftimeFormat($dateFormat) { return RL_Date::dateToStrftimeFormat($dateFormat); } /* String functions */ public static function html_entity_decoder($string, $quote_style = ENT_QUOTES, $charset = 'UTF-8') { return RL_String::html_entity_decoder($string, $quote_style, $charset); } public static function stringContains($haystacks, $needles) { return RL_String::contains($haystacks, $needles); } public static function is_alphanumeric($string) { return RL_String::is_alphanumeric($string); } public static function splitString($string, $delimiters = [], $max_length = 10000, $maximize_parts = true) { return RL_String::split($string, $delimiters, $max_length, $maximize_parts); } public static function strReplaceOnce($search, $replace, $string) { return RL_String::replaceOnce($search, $replace, $string); } /* Array functions */ public static function toArray($data, $separator = '') { return RL_Array::toArray($data, $separator); } public static function createArray($data, $separator = ',') { return RL_Array::toArray($data, $separator, true); } /* RegEx functions */ public static function regexReplace($pattern, $replacement, $string) { return RL_RegEx::replace($pattern, $replacement, $string); } public static function pregQuote($string = '', $delimiter = '#') { return RL_RegEx::quote($string, $delimiter); } public static function pregQuoteArray($array = [], $delimiter = '#') { return RL_RegEx::quoteArray($array, $delimiter); } /* Title functions */ public static function cleanTitle($string, $strip_tags = false, $strip_spaces = true) { return RL_Title::clean($string, $strip_tags, $strip_spaces); } public static function createUrlMatches($titles = []) { return RL_Title::getUrlMatches($titles); } /* Alias functions */ public static function createAlias($string) { return RL_Alias::get($string); } /* Uri functions */ public static function getURI($hash = '') { return RL_Uri::get($hash); } /* Plugin Tag functions */ public static function getTagRegex($tags, $include_no_attributes = true, $include_ending = true, $required_attributes = []) { return RL_PluginTag::getRegexTags($tags, $include_no_attributes, $include_ending, $required_attributes); } /* HTML functions */ public static function getBody($html) { return RL_Html::getBody($html); } public static function getContentContainingSearches($string, $start_searches = [], $end_searches = [], $start_offset = 1000, $end_offset = null) { return RL_Html::getContentContainingSearches($string, $start_searches, $end_searches, $start_offset, $end_offset); } public static function convertWysiwygToPlainText($string) { return RL_Html::convertWysiwygToPlainText($string); } public static function combinePTags(&$string) { RL_Html::combinePTags($string); } /* HTML Tag functions */ public static function combineTags($tag1, $tag2) { return RL_HtmlTag::combine($tag1, $tag2); } public static function getAttribute($key, $string) { return RL_HtmlTag::getAttributeValue($key, $string); } public static function getAttributes($string) { return RL_HtmlTag::getAttributes($string); } public static function combineAttributes($string1, $string2) { return RL_HtmlTag::combineAttributes($string1, $string2); } /* Form functions */ public static function prepareSelectItem($string, $published = 1, $type = '', $remove_first = 0) { return RL_Form::prepareSelectItem($string, $published, $type, $remove_first); } } assignments/mijoshop.php 0000604 00000005770 15245535622 0011456 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsMijoShop extends RLAssignment { public function init() { $input = JFactory::getApplication()->input; $category_id = $input->getCmd('path', 0); if (strpos($category_id, '_')) { $category_id = end(explode('_', $category_id)); } $this->request->item_id = $input->getInt('product_id', 0); $this->request->category_id = $category_id; $this->request->id = ($this->request->item_id) ? $this->request->item_id : $this->request->category_id; $view = $input->getCmd('view', ''); if (empty($view)) { $mijoshop = JPATH_ROOT . '/components/com_mijoshop/mijoshop/mijoshop.php'; if ( ! file_exists($mijoshop)) { return; } require_once($mijoshop); $route = $input->getString('route', ''); $view = MijoShop::get('router')->getView($route); } $this->request->view = $view; } public function passPageTypes() { return $this->passByPageTypes('com_mijoshop', $this->selection, $this->assignment, true); } public function passCategories() { if ($this->request->option != 'com_mijoshop') { return $this->pass(false); } $pass = ( ($this->params->inc_categories && ($this->request->view == 'category') ) || ($this->params->inc_items && $this->request->view == 'product') ); if ( ! $pass) { return $this->pass(false); } $cats = []; if ($this->request->category_id) { $cats = $this->request->category_id; } else if ($this->request->item_id) { $query = $this->db->getQuery(true) ->select('c.category_id') ->from('#__mijoshop_product_to_category AS c') ->where('c.product_id = ' . (int) $this->request->id); $this->db->setQuery($query); $cats = $this->db->loadColumn(); } $cats = $this->makeArray($cats); $pass = $this->passSimple($cats, 'include'); if ($pass && $this->params->inc_children == 2) { return $this->pass(false); } else if ( ! $pass && $this->params->inc_children) { foreach ($cats as $cat) { $cats = array_merge($cats, $this->getCatParentIds($cat)); } } return $this->passSimple($cats); } public function passProducts() { if ( ! $this->request->id || $this->request->option != 'com_mijoshop' || $this->request->view != 'product') { return $this->pass(false); } return $this->passSimple($this->request->id); } private function getCatParentIds($id = 0) { return $this->getParentIds($id, 'mijoshop_category', 'parent_id', 'category_id'); } } assignments/akeebasubs.php 0000604 00000002606 15245535622 0011726 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLAssignmentsAkeebaSubs extends RLAssignment { public function init() { if ( ! $this->request->id && $this->request->view == 'level') { $slug = JFactory::getApplication()->input->getString('slug', ''); if ($slug) { $query = $this->db->getQuery(true) ->select('l.akeebasubs_level_id') ->from('#__akeebasubs_levels AS l') ->where('l.slug = ' . $this->db->quote($slug)); $this->db->setQuery($query); $this->request->id = $this->db->loadResult(); } } } public function passPageTypes() { return $this->passByPageTypes('com_akeebasubs', $this->selection, $this->assignment); } public function passLevels() { if ( ! $this->request->id || $this->request->option != 'com_akeebasubs' || $this->request->view != 'level') { return $this->pass(false); } return $this->passSimple($this->request->id); } } assignments/tags.php 0000604 00000005173 15245535622 0010561 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsTags extends RLAssignment { public function passTags() { if (in_array($this->request->option, ['com_content', 'com_flexicontent'])) { return $this->passTagsContent(); } if ($this->request->option != 'com_tags' || $this->request->view != 'tag' || ! $this->request->id ) { return $this->pass(false); } return $this->passTag($this->request->id); } private function passTagsContent() { $is_item = in_array($this->request->view, ['', 'article', 'item']); $is_category = in_array($this->request->view, ['category']); switch (true) { case ($is_item): $prefix = 'com_content.article'; break; case ($is_category): $prefix = 'com_content.category'; break; default: return $this->pass(false); } // Load the tags. $query = $this->db->getQuery(true) ->select($this->db->quoteName('t.id')) ->select($this->db->quoteName('t.title')) ->from('#__tags AS t') ->join( 'INNER', '#__contentitem_tag_map AS m' . ' ON m.tag_id = t.id' . ' AND m.type_alias = ' . $this->db->quote($prefix) . ' AND m.content_item_id IN ( ' . $this->request->id . ')' ); $this->db->setQuery($query); $tags = $this->db->loadObjectList(); if (empty($tags)) { return $this->pass(false); } foreach ($tags as $tag) { if ( ! $this->passTag($tag->id) && ! $this->passTag($tag->title)) { continue; } return $this->pass(true); } return $this->pass(false); } private function passTag($tag) { $pass = in_array($tag, $this->selection); if ($pass) { // If passed, return false if assigned to only children // Else return true return ($this->params->inc_children != 2); } if ( ! $this->params->inc_children) { return false; } // Return true if a parent id is present in the selection return array_intersect( $this->getTagsParentIds($tag), $this->selection ); } private function getTagsParentIds($id = 0) { $parentids = $this->getParentIds($id, 'tags'); // Remove the root tag $parentids = array_diff($parentids, [1]); return $parentids; } } assignments/geo.php 0000604 00000005162 15245535622 0010373 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; use Joomla\CMS\Log\Log as JLog; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsGeo extends RLAssignment { var $geo = null; /** * passContinents */ public function passContinents() { if ( ! $this->getGeo() || empty($this->geo->continentCode)) { return $this->pass(false); } return $this->passSimple([$this->geo->continent, $this->geo->continentCode]); } /** * passCountries */ public function passCountries() { $this->getGeo(); if ( ! $this->getGeo() || empty($this->geo->countryCode)) { return $this->pass(false); } return $this->passSimple([$this->geo->country, $this->geo->countryCode]); } /** * passRegions */ public function passRegions() { if ( ! $this->getGeo() || empty($this->geo->countryCode) || empty($this->geo->regionCodes)) { return $this->pass(false); } $regions = $this->geo->regionCodes; array_walk($regions, function (&$value) { $value = $this->geo->countryCode . '-' . $value; }); return $this->passSimple($regions); } /** * passPostalcodes */ public function passPostalcodes() { if ( ! $this->getGeo() || empty($this->geo->postalCode)) { return $this->pass(false); } // replace dashes with dots: 730-0011 => 730.0011 $postalcode = str_replace('-', '.', $this->geo->postalCode); return $this->passInRange($postalcode); } public function getGeo($ip = '') { if ($this->geo !== null) { return $this->geo; } $geo = $this->getGeoObject($ip); if (empty($geo)) { return false; } $this->geo = $geo->get(); if (JFactory::getApplication()->get('debug')) { JLog::addLogger(['text_file' => 'regularlabs_geoip.log.php'], JLog::ALL, ['regularlabs_geoip']); JLog::add(json_encode($this->geo), JLog::DEBUG, 'regularlabs_geoip'); } return $this->geo; } private function getGeoObject($ip) { if ( ! file_exists(JPATH_LIBRARIES . '/geoip/geoip.php')) { return false; } require_once JPATH_LIBRARIES . '/geoip/geoip.php'; if ( ! class_exists('RegularLabs_GeoIp')) { return new GeoIp($ip); } return new RegularLabs_GeoIp($ip); } } assignments/cookieconfirm.php 0000604 00000001477 15245535622 0012455 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsCookieConfirm extends RLAssignment { public function passCookieConfirm() { require_once JPATH_PLUGINS . '/system/cookieconfirm/core.php'; $pass = PlgSystemCookieconfirmCore::getInstance()->isCookiesAllowed(); return $this->pass($pass); } } assignments/users.php 0000604 00000007123 15245535622 0010761 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsUsers extends RLAssignment { public function passAccessLevels() { $user = JFactory::getUser(); $levels = $user->getAuthorisedViewLevels(); $this->selection = $this->convertAccessLevelNamesToIds($this->selection); return $this->passSimple($levels); } public function passUserGroupLevels() { $user = JFactory::getUser(); if ( ! empty($user->groups)) { $groups = array_values($user->groups); } else { $groups = $user->getAuthorisedGroups(); } if ($this->params->inc_children) { $this->setUserGroupChildrenIds(); } $this->selection = $this->convertUsergroupNamesToIds($this->selection); return $this->passSimple($groups); } public function passUsers() { return $this->passSimple(JFactory::getUser()->get('id')); } private function convertAccessLevelNamesToIds($selection) { $names = []; foreach ($selection as $i => $level) { if (is_numeric($level)) { continue; } unset($selection[$i]); $names[] = strtolower(str_replace(' ', '', $level)); } $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('id')) ->from('#__viewlevels') ->where('LOWER(REPLACE(' . $db->quoteName('title') . ', " ", "")) IN (\'' . implode('\',\'', $names) . '\')'); $db->setQuery($query); $level_ids = $db->loadColumn(); return array_unique(array_merge($selection, $level_ids)); } private function convertUsergroupNamesToIds($selection) { $names = []; foreach ($selection as $i => $group) { if (is_numeric($group)) { continue; } unset($selection[$i]); $names[] = strtolower(str_replace(' ', '', $group)); } $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('id')) ->from('#__usergroups') ->where('LOWER(REPLACE(' . $db->quoteName('title') . ', " ", "")) IN (\'' . implode('\',\'', $names) . '\')'); $db->setQuery($query); $group_ids = $db->loadColumn(); return array_unique(array_merge($selection, $group_ids)); } private function setUserGroupChildrenIds() { $children = $this->getUserGroupChildrenIds($this->selection); if ($this->params->inc_children == 2) { $this->selection = $children; return; } $this->selection = array_merge($this->selection, $children); } private function getUserGroupChildrenIds($groups) { $children = []; $db = JFactory::getDbo(); foreach ($groups as $group) { $query = $db->getQuery(true) ->select($db->quoteName('id')) ->from($db->quoteName('#__usergroups')) ->where($db->quoteName('parent_id') . ' = ' . (int) $group); $db->setQuery($query); $group_children = $db->loadColumn(); if (empty($group_children)) { continue; } $children = array_merge($children, $group_children); $group_grand_children = $this->getUserGroupChildrenIds($group_children); if (empty($group_grand_children)) { continue; } $children = array_merge($children, $group_grand_children); } $children = array_unique($children); return $children; } } assignments/easyblog.php 0000604 00000010007 15245535622 0011420 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsEasyBlog extends RLAssignment { public function passPageTypes() { return $this->passByPageTypes('com_easyblog', $this->selection, $this->assignment); } public function passCategories() { if ($this->request->option != 'com_easyblog') { return $this->pass(false); } $pass = ( ($this->params->inc_categories && $this->request->view == 'categories') || ($this->params->inc_items && $this->request->view == 'entry') ); if ( ! $pass) { return $this->pass(false); } $cats = $this->makeArray($this->getCategories()); $pass = $this->passSimple($cats, 'include'); if ($pass && $this->params->inc_children == 2) { return $this->pass(false); } else if ( ! $pass && $this->params->inc_children) { foreach ($cats as $cat) { $cats = array_merge($cats, $this->getCatParentIds($cat)); } } return $this->passSimple($cats); } private function getCategories() { switch ($this->request->view) { case 'entry' : return $this->getCategoryIDFromItem(); break; case 'categories' : return $this->request->id; break; default: return ''; } } private function getCategoryIDFromItem() { $query = $this->db->getQuery(true) ->select('i.category_id') ->from('#__easyblog_post AS i') ->where('i.id = ' . (int) $this->request->id); $this->db->setQuery($query); return $this->db->loadResult(); } public function passTags() { if ($this->request->option != 'com_easyblog') { return $this->pass(false); } $pass = ( ($this->params->inc_tags && $this->request->layout == 'tag') || ($this->params->inc_items && $this->request->view == 'entry') ); if ( ! $pass) { return $this->pass(false); } if ($this->params->inc_tags && $this->request->layout == 'tag') { $query = $this->db->getQuery(true) ->select('t.alias') ->from('#__easyblog_tag AS t') ->where('t.id = ' . (int) $this->request->id) ->where('t.published = 1'); $this->db->setQuery($query); $tags = $this->db->loadColumn(); return $this->passSimple($tags, true); } $query = $this->db->getQuery(true) ->select('t.alias') ->from('#__easyblog_post_tag AS x') ->join('LEFT', '#__easyblog_tag AS t ON t.id = x.tag_id') ->where('x.post_id = ' . (int) $this->request->id) ->where('t.published = 1'); $this->db->setQuery($query); $tags = $this->db->loadColumn(); return $this->passSimple($tags, true); } public function passItems() { if ( ! $this->request->id || $this->request->option != 'com_easyblog' || $this->request->view != 'entry') { return $this->pass(false); } $pass = false; // Pass Article Id if ( ! $this->passItemByType($pass, 'ContentIds')) { return $this->pass(false); } // Pass Content Keywords if ( ! $this->passItemByType($pass, 'ContentKeywords')) { return $this->pass(false); } // Pass Authors if ( ! $this->passItemByType($pass, 'Authors')) { return $this->pass(false); } return $this->pass($pass); } public function passContentKeywords($fields = ['title', 'intro', 'content'], $text = '') { parent::passContentKeywords($fields); } public function getItem($fields = []) { $query = $this->db->getQuery(true) ->select($fields) ->from('#__easyblog_post') ->where('id = ' . (int) $this->request->id); $this->db->setQuery($query); return $this->db->loadObject(); } private function getCatParentIds($id = 0) { return $this->getParentIds($id, 'easyblog_category', 'parent_id'); } } assignments/ips.php 0000604 00000005742 15245535622 0010420 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsIPs extends RLAssignment { public function passIPs() { if (is_array($this->selection)) { $this->selection = implode(',', $this->selection); } $this->selection = explode(',', str_replace([' ', "\r", "\n"], ['', '', ','], $this->selection)); $pass = $this->checkIPList(); return $this->pass($pass); } private function checkIPList() { foreach ($this->selection as $range) { // Check next range if this one doesn't match if ( ! $this->checkIP($range)) { continue; } // Match found, so return true! return true; } // No matches found, so return false return false; } private function checkIP($range) { if (empty($range)) { return false; } if (strpos($range, '-') !== false) { // Selection is an IP range return $this->checkIPRange($range); } // Selection is a single IP (part) return $this->checkIPPart($range); } private function checkIPRange($range) { $ip = $_SERVER['REMOTE_ADDR']; // Return if no IP address can be found (shouldn't happen, but who knows) if (empty($ip)) { return false; } // check if IP is between or equal to the from and to IP range list($min, $max) = explode('-', trim($range), 2); // Return false if IP is smaller than the range start if ($ip < trim($min)) { return false; } $max = $this->fillMaxRange($max, $min); // Return false if IP is larger than the range end if ($ip > trim($max)) { return false; } return true; } /* Fill the max range by prefixing it with the missing parts from the min range * So 101.102.103.104-201.202 becomes: * max: 101.102.201.202 */ private function fillMaxRange($max, $min) { $max_parts = explode('.', $max); if (count() == 4) { return $max; } $min_parts = explode('.', $min); $prefix = array_slice($min_parts, 0, count($min_parts) - count($max_parts)); return implode('.', $prefix) . '.' . implode('.', $max_parts); } private function checkIPPart($range) { $ip = $_SERVER['REMOTE_ADDR']; // Return if no IP address can be found (shouldn't happen, but who knows) if (empty($ip)) { return false; } $ip_parts = explode('.', $ip); $range_parts = explode('.', trim($range)); // Trim the IP to the part length of the range $ip = implode('.', array_slice($ip_parts, 0, count($range_parts))); // Return false if ip does not match the range if ($range != $ip) { return false; } return true; } } assignments/menu.php 0000604 00000004547 15245535622 0010573 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsMenu extends RLAssignment { public function passMenu() { // return if no Itemid or selection is set if ( ! $this->request->Itemid || empty($this->selection)) { return $this->pass($this->params->inc_noitemid); } $menutype = 'type.' . self::getMenuType(); // return true if menu type is in selection if (in_array($menutype, $this->selection)) { return $this->pass(true); } // return true if menu is in selection if (in_array($this->request->Itemid, $this->selection)) { return $this->pass(($this->params->inc_children != 2)); } if ( ! $this->params->inc_children) { return $this->pass(false); } $parent_ids = $this->getMenuParentIds($this->request->Itemid); $parent_ids = array_diff($parent_ids, [1]); foreach ($parent_ids as $id) { if ( ! in_array($id, $this->selection)) { continue; } return $this->pass(true); } return $this->pass(false); } private function getMenuParentIds($id = 0) { return $this->getParentIds($id, 'menu'); } private function getMenuType() { if (isset($this->request->menutype)) { return $this->request->menutype; } if (empty($this->request->Itemid)) { $this->request->menutype = ''; return $this->request->menutype; } if (JFactory::getApplication()->isClient('site')) { $menu = JFactory::getApplication()->getMenu()->getItem((int) $this->request->Itemid); $this->request->menutype = isset($menu->menutype) ? $menu->menutype : ''; return $this->request->menutype; } $query = $this->db->getQuery(true) ->select('m.menutype') ->from('#__menu AS m') ->where('m.id = ' . (int) $this->request->Itemid); $this->db->setQuery($query); $this->request->menutype = $this->db->loadResult(); return $this->request->menutype; } } assignments/content.php 0000604 00000013030 15245535622 0011264 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; use Joomla\CMS\MVC\Model\BaseDatabaseModel as JModel; use Joomla\CMS\Table\Table as JTable; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsContent extends RLAssignment { public function passPageTypes() { $components = ['com_content', 'com_contentsubmit']; if ( ! in_array($this->request->option, $components)) { return $this->pass(false); } if ($this->request->view == 'category' && $this->request->layout == 'blog') { $view = 'categoryblog'; } else { $view = $this->request->view; } return $this->passSimple($view); } public function passCategories() { // components that use the com_content secs/cats $components = ['com_content', 'com_flexicontent', 'com_contentsubmit']; if ( ! in_array($this->request->option, $components)) { return $this->pass(false); } if (empty($this->selection)) { return $this->pass(false); } $is_content = in_array($this->request->option, ['com_content', 'com_flexicontent']); $is_category = in_array($this->request->view, ['category']); $is_item = in_array($this->request->view, ['', 'article', 'item', 'form']); if ( $this->request->option != 'com_contentsubmit' && ! ($this->params->inc_categories && $is_content && $is_category) && ! ($this->params->inc_articles && $is_content && $is_item) && ! ($this->params->inc_others && ! ($is_content && ($is_category || $is_item))) ) { return $this->pass(false); } if ($this->request->option == 'com_contentsubmit') { // Content Submit $contentsubmit_params = new ContentsubmitModelArticle; if (in_array($contentsubmit_params->_id, $this->selection)) { return $this->pass(true); } return $this->pass(false); } $pass = false; if ( $this->params->inc_others && ! ($is_content && ($is_category || $is_item)) && $this->article ) { if ( ! isset($this->article->id) && isset($this->article->slug)) { $this->article->id = (int) $this->article->slug; } if ( ! isset($this->article->catid) && isset($this->article->catslug)) { $this->article->catid = (int) $this->article->catslug; } $this->request->id = $this->article->id; $this->request->view = 'article'; } $catids = $this->getCategoryIds($is_category); foreach ($catids as $catid) { if ( ! $catid) { continue; } $pass = in_array($catid, $this->selection); if ($pass && $this->params->inc_children == 2) { $pass = false; continue; } if ( ! $pass && $this->params->inc_children) { $parent_ids = $this->getCatParentIds($catid); $parent_ids = array_diff($parent_ids, [1]); foreach ($parent_ids as $id) { if (in_array($id, $this->selection)) { $pass = true; break; } } unset($parent_ids); } } return $this->pass($pass); } private function getCategoryIds($is_category = false) { if ($is_category) { return (array) $this->request->id; } if ( ! $this->article && $this->request->id) { $this->article = JTable::getInstance('content'); $this->article->load($this->request->id); } if ($this->article && $this->article->catid) { return (array) $this->article->catid; } $catid = JFactory::getApplication()->input->getInt('catid', JFactory::getApplication()->getUserState('com_content.articles.filter.category_id')); $menuparams = $this->getMenuItemParams($this->request->Itemid); if ($this->request->view == 'featured') { $menuparams = $this->getMenuItemParams($this->request->Itemid); return isset($menuparams->featured_categories) ? (array) $menuparams->featured_categories : (array) $catid; } return isset($menuparams->catid) ? (array) $menuparams->catid : (array) $catid; } public function passArticles() { if ( ! $this->request->id || ! (($this->request->option == 'com_content' && $this->request->view == 'article') || ($this->request->option == 'com_flexicontent' && $this->request->view == 'item') ) ) { return $this->pass(false); } $pass = false; // Pass Article Id if ( ! $this->passItemByType($pass, 'ContentIds')) { return $this->pass(false); } // Pass Content Keywords if ( ! $this->passItemByType($pass, 'ContentKeywords')) { return $this->pass(false); } // Pass Meta Keywords if ( ! $this->passItemByType($pass, 'MetaKeywords')) { return $this->pass(false); } // Pass Authors if ( ! $this->passItemByType($pass, 'Authors')) { return $this->pass(false); } return $this->pass($pass); } public function getItem($fields = []) { if ($this->article) { return $this->article; } if ( ! class_exists('ContentModelArticle')) { require_once JPATH_SITE . '/components/com_content/models/article.php'; } $model = JModel::getInstance('article', 'contentModel'); if ( ! method_exists($model, 'getItem')) { return null; } $this->article = $model->getItem($this->request->id); return $this->article; } private function getCatParentIds($id = 0) { return $this->getParentIds($id, 'categories'); } } assignments/components.php 0000604 00000001321 15245535622 0011777 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsComponents extends RLAssignment { public function passComponents() { return $this->passSimple(strtolower($this->request->option)); } } assignments/k2.php 0000604 00000010676 15245535622 0010143 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; // If controller.php exists, assume this is K2 v3 defined('RL_K2_VERSION') or define('RL_K2_VERSION', file_exists(JPATH_ADMINISTRATOR . '/components/com_k2/controller.php') ? 3 : 2); class RLAssignmentsK2 extends RLAssignment { public function passPageTypes() { return $this->passByPageTypes('com_k2', $this->selection, $this->assignment, false, true); } public function passCategories() { if ($this->request->option != 'com_k2') { return $this->pass(false); } $pass = ( ($this->params->inc_categories && (($this->request->view == 'itemlist' && $this->request->task == 'category') || $this->request->view == 'latest' ) ) || ($this->params->inc_items && $this->request->view == 'item') ); if ( ! $pass) { return $this->pass(false); } $cats = $this->makeArray($this->getCategories()); $pass = $this->passSimple($cats, 'include'); if ($pass && $this->params->inc_children == 2) { return $this->pass(false); } else if ( ! $pass && $this->params->inc_children) { foreach ($cats as $cat) { $cats = array_merge($cats, $this->getCatParentIds($cat)); } } return $this->passSimple($cats); } private function getCategories() { switch ($this->request->view) { case 'item' : return $this->getCategoryIDFromItem(); break; case 'itemlist' : return $this->getCategoryID(); break; default: return ''; } } private function getCategoryID() { return $this->request->id ?: JFactory::getApplication()->getUserStateFromRequest('com_k2itemsfilter_category', 'catid', 0, 'int'); } private function getCategoryIDFromItem() { if ($this->article && isset($this->article->catid)) { return $this->article->catid; } $query = $this->db->getQuery(true) ->select('i.catid') ->from('#__k2_items AS i') ->where('i.id = ' . (int) $this->request->id); $this->db->setQuery($query); return $this->db->loadResult(); } public function passTags() { if ($this->request->option != 'com_k2') { return $this->pass(false); } $tag = trim(JFactory::getApplication()->input->getString('tag', '')); $pass = ( ($this->params->inc_tags && $tag != '') || ($this->params->inc_items && $this->request->view == 'item') ); if ( ! $pass) { return $this->pass(false); } if ($this->params->inc_tags && $tag != '') { $tags = [trim(JFactory::getApplication()->input->getString('tag', ''))]; return $this->passSimple($tags, true); } $query = $this->db->getQuery(true) ->select('t.name') ->from('#__k2_tags_xref AS x') ->join('LEFT', '#__k2_tags AS t ON t.id = x.tagID') ->where('x.itemID = ' . (int) $this->request->id) ->where('t.published = 1'); $this->db->setQuery($query); $tags = $this->db->loadColumn(); return $this->passSimple($tags, true); } public function passItems() { if ( ! $this->request->id || $this->request->option != 'com_k2' || $this->request->view != 'item') { return $this->pass(false); } $pass = false; // Pass Article Id if ( ! $this->passItemByType($pass, 'ContentIds')) { return $this->pass(false); } // Pass Content Keywords if ( ! $this->passItemByType($pass, 'ContentKeywords')) { return $this->pass(false); } // Pass Meta Keywords if ( ! $this->passItemByType($pass, 'MetaKeywords')) { return $this->pass(false); } // Pass Authors if ( ! $this->passItemByType($pass, 'Authors')) { return $this->pass(false); } return $this->pass($pass); } public function getItem($fields = []) { $query = $this->db->getQuery(true) ->select($fields) ->from('#__k2_items') ->where('id = ' . (int) $this->request->id); $this->db->setQuery($query); return $this->db->loadObject(); } private function getCatParentIds($id = 0) { $parent_field = RL_K2_VERSION == 3 ? 'parent_id' : 'parent'; return $this->getParentIds($id, 'k2_categories', $parent_field); } } assignments/zoo.php 0000604 00000013015 15245535622 0010424 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsZoo extends RLAssignment { public function init() { if ( ! $this->request->view) { $this->request->view = $this->request->task; } switch ($this->request->view) { case 'item': $this->request->idname = 'item_id'; break; case 'category': $this->request->idname = 'category_id'; break; } $this->request->id = JFactory::getApplication()->input->getInt($this->request->idname, 0); } public function initAssignment($assignment, $article = 0) { parent::initAssignment($assignment, $article); if ($this->request->option != 'com_zoo' && ! isset($this->request->idname)) { return; } switch ($this->request->idname) { case 'item_id': $this->request->view = 'item'; break; case 'category_id': $this->request->view = 'category'; break; } } public function passPageTypes() { return $this->passByPageTypes('com_zoo', $this->selection, $this->assignment); } public function passCategories() { if ($this->request->option != 'com_zoo') { return $this->pass(false); } $pass = ( ($this->params->inc_apps && $this->request->view == 'frontpage') || ($this->params->inc_categories && $this->request->view == 'category') || ($this->params->inc_items && $this->request->view == 'item') ); if ( ! $pass) { return $this->pass(false); } $cats = $this->getCategories(); if ($cats === false) { return $this->pass(false); } $cats = $this->makeArray($cats); $pass = $this->passSimple($cats, 'include'); if ($pass && $this->params->inc_children == 2) { return $this->pass(false); } if ( ! $pass && $this->params->inc_children) { foreach ($cats as $cat) { $cats = array_merge($cats, $this->getCatParentIds($cat)); } } return $this->passSimple($cats); } private function getCategories() { if ($this->article && isset($this->article->catid)) { return [$this->article->catid]; } $menuparams = $this->getMenuItemParams($this->request->Itemid); switch ($this->request->view) { case 'frontpage': if ($this->request->id) { return [$this->request->id]; } if ( ! isset($menuparams->application)) { return []; } return ['app' . $menuparams->application]; case 'category': $cats = []; if ($this->request->id) { $cats[] = $this->request->id; } else if (isset($menuparams->category)) { $cats[] = $menuparams->category; } if (empty($cats[0])) { return []; } $query = $this->db->getQuery(true) ->select('c.application_id') ->from('#__zoo_category AS c') ->where('c.id = ' . (int) $cats[0]); $this->db->setQuery($query); $cats[] = 'app' . $this->db->loadResult(); return $cats; case 'item': $id = $this->request->id; if ( ! $id && isset($menuparams->item_id)) { $id = $menuparams->item_id; } if ( ! $id) { return []; } $query = $this->db->getQuery(true) ->select('c.category_id') ->from('#__zoo_category_item AS c') ->where('c.item_id = ' . (int) $id) ->where('c.category_id != 0'); $this->db->setQuery($query); $cats = $this->db->loadColumn(); $query = $this->db->getQuery(true) ->select('i.application_id') ->from('#__zoo_item AS i') ->where('i.id = ' . (int) $id); $this->db->setQuery($query); $cats[] = 'app' . $this->db->loadResult(); return $cats; default: return false; } } public function passItems() { if ( ! $this->request->id || $this->request->option != 'com_zoo') { return $this->pass(false); } if ($this->request->view != 'item') { return $this->pass(false); } $pass = false; // Pass Article Id if ( ! $this->passItemByType($pass, 'ContentIds')) { return $this->pass(false); } // Pass Authors if ( ! $this->passItemByType($pass, 'Authors')) { return $this->pass(false); } return $this->pass($pass); } public function getItem($fields = []) { $query = $this->db->getQuery(true) ->select($fields) ->from('#__zoo_item') ->where('id = ' . (int) $this->request->id); $this->db->setQuery($query); return $this->db->loadObject(); } private function getCatParentIds($id = 0) { $parent_ids = []; if ( ! $id) { return $parent_ids; } while ($id) { if (substr($id, 0, 3) == 'app') { $parent_ids[] = $id; break; } $query = $this->db->getQuery(true) ->select('c.parent') ->from('#__zoo_category AS c') ->where('c.id = ' . (int) $id); $this->db->setQuery($query); $pid = $this->db->loadResult(); if ( ! $pid) { $query = $this->db->getQuery(true) ->select('c.application_id') ->from('#__zoo_category AS c') ->where('c.id = ' . (int) $id); $this->db->setQuery($query); $app = $this->db->loadResult(); if ($app) { $parent_ids[] = 'app' . $app; } break; } $parent_ids[] = $pid; $id = $pid; } return $parent_ids; } } assignments/datetime.php 0000604 00000014107 15245535622 0011414 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsDateTime extends RLAssignment { var $timezone = null; var $dates = []; public function passDate() { if ( ! $this->params->publish_up && ! $this->params->publish_down) { // no date range set return ($this->assignment == 'include'); } require_once dirname(__DIR__) . '/text.php'; RLText::fixDate($this->params->publish_up); RLText::fixDate($this->params->publish_down); $now = $this->getNow(); $up = $this->getDate($this->params->publish_up); $down = $this->getDate($this->params->publish_down); if (isset($this->params->recurring) && $this->params->recurring) { if ( ! (int) $this->params->publish_up || ! (int) $this->params->publish_down) { // no date range set return ($this->assignment == 'include'); } $up = strtotime(date('Y') . $up->format('-m-d H:i:s', true)); $down = strtotime(date('Y') . $down->format('-m-d H:i:s', true)); // pass: // 1) now is between up and down // 2) up is later in year than down and: // 2a) now is after up // 2b) now is before down if ( ($up < $now && $down > $now) || ($up > $down && ( $up < $now || $down > $now ) ) ) { return ($this->assignment == 'include'); } // outside date range return $this->pass(false); } if ( ( (int) $this->params->publish_up && strtotime($up->format('Y-m-d H:i:s', true)) > $now ) || ( (int) $this->params->publish_down && strtotime($down->format('Y-m-d H:i:s', true)) < $now ) ) { // outside date range return $this->pass(false); } // pass return ($this->assignment == 'include'); } public function passSeasons() { $season = self::getSeason($this->date, $this->params->hemisphere); return $this->passSimple($season); } public function passMonths() { $month = $this->date->format('m', true); // 01 (for January) through 12 (for December) return $this->passSimple((int) $month); } public function passDays() { $day = $this->date->format('N', true); // 1 (for Monday) though 7 (for Sunday ) return $this->passSimple($day); } public function passTime() { $now = $this->getNow(); $up = strtotime($this->date->format('Y-m-d ', true) . $this->params->publish_up); $down = strtotime($this->date->format('Y-m-d ', true) . $this->params->publish_down); if ($up > $down) { // publish up is after publish down (spans midnight) // current time should be: // - after publish up // - OR before publish down if ($now >= $up || $now < $down) { return $this->pass(true); } return $this->pass(false); } // publish down is after publish up (simple time span) // current time should be: // - after publish up // - AND before publish down if ($now >= $up && $now < $down) { return $this->pass(true); } return $this->pass(false); } private function getSeason(&$d, $hemisphere = 'northern') { // Set $date to today $date = strtotime($d->format('Y-m-d H:i:s', true)); // Get year of date specified $date_year = $d->format('Y', true); // Four digit representation for the year // Specify the season names $season_names = ['winter', 'spring', 'summer', 'fall']; // Declare season date ranges switch (strtolower($hemisphere)) { case 'southern': if ( $date < strtotime($date_year . '-03-21') || $date >= strtotime($date_year . '-12-21') ) { return $season_names[2]; // Must be in Summer } if ($date >= strtotime($date_year . '-09-23')) { return $season_names[1]; // Must be in Spring } if ($date >= strtotime($date_year . '-06-21')) { return $season_names[0]; // Must be in Winter } if ($date >= strtotime($date_year . '-03-21')) { return $season_names[3]; // Must be in Fall } break; case 'australia': if ( $date < strtotime($date_year . '-03-01') || $date >= strtotime($date_year . '-12-01') ) { return $season_names[2]; // Must be in Summer } if ($date >= strtotime($date_year . '-09-01')) { return $season_names[1]; // Must be in Spring } if ($date >= strtotime($date_year . '-06-01')) { return $season_names[0]; // Must be in Winter } if ($date >= strtotime($date_year . '-03-01')) { return $season_names[3]; // Must be in Fall } break; default: // northern if ( $date < strtotime($date_year . '-03-21') || $date >= strtotime($date_year . '-12-21') ) { return $season_names[0]; // Must be in Winter } if ($date >= strtotime($date_year . '-09-23')) { return $season_names[3]; // Must be in Fall } if ($date >= strtotime($date_year . '-06-21')) { return $season_names[2]; // Must be in Summer } if ($date >= strtotime($date_year . '-03-21')) { return $season_names[1]; // Must be in Spring } break; } return 0; } private function getNow() { return strtotime($this->date->format('Y-m-d H:i:s', true)); } private function getDate($date = '') { $id = 'date_' . $date; if (isset($this->dates[$id])) { return $this->dates[$id]; } $this->dates[$id] = JFactory::getDate($date); if (empty($this->params->ignore_time_zone)) { $this->dates[$id]->setTimeZone($this->getTimeZone()); } return $this->dates[$id]; } private function getTimeZone() { if ( ! is_null($this->timezone)) { return $this->timezone; } $this->timezone = new DateTimeZone(JFactory::getApplication()->getCfg('offset')); return $this->timezone; } } assignments/urls.php 0000604 00000003401 15245535622 0010600 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Uri\Uri as JUri; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; require_once dirname(__DIR__) . '/text.php'; class RLAssignmentsURLs extends RLAssignment { public function passURLs() { $regex = isset($this->params->regex) ? $this->params->regex : 0; if ( ! is_array($this->selection)) { $this->selection = explode("\n", $this->selection); } if (count($this->selection) == 1) { $this->selection = explode("\n", $this->selection[0]); } $url = JUri::getInstance(); $url = $url->toString(); $urls = [ RLText::html_entity_decoder(urldecode($url)), urldecode($url), RLText::html_entity_decoder($url), $url, ]; $urls = array_unique($urls); $pass = false; foreach ($urls as $url) { foreach ($this->selection as $s) { $s = trim($s); if ($s == '') { continue; } if ($regex) { $url_part = str_replace(['#', '&'], ['\#', '(&|&)'], $s); $s = '#' . $url_part . '#si'; if (@preg_match($s . 'u', $url) || @preg_match($s, $url)) { $pass = true; break; } continue; } if (strpos($url, $s) !== false) { $pass = true; break; } } if ($pass) { break; } } return $this->pass($pass); } } assignments/flexicontent.php 0000604 00000004622 15245535622 0012323 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsFlexiContent extends RLAssignment { public function passPageTypes() { return $this->passByPageTypes('com_flexicontent', $this->selection, $this->assignment); } public function passTags() { if ($this->request->option != 'com_flexicontent') { return $this->pass(false); } $pass = ( ($this->params->inc_tags && $this->request->view == 'tags') || ($this->params->inc_items && in_array($this->request->view, ['item', 'items'])) ); if ( ! $pass) { return $this->pass(false); } if ($this->params->inc_tags && $this->request->view == 'tags') { $query = $this->db->getQuery(true) ->select('t.name') ->from('#__flexicontent_tags AS t') ->where('t.id = ' . (int) trim(JFactory::getApplication()->input->getInt('id', 0))) ->where('t.published = 1'); $this->db->setQuery($query); $tag = $this->db->loadResult(); $tags = [$tag]; } else { $query = $this->db->getQuery(true) ->select('t.name') ->from('#__flexicontent_tags_item_relations AS x') ->join('LEFT', '#__flexicontent_tags AS t ON t.id = x.tid') ->where('x.itemid = ' . (int) $this->request->id) ->where('t.published = 1'); $this->db->setQuery($query); $tags = $this->db->loadColumn(); } return $this->passSimple($tags, true); } public function passTypes() { if ($this->request->option != 'com_flexicontent') { return $this->pass(false); } $pass = in_array($this->request->view, ['item', 'items']); if ( ! $pass) { return $this->pass(false); } $query = $this->db->getQuery(true) ->select('x.type_id') ->from('#__flexicontent_items_ext AS x') ->where('x.item_id = ' . (int) $this->request->id); $this->db->setQuery($query); $type = $this->db->loadResult(); $types = $this->makeArray($type); return $this->passSimple($types); } } assignments/redshop.php 0000604 00000005046 15245535622 0011266 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsRedShop extends RLAssignment { public function init() { $this->request->item_id = JFactory::getApplication()->input->getInt('pid', 0); $this->request->category_id = JFactory::getApplication()->input->getInt('cid', 0); $this->request->id = ($this->request->item_id) ? $this->request->item_id : $this->request->category_id; } public function passPageTypes() { return $this->passByPageTypes('com_redshop', $this->selection, $this->assignment, true); } public function passCategories() { if ($this->request->option != 'com_redshop') { return $this->pass(false); } $pass = ( ($this->params->inc_categories && ($this->request->view == 'category') ) || ($this->params->inc_items && $this->request->view == 'product') ); if ( ! $pass) { return $this->pass(false); } $cats = []; if ($this->request->category_id) { $cats = $this->request->category_id; } else if ($this->request->item_id) { $query = $this->db->getQuery(true) ->select('x.category_id') ->from('#__redshop_product_category_xref AS x') ->where('x.product_id = ' . (int) $this->request->item_id); $this->db->setQuery($query); $cats = $this->db->loadColumn(); } $cats = $this->makeArray($cats); $pass = $this->passSimple($cats, 'include'); if ($pass && $this->params->inc_children == 2) { return $this->pass(false); } else if ( ! $pass && $this->params->inc_children) { foreach ($cats as $cat) { $cats = array_merge($cats, $this->getCatParentIds($cat)); } } return $this->passSimple($cats); } public function passProducts() { if ( ! $this->request->id || $this->request->option != 'com_redshop' || $this->request->view != 'product') { return $this->pass(false); } return $this->passSimple($this->request->id); } private function getCatParentIds($id = 0) { return $this->getParentIds($id, 'redshop_category_xref', 'category_parent_id', 'category_child_id'); } } assignments/agents.php 0000604 00000007077 15245535622 0011111 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; require_once dirname(__DIR__) . '/text.php'; require_once dirname(__DIR__) . '/mobile_detect.php'; class RLAssignmentsAgents extends RLAssignment { var $agent = null; var $device = null; /** * passBrowsers */ public function passBrowsers() { if (empty($this->selection)) { return $this->pass(false); } foreach ($this->selection as $browser) { if ( ! $this->passBrowser($browser)) { continue; } return $this->pass(true); } return $this->pass(false); } /** * passOS */ public function passOS() { return self::passBrowsers(); } /** * passDevices */ public function passDevices() { $pass = (in_array('mobile', $this->selection) && $this->isMobile()) || (in_array('tablet', $this->selection) && $this->isTablet()) || (in_array('desktop', $this->selection) && $this->isDesktop()); return $this->pass($pass); } /** * isPhone */ public function isPhone() { return $this->isMobile(); } /** * isMobile */ public function isMobile() { return $this->getDevice() == 'mobile'; } /** * isTablet */ public function isTablet() { return $this->getDevice() == 'tablet'; } /** * isDesktop */ public function isDesktop() { return $this->getDevice() == 'desktop'; } /** * setDevice */ private function getDevice() { if ( ! is_null($this->device)) { return $this->device; } $detect = new RLMobile_Detect; $this->is_mobile = $detect->isMobile(); switch (true) { case($detect->isTablet()): $this->device = 'tablet'; break; case ($detect->isMobile()): $this->device = 'mobile'; break; default: $this->device = 'desktop'; } return $this->device; } /** * getAgent */ private function getAgent() { if ( ! is_null($this->agent)) { return $this->agent; } $detect = new RLMobile_Detect; $agent = $detect->getUserAgent(); switch (true) { case (stripos($agent, 'Trident') !== false): // Add MSIE to IE11 $agent = preg_replace('#(Trident/[0-9\.]+; rv:([0-9\.]+))#is', '\1 MSIE \2', $agent); break; case (stripos($agent, 'Chrome') !== false): // Remove Safari from Chrome $agent = preg_replace('#(Chrome/.*)Safari/[0-9\.]*#is', '\1', $agent); // Add MSIE to IE Edge and remove Chrome from IE Edge $agent = preg_replace('#Chrome/.*(Edge/[0-9])#is', 'MSIE \1', $agent); break; case (stripos($agent, 'Opera') !== false): $agent = preg_replace('#(Opera/.*)Version/#is', '\1Opera/', $agent); break; } $this->agent = $agent; return $this->agent; } /** * passBrowser */ private function passBrowser($browser = '') { if ( ! $browser) { return false; } if ($browser == 'mobile') { return $this->isMobile(); } if ( ! (strpos($browser, '#') === 0)) { $browser = '#' . RLText::pregQuote($browser) . '#'; } // also check for _ instead of . $browser = preg_replace('#\\\.([^\]])#', '[\._]\1', $browser); $browser = str_replace('\.]', '\._]', $browser); return preg_match($browser . 'i', $this->getAgent()); } } assignments/form2content.php 0000604 00000002062 15245535622 0012235 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsForm2Content extends RLAssignment { public function passProjects() { if ($this->request->option != 'com_content' && $this->request->view == 'article') { return $this->pass(false); } $query = $this->db->getQuery(true) ->select('c.projectid') ->from('#__f2c_form AS c') ->where('c.reference_id = ' . (int) $this->request->id); $this->db->setQuery($query); $type = $this->db->loadResult(); $types = $this->makeArray($type); return $this->passSimple($types); } } assignments/homepage.php 0000604 00000011606 15245535622 0011406 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; use Joomla\CMS\Language\LanguageHelper as JLanguageHelper; use Joomla\CMS\Uri\Uri as JUri; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/text.php'; require_once dirname(__DIR__) . '/string.php'; require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsHomePage extends RLAssignment { public function passHomePage() { $home = JFactory::getApplication()->getMenu('site')->getDefault(JFactory::getLanguage()->getTag()); // return if option or other set values do not match the homepage menu item values if ($this->request->option) { // check if option is different to home menu if ( ! $home || ! isset($home->query['option']) || $home->query['option'] != $this->request->option) { return $this->pass(false); } if ( ! $this->request->option) { // set the view/task/layout in the menu item to empty if not set $home->query['view'] = isset($home->query['view']) ? $home->query['view'] : ''; $home->query['task'] = isset($home->query['task']) ? $home->query['task'] : ''; $home->query['layout'] = isset($home->query['layout']) ? $home->query['layout'] : ''; } // check set values against home menu query items foreach ($home->query as $k => $v) { if ((isset($this->request->{$k}) && $this->request->{$k} != $v) || ( ( ! isset($this->request->{$k}) || in_array($v, ['virtuemart', 'mijoshop'])) && JFactory::getApplication()->input->get($k) != $v ) ) { return $this->pass(false); } } // check post values against home menu params foreach ($home->params->toObject() as $k => $v) { if (($v && isset($_POST[$k]) && $_POST[$k] != $v) || ( ! $v && isset($_POST[$k]) && $_POST[$k]) ) { return $this->pass(false); } } } $pass = $this->checkPass($home); if ( ! $pass) { $pass = $this->checkPass($home, 1); } return $this->pass($pass); } private function checkPass(&$home, $addlang = 0) { $uri = JUri::getInstance(); if ($addlang) { $sef = $uri->getVar('lang'); if (empty($sef)) { $langs = array_keys(JLanguageHelper::getLanguages('sef')); $path = RLString::substr( $uri->toString(['scheme', 'user', 'pass', 'host', 'port', 'path']), RLString::strlen($uri->base()) ); $path = preg_replace('#^index\.php/?#', '', $path); $parts = explode('/', $path); $part = reset($parts); if (in_array($part, $langs)) { $sef = $part; } } if (empty($sef)) { return false; } } $query = $uri->toString(['query']); if (strpos($query, 'option=') === false && strpos($query, 'Itemid=') === false) { $url = $uri->toString(['host', 'path']); } else { $url = $uri->toString(['host', 'path', 'query']); } // remove the www. $url = preg_replace('#^www\.#', '', $url); // replace ampersand chars $url = str_replace('&', '&', $url); // remove any language vars $url = preg_replace('#((\?)lang=[a-z-_]*(&|$)|&lang=[a-z-_]*)#', '\2', $url); // remove trailing nonsense $url = trim(preg_replace('#/?\??&?$#', '', $url)); // remove the index.php/ $url = preg_replace('#/index\.php(/|$)#', '/', $url); // remove trailing / $url = trim(preg_replace('#/$#', '', $url)); $root = JUri::root(); // remove the http(s) $root = preg_replace('#^.*?://#', '', $root); // remove the www. $root = preg_replace('#^www\.#', '', $root); //remove the port $root = preg_replace('#:[0-9]+#', '', $root); // so also passes on urls with trailing /, ?, &, /?, etc... $root = preg_replace('#(Itemid=[0-9]*).*^#', '\1', $root); // remove trailing / $root = trim(preg_replace('#/$#', '', $root)); if ($addlang) { $root .= '/' . $sef; } /* Pass urls: * [root] */ $regex = '#^' . $root . '$#i'; if (preg_match($regex, $url)) { return true; } /* Pass urls: * [root]?Itemid=[menu-id] * [root]/?Itemid=[menu-id] * [root]/index.php?Itemid=[menu-id] * [root]/[menu-alias] * [root]/[menu-alias]?Itemid=[menu-id] * [root]/index.php?[menu-alias] * [root]/index.php?[menu-alias]?Itemid=[menu-id] * [root]/[menu-link] * [root]/[menu-link]&Itemid=[menu-id] */ $regex = '#^' . $root . '(/(' . 'index\.php' . '|' . '(index\.php\?)?' . RLText::pregQuote($home->alias) . '|' . RLText::pregQuote($home->link) . ')?)?' . '(/?[\?&]Itemid=' . (int) $home->id . ')?' . '$#i'; return preg_match($regex, $url); } } assignments/languages.php 0000604 00000001371 15245535622 0011565 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsLanguages extends RLAssignment { public function passLanguages() { return $this->passSimple(JFactory::getLanguage()->getTag(), true); } } assignments/virtuemart.php 0000604 00000010021 15245535622 0012011 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsVirtueMart extends RLAssignment { public function init() { $virtuemart_product_id = JFactory::getApplication()->input->get('virtuemart_product_id', [], 'array'); $virtuemart_category_id = JFactory::getApplication()->input->get('virtuemart_category_id', [], 'array'); $this->request->item_id = isset($virtuemart_product_id[0]) ? $virtuemart_product_id[0] : null; $this->request->category_id = isset($virtuemart_category_id[0]) ? $virtuemart_category_id[0] : null; $this->request->id = ($this->request->item_id) ? $this->request->item_id : $this->request->category_id; } public function passPageTypes() { // Because VM sucks, we have to get the view again $this->request->view = JFactory::getApplication()->input->getString('view'); return $this->passByPageTypes('com_virtuemart', $this->selection, $this->assignment, true); } public function passCategories() { if ($this->request->option != 'com_virtuemart') { return $this->pass(false); } // Because VM sucks, we have to get the view again $this->request->view = JFactory::getApplication()->input->getString('view'); $pass = (($this->params->inc_categories && in_array($this->request->view, ['categories', 'category'])) || ($this->params->inc_items && $this->request->view == 'productdetails') ); if ( ! $pass) { return $this->pass(false); } $cats = []; if ($this->request->view == 'productdetails' && $this->request->item_id) { $query = $this->db->getQuery(true) ->select('x.virtuemart_category_id') ->from('#__virtuemart_product_categories AS x') ->where('x.virtuemart_product_id = ' . (int) $this->request->item_id); $this->db->setQuery($query); $cats = $this->db->loadColumn(); } else if ($this->request->category_id) { $cats = $this->request->category_id; if ( ! is_numeric($cats)) { $query = $this->db->getQuery(true) ->select('config') ->from('#__virtuemart_configs') ->where('virtuemart_config_id = 1'); $this->db->setQuery($query); $config = $this->db->loadResult(); $lang = substr($config, strpos($config, 'vmlang=')); $lang = substr($lang, 0, strpos($lang, '|')); if (preg_match('#"([^"]*_[^"]*)"#', $lang, $lang)) { $lang = $lang[1]; } else { $lang = 'en_gb'; } $query = $this->db->getQuery(true) ->select('l.virtuemart_category_id') ->from('#__virtuemart_categories_' . $lang . ' AS l') ->where('l.slug = ' . $this->db->quote($cats)); $this->db->setQuery($query); $cats = $this->db->loadResult(); } } $cats = $this->makeArray($cats); $pass = $this->passSimple($cats, 'include'); if ($pass && $this->params->inc_children == 2) { return $this->pass(false); } if ( ! $pass && $this->params->inc_children) { foreach ($cats as $cat) { $cats = array_merge($cats, $this->getCatParentIds($cat)); } } return $this->passSimple($cats); } public function passProducts() { // Because VM sucks, we have to get the view again $this->request->view = JFactory::getApplication()->input->getString('view'); if ( ! $this->request->id || $this->request->option != 'com_virtuemart' || $this->request->view != 'productdetails') { return $this->pass(false); } return $this->passSimple($this->request->id); } private function getCatParentIds($id = 0) { return $this->getParentIds($id, 'virtuemart_category_categories', 'category_parent_id', 'category_child_id'); } } assignments/hikashop.php 0000604 00000005775 15245535622 0011441 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsHikaShop extends RLAssignment { public function passPageTypes() { if ($this->request->option != 'com_hikashop') { return $this->pass(false); } $type = $this->request->view; if ( ($type == 'product' && in_array($this->request->layout, ['contact', 'show'])) || ($type == 'user' && in_array($this->request->layout, ['cpanel'])) ) { $type .= '_' . $this->request->layout; } return $this->passSimple($type); } public function passCategories() { if ($this->request->option != 'com_hikashop') { return $this->pass(false); } $pass = ( ($this->params->inc_categories && ($this->request->view == 'category' || $this->request->layout == 'listing') ) || ($this->params->inc_items && $this->request->view == 'product') ); if ( ! $pass) { return $this->pass(false); } $cats = $this->getCategories(); $pass = $this->passSimple($cats, 'include'); if ($pass && $this->params->inc_children == 2) { return $this->pass(false); } else if ( ! $pass && $this->params->inc_children) { foreach ($cats as $cat) { $cats = array_merge($cats, $this->getCatParentIds($cat)); } } return $this->passSimple($cats); } public function passProducts() { if ( ! $this->request->id || $this->request->option != 'com_hikashop' || $this->request->view != 'product') { return $this->pass(false); } return $this->passSimple($this->request->id); } private function getCategories() { switch (true) { case (($this->request->view == 'category' || $this->request->layout == 'listing') && $this->request->id): return [$this->request->id]; case ($this->request->view == 'category' || $this->request->layout == 'listing'): include_once JPATH_ADMINISTRATOR . '/components/com_hikashop/helpers/helper.php'; $menuClass = hikashop_get('class.menus'); $menuData = $menuClass->get($this->request->Itemid); return $this->makeArray($menuData->hikashop_params['selectparentlisting']); case ($this->request->id): $query = $this->db->getQuery(true) ->select('c.category_id') ->from('#__hikashop_product_category AS c') ->where('c.product_id = ' . (int) $this->request->id); $this->db->setQuery($query); $cats = $this->db->loadColumn(); return $this->makeArray($cats); default: return []; } } private function getCatParentIds($id = 0) { return $this->getParentIds($id, 'hikashop_category', 'category_parent_id', 'category_id'); } } assignments/php.php 0000604 00000005445 15245535622 0010414 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; use Joomla\CMS\MVC\Model\BaseDatabaseModel as JModel; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsPHP extends RLAssignment { public function passPHP() { $article = $this->article; if ( ! is_array($this->selection)) { $this->selection = [$this->selection]; } $pass = false; foreach ($this->selection as $php) { // replace \n with newline and other fix stuff $php = str_replace('\|', '|', $php); $php = preg_replace('#(?<!\\\)\\\n#', "\n", $php); $php = trim(str_replace('[:REGEX_ENTER:]', '\n', $php)); if ($php == '') { $pass = true; break; } if ( ! $article && strpos($php, '$article') !== false) { $article = null; if ($this->request->option == 'com_content' && $this->request->view == 'article') { $article = $this->getArticleById($this->request->id); } } if ( ! isset($Itemid)) { $Itemid = JFactory::getApplication()->input->getInt('Itemid', 0); } if ( ! isset($mainframe)) { $mainframe = JFactory::getApplication(); } if ( ! isset($app)) { $app = JFactory::getApplication(); } if ( ! isset($document)) { $document = JFactory::getDocument(); } if ( ! isset($doc)) { $doc = JFactory::getDocument(); } if ( ! isset($database)) { $database = JFactory::getDbo(); } if ( ! isset($db)) { $db = JFactory::getDbo(); } if ( ! isset($user)) { $user = JFactory::getUser(); } $php .= ';return true;'; $temp_PHP_func = create_function('&$article, &$Itemid, &$mainframe, &$app, &$document, &$doc, &$database, &$db, &$user', $php); // evaluate the script ob_start(); $pass = (bool) $temp_PHP_func($article, $Itemid, $mainframe, $app, $document, $doc, $database, $db, $user); unset($temp_PHP_func); ob_end_clean(); if ($pass) { break; } } return $this->pass($pass); } private function getArticleById($id = 0) { if ( ! $id) { return null; } if ( ! class_exists('ContentModelArticle')) { require_once JPATH_SITE . '/components/com_content/models/article.php'; } $model = JModel::getInstance('article', 'contentModel'); if ( ! method_exists($model, 'getItem')) { return null; } return $model->getItem($this->request->id); } } assignments/templates.php 0000604 00000003773 15245535622 0011625 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use Joomla\CMS\Factory as JFactory; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } require_once dirname(__DIR__) . '/assignment.php'; class RLAssignmentsTemplates extends RLAssignment { public function passTemplates() { $template = $this->getTemplate(); // Put template name and name + style id into array // The '::' separator was used in pre Joomla 3.3 $template = [$template->template, $template->template . '--' . $template->id, $template->template . '::' . $template->id]; return $this->passSimple($template, true); } public function getTemplate() { $template = JFactory::getApplication()->getTemplate(true); if (isset($template->id)) { return $template; } $params = json_encode($template->params); // Find template style id based on params, as the template style id is not always stored in the getTemplate $query = $this->db->getQuery(true) ->select('id') ->from('#__template_styles as s') ->where('s.client_id = 0') ->where('s.template = ' . $this->db->quote($template->template)) ->where('s.params = ' . $this->db->quote($params)) ->setLimit(1); $this->db->setQuery($query); $template->id = $this->db->loadResult('id'); if ($template->id) { return $template; } // No template style id is found, so just grab the first result based on the template name $query->clear('where') ->where('s.client_id = 0') ->where('s.template = ' . $this->db->quote($template->template)) ->setLimit(1); $this->db->setQuery($query); $template->id = $this->db->loadResult('id'); return $template; } } html.php 0000604 00000001656 15245535622 0006236 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\Form as RL_Form; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLHtml { static function selectlist(&$options, $name, $value, $id, $size = 0, $multiple = 0, $simple = 0) { return RL_Form::selectList($options, $name, $value, $id, $size, $multiple, $simple); } static function selectlistsimple(&$options, $name, $value, $id, $size = 0, $multiple = 0) { return RL_Form::selectListSimple($options, $name, $value, $id, $size, $multiple); } } parameters.php 0000604 00000001236 15245535622 0007427 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\Parameters as RL_Parameters; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLParameters { public static function getInstance() { return RL_Parameters::getInstance(); } } mobile_detect.php 0000604 00000001232 15245535622 0010057 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLMobile_Detect extends \RegularLabs\Library\MobileDetect { public function isMac() { return $this->match('(Mac OS|Mac_PowerPC|Macintosh)'); } } tags.php 0000604 00000012022 15245535622 0006215 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\Html as RL_Html; use RegularLabs\Library\PluginTag as RL_PluginTag; use RegularLabs\Library\RegEx as RL_RegEx; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLTags { static $protected_characters = [ '=' => '[[:EQUAL:]]', '"' => '[[:QUOTE:]]', ',' => '[[:COMMA:]]', '|' => '[[:BAR:]]', ':' => '[[:COLON:]]', ]; public static function getValuesFromString($string = '', $main_key = 'title', $known_boolean_keys = [], $keep_escaped = [',']) { return RL_PluginTag::getAttributesFromString($string, $main_key, $known_boolean_keys, $keep_escaped); } public static function protectSpecialChars(&$string) { RL_PluginTag::protectSpecialChars($string); } public static function unprotectSpecialChars(&$string, $keep_escaped_chars = []) { RL_PluginTag::unprotectSpecialChars($string, $keep_escaped_chars); } public static function replaceKeyAliases(&$values, $key_aliases = [], $handle_plurals = false) { RL_PluginTag::replaceKeyAliases($values, $key_aliases, $handle_plurals); } public static function convertOldSyntax(&$values, $known_boolean_keys = [], $extra_key = 'class') { RL_PluginTag::convertOldSyntax($values, $known_boolean_keys, $extra_key); } public static function getRegexSpaces($modifier = '+') { return RL_PluginTag::getRegexSpaces($modifier); } public static function getRegexInsideTag() { return RL_PluginTag::getRegexInsideTag(); } public static function getRegexSurroundingTagPre($elements = ['p', 'span']) { return RL_PluginTag::getRegexSurroundingTagPre($elements); } public static function getRegexSurroundingTagPost($elements = ['p', 'span']) { return RL_PluginTag::getRegexSurroundingTagPost($elements); } public static function getRegexTags($tags, $include_no_attributes = true, $include_ending = true, $required_attributes = []) { return RL_PluginTag::getRegexTags($tags, $include_no_attributes, $include_ending, $required_attributes); } public static function fixBrokenHtmlTags($string) { return RL_Html::fix($string); } public static function cleanSurroundingTags($tags, $elements = ['p', 'span']) { return RL_Html::cleanSurroundingTags($tags, $elements); } public static function fixSurroundingTags($tags) { return RL_Html::fixArray($tags); } public static function removeEmptyHtmlTagPairs($string, $elements = ['p', 'span']) { return RL_Html::removeEmptyTagPairs($string, $elements); } public static function getDivTags($start_tag = '', $end_tag = '', $tag_start = '{', $tag_end = '}') { $tag_start = RL_RegEx::unquote($tag_start); $tag_end = RL_RegEx::unquote($tag_end); return RL_PluginTag::getDivTags($start_tag, $end_tag, $tag_start, $tag_end); } public static function getTagValues($string = '', $keys = ['title'], $separator = '|', $equal = '=', $limit = 0) { return RL_PluginTag::getAttributesFromStringOld($string, $keys, $separator, $equal, $limit); } /* @Deprecated */ public static function setSurroundingTags($pre, $post, $tags = 0) { if ($tags == 0) { // tags that have a matching ending tag $tags = [ 'div', 'p', 'span', 'pre', 'a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'strong', 'b', 'em', 'i', 'u', 'big', 'small', 'font', // html 5 stuff 'header', 'nav', 'section', 'article', 'aside', 'footer', 'figure', 'figcaption', 'details', 'summary', 'mark', 'time', ]; } $a = explode('<', $pre); $b = explode('</', $post); if (count($b) < 2 || count($a) < 2) { return [trim($pre), trim($post)]; } $a = array_reverse($a); $a_pre = array_pop($a); $b_pre = array_shift($b); $a_tags = $a; foreach ($a_tags as $i => $a_tag) { $a[$i] = '<' . trim($a_tag); $a_tags[$i] = RL_RegEx::replace('^([a-z0-9]+).*$', '\1', trim($a_tag)); } $b_tags = $b; foreach ($b_tags as $i => $b_tag) { $b[$i] = '</' . trim($b_tag); $b_tags[$i] = RL_RegEx::replace('^([a-z0-9]+).*$', '\1', trim($b_tag)); } foreach ($b_tags as $i => $b_tag) { if (empty($b_tag) || ! in_array($b_tag, $tags)) { continue; } foreach ($a_tags as $j => $a_tag) { if ($b_tag != $a_tag) { continue; } $a_tags[$i] = ''; $b[$i] = trim(RL_RegEx::replace('^</' . $b_tag . '.*?>', '', $b[$i])); $a[$j] = trim(RL_RegEx::replace('^<' . $a_tag . '.*?>', '', $a[$j])); break; } } foreach ($a_tags as $i => $tag) { if (empty($tag) || ! in_array($tag, $tags)) { continue; } array_unshift($b, trim($a[$i])); $a[$i] = ''; } $a = array_reverse($a); list($pre, $post) = [implode('', $a), implode('', $b)]; return [trim($pre), trim($post)]; } } htmlfix.php 0000604 00000001205 15245535622 0006733 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\Html as RL_Html; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLHtmlFix { public static function _($string) { return RL_Html::fix($string); } } assignment.php 0000604 00000002561 15245535622 0007436 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLAssignment extends \RegularLabs\Library\Condition { function pass($pass = true, $include_type = null) { return $this->_($pass, $include_type); } public function passByPageTypes($option, $selection = [], $assignment = 'all', $add_view = false, $get_task = false, $get_layout = true) { return $this->passByPageType($option, $selection, $assignment, $add_view, $get_task, $get_layout); } public function passContentIds() { return $this->passContentId(); } public function passContentKeywords($fields = ['title', 'introtext', 'fulltext'], $text = '') { return $this->passContentKeyword($fields, $text); } public function passMetaKeywords($field = 'metakey', $keywords = '') { return $this->passMetaKeyword($field, $keywords); } public function passAuthors($field = 'created_by', $author = '') { return $this->passAuthors($field, $author); } } search.php 0000604 00000021534 15245535622 0006534 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_search * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\String\StringHelper; /** * Search component helper. * * @since 1.5 */ class SearchHelper { /** * Configure the Linkbar. * * @param string $vName The name of the active view. * * @return void * * @since 1.6 */ public static function addSubmenu($vName) { // Not required. } /** * Gets a list of the actions that can be performed. * * @return JObject * * @deprecated 3.2 Use JHelperContent::getActions() instead. */ public static function getActions() { // Log usage of deprecated function. try { JLog::add( sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } // Get list of actions. return JHelperContent::getActions('com_search'); } /** * Sanitise search word. * * @param string &$searchword Search word to be sanitised. * @param string $searchphrase Either 'all', 'any' or 'exact'. * * @return boolean True if search word needs to be sanitised. */ public static function santiseSearchWord(&$searchword, $searchphrase) { $ignored = false; $lang = JFactory::getLanguage(); $tag = $lang->getTag(); $search_ignore = $lang->getIgnoredSearchWords(); // Deprecated in 1.6 use $lang->getIgnoredSearchWords instead. $ignoreFile = JLanguageHelper::getLanguagePath() . '/' . $tag . '/' . $tag . '.ignore.php'; if (file_exists($ignoreFile)) { include $ignoreFile; } // Check for words to ignore. $aterms = explode(' ', StringHelper::strtolower($searchword)); // First case is single ignored word. if (count($aterms) == 1 && in_array(StringHelper::strtolower($searchword), $search_ignore)) { $ignored = true; } // Filter out search terms that are too small. $lower_limit = $lang->getLowerLimitSearchWord(); foreach ($aterms as $aterm) { if (StringHelper::strlen($aterm) < $lower_limit) { $search_ignore[] = $aterm; } } // Next is to remove ignored words from type 'all' or 'any' (not exact) searches with multiple words. if (count($aterms) > 1 && $searchphrase != 'exact') { $pruned = array_diff($aterms, $search_ignore); $searchword = implode(' ', $pruned); } return $ignored; } /** * Does search word need to be limited? * * @param string &$searchword Search word to be checked. * * @return boolean True if search word should be limited; false otherwise. * * @since 1.5 */ public static function limitSearchWord(&$searchword) { $restriction = false; $lang = JFactory::getLanguage(); // Limit searchword to a maximum of characters. $upper_limit = $lang->getUpperLimitSearchWord(); if (StringHelper::strlen($searchword) > $upper_limit) { $searchword = StringHelper::substr($searchword, 0, $upper_limit - 1); $restriction = true; } // Searchword must contain a minimum of characters. if ($searchword && StringHelper::strlen($searchword) < $lang->getLowerLimitSearchWord()) { $searchword = ''; $restriction = true; } return $restriction; } /** * Logs a search term. * * @param string $searchTerm The term being searched. * * @return void * * @since 1.5 * @deprecated 4.0 Use \Joomla\CMS\Helper\SearchHelper::logSearch() instead. */ public static function logSearch($searchTerm) { try { JLog::add( sprintf('%s() is deprecated. Use \Joomla\CMS\Helper\SearchHelper::logSearch() instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } \Joomla\CMS\Helper\SearchHelper::logSearch($searchTerm, 'com_search'); } /** * Prepares results from search for display. * * @param string $text The source string. * @param string $searchword The searchword to select around. * * @return string * * @since 1.5 */ public static function prepareSearchContent($text, $searchword) { // Strips tags won't remove the actual jscript. $text = preg_replace("'<script[^>]*>.*?</script>'si", '', $text); $text = preg_replace('/{.+?}/', '', $text); // $text = preg_replace('/<a\s+.*?href="([^"]+)"[^>]*>([^<]+)<\/a>/is','\2', $text); // Replace line breaking tags with whitespace. $text = preg_replace("'<(br[^/>]*?/|hr[^/>]*?/|/(div|h[1-6]|li|p|td))>'si", ' ', $text); return self::_smartSubstr(strip_tags($text), $searchword); } /** * Checks an object for search terms (after stripping fields of HTML). * * @param object $object The object to check. * @param string $searchTerm Search words to check for. * @param array $fields List of object variables to check against. * * @return boolean True if searchTerm is in object, false otherwise. */ public static function checkNoHtml($object, $searchTerm, $fields) { $searchRegex = array( '#<script[^>]*>.*?</script>#si', '#<style[^>]*>.*?</style>#si', '#<!.*?(--|]])>#si', '#<[^>]*>#i' ); $terms = explode(' ', $searchTerm); if (empty($fields)) { return false; } foreach ($fields as $field) { if (!isset($object->$field)) { continue; } $text = self::remove_accents($object->$field); foreach ($searchRegex as $regex) { $text = preg_replace($regex, '', $text); } foreach ($terms as $term) { $term = self::remove_accents($term); if (StringHelper::stristr($text, $term) !== false) { return true; } } } return false; } /** * Transliterates given text to ASCII. * * @param string $str String to remove accents from. * * @return string * * @since 3.2 */ public static function remove_accents($str) { $str = JLanguageTransliterate::utf8_latin_to_ascii($str); // @TODO: remove other prefixes as well? return preg_replace("/[\"'^]([a-z])/ui", '\1', $str); } /** * Returns substring of characters around a searchword. * * @param string $text The source string. * @param integer $searchword Number of chars to return. * * @return string * * @since 1.5 */ public static function _smartSubstr($text, $searchword) { $lang = JFactory::getLanguage(); $length = $lang->getSearchDisplayedCharactersNumber(); $ltext = self::remove_accents($text); $textlen = StringHelper::strlen($ltext); $lsearchword = StringHelper::strtolower(self::remove_accents($searchword)); $wordfound = false; $pos = 0; $length = $length > $textlen ? $textlen : $length; while ($wordfound === false && $pos + $length < $textlen) { if (($wordpos = @StringHelper::strpos($ltext, ' ', $pos + $length)) !== false) { $chunk_size = $wordpos - $pos; } else { $chunk_size = $length; } $chunk = StringHelper::substr($ltext, $pos, $chunk_size); $wordfound = StringHelper::strpos(StringHelper::strtolower($chunk), $lsearchword); if ($wordfound === false) { $pos += $chunk_size + 1; } } if ($wordfound !== false) { // Check if original text is different length than searched text (changed by function self::remove_accents) // Displayed text only, adjust $chunk_size if ($pos === 0) { $iOriLen = StringHelper::strlen(StringHelper::substr($text, 0, $pos + $chunk_size)); $iModLen = StringHelper::strlen(self::remove_accents(StringHelper::substr($text, 0, $pos + $chunk_size))); $chunk_size += $iOriLen - $iModLen; } else { $iOriSkippedLen = StringHelper::strlen(StringHelper::substr($text, 0, $pos)); $iModSkippedLen = StringHelper::strlen(self::remove_accents(StringHelper::substr($text, 0, $pos))); // Adjust starting position $pos if ($iOriSkippedLen !== $iModSkippedLen) { $pos += $iOriSkippedLen - $iModSkippedLen; } $iOriReturnLen = StringHelper::strlen(StringHelper::substr($text, $pos, $chunk_size)); $iModReturnLen = StringHelper::strlen(self::remove_accents(StringHelper::substr($text, $pos, $chunk_size))); if ($iOriReturnLen !== $iModReturnLen) { $chunk_size += $iOriReturnLen - $iModReturnLen; } } $sPre = $pos > 0 ? '... ' : ''; $sPost = ($pos + $chunk_size) >= StringHelper::strlen($text) ? '' : ' ...'; return $sPre . StringHelper::substr($text, $pos, $chunk_size) . $sPost; } else { if (($mbtextlen = StringHelper::strlen($text)) < $length) { $length = $mbtextlen; } if (($wordpos = StringHelper::strpos($text, ' ', $length)) !== false) { return StringHelper::substr($text, 0, $wordpos) . ' ...'; } else { return StringHelper::substr($text, 0, $length); } } } } licenses.php 0000604 00000001354 15245535622 0007072 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\License as RL_License; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLLicenses { public static function render($name, $check_pro = false) { return ! class_exists('RegularLabs\Library\License') ? '' : RL_License::getMessage($name, $check_pro); } } cache.php 0000604 00000002542 15245535622 0006330 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_cache * * @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Cache component helper. * * @since 1.6 */ class CacheHelper { /** * Get a list of filter options for the application clients. * * @return array An array of JHtmlOption elements. * * @deprecated 4.0 No replacement. */ public static function getClientOptions() { // Build the filter options. $options = array(); $options[] = JHtml::_('select.option', '0', JText::_('JSITE')); $options[] = JHtml::_('select.option', '1', JText::_('JADMINISTRATOR')); return $options; } /** * Configure the Linkbar. * * @param string $vName The name of the active view. * * @return void * * @since 1.6 */ public static function addSubmenu($vName) { JHtmlSidebar::addEntry( JText::_('JGLOBAL_SUBMENU_CHECKIN'), 'index.php?option=com_checkin', $vName == 'com_checkin' ); JHtmlSidebar::addEntry( JText::_('JGLOBAL_SUBMENU_CLEAR_CACHE'), 'index.php?option=com_cache', $vName == 'cache' ); JHtmlSidebar::addEntry( JText::_('JGLOBAL_SUBMENU_PURGE_EXPIRED_CACHE'), 'index.php?option=com_cache&view=purge', $vName == 'purge' ); } } versions.php 0000604 00000002413 15245535622 0007132 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; use RegularLabs\Library\Version as RL_Version; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLVersions { public static function getXMLVersion($alias, $urlformat = false, $type = 'component', $folder = 'system') { return ! class_exists('RegularLabs\Library\Version') ? '' : RL_Version::get($alias, $type, $folder); } public static function getPluginXMLVersion($alias, $folder = 'system') { return ! class_exists('RegularLabs\Library\Version') ? '' : RL_Version::getPluginVersion($alias, $folder); } public static function render($alias) { return ! class_exists('RegularLabs\Library\Version') ? '' : RL_Version::getMessage($alias); } public static function getFooter($name, $copyright = 1) { return ! class_exists('RegularLabs\Library\Version') ? '' : RL_Version::getFooter($name, $copyright); } } field.php 0000604 00000001070 15245535622 0006343 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLFormField extends \RegularLabs\Library\Field { } groupfield.php 0000604 00000001102 15245535622 0007414 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php')) { require_once JPATH_LIBRARIES . '/regularlabs/autoload.php'; } class RLFormGroupField extends \RegularLabs\Library\FieldGroup { } string.php 0000604 00000000716 15245535622 0006574 0 ustar 00 <?php /** * @package Regular Labs Library * @version 21.4.10972 * * @author Peter van Westen <info@regularlabs.com> * @link http://www.regularlabs.com * @copyright Copyright © 2021 Regular Labs All Rights Reserved * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL */ /* @DEPRECATED */ defined('_JEXEC') or die; jimport('joomla.string.string'); abstract class RLString extends JString { } helper.php 0000604 00000045476 15245535622 0006561 0 ustar 00 <?php /** * @name Slideshow CK * @package com_slideshowck * @copyright Copyright (C) 2019. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt * @author Cedric Keiflin - https://www.template-creator.com - https://www.joomlack.fr */ // No direct access defined('_JEXEC') or die; require_once JPATH_ADMINISTRATOR . '/components/com_slideshowck/helpers/defines.php'; use Slideshowck\CKInput; use Slideshowck\CKFof; use Slideshowck\CKText; /** * Helper Class. */ class SlideshowckHelper { static $cssreplacements; /* * Load the JS and CSS files needed to use CKBox * * Return void */ public static function loadCkbox() { $doc = \Joomla\CMS\Factory::getDocument(); \Joomla\CMS\HTML\HTMLHelper::_('jquery.framework', true); // $doc->addScript(\Joomla\CMS\Uri\Uri::root(true) . '/media/jui/js/jquery.min.js'); $doc->addStyleSheet(SLIDESHOWCK_MEDIA_URI . '/assets/ckbox.css'); $doc->addScript(SLIDESHOWCK_MEDIA_URI . '/assets/ckbox.js'); } /* * Load the JS and CSS files needed to use CKBox * * Return void */ // public static function loadCKFramework() { // $doc = \Joomla\CMS\Factory::getDocument(); // $doc->addScript(\Joomla\CMS\Uri\Uri::root(true) . '/media/jui/js/jquery.min.js'); // $doc->addStyleSheet(SLIDESHOWCK_MEDIA_URI . '/assets/ckframework.css'); // } /* * Load the JS and CSS files needed to use CKBox * * Return void */ /*public static function loadInlineCKFramework() { ?> <script src="<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/media/jui/js/jquery.min.js" type="text/javascript"></script> <link rel="stylesheet" href="<?php echo \Joomla\CMS\Uri\Uri::root(true) ?>/components/com_slideshowck/assets/font-awesome.min.css" type="text/css" /> <link rel="stylesheet" href="<?php echo SLIDESHOWCK_MEDIA_URI ?>/assets/ckframework.css" type="text/css" /> <?php }*/ /** * Convert a hexa decimal color code to its RGB equivalent * * @param string $hexStr (hexadecimal color value) * @param boolean $returnAsString (if set true, returns the value separated by the separator character. Otherwise returns associative array) * @param string $seperator (to separate RGB values. Applicable only if second parameter is true.) * @return array or string (depending on second parameter. Returns False if invalid hex color value) */ static function hex2RGB($hexStr, $opacity) { $hexStr = preg_replace("/[^0-9A-Fa-f]/", '', $hexStr); // Gets a proper hex string $rgbArray = array(); if (strlen($hexStr) == 6) { //If a proper hex code, convert using bitwise operation. No overhead... faster $colorVal = hexdec($hexStr); $rgbArray['red'] = 0xFF & ($colorVal >> 0x10); $rgbArray['green'] = 0xFF & ($colorVal >> 0x8); $rgbArray['blue'] = 0xFF & $colorVal; } elseif (strlen($hexStr) == 3) { //if shorthand notation, need some string manipulations $rgbArray['red'] = hexdec(str_repeat(substr($hexStr, 0, 1), 2)); $rgbArray['green'] = hexdec(str_repeat(substr($hexStr, 1, 1), 2)); $rgbArray['blue'] = hexdec(str_repeat(substr($hexStr, 2, 1), 2)); } else { return false; //Invalid hex color code } $rgbacolor = "rgba(" . $rgbArray['red'] . "," . $rgbArray['green'] . "," . $rgbArray['blue'] . "," . ($opacity / 100) . ")"; return $rgbacolor; } /** * Test if there is already a unit, else add the px * * @param string $value * @return string */ public static function testUnit($value) { if ((stristr($value, 'px')) OR (stristr($value, 'em')) OR (stristr($value, '%'))) { return $value; } if ($value == '') { $value = 0; } return $value . 'px'; } /** * Remove special character */ public static function cleanName($path) { return preg_replace('/[^a-z0-9]/i', '_', $path); } public static function formatPath($p) { return trim(str_replace("\\", "/", $p), "/"); } /** * Get a subtring with the max length setting. * * @param string $text; * @param int $length limit characters showing; * @param string $replacer; * @return tring; */ public static function substring($text, $length = 100, $replacer = '...', $isStrips = true, $stringtags = '') { if($isStrips){ $text = preg_replace('/\<p.*\>/Us','',$text); $text = str_replace('</p>','<br/>',$text); $text = strip_tags($text, $stringtags); } if(function_exists('mb_strlen')){ if (mb_strlen($text) < $length) return $text; $text = mb_substr($text, 0, $length); }else{ if (strlen($text) < $length) return $text; $text = substr($text, 0, $length); } return $text . $replacer; } /* * update the table */ /*public static function createTableOptions() { $sqlsrc = SLIDESHOWCK_PATH . '/sql/updates/2.4.0.sql'; $query = file_get_contents($sqlsrc); $db = \Joomla\CMS\Factory::getDbo(); $db->setQuery($query); if (!$db->execute()) { echo '<p class="alert alert-danger">Error during table options creation</p>'; } else { echo '<p class="alert alert-success">Table options successfully created</p>'; } }*/ /** * Get the name of the style */ public static function getStyleNameById($id) { if (! $id) return ''; // Create a new query object. $db = \Joomla\CMS\Factory::getDbo(); $query = $db->getQuery(true); // Select the required fields from the table. $query->select('a.name'); $query->from($db->quoteName('#__slideshowck_styles') . ' AS a'); $query->where('(a.state IN (0, 1))'); $query->where('a.id = ' . (int)$id); // Reset the query using our newly populated query object. $db->setQuery($query); // Load the results as a list of stdClass objects (see later for more options on retrieving data). $results = $db->loadResult(); return $results; } /** * Create the list of all modules published as Object * * $file string the image path * $x integer the new image width * $y integer the new image height * * @return Boolean True on Success */ static function resizeImage($file, $x, $y = '', $thumbpath = 'th', $thumbsuffix = '_th') { if (!$file) return; $thumbext = explode(".", $file); $thumbext = end($thumbext); $thumbfile = str_replace(basename($file), $thumbpath . "/" . basename($file), $file); $thumbfile = str_replace("." . $thumbext, $thumbsuffix . "." . $thumbext, $thumbfile); $filetmp = JPATH_ROOT . '/' . $file; $filetmp = str_replace("%20", " ", $filetmp); if (! file_exists($filetmp)) return $file; $size = getimagesize($filetmp); if ($size[0] > $size[1] || !$y) // paysage { $y = $x * $size[1] / $size[0]; } else { $x = $y * $size[0] / $size[1]; } if ($size) { if (\Joomla\CMS\Filesystem\File::exists($thumbfile)) { return $thumbfile; } $thumbfolder = str_replace(basename($file), $thumbpath . "/", $filetmp); if (!\Joomla\CMS\Filesystem\Folder::exists($thumbfolder)) { \Joomla\CMS\Filesystem\Folder::create($thumbfolder); \Joomla\CMS\Filesystem\File::copy(JPATH_ROOT . '/modules/mod_slideshowck/index.html', $thumbfolder . 'index.html' ); } if ($size['mime'] == 'image/jpeg') { $img_big = imagecreatefromjpeg($filetmp); # On ouvre l'image d'origine $img_new = imagecreate($x, $y); # création de la miniature $img_mini = imagecreatetruecolor($x, $y) or $img_mini = imagecreate($x, $y); // copie de l'image, avec le redimensionnement. imagecopyresized($img_mini, $img_big, 0, 0, 0, 0, $x, $y, $size[0], $size[1]); imagejpeg($img_mini, JPATH_ROOT . '/' . $thumbfile); } elseif ($size['mime'] == 'image/png') { $img_big = imagecreatefrompng($filetmp); # On ouvre l'image d'origine $img_new = imagecreate($x, $y); # création de la miniature $img_mini = imagecreatetruecolor($x, $y) or $img_mini = imagecreate($x, $y); // copie de l'image, avec le redimensionnement. imagecopyresized($img_mini, $img_big, 0, 0, 0, 0, $x, $y, $size[0], $size[1]); imagepng($img_mini, JPATH_ROOT . '/' . $thumbfile); } elseif ($size['mime'] == 'image/gif') { $img_big = imagecreatefromgif($filetmp); # On ouvre l'image d'origine $img_new = imagecreate($x, $y); # création de la miniature $img_mini = imagecreatetruecolor($x, $y) or $img_mini = imagecreate($x, $y); // copie de l'image, avec le redimensionnement. imagecopyresized($img_mini, $img_big, 0, 0, 0, 0, $x, $y, $size[0], $size[1]); imagegif($img_mini, JPATH_ROOT . '/' . $thumbfile); } //echo 'Image redimensionnée !'; } return $thumbfile; } /* * Make empty slide object */ public static function initItem() { $item = new stdClass(); $item->image = null; $item->link = null; $item->title = null; $item->text = null; $item->more = array(); $item->alignment = null; $item->time = null; $item->target = 'default'; $item->video = null; $item->texttype = null; $item->articleid = null; return $item; } /* * Convert an old item to the new convention */ public static function legacyUpdateItem(&$item) { $newItem = self::initItem(); foreach ($newItem as $key => $value) { if (!isset($item->$key)) $item->$key = $value; } $item->image = $item->imgname; $item->link = $item->imglink; $item->time = $item->imgtime; $item->thumb = $item->imgthumb; $item->title = $item->imgtitle; $item->text = strip_tags($item->imgcaption); } /* * Convert an item to the old convention to render in a V1 layout * To call manually in the layout file */ public static function legacyItemForV1Layout(&$item) { $newItem = self::initItem(); foreach ($newItem as $key => $value) { if (!isset($item->$key)) $item->$key = $value; } $item->imgname = $item->image; $item->imglink = $item->link; $item->imgtime = $item->time; $item->imgthumb = $item->imgname; // $item->imgthumb = $item->thumb; $item->imgtitle = $item->title; $item->imgcaption = $item->text; $item->imgalignment = $item->alignment; $item->imgtime = $item->time; $item->imgtarget = $item->target; $item->imgvideo = $item->video; $item->article = null; } /** * Set the correct video link * * $videolink string the video path * * @return string the new video path */ static function setVideolink($videolink) { // youtube if (stristr($videolink, 'youtu.be')) { $videolink = str_replace('youtu.be', 'www.youtube.com/embed', $videolink); } else if (stristr($videolink, 'www.youtube.com') AND !stristr($videolink, 'embed')) { $videolink = str_replace('youtube.com', 'youtube.com/embed', $videolink); } if (strpos($videolink, 'http') !== false) $videolink .= ( stristr($videolink, '?')) ? '&wmode=transparent' : '?wmode=transparent'; return $videolink; } /** * Set the correct video link * * $videolink string the video path * * @return string the new video path */ static function setImageUrl($url) { if (strpos($url, 'http') !== 0) { $url = \Joomla\CMS\Uri\Uri::root(true) . '/' . trim($url, '/'); } return $url; } /** * Truncates text blocks over the specified character limit and closes * all open HTML tags. The method will optionally not truncate an individual * word, it will find the first space that is within the limit and * truncate at that point. This method is UTF-8 safe. * * @param string $text The text to truncate. * @param integer $length The maximum length of the text. * @param boolean $noSplit Don't split a word if that is where the cutoff occurs (default: true). * @param boolean $allowHtml Allow HTML tags in the output, and close any open tags (default: true). * * @return string The truncated text. * * @since 11.1 */ public static function truncate($text, $length = 0, $noSplit = true, $allowHtml = true) { if ($length == 0) return ''; // Check if HTML tags are allowed. if (!$allowHtml) { // Deal with spacing issues in the input. $text = str_replace('>', '> ', $text); $text = str_replace(array(' ', ' '), ' ', $text); $text = JString::trim(preg_replace('#\s+#mui', ' ', $text)); // Strip the tags from the input and decode entities. $text = strip_tags($text); $text = html_entity_decode($text, ENT_QUOTES, 'UTF-8'); // Remove remaining extra spaces. $text = str_replace(' ', ' ', $text); $text = JString::trim(preg_replace('#\s+#mui', ' ', $text)); } // Truncate the item text if it is too long. if ($length > 0 && JString::strlen($text) > $length) { // Find the first space within the allowed length. $tmp = JString::substr($text, 0, $length); if ($noSplit) { $offset = JString::strrpos($tmp, ' '); if (JString::strrpos($tmp, '<') > JString::strrpos($tmp, '>')) { $offset = JString::strrpos($tmp, '<'); } $tmp = JString::substr($tmp, 0, $offset); // If we don't have 3 characters of room, go to the second space within the limit. if (JString::strlen($tmp) > $length - 3) { $tmp = JString::substr($tmp, 0, JString::strrpos($tmp, ' ')); } } if ($allowHtml) { // Put all opened tags into an array preg_match_all("#<([a-z][a-z0-9]*)\b.*?(?!/)>#i", $tmp, $result); $openedTags = $result[1]; $openedTags = array_diff($openedTags, array("img", "hr", "br")); $openedTags = array_values($openedTags); // Put all closed tags into an array preg_match_all("#</([a-z]+)>#iU", $tmp, $result); $closedTags = $result[1]; $numOpened = count($openedTags); // All tags are closed if (count($closedTags) == $numOpened) { return $tmp . '...'; } $tmp .= '...'; $openedTags = array_reverse($openedTags); // Close tags for ($i = 0; $i < $numOpened; $i++) { if (!in_array($openedTags[$i], $closedTags)) { $tmp .= "</" . $openedTags[$i] . ">"; } else { unset($closedTags[array_search($openedTags[$i], $closedTags)]); } } } $text = $tmp; } return $text; } static function getArticle($item) { $app = \Joomla\CMS\Factory::getApplication(); if (version_compare(JVERSION, '4') >= 0) { $factory = $app->bootComponent('com_content')->getMVCFactory(); // Get an instance of the generic articles model $articles = $factory->createModel('Articles', 'Site', ['ignore_request' => true]); } else { // load the content articles file $com_path = JPATH_SITE . '/components/com_content/'; include_once $com_path . 'router.php'; include_once $com_path . 'helpers/route.php'; \Joomla\CMS\MVC\Model\BaseDatabaseModel::addIncludePath($com_path . '/models', 'ContentModel'); // Get an instance of the generic articles model $articles = \Joomla\CMS\MVC\Model\BaseDatabaseModel::getInstance('Articles', 'ContentModel', array('ignore_request' => true)); } // Access filter $access = !\Joomla\CMS\Component\ComponentHelper::getParams('com_content')->get('show_noauth'); $authorised = \Joomla\CMS\Access\Access::getAuthorisedViewLevels(\Joomla\CMS\Factory::getUser()->get('id')); // Get an instance of the generic articles model $articles = \Joomla\CMS\MVC\Model\BaseDatabaseModel::getInstance('Articles', 'ContentModel', array('ignore_request' => true)); // Set application parameters in model $app = \Joomla\CMS\Factory::getApplication(); // $appParams = $app->getParams(); $articles->setState('params', \Joomla\CMS\Component\ComponentHelper::getParams('com_content')); // $articles->setState('params', $appParams); $articles->setState('filter.published', 1); // $item->slidearticleid = isset($item->slidearticleid) ? $item->slidearticleid : $item->articleid; $articles->setState('filter.article_id', $item->slidearticleid); $items2 = $articles->getItems(); $item->article = $items2[0]; $item->text = $item->article->introtext; // $item->text = \Joomla\CMS\HTML\HTMLHelper::_('content.prepare', $item->text); $item->title = $item->article->title; // set the item link to the article depending on the user rights if ($access || in_array($item->article->access, $authorised)) { // We know that user has the privilege to view the article $item->slug = $item->article->id . ':' . $item->article->alias; $item->catslug = $item->article->catid ? $item->article->catid . ':' . $item->article->category_alias : $item->article->catid; if (version_compare(JVERSION, '4') >= 0) { $item->link = \Joomla\CMS\Router\Route::_(\Joomla\Component\Content\Site\Helper\RouteHelper::getArticleRoute($item->slug, $item->catslug)); } else { $item->link = \Joomla\CMS\Router\Route::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catslug)); } } else { $app = \Joomla\CMS\Factory::getApplication(); $menu = $app->getMenu(); $menuitems = $menu->getItems('link', 'index.php?option=com_users&view=login'); if (isset($menuitems[0])) { $Itemid = $menuitems[0]->id; } elseif ($app->input->get('Itemid', 0, 'int') > 0) { $Itemid = $app->input->get('Itemid', 0, 'int'); } $item->link = \Joomla\CMS\Router\Route::_('index.php?option=com_users&view=login&Itemid=' . $Itemid); } return $item; } /** * List the replacement between the tags and the real final CSS rules */ public static function getCssReplacement() { if (! empty(self::$cssreplacements)) return self::$cssreplacements; self::$cssreplacements = Array( '[container]' => '' ,'[slide]' => '.cameraSlide img' ,'[caption]' => '.camera_caption > div' ,'[title]' => '.camera_caption_title' ,'[text]' => '.camera_caption_desc' ,'[button]' => 'a.camera-button' ,'[buttonhover]' => 'a.camera-button:hover' // ,'[thumbs]' => '.camera_pag_ul li img' ,'[paginationdotthumbs]' => '.camera_pag_ul li img' ); return self::$cssreplacements; } /** * Get the CSS of the style * @id - the style ID */ public static function getStyleLayoutcss($id) { if (! $id) return ''; // Create a new query object. $db = \Joomla\CMS\Factory::getDbo(); $query = $db->getQuery(true); // Select the required fields from the table. $query->select('a.layoutcss'); $query->from($db->quoteName('#__slideshowck_styles') . ' AS a'); $query->where('(a.state IN (0, 1))'); $query->where('a.id = ' . (int)$id); // Reset the query using our newly populated query object. $db->setQuery($query); // Load the results as a list of stdClass objects (see later for more options on retrieving data). $result = $db->loadResult(); self::makeCssReplacement($result); return $result; } public static function makeCssReplacement(&$css) { $cssreplacements = self::getCssReplacement(); foreach ($cssreplacements as $tag => $rep) { $css = str_replace($tag, $rep, $css); } // return $css; } public static function getProMessage() { $html = '<div class="ckinfo"><i class="fas fa-info"></i><a href="https://www.joomlack.fr/en/joomla-extensions/slideshow-ck" target="_blank">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_ONLY_PRO') . '</a></div>'; return $html; } public static function getProPreview($imgName) { $html = '<div class="ckpropreview">' . '<img src="' . SLIDESHOWCK_MEDIA_URL . '/images/proonly/' . $imgName . '" />' . '<a href="https://www.joomlack.fr/en/joomla-extensions/slideshow-ck" target="_blank">' . \Joomla\CMS\Language\Text::_('SLIDESHOWCK_ONLY_PRO') . '</a>' . '</div>'; return $html; } } legacyrouter.php 0000604 00000013324 15245551602 0007766 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_newsfeeds * * @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Legacy routing rules class from com_newsfeeds * * @since 3.6 * @deprecated 4.0 */ class NewsfeedsRouterRulesLegacy implements JComponentRouterRulesInterface { /** * Constructor for this legacy router * * @param JComponentRouterAdvanced $router The router this rule belongs to * * @since 3.6 * @deprecated 4.0 */ public function __construct($router) { $this->router = $router; } /** * Preprocess the route for the com_newsfeeds component * * @param array &$query An array of URL arguments * * @return void * * @since 3.6 * @deprecated 4.0 */ public function preprocess(&$query) { } /** * Build the route for the com_newsfeeds component * * @param array &$query An array of URL arguments * @param array &$segments The URL arguments to use to assemble the subsequent URL. * * @return void * * @since 3.6 * @deprecated 4.0 */ public function build(&$query, &$segments) { // Get a menu item based on Itemid or currently active $params = JComponentHelper::getParams('com_newsfeeds'); $advanced = $params->get('sef_advanced_link', 0); if (empty($query['Itemid'])) { $menuItem = $this->router->menu->getActive(); } else { $menuItem = $this->router->menu->getItem($query['Itemid']); } $mView = empty($menuItem->query['view']) ? null : $menuItem->query['view']; $mId = empty($menuItem->query['id']) ? null : $menuItem->query['id']; if (isset($query['view'])) { $view = $query['view']; if (empty($menuItem) || $menuItem->component !== 'com_newsfeeds' || empty($query['Itemid'])) { $segments[] = $query['view']; } unset($query['view']); } // Are we dealing with a newsfeed that is attached to a menu item? if (isset($query['view'], $query['id']) && $mView == $query['view'] && $mId == (int) $query['id']) { unset($query['view'], $query['catid'], $query['id']); return; } if (isset($view) && ($view === 'category' || $view === 'newsfeed')) { if ($mId != (int) $query['id'] || $mView != $view) { if ($view === 'newsfeed' && isset($query['catid'])) { $catid = $query['catid']; } elseif (isset($query['id'])) { $catid = $query['id']; } $menuCatid = $mId; $categories = JCategories::getInstance('Newsfeeds'); $category = $categories->get($catid); if ($category) { $path = $category->getPath(); $path = array_reverse($path); $array = array(); foreach ($path as $id) { if ((int) $id === (int) $menuCatid) { break; } if ($advanced) { list($tmp, $id) = explode(':', $id, 2); } $array[] = $id; } $segments = array_merge($segments, array_reverse($array)); } if ($view === 'newsfeed') { if ($advanced) { list($tmp, $id) = explode(':', $query['id'], 2); } else { $id = $query['id']; } $segments[] = $id; } } unset($query['id'], $query['catid']); } if (isset($query['layout'])) { if (!empty($query['Itemid']) && isset($menuItem->query['layout'])) { if ($query['layout'] == $menuItem->query['layout']) { unset($query['layout']); } } else { if ($query['layout'] === 'default') { unset($query['layout']); } } } $total = count($segments); for ($i = 0; $i < $total; $i++) { $segments[$i] = str_replace(':', '-', $segments[$i]); } } /** * Parse the segments of a URL. * * @param array &$segments The segments of the URL to parse. * @param array &$vars The URL attributes to be used by the application. * * @return void * * @since 3.6 * @deprecated 4.0 */ public function parse(&$segments, &$vars) { $total = count($segments); for ($i = 0; $i < $total; $i++) { $segments[$i] = preg_replace('/-/', ':', $segments[$i], 1); } // Get the active menu item. $item = $this->router->menu->getActive(); $params = JComponentHelper::getParams('com_newsfeeds'); $advanced = $params->get('sef_advanced_link', 0); // Count route segments $count = count($segments); // Standard routing for newsfeeds. if (!isset($item)) { $vars['view'] = $segments[0]; $vars['id'] = $segments[$count - 1]; return; } // From the categories view, we can only jump to a category. $id = (isset($item->query['id']) && $item->query['id'] > 1) ? $item->query['id'] : 'root'; $categories = JCategories::getInstance('Newsfeeds')->get($id)->getChildren(); $vars['catid'] = $id; $vars['id'] = $id; $found = 0; foreach ($segments as $segment) { $segment = $advanced ? str_replace(':', '-', $segment) : $segment; foreach ($categories as $category) { if ($category->slug == $segment || $category->alias == $segment) { $vars['id'] = $category->id; $vars['catid'] = $category->id; $vars['view'] = 'category'; $categories = $category->getChildren(); $found = 1; break; } } if ($found == 0) { if ($advanced) { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('id')) ->from('#__newsfeeds') ->where($db->quoteName('catid') . ' = ' . (int) $vars['catid']) ->where($db->quoteName('alias') . ' = ' . $db->quote($segment)); $db->setQuery($query); $nid = $db->loadResult(); } else { $nid = $segment; } $vars['id'] = $nid; $vars['view'] = 'newsfeed'; } $found = 0; } } } category.php 0000604 00000001206 15245551602 0007072 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_newsfeeds * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Content Component Category Tree * * @since 1.6 */ class NewsfeedsCategories extends JCategories { /** * Constructor * * @param array $options options */ public function __construct($options = array()) { $options['table'] = '#__newsfeeds'; $options['extension'] = 'com_newsfeeds'; $options['statefield'] = 'published'; parent::__construct($options); } } association.php 0000604 00000003322 15245551602 0007572 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_newsfeeds * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('NewsfeedsHelper', JPATH_ADMINISTRATOR . '/components/com_newsfeeds/helpers/newsfeeds.php'); JLoader::register('NewsfeedsHelperRoute', JPATH_SITE . '/components/com_newsfeeds/helpers/route.php'); JLoader::register('CategoryHelperAssociation', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/association.php'); /** * Newsfeeds Component Association Helper * * @since 3.0 */ abstract class NewsfeedsHelperAssociation extends CategoryHelperAssociation { /** * Method to get the associations for a given item * * @param integer $id Id of the item * @param string $view Name of the view * * @return array Array of associations for the item * * @since 3.0 */ public static function getAssociations($id = 0, $view = null) { $jinput = JFactory::getApplication()->input; $view = $view === null ? $jinput->get('view') : $view; $id = empty($id) ? $jinput->getInt('id') : $id; if ($view === 'newsfeed') { if ($id) { $associations = JLanguageAssociations::getAssociations('com_newsfeeds', '#__newsfeeds', 'com_newsfeeds.item', $id); $return = array(); foreach ($associations as $tag => $item) { $return[$tag] = NewsfeedsHelperRoute::getNewsfeedRoute($item->id, (int) $item->catid, $item->language); } return $return; } } if ($view === 'category' || $view === 'categories') { return self::getCategoryAssociations($id, 'com_newsfeeds'); } return array(); } } route.php 0000604 00000002730 15245551602 0006416 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_newsfeeds * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Newsfeeds Component Route Helper * * @since 1.5 */ abstract class NewsfeedsHelperRoute { /** * getNewsfeedRoute * * @param int $id menu itemid * @param int $catid category id * @param int $language language * * @return string */ public static function getNewsfeedRoute($id, $catid, $language = 0) { // Create the link $link = 'index.php?option=com_newsfeeds&view=newsfeed&id=' . $id; if ((int) $catid > 1) { $link .= '&catid=' . $catid; } if ($language && $language !== '*' && JLanguageMultilang::isEnabled()) { $link .= '&lang=' . $language; } return $link; } /** * getCategoryRoute * * @param int $catid category id * @param int $language language * * @return string */ public static function getCategoryRoute($catid, $language = 0) { if ($catid instanceof JCategoryNode) { $id = $catid->id; } else { $id = (int) $catid; } if ($id < 1) { $link = ''; } else { // Create the link $link = 'index.php?option=com_newsfeeds&view=category&id=' . $id; if ($language && $language !== '*' && JLanguageMultilang::isEnabled()) { $link .= '&lang=' . $language; } } return $link; } } html/filter.php 0000604 00000033674 15245561110 0007517 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Registry\Registry; JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php'); /** * Filter HTML Behaviors for Finder. * * @since 2.5 */ abstract class JHtmlFilter { /** * Method to generate filters using the slider widget and decorated * with the FinderFilter JavaScript behaviors. * * @param array $options An array of configuration options. [optional] * * @return mixed A rendered HTML widget on success, null otherwise. * * @since 2.5 */ public static function slider($options = array()) { $db = JFactory::getDbo(); $query = $db->getQuery(true); $user = JFactory::getUser(); $groups = implode(',', $user->getAuthorisedViewLevels()); $html = ''; $filter = null; // Get the configuration options. $filterId = array_key_exists('filter_id', $options) ? $options['filter_id'] : null; $activeNodes = array_key_exists('selected_nodes', $options) ? $options['selected_nodes'] : array(); $classSuffix = array_key_exists('class_suffix', $options) ? $options['class_suffix'] : ''; // Load the predefined filter if specified. if (!empty($filterId)) { $query->select('f.data, f.params') ->from($db->quoteName('#__finder_filters') . ' AS f') ->where('f.filter_id = ' . (int) $filterId); // Load the filter data. $db->setQuery($query); try { $filter = $db->loadObject(); } catch (RuntimeException $e) { return null; } // Initialize the filter parameters. if ($filter) { $filter->params = new Registry($filter->params); } } // Build the query to get the branch data and the number of child nodes. $query->clear() ->select('t.*, count(c.id) AS children') ->from($db->quoteName('#__finder_taxonomy') . ' AS t') ->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS c ON c.parent_id = t.id') ->where('t.parent_id = 1') ->where('t.state = 1') ->where('t.access IN (' . $groups . ')') ->group('t.id, t.parent_id, t.state, t.access, t.ordering, t.title, c.parent_id') ->order('t.ordering, t.title'); // Limit the branch children to a predefined filter. if ($filter) { $query->where('c.id IN(' . $filter->data . ')'); } // Load the branches. $db->setQuery($query); try { $branches = $db->loadObjectList('id'); } catch (RuntimeException $e) { return null; } // Check that we have at least one branch. if (count($branches) === 0) { return null; } $branch_keys = array_keys($branches); $html .= JHtml::_('bootstrap.startAccordion', 'accordion', array('parent' => true, 'active' => 'accordion-' . $branch_keys[0]) ); // Load plugin language files. FinderHelperLanguage::loadPluginLanguage(); // Iterate through the branches and build the branch groups. foreach ($branches as $bk => $bv) { // If the multi-lang plugin is enabled then drop the language branch. if ($bv->title === 'Language' && JLanguageMultilang::isEnabled()) { continue; } // Build the query to get the child nodes for this branch. $query->clear() ->select('t.*') ->from($db->quoteName('#__finder_taxonomy') . ' AS t') ->where('t.parent_id = ' . (int) $bk) ->where('t.state = 1') ->where('t.access IN (' . $groups . ')') ->order('t.ordering, t.title'); // Self-join to get the parent title. $query->select('e.title AS parent_title') ->join('LEFT', $db->quoteName('#__finder_taxonomy', 'e') . ' ON ' . $db->quoteName('e.id') . ' = ' . $db->quoteName('t.parent_id')); // Load the branches. $db->setQuery($query); try { $nodes = $db->loadObjectList('id'); } catch (RuntimeException $e) { return null; } // Translate node titles if possible. $lang = JFactory::getLanguage(); foreach ($nodes as $nk => $nv) { if (trim($nv->parent_title, '**') === 'Language') { $title = FinderHelperLanguage::branchLanguageTitle($nv->title); } else { $key = FinderHelperLanguage::branchPlural($nv->title); $title = $lang->hasKey($key) ? JText::_($key) : $nv->title; } $nodes[$nk]->title = $title; } // Adding slides $html .= JHtml::_('bootstrap.addSlide', 'accordion', JText::sprintf('COM_FINDER_FILTER_BRANCH_LABEL', JText::_(FinderHelperLanguage::branchSingular($bv->title)) . ' - ' . count($nodes) ), 'accordion-' . $bk ); // Populate the toggle button. $html .= '<button class="btn jform-rightbtn" type="button" onclick="jQuery(\'[id="tax-' . $bk . '"]\').each(function(){this.click();});"><span class="icon-checkbox-partial"></span> ' . JText::_('JGLOBAL_SELECTION_INVERT') . '</button><hr/>'; // Populate the group with nodes. foreach ($nodes as $nk => $nv) { // Determine if the node should be checked. $checked = in_array($nk, $activeNodes) ? ' checked="checked"' : ''; // Build a node. $html .= '<div class="control-group">'; $html .= '<div class="controls">'; $html .= '<label class="checkbox">'; $html .= '<input type="checkbox" class="selector filter-node' . $classSuffix . '" value="' . $nk . '" name="t[]" id="tax-' . $bk . '"' . $checked . ' />'; $html .= $nv->title; $html .= '</label>'; $html .= '</div>'; $html .= '</div>'; } $html .= JHtml::_('bootstrap.endSlide'); } $html .= JHtml::_('bootstrap.endAccordion'); return $html; } /** * Method to generate filters using select box dropdown controls. * * @param FinderIndexerQuery $idxQuery A FinderIndexerQuery object. * @param array $options An array of options. * * @return mixed A rendered HTML widget on success, null otherwise. * * @since 2.5 */ public static function select($idxQuery, $options) { $user = JFactory::getUser(); $groups = implode(',', $user->getAuthorisedViewLevels()); $filter = null; // Get the configuration options. $classSuffix = $options->get('class_suffix', null); $showDates = $options->get('show_date_filters', false); // Try to load the results from cache. $cache = JFactory::getCache('com_finder', ''); $cacheId = 'filter_select_' . serialize(array($idxQuery->filter, $options, $groups, JFactory::getLanguage()->getTag())); // Check the cached results. if ($cache->contains($cacheId)) { $branches = $cache->get($cacheId); } else { $db = JFactory::getDbo(); $query = $db->getQuery(true); // Load the predefined filter if specified. if (!empty($idxQuery->filter)) { $query->select('f.data, ' . $db->quoteName('f.params')) ->from($db->quoteName('#__finder_filters') . ' AS f') ->where('f.filter_id = ' . (int) $idxQuery->filter); // Load the filter data. $db->setQuery($query); try { $filter = $db->loadObject(); } catch (RuntimeException $e) { return null; } // Initialize the filter parameters. if ($filter) { $filter->params = new Registry($filter->params); } } // Build the query to get the branch data and the number of child nodes. $query->clear() ->select('t.*, count(c.id) AS children') ->from($db->quoteName('#__finder_taxonomy') . ' AS t') ->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS c ON c.parent_id = t.id') ->where('t.parent_id = 1') ->where('t.state = 1') ->where('t.access IN (' . $groups . ')') ->where('c.state = 1') ->where('c.access IN (' . $groups . ')') ->group($db->quoteName('t.id')) ->order('t.ordering, t.title'); // Limit the branch children to a predefined filter. if (!empty($filter->data)) { $query->where('c.id IN(' . $filter->data . ')'); } // Load the branches. $db->setQuery($query); try { $branches = $db->loadObjectList('id'); } catch (RuntimeException $e) { return null; } // Check that we have at least one branch. if (count($branches) === 0) { return null; } // Iterate through the branches and build the branch groups. foreach ($branches as $bk => $bv) { // If the multi-lang plugin is enabled then drop the language branch. if ($bv->title === 'Language' && JLanguageMultilang::isEnabled()) { continue; } // Build the query to get the child nodes for this branch. $query->clear() ->select('t.*') ->from($db->quoteName('#__finder_taxonomy') . ' AS t') ->where('t.parent_id = ' . (int) $bk) ->where('t.state = 1') ->where('t.access IN (' . $groups . ')') ->order('t.ordering, t.title'); // Self-join to get the parent title. $query->select('e.title AS parent_title') ->join('LEFT', $db->quoteName('#__finder_taxonomy', 'e') . ' ON ' . $db->quoteName('e.id') . ' = ' . $db->quoteName('t.parent_id')); // Limit the nodes to a predefined filter. if (!empty($filter->data)) { $query->where('t.id IN(' . $filter->data . ')'); } // Load the branches. $db->setQuery($query); try { $branches[$bk]->nodes = $db->loadObjectList('id'); } catch (RuntimeException $e) { return null; } // Translate branch nodes if possible. $language = JFactory::getLanguage(); foreach ($branches[$bk]->nodes as $node_id => $node) { if (trim($node->parent_title, '**') === 'Language') { $title = FinderHelperLanguage::branchLanguageTitle($node->title); } else { $key = FinderHelperLanguage::branchPlural($node->title); $title = $language->hasKey($key) ? JText::_($key) : $node->title; } $branches[$bk]->nodes[$node_id]->title = $title; } // Add the Search All option to the branch. array_unshift($branches[$bk]->nodes, array('id' => null, 'title' => JText::_('COM_FINDER_FILTER_SELECT_ALL_LABEL'))); } // Store the data in cache. $cache->store($branches, $cacheId); } $html = ''; // Add the dates if enabled. if ($showDates) { $html .= JHtml::_('filter.dates', $idxQuery, $options); } $html .= '<div class="filter-branch' . $classSuffix . ' control-group clearfix">'; // Iterate through all branches and build code. foreach ($branches as $bk => $bv) { // If the multi-lang plugin is enabled then drop the language branch. if ($bv->title === 'Language' && JLanguageMultilang::isEnabled()) { continue; } $active = null; // Check if the branch is in the filter. if (array_key_exists($bv->title, $idxQuery->filters)) { // Get the request filters. $temp = JFactory::getApplication()->input->request->get('t', array(), 'array'); // Search for active nodes in the branch and get the active node. $active = array_intersect($temp, $idxQuery->filters[$bv->title]); $active = count($active) === 1 ? array_shift($active) : null; } // Build a node. $html .= '<div class="controls finder-selects">'; $html .= '<label for="tax-' . JFilterOutput::stringURLSafe($bv->title) . '" class="control-label">'; $html .= JText::sprintf('COM_FINDER_FILTER_BRANCH_LABEL', JText::_(FinderHelperLanguage::branchSingular($bv->title))); $html .= '</label>'; $html .= '<br />'; $html .= JHtml::_( 'select.genericlist', $branches[$bk]->nodes, 't[]', 'class="inputbox advancedSelect"', 'id', 'title', $active, 'tax-' . JFilterOutput::stringURLSafe($bv->title) ); $html .= '</div>'; } $html .= '</div>'; return $html; } /** * Method to generate fields for filtering dates * * @param FinderIndexerQuery $idxQuery A FinderIndexerQuery object. * @param array $options An array of options. * * @return mixed A rendered HTML widget on success, null otherwise. * * @since 2.5 */ public static function dates($idxQuery, $options) { $html = ''; // Get the configuration options. $classSuffix = $options->get('class_suffix', null); $loadMedia = $options->get('load_media', true); $showDates = $options->get('show_date_filters', false); if (!empty($showDates)) { // Build the date operators options. $operators = array(); $operators[] = JHtml::_('select.option', 'before', JText::_('COM_FINDER_FILTER_DATE_BEFORE')); $operators[] = JHtml::_('select.option', 'exact', JText::_('COM_FINDER_FILTER_DATE_EXACTLY')); $operators[] = JHtml::_('select.option', 'after', JText::_('COM_FINDER_FILTER_DATE_AFTER')); // Load the CSS/JS resources. if ($loadMedia) { JHtml::_('stylesheet', 'com_finder/dates.css', array('version' => 'auto', 'relative' => true)); } // Open the widget. $html .= '<ul id="finder-filter-select-dates">'; // Start date filter. $attribs['class'] = 'input-medium'; $html .= '<li class="filter-date' . $classSuffix . '">'; $html .= '<label for="filter_date1" class="hasTooltip" title ="' . JText::_('COM_FINDER_FILTER_DATE1_DESC') . '">'; $html .= JText::_('COM_FINDER_FILTER_DATE1'); $html .= '</label>'; $html .= '<br />'; $html .= JHtml::_( 'select.genericlist', $operators, 'w1', 'class="inputbox filter-date-operator advancedSelect"', 'value', 'text', $idxQuery->when1, 'finder-filter-w1' ); $html .= JHtml::_('calendar', $idxQuery->date1, 'd1', 'filter_date1', '%Y-%m-%d', $attribs); $html .= '</li>'; // End date filter. $html .= '<li class="filter-date' . $classSuffix . '">'; $html .= '<label for="filter_date2" class="hasTooltip" title ="' . JText::_('COM_FINDER_FILTER_DATE2_DESC') . '">'; $html .= JText::_('COM_FINDER_FILTER_DATE2'); $html .= '</label>'; $html .= '<br />'; $html .= JHtml::_( 'select.genericlist', $operators, 'w2', 'class="inputbox filter-date-operator advancedSelect"', 'value', 'text', $idxQuery->when2, 'finder-filter-w2' ); $html .= JHtml::_('calendar', $idxQuery->date2, 'd2', 'filter_date2', '%Y-%m-%d', $attribs); $html .= '</li>'; // Close the widget. $html .= '</ul>'; } return $html; } } html/query.php 0000604 00000010755 15245561110 0007372 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Query HTML behavior class for Finder. * * @since 2.5 */ abstract class JHtmlQuery { /** * Method to get the explained (human-readable) search query. * * @param FinderIndexerQuery $query A FinderIndexerQuery object to explain. * * @return mixed String if there is data to explain, null otherwise. * * @since 2.5 */ public static function explained(FinderIndexerQuery $query) { $parts = array(); // Process the required tokens. foreach ($query->included as $token) { if ($token->required && (!isset($token->derived) || $token->derived == false)) { $parts[] = '<span class="query-required">' . JText::sprintf('COM_FINDER_QUERY_TOKEN_REQUIRED', $token->term) . '</span>'; } } // Process the optional tokens. foreach ($query->included as $token) { if (!$token->required && (!isset($token->derived) || $token->derived == false)) { $parts[] = '<span class="query-optional">' . JText::sprintf('COM_FINDER_QUERY_TOKEN_OPTIONAL', $token->term) . '</span>'; } } // Process the excluded tokens. foreach ($query->excluded as $token) { if (!isset($token->derived) || $token->derived === false) { $parts[] = '<span class="query-excluded">' . JText::sprintf('COM_FINDER_QUERY_TOKEN_EXCLUDED', $token->term) . '</span>'; } } // Process the start date. if ($query->date1) { $date = JFactory::getDate($query->date1)->format(JText::_('DATE_FORMAT_LC')); $datecondition = JText::_('COM_FINDER_QUERY_DATE_CONDITION_' . strtoupper($query->when1)); $parts[] = '<span class="query-start-date">' . JText::sprintf('COM_FINDER_QUERY_START_DATE', $datecondition, $date) . '</span>'; } // Process the end date. if ($query->date2) { $date = JFactory::getDate($query->date2)->format(JText::_('DATE_FORMAT_LC')); $datecondition = JText::_('COM_FINDER_QUERY_DATE_CONDITION_' . strtoupper($query->when2)); $parts[] = '<span class="query-end-date">' . JText::sprintf('COM_FINDER_QUERY_END_DATE', $datecondition, $date) . '</span>'; } // Process the taxonomy filters. if (!empty($query->filters)) { // Get the filters in the request. $t = JFactory::getApplication()->input->request->get('t', array(), 'array'); // Process the taxonomy branches. foreach ($query->filters as $branch => $nodes) { // Process the taxonomy nodes. $lang = JFactory::getLanguage(); foreach ($nodes as $title => $id) { // Translate the title for Types $key = FinderHelperLanguage::branchPlural($title); if ($lang->hasKey($key)) { $title = JText::_($key); } // Don't include the node if it is not in the request. if (!in_array($id, $t)) { continue; } // Add the node to the explanation. $parts[] = '<span class="query-taxonomy">' . JText::sprintf('COM_FINDER_QUERY_TAXONOMY_NODE', $title, JText::_(FinderHelperLanguage::branchSingular($branch))) . '</span>'; } } } // Build the interpreted query. return count($parts) ? JText::sprintf('COM_FINDER_QUERY_TOKEN_INTERPRETED', implode(JText::_('COM_FINDER_QUERY_TOKEN_GLUE'), $parts)) : null; } /** * Method to get the suggested search query. * * @param FinderIndexerQuery $query A FinderIndexerQuery object. * * @return mixed String if there is a suggestion, false otherwise. * * @since 2.5 */ public static function suggested(FinderIndexerQuery $query) { $suggested = false; // Check if the query input is empty. if (empty($query->input)) { return $suggested; } // Check if there were any ignored or included keywords. if (count($query->ignored) || count($query->included)) { $suggested = $query->input; // Replace the ignored keyword suggestions. foreach (array_reverse($query->ignored) as $token) { if (isset($token->suggestion)) { $suggested = str_ireplace($token->term, $token->suggestion, $suggested); } } // Replace the included keyword suggestions. foreach (array_reverse($query->included) as $token) { if (isset($token->suggestion)) { $suggested = str_ireplace($token->term, $token->suggestion, $suggested); } } // Check if we made any changes. if ($suggested == $query->input) { $suggested = false; } } return $suggested; } } icon.php 0000604 00000016773 15245562540 0006227 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_content * * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Registry\Registry; /** * Content Component HTML Helper * * @since 1.5 */ abstract class JHtmlIcon { /** * Method to generate a link to the create item page for the given category * * @param object $category The category information * @param Registry $params The item parameters * @param array $attribs Optional attributes for the link * @param boolean $legacy True to use legacy images, false to use icomoon based graphic * * @return string The HTML markup for the create item link */ public static function create($category, $params, $attribs = array(), $legacy = false) { $uri = JUri::getInstance(); $url = 'index.php?option=com_content&task=article.add&return=' . base64_encode($uri) . '&a_id=0&catid=' . $category->id; $text = JLayoutHelper::render('joomla.content.icons.create', array('params' => $params, 'legacy' => $legacy)); // Add the button classes to the attribs array if (isset($attribs['class'])) { $attribs['class'] .= ' btn btn-primary'; } else { $attribs['class'] = 'btn btn-primary'; } $button = JHtml::_('link', JRoute::_($url), $text, $attribs); $output = '<span class="hasTooltip" title="' . JHtml::_('tooltipText', 'COM_CONTENT_CREATE_ARTICLE') . '">' . $button . '</span>'; return $output; } /** * Method to generate a link to the email item page for the given article * * @param object $article The article information * @param Registry $params The item parameters * @param array $attribs Optional attributes for the link * @param boolean $legacy True to use legacy images, false to use icomoon based graphic * * @return string The HTML markup for the email item link * * @deprecated 4.0 The functionality to email an article is removed in Joomla 4 */ public static function email($article, $params, $attribs = array(), $legacy = false) { JLoader::register('MailtoHelper', JPATH_SITE . '/components/com_mailto/helpers/mailto.php'); $uri = JUri::getInstance(); $base = $uri->toString(array('scheme', 'host', 'port')); $template = JFactory::getApplication()->getTemplate(); $link = $base . JRoute::_(ContentHelperRoute::getArticleRoute($article->slug, $article->catid, $article->language), false); $url = 'index.php?option=com_mailto&tmpl=component&template=' . $template . '&link=' . MailtoHelper::addLink($link); $height = JFactory::getApplication()->get('captcha', '0') === '0' ? 450 : 550; $status = 'width=400,height=' . $height . ',menubar=yes,resizable=yes'; $text = JLayoutHelper::render('joomla.content.icons.email', array('params' => $params, 'legacy' => $legacy)); $attribs['title'] = JText::_('JGLOBAL_EMAIL_TITLE'); $attribs['onclick'] = "window.open(this.href,'win2','" . $status . "'); return false;"; $attribs['rel'] = 'nofollow'; return JHtml::_('link', JRoute::_($url), $text, $attribs); } /** * Display an edit icon for the article. * * This icon will not display in a popup window, nor if the article is trashed. * Edit access checks must be performed in the calling code. * * @param object $article The article information * @param Registry $params The item parameters * @param array $attribs Optional attributes for the link * @param boolean $legacy True to use legacy images, false to use icomoon based graphic * * @return string The HTML for the article edit icon. * * @since 1.6 */ public static function edit($article, $params, $attribs = array(), $legacy = false) { $user = JFactory::getUser(); $uri = JUri::getInstance(); // Ignore if in a popup window. if ($params && $params->get('popup')) { return; } // Ignore if the state is negative (trashed). if ($article->state < 0) { return; } // Show checked_out icon if the article is checked out by a different user if (property_exists($article, 'checked_out') && property_exists($article, 'checked_out_time') && $article->checked_out > 0 && $article->checked_out != $user->get('id')) { $checkoutUser = JFactory::getUser($article->checked_out); $date = JHtml::_('date', $article->checked_out_time); $tooltip = JText::_('JLIB_HTML_CHECKED_OUT') . ' :: ' . JText::sprintf('COM_CONTENT_CHECKED_OUT_BY', $checkoutUser->name) . ' <br /> ' . $date; $text = JLayoutHelper::render('joomla.content.icons.edit_lock', array('tooltip' => $tooltip, 'legacy' => $legacy)); $output = JHtml::_('link', '#', $text, $attribs); return $output; } $contentUrl = ContentHelperRoute::getArticleRoute($article->slug, $article->catid, $article->language); $url = $contentUrl . '&task=article.edit&a_id=' . $article->id . '&return=' . base64_encode($uri); if ($article->state == 0) { $overlib = JText::_('JUNPUBLISHED'); } else { $overlib = JText::_('JPUBLISHED'); } $date = JHtml::_('date', $article->created); $author = $article->created_by_alias ?: $article->author; $overlib .= '<br />'; $overlib .= $date; $overlib .= '<br />'; $overlib .= JText::sprintf('COM_CONTENT_WRITTEN_BY', htmlspecialchars($author, ENT_COMPAT, 'UTF-8')); $text = JLayoutHelper::render('joomla.content.icons.edit', array('article' => $article, 'overlib' => $overlib, 'legacy' => $legacy)); $attribs['title'] = JText::_('JGLOBAL_EDIT_TITLE'); $output = JHtml::_('link', JRoute::_($url), $text, $attribs); return $output; } /** * Method to generate a popup link to print an article * * @param object $article The article information * @param Registry $params The item parameters * @param array $attribs Optional attributes for the link * @param boolean $legacy True to use legacy images, false to use icomoon based graphic * * @return string The HTML markup for the popup link */ public static function print_popup($article, $params, $attribs = array(), $legacy = false) { $url = ContentHelperRoute::getArticleRoute($article->slug, $article->catid, $article->language); $url .= '&tmpl=component&print=1&layout=default'; $status = 'status=no,toolbar=no,scrollbars=yes,titlebar=no,menubar=no,resizable=yes,width=640,height=480,directories=no,location=no'; $text = JLayoutHelper::render('joomla.content.icons.print_popup', array('params' => $params, 'legacy' => $legacy)); $attribs['title'] = JText::sprintf('JGLOBAL_PRINT_TITLE', htmlspecialchars($article->title, ENT_QUOTES, 'UTF-8')); $attribs['onclick'] = "window.open(this.href,'win2','" . $status . "'); return false;"; $attribs['rel'] = 'nofollow'; return JHtml::_('link', JRoute::_($url), $text, $attribs); } /** * Method to generate a link to print an article * * @param object $article Not used, @deprecated for 4.0 * @param Registry $params The item parameters * @param array $attribs Not used, @deprecated for 4.0 * @param boolean $legacy True to use legacy images, false to use icomoon based graphic * * @return string The HTML markup for the popup link */ public static function print_screen($article, $params, $attribs = array(), $legacy = false) { $text = JLayoutHelper::render('joomla.content.icons.print_screen', array('params' => $params, 'legacy' => $legacy)); return '<a href="#" onclick="window.print();return false;">' . $text . '</a>'; } } query.php 0000604 00000015411 15245562540 0006430 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_content * * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Content Component Query Helper * * @since 1.5 */ class ContentHelperQuery { /** * Translate an order code to a field for primary category ordering. * * @param string $orderby The ordering code. * * @return string The SQL field(s) to order by. * * @since 1.5 */ public static function orderbyPrimary($orderby) { switch ($orderby) { case 'alpha' : $orderby = 'c.path, '; break; case 'ralpha' : $orderby = 'c.path DESC, '; break; case 'order' : $orderby = 'c.lft, '; break; default : $orderby = ''; break; } return $orderby; } /** * Translate an order code to a field for secondary category ordering. * * @param string $orderby The ordering code. * @param string $orderDate The ordering code for the date. * * @return string The SQL field(s) to order by. * * @since 1.5 */ public static function orderbySecondary($orderby, $orderDate = 'created') { $queryDate = self::getQueryDate($orderDate); switch ($orderby) { case 'date' : $orderby = $queryDate; break; case 'rdate' : $orderby = $queryDate . ' DESC '; break; case 'alpha' : $orderby = 'a.title'; break; case 'ralpha' : $orderby = 'a.title DESC'; break; case 'hits' : $orderby = 'a.hits DESC'; break; case 'rhits' : $orderby = 'a.hits'; break; case 'order' : $orderby = 'a.ordering'; break; case 'rorder' : $orderby = 'a.ordering DESC'; break; case 'author' : $orderby = 'author'; break; case 'rauthor' : $orderby = 'author DESC'; break; case 'front' : $orderby = 'a.featured DESC, fp.ordering, ' . $queryDate . ' DESC '; break; case 'random' : $orderby = JFactory::getDbo()->getQuery(true)->Rand(); break; case 'vote' : $orderby = 'a.id DESC '; if (JPluginHelper::isEnabled('content', 'vote')) { $orderby = 'rating_count DESC '; } break; case 'rvote' : $orderby = 'a.id ASC '; if (JPluginHelper::isEnabled('content', 'vote')) { $orderby = 'rating_count ASC '; } break; case 'rank' : $orderby = 'a.id DESC '; if (JPluginHelper::isEnabled('content', 'vote')) { $orderby = 'rating DESC '; } break; case 'rrank' : $orderby = 'a.id ASC '; if (JPluginHelper::isEnabled('content', 'vote')) { $orderby = 'rating ASC '; } break; default : $orderby = 'a.ordering'; break; } return $orderby; } /** * Translate an order code to a field for primary category ordering. * * @param string $orderDate The ordering code. * * @return string The SQL field(s) to order by. * * @since 1.6 */ public static function getQueryDate($orderDate) { $db = JFactory::getDbo(); switch ($orderDate) { case 'modified' : $queryDate = ' CASE WHEN a.modified = ' . $db->quote($db->getNullDate()) . ' THEN a.created ELSE a.modified END'; break; // Use created if publish_up is not set case 'published' : $queryDate = ' CASE WHEN a.publish_up = ' . $db->quote($db->getNullDate()) . ' THEN a.created ELSE a.publish_up END '; break; case 'unpublished' : $queryDate = ' CASE WHEN a.publish_down = ' . $db->quote($db->getNullDate()) . ' THEN a.created ELSE a.publish_down END '; break; case 'created' : default : $queryDate = ' a.created '; break; } return $queryDate; } /** * Get join information for the voting query. * * @param \Joomla\Registry\Registry $params An options object for the article. * * @return array A named array with "select" and "join" keys. * * @since 1.5 */ public static function buildVotingQuery($params = null) { if (!$params) { $params = JComponentHelper::getParams('com_content'); } $voting = $params->get('show_vote'); if ($voting) { // Calculate voting count $select = ' , ROUND(v.rating_sum / v.rating_count) AS rating, v.rating_count'; $join = ' LEFT JOIN #__content_rating AS v ON a.id = v.content_id'; } else { $select = ''; $join = ''; } return array('select' => $select, 'join' => $join); } /** * Method to order the intro articles array for ordering * down the columns instead of across. * The layout always lays the introtext articles out across columns. * Array is reordered so that, when articles are displayed in index order * across columns in the layout, the result is that the * desired article ordering is achieved down the columns. * * @param array &$articles Array of intro text articles * @param integer $numColumns Number of columns in the layout * * @return array Reordered array to achieve desired ordering down columns * * @since 1.6 * @deprecated 4.0 */ public static function orderDownColumns(&$articles, $numColumns = 1) { $count = count($articles); // Just return the same array if there is nothing to change if ($numColumns == 1 || !is_array($articles) || $count <= $numColumns) { $return = $articles; } // We need to re-order the intro articles array else { // We need to preserve the original array keys $keys = array_keys($articles); $maxRows = ceil($count / $numColumns); $numCells = $maxRows * $numColumns; $numEmpty = $numCells - $count; $index = array(); // Calculate number of empty cells in the array // Fill in all cells of the array // Put -1 in empty cells so we can skip later for ($row = 1, $i = 1; $row <= $maxRows; $row++) { for ($col = 1; $col <= $numColumns; $col++) { if ($numEmpty > ($numCells - $i)) { // Put -1 in empty cells $index[$row][$col] = -1; } else { // Put in zero as placeholder $index[$row][$col] = 0; } $i++; } } // Layout the articles in column order, skipping empty cells $i = 0; for ($col = 1; ($col <= $numColumns) && ($i < $count); $col++) { for ($row = 1; ($row <= $maxRows) && ($i < $count); $row++) { if ($index[$row][$col] != - 1) { $index[$row][$col] = $keys[$i]; $i++; } } } // Now read the $index back row by row to get articles in right row/col // so that they will actually be ordered down the columns (when read by row in the layout) $return = array(); $i = 0; for ($row = 1; ($row <= $maxRows) && ($i < $count); $row++) { for ($col = 1; ($col <= $numColumns) && ($i < $count); $col++) { $return[$keys[$i]] = $articles[$index[$row][$col]]; $i++; } } } return $return; } } html/contentadministrator.php 0000604 00000007362 15245567000 0012504 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_content * * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Utilities\ArrayHelper; JLoader::register('ContentHelper', JPATH_ADMINISTRATOR . '/components/com_content/helpers/content.php'); /** * Content HTML helper * * @since 3.0 */ abstract class JHtmlContentAdministrator { /** * Render the list of associated items * * @param integer $articleid The article item id * * @return string The language HTML * * @throws Exception */ public static function association($articleid) { // Defaults $html = ''; // Get the associations if ($associations = JLanguageAssociations::getAssociations('com_content', '#__content', 'com_content.item', $articleid)) { foreach ($associations as $tag => $associated) { $associations[$tag] = (int) $associated->id; } // Get the associated menu items $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('c.*') ->select('l.sef as lang_sef') ->select('l.lang_code') ->from('#__content as c') ->select('cat.title as category_title') ->join('LEFT', '#__categories as cat ON cat.id=c.catid') ->where('c.id IN (' . implode(',', array_values($associations)) . ')') ->where('c.id != ' . $articleid) ->join('LEFT', '#__languages as l ON c.language=l.lang_code') ->select('l.image') ->select('l.title as language_title'); $db->setQuery($query); try { $items = $db->loadObjectList('id'); } catch (RuntimeException $e) { throw new Exception($e->getMessage(), 500, $e); } if ($items) { foreach ($items as &$item) { $text = $item->lang_sef ? strtoupper($item->lang_sef) : 'XX'; $url = JRoute::_('index.php?option=com_content&task=article.edit&id=' . (int) $item->id); $tooltip = htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8') . '<br />' . JText::sprintf('JCATEGORY_SPRINTF', $item->category_title); $classes = 'hasPopover label label-association label-' . $item->lang_sef; $item->link = '<a href="' . $url . '" title="' . $item->language_title . '" class="' . $classes . '" data-content="' . $tooltip . '" data-placement="top">' . $text . '</a>'; } } JHtml::_('bootstrap.popover'); $html = JLayoutHelper::render('joomla.content.associations', $items); } return $html; } /** * Show the feature/unfeature links * * @param integer $value The state value * @param integer $i Row number * @param boolean $canChange Is user allowed to change? * * @return string HTML code */ public static function featured($value = 0, $i = 0, $canChange = true) { JHtml::_('bootstrap.tooltip'); // Array of image, task, title, action $states = array( 0 => array('unfeatured', 'articles.featured', 'COM_CONTENT_UNFEATURED', 'JGLOBAL_TOGGLE_FEATURED'), 1 => array('featured', 'articles.unfeatured', 'COM_CONTENT_FEATURED', 'JGLOBAL_TOGGLE_FEATURED'), ); $state = ArrayHelper::getValue($states, (int) $value, $states[1]); $icon = $state[0]; if ($canChange) { $html = '<a href="#" onclick="return listItemTask(\'cb' . $i . '\',\'' . $state[1] . '\')" class="btn btn-micro hasTooltip' . ($value == 1 ? ' active' : '') . '" title="' . JHtml::_('tooltipText', $state[3]) . '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>'; } else { $html = '<a class="btn btn-micro hasTooltip disabled' . ($value == 1 ? ' active' : '') . '" title="' . JHtml::_('tooltipText', $state[2]) . '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>'; } return $html; } } associations.php 0000604 00000005671 15245567000 0007765 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_menus * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Association\AssociationExtensionHelper; /** * Menu associations helper. * * @since 3.7.0 */ class MenusAssociationsHelper extends AssociationExtensionHelper { /** * The extension name * * @var array $extension * * @since 3.7.0 */ protected $extension = 'com_menus'; /** * Array of item types * * @var array $itemTypes * * @since 3.7.0 */ protected $itemTypes = array('item'); /** * Has the extension association support * * @var boolean $associationsSupport * * @since 3.7.0 */ protected $associationsSupport = true; /** * Get the associated items for an item * * @param string $typeName The item type * @param int $id The id of item for which we need the associated items * * @return array * * @since 3.7.0 */ public function getAssociations($typeName, $id) { $type = $this->getType($typeName); $context = $this->extension . '.item'; // Get the associations. $associations = JLanguageAssociations::getAssociations( $this->extension, $type['tables']['a'], $context, $id, 'id', 'alias', '' ); return $associations; } /** * Get item information * * @param string $typeName The item type * @param int $id The id of item for which we need the associated items * * @return JTable|null * * @since 3.7.0 */ public function getItem($typeName, $id) { if (empty($id)) { return null; } $table = null; switch ($typeName) { case 'item': $table = JTable::getInstance('menu'); break; } if (is_null($table)) { return null; } $table->load($id); return $table; } /** * Get information about the type * * @param string $typeName The item type * * @return array Array of item types * * @since 3.7.0 */ public function getType($typeName = '') { $fields = $this->getFieldsTemplate(); $tables = array(); $joins = array(); $support = $this->getSupportTemplate(); $title = ''; if (in_array($typeName, $this->itemTypes)) { switch ($typeName) { case 'item': $fields['ordering'] = 'a.lft'; $fields['level'] = 'a.level'; $fields['catid'] = ''; $fields['state'] = 'a.published'; $fields['created_user_id'] = ''; $fields['menutype'] = 'a.menutype'; $support['state'] = true; $support['acl'] = true; $support['checkout'] = true; $support['level'] = true; $tables = array( 'a' => '#__menu' ); $title = 'menu'; break; } } return array( 'fields' => $fields, 'support' => $support, 'tables' => $tables, 'joins' => $joins, 'title' => $title ); } } content.php 0000604 00000010333 15245567000 0006727 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_content * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Content component helper. * * @since 1.6 */ class ContentHelper extends JHelperContent { public static $extension = 'com_content'; /** * Configure the Linkbar. * * @param string $vName The name of the active view. * * @return void * * @since 1.6 */ public static function addSubmenu($vName) { JHtmlSidebar::addEntry( JText::_('JGLOBAL_ARTICLES'), 'index.php?option=com_content&view=articles', $vName == 'articles' ); JHtmlSidebar::addEntry( JText::_('COM_CONTENT_SUBMENU_CATEGORIES'), 'index.php?option=com_categories&extension=com_content', $vName == 'categories' ); JHtmlSidebar::addEntry( JText::_('COM_CONTENT_SUBMENU_FEATURED'), 'index.php?option=com_content&view=featured', $vName == 'featured' ); if (JComponentHelper::isEnabled('com_fields') && JComponentHelper::getParams('com_content')->get('custom_fields_enable', '1')) { JHtmlSidebar::addEntry( JText::_('JGLOBAL_FIELDS'), 'index.php?option=com_fields&context=com_content.article', $vName == 'fields.fields' ); JHtmlSidebar::addEntry( JText::_('JGLOBAL_FIELD_GROUPS'), 'index.php?option=com_fields&view=groups&context=com_content.article', $vName == 'fields.groups' ); } } /** * Applies the content tag filters to arbitrary text as per settings for current user group * * @param text $text The string to filter * * @return string The filtered string * * @deprecated 4.0 Use JComponentHelper::filterText() instead. */ public static function filterText($text) { try { JLog::add( sprintf('%s() is deprecated. Use JComponentHelper::filterText() instead', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } return JComponentHelper::filterText($text); } /** * Adds Count Items for Category Manager. * * @param stdClass[] &$items The category objects * * @return stdClass[] * * @since 3.5 */ public static function countItems(&$items) { $config = (object) array( 'related_tbl' => 'content', 'state_col' => 'state', 'group_col' => 'catid', 'relation_type' => 'category_or_group', ); return parent::countRelations($items, $config); } /** * Adds Count Items for Tag Manager. * * @param stdClass[] &$items The tag objects * @param string $extension The name of the active view. * * @return stdClass[] * * @since 3.6 */ public static function countTagItems(&$items, $extension) { $parts = explode('.', $extension); $section = count($parts) > 1 ? $parts[1] : null; $config = (object) array( 'related_tbl' => ($section === 'category' ? 'categories' : 'content'), 'state_col' => ($section === 'category' ? 'published' : 'state'), 'group_col' => 'tag_id', 'extension' => $extension, 'relation_type' => 'tag_assigments', ); return parent::countRelations($items, $config); } /** * Returns a valid section for articles. If it is not valid then null * is returned. * * @param string $section The section to get the mapping for * * @return string|null The new section * * @since 3.7.0 */ public static function validateSection($section) { if (JFactory::getApplication()->isClient('site')) { // On the front end we need to map some sections switch ($section) { // Editing an article case 'form': // Category list view case 'featured': case 'category': $section = 'article'; } } if ($section != 'article') { // We don't know other sections return null; } return $section; } /** * Returns valid contexts * * @return array * * @since 3.7.0 */ public static function getContexts() { JFactory::getLanguage()->load('com_content', JPATH_ADMINISTRATOR); $contexts = array( 'com_content.article' => JText::_('COM_CONTENT'), 'com_content.categories' => JText::_('JCATEGORY') ); return $contexts; } } fields.php 0000604 00000046764 15245567005 0006551 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_fields * * @copyright (C) 2016 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('JFolder', JPATH_LIBRARIES . '/joomla/filesystem/folder.php'); /** * FieldsHelper * * @since 3.7.0 */ class FieldsHelper { private static $fieldsCache = null; private static $fieldCache = null; /** * Extracts the component and section from the context string which has to * be in the format component.context. * * @param string $contextString contextString * @param object $item optional item object * * @return array|null * * @since 3.7.0 */ public static function extract($contextString, $item = null) { $parts = explode('.', $contextString, 2); if (count($parts) < 2) { return null; } $component = $parts[0]; $eName = str_replace('com_', '', $component); $path = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/helpers/' . $eName . '.php'); if (file_exists($path)) { $cName = ucfirst($eName) . 'Helper'; JLoader::register($cName, $path); if (class_exists($cName) && is_callable(array($cName, 'validateSection'))) { $section = call_user_func_array(array($cName, 'validateSection'), array($parts[1], $item)); if ($section) { $parts[1] = $section; } } } return $parts; } /** * Returns the fields for the given context. * If the item is an object the returned fields do have an additional field * "value" which represents the value for the given item. If the item has an * assigned_cat_ids field, then additionally fields which belong to that * category will be returned. * Should the value being prepared to be shown in an HTML context then * prepareValue must be set to true. No further escaping needs to be done. * The values of the fields can be overridden by an associative array where the keys * have to be a name and its corresponding value. * * @param string $context The context of the content passed to the helper * @param stdClass $item item * @param int|bool $prepareValue (if int is display event): 1 - AfterTitle, 2 - BeforeDisplay, 3 - AfterDisplay, 0 - OFF * @param array $valuesToOverride The values to override * * @return array * * @since 3.7.0 */ public static function getFields($context, $item = null, $prepareValue = false, array $valuesToOverride = null) { if (self::$fieldsCache === null) { // Load the model JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_fields/models', 'FieldsModel'); self::$fieldsCache = JModelLegacy::getInstance('Fields', 'FieldsModel', array( 'ignore_request' => true) ); self::$fieldsCache->setState('filter.state', 1); self::$fieldsCache->setState('list.limit', 0); } if (is_array($item)) { $item = (object) $item; } if (JLanguageMultilang::isEnabled() && isset($item->language) && $item->language != '*') { self::$fieldsCache->setState('filter.language', array('*', $item->language)); } self::$fieldsCache->setState('filter.context', $context); self::$fieldsCache->setState('filter.assigned_cat_ids', array()); /* * If item has assigned_cat_ids parameter display only fields which * belong to the category */ if ($item && (isset($item->catid) || isset($item->fieldscatid))) { $assignedCatIds = isset($item->catid) ? $item->catid : $item->fieldscatid; if (!is_array($assignedCatIds)) { $assignedCatIds = explode(',', $assignedCatIds); } // Fields without any category assigned should show as well $assignedCatIds[] = 0; self::$fieldsCache->setState('filter.assigned_cat_ids', $assignedCatIds); } $fields = self::$fieldsCache->getItems(); if ($fields === false) { return array(); } if ($item && isset($item->id)) { if (self::$fieldCache === null) { self::$fieldCache = JModelLegacy::getInstance('Field', 'FieldsModel', array('ignore_request' => true)); } $fieldIds = array_map( function ($f) { return $f->id; }, $fields ); $fieldValues = self::$fieldCache->getFieldValues($fieldIds, $item->id); $new = array(); foreach ($fields as $key => $original) { /* * Doing a clone, otherwise fields for different items will * always reference to the same object */ $field = clone $original; if ($valuesToOverride && key_exists($field->name, $valuesToOverride)) { $field->value = $valuesToOverride[$field->name]; } elseif ($valuesToOverride && key_exists($field->id, $valuesToOverride)) { $field->value = $valuesToOverride[$field->id]; } elseif (key_exists($field->id, $fieldValues)) { $field->value = $fieldValues[$field->id]; } if (!isset($field->value) || $field->value === '') { $field->value = $field->default_value; } $field->rawvalue = $field->value; // If boolean prepare, if int, it is the event type: 1 - After Title, 2 - Before Display, 3 - After Display, 0 - Do not prepare if ($prepareValue && (is_bool($prepareValue) || $prepareValue === (int) $field->params->get('display', '2'))) { JPluginHelper::importPlugin('fields'); $dispatcher = JEventDispatcher::getInstance(); // Event allow plugins to modify the output of the field before it is prepared $dispatcher->trigger('onCustomFieldsBeforePrepareField', array($context, $item, &$field)); // Gathering the value for the field $value = $dispatcher->trigger('onCustomFieldsPrepareField', array($context, $item, &$field)); if (is_array($value)) { $value = implode(' ', $value); } // Event allow plugins to modify the output of the prepared field $dispatcher->trigger('onCustomFieldsAfterPrepareField', array($context, $item, $field, &$value)); // Assign the value $field->value = $value; } $new[$key] = $field; } $fields = $new; } return $fields; } /** * Renders the layout file and data on the context and does a fall back to * Fields afterwards. * * @param string $context The context of the content passed to the helper * @param string $layoutFile layoutFile * @param array $displayData displayData * * @return NULL|string * * @since 3.7.0 */ public static function render($context, $layoutFile, $displayData) { $value = ''; /* * Because the layout refreshes the paths before the render function is * called, so there is no way to load the layout overrides in the order * template -> context -> fields. * If there is no override in the context then we need to call the * layout from Fields. */ if ($parts = self::extract($context)) { // Trying to render the layout on the component from the context $value = JLayoutHelper::render($layoutFile, $displayData, null, array('component' => $parts[0], 'client' => 0)); } if ($value == '') { // Trying to render the layout on Fields itself $value = JLayoutHelper::render($layoutFile, $displayData, null, array('component' => 'com_fields','client' => 0)); } return $value; } /** * PrepareForm * * @param string $context The context of the content passed to the helper * @param JForm $form form * @param object $data data. * * @return boolean * * @since 3.7.0 */ public static function prepareForm($context, JForm $form, $data) { // Extracting the component and section $parts = self::extract($context); if (! $parts) { return true; } $context = $parts[0] . '.' . $parts[1]; // When no fields available return here $fields = self::getFields($parts[0] . '.' . $parts[1], new JObject); if (! $fields) { return true; } $component = $parts[0]; $section = $parts[1]; $assignedCatids = isset($data->catid) ? $data->catid : (isset($data->fieldscatid) ? $data->fieldscatid : $form->getValue('catid')); // Account for case that a submitted form has a multi-value category id field (e.g. a filtering form), just use the first category $assignedCatids = is_array($assignedCatids) ? (int) reset($assignedCatids) : (int) $assignedCatids; if (!$assignedCatids && $formField = $form->getField('catid')) { $assignedCatids = $formField->getAttribute('default', null); // Choose the first category available $xml = new DOMDocument; $xml->loadHTML($formField->__get('input')); $options = $xml->getElementsByTagName('option'); if (!$assignedCatids && $firstChoice = $options->item(0)) { $assignedCatids = $firstChoice->getAttribute('value'); } $data->fieldscatid = $assignedCatids; } /* * If there is a catid field we need to reload the page when the catid * is changed */ if ($form->getField('catid') && $parts[0] != 'com_fields') { /* * Setting the onchange event to reload the page when the category * has changed */ $form->setFieldAttribute('catid', 'onchange', 'categoryHasChanged(this);'); // Preload spindle-wheel when we need to submit form due to category selector changed JFactory::getDocument()->addScriptDeclaration(" function categoryHasChanged(element) { var cat = jQuery(element); if (cat.val() == '" . $assignedCatids . "')return; Joomla.loadingLayer('show'); jQuery('input[name=task]').val('" . $section . ".reload'); Joomla.submitform('" . $section . ".reload', element.form); } jQuery( document ).ready(function() { Joomla.loadingLayer('load'); var formControl = '#" . $form->getFormControl() . "_catid'; if (!jQuery(formControl).val() != '" . $assignedCatids . "'){jQuery(formControl).val('" . $assignedCatids . "');} });" ); } // Getting the fields $fields = self::getFields($parts[0] . '.' . $parts[1], $data); if (!$fields) { return true; } $fieldTypes = self::getFieldTypes(); // Creating the dom $xml = new DOMDocument('1.0', 'UTF-8'); $fieldsNode = $xml->appendChild(new DOMElement('form'))->appendChild(new DOMElement('fields')); $fieldsNode->setAttribute('name', 'com_fields'); // Organizing the fields according to their group $fieldsPerGroup = array(0 => array()); foreach ($fields as $field) { if (!array_key_exists($field->type, $fieldTypes)) { // Field type is not available continue; } if (!array_key_exists($field->group_id, $fieldsPerGroup)) { $fieldsPerGroup[$field->group_id] = array(); } if ($path = $fieldTypes[$field->type]['path']) { // Add the lookup path for the field JFormHelper::addFieldPath($path); } if ($path = $fieldTypes[$field->type]['rules']) { // Add the lookup path for the rule JFormHelper::addRulePath($path); } $fieldsPerGroup[$field->group_id][] = $field; } // On the front, sometimes the admin fields path is not included JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_fields/tables'); $model = JModelLegacy::getInstance('Groups', 'FieldsModel', array('ignore_request' => true)); $model->setState('filter.context', $context); /** * $model->getItems() would only return existing groups, but we also * have the 'default' group with id 0 which is not in the database, * so we create it virtually here. */ $defaultGroup = new \stdClass; $defaultGroup->id = 0; $defaultGroup->title = ''; $defaultGroup->description = ''; $iterateGroups = array_merge(array($defaultGroup), $model->getItems()); // Looping through the groups foreach ($iterateGroups as $group) { if (empty($fieldsPerGroup[$group->id])) { continue; } // Defining the field set /** @var DOMElement $fieldset */ $fieldset = $fieldsNode->appendChild(new DOMElement('fieldset')); $fieldset->setAttribute('name', 'fields-' . $group->id); $fieldset->setAttribute('addfieldpath', '/administrator/components/' . $component . '/models/fields'); $fieldset->setAttribute('addrulepath', '/administrator/components/' . $component . '/models/rules'); $label = $group->title; $description = $group->description; if (!$label) { $key = strtoupper($component . '_FIELDS_' . $section . '_LABEL'); if (!JFactory::getLanguage()->hasKey($key)) { $key = 'JGLOBAL_FIELDS'; } $label = $key; } if (!$description) { $key = strtoupper($component . '_FIELDS_' . $section . '_DESC'); if (JFactory::getLanguage()->hasKey($key)) { $description = $key; } } $fieldset->setAttribute('label', $label); $fieldset->setAttribute('description', strip_tags($description)); // Looping through the fields for that context foreach ($fieldsPerGroup[$group->id] as $field) { try { JFactory::getApplication()->triggerEvent('onCustomFieldsPrepareDom', array($field, $fieldset, $form)); /* * If the field belongs to an assigned_cat_id but the assigned_cat_ids in the data * is not known, set the required flag to false on any circumstance. */ if (!$assignedCatids && !empty($field->assigned_cat_ids) && $form->getField($field->name)) { $form->setFieldAttribute($field->name, 'required', 'false'); } } catch (Exception $e) { JFactory::getApplication()->enqueueMessage($e->getMessage(), 'error'); } } // When the field set is empty, then remove it if (!$fieldset->hasChildNodes()) { $fieldsNode->removeChild($fieldset); } } // Loading the XML fields string into the form $form->load($xml->saveXML()); $model = JModelLegacy::getInstance('Field', 'FieldsModel', array('ignore_request' => true)); if ((!isset($data->id) || !$data->id) && JFactory::getApplication()->input->getCmd('controller') == 'config.display.modules' && JFactory::getApplication()->isClient('site')) { // Modules on front end editing don't have data and an id set $data->id = JFactory::getApplication()->input->getInt('id'); } // Looping through the fields again to set the value if (!isset($data->id) || !$data->id) { return true; } foreach ($fields as $field) { $value = $model->getFieldValue($field->id, $data->id); if ($value === null) { continue; } if (!is_array($value) && $value !== '') { // Function getField doesn't cache the fields, so we try to do it only when necessary $formField = $form->getField($field->name, 'com_fields'); if ($formField && $formField->forceMultiple) { $value = (array) $value; } } // Setting the value on the field $form->setValue($field->name, 'com_fields', $value); } return true; } /** * Return a boolean if the actual logged in user can edit the given field value. * * @param stdClass $field The field * * @return boolean * * @since 3.7.0 */ public static function canEditFieldValue($field) { $parts = self::extract($field->context); return JFactory::getUser()->authorise('core.edit.value', $parts[0] . '.field.' . (int) $field->id); } /** * Return a boolean based on field (and field group) display / show_on settings * * @param stdClass $field The field * * @return boolean * * @since 3.8.7 */ public static function displayFieldOnForm($field) { $app = JFactory::getApplication(); // Detect if the field should be shown at all if ($field->params->get('show_on') == 1 && $app->isClient('administrator')) { return false; } elseif ($field->params->get('show_on') == 2 && $app->isClient('site')) { return false; } if (!self::canEditFieldValue($field)) { $fieldDisplayReadOnly = $field->params->get('display_readonly', '2'); if ($fieldDisplayReadOnly == '2') { // Inherit from field group display read-only setting $groupModel = JModelLegacy::getInstance('Group', 'FieldsModel', array('ignore_request' => true)); $groupDisplayReadOnly = $groupModel->getItem($field->group_id)->params->get('display_readonly', '1'); $fieldDisplayReadOnly = $groupDisplayReadOnly; } if ($fieldDisplayReadOnly == '0') { // Do not display field on form when field is read-only return false; } } // Display field on form return true; } /** * Gets assigned categories titles for a field * * @param stdClass[] $fieldId The field ID * * @return array Array with the assigned categories * * @since 3.7.0 */ public static function getAssignedCategoriesTitles($fieldId) { $fieldId = (int) $fieldId; if (!$fieldId) { return array(); } $db = JFactory::getDbo(); $query = $db->getQuery(true); $query->select($db->quoteName('c.title')) ->from($db->quoteName('#__fields_categories', 'a')) ->join('INNER', $db->quoteName('#__categories', 'c') . ' ON a.category_id = c.id') ->where('field_id = ' . $fieldId); $db->setQuery($query); return $db->loadColumn(); } /** * Gets the fields system plugin extension id. * * @return integer The fields system plugin extension id. * * @since 3.7.0 */ public static function getFieldsPluginId() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) ->where($db->quoteName('element') . ' = ' . $db->quote('fields')); $db->setQuery($query); try { $result = (int) $db->loadResult(); } catch (RuntimeException $e) { JError::raiseWarning(500, $e->getMessage()); $result = 0; } return $result; } /** * Configure the Linkbar. * * @param string $context The context the fields are used for * @param string $vName The view currently active * * @return void * * @since 3.7.0 */ public static function addSubmenu($context, $vName) { $parts = self::extract($context); if (!$parts) { return; } $component = $parts[0]; // Avoid nonsense situation. if ($component == 'com_fields') { return; } // Try to find the component helper. $eName = str_replace('com_', '', $component); $file = JPath::clean(JPATH_ADMINISTRATOR . '/components/' . $component . '/helpers/' . $eName . '.php'); if (!file_exists($file)) { return; } require_once $file; $cName = ucfirst($eName) . 'Helper'; if (class_exists($cName) && is_callable(array($cName, 'addSubmenu'))) { $lang = JFactory::getLanguage(); $lang->load($component, JPATH_ADMINISTRATOR) || $lang->load($component, JPATH_ADMINISTRATOR . '/components/' . $component); $cName::addSubmenu('fields.' . $vName); } } /** * Loads the fields plugins and returns an array of field types from the plugins. * * The returned array contains arrays with the following keys: * - label: The label of the field * - type: The type of the field * - path: The path of the folder where the field can be found * * @return array * * @since 3.7.0 */ public static function getFieldTypes() { JPluginHelper::importPlugin('fields'); $eventData = JEventDispatcher::getInstance()->trigger('onCustomFieldsGetTypes'); $data = array(); foreach ($eventData as $fields) { foreach ($fields as $fieldDescription) { if (!array_key_exists('path', $fieldDescription)) { $fieldDescription['path'] = null; } if (!array_key_exists('rules', $fieldDescription)) { $fieldDescription['rules'] = null; } $data[$fieldDescription['type']] = $fieldDescription; } } return $data; } /** * Clears the internal cache for the custom fields. * * @return void * * @since 3.8.0 */ public static function clearFieldsCache() { self::$fieldCache = null; self::$fieldsCache = null; } } html/contact.php 0000604 00000007427 15245570217 0007672 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_contact * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Utilities\ArrayHelper; JLoader::register('ContactHelper', JPATH_ADMINISTRATOR . '/components/com_contact/helpers/contact.php'); /** * Contact HTML helper class. * * @since 1.6 */ abstract class JHtmlContact { /** * Get the associated language flags * * @param integer $contactid The item id to search associations * * @return string The language HTML * * @throws Exception */ public static function association($contactid) { // Defaults $html = ''; // Get the associations if ($associations = JLanguageAssociations::getAssociations('com_contact', '#__contact_details', 'com_contact.item', $contactid)) { foreach ($associations as $tag => $associated) { $associations[$tag] = (int) $associated->id; } // Get the associated contact items $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('c.id, c.name as title') ->select('l.sef as lang_sef, lang_code') ->from('#__contact_details as c') ->select('cat.title as category_title') ->join('LEFT', '#__categories as cat ON cat.id=c.catid') ->where('c.id IN (' . implode(',', array_values($associations)) . ')') ->where('c.id != ' . $contactid) ->join('LEFT', '#__languages as l ON c.language=l.lang_code') ->select('l.image') ->select('l.title as language_title'); $db->setQuery($query); try { $items = $db->loadObjectList('id'); } catch (RuntimeException $e) { throw new Exception($e->getMessage(), 500, $e); } if ($items) { foreach ($items as &$item) { $text = strtoupper($item->lang_sef); $url = JRoute::_('index.php?option=com_contact&task=contact.edit&id=' . (int) $item->id); $tooltip = htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8') . '<br />' . JText::sprintf('JCATEGORY_SPRINTF', $item->category_title); $classes = 'hasPopover label label-association label-' . $item->lang_sef; $item->link = '<a href="' . $url . '" title="' . $item->language_title . '" class="' . $classes . '" data-content="' . $tooltip . '" data-placement="top">' . $text . '</a>'; } } JHtml::_('bootstrap.popover'); $html = JLayoutHelper::render('joomla.content.associations', $items); } return $html; } /** * Show the featured/not-featured icon. * * @param integer $value The featured value. * @param integer $i Id of the item. * @param boolean $canChange Whether the value can be changed or not. * * @return string The anchor tag to toggle featured/unfeatured contacts. * * @since 1.6 */ public static function featured($value = 0, $i = 0, $canChange = true) { // Array of image, task, title, action $states = array( 0 => array('unfeatured', 'contacts.featured', 'COM_CONTACT_UNFEATURED', 'JGLOBAL_TOGGLE_FEATURED'), 1 => array('featured', 'contacts.unfeatured', 'JFEATURED', 'JGLOBAL_TOGGLE_FEATURED'), ); $state = ArrayHelper::getValue($states, (int) $value, $states[1]); $icon = $state[0]; if ($canChange) { $html = '<a href="#" onclick="return listItemTask(\'cb' . $i . '\',\'' . $state[1] . '\')" class="btn btn-micro hasTooltip' . ($value == 1 ? ' active' : '') . '" title="' . JHtml::_('tooltipText', $state[3]) . '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>'; } else { $html = '<a class="btn btn-micro hasTooltip disabled' . ($value == 1 ? ' active' : '') . '" title="' . JHtml::_('tooltipText', $state[2]) . '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>'; } return $html; } } contact.php 0000604 00000007262 15245570217 0006723 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_contact * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Contact component helper. * * @since 1.6 */ class ContactHelper extends JHelperContent { /** * Configure the Linkbar. * * @param string $vName The name of the active view. * * @return void * * @since 1.6 */ public static function addSubmenu($vName) { JHtmlSidebar::addEntry( JText::_('COM_CONTACT_SUBMENU_CONTACTS'), 'index.php?option=com_contact&view=contacts', $vName == 'contacts' ); JHtmlSidebar::addEntry( JText::_('COM_CONTACT_SUBMENU_CATEGORIES'), 'index.php?option=com_categories&extension=com_contact', $vName == 'categories' ); if (JComponentHelper::isEnabled('com_fields') && JComponentHelper::getParams('com_contact')->get('custom_fields_enable', '1')) { JHtmlSidebar::addEntry( JText::_('JGLOBAL_FIELDS'), 'index.php?option=com_fields&context=com_contact.contact', $vName == 'fields.fields' ); JHtmlSidebar::addEntry( JText::_('JGLOBAL_FIELD_GROUPS'), 'index.php?option=com_fields&view=groups&context=com_contact.contact', $vName == 'fields.groups' ); } } /** * Adds Count Items for Category Manager. * * @param stdClass[] &$items The category objects * * @return stdClass[] * * @since 3.5 */ public static function countItems(&$items) { $config = (object) array( 'related_tbl' => 'contact_details', 'state_col' => 'published', 'group_col' => 'catid', 'relation_type' => 'category_or_group', ); return parent::countRelations($items, $config); } /** * Adds Count Items for Tag Manager. * * @param stdClass[] &$items The tag objects * @param string $extension The name of the active view. * * @return stdClass[] * * @since 3.6 */ public static function countTagItems(&$items, $extension) { $parts = explode('.', $extension); $section = count($parts) > 1 ? $parts[1] : null; $config = (object) array( 'related_tbl' => ($section === 'category' ? 'categories' : 'contact_details'), 'state_col' => 'published', 'group_col' => 'tag_id', 'extension' => $extension, 'relation_type' => 'tag_assigments', ); return parent::countRelations($items, $config); } /** * Returns a valid section for contacts. If it is not valid then null * is returned. * * @param string $section The section to get the mapping for * @param object $item optional item object * * @return string|null The new section * * @since 3.7.0 */ public static function validateSection($section, $item) { if (JFactory::getApplication()->isClient('site') && $section == 'contact' && $item instanceof JForm) { // The contact form needs to be the mail section $section = 'mail'; } if (JFactory::getApplication()->isClient('site') && $section == 'category') { // The contact form needs to be the mail section $section = 'contact'; } if ($section != 'mail' && $section != 'contact') { // We don't know other sections return null; } return $section; } /** * Returns valid contexts * * @return array * * @since 3.7.0 */ public static function getContexts() { JFactory::getLanguage()->load('com_contact', JPATH_ADMINISTRATOR); $contexts = array( 'com_contact.contact' => JText::_('COM_CONTACT_FIELDS_CONTEXT_CONTACT'), 'com_contact.mail' => JText::_('COM_CONTACT_FIELDS_CONTEXT_MAIL'), 'com_contact.categories' => JText::_('JCATEGORY') ); return $contexts; } } html/banner.php 0000604 00000005333 15245570230 0007471 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_banners * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Banner HTML class. * * @since 2.5 */ abstract class JHtmlBanner { /** * Display a batch widget for the client selector. * * @return string The necessary HTML for the widget. * * @since 2.5 */ public static function clients() { JHtml::_('bootstrap.tooltip'); // Create the batch selector to change the client on a selection list. return implode( "\n", array( '<label id="batch-client-lbl" for="batch-client" class="hasTooltip" title="' . JHtml::_('tooltipText', 'COM_BANNERS_BATCH_CLIENT_LABEL', 'COM_BANNERS_BATCH_CLIENT_LABEL_DESC') . '">', JText::_('COM_BANNERS_BATCH_CLIENT_LABEL'), '</label>', '<select name="batch[client_id]" id="batch-client-id">', '<option value="">' . JText::_('COM_BANNERS_BATCH_CLIENT_NOCHANGE') . '</option>', '<option value="0">' . JText::_('COM_BANNERS_NO_CLIENT') . '</option>', JHtml::_('select.options', static::clientlist(), 'value', 'text'), '</select>' ) ); } /** * Method to get the field options. * * @return array The field option objects. * * @since 1.6 */ public static function clientlist() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('id As value, name As text') ->from('#__banner_clients AS a') ->order('a.name'); // Get the options. $db->setQuery($query); try { $options = $db->loadObjectList(); } catch (RuntimeException $e) { JError::raiseWarning(500, $e->getMessage()); } return $options; } /** * Returns a pinned state on a grid * * @param integer $value The state value. * @param integer $i The row index * @param boolean $enabled An optional setting for access control on the action. * @param string $checkbox An optional prefix for checkboxes. * * @return string The Html code * * @see JHtmlJGrid::state * @since 2.5.5 */ public static function pinned($value, $i, $enabled = true, $checkbox = 'cb') { $states = array( 1 => array( 'sticky_unpublish', 'COM_BANNERS_BANNERS_PINNED', 'COM_BANNERS_BANNERS_HTML_PIN_BANNER', 'COM_BANNERS_BANNERS_PINNED', true, 'publish', 'publish' ), 0 => array( 'sticky_publish', 'COM_BANNERS_BANNERS_UNPINNED', 'COM_BANNERS_BANNERS_HTML_UNPIN_BANNER', 'COM_BANNERS_BANNERS_UNPINNED', true, 'unpublish', 'unpublish' ), ); return JHtml::_('jgrid.state', $states, $value, $i, 'banners.', $enabled, true, $checkbox); } } banners.php 0000604 00000011140 15245570230 0006701 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_banners * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Banners component helper. * * @since 1.6 */ class BannersHelper extends JHelperContent { /** * Configure the Linkbar. * * @param string $vName The name of the active view. * * @return void * * @since 1.6 */ public static function addSubmenu($vName) { JHtmlSidebar::addEntry( JText::_('COM_BANNERS_SUBMENU_BANNERS'), 'index.php?option=com_banners&view=banners', $vName == 'banners' ); JHtmlSidebar::addEntry( JText::_('COM_BANNERS_SUBMENU_CATEGORIES'), 'index.php?option=com_categories&extension=com_banners', $vName == 'categories' ); JHtmlSidebar::addEntry( JText::_('COM_BANNERS_SUBMENU_CLIENTS'), 'index.php?option=com_banners&view=clients', $vName == 'clients' ); JHtmlSidebar::addEntry( JText::_('COM_BANNERS_SUBMENU_TRACKS'), 'index.php?option=com_banners&view=tracks', $vName == 'tracks' ); } /** * Update / reset the banners * * @return boolean * * @since 1.6 */ public static function updateReset() { $db = JFactory::getDbo(); $nullDate = $db->getNullDate(); $query = $db->getQuery(true) ->select('*') ->from('#__banners') ->where($db->quote(JFactory::getDate()) . ' >= ' . $db->quote('reset')) ->where($db->quoteName('reset') . ' != ' . $db->quote($nullDate) . ' AND ' . $db->quoteName('reset') . '!= NULL') ->where( '(' . $db->quoteName('checked_out') . ' = 0 OR ' . $db->quoteName('checked_out') . ' = ' . (int) $db->quote(JFactory::getUser()->id) . ')' ); $db->setQuery($query); try { $rows = $db->loadObjectList(); } catch (RuntimeException $e) { JError::raiseWarning(500, $e->getMessage()); return false; } JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables'); foreach ($rows as $row) { $purchaseType = $row->purchase_type; if ($purchaseType < 0 && $row->cid) { /** @var BannersTableClient $client */ $client = JTable::getInstance('Client', 'BannersTable'); $client->load($row->cid); $purchaseType = $client->purchase_type; } if ($purchaseType < 0) { $params = JComponentHelper::getParams('com_banners'); $purchaseType = $params->get('purchase_type'); } switch ($purchaseType) { case 1: $reset = $nullDate; break; case 2: $date = JFactory::getDate('+1 year ' . date('Y-m-d')); $reset = $db->quote($date->toSql()); break; case 3: $date = JFactory::getDate('+1 month ' . date('Y-m-d')); $reset = $db->quote($date->toSql()); break; case 4: $date = JFactory::getDate('+7 day ' . date('Y-m-d')); $reset = $db->quote($date->toSql()); break; case 5: $date = JFactory::getDate('+1 day ' . date('Y-m-d')); $reset = $db->quote($date->toSql()); break; } // Update the row ordering field. $query->clear() ->update($db->quoteName('#__banners')) ->set($db->quoteName('reset') . ' = ' . $db->quote($reset)) ->set($db->quoteName('impmade') . ' = ' . $db->quote(0)) ->set($db->quoteName('clicks') . ' = ' . $db->quote(0)) ->where($db->quoteName('id') . ' = ' . $db->quote($row->id)); $db->setQuery($query); try { $db->execute(); } catch (RuntimeException $e) { JError::raiseWarning(500, $db->getMessage()); return false; } } return true; } /** * Get client list in text/value format for a select field * * @return array */ public static function getClientOptions() { $options = array(); $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('id AS value, name AS text') ->from('#__banner_clients AS a') ->where('a.state = 1') ->order('a.name'); // Get the options. $db->setQuery($query); try { $options = $db->loadObjectList(); } catch (RuntimeException $e) { JError::raiseWarning(500, $e->getMessage()); } array_unshift($options, JHtml::_('select.option', '0', JText::_('COM_BANNERS_NO_CLIENT'))); return $options; } /** * Adds Count Items for Category Manager. * * @param stdClass[] &$items The category objects * * @return stdClass[] * * @since 3.5 */ public static function countItems(&$items) { $config = (object) array( 'related_tbl' => 'banners', 'state_col' => 'state', 'group_col' => 'catid', 'relation_type' => 'category_or_group', ); return parent::countRelations($items, $config); } } html/finder.php 0000604 00000006225 15245570236 0007502 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php'); use Joomla\Utilities\ArrayHelper; /** * HTML behavior class for Finder. * * @since 2.5 */ abstract class JHtmlFinder { /** * Creates a list of types to filter on. * * @return array An array containing the types that can be selected. * * @since 2.5 */ public static function typeslist() { // Load the finder types. $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('DISTINCT t.title AS text, t.id AS value') ->from($db->quoteName('#__finder_types') . ' AS t') ->join('LEFT', $db->quoteName('#__finder_links') . ' AS l ON l.type_id = t.id') ->order('t.title ASC'); $db->setQuery($query); try { $rows = $db->loadObjectList(); } catch (RuntimeException $e) { return array(); } // Compile the options. $options = array(); $lang = JFactory::getLanguage(); foreach ($rows as $row) { $key = $lang->hasKey(FinderHelperLanguage::branchPlural($row->text)) ? FinderHelperLanguage::branchPlural($row->text) : $row->text; $options[] = JHtml::_('select.option', $row->value, JText::sprintf('COM_FINDER_ITEM_X_ONLY', JText::_($key))); } return $options; } /** * Creates a list of maps. * * @return array An array containing the maps that can be selected. * * @since 2.5 */ public static function mapslist() { // Load the finder types. $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('title', 'text')) ->select($db->quoteName('id', 'value')) ->from($db->quoteName('#__finder_taxonomy')) ->where($db->quoteName('parent_id') . ' = 1'); $db->setQuery($query); try { $branches = $db->loadObjectList(); } catch (RuntimeException $e) { JError::raiseWarning(500, $db->getMessage()); } // Translate. $lang = JFactory::getLanguage(); foreach ($branches as $branch) { $key = FinderHelperLanguage::branchPlural($branch->text); $branch->translatedText = $lang->hasKey($key) ? JText::_($key) : $branch->text; } // Order by title. $branches = ArrayHelper::sortObjects($branches, 'translatedText', 1, true, true); // Compile the options. $options = array(); $options[] = JHtml::_('select.option', '', JText::_('COM_FINDER_MAPS_SELECT_BRANCH')); // Convert the values to options. foreach ($branches as $branch) { $options[] = JHtml::_('select.option', $branch->value, $branch->translatedText); } return $options; } /** * Creates a list of published states. * * @return array An array containing the states that can be selected. * * @since 2.5 */ public static function statelist() { return array( JHtml::_('select.option', '1', JText::sprintf('COM_FINDER_ITEM_X_ONLY', JText::_('JPUBLISHED'))), JHtml::_('select.option', '0', JText::sprintf('COM_FINDER_ITEM_X_ONLY', JText::_('JUNPUBLISHED'))) ); } } indexer/indexer.php 0000604 00000034654 15245570236 0010372 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\String\StringHelper; JLoader::register('FinderIndexerHelper', __DIR__ . '/helper.php'); JLoader::register('FinderIndexerParser', __DIR__ . '/parser.php'); JLoader::register('FinderIndexerStemmer', __DIR__ . '/stemmer.php'); JLoader::register('FinderIndexerTaxonomy', __DIR__ . '/taxonomy.php'); JLoader::register('FinderIndexerToken', __DIR__ . '/token.php'); jimport('joomla.filesystem.file'); /** * Main indexer class for the Finder indexer package. * * The indexer class provides the core functionality of the Finder * search engine. It is responsible for adding and updating the * content links table; extracting and scoring tokens; and maintaining * all referential information for the content. * * Note: All exceptions thrown from within this class should be caught * by the controller. * * @since 2.5 */ abstract class FinderIndexer { /** * The title context identifier. * * @var integer * @since 2.5 */ const TITLE_CONTEXT = 1; /** * The text context identifier. * * @var integer * @since 2.5 */ const TEXT_CONTEXT = 2; /** * The meta context identifier. * * @var integer * @since 2.5 */ const META_CONTEXT = 3; /** * The path context identifier. * * @var integer * @since 2.5 */ const PATH_CONTEXT = 4; /** * The misc context identifier. * * @var integer * @since 2.5 */ const MISC_CONTEXT = 5; /** * The indexer state object. * * @var JObject * @since 2.5 */ public static $state; /** * The indexer profiler object. * * @var JProfiler * @since 2.5 */ public static $profiler; /** * Database driver cache. * * @var JDatabaseDriver * @since 3.8.0 */ protected $db; /** * Reusable Query Template. To be used with clone. * * @var JDatabaseQuery * @since 3.8.0 */ protected $addTokensToDbQueryTemplate; /** * FinderIndexer constructor. * * @since 3.8.0 */ public function __construct() { $this->db = JFactory::getDbo(); $db = $this->db; /** * Set up query template for addTokensToDb, we will be cloning this template when needed. * This is about twice as fast as calling the clear function or setting up a new object. */ $this->addTokensToDbQueryTemplate = $db->getQuery(true)->insert($db->quoteName('#__finder_tokens')) ->columns( array( $db->quoteName('term'), $db->quoteName('stem'), $db->quoteName('common'), $db->quoteName('phrase'), $db->quoteName('weight'), $db->quoteName('context'), $db->quoteName('language') ) ); } /** * Returns a reference to the FinderIndexer object. * * @return FinderIndexer instance based on the database driver * * @since 3.0 * @throws RuntimeException if driver class for indexer not present. */ public static function getInstance() { // Setup the adapter for the indexer. $serverType = JFactory::getDbo()->getServerType(); // For `mssql` server types, convert the type to `sqlsrv` if ($serverType === 'mssql') { $serverType = 'sqlsrv'; } $path = __DIR__ . '/driver/' . $serverType . '.php'; $class = 'FinderIndexerDriver' . ucfirst($serverType); // Check if a parser exists for the format. if (file_exists($path)) { // Instantiate the parser. JLoader::register($class, $path); return new $class; } // Throw invalid format exception. throw new RuntimeException(JText::sprintf('COM_FINDER_INDEXER_INVALID_DRIVER', $serverType)); } /** * Method to get the indexer state. * * @return object The indexer state object. * * @since 2.5 */ public static function getState() { // First, try to load from the internal state. if ((bool) static::$state) { return static::$state; } // If we couldn't load from the internal state, try the session. $session = JFactory::getSession(); $data = $session->get('_finder.state', null); // If the state is empty, load the values for the first time. if (empty($data)) { $data = new JObject; // Load the default configuration options. $data->options = JComponentHelper::getParams('com_finder'); // Setup the weight lookup information. $data->weights = array( self::TITLE_CONTEXT => round($data->options->get('title_multiplier', 1.7), 2), self::TEXT_CONTEXT => round($data->options->get('text_multiplier', 0.7), 2), self::META_CONTEXT => round($data->options->get('meta_multiplier', 1.2), 2), self::PATH_CONTEXT => round($data->options->get('path_multiplier', 2.0), 2), self::MISC_CONTEXT => round($data->options->get('misc_multiplier', 0.3), 2) ); // Set the current time as the start time. $data->startTime = JFactory::getDate()->toSql(); // Set the remaining default values. $data->batchSize = (int) $data->options->get('batch_size', 50); $data->batchOffset = 0; $data->totalItems = 0; $data->pluginState = array(); } // Setup the profiler if debugging is enabled. if (JFactory::getApplication()->get('debug')) { static::$profiler = JProfiler::getInstance('FinderIndexer'); } // Setup the stemmer. if ($data->options->get('stem', 1) && $data->options->get('stemmer', 'porter_en')) { FinderIndexerHelper::$stemmer = FinderIndexerStemmer::getInstance($data->options->get('stemmer', 'porter_en')); } // Set the state. static::$state = $data; return static::$state; } /** * Method to set the indexer state. * * @param object $data A new indexer state object. * * @return boolean True on success, false on failure. * * @since 2.5 */ public static function setState($data) { // Check the state object. if (empty($data) || !$data instanceof JObject) { return false; } // Set the new internal state. static::$state = $data; // Set the new session state. JFactory::getSession()->set('_finder.state', $data); return true; } /** * Method to reset the indexer state. * * @return void * * @since 2.5 */ public static function resetState() { // Reset the internal state to null. self::$state = null; // Reset the session state to null. JFactory::getSession()->set('_finder.state', null); } /** * Method to index a content item. * * @param FinderIndexerResult $item The content item to index. * @param string $format The format of the content. [optional] * * @return integer The ID of the record in the links table. * * @since 2.5 * @throws Exception on database error. */ abstract public function index($item, $format = 'html'); /** * Method to remove a link from the index. * * @param integer $linkId The id of the link. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ public function remove($linkId) { $db = $this->db; $query = $db->getQuery(true); // Update the link counts and remove the mapping records. for ($i = 0; $i <= 15; $i++) { // Update the link counts for the terms. $query->clear() ->update($db->quoteName('#__finder_terms', 't')) ->join('INNER', $db->quoteName('#__finder_links_terms' . dechex($i), 'm') . ' ON ' . $db->quoteName('m.term_id') . ' = ' . $db->quoteName('t.term_id') ) ->set($db->quoteName('links') . ' = ' . $db->quoteName('links') . ' - 1') ->where($db->quoteName('m.link_id') . ' = ' . (int) $linkId); $db->setQuery($query)->execute(); // Remove all records from the mapping tables. $query->clear() ->delete($db->quoteName('#__finder_links_terms' . dechex($i))) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); $db->setQuery($query)->execute(); } // Delete all orphaned terms. $query->clear() ->delete($db->quoteName('#__finder_terms')) ->where($db->quoteName('links') . ' <= 0'); $db->setQuery($query)->execute(); // Delete the link from the index. $query->clear() ->delete($db->quoteName('#__finder_links')) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); $db->setQuery($query)->execute(); // Remove the taxonomy maps. FinderIndexerTaxonomy::removeMaps($linkId); // Remove the orphaned taxonomy nodes. FinderIndexerTaxonomy::removeOrphanNodes(); return true; } /** * Method to optimize the index. We use this method to remove unused terms * and any other optimizations that might be necessary. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ abstract public function optimize(); /** * Method to get a content item's signature. * * @param object $item The content item to index. * * @return string The content item's signature. * * @since 2.5 */ protected static function getSignature($item) { // Get the indexer state. $state = static::getState(); // Get the relevant configuration variables. $config = array( $state->weights, $state->options->get('stem', 1), $state->options->get('stemmer', 'porter_en') ); return md5(serialize(array($item, $config))); } /** * Method to parse input, tokenize it, and then add it to the database. * * @param mixed $input String or resource to use as input. A resource input will automatically be chunked to conserve * memory. Strings will be chunked if longer than 2K in size. * @param integer $context The context of the input. See context constants. * @param string $lang The language of the input. * @param string $format The format of the input. * * @return integer The number of tokens extracted from the input. * * @since 2.5 */ protected function tokenizeToDb($input, $context, $lang, $format) { $count = 0; $buffer = null; if (empty($input)) { return $count; } // If the input is a resource, batch the process out. if (is_resource($input)) { // Batch the process out to avoid memory limits. while (!feof($input)) { // Read into the buffer. $buffer .= fread($input, 2048); /* * If we haven't reached the end of the file, seek to the last * space character and drop whatever is after that to make sure * we didn't truncate a term while reading the input. */ if (!feof($input)) { // Find the last space character. $ls = strrpos($buffer, ' '); // Adjust string based on the last space character. if ($ls) { // Truncate the string to the last space character. $string = substr($buffer, 0, $ls); // Adjust the buffer based on the last space for the next iteration and trim. $buffer = StringHelper::trim(substr($buffer, $ls)); } // No space character was found. else { $string = $buffer; } } // We've reached the end of the file, so parse whatever remains. else { $string = $buffer; } // Parse, tokenise and add tokens to the database. $count = $this->tokenizeToDbShort($string, $context, $lang, $format, $count); unset($string, $tokens); } return $count; } // Parse, tokenise and add tokens to the database. $count = $this->tokenizeToDbShort($input, $context, $lang, $format, $count); return $count; } /** * Method to parse input, tokenise it, then add the tokens to the database. * * @param string $input String to parse, tokenise and add to database. * @param integer $context The context of the input. See context constants. * @param string $lang The language of the input. * @param string $format The format of the input. * @param integer $count The number of tokens processed so far. * * @return integer Cumulative number of tokens extracted from the input so far. * * @since 3.7.0 */ private function tokenizeToDbShort($input, $context, $lang, $format, $count) { // Parse the input. $input = FinderIndexerHelper::parse($input, $format); // Check the input. if (empty($input)) { return $count; } // Tokenize the input. $tokens = FinderIndexerHelper::tokenize($input, $lang); // Add the tokens to the database. $count += $this->addTokensToDb($tokens, $context); // Check if we're approaching the memory limit of the token table. if ($count > static::$state->options->get('memory_table_limit', 30000)) { $this->toggleTables(false); } return $count; } /** * Method to add a set of tokens to the database. * * @param mixed $tokens An array or single FinderIndexerToken object. * @param mixed $context The context of the tokens. See context constants. [optional] * * @return integer The number of tokens inserted into the database. * * @since 2.5 * @throws Exception on database error. */ protected function addTokensToDb($tokens, $context = '') { // Get the database object. $db = $this->db; $query = clone $this->addTokensToDbQueryTemplate; // Check if a single FinderIndexerToken object was given and make it to be an array of FinderIndexerToken objects $tokens = is_array($tokens) ? $tokens : array($tokens); // Count the number of token values. $values = 0; // Break into chunks of no more than 1000 items $chunks = array_chunk($tokens, 128); foreach ($chunks as $tokens) { $query->clear('values'); // Iterate through the tokens to create SQL value sets. foreach ($tokens as $token) { $query->values( $db->quote($token->term) . ', ' . $db->quote($token->stem) . ', ' . (int) $token->common . ', ' . (int) $token->phrase . ', ' . $db->escape((float) $token->weight) . ', ' . (int) $context . ', ' . $db->quote($token->language) ); ++$values; } $db->setQuery($query)->execute(); // Check if we're approaching the memory limit of the token table. if ($values > static::$state->options->get('memory_table_limit', 10000)) { $this->toggleTables(false); } } return $values; } /** * Method to switch the token tables from Memory tables to Disk tables * when they are close to running out of memory. * Since this is not supported/implemented in all DB-drivers, the default is a stub method, which simply returns true. * * @param boolean $memory Flag to control how they should be toggled. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ protected function toggleTables($memory) { return true; } } indexer/taxonomy.php 0000604 00000023457 15245570236 0010611 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Stemmer base class for the Finder indexer package. * * @since 2.5 */ class FinderIndexerTaxonomy { /** * An internal cache of taxonomy branch data. * * @var array * @since 2.5 */ public static $branches = array(); /** * An internal cache of taxonomy node data. * * @var array * @since 2.5 */ public static $nodes = array(); /** * Method to add a branch to the taxonomy tree. * * @param string $title The title of the branch. * @param integer $state The published state of the branch. [optional] * @param integer $access The access state of the branch. [optional] * * @return integer The id of the branch. * * @since 2.5 * @throws Exception on database error. */ public static function addBranch($title, $state = 1, $access = 1) { // Check to see if the branch is in the cache. if (isset(static::$branches[$title])) { return static::$branches[$title]->id; } // Check to see if the branch is in the table. $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('*') ->from($db->quoteName('#__finder_taxonomy')) ->where($db->quoteName('parent_id') . ' = 1') ->where($db->quoteName('title') . ' = ' . $db->quote($title)); $db->setQuery($query); // Get the result. $result = $db->loadObject(); // Check if the database matches the input data. if ((bool) $result && $result->state == $state && $result->access == $access) { // The data matches, add the item to the cache. static::$branches[$title] = $result; return static::$branches[$title]->id; } /* * The database did not match the input. This could be because the * state has changed or because the branch does not exist. Let's figure * out which case is true and deal with it. */ $branch = new JObject; if (empty($result)) { // Prepare the branch object. $branch->parent_id = 1; $branch->title = $title; $branch->state = (int) $state; $branch->access = (int) $access; } else { // Prepare the branch object. $branch->id = (int) $result->id; $branch->parent_id = (int) $result->parent_id; $branch->title = $result->title; $branch->state = (int) $result->title; $branch->access = (int) $result->access; $branch->ordering = (int) $result->ordering; } // Store the branch. static::storeNode($branch); // Add the branch to the cache. static::$branches[$title] = $branch; return static::$branches[$title]->id; } /** * Method to add a node to the taxonomy tree. * * @param string $branch The title of the branch to store the node in. * @param string $title The title of the node. * @param integer $state The published state of the node. [optional] * @param integer $access The access state of the node. [optional] * * @return integer The id of the node. * * @since 2.5 * @throws Exception on database error. */ public static function addNode($branch, $title, $state = 1, $access = 1) { // Check to see if the node is in the cache. if (isset(static::$nodes[$branch][$title])) { return static::$nodes[$branch][$title]->id; } // Get the branch id, insert it if it does not exist. $branchId = static::addBranch($branch); // Check to see if the node is in the table. $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('*') ->from($db->quoteName('#__finder_taxonomy')) ->where($db->quoteName('parent_id') . ' = ' . $db->quote($branchId)) ->where($db->quoteName('title') . ' = ' . $db->quote($title)); $db->setQuery($query); // Get the result. $result = $db->loadObject(); // Check if the database matches the input data. if ((bool) $result && $result->state == $state && $result->access == $access) { // The data matches, add the item to the cache. static::$nodes[$branch][$title] = $result; return static::$nodes[$branch][$title]->id; } /* * The database did not match the input. This could be because the * state has changed or because the node does not exist. Let's figure * out which case is true and deal with it. */ $node = new JObject; if (empty($result)) { // Prepare the node object. $node->parent_id = (int) $branchId; $node->title = $title; $node->state = (int) $state; $node->access = (int) $access; } else { // Prepare the node object. $node->id = (int) $result->id; $node->parent_id = (int) $result->parent_id; $node->title = $result->title; $node->state = (int) $result->title; $node->access = (int) $result->access; $node->ordering = (int) $result->ordering; } // Store the node. static::storeNode($node); // Add the node to the cache. static::$nodes[$branch][$title] = $node; return static::$nodes[$branch][$title]->id; } /** * Method to add a map entry between a link and a taxonomy node. * * @param integer $linkId The link to map to. * @param integer $nodeId The node to map to. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ public static function addMap($linkId, $nodeId) { // Insert the map. $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('link_id')) ->from($db->quoteName('#__finder_taxonomy_map')) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId) ->where($db->quoteName('node_id') . ' = ' . (int) $nodeId); $db->setQuery($query); $db->execute(); $id = (int) $db->loadResult(); $map = new JObject; $map->link_id = (int) $linkId; $map->node_id = (int) $nodeId; if ($id) { $db->updateObject('#__finder_taxonomy_map', $map, array('link_id', 'node_id')); } else { $db->insertObject('#__finder_taxonomy_map', $map); } return true; } /** * Method to get the title of all taxonomy branches. * * @return array An array of branch titles. * * @since 2.5 * @throws Exception on database error. */ public static function getBranchTitles() { $db = JFactory::getDbo(); // Set user variables $groups = implode(',', JFactory::getUser()->getAuthorisedViewLevels()); // Create a query to get the taxonomy branch titles. $query = $db->getQuery(true) ->select($db->quoteName('title')) ->from($db->quoteName('#__finder_taxonomy')) ->where($db->quoteName('parent_id') . ' = 1') ->where($db->quoteName('state') . ' = 1') ->where($db->quoteName('access') . ' IN (' . $groups . ')'); // Get the branch titles. $db->setQuery($query); return $db->loadColumn(); } /** * Method to find a taxonomy node in a branch. * * @param string $branch The branch to search. * @param string $title The title of the node. * * @return mixed Integer id on success, null on no match. * * @since 2.5 * @throws Exception on database error. */ public static function getNodeByTitle($branch, $title) { $db = JFactory::getDbo(); // Set user variables $groups = implode(',', JFactory::getUser()->getAuthorisedViewLevels()); // Create a query to get the node. $query = $db->getQuery(true) ->select('t1.*') ->from($db->quoteName('#__finder_taxonomy') . ' AS t1') ->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS t2 ON t2.id = t1.parent_id') ->where('t1.access IN (' . $groups . ')') ->where('t1.state = 1') ->where('t1.title LIKE ' . $db->quote($db->escape($title) . '%')) ->where('t2.access IN (' . $groups . ')') ->where('t2.state = 1') ->where('t2.title = ' . $db->quote($branch)); // Get the node. $db->setQuery($query, 0, 1); return $db->loadObject(); } /** * Method to remove map entries for a link. * * @param integer $linkId The link to remove. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ public static function removeMaps($linkId) { // Delete the maps. $db = JFactory::getDbo(); $query = $db->getQuery(true) ->delete($db->quoteName('#__finder_taxonomy_map')) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); $db->setQuery($query); $db->execute(); return true; } /** * Method to remove orphaned taxonomy nodes and branches. * * @return integer The number of deleted rows. * * @since 2.5 * @throws Exception on database error. */ public static function removeOrphanNodes() { // Delete all orphaned nodes. $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('t.id')) ->from($db->quoteName('#__finder_taxonomy', 't')) ->join('LEFT', $db->quoteName('#__finder_taxonomy_map', 'm') . ' ON ' . $db->quoteName('m.node_id') . '=' . $db->quoteName('t.id')) ->where($db->quoteName('t.parent_id') . ' > 1 ') ->where($db->quoteName('m.link_id') . ' IS NULL'); $db->setQuery($query); $ids = $db->loadColumn(); if (empty($ids)) { return 0; } $query->clear() ->delete($db->quoteName('#__finder_taxonomy')) ->where($db->quoteName('id') . ' IN (' . implode(',', $ids) . ')'); $db->setQuery($query); $db->execute(); return $db->getAffectedRows(); } /** * Method to store a node to the database. This method will accept either a branch or a node. * * @param object $item The item to store. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ protected static function storeNode($item) { $db = JFactory::getDbo(); // Check if we are updating or inserting the item. if (empty($item->id)) { // Insert the item. $db->insertObject('#__finder_taxonomy', $item, 'id'); } else { // Update the item. $db->updateObject('#__finder_taxonomy', $item, 'id'); } return true; } } indexer/query.php 0000604 00000105675 15245570236 0010103 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Registry\Registry; use Joomla\String\StringHelper; use Joomla\Utilities\ArrayHelper; JLoader::register('FinderIndexerHelper', __DIR__ . '/helper.php'); JLoader::register('FinderIndexerTaxonomy', __DIR__ . '/taxonomy.php'); JLoader::register('FinderHelperRoute', JPATH_SITE . '/components/com_finder/helpers/route.php'); JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php'); /** * Query class for the Finder indexer package. * * @since 2.5 */ class FinderIndexerQuery { /** * Flag to show whether the query can return results. * * @var boolean * @since 2.5 */ public $search; /** * The query input string. * * @var string * @since 2.5 */ public $input; /** * The language of the query. * * @var string * @since 2.5 */ public $language; /** * The query string matching mode. * * @var string * @since 2.5 */ public $mode; /** * The included tokens. * * @var array * @since 2.5 */ public $included = array(); /** * The excluded tokens. * * @var array * @since 2.5 */ public $excluded = array(); /** * The tokens to ignore because no matches exist. * * @var array * @since 2.5 */ public $ignored = array(); /** * The operators used in the query input string. * * @var array * @since 2.5 */ public $operators = array(); /** * The terms to highlight as matches. * * @var array * @since 2.5 */ public $highlight = array(); /** * The number of matching terms for the query input. * * @var integer * @since 2.5 */ public $terms; /** * The static filter id. * * @var string * @since 2.5 */ public $filter; /** * The taxonomy filters. This is a multi-dimensional array of taxonomy * branches as the first level and then the taxonomy nodes as the values. * * For example: * $filters = array( * 'Type' = array(10, 32, 29, 11, ...); * 'Label' = array(20, 314, 349, 91, 82, ...); * ... * ); * * @var array * @since 2.5 */ public $filters = array(); /** * The start date filter. * * @var string * @since 2.5 */ public $date1; /** * The end date filter. * * @var string * @since 2.5 */ public $date2; /** * The start date filter modifier. * * @var string * @since 2.5 */ public $when1; /** * The end date filter modifier. * * @var string * @since 2.5 */ public $when2; /** * Method to instantiate the query object. * * @param array $options An array of query options. * * @since 2.5 * @throws Exception on database error. */ public function __construct($options) { // Get the input string. $this->input = isset($options['input']) ? $options['input'] : ''; // Get the empty query setting. $this->empty = isset($options['empty']) ? (bool) $options['empty'] : false; // Get the input language. $this->language = !empty($options['language']) ? $options['language'] : FinderIndexerHelper::getDefaultLanguage(); $this->language = FinderIndexerHelper::getPrimaryLanguage($this->language); // Get the matching mode. $this->mode = 'AND'; // Initialize the temporary date storage. $this->dates = new Registry; // Populate the temporary date storage. if (!empty($options['date1'])) { $this->dates->set('date1', $options['date1']); } if (!empty($options['date2'])) { $this->dates->set('date2', $options['date2']); } if (!empty($options['when1'])) { $this->dates->set('when1', $options['when1']); } if (!empty($options['when2'])) { $this->dates->set('when2', $options['when2']); } // Process the static taxonomy filters. if (!empty($options['filter'])) { $this->processStaticTaxonomy($options['filter']); } // Process the dynamic taxonomy filters. if (!empty($options['filters'])) { $this->processDynamicTaxonomy($options['filters']); } // Get the date filters. $d1 = $this->dates->get('date1'); $d2 = $this->dates->get('date2'); $w1 = $this->dates->get('when1'); $w2 = $this->dates->get('when2'); // Process the date filters. if (!empty($d1) || !empty($d2)) { $this->processDates($d1, $d2, $w1, $w2); } // Process the input string. $this->processString($this->input, $this->language, $this->mode); // Get the number of matching terms. foreach ($this->included as $token) { $this->terms += count($token->matches); } // Remove the temporary date storage. unset($this->dates); // Lastly, determine whether this query can return a result set. // Check if we have a query string. if (!empty($this->input)) { $this->search = true; } // Check if we can search without a query string. elseif ($this->empty && (!empty($this->filter) || !empty($this->filters) || !empty($this->date1) || !empty($this->date2))) { $this->search = true; } // We do not have a valid search query. else { $this->search = false; } } /** * Method to convert the query object into a URI string. * * @param string $base The base URI. [optional] * * @return string The complete query URI. * * @since 2.5 */ public function toUri($base = '') { // Set the base if not specified. if ($base === '') { $base = 'index.php?option=com_finder&view=search'; } // Get the base URI. $uri = JUri::getInstance($base); // Add the static taxonomy filter if present. if ((bool) $this->filter) { $uri->setVar('f', $this->filter); } // Get the filters in the request. $t = JFactory::getApplication()->input->request->get('t', array(), 'array'); // Add the dynamic taxonomy filters if present. if ((bool) $this->filters) { foreach ($this->filters as $nodes) { foreach ($nodes as $node) { if (!in_array($node, $t)) { continue; } $uri->setVar('t[]', $node); } } } // Add the input string if present. if (!empty($this->input)) { $uri->setVar('q', $this->input); } // Add the start date if present. if (!empty($this->date1)) { $uri->setVar('d1', $this->date1); } // Add the end date if present. if (!empty($this->date2)) { $uri->setVar('d2', $this->date2); } // Add the start date modifier if present. if (!empty($this->when1)) { $uri->setVar('w1', $this->when1); } // Add the end date modifier if present. if (!empty($this->when2)) { $uri->setVar('w2', $this->when2); } // Add a menu item id if one is not present. if (!$uri->getVar('Itemid')) { // Get the menu item id. $query = array( 'view' => $uri->getVar('view'), 'f' => $uri->getVar('f'), 'q' => $uri->getVar('q'), ); $item = FinderHelperRoute::getItemid($query); // Add the menu item id if present. if ($item !== null) { $uri->setVar('Itemid', $item); } } return $uri->toString(array('path', 'query')); } /** * Method to get a list of excluded search term ids. * * @return array An array of excluded term ids. * * @since 2.5 */ public function getExcludedTermIds() { $results = array(); // Iterate through the excluded tokens and compile the matching terms. for ($i = 0, $c = count($this->excluded); $i < $c; $i++) { $results = array_merge($results, $this->excluded[$i]->matches); } // Sanitize the terms. $results = array_unique($results); return ArrayHelper::toInteger($results); } /** * Method to get a list of included search term ids. * * @return array An array of included term ids. * * @since 2.5 */ public function getIncludedTermIds() { $results = array(); // Iterate through the included tokens and compile the matching terms. for ($i = 0, $c = count($this->included); $i < $c; $i++) { // Check if we have any terms. if (empty($this->included[$i]->matches)) { continue; } // Get the term. $term = $this->included[$i]->term; // Prepare the container for the term if necessary. if (!array_key_exists($term, $results)) { $results[$term] = array(); } // Add the matches to the stack. $results[$term] = array_merge($results[$term], $this->included[$i]->matches); } // Sanitize the terms. foreach ($results as $key => $value) { $results[$key] = array_unique($results[$key]); $results[$key] = ArrayHelper::toInteger($results[$key]); } return $results; } /** * Method to get a list of required search term ids. * * @return array An array of required term ids. * * @since 2.5 */ public function getRequiredTermIds() { $results = array(); // Iterate through the included tokens and compile the matching terms. for ($i = 0, $c = count($this->included); $i < $c; $i++) { // Check if the token is required. if ($this->included[$i]->required) { // Get the term. $term = $this->included[$i]->term; // Prepare the container for the term if necessary. if (!array_key_exists($term, $results)) { $results[$term] = array(); } // Add the matches to the stack. $results[$term] = array_merge($results[$term], $this->included[$i]->matches); } } // Sanitize the terms. foreach ($results as $key => $value) { $results[$key] = array_unique($results[$key]); $results[$key] = ArrayHelper::toInteger($results[$key]); } return $results; } /** * Method to process the static taxonomy input. The static taxonomy input * comes in the form of a pre-defined search filter that is assigned to the * search form. * * @param integer $filterId The id of static filter. * * @return boolean True on success, false on failure. * * @since 2.5 * @throws Exception on database error. */ protected function processStaticTaxonomy($filterId) { // Get the database object. $db = JFactory::getDbo(); // Initialize user variables $groups = implode(',', JFactory::getUser()->getAuthorisedViewLevels()); // Load the predefined filter. $query = $db->getQuery(true) ->select('f.data, f.params') ->from($db->quoteName('#__finder_filters') . ' AS f') ->where('f.filter_id = ' . (int) $filterId); $db->setQuery($query); $return = $db->loadObject(); // Check the returned filter. if (empty($return)) { return false; } // Set the filter. $this->filter = (int) $filterId; // Get a parameter object for the filter date options. $registry = new Registry($return->params); $params = $registry; // Set the dates if not already set. $this->dates->def('d1', $params->get('d1')); $this->dates->def('d2', $params->get('d2')); $this->dates->def('w1', $params->get('w1')); $this->dates->def('w2', $params->get('w2')); // Remove duplicates and sanitize. $filters = explode(',', $return->data); $filters = array_unique($filters); $filters = ArrayHelper::toInteger($filters); // Remove any values of zero. if (in_array(0, $filters, true) !== false) { unset($filters[array_search(0, $filters, true)]); } // Check if we have any real input. if (empty($filters)) { return true; } /* * Create the query to get filters from the database. We do this for * two reasons: one, it allows us to ensure that the filters being used * are real; two, we need to sort the filters by taxonomy branch. */ $query->clear() ->select('t1.id, t1.title, t2.title AS branch') ->from($db->quoteName('#__finder_taxonomy') . ' AS t1') ->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS t2 ON t2.id = t1.parent_id') ->where('t1.state = 1') ->where('t1.access IN (' . $groups . ')') ->where('t1.id IN (' . implode(',', $filters) . ')') ->where('t2.state = 1') ->where('t2.access IN (' . $groups . ')'); // Load the filters. $db->setQuery($query); $results = $db->loadObjectList(); // Sort the filter ids by branch. foreach ($results as $result) { $this->filters[$result->branch][$result->title] = (int) $result->id; } return true; } /** * Method to process the dynamic taxonomy input. The dynamic taxonomy input * comes in the form of select fields that the user chooses from. The * dynamic taxonomy input is processed AFTER the static taxonomy input * because the dynamic options can be used to further narrow a static * taxonomy filter. * * @param array $filters An array of taxonomy node ids. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ protected function processDynamicTaxonomy($filters) { // Initialize user variables $groups = implode(',', JFactory::getUser()->getAuthorisedViewLevels()); // Remove duplicates and sanitize. $filters = array_unique($filters); $filters = ArrayHelper::toInteger($filters); // Remove any values of zero. if (in_array(0, $filters, true) !== false) { unset($filters[array_search(0, $filters, true)]); } // Check if we have any real input. if (empty($filters)) { return true; } // Get the database object. $db = JFactory::getDbo(); $query = $db->getQuery(true); /* * Create the query to get filters from the database. We do this for * two reasons: one, it allows us to ensure that the filters being used * are real; two, we need to sort the filters by taxonomy branch. */ $query->select('t1.id, t1.title, t2.title AS branch') ->from($db->quoteName('#__finder_taxonomy') . ' AS t1') ->join('INNER', $db->quoteName('#__finder_taxonomy') . ' AS t2 ON t2.id = t1.parent_id') ->where('t1.state = 1') ->where('t1.access IN (' . $groups . ')') ->where('t1.id IN (' . implode(',', $filters) . ')') ->where('t2.state = 1') ->where('t2.access IN (' . $groups . ')'); // Load the filters. $db->setQuery($query); $results = $db->loadObjectList(); // Cleared filter branches. $cleared = array(); /* * Sort the filter ids by branch. Because these filters are designed to * override and further narrow the items selected in the static filter, * we will clear the values from the static filter on a branch by * branch basis before adding the dynamic filters. So, if the static * filter defines a type filter of "articles" and three "category" * filters but the user only limits the category further, the category * filters will be flushed but the type filters will not. */ foreach ($results as $result) { // Check if the branch has been cleared. if (!in_array($result->branch, $cleared, true)) { // Clear the branch. $this->filters[$result->branch] = array(); // Add the branch to the cleared list. $cleared[] = $result->branch; } // Add the filter to the list. $this->filters[$result->branch][$result->title] = (int) $result->id; } return true; } /** * Method to process the query date filters to determine start and end * date limitations. * * @param string $date1 The first date filter. * @param string $date2 The second date filter. * @param string $when1 The first date modifier. * @param string $when2 The second date modifier. * * @return boolean True on success. * * @since 2.5 */ protected function processDates($date1, $date2, $when1, $when2) { // Clean up the inputs. $date1 = trim(StringHelper::strtolower($date1)); $date2 = trim(StringHelper::strtolower($date2)); $when1 = trim(StringHelper::strtolower($when1)); $when2 = trim(StringHelper::strtolower($when2)); // Get the time offset. $offset = JFactory::getApplication()->get('offset'); // Array of allowed when values. $whens = array('before', 'after', 'exact'); // The value of 'today' is a special case that we need to handle. if ($date1 === StringHelper::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY'))) { $date1 = JFactory::getDate('now', $offset)->format('%Y-%m-%d'); } // Try to parse the date string. $date = JFactory::getDate($date1, $offset); // Check if the date was parsed successfully. if ($date->toUnix() !== null) { // Set the date filter. $this->date1 = $date->toSql(); $this->when1 = in_array($when1, $whens, true) ? $when1 : 'before'; } // The value of 'today' is a special case that we need to handle. if ($date2 === StringHelper::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY'))) { $date2 = JFactory::getDate('now', $offset)->format('%Y-%m-%d'); } // Try to parse the date string. $date = JFactory::getDate($date2, $offset); // Check if the date was parsed successfully. if ($date->toUnix() !== null) { // Set the date filter. $this->date2 = $date->toSql(); $this->when2 = in_array($when2, $whens, true) ? $when2 : 'before'; } return true; } /** * Method to process the query input string and extract required, optional, * and excluded tokens; taxonomy filters; and date filters. * * @param string $input The query input string. * @param string $lang The query input language. * @param string $mode The query matching mode. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ protected function processString($input, $lang, $mode) { // Clean up the input string. $input = html_entity_decode($input, ENT_QUOTES, 'UTF-8'); $input = StringHelper::strtolower($input); $input = preg_replace('#\s+#mi', ' ', $input); $input = trim($input); $debug = JFactory::getConfig()->get('debug_lang'); /* * First, we need to handle string based modifiers. String based * modifiers could potentially include things like "category:blah" or * "before:2009-10-21" or "type:article", etc. */ $patterns = array( 'before' => JText::_('COM_FINDER_FILTER_WHEN_BEFORE'), 'after' => JText::_('COM_FINDER_FILTER_WHEN_AFTER'), ); // Add the taxonomy branch titles to the possible patterns. foreach (FinderIndexerTaxonomy::getBranchTitles() as $branch) { // Add the pattern. $patterns[$branch] = StringHelper::strtolower(JText::_(FinderHelperLanguage::branchSingular($branch))); } // Container for search terms and phrases. $terms = array(); $phrases = array(); // Cleared filter branches. $cleared = array(); /* * Compile the suffix pattern. This is used to match the values of the * filter input string. Single words can be input directly, multi-word * values have to be wrapped in double quotes. */ $quotes = html_entity_decode('‘’'', ENT_QUOTES, 'UTF-8'); $suffix = '(([\w\d' . $quotes . '-]+)|\"([\w\d\s' . $quotes . '-]+)\")'; /* * Iterate through the possible filter patterns and search for matches. * We need to match the key, colon, and a value pattern for the match * to be valid. */ foreach ($patterns as $modifier => $pattern) { $matches = array(); if ($debug) { $pattern = substr($pattern, 2, -2); } // Check if the filter pattern is in the input string. if (preg_match('#' . $pattern . '\s*:\s*' . $suffix . '#mi', $input, $matches)) { // Get the value given to the modifier. $value = isset($matches[3]) ? $matches[3] : $matches[1]; // Now we have to handle the filter string. switch ($modifier) { // Handle a before and after date filters. case 'before': case 'after': { // Get the time offset. $offset = JFactory::getApplication()->get('offset'); // Array of allowed when values. $whens = array('before', 'after', 'exact'); // The value of 'today' is a special case that we need to handle. if ($value === StringHelper::strtolower(JText::_('COM_FINDER_QUERY_FILTER_TODAY'))) { $value = JFactory::getDate('now', $offset)->format('%Y-%m-%d'); } // Try to parse the date string. $date = JFactory::getDate($value, $offset); // Check if the date was parsed successfully. if ($date->toUnix() !== null) { // Set the date filter. $this->date1 = $date->toSql(); $this->when1 = in_array($modifier, $whens, true) ? $modifier : 'before'; } break; } // Handle a taxonomy branch filter. default: { // Try to find the node id. $return = FinderIndexerTaxonomy::getNodeByTitle($modifier, $value); // Check if the node id was found. if ($return) { // Check if the branch has been cleared. if (!in_array($modifier, $cleared, true)) { // Clear the branch. $this->filters[$modifier] = array(); // Add the branch to the cleared list. $cleared[] = $modifier; } // Add the filter to the list. $this->filters[$modifier][$return->title] = (int) $return->id; } break; } } // Clean up the input string again. $input = str_replace($matches[0], '', $input); $input = preg_replace('#\s+#mi', ' ', $input); $input = trim($input); } } /* * Extract the tokens enclosed in double quotes so that we can handle * them as phrases. */ if (StringHelper::strpos($input, '"') !== false) { $matches = array(); // Extract the tokens enclosed in double quotes. if (preg_match_all('#\"([^"]+)\"#m', $input, $matches)) { /* * One or more phrases were found so we need to iterate through * them, tokenize them as phrases, and remove them from the raw * input string before we move on to the next processing step. */ foreach ($matches[1] as $key => $match) { // Find the complete phrase in the input string. $pos = StringHelper::strpos($input, $matches[0][$key]); $len = StringHelper::strlen($matches[0][$key]); // Add any terms that are before this phrase to the stack. if (trim(StringHelper::substr($input, 0, $pos))) { $terms = array_merge($terms, explode(' ', trim(StringHelper::substr($input, 0, $pos)))); } // Strip out everything up to and including the phrase. $input = StringHelper::substr($input, $pos + $len); // Clean up the input string again. $input = preg_replace('#\s+#mi', ' ', $input); $input = trim($input); // Get the number of words in the phrase. $parts = explode(' ', $match); // Check if the phrase is longer than three words. if (count($parts) > 3) { /* * If the phrase is longer than three words, we need to * break it down into smaller chunks of phrases that * are less than or equal to three words. We overlap * the chunks so that we can ensure that a match is * found for the complete phrase and not just portions * of it. */ for ($i = 0, $c = count($parts); $i < $c; $i += 2) { // Set up the chunk. $chunk = array(); // The chunk has to be assembled based on how many // pieces are available to use. switch ($c - $i) { /* * If only one word is left, we can break from * the switch and loop because the last word * was already used at the end of the last * chunk. */ case 1: break 2; // If there words are left, we use them both as // the last chunk of the phrase and we're done. case 2: $chunk[] = $parts[$i]; $chunk[] = $parts[$i + 1]; break; // If there are three or more words left, we // build a three word chunk and continue on. default: $chunk[] = $parts[$i]; $chunk[] = $parts[$i + 1]; $chunk[] = $parts[$i + 2]; break; } // If the chunk is not empty, add it as a phrase. if (count($chunk)) { $phrases[] = implode(' ', $chunk); $terms[] = implode(' ', $chunk); } } } else { // The phrase is <= 3 words so we can use it as is. $phrases[] = $match; $terms[] = $match; } } } } // Add the remaining terms if present. if ((bool) $input) { $terms = array_merge($terms, explode(' ', $input)); } // An array of our boolean operators. $operator => $translation $operators = array( 'AND' => StringHelper::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_AND')), 'OR' => StringHelper::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_OR')), 'NOT' => StringHelper::strtolower(JText::_('COM_FINDER_QUERY_OPERATOR_NOT')), ); // If language debugging is enabled you need to ignore the debug strings in matching. if (JDEBUG) { $debugStrings = array('**', '??'); $operators = str_replace($debugStrings, '', $operators); } /* * Iterate through the terms and perform any sorting that needs to be * done based on boolean search operators. Terms that are before an * and/or/not modifier have to be handled in relation to their operator. */ for ($i = 0, $c = count($terms); $i < $c; $i++) { // Check if the term is followed by an operator that we understand. if (isset($terms[$i + 1]) && in_array($terms[$i + 1], $operators, true)) { // Get the operator mode. $op = array_search($terms[$i + 1], $operators, true); // Handle the AND operator. if ($op === 'AND' && isset($terms[$i + 2])) { // Tokenize the current term. $token = FinderIndexerHelper::tokenize($terms[$i], $lang, true); // Todo: The previous function call may return an array, which seems not to be handled by the next one, which expects an object $token = $this->getTokenData($token); // Set the required flag. $token->required = true; // Add the current token to the stack. $this->included[] = $token; $this->highlight = array_merge($this->highlight, array_keys($token->matches)); // Skip the next token (the mode operator). $this->operators[] = $terms[$i + 1]; // Tokenize the term after the next term (current plus two). $other = FinderIndexerHelper::tokenize($terms[$i + 2], $lang, true); $other = $this->getTokenData($other); // Set the required flag. $other->required = true; // Add the token after the next token to the stack. $this->included[] = $other; $this->highlight = array_merge($this->highlight, array_keys($other->matches)); // Remove the processed phrases if possible. if (($pk = array_search($terms[$i], $phrases, true)) !== false) { unset($phrases[$pk]); } if (($pk = array_search($terms[$i + 2], $phrases, true)) !== false) { unset($phrases[$pk]); } // Remove the processed terms. unset($terms[$i], $terms[$i + 1], $terms[$i + 2]); // Adjust the loop. $i += 2; continue; } // Handle the OR operator. elseif ($op === 'OR' && isset($terms[$i + 2])) { // Tokenize the current term. $token = FinderIndexerHelper::tokenize($terms[$i], $lang, true); $token = $this->getTokenData($token); // Set the required flag. $token->required = false; // Add the current token to the stack. if ((bool) $token->matches) { $this->included[] = $token; $this->highlight = array_merge($this->highlight, array_keys($token->matches)); } else { $this->ignored[] = $token; } // Skip the next token (the mode operator). $this->operators[] = $terms[$i + 1]; // Tokenize the term after the next term (current plus two). $other = FinderIndexerHelper::tokenize($terms[$i + 2], $lang, true); $other = $this->getTokenData($other); // Set the required flag. $other->required = false; // Add the token after the next token to the stack. if ((bool) $other->matches) { $this->included[] = $other; $this->highlight = array_merge($this->highlight, array_keys($other->matches)); } else { $this->ignored[] = $other; } // Remove the processed phrases if possible. if (($pk = array_search($terms[$i], $phrases, true)) !== false) { unset($phrases[$pk]); } if (($pk = array_search($terms[$i + 2], $phrases, true)) !== false) { unset($phrases[$pk]); } // Remove the processed terms. unset($terms[$i], $terms[$i + 1], $terms[$i + 2]); // Adjust the loop. $i += 2; continue; } } // Handle an orphaned OR operator. elseif (isset($terms[$i + 1]) && array_search($terms[$i], $operators, true) === 'OR') { // Skip the next token (the mode operator). $this->operators[] = $terms[$i]; // Tokenize the next term (current plus one). $other = FinderIndexerHelper::tokenize($terms[$i + 1], $lang, true); $other = $this->getTokenData($other); // Set the required flag. $other->required = false; // Add the token after the next token to the stack. if ((bool) $other->matches) { $this->included[] = $other; $this->highlight = array_merge($this->highlight, array_keys($other->matches)); } else { $this->ignored[] = $other; } // Remove the processed phrase if possible. if (($pk = array_search($terms[$i + 1], $phrases, true)) !== false) { unset($phrases[$pk]); } // Remove the processed terms. unset($terms[$i], $terms[$i + 1]); // Adjust the loop. $i++; continue; } // Handle the NOT operator. elseif (isset($terms[$i + 1]) && array_search($terms[$i], $operators, true) === 'NOT') { // Skip the next token (the mode operator). $this->operators[] = $terms[$i]; // Tokenize the next term (current plus one). $other = FinderIndexerHelper::tokenize($terms[$i + 1], $lang, true); $other = $this->getTokenData($other); // Set the required flag. $other->required = false; // Add the next token to the stack. if ((bool) $other->matches) { $this->excluded[] = $other; } else { $this->ignored[] = $other; } // Remove the processed phrase if possible. if (($pk = array_search($terms[$i + 1], $phrases, true)) !== false) { unset($phrases[$pk]); } // Remove the processed terms. unset($terms[$i], $terms[$i + 1]); // Adjust the loop. $i++; continue; } } /* * Iterate through any search phrases and tokenize them. We handle * phrases as autonomous units and do not break them down into two and * three word combinations. */ for ($i = 0, $c = count($phrases); $i < $c; $i++) { // Tokenize the phrase. $token = FinderIndexerHelper::tokenize($phrases[$i], $lang, true); $token = $this->getTokenData($token); // Set the required flag. $token->required = true; // Add the current token to the stack. $this->included[] = $token; $this->highlight = array_merge($this->highlight, array_keys($token->matches)); // Remove the processed term if possible. if (($pk = array_search($phrases[$i], $terms, true)) !== false) { unset($terms[$pk]); } // Remove the processed phrase. unset($phrases[$i]); } /* * Handle any remaining tokens using the standard processing mechanism. */ if ((bool) $terms) { // Tokenize the terms. $terms = implode(' ', $terms); $tokens = FinderIndexerHelper::tokenize($terms, $lang, false); // Make sure we are working with an array. $tokens = is_array($tokens) ? $tokens : array($tokens); // Get the token data and required state for all the tokens. foreach ($tokens as $token) { // Get the token data. $token = $this->getTokenData($token); // Set the required flag for the token. $token->required = $mode === 'AND' ? (!$token->phrase) : false; // Add the token to the appropriate stack. if ($token->required || (bool) $token->matches) { $this->included[] = $token; $this->highlight = array_merge($this->highlight, array_keys($token->matches)); } else { $this->ignored[] = $token; } } } return true; } /** * Method to get the base and similar term ids and, if necessary, suggested * term data from the database. The terms ids are identified based on a * 'like' match in MySQL and/or a common stem. If no term ids could be * found, then we know that we will not be able to return any results for * that term and we should try to find a similar term to use that we can * match so that we can suggest the alternative search query to the user. * * @param FinderIndexerToken $token A FinderIndexerToken object. * * @return FinderIndexerToken A FinderIndexerToken object. * * @since 2.5 * @throws Exception on database error. */ protected function getTokenData($token) { // Get the database object. $db = JFactory::getDbo(); // Create a database query to build match the token. $query = $db->getQuery(true) ->select('t.term, t.term_id') ->from('#__finder_terms AS t'); /* * If the token is a phrase, the lookup process is fairly simple. If * the token is a word, it is a little more complicated. We have to * create two queries to lookup the term and the stem respectively, * then union the result sets together. This is MUCH faster than using * an or condition in the database query. */ if ($token->phrase) { // Add the phrase to the query. $query->where('t.term = ' . $db->quote($token->term)) ->where('t.phrase = 1'); } else { // Add the term to the query. $query->where('t.term = ' . $db->quote($token->term)) ->where('t.phrase = 0'); // Clone the query, replace the WHERE clause. $sub = clone $query; $sub->clear('where'); $sub->where('t.stem = ' . $db->quote($token->stem)); $sub->where('t.phrase = 0'); // Union the two queries. $query->union($sub); } // Get the terms. $db->setQuery($query); $matches = $db->loadObjectList(); // Check the matching terms. if ((bool) $matches) { // Add the matches to the token. for ($i = 0, $c = count($matches); $i < $c; $i++) { $token->matches[$matches[$i]->term] = (int) $matches[$i]->term_id; } } // If no matches were found, try to find a similar but better token. if (empty($token->matches)) { // Create a database query to get the similar terms. // TODO: PostgreSQL doesn't support SOUNDEX out of the box $query->clear() ->select('DISTINCT t.term_id AS id, t.term AS term') ->from('#__finder_terms AS t') // ->where('t.soundex = ' . soundex($db->quote($token->term))) ->where('t.soundex = SOUNDEX(' . $db->quote($token->term) . ')') ->where('t.phrase = ' . (int) $token->phrase); // Get the terms. $db->setQuery($query); $results = $db->loadObjectList(); // Check if any similar terms were found. if (empty($results)) { return $token; } // Stack for sorting the similar terms. $suggestions = array(); // Get the levnshtein distance for all suggested terms. foreach ($results as $sk => $st) { // Get the levenshtein distance between terms. $distance = levenshtein($st->term, $token->term); // Make sure the levenshtein distance isn't over 50. if ($distance < 50) { $suggestions[$sk] = $distance; } } // Sort the suggestions. asort($suggestions, SORT_NUMERIC); // Get the closest match. $keys = array_keys($suggestions); $key = $keys[0]; // Add the suggested term. $token->suggestion = $results[$key]->term; } return $token; } } indexer/driver/mysql.php 0000604 00000046020 15245570236 0011362 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; jimport('joomla.filesystem.file'); /** * Indexer class supporting MySQL(i) for the Finder indexer package. * * The indexer class provides the core functionality of the Finder * search engine. It is responsible for adding and updating the * content links table; extracting and scoring tokens; and maintaining * all referential information for the content. * * Note: All exceptions thrown from within this class should be caught * by the controller. * * @since 3.0 */ class FinderIndexerDriverMysql extends FinderIndexer { /** * Method to index a content item. * * @param FinderIndexerResult $item The content item to index. * @param string $format The format of the content. [optional] * * @return integer The ID of the record in the links table. * * @since 3.0 * @throws Exception on database error. */ public function index($item, $format = 'html') { // Mark beforeIndexing in the profiler. static::$profiler ? static::$profiler->mark('beforeIndexing') : null; $db = $this->db; $nd = $db->getNullDate(); // Check if the item is in the database. $query = $db->getQuery(true) ->select($db->quoteName('link_id') . ', ' . $db->quoteName('md5sum')) ->from($db->quoteName('#__finder_links')) ->where($db->quoteName('url') . ' = ' . $db->quote($item->url)); // Load the item from the database. $db->setQuery($query); $link = $db->loadObject(); // Get the indexer state. $state = static::getState(); // Get the signatures of the item. $curSig = static::getSignature($item); $oldSig = isset($link->md5sum) ? $link->md5sum : null; // Get the other item information. $linkId = empty($link->link_id) ? null : $link->link_id; $isNew = empty($link->link_id) ? true : false; // Check the signatures. If they match, the item is up to date. if (!$isNew && $curSig == $oldSig) { return $linkId; } /* * If the link already exists, flush all the term maps for the item. * Maps are stored in 16 tables so we need to iterate through and flush * each table one at a time. */ if (!$isNew) { for ($i = 0; $i <= 15; $i++) { // Flush the maps for the link. $query->clear() ->delete($db->quoteName('#__finder_links_terms' . dechex($i))) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); $db->setQuery($query); $db->execute(); } // Remove the taxonomy maps. FinderIndexerTaxonomy::removeMaps($linkId); } // Mark afterUnmapping in the profiler. static::$profiler ? static::$profiler->mark('afterUnmapping') : null; // Perform cleanup on the item data. $item->publish_start_date = (int) $item->publish_start_date != 0 ? $item->publish_start_date : $nd; $item->publish_end_date = (int) $item->publish_end_date != 0 ? $item->publish_end_date : $nd; $item->start_date = (int) $item->start_date != 0 ? $item->start_date : $nd; $item->end_date = (int) $item->end_date != 0 ? $item->end_date : $nd; // Prepare the item description. $item->description = FinderIndexerHelper::parse($item->summary); /* * Now, we need to enter the item into the links table. If the item * already exists in the database, we need to use an UPDATE query. * Otherwise, we need to use an INSERT to get the link id back. */ if ($isNew) { $columnsArray = array( $db->quoteName('url'), $db->quoteName('route'), $db->quoteName('title'), $db->quoteName('description'), $db->quoteName('indexdate'), $db->quoteName('published'), $db->quoteName('state'), $db->quoteName('access'), $db->quoteName('language'), $db->quoteName('type_id'), $db->quoteName('object'), $db->quoteName('publish_start_date'), $db->quoteName('publish_end_date'), $db->quoteName('start_date'), $db->quoteName('end_date'), $db->quoteName('list_price'), $db->quoteName('sale_price') ); // Insert the link. $query->clear() ->insert($db->quoteName('#__finder_links')) ->columns($columnsArray) ->values( $db->quote($item->url) . ', ' . $db->quote($item->route) . ', ' . $db->quote($item->title) . ', ' . $db->quote($item->description) . ', ' . $query->currentTimestamp() . ', ' . '1, ' . (int) $item->state . ', ' . (int) $item->access . ', ' . $db->quote($item->language) . ', ' . (int) $item->type_id . ', ' . $db->quote(serialize($item)) . ', ' . $db->quote($item->publish_start_date) . ', ' . $db->quote($item->publish_end_date) . ', ' . $db->quote($item->start_date) . ', ' . $db->quote($item->end_date) . ', ' . (double) ($item->list_price ?: 0) . ', ' . (double) ($item->sale_price ?: 0) ); $db->setQuery($query); $db->execute(); // Get the link id. $linkId = (int) $db->insertid(); } else { // Update the link. $query->clear() ->update($db->quoteName('#__finder_links')) ->set($db->quoteName('route') . ' = ' . $db->quote($item->route)) ->set($db->quoteName('title') . ' = ' . $db->quote($item->title)) ->set($db->quoteName('description') . ' = ' . $db->quote($item->description)) ->set($db->quoteName('indexdate') . ' = ' . $query->currentTimestamp()) ->set($db->quoteName('state') . ' = ' . (int) $item->state) ->set($db->quoteName('access') . ' = ' . (int) $item->access) ->set($db->quoteName('language') . ' = ' . $db->quote($item->language)) ->set($db->quoteName('type_id') . ' = ' . (int) $item->type_id) ->set($db->quoteName('object') . ' = ' . $db->quote(serialize($item))) ->set($db->quoteName('publish_start_date') . ' = ' . $db->quote($item->publish_start_date)) ->set($db->quoteName('publish_end_date') . ' = ' . $db->quote($item->publish_end_date)) ->set($db->quoteName('start_date') . ' = ' . $db->quote($item->start_date)) ->set($db->quoteName('end_date') . ' = ' . $db->quote($item->end_date)) ->set($db->quoteName('list_price') . ' = ' . (double) ($item->list_price ?: 0)) ->set($db->quoteName('sale_price') . ' = ' . (double) ($item->sale_price ?: 0)) ->where('link_id = ' . (int) $linkId); $db->setQuery($query); $db->execute(); } // Set up the variables we will need during processing. $count = 0; // Mark afterLinking in the profiler. static::$profiler ? static::$profiler->mark('afterLinking') : null; // Truncate the tokens tables. $db->truncateTable('#__finder_tokens'); // Truncate the tokens aggregate table. $db->truncateTable('#__finder_tokens_aggregate'); /* * Process the item's content. The items can customize their * processing instructions to define extra properties to process * or rearrange how properties are weighted. */ foreach ($item->getInstructions() as $group => $properties) { // Iterate through the properties of the group. foreach ($properties as $property) { // Check if the property exists in the item. if (empty($item->$property)) { continue; } // Tokenize the property. if (is_array($item->$property)) { // Tokenize an array of content and add it to the database. foreach ($item->$property as $ip) { /* * If the group is path, we need to a few extra processing * steps to strip the extension and convert slashes and dashes * to spaces. */ if ($group === static::PATH_CONTEXT) { $ip = JFile::stripExt($ip); $ip = str_replace(array('/', '-'), ' ', $ip); } // Tokenize a string of content and add it to the database. $count += $this->tokenizeToDb($ip, $group, $item->language, $format); // Check if we're approaching the memory limit of the token table. if ($count > static::$state->options->get('memory_table_limit', 30000)) { $this->toggleTables(false); } } } else { /* * If the group is path, we need to a few extra processing * steps to strip the extension and convert slashes and dashes * to spaces. */ if ($group === static::PATH_CONTEXT) { $item->$property = JFile::stripExt($item->$property); $item->$property = str_replace('/', ' ', $item->$property); $item->$property = str_replace('-', ' ', $item->$property); } // Tokenize a string of content and add it to the database. $count += $this->tokenizeToDb($item->$property, $group, $item->language, $format); // Check if we're approaching the memory limit of the token table. if ($count > static::$state->options->get('memory_table_limit', 30000)) { $this->toggleTables(false); } } } } /* * Process the item's taxonomy. The items can customize their * taxonomy mappings to define extra properties to map. */ foreach ($item->getTaxonomy() as $branch => $nodes) { // Iterate through the nodes and map them to the branch. foreach ($nodes as $node) { // Add the node to the tree. $nodeId = FinderIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access); // Add the link => node map. FinderIndexerTaxonomy::addMap($linkId, $nodeId); } } // Mark afterProcessing in the profiler. static::$profiler ? static::$profiler->mark('afterProcessing') : null; /* * At this point, all of the item's content has been parsed, tokenized * and inserted into the #__finder_tokens table. Now, we need to * aggregate all the data into that table into a more usable form. The * aggregated data will be inserted into #__finder_tokens_aggregate * table. */ $query = 'INSERT INTO ' . $db->quoteName('#__finder_tokens_aggregate') . ' (' . $db->quoteName('term_id') . ', ' . $db->quoteName('map_suffix') . ', ' . $db->quoteName('term') . ', ' . $db->quoteName('stem') . ', ' . $db->quoteName('common') . ', ' . $db->quoteName('phrase') . ', ' . $db->quoteName('term_weight') . ', ' . $db->quoteName('context') . ', ' . $db->quoteName('context_weight') . ', ' . $db->quoteName('total_weight') . ', ' . $db->quoteName('language') . ')' . ' SELECT' . ' COALESCE(t.term_id, 0), \'\', t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context,' . ' ROUND( t1.weight * COUNT( t2.term ) * %F, 8 ) AS context_weight, 0, t1.language' . ' FROM (' . ' SELECT DISTINCT t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' . ' FROM ' . $db->quoteName('#__finder_tokens') . ' AS t1' . ' WHERE t1.context = %d' . ' ) AS t1' . ' JOIN ' . $db->quoteName('#__finder_tokens') . ' AS t2 ON t2.term = t1.term' . ' LEFT JOIN ' . $db->quoteName('#__finder_terms') . ' AS t ON t.term = t1.term' . ' WHERE t2.context = %d' . ' GROUP BY t1.term, t.term_id, t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' . ' ORDER BY t1.term DESC'; // Iterate through the contexts and aggregate the tokens per context. foreach ($state->weights as $context => $multiplier) { // Run the query to aggregate the tokens for this context.. $db->setQuery(sprintf($query, $multiplier, $context, $context)); $db->execute(); } // Mark afterAggregating in the profiler. static::$profiler ? static::$profiler->mark('afterAggregating') : null; /* * When we pulled down all of the aggregate data, we did a LEFT JOIN * over the terms table to try to find all the term ids that * already exist for our tokens. If any of the rows in the aggregate * table have a term of 0, then no term record exists for that * term so we need to add it to the terms table. */ $db->setQuery( 'INSERT IGNORE INTO ' . $db->quoteName('#__finder_terms') . ' (' . $db->quoteName('term') . ', ' . $db->quoteName('stem') . ', ' . $db->quoteName('common') . ', ' . $db->quoteName('phrase') . ', ' . $db->quoteName('weight') . ', ' . $db->quoteName('soundex') . ', ' . $db->quoteName('language') . ')' . ' SELECT ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language' . ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' AS ta' . ' WHERE ta.term_id = 0' . ' GROUP BY ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language' ); $db->execute(); /* * Now, we just inserted a bunch of new records into the terms table * so we need to go back and update the aggregate table with all the * new term ids. */ $query = $db->getQuery(true) ->update($db->quoteName('#__finder_tokens_aggregate') . ' AS ta') ->join('INNER', $db->quoteName('#__finder_terms') . ' AS t ON t.term = ta.term') ->set('ta.term_id = t.term_id') ->where('ta.term_id = 0'); $db->setQuery($query); $db->execute(); // Mark afterTerms in the profiler. static::$profiler ? static::$profiler->mark('afterTerms') : null; /* * After we've made sure that all of the terms are in the terms table * and the aggregate table has the correct term ids, we need to update * the links counter for each term by one. */ $query->clear() ->update($db->quoteName('#__finder_terms') . ' AS t') ->join('INNER', $db->quoteName('#__finder_tokens_aggregate') . ' AS ta ON ta.term_id = t.term_id') ->set('t.' . $db->quoteName('links') . ' = t.links + 1'); $db->setQuery($query); $db->execute(); // Mark afterTerms in the profiler. static::$profiler ? static::$profiler->mark('afterTerms') : null; /* * Before we can insert all of the mapping rows, we have to figure out * which mapping table the rows need to be inserted into. The mapping * table for each term is based on the first character of the md5 of * the first character of the term. In php, it would be expressed as * substr(md5(substr($token, 0, 1)), 0, 1) */ $query->clear() ->update($db->quoteName('#__finder_tokens_aggregate')) ->set($db->quoteName('map_suffix') . ' = SUBSTR(MD5(SUBSTR(' . $db->quoteName('term') . ', 1, 1)), 1, 1)'); $db->setQuery($query); $db->execute(); /* * At this point, the aggregate table contains a record for each * term in each context. So, we're going to pull down all of that * data while grouping the records by term and add all of the * sub-totals together to arrive at the final total for each token for * this link. Then, we insert all of that data into the appropriate * mapping table. */ for ($i = 0; $i <= 15; $i++) { // Get the mapping table suffix. $suffix = dechex($i); /* * We have to run this query 16 times, one for each link => term * mapping table. */ $db->setQuery( 'INSERT INTO ' . $db->quoteName('#__finder_links_terms' . $suffix) . ' (' . $db->quoteName('link_id') . ', ' . $db->quoteName('term_id') . ', ' . $db->quoteName('weight') . ')' . ' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' . ' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' . ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' WHERE ' . $db->quoteName('map_suffix') . ' = ' . $db->quote($suffix) . ' GROUP BY ' . $db->quoteName('term') . ', ' . $db->quoteName('term_id') . ' ORDER BY ' . $db->quoteName('term') . ' DESC' ); $db->execute(); } // Mark afterMapping in the profiler. static::$profiler ? static::$profiler->mark('afterMapping') : null; // Update the signature. $object = serialize($item); $query->clear() ->update($db->quoteName('#__finder_links')) ->set($db->quoteName('md5sum') . ' = ' . $db->quote($curSig)) ->set($db->quoteName('object') . ' = ' . $db->quote($object)) ->where($db->quoteName('link_id') . ' = ' . $db->quote($linkId)); $db->setQuery($query); $db->execute(); // Mark afterSigning in the profiler. static::$profiler ? static::$profiler->mark('afterSigning') : null; // Truncate the tokens tables. $db->truncateTable('#__finder_tokens'); // Truncate the tokens aggregate table. $db->truncateTable('#__finder_tokens_aggregate'); // Toggle the token tables back to memory tables. $this->toggleTables(true); // Mark afterTruncating in the profiler. static::$profiler ? static::$profiler->mark('afterTruncating') : null; return $linkId; } /** * Method to optimize the index. We use this method to remove unused terms * and any other optimizations that might be necessary. * * @return boolean True on success. * * @since 3.0 * @throws Exception on database error. */ public function optimize() { // Get the database object. $db = $this->db; $query = $db->getQuery(true); // Delete all orphaned terms. $query->delete($db->quoteName('#__finder_terms')) ->where($db->quoteName('links') . ' <= 0'); $db->setQuery($query); $db->execute(); // Optimize the links table. $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_links')); $db->execute(); for ($i = 0; $i <= 15; $i++) { // Optimize the terms mapping table. $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_links_terms' . dechex($i))); $db->execute(); } // Optimize the filters table. $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_filters')); $db->execute(); // Optimize the terms common table. $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_terms_common')); $db->execute(); // Optimize the types table. $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_types')); $db->execute(); // Remove the orphaned taxonomy nodes. FinderIndexerTaxonomy::removeOrphanNodes(); // Optimize the taxonomy mapping table. $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_taxonomy_map')); $db->execute(); // Optimize the taxonomy table. $db->setQuery('OPTIMIZE TABLE ' . $db->quoteName('#__finder_taxonomy')); $db->execute(); return true; } /** * Method to switch the token tables from Memory tables to MyISAM tables * when they are close to running out of memory. * * @param boolean $memory Flag to control how they should be toggled. * * @return boolean True on success. * * @since 3.0 * @throws Exception on database error. */ protected function toggleTables($memory) { static $state; // Get the database adapter. $db = $this->db; // Check if we are setting the tables to the Memory engine. if ($memory === true && $state !== true) { // Set the tokens table to Memory. $db->setQuery('ALTER TABLE ' . $db->quoteName('#__finder_tokens') . ' ENGINE = MEMORY'); $db->execute(); // Set the tokens aggregate table to Memory. $db->setQuery('ALTER TABLE ' . $db->quoteName('#__finder_tokens_aggregate') . ' ENGINE = MEMORY'); $db->execute(); // Set the internal state. $state = $memory; } // We must be setting the tables to the MyISAM engine. elseif ($memory === false && $state !== false) { // Set the tokens table to MyISAM. $db->setQuery('ALTER TABLE ' . $db->quoteName('#__finder_tokens') . ' ENGINE = MYISAM'); $db->execute(); // Set the tokens aggregate table to MyISAM. $db->setQuery('ALTER TABLE ' . $db->quoteName('#__finder_tokens_aggregate') . ' ENGINE = MYISAM'); $db->execute(); // Set the internal state. $state = $memory; } return true; } } indexer/driver/postgresql.php 0000604 00000037550 15245570236 0012430 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Factory; use Joomla\String\StringHelper; jimport('joomla.filesystem.file'); /** * Indexer class supporting PostgreSQL for the Finder indexer package. * * @since 3.0 */ class FinderIndexerDriverPostgresql extends FinderIndexer { /** * Method to index a content item. * * @param FinderIndexerResult $item The content item to index. * @param string $format The format of the content. [optional] * * @return integer The ID of the record in the links table. * * @since 3.0 * @throws Exception on database error. */ public function index($item, $format = 'html') { // Mark beforeIndexing in the profiler. static::$profiler ? static::$profiler->mark('beforeIndexing') : null; $db = $this->db; $nd = $db->getNullDate(); // Check if the item is in the database. $query = $db->getQuery(true) ->select($db->quoteName('link_id') . ', ' . $db->quoteName('md5sum')) ->from($db->quoteName('#__finder_links')) ->where($db->quoteName('url') . ' = ' . $db->quote($item->url)); // Load the item from the database. $db->setQuery($query); $link = $db->loadObject(); // Get the indexer state. $state = static::getState(); // Get the signatures of the item. $curSig = static::getSignature($item); $oldSig = isset($link->md5sum) ? $link->md5sum : null; // Get the other item information. $linkId = empty($link->link_id) ? null : $link->link_id; $isNew = empty($link->link_id) ? true : false; // Check the signatures. If they match, the item is up to date. if (!$isNew && $curSig === $oldSig) { return $linkId; } /* * If the link already exists, flush all the term maps for the item. * Maps are stored in 16 tables so we need to iterate through and flush * each table one at a time. */ if (!$isNew) { for ($i = 0; $i <= 15; $i++) { // Flush the maps for the link. $query->clear() ->delete($db->quoteName('#__finder_links_terms' . dechex($i))) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); $db->setQuery($query); $db->execute(); } // Remove the taxonomy maps. FinderIndexerTaxonomy::removeMaps($linkId); } // Mark afterUnmapping in the profiler. static::$profiler ? static::$profiler->mark('afterUnmapping') : null; // Perform cleanup on the item data. $item->publish_start_date = (int) $item->publish_start_date != 0 ? $item->publish_start_date : $nd; $item->publish_end_date = (int) $item->publish_end_date != 0 ? $item->publish_end_date : $nd; $item->start_date = (int) $item->start_date != 0 ? $item->start_date : $nd; $item->end_date = (int) $item->end_date != 0 ? $item->end_date : $nd; // Prepare the item description. $item->description = FinderIndexerHelper::parse($item->summary); /* * Now, we need to enter the item into the links table. If the item * already exists in the database, we need to use an UPDATE query. * Otherwise, we need to use an INSERT to get the link id back. */ $entry = new stdClass; $entry->url = $item->url; $entry->route = $item->route; $entry->title = $item->title; // We are shortening the description in order to not run into length issues with this field $entry->description = StringHelper::substr($item->description, 0, 32000); $entry->indexdate = Factory::getDate()->toSql(); $entry->state = (int) $item->state; $entry->access = (int) $item->access; $entry->language = $item->language; $entry->type_id = (int) $item->type_id; $entry->object = ''; $entry->publish_start_date = $item->publish_start_date; $entry->publish_end_date = $item->publish_end_date; $entry->start_date = $item->start_date; $entry->end_date = $item->end_date; $entry->list_price = (double) ($item->list_price ?: 0); $entry->sale_price = (double) ($item->sale_price ?: 0); if ($isNew) { // Insert the link and get its id. $db->insertObject('#__finder_links', $entry); $linkId = (int) $db->insertid(); } else { // Update the link. $entry->link_id = $linkId; $db->updateObject('#__finder_links', $entry, 'link_id'); } // Set up the variables we will need during processing. $count = 0; // Mark afterLinking in the profiler. static::$profiler ? static::$profiler->mark('afterLinking') : null; // Truncate the tokens tables. $db->truncateTable('#__finder_tokens'); // Truncate the tokens aggregate table. $db->truncateTable('#__finder_tokens_aggregate'); /* * Process the item's content. The items can customize their * processing instructions to define extra properties to process * or rearrange how properties are weighted. */ foreach ($item->getInstructions() as $group => $properties) { // Iterate through the properties of the group. foreach ($properties as $property) { // Check if the property exists in the item. if (empty($item->$property)) { continue; } // Tokenize the property. if (is_array($item->$property)) { // Tokenize an array of content and add it to the database. foreach ($item->$property as $ip) { /* * If the group is path, we need to a few extra processing * steps to strip the extension and convert slashes and dashes * to spaces. */ if ($group === static::PATH_CONTEXT) { $ip = JFile::stripExt($ip); $ip = str_replace(array('/', '-'), ' ', $ip); } // Tokenize a string of content and add it to the database. $count += $this->tokenizeToDb($ip, $group, $item->language, $format); // Check if we're approaching the memory limit of the token table. if ($count > static::$state->options->get('memory_table_limit', 30000)) { $this->toggleTables(false); } } } else { /* * If the group is path, we need to a few extra processing * steps to strip the extension and convert slashes and dashes * to spaces. */ if ($group === static::PATH_CONTEXT) { $item->$property = JFile::stripExt($item->$property); $item->$property = str_replace('/', ' ', $item->$property); $item->$property = str_replace('-', ' ', $item->$property); } // Tokenize a string of content and add it to the database. $count += $this->tokenizeToDb($item->$property, $group, $item->language, $format); // Check if we're approaching the memory limit of the token table. if ($count > static::$state->options->get('memory_table_limit', 30000)) { $this->toggleTables(false); } } } } /* * Process the item's taxonomy. The items can customize their * taxonomy mappings to define extra properties to map. */ foreach ($item->getTaxonomy() as $branch => $nodes) { // Iterate through the nodes and map them to the branch. foreach ($nodes as $node) { // Add the node to the tree. $nodeId = FinderIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access); // Add the link => node map. FinderIndexerTaxonomy::addMap($linkId, $nodeId); } } // Mark afterProcessing in the profiler. static::$profiler ? static::$profiler->mark('afterProcessing') : null; /* * At this point, all of the item's content has been parsed, tokenized * and inserted into the #__finder_tokens table. Now, we need to * aggregate all the data into that table into a more usable form. The * aggregated data will be inserted into #__finder_tokens_aggregate * table. */ $query = 'INSERT INTO ' . $db->quoteName('#__finder_tokens_aggregate') . ' (' . $db->quoteName('term_id') . ', ' . $db->quoteName('map_suffix') . ', ' . $db->quoteName('term') . ', ' . $db->quoteName('stem') . ', ' . $db->quoteName('common') . ', ' . $db->quoteName('phrase') . ', ' . $db->quoteName('term_weight') . ', ' . $db->quoteName('context') . ', ' . $db->quoteName('context_weight') . ', ' . $db->quoteName('total_weight') . ', ' . $db->quoteName('language') . ')' . ' SELECT' . ' COALESCE(t.term_id, 0), \'\', t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context,' . ' ROUND( t1.weight * COUNT( t2.term ) * %F, 8 ) AS context_weight, 0, t1.language' . ' FROM (' . ' SELECT DISTINCT t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' . ' FROM ' . $db->quoteName('#__finder_tokens') . ' AS t1' . ' WHERE t1.context = %d' . ' ) AS t1' . ' JOIN ' . $db->quoteName('#__finder_tokens') . ' AS t2 ON t2.term = t1.term AND t2.language = t1.language' . ' LEFT JOIN ' . $db->quoteName('#__finder_terms') . ' AS t ON t.term = t1.term ' . ' WHERE t2.context = %d' . ' GROUP BY t1.term, t.term_id, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' . ' ORDER BY t1.term DESC'; // Iterate through the contexts and aggregate the tokens per context. foreach ($state->weights as $context => $multiplier) { // Run the query to aggregate the tokens for this context.. $db->setQuery(sprintf($query, $multiplier, $context, $context)); $db->execute(); } // Mark afterAggregating in the profiler. static::$profiler ? static::$profiler->mark('afterAggregating') : null; /* * When we pulled down all of the aggregate data, we did a LEFT JOIN * over the terms table to try to find all the term ids that * already exist for our tokens. If any of the rows in the aggregate * table have a term of 0, then no term record exists for that * term so we need to add it to the terms table. */ $db->setQuery( 'INSERT INTO ' . $db->quoteName('#__finder_terms') . ' (' . $db->quoteName('term') . ', ' . $db->quoteName('stem') . ', ' . $db->quoteName('common') . ', ' . $db->quoteName('phrase') . ', ' . $db->quoteName('weight') . ', ' . $db->quoteName('soundex') . ', ' . $db->quoteName('language') . ')' . ' SELECT ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language' . ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' AS ta' . ' WHERE ta.term_id = 0' . ' GROUP BY ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term), ta.language' ); $db->execute(); /* * Now, we just inserted a bunch of new records into the terms table * so we need to go back and update the aggregate table with all the * new term ids. */ $query = $db->getQuery(true) ->update($db->quoteName('#__finder_tokens_aggregate') . ' AS ta') ->join('INNER', $db->quoteName('#__finder_terms') . ' AS t ON t.term = ta.term') ->set('term_id = t.term_id') ->where('ta.term_id = 0'); $db->setQuery($query); $db->execute(); // Mark afterTerms in the profiler. static::$profiler ? static::$profiler->mark('afterTerms') : null; /* * After we've made sure that all of the terms are in the terms table * and the aggregate table has the correct term ids, we need to update * the links counter for each term by one. */ $query->clear() ->update($db->quoteName('#__finder_terms') . ' AS t') ->join('INNER', $db->quoteName('#__finder_tokens_aggregate') . ' AS ta ON ta.term_id = t.term_id') ->set($db->quoteName('links') . ' = t.links + 1'); $db->setQuery($query); $db->execute(); // Mark afterTerms in the profiler. static::$profiler ? static::$profiler->mark('afterTerms') : null; /* * Before we can insert all of the mapping rows, we have to figure out * which mapping table the rows need to be inserted into. The mapping * table for each term is based on the first character of the md5 of * the first character of the term. In php, it would be expressed as * substr(md5(substr($token, 0, 1)), 0, 1) */ $query->clear() ->update($db->quoteName('#__finder_tokens_aggregate')) ->set($db->quoteName('map_suffix') . ' = SUBSTR(MD5(SUBSTR(' . $db->quoteName('term') . ', 1, 1)), 1, 1)'); $db->setQuery($query); $db->execute(); /* * At this point, the aggregate table contains a record for each * term in each context. So, we're going to pull down all of that * data while grouping the records by term and add all of the * sub-totals together to arrive at the final total for each token for * this link. Then, we insert all of that data into the appropriate * mapping table. */ for ($i = 0; $i <= 15; $i++) { // Get the mapping table suffix. $suffix = dechex($i); /* * We have to run this query 16 times, one for each link => term * mapping table. */ $db->setQuery( 'INSERT INTO ' . $db->quoteName('#__finder_links_terms' . $suffix) . ' (' . $db->quoteName('link_id') . ', ' . $db->quoteName('term_id') . ', ' . $db->quoteName('weight') . ')' . ' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' . ' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' . ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' WHERE ' . $db->quoteName('map_suffix') . ' = ' . $db->quote($suffix) . ' GROUP BY ' . $db->quoteName('term') . ', ' . $db->quoteName('term_id') . ' ORDER BY ' . $db->quoteName('term') . ' DESC' ); $db->execute(); } // Mark afterMapping in the profiler. static::$profiler ? static::$profiler->mark('afterMapping') : null; // Update the signature. $object = serialize($item); $query->clear() ->update($db->quoteName('#__finder_links')) ->set($db->quoteName('md5sum') . ' = ' . $db->quote($curSig)) ->set($db->quoteName('object') . ' = ' . $db->quote(pg_escape_bytea($object))) ->where($db->quoteName('link_id') . ' = ' . $db->quote($linkId)); $db->setQuery($query); $db->execute(); // Mark afterSigning in the profiler. static::$profiler ? static::$profiler->mark('afterSigning') : null; // Truncate the tokens tables. $db->truncateTable('#__finder_tokens'); // Truncate the tokens aggregate table. $db->truncateTable('#__finder_tokens_aggregate'); // Toggle the token tables back to memory tables. $this->toggleTables(true); // Mark afterTruncating in the profiler. static::$profiler ? static::$profiler->mark('afterTruncating') : null; return $linkId; } /** * Method to optimize the index. We use this method to remove unused terms * and any other optimizations that might be necessary. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ public function optimize() { // Get the database object. $db = $this->db; $query = $db->getQuery(true); // Delete all orphaned terms. $query->delete($db->quoteName('#__finder_terms')) ->where($db->quoteName('links') . ' <= 0'); $db->setQuery($query); $db->execute(); // Optimize the links table. $db->setQuery('VACUUM ' . $db->quoteName('#__finder_links')); $db->execute(); $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_links')); $db->execute(); for ($i = 0; $i <= 15; $i++) { // Optimize the terms mapping table. $db->setQuery('VACUUM ' . $db->quoteName('#__finder_links_terms' . dechex($i))); $db->execute(); $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_links_terms' . dechex($i))); $db->execute(); } // Optimize the filters table. $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_filters')); $db->execute(); // Optimize the terms common table. $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_terms_common')); $db->execute(); // Optimize the types table. $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_types')); $db->execute(); // Remove the orphaned taxonomy nodes. FinderIndexerTaxonomy::removeOrphanNodes(); // Optimize the taxonomy mapping table. $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_taxonomy_map')); $db->execute(); // Optimize the taxonomy table. $db->setQuery('REINDEX TABLE ' . $db->quoteName('#__finder_taxonomy')); $db->execute(); return true; } } indexer/driver/sqlsrv.php 0000604 00000043472 15245570236 0011557 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2013 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; jimport('joomla.filesystem.file'); /** * Indexer class supporting SQL Server for the Finder indexer package. * * The indexer class provides the core functionality of the Finder * search engine. It is responsible for adding and updating the * content links table; extracting and scoring tokens; and maintaining * all referential information for the content. * * Note: All exceptions thrown from within this class should be caught * by the controller. * * @since 3.1 */ class FinderIndexerDriverSqlsrv extends FinderIndexer { /** * Method to index a content item. * * @param FinderIndexerResult $item The content item to index. * @param string $format The format of the content. [optional] * * @return integer The ID of the record in the links table. * * @since 3.1 * @throws Exception on database error. */ public function index($item, $format = 'html') { // Mark beforeIndexing in the profiler. static::$profiler ? static::$profiler->mark('beforeIndexing') : null; $db = $this->db; $nd = $db->getNullDate(); // Check if the item is in the database. $query = $db->getQuery(true) ->select($db->quoteName('link_id') . ', ' . $db->quoteName('md5sum')) ->from($db->quoteName('#__finder_links')) ->where($db->quoteName('url') . ' = ' . $db->quote($item->url)); // Load the item from the database. $db->setQuery($query); $link = $db->loadObject(); // Get the indexer state. $state = static::getState(); // Get the signatures of the item. $curSig = static::getSignature($item); $oldSig = isset($link->md5sum) ? $link->md5sum : null; // Get the other item information. $linkId = empty($link->link_id) ? null : $link->link_id; $isNew = empty($link->link_id) ? true : false; // Check the signatures. If they match, the item is up to date. if (!$isNew && $curSig === $oldSig) { return $linkId; } /* * If the link already exists, flush all the term maps for the item. * Maps are stored in 16 tables so we need to iterate through and flush * each table one at a time. */ if (!$isNew) { for ($i = 0; $i <= 15; $i++) { // Flush the maps for the link. $query->clear() ->delete($db->quoteName('#__finder_links_terms' . dechex($i))) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); $db->setQuery($query); $db->execute(); } // Remove the taxonomy maps. FinderIndexerTaxonomy::removeMaps($linkId); } // Mark afterUnmapping in the profiler. static::$profiler ? static::$profiler->mark('afterUnmapping') : null; // Perform cleanup on the item data. $item->publish_start_date = (int) $item->publish_start_date != 0 ? $item->publish_start_date : $nd; $item->publish_end_date = (int) $item->publish_end_date != 0 ? $item->publish_end_date : $nd; $item->start_date = (int) $item->start_date != 0 ? $item->start_date : $nd; $item->end_date = (int) $item->end_date != 0 ? $item->end_date : $nd; // Prepare the item description. $item->description = FinderIndexerHelper::parse($item->summary); /* * Now, we need to enter the item into the links table. If the item * already exists in the database, we need to use an UPDATE query. * Otherwise, we need to use an INSERT to get the link id back. */ if ($isNew) { $columnsArray = array( $db->quoteName('url'), $db->quoteName('route'), $db->quoteName('title'), $db->quoteName('description'), $db->quoteName('indexdate'), $db->quoteName('published'), $db->quoteName('state'), $db->quoteName('access'), $db->quoteName('language'), $db->quoteName('type_id'), $db->quoteName('object'), $db->quoteName('publish_start_date'), $db->quoteName('publish_end_date'), $db->quoteName('start_date'), $db->quoteName('end_date'), $db->quoteName('list_price'), $db->quoteName('sale_price') ); // Insert the link. $query->clear() ->insert($db->quoteName('#__finder_links')) ->columns($columnsArray) ->values( $db->quote($item->url) . ', ' . $db->quote($item->route) . ', ' . $db->quote($item->title) . ', ' . $db->quote($item->description) . ', ' . $query->currentTimestamp() . ', ' . '1, ' . (int) $item->state . ', ' . (int) $item->access . ', ' . $db->quote($item->language) . ', ' . (int) $item->type_id . ', ' . $db->quote(serialize($item)) . ', ' . $db->quote($item->publish_start_date) . ', ' . $db->quote($item->publish_end_date) . ', ' . $db->quote($item->start_date) . ', ' . $db->quote($item->end_date) . ', ' . (double) ($item->list_price ?: 0) . ', ' . (double) ($item->sale_price ?: 0) ); $db->setQuery($query); $db->execute(); // Get the link id. $linkId = (int) $db->insertid(); } else { // Update the link. $query->clear() ->update($db->quoteName('#__finder_links')) ->set($db->quoteName('route') . ' = ' . $db->quote($item->route)) ->set($db->quoteName('title') . ' = ' . $db->quote($item->title)) ->set($db->quoteName('description') . ' = ' . $db->quote($item->description)) ->set($db->quoteName('indexdate') . ' = ' . $query->currentTimestamp()) ->set($db->quoteName('state') . ' = ' . (int) $item->state) ->set($db->quoteName('access') . ' = ' . (int) $item->access) ->set($db->quoteName('language') . ' = ' . $db->quote($item->language)) ->set($db->quoteName('type_id') . ' = ' . (int) $item->type_id) ->set($db->quoteName('object') . ' = ' . $db->quote(serialize($item))) ->set($db->quoteName('publish_start_date') . ' = ' . $db->quote($item->publish_start_date)) ->set($db->quoteName('publish_end_date') . ' = ' . $db->quote($item->publish_end_date)) ->set($db->quoteName('start_date') . ' = ' . $db->quote($item->start_date)) ->set($db->quoteName('end_date') . ' = ' . $db->quote($item->end_date)) ->set($db->quoteName('list_price') . ' = ' . (double) ($item->list_price ?: 0)) ->set($db->quoteName('sale_price') . ' = ' . (double) ($item->sale_price ?: 0)) ->where('link_id = ' . (int) $linkId); $db->setQuery($query); $db->execute(); } // Set up the variables we will need during processing. $count = 0; // Mark afterLinking in the profiler. static::$profiler ? static::$profiler->mark('afterLinking') : null; // Truncate the tokens tables. $db->truncateTable('#__finder_tokens'); // Truncate the tokens aggregate table. $db->truncateTable('#__finder_tokens_aggregate'); /* * Process the item's content. The items can customize their * processing instructions to define extra properties to process * or rearrange how properties are weighted. */ foreach ($item->getInstructions() as $group => $properties) { // Iterate through the properties of the group. foreach ($properties as $property) { // Check if the property exists in the item. if (empty($item->$property)) { continue; } // Tokenize the property. if (is_array($item->$property)) { // Tokenize an array of content and add it to the database. foreach ($item->$property as $ip) { /* * If the group is path, we need to a few extra processing * steps to strip the extension and convert slashes and dashes * to spaces. */ if ($group === static::PATH_CONTEXT) { $ip = JFile::stripExt($ip); $ip = str_replace(array('/', '-'), ' ', $ip); } // Tokenize a string of content and add it to the database. $count += $this->tokenizeToDb($ip, $group, $item->language, $format); // Check if we're approaching the memory limit of the token table. if ($count > static::$state->options->get('memory_table_limit', 30000)) { $this->toggleTables(false); } } } else { /* * If the group is path, we need to a few extra processing * steps to strip the extension and convert slashes and dashes * to spaces. */ if ($group === static::PATH_CONTEXT) { $item->$property = JFile::stripExt($item->$property); $item->$property = str_replace('/', ' ', $item->$property); $item->$property = str_replace('-', ' ', $item->$property); } // Tokenize a string of content and add it to the database. $count += $this->tokenizeToDb($item->$property, $group, $item->language, $format); // Check if we're approaching the memory limit of the token table. if ($count > static::$state->options->get('memory_table_limit', 30000)) { $this->toggleTables(false); } } } } /* * Process the item's taxonomy. The items can customize their * taxonomy mappings to define extra properties to map. */ foreach ($item->getTaxonomy() as $branch => $nodes) { // Iterate through the nodes and map them to the branch. foreach ($nodes as $node) { // Add the node to the tree. $nodeId = FinderIndexerTaxonomy::addNode($branch, $node->title, $node->state, $node->access); // Add the link => node map. FinderIndexerTaxonomy::addMap($linkId, $nodeId); } } // Mark afterProcessing in the profiler. static::$profiler ? static::$profiler->mark('afterProcessing') : null; /* * At this point, all of the item's content has been parsed, tokenized * and inserted into the #__finder_tokens table. Now, we need to * aggregate all the data into that table into a more usable form. The * aggregated data will be inserted into #__finder_tokens_aggregate * table. */ $query = 'INSERT INTO ' . $db->quoteName('#__finder_tokens_aggregate') . ' (' . $db->quoteName('term_id') . ', ' . $db->quoteName('term') . ', ' . $db->quoteName('stem') . ', ' . $db->quoteName('common') . ', ' . $db->quoteName('phrase') . ', ' . $db->quoteName('term_weight') . ', ' . $db->quoteName('context') . ', ' . $db->quoteName('context_weight') . ', ' . $db->quoteName('language') . ')' . ' SELECT' . ' t.term_id, t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context,' . ' ROUND( t1.weight * COUNT( t2.term ) * %F, 8 ) AS context_weight, t1.language' . ' FROM (' . ' SELECT DISTINCT t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' . ' FROM ' . $db->quoteName('#__finder_tokens') . ' AS t1' . ' WHERE t1.context = %d' . ' ) AS t1' . ' JOIN ' . $db->quoteName('#__finder_tokens') . ' AS t2 ON t2.term = t1.term' . ' LEFT JOIN ' . $db->quoteName('#__finder_terms') . ' AS t ON t.term = t1.term' . ' WHERE t2.context = %d' . ' GROUP BY t1.term, t.term_id, t1.term, t1.stem, t1.common, t1.phrase, t1.weight, t1.context, t1.language' . ' ORDER BY t1.term DESC'; // Iterate through the contexts and aggregate the tokens per context. foreach ($state->weights as $context => $multiplier) { // Run the query to aggregate the tokens for this context.. $db->setQuery(sprintf($query, $multiplier, $context, $context)); $db->execute(); } // Mark afterAggregating in the profiler. static::$profiler ? static::$profiler->mark('afterAggregating') : null; /* * When we pulled down all of the aggregate data, we did a LEFT JOIN * over the terms table to try to find all the term ids that * already exist for our tokens. If any of the rows in the aggregate * table have a term of 0, then no term record exists for that * term so we need to add it to the terms table. */ $db->setQuery( 'INSERT INTO ' . $db->quoteName('#__finder_terms') . ' (' . $db->quoteName('term') . ', ' . $db->quoteName('stem') . ', ' . $db->quoteName('common') . ', ' . $db->quoteName('phrase') . ', ' . $db->quoteName('weight') . ', ' . $db->quoteName('soundex') . ')' . ' SELECT ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight, SOUNDEX(ta.term)' . ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' AS ta' . ' WHERE ta.term_id IS NULL' . ' GROUP BY ta.term, ta.stem, ta.common, ta.phrase, ta.term_weight' ); $db->execute(); /* * Now, we just inserted a bunch of new records into the terms table * so we need to go back and update the aggregate table with all the * new term ids. */ $query = $db->getQuery(true) ->update('ta') ->set('ta.term_id = t.term_id from #__finder_tokens_aggregate AS ta INNER JOIN #__finder_terms AS t ON t.term = ta.term') ->where('ta.term_id IS NULL'); $db->setQuery($query); $db->execute(); // Mark afterTerms in the profiler. static::$profiler ? static::$profiler->mark('afterTerms') : null; /* * After we've made sure that all of the terms are in the terms table * and the aggregate table has the correct term ids, we need to update * the links counter for each term by one. */ $query->clear() ->update('t') ->set('t.links = t.links + 1 FROM #__finder_terms AS t INNER JOIN #__finder_tokens_aggregate AS ta ON ta.term_id = t.term_id'); $db->setQuery($query); $db->execute(); // Mark afterTerms in the profiler. static::$profiler ? static::$profiler->mark('afterTerms') : null; /* * Before we can insert all of the mapping rows, we have to figure out * which mapping table the rows need to be inserted into. The mapping * table for each term is based on the first character of the md5 of * the first character of the term. In php, it would be expressed as * substr(md5(substr($token, 0, 1)), 0, 1) */ $query->clear() ->update($db->quoteName('#__finder_tokens_aggregate')) ->set($db->quoteName('map_suffix') . " = SUBSTRING(HASHBYTES('MD5', SUBSTRING(" . $db->quoteName('term') . ', 1, 1)), 1, 1)'); $db->setQuery($query); $db->execute(); /* * At this point, the aggregate table contains a record for each * term in each context. So, we're going to pull down all of that * data while grouping the records by term and add all of the * sub-totals together to arrive at the final total for each token for * this link. Then, we insert all of that data into the appropriate * mapping table. */ for ($i = 0; $i <= 15; $i++) { // Get the mapping table suffix. $suffix = dechex($i); /* * We have to run this query 16 times, one for each link => term * mapping table. */ $db->setQuery( 'INSERT INTO ' . $db->quoteName('#__finder_links_terms' . $suffix) . ' (' . $db->quoteName('link_id') . ', ' . $db->quoteName('term_id') . ', ' . $db->quoteName('weight') . ')' . ' SELECT ' . (int) $linkId . ', ' . $db->quoteName('term_id') . ',' . ' ROUND(SUM(' . $db->quoteName('context_weight') . '), 8)' . ' FROM ' . $db->quoteName('#__finder_tokens_aggregate') . ' WHERE ' . $db->quoteName('map_suffix') . ' = ' . $db->quote($suffix) . ' GROUP BY term, term_id' . ' ORDER BY ' . $db->quoteName('term') . ' DESC' ); $db->execute(); } // Mark afterMapping in the profiler. static::$profiler ? static::$profiler->mark('afterMapping') : null; // Update the signature. $query->clear() ->update($db->quoteName('#__finder_links')) ->set($db->quoteName('md5sum') . ' = ' . $db->quote($curSig)) ->where($db->quoteName('link_id') . ' = ' . $db->quote($linkId)); $db->setQuery($query); $db->execute(); // Mark afterSigning in the profiler. static::$profiler ? static::$profiler->mark('afterSigning') : null; // Truncate the tokens tables. $db->truncateTable('#__finder_tokens'); // Truncate the tokens aggregate table. $db->truncateTable('#__finder_tokens_aggregate'); // Toggle the token tables back to memory tables. $this->toggleTables(true); // Mark afterTruncating in the profiler. static::$profiler ? static::$profiler->mark('afterTruncating') : null; return $linkId; } /** * Method to remove a link from the index. * * @param integer $linkId The id of the link. * * @return boolean True on success. * * @since 3.1 * @throws Exception on database error. */ public function remove($linkId) { $db = $this->db; $query = $db->getQuery(true); // Update the link counts and remove the mapping records. for ($i = 0; $i <= 15; $i++) { // Update the link counts for the terms. $query->update('t') ->set('t.links = t.links - 1 from #__finder_terms AS t INNER JOIN #__finder_links_terms' . dechex($i) . ' AS m ON m.term_id = t.term_id') ->where('m.link_id = ' . $db->quote((int) $linkId)); $db->setQuery($query); $db->execute(); // Remove all records from the mapping tables. $query->clear() ->delete($db->quoteName('#__finder_links_terms' . dechex($i))) ->where($db->quoteName('link_id') . ' = ' . (int) $linkId); $db->setQuery($query); $db->execute(); } // Delete all orphaned terms. $query->clear() ->delete($db->quoteName('#__finder_terms')) ->where($db->quoteName('links') . ' <= 0'); $db->setQuery($query); $db->execute(); // Delete the link from the index. $query->clear() ->delete($db->quoteName('#__finder_links')) ->where($db->quoteName('link_id') . ' = ' . $db->quote((int) $linkId)); $db->setQuery($query); $db->execute(); // Remove the taxonomy maps. FinderIndexerTaxonomy::removeMaps($linkId); // Remove the orphaned taxonomy nodes. FinderIndexerTaxonomy::removeOrphanNodes(); return true; } /** * Method to optimize the index. We use this method to remove unused terms * and any other optimizations that might be necessary. * * @return boolean True on success. * * @since 3.1 * @throws Exception on database error. */ public function optimize() { // Get the database object. $db = $this->db; $query = $db->getQuery(true); // Delete all orphaned terms. $query->delete($db->quoteName('#__finder_terms')) ->where($db->quoteName('links') . ' <= 0'); $db->setQuery($query); $db->execute(); // Remove the orphaned taxonomy nodes. FinderIndexerTaxonomy::removeOrphanNodes(); return true; } } indexer/stemmer/porter_en.php 0000604 00000023413 15245570236 0012374 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('FinderIndexerStemmer', dirname(__DIR__) . '/stemmer.php'); /** * Porter English stemmer class for the Finder indexer package. * * This class was adapted from one written by Richard Heyes. * See copyright and link information above. * * @since 2.5 */ class FinderIndexerStemmerPorter_En extends FinderIndexerStemmer { /** * Regex for matching a consonant. * * @var string * @since 2.5 */ private static $regex_consonant = '(?:[bcdfghjklmnpqrstvwxz]|(?<=[aeiou])y|^y)'; /** * Regex for matching a vowel * * @var string * @since 2.5 */ private static $regex_vowel = '(?:[aeiou]|(?<![aeiou])y)'; /** * Method to stem a token and return the root. * * @param string $token The token to stem. * @param string $lang The language of the token. * * @return string The root token. * * @since 2.5 */ public function stem($token, $lang) { // Check if the token is long enough to merit stemming. if (strlen($token) <= 2) { return $token; } // Check if the language is English or All. if ($lang !== 'en' && $lang !== '*') { return $token; } // Stem the token if it is not in the cache. if (!isset($this->cache[$lang][$token])) { // Stem the token. $result = $token; $result = self::step1ab($result); $result = self::step1c($result); $result = self::step2($result); $result = self::step3($result); $result = self::step4($result); $result = self::step5($result); // Add the token to the cache. $this->cache[$lang][$token] = $result; } return $this->cache[$lang][$token]; } /** * Step 1 * * @param string $word The token to stem. * * @return string * * @since 2.5 */ private static function step1ab($word) { // Part a if (substr($word, -1) === 's') { self::replace($word, 'sses', 'ss') || self::replace($word, 'ies', 'i') || self::replace($word, 'ss', 'ss') || self::replace($word, 's', ''); } // Part b if (substr($word, -2, 1) !== 'e' || !self::replace($word, 'eed', 'ee', 0)) { // First rule $v = self::$regex_vowel; // Words ending with ing and ed // Note use of && and OR, for precedence reasons if (preg_match("#$v+#", substr($word, 0, -3)) && self::replace($word, 'ing', '') || preg_match("#$v+#", substr($word, 0, -2)) && self::replace($word, 'ed', '')) { // If one of above two test successful if (!self::replace($word, 'at', 'ate') && !self::replace($word, 'bl', 'ble') && !self::replace($word, 'iz', 'ize')) { // Double consonant ending $wordSubStr = substr($word, -2); if ($wordSubStr !== 'll' && $wordSubStr !== 'ss' && $wordSubStr !== 'zz' && self::doubleConsonant($word)) { $word = substr($word, 0, -1); } elseif (self::m($word) === 1 && self::cvc($word)) { $word .= 'e'; } } } } return $word; } /** * Step 1c * * @param string $word The token to stem. * * @return string * * @since 2.5 */ private static function step1c($word) { $v = self::$regex_vowel; if (substr($word, -1) === 'y' && preg_match("#$v+#", substr($word, 0, -1))) { self::replace($word, 'y', 'i'); } return $word; } /** * Step 2 * * @param string $word The token to stem. * * @return string * * @since 2.5 */ private static function step2($word) { switch (substr($word, -2, 1)) { case 'a': self::replace($word, 'ational', 'ate', 0) || self::replace($word, 'tional', 'tion', 0); break; case 'c': self::replace($word, 'enci', 'ence', 0) || self::replace($word, 'anci', 'ance', 0); break; case 'e': self::replace($word, 'izer', 'ize', 0); break; case 'g': self::replace($word, 'logi', 'log', 0); break; case 'l': self::replace($word, 'entli', 'ent', 0) || self::replace($word, 'ousli', 'ous', 0) || self::replace($word, 'alli', 'al', 0) || self::replace($word, 'bli', 'ble', 0) || self::replace($word, 'eli', 'e', 0); break; case 'o': self::replace($word, 'ization', 'ize', 0) || self::replace($word, 'ation', 'ate', 0) || self::replace($word, 'ator', 'ate', 0); break; case 's': self::replace($word, 'iveness', 'ive', 0) || self::replace($word, 'fulness', 'ful', 0) || self::replace($word, 'ousness', 'ous', 0) || self::replace($word, 'alism', 'al', 0); break; case 't': self::replace($word, 'biliti', 'ble', 0) || self::replace($word, 'aliti', 'al', 0) || self::replace($word, 'iviti', 'ive', 0); break; } return $word; } /** * Step 3 * * @param string $word The token to stem. * * @return string * * @since 2.5 */ private static function step3($word) { switch (substr($word, -2, 1)) { case 'a': self::replace($word, 'ical', 'ic', 0); break; case 's': self::replace($word, 'ness', '', 0); break; case 't': self::replace($word, 'icate', 'ic', 0) || self::replace($word, 'iciti', 'ic', 0); break; case 'u': self::replace($word, 'ful', '', 0); break; case 'v': self::replace($word, 'ative', '', 0); break; case 'z': self::replace($word, 'alize', 'al', 0); break; } return $word; } /** * Step 4 * * @param string $word The token to stem. * * @return string * * @since 2.5 */ private static function step4($word) { switch (substr($word, -2, 1)) { case 'a': self::replace($word, 'al', '', 1); break; case 'c': self::replace($word, 'ance', '', 1) || self::replace($word, 'ence', '', 1); break; case 'e': self::replace($word, 'er', '', 1); break; case 'i': self::replace($word, 'ic', '', 1); break; case 'l': self::replace($word, 'able', '', 1) || self::replace($word, 'ible', '', 1); break; case 'n': self::replace($word, 'ant', '', 1) || self::replace($word, 'ement', '', 1) || self::replace($word, 'ment', '', 1) || self::replace($word, 'ent', '', 1); break; case 'o': $wordSubStr = substr($word, -4); if ($wordSubStr === 'tion' || $wordSubStr === 'sion') { self::replace($word, 'ion', '', 1); } else { self::replace($word, 'ou', '', 1); } break; case 's': self::replace($word, 'ism', '', 1); break; case 't': self::replace($word, 'ate', '', 1) || self::replace($word, 'iti', '', 1); break; case 'u': self::replace($word, 'ous', '', 1); break; case 'v': self::replace($word, 'ive', '', 1); break; case 'z': self::replace($word, 'ize', '', 1); break; } return $word; } /** * Step 5 * * @param string $word The token to stem. * * @return string * * @since 2.5 */ private static function step5($word) { // Part a if (substr($word, -1) === 'e') { if (self::m(substr($word, 0, -1)) > 1) { self::replace($word, 'e', ''); } elseif (self::m(substr($word, 0, -1)) === 1) { if (!self::cvc(substr($word, 0, -1))) { self::replace($word, 'e', ''); } } } // Part b if (self::m($word) > 1 && self::doubleConsonant($word) && substr($word, -1) === 'l') { $word = substr($word, 0, -1); } return $word; } /** * Replaces the first string with the second, at the end of the string. If third * arg is given, then the preceding string must match that m count at least. * * @param string $str String to check * @param string $check Ending to check for * @param string $repl Replacement string * @param integer $m Optional minimum number of m() to meet * * @return boolean Whether the $check string was at the end * of the $str string. True does not necessarily mean * that it was replaced. * * @since 2.5 */ private static function replace(&$str, $check, $repl, $m = null) { $len = 0 - strlen($check); if (substr($str, $len) === $check) { $substr = substr($str, 0, $len); if ($m === null || self::m($substr) > $m) { $str = $substr . $repl; } return true; } return false; } /** * m() measures the number of consonant sequences in $str. if c is * a consonant sequence and v a vowel sequence, and <..> indicates arbitrary * presence, * * <c><v> gives 0 * <c>vc<v> gives 1 * <c>vcvc<v> gives 2 * <c>vcvcvc<v> gives 3 * * @param string $str The string to return the m count for * * @return integer The m count * * @since 2.5 */ private static function m($str) { $c = self::$regex_consonant; $v = self::$regex_vowel; $str = preg_replace("#^$c+#", '', $str); $str = preg_replace("#$v+$#", '', $str); preg_match_all("#($v+$c+)#", $str, $matches); return count($matches[1]); } /** * Returns true/false as to whether the given string contains two * of the same consonant next to each other at the end of the string. * * @param string $str String to check * * @return boolean Result * * @since 2.5 */ private static function doubleConsonant($str) { $c = self::$regex_consonant; return preg_match("#$c{2}$#", $str, $matches) && $matches[0][0] === $matches[0][1]; } /** * Checks for ending CVC sequence where second C is not W, X or Y * * @param string $str String to check * * @return boolean Result * * @since 2.5 */ private static function cvc($str) { $c = self::$regex_consonant; $v = self::$regex_vowel; return preg_match("#($c$v$c)$#", $str, $matches) && strlen($matches[1]) === 3 && $matches[1][2] !== 'w' && $matches[1][2] !== 'x' && $matches[1][2] !== 'y'; } } indexer/stemmer/fr.php 0000604 00000024133 15245570236 0011006 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('FinderIndexerStemmer', dirname(__DIR__) . '/stemmer.php'); /** * French stemmer class for Smart Search indexer. * * First contributed by Eric Sanou (bobotche@hotmail.fr) * This class is inspired in Alexis Ulrich's French stemmer code (http://alx2002.free.fr) * * @since 3.0 */ class FinderIndexerStemmerFr extends FinderIndexerStemmer { /** * Stemming rules. * * @var array * @since 3.0 */ private static $stemRules; /** * Method to stem a token and return the root. * * @param string $token The token to stem. * @param string $lang The language of the token. * * @return string The root token. * * @since 3.0 */ public function stem($token, $lang) { // Check if the token is long enough to merit stemming. if (strlen($token) <= 2) { return $token; } // Check if the language is French or All. if ($lang !== 'fr' && $lang !== '*') { return $token; } // Stem the token if it is not in the cache. if (!isset($this->cache[$lang][$token])) { // Stem the token. $result = self::getStem($token); // Add the token to the cache. $this->cache[$lang][$token] = $result; } return $this->cache[$lang][$token]; } /** * French stemmer rules variables. * * @return array The rules * * @since 3.0 */ protected static function getStemRules() { if (self::$stemRules) { return self::$stemRules; } $vars = array(); // French accented letters in ISO-8859-1 encoding $vars['accents'] = chr(224) . chr(226) . chr(232) . chr(233) . chr(234) . chr(235) . chr(238) . chr(239) . chr(244) . chr(251) . chr(249) . chr(231); // The rule patterns include all accented words for french language $vars['rule_pattern'] = '/^([a-z' . $vars['accents'] . ']*)(\*){0,1}(\d)([a-z' . $vars['accents'] . ']*)([.|>])/'; // French vowels (including y) in ISO-8859-1 encoding $vars['vowels'] = chr(97) . chr(224) . chr(226) . chr(101) . chr(232) . chr(233) . chr(234) . chr(235) . chr(105) . chr(238) . chr(239) . chr(111) . chr(244) . chr(117) . chr(251) . chr(249) . chr(121); // The French rules in ISO-8859-1 encoding $vars['rules'] = array( 'esre1>', 'esio1>', 'siol1.', 'siof0.', 'sioe0.', 'sio3>', 'st1>', 'sf1>', 'sle1>', 'slo1>', 's' . chr(233) . '1>', chr(233) . 'tuae5.', chr(233) . 'tuae2.', 'tnia0.', 'tniv1.', 'tni3>', 'suor1.', 'suo0.', 'sdrail5.', 'sdrai4.', 'er' . chr(232) . 'i1>', 'sesue3x>', 'esuey5i.', 'esue2x>', 'se1>', 'er' . chr(232) . 'g3.', 'eca1>', 'esiah0.', 'esi1>', 'siss2.', 'sir2>', 'sit2>', 'egan' . chr(233) . '1.', 'egalli6>', 'egass1.', 'egas0.', 'egat3.', 'ega3>', 'ette4>', 'ett2>', 'etio1.', 'tio' . chr(231) . '4c.', 'tio0.', 'et1>', 'eb1>', 'snia1>', 'eniatnau8>', 'eniatn4.', 'enia1>', 'niatnio3.', 'niatg3.', 'e' . chr(233) . '1>', chr(233) . 'hcat1.', chr(233) . 'hca4.', chr(233) . 'tila5>', chr(233) . 'tici5.', chr(233) . 'tir1.', chr(233) . 'ti3>', chr(233) . 'gan1.', chr(233) . 'ga3>', chr(233) . 'tehc1.', chr(233) . 'te3>', chr(233) . 'it0.', chr(233) . '1>', 'eire4.', 'eirue5.', 'eio1.', 'eia1.', 'ei1>', 'eng1.', 'xuaessi7.', 'xuae1>', 'uaes0.', 'uae3.', 'xuave2l.', 'xuav2li>', 'xua3la>', 'ela1>', 'lart2.', 'lani2>', 'la' . chr(233) . '2>', 'siay4i.', 'siassia7.', 'siarv1*.', 'sia1>', 'tneiayo6i.', 'tneiay6i.', 'tneiassia9.', 'tneiareio7.', 'tneia5>', 'tneia4>', 'tiario4.', 'tiarim3.', 'tiaria3.', 'tiaris3.', 'tiari5.', 'tiarve6>', 'tiare5>', 'iare4>', 'are3>', 'tiay4i.', 'tia3>', 'tnay4i.', 'em' . chr(232) . 'iu5>', 'em' . chr(232) . 'i4>', 'tnaun3.', 'tnauqo3.', 'tnau4>', 'tnaf0.', 'tnat' . chr(233) . '2>', 'tna3>', 'tno3>', 'zeiy4i.', 'zey3i.', 'zeire5>', 'zeird4.', 'zeirio4.', 'ze2>', 'ssiab0.', 'ssia4.', 'ssi3.', 'tnemma6>', 'tnemesuey9i.', 'tnemesue8>', 'tnemevi7.', 'tnemessia5.', 'tnemessi8.', 'tneme5>', 'tnemia4.', 'tnem' . chr(233) . '5>', 'el2l>', 'lle3le>', 'let' . chr(244) . '0.', 'lepp0.', 'le2>', 'srei1>', 'reit3.', 'reila2.', 'rei3>', 'ert' . chr(226) . 'e5.', 'ert' . chr(226) . chr(233) . '1.', 'ert' . chr(226) . '4.', 'drai4.', 'erdro0.', 'erute5.', 'ruta0.', 'eruta1.', 'erutiov1.', 'erub3.', 'eruh3.', 'erul3.', 'er2r>', 'nn1>', 'r' . chr(232) . 'i3.', 'srev0.', 'sr1>', 'rid2>', 're2>', 'xuei4.', 'esuei5.', 'lbati3.', 'lba3>', 'rueis0.', 'ruehcn4.', 'ecirta6.', 'ruetai6.', 'rueta5.', 'rueir0.', 'rue3>', 'esseti6.', 'essere6>', 'esserd1.', 'esse4>', 'essiab1.', 'essia5.', 'essio1.', 'essi4.', 'essal4.', 'essa1>', 'ssab1.', 'essurp1.', 'essu4.', 'essi1.', 'ssor1.', 'essor2.', 'esso1>', 'ess2>', 'tio3.', 'r' . chr(232) . 's2re.', 'r' . chr(232) . '0e.', 'esn1.', 'eu1>', 'sua0.', 'su1>', 'utt1>', 'tu' . chr(231) . '3c.', 'u' . chr(231) . '2c.', 'ur1.', 'ehcn2>', 'ehcu1>', 'snorr3.', 'snoru3.', 'snorua3.', 'snorv3.', 'snorio4.', 'snori5.', 'snore5>', 'snortt4>', 'snort' . chr(238) . 'a7.', 'snort3.', 'snor4.', 'snossi6.', 'snoire6.', 'snoird5.', 'snoitai7.', 'snoita6.', 'snoits1>', 'noits0.', 'snoi4>', 'noitaci7>', 'noitai6.', 'noita5.', 'noitu4.', 'noi3>', 'snoya0.', 'snoy4i.', 'sno' . chr(231) . 'a1.', 'sno' . chr(231) . 'r1.', 'snoe4.', 'snosiar1>', 'snola1.', 'sno3>', 'sno1>', 'noll2.', 'tnennei4.', 'ennei2>', 'snei1>', 'sne' . chr(233) . '1>', 'enne' . chr(233) . '5e.', 'ne' . chr(233) . '3e.', 'neic0.', 'neiv0.', 'nei3.', 'sc1.', 'sd1.', 'sg1.', 'sni1.', 'tiu0.', 'ti2.', 'sp1>', 'sna1>', 'sue1.', 'enn2>', 'nong2.', 'noss2.', 'rioe4.', 'riot0.', 'riorc1.', 'riovec5.', 'rio3.', 'ric2.', 'ril2.', 'tnerim3.', 'tneris3>', 'tneri5.', 't' . chr(238) . 'a3.', 'riss2.', 't' . chr(238) . '2.', 't' . chr(226) . '2>', 'ario2.', 'arim1.', 'ara1.', 'aris1.', 'ari3.', 'art1>', 'ardn2.', 'arr1.', 'arua1.', 'aro1.', 'arv1.', 'aru1.', 'ar2.', 'rd1.', 'ud1.', 'ul1.', 'ini1.', 'rin2.', 'tnessiab3.', 'tnessia7.', 'tnessi6.', 'tnessni4.', 'sini2.', 'sl1.', 'iard3.', 'iario3.', 'ia2>', 'io0.', 'iule2.', 'i1>', 'sid2.', 'sic2.', 'esoi4.', 'ed1.', 'ai2>', 'a1>', 'adr1.', 'tner' . chr(232) . '5>', 'evir1.', 'evio4>', 'evi3.', 'fita4.', 'fi2>', 'enie1.', 'sare4>', 'sari4>', 'sard3.', 'sart2>', 'sa2.', 'tnessa6>', 'tnessu6>', 'tnegna3.', 'tnegi3.', 'tneg0.', 'tneru5>', 'tnemg0.', 'tnerni4.', 'tneiv1.', 'tne3>', 'une1.', 'en1>', 'nitn2.', 'ecnay5i.', 'ecnal1.', 'ecna4.', 'ec1>', 'nn1.', 'rit2>', 'rut2>', 'rud2.', 'ugn1>', 'eg1>', 'tuo0.', 'tul2>', 't' . chr(251) . '2>', 'ev1>', 'v' . chr(232) . '2ve>', 'rtt1>', 'emissi6.', 'em1.', 'ehc1.', 'c' . chr(233) . 'i2c' . chr(232) . '.', 'libi2l.', 'llie1.', 'liei4i.', 'xuev1.', 'xuey4i.', 'xueni5>', 'xuell4.', 'xuere5.', 'xue3>', 'rb' . chr(233) . '3rb' . chr(232) . '.', 'tur2.', 'rir' . chr(233) . '4re.', 'rir2.', 'c' . chr(226) . '2ca.', 'snu1.', 'rt' . chr(238) . 'a4.', 'long2.', 'vec2.', chr(231) . '1c>', 'ssilp3.', 'silp2.', 't' . chr(232) . 'hc2te.', 'n' . chr(232) . 'm2ne.', 'llepp1.', 'tan2.', 'rv' . chr(232) . '3rve.', 'rv' . chr(233) . '3rve.', 'r' . chr(232) . '2re.', 'r' . chr(233) . '2re.', 't' . chr(232) . '2te.', 't' . chr(233) . '2te.', 'epp1.', 'eya2i.', 'ya1i.', 'yo1i.', 'esu1.', 'ugi1.', 'tt1.', 'end0.' ); self::$stemRules = $vars; return self::$stemRules; } /** * Returns the number of the first rule from the rule number * that can be applied to the given reversed input. * returns -1 if no rule can be applied, ie the stem has been found * * @param string $reversedInput The input to check in reversed order * @param integer $ruleNumber The rule number to check * * @return integer Number of the first rule * * @since 3.0 */ private static function getFirstRule($reversedInput, $ruleNumber) { $vars = static::getStemRules(); $nb_rules = count($vars['rules']); for ($i = $ruleNumber; $i < $nb_rules; $i++) { // Gets the letters from the current rule $rule = $vars['rules'][$i]; $rule = preg_replace($vars['rule_pattern'], "\\1", $rule); if (strncasecmp(utf8_decode($rule), $reversedInput, strlen(utf8_decode($rule))) == 0) { return $i; } } return -1; } /** * Check the acceptability of a stem for French language * * @param string $reversedStem The stem to check in reverse form * * @return boolean True if stem is acceptable * * @since 3.0 */ private static function check($reversedStem) { $vars = static::getStemRules(); if (preg_match('/[' . $vars['vowels'] . ']$/', utf8_encode($reversedStem))) { // If the form starts with a vowel then at least two letters must remain after stemming (e.g.: "etaient" --> "et") return (strlen($reversedStem) > 2); } else { // If the reversed stem starts with a consonant then at least two letters must remain after stemming if (strlen($reversedStem) <= 2) { return false; } // And at least one of these must be a vowel or "y" return preg_match('/[' . $vars['vowels'] . ']/', utf8_encode($reversedStem)); } } /** * Paice/Husk stemmer which returns a stem for the given $input * * @param string $input The word for which we want the stem in UTF-8 * * @return string The stem * * @since 3.0 */ private static function getStem($input) { $vars = static::getStemRules(); $reversed_input = strrev(utf8_decode($input)); $rule_number = 0; // This loop goes through the rules' array until it finds an ending one (ending by '.') or the last one ('end0.') while (true) { $rule_number = self::getFirstRule($reversed_input, $rule_number); if ($rule_number === -1) { // No other rule can be applied => the stem has been found break; } $rule = $vars['rules'][$rule_number]; preg_match($vars['rule_pattern'], $rule, $matches); $reversed_stem = utf8_decode($matches[4]) . substr($reversed_input, $matches[3]); if (self::check($reversed_stem)) { $reversed_input = $reversed_stem; if ($matches[5] === '.') { break; } } else { // Go to another rule $rule_number++; } } return utf8_encode(strrev($reversed_input)); } } indexer/stemmer/snowball.php 0000604 00000005320 15245570236 0012215 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('FinderIndexerStemmer', dirname(__DIR__) . '/stemmer.php'); /** * Snowball stemmer class for the Finder indexer package. * * @since 2.5 */ class FinderIndexerStemmerSnowball extends FinderIndexerStemmer { /** * Method to stem a token and return the root. * * @param string $token The token to stem. * @param string $lang The language of the token. * * @return string The root token. * * @since 2.5 */ public function stem($token, $lang) { // Language to use if All is specified. static $defaultLang = ''; // If language is All then try to get site default language. if ($lang === '*' && $defaultLang === '') { $languages = JLanguageHelper::getLanguages(); $defaultLang = isset($languages[0]->sef) ? $languages[0]->sef : '*'; $lang = $defaultLang; } // Stem the token if it is not in the cache. if (!isset($this->cache[$lang][$token])) { // Get the stem function from the language string. switch ($lang) { // Danish stemmer. case 'da': $function = 'stem_danish'; break; // German stemmer. case 'de': $function = 'stem_german'; break; // English stemmer. default: case 'en': $function = 'stem_english'; break; // Spanish stemmer. case 'es': $function = 'stem_spanish'; break; // Finnish stemmer. case 'fi': $function = 'stem_finnish'; break; // French stemmer. case 'fr': $function = 'stem_french'; break; // Hungarian stemmer. case 'hu': $function = 'stem_hungarian'; break; // Italian stemmer. case 'it': $function = 'stem_italian'; break; // Norwegian stemmer. case 'nb': $function = 'stem_norwegian'; break; // Dutch stemmer. case 'nl': $function = 'stem_dutch'; break; // Portuguese stemmer. case 'pt': $function = 'stem_portuguese'; break; // Romanian stemmer. case 'ro': $function = 'stem_romanian'; break; // Russian stemmer. case 'ru': $function = 'stem_russian_unicode'; break; // Swedish stemmer. case 'sv': $function = 'stem_swedish'; break; // Turkish stemmer. case 'tr': $function = 'stem_turkish_unicode'; break; } // Stem the word if the stemmer method exists. $this->cache[$lang][$token] = function_exists($function) ? $function($token) : $token; } return $this->cache[$lang][$token]; } } indexer/result.php 0000604 00000021021 15245570236 0010232 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('FinderIndexer', __DIR__ . '/indexer.php'); /** * Result class for the Finder indexer package. * * This class uses magic __get() and __set() methods to prevent properties * being added that might confuse the system. All properties not explicitly * declared will be pushed into the elements array and can be accessed * explicitly using the getElement() method. * * @since 2.5 */ class FinderIndexerResult { /** * An array of extra result properties. * * @var array * @since 2.5 */ protected $elements = array(); /** * This array tells the indexer which properties should be indexed and what * weights to use for those properties. * * @var array * @since 2.5 */ protected $instructions = array( FinderIndexer::TITLE_CONTEXT => array('title', 'subtitle', 'id'), FinderIndexer::TEXT_CONTEXT => array('summary', 'body'), FinderIndexer::META_CONTEXT => array('meta', 'list_price', 'sale_price'), FinderIndexer::PATH_CONTEXT => array('path', 'alias'), FinderIndexer::MISC_CONTEXT => array('comments'), ); /** * The indexer will use this data to create taxonomy mapping entries for * the item so that it can be filtered by type, label, category, * or whatever. * * @var array * @since 2.5 */ protected $taxonomy = array(); /** * The content URL. * * @var string * @since 2.5 */ public $url; /** * The content route. * * @var string * @since 2.5 */ public $route; /** * The content title. * * @var string * @since 2.5 */ public $title; /** * The content description. * * @var string * @since 2.5 */ public $description; /** * The published state of the result. * * @var integer * @since 2.5 */ public $published; /** * The content published state. * * @var integer * @since 2.5 */ public $state; /** * The content access level. * * @var integer * @since 2.5 */ public $access; /** * The content language. * * @var string * @since 2.5 */ public $language = '*'; /** * The publishing start date. * * @var string * @since 2.5 */ public $publish_start_date; /** * The publishing end date. * * @var string * @since 2.5 */ public $publish_end_date; /** * The generic start date. * * @var string * @since 2.5 */ public $start_date; /** * The generic end date. * * @var string * @since 2.5 */ public $end_date; /** * The item list price. * * @var mixed * @since 2.5 */ public $list_price; /** * The item sale price. * * @var mixed * @since 2.5 */ public $sale_price; /** * The content type id. This is set by the adapter. * * @var integer * @since 2.5 */ public $type_id; /** * The default language for content. * * @var string * @since 3.0.2 */ public $defaultLanguage; /** * Constructor * * @since 3.0.3 */ public function __construct() { $this->defaultLanguage = JComponentHelper::getParams('com_languages')->get('site', 'en-GB'); } /** * The magic set method is used to push additional values into the elements * array in order to preserve the cleanliness of the object. * * @param string $name The name of the element. * @param mixed $value The value of the element. * * @return void * * @since 2.5 */ public function __set($name, $value) { $this->setElement($name, $value); } /** * The magic get method is used to retrieve additional element values from the elements array. * * @param string $name The name of the element. * * @return mixed The value of the element if set, null otherwise. * * @since 2.5 */ public function __get($name) { return $this->getElement($name); } /** * The magic isset method is used to check the state of additional element values in the elements array. * * @param string $name The name of the element. * * @return boolean True if set, false otherwise. * * @since 2.5 */ public function __isset($name) { return isset($this->elements[$name]); } /** * The magic unset method is used to unset additional element values in the elements array. * * @param string $name The name of the element. * * @return void * * @since 2.5 */ public function __unset($name) { unset($this->elements[$name]); } /** * Method to retrieve additional element values from the elements array. * * @param string $name The name of the element. * * @return mixed The value of the element if set, null otherwise. * * @since 2.5 */ public function getElement($name) { // Get the element value if set. if (array_key_exists($name, $this->elements)) { return $this->elements[$name]; } return null; } /** * Method to retrieve all elements. * * @return array The elements * * @since 3.8.3 */ public function getElements() { return $this->elements; } /** * Method to set additional element values in the elements array. * * @param string $name The name of the element. * @param mixed $value The value of the element. * * @return void * * @since 2.5 */ public function setElement($name, $value) { $this->elements[$name] = $value; } /** * Method to get all processing instructions. * * @return array An array of processing instructions. * * @since 2.5 */ public function getInstructions() { return $this->instructions; } /** * Method to add a processing instruction for an item property. * * @param string $group The group to associate the property with. * @param string $property The property to process. * * @return void * * @since 2.5 */ public function addInstruction($group, $property) { // Check if the group exists. We can't add instructions for unknown groups. // Check if the property exists in the group. if (array_key_exists($group, $this->instructions) && !in_array($property, $this->instructions[$group], true)) { // Add the property to the group. $this->instructions[$group][] = $property; } } /** * Method to remove a processing instruction for an item property. * * @param string $group The group to associate the property with. * @param string $property The property to process. * * @return void * * @since 2.5 */ public function removeInstruction($group, $property) { // Check if the group exists. We can't remove instructions for unknown groups. if (array_key_exists($group, $this->instructions)) { // Search for the property in the group. $key = array_search($property, $this->instructions[$group]); // If the property was found, remove it. if ($key !== false) { unset($this->instructions[$group][$key]); } } } /** * Method to get the taxonomy maps for an item. * * @param string $branch The taxonomy branch to get. [optional] * * @return array An array of taxonomy maps. * * @since 2.5 */ public function getTaxonomy($branch = null) { // Get the taxonomy branch if available. if ($branch !== null && isset($this->taxonomy[$branch])) { // Filter the input. $branch = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,_]+#mui', ' ', $branch); return $this->taxonomy[$branch]; } return $this->taxonomy; } /** * Method to add a taxonomy map for an item. * * @param string $branch The title of the taxonomy branch to add the node to. * @param string $title The title of the taxonomy node. * @param integer $state The published state of the taxonomy node. [optional] * @param integer $access The access level of the taxonomy node. [optional] * * @return void * * @since 2.5 */ public function addTaxonomy($branch, $title, $state = 1, $access = 1) { // Filter the input. $branch = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,_]+#mui', ' ', $branch); // Create the taxonomy node. $node = new JObject; $node->title = $title; $node->state = (int) $state; $node->access = (int) $access; // Add the node to the taxonomy branch. $this->taxonomy[$branch][$node->title] = $node; } /** * Method to set the item language * * @return void * * @since 3.0 */ public function setLanguage() { if ($this->language == '') { $this->language = $this->defaultLanguage; } } } indexer/token.php 0000604 00000007657 15245570236 0010057 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\String\StringHelper; /** * Token class for the Finder indexer package. * * @since 2.5 */ class FinderIndexerToken { /** * This is the term that will be referenced in the terms table and the * mapping tables. * * @var string * @since 2.5 */ public $term; /** * The stem is used to match the root term and produce more potential * matches when searching the index. * * @var string * @since 2.5 */ public $stem; /** * If the token is numeric, it is likely to be short and uncommon so the * weight is adjusted to compensate for that situation. * * @var boolean * @since 2.5 */ public $numeric; /** * If the token is a common term, the weight is adjusted to compensate for * the higher frequency of the term in relation to other terms. * * @var boolean * @since 2.5 */ public $common; /** * Flag for phrase tokens. * * @var boolean * @since 2.5 */ public $phrase; /** * The length is used to calculate the weight of the token. * * @var integer * @since 2.5 */ public $length; /** * The weight is calculated based on token size and whether the token is * considered a common term. * * @var integer * @since 2.5 */ public $weight; /** * The simple language identifier for the token. * * @var string * @since 2.5 */ public $language; /** * The container for matches. * * @var array * @since 3.8.12 */ public $matches = array(); /** * Is derived token (from individual words) * * @var boolean * @since 3.8.12 */ public $derived; /** * The suggested term * * @var string * @since 3.8.12 */ public $suggestion; /** * Method to construct the token object. * * @param mixed $term The term as a string for words or an array for phrases. * @param string $lang The simple language identifier. * @param string $spacer The space separator for phrases. [optional] * * @since 2.5 */ public function __construct($term, $lang, $spacer = ' ') { $this->language = $lang; // Tokens can be a single word or an array of words representing a phrase. if (is_array($term)) { // Populate the token instance. $this->term = implode($spacer, $term); $this->stem = implode($spacer, array_map(array('FinderIndexerHelper', 'stem'), $term, array($lang))); $this->numeric = false; $this->common = false; $this->phrase = true; $this->length = StringHelper::strlen($this->term); /* * Calculate the weight of the token. * * 1. Length of the token up to 30 and divide by 30, add 1. * 2. Round weight to 4 decimal points. */ $this->weight = (($this->length >= 30 ? 30 : $this->length) / 30) + 1; $this->weight = round($this->weight, 4); } else { // Populate the token instance. $this->term = $term; $this->stem = FinderIndexerHelper::stem($this->term, $lang); $this->numeric = (is_numeric($this->term) || (bool) preg_match('#^[0-9,.\-\+]+$#', $this->term)); $this->common = $this->numeric ? false : FinderIndexerHelper::isCommon($this->term, $lang); $this->phrase = false; $this->length = StringHelper::strlen($this->term); /* * Calculate the weight of the token. * * 1. Length of the token up to 15 and divide by 15. * 2. If common term, divide weight by 8. * 3. If numeric, multiply weight by 1.5. * 4. Round weight to 4 decimal points. */ $this->weight = ($this->length >= 15 ? 15 : $this->length) / 15; $this->weight = $this->common === true ? $this->weight / 8 : $this->weight; $this->weight = $this->numeric === true ? $this->weight * 1.5 : $this->weight; $this->weight = round($this->weight, 4); } } } indexer/parser/txt.php 0000604 00000001336 15245570236 0011036 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('FinderIndexerParser', dirname(__DIR__) . '/parser.php'); /** * Text Parser class for the Finder indexer package. * * @since 2.5 */ class FinderIndexerParserTxt extends FinderIndexerParser { /** * Method to process Text input and extract the plain text. * * @param string $input The input to process. * * @return string The plain text input. * * @since 2.5 */ protected function process($input) { return $input; } } indexer/parser/html.php 0000604 00000010556 15245570236 0011167 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('FinderIndexerParser', dirname(__DIR__) . '/parser.php'); /** * HTML Parser class for the Finder indexer package. * * @since 2.5 */ class FinderIndexerParserHtml extends FinderIndexerParser { /** * Method to parse input and extract the plain text. Because this method is * called from both inside and outside the indexer, it needs to be able to * batch out its parsing functionality to deal with the inefficiencies of * regular expressions. We will parse recursively in 2KB chunks. * * @param string $input The input to parse. * * @return string The plain text input. * * @since 2.5 */ public function parse($input) { // Strip invalid UTF-8 characters. $input = iconv('utf-8', 'utf-8//IGNORE', $input); // Remove anything between <head> and </head> tags. Do this first // because there might be <script> or <style> tags nested inside. $input = $this->removeBlocks($input, '<head>', '</head>'); // Convert <style> and <noscript> tags to <script> tags // so we can remove them efficiently. $search = array( '<style', '</style', '<noscript', '</noscript', ); $replace = array( '<script', '</script', '<script', '</script', ); $input = str_replace($search, $replace, $input); // Strip all script blocks. $input = $this->removeBlocks($input, '<script', '</script>'); // Decode HTML entities. $input = html_entity_decode($input, ENT_QUOTES, 'UTF-8'); // Convert entities equivalent to spaces to actual spaces. $input = str_replace(array(' ', ' '), ' ', $input); // Add a space before both the OPEN and CLOSE tags of BLOCK and LINE BREAKING elements, // e.g. 'all<h1><em>m</em>obile List</h1>' will become 'all mobile List' $input = preg_replace('/(<|<\/)(' . 'address|article|aside|blockquote|br|canvas|dd|div|dl|dt|' . 'fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hgroup|hr|li|' . 'main|nav|noscript|ol|output|p|pre|section|table|tfoot|ul|video' . ')\b/i', ' $1$2', $input ); // Strip HTML tags. $input = strip_tags($input); return parent::parse($input); } /** * Method to process HTML input and extract the plain text. * * @param string $input The input to process. * * @return string The plain text input. * * @since 2.5 */ protected function process($input) { // Replace any amount of white space with a single space. return preg_replace('#\s+#u', ' ', $input); } /** * Method to remove blocks of text between a start and an end tag. * Each block removed is effectively replaced by a single space. * * Note: The start tag and the end tag must be different. * Note: Blocks must not be nested. * Note: This method will function correctly with multi-byte strings. * * @param string $input String to be processed. * @param string $startTag String representing the start tag. * @param string $endTag String representing the end tag. * * @return string with blocks removed. * * @since 3.4 */ private function removeBlocks($input, $startTag, $endTag) { $return = ''; $offset = 0; $startTagLength = strlen($startTag); $endTagLength = strlen($endTag); // Find the first start tag. $start = stripos($input, $startTag); // If no start tags were found, return the string unchanged. if ($start === false) { return $input; } // Look for all blocks defined by the start and end tags. while ($start !== false) { // Accumulate the substring up to the start tag. $return .= substr($input, $offset, $start - $offset) . ' '; // Look for an end tag corresponding to the start tag. $end = stripos($input, $endTag, $start + $startTagLength); // If no corresponding end tag, leave the string alone. if ($end === false) { // Fix the offset so part of the string is not duplicated. $offset = $start; break; } // Advance the start position. $offset = $end + $endTagLength; // Look for the next start tag and loop. $start = stripos($input, $startTag, $offset); } // Add in the final substring after the last end tag. $return .= substr($input, $offset); return $return; } } indexer/parser/rtf.php 0000604 00000002040 15245570236 0011003 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('FinderIndexerParser', dirname(__DIR__) . '/parser.php'); /** * RTF Parser class for the Finder indexer package. * * @since 2.5 */ class FinderIndexerParserRtf extends FinderIndexerParser { /** * Method to process RTF input and extract the plain text. * * @param string $input The input to process. * * @return string The plain text input. * * @since 2.5 */ protected function process($input) { // Remove embedded pictures. $input = preg_replace('#{\\\pict[^}]*}#mi', '', $input); // Remove control characters. $input = str_replace(array('{', '}', "\\\n"), array(' ', ' ', "\n"), $input); $input = preg_replace('#\\\([^;]+?);#m', ' ', $input); $input = preg_replace('#\\\[\'a-zA-Z0-9]+#mi', ' ', $input); return $input; } } indexer/helper.php 0000604 00000034247 15245570236 0010211 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Registry\Registry; use Joomla\String\StringHelper; JLoader::register('FinderIndexerParser', __DIR__ . '/parser.php'); JLoader::register('FinderIndexerStemmer', __DIR__ . '/stemmer.php'); JLoader::register('FinderIndexerToken', __DIR__ . '/token.php'); /** * Helper class for the Finder indexer package. * * @since 2.5 */ class FinderIndexerHelper { /** * The token stemmer object. The stemmer is set by whatever class * wishes to use it but it must be an instance of FinderIndexerStemmer. * * @var FinderIndexerStemmer * @since 2.5 */ public static $stemmer; /** * A state flag, in order to not constantly check if the stemmer is an instance of FinderIndexerStemmer * * @var boolean * @since 3.7.0 */ protected static $stemmerOK; /** * Method to parse input into plain text. * * @param string $input The raw input. * @param string $format The format of the input. [optional] * * @return string The parsed input. * * @since 2.5 * @throws Exception on invalid parser. */ public static function parse($input, $format = 'html') { // Get a parser for the specified format and parse the input. return FinderIndexerParser::getInstance($format)->parse($input); } /** * Method to tokenize a text string. * * @param string $input The input to tokenize. * @param string $lang The language of the input. * @param boolean $phrase Flag to indicate whether input could be a phrase. [optional] * * @return array|FinderIndexerToken An array of FinderIndexerToken objects or a single FinderIndexerToken object. * * @since 2.5 */ public static function tokenize($input, $lang, $phrase = false) { static $cache; $store = StringHelper::strlen($input) < 128 ? md5($input . '::' . $lang . '::' . $phrase) : null; // Check if the string has been tokenized already. if ($store && isset($cache[$store])) { return $cache[$store]; } $tokens = array(); $quotes = html_entity_decode('‘’'', ENT_QUOTES, 'UTF-8'); // Get the simple language key. $lang = static::getPrimaryLanguage($lang); /* * Parsing the string input into terms is a multi-step process. * * Regexes: * 1. Remove everything except letters, numbers, quotes, apostrophe, plus, dash, period, and comma. * 2. Remove plus, dash, period, and comma characters located before letter characters. * 3. Remove plus, dash, period, and comma characters located after other characters. * 4. Remove plus, period, and comma characters enclosed in alphabetical characters. Ungreedy. * 5. Remove orphaned apostrophe, plus, dash, period, and comma characters. * 6. Remove orphaned quote characters. * 7. Replace the assorted single quotation marks with the ASCII standard single quotation. * 8. Remove multiple space characters and replaces with a single space. */ $input = StringHelper::strtolower($input); $input = preg_replace('#[^\pL\pM\pN\p{Pi}\p{Pf}\'+-.,]+#mui', ' ', $input); $input = preg_replace('#(^|\s)[+-.,]+([\pL\pM]+)#mui', ' $1', $input); $input = preg_replace('#([\pL\pM\pN]+)[+-.,]+(\s|$)#mui', '$1 ', $input); $input = preg_replace('#([\pL\pM]+)[+.,]+([\pL\pM]+)#muiU', '$1 $2', $input); $input = preg_replace('#(^|\s)[\'+-.,]+(\s|$)#mui', ' ', $input); $input = preg_replace('#(^|\s)[\p{Pi}\p{Pf}]+(\s|$)#mui', ' ', $input); $input = preg_replace('#[' . $quotes . ']+#mui', '\'', $input); $input = preg_replace('#\s+#mui', ' ', $input); $input = trim($input); // Explode the normalized string to get the terms. $terms = explode(' ', $input); /* * If we have Unicode support and are dealing with Chinese text, Chinese * has to be handled specially because there are not necessarily any spaces * between the "words". So, we have to test if the words belong to the Chinese * character set and if so, explode them into single glyphs or "words". */ if ($lang === 'zh') { // Iterate through the terms and test if they contain Chinese. for ($i = 0, $n = count($terms); $i < $n; $i++) { $charMatches = array(); $charCount = preg_match_all('#[\p{Han}]#mui', $terms[$i], $charMatches); // Split apart any groups of Chinese characters. for ($j = 0; $j < $charCount; $j++) { $tSplit = StringHelper::str_ireplace($charMatches[0][$j], '', $terms[$i], false); if ((bool) $tSplit) { $terms[$i] = $tSplit; } else { unset($terms[$i]); } $terms[] = $charMatches[0][$j]; } } // Reset array keys. $terms = array_values($terms); } /* * If we have to handle the input as a phrase, that means we don't * tokenize the individual terms and we do not create the two and three * term combinations. The phrase must contain more than one word! */ if ($phrase === true && count($terms) > 1) { // Create tokens from the phrase. $tokens[] = new FinderIndexerToken($terms, $lang); } else { // Create tokens from the terms. for ($i = 0, $n = count($terms); $i < $n; $i++) { $tokens[] = new FinderIndexerToken($terms[$i], $lang); } // Create two and three word phrase tokens from the individual words. for ($i = 0, $n = count($tokens); $i < $n; $i++) { // Setup the phrase positions. $i2 = $i + 1; $i3 = $i + 2; // Create the two word phrase. if ($i2 < $n && isset($tokens[$i2])) { // Tokenize the two word phrase. $token = new FinderIndexerToken( array( $tokens[$i]->term, $tokens[$i2]->term ), $lang, $lang === 'zh' ? '' : ' ' ); $token->derived = true; // Add the token to the stack. $tokens[] = $token; } // Create the three word phrase. if ($i3 < $n && isset($tokens[$i3])) { // Tokenize the three word phrase. $token = new FinderIndexerToken( array( $tokens[$i]->term, $tokens[$i2]->term, $tokens[$i3]->term ), $lang, $lang === 'zh' ? '' : ' ' ); $token->derived = true; // Add the token to the stack. $tokens[] = $token; } } } if ($store) { $cache[$store] = count($tokens) > 1 ? $tokens : array_shift($tokens); return $cache[$store]; } else { return count($tokens) > 1 ? $tokens : array_shift($tokens); } } /** * Method to get the base word of a token. This method uses the public * {@link FinderIndexerHelper::$stemmer} object if it is set. If no stemmer is set, * the original token is returned. * * @param string $token The token to stem. * @param string $lang The language of the token. * * @return string The root token. * * @since 2.5 */ public static function stem($token, $lang) { // Trim apostrophes at either end of the token. $token = trim($token, '\''); // Trim everything after any apostrophe in the token. if ($res = explode('\'', $token)) { $token = $res[0]; } if (static::$stemmerOK === true) { return static::$stemmer->stem($token, $lang); } else { // Stem the token if we have a valid stemmer to use. if (static::$stemmer instanceof FinderIndexerStemmer) { static::$stemmerOK = true; return static::$stemmer->stem($token, $lang); } } return $token; } /** * Method to add a content type to the database. * * @param string $title The type of content. For example: PDF * @param string $mime The mime type of the content. For example: PDF [optional] * * @return integer The id of the content type. * * @since 2.5 * @throws Exception on database error. */ public static function addContentType($title, $mime = null) { static $types; $db = JFactory::getDbo(); $query = $db->getQuery(true); // Check if the types are loaded. if (empty($types)) { // Build the query to get the types. $query->select('*') ->from($db->quoteName('#__finder_types')); // Get the types. $db->setQuery($query); $types = $db->loadObjectList('title'); } // Check if the type already exists. if (isset($types[$title])) { return (int) $types[$title]->id; } // Add the type. $query->clear() ->insert($db->quoteName('#__finder_types')) ->columns(array($db->quoteName('title'), $db->quoteName('mime'))) ->values($db->quote($title) . ', ' . $db->quote($mime)); $db->setQuery($query); $db->execute(); // Return the new id. return (int) $db->insertid(); } /** * Method to check if a token is common in a language. * * @param string $token The token to test. * @param string $lang The language to reference. * * @return boolean True if common, false otherwise. * * @since 2.5 */ public static function isCommon($token, $lang) { static $data; static $default; $langCode = $lang; // If language requested is wildcard, use the default language. if ($default === null && $lang === '*') { $default = strstr(self::getDefaultLanguage(), '-', true); $langCode = $default; } // Load the common tokens for the language if necessary. if (!isset($data[$langCode])) { $data[$langCode] = self::getCommonWords($langCode); } // Check if the token is in the common array. return in_array($token, $data[$langCode], true); } /** * Method to get an array of common terms for a language. * * @param string $lang The language to use. * * @return array Array of common terms. * * @since 2.5 * @throws Exception on database error. */ public static function getCommonWords($lang) { $db = JFactory::getDbo(); // Create the query to load all the common terms for the language. $query = $db->getQuery(true) ->select($db->quoteName('term')) ->from($db->quoteName('#__finder_terms_common')) ->where($db->quoteName('language') . ' = ' . $db->quote($lang)); // Load all of the common terms for the language. $db->setQuery($query); return $db->loadColumn(); } /** * Method to get the default language for the site. * * @return string The default language string. * * @since 2.5 */ public static function getDefaultLanguage() { static $lang; // We need to go to com_languages to get the site default language, it's the best we can guess. if (empty($lang)) { $lang = JComponentHelper::getParams('com_languages')->get('site', 'en-GB'); } return $lang; } /** * Method to parse a language/locale key and return a simple language string. * * @param string $lang The language/locale key. For example: en-GB * * @return string The simple language string. For example: en * * @since 2.5 */ public static function getPrimaryLanguage($lang) { static $data; // Only parse the identifier if necessary. if (!isset($data[$lang])) { if (is_callable(array('Locale', 'getPrimaryLanguage'))) { // Get the language key using the Locale package. $data[$lang] = Locale::getPrimaryLanguage($lang); } else { // Get the language key using string position. $data[$lang] = StringHelper::substr($lang, 0, StringHelper::strpos($lang, '-')); } } return $data[$lang]; } /** * Method to get the path (SEF route) for a content item. * * @param string $url The non-SEF route to the content item. * * @return string The path for the content item. * * @since 2.5 * @deprecated 4.0 */ public static function getContentPath($url) { static $router; // Only get the router once. if (!($router instanceof JRouter)) { // Get and configure the site router. $config = JFactory::getConfig(); $router = JRouter::getInstance('site'); $router->setMode($config->get('sef', 1)); } // Build the relative route. $uri = $router->build($url); $route = $uri->toString(array('path', 'query', 'fragment')); $route = str_replace(JUri::base(true) . '/', '', $route); return $route; } /** * Method to get extra data for a content before being indexed. This is how * we add Comments, Tags, Labels, etc. that should be available to Finder. * * @param FinderIndexerResult $item The item to index as a FinderIndexerResult object. * * @return boolean True on success, false on failure. * * @since 2.5 * @throws Exception on database error. */ public static function getContentExtras(FinderIndexerResult $item) { // Get the event dispatcher. $dispatcher = JEventDispatcher::getInstance(); // Load the finder plugin group. JPluginHelper::importPlugin('finder'); // Trigger the event. $results = $dispatcher->trigger('onPrepareFinderContent', array(&$item)); // Check the returned results. This is for plugins that don't throw // exceptions when they encounter serious errors. if (in_array(false, $results)) { throw new Exception($dispatcher->getError(), 500); } return true; } /** * Method to process content text using the onContentPrepare event trigger. * * @param string $text The content to process. * @param Registry $params The parameters object. [optional] * @param FinderIndexerResult $item The item which get prepared. [optional] * * @return string The processed content. * * @since 2.5 */ public static function prepareContent($text, $params = null, FinderIndexerResult $item = null) { static $loaded; // Get the dispatcher. $dispatcher = JEventDispatcher::getInstance(); // Load the content plugins if necessary. if (empty($loaded)) { JPluginHelper::importPlugin('content'); $loaded = true; } // Instantiate the parameter object if necessary. if (!($params instanceof Registry)) { $registry = new Registry($params); $params = $registry; } // Create a mock content object. $content = JTable::getInstance('Content'); $content->text = $text; if ($item) { $content->bind((array) $item); $content->bind($item->getElements()); } if ($item && !empty($item->context)) { $content->context = $item->context; } // Fire the onContentPrepare event. $dispatcher->trigger('onContentPrepare', array('com_finder.indexer', &$content, &$params, 0)); return $content->text; } } indexer/adapter.php 0000604 00000052672 15245570236 0010354 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Utilities\ArrayHelper; JLoader::register('FinderIndexer', __DIR__ . '/indexer.php'); JLoader::register('FinderIndexerHelper', __DIR__ . '/helper.php'); JLoader::register('FinderIndexerResult', __DIR__ . '/result.php'); JLoader::register('FinderIndexerTaxonomy', __DIR__ . '/taxonomy.php'); /** * Prototype adapter class for the Finder indexer package. * * @since 2.5 */ abstract class FinderIndexerAdapter extends JPlugin { /** * The context is somewhat arbitrary but it must be unique or there will be * conflicts when managing plugin/indexer state. A good best practice is to * use the plugin name suffix as the context. For example, if the plugin is * named 'plgFinderContent', the context could be 'Content'. * * @var string * @since 2.5 */ protected $context; /** * The extension name. * * @var string * @since 2.5 */ protected $extension; /** * The sublayout to use when rendering the results. * * @var string * @since 2.5 */ protected $layout; /** * The mime type of the content the adapter indexes. * * @var string * @since 2.5 */ protected $mime; /** * The access level of an item before save. * * @var integer * @since 2.5 */ protected $old_access; /** * The access level of a category before save. * * @var integer * @since 2.5 */ protected $old_cataccess; /** * The type of content the adapter indexes. * * @var string * @since 2.5 */ protected $type_title; /** * The type id of the content. * * @var integer * @since 2.5 */ protected $type_id; /** * The database object. * * @var object * @since 2.5 */ protected $db; /** * The table name. * * @var string * @since 2.5 */ protected $table; /** * The indexer object. * * @var FinderIndexer * @since 3.0 */ protected $indexer; /** * The field the published state is stored in. * * @var string * @since 2.5 */ protected $state_field = 'state'; /** * Method to instantiate the indexer adapter. * * @param object $subject The object to observe. * @param array $config An array that holds the plugin configuration. * * @since 2.5 */ public function __construct(&$subject, $config) { // Get the database object. $this->db = JFactory::getDbo(); // Call the parent constructor. parent::__construct($subject, $config); // Get the type id. $this->type_id = $this->getTypeId(); // Add the content type if it doesn't exist and is set. if (empty($this->type_id) && !empty($this->type_title)) { $this->type_id = FinderIndexerHelper::addContentType($this->type_title, $this->mime); } // Check for a layout override. if ($this->params->get('layout')) { $this->layout = $this->params->get('layout'); } // Get the indexer object $this->indexer = FinderIndexer::getInstance(); } /** * Method to get the adapter state and push it into the indexer. * * @return void * * @since 2.5 * @throws Exception on error. */ public function onStartIndex() { // Get the indexer state. $iState = FinderIndexer::getState(); // Get the number of content items. $total = (int) $this->getContentCount(); // Add the content count to the total number of items. $iState->totalItems += $total; // Populate the indexer state information for the adapter. $iState->pluginState[$this->context]['total'] = $total; $iState->pluginState[$this->context]['offset'] = 0; // Set the indexer state. FinderIndexer::setState($iState); } /** * Method to prepare for the indexer to be run. This method will often * be used to include dependencies and things of that nature. * * @return boolean True on success. * * @since 2.5 * @throws Exception on error. */ public function onBeforeIndex() { // Get the indexer and adapter state. $iState = FinderIndexer::getState(); $aState = $iState->pluginState[$this->context]; // Check the progress of the indexer and the adapter. if ($iState->batchOffset == $iState->batchSize || $aState['offset'] == $aState['total']) { return true; } // Run the setup method. return $this->setup(); } /** * Method to index a batch of content items. This method can be called by * the indexer many times throughout the indexing process depending on how * much content is available for indexing. It is important to track the * progress correctly so we can display it to the user. * * @return boolean True on success. * * @since 2.5 * @throws Exception on error. */ public function onBuildIndex() { // Get the indexer and adapter state. $iState = FinderIndexer::getState(); $aState = $iState->pluginState[$this->context]; // Check the progress of the indexer and the adapter. if ($iState->batchOffset == $iState->batchSize || $aState['offset'] == $aState['total']) { return true; } // Get the batch offset and size. $offset = (int) $aState['offset']; $limit = (int) ($iState->batchSize - $iState->batchOffset); // Get the content items to index. $items = $this->getItems($offset, $limit); // Iterate through the items and index them. for ($i = 0, $n = count($items); $i < $n; $i++) { // Index the item. $this->index($items[$i]); // Adjust the offsets. $offset++; $iState->batchOffset++; $iState->totalItems--; } // Update the indexer state. $aState['offset'] = $offset; $iState->pluginState[$this->context] = $aState; FinderIndexer::setState($iState); return true; } /** * Method to change the value of a content item's property in the links * table. This is used to synchronize published and access states that * are changed when not editing an item directly. * * @param string $id The ID of the item to change. * @param string $property The property that is being changed. * @param integer $value The new value of that property. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ protected function change($id, $property, $value) { // Check for a property we know how to handle. if ($property !== 'state' && $property !== 'access') { return true; } // Get the URL for the content id. $item = $this->db->quote($this->getUrl($id, $this->extension, $this->layout)); // Update the content items. $query = $this->db->getQuery(true) ->update($this->db->quoteName('#__finder_links')) ->set($this->db->quoteName($property) . ' = ' . (int) $value) ->where($this->db->quoteName('url') . ' = ' . $item); $this->db->setQuery($query); $this->db->execute(); return true; } /** * Method to index an item. * * @param FinderIndexerResult $item The item to index as a FinderIndexerResult object. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ abstract protected function index(FinderIndexerResult $item); /** * Method to reindex an item. * * @param integer $id The ID of the item to reindex. * * @return void * * @since 2.5 * @throws Exception on database error. */ protected function reindex($id) { // Run the setup method. $this->setup(); // Remove the old item. $this->remove($id); // Get the item. $item = $this->getItem($id); // Index the item. $this->index($item); } /** * Method to remove an item from the index. * * @param string $id The ID of the item to remove. * * @return boolean True on success. * * @since 2.5 * @throws Exception on database error. */ protected function remove($id) { // Get the item's URL $url = $this->db->quote($this->getUrl($id, $this->extension, $this->layout)); // Get the link ids for the content items. $query = $this->db->getQuery(true) ->select($this->db->quoteName('link_id')) ->from($this->db->quoteName('#__finder_links')) ->where($this->db->quoteName('url') . ' = ' . $url); $this->db->setQuery($query); $items = $this->db->loadColumn(); // Check the items. if (empty($items)) { return true; } // Remove the items. foreach ($items as $item) { $this->indexer->remove($item); } return true; } /** * Method to setup the adapter before indexing. * * @return boolean True on success, false on failure. * * @since 2.5 * @throws Exception on database error. */ abstract protected function setup(); /** * Method to update index data on category access level changes * * @param JTable $row A JTable object * * @return void * * @since 2.5 */ protected function categoryAccessChange($row) { $query = clone $this->getStateQuery(); $query->where('c.id = ' . (int) $row->id); // Get the access level. $this->db->setQuery($query); $items = $this->db->loadObjectList(); // Adjust the access level for each item within the category. foreach ($items as $item) { // Set the access level. $temp = max($item->access, $row->access); // Update the item. $this->change((int) $item->id, 'access', $temp); // Reindex the item $this->reindex($row->id); } } /** * Method to update index data on category access level changes * * @param array $pks A list of primary key ids of the content that has changed state. * @param integer $value The value of the state that the content has been changed to. * * @return void * * @since 2.5 */ protected function categoryStateChange($pks, $value) { /* * The item's published state is tied to the category * published state so we need to look up all published states * before we change anything. */ foreach ($pks as $pk) { $query = clone $this->getStateQuery(); $query->where('c.id = ' . (int) $pk); // Get the published states. $this->db->setQuery($query); $items = $this->db->loadObjectList(); // Adjust the state for each item within the category. foreach ($items as $item) { // Translate the state. $temp = $this->translateState($item->state, $value); // Update the item. $this->change($item->id, 'state', $temp); // Reindex the item $this->reindex($item->id); } } } /** * Method to check the existing access level for categories * * @param JTable $row A JTable object * * @return void * * @since 2.5 */ protected function checkCategoryAccess($row) { $query = $this->db->getQuery(true) ->select($this->db->quoteName('access')) ->from($this->db->quoteName('#__categories')) ->where($this->db->quoteName('id') . ' = ' . (int) $row->id); $this->db->setQuery($query); // Store the access level to determine if it changes $this->old_cataccess = $this->db->loadResult(); } /** * Method to check the existing access level for items * * @param JTable $row A JTable object * * @return void * * @since 2.5 */ protected function checkItemAccess($row) { $query = $this->db->getQuery(true) ->select($this->db->quoteName('access')) ->from($this->db->quoteName($this->table)) ->where($this->db->quoteName('id') . ' = ' . (int) $row->id); $this->db->setQuery($query); // Store the access level to determine if it changes $this->old_access = $this->db->loadResult(); } /** * Method to get the number of content items available to index. * * @return integer The number of content items available to index. * * @since 2.5 * @throws Exception on database error. */ protected function getContentCount() { $return = 0; // Get the list query. $query = $this->getListQuery(); // Check if the query is valid. if (empty($query)) { return $return; } // Tweak the SQL query to make the total lookup faster. if ($query instanceof JDatabaseQuery) { $query = clone $query; $query->clear('select') ->select('COUNT(*)') ->clear('order'); } // Get the total number of content items to index. $this->db->setQuery($query); return (int) $this->db->loadResult(); } /** * Method to get a content item to index. * * @param integer $id The id of the content item. * * @return FinderIndexerResult A FinderIndexerResult object. * * @since 2.5 * @throws Exception on database error. */ protected function getItem($id) { // Get the list query and add the extra WHERE clause. $query = $this->getListQuery(); $query->where('a.id = ' . (int) $id); // Get the item to index. $this->db->setQuery($query); $row = $this->db->loadAssoc(); // Convert the item to a result object. $item = ArrayHelper::toObject((array) $row, 'FinderIndexerResult'); // Set the item type. $item->type_id = $this->type_id; // Set the item layout. $item->layout = $this->layout; return $item; } /** * Method to get a list of content items to index. * * @param integer $offset The list offset. * @param integer $limit The list limit. * @param JDatabaseQuery $query A JDatabaseQuery object. [optional] * * @return array An array of FinderIndexerResult objects. * * @since 2.5 * @throws Exception on database error. */ protected function getItems($offset, $limit, $query = null) { $items = array(); // Get the content items to index. $this->db->setQuery($this->getListQuery($query), $offset, $limit); $rows = $this->db->loadAssocList(); // Convert the items to result objects. foreach ($rows as $row) { // Convert the item to a result object. $item = ArrayHelper::toObject((array) $row, 'FinderIndexerResult'); // Set the item type. $item->type_id = $this->type_id; // Set the mime type. $item->mime = $this->mime; // Set the item layout. $item->layout = $this->layout; // Set the extension if present if (isset($row->extension)) { $item->extension = $row->extension; } // Add the item to the stack. $items[] = $item; } return $items; } /** * Method to get the SQL query used to retrieve the list of content items. * * @param mixed $query A JDatabaseQuery object. [optional] * * @return JDatabaseQuery A database object. * * @since 2.5 */ protected function getListQuery($query = null) { // Check if we can use the supplied SQL query. return $query instanceof JDatabaseQuery ? $query : $this->db->getQuery(true); } /** * Method to get the plugin type * * @param integer $id The plugin ID * * @return string The plugin type * * @since 2.5 */ protected function getPluginType($id) { // Prepare the query $query = $this->db->getQuery(true) ->select($this->db->quoteName('element')) ->from($this->db->quoteName('#__extensions')) ->where($this->db->quoteName('extension_id') . ' = ' . (int) $id); $this->db->setQuery($query); return $this->db->loadResult(); } /** * Method to get a SQL query to load the published and access states for * an article and category. * * @return JDatabaseQuery A database object. * * @since 2.5 */ protected function getStateQuery() { $query = $this->db->getQuery(true); // Item ID $query->select('a.id'); // Item and category published state $query->select('a.' . $this->state_field . ' AS state, c.published AS cat_state'); // Item and category access levels $query->select('a.access, c.access AS cat_access') ->from($this->table . ' AS a') ->join('LEFT', '#__categories AS c ON c.id = a.catid'); return $query; } /** * Method to get the query clause for getting items to update by time. * * @param string $time The modified timestamp. * * @return JDatabaseQuery A database object. * * @since 2.5 */ protected function getUpdateQueryByTime($time) { // Build an SQL query based on the modified time. $query = $this->db->getQuery(true) ->where('a.modified >= ' . $this->db->quote($time)); return $query; } /** * Method to get the query clause for getting items to update by id. * * @param array $ids The ids to load. * * @return JDatabaseQuery A database object. * * @since 2.5 */ protected function getUpdateQueryByIds($ids) { // Build an SQL query based on the item ids. $query = $this->db->getQuery(true) ->where('a.id IN(' . implode(',', $ids) . ')'); return $query; } /** * Method to get the type id for the adapter content. * * @return integer The numeric type id for the content. * * @since 2.5 * @throws Exception on database error. */ protected function getTypeId() { // Get the type id from the database. $query = $this->db->getQuery(true) ->select($this->db->quoteName('id')) ->from($this->db->quoteName('#__finder_types')) ->where($this->db->quoteName('title') . ' = ' . $this->db->quote($this->type_title)); $this->db->setQuery($query); return (int) $this->db->loadResult(); } /** * Method to get the URL for the item. The URL is how we look up the link * in the Finder index. * * @param integer $id The id of the item. * @param string $extension The extension the category is in. * @param string $view The view for the URL. * * @return string The URL of the item. * * @since 2.5 */ protected function getUrl($id, $extension, $view) { return 'index.php?option=' . $extension . '&view=' . $view . '&id=' . $id; } /** * Method to get the page title of any menu item that is linked to the * content item, if it exists and is set. * * @param string $url The URL of the item. * * @return mixed The title on success, null if not found. * * @since 2.5 * @throws Exception on database error. */ protected function getItemMenuTitle($url) { $return = null; // Set variables $user = JFactory::getUser(); $groups = implode(',', $user->getAuthorisedViewLevels()); // Build a query to get the menu params. $query = $this->db->getQuery(true) ->select($this->db->quoteName('params')) ->from($this->db->quoteName('#__menu')) ->where($this->db->quoteName('link') . ' = ' . $this->db->quote($url)) ->where($this->db->quoteName('published') . ' = 1') ->where($this->db->quoteName('access') . ' IN (' . $groups . ')'); // Get the menu params from the database. $this->db->setQuery($query); $params = $this->db->loadResult(); // Check the results. if (empty($params)) { return $return; } // Instantiate the params. $params = json_decode($params); // Get the page title if it is set. if (isset($params->page_title) && $params->page_title) { $return = $params->page_title; } return $return; } /** * Method to update index data on access level changes * * @param JTable $row A JTable object * * @return void * * @since 2.5 */ protected function itemAccessChange($row) { $query = clone $this->getStateQuery(); $query->where('a.id = ' . (int) $row->id); // Get the access level. $this->db->setQuery($query); $item = $this->db->loadObject(); // Set the access level. $temp = max($row->access, $item->cat_access); // Update the item. $this->change((int) $row->id, 'access', $temp); } /** * Method to update index data on published state changes * * @param array $pks A list of primary key ids of the content that has changed state. * @param integer $value The value of the state that the content has been changed to. * * @return void * * @since 2.5 */ protected function itemStateChange($pks, $value) { /* * The item's published state is tied to the category * published state so we need to look up all published states * before we change anything. */ foreach ($pks as $pk) { $query = clone $this->getStateQuery(); $query->where('a.id = ' . (int) $pk); // Get the published states. $this->db->setQuery($query); $item = $this->db->loadObject(); // Translate the state. $temp = $this->translateState($value, $item->cat_state); // Update the item. $this->change($pk, 'state', $temp); // Reindex the item $this->reindex($pk); } } /** * Method to update index data when a plugin is disabled * * @param array $pks A list of primary key ids of the content that has changed state. * * @return void * * @since 2.5 */ protected function pluginDisable($pks) { // Since multiple plugins may be disabled at a time, we need to check first // that we're handling the appropriate one for the context foreach ($pks as $pk) { if ($this->getPluginType($pk) == strtolower($this->context)) { // Get all of the items to unindex them $query = clone $this->getStateQuery(); $this->db->setQuery($query); $items = $this->db->loadColumn(); // Remove each item foreach ($items as $item) { $this->remove($item); } } } } /** * Method to translate the native content states into states that the * indexer can use. * * @param integer $item The item state. * @param integer $category The category state. [optional] * * @return integer The translated indexer state. * * @since 2.5 */ protected function translateState($item, $category = null) { // If category is present, factor in its states as well if ($category !== null && $category == 0) { $item = 0; } // Translate the state switch ($item) { // Published and archived items only should return a published state case 1; case 2: return 1; // All other states should return an unpublished state default: case 0: return 0; } } } indexer/parser.php 0000604 00000005717 15245570236 0010226 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Parser base class for the Finder indexer package. * * @since 2.5 */ abstract class FinderIndexerParser { /** * Method to get a parser, creating it if necessary. * * @param string $format The type of parser to load. * * @return FinderIndexerParser A FinderIndexerParser instance. * * @since 2.5 * @throws Exception on invalid parser. */ public static function getInstance($format) { static $instances; // Only create one parser for each format. if (isset($instances[$format])) { return $instances[$format]; } // Create an array of instances if necessary. if (!is_array($instances)) { $instances = array(); } // Setup the adapter for the parser. $format = JFilterInput::getInstance()->clean($format, 'cmd'); $path = __DIR__ . '/parser/' . $format . '.php'; $class = 'FinderIndexerParser' . ucfirst($format); // Check if a parser exists for the format. if (!file_exists($path)) { // Throw invalid format exception. throw new Exception(JText::sprintf('COM_FINDER_INDEXER_INVALID_PARSER', $format)); } // Instantiate the parser. JLoader::register($class, $path); $instances[$format] = new $class; return $instances[$format]; } /** * Method to parse input and extract the plain text. Because this method is * called from both inside and outside the indexer, it needs to be able to * batch out its parsing functionality to deal with the inefficiencies of * regular expressions. We will parse recursively in 2KB chunks. * * @param string $input The input to parse. * * @return string The plain text input. * * @since 2.5 */ public function parse($input) { // If the input is less than 2KB we can parse it in one go. if (strlen($input) <= 2048) { return $this->process($input); } // Input is longer than 2Kb so parse it in chunks of 2Kb or less. $start = 0; $end = strlen($input); $chunk = 2048; $return = null; while ($start < $end) { // Setup the string. $string = substr($input, $start, $chunk); // Find the last space character if we aren't at the end. $ls = (($start + $chunk) < $end ? strrpos($string, ' ') : false); // Truncate to the last space character. if ($ls !== false) { $string = substr($string, 0, $ls); } // Adjust the start position for the next iteration. $start += ($ls !== false ? ($ls + 1 - $chunk) + $chunk : $chunk); // Parse the chunk. $return .= $this->process($string); } return $return; } /** * Method to process input and extract the plain text. * * @param string $input The input to process. * * @return string The plain text input. * * @since 2.5 */ abstract protected function process($input); } indexer/stemmer.php 0000604 00000003566 15245570236 0010406 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Stemmer base class for the Finder indexer package. * * @since 2.5 */ abstract class FinderIndexerStemmer { /** * An internal cache of stemmed tokens. * * @var array * @since 2.5 */ public $cache = array(); /** * Method to get a stemmer, creating it if necessary. * * @param string $adapter The type of stemmer to load. * * @return FinderIndexerStemmer A FinderIndexerStemmer instance. * * @since 2.5 * @throws Exception on invalid stemmer. */ public static function getInstance($adapter) { static $instances; // Only create one stemmer for each adapter. if (isset($instances[$adapter])) { return $instances[$adapter]; } // Create an array of instances if necessary. if (!is_array($instances)) { $instances = array(); } // Setup the adapter for the stemmer. $adapter = JFilterInput::getInstance()->clean($adapter, 'cmd'); $path = __DIR__ . '/stemmer/' . $adapter . '.php'; $class = 'FinderIndexerStemmer' . ucfirst($adapter); // Check if a stemmer exists for the adapter. if (!file_exists($path)) { // Throw invalid adapter exception. throw new Exception(JText::sprintf('COM_FINDER_INDEXER_INVALID_STEMMER', $adapter)); } // Instantiate the stemmer. JLoader::register($class, $path); $instances[$adapter] = new $class; return $instances[$adapter]; } /** * Method to stem a token and return the root. * * @param string $token The token to stem. * @param string $lang The language of the token. * * @return string The root token. * * @since 2.5 */ abstract public function stem($token, $lang); } finder.php 0000604 00000004503 15245570236 0006533 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Helper class for Finder. * * @since 2.5 */ class FinderHelper { /** * The extension name. * * @var string * @since 2.5 */ public static $extension = 'com_finder'; /** * Configure the Linkbar. * * @param string $vName The name of the active view. * * @return void * * @since 2.5 */ public static function addSubmenu($vName) { JHtmlSidebar::addEntry( JText::_('COM_FINDER_SUBMENU_INDEX'), 'index.php?option=com_finder&view=index', $vName === 'index' ); JHtmlSidebar::addEntry( JText::_('COM_FINDER_SUBMENU_MAPS'), 'index.php?option=com_finder&view=maps', $vName === 'maps' ); JHtmlSidebar::addEntry( JText::_('COM_FINDER_SUBMENU_FILTERS'), 'index.php?option=com_finder&view=filters', $vName === 'filters' ); } /** * Gets the finder system plugin extension id. * * @return integer The finder system plugin extension id. * * @since 3.6.0 */ public static function getFinderPluginId() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' = ' . $db->quote('content')) ->where($db->quoteName('element') . ' = ' . $db->quote('finder')); $db->setQuery($query); try { $result = (int) $db->loadResult(); } catch (RuntimeException $e) { JError::raiseWarning(500, $e->getMessage()); } return $result; } /** * Gets a list of the actions that can be performed. * * @return JObject A JObject containing the allowed actions. * * @since 2.5 * @deprecated 3.2 Use JHelperContent::getActions() instead */ public static function getActions() { // Log usage of deprecated function try { JLog::add( sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } // Get list of actions return JHelperContent::getActions('com_finder'); } } language.php 0000604 00000006026 15245570236 0007051 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_finder * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Finder language helper class. * * @since 2.5 */ class FinderHelperLanguage { /** * Method to return a plural language code for a taxonomy branch. * * @param string $branchName Branch title. * * @return string Language key code. * * @since 2.5 */ public static function branchPlural($branchName) { $return = preg_replace('/[^a-zA-Z0-9]+/', '_', strtoupper($branchName)); if ($return !== '_') { return 'PLG_FINDER_QUERY_FILTER_BRANCH_P_' . $return; } return $branchName; } /** * Method to return a singular language code for a taxonomy branch. * * @param string $branchName Branch name. * * @return string Language key code. * * @since 2.5 */ public static function branchSingular($branchName) { $return = preg_replace('/[^a-zA-Z0-9]+/', '_', strtoupper($branchName)); return 'PLG_FINDER_QUERY_FILTER_BRANCH_S_' . $return; } /** * Method to return the language name for a language taxonomy branch. * * @param string $branchName Language branch name. * * @return string The language title. * * @since 3.6.0 */ public static function branchLanguageTitle($branchName) { $title = $branchName; if ($branchName === '*') { $title = JText::_('JALL_LANGUAGE'); } else { $languages = JLanguageHelper::getLanguages('lang_code'); if (isset($languages[$branchName])) { $title = $languages[$branchName]->title; } } return $title; } /** * Method to load Smart Search component language file. * * @return void * * @since 2.5 */ public static function loadComponentLanguage() { JFactory::getLanguage()->load('com_finder', JPATH_SITE); } /** * Method to load Smart Search plugin language files. * * @return void * * @since 2.5 */ public static function loadPluginLanguage() { static $loaded = false; // If already loaded, don't load again. if ($loaded) { return; } $loaded = true; // Get array of all the enabled Smart Search plugin names. $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select(array($db->qn('name'), $db->qn('element'))) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('type') . ' = ' . $db->quote('plugin')) ->where($db->quoteName('folder') . ' = ' . $db->quote('finder')) ->where($db->quoteName('enabled') . ' = 1'); $db->setQuery($query); $plugins = $db->loadObjectList(); if (empty($plugins)) { return; } // Load generic language strings. $lang = JFactory::getLanguage(); $lang->load('plg_content_finder', JPATH_ADMINISTRATOR); // Load language file for each plugin. foreach ($plugins as $plugin) { $lang->load($plugin->name, JPATH_ADMINISTRATOR) || $lang->load($plugin->name, JPATH_PLUGINS . '/finder/' . $plugin->element); } } } site.php 0000604 00000001365 15245570246 0006234 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_search * * @copyright (C) 2007 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Mock JSite class used to fool the frontend search plugins because they route the results. * * @since 1.5 */ class JSite extends JObject { /** * False method to fool the frontend search plugins. * * @return JSite * * @since 1.5 */ public function getMenu() { $result = new JSite; return $result; } /** * False method to fool the frontend search plugins. * * @return array * * @since 1.5 */ public function getItems() { return array(); } } joomlaupdate.php 0000604 00000001666 15245570246 0007760 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_joomlaupdate * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Joomla! update helper. * * @since 2.5.4 */ class JoomlaupdateHelper { /** * Gets a list of the actions that can be performed. * * @return JObject * * @since 2.5.4 * @deprecated 3.2 Use JHelperContent::getActions() instead */ public static function getActions() { // Log usage of deprecated function try { JLog::add( sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } // Get list of actions return JHelperContent::getActions('com_joomlaupdate'); } } select.php 0000604 00000002326 15245570246 0006545 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_joomlaupdate * * @copyright (C) 2012 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Joomla! update selection list helper. * * @since 2.5.4 */ class JoomlaupdateHelperSelect { /** * Returns an HTML select element with the different extraction modes * * @param string $default The default value of the select element * @param string $name The name of the form field * @param string $id The id of the select field * * @return string * * @since 2.5.4 */ public static function getMethods($default = 'hybrid', $name = 'method', $id = 'extraction_method') { $options = array(); $options[] = JHtml::_('select.option', 'direct', JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_METHOD_DIRECT')); $options[] = JHtml::_('select.option', 'hybrid', JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_METHOD_HYBRID')); $options[] = JHtml::_('select.option', 'ftp', JText::_('COM_JOOMLAUPDATE_VIEW_DEFAULT_METHOD_FTP')); return JHtml::_('select.genericlist', $options, $name, '', 'value', 'text', $default, $id); } } html/messages.php 0000604 00000005222 15245570253 0010035 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_messages * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Utilities\ArrayHelper; /** * JHtml administrator messages class. * * @since 1.6 */ class JHtmlMessages { /** * Get the HTML code of the state switcher * * @param int $value The state value * @param int $i Row number * @param boolean $canChange Can the user change the state? * * @return string * * @since 1.6 * * @deprecated 4.0 Use JHtmlMessages::status() instead */ public static function state($value = 0, $i = 0, $canChange = false) { // Log deprecated message try { JLog::add( sprintf('%s() is deprecated. Use JHtmlMessages::status() instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } // Note: $i is required but has to be an optional argument in the function call due to argument order if (null === $i) { throw new InvalidArgumentException('$i is a required argument in JHtmlMessages::state'); } // Note: $canChange is required but has to be an optional argument in the function call due to argument order if (null === $canChange) { throw new InvalidArgumentException('$canChange is a required argument in JHtmlMessages::state'); } return static::status($i, $value, $canChange); } /** * Get the HTML code of the state switcher * * @param int $i Row number * @param int $value The state value * @param boolean $canChange Can the user change the state? * * @return string * * @since 3.4 */ public static function status($i, $value = 0, $canChange = false) { // Array of image, task, title, action. $states = array( -2 => array('trash', 'messages.unpublish', 'JTRASHED', 'COM_MESSAGES_MARK_AS_UNREAD'), 1 => array('publish', 'messages.unpublish', 'COM_MESSAGES_OPTION_READ', 'COM_MESSAGES_MARK_AS_UNREAD'), 0 => array('unpublish', 'messages.publish', 'COM_MESSAGES_OPTION_UNREAD', 'COM_MESSAGES_MARK_AS_READ'), ); $state = ArrayHelper::getValue($states, (int) $value, $states[0]); $icon = $state[0]; if ($canChange) { $html = '<a href="#" onclick="return listItemTask(\'cb' . $i . '\',\'' . $state[1] . '\')" class="btn btn-micro hasTooltip' . ($value == 1 ? ' active' : '') . '" title="' . JHtml::_('tooltipText', $state[3]) . '"><span class="icon-' . $icon . '" aria-hidden="true"></span></a>'; } return $html; } } messages.php 0000604 00000003554 15245570253 0007077 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_messages * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Messages helper class. * * @since 1.6 */ class MessagesHelper { /** * Configure the Linkbar. * * @param string $vName The name of the active view. * * @return void * * @since 1.6 */ public static function addSubmenu($vName) { JHtmlSidebar::addEntry( JText::_('COM_MESSAGES_ADD'), 'index.php?option=com_messages&view=message&layout=edit', $vName == 'message' ); JHtmlSidebar::addEntry( JText::_('COM_MESSAGES_READ'), 'index.php?option=com_messages', $vName == 'messages' ); } /** * Gets a list of the actions that can be performed. * * @return JObject * * @deprecated 3.2 Use JHelperContent::getActions() instead */ public static function getActions() { // Log usage of deprecated function try { JLog::add( sprintf('%s() is deprecated. Use JHelperContent::getActions() with new arguments order instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } // Get list of actions return JHelperContent::getActions('com_messages'); } /** * Get a list of filter options for the state of a module. * * @return array An array of JHtmlOption elements. * * @since 1.6 */ public static function getStateOptions() { // Build the filter options. $options = array(); $options[] = JHtml::_('select.option', '1', JText::_('COM_MESSAGES_OPTION_READ')); $options[] = JHtml::_('select.option', '0', JText::_('COM_MESSAGES_OPTION_UNREAD')); $options[] = JHtml::_('select.option', '-2', JText::_('JTRASHED')); return $options; } } html/newsfeed.php 0000604 00000004764 15245570602 0010036 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_newsfeeds * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('NewsfeedsHelper', JPATH_ADMINISTRATOR . '/components/com_newsfeeds/helpers/newsfeeds.php'); /** * Utility class for creating HTML Grids. * * @since 1.5 */ class JHtmlNewsfeed { /** * Get the associated language flags * * @param int $newsfeedid The item id to search associations * * @return string The language HTML * * @throws Exception Throws a 500 Exception on Database failure */ public static function association($newsfeedid) { // Defaults $html = ''; // Get the associations if ($associations = JLanguageAssociations::getAssociations('com_newsfeeds', '#__newsfeeds', 'com_newsfeeds.item', $newsfeedid)) { foreach ($associations as $tag => $associated) { $associations[$tag] = (int) $associated->id; } // Get the associated newsfeed items $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('c.id, c.name as title') ->select('l.sef as lang_sef, lang_code') ->from('#__newsfeeds as c') ->select('cat.title as category_title') ->join('LEFT', '#__categories as cat ON cat.id=c.catid') ->where('c.id IN (' . implode(',', array_values($associations)) . ')') ->where('c.id != ' . $newsfeedid) ->join('LEFT', '#__languages as l ON c.language=l.lang_code') ->select('l.image') ->select('l.title as language_title'); $db->setQuery($query); try { $items = $db->loadObjectList('id'); } catch (RuntimeException $e) { throw new Exception($e->getMessage(), 500); } if ($items) { foreach ($items as &$item) { $text = strtoupper($item->lang_sef); $url = JRoute::_('index.php?option=com_newsfeeds&task=newsfeed.edit&id=' . (int) $item->id); $tooltip = htmlspecialchars($item->title, ENT_QUOTES, 'UTF-8') . '<br />' . JText::sprintf('JCATEGORY_SPRINTF', $item->category_title); $classes = 'hasPopover label label-association label-' . $item->lang_sef; $item->link = '<a href="' . $url . '" title="' . $item->language_title . '" class="' . $classes . '" data-content="' . $tooltip . '" data-placement="top">' . $text . '</a>'; } } JHtml::_('bootstrap.popover'); $html = JLayoutHelper::render('joomla.content.associations', $items); } return $html; } } newsfeeds.php 0000604 00000003762 15245570602 0007252 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_newsfeeds * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Newsfeeds component helper. * * @since 1.6 */ class NewsfeedsHelper extends JHelperContent { public static $extension = 'com_newsfeeds'; /** * Configure the Linkbar. * * @param string $vName The name of the active view. * * @return void */ public static function addSubmenu($vName) { JHtmlSidebar::addEntry( JText::_('COM_NEWSFEEDS_SUBMENU_NEWSFEEDS'), 'index.php?option=com_newsfeeds&view=newsfeeds', $vName == 'newsfeeds' ); JHtmlSidebar::addEntry( JText::_('COM_NEWSFEEDS_SUBMENU_CATEGORIES'), 'index.php?option=com_categories&extension=com_newsfeeds', $vName == 'categories' ); } /** * Adds Count Items for Category Manager. * * @param stdClass[] &$items The category objects * * @return stdClass[] * * @since 3.5 */ public static function countItems(&$items) { $config = (object) array( 'related_tbl' => 'newsfeeds', 'state_col' => 'published', 'group_col' => 'catid', 'relation_type' => 'category_or_group', ); return parent::countRelations($items, $config); } /** * Adds Count Items for Tag Manager. * * @param stdClass[] &$items The tag objects * @param string $extension The name of the active view. * * @return stdClass[] * * @since 3.6 */ public static function countTagItems(&$items, $extension) { $parts = explode('.', $extension); $section = count($parts) > 1 ? $parts[1] : null; $config = (object) array( 'related_tbl' => ($section === 'category' ? 'categories' : 'newsfeeds'), 'state_col' => 'published', 'group_col' => 'tag_id', 'extension' => $extension, 'relation_type' => 'tag_assigments', ); return parent::countRelations($items, $config); } } mailto.php 0000604 00000003776 15245571224 0006562 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_mailto * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Mailto route helper class. * * @package Joomla.Site * @subpackage com_mailto * @since 1.6.1 */ abstract class MailtoHelper { /** * Adds a URL to the mailto system and returns the hash * * @param string $url Url * * @return string URL hash */ public static function addLink($url) { $hash = sha1($url); self::cleanHashes(); $session = JFactory::getSession(); $mailto_links = $session->get('com_mailto.links', array()); if (!isset($mailto_links[$hash])) { $mailto_links[$hash] = new stdClass; } $mailto_links[$hash]->link = $url; $mailto_links[$hash]->expiry = time(); $session->set('com_mailto.links', $mailto_links); return $hash; } /** * Checks if a URL is a Flash file * * @param string $hash File hash * * @return URL */ public static function validateHash($hash) { $retval = false; $session = JFactory::getSession(); self::cleanHashes(); $mailto_links = $session->get('com_mailto.links', array()); if (isset($mailto_links[$hash])) { $retval = $mailto_links[$hash]->link; } return $retval; } /** * Cleans out old hashes * * @param integer $lifetime How old are the hashes we want to remove * * @return void * * @since 1.6.1 */ public static function cleanHashes($lifetime = 1440) { // Flag for if we've cleaned on this cycle static $cleaned = false; if (!$cleaned) { $past = time() - $lifetime; $session = JFactory::getSession(); $mailto_links = $session->get('com_mailto.links', array()); foreach ($mailto_links as $index => $link) { if ($link->expiry < $past) { unset($mailto_links[$index]); } } $session->set('com_mailto.links', $mailto_links); $cleaned = true; } } } media.php 0000604 00000011733 15245571344 0006347 0 ustar 00 <?php /** * @package Joomla.Administrator * @subpackage com_media * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Object\CMSObject; /** * Media helper class. * * @since 1.6 * @deprecated 4.0 Use JHelperMedia instead */ abstract class MediaHelper { /** * Checks if the file is an image * * @param string $fileName The filename * * @return boolean * * @since 1.5 * @deprecated 4.0 Use JHelperMedia::isImage instead */ public static function isImage($fileName) { try { JLog::add( sprintf('%s() is deprecated. Use JHelperMedia::isImage() instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } $mediaHelper = new JHelperMedia; return $mediaHelper->isImage($fileName); } /** * Gets the file extension for the purpose of using an icon. * * @param string $fileName The filename * * @return string File extension * * @since 1.5 * @deprecated 4.0 Use JHelperMedia::getTypeIcon instead */ public static function getTypeIcon($fileName) { try { JLog::add( sprintf('%s() is deprecated. Use JHelperMedia::getTypeIcon() instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } $mediaHelper = new JHelperMedia; return $mediaHelper->getTypeIcon($fileName); } /** * Checks if the file can be uploaded * * @param array $file File information * @param string $error An error message to be returned * * @return boolean * * @since 1.5 * @deprecated 4.0 Use JHelperMedia::canUpload instead */ public static function canUpload($file, $error = '') { try { JLog::add( sprintf('%s() is deprecated. Use JHelperMedia::canUpload() instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } $mediaHelper = new JHelperMedia; return $mediaHelper->canUpload($file, 'com_media'); } /** * Method to parse a file size * * @param integer $size The file size in bytes * * @return string The converted file size * * @since 1.6 * @deprecated 4.0 Use JHtml::_('number.bytes') instead */ public static function parseSize($size) { try { JLog::add( sprintf("%s() is deprecated. Use JHtml::_('number.bytes') instead.", __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } return JHtml::_('number.bytes', $size); } /** * Calculate the size of a resized image * * @param integer $width Image width * @param integer $height Image height * @param integer $target Target size * * @return array The new width and height * * @since 3.2 * @deprecated 4.0 Use JHelperMedia::imageResize instead */ public static function imageResize($width, $height, $target) { try { JLog::add( sprintf('%s() is deprecated. Use JHelperMedia::imageResize() instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } $mediaHelper = new JHelperMedia; return $mediaHelper->imageResize($width, $height, $target); } /** * Counts the files and directories in a directory that are not php or html files. * * @param string $dir Directory name * * @return array The number of files and directories in the given directory * * @since 1.5 * @deprecated 4.0 Use JHelperMedia::countFiles instead */ public static function countFiles($dir) { try { JLog::add( sprintf('%s() is deprecated. Use JHelperMedia::countFiles() instead.', __METHOD__), JLog::WARNING, 'deprecated' ); } catch (RuntimeException $exception) { // Informational log only } $mediaHelper = new JHelperMedia; return $mediaHelper->countFiles($dir); } /** * Generates the URL to the object in the action logs component * * @param string $contentType The content type * @param integer $id The integer id * @param CMSObject $mediaObject The media object being uploaded * * @return string The link for the action log * * @since 3.9.27 */ public static function getContentTypeLink($contentType, $id, CMSObject $mediaObject) { if ($contentType === 'com_media.file') { return ''; } $link = 'index.php?option=com_media&view=media'; $uploadedPath = substr($mediaObject->get('filepath'), strlen(COM_MEDIA_BASE) + 1); // Now remove the filename $uploadedBasePath = substr_replace( $uploadedPath, '', (strlen(DIRECTORY_SEPARATOR . $mediaObject->get('name')) * -1) ); if (!empty($uploadedBasePath)) { $link = $link . '&folder=' . $uploadedBasePath; } return $link; } } banner.php 0000604 00000001721 15245572077 0006535 0 ustar 00 <?php /** * @package Joomla.Site * @subpackage com_banners * * @copyright (C) 2009 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Banner Helper Class * * @since 1.6 */ abstract class BannerHelper { /** * Checks if a URL is an image * * @param string $url The URL path to the potential image * * @return boolean True if an image of type bmp, gif, jp(e)g or png, false otherwise * * @since 1.6 */ public static function isImage($url) { return preg_match('#\.(?:bmp|gif|jpe?g|png)$#i', $url); } /** * Checks if a URL is a Flash file * * @param string $url The URL path to the potential flash file * * @return boolean True if an image of type bmp, gif, jp(e)g or png, false otherwise * * @since 1.6 */ public static function isFlash($url) { return preg_match('#\.swf$#i', $url); } } index.html 0000604 00000000054 15245607012 0006536 0 ustar 00 <html><body bgcolor="#FFFFFF"></body></html>