primo commit
This commit is contained in:
72
plugins/content/confirmconsent/confirmconsent.xml
Normal file
72
plugins/content/confirmconsent/confirmconsent.xml
Normal file
@ -0,0 +1,72 @@
|
||||
<?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>
|
||||
46
plugins/content/confirmconsent/services/provider.php
Normal file
46
plugins/content/confirmconsent/services/provider.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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) {
|
||||
$plugin = new ConfirmConsent(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'confirmconsent')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,92 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
339
plugins/content/confirmconsent/src/Field/ConsentBoxField.php
Normal file
339
plugins/content/confirmconsent/src/Field/ConsentBoxField.php
Normal file
@ -0,0 +1,339 @@
|
||||
<?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 Form 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
|
||||
);
|
||||
}
|
||||
}
|
||||
52
plugins/content/contact/contact.xml
Normal file
52
plugins/content/contact/contact.xml
Normal file
@ -0,0 +1,52 @@
|
||||
<?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>
|
||||
48
plugins/content/contact/services/provider.php
Normal file
48
plugins/content/contact/services/provider.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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) {
|
||||
$plugin = new Contact(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'contact')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
$plugin->setDatabase($container->get(DatabaseInterface::class));
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
146
plugins/content/contact/src/Extension/Contact.php
Normal file
146
plugins/content/contact/src/Extension/Contact.php
Normal file
@ -0,0 +1,146 @@
|
||||
<?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];
|
||||
}
|
||||
}
|
||||
38
plugins/content/emailcloak/emailcloak.xml
Normal file
38
plugins/content/emailcloak/emailcloak.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?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>
|
||||
46
plugins/content/emailcloak/services/provider.php
Normal file
46
plugins/content/emailcloak/services/provider.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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) {
|
||||
$plugin = new EmailCloak(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'emailcloak')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
494
plugins/content/emailcloak/src/Extension/EmailCloak.php
Normal file
494
plugins/content/emailcloak/src/Extension/EmailCloak.php
Normal file
@ -0,0 +1,494 @@
|
||||
<?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\Event\Content\ContentPrepareEvent;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\Event\SubscriberInterface;
|
||||
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 implements SubscriberInterface
|
||||
{
|
||||
/**
|
||||
* Returns an array of events this subscriber will listen to.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return ['onContentPrepare' => 'onContentPrepare'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin that cloaks all emails in content from spambots via Javascript.
|
||||
*
|
||||
* @param ContentPrepareEvent $event Event instance
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function onContentPrepare(ContentPrepareEvent $event)
|
||||
{
|
||||
// Don't run if in the API Application
|
||||
// Don't run this plugin when the content is being indexed
|
||||
if ($this->getApplication()->isClient('api') || $event->getContext() === 'com_finder.indexer') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get content item
|
||||
$item = $event->getItem();
|
||||
|
||||
// If the item does not have a text property there is nothing to do
|
||||
if (!isset($item->text)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$text = $this->cloak($item->text);
|
||||
|
||||
if ($text) {
|
||||
$item->text = $text;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function cloak($text)
|
||||
{
|
||||
/*
|
||||
* Check for presence of {emailcloak=off} which is explicits disables this
|
||||
* bot for the item.
|
||||
*/
|
||||
if (StringHelper::strpos($text, '{emailcloak=off}') !== false) {
|
||||
return StringHelper::str_ireplace('{emailcloak=off}', '', $text);
|
||||
}
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
86
plugins/content/eventcalendar/eventcalendar.php
Normal file
86
plugins/content/eventcalendar/eventcalendar.php
Normal file
@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* @version $Id: example.php 14401 2010-01-26 14:10:00Z louis $
|
||||
* @package Joomla
|
||||
* @subpackage Content
|
||||
* @copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved.
|
||||
* @license GNU/GPL, see LICENSE.php
|
||||
* Joomla! is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses.
|
||||
* See COPYRIGHT.php for copyright notices and details.
|
||||
*/
|
||||
|
||||
// Check to ensure this file is included in Joomla!
|
||||
defined( '_JEXEC' ) or die( 'Restricted access' );
|
||||
|
||||
jimport( 'joomla.plugin.plugin' );
|
||||
|
||||
/**
|
||||
* Event Calendar Content Plugin
|
||||
*
|
||||
* @package Joomla
|
||||
* @subpackage Content
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
function EventCalendar_replacer( &$matches ) {
|
||||
$id = (int)$matches[1];
|
||||
$document =& JFactory::getDocument();
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/utilities.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/button.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/container.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/yahoo.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/event.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/dom.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/calendar.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/element.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/DCEventCalendar.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/intervalcalendar.js");
|
||||
$document->addScript("components/com_cpeventcalendar/DC_EventCalendar/calendarcolors.js");
|
||||
$document->addStyleSheet("components/com_cpeventcalendar/DC_EventCalendar/fonts-min.css");
|
||||
$document->addStyleSheet("components/com_cpeventcalendar/DC_EventCalendar/button.css");
|
||||
$document->addStyleSheet("components/com_cpeventcalendar/DC_EventCalendar/container.css");
|
||||
$document->addStyleSheet("components/com_cpeventcalendar/DC_EventCalendar/calendar.css");
|
||||
$document->addStyleSheet("components/com_cpeventcalendar/DC_EventCalendar/DCEventCalendar.css");
|
||||
$container = "plg".mt_rand();
|
||||
$styletext = "#".$container." .yui-calendar td.calcell {width:".(int)$matches[3]."px;height:".(int)$matches[4]."px;}";
|
||||
$document->addStyleDeclaration($styletext);
|
||||
$document->addScriptDeclaration("var pathCalendarCPE = \"".JURI::base(true)."/components/com_cpeventcalendar/DC_EventCalendar/\";\n".
|
||||
"var pathCalendarCPEJB = \"".JURI::base(true)."/\";\n".
|
||||
"initEventCalendar(\"".$id."\",\"".$container."\",".(int)$matches[5].",2,\"".$matches[2]."\",{},".(int)$matches[3].",".(int)$matches[4].");");
|
||||
$str = '<div style="z-index:1000;">
|
||||
<div id="'.$container.'"></div>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
';
|
||||
return $str;
|
||||
}
|
||||
|
||||
class plgContentEventcalendar extends JPlugin
|
||||
{
|
||||
public function __construct(& $subject, $config)
|
||||
{
|
||||
parent::__construct($subject, $config);
|
||||
$this->loadLanguage();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Example prepare content method
|
||||
*
|
||||
* Method is called by the view
|
||||
*
|
||||
* @param object The article object. Note $article->text is also available
|
||||
* @param object The article params
|
||||
* @param int The 'page' number
|
||||
*/
|
||||
public function onContentPrepare($context, &$article, &$params, $limitstart)
|
||||
{
|
||||
// define the regular expression for the bot
|
||||
$regex = "#\{eventcalendar\:(\d{1,2})\:(\S{5})\:(\d{1,3})\:(\d{1,3})\:(\d{1,2})\}#s";
|
||||
$article->text = preg_replace_callback( $regex, 'EventCalendar_replacer', $article->text );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
15
plugins/content/eventcalendar/eventcalendar.xml
Normal file
15
plugins/content/eventcalendar/eventcalendar.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension version="1.7" type="plugin" group="content">
|
||||
<name>Content - Event Calendar</name>
|
||||
<author>Codepeople</author>
|
||||
<creationDate>Julio 2011</creationDate>
|
||||
<copyright>Copyright (C) 2011 Codepeople. All rights reserved.</copyright>
|
||||
<license>GNU/GPL http://www.gnu.org/copyleft/gpl.html</license>
|
||||
<authorEmail>info@joomlacalendars.com</authorEmail>
|
||||
<authorUrl>www.joomlacalendars.org</authorUrl>
|
||||
<version>1.6.0</version>
|
||||
<description>Replace Event Calendar placeholders in article contents.</description>
|
||||
<files>
|
||||
<filename plugin="eventcalendar">eventcalendar.php</filename>
|
||||
</files>
|
||||
</extension>
|
||||
27
plugins/content/fields/fields.xml
Normal file
27
plugins/content/fields/fields.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?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>
|
||||
44
plugins/content/fields/services/provider.php
Normal file
44
plugins/content/fields/services/provider.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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) {
|
||||
$plugin = new Fields(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'fields')
|
||||
);
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
160
plugins/content/fields/src/Extension/Fields.php
Normal file
160
plugins/content/fields/src/Extension/Fields.php
Normal file
@ -0,0 +1,160 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
25
plugins/content/finder/finder.xml
Normal file
25
plugins/content/finder/finder.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?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>
|
||||
46
plugins/content/finder/services/provider.php
Normal file
46
plugins/content/finder/services/provider.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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) {
|
||||
$plugin = new Finder(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'finder')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
176
plugins/content/finder/src/Extension/Finder.php
Normal file
176
plugins/content/finder/src/Extension/Finder.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?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\Event\Finder as FinderEvent;
|
||||
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
|
||||
{
|
||||
/**
|
||||
* Flag to check whether finder plugins already imported.
|
||||
*
|
||||
* @var bool
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected $pluginsImported = false;
|
||||
|
||||
/**
|
||||
* 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 \Joomla\CMS\Table\Table\ object
|
||||
* @param bool $isNew If the content has just been created
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function onContentAfterSave($context, $article, $isNew): void
|
||||
{
|
||||
$this->importFinderPlugins();
|
||||
|
||||
// Trigger the onFinderAfterSave event.
|
||||
$this->getDispatcher()->dispatch('onFinderAfterSave', new FinderEvent\AfterSaveEvent('onFinderAfterSave', [
|
||||
'context' => $context,
|
||||
'subject' => $article,
|
||||
'isNew' => $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 \Joomla\CMS\Table\Table\ object.
|
||||
* @param bool $isNew If the content is just about to be created.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function onContentBeforeSave($context, $article, $isNew)
|
||||
{
|
||||
$this->importFinderPlugins();
|
||||
|
||||
// Trigger the onFinderBeforeSave event.
|
||||
$this->getDispatcher()->dispatch('onFinderBeforeSave', new FinderEvent\BeforeSaveEvent('onFinderBeforeSave', [
|
||||
'context' => $context,
|
||||
'subject' => $article,
|
||||
'isNew' => $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 \Joomla\CMS\Table\Table object.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 2.5
|
||||
*/
|
||||
public function onContentAfterDelete($context, $article): void
|
||||
{
|
||||
$this->importFinderPlugins();
|
||||
|
||||
// Trigger the onFinderAfterDelete event.
|
||||
$this->getDispatcher()->dispatch('onFinderAfterDelete', new FinderEvent\AfterDeleteEvent('onFinderAfterDelete', [
|
||||
'context' => $context,
|
||||
'subject' => $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)
|
||||
{
|
||||
$this->importFinderPlugins();
|
||||
|
||||
// Trigger the onFinderChangeState event.
|
||||
$this->getDispatcher()->dispatch('onFinderChangeState', new FinderEvent\AfterChangeStateEvent('onFinderChangeState', [
|
||||
'context' => $context,
|
||||
'subject' => $pks,
|
||||
'value' => $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)
|
||||
{
|
||||
$this->importFinderPlugins();
|
||||
|
||||
// Trigger the onFinderCategoryChangeState event.
|
||||
$this->getDispatcher()->dispatch('onFinderCategoryChangeState', new FinderEvent\AfterCategoryChangeStateEvent('onFinderCategoryChangeState', [
|
||||
'context' => $extension,
|
||||
'subject' => $pks,
|
||||
'value' => $value,
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper method to import finder plugins.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
protected function importFinderPlugins()
|
||||
{
|
||||
if ($this->pluginsImported) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->pluginsImported = true;
|
||||
|
||||
PluginHelper::importPlugin('finder', null, true, $this->getDispatcher());
|
||||
}
|
||||
}
|
||||
1
plugins/content/jem/index.html
Normal file
1
plugins/content/jem/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
42
plugins/content/jem/jem.php
Normal file
42
plugins/content/jem/jem.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @package JEM
|
||||
* @subpackage JEM Content Plugin
|
||||
* @copyright (C) 2013-2024 joomlaeventmanager.net
|
||||
* @license https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
|
||||
/**
|
||||
* JEM Content Plugin
|
||||
*
|
||||
* @package JEM.Plugin
|
||||
* @subpackage Content.jem
|
||||
* @since 1.9.6
|
||||
*/
|
||||
class plgContentJem extends CMSPlugin
|
||||
{
|
||||
/**
|
||||
* Dissolve recurrence sets where deleted event is referred to as first.
|
||||
*
|
||||
* @param string The context for the content passed to the plugin.
|
||||
* @param object The data relating to the content that was deleted.
|
||||
*
|
||||
* @since 1.9.6
|
||||
*/
|
||||
public function onContentAfterDelete($context, $data)
|
||||
{
|
||||
// Skip plugin if we are deleting something other than events
|
||||
if (($context != 'com_jem.event') || empty($data->id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// event maybe first of recurrence set -> dissolve complete set
|
||||
JemHelper::dissolve_recurrence($data->id);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
24
plugins/content/jem/jem.xml
Normal file
24
plugins/content/jem/jem.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension version="2.5" type="plugin" group="content" method="upgrade">
|
||||
<name>plg_content_jem</name>
|
||||
<author>JEM Community</author>
|
||||
<authorEmail>info@joomlaeventmanager.net</authorEmail>
|
||||
<authorUrl>https://www.joomlaeventmanager.net</authorUrl>
|
||||
<creationDate>October 2024</creationDate>
|
||||
<copyright>copyright (C) 2013-2024 joomlaeventmanager.net</copyright>
|
||||
<license>https://www.gnu.org/licenses/gpl-3.0 GNU/GPL</license>
|
||||
<version>4.3.1</version>
|
||||
<description>PLG_CONTENT_JEM_XML_DESCRIPTION</description>
|
||||
|
||||
<files>
|
||||
<filename plugin="jem">jem.php</filename>
|
||||
<filename>index.html</filename>
|
||||
<folder>language</folder>
|
||||
</files>
|
||||
|
||||
<languages>
|
||||
<language tag="en-GB">language/en-GB/plg_content_jem.ini</language>
|
||||
<language tag="en-GB">language/en-GB/plg_content_jem.sys.ini</language>
|
||||
</languages>
|
||||
|
||||
</extension>
|
||||
1
plugins/content/jem/language/en-GB/index.html
Normal file
1
plugins/content/jem/language/en-GB/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
13
plugins/content/jem/language/en-GB/plg_content_jem.ini
Normal file
13
plugins/content/jem/language/en-GB/plg_content_jem.ini
Normal file
@ -0,0 +1,13 @@
|
||||
; @package JEM
|
||||
; @subpackage JEM Content Plugin
|
||||
; @copyright (C) 2013-2024 joomlaeventmanager.net
|
||||
; @copyright (C) 2005-2009 Christoph Lukes
|
||||
; @license https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
|
||||
;
|
||||
; All translations can be found at https://app.transifex.com/jemproject/
|
||||
; Please join the translation team if you want to contribute your changes to the translations
|
||||
;
|
||||
; Note: All ini files need to be saved as UTF-8, no BOM
|
||||
|
||||
PLG_CONTENT_JEM = "JEM - Content Plugin"
|
||||
PLG_CONTENT_JEM_XML_DESCRIPTION = "The plugin processes the events for the JEM extension."
|
||||
13
plugins/content/jem/language/en-GB/plg_content_jem.sys.ini
Normal file
13
plugins/content/jem/language/en-GB/plg_content_jem.sys.ini
Normal file
@ -0,0 +1,13 @@
|
||||
; @package JEM
|
||||
; @subpackage JEM Content Plugin
|
||||
; @copyright (C) 2013-2024 joomlaeventmanager.net
|
||||
; @copyright (C) 2005-2009 Christoph Lukes
|
||||
; @license https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
|
||||
;
|
||||
; All translations can be found at https://app.transifex.com/jemproject/
|
||||
; Please join the translation team if you want to contribute your changes to the translations
|
||||
;
|
||||
; Note: All ini files need to be saved as UTF-8, no BOM
|
||||
|
||||
PLG_CONTENT_JEM = "JEM - Content Plugin"
|
||||
PLG_CONTENT_JEM_XML_DESCRIPTION = "Does event processing for JEM extension."
|
||||
1
plugins/content/jem/language/index.html
Normal file
1
plugins/content/jem/language/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
1
plugins/content/jemlistevents/index.html
Normal file
1
plugins/content/jemlistevents/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
407
plugins/content/jemlistevents/jemlistevents.php
Normal file
407
plugins/content/jemlistevents/jemlistevents.php
Normal file
@ -0,0 +1,407 @@
|
||||
<?php
|
||||
/**
|
||||
* JemListEvent is a Plugin to display events in articles.
|
||||
* For more information visit joomlaeventmanager.net
|
||||
*
|
||||
* @package JEM
|
||||
* @subpackage JEM Listevents Plugin
|
||||
* @author JEM Team <info@joomlaeventmanager.net>, Luis Raposo
|
||||
* @copyright (C) 2013-2024 joomlaeventmanager.net
|
||||
* @license https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
BaseDatabaseModel::addIncludePath(JPATH_SITE.'/components/com_jem/models', 'JemModel');
|
||||
require_once JPATH_SITE.'/components/com_jem/helpers/helper.php';
|
||||
require_once(JPATH_SITE.'/components/com_jem/classes/output.class.php');
|
||||
|
||||
|
||||
/**
|
||||
* JEM List Events Plugin
|
||||
*
|
||||
* @since 2.2.2
|
||||
*/
|
||||
class PlgContentJemlistevents extends CMSPlugin
|
||||
{
|
||||
/** all options with their default values
|
||||
*/
|
||||
protected static $optionDefaults = array(
|
||||
'type' => 'unfinished',
|
||||
'show_featured' => 'off',
|
||||
'title' => 'on',
|
||||
'cut_title' => 40,
|
||||
'show_date' => 'on',
|
||||
'date_format' => '',
|
||||
'show_time' => 'on',
|
||||
'time_format' => '',
|
||||
'show_enddatetime' => 'off', // for backward compatibility
|
||||
'catids' => '',
|
||||
'show_category' => 'off',
|
||||
'venueids' => '',
|
||||
'show_venue' => 'off',
|
||||
'max_events' => '5',
|
||||
'no_events_msg' => '',
|
||||
);
|
||||
|
||||
/** options we have to convert from numbers to 'on'/'off'
|
||||
*/
|
||||
protected static $optionConvert = array('show_featured', 'show_time', 'show_enddatetime');
|
||||
|
||||
/** all text tokens with their corresponding option
|
||||
*/
|
||||
protected static $optionTokens = array( // {jemlistevents
|
||||
'type' => 'type', // [type=today|unfinished|upcoming|archived|newest];
|
||||
'featured' => 'show_featured', // [featured=on|off];
|
||||
'title' => 'title', // [title=on|link|off];
|
||||
'cuttitle' => 'cut_title', // [cuttitle=n];
|
||||
'date' => 'show_date', // [date=on|link|off];
|
||||
// 'dateformat' => 'date_format', //
|
||||
'time' => 'show_time', // [time=on|off];
|
||||
// 'timeformat' => 'time_format', //
|
||||
'enddatetime' => 'show_enddatetime', // [enddatetime=on|off];
|
||||
'catids' => 'catids', // [catids=n];
|
||||
'category' => 'show_category', // [category=on|link|off];
|
||||
'venueids' => 'venueids', // [venueids=n];
|
||||
'venue' => 'show_venue', // [venue=on|link|off];
|
||||
'max' => 'max_events', // [max=n];
|
||||
'noeventsmsg' => 'no_events_msg', // [noeventsmsg=msg]
|
||||
); // }
|
||||
|
||||
/** all text tokens with their corresponding option
|
||||
*/
|
||||
protected static $tokenValues = array( // {jemlistevents
|
||||
'type' => array('today', 'unfinished', 'upcoming', 'archived', 'newest'),
|
||||
'featured' => array('on', 'off'),
|
||||
'title' => array('on', 'link', 'off'),
|
||||
'date' => array('on', 'link', 'off'),
|
||||
'time' => array('on', 'off'),
|
||||
'enddatetime' => array('on', 'off'),
|
||||
'category' => array('on', 'link', 'off'),
|
||||
'venue' => array('on', 'link', 'off'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param object $subject The object to observe
|
||||
* @param array $config An array that holds the plugin configuration
|
||||
*/
|
||||
public function __construct(&$subject, $config)
|
||||
{
|
||||
parent::__construct($subject, $config);
|
||||
$this->loadLanguage();
|
||||
$this->loadLanguage('com_jem', JPATH_ADMINISTRATOR.'/components/com_jem');
|
||||
|
||||
// JemHelper::addFileLogger();
|
||||
} // __construct()
|
||||
|
||||
/**
|
||||
* Plugin that outputs a list of events from JEM
|
||||
*
|
||||
* @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 boolean True on success.
|
||||
*/
|
||||
public function onContentPrepare($context, &$row, &$params, $page = 0)
|
||||
{
|
||||
// Don't run this plugin when the content is being indexed
|
||||
if ($context == 'com_finder.indexer') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// simple performance check to determine whether the bot should process further
|
||||
if (!isset($row->text) || \Joomla\String\StringHelper::strpos($row->text, 'jemlistevents') === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// expression to search for
|
||||
$regex = '/{jemlistevents\s*(.*?)}/i';
|
||||
|
||||
// check whether the plugin has been unpublished
|
||||
if (!$this->params->get('enabled', 1)) {
|
||||
$row->text = preg_replace($regex, '', $row->text);
|
||||
return true;
|
||||
}
|
||||
|
||||
// find all instances of plugin and put in $matches
|
||||
preg_match_all($regex, $row->text, $matches);
|
||||
|
||||
// plugin only processes if there are any instances of the plugin in the text
|
||||
if ($matches) {
|
||||
$this->_process($row, $matches, $regex);
|
||||
}
|
||||
|
||||
return true;
|
||||
} // onContentPrepare()
|
||||
|
||||
// The proccessing function
|
||||
protected function _process(&$content, &$matches, $regex)
|
||||
{
|
||||
// Get plugin parameters
|
||||
$defaults = array();
|
||||
foreach (self::$optionDefaults as $k => $v) {
|
||||
$defaults[$k] = $this->params->def($k, $v);
|
||||
if (in_array($k, self::$optionConvert) && is_numeric($defaults[$k])) {
|
||||
$defaults[$k] = ($defaults[$k] == '0') ? 'off' : 'on';
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($matches[0]); ++$i)
|
||||
{
|
||||
$match = $matches[1][$i];
|
||||
$params = $defaults;
|
||||
$options = explode(';', $match);
|
||||
|
||||
foreach ($options as $option)
|
||||
{
|
||||
$option = str_replace(array('[', ']'), '', $option);
|
||||
$pair = explode("=", $option, 2);
|
||||
if (empty($pair[0]) || empty($pair[1])) {
|
||||
continue;
|
||||
}
|
||||
$token = strtolower(trim($pair[0]));
|
||||
if (preg_match('/[ \'"]*(.*)[ \'"]*/', $pair[1], $m)) {
|
||||
$value = $m[1];
|
||||
// is this a known option?
|
||||
if (array_key_exists($token, self::$optionTokens)) {
|
||||
// option limited to specific values?
|
||||
if (!array_key_exists($token, self::$tokenValues) || (in_array($value, self::$tokenValues[$token]))) {
|
||||
$params[self::$optionTokens[$token]] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // foreach options
|
||||
|
||||
$eventlist = $this->_load($params);
|
||||
$display = $this->_display($eventlist, $params, $i);
|
||||
$content->text = str_replace($matches[0][$i], $display, $content->text);
|
||||
} // foreach matches
|
||||
} // _process()
|
||||
|
||||
// The function who takes care for the 'completing' of the plugins' actions : load the events
|
||||
protected function _load($parameters)
|
||||
{
|
||||
// Retrieve Eventslist model for the data
|
||||
$model = BaseDatabaseModel::getInstance('Eventslist', 'JemModel', array('ignore_request' => true));
|
||||
|
||||
if (isset($parameters['max_events'])) {
|
||||
$max = $parameters['max_events'];
|
||||
$model->setState('list.limit', ($max > 0) ? $max : 100);
|
||||
}
|
||||
|
||||
/****************************
|
||||
* FILTER CATEGORIES.
|
||||
****************************/
|
||||
if (isset($parameters['catids'])) {
|
||||
$catids = $parameters['catids'];
|
||||
|
||||
if ($catids) {
|
||||
$included_cats = explode(",", $catids);// make change in default code by jwsolution
|
||||
$model->setState('filter.category_id', $included_cats);
|
||||
$model->setState('filter.category_id.include', 1);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************
|
||||
* FILTER - VENUE.
|
||||
****************************/
|
||||
if (isset($parameters['venueids'])) {
|
||||
$venueids = $parameters['venueids'];
|
||||
|
||||
if ($venueids) {
|
||||
$model->setState('filter.venue_id', $venueids);
|
||||
$model->setState('filter.venue_id.include', 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($parameters['show_featured'])) {
|
||||
$featured = $parameters['show_featured'];
|
||||
|
||||
if ($featured == 'on') {
|
||||
$model->setState('filter.featured', 1);
|
||||
}
|
||||
}
|
||||
|
||||
$type = $parameters['type'];
|
||||
$offset_hourss = 0;
|
||||
|
||||
switch ($type) {
|
||||
case 'today': // All events starting today.
|
||||
//$offset_minutes = ($offset_hourss * 60);
|
||||
$timestamp = mktime(0, 0, 0, date("m"), date("d"), date("Y"));
|
||||
$to_date = date('Y-m-d', $timestamp);
|
||||
$model->setState('filter.published', 1);
|
||||
$model->setState('filter.orderby', array('a.dates ASC', 'a.times ASC'));
|
||||
$where = ' DATEDIFF (a.dates, "'. $to_date .'") = 0';
|
||||
$model->setState('filter.calendar_to',$where);
|
||||
//$cal_from = "((TIMESTAMPDIFF(MINUTE, NOW(), CONCAT(a.dates,' ',IFNULL(a.times,'00:00:00'))) > $offset_minutes) ";
|
||||
//$cal_from .= ($type === 1) ? " OR (TIMESTAMPDIFF(MINUTE, NOW(), CONCAT(IFNULL(a.enddates,a.dates),' ',IFNULL(a.endtimes,'23:59:59'))) > $offset_minutes)) " : ") ";
|
||||
break;
|
||||
default:
|
||||
case 'unfinished': // All upcoming events, incl. today.
|
||||
//$offset_minutes = ($offset_hourss * 60);
|
||||
$timestamp = mktime(0, 0, 0, date("m"), date("d"), date("Y"));
|
||||
$model->setState('filter.published', 1);
|
||||
$model->setState('filter.orderby', array('a.dates ASC', 'a.times ASC'));
|
||||
$timestamp = mktime(0, 0, 0, date("m"), date("d"), date("Y"));
|
||||
$to_date = date('Y-m-d', $timestamp);
|
||||
$where = ' (DATEDIFF (a.dates, "'. $to_date .'") = 0 AND a.enddates IS null) OR (DATEDIFF (a.dates, "'. $to_date .'") <= 0 AND DATEDIFF (a.enddates, "'. $to_date .'") >= 0)';
|
||||
$model->setState('filter.calendar_to', $where);
|
||||
break;
|
||||
case 'upcoming': // All upcoming events, excl. today.
|
||||
$timestamp = mktime(0, 0, 0, date("m"), date("d"), date("Y"));
|
||||
$offset_minutes = ($offset_hourss * 60);
|
||||
$model->setState('filter.published', 1);
|
||||
$model->setState('filter.orderby', array('a.dates ASC', 'a.times ASC'));
|
||||
$to_date = date('Y-m-d', $timestamp);
|
||||
$where = ' DATEDIFF (a.dates, "'. $to_date .'") > 0';
|
||||
$model->setState('filter.calendar_to', $where);
|
||||
break;
|
||||
case 'archived': // Archived events only.
|
||||
$model->setState('filter.published', 2);
|
||||
$model->setState('filter.orderby', array('a.dates DESC', 'a.times DESC'));
|
||||
$cal_from = "";
|
||||
break;
|
||||
case 'newest': //newest events = events with the highest IDs
|
||||
$model->setState('filter.published', 1);
|
||||
$model->setState('filter.orderby', array('a.id DESC'));
|
||||
break;
|
||||
} // switch type
|
||||
|
||||
//$model->setState('filter.calendar_from', $cal_from);
|
||||
|
||||
$model->setState('filter.groupby', array('a.id'));
|
||||
|
||||
// Retrieve the available Events.
|
||||
$rows = $model->getItems();
|
||||
|
||||
return $rows;
|
||||
} // _load()
|
||||
|
||||
// The function who takes care for the 'completing' of the plugins' actions : display the events.
|
||||
protected function _display($rows, $parameters, $listevents_id)
|
||||
{
|
||||
include_once JPATH_BASE."/components/com_jem/helpers/route.php";
|
||||
|
||||
$html_list = '<div class="jemlistevents" id="jemlistevents-'.$listevents_id.'">';
|
||||
$html_list .= '<table class="table table-hover table-striped">';
|
||||
|
||||
if ($rows === false) {
|
||||
$rows = array(); // to skip foreach w/o warning
|
||||
}
|
||||
|
||||
$n_event = 0;
|
||||
foreach ($rows as $event)
|
||||
{
|
||||
$linkdetails = Route::_(JemHelperRoute::getEventRoute($event->slug));
|
||||
$linkdate = Route::_(JemHelperRoute::getRoute(str_replace('-', '', $event->dates), 'day'));
|
||||
$linkvenue = Route::_(JemHelperRoute::getVenueRoute($event->venueslug));
|
||||
|
||||
$html_list .= '<tr class="listevent event'.($n_event + 1).'">';
|
||||
|
||||
if ($parameters['title'] !== 'off') {
|
||||
$html_list .= '<td class="eventtitle">';
|
||||
$html_list .= (($parameters['title'] === 'link') ? ('<a href="'.$linkdetails.'">') : '');
|
||||
$fulltitle = htmlspecialchars($event->title, ENT_COMPAT, 'UTF-8');
|
||||
if (mb_strlen($fulltitle) > $parameters['cut_title']) {
|
||||
$title = mb_substr($fulltitle, 0, $parameters['cut_title']).' …';
|
||||
} else {
|
||||
$title = $fulltitle;
|
||||
}
|
||||
$html_list .= $title;
|
||||
$html_list .= (($parameters['title'] === 'link') ? '</a>' : '');
|
||||
$html_list .= '</td>';
|
||||
}
|
||||
|
||||
if (($parameters['show_enddatetime'] === 'off') || ($parameters['show_date'] === 'off')) {
|
||||
if ($parameters['show_date'] !== 'off') {
|
||||
// Display startdate.
|
||||
$html_list .= '<td class="eventdate">';
|
||||
if ($event->dates) {
|
||||
$html_list .= (($parameters['show_date'] === 'link') ? ('<a href="'.$linkdate.'">') : '');
|
||||
$html_list .= JemOutput::formatdate($event->dates, $parameters['date_format']);
|
||||
$html_list .= (($parameters['show_date'] === 'link') ? '</a>' : '');
|
||||
}
|
||||
$html_list .= '</td>';
|
||||
}
|
||||
|
||||
if ($parameters['show_time'] !== 'off') {
|
||||
// Display starttime.
|
||||
$html_list .= ' '.'<td class="eventtime">';
|
||||
if ($event->times) {
|
||||
$html_list .= JemOutput::formattime($event->times, $parameters['time_format']);
|
||||
}
|
||||
// Display endtime if requested.
|
||||
if ($event->endtimes && ($parameters['show_enddatetime'] !== 'off')) {
|
||||
$html_list .= ' - ' . JemOutput::formattime($event->endtimes, $parameters['time_format']);
|
||||
}
|
||||
$html_list .= '</td>';
|
||||
}
|
||||
} else { // single column with all start/end date/time values
|
||||
$params = array(
|
||||
'dateStart' => $event->dates,
|
||||
'timeStart' => $event->times,
|
||||
'dateEnd' => $event->enddates,
|
||||
'timeEnd' => $event->endtimes,
|
||||
'dateFormat' => $parameters['date_format'],
|
||||
'timeFormat' => $parameters['time_format'],
|
||||
'showTime' => $parameters['show_time'] !== 'off',
|
||||
'showDayLink' => $parameters['show_date'] === 'link',
|
||||
);
|
||||
|
||||
// Display start/end date/time.
|
||||
$html_list .= ' '.'<td class="eventdatetime">';
|
||||
$html_list .= JemOutput::formatDateTime($params);
|
||||
$html_list .= '</td>';
|
||||
}
|
||||
|
||||
if ($parameters['show_venue'] !== 'off') {
|
||||
$html_list .= '<td class="eventvenue">';
|
||||
if ($event->venue) {
|
||||
$html_list .= (($parameters['show_venue'] === 'link') ? ('<a href="'.$linkvenue.'">') : '');
|
||||
$html_list .= $event->venue;
|
||||
$html_list .= (($parameters['show_venue'] === 'link') ? '</a>' : '');
|
||||
}
|
||||
$html_list .= '</td>';
|
||||
}
|
||||
|
||||
if ($parameters['show_category'] !== 'off') {
|
||||
if ($parameters['show_category'] === 'link') {
|
||||
$catlink = 1;
|
||||
} else {
|
||||
$catlink = false;
|
||||
}
|
||||
|
||||
$html_list .= "<td>";
|
||||
if ($event->categories) {
|
||||
$html_list .= implode(", ", JemOutput::getCategoryList($event->categories, $catlink));
|
||||
}
|
||||
$html_list .= "</td>";
|
||||
}
|
||||
|
||||
$html_list .= '</tr>';
|
||||
|
||||
$n_event++;
|
||||
if ((int)$parameters['max_events'] && ($n_event >= (int)$parameters['max_events'])) {
|
||||
break;
|
||||
}
|
||||
} // foreach rows
|
||||
|
||||
if ($n_event === 0) {
|
||||
$html_list .= $parameters['no_events_msg'];
|
||||
}
|
||||
|
||||
$html_list .= '</table>';
|
||||
$html_list .= '</div>';
|
||||
|
||||
return $html_list;
|
||||
} // _display()
|
||||
|
||||
}
|
||||
150
plugins/content/jemlistevents/jemlistevents.xml
Normal file
150
plugins/content/jemlistevents/jemlistevents.xml
Normal file
@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension version="2.5" type="plugin" group="content" method="upgrade">
|
||||
<name>plg_content_jemlistevents</name>
|
||||
<creationDate>October 2024</creationDate>
|
||||
<author>JEM Community</author>
|
||||
<authorEmail>info@joomlaeventmanager.net</authorEmail>
|
||||
<authorUrl>www.joomlaeventmanager.net</authorUrl>
|
||||
<copyright>copyright (C) 2013-2024 joomlaeventmanager.net</copyright>
|
||||
<license>https://www.gnu.org/licenses/gpl-3.0 GNU/GPL</license>
|
||||
<version>4.3.1</version>
|
||||
<description>PLG_CONTENT_JEMLISTEVENTS_XML_INSTRUCTION</description>
|
||||
|
||||
<files>
|
||||
<filename plugin="jemlistevents">jemlistevents.php</filename>
|
||||
<filename>index.html</filename>
|
||||
<folder>language</folder>
|
||||
</files>
|
||||
<languages>
|
||||
<language tag="en-GB">language/en-GB/plg_content_jemlistevents.ini</language>
|
||||
<language tag="en-GB">language/en-GB/plg_content_jemlistevents.sys.ini</language>
|
||||
</languages>
|
||||
|
||||
<config>
|
||||
<fields name="params">
|
||||
<fieldset name="basic">
|
||||
<field name="type" type="list"
|
||||
size="1"
|
||||
default="unfinished"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_TYPE_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_TYPE_DESCRIPTION"
|
||||
>
|
||||
<option value="today" >PLG_CONTENT_JEMLISTEVENTS_TODAYS_EVENTS</option>
|
||||
<option value="unfinished">PLG_CONTENT_JEMLISTEVENTS_UNFINISHED_EVENTS</option>
|
||||
<option value="upcoming" >PLG_CONTENT_JEMLISTEVENTS_UPCOMING_EVENTS</option>
|
||||
<option value="archived" >PLG_CONTENT_JEMLISTEVENTS_ARCHIVED_EVENTS</option>
|
||||
<option value="newest" >PLG_CONTENT_JEMLISTEVENTS_NEWEST_EVENTS</option>
|
||||
</field>
|
||||
<field name="show_featured" type="radio"
|
||||
class="btn-group btn-group-yesno"
|
||||
default="0"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_FEATURED_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_FEATURED_DESCRIPTION"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field name="title" type="list"
|
||||
size="1"
|
||||
default="link"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_TITLE_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_TITLE_DESCRIPTION"
|
||||
>
|
||||
<option value="on" >PLG_CONTENT_JEMLISTEVENTS_ON</option>
|
||||
<option value="link">PLG_CONTENT_JEMLISTEVENTS_LINK</option>
|
||||
<option value="off" >PLG_CONTENT_JEMLISTEVENTS_OFF</option>
|
||||
</field>
|
||||
<field name="cut_title" type="text"
|
||||
default="40"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_MAX_TITLE_LENGTH"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_MAX_TITLE_LENGTH_DESC"
|
||||
showon="title:on[OR]title:link"
|
||||
/>
|
||||
<field name="show_date" type="list"
|
||||
size="1"
|
||||
default="on"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_DATE_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_DATE_DESCRIPTION"
|
||||
>
|
||||
<option value="on" >PLG_CONTENT_JEMLISTEVENTS_ON</option>
|
||||
<option value="link">PLG_CONTENT_JEMLISTEVENTS_LINK</option>
|
||||
<option value="off" >PLG_CONTENT_JEMLISTEVENTS_OFF</option>
|
||||
</field>
|
||||
<field name="date_format" type="text"
|
||||
default="d.m.Y"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_DATE_FORMAT"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_DATE_FORMAT_DESC"
|
||||
showon="show_date:on[OR]show_date:link"
|
||||
/>
|
||||
<field name="show_time" type="radio"
|
||||
class="btn-group btn-group-yesno"
|
||||
default="0"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_TIME_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_TIME_DESCRIPTION"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field name="time_format" type="text"
|
||||
default=""
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_TIME_FORMAT"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_TIME_FORMAT_DESC"
|
||||
showon="show_time:1"
|
||||
/>
|
||||
<field name="show_enddatetime" type="radio"
|
||||
class="btn-group btn-group-yesno"
|
||||
default="1"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_ENDDATETIME_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_ENDDATETIME_DESCRIPTION"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field name="catids" type="text"
|
||||
size="10"
|
||||
default=""
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_CATEGORIES_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_CATEGORIES_DESCRIPTION"
|
||||
/>
|
||||
<field name="show_category" type="list"
|
||||
size="1"
|
||||
default="link"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_CATEGORY_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_CATEGORY_DESCRIPTION"
|
||||
>
|
||||
<option value="on" >PLG_CONTENT_JEMLISTEVENTS_ON</option>
|
||||
<option value="link">PLG_CONTENT_JEMLISTEVENTS_LINK</option>
|
||||
<option value="off" >PLG_CONTENT_JEMLISTEVENTS_OFF</option>
|
||||
</field>
|
||||
<field name="venueids" type="text"
|
||||
size="10"
|
||||
default=""
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_VENUES_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_VENUES_DESCRIPTION"
|
||||
/>
|
||||
<field name="show_venue" type="list"
|
||||
size="1"
|
||||
default="link"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_VENUE_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_VENUE_DESCRIPTION"
|
||||
>
|
||||
<option value="on" >PLG_CONTENT_JEMLISTEVENTS_ON</option>
|
||||
<option value="link">PLG_CONTENT_JEMLISTEVENTS_LINK</option>
|
||||
<option value="off" >PLG_CONTENT_JEMLISTEVENTS_OFF</option>
|
||||
</field>
|
||||
<field name="max_events" type="text"
|
||||
size="10"
|
||||
default="10"
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_MAXIMUM_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_MAXIMUM_DESCRIPTION"
|
||||
/>
|
||||
<field name="no_events_msg" type="text"
|
||||
size="70"
|
||||
default=""
|
||||
label="PLG_CONTENT_JEMLISTEVENTS_NO_EVENTS_MESSAGE_LABEL"
|
||||
description="PLG_CONTENT_JEMLISTEVENTS_NO_EVENTS_MESSAGE_DESCRIPTION"
|
||||
/>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
</extension>
|
||||
1
plugins/content/jemlistevents/language/en-GB/index.html
Normal file
1
plugins/content/jemlistevents/language/en-GB/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!DOCTYPE html><title></title>
|
||||
@ -0,0 +1,51 @@
|
||||
; @package JEM
|
||||
; @subpackage JEM Listevents Plugin
|
||||
; @copyright (C) 2013-2024 joomlaeventmanager.net
|
||||
; @copyright (C) 2005-2009 Christoph Lukes
|
||||
; @license https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
|
||||
;
|
||||
; All translations can be found at https://app.transifex.com/jemproject/
|
||||
; Please join the translation team if you want to contribute your changes to the translations
|
||||
;
|
||||
; Note: All ini files need to be saved as UTF-8, no BOM
|
||||
|
||||
PLG_CONTENT_JEMLISTEVENTS="JEM List Events"
|
||||
PLG_CONTENT_JEMLISTEVENTS_XML_DESCRIPTION="<h3>JEM List Events</h3><p>Plugin to display JEM events inside Joomla content (articles, custom modules (with 'prepare content' = yes)) with help of the tag {jemlistevents …}</p><p>Default parameters are defined in the plugin configuration.</p><p>When inserting the plugin command line, the default settings can be overridden with the parameters:<br /><span class=\"rl_code\">{jemlistevents [type=today|unfinished|upcoming|archived|newest];[featured=on|off];[title=on|link|off];[date=on|link|off];[time=on|off];[enddatetime=on|off];[catids=n];[category=on|link|off];[venueids=n];[venue=on|link|off];[max=n];[cuttitle=n];[noeventsmsg=msg]}</span><br />('n' stands for a positive number, '|' divides options you can choose one from)</p><p>For example: <span class=\"rl_code\">{jemlistevents catids=2,14,62;venueids=3;max=5;cuttitle=25;noeventsmsg=nothing going on}</span></p><p>type=today: Today's events<br />type=unfinished: Upcoming and ongoing events<br />type=upcoming: Upcoming events not started yet<br />type=archived: Archived events<br />type=newest: Newest events (events with the highest IDs)</p><p>max: max number of displayed events</p><p>cuttitle: Max. length of the title</p><p>noeventsmsg: message to be displayed, when there are no events</p><p>The date and time format use the parameter strings from <a href='https://www.php.net/manual/en/datetime.format.php' target='_blank'>https://www.php.net/manual/en/datetime.format.php</a></p><p>Have fun!"
|
||||
PLG_CONTENT_JEMLISTEVENTS_ON="Yes"
|
||||
PLG_CONTENT_JEMLISTEVENTS_OFF="No"
|
||||
PLG_CONTENT_JEMLISTEVENTS_LINK="Yes with link"
|
||||
PLG_CONTENT_JEMLISTEVENTS_TODAYS_EVENTS="Today's events"
|
||||
PLG_CONTENT_JEMLISTEVENTS_UNFINISHED_EVENTS="Unfinished events"
|
||||
PLG_CONTENT_JEMLISTEVENTS_UPCOMING_EVENTS="Upcoming events"
|
||||
PLG_CONTENT_JEMLISTEVENTS_ARCHIVED_EVENTS="Archived events"
|
||||
PLG_CONTENT_JEMLISTEVENTS_NEWEST_EVENTS="Newest events"
|
||||
PLG_CONTENT_JEMLISTEVENTS_FEATURED_LABEL="Featured only"
|
||||
PLG_CONTENT_JEMLISTEVENTS_FEATURED_DESCRIPTION="Only show featured events accordiung to the settings above"
|
||||
PLG_CONTENT_JEMLISTEVENTS_TYPE_LABEL="Type of events"
|
||||
PLG_CONTENT_JEMLISTEVENTS_TYPE_DESCRIPTION="What kind of events should be listed. '<strong>today</strong>' for events of today; '<strong>Next events</strong>' for upcoming events; '<strong>Archived events</strong>' for past events if the settings are set to archive them."
|
||||
PLG_CONTENT_JEMLISTEVENTS_TITLE_LABEL="Show title"
|
||||
PLG_CONTENT_JEMLISTEVENTS_TITLE_DESCRIPTION="Display event Title?"
|
||||
PLG_CONTENT_JEMLISTEVENTS_MAX_TITLE_LENGTH="Max. title length"
|
||||
PLG_CONTENT_JEMLISTEVENTS_MAX_TITLE_LENGTH_DESC="Max. length of the title."
|
||||
PLG_CONTENT_JEMLISTEVENTS_DATE_LABEL="Show date"
|
||||
PLG_CONTENT_JEMLISTEVENTS_DATE_DESCRIPTION="Display event Date?"
|
||||
PLG_CONTENT_JEMLISTEVENTS_DATE_FORMAT="Date format"
|
||||
PLG_CONTENT_JEMLISTEVENTS_DATE_FORMAT_DESC="Date format using the PHP date format, for example: \"Y-m-d\" for 2017-06-15. For more information <a href=\"https://www.php.net/manual/en/datetime.format.php\" target=\"_blank\">visit the PHP manual</a>."
|
||||
PLG_CONTENT_JEMLISTEVENTS_TIME_LABEL="Show time"
|
||||
PLG_CONTENT_JEMLISTEVENTS_TIME_DESCRIPTION="Display event Time?"
|
||||
PLG_CONTENT_JEMLISTEVENTS_TIME_FORMAT="Time format"
|
||||
PLG_CONTENT_JEMLISTEVENTS_TIME_FORMAT_DESC="Time format using the PHP time format, for example: \"H:i\". For more information <a href=\"https://www.php.net/manual/en/datetime.format.php\" target=\"_blank\">visit the PHP manual</a>."
|
||||
PLG_CONTENT_JEMLISTEVENTS_ENDDATETIME_LABEL="Show enddate/endtime"
|
||||
PLG_CONTENT_JEMLISTEVENTS_ENDDATETIME_DESCRIPTION="Additionally display date / time event ends. This will combine all up to four date and time values to be shown in a single column, same as in JEM component's list views."
|
||||
PLG_CONTENT_JEMLISTEVENTS_CATEGORIES_LABEL="Categories"
|
||||
PLG_CONTENT_JEMLISTEVENTS_CATEGORIES_DESCRIPTION="Filter event Categories. Insert Category IDs, comma separated, or leave blank for all."
|
||||
PLG_CONTENT_JEMLISTEVENTS_CATEGORY_LABEL="Show category"
|
||||
PLG_CONTENT_JEMLISTEVENTS_CATEGORY_DESCRIPTION="Display event Category?"
|
||||
PLG_CONTENT_JEMLISTEVENTS_VENUES_LABEL="Venues"
|
||||
PLG_CONTENT_JEMLISTEVENTS_VENUES_DESCRIPTION="Filter event Venues. Insert Venue/Location IDs, comma separated, or leave blank for all."
|
||||
PLG_CONTENT_JEMLISTEVENTS_VENUE_LABEL="Show venue"
|
||||
PLG_CONTENT_JEMLISTEVENTS_VENUE_DESCRIPTION="Display event Venue?"
|
||||
PLG_CONTENT_JEMLISTEVENTS_MAXIMUM_LABEL="Maximum events"
|
||||
PLG_CONTENT_JEMLISTEVENTS_MAXIMUM_DESCRIPTION="Maximum number of events listed."
|
||||
PLG_CONTENT_JEMLISTEVENTS_NO_EVENTS_MESSAGE_LABEL="No events message"
|
||||
PLG_CONTENT_JEMLISTEVENTS_NO_EVENTS_MESSAGE_DESCRIPTION="Message to display when there are no events."
|
||||
@ -0,0 +1,14 @@
|
||||
; @package JEM
|
||||
; @subpackage JEM Listevents Plugin
|
||||
; @copyright (C) 2013-2024 joomlaeventmanager.net
|
||||
; @copyright (C) 2005-2009 Christoph Lukes
|
||||
; @license https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
|
||||
;
|
||||
; All translations can be found at https://app.transifex.com/jemproject/
|
||||
; Please join the translation team if you want to contribute your changes to the translations
|
||||
;
|
||||
; Note: All ini files need to be saved as UTF-8, no BOM
|
||||
|
||||
PLG_CONTENT_JEMLISTEVENTS="JEM - List Events Plugin"
|
||||
PLG_CONTENT_JEMLISTEVENTS_XML_DESCRIPTION="Plugin to display JEM events inside Joomla content"
|
||||
PLG_CONTENT_JEMLISTEVENTS_XML_INSTRUCTION="<h3>JEM List Events</h3><p>Plugin to display JEM events inside Joomla content (articles, custom modules (with 'prepare content' = yes)) with help of the tag {jemlistevents …}</p><p>Default parameters are defined in the plugin configuration.</p><p>When inserting the plugin command line, the default settings can be overridden with the parameters:<br /><span class=\"rl_code\">{jemlistevents [type=today|unfinished|upcoming|archived|newest];[featured=on|off];[title=on|link|off];[date=on|link|off];[time=on|off];[enddatetime=on|off];[catids=n];[category=on|link|off];[venueids=n];[venue=on|link|off];[max=n];[cuttitle=n];[noeventsmsg=msg]}</span><br />('n' stands for a positive number, '|' divides options you can choose one from)</p><p>For example: <span class=\"rl_code\">{jemlistevents catids=2,14,62;venueids=3;max=5;cuttitle=25;noeventsmsg=nothing going on}</span></p><p>type=today: Today's events<br />type=unfinished: Upcoming and ongoing events<br />type=upcoming: Upcoming events not started yet<br />type=archived: Archived events<br />type=newest: Newest events (events with the highest IDs)</p><p>max: max number of displayed events</p><p>cuttitle: Max. length of the title</p><p>noeventsmsg: message to be displayed, when there are no events</p><p>The date and time format use the parameter strings from <a href='https://www.php.net/manual/en/datetime.format.php' target='_blank'>https://www.php.net/manual/en/datetime.format.php</a></p><p>Have fun!"
|
||||
79
plugins/content/joomla/joomla.xml
Normal file
79
plugins/content/joomla/joomla.xml
Normal file
@ -0,0 +1,79 @@
|
||||
<?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>
|
||||
<field
|
||||
name="schema_content"
|
||||
type="radio"
|
||||
label="PLG_CONTENT_JOOMLA_SCHEMA_CONTENT_LABEL"
|
||||
description="PLG_CONTENT_JOOMLA_SCHEMA_CONTENT_DESC"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
filter="integer"
|
||||
required="true"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field
|
||||
name="schema_contact"
|
||||
type="radio"
|
||||
label="PLG_CONTENT_JOOMLA_SCHEMA_CONTACT_LABEL"
|
||||
description="PLG_CONTENT_JOOMLA_SCHEMA_CONTACT_DESC"
|
||||
layout="joomla.form.field.radio.switcher"
|
||||
default="1"
|
||||
filter="integer"
|
||||
required="true"
|
||||
>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
|
||||
</extension>
|
||||
50
plugins/content/joomla/services/provider.php
Normal file
50
plugins/content/joomla/services/provider.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?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) {
|
||||
$plugin = new Joomla(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'joomla')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
$plugin->setDatabase($container->get(DatabaseInterface::class));
|
||||
$plugin->setUserFactory($container->get(UserFactoryInterface::class));
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
1022
plugins/content/joomla/src/Extension/Joomla.php
Normal file
1022
plugins/content/joomla/src/Extension/Joomla.php
Normal file
File diff suppressed because it is too large
Load Diff
41
plugins/content/loadmodule/loadmodule.xml
Normal file
41
plugins/content/loadmodule/loadmodule.xml
Normal file
@ -0,0 +1,41 @@
|
||||
<?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>
|
||||
46
plugins/content/loadmodule/services/provider.php
Normal file
46
plugins/content/loadmodule/services/provider.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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) {
|
||||
$plugin = new LoadModule(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'loadmodule')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
250
plugins/content/loadmodule/src/Extension/LoadModule.php
Normal file
250
plugins/content/loadmodule/src/Extension/LoadModule.php
Normal file
@ -0,0 +1,250 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
96
plugins/content/pagebreak/pagebreak.xml
Normal file
96
plugins/content/pagebreak/pagebreak.xml
Normal file
@ -0,0 +1,96 @@
|
||||
<?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>
|
||||
46
plugins/content/pagebreak/services/provider.php
Normal file
46
plugins/content/pagebreak/services/provider.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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) {
|
||||
$plugin = new PageBreak(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'pagebreak')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
358
plugins/content/pagebreak/src/Extension/PageBreak.php
Normal file
358
plugins/content/pagebreak/src/Extension/PageBreak.php
Normal file
@ -0,0 +1,358 @@
|
||||
<?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();
|
||||
}
|
||||
}
|
||||
48
plugins/content/pagebreak/tmpl/navigation.php
Normal file
48
plugins/content/pagebreak/tmpl/navigation.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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;
|
||||
use Joomla\Plugin\Content\PageBreak\Extension\PageBreak;
|
||||
|
||||
/**
|
||||
* @var PageBreak $this
|
||||
* @var array $links Array with keys 'previous' and 'next' with non-SEO links to the previous and next pages
|
||||
* @var integer $page 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>
|
||||
34
plugins/content/pagebreak/tmpl/toc.php
Normal file
34
plugins/content/pagebreak/tmpl/toc.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?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>
|
||||
65
plugins/content/pagenavigation/pagenavigation.xml
Normal file
65
plugins/content/pagenavigation/pagenavigation.xml
Normal file
@ -0,0 +1,65 @@
|
||||
<?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>
|
||||
48
plugins/content/pagenavigation/services/provider.php
Normal file
48
plugins/content/pagenavigation/services/provider.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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) {
|
||||
$plugin = new PageNavigation(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'pagenavigation')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
$plugin->setDatabase($container->get(DatabaseInterface::class));
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
247
plugins/content/pagenavigation/src/Extension/PageNavigation.php
Normal file
247
plugins/content/pagenavigation/src/Extension/PageNavigation.php
Normal file
@ -0,0 +1,247 @@
|
||||
<?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 void
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
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) {
|
||||
case 'modified':
|
||||
// Use created if modified is not set
|
||||
$orderby = 'CASE WHEN ' . $db->quoteName('a.modified') . ' IS NULL THEN ' .
|
||||
$db->quoteName('a.created') . ' ELSE ' . $db->quoteName('a.modified') . ' END';
|
||||
break;
|
||||
|
||||
case 'published':
|
||||
// Use created if publish_up is not set
|
||||
$orderby = 'CASE WHEN ' . $db->quoteName('a.publish_up') . ' IS NULL THEN ' .
|
||||
$db->quoteName('a.created') . ' ELSE ' . $db->quoteName('a.publish_up') . ' END';
|
||||
break;
|
||||
|
||||
default:
|
||||
// Use created as 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
plugins/content/pagenavigation/tmpl/default.php
Normal file
44
plugins/content/pagenavigation/tmpl/default.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* @var \Joomla\Plugin\Content\PageNavigation\Extension\PageNavigation $this
|
||||
*/
|
||||
$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>
|
||||
1
plugins/content/phocamaps/index.html
Normal file
1
plugins/content/phocamaps/index.html
Normal file
@ -0,0 +1 @@
|
||||
<html><body></body></html>
|
||||
63
plugins/content/phocamaps/manifest.xml
Normal file
63
plugins/content/phocamaps/manifest.xml
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" ?>
|
||||
<updates>
|
||||
<update>
|
||||
<name><![CDATA[ Phoca Maps Content Plugin ]]></name>
|
||||
<description><![CDATA[ Phoca Maps Plugin is a Joomla! plugin. With Phoca Maps Plugin you can display one or more maps on your site (in the article). You can display the map or only link to selected map. When user click on this link, the map will be displayed in Modal Box window or in standard Popup window. ]]></description>
|
||||
<element>phocamaps</element>
|
||||
<folder>content</folder>
|
||||
<type>plugin</type>
|
||||
<version>3.0.12</version>
|
||||
<infourl title="Phoca Maps Content Plugin 3.0.12">https://www.phoca.cz/</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/PhocaCz/PhocaMapsPlugin/releases/download/3.0.12/plg_content_phocamaps_v3.0.12.zip</downloadurl>
|
||||
</downloads>
|
||||
<tags>
|
||||
<tag>stable</tag>
|
||||
</tags>
|
||||
<maintainer><![CDATA[ Phoca.cz ]]></maintainer>
|
||||
<maintainerurl>https://www.phoca.cz/</maintainerurl>
|
||||
<section>Updates</section>
|
||||
<targetplatform name="joomla" version="3.([89]|10)"/>
|
||||
<client>site</client>
|
||||
</update>
|
||||
<update>
|
||||
<name><![CDATA[ Phoca Maps Content Plugin ]]></name>
|
||||
<description><![CDATA[ Phoca Maps Plugin is a Joomla! plugin. With Phoca Maps Plugin you can display one or more maps on your site (in the article). You can display the map or only link to selected map. When user click on this link, the map will be displayed in Modal Box window or in standard Popup window. ]]></description>
|
||||
<element>phocamaps</element>
|
||||
<folder>content</folder>
|
||||
<type>plugin</type>
|
||||
<version>4.0.1</version>
|
||||
<infourl title="Phoca Maps Content Plugin 4.0.1">https://www.phoca.cz/</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/PhocaCz/PhocaMapsPlugin/releases/download/4.0.1/plg_content_phocamaps_v4.0.1.zip</downloadurl>
|
||||
</downloads>
|
||||
<tags>
|
||||
<tag>stable</tag>
|
||||
</tags>
|
||||
<maintainer><![CDATA[ Phoca.cz ]]></maintainer>
|
||||
<maintainerurl>https://www.phoca.cz/</maintainerurl>
|
||||
<section>Updates</section>
|
||||
<targetplatform name="joomla" version="4\.*"/>
|
||||
<client>site</client>
|
||||
</update>
|
||||
<update>
|
||||
<name><![CDATA[ Phoca Maps Content Plugin ]]></name>
|
||||
<description><![CDATA[ Phoca Maps Plugin is a Joomla! plugin. With Phoca Maps Plugin you can display one or more maps on your site (in the article). You can display the map or only link to selected map. When user click on this link, the map will be displayed in Modal Box window or in standard Popup window. ]]></description>
|
||||
<element>phocamaps</element>
|
||||
<folder>content</folder>
|
||||
<type>plugin</type>
|
||||
<version>5.0.2</version>
|
||||
<infourl title="Phoca Maps Content Plugin 5.0.2">https://www.phoca.cz/</infourl>
|
||||
<downloads>
|
||||
<downloadurl type="full" format="zip">https://github.com/PhocaCz/PhocaMapsPlugin/releases/download/5.0.2/plg_content_phocamaps_v5.0.2.zip</downloadurl>
|
||||
</downloads>
|
||||
<tags>
|
||||
<tag>stable</tag>
|
||||
</tags>
|
||||
<maintainer><![CDATA[ Phoca.cz ]]></maintainer>
|
||||
<maintainerurl>https://www.phoca.cz/</maintainerurl>
|
||||
<section>Updates</section>
|
||||
<targetplatform name="joomla" version="(4|5)\.*"/>
|
||||
<client>site</client>
|
||||
</update>
|
||||
</updates>
|
||||
979
plugins/content/phocamaps/phocamaps.php
Normal file
979
plugins/content/phocamaps/phocamaps.php
Normal file
@ -0,0 +1,979 @@
|
||||
<?php
|
||||
/*
|
||||
* @package Joomla 1.5
|
||||
* @copyright Copyright (C) 2005 Open Source Matters. All rights reserved.
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php
|
||||
*
|
||||
* @plugin Phoca Plugin
|
||||
* @copyright Copyright (C) Jan Pavelka www.phoca.cz
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
|
||||
*/
|
||||
|
||||
use Joomla\CMS\Component\ComponentHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Filesystem\File;
|
||||
use Joomla\CMS\Object\CMSObject;
|
||||
use Joomla\CMS\Plugin\CMSPlugin;
|
||||
use Joomla\CMS\Plugin\PluginHelper;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
defined( '_JEXEC' ) or die( 'Restricted access' );
|
||||
|
||||
jimport( 'joomla.plugin.plugin' );
|
||||
jimport( 'joomla.application.component.helper' );
|
||||
|
||||
class plgContentPhocaMaps extends CMSPlugin
|
||||
{
|
||||
protected $_plgPhocaMapsNr = 0;
|
||||
protected $_loadedBootstrap = 0;
|
||||
public $plg_name = "phocamaps";
|
||||
|
||||
|
||||
public function __construct(& $subject, $config) {
|
||||
parent::__construct($subject, $config);
|
||||
$this->loadLanguage();
|
||||
}
|
||||
|
||||
public function _setPhocaMapsPluginNumber() {
|
||||
$this->_plgPhocaMapsNr = (int)$this->_plgPhocaMapsNr + 1;
|
||||
}
|
||||
|
||||
public function _setPhocaMapsPluginLoadedBootstrap() {
|
||||
$this->_loadedBootstrap = (int)$this->_loadedBootstrap + 1;
|
||||
}
|
||||
|
||||
public function onContentPrepare($context, &$article, &$params, $page = 0) {
|
||||
|
||||
// Don't run this plugin when the content is being indexed
|
||||
if ($context == 'com_finder.indexer') {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//$layout = new FileLayout('test', null, []);
|
||||
//$layout->addIncludePaths([JPATH_SITE . '/plugins/content/phocamaps/layouts']);
|
||||
|
||||
|
||||
$app = Factory::getApplication();
|
||||
$view = $app->input->get('view');
|
||||
|
||||
if ($view == 'tag') { return; }
|
||||
|
||||
$param['display_map_description'] = $this->params->get('display_map_description', 0);
|
||||
$param['display_auto_location'] = $this->params->get('display_auto_location', 0);
|
||||
|
||||
|
||||
// Start Plugin
|
||||
$regex_one = '/({phocamaps\s*)(.*?)(})/si';
|
||||
$regex_all = '/{phocamaps\s*.*?}/si';
|
||||
$matches = array();
|
||||
$count_matches = preg_match_all($regex_all,$article->text,$matches,PREG_OFFSET_CAPTURE | PREG_PATTERN_ORDER);
|
||||
|
||||
$lang = Factory::getLanguage();
|
||||
$lang->load('com_phocamaps.sys');
|
||||
$lang->load('com_phocamaps');
|
||||
|
||||
// Start if count_matches
|
||||
|
||||
if ($count_matches != 0) {
|
||||
|
||||
if (!ComponentHelper::isEnabled('com_phocamaps', true)) {
|
||||
Text::_('PLG_CONTENT_PHOCAMAPS_PLUGIN_REQUIRE_COMPONENT');
|
||||
return true;
|
||||
}
|
||||
|
||||
$document = Factory::getDocument();
|
||||
$db = Factory::getDBO();
|
||||
//$menu = &JSite::getMenu();
|
||||
//$plugin = &JPluginHelper::getPlugin('content', 'phocamaps');
|
||||
//$paramsP = new JParameter( $plugin->params );
|
||||
|
||||
$paramsP = $this->params;
|
||||
require_once( JPATH_ROOT.'/components/com_phocamaps/helpers/route.php' );
|
||||
require_once( JPATH_ADMINISTRATOR.'/components/com_phocamaps/helpers/phocamapspath.php' );
|
||||
require_once( JPATH_ADMINISTRATOR.'/components/com_phocamaps/helpers/phocamaps.php' );
|
||||
require_once( JPATH_ADMINISTRATOR.'/components/com_phocamaps/helpers/phocamapsmap.php' );
|
||||
require_once( JPATH_ADMINISTRATOR.'/components/com_phocamaps/helpers/phocamapsmaposm.php' );
|
||||
//$component = 'com_phocamaps';
|
||||
//$table =& JTable::getInstance('component');
|
||||
//$table->loadByOption( $component );
|
||||
//$paramsC = new JParameter( $table->params );
|
||||
|
||||
$component = 'com_phocamaps';
|
||||
$paramsC = ComponentHelper::getParams($component) ;
|
||||
|
||||
$tmpl = array();
|
||||
|
||||
HTMLHelper::_('jquery.framework', false);
|
||||
|
||||
$document->addStyleSheet(URI::base(true).'/media/com_phocamaps/css/phocamaps.css');
|
||||
$document->addStyleSheet(URI::base(true).'/media/plg_content_phocamaps/css/default.css');
|
||||
|
||||
$allIds = array();
|
||||
|
||||
for($i = 0; $i < $count_matches; $i++) {
|
||||
|
||||
// MUST BE HERE - defined for each instance
|
||||
$tmpl['enable_kml'] = $paramsC->get( 'enable_kml', 0 );
|
||||
$tmpl['display_print_route'] = $paramsC->get( 'display_print_route', 1 );
|
||||
$tmpl['close_opened_window'] = $paramsC->get( 'close_opened_window', 0 );
|
||||
$tmpl['map_type'] = $paramsC->get( 'map_type', 2 );
|
||||
$tmpl['osm_map_type'] = $paramsC->get( 'osm_map_type', 'osm' );
|
||||
$tmpl['osm_search'] = $paramsC->get( 'osm_search', 0 );
|
||||
$tmpl['osm_easyprint'] = $paramsC->get( 'osm_easyprint', 0 );
|
||||
|
||||
$this->_setPhocaMapsPluginNumber();
|
||||
// Only loaded when the type is really map not a link - see below view=map YES, view=link NO
|
||||
//$id = 'PlgPM'.(int)$this->_plgPhocaMapsNr;
|
||||
//$allIds[] = $id;
|
||||
|
||||
$view = '';
|
||||
$idMap = '';
|
||||
$text = '';
|
||||
//$lang = '';
|
||||
|
||||
// Get plugin parameters
|
||||
$phocaMaps = $matches[0][$i][0];
|
||||
preg_match($regex_one,$phocaMaps,$phocaMaps_parts);
|
||||
$parts = explode("|", $phocaMaps_parts[2]);
|
||||
$values_replace = array ("/^'/", "/'$/", "/^'/", "/'$/", "/<br \/>/");
|
||||
|
||||
|
||||
foreach($parts as $key => $value) {
|
||||
$values = explode("=", $value, 2);
|
||||
foreach ($values_replace as $key2 => $values2) {
|
||||
$values = preg_replace($values2, '', $values);
|
||||
}
|
||||
|
||||
// Get plugin parameters from article
|
||||
if($values[0]=='view') {$view = $values[1];}
|
||||
else if($values[0]=='id') {$idMap = $values[1];}
|
||||
else if($values[0]=='text') {$text = $values[1];}
|
||||
//else if($values[0]=='lang') {$lang = $values[1];}
|
||||
else if($values[0]=='kmlfile') {$tmpl['enable_kml'] = $values[1];}
|
||||
else if($values[0]=='printroute') {$tmpl['display_print_route'] = $values[1];}
|
||||
else if($values[0]=='maptype') {$tmpl['map_type'] = $values[1];}
|
||||
else if($values[0]=='osmmaptype') {$tmpl['osm_map_type'] = $values[1];}
|
||||
|
||||
else if($values[0]=='iframesrc') {$tmpl['iframesrc'] = $values[1];}
|
||||
else if($values[0]=='iframewidth') {$tmpl['iframewidth'] = $values[1];}
|
||||
else if($values[0]=='iframeheight') {$tmpl['iframeheight'] = $values[1];}
|
||||
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
||||
switch($view) {
|
||||
|
||||
// - - - - - - - - - - - - - - - -
|
||||
// Map
|
||||
// - - - - - - - - - - - - - - - -
|
||||
case 'map':
|
||||
|
||||
$id = 'PlgPM' . (int)$this->_plgPhocaMapsNr;
|
||||
|
||||
// Javascript for all Google Maps
|
||||
if ($tmpl['map_type'] == 1) {
|
||||
$allIds[] = $id;
|
||||
}
|
||||
|
||||
$query = 'SELECT a.*'
|
||||
.' FROM #__phocamaps_map AS a'
|
||||
.' WHERE a.id = '.(int) $idMap;
|
||||
$db->setQuery($query);
|
||||
$mapp = $db->loadObject();
|
||||
|
||||
|
||||
if (empty($mapp)) {
|
||||
echo '<div class="alert alert-error">'. Text::_('PLG_CONTENT_PHOCAMAPS_PLUGIN_ERROR') . ' - '. Text::_('PLG_CONTENT_PHOCAMAPS_MAP_NOT_EXISTS') . ' (ID = '.$idMap.')</div>';
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$query = 'SELECT a.*, i.id as iconid, i.url as iurl, i.urls as iurls, i.object as iobject, i.objects as iobjects, i.objectshape as iobjectshape'
|
||||
.' FROM #__phocamaps_marker AS a'
|
||||
.' LEFT JOIN #__phocamaps_map AS c ON c.id = a.catid '
|
||||
.' LEFT JOIN #__phocamaps_icon AS i ON i.id = a.iconext '
|
||||
.' WHERE c.id = '.(int) $idMap
|
||||
.' AND a.published = 1'
|
||||
.' ORDER BY a.ordering ASC';
|
||||
$db->setQuery($query);
|
||||
$markerp = $db->loadObjectList();
|
||||
|
||||
// Parameters
|
||||
$tmpl['apikey'] = $paramsC->get( 'google_maps_api_key', '' );
|
||||
$tmpl['displayphocainfo'] = $paramsC->get( 'display_phoca_info', 1 );
|
||||
$tmpl['displaymapdescription'] = $paramsP->get( 'display_map_description', 0 );
|
||||
// - - - - - - - - - - - - - - -
|
||||
// RENDER
|
||||
// - - - - - - - - - - - - - - -
|
||||
// Display Description
|
||||
$tmpl['description'] = '';
|
||||
|
||||
if (isset($mapp->description) && $mapp->description != '' && $param['display_map_description'] == 1) {
|
||||
$tmpl['description'] = '<div class="pm-desc">'.$mapp->description.'</div>';
|
||||
}
|
||||
|
||||
// Check Width and Height
|
||||
$tmpl['fullwidth'] = 0;
|
||||
if (!isset($mapp->width)) {
|
||||
$mapp->width = '100%';
|
||||
}
|
||||
if (isset($mapp->width) && (int)$mapp->width < 1) {
|
||||
$tmpl['fullwidth'] = 1;
|
||||
}
|
||||
if (!isset($mapp->height) || (isset($mapp->height) && (int)$mapp->height < 1)) {
|
||||
$mapp->height = '50vh';
|
||||
}
|
||||
if (!isset($mapp->zoom) || (isset($mapp->zoom) && (int)$mapp->zoom < 1)) {
|
||||
$mapp->zoom = 2;
|
||||
}
|
||||
|
||||
if (is_numeric($mapp->width)) {
|
||||
$mapp->width = $mapp->width . 'px';
|
||||
}
|
||||
|
||||
if (is_numeric($mapp->height)) {
|
||||
$mapp->height = $mapp->height . 'px';
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Map Langugage
|
||||
$tmpl['params'] = '';
|
||||
if (!isset($mapp->lang) || (isset($mapp->lang) && $mapp->lang == '')) {
|
||||
//$tmpl['params'] = '{other_params:"sensor=false"}';
|
||||
$tmpl['params'] = '';
|
||||
$tmpl['paramssearch'] = '';
|
||||
$tmpl['lang'] = '';
|
||||
} else {
|
||||
//$tmpl['params'] = '{other_params:"sensor=false&language='.$mapp->lang.'"}';
|
||||
$tmpl['params'] = '{other_params:"language='.$mapp->lang.'"}';
|
||||
$tmpl['paramssearch'] = '{"language":"'.$mapp->lang.'"}';
|
||||
$tmpl['lang'] = $mapp->lang;
|
||||
}
|
||||
|
||||
|
||||
// Design
|
||||
$tmpl['border'] = '';
|
||||
if (isset($mapp->border)) {
|
||||
switch ($mapp->border) {
|
||||
case 1:
|
||||
$tmpl['border'] = '-grey';
|
||||
break;
|
||||
case 2:
|
||||
$tmpl['border'] = '-greywb';
|
||||
break;
|
||||
case 3:
|
||||
$tmpl['border'] = '-greyrc';
|
||||
break;
|
||||
case 4:
|
||||
$tmpl['border'] = '-black';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Plugin - no border
|
||||
$tmpl['stylesite'] = 'margin:0;padding:0;margin-top:10px;';
|
||||
|
||||
$tmpl['stylesitewidth'] = '';
|
||||
if ($tmpl['fullwidth'] == 1) {
|
||||
$tmpl['stylesitewidth'] = 'style="width:100%"';
|
||||
}
|
||||
|
||||
// Parameters
|
||||
if (isset($mapp->continuouszoom) && (int)$mapp->continuouszoom == 1) {
|
||||
$mapp->continuouszoom = 1;
|
||||
} else {
|
||||
$mapp->continuouszoom = 0;
|
||||
}
|
||||
|
||||
if (isset($mapp->doubleclickzoom) && (int)$mapp->doubleclickzoom == 1) {
|
||||
$mapp->disabledoubleclickzoom = 0;
|
||||
} else {
|
||||
$mapp->disabledoubleclickzoom = 1;
|
||||
}
|
||||
|
||||
if (isset($mapp->scrollwheelzoom) && (int)$mapp->scrollwheelzoom == 1) {
|
||||
$mapp->scrollwheelzoom = 1;
|
||||
} else {
|
||||
$mapp->scrollwheelzoom = 0;
|
||||
}
|
||||
|
||||
// Since 1.1.0 zoomcontrol is alias for navigationcontrol
|
||||
if (empty($mapp->zoomcontrol)) {
|
||||
$mapp->zoomcontrol = 0;
|
||||
}
|
||||
|
||||
if (empty($mapp->scalecontrol)) {
|
||||
$mapp->scalecontrol = 0;
|
||||
}
|
||||
|
||||
if (empty($mapp->typecontrol)) {
|
||||
$mapp->typecontrol = 0;
|
||||
}
|
||||
if (empty($mapp->typecontrolposition)) {
|
||||
$mapp->typecontrolposition = 0;
|
||||
}
|
||||
|
||||
|
||||
if (empty($mapp->typeid)) {
|
||||
$mapp->typeid = 0;
|
||||
}
|
||||
|
||||
|
||||
// Display Direction
|
||||
$tmpl['displaydir'] = 0;
|
||||
if (isset($mapp->displayroute) && $mapp->displayroute == 1) {
|
||||
if (isset($markerp) && !empty($markerp)) {
|
||||
$tmpl['displaydir'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// KML Support
|
||||
$tmpl['load_kml'] = FALSE;
|
||||
if($tmpl['enable_kml'] == 1) {
|
||||
jimport( 'joomla.filesystem.folder' );
|
||||
jimport( 'joomla.filesystem.file' );
|
||||
$path = PhocaMapsPath::getPath();
|
||||
if (isset($mapp->kmlfile) && File::exists($path->kml_abs . $mapp->kmlfile)) {
|
||||
$tmpl['load_kml'] = $path->kml_rel_full . $mapp->kmlfile;
|
||||
}
|
||||
}
|
||||
|
||||
$output .= '<div class="phocamaps">';
|
||||
|
||||
if ((!isset($mapp->longitude))
|
||||
|| (!isset($mapp->latitude))
|
||||
|| (isset($mapp->longitude) && $mapp->longitude == '')
|
||||
|| (isset($mapp->latitude) && $mapp->latitude == '')) {
|
||||
$output .= '<p>' . Text::_('COM_PHOCAMAPS_MAP_ERROR_FRONT') . '</p>';
|
||||
} else {
|
||||
|
||||
|
||||
#########################
|
||||
# ALL MAPS - Google Maps, OpenStreetMap
|
||||
#########################
|
||||
|
||||
$output .= $tmpl['description'];
|
||||
|
||||
// Map Box
|
||||
if ($tmpl['border'] == '') {
|
||||
$output .= '<div class="phocamaps-box" align="center" style="'.$tmpl['stylesite'].'">';
|
||||
if ($tmpl['fullwidth'] == 1) {
|
||||
$output .= '<div id="phocaMap'.$id.'" style="margin:0;padding:0;width:100%;height:'.$mapp->height.'"></div>';
|
||||
} else {
|
||||
$output .= '<div id="phocaMap'.$id.'" style="margin:0;padding:0;width:'.$mapp->width.';height:'.$mapp->height.'"></div>';
|
||||
}
|
||||
$output .= '</div>';
|
||||
} else {
|
||||
$output .= '<div class="phocamaps-box phocamaps-box-border'.$tmpl['border'].'" align="center" style="'.$tmpl['stylesite'].'">';
|
||||
if ($tmpl['fullwidth'] == 1) {
|
||||
$output .= '<div id="phocaMap'.$id.'" class="phocamaps-map" style="width:100%;height:'.$mapp->height.'"></div>';
|
||||
} else {
|
||||
$output .= '<div id="phocaMap'.$id.'" class="phocamaps-map" style="width:'.$mapp->width.';height:'.$mapp->height.'"></div>';
|
||||
}
|
||||
$output .= '</div>';
|
||||
//echo '</div></div></div></div></div>';
|
||||
}
|
||||
|
||||
|
||||
###########################
|
||||
# GOOGLE MAPS
|
||||
###########################
|
||||
if ($tmpl['map_type'] == 1) {
|
||||
|
||||
|
||||
//$id = '';
|
||||
$map = new PhocaMapsMap($id);
|
||||
//$map->loadAPI();
|
||||
//$map->loadAPI('jsapi',$paramsC->get( 'load_api_ssl',0));
|
||||
//$map->loadAPI($article->id);//must be loaded at the end
|
||||
$map->loadGeoXMLJS();
|
||||
$map->loadBase64JS();
|
||||
|
||||
|
||||
// Direction
|
||||
if ($tmpl['displaydir']) {
|
||||
|
||||
$countMarker = count($markerp);
|
||||
$form = '';
|
||||
if ((int)$countMarker > 1) {
|
||||
|
||||
$form .= ' ' . Text::_('PLG_CONTENT_PHOCAMAPS_TO').': <select name="pmto'.$id.'" id="toPMAddress'.$id.'">';
|
||||
foreach ($markerp as $key => $markerV) {
|
||||
if ((isset($markerV->longitude) && $markerV->longitude != '')
|
||||
&& (isset($markerV->latitude) && $markerV->latitude != '')) {
|
||||
$form .= '<option value="'.$markerV->latitude.','.$markerV->longitude.'">'.$markerV->title.'</option>';
|
||||
}
|
||||
}
|
||||
$form .= '</select>';
|
||||
} else if ((int)$countMarker == 1) {
|
||||
|
||||
foreach ($markerp as $key => $markerV) {
|
||||
if ((isset($markerV->longitude) && $markerV->longitude != '')
|
||||
&& (isset($markerV->latitude) && $markerV->latitude != '')) {
|
||||
$form .= '<input name="pmto'.$id.'" id="toPMAddress'.$id.'" type="hidden" value="'.$markerV->latitude.','.$markerV->longitude.'" />';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($form != '') {
|
||||
/*$output .= '<div class="pmroute"><form action="#" onsubmit="setPhocaDir'.$id.'(this.pmfrom'.$id.'.value, this.pmto'.$id.'.value); return false;">';
|
||||
$output .= Text::_('PLG_CONTENT_PHOCAMAPS_FROM_ADDRESS').': <input type="text" size="30" id="fromPMAddress'.$id.'" name="pmfrom'.$id.'" value=""/>';
|
||||
$output .= $form;
|
||||
$output .= ' <input name="pmsubmit'.$id.'" type="submit" value="'.Text::_('PLG_CONTENT_PHOCAMAPS_GET_ROUTE').'" /></form></div>';
|
||||
$output .= '<div id="phocaDir'.$id.'">';
|
||||
if ($tmpl['display_print_route'] == 1) {
|
||||
$output .= '<div id="phocaMapsPrintIcon'.$id.'" style="display:none"></div>';
|
||||
}
|
||||
$output .= '</div>';*/
|
||||
|
||||
$output .= '<div class="pmroute">';
|
||||
$output .= '<form class="form-inline input-group" action="#" onsubmit="setPhocaDir'.$id.'(this.pmfrom'.$id.'.value, this.pmto'.$id.'.value); return false;">';
|
||||
$output .= Text::_('PLG_CONTENT_PHOCAMAPS_FROM_ADDRESS').': <input class="pm-input-route input form-control" type="text" size="30" id="fromPMAddress'.$id.'" name="pmfrom'.$id.'" value=""/>';
|
||||
$output .= $form;
|
||||
$output .= ' <input name="pmsubmit'.$id.'" type="submit" class="pm-input-route-btn btn btn-primary" value="'.Text::_('PLG_CONTENT_PHOCAMAPS_GET_ROUTE').'" />';
|
||||
$output .= '</form></div>';
|
||||
$output .= '<div id="phocaDir'.$id.'">';
|
||||
if ($tmpl['display_print_route'] == 1) {
|
||||
$output .= '<div id="phocaMapsPrintIcon'.$id.'" style="display:none"></div>';
|
||||
}
|
||||
$output .= '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
// $id is not used anymore as this is added in methods of Phoca Maps Class
|
||||
// e.g. 'phocaMap' will be not 'phocaMap'.$id as the id will be set in methods
|
||||
|
||||
$output .= $map->startJScData();
|
||||
$output .= $map->addAjaxAPI('maps', '3', $tmpl['params']);
|
||||
$output .= $map->addAjaxAPI('search', '1', $tmpl['paramssearch']);
|
||||
|
||||
$output .= $map->createMap('phocaMap', 'mapPhocaMap', 'phocaLatLng', 'phocaOptions','tstPhocaMap', 'tstIntPhocaMap', FALSE, FALSE, $tmpl['displaydir']);
|
||||
$output .= $map->cancelEventFunction();
|
||||
$output .= $map->checkMapFunction();
|
||||
$output .= $map->startMapFunction();
|
||||
|
||||
$output .= $map->setLatLng( $mapp->latitude, $mapp->longitude );
|
||||
|
||||
$output .= $map->startMapOptions();
|
||||
$output .= $map->setMapOption('zoom', $mapp->zoom).','."\n";
|
||||
$output .= $map->setCenterOpt().','."\n";
|
||||
$output .= $map->setTypeControlOpt($mapp->typecontrol, $mapp->typecontrolposition).','."\n";
|
||||
$output .= $map->setNavigationControlOpt($mapp->zoomcontrol).','."\n";
|
||||
$output .= $map->setMapOption('scaleControl', $mapp->scalecontrol, TRUE ).','."\n";
|
||||
//$output .= $map->setMapOption('scrollwheel', $mapp->scrollwheelzoom, TRUE).','."\n";
|
||||
|
||||
if ($mapp->gesturehandling != '') {
|
||||
$output .= $map->setMapOption('gestureHandling', '"' . $mapp->gesturehandling . '"').','."\n";
|
||||
} else {
|
||||
$output .= $map->setMapOption('scrollwheel', $mapp->scrollwheelzoom, TRUE).','."\n";
|
||||
}
|
||||
|
||||
$output .= $map->setMapOption('disableDoubleClickZoom', $mapp->disabledoubleclickzoom).','."\n";
|
||||
// $output .= $map->setMapOption('googleBar', $mapp->googlebar).','."\n";// Not ready yet
|
||||
// $output .= $map->setMapOption('continuousZoom', $mapp->continuouszoom).','."\n";// Not ready yet
|
||||
|
||||
if (isset($mapp->map_styles)) {
|
||||
$output .= $map->setMapOption('styles', $mapp->map_styles).','."\n";
|
||||
}
|
||||
$output .= $map->setMapTypeOpt($mapp->typeid)."\n";
|
||||
if (isset($mapp->custom_options)) {
|
||||
$output .= $map->endMapOptions($mapp->custom_options);
|
||||
} else {
|
||||
$output .= $map->endMapOptions();
|
||||
}
|
||||
if ($tmpl['close_opened_window'] == 1) {
|
||||
$output .= $map->setCloseOpenedWindow();
|
||||
}
|
||||
$output .= $map->setMap();
|
||||
|
||||
// Markers
|
||||
jimport('joomla.filter.output');
|
||||
if (isset($markerp) && !empty($markerp)) {
|
||||
|
||||
$iconArray = array(); // add information about created icons to array and check it so no duplicity icons js code will be created
|
||||
foreach ($markerp as $key => $markerV) {
|
||||
|
||||
if ((isset($markerV->longitude) && $markerV->longitude != '')
|
||||
&& (isset($markerV->latitude) && $markerV->latitude != '')) {
|
||||
|
||||
|
||||
|
||||
//$hStyle = 'font-size:120%;margin: 5px 0px;font-weight:bold;';
|
||||
//$text = '<div style="'.$hStyle.'">' . addslashes($markerV->title) . '</div>';
|
||||
|
||||
// template
|
||||
// $text = '<div class="pmMarkerTitle">' . addslashes($markerV->title) . '</div>';
|
||||
|
||||
// Try to correct images in description
|
||||
$markerV->description = PhocaMapsHelper::fixImagePath($markerV->description);
|
||||
$markerV->description = str_replace('@', '@', $markerV->description);
|
||||
//$markerV->description = str_replace("/", '/', $markerV->description);
|
||||
$markerV->description = str_replace("'", ''', $markerV->description);
|
||||
//$markerV->description = str_replace('"', '"', $markerV->description);
|
||||
|
||||
//$markerV->description = htmlentities($markerV->description);
|
||||
|
||||
// template
|
||||
/*
|
||||
$text .= '<div>'. PhocaMapsHelper::strTrimAll(addslashes($markerV->description)).'</div>';
|
||||
|
||||
|
||||
if ($markerV->displaygps == 1) {
|
||||
$text .= '<div class="pmgps"><table border="0"><tr><td><strong>'. Text::_('PLG_CONTENT_PHOCAMAPS_GPS') . ': </strong></td>'
|
||||
.'<td>'.PhocaMapsHelper::strTrimAll(addslashes($markerV->gpslatitude)).'</td></tr>'
|
||||
.'<tr><td></td>'
|
||||
.'<td>'.PhocaMapsHelper::strTrimAll(addslashes($markerV->gpslongitude)).'</td></tr></table></div>';
|
||||
}*/
|
||||
|
||||
// Get marker text from tmpl so it can be overriden by template override
|
||||
$text = str_replace(array("\r", "\n", "\t"), '', $this->getTemplateOutput($markerV, "marker"));
|
||||
|
||||
if(empty($markerV->icon)) {
|
||||
$markerV->icon = 0;
|
||||
}
|
||||
if(empty($markerV->title)){
|
||||
$markerV->title = '';
|
||||
}
|
||||
if(empty($markerV->description)){
|
||||
$markerV->description = '';
|
||||
}
|
||||
|
||||
|
||||
$iconOutput = $map->setMarkerIcon($markerV->icon, $markerV->iconext, $markerV->iurl, $markerV->iobject, $markerV->iurls, $markerV->iobjects, $markerV->iobjectshape);
|
||||
$output .= $map->outputMarkerJs($iconOutput['js'], $markerV->icon, $markerV->iconext);
|
||||
|
||||
$output .= $map->setMarker($markerV->id,$markerV->title,$markerV->description,$markerV->latitude, $markerV->longitude, $iconOutput['icon'], $iconOutput['iconid'], $text, $markerV->contentwidth, $markerV->contentheight, $markerV->markerwindow, $iconOutput['iconshadow'], $iconOutput['iconshape'], $tmpl['close_opened_window']);
|
||||
|
||||
}
|
||||
}
|
||||
$output .= $map->setMarkerClusterer();
|
||||
}
|
||||
|
||||
if ($tmpl['load_kml']) {
|
||||
$output .= $map->setKMLFile($tmpl['load_kml']);
|
||||
}
|
||||
|
||||
if ($tmpl['displaydir']) {
|
||||
$output .= $map->setDirectionDisplayService('phocaDir');
|
||||
}
|
||||
if(isset($mapp->scrollwheelzoom) && $mapp->scrollwheelzoom != 0){
|
||||
$output .= $map->setListener();
|
||||
}
|
||||
|
||||
|
||||
if ((int)$mapp->autolocation == 1) {
|
||||
$output .= $map->setAutolocation();
|
||||
}
|
||||
|
||||
// Set own custom JS which can be overriden by template
|
||||
$output .= $this->getTemplateOutput(["mapId"=>$this->_plgPhocaMapsNr], "custom_js");
|
||||
|
||||
$output .= $map->endMapFunction();
|
||||
|
||||
if ($tmpl['displaydir']) {
|
||||
$output .= $map->setDirectionFunction($tmpl['display_print_route'], $mapp->id, $mapp->alias, $tmpl['lang']);
|
||||
}
|
||||
|
||||
//if ((int)$this->_plgPhocaMapsNr < 2) {
|
||||
|
||||
//$output .= $map->setInitializeFunction();// will be set at bottom for all items - Add init for all maps
|
||||
$output .= $map->setInitializeFunctionSpecificMap();
|
||||
//}
|
||||
$output .= $map->endJScData();
|
||||
|
||||
|
||||
########################### END GOOGLE MAPS
|
||||
|
||||
###########################
|
||||
# OPENSTREETMAP
|
||||
###########################
|
||||
|
||||
} else {
|
||||
|
||||
//OSM tracks
|
||||
if ($tmpl['map_type'] == 2) {
|
||||
|
||||
$tmpl['fitbounds'] = $mapp->fitbounds_osm;
|
||||
$textarea = $mapp->trackfiles_osm;
|
||||
$textarea = str_replace(array("\r\n", "\n", "\r"),'',$textarea);
|
||||
$tracks = explode(",",$textarea);
|
||||
|
||||
$textarea = $mapp->trackcolors_osm;
|
||||
$textarea = str_replace(array("\r\n", "\n", "\r"),'',$textarea);
|
||||
//$colors = explode(",",$textarea);
|
||||
$colors = array_map('trim', explode(',', $textarea));
|
||||
|
||||
$tracksA = array();
|
||||
foreach ($tracks as $k => $v) {
|
||||
$v = trim($v);
|
||||
$ext = pathinfo($v,PATHINFO_EXTENSION);
|
||||
|
||||
if (($ext != 'gpx') && ($ext != 'kml')) {
|
||||
$v = '';
|
||||
} else {
|
||||
//if no path specified add default path (hardcoded to /phocamapskml for now)
|
||||
if (strpos($v,'/') === false) {
|
||||
$v = 'phocamapskml/'.$v;
|
||||
}
|
||||
$v = trim($v,'/');
|
||||
|
||||
$tracksA[$k] = array();
|
||||
$tracksA[$k]['file'] = File::exists(JPATH_ROOT.'/'.$v) ? URI::base().$v : '';
|
||||
$tracksA[$k]['color'] = isset($colors[$k]) ? $colors[$k] : '';
|
||||
}
|
||||
}
|
||||
$tmpl['tracks'] = $tracksA;
|
||||
} else {
|
||||
$tmpl['tracks'] = array();
|
||||
}
|
||||
|
||||
|
||||
|
||||
$map = new PhocaMapsMapOsm($id);
|
||||
|
||||
|
||||
$map->osmmaptype = $tmpl['osm_map_type'];
|
||||
|
||||
$map->loadAPI();
|
||||
$map->loadCoordinatesJS();
|
||||
$map->createMap($mapp->latitude, $mapp->longitude, $mapp->zoom);
|
||||
|
||||
$map->setMapType();
|
||||
|
||||
|
||||
// Markers
|
||||
jimport('joomla.filter.output');
|
||||
$iM = 0;
|
||||
if (isset($markerp) && !empty($markerp)) {
|
||||
|
||||
$iconArray = array(); // add information about created icons to array and check it so no duplicity icons js code will be created
|
||||
foreach ($markerp as $key => $markerV) {
|
||||
|
||||
if ((isset($markerV->longitude) && $markerV->longitude != '')
|
||||
&& (isset($markerV->latitude) && $markerV->latitude != '')) {
|
||||
if ($iM == 0) {
|
||||
// Get info about first marker to use it in routing plan
|
||||
$firstMarker = $markerV;
|
||||
}
|
||||
|
||||
$hStyle = 'font-size:120%;margin: 5px 0px;font-weight:bold;';
|
||||
$text = '<div style="'.$hStyle.'">' . addslashes($markerV->title) . '</div>';
|
||||
|
||||
// Try to correct images in description
|
||||
$markerV->description = PhocaMapsHelper::fixImagePath($markerV->description);
|
||||
$markerV->description = str_replace('@', '@', $markerV->description);
|
||||
$text .= '<div>'. PhocaMapsHelper::strTrimAll(addslashes($markerV->description)).'</div>';
|
||||
if ($markerV->displaygps == 1) {
|
||||
$text .= '<div class="pmgps"><table border="0"><tr><td><strong>'. Text::_('COM_PHOCAMAPS_GPS') . ': </strong></td>'
|
||||
.'<td>'.PhocaMapsHelper::strTrimAll(addslashes($markerV->gpslatitude)).'</td></tr>'
|
||||
.'<tr><td></td>'
|
||||
.'<td>'.PhocaMapsHelper::strTrimAll(addslashes($markerV->gpslongitude)).'</td></tr></table></div>';
|
||||
}
|
||||
|
||||
|
||||
if(empty($markerV->icon)) {
|
||||
$markerV->icon = 0;
|
||||
}
|
||||
if(empty($markerV->title)){
|
||||
$markerV->title = '';
|
||||
}
|
||||
if(empty($markerV->description)){
|
||||
$markerV->description = '';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$map->setMarker($id . 'm'.$markerV->id, $markerV->title, $markerV->description, $markerV->latitude, $markerV->longitude, $text, $markerV->contentwidth, $markerV->contentheight, $markerV->markerwindow, $tmpl['close_opened_window']);
|
||||
|
||||
$markerIconOptions = array();
|
||||
|
||||
if (isset($markerV->osm_icon) && $markerV->osm_icon != '') {
|
||||
$markerIconOptions = $map->setMarkerIcon($id . 'm'.$markerV->id, $markerV->osm_icon, $markerV->osm_marker_color, $markerV->osm_icon_color, $markerV->osm_icon_prefix, $markerV->osm_icon_spin, $markerV->osm_icon_class);
|
||||
}
|
||||
|
||||
if ($iM == 0) {
|
||||
// Get info about first marker to use it in routing plan
|
||||
// so we get the same icons for markers in Options like the first marker has
|
||||
$firstMarker->markericonoptions = $markerIconOptions;
|
||||
}
|
||||
$iM++;
|
||||
}
|
||||
}
|
||||
$map->setMarkerClusterer();
|
||||
}
|
||||
|
||||
$map->renderFullScreenControl();
|
||||
$map->renderCurrentPosition();
|
||||
|
||||
if ($tmpl['osm_search'] == 1) {
|
||||
$map->renderSearch('', 'topleft');
|
||||
}
|
||||
// Get Lat and Lng TO (first marker)
|
||||
$lat = $lng = 0;
|
||||
$mId = '';
|
||||
$markerIconOptions = array();
|
||||
if (isset($firstMarker->latitude)) {
|
||||
$lat = $firstMarker->latitude;
|
||||
}
|
||||
if (isset($firstMarker->longitude)) {
|
||||
$lng = $firstMarker->longitude;
|
||||
}
|
||||
if (isset($firstMarker->id)) {
|
||||
$mId = $id . 'm'.$firstMarker->id;
|
||||
}
|
||||
if (isset($firstMarker->markericonoptions)) {
|
||||
$markerIconOptions = $firstMarker->markericonoptions;
|
||||
}
|
||||
$map->renderRouting(0,0,$lat,$lng, $mId, $markerIconOptions, $mapp->lang);
|
||||
if ($tmpl['osm_easyprint'] == 1) {
|
||||
$map->renderEasyPrint();
|
||||
}
|
||||
|
||||
if (!empty($tmpl['tracks'])) {
|
||||
foreach ($tmpl['tracks'] as $ky=>$trk) {
|
||||
$fitbounds = $ky==0 ? $tmpl['fitbounds'] : false;
|
||||
if (isset($trk['file'])) {
|
||||
$map->renderTrack($trk['file'], $trk['color'], $fitbounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$map->renderMap();
|
||||
|
||||
########################### END OPENSTREETMAP
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$output .= '<div style="clear:both"></div>';
|
||||
$output .= '</div>';
|
||||
|
||||
|
||||
// END RENDER
|
||||
// - - - - - - - - - - - - - - -
|
||||
|
||||
|
||||
|
||||
break;
|
||||
|
||||
// - - - - - - - - - - - - - - - -
|
||||
// Link
|
||||
// - - - - - - - - - - - - - - - -
|
||||
case 'link':
|
||||
if ((int)$idMap > 0) {
|
||||
|
||||
$query = 'SELECT a.*,'
|
||||
. ' CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(\':\', a.id, a.alias) ELSE a.id END as slug'
|
||||
.' FROM #__phocamaps_map AS a'
|
||||
.' WHERE a.id = '.(int) $idMap;
|
||||
$db->setQuery($query);
|
||||
$mapp = $db->loadObject();
|
||||
|
||||
if (empty($mapp)) {
|
||||
|
||||
|
||||
echo '<div class="alert alert-error">'. Text::_('PLG_CONTENT_PHOCAMAPS_PLUGIN_ERROR') . ' - '. Text::_('PLG_CONTENT_PHOCAMAPS_MAP_NOT_EXISTS') . ' (ID = '.$idMap.')</div>';
|
||||
return false;
|
||||
}
|
||||
|
||||
$query = 'SELECT a.id'
|
||||
.' FROM #__phocamaps_marker AS a'
|
||||
.' LEFT JOIN #__phocamaps_map AS c ON c.id = a.catid '
|
||||
.' WHERE c.id = '.(int) $idMap
|
||||
.' AND a.published = 1';
|
||||
$db->setQuery($query);
|
||||
$markerp = $db->loadObjectList();
|
||||
|
||||
|
||||
$linkMap = PhocaMapsHelperRoute::getMapRoute( $mapp->id, $mapp->alias);
|
||||
if ($text =='') {
|
||||
$text = Text::_('PLG_CONTENT_PHOCAMAPS_LINK_TO_MAP');
|
||||
}
|
||||
|
||||
// Parameters
|
||||
$tmpl['detailwindow'] = $paramsP->get( 'detail_window', 0 );
|
||||
$tmpl['mbbordercolor'] = $paramsP->get( 'modal_box_border_color', '#6b6b6b' );
|
||||
$tmpl['mbborderwidth'] = $paramsP->get( 'modal_box_border_width', 2 );
|
||||
$tmpl['mboverlaycolor'] = $paramsP->get( 'modal_box_overlay_color', '#000000' );
|
||||
$tmpl['mboverlayopacity'] = $paramsP->get( 'modal_box_overlay_opacity', 0.3 );
|
||||
|
||||
|
||||
if ($mapp->width > 0) {
|
||||
$tmpl['windowwidth'] = (int)$mapp->width + 20;
|
||||
} else {
|
||||
$tmpl['windowwidth'] = 640;
|
||||
}
|
||||
if ($mapp->width > 0) {
|
||||
$tmpl['windowheight'] = (int)$mapp->height + 20;
|
||||
} else {
|
||||
$tmpl['windowheight'] = 360;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Route
|
||||
if (isset($mapp->displayroute) && $mapp->displayroute == 1) {
|
||||
if (isset($markerp) && !empty($markerp)) {
|
||||
$tmpl['windowheight'] = (int)$tmpl['windowheight'] + 40;
|
||||
}
|
||||
}
|
||||
|
||||
if ($tmpl['detailwindow'] == 1) {
|
||||
|
||||
$button = new CMSObject();
|
||||
$button->set('name', 'phocamaps');
|
||||
$button->set('methodname', 'js-button');
|
||||
$button->set('options', "window.open(this.href,'win2','width=".$tmpl['windowwidth'].",height=".$tmpl['windowheight'].",menubar=no,resizable=yes'); return false;");
|
||||
$output .= '<a title="'.$text.'" href="'.Route::_($linkMap . '&tmpl=component').'" onclick="'. $button->options.'">'.$text.'</a>';
|
||||
|
||||
|
||||
} else if ($tmpl['detailwindow'] == 0) {
|
||||
|
||||
// Button
|
||||
HTMLHelper::_('behavior.modal', 'a.modal-button');
|
||||
$cssSbox = " #sbox-window {background-color:".$tmpl['mbbordercolor'].";padding:".$tmpl['mbborderwidth']."px} \n"
|
||||
." #sbox-overlay {background-color:".$tmpl['mboverlaycolor'].";} \n";
|
||||
|
||||
$document->addCustomTag( "<style type=\"text/css\">\n" . $cssSbox . "\n" . " </style>\n");
|
||||
|
||||
$button = new CMSObject();
|
||||
$button->set('name', 'phocamaps');
|
||||
$button->set('modal', true);
|
||||
$button->set('methodname', 'modal-button');
|
||||
$button->set('options', "{handler: 'iframe', size: {x: ".$tmpl['windowwidth'].", y: ".$tmpl['windowheight']."}, overlayOpacity: ".$tmpl['mboverlayopacity'].", classWindow: 'phocamaps-plugin-window', classOverlay: 'phocamaps-plugin-overlay'}");
|
||||
|
||||
$output .= '<a class="modal-button" title="'.$text.'" href="'.Route::_($linkMap . '&tmpl=component').'" rel="'. $button->options.'">'.$text.'</a>';
|
||||
} else if ($tmpl['detailwindow'] == 2) {
|
||||
|
||||
// Bootstrap Modal
|
||||
$item = 'phPlgMapsModalDetail' . $this->_plgPhocaMapsNr;
|
||||
|
||||
if($this->_loadedBootstrap == 0) {
|
||||
HTMLHelper::_('script', 'media/plg_content_phocamaps/js/main.js', array('version' => 'auto'));
|
||||
Factory::getApplication()
|
||||
->getDocument()
|
||||
->getWebAssetManager()
|
||||
->useScript('bootstrap.modal');
|
||||
|
||||
$output .= '<div id="pmPlgModal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="pmPlgModal">
|
||||
<div class="modal-dialog" role="document" id="' . $item . 'Dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
|
||||
<h4 class="modal-title" id="pmPlgModalLabel">' . Text::_('COM_PHOCAMAPS_MAP') . '</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="' . Text::_('COM_PHOCAMAPS_CLOSE') . '"></button>
|
||||
</div>
|
||||
<div class="modal-body"><iframe id="pmPlgModalIframe" height="100%" frameborder="0"></iframe></div>
|
||||
<div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">' . Text::_('COM_PHOCAMAPS_CLOSE') . '</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
|
||||
$this->_setPhocaMapsPluginLoadedBootstrap();
|
||||
|
||||
}
|
||||
|
||||
$output .= '<a class="pm-plg-bs-modal-button" title="'.$text.'" href="'.Route::_($linkMap . '&tmpl=component').'" data-bs-toggle="modal" data-title="' . $text. '" data-id="' . $this->_plgPhocaMapsNr . '" data-href="'.Route::_($linkMap . '&tmpl=component').'" data-height='.$tmpl['windowheight'].' data-width='.$tmpl['windowwidth'].'" data-bs-target="#'.$item.'">'.$text.'</a>';
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'iframe':
|
||||
|
||||
$output = '';
|
||||
$width = isset($tmpl['iframewidth']) && $tmpl['iframewidth'] != '' ? $tmpl['iframewidth'] : '100%';
|
||||
$height = isset($tmpl['iframeheight']) && $tmpl['iframeheight'] != '' ? $tmpl['iframeheight'] : '450';
|
||||
if (isset($tmpl['iframesrc']) && $tmpl['iframesrc'] != '') {
|
||||
|
||||
$output = '<iframe src="'.strip_tags(htmlspecialchars($tmpl['iframesrc'])).'" width="'.strip_tags($width).'" height="'.strip_tags($height).'" frameborder="0" style="border:0" allowfullscreen></iframe>';
|
||||
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
$article->text = preg_replace($regex_all, $output, $article->text, 1);
|
||||
} // end foreach
|
||||
|
||||
|
||||
|
||||
// Add init for all Google Maps
|
||||
$iDi = '';
|
||||
|
||||
if (!empty($allIds)) {
|
||||
$jsI = '<script type="text/javascript">//<![CDATA['."\n";
|
||||
// Article view = All OK
|
||||
// Blog view = we get warning from google maps api that the api is loaded twice or more times but the map will be displayed
|
||||
// so we can load all maps with warning or no map
|
||||
|
||||
if (isset($article->id)) {
|
||||
// We need to load google maps javascript for whole article - even there are more plugin instances
|
||||
// this javascript must be loaded as last
|
||||
// we run only loadAPI function which does not set any other variables for other functions
|
||||
//$mapA = new PhocaMapsMap();
|
||||
//$jsI .= $mapA->loadAPI($article->id);
|
||||
$iDi = $context . $article->id;
|
||||
} else {
|
||||
$iDi = $context;
|
||||
}
|
||||
$iDi = str_replace('_', '', $iDi);
|
||||
$iDi = str_replace('.', '', $iDi);
|
||||
$iDi = str_replace('-', '', $iDi);
|
||||
$iDi = strip_tags($iDi);
|
||||
$iDi = ucfirst($iDi);
|
||||
|
||||
//$jsI .= 'function initMaps() {'."\n"; // NO WARNING BUT MAPS IN BLOG WILL BE LOADED ONLY IN ONE ARTICLE
|
||||
|
||||
$jsI .= 'function initMaps'.$iDi.'() {'."\n";// WARNING BUT MAPS WILL BE LOADED IN ALL ARTICLES IN BLOG VIEW
|
||||
|
||||
|
||||
foreach($allIds as $k => $v){
|
||||
$jsI .= ' '.'initMap'.$v.'();'."\n";
|
||||
}
|
||||
$jsI .= '}'."\n";
|
||||
$jsI .= '//]]></script>'."\n";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$mapA = new PhocaMapsMap($iDi);
|
||||
$jsI .= $mapA->loadAPI($iDi, $mapp->lang);
|
||||
|
||||
$article->text = $article->text . $jsI;
|
||||
|
||||
}
|
||||
}// end if count_matches
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getTemplateOutput($data, $tmpl = "default") {
|
||||
|
||||
ob_start();
|
||||
|
||||
$getTemplatePath = PluginHelper::getLayoutPath('content', $this->plg_name, $tmpl);
|
||||
include($getTemplatePath);
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
?>
|
||||
63
plugins/content/phocamaps/phocamaps.xml
Normal file
63
plugins/content/phocamaps/phocamaps.xml
Normal file
@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension type="plugin" group="content" method="upgrade" version="5.0">
|
||||
<name>plg_content_phocamaps</name>
|
||||
<author>Jan Pavelka (www.phoca.cz)</author>
|
||||
<creationDate>01/08/2024</creationDate>
|
||||
<authorEmail></authorEmail>
|
||||
<authorUrl>https://www.phoca.cz</authorUrl>
|
||||
<copyright>Jan Pavelka</copyright>
|
||||
<license>GNU/GPL</license>
|
||||
<version>5.0.2</version>
|
||||
<description>PLG_CONTENT_PHOCAMAPS_DESCRIPTION</description>
|
||||
<projectName>PhocaMapsPlugin</projectName>
|
||||
|
||||
<media destination="plg_content_phocamaps" folder="media">
|
||||
<folder>css</folder>
|
||||
<folder>js</folder>
|
||||
<filename>index.html</filename>
|
||||
</media>
|
||||
|
||||
<files>
|
||||
<folder>tmpl</folder>
|
||||
<filename plugin="phocamaps">index.html</filename>
|
||||
<filename plugin="phocamaps">manifest.xml</filename>
|
||||
<filename plugin="phocamaps">phocamaps.php</filename>
|
||||
</files>
|
||||
|
||||
<languages>
|
||||
<language tag="en-GB">language/en-GB/en-GB.plg_content_phocamaps.ini</language>
|
||||
<language tag="en-GB">language/en-GB/en-GB.plg_content_phocamaps.sys.ini</language>
|
||||
</languages>
|
||||
|
||||
<administration>
|
||||
<languages>
|
||||
<language tag="en-GB">language/en-GB/en-GB.plg_content_phocamaps.ini</language>
|
||||
<language tag="en-GB">language/en-GB/en-GB.plg_content_phocamaps.sys.ini</language>
|
||||
</languages>
|
||||
</administration>
|
||||
|
||||
<config>
|
||||
|
||||
<fields name="params" addpath="/administrator/components/com_phocamaps/models/fields">
|
||||
|
||||
<fieldset name="basic">
|
||||
|
||||
<field name="display_map_description" type="list" default="0" label="PLG_CONTENT_PHOCAMAPS_DISPLAY_MAP_DESCRIPTION_LABEL" description="PLG_CONTENT_PHOCAMAPS_DISPLAY_MAP_DESCRIPTION_DESC">
|
||||
<option value="0">PLG_CONTENT_PHOCAMAPS_NO</option>
|
||||
<option value="1">PLG_CONTENT_PHOCAMAPS_YES</option>
|
||||
</field>
|
||||
|
||||
<field name="detail_window" type="list" default="1" label="PLG_CONTENT_PHOCAMAPS_DETAIL_WINDOW_LABEL" description="PLG_CONTENT_PHOCAMAPS_DETAIL_WINDOW_DESC">
|
||||
<option value="1">PLG_CONTENT_PHOCAMAPS_STANDARD_POPUP_WINDOW</option>
|
||||
<option value="2">PLG_CONTENT_PHOCAMAPS_BOOTSTRAP_MODAL_BOX</option>
|
||||
</field>
|
||||
|
||||
|
||||
</fieldset>
|
||||
</fields>
|
||||
</config>
|
||||
|
||||
<updateservers>
|
||||
<server type="extension" name="PLG_CONTENT_PHOCAMAPS" priority="1"><![CDATA[https://raw.githubusercontent.com/PhocaCz/PhocaMapsPlugin/master/manifest.xml]]></server>
|
||||
</updateservers>
|
||||
</extension>
|
||||
14
plugins/content/phocamaps/tmpl/custom_js.php
Normal file
14
plugins/content/phocamaps/tmpl/custom_js.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/* @package Joomla
|
||||
* @copyright Copyright (C) Open Source Matters. All rights reserved.
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php
|
||||
* @extension Phoca Extension
|
||||
* @copyright Copyright (C) Jan Pavelka www.phoca.cz
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
|
||||
*/
|
||||
|
||||
use Joomla\Language\Text;
|
||||
|
||||
defined( '_JEXEC' ) or die( 'Restricted access' );
|
||||
|
||||
?>
|
||||
33
plugins/content/phocamaps/tmpl/marker.php
Normal file
33
plugins/content/phocamaps/tmpl/marker.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/* @package Joomla
|
||||
* @copyright Copyright (C) Open Source Matters. All rights reserved.
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL, see LICENSE.php
|
||||
* @extension Phoca Extension
|
||||
* @copyright Copyright (C) Jan Pavelka www.phoca.cz
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
|
||||
*/
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
|
||||
defined( '_JEXEC' ) or die( 'Restricted access' );
|
||||
|
||||
?>
|
||||
<div class="pmMarkerTitle"><?= addslashes($data->title);?></div>
|
||||
<div><?php echo PhocaMapsHelper::strTrimAll(addslashes($data->description)); ?></div>
|
||||
<?php
|
||||
if ($data->displaygps == 1) :
|
||||
?>
|
||||
<div class="pmgps">
|
||||
<table style="border:0">
|
||||
<tr>
|
||||
<td><strong><?php echo Text::_('PLG_CONTENT_PHOCAMAPS_GPS');?>: </strong></td>
|
||||
<td><?php echo PhocaMapsHelper::strTrimAll(addslashes($data->gpslatitude));?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><?php echo PhocaMapsHelper::strTrimAll(addslashes($data->gpslongitude));?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
77
plugins/content/tabulizercss/tabulizercss.php
Normal file
77
plugins/content/tabulizercss/tabulizercss.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* Include CSS files required by the Tabulizer editor plugin
|
||||
*
|
||||
* @package tabulizer
|
||||
* @copyright Copyright © 2011 - All rights reserved.
|
||||
* @license GNU/GPL
|
||||
* @author Dimitrios Mourloukos
|
||||
* @author mail info@alterora.gr
|
||||
* @website www.alterora.gr
|
||||
*
|
||||
*/
|
||||
|
||||
// no direct access
|
||||
defined( '_JEXEC' ) or die( 'Restricted access' );
|
||||
|
||||
jimport( 'joomla.plugin.plugin' );
|
||||
|
||||
if(!defined('DS')){define('DS',DIRECTORY_SEPARATOR);}
|
||||
|
||||
|
||||
class plgContentTabulizerCSS extends JPlugin
|
||||
{
|
||||
function __construct(&$subject, $config) {
|
||||
parent::__construct($subject, $config);
|
||||
$this->loadLanguage();
|
||||
}
|
||||
|
||||
public function onContentPrepare($context, &$row, &$params, $page = 0)
|
||||
{
|
||||
$JApplication=JFactory::getApplication();
|
||||
|
||||
// don't run this plugin on administrator site
|
||||
if ($JApplication->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Don't run this plugin when the content is being indexed
|
||||
if (!empty($context)) {
|
||||
if ($context == 'com_finder.indexer') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_object($row)) {
|
||||
return $this->_includeCSS($row->text);
|
||||
}
|
||||
return $this->_includeCSS($row);
|
||||
}
|
||||
|
||||
public function onPrepareContent( &$article, &$params, $limitstart = 0 )
|
||||
{
|
||||
$JApplication=JFactory::getApplication();
|
||||
|
||||
// don't run this plugin on administrator site
|
||||
if ($JApplication->isAdmin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->_includeCSS($article->text);
|
||||
}
|
||||
|
||||
protected function _includeCSS(&$text) {
|
||||
// load the admin tabulizer component language, as well
|
||||
$lang = JFactory::getLanguage();
|
||||
$lang->load('com_tabulizer', JPATH_ADMINISTRATOR);
|
||||
|
||||
require_once(JPATH_ADMINISTRATOR.DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_tabulizer'.DIRECTORY_SEPARATOR.'assets'.DIRECTORY_SEPARATOR.'classes'.DIRECTORY_SEPARATOR.'common'.DIRECTORY_SEPARATOR.'tags_processor.php');
|
||||
$tag_processor = new TabulizerTagsProcessor();
|
||||
$tag_processor->init('content');
|
||||
$tag_processor->processTags($text);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
20
plugins/content/tabulizercss/tabulizercss.xml
Normal file
20
plugins/content/tabulizercss/tabulizercss.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<extension type="plugin" version="1.5" group="content" method="upgrade">
|
||||
<name>Content - Tabulizer CSS</name>
|
||||
<creationDate>2019-01-17</creationDate>
|
||||
<copyright>Copyright (C) 2011. All rights reserved.</copyright>
|
||||
<license>GNU General Public License</license>
|
||||
<author>Dimitrios Mourloukos</author>
|
||||
<authorEmail>info@alterora.gr</authorEmail>
|
||||
<authorUrl>www.tabulizer.gr</authorUrl>
|
||||
<version>6.2.6</version>
|
||||
|
||||
<description>PLG_TABULIZERCSS_INSTALLATION_DESCRIPTION</description>
|
||||
<files>
|
||||
<filename plugin="tabulizercss">tabulizercss.php</filename>
|
||||
</files>
|
||||
<languages folder="language">
|
||||
<language tag="en-GB">en-GB/en-GB.plg_content_tabulizercss.ini</language>
|
||||
<language tag="en-GB">en-GB/en-GB.plg_content_tabulizercss.sys.ini</language>
|
||||
</languages>
|
||||
</extension>
|
||||
46
plugins/content/vote/services/provider.php
Normal file
46
plugins/content/vote/services/provider.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?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) {
|
||||
$plugin = new Vote(
|
||||
$container->get(DispatcherInterface::class),
|
||||
(array) PluginHelper::getPlugin('content', 'vote')
|
||||
);
|
||||
$plugin->setApplication(Factory::getApplication());
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
233
plugins/content/vote/src/Extension/Vote.php
Normal file
233
plugins/content/vote/src/Extension/Vote.php
Normal file
@ -0,0 +1,233 @@
|
||||
<?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;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
// 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 HTML string containing code for the votes if in com_content else empty string
|
||||
*
|
||||
* @since 3.7.0
|
||||
*/
|
||||
private function displayVotingData($context, &$row, &$params, $page)
|
||||
{
|
||||
$parts = explode('.', $context);
|
||||
|
||||
if ($parts[0] !== 'com_content') {
|
||||
return '';
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create SchemaOrg AggregateRating
|
||||
*
|
||||
* @param object $schema The schema of the content being passed to the plugin
|
||||
* @param string $context The context of the content being passed to the plugin
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 5.2.0
|
||||
*/
|
||||
public function onSchemaBeforeCompileHead($schema, $context): void
|
||||
{
|
||||
$graph = $schema->get('@graph');
|
||||
$baseId = Uri::root() . '#/schema/';
|
||||
$schemaId = $baseId . str_replace('.', '/', $context);
|
||||
|
||||
foreach ($graph as &$entry) {
|
||||
if (!isset($entry['@type']) || !isset($entry['@id'])) {
|
||||
continue;
|
||||
}
|
||||
if ($entry['@id'] !== $schemaId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($entry['@type']) {
|
||||
case 'Book':
|
||||
case 'Brand':
|
||||
case 'CreativeWork':
|
||||
case 'Event':
|
||||
case 'Offer':
|
||||
case 'Organization':
|
||||
case 'Place':
|
||||
case 'Product':
|
||||
case 'Recipe':
|
||||
case 'Service':
|
||||
$rating = $this->prepareAggregateRating($context);
|
||||
break;
|
||||
case 'Article':
|
||||
case 'BlogPosting':
|
||||
$rating = $this->prepareProductAggregateRating($context);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($rating) && $rating) {
|
||||
$graph[] = $rating;
|
||||
$schema->set('@graph', $graph);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare AggregateRating
|
||||
*
|
||||
* @param string $context
|
||||
*
|
||||
* @return ?string
|
||||
*
|
||||
* @since 5.2.0
|
||||
*/
|
||||
protected function prepareAggregateRating($context)
|
||||
{
|
||||
[$extension, $view, $id] = explode('.', $context);
|
||||
|
||||
if ($view === 'article') {
|
||||
$baseId = Uri::root() . '#/schema/';
|
||||
$schemaId = $baseId . str_replace('.', '/', $context);
|
||||
|
||||
$component = $this->getApplication()->bootComponent('com_content')->getMVCFactory();
|
||||
$model = $component->createModel('Article', 'Site');
|
||||
$article = $model->getItem($id);
|
||||
if ($article->rating_count > 0) {
|
||||
return ['@isPartOf' => ['@id' => $schemaId, 'aggregateRating' => ['@type' => 'AggregateRating','ratingCount' => (string) $article->rating_count,'ratingValue' => (string) $article->rating]]];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare Product AggregateRating
|
||||
*
|
||||
* @param string $context
|
||||
*
|
||||
* @return ?string
|
||||
*
|
||||
* @since 5.2.0
|
||||
*/
|
||||
protected function prepareProductAggregateRating($context)
|
||||
{
|
||||
[$extension, $view, $id] = explode('.', $context);
|
||||
|
||||
if ($view === 'article') {
|
||||
$baseId = Uri::root() . '#/schema/';
|
||||
$schemaId = $baseId . str_replace('.', '/', $context);
|
||||
|
||||
$component = $this->getApplication()->bootComponent('com_content')->getMVCFactory();
|
||||
$model = $component->createModel('Article', 'Site');
|
||||
$article = $model->getItem($id);
|
||||
if ($article->rating_count > 0) {
|
||||
return ['@isPartOf' => ['@id' => $schemaId, '@type' => 'Product', 'name' => $article->title, 'aggregateRating' => ['@type' => 'AggregateRating', 'ratingCount' => (string) $article->rating_count, 'ratingValue' => (string) $article->rating]]];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
100
plugins/content/vote/tmpl/rating.php
Normal file
100
plugins/content/vote/tmpl/rating.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?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
|
||||
* @var \Joomla\Plugin\Content\Vote\Extension\Vote $this
|
||||
*/
|
||||
$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>
|
||||
48
plugins/content/vote/tmpl/vote.php
Normal file
48
plugins/content/vote/tmpl/vote.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?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>
|
||||
49
plugins/content/vote/vote.xml
Normal file
49
plugins/content/vote/vote.xml
Normal file
@ -0,0 +1,49 @@
|
||||
<?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>
|
||||
Reference in New Issue
Block a user