uawdijnntqw1x1x1
IP : 216.73.216.84
Hostname : webm003.cluster107.gra.hosting.ovh.net
Kernel : Linux webm003.cluster107.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
OS : Linux
PATH:
/
home
/
opticamezl
/
.
/
www
/
newok
/
media
/
com_osmap
/
..
/
com_languages
/
.
/
..
/
..
/
.
/
libraries
/
.
/
..
/
content.tar
/
/
pagenavigation/index.html000060400000000037151664163730011545 0ustar00<!DOCTYPE html><title></title> pagenavigation/src/Extension/PageNavigation.php000064400000023360151664163730015730 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.pagenavigation * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\PageNavigation\Extension; use Joomla\CMS\Access\Access; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Component\Content\Site\Helper\RouteHelper; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Pagenavigation plugin class. * * @since 1.5 */ final class PageNavigation extends CMSPlugin { use DatabaseAwareTrait; /** * If in the article view and the parameter is enabled shows the page navigation * * @param string $context The context of the content being passed to the plugin * @param object &$row The article object * @param mixed &$params The article params * @param integer $page The 'page' number * * @return mixed void or true * * @since 1.6 */ public function onContentBeforeDisplay($context, &$row, &$params, $page = 0) { $app = $this->getApplication(); $view = $app->getInput()->get('view'); $print = $app->getInput()->getBool('print'); if ($print) { return false; } if ($context === 'com_content.article' && $view === 'article' && $params->get('show_item_navigation')) { $db = $this->getDatabase(); $user = $app->getIdentity(); $lang = $app->getLanguage(); $now = Factory::getDate()->toSql(); $query = $db->getQuery(true); $uid = $row->id; $option = 'com_content'; $canPublish = $user->authorise('core.edit.state', $option . '.article.' . $row->id); /** * The following is needed as different menu items types utilise a different param to control ordering. * For Blogs the `orderby_sec` param is the order controlling param. * For Table and List views it is the `orderby` param. */ $params_list = $params->toArray(); if (array_key_exists('orderby_sec', $params_list)) { $order_method = $params->get('orderby_sec', ''); } else { $order_method = $params->get('orderby', ''); } // Additional check for invalid sort ordering. if ($order_method === 'front') { $order_method = ''; } if (in_array($order_method, ['date', 'rdate'])) { // Get the order code $orderDate = $params->get('order_date'); switch ($orderDate) { // Use created if modified is not set case 'modified': $orderby = 'CASE WHEN ' . $db->quoteName('a.modified') . ' IS NULL THEN ' . $db->quoteName('a.created') . ' ELSE ' . $db->quoteName('a.modified') . ' END'; break; // Use created if publish_up is not set case 'published': $orderby = 'CASE WHEN ' . $db->quoteName('a.publish_up') . ' IS NULL THEN ' . $db->quoteName('a.created') . ' ELSE ' . $db->quoteName('a.publish_up') . ' END'; break; // Use created as default default: $orderby = $db->quoteName('a.created'); break; } if ($order_method === 'rdate') { $orderby .= ' DESC'; } } else { // Determine sort order. switch ($order_method) { case 'alpha': $orderby = $db->quoteName('a.title'); break; case 'ralpha': $orderby = $db->quoteName('a.title') . ' DESC'; break; case 'hits': $orderby = $db->quoteName('a.hits'); break; case 'rhits': $orderby = $db->quoteName('a.hits') . ' DESC'; break; case 'author': $orderby = $db->quoteName(['a.created_by_alias', 'u.name']); break; case 'rauthor': $orderby = $db->quoteName('a.created_by_alias') . ' DESC, ' . $db->quoteName('u.name') . ' DESC'; break; case 'front': $orderby = $db->quoteName('f.ordering'); break; default: $orderby = $db->quoteName('a.ordering'); break; } } $query->order($orderby); $case_when = ' CASE WHEN ' . $query->charLength($db->quoteName('a.alias'), '!=', '0') . ' THEN ' . $query->concatenate([$query->castAsChar($db->quoteName('a.id')), $db->quoteName('a.alias')], ':') . ' ELSE ' . $query->castAsChar('a.id') . ' END AS ' . $db->quoteName('slug'); $case_when1 = ' CASE WHEN ' . $query->charLength($db->quoteName('cc.alias'), '!=', '0') . ' THEN ' . $query->concatenate([$query->castAsChar($db->quoteName('cc.id')), $db->quoteName('cc.alias')], ':') . ' ELSE ' . $query->castAsChar('cc.id') . ' END AS ' . $db->quoteName('catslug'); $query->select($db->quoteName(['a.id', 'a.title', 'a.catid', 'a.language'])) ->select([$case_when, $case_when1]) ->from($db->quoteName('#__content', 'a')) ->join('LEFT', $db->quoteName('#__categories', 'cc'), $db->quoteName('cc.id') . ' = ' . $db->quoteName('a.catid')); if ($order_method === 'author' || $order_method === 'rauthor') { $query->select($db->quoteName(['a.created_by', 'u.name'])); $query->join('LEFT', $db->quoteName('#__users', 'u'), $db->quoteName('u.id') . ' = ' . $db->quoteName('a.created_by')); } $query->where( [ $db->quoteName('a.catid') . ' = :catid', $db->quoteName('a.state') . ' = :state', ] ) ->bind(':catid', $row->catid, ParameterType::INTEGER) ->bind(':state', $row->state, ParameterType::INTEGER); if (!$canPublish) { $query->whereIn($db->quoteName('a.access'), Access::getAuthorisedViewLevels($user->id)); } $query->where( [ '(' . $db->quoteName('publish_up') . ' IS NULL OR ' . $db->quoteName('publish_up') . ' <= :nowDate1)', '(' . $db->quoteName('publish_down') . ' IS NULL OR ' . $db->quoteName('publish_down') . ' >= :nowDate2)', ] ) ->bind(':nowDate1', $now) ->bind(':nowDate2', $now); if ($app->isClient('site') && $app->getLanguageFilter()) { $query->whereIn($db->quoteName('a.language'), [$lang->getTag(), '*'], ParameterType::STRING); } $db->setQuery($query); $list = $db->loadObjectList('id'); // This check needed if incorrect Itemid is given resulting in an incorrect result. if (!is_array($list)) { $list = []; } reset($list); // Location of current content item in array list. $location = array_search($uid, array_keys($list)); $rows = array_values($list); $row->prev = null; $row->next = null; if ($location - 1 >= 0) { // The previous content item cannot be in the array position -1. $row->prev = $rows[$location - 1]; } if (($location + 1) < count($rows)) { // The next content item cannot be in an array position greater than the number of array positions. $row->next = $rows[$location + 1]; } if ($row->prev) { $row->prev_label = ($this->params->get('display', 0) == 0) ? $lang->_('JPREV') : $row->prev->title; $row->prev = RouteHelper::getArticleRoute($row->prev->slug, $row->prev->catid, $row->prev->language); } else { $row->prev_label = ''; $row->prev = ''; } if ($row->next) { $row->next_label = ($this->params->get('display', 0) == 0) ? $lang->_('JNEXT') : $row->next->title; $row->next = RouteHelper::getArticleRoute($row->next->slug, $row->next->catid, $row->next->language); } else { $row->next_label = ''; $row->next = ''; } // Output. if ($row->prev || $row->next) { // Get the path for the layout file $path = PluginHelper::getLayoutPath('content', 'pagenavigation'); // Render the pagenav ob_start(); include $path; $row->pagination = ob_get_clean(); $row->paginationposition = $this->params->get('position', 1); // This will default to the 1.5 and 1.6-1.7 behavior. $row->paginationrelative = $this->params->get('relative', 0); } } } } pagenavigation/tmpl/index.html000060400000000037151664163730012521 0ustar00<!DOCTYPE html><title></title> pagenavigation/tmpl/default.php000064400000003206151664163730012666 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.pagenavigation * * @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; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; $this->loadLanguage(); $lang = $this->getLanguage(); ?> <nav class="pagenavigation" aria-label="<?php echo Text::_('PLG_PAGENAVIGATION_ARIA_LABEL'); ?>"> <span class="pagination ms-0"> <?php if ($row->prev) : $direction = $lang->isRtl() ? 'right' : 'left'; ?> <a class="btn btn-sm btn-secondary previous" href="<?php echo Route::_($row->prev); ?>" rel="prev"> <span class="visually-hidden"> <?php echo Text::sprintf('JPREVIOUS_TITLE', htmlspecialchars($rows[$location - 1]->title)); ?> </span> <?php echo '<span class="icon-chevron-' . $direction . '" aria-hidden="true"></span> <span aria-hidden="true">' . $row->prev_label . '</span>'; ?> </a> <?php endif; ?> <?php if ($row->next) : $direction = $lang->isRtl() ? 'left' : 'right'; ?> <a class="btn btn-sm btn-secondary next" href="<?php echo Route::_($row->next); ?>" rel="next"> <span class="visually-hidden"> <?php echo Text::sprintf('JNEXT_TITLE', htmlspecialchars($rows[$location + 1]->title)); ?> </span> <?php echo '<span aria-hidden="true">' . $row->next_label . '</span> <span class="icon-chevron-' . $direction . '" aria-hidden="true"></span>'; ?> </a> <?php endif; ?> </span> </nav> pagenavigation/services/provider.php000064400000002710151664163730013742 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.pagenavigation * * @copyright (C) 2023 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\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\PageNavigation\Extension\PageNavigation; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.4.0 */ public function register(Container $container): void { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new PageNavigation( $dispatcher, (array) PluginHelper::getPlugin('content', 'pagenavigation') ); $plugin->setApplication(Factory::getApplication()); $plugin->setDatabase($container->get(DatabaseInterface::class)); return $plugin; } ); } }; pagenavigation/pagenavigation.xml000064400000003715151664163730013300 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_pagenavigation</name> <author>Joomla! Project</author> <creationDate>2006-01</creationDate> <copyright>(C) 2006 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.0.0</version> <description>PLG_PAGENAVIGATION_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\PageNavigation</namespace> <files> <folder plugin="pagenavigation">services</folder> <folder>src</folder> <folder>tmpl</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_pagenavigation.ini</language> <language tag="en-GB">language/en-GB/plg_content_pagenavigation.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="position" type="list" label="PLG_PAGENAVIGATION_FIELD_POSITION_LABEL" default="1" filter="integer" validate="options" > <option value="1">PLG_PAGENAVIGATION_FIELD_VALUE_BELOW</option> <option value="0">PLG_PAGENAVIGATION_FIELD_VALUE_ABOVE</option> </field> <field name="relative" type="list" label="PLG_PAGENAVIGATION_FIELD_RELATIVE_LABEL" default="1" filter="integer" validate="options" > <option value="1">PLG_PAGENAVIGATION_FIELD_VALUE_ARTICLE</option> <option value="0">PLG_PAGENAVIGATION_FIELD_VALUE_TEXT</option> </field> <field name="display" type="list" label="PLG_PAGENAVIGATION_FIELD_DISPLAY_LABEL" default="0" filter="integer" validate="options" > <option value="0">PLG_PAGENAVIGATION_FIELD_VALUE_NEXTPREV</option> <option value="1">PLG_PAGENAVIGATION_FIELD_VALUE_TITLE</option> </field> </fieldset> </fields> </config> </extension> vote/tmpl/rating.php000064400000006027151664163730010513 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.vote * * @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; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Uri\Uri; /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ $wa = $this->getApplication()->getDocument()->getWebAssetManager(); $wa->registerAndUseStyle('plg_content_vote', 'plg_content_vote/rating.css'); /** * Layout variables * ----------------- * @var string $context The context of the content being passed to the plugin * @var object &$row The article object * @var object &$params The article params * @var integer $page The 'page' number * @var array $parts The context segments * @var string $path Path to this file */ if ($context === 'com_content.categories') { return; } // Get the icons $iconStar = HTMLHelper::_('image', 'plg_content_vote/vote-star.svg', '', '', true, true); $iconHalfstar = HTMLHelper::_('image', 'plg_content_vote/vote-star-half.svg', '', '', true, true); // If you can't find the icons then skip it if ($iconStar === null || $iconHalfstar === null) { return; } // Get paths to icons $pathStar = JPATH_ROOT . substr($iconStar, strlen(Uri::root(true))); $pathHalfstar = JPATH_ROOT . substr($iconHalfstar, strlen(Uri::root(true))); // Write inline '<svg>' elements $star = file_exists($pathStar) ? file_get_contents($pathStar) : ''; $halfstar = file_exists($pathHalfstar) ? file_get_contents($pathHalfstar) : ''; // Get rating $rating = (float) $row->rating; $rcount = (int) $row->rating_count; // Round to 0.5 $rating = round($rating / 0.5) * 0.5; // Determine number of stars $stars = $rating; $img = ''; for ($i = 0; $i < floor($stars); $i++) { $img .= '<li class="vote-star">' . $star . '</li>'; } if (($stars - floor($stars)) >= 0.5) { $img .= '<li class="vote-star-empty">' . $star . '</li>'; $img .= '<li class="vote-star-half">' . $halfstar . '</li>'; ++$stars; } for ($i = $stars; $i < 5; $i++) { $img .= '<li class="vote-star-empty">' . $star . '</li>'; } ?> <div class="content_rating" role="img" aria-label="<?php echo Text::sprintf('PLG_VOTE_STAR_RATING', $rating); ?>"> <?php if ($rcount) : ?> <div class="visually-hidden"> <p itemprop="aggregateRating" itemscope itemtype="https://schema.org/AggregateRating"> <?php echo Text::sprintf('PLG_VOTE_USER_RATING', '<span itemprop="ratingValue">' . $rating . '</span>', '<span itemprop="bestRating">5</span>'); ?> <meta itemprop="ratingCount" content="<?php echo $rcount; ?>"> <meta itemprop="worstRating" content="1"> </p> </div> <?php if ($this->params->get('show_total_votes', 0)) : ?> <?php echo Text::sprintf('PLG_VOTE_TOTAL_VOTES', $rcount); ?> <?php endif; ?> <?php endif; ?> <ul> <?php echo $img; ?> </ul> </div> vote/tmpl/vote.php000064400000003517151664163730010205 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.vote * * @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; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Uri\Uri; /** * Layout variables * ----------------- * @var string $context The context of the content being passed to the plugin * @var object &$row The article object * @var object &$params The article params * @var integer $page The 'page' number * @var array $parts The context segments * @var string $path Path to this file */ $uri = clone Uri::getInstance(); // Create option list for voting select box $options = []; for ($i = 1; $i < 6; $i++) { $options[] = HTMLHelper::_('select.option', $i, Text::sprintf('PLG_VOTE_VOTE', $i)); } ?> <form method="post" action="<?php echo htmlspecialchars($uri->toString(), ENT_COMPAT, 'UTF-8'); ?>" class="form-inline mb-2"> <span class="content_vote"> <label class="visually-hidden" for="content_vote_<?php echo (int) $row->id; ?>"><?php echo Text::_('PLG_VOTE_LABEL'); ?></label> <?php echo HTMLHelper::_('select.genericlist', $options, 'user_rating', 'class="form-select form-select-sm w-auto"', 'value', 'text', '5', 'content_vote_' . (int) $row->id); ?> <input class="btn btn-sm btn-primary align-baseline" type="submit" name="submit_vote" value="<?php echo Text::_('PLG_VOTE_RATE'); ?>"> <input type="hidden" name="task" value="article.vote"> <input type="hidden" name="hitcount" value="0"> <input type="hidden" name="url" value="<?php echo htmlspecialchars($uri->toString(), ENT_COMPAT, 'UTF-8'); ?>"> <?php echo HTMLHelper::_('form.token'); ?> </span> </form> vote/vote.xml000064400000002723151664163730007240 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_vote</name> <author>Joomla! Project</author> <creationDate>2005-11</creationDate> <copyright>(C) 2005 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.0.0</version> <description>PLG_VOTE_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\Vote</namespace> <files> <folder plugin="vote">services</folder> <folder>src</folder> <folder>tmpl</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_vote.ini</language> <language tag="en-GB">language/en-GB/plg_content_vote.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="position" type="list" label="PLG_VOTE_POSITION_LABEL" default="top" validate="options" > <option value="top">PLG_VOTE_TOP</option> <option value="bottom">PLG_VOTE_BOTTOM</option> </field> <field name="show_total_votes" type="radio" label="PLG_VOTE_TOTAL_VOTES_LABEL" layout="joomla.form.field.radio.switcher" default="0" filter="integer" > <option value="0">JHIDE</option> <option value="1">JSHOW</option> </field> </fieldset> </fields> </config> </extension> vote/src/Extension/Vote.php000064400000007532151664163730011735 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.vote * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\Vote\Extension; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Plugin\PluginHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Vote plugin. * * @since 1.5 */ final class Vote extends CMSPlugin { /** * @var \Joomla\CMS\Application\CMSApplication * * @since 3.7.0 * * @deprecated 4.4.0 will be removed in 6.0 as it is there only for layout overrides * Use getApplication() instead */ protected $app; /** * Displays the voting area when viewing an article and the voting section is displayed before the article * * @param string $context The context of the content being passed to the plugin * @param object &$row The article object * @param object &$params The article params * @param integer $page The 'page' number * * @return string|boolean HTML string containing code for the votes if in com_content else boolean false * * @since 1.6 */ public function onContentBeforeDisplay($context, &$row, &$params, $page = 0) { if ($this->params->get('position', 'top') !== 'top') { return ''; } return $this->displayVotingData($context, $row, $params, $page); } /** * Displays the voting area when viewing an article and the voting section is displayed after the article * * @param string $context The context of the content being passed to the plugin * @param object &$row The article object * @param object &$params The article params * @param integer $page The 'page' number * * @return string|boolean HTML string containing code for the votes if in com_content else boolean false * * @since 3.7.0 */ public function onContentAfterDisplay($context, &$row, &$params, $page = 0) { if ($this->params->get('position', 'top') !== 'bottom') { return ''; } return $this->displayVotingData($context, $row, $params, $page); } /** * Displays the voting area * * @param string $context The context of the content being passed to the plugin * @param object &$row The article object * @param object &$params The article params * @param integer $page The 'page' number * * @return string|boolean HTML string containing code for the votes if in com_content else boolean false * * @since 3.7.0 */ private function displayVotingData($context, &$row, &$params, $page) { $parts = explode('.', $context); if ($parts[0] !== 'com_content') { return false; } if (empty($params) || !$params->get('show_vote', null)) { return ''; } // Load plugin language files only when needed (ex: they are not needed if show_vote is not active). $this->loadLanguage(); // Get the path for the rating summary layout file $path = PluginHelper::getLayoutPath('content', 'vote', 'rating'); // Render the layout ob_start(); include $path; $html = ob_get_clean(); if ($this->getApplication()->getInput()->getString('view', '') === 'article' && $row->state == 1) { // Get the path for the voting form layout file $path = PluginHelper::getLayoutPath('content', 'vote', 'vote'); // Render the layout ob_start(); include $path; $html .= ob_get_clean(); } return $html; } } vote/index.html000060400000000037151664163730007526 0ustar00<!DOCTYPE html><title></title> vote/services/provider.php000064400000002436151664163730011730 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.vote * * @copyright (C) 2023 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\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\Vote\Extension\Vote; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.4.0 */ public function register(Container $container): void { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new Vote( $dispatcher, (array) PluginHelper::getPlugin('content', 'vote') ); $plugin->setApplication(Factory::getApplication()); return $plugin; } ); } }; loadmodule/index.html000060400000000037151664163730010676 0ustar00<!DOCTYPE html><title></title> loadmodule/services/provider.php000064400000002474151664163730013102 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.loadmodule * * @copyright (C) 2023 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\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\LoadModule\Extension\LoadModule; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.4.0 */ public function register(Container $container): void { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new LoadModule( $dispatcher, (array) PluginHelper::getPlugin('content', 'loadmodule') ); $plugin->setApplication(Factory::getApplication()); return $plugin; } ); } }; loadmodule/src/Extension/LoadModule.php000064400000020652151664163730014213 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.loadmodule * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\LoadModule\Extension; use Joomla\CMS\Helper\ModuleHelper; use Joomla\CMS\Plugin\CMSPlugin; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Plugin to enable loading modules into content (e.g. articles) * This uses the {loadmodule} syntax * * @since 1.5 */ final class LoadModule extends CMSPlugin { protected static $modules = []; protected static $mods = []; /** * Plugin that loads module positions within content * * @param string $context The context of the content being passed to the plugin. * @param object &$article The article object. Note $article->text is also available * @param mixed &$params The article params * @param integer $page The 'page' number * * @return void * * @since 1.6 */ public function onContentPrepare($context, &$article, &$params, $page = 0) { // Only execute if $article is an object and has a text property if (!is_object($article) || !property_exists($article, 'text') || is_null($article->text)) { return; } $defaultStyle = $this->params->get('style', 'none'); // Fallback xhtml (used in Joomla 3) to html5 if ($defaultStyle === 'xhtml') { $defaultStyle = 'html5'; } // Expression to search for (positions) $regex = '/{loadposition\s(.*?)}/i'; // Expression to search for(modules) $regexmod = '/{loadmodule\s(.*?)}/i'; // Expression to search for(id) $regexmodid = '/{loadmoduleid\s([1-9][0-9]*)}/i'; // Remove macros and don't run this plugin when the content is being indexed if ($context === 'com_finder.indexer') { if (str_contains($article->text, 'loadposition')) { $article->text = preg_replace($regex, '', $article->text); } if (str_contains($article->text, 'loadmoduleid')) { $article->text = preg_replace($regexmodid, '', $article->text); } if (str_contains($article->text, 'loadmodule')) { $article->text = preg_replace($regexmod, '', $article->text); } return; } if (str_contains($article->text, '{loadposition ')) { // Find all instances of plugin and put in $matches for loadposition // $matches[0] is full pattern match, $matches[1] is the position preg_match_all($regex, $article->text, $matches, PREG_SET_ORDER); // No matches, skip this if ($matches) { foreach ($matches as $match) { $matcheslist = explode(',', $match[1]); // We may not have a module style so fall back to the plugin default. if (!array_key_exists(1, $matcheslist)) { $matcheslist[1] = $defaultStyle; } $position = trim($matcheslist[0]); $style = trim($matcheslist[1]); $output = $this->load($position, $style); // We should replace only first occurrence in order to allow positions with the same name to regenerate their content: if (($start = strpos($article->text, $match[0])) !== false) { $article->text = substr_replace($article->text, $output, $start, strlen($match[0])); } } } } if (str_contains($article->text, '{loadmodule ')) { // Find all instances of plugin and put in $matchesmod for loadmodule preg_match_all($regexmod, $article->text, $matchesmod, PREG_SET_ORDER); // If no matches, skip this if ($matchesmod) { foreach ($matchesmod as $matchmod) { $matchesmodlist = explode(',', $matchmod[1]); // First parameter is the module, will be prefixed with mod_ later $module = trim($matchesmodlist[0]); // Second parameter is the title $title = ''; if (array_key_exists(1, $matchesmodlist)) { $title = htmlspecialchars_decode(trim($matchesmodlist[1])); } // Third parameter is the module style, (fallback is the plugin default set earlier). $stylemod = $defaultStyle; if (array_key_exists(2, $matchesmodlist)) { $stylemod = trim($matchesmodlist[2]); } $output = $this->loadModule($module, $title, $stylemod); // We should replace only first occurrence in order to allow positions with the same name to regenerate their content: if (($start = strpos($article->text, $matchmod[0])) !== false) { $article->text = substr_replace($article->text, $output, $start, strlen($matchmod[0])); } } } } if (str_contains($article->text, '{loadmoduleid ')) { // Find all instances of plugin and put in $matchesmodid for loadmoduleid preg_match_all($regexmodid, $article->text, $matchesmodid, PREG_SET_ORDER); // If no matches, skip this if ($matchesmodid) { foreach ($matchesmodid as $match) { $id = trim($match[1]); $output = $this->loadID($id); // We should replace only first occurrence in order to allow positions with the same name to regenerate their content: if (($start = strpos($article->text, $match[0])) !== false) { $article->text = substr_replace($article->text, $output, $start, strlen($match[0])); } } } } } /** * Loads and renders the module * * @param string $position The position assigned to the module * @param string $style The style assigned to the module * * @return mixed * * @since 1.6 */ private function load($position, $style = 'none') { $document = $this->getApplication()->getDocument(); $renderer = $document->loadRenderer('module'); $modules = ModuleHelper::getModules($position); $params = ['style' => $style]; ob_start(); foreach ($modules as $module) { echo $renderer->render($module, $params); } return ob_get_clean(); } /** * This is always going to get the first instance of the module type unless * there is a title. * * @param string $module The module title * @param string $title The title of the module * @param string $style The style of the module * * @return mixed * * @since 1.6 */ private function loadModule($module, $title, $style = 'none') { $document = $this->getApplication()->getDocument(); $renderer = $document->loadRenderer('module'); $mod = ModuleHelper::getModule($module, $title); // If the module without the mod_ isn't found, try it with mod_. // This allows people to enter it either way in the content if (!isset($mod)) { $name = 'mod_' . $module; $mod = ModuleHelper::getModule($name, $title); } $params = ['style' => $style]; ob_start(); if ($mod->id) { echo $renderer->render($mod, $params); } return ob_get_clean(); } /** * Loads and renders the module * * @param string $id The id of the module * * @return mixed * * @since 3.9.0 */ private function loadID($id) { $document = $this->getApplication()->getDocument(); $renderer = $document->loadRenderer('module'); $modules = ModuleHelper::getModuleById($id); $params = ['style' => 'none']; ob_start(); if ($modules->id > 0) { echo $renderer->render($modules, $params); } return ob_get_clean(); } } loadmodule/loadmodule.xml000064400000003071151664163730011555 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_loadmodule</name> <author>Joomla! Project</author> <creationDate>2005-11</creationDate> <copyright>(C) 2005 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.0.0</version> <description>PLG_LOADMODULE_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\LoadModule</namespace> <files> <folder plugin="loadmodule">services</folder> <folder>src</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_loadmodule.ini</language> <language tag="en-GB">language/en-GB/plg_content_loadmodule.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="style" type="list" label="PLG_LOADMODULE_FIELD_STYLE_LABEL" default="none" validate="options" > <option value="none">PLG_LOADMODULE_FIELD_VALUE_RAW</option> <option value="html5">PLG_LOADMODULE_FIELD_VALUE_DIVS</option> <option value="table">PLG_LOADMODULE_FIELD_VALUE_TABLE</option> <!-- @TODO: The following styles don't exist in default installation and can be removed in Joomla 5 --> <option value="horz">PLG_LOADMODULE_FIELD_VALUE_HORIZONTAL</option> <option value="rounded">PLG_LOADMODULE_FIELD_VALUE_MULTIPLEDIVS</option> </field> </fieldset> </fields> </config> </extension> confirmconsent/confirmconsent.xml000064400000004471151664163730013366 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_confirmconsent</name> <author>Joomla! Project</author> <creationDate>2018-05</creationDate> <copyright>(C) 2018 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.9.0</version> <description>PLG_CONTENT_CONFIRMCONSENT_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\ConfirmConsent</namespace> <files> <folder plugin="confirmconsent">services</folder> <folder>src</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_confirmconsent.ini</language> <language tag="en-GB">language/en-GB/plg_content_confirmconsent.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic" addfieldprefix="Joomla\Component\Content\Administrator\Field"> <field name="consentbox_text" type="textarea" label="PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_LABEL" description="PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DESC" hint="PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DEFAULT" rows="7" cols="20" filter="html" /> <field name="privacy_type" type="list" label="PLG_CONTENT_CONFIRMCONSENT_FIELD_TYPE_LABEL" default="article" validate="options" > <option value="article">PLG_CONTENT_CONFIRMCONSENT_FIELD_TYPE_ARTICLE</option> <option value="menu_item">PLG_CONTENT_CONFIRMCONSENT_FIELD_TYPE_MENU_ITEM</option> </field> <field name="privacy_article" type="modal_article" label="PLG_CONTENT_CONFIRMCONSENT_FIELD_ARTICLE_LABEL" description="PLG_CONTENT_CONFIRMCONSENT_FIELD_ARTICLE_DESC" select="true" new="true" edit="true" clear="true" filter="integer" showon="privacy_type:article" /> <field addfieldprefix="Joomla\Component\Menus\Administrator\Field" name="privacy_menu_item" type="modal_menu" label="PLG_CONTENT_CONFIRMCONSENT_FIELD_MENU_ITEM_LABEL" select="true" new="true" edit="true" clear="true" filter="integer" showon="privacy_type:menu_item" /> </fieldset> </fields> </config> </extension> confirmconsent/src/Field/ConsentBoxField.php000064400000024451151664163730015166 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.confirmconsent * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\ConfirmConsent\Field; use Joomla\CMS\Factory; use Joomla\CMS\Form\Field\CheckboxesField; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Associations; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Router\Route; use Joomla\Component\Content\Site\Helper\RouteHelper; use Joomla\Database\Exception\ExecutionFailureException; use Joomla\Database\ParameterType; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Consentbox Field class for the Confirm Consent Plugin. * * @since 3.9.1 */ class ConsentBoxField extends CheckboxesField { /** * The form field type. * * @var string * @since 3.9.1 */ protected $type = 'ConsentBox'; /** * Flag to tell the field to always be in multiple values mode. * * @var boolean * @since 3.9.1 */ protected $forceMultiple = false; /** * The article ID. * * @var integer * @since 3.9.1 */ protected $articleid; /** * The menu item ID. * * @var integer * @since 4.0.0 */ protected $menuItemId; /** * Type of the privacy policy. * * @var string * @since 4.0.0 */ protected $privacyType; /** * Method to set certain otherwise inaccessible properties of the form field object. * * @param string $name The property name for which to set the value. * @param mixed $value The value of the property. * * @return void * * @since 3.9.1 */ public function __set($name, $value) { switch ($name) { case 'articleid': $this->articleid = (int) $value; break; default: parent::__set($name, $value); } } /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to get the value. * * @return mixed The property value or null. * * @since 3.9.1 */ public function __get($name) { if ($name == 'articleid') { return $this->$name; } return parent::__get($name); } /** * Method to attach a JForm object to the field. * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object. * @param mixed $value The form field value to validate. * @param string $group The field name group control value. This acts as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * * @return boolean True on success. * * @see \Joomla\CMS\Form\FormField::setup() * @since 3.9.1 */ public function setup(\SimpleXMLElement $element, $value, $group = null) { $return = parent::setup($element, $value, $group); if ($return) { $this->articleid = (int) $this->element['articleid']; $this->menuItemId = (int) $this->element['menu_item_id']; $this->privacyType = (string) $this->element['privacy_type']; } return $return; } /** * Method to get the field label markup. * * @return string The field label markup. * * @since 3.9.1 */ protected function getLabel() { if ($this->hidden) { return ''; } $data = $this->getLayoutData(); // Forcing the Alias field to display the tip below $position = $this->element['name'] == 'alias' ? ' data-bs-placement="bottom" ' : ''; // When we have an article let's add the modal and make the title clickable $hasLink = ($data['privacyType'] === 'article' && $data['articleid']) || ($data['privacyType'] === 'menu_item' && $data['menuItemId']); if ($hasLink) { $attribs['data-bs-toggle'] = 'modal'; $data['label'] = HTMLHelper::_( 'link', '#modal-' . $this->id, $data['label'], $attribs ); } // Here mainly for B/C with old layouts. This can be done in the layouts directly $extraData = [ 'text' => $data['label'], 'for' => $this->id, 'classes' => explode(' ', $data['labelclass']), 'position' => $position, ]; return $this->getRenderer($this->renderLabelLayout)->render(array_merge($data, $extraData)); } /** * Method to get the field input markup. * * @return string The field input markup. * * @since 4.0.0 */ protected function getInput() { $modalHtml = ''; $layoutData = $this->getLayoutData(); $hasLink = ($this->privacyType === 'article' && $this->articleid) || ($this->privacyType === 'menu_item' && $this->menuItemId); if ($hasLink) { $modalParams['title'] = $layoutData['label']; $modalParams['url'] = ($this->privacyType === 'menu_item') ? $this->getAssignedMenuItemUrl() : $this->getAssignedArticleUrl(); $modalParams['height'] = '100%'; $modalParams['width'] = '100%'; $modalParams['bodyHeight'] = 70; $modalParams['modalWidth'] = 80; $modalHtml = HTMLHelper::_('bootstrap.renderModal', 'modal-' . $this->id, $modalParams); } return $modalHtml . parent::getInput(); } /** * Method to get the data to be passed to the layout for rendering. * * @return array * * @since 3.9.1 */ protected function getLayoutData() { $data = parent::getLayoutData(); $extraData = [ 'articleid' => (int) $this->articleid, 'menuItemId' => (int) $this->menuItemId, 'privacyType' => (string) $this->privacyType, ]; return array_merge($data, $extraData); } /** * Return the url of the assigned article based on the current user language * * @return string Returns the link to the article * * @since 3.9.1 */ private function getAssignedArticleUrl() { $db = $this->getDatabase(); // Get the info from the article $query = $db->getQuery(true) ->select($db->quoteName(['id', 'catid', 'language'])) ->from($db->quoteName('#__content')) ->where($db->quoteName('id') . ' = ' . (int) $this->articleid); $db->setQuery($query); try { $article = $db->loadObject(); } catch (ExecutionFailureException $e) { // Something at the database layer went wrong return Route::_( 'index.php?option=com_content&view=article&id=' . $this->articleid . '&tmpl=component' ); } if (!\is_object($article)) { // We have not found the article object lets show a 404 to the user return Route::_( 'index.php?option=com_content&view=article&id=' . $this->articleid . '&tmpl=component' ); } if (!Associations::isEnabled()) { return Route::_( RouteHelper::getArticleRoute( $article->id, $article->catid, $article->language ) . '&tmpl=component' ); } $associatedArticles = Associations::getAssociations('com_content', '#__content', 'com_content.item', $article->id); $currentLang = Factory::getLanguage()->getTag(); if (isset($associatedArticles) && $currentLang !== $article->language && \array_key_exists($currentLang, $associatedArticles)) { return Route::_( RouteHelper::getArticleRoute( $associatedArticles[$currentLang]->id, $associatedArticles[$currentLang]->catid, $associatedArticles[$currentLang]->language ) . '&tmpl=component' ); } // Association is enabled but this article is not associated return Route::_( 'index.php?option=com_content&view=article&id=' . $article->id . '&catid=' . $article->catid . '&tmpl=component&lang=' . $article->language ); } /** * Get privacy menu item URL. If the site is a multilingual website and there is associated menu item for the * current language, the URL of the associated menu item will be returned. * * @return string * * @since 4.0.0 */ private function getAssignedMenuItemUrl() { $itemId = $this->menuItemId; $languageSuffix = ''; if ($itemId > 0 && Associations::isEnabled()) { $privacyAssociated = Associations::getAssociations('com_menus', '#__menu', 'com_menus.item', $itemId, 'id', '', ''); $currentLang = Factory::getLanguage()->getTag(); if (isset($privacyAssociated[$currentLang])) { $itemId = $privacyAssociated[$currentLang]->id; } if (Multilanguage::isEnabled()) { $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName(['id', 'language'])) ->from($db->quoteName('#__menu')) ->where($db->quoteName('id') . ' = :id') ->bind(':id', $itemId, ParameterType::INTEGER); $db->setQuery($query); $menuItem = $db->loadObject(); $languageSuffix = '&lang=' . $menuItem->language; } } return Route::_( 'index.php?Itemid=' . (int) $itemId . '&tmpl=component' . $languageSuffix ); } } confirmconsent/src/Extension/ConfirmConsent.php000064400000004707151664163730016022 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.confirmconsent * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\ConfirmConsent\Extension; use Joomla\CMS\Form\Form; use Joomla\CMS\Plugin\CMSPlugin; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * The Joomla Core confirm consent plugin * * @since 3.9.0 */ final class ConfirmConsent extends CMSPlugin { /** * Load the language file on instantiation. * * @var boolean * * @since 3.9.0 */ protected $autoloadLanguage = true; /** * The supported form contexts * * @var array * * @since 3.9.0 */ protected $supportedContext = [ 'com_contact.contact', 'com_privacy.request', ]; /** * Add additional fields to the supported forms * * @param Form $form The form to be altered. * @param mixed $data The associated data for the form. * * @return boolean * * @since 3.9.0 */ public function onContentPrepareForm(Form $form, $data) { if ($this->getApplication()->isClient('administrator') || !in_array($form->getName(), $this->supportedContext)) { return true; } // Get the consent box Text & the selected privacyarticle $consentboxText = (string) $this->params->get( 'consentbox_text', $this->getApplication()->getLanguage()->_('PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DEFAULT') ); $privacyArticle = $this->params->get('privacy_article', false); $privacyType = $this->params->get('privacy_type', 'article'); $privacyMenuItem = $this->params->get('privacy_menu_item', false); $form->load(' <form> <fieldset name="default" addfieldprefix="Joomla\\Plugin\\Content\\ConfirmConsent\\Field"> <field name="consentbox" type="ConsentBox" articleid="' . $privacyArticle . '" menu_item_id="' . $privacyMenuItem . '" privacy_type="' . $privacyType . '" label="PLG_CONTENT_CONFIRMCONSENT_CONSENTBOX_LABEL" required="true" > <option value="0">' . htmlspecialchars($consentboxText, ENT_COMPAT, 'UTF-8') . '</option> </field> </fieldset> </form>'); return true; } } confirmconsent/services/provider.php000064400000002512151664163730013775 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.confirmconsent * * @copyright (C) 2022 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\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\ConfirmConsent\Extension\ConfirmConsent; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.3.0 */ public function register(Container $container) { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new ConfirmConsent( $dispatcher, (array) PluginHelper::getPlugin('content', 'confirmconsent') ); $plugin->setApplication(Factory::getApplication()); return $plugin; } ); } }; finder/index.html000060400000000037151664163730010020 0ustar00<!DOCTYPE html><title></title> finder/finder.xml000064400000001624151664163730010023 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_finder</name> <author>Joomla! Project</author> <creationDate>2011-12</creationDate> <copyright>(C) 2011 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.0.0</version> <description>PLG_CONTENT_FINDER_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\Finder</namespace> <files> <folder plugin="finder">services</folder> <folder>src</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_finder.ini</language> <language tag="en-GB">language/en-GB/plg_content_finder.sys.ini</language> </languages> <config> <fields name="params"> </fields> </config> </extension> finder/src/Extension/Finder.php000064400000010447151664163730012520 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.finder * * @copyright (C) 2011 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\Finder\Extension; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Plugin\PluginHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Smart Search Content Plugin * * @since 2.5 */ final class Finder extends CMSPlugin { /** * Smart Search after save content method. * Content is passed by reference, but after the save, so no changes will be saved. * Method is called right after the content is saved. * * @param string $context The context of the content passed to the plugin (added in 1.6) * @param object $article A JTableContent object * @param bool $isNew If the content has just been created * * @return void * * @since 2.5 */ public function onContentAfterSave($context, $article, $isNew): void { PluginHelper::importPlugin('finder'); // Trigger the onFinderAfterSave event. $this->getApplication()->triggerEvent('onFinderAfterSave', [$context, $article, $isNew]); } /** * Smart Search before save content method. * Content is passed by reference. Method is called before the content is saved. * * @param string $context The context of the content passed to the plugin (added in 1.6). * @param object $article A JTableContent object. * @param bool $isNew If the content is just about to be created. * * @return void * * @since 2.5 */ public function onContentBeforeSave($context, $article, $isNew) { PluginHelper::importPlugin('finder'); // Trigger the onFinderBeforeSave event. $this->getApplication()->triggerEvent('onFinderBeforeSave', [$context, $article, $isNew]); } /** * Smart Search after delete content method. * Content is passed by reference, but after the deletion. * * @param string $context The context of the content passed to the plugin (added in 1.6). * @param object $article A JTableContent object. * * @return void * * @since 2.5 */ public function onContentAfterDelete($context, $article): void { PluginHelper::importPlugin('finder'); // Trigger the onFinderAfterDelete event. $this->getApplication()->triggerEvent('onFinderAfterDelete', [$context, $article]); } /** * Smart Search content state change method. * Method to update the link information for items that have been changed * from outside the edit screen. This is fired when the item is published, * unpublished, archived, or unarchived from the list view. * * @param string $context The context for the content passed to the plugin. * @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 */ public function onContentChangeState($context, $pks, $value) { PluginHelper::importPlugin('finder'); // Trigger the onFinderChangeState event. $this->getApplication()->triggerEvent('onFinderChangeState', [$context, $pks, $value]); } /** * Smart Search change category state content method. * Method is called when the state of the category to which the * content item belongs is changed. * * @param string $extension The extension whose category has been updated. * @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 */ public function onCategoryChangeState($extension, $pks, $value) { PluginHelper::importPlugin('finder'); // Trigger the onFinderCategoryChangeState event. $this->getApplication()->triggerEvent('onFinderCategoryChangeState', [$extension, $pks, $value]); } } finder/services/provider.php000064400000002450151664163730012216 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.finder * * @copyright (C) 2023 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\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\Finder\Extension\Finder; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.4.0 */ public function register(Container $container): void { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new Finder( $dispatcher, (array) PluginHelper::getPlugin('content', 'finder') ); $plugin->setApplication(Factory::getApplication()); return $plugin; } ); } }; contact/src/Extension/Contact.php000064400000011031151664163730013056 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.contact * * @copyright (C) 2014 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\Contact\Extension; use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Router\Route; use Joomla\Component\Contact\Site\Helper\RouteHelper; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; use Joomla\Registry\Registry; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Contact Plugin * * @since 3.2 */ final class Contact extends CMSPlugin { use DatabaseAwareTrait; /** * Plugin that retrieves contact information for contact * * @param string $context The context of the content being passed to the plugin. * @param mixed &$row An object with a "text" property * @param mixed $params Additional parameters. See {@see PlgContentContent()}. * @param integer $page Optional page number. Unused. Defaults to zero. * * @return void */ public function onContentPrepare($context, &$row, $params, $page = 0) { $allowed_contexts = ['com_content.category', 'com_content.article', 'com_content.featured']; if (!in_array($context, $allowed_contexts)) { return; } // Return if we don't have valid params or don't link the author if (!($params instanceof Registry) || !$params->get('link_author')) { return; } // Return if an alias is used if ((int) $this->params->get('link_to_alias', 0) === 0 && $row->created_by_alias != '') { return; } // Return if we don't have a valid article id if (!isset($row->id) || !(int) $row->id) { return; } $contact = $this->getContactData($row->created_by); if ($contact === null) { return; } $row->contactid = $contact->contactid; $row->webpage = $contact->webpage; $row->email = $contact->email_to; $url = $this->params->get('url', 'url'); if ($row->contactid && $url === 'url') { $row->contact_link = Route::_(RouteHelper::getContactRoute($contact->contactid . ':' . $contact->alias, $contact->catid)); } elseif ($row->webpage && $url === 'webpage') { $row->contact_link = $row->webpage; } elseif ($row->email && $url === 'email') { $row->contact_link = 'mailto:' . $row->email; } else { $row->contact_link = ''; } } /** * Retrieve Contact * * @param int $userId Id of the user who created the article * * @return stdClass|null Object containing contact details or null if not found */ private function getContactData($userId) { static $contacts = []; // Note: don't use isset() because value could be null. if (array_key_exists($userId, $contacts)) { return $contacts[$userId]; } $db = $this->getDatabase(); $query = $db->getQuery(true); $userId = (int) $userId; $query->select($db->quoteName('contact.id', 'contactid')) ->select( $db->quoteName( [ 'contact.alias', 'contact.catid', 'contact.webpage', 'contact.email_to', ] ) ) ->from($db->quoteName('#__contact_details', 'contact')) ->where( [ $db->quoteName('contact.published') . ' = 1', $db->quoteName('contact.user_id') . ' = :createdby', ] ) ->bind(':createdby', $userId, ParameterType::INTEGER); if (Multilanguage::isEnabled() === true) { $query->where( '(' . $db->quoteName('contact.language') . ' IN (' . implode(',', $query->bindArray([$this->getApplication()->getLanguage()->getTag(), '*'], ParameterType::STRING)) . ') OR ' . $db->quoteName('contact.language') . ' IS NULL)' ); } $query->order($db->quoteName('contact.id') . ' DESC') ->setLimit(1); $db->setQuery($query); $contacts[$userId] = $db->loadObject(); return $contacts[$userId]; } } contact/contact.xml000064400000003322151664163730010370 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_contact</name> <author>Joomla! Project</author> <creationDate>2014-01</creationDate> <copyright>(C) 2014 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.2.2</version> <description>PLG_CONTENT_CONTACT_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\Contact</namespace> <files> <folder plugin="contact">services</folder> <folder>src</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_contact.ini</language> <language tag="en-GB">language/en-GB/plg_content_contact.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="url" type="list" label="PLG_CONTENT_CONTACT_PARAM_URL_LABEL" description="PLG_CONTENT_CONTACT_PARAM_URL_DESCRIPTION" default="url" validate="options" > <option value="url">PLG_CONTENT_CONTACT_PARAM_URL_URL</option> <option value="webpage">PLG_CONTENT_CONTACT_PARAM_URL_WEBPAGE</option> <option value="email">PLG_CONTENT_CONTACT_PARAM_URL_EMAIL</option> </field> <field name="link_to_alias" type="radio" label="PLG_CONTENT_CONTACT_PARAM_ALIAS_LABEL" description="PLG_CONTENT_CONTACT_PARAM_ALIAS_DESCRIPTION" default="0" layout="joomla.form.field.radio.switcher" filter="integer" > <option value="0">JNO</option> <option value="1">JYES</option> </field> </fieldset> </fields> </config> </extension> contact/services/provider.php000064400000002637151664163730012411 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.contact * * @copyright (C) 2022 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\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\Contact\Extension\Contact; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.3.0 */ public function register(Container $container) { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new Contact( $dispatcher, (array) PluginHelper::getPlugin('content', 'contact') ); $plugin->setApplication(Factory::getApplication()); $plugin->setDatabase($container->get(DatabaseInterface::class)); return $plugin; } ); } }; contact/index.html000060400000000037151664163730010204 0ustar00<!DOCTYPE html><title></title> pagebreak/pagebreak.xml000064400000005134151664163730011147 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_pagebreak</name> <author>Joomla! Project</author> <creationDate>2005-11</creationDate> <copyright>(C) 2005 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.0.0</version> <description>PLG_CONTENT_PAGEBREAK_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\PageBreak</namespace> <files> <folder plugin="pagebreak">services</folder> <folder>src</folder> <folder>tmpl</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_pagebreak.ini</language> <language tag="en-GB">language/en-GB/plg_content_pagebreak.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="title" type="radio" layout="joomla.form.field.radio.switcher" label="PLG_CONTENT_PAGEBREAK_SITE_TITLE_LABEL" default="1" filter="integer" > <option value="0">JHIDE</option> <option value="1">JSHOW</option> </field> <field name="article_index" type="radio" layout="joomla.form.field.radio.switcher" label="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEX_LABEL" default="1" filter="integer" > <option value="0">JHIDE</option> <option value="1">JSHOW</option> </field> <field name="article_index_text" type="text" label="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEXTEXT" showon="article_index:1" /> <field name="multipage_toc" type="radio" layout="joomla.form.field.radio.switcher" label="PLG_CONTENT_PAGEBREAK_TOC_LABEL" default="1" filter="integer" > <option value="0">JHIDE</option> <option value="1">JSHOW</option> </field> <field name="showall" type="radio" layout="joomla.form.field.radio.switcher" label="PLG_CONTENT_PAGEBREAK_SHOW_ALL_LABEL" default="1" filter="integer" > <option value="0">JHIDE</option> <option value="1">JSHOW</option> </field> <field name="style" type="list" label="PLG_CONTENT_PAGEBREAK_STYLE_LABEL" default="pages" validate="options" > <option value="pages">PLG_CONTENT_PAGEBREAK_PAGES</option> <option value="sliders">PLG_CONTENT_PAGEBREAK_SLIDERS</option> <option value="tabs">PLG_CONTENT_PAGEBREAK_TABS</option> </field> </fieldset> </fields> </config> </extension> pagebreak/tmpl/toc.php000064400000001635151664163730010760 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.pagebreak * * @copyright (C) 2018 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\Router\Route; ?> <div class="card float-end article-index ms-3 mb-3"> <div class="card-body"> <?php if ($headingtext) : ?> <h3><?php echo $headingtext; ?></h3> <?php endif; ?> <ul class="nav flex-column"> <?php foreach ($list as $listItem) : ?> <?php $class = $listItem->active ? ' active' : ''; ?> <li class="py-1"> <a href="<?php echo Route::_($listItem->link); ?>" class="toclink<?php echo $class; ?>"> <?php echo $listItem->title; ?> </a> </li> <?php endforeach; ?> </ul> </div> </div> pagebreak/tmpl/navigation.php000064400000003671151664163730012334 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.pagebreak * * @copyright (C) 2018 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\Language\Text; use Joomla\CMS\Router\Route; /** * @var $links array Array with keys 'previous' and 'next' with non-SEO links to the previous and next pages * @var $page integer The page number */ $lang = $this->getApplication()->getLanguage(); ?> <ul class="pagination"> <li class="previous page-item"> <?php if ($links['previous']) : $direction = $lang->isRtl() ? 'right' : 'left'; $title = htmlspecialchars($this->list[$page]->title, ENT_QUOTES, 'UTF-8'); $ariaLabel = Text::_('JPREVIOUS') . ': ' . $title . ' (' . Text::sprintf('JLIB_HTML_PAGE_CURRENT_OF_TOTAL', $page, $n) . ')'; ?> <a class="page-link" href="<?php echo Route::_($links['previous']); ?>" title="<?php echo $title; ?>" aria-label="<?php echo $ariaLabel; ?>" rel="prev"> <?php echo '<span class="icon-chevron-' . $direction . '" aria-hidden="true"></span> ' . Text::_('JPREV'); ?> </a> <?php endif; ?> </li> <li class="next page-item"> <?php if ($links['next']) : $direction = $lang->isRtl() ? 'left' : 'right'; $title = htmlspecialchars($this->list[$page + 2]->title, ENT_QUOTES, 'UTF-8'); $ariaLabel = Text::_('JNEXT') . ': ' . $title . ' (' . Text::sprintf('JLIB_HTML_PAGE_CURRENT_OF_TOTAL', ($page + 2), $n) . ')'; ?> <a class="page-link" href="<?php echo Route::_($links['next']); ?>" title="<?php echo $title; ?>" aria-label="<?php echo $ariaLabel; ?>" rel="next"> <?php echo Text::_('JNEXT') . ' <span class="icon-chevron-' . $direction . '" aria-hidden="true"></span>'; ?> </a> <?php endif; ?> </li> </ul> pagebreak/src/Extension/PageBreak.php000064400000030145151664163730013601 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.pagebreak * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\PageBreak\Extension; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; use Joomla\CMS\Pagination\Pagination; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Utility\Utility; use Joomla\Component\Content\Site\Helper\RouteHelper; use Joomla\String\StringHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Page break plugin * * <strong>Usage:</strong> * <code><hr class="system-pagebreak" /></code> * <code><hr class="system-pagebreak" title="The page title" /></code> * or * <code><hr class="system-pagebreak" alt="The first page" /></code> * or * <code><hr class="system-pagebreak" title="The page title" alt="The first page" /></code> * or * <code><hr class="system-pagebreak" alt="The first page" title="The page title" /></code> * * @since 1.6 */ final class PageBreak extends CMSPlugin { /** * The navigation list with all page objects if parameter 'multipage_toc' is active. * * @var array * @since 4.0.0 */ protected $list = []; /** * Plugin that adds a pagebreak into the text and truncates text at that point * * @param string $context The context of the content being passed to the plugin. * @param object &$row The article object. Note $article->text is also available * @param mixed &$params The article params * @param integer $page The 'page' number * * @return void * * @since 1.6 */ public function onContentPrepare($context, &$row, &$params, $page = 0) { $canProceed = $context === 'com_content.article'; if (!$canProceed) { return; } $style = $this->params->get('style', 'pages'); // Expression to search for. $regex = '#<hr(.*)class="system-pagebreak"(.*)\/?>#iU'; $input = $this->getApplication()->getInput(); $print = $input->getBool('print'); $showall = $input->getBool('showall'); if (!$this->params->get('enabled', 1)) { $print = true; } if ($print) { $row->text = preg_replace($regex, '<br>', $row->text); return; } // Simple performance check to determine whether bot should process further. if (StringHelper::strpos($row->text, 'class="system-pagebreak') === false) { if ($page > 0) { throw new \Exception($this->getApplication()->getLanguage()->_('JERROR_PAGE_NOT_FOUND'), 404); } return; } $view = $input->getString('view'); $full = $input->getBool('fullview'); if (!$page) { $page = 0; } if ($full || $view !== 'article' || $params->get('intro_only') || $params->get('popup')) { $row->text = preg_replace($regex, '', $row->text); return; } // Load plugin language files only when needed (ex: not needed if no system-pagebreak class exists). $this->loadLanguage(); // Find all instances of plugin and put in $matches. $matches = []; preg_match_all($regex, $row->text, $matches, PREG_SET_ORDER); if ($showall && $this->params->get('showall', 1)) { $hasToc = $this->params->get('multipage_toc', 1); if ($hasToc) { // Display TOC. $page = 1; $this->createToc($row, $matches, $page); } else { $row->toc = ''; } $row->text = preg_replace($regex, '<br>', $row->text); return; } // Split the text around the plugin. $text = preg_split($regex, $row->text); if (!isset($text[$page])) { throw new \Exception($this->getApplication()->getLanguage()->_('JERROR_PAGE_NOT_FOUND'), 404); } // Count the number of pages. $n = count($text); // We have found at least one plugin, therefore at least 2 pages. if ($n > 1) { $title = $this->params->get('title', 1); $hasToc = $this->params->get('multipage_toc', 1); // Adds heading or title to <site> Title. if ($title && $page && isset($matches[$page - 1][0])) { $attrs = Utility::parseAttributes($matches[$page - 1][0]); if (isset($attrs['title'])) { $row->page_title = $attrs['title']; } } // Reset the text, we already hold it in the $text array. $row->text = ''; if ($style === 'pages') { // Display TOC. if ($hasToc) { $this->createToc($row, $matches, $page); } else { $row->toc = ''; } // Traditional mos page navigation $pageNav = new Pagination($n, $page, 1); // Flag indicates to not add limitstart=0 to URL $pageNav->hideEmptyLimitstart = true; // Page counter. $row->text .= '<div class="pagenavcounter">'; $row->text .= $pageNav->getPagesCounter(); $row->text .= '</div>'; // Page text. $text[$page] = str_replace('<hr id="system-readmore" />', '', $text[$page]); $row->text .= $text[$page]; // $row->text .= '<br>'; $row->text .= '<div class="pager">'; // Adds navigation between pages to bottom of text. if ($hasToc) { $this->createNavigation($row, $page, $n); } // Page links shown at bottom of page if TOC disabled. if (!$hasToc) { $row->text .= $pageNav->getPagesLinks(); } $row->text .= '</div>'; } else { $t[] = $text[0]; if ($style === 'tabs') { $t[] = (string) HTMLHelper::_('uitab.startTabSet', 'myTab', ['active' => 'article' . $row->id . '-' . $style . '0', 'view' => 'tabs']); } else { $t[] = (string) HTMLHelper::_('bootstrap.startAccordion', 'myAccordion', ['active' => 'article' . $row->id . '-' . $style . '0']); } foreach ($text as $key => $subtext) { $index = 'article' . $row->id . '-' . $style . $key; if ($key >= 1) { $match = $matches[$key - 1]; $match = (array) Utility::parseAttributes($match[0]); if (isset($match['alt'])) { $title = stripslashes($match['alt']); } elseif (isset($match['title'])) { $title = stripslashes($match['title']); } else { $title = Text::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM', $key + 1); } if ($style === 'tabs') { $t[] = (string) HTMLHelper::_('uitab.addTab', 'myTab', $index, $title); } else { $t[] = (string) HTMLHelper::_('bootstrap.addSlide', 'myAccordion', $title, $index); } $t[] = (string) $subtext; if ($style === 'tabs') { $t[] = (string) HTMLHelper::_('uitab.endTab'); } else { $t[] = (string) HTMLHelper::_('bootstrap.endSlide'); } } } if ($style === 'tabs') { $t[] = (string) HTMLHelper::_('uitab.endTabSet'); } else { $t[] = (string) HTMLHelper::_('bootstrap.endAccordion'); } $row->text = implode(' ', $t); } } } /** * Creates a Table of Contents for the pagebreak * * @param object &$row The article object. Note $article->text is also available * @param array &$matches Array of matches of a regex in onContentPrepare * @param integer &$page The 'page' number * * @return void * * @since 1.6 */ private function createToc(&$row, &$matches, &$page) { $heading = $row->title ?? $this->getApplication()->getLanguage()->_('PLG_CONTENT_PAGEBREAK_NO_TITLE'); $input = $this->getApplication()->getInput(); $limitstart = $input->getUint('limitstart', 0); $showall = $input->getInt('showall', 0); $headingtext = ''; if ($this->params->get('article_index', 1) == 1) { $headingtext = $this->getApplication()->getLanguage()->_('PLG_CONTENT_PAGEBREAK_ARTICLE_INDEX'); if ($this->params->get('article_index_text')) { $headingtext = htmlspecialchars($this->params->get('article_index_text'), ENT_QUOTES, 'UTF-8'); } } // TOC first Page link. $this->list[1] = new \stdClass(); $this->list[1]->link = RouteHelper::getArticleRoute($row->slug, $row->catid, $row->language); $this->list[1]->title = $heading; $this->list[1]->active = ($limitstart === 0 && $showall === 0); $i = 2; foreach ($matches as $bot) { if (@$bot[0]) { $attrs2 = Utility::parseAttributes($bot[0]); if (@$attrs2['alt']) { $title = stripslashes($attrs2['alt']); } elseif (@$attrs2['title']) { $title = stripslashes($attrs2['title']); } else { $title = Text::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM', $i); } } else { $title = Text::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM', $i); } $this->list[$i] = new \stdClass(); $this->list[$i]->link = RouteHelper::getArticleRoute($row->slug, $row->catid, $row->language) . '&limitstart=' . ($i - 1); $this->list[$i]->title = $title; $this->list[$i]->active = ($limitstart === $i - 1); $i++; } if ($this->params->get('showall')) { $this->list[$i] = new \stdClass(); $this->list[$i]->link = RouteHelper::getArticleRoute($row->slug, $row->catid, $row->language) . '&showall=1'; $this->list[$i]->title = $this->getApplication()->getLanguage()->_('PLG_CONTENT_PAGEBREAK_ALL_PAGES'); $this->list[$i]->active = ($limitstart === $i - 1); } $list = $this->list; $path = PluginHelper::getLayoutPath('content', 'pagebreak', 'toc'); ob_start(); include $path; $row->toc = ob_get_clean(); } /** * Creates the navigation for the item * * @param object &$row The article object. Note $article->text is also available * @param int $page The page number * @param int $n The total number of pages * * @return void * * @since 1.6 */ private function createNavigation(&$row, $page, $n) { $links = [ 'next' => '', 'previous' => '', ]; if ($page < $n - 1) { $links['next'] = RouteHelper::getArticleRoute($row->slug, $row->catid, $row->language) . '&limitstart=' . ($page + 1); } if ($page > 0) { $links['previous'] = RouteHelper::getArticleRoute($row->slug, $row->catid, $row->language); if ($page > 1) { $links['previous'] .= '&limitstart=' . ($page - 1); } } $path = PluginHelper::getLayoutPath('content', 'pagebreak', 'navigation'); ob_start(); include $path; $row->text .= ob_get_clean(); } } pagebreak/services/provider.php000064400000002467151664163730012700 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.pagebreak * * @copyright (C) 2023 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\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\PageBreak\Extension\PageBreak; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.4.0 */ public function register(Container $container): void { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new PageBreak( $dispatcher, (array) PluginHelper::getPlugin('content', 'pagebreak') ); $plugin->setApplication(Factory::getApplication()); return $plugin; } ); } }; pagebreak/index.html000060400000000037151664163730010472 0ustar00<!DOCTYPE html><title></title> joomla/src/Extension/Joomla.php000064400000045245151664163730012550 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.joomla * * @copyright (C) 2010 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\Joomla\Extension; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Language\Language; use Joomla\CMS\Language\Text; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\CMS\Table\CoreContent; use Joomla\CMS\User\UserFactoryAwareTrait; use Joomla\CMS\Workflow\WorkflowServiceInterface; use Joomla\Component\Workflow\Administrator\Table\StageTable; use Joomla\Component\Workflow\Administrator\Table\WorkflowTable; use Joomla\Database\DatabaseAwareTrait; use Joomla\Database\ParameterType; use Joomla\Utilities\ArrayHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Example Content Plugin * * @since 1.6 */ final class Joomla extends CMSPlugin { use DatabaseAwareTrait; use UserFactoryAwareTrait; /** * The save event. * * @param string $context The context * @param object $table The item * @param boolean $isNew Is new item * @param array $data The validated data * * @return boolean * * @since 4.0.0 */ public function onContentBeforeSave($context, $table, $isNew, $data) { if ($context === 'com_menus.item') { return $this->checkMenuItemBeforeSave($context, $table, $isNew, $data); } // Check we are handling the frontend edit form. if (!in_array($context, ['com_workflow.stage', 'com_workflow.workflow']) || $isNew || !$table->hasField('published')) { return true; } $item = clone $table; $item->load($table->id); $publishedField = $item->getColumnAlias('published'); if ($item->$publishedField > 0 && isset($data[$publishedField]) && $data[$publishedField] < 1) { switch ($context) { case 'com_workflow.workflow': return $this->workflowNotUsed($item->id); case 'com_workflow.stage': return $this->stageNotUsed($item->id); } } return true; } /** * Example after save content method * Article is passed by reference, but after the save, so no changes will be saved. * Method is called right after the content is saved * * @param string $context The context of the content passed to the plugin (added in 1.6) * @param object $article A JTableContent object * @param boolean $isNew If the content is just about to be created * * @return void * * @since 1.6 */ public function onContentAfterSave($context, $article, $isNew): void { // Check we are handling the frontend edit form. if ($context !== 'com_content.form') { return; } // Check if this function is enabled. if (!$this->params->def('email_new_fe', 1)) { return; } // Check this is a new article. if (!$isNew) { return; } $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('id')) ->from($db->quoteName('#__users')) ->where($db->quoteName('sendEmail') . ' = 1') ->where($db->quoteName('block') . ' = 0'); $db->setQuery($query); $users = (array) $db->loadColumn(); if (empty($users)) { return; } $user = $this->getApplication()->getIdentity(); // Messaging for new items $default_language = ComponentHelper::getParams('com_languages')->get('administrator'); $debug = $this->getApplication()->get('debug_lang'); foreach ($users as $user_id) { if ($user_id != $user->id) { // Load language for messaging $receiver = $this->getUserFactory()->loadUserById($user_id); $lang = Language::getInstance($receiver->getParam('admin_language', $default_language), $debug); $lang->load('com_content'); $message = [ 'user_id_to' => $user_id, 'subject' => $lang->_('COM_CONTENT_NEW_ARTICLE'), 'message' => sprintf($lang->_('COM_CONTENT_ON_NEW_CONTENT'), $user->get('name'), $article->title), ]; $model_message = $this->getApplication()->bootComponent('com_messages')->getMVCFactory() ->createModel('Message', 'Administrator'); $model_message->save($message); } } } /** * Don't allow categories to be deleted if they contain items or subcategories with items * * @param string $context The context for the content passed to the plugin. * @param object $data The data relating to the content that was deleted. * * @return boolean * * @since 1.6 */ public function onContentBeforeDelete($context, $data) { // Skip plugin if we are deleting something other than categories if (!in_array($context, ['com_categories.category', 'com_workflow.stage', 'com_workflow.workflow'])) { return true; } switch ($context) { case 'com_categories.category': return $this->canDeleteCategories($data); case 'com_workflow.workflow': return $this->workflowNotUsed($data->id); case 'com_workflow.stage': return $this->stageNotUsed($data->id); } } /** * Don't allow workflows/stages to be deleted if they contain items * * @param string $context The context for the content passed to the plugin. * @param object $pks The IDs of the records which will be changed. * @param object $value The new state. * * @return boolean * * @since 4.0.0 */ public function onContentBeforeChangeState($context, $pks, $value) { if ($value > 0 || !in_array($context, ['com_workflow.workflow', 'com_workflow.stage'])) { return true; } $result = true; foreach ($pks as $id) { switch ($context) { case 'com_workflow.workflow': $result = $result && $this->workflowNotUsed($id); break; case 'com_workflow.stage': $result = $result && $this->stageNotUsed($id); break; } } return $result; } /** * Checks if a given category can be deleted * * @param object $data The category object * * @return boolean */ private function canDeleteCategories($data) { // Check if this function is enabled. if (!$this->params->def('check_categories', 1)) { return true; } $extension = $this->getApplication()->getInput()->getString('extension'); // Default to true if not a core extension $result = true; $tableInfo = [ 'com_banners' => ['table_name' => '#__banners'], 'com_contact' => ['table_name' => '#__contact_details'], 'com_content' => ['table_name' => '#__content'], 'com_newsfeeds' => ['table_name' => '#__newsfeeds'], 'com_users' => ['table_name' => '#__user_notes'], 'com_weblinks' => ['table_name' => '#__weblinks'], ]; // Now check to see if this is a known core extension if (isset($tableInfo[$extension])) { // Get table name for known core extensions $table = $tableInfo[$extension]['table_name']; // See if this category has any content items $count = $this->countItemsInCategory($table, $data->get('id')); // Return false if db error if ($count === false) { $result = false; } else { // Show error if items are found in the category if ($count > 0) { $msg = Text::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED', $data->get('title')) . ' ' . Text::plural('COM_CATEGORIES_N_ITEMS_ASSIGNED', $count); $this->getApplication()->enqueueMessage($msg, 'error'); $result = false; } // Check for items in any child categories (if it is a leaf, there are no child categories) if (!$data->isLeaf()) { $count = $this->countItemsInChildren($table, $data->get('id'), $data); if ($count === false) { $result = false; } elseif ($count > 0) { $msg = Text::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED', $data->get('title')) . ' ' . Text::plural('COM_CATEGORIES_HAS_SUBCATEGORY_ITEMS', $count); $this->getApplication()->enqueueMessage($msg, 'error'); $result = false; } } } } return $result; } /** * Checks if a given workflow can be deleted * * @param int $pk The stage ID * * @return boolean * * @since 4.0.0 */ private function workflowNotUsed($pk) { // Check if this workflow is the default stage $table = new WorkflowTable($this->getDatabase()); $table->load($pk); if (empty($table->id)) { return true; } if ($table->default) { throw new \Exception($this->getApplication()->getLanguage()->_('COM_WORKFLOW_MSG_DELETE_IS_DEFAULT')); } $parts = explode('.', $table->extension); $component = $this->getApplication()->bootComponent($parts[0]); $section = ''; if (!empty($parts[1])) { $section = $parts[1]; } // No core interface => we're ok if (!$component instanceof WorkflowServiceInterface) { return true; } /** @var \Joomla\Component\Workflow\Administrator\Model\StagesModel $model */ $model = $this->getApplication()->bootComponent('com_workflow')->getMVCFactory() ->createModel('Stages', 'Administrator', ['ignore_request' => true]); $model->setState('filter.workflow_id', $pk); $model->setState('filter.extension', $table->extension); $stages = $model->getItems(); $stage_ids = array_column($stages, 'id'); $result = $this->countItemsInStage($stage_ids, $table->extension); // Return false if db error if ($result > 0) { throw new \Exception($this->getApplication()->getLanguage()->_('COM_WORKFLOW_MSG_DELETE_WORKFLOW_IS_ASSIGNED')); } return true; } /** * Checks if a given stage can be deleted * * @param int $pk The stage ID * * @return boolean * * @since 4.0.0 */ private function stageNotUsed($pk) { $table = new StageTable($this->getDatabase()); $table->load($pk); if (empty($table->id)) { return true; } // Check if this stage is the default stage if ($table->default) { throw new \Exception($this->getApplication()->getLanguage()->_('COM_WORKFLOW_MSG_DELETE_IS_DEFAULT')); } $workflow = new WorkflowTable($this->getDatabase()); $workflow->load($table->workflow_id); if (empty($workflow->id)) { return true; } $parts = explode('.', $workflow->extension); $component = $this->getApplication()->bootComponent($parts[0]); // No core interface => we're ok if (!$component instanceof WorkflowServiceInterface) { return true; } $stage_ids = [$table->id]; $result = $this->countItemsInStage($stage_ids, $workflow->extension); // Return false if db error if ($result > 0) { throw new \Exception($this->getApplication()->getLanguage()->_('COM_WORKFLOW_MSG_DELETE_STAGE_IS_ASSIGNED')); } return true; } /** * Get count of items in a category * * @param string $table table name of component table (column is catid) * @param integer $catid id of the category to check * * @return mixed count of items found or false if db error * * @since 1.6 */ private function countItemsInCategory($table, $catid) { $db = $this->getDatabase(); $query = $db->getQuery(true); // Count the items in this category $query->select('COUNT(' . $db->quoteName('id') . ')') ->from($db->quoteName($table)) ->where($db->quoteName('catid') . ' = :catid') ->bind(':catid', $catid, ParameterType::INTEGER); $db->setQuery($query); try { $count = $db->loadResult(); } catch (\RuntimeException $e) { $this->getApplication()->enqueueMessage($e->getMessage(), 'error'); return false; } return $count; } /** * Get count of items in assigned to a stage * * @param array $stageIds The stage ids to test for * @param string $extension The extension of the workflow * * @return bool * * @since 4.0.0 */ private function countItemsInStage(array $stageIds, string $extension): bool { $db = $this->getDatabase(); $parts = explode('.', $extension); $stageIds = ArrayHelper::toInteger($stageIds); $stageIds = array_filter($stageIds); $section = ''; if (!empty($parts[1])) { $section = $parts[1]; } $component = $this->getApplication()->bootComponent($parts[0]); $table = $component->getWorkflowTableBySection($section); if (empty($stageIds) || !$table) { return false; } $query = $db->getQuery(true); $query->select('COUNT(' . $db->quoteName('b.id') . ')') ->from($db->quoteName('#__workflow_associations', 'wa')) ->from($db->quoteName('#__workflow_stages', 's')) ->from($db->quoteName($table, 'b')) ->where($db->quoteName('wa.stage_id') . ' = ' . $db->quoteName('s.id')) ->where($db->quoteName('wa.item_id') . ' = ' . $db->quoteName('b.id')) ->whereIn($db->quoteName('s.id'), $stageIds); try { return (int) $db->setQuery($query)->loadResult(); } catch (\Exception $e) { $this->getApplication()->enqueueMessage($e->getMessage(), 'error'); } return false; } /** * Get count of items in a category's child categories * * @param string $table table name of component table (column is catid) * @param integer $catid id of the category to check * @param object $data The data relating to the content that was deleted. * * @return mixed count of items found or false if db error * * @since 1.6 */ private function countItemsInChildren($table, $catid, $data) { $db = $this->getDatabase(); // Create subquery for list of child categories $childCategoryTree = $data->getTree(); // First element in tree is the current category, so we can skip that one unset($childCategoryTree[0]); $childCategoryIds = []; foreach ($childCategoryTree as $node) { $childCategoryIds[] = (int) $node->id; } // Make sure we only do the query if we have some categories to look in if (count($childCategoryIds)) { // Count the items in this category $query = $db->getQuery(true) ->select('COUNT(' . $db->quoteName('id') . ')') ->from($db->quoteName($table)) ->whereIn($db->quoteName('catid'), $childCategoryIds); $db->setQuery($query); try { $count = $db->loadResult(); } catch (\RuntimeException $e) { $this->getApplication()->enqueueMessage($e->getMessage(), 'error'); return false; } return $count; } else { // If we didn't have any categories to check, return 0 return 0; } } /** * Change the state in core_content if the stage in a table is changed * * @param string $context The context for the content passed to the plugin. * @param array $pks A list of primary key ids of the content that has changed stage. * @param integer $value The value of the condition that the content has been changed to * * @return boolean * * @since 3.1 */ public function onContentChangeState($context, $pks, $value) { $pks = ArrayHelper::toInteger($pks); if ($context === 'com_workflow.stage' && $value < 1) { foreach ($pks as $pk) { if (!$this->stageNotUsed($pk)) { return false; } } return true; } $db = $this->getDatabase(); $query = $db->getQuery(true) ->select($db->quoteName('core_content_id')) ->from($db->quoteName('#__ucm_content')) ->where($db->quoteName('core_type_alias') . ' = :context') ->whereIn($db->quoteName('core_content_item_id'), $pks) ->bind(':context', $context); $db->setQuery($query); $ccIds = $db->loadColumn(); $cctable = new CoreContent($db); $cctable->publish($ccIds, $value); return true; } /** * The save event. * * @param string $context The context * @param object $table The item * @param boolean $isNew Is new item * @param array $data The validated data * * @return boolean * * @since 3.9.12 */ private function checkMenuItemBeforeSave($context, $table, $isNew, $data) { // Special case for Create article menu item if ($table->link !== 'index.php?option=com_content&view=form&layout=edit') { return true; } // Display error if catid is not set when enable_category is enabled $params = json_decode($table->params, true); if (isset($params['enable_category']) && $params['enable_category'] === 1 && empty($params['catid'])) { $table->setError($this->getApplication()->getLanguage()->_('COM_CONTENT_CREATE_ARTICLE_ERROR')); return false; } return true; } } joomla/services/provider.php000064400000003041151664163730012225 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.joomla * * @copyright (C) 2023 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\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\User\UserFactoryInterface; use Joomla\Database\DatabaseInterface; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\Joomla\Extension\Joomla; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.4.0 */ public function register(Container $container): void { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new Joomla( $dispatcher, (array) PluginHelper::getPlugin('content', 'joomla') ); $plugin->setApplication(Factory::getApplication()); $plugin->setDatabase($container->get(DatabaseInterface::class)); $plugin->setUserFactory($container->get(UserFactoryInterface::class)); return $plugin; } ); } }; joomla/index.html000060400000000037151664163730010032 0ustar00<!DOCTYPE html><title></title> joomla/joomla.xml000064400000003214151664163730010044 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_joomla</name> <author>Joomla! Project</author> <creationDate>2010-11</creationDate> <copyright>(C) 2010 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.0.0</version> <description>PLG_CONTENT_JOOMLA_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\Joomla</namespace> <files> <folder plugin="joomla">services</folder> <folder>src</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_joomla.ini</language> <language tag="en-GB">language/en-GB/plg_content_joomla.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="check_categories" type="radio" layout="joomla.form.field.radio.switcher" label="PLG_CONTENT_JOOMLA_FIELD_CHECK_CATEGORIES_LABEL" description="PLG_CONTENT_JOOMLA_FIELD_CHECK_CATEGORIES_DESC" default="1" filter="integer" > <option value="0">JNO</option> <option value="1">JYES</option> </field> <field name="email_new_fe" type="radio" label="PLG_CONTENT_JOOMLA_FIELD_EMAIL_NEW_FE_LABEL" description="PLG_CONTENT_JOOMLA_FIELD_EMAIL_NEW_FE_DESC" layout="joomla.form.field.radio.switcher" default="1" filter="integer" > <option value="0">JNO</option> <option value="1">JYES</option> </field> </fieldset> </fields> </config> </extension> fields/services/provider.php000064400000002306151664163730012215 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.fields * * @copyright (C) 2022 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\Extension\PluginInterface; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\Fields\Extension\Fields; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.3.0 */ public function register(Container $container) { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new Fields( $dispatcher, (array) PluginHelper::getPlugin('content', 'fields') ); return $plugin; } ); } }; fields/fields.xml000064400000001676151664163730010030 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_fields</name> <author>Joomla! Project</author> <creationDate>2017-02</creationDate> <copyright>(C) 2017 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.7.0</version> <description>PLG_CONTENT_FIELDS_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\Fields</namespace> <files> <folder plugin="fields">services</folder> <folder>src</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_fields.ini</language> <language tag="en-GB">language/en-GB/plg_content_fields.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> </fieldset> </fields> </config> </extension> fields/src/Extension/Fields.php000064400000012573151664163730012520 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.fields * * @copyright (C) 2017 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\Fields\Extension; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\Component\Fields\Administrator\Helper\FieldsHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Plug-in to show a custom field in eg an article * This uses the {fields ID} syntax * * @since 3.7.0 */ final class Fields extends CMSPlugin { /** * Plugin that shows a custom field * * @param string $context The context of the content being passed to the plugin. * @param object &$item The item object. Note $article->text is also available * @param object &$params The article params * @param int $page The 'page' number * * @return void * * @since 3.7.0 */ public function onContentPrepare($context, &$item, &$params, $page = 0) { // If the item has a context, overwrite the existing one if ($context === 'com_finder.indexer' && !empty($item->context)) { $context = $item->context; } elseif ($context === 'com_finder.indexer') { // Don't run this plugin when the content is being indexed and we have no real context return; } // This plugin only works if $item is an object if (!is_object($item)) { return; } // Don't run if there is no text property (in case of bad calls) or it is empty if (!property_exists($item, 'text') || empty($item->text)) { return; } // Prepare the text if (property_exists($item, 'text') && strpos($item->text, 'field') !== false) { $item->text = $this->prepare($item->text, $context, $item); } // Prepare the intro text if (property_exists($item, 'introtext') && is_string($item->introtext) && strpos($item->introtext, 'field') !== false) { $item->introtext = $this->prepare($item->introtext, $context, $item); } // Prepare the full text if (!empty($item->fulltext) && strpos($item->fulltext, 'field') !== false) { $item->fulltext = $this->prepare($item->fulltext, $context, $item); } } /** * Prepares the given string by parsing {field} and {fieldgroup} groups and replacing them. * * @param string $string The text to prepare * @param string $context The context of the content * @param object $item The item object * * @return string * * @since 3.8.1 */ private function prepare($string, $context, $item) { // Search for {field ID} or {fieldgroup ID} tags and put the results into $matches. $regex = '/{(field|fieldgroup)\s+(.*?)}/i'; preg_match_all($regex, $string, $matches, PREG_SET_ORDER); if (!$matches) { return $string; } $parts = FieldsHelper::extract($context); if (!$parts || count($parts) < 2) { return $string; } $context = $parts[0] . '.' . $parts[1]; $fields = FieldsHelper::getFields($context, $item, true); $fieldsById = []; $groups = []; // Rearranging fields in arrays for easier lookup later. foreach ($fields as $field) { $fieldsById[$field->id] = $field; $groups[$field->group_id][] = $field; } foreach ($matches as $i => $match) { // $match[0] is the full pattern match, $match[1] is the type (field or fieldgroup) and $match[2] the ID and optional the layout $explode = explode(',', $match[2]); $id = (int) $explode[0]; $output = ''; if ($match[1] === 'field' && $id) { if (isset($fieldsById[$id])) { $layout = !empty($explode[1]) ? trim($explode[1]) : $fieldsById[$id]->params->get('layout', 'render'); $output = FieldsHelper::render( $context, 'field.' . $layout, [ 'item' => $item, 'context' => $context, 'field' => $fieldsById[$id], ] ); } } else { if ($match[2] === '*') { $match[0] = str_replace('*', '\*', $match[0]); $renderFields = $fields; } else { $renderFields = $groups[$id] ?? ''; } if ($renderFields) { $layout = !empty($explode[1]) ? trim($explode[1]) : 'render'; $output = FieldsHelper::render( $context, 'fields.' . $layout, [ 'item' => $item, 'context' => $context, 'fields' => $renderFields, ] ); } } $string = preg_replace("|$match[0]|", addcslashes($output, '\\$'), $string, 1); } return $string; } } index.html000060400000000037151664163730006551 0ustar00<!DOCTYPE html><title></title> emailcloak/services/provider.php000064400000002466151664163730013057 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.emailcloak * * @copyright (C) 2022 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\Extension\PluginInterface; use Joomla\CMS\Factory; use Joomla\CMS\Plugin\PluginHelper; use Joomla\DI\Container; use Joomla\DI\ServiceProviderInterface; use Joomla\Event\DispatcherInterface; use Joomla\Plugin\Content\EmailCloak\Extension\EmailCloak; return new class () implements ServiceProviderInterface { /** * Registers the service provider with a DI container. * * @param Container $container The DI container. * * @return void * * @since 4.3.0 */ public function register(Container $container) { $container->set( PluginInterface::class, function (Container $container) { $dispatcher = $container->get(DispatcherInterface::class); $plugin = new EmailCloak( $dispatcher, (array) PluginHelper::getPlugin('content', 'emailcloak') ); $plugin->setApplication(Factory::getApplication()); return $plugin; } ); } }; emailcloak/emailcloak.xml000064400000002410151664163730011501 0ustar00<?xml version="1.0" encoding="UTF-8"?> <extension type="plugin" group="content" method="upgrade"> <name>plg_content_emailcloak</name> <author>Joomla! Project</author> <creationDate>2005-11</creationDate> <copyright>(C) 2005 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.0.0</version> <description>PLG_CONTENT_EMAILCLOAK_XML_DESCRIPTION</description> <namespace path="src">Joomla\Plugin\Content\EmailCloak</namespace> <files> <folder plugin="emailcloak">services</folder> <folder>src</folder> </files> <languages> <language tag="en-GB">language/en-GB/plg_content_emailcloak.ini</language> <language tag="en-GB">language/en-GB/plg_content_emailcloak.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="mode" type="list" label="PLG_CONTENT_EMAILCLOAK_MODE_LABEL" default="1" filter="integer" validate="options" > <option value="0">PLG_CONTENT_EMAILCLOAK_NONLINKABLE</option> <option value="1">PLG_CONTENT_EMAILCLOAK_LINKABLE</option> </field> </fieldset> </fields> </config> </extension> emailcloak/index.html000060400000000037151664163730010652 0ustar00<!DOCTYPE html><title></title> emailcloak/src/Extension/EmailCloak.php000064400000047044151664163730014147 0ustar00<?php /** * @package Joomla.Plugin * @subpackage Content.emailcloak * * @copyright (C) 2006 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ namespace Joomla\Plugin\Content\EmailCloak\Extension; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Plugin\CMSPlugin; use Joomla\String\StringHelper; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; // phpcs:enable PSR1.Files.SideEffects /** * Email cloak plugin class. * * @since 1.5 */ final class EmailCloak extends CMSPlugin { /** * Plugin that cloaks all emails in content from spambots via Javascript. * * @param string $context The context of the content being passed to the plugin. * @param mixed &$row An object with a "text" property or the string to be cloaked. * @param mixed &$params Additional parameters. * @param integer $page Optional page number. Unused. Defaults to zero. * * @return void */ public function onContentPrepare($context, &$row, &$params, $page = 0) { // Don't run if in the API Application // Don't run this plugin when the content is being indexed if ($this->getApplication()->isClient('api') || $context === 'com_finder.indexer') { return; } // If the row is not an object or does not have a text property there is nothing to do if (!is_object($row) || !property_exists($row, 'text')) { return; } $this->cloak($row->text, $params); } /** * Generate a search pattern based on link and text. * * @param string $link The target of an email link. * @param string $text The text enclosed by the link. * * @return string A regular expression that matches a link containing the parameters. */ private function getPattern($link, $text) { $pattern = '~(?:<a ([^>]*)href\s*=\s*"mailto:' . $link . '"([^>]*))>' . $text . '</a>~i'; return $pattern; } /** * Cloak all emails in text from spambots via Javascript. * * @param string &$text The string to be cloaked. * @param mixed &$params Additional parameters. Parameter "mode" (integer, default 1) * replaces addresses with "mailto:" links if nonzero. * * @return void */ private function cloak(&$text, &$params) { /* * Check for presence of {emailcloak=off} which is explicits disables this * bot for the item. */ if (StringHelper::strpos($text, '{emailcloak=off}') !== false) { $text = StringHelper::str_ireplace('{emailcloak=off}', '', $text); return; } // Simple performance check to determine whether bot should process further. if (StringHelper::strpos($text, '@') === false) { return; } $mode = (int) $this->params->def('mode', 1); $mode = $mode === 1; // Example: any@example.org $searchEmail = '([\w\.\'\-\+]+\@(?:[a-z0-9\.\-]+\.)+(?:[a-zA-Z0-9\-]{2,24}))'; // Example: any@example.org?subject=anyText $searchEmailLink = $searchEmail . '([?&][\x20-\x7f][^"<>]+)'; // Any Text $searchText = '((?:[\x20-\x7f]|[\xA1-\xFF]|[\xC2-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF4][\x80-\xBF]{3})[^<>]+)'; // Any Image link $searchImage = '(<img[^>]+>)'; // Any Text with <span or <strong $searchTextSpan = '(<span[^>]+>|<span>|<strong>|<strong><span[^>]+>|<strong><span>)' . $searchText . '(</span>|</strong>|</span></strong>)'; // Any address with <span or <strong $searchEmailSpan = '(<span[^>]+>|<span>|<strong>|<strong><span[^>]+>|<strong><span>)' . $searchEmail . '(</span>|</strong>|</span></strong>)'; /* * Search and fix derivatives of link code <a href="http://mce_host/ourdirectory/email@example.org" * >email@example.org</a>. This happens when inserting an email in TinyMCE, cancelling its suggestion to add * the mailto: prefix... */ $pattern = $this->getPattern($searchEmail, $searchEmail); $pattern = str_replace('"mailto:', '"([\x20-\x7f][^<>]+/)', $pattern); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[3][0]; $mailText = $regs[5][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[4][0]; // Check to see if mail text is different from mail addy $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 1, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search and fix derivatives of link code <a href="http://mce_host/ourdirectory/email@example.org" * >anytext</a>. This happens when inserting an email in TinyMCE, cancelling its suggestion to add * the mailto: prefix... */ $pattern = $this->getPattern($searchEmail, $searchText); $pattern = str_replace('"mailto:', '"([\x20-\x7f][^<>]+/)', $pattern); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[3][0]; $mailText = $regs[5][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[4][0]; // Check to see if mail text is different from mail addy $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 0, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@example.org" * >email@example.org</a> */ $pattern = $this->getPattern($searchEmail, $searchEmail); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0]; $mailText = $regs[4][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[3][0]; // Check to see if mail text is different from mail addy $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 1, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@amail.com" * ><anyspan >email@amail.com</anyspan></a> */ $pattern = $this->getPattern($searchEmail, $searchEmailSpan); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0]; $mailText = $regs[4][0] . $regs[5][0] . $regs[6][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[3][0]; // Check to see if mail text is different from mail addy $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 1, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@amail.com"> * <anyspan >anytext</anyspan></a> */ $pattern = $this->getPattern($searchEmail, $searchTextSpan); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0]; $mailText = $regs[4][0] . $regs[5][0] . $regs[6][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[3][0]; $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 0, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@example.org"> * anytext</a> */ $pattern = $this->getPattern($searchEmail, $searchText); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0]; $mailText = $regs[4][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[3][0]; $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 0, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@example.org"> * <img anything></a> */ $pattern = $this->getPattern($searchEmail, $searchImage); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0]; $mailText = $regs[4][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[3][0]; $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 0, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@example.org"> * <img anything>email@example.org</a> */ $pattern = $this->getPattern($searchEmail, $searchImage . $searchEmail); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0]; $mailText = $regs[4][0] . $regs[5][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[3][0]; $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 1, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@example.org"> * <img anything>any text</a> */ $pattern = $this->getPattern($searchEmail, $searchImage . $searchText); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0]; $mailText = $regs[4][0] . $regs[5][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[3][0]; $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 0, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@example.org? * subject=Text">email@example.org</a> */ $pattern = $this->getPattern($searchEmailLink, $searchEmail); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0] . $regs[3][0]; $mailText = $regs[5][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[4][0]; // Needed for handling of Body parameter $mail = str_replace('&', '&', $mail); // Check to see if mail text is different from mail addy $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 1, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@example.org? * subject=Text">anytext</a> */ $pattern = $this->getPattern($searchEmailLink, $searchText); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0] . $regs[3][0]; $mailText = $regs[5][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[4][0]; // Needed for handling of Body parameter $mail = str_replace('&', '&', $mail); $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 0, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@amail.com?subject= Text" * ><anyspan >email@amail.com</anyspan></a> */ $pattern = $this->getPattern($searchEmailLink, $searchEmailSpan); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0] . $regs[3][0]; $mailText = $regs[5][0] . $regs[6][0] . $regs[7][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[4][0]; // Check to see if mail text is different from mail addy $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 1, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code <a href="mailto:email@amail.com?subject= Text"> * <anyspan >anytext</anyspan></a> */ $pattern = $this->getPattern($searchEmailLink, $searchTextSpan); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0] . $regs[3][0]; $mailText = $regs[5][0] . $regs[6][0] . $regs[7][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[4][0]; $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 0, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code * <a href="mailto:email@amail.com?subject=Text"><img anything></a> */ $pattern = $this->getPattern($searchEmailLink, $searchImage); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0] . $regs[3][0]; $mailText = $regs[5][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[4][0]; // Needed for handling of Body parameter $mail = str_replace('&', '&', $mail); // Check to see if mail text is different from mail addy $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 0, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code * <a href="mailto:email@amail.com?subject=Text"><img anything>email@amail.com</a> */ $pattern = $this->getPattern($searchEmailLink, $searchImage . $searchEmail); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0] . $regs[3][0]; $mailText = $regs[5][0] . $regs[6][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[4][0]; // Needed for handling of Body parameter $mail = str_replace('&', '&', $mail); // Check to see if mail text is different from mail addy $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 1, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for derivatives of link code * <a href="mailto:email@amail.com?subject=Text"><img anything>any text</a> */ $pattern = $this->getPattern($searchEmailLink, $searchImage . $searchText); while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[2][0] . $regs[3][0]; $mailText = $regs[5][0] . $regs[6][0]; $attribsBefore = $regs[1][0]; $attribsAfter = $regs[4][0]; // Needed for handling of Body parameter $mail = str_replace('&', '&', $mail); // Check to see if mail text is different from mail addy $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mailText, 0, $attribsBefore, $attribsAfter); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0])); } /* * Search for plain text email addresses, such as email@example.org but within HTML tags: * <img src="..." title="email@example.org"> or <input type="text" placeholder="email@example.org"> * The '<[^<]*>(*SKIP)(*F)|' trick is used to exclude this kind of occurrences */ $pattern = '~<[^<]*(?<!\/)>(*SKIP)(*F)|<[^>]+?(\w*=\"' . $searchEmail . '\")[^>]*\/>~i'; while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[0][0]; $replacement = HTMLHelper::_('email.cloak', $mail, 0, $mail); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($mail)); } /* * Search for plain text email addresses, such as email@example.org but within HTML attributes: * <a title="email@example.org" href="#">email</a> or <li title="email@example.org">email</li> */ $pattern = '(<[^>]+?(\w*=\"' . $searchEmail . '")[^>]*>[^<]+<[^<]+>)'; while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[0][0]; $replacement = HTMLHelper::_('email.cloak', $mail, 0, $mail); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[0][1], strlen($mail)); } /* * Search for plain text email addresses, such as email@example.org but not within HTML tags: * <p>email@example.org</p> * The '<[^<]*>(*SKIP)(*F)|' trick is used to exclude this kind of occurrences * The '<[^<]*(?<!\/(?:src))>(*SKIP)(*F)|' exclude image files with @ in filename */ $pattern = '~<[^<]*(?<!\/(?:src))>(*SKIP)(*F)|' . $searchEmail . '~i'; while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) { $mail = $regs[1][0]; $replacement = HTMLHelper::_('email.cloak', $mail, $mode, $mail); // Replace the found address with the js cloaked email $text = substr_replace($text, $replacement, $regs[1][1], strlen($mail)); } } }
/home/opticamezl/./www/newok/media/com_osmap/../com_languages/./../.././libraries/./../content.tar