| Current Path : /home/w/u/e/wuectly/www/03cbe/ |
| Current File : /home/w/u/e/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 00000013547 15245535622 0006541 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
*/
/**
* BASE ON JOOMLA CORE FILE:
* /components/com_search/models/search.php
*/
/**
* @package Joomla.Site
* @subpackage com_search
*
* @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\MVC\Model\BaseDatabaseModel as JModel;
use Joomla\CMS\Pagination\Pagination as JPagination;
use Joomla\CMS\Plugin\PluginHelper as JPluginHelper;
/**
* Search Component Search Model
*
* @since 1.5
*/
class SearchModelSearch extends JModel
{
/**
* Search data array
*
* @var array
*/
protected $_data = null;
/**
* Search total
*
* @var integer
*/
protected $_total = null;
/**
* Search areas
*
* @var integer
*/
protected $_areas = null;
/**
* Pagination object
*
* @var object
*/
protected $_pagination = null;
/**
* Constructor
*
* @since 1.5
*/
public function __construct()
{
parent::__construct();
// Get configuration
$app = JFactory::getApplication();
$config = JFactory::getConfig();
// Get the pagination request variables
$this->setState('limit', $app->getUserStateFromRequest('com_search.limit', 'limit', $config->get('list_limit'), 'uint'));
$this->setState('limitstart', $app->input->get('limitstart', 0, 'uint'));
// Get parameters.
$params = $app->getParams();
if ($params->get('searchphrase') == 1)
{
$searchphrase = 'any';
}
elseif ($params->get('searchphrase') == 2)
{
$searchphrase = 'exact';
}
else
{
$searchphrase = 'all';
}
// Set the search parameters
$keyword = urldecode($app->input->getString('searchword'));
$match = $app->input->get('searchphrase', $searchphrase, 'word');
$ordering = $app->input->get('ordering', $params->get('ordering', 'newest'), 'word');
$this->setSearch($keyword, $match, $ordering);
// Set the search areas
$areas = $app->input->get('areas', null, 'array');
$this->setAreas($areas);
}
/**
* Method to set the search parameters
*
* @param string $keyword string search string
* @param string $match matching option, exact|any|all
* @param string $ordering option, newest|oldest|popular|alpha|category
*
* @return void
*
* @access public
*/
public function setSearch($keyword, $match = 'all', $ordering = 'newest')
{
if (isset($keyword))
{
$this->setState('origkeyword', $keyword);
if ($match !== 'exact')
{
$keyword = preg_replace('#\xE3\x80\x80#s', ' ', $keyword);
}
$this->setState('keyword', $keyword);
}
if (isset($match))
{
$this->setState('match', $match);
}
if (isset($ordering))
{
$this->setState('ordering', $ordering);
}
}
/**
* Method to get weblink item data for the category
*
* @access public
* @return array
*/
public function getData()
{
// Lets load the content if it doesn't already exist
if (empty($this->_data))
{
$areas = $this->getAreas();
JPluginHelper::importPlugin('search');
$dispatcher = JEventDispatcher::getInstance();
$results = $dispatcher->trigger('onContentSearch', [
$this->getState('keyword'),
$this->getState('match'),
$this->getState('ordering'),
$areas['active'],
]
);
$rows = [];
foreach ($results as $result)
{
$rows = array_merge((array) $rows, (array) $result);
}
$this->_total = count($rows);
if ($this->getState('limit') > 0)
{
$this->_data = array_splice($rows, $this->getState('limitstart'), $this->getState('limit'));
}
else
{
$this->_data = $rows;
}
/* >>> ADDED: Run content plugins over results */
$params = JFactory::getApplication()->getParams('com_content');
$params->set('rl_search', 1);
foreach ($this->_data as $item)
{
if (empty($item->text))
{
continue;
}
$dispatcher->trigger('onContentPrepare', ['com_search.search.article', &$item, &$params, 0]);
if (empty($item->title))
{
continue;
}
// strip html tags from title
$item->title = strip_tags($item->title);
}
/* <<< */
}
return $this->_data;
}
/**
* Method to get the total number of weblink items for the category
*
* @access public
*
* @return integer
*/
public function getTotal()
{
return $this->_total;
}
/**
* Method to set the search areas
*
* @param array $active areas
* @param array $search areas
*
* @return void
*
* @access public
*/
public function setAreas($active = [], $search = [])
{
$this->_areas['active'] = $active;
$this->_areas['search'] = $search;
}
/**
* Method to get a pagination object of the weblink items for the category
*
* @access public
* @return integer
*/
public function getPagination()
{
// Lets load the content if it doesn't already exist
if (empty($this->_pagination))
{
$this->_pagination = new JPagination($this->getTotal(), $this->getState('limitstart'), $this->getState('limit'));
}
return $this->_pagination;
}
/**
* Method to get the search areas
*
* @return int
*
* @since 1.5
*/
public function getAreas()
{
// Load the Category data
if (empty($this->_areas['search']))
{
$areas = [];
JPluginHelper::importPlugin('search');
$dispatcher = JEventDispatcher::getInstance();
$searchareas = $dispatcher->trigger('onContentSearchAreas');
foreach ($searchareas as $area)
{
if (is_array($area))
{
$areas = array_merge($areas, $area);
}
}
$this->_areas['search'] = $areas;
}
return $this->_areas;
}
}
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 00000001734 15245535622 0006332 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\Cache as RL_Cache;
if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php'))
{
require_once JPATH_LIBRARIES . '/regularlabs/autoload.php';
}
class RLCache
{
static $cache = [];
public static function has($id)
{
return RL_Cache::has($id);
}
public static function get($id)
{
return RL_Cache::get($id);
}
public static function set($id, $data)
{
return RL_Cache::set($id, $data);
}
public static function read($id)
{
return RL_Cache::read($id);
}
public static function write($id, $data, $ttl = 0)
{
return RL_Cache::write($id, $data, $ttl);
}
}
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 00000003406 15245535622 0006544 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
*/
defined('_JEXEC') or die;
use RegularLabs\Library\Article as RL_Article;
use RegularLabs\Library\Cache as RL_Cache;
use RegularLabs\Library\Document as RL_Document;
use RegularLabs\Library\Parameters as RL_Parameters;
if (is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php'))
{
require_once JPATH_LIBRARIES . '/regularlabs/autoload.php';
}
class RLHelper
{
public static function getPluginHelper($plugin, $params = null)
{
if ( ! class_exists('RegularLabs\Library\Cache'))
{
return null;
}
$hash = md5('getPluginHelper_' . $plugin->get('_type') . '_' . $plugin->get('_name') . '_' . json_encode($params));
if (RL_Cache::has($hash))
{
return RL_Cache::get($hash);
}
if ( ! $params)
{
$params = RL_Parameters::getInstance()->getPluginParams($plugin->get('_name'));
}
$file = JPATH_PLUGINS . '/' . $plugin->get('_type') . '/' . $plugin->get('_name') . '/helper.php';
if ( ! is_file($file))
{
return null;
}
require_once $file;
$class = get_class($plugin) . 'Helper';
return RL_Cache::set(
$hash,
new $class($params)
);
}
public static function processArticle(&$article, &$context, &$helper, $method, $params = [])
{
class_exists('RegularLabs\Library\Article') && RL_Article::process($article, $context, $helper, $method, $params);
}
public static function isCategoryList($context)
{
return class_exists('RegularLabs\Library\Document') && RL_Document::isCategoryList($context);
}
}
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 00000003206 15245551602 0007573 0 ustar 00 <?php
/**
* @package Joomla.Administrator
* @subpackage com_categories
*
* @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('CategoriesHelper', JPATH_ADMINISTRATOR . '/components/com_categories/helpers/categories.php');
/**
* Category Component Association Helper
*
* @since 3.0
*/
abstract class CategoryHelperAssociation
{
public static $category_association = true;
/**
* Method to get the associations for a given category
*
* @param integer $id Id of the item
* @param string $extension Name of the component
* @param string $layout Category layout
*
* @return array Array of associations for the component categories
*
* @since 3.0
*/
public static function getCategoryAssociations($id = 0, $extension = 'com_content', $layout = null)
{
$return = array();
if ($id)
{
// Load route helper
jimport('helper.route', JPATH_COMPONENT_SITE);
$helperClassname = ucfirst(substr($extension, 4)) . 'HelperRoute';
$associations = CategoriesHelper::getAssociations($id, $extension);
foreach ($associations as $tag => $item)
{
if (class_exists($helperClassname) && is_callable(array($helperClassname, 'getCategoryRoute')))
{
$return[$tag] = $helperClassname::getCategoryRoute($item, $tag, $layout);
}
else
{
$viewLayout = $layout ? '&layout=' . $layout : '';
$return[$tag] = 'index.php?option=' . $extension . '&view=category&id=' . $item . $viewLayout;
}
}
}
return $return;
}
}
route.php 0000604 00000007026 15245551602 0006421 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;
/**
* Finder route helper class.
*
* @since 2.5
*/
class FinderHelperRoute
{
/**
* Method to get the route for a search page.
*
* @param integer $f The search filter id. [optional]
* @param string $q The search query string. [optional]
*
* @return string The search route.
*
* @since 2.5
*/
public static function getSearchRoute($f = null, $q = null)
{
// Get the menu item id.
$query = array('view' => 'search', 'q' => $q, 'f' => $f);
$item = self::getItemid($query);
// Get the base route.
$uri = clone JUri::getInstance('index.php?option=com_finder&view=search');
// Add the pre-defined search filter if present.
if ($f !== null)
{
$uri->setVar('f', $f);
}
// Add the search query string if present.
if ($q !== null)
{
$uri->setVar('q', $q);
}
// Add the menu item id if present.
if ($item !== null)
{
$uri->setVar('Itemid', $item);
}
return $uri->toString(array('path', 'query'));
}
/**
* Method to get the route for an advanced search page.
*
* @param integer $f The search filter id. [optional]
* @param string $q The search query string. [optional]
*
* @return string The advanced search route.
*
* @since 2.5
*/
public static function getAdvancedRoute($f = null, $q = null)
{
// Get the menu item id.
$query = array('view' => 'advanced', 'q' => $q, 'f' => $f);
$item = self::getItemid($query);
// Get the base route.
$uri = clone JUri::getInstance('index.php?option=com_finder&view=advanced');
// Add the pre-defined search filter if present.
if ($q !== null)
{
$uri->setVar('f', $f);
}
// Add the search query string if present.
if ($q !== null)
{
$uri->setVar('q', $q);
}
// Add the menu item id if present.
if ($item !== null)
{
$uri->setVar('Itemid', $item);
}
return $uri->toString(array('path', 'query'));
}
/**
* Method to get the most appropriate menu item for the route based on the
* supplied query needles.
*
* @param array $query An array of URL parameters.
*
* @return mixed An integer on success, null otherwise.
*
* @since 2.5
*/
public static function getItemid($query)
{
static $items, $active;
// Get the menu items for com_finder.
if (!$items || !$active)
{
$app = JFactory::getApplication('site');
$com = JComponentHelper::getComponent('com_finder');
$menu = $app->getMenu();
$active = $menu->getActive();
$items = $menu->getItems('component_id', $com->id);
$items = is_array($items) ? $items : array();
}
// Try to match the active view and filter.
if ($active && @$active->query['view'] == @$query['view'] && @$active->query['f'] == @$query['f'])
{
return $active->id;
}
// Try to match the view, query, and filter.
foreach ($items as $item)
{
if (@$item->query['view'] == @$query['view'] && @$item->query['q'] == @$query['q'] && @$item->query['f'] == @$query['f'])
{
return $item->id;
}
}
// Try to match the view and filter.
foreach ($items as $item)
{
if (@$item->query['view'] == @$query['view'] && @$item->query['f'] == @$query['f'])
{
return $item->id;
}
}
// Try to match the view.
foreach ($items as $item)
{
if (@$item->query['view'] == @$query['view'])
{
return $item->id;
}
}
return null;
}
}
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>