Spade
Mini Shell
| Directory:~$ /home/lmsyaran/public_html/joomla4/ |
| [Home] [System Details] [Kill Me] |
actionlog/joomla/joomla.php000064400000071772147357022230012021
0ustar00<?php
/**
* @package Joomla.Plugins
* @subpackage System.actionlogs
*
* @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\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\User\User;
use Joomla\CMS\Version;
use Joomla\Utilities\ArrayHelper;
JLoader::register('ActionLogPlugin', JPATH_ADMINISTRATOR .
'/components/com_actionlogs/libraries/actionlogplugin.php');
JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR .
'/components/com_actionlogs/helpers/actionlogs.php');
/**
* Joomla! Users Actions Logging Plugin.
*
* @since 3.9.0
*/
class PlgActionlogJoomla extends ActionLogPlugin
{
/**
* Array of loggable extensions.
*
* @var array
* @since 3.9.0
*/
protected $loggableExtensions = array();
/**
* Context aliases
*
* @var array
* @since 3.9.0
*/
protected $contextAliases = array('com_content.form' =>
'com_content.article');
/**
* Constructor.
*
* @param object &$subject The object to observe.
* @param array $config An optional associative array of
configuration settings.
*
* @since 3.9.0
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
$params =
ComponentHelper::getComponent('com_actionlogs')->getParams();
$this->loggableExtensions =
$params->get('loggable_extensions', array());
}
/**
* After save content logging method
* This method adds a record to #__action_logs contains (message, date,
context, user)
* Method is called right after the content is saved
*
* @param string $context The context of the content passed to the
plugin
* @param object $article A JTableContent object
* @param boolean $isNew If the content is just about to be created
*
* @return void
*
* @since 3.9.0
*/
public function onContentAfterSave($context, $article, $isNew)
{
if (isset($this->contextAliases[$context]))
{
$context = $this->contextAliases[$context];
}
$option = $this->app->input->getCmd('option');
if (!$this->checkLoggable($option))
{
return;
}
$params = ActionlogsHelper::getLogContentTypeParams($context);
// Not found a valid content type, don't process further
if ($params === null)
{
return;
}
list(, $contentType) = explode('.', $params->type_alias);
if ($isNew)
{
$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_ADDED';
$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
}
else
{
$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_UPDATED';
$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
}
// If the content type doesn't has it own language key, use default
language key
if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
{
$messageLanguageKey = $defaultLanguageKey;
}
$id = empty($params->id_holder) ? 0 :
$article->get($params->id_holder);
$message = array(
'action' => $isNew ? 'add' :
'update',
'type' => $params->text_prefix . '_TYPE_'
. $params->type_title,
'id' => $id,
'title' => $article->get($params->title_holder),
'itemlink' => ActionlogsHelper::getContentTypeLink($option,
$contentType, $id, $params->id_holder, $article),
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* After delete content logging method
* This method adds a record to #__action_logs contains (message, date,
context, user)
* Method is called right after the content is deleted
*
* @param string $context The context of the content passed to the
plugin
* @param object $article A JTableContent object
*
* @return void
*
* @since 3.9.0
*/
public function onContentAfterDelete($context, $article)
{
$option = $this->app->input->get('option');
if (!$this->checkLoggable($option))
{
return;
}
$params = ActionlogsHelper::getLogContentTypeParams($context);
// Not found a valid content type, don't process further
if ($params === null)
{
return;
}
// If the content type has it own language key, use it, otherwise, use
default language key
if
($this->app->getLanguage()->hasKey(strtoupper($params->text_prefix
. '_' . $params->type_title . '_DELETED')))
{
$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_DELETED';
}
else
{
$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';
}
$id = empty($params->id_holder) ? 0 :
$article->get($params->id_holder);
$message = array(
'action' => 'delete',
'type' => $params->text_prefix . '_TYPE_' .
$params->type_title,
'id' => $id,
'title' => $article->get($params->title_holder)
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* On content change status logging method
* This method adds a record to #__action_logs contains (message, date,
context, user)
* Method is called when the status of the article is changed
*
* @param string $context The context of the content passed to the
plugin
* @param array $pks An array 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 3.9.0
*/
public function onContentChangeState($context, $pks, $value)
{
$option = $this->app->input->getCmd('option');
if (!$this->checkLoggable($option))
{
return;
}
$params = ActionlogsHelper::getLogContentTypeParams($context);
// Not found a valid content type, don't process further
if ($params === null)
{
return;
}
list(, $contentType) = explode('.', $params->type_alias);
switch ($value)
{
case 0:
$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_UNPUBLISHED';
$defaultLanguageKey =
'PLG_SYSTEM_ACTIONLOGS_CONTENT_UNPUBLISHED';
$action = 'unpublish';
break;
case 1:
$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_PUBLISHED';
$defaultLanguageKey =
'PLG_SYSTEM_ACTIONLOGS_CONTENT_PUBLISHED';
$action = 'publish';
break;
case 2:
$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_ARCHIVED';
$defaultLanguageKey =
'PLG_SYSTEM_ACTIONLOGS_CONTENT_ARCHIVED';
$action = 'archive';
break;
case -2:
$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_TRASHED';
$defaultLanguageKey =
'PLG_SYSTEM_ACTIONLOGS_CONTENT_TRASHED';
$action = 'trash';
break;
default:
$messageLanguageKey = '';
$defaultLanguageKey = '';
$action = '';
break;
}
// If the content type doesn't has it own language key, use default
language key
if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
{
$messageLanguageKey = $defaultLanguageKey;
}
$db = $this->db;
$query = $db->getQuery(true)
->select($db->quoteName(array($params->title_holder,
$params->id_holder)))
->from($db->quoteName($params->table_name))
->where($db->quoteName($params->id_holder) . ' IN ('
. implode(',', ArrayHelper::toInteger($pks)) . ')');
$db->setQuery($query);
try
{
$items = $db->loadObjectList($params->id_holder);
}
catch (RuntimeException $e)
{
$items = array();
}
$messages = array();
foreach ($pks as $pk)
{
$message = array(
'action' => $action,
'type' => $params->text_prefix .
'_TYPE_' . $params->type_title,
'id' => $pk,
'title' =>
$items[$pk]->{$params->title_holder},
'itemlink' =>
ActionlogsHelper::getContentTypeLink($option, $contentType, $pk,
$params->id_holder, null)
);
$messages[] = $message;
}
$this->addLog($messages, $messageLanguageKey, $context);
}
/**
* On Saving application configuration logging method
* Method is called when the application config is being saved
*
* @param JRegistry $config JRegistry object with the new config
*
* @return void
*
* @since 3.9.0
*/
public function onApplicationAfterSave($config)
{
$option = $this->app->input->getCmd('option');
if (!$this->checkLoggable($option))
{
return;
}
$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED';
$action = 'update';
$message = array(
'action' => $action,
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_APPLICATION_CONFIG',
'extension_name' => 'com_config.application',
'itemlink' => 'index.php?option=com_config'
);
$this->addLog(array($message), $messageLanguageKey,
'com_config.application');
}
/**
* On installing extensions logging method
* This method adds a record to #__action_logs contains (message, date,
context, user)
* Method is called when an extension is installed
*
* @param JInstaller $installer Installer object
* @param integer $eid Extension Identifier
*
* @return void
*
* @since 3.9.0
*/
public function onExtensionAfterInstall($installer, $eid)
{
$context = $this->app->input->get('option');
if (!$this->checkLoggable($context))
{
return;
}
$manifest = $installer->get('manifest');
if ($manifest === null)
{
return;
}
$extensionType = $manifest->attributes()->type;
// If the extension type has it own language key, use it, otherwise, use
default language key
if
($this->app->getLanguage()->hasKey(strtoupper('PLG_ACTIONLOG_JOOMLA_'
. $extensionType . '_INSTALLED')))
{
$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_' . $extensionType
. '_INSTALLED';
}
else
{
$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_EXTENSION_INSTALLED';
}
$message = array(
'action' => 'install',
'type' => 'PLG_ACTIONLOG_JOOMLA_TYPE_'
. $extensionType,
'id' => $eid,
'name' => (string) $manifest->name,
'extension_name' => (string) $manifest->name
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* On uninstalling extensions logging method
* This method adds a record to #__action_logs contains (message, date,
context, user)
* Method is called when an extension is uninstalled
*
* @param JInstaller $installer Installer instance
* @param integer $eid Extension id
* @param integer $result Installation result
*
* @return void
*
* @since 3.9.0
*/
public function onExtensionAfterUninstall($installer, $eid, $result)
{
$context = $this->app->input->get('option');
if (!$this->checkLoggable($context))
{
return;
}
// If the process failed, we don't have manifest data, stop process
to avoid fatal error
if ($result === false)
{
return;
}
$manifest = $installer->get('manifest');
if ($manifest === null)
{
return;
}
$extensionType = $manifest->attributes()->type;
// If the extension type has it own language key, use it, otherwise, use
default language key
if
($this->app->getLanguage()->hasKey(strtoupper('PLG_ACTIONLOG_JOOMLA_'
. $extensionType . '_UNINSTALLED')))
{
$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_' . $extensionType
. '_UNINSTALLED';
}
else
{
$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_EXTENSION_UNINSTALLED';
}
$message = array(
'action' => 'install',
'type' => 'PLG_ACTIONLOG_JOOMLA_TYPE_'
. $extensionType,
'id' => $eid,
'name' => (string) $manifest->name,
'extension_name' => (string) $manifest->name
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* On updating extensions logging method
* This method adds a record to #__action_logs contains (message, date,
context, user)
* Method is called when an extension is updated
*
* @param JInstaller $installer Installer instance
* @param integer $eid Extension id
*
* @return void
*
* @since 3.9.0
*/
public function onExtensionAfterUpdate($installer, $eid)
{
$context = $this->app->input->get('option');
if (!$this->checkLoggable($context))
{
return;
}
$manifest = $installer->get('manifest');
if ($manifest === null)
{
return;
}
$extensionType = $manifest->attributes()->type;
// If the extension type has it own language key, use it, otherwise, use
default language key
if
($this->app->getLanguage()->hasKey('PLG_ACTIONLOG_JOOMLA_'
. $extensionType . '_UPDATED'))
{
$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_' . $extensionType
. '_UPDATED';
}
else
{
$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_EXTENSION_UPDATED';
}
$message = array(
'action' => 'update',
'type' => 'PLG_ACTIONLOG_JOOMLA_TYPE_'
. $extensionType,
'id' => $eid,
'name' => (string) $manifest->name,
'extension_name' => (string) $manifest->name
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* On Saving extensions logging method
* Method is called when an extension is being saved
*
* @param string $context The extension
* @param JTable $table DataBase Table object
* @param boolean $isNew If the extension is new or not
*
* @return void
*
* @since 3.9.0
*/
public function onExtensionAfterSave($context, $table, $isNew)
{
$option = $this->app->input->getCmd('option');
if ($table->get('module') != null)
{
$option = 'com_modules';
}
if (!$this->checkLoggable($option))
{
return;
}
$params = ActionlogsHelper::getLogContentTypeParams($context);
// Not found a valid content type, don't process further
if ($params === null)
{
return;
}
list(, $contentType) = explode('.', $params->type_alias);
if ($isNew)
{
$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_ADDED';
$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
}
else
{
$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_UPDATED';
$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
}
// If the extension type doesn't have it own language key, use
default language key
if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
{
$messageLanguageKey = $defaultLanguageKey;
}
$message = array(
'action' => $isNew ? 'add' :
'update',
'type' => 'PLG_ACTIONLOG_JOOMLA_TYPE_'
. $params->type_title,
'id' => $table->get($params->id_holder),
'title' =>
$table->get($params->title_holder),
'extension_name' =>
$table->get($params->title_holder),
'itemlink' =>
ActionlogsHelper::getContentTypeLink($option, $contentType,
$table->get($params->id_holder), $params->id_holder, null)
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* On Deleting extensions logging method
* Method is called when an extension is being deleted
*
* @param string $context The extension
* @param JTable $table DataBase Table object
*
* @return void
*
* @since 3.9.0
*/
public function onExtensionAfterDelete($context, $table)
{
if
(!$this->checkLoggable($this->app->input->get('option')))
{
return;
}
$params = ActionlogsHelper::getLogContentTypeParams($context);
// Not found a valid content type, don't process further
if ($params === null)
{
return;
}
$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';
$message = array(
'action' => 'delete',
'type' => 'PLG_ACTIONLOG_JOOMLA_TYPE_' .
$params->type_title,
'title' => $table->get($params->title_holder)
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* On saving user data logging method
*
* Method is called after user data is stored in the database.
* This method logs who created/edited any user's data
*
* @param array $user Holds the new user data.
* @param boolean $isnew True if a new user is stored.
* @param boolean $success True if user was successfully stored in the
database.
* @param string $msg Message.
*
* @return void
*
* @since 3.9.0
*/
public function onUserAfterSave($user, $isnew, $success, $msg)
{
$context = $this->app->input->get('option');
$task = $this->app->input->get->getCmd('task');
if (!$this->checkLoggable($context))
{
return;
}
$jUser = Factory::getUser();
if (!$jUser->id)
{
$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_REGISTERED';
$action = 'register';
// Reset request
if ($task === 'reset.request')
{
$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_USER_RESET_REQUEST';
$action = 'resetrequest';
}
// Reset complete
if ($task === 'reset.complete')
{
$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_USER_RESET_COMPLETE';
$action = 'resetcomplete';
}
// Registration Activation
if ($task === 'registration.activate')
{
$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_USER_REGISTRATION_ACTIVATE';
$action = 'activaterequest';
}
}
elseif ($isnew)
{
$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
$action = 'add';
}
else
{
$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
$action = 'update';
}
$userId = $jUser->id ?: $user['id'];
$username = $jUser->username ?: $user['username'];
$message = array(
'action' => $action,
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
'id' => $user['id'],
'title' => $user['name'],
'itemlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user['id'],
'userid' => $userId,
'username' => $username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$userId,
);
$this->addLog(array($message), $messageLanguageKey, $context,
$userId);
}
/**
* On deleting user data logging method
*
* Method is called after user data is deleted from the database
*
* @param array $user Holds the user data
* @param boolean $success True if user was successfully stored in the
database
* @param string $msg Message
*
* @return void
*
* @since 3.9.0
*/
public function onUserAfterDelete($user, $success, $msg)
{
$context = $this->app->input->get('option');
if (!$this->checkLoggable($context))
{
return;
}
$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';
$message = array(
'action' => 'delete',
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
'id' => $user['id'],
'title' => $user['name']
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* On after save user group data logging method
*
* Method is called after user group is stored into the database
*
* @param string $context The context
* @param JTable $table DataBase Table object
* @param boolean $isNew Is new or not
*
* @return void
*
* @since 3.9.0
*/
public function onUserAfterSaveGroup($context, $table, $isNew)
{
// Override context (com_users.group) with the component context
(com_users) to pass the checkLoggable
$context = $this->app->input->get('option');
if (!$this->checkLoggable($context))
{
return;
}
if ($isNew)
{
$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
$action = 'add';
}
else
{
$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
$action = 'update';
}
$message = array(
'action' => $action,
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP',
'id' => $table->id,
'title' => $table->title,
'itemlink' =>
'index.php?option=com_users&task=group.edit&id=' .
$table->id
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* On deleting user group data logging method
*
* Method is called after user group is deleted from the database
*
* @param array $group Holds the group data
* @param boolean $success True if user was successfully stored in the
database
* @param string $msg Message
*
* @return void
*
* @since 3.9.0
*/
public function onUserAfterDeleteGroup($group, $success, $msg)
{
$context = $this->app->input->get('option');
if (!$this->checkLoggable($context))
{
return;
}
$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';
$message = array(
'action' => 'delete',
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP',
'id' => $group['id'],
'title' => $group['title']
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* Method to log user login success action
*
* @param array $options Array holding options (user, responseType)
*
* @return void
*
* @since 3.9.0
*/
public function onUserAfterLogin($options)
{
$context = 'com_users';
if (!$this->checkLoggable($context))
{
return;
}
$loggedInUser = $options['user'];
$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGGED_IN';
$message = array(
'action' => 'login',
'userid' => $loggedInUser->id,
'username' => $loggedInUser->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$loggedInUser->id,
'app' =>
'PLG_ACTIONLOG_JOOMLA_APPLICATION_' .
$this->app->getName(),
);
$this->addLog(array($message), $messageLanguageKey, $context,
$loggedInUser->id);
}
/**
* Method to log user login failed action
*
* @param array $response Array of response data.
*
* @return void
*
* @since 3.9.0
*/
public function onUserLoginFailure($response)
{
$context = 'com_users';
if (!$this->checkLoggable($context))
{
return;
}
// Get the user id for the given username
$query = $this->db->getQuery(true)
->select($this->db->quoteName(array('id',
'username')))
->from($this->db->quoteName('#__users'))
->where($this->db->quoteName('username') . ' =
' . $this->db->quote($response['username']));
$this->db->setQuery($query);
try
{
$loggedInUser = $this->db->loadObject();
}
catch (JDatabaseExceptionExecuting $e)
{
return;
}
// Not a valid user, return
if (!isset($loggedInUser->id))
{
return;
}
$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGIN_FAILED';
$message = array(
'action' => 'login',
'id' => $loggedInUser->id,
'userid' => $loggedInUser->id,
'username' => $loggedInUser->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$loggedInUser->id,
'app' =>
'PLG_ACTIONLOG_JOOMLA_APPLICATION_' .
$this->app->getName(),
);
$this->addLog(array($message), $messageLanguageKey, $context,
$loggedInUser->id);
}
/**
* Method to log user's logout action
*
* @param array $user Holds the user data
* @param array $options Array holding options (remember,
autoregister, group)
*
* @return void
*
* @since 3.9.0
*/
public function onUserLogout($user, $options = array())
{
$context = 'com_users';
if (!$this->checkLoggable($context))
{
return;
}
$loggedOutUser = User::getInstance($user['id']);
if ($loggedOutUser->block)
{
return;
}
$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGGED_OUT';
$message = array(
'action' => 'logout',
'id' => $loggedOutUser->id,
'userid' => $loggedOutUser->id,
'username' => $loggedOutUser->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$loggedOutUser->id,
'app' =>
'PLG_ACTIONLOG_JOOMLA_APPLICATION_' .
$this->app->getName(),
);
$this->addLog(array($message), $messageLanguageKey, $context);
}
/**
* Function to check if a component is loggable or not
*
* @param string $extension The extension that triggered the event
*
* @return boolean
*
* @since 3.9.0
*/
protected function checkLoggable($extension)
{
return in_array($extension, $this->loggableExtensions);
}
/**
* On after Remind username request
*
* Method is called after user request to remind their username.
*
* @param array $user Holds the user data.
*
* @return void
*
* @since 3.9.0
*/
public function onUserAfterRemind($user)
{
$context = $this->app->input->get('option');
if (!$this->checkLoggable($context))
{
return;
}
$message = array(
'action' => 'remind',
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
'id' => $user->id,
'title' => $user->name,
'itemlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'userid' => $user->id,
'username' => $user->name,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
);
$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_REMIND', $context, $user->id);
}
/**
* On after Check-in request
*
* Method is called after user request to check-in items.
*
* @param array $table Holds the table name.
*
* @return void
*
* @since 3.9.3
*/
public function onAfterCheckin($table)
{
$context = 'com_checkin';
$user = Factory::getUser();
if (!$this->checkLoggable($context))
{
return;
}
$message = array(
'action' => 'checkin',
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
'id' => $user->id,
'title' => $user->username,
'itemlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'userid' => $user->id,
'username' => $user->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'table' => $table,
);
$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_CHECKIN', $context, $user->id);
}
/**
* On after log action purge
*
* Method is called after user request to clean action log items.
*
* @param array $group Holds the group name.
*
* @return void
*
* @since 3.9.4
*/
public function onAfterLogPurge($group = '')
{
$context = $this->app->input->get('option');
$user = Factory::getUser();
$message = array(
'action' => 'actionlogs',
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
'id' => $user->id,
'title' => $user->username,
'itemlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'userid' => $user->id,
'username' => $user->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
);
$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_LOG', $context, $user->id);
}
/**
* On after log export
*
* Method is called after user request to export action log items.
*
* @param array $group Holds the group name.
*
* @return void
*
* @since 3.9.4
*/
public function onAfterLogExport($group = '')
{
$context = $this->app->input->get('option');
$user = Factory::getUser();
$message = array(
'action' => 'actionlogs',
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
'id' => $user->id,
'title' => $user->username,
'itemlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'userid' => $user->id,
'username' => $user->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
);
$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_LOGEXPORT', $context, $user->id);
}
/**
* On after Cache purge
*
* Method is called after user request to clean cached items.
*
* @param string $group Holds the group name.
*
* @return void
*
* @since 3.9.4
*/
public function onAfterPurge($group = 'all')
{
$context = $this->app->input->get('option');
$user = JFactory::getUser();
if (!$this->checkLoggable($context))
{
return;
}
$message = array(
'action' => 'cache',
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
'id' => $user->id,
'title' => $user->username,
'itemlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'userid' => $user->id,
'username' => $user->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'group' => $group,
);
$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_CACHE', $context, $user->id);
}
/**
* On after CMS Update
*
* Method is called after user update the CMS.
*
* @param string $oldVersion The Joomla version before the update
*
* @return void
*
* @since 3.9.21
*/
public function onJoomlaAfterUpdate($oldVersion = null)
{
$context = $this->app->input->get('option');
$user = JFactory::getUser();
if (empty($oldVersion))
{
$oldVersion = JText::_('JLIB_UNKNOWN');
}
$message = array(
'action' => 'joomlaupdate',
'type' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
'id' => $user->id,
'title' => $user->username,
'itemlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'userid' => $user->id,
'username' => $user->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'version' => JVERSION,
'oldversion' => $oldVersion,
);
$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_UPDATE', $context, $user->id);
}
}
actionlog/joomla/joomla.xml000064400000001420147357022230012011
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<extension version="3.9" type="plugin"
group="actionlog" method="upgrade">
<name>PLG_ACTIONLOG_JOOMLA</name>
<author>Joomla! Project</author>
<creationDate>May 2018</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_ACTIONLOG_JOOMLA_XML_DESCRIPTION</description>
<files>
<filename plugin="joomla">joomla.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_actionlog_joomla.ini</language>
<language
tag="en-GB">en-GB.plg_actionlog_joomla.sys.ini</language>
</languages>
</extension>
authentication/cookie/cookie.php000064400000026743147357022230013037
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Authentication.cookie
*
* @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;
/**
* Joomla Authentication plugin
*
* @since 3.2
* @note Code based on
http://jaspan.com/improved_persistent_login_cookie_best_practice
* and
http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/
*/
class PlgAuthenticationCookie extends JPlugin
{
/**
* Application object
*
* @var JApplicationCms
* @since 3.2
*/
protected $app;
/**
* Database object
*
* @var JDatabaseDriver
* @since 3.2
*/
protected $db;
/**
* Reports the privacy related capabilities for this plugin to site
administrators.
*
* @return array
*
* @since 3.9.0
*/
public function onPrivacyCollectAdminCapabilities()
{
$this->loadLanguage();
return array(
JText::_('PLG_AUTHENTICATION_COOKIE') => array(
JText::_('PLG_AUTH_COOKIE_PRIVACY_CAPABILITY_COOKIE'),
)
);
}
/**
* This method should handle any authentication and report back to the
subject
*
* @param array $credentials Array holding the user credentials
* @param array $options Array of extra options
* @param object &$response Authentication response object
*
* @return boolean
*
* @since 3.2
*/
public function onUserAuthenticate($credentials, $options, &$response)
{
// No remember me for admin
if ($this->app->isClient('administrator'))
{
return false;
}
// Get cookie
$cookieName = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();
$cookieValue = $this->app->input->cookie->get($cookieName);
// Try with old cookieName (pre 3.6.0) if not found
if (!$cookieValue)
{
$cookieName = JUserHelper::getShortHashedUserAgent();
$cookieValue = $this->app->input->cookie->get($cookieName);
}
if (!$cookieValue)
{
return false;
}
$cookieArray = explode('.', $cookieValue);
// Check for valid cookie value
if (count($cookieArray) !== 2)
{
// Destroy the cookie in the browser.
$this->app->input->cookie->set($cookieName, '', 1,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''));
JLog::add('Invalid cookie detected.', JLog::WARNING,
'error');
return false;
}
$response->type = 'Cookie';
// Filter series since we're going to use it in the query
$filter = new JFilterInput;
$series = $filter->clean($cookieArray[1], 'ALNUM');
// Remove expired tokens
$query = $this->db->getQuery(true)
->delete('#__user_keys')
->where($this->db->quoteName('time') . ' <
' . $this->db->quote(time()));
try
{
$this->db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
// We aren't concerned with errors from this query, carry on
}
// Find the matching record if it exists.
$query = $this->db->getQuery(true)
->select($this->db->quoteName(array('user_id',
'token', 'series', 'time')))
->from($this->db->quoteName('#__user_keys'))
->where($this->db->quoteName('series') . ' =
' . $this->db->quote($series))
->where($this->db->quoteName('uastring') . ' =
' . $this->db->quote($cookieName))
->order($this->db->quoteName('time') . '
DESC');
try
{
$results = $this->db->setQuery($query)->loadObjectList();
}
catch (RuntimeException $e)
{
$response->status = JAuthentication::STATUS_FAILURE;
return false;
}
if (count($results) !== 1)
{
// Destroy the cookie in the browser.
$this->app->input->cookie->set($cookieName, '', 1,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''));
$response->status = JAuthentication::STATUS_FAILURE;
return false;
}
// We have a user with one cookie with a valid series and a corresponding
record in the database.
if (!JUserHelper::verifyPassword($cookieArray[0], $results[0]->token))
{
/*
* This is a real attack!
* Either the series was guessed correctly or a cookie was stolen and
used twice (once by attacker and once by victim).
* Delete all tokens for this user!
*/
$query = $this->db->getQuery(true)
->delete('#__user_keys')
->where($this->db->quoteName('user_id') . ' =
' . $this->db->quote($results[0]->user_id));
try
{
$this->db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
// Log an alert for the site admin
JLog::add(
sprintf('Failed to delete cookie token for user %s with the
following error: %s', $results[0]->user_id, $e->getMessage()),
JLog::WARNING,
'security'
);
}
// Destroy the cookie in the browser.
$this->app->input->cookie->set($cookieName, '', 1,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''));
// Issue warning by email to user and/or admin?
JLog::add(JText::sprintf('PLG_AUTH_COOKIE_ERROR_LOG_LOGIN_FAILED',
$results[0]->user_id), JLog::WARNING, 'security');
$response->status = JAuthentication::STATUS_FAILURE;
return false;
}
// Make sure there really is a user with this name and get the data for
the session.
$query = $this->db->getQuery(true)
->select($this->db->quoteName(array('id',
'username', 'password')))
->from($this->db->quoteName('#__users'))
->where($this->db->quoteName('username') . ' =
' . $this->db->quote($results[0]->user_id))
->where($this->db->quoteName('requireReset') . '
= 0');
try
{
$result = $this->db->setQuery($query)->loadObject();
}
catch (RuntimeException $e)
{
$response->status = JAuthentication::STATUS_FAILURE;
return false;
}
if ($result)
{
// Bring this in line with the rest of the system
$user = JUser::getInstance($result->id);
// Set response data.
$response->username = $result->username;
$response->email = $user->email;
$response->fullname = $user->name;
$response->password = $result->password;
$response->language = $user->getParam('language');
// Set response status.
$response->status = JAuthentication::STATUS_SUCCESS;
$response->error_message = '';
}
else
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_NO_USER');
}
}
/**
* We set the authentication cookie only after login is successfully
finished.
* We set a new cookie either for a user with no cookies or one
* where the user used a cookie to authenticate.
*
* @param array $options Array holding options
*
* @return boolean True on success
*
* @since 3.2
*/
public function onUserAfterLogin($options)
{
// No remember me for admin
if ($this->app->isClient('administrator'))
{
return false;
}
if (isset($options['responseType']) &&
$options['responseType'] === 'Cookie')
{
// Logged in using a cookie
$cookieName = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();
// We need the old data to get the existing series
$cookieValue = $this->app->input->cookie->get($cookieName);
// Try with old cookieName (pre 3.6.0) if not found
if (!$cookieValue)
{
$oldCookieName = JUserHelper::getShortHashedUserAgent();
$cookieValue =
$this->app->input->cookie->get($oldCookieName);
// Destroy the old cookie in the browser
$this->app->input->cookie->set($oldCookieName,
'', 1, $this->app->get('cookie_path',
'/'), $this->app->get('cookie_domain',
''));
}
$cookieArray = explode('.', $cookieValue);
// Filter series since we're going to use it in the query
$filter = new JFilterInput;
$series = $filter->clean($cookieArray[1], 'ALNUM');
}
elseif (!empty($options['remember']))
{
// Remember checkbox is set
$cookieName = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();
// Create a unique series which will be used over the lifespan of the
cookie
$unique = false;
$errorCount = 0;
do
{
$series = JUserHelper::genRandomPassword(20);
$query = $this->db->getQuery(true)
->select($this->db->quoteName('series'))
->from($this->db->quoteName('#__user_keys'))
->where($this->db->quoteName('series') . ' =
' . $this->db->quote($series));
try
{
$results = $this->db->setQuery($query)->loadResult();
if ($results === null)
{
$unique = true;
}
}
catch (RuntimeException $e)
{
$errorCount++;
// We'll let this query fail up to 5 times before giving up,
there's probably a bigger issue at this point
if ($errorCount === 5)
{
return false;
}
}
}
while ($unique === false);
}
else
{
return false;
}
// Get the parameter values
$lifetime = $this->params->get('cookie_lifetime', 60) *
24 * 60 * 60;
$length = $this->params->get('key_length', 16);
// Generate new cookie
$token = JUserHelper::genRandomPassword($length);
$cookieValue = $token . '.' . $series;
// Overwrite existing cookie with new value
$this->app->input->cookie->set(
$cookieName,
$cookieValue,
time() + $lifetime,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''),
$this->app->isHttpsForced(),
true
);
$query = $this->db->getQuery(true);
if (!empty($options['remember']))
{
// Create new record
$query
->insert($this->db->quoteName('#__user_keys'))
->set($this->db->quoteName('user_id') . ' =
' . $this->db->quote($options['user']->username))
->set($this->db->quoteName('series') . ' =
' . $this->db->quote($series))
->set($this->db->quoteName('uastring') . ' =
' . $this->db->quote($cookieName))
->set($this->db->quoteName('time') . ' = '
. (time() + $lifetime));
}
else
{
// Update existing record with new token
$query
->update($this->db->quoteName('#__user_keys'))
->where($this->db->quoteName('user_id') . ' =
' . $this->db->quote($options['user']->username))
->where($this->db->quoteName('series') . ' =
' . $this->db->quote($series))
->where($this->db->quoteName('uastring') . ' =
' . $this->db->quote($cookieName));
}
$hashedToken = JUserHelper::hashPassword($token);
$query->set($this->db->quoteName('token') . ' =
' . $this->db->quote($hashedToken));
try
{
$this->db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
return false;
}
return true;
}
/**
* This is where we delete any authentication cookie when a user logs out
*
* @param array $options Array holding options (length,
timeToExpiration)
*
* @return boolean True on success
*
* @since 3.2
*/
public function onUserAfterLogout($options)
{
// No remember me for admin
if ($this->app->isClient('administrator'))
{
return false;
}
$cookieName = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();
$cookieValue = $this->app->input->cookie->get($cookieName);
// There are no cookies to delete.
if (!$cookieValue)
{
return true;
}
$cookieArray = explode('.', $cookieValue);
// Filter series since we're going to use it in the query
$filter = new JFilterInput;
$series = $filter->clean($cookieArray[1], 'ALNUM');
// Remove the record from the database
$query = $this->db->getQuery(true)
->delete('#__user_keys')
->where($this->db->quoteName('series') . ' =
' . $this->db->quote($series));
try
{
$this->db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
// We aren't concerned with errors from this query, carry on
}
// Destroy the cookie
$this->app->input->cookie->set($cookieName, '', 1,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''));
return true;
}
}
authentication/cookie/cookie.xml000064400000002772147357022230013044
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.2" type="plugin"
group="authentication" method="upgrade">
<name>plg_authentication_cookie</name>
<author>Joomla! Project</author>
<creationDate>July 2013</creationDate>
<copyright>(C) 2013 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_AUTH_COOKIE_XML_DESCRIPTION</description>
<files>
<filename plugin="cookie">cookie.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_authentication_cookie.ini</language>
<language
tag="en-GB">en-GB.plg_authentication_cookie.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="cookie_lifetime"
type="number"
label="PLG_AUTH_COOKIE_FIELD_COOKIE_LIFETIME_LABEL"
description="PLG_AUTH_COOKIE_FIELD_COOKIE_LIFETIME_DESC"
default="60"
filter="integer"
required="true"
/>
<field
name="key_length"
type="list"
label="PLG_AUTH_COOKIE_FIELD_KEY_LENGTH_LABEL"
description="PLG_AUTH_COOKIE_FIELD_KEY_LENGTH_DESC"
default="16"
filter="integer"
required="true"
>
<option value="8">8</option>
<option value="16">16</option>
<option value="32">32</option>
<option value="64">64</option>
</field>
</fieldset>
</fields>
</config>
</extension>
authentication/gmail/gmail.php000064400000014535147357022230012473
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Authentication.gmail
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Authentication\AuthenticationResponse;
use Joomla\Registry\Registry;
/**
* GMail Authentication Plugin
*
* @since 1.5
*/
class PlgAuthenticationGMail extends JPlugin
{
/**
* This method should handle any authentication and report back to the
subject
*
* @param array $credentials Array holding the user
credentials
* @param array $options Array of extra options
* @param AuthenticationResponse &$response Authentication
response object
*
* @return void
*
* @since 1.5
*/
public function onUserAuthenticate($credentials, $options, &$response)
{
// Load plugin language
$this->loadLanguage();
// No backend authentication
if (JFactory::getApplication()->isClient('administrator')
&& !$this->params->get('backendLogin', 0))
{
return;
}
$success = false;
$curlParams = array(
'follow_location' => true,
'transport.curl' => array(
CURLOPT_SSL_VERIFYPEER =>
$this->params->get('verifypeer', 1)
),
);
$transportParams = new Registry($curlParams);
try
{
$http = JHttpFactory::getHttp($transportParams, 'curl');
}
catch (RuntimeException $e)
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->type = 'GMail';
$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('JGLOBAL_AUTH_CURL_NOT_INSTALLED'));
return;
}
// Check if we have a username and password
if ($credentials['username'] === '' ||
$credentials['password'] === '')
{
$response->type = 'GMail';
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('JGLOBAL_AUTH_USER_BLACKLISTED'));
return;
}
$blacklist = explode(',',
$this->params->get('user_blacklist', ''));
// Check if the username isn't blacklisted
if (in_array($credentials['username'], $blacklist))
{
$response->type = 'GMail';
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('JGLOBAL_AUTH_USER_BLACKLISTED'));
return;
}
$suffix = $this->params->get('suffix',
'');
$applysuffix = $this->params->get('applysuffix', 0);
$offset = strpos($credentials['username'], '@');
// Check if we want to do suffix stuff, typically for Google Apps for
Your Domain
if ($suffix && $applysuffix)
{
if ($applysuffix == 1 && $offset === false)
{
// Apply suffix if missing
$credentials['username'] .= '@' . $suffix;
}
elseif ($applysuffix == 2)
{
// Always use suffix
if ($offset)
{
// If we already have an @, get rid of it and replace it
$credentials['username'] =
substr($credentials['username'], 0, $offset);
}
$credentials['username'] .= '@' . $suffix;
}
}
$headers = array(
'Authorization' => 'Basic ' .
base64_encode($credentials['username'] . ':' .
$credentials['password'])
);
try
{
$result =
$http->get('https://mail.google.com/mail/feed/atom',
$headers);
}
catch (Exception $e)
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->type = 'GMail';
$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('JGLOBAL_AUTH_UNKNOWN_ACCESS_DENIED'));
return;
}
$code = $result->code;
switch ($code)
{
case 200 :
$message = JText::_('JGLOBAL_AUTH_ACCESS_GRANTED');
$success = true;
break;
case 401 :
$message = JText::_('JGLOBAL_AUTH_ACCESS_DENIED');
break;
default :
$message = JText::_('JGLOBAL_AUTH_UNKNOWN_ACCESS_DENIED');
break;
}
$response->type = 'GMail';
if (!$success)
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED', $message);
return;
}
if (strpos($credentials['username'], '@') === false)
{
if ($suffix)
{
// If there is a suffix then we want to apply it
$email = $credentials['username'] . '@' . $suffix;
}
else
{
// If there isn't a suffix just use the default gmail one
$email = $credentials['username'] . '@gmail.com';
}
}
else
{
// The username looks like an email address (probably is) so use that
$email = $credentials['username'];
}
// Extra security checks with existing local accounts
$db = JFactory::getDbo();
$localUsernameChecks = array(strstr($email, '@', true),
$email);
$query = $db->getQuery(true)
->select('id, activation, username, email, block')
->from('#__users')
->where('username IN(' . implode(',',
array_map(array($db, 'quote'), $localUsernameChecks)) .
')'
. ' OR email = ' . $db->quote($email)
);
$db->setQuery($query);
if ($localUsers = $db->loadObjectList())
{
foreach ($localUsers as $localUser)
{
// Local user exists with same username but different email address
if ($email !== $localUser->email)
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('PLG_GMAIL_ERROR_LOCAL_USERNAME_CONFLICT'));
return;
}
else
{
// Existing user disabled locally
if ($localUser->block || !empty($localUser->activation))
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_ACCESS_DENIED');
return;
}
// We will always keep the local username for existing accounts
$credentials['username'] = $localUser->username;
break;
}
}
}
elseif
(JFactory::getApplication()->isClient('administrator'))
{
// We wont' allow backend access without local account
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message = JText::_('JERROR_LOGIN_DENIED');
return;
}
$response->status = JAuthentication::STATUS_SUCCESS;
$response->error_message = '';
$response->email = $email;
// Reset the username to what we ended up using
$response->username = $credentials['username'];
$response->fullname = $credentials['username'];
}
}
authentication/gmail/gmail.xml000064400000004454147357022230012503
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="authentication" method="upgrade">
<name>plg_authentication_gmail</name>
<author>Joomla! Project</author>
<creationDate>February 2006</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_GMAIL_XML_DESCRIPTION</description>
<files>
<filename plugin="gmail">gmail.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_authentication_gmail.ini</language>
<language
tag="en-GB">en-GB.plg_authentication_gmail.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="applysuffix"
type="list"
label="PLG_GMAIL_FIELD_APPLYSUFFIX_LABEL"
description="PLG_GMAIL_FIELD_APPLYSUFFIX_DESC"
default="0"
filter="integer"
>
<option
value="0">PLG_GMAIL_FIELD_VALUE_NOAPPLYSUFFIX</option>
<option
value="1">PLG_GMAIL_FIELD_VALUE_APPLYSUFFIXMISSING</option>
<option
value="2">PLG_GMAIL_FIELD_VALUE_APPLYSUFFIXALWAYS</option>
</field>
<field
name="suffix"
type="text"
label="PLG_GMAIL_FIELD_SUFFIX_LABEL"
description="PLG_GMAIL_FIELD_SUFFIX_DESC"
size="20"
showon="applysuffix:1,2"
/>
<field
name="verifypeer"
type="radio"
label="PLG_GMAIL_FIELD_VERIFYPEER_LABEL"
description="PLG_GMAIL_FIELD_VERIFYPEER_DESC"
default="1"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="user_blacklist"
type="text"
label="PLG_GMAIL_FIELD_USER_BLACKLIST_LABEL"
description="PLG_GMAIL_FIELD_USER_BLACKLIST_DESC"
size="20"
/>
<field
name="backendLogin"
type="radio"
label="PLG_GMAIL_FIELD_BACKEND_LOGIN_LABEL"
description="PLG_GMAIL_FIELD_BACKEND_LOGIN_DESC"
default="0"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JENABLED</option>
<option value="0">JDISABLED</option>
</field>
</fieldset>
</fields>
</config>
</extension>
authentication/joomla/joomla.php000064400000013766147357022230013060
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Authentication.joomla
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Joomla Authentication plugin
*
* @since 1.5
*/
class PlgAuthenticationJoomla extends JPlugin
{
/**
* This method should handle any authentication and report back to the
subject
*
* @param array $credentials Array holding the user credentials
* @param array $options Array of extra options
* @param object &$response Authentication response object
*
* @return void
*
* @since 1.5
*/
public function onUserAuthenticate($credentials, $options, &$response)
{
$response->type = 'Joomla';
// Joomla does not like blank passwords
if (empty($credentials['password']))
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
return;
}
// Get a database object
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('id, password')
->from('#__users')
->where('username=' .
$db->quote($credentials['username']));
$db->setQuery($query);
$result = $db->loadObject();
if ($result)
{
$match = JUserHelper::verifyPassword($credentials['password'],
$result->password, $result->id);
if ($match === true)
{
// Bring this in line with the rest of the system
$user = JUser::getInstance($result->id);
$response->email = $user->email;
$response->fullname = $user->name;
if (JFactory::getApplication()->isClient('administrator'))
{
$response->language =
$user->getParam('admin_language');
}
else
{
$response->language = $user->getParam('language');
}
$response->status = JAuthentication::STATUS_SUCCESS;
$response->error_message = '';
}
else
{
// Invalid password
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_PASS');
}
}
else
{
// Let's hash the entered password even if we don't have a
matching user for some extra response time
// By doing so, we mitigate side channel user enumeration attacks
JUserHelper::hashPassword($credentials['password']);
// Invalid user
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_NO_USER');
}
// Check the two factor authentication
if ($response->status === JAuthentication::STATUS_SUCCESS)
{
$methods = JAuthenticationHelper::getTwoFactorMethods();
if (count($methods) <= 1)
{
// No two factor authentication method is enabled
return;
}
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_users/models', 'UsersModel');
/** @var UsersModelUser $model */
$model = JModelLegacy::getInstance('User',
'UsersModel', array('ignore_request' => true));
// Load the user's OTP (one time password, a.k.a. two factor auth)
configuration
if (!array_key_exists('otp_config', $options))
{
$otpConfig = $model->getOtpConfig($result->id);
$options['otp_config'] = $otpConfig;
}
else
{
$otpConfig = $options['otp_config'];
}
// Check if the user has enabled two factor authentication
if (empty($otpConfig->method) || ($otpConfig->method ===
'none'))
{
// Warn the user if they are using a secret code but they have not
// enabled two factor auth in their account.
if (!empty($credentials['secretkey']))
{
try
{
$app = JFactory::getApplication();
$this->loadLanguage();
$app->enqueueMessage(JText::_('PLG_AUTH_JOOMLA_ERR_SECRET_CODE_WITHOUT_TFA'),
'warning');
}
catch (Exception $exc)
{
// This happens when we are in CLI mode. In this case
// no warning is issued
return;
}
}
return;
}
// Try to validate the OTP
FOFPlatform::getInstance()->importPlugin('twofactorauth');
$otpAuthReplies =
FOFPlatform::getInstance()->runPlugins('onUserTwofactorAuthenticate',
array($credentials, $options));
$check = false;
/*
* This looks like noob code but DO NOT TOUCH IT and do not convert
* to in_array(). During testing in_array() inexplicably returned
* null when the OTEP begins with a zero! o_O
*/
if (!empty($otpAuthReplies))
{
foreach ($otpAuthReplies as $authReply)
{
$check = $check || $authReply;
}
}
// Fall back to one time emergency passwords
if (!$check)
{
// Did the user use an OTEP instead?
if (empty($otpConfig->otep))
{
if (empty($otpConfig->method) || ($otpConfig->method ===
'none'))
{
// Two factor authentication is not enabled on this account.
// Any string is assumed to be a valid OTEP.
return;
}
else
{
/*
* Two factor authentication enabled and no OTEPs defined. The
* user has used them all up. Therefore anything they enter is
* an invalid OTEP.
*/
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_SECRETKEY');
return;
}
}
// Clean up the OTEP (remove dashes, spaces and other funny stuff
// our beloved users may have unwittingly stuffed in it)
$otep = $credentials['secretkey'];
$otep = filter_var($otep, FILTER_SANITIZE_NUMBER_INT);
$otep = str_replace('-', '', $otep);
$check = false;
// Did we find a valid OTEP?
if (in_array($otep, $otpConfig->otep))
{
// Remove the OTEP from the array
$otpConfig->otep = array_diff($otpConfig->otep, array($otep));
$model->setOtpConfig($result->id, $otpConfig);
// Return true; the OTEP was a valid one
$check = true;
}
}
if (!$check)
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_SECRETKEY');
}
}
}
}
authentication/joomla/joomla.xml000064400000001444147357022230013057
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="authentication" method="upgrade">
<name>plg_authentication_joomla</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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_AUTH_JOOMLA_XML_DESCRIPTION</description>
<files>
<filename plugin="joomla">joomla.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_authentication_joomla.ini</language>
<language
tag="en-GB">en-GB.plg_authentication_joomla.sys.ini</language>
</languages>
</extension>
authentication/ldap/ldap.php000064400000011767147357022230012155
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Authentication.ldap
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Ldap\LdapClient;
/**
* LDAP Authentication Plugin
*
* @since 1.5
*/
class PlgAuthenticationLdap extends JPlugin
{
/**
* This method should handle any authentication and report back to the
subject
*
* @param array $credentials Array holding the user credentials
* @param array $options Array of extra options
* @param object &$response Authentication response object
*
* @return boolean
*
* @since 1.5
*/
public function onUserAuthenticate($credentials, $options, &$response)
{
$userdetails = null;
$success = 0;
$userdetails = array();
// For JLog
$response->type = 'LDAP';
// Strip null bytes from the password
$credentials['password'] = str_replace(chr(0), '',
$credentials['password']);
// LDAP does not like Blank passwords (tries to Anon Bind which is bad)
if (empty($credentials['password']))
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
return false;
}
// Load plugin params info
$ldap_email = $this->params->get('ldap_email');
$ldap_fullname = $this->params->get('ldap_fullname');
$ldap_uid = $this->params->get('ldap_uid');
$auth_method = $this->params->get('auth_method');
$ldap = new LdapClient($this->params);
if (!$ldap->connect())
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_NOT_CONNECT');
return;
}
switch ($auth_method)
{
case 'search':
{
// Bind using Connect Username/password
// Force anon bind to mitigate misconfiguration like [#7119]
if ($this->params->get('username', '') !==
'')
{
$bindtest = $ldap->bind();
}
else
{
$bindtest = $ldap->anonymous_bind();
}
if ($bindtest)
{
// Search for users DN
$binddata = $this->searchByString(
str_replace(
'[search]',
str_replace(';', '\3b',
$ldap->escape($credentials['username'], null,
LDAP_ESCAPE_FILTER)),
$this->params->get('search_string')
),
$ldap
);
if (isset($binddata[0], $binddata[0]['dn']))
{
// Verify Users Credentials
$success = $ldap->bind($binddata[0]['dn'],
$credentials['password'], 1);
// Get users details
$userdetails = $binddata;
}
else
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_NO_USER');
}
}
else
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_NOT_CONNECT');
}
} break;
case 'bind':
{
// We just accept the result here
$success =
$ldap->bind($ldap->escape($credentials['username'], null,
LDAP_ESCAPE_DN), $credentials['password']);
if ($success)
{
$userdetails = $this->searchByString(
str_replace(
'[search]',
str_replace(';', '\3b',
$ldap->escape($credentials['username'], null,
LDAP_ESCAPE_FILTER)),
$this->params->get('search_string')
),
$ldap
);
}
else
{
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_PASS');
}
} break;
}
if (!$success)
{
$response->status = JAuthentication::STATUS_FAILURE;
if ($response->error_message === '')
{
$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_PASS');
}
}
else
{
// Grab some details from LDAP and return them
if (isset($userdetails[0][$ldap_uid][0]))
{
$response->username = $userdetails[0][$ldap_uid][0];
}
if (isset($userdetails[0][$ldap_email][0]))
{
$response->email = $userdetails[0][$ldap_email][0];
}
if (isset($userdetails[0][$ldap_fullname][0]))
{
$response->fullname = $userdetails[0][$ldap_fullname][0];
}
else
{
$response->fullname = $credentials['username'];
}
// Were good - So say so.
$response->status = JAuthentication::STATUS_SUCCESS;
$response->error_message = '';
}
$ldap->close();
}
/**
* Shortcut method to build a LDAP search based on a semicolon separated
string
*
* Note that this method requires that semicolons which should be part of
the search term to be escaped
* to correctly split the search string into separate lookups
*
* @param string $search search string of search values
* @param LdapClient $ldap The LDAP client
*
* @return array Search results
*
* @since 3.8.2
*/
private static function searchByString($search, LdapClient $ldap)
{
$results = explode(';', $search);
foreach ($results as $key => $result)
{
$results[$key] = '(' . str_replace('\3b',
';', $result) . ')';
}
return $ldap->search($results);
}
}
authentication/ldap/ldap.xml000064400000010756147357022230012163
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="authentication" method="upgrade">
<name>plg_authentication_ldap</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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_LDAP_XML_DESCRIPTION</description>
<files>
<filename plugin="ldap">ldap.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_authentication_ldap.ini</language>
<language
tag="en-GB">en-GB.plg_authentication_ldap.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="host"
type="text"
label="PLG_LDAP_FIELD_HOST_LABEL"
description="PLG_LDAP_FIELD_HOST_DESC"
size="20"
/>
<field
name="port"
type="number"
label="PLG_LDAP_FIELD_PORT_LABEL"
description="PLG_LDAP_FIELD_PORT_DESC"
min="1"
max="65535"
default="389"
hint="389"
validate="number"
filter="integer"
size="5"
/>
<field
name="use_ldapV3"
type="radio"
label="PLG_LDAP_FIELD_V3_LABEL"
description="PLG_LDAP_FIELD_V3_DESC"
default="0"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="negotiate_tls"
type="radio"
label="PLG_LDAP_FIELD_NEGOCIATE_LABEL"
description="PLG_LDAP_FIELD_NEGOCIATE_DESC"
default="0"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="ignore_reqcert_tls"
type="radio"
label="PLG_LDAP_FIELD_IGNORE_REQCERT_TLS_LABEL"
description="PLG_LDAP_FIELD_IGNORE_REQCERT_TLS_DESC"
default="0"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="no_referrals"
type="radio"
label="PLG_LDAP_FIELD_REFERRALS_LABEL"
description="PLG_LDAP_FIELD_REFERRALS_DESC"
default="0"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="auth_method"
type="list"
label="PLG_LDAP_FIELD_AUTHMETHOD_LABEL"
description="PLG_LDAP_FIELD_AUTHMETHOD_DESC"
default="bind"
>
<option
value="search">PLG_LDAP_FIELD_VALUE_BINDSEARCH</option>
<option
value="bind">PLG_LDAP_FIELD_VALUE_BINDUSER</option>
</field>
<field
name="base_dn"
type="text"
label="PLG_LDAP_FIELD_BASEDN_LABEL"
description="PLG_LDAP_FIELD_BASEDN_DESC"
size="20"
/>
<field
name="search_string"
type="text"
label="PLG_LDAP_FIELD_SEARCHSTRING_LABEL"
description="PLG_LDAP_FIELD_SEARCHSTRING_DESC"
size="20"
/>
<field
name="users_dn"
type="text"
label="PLG_LDAP_FIELD_USERSDN_LABEL"
description="PLG_LDAP_FIELD_USERSDN_DESC"
size="20"
/>
<field
name="username"
type="text"
label="PLG_LDAP_FIELD_USERNAME_LABEL"
description="PLG_LDAP_FIELD_USERNAME_DESC"
size="20"
/>
<field
name="password"
type="password"
label="PLG_LDAP_FIELD_PASSWORD_LABEL"
description="PLG_LDAP_FIELD_PASSWORD_DESC"
size="20"
/>
<field
name="ldap_fullname"
type="text"
label="PLG_LDAP_FIELD_FULLNAME_LABEL"
description="PLG_LDAP_FIELD_FULLNAME_DESC"
default="fullName"
size="20"
/>
<field
name="ldap_email"
type="text"
label="PLG_LDAP_FIELD_EMAIL_LABEL"
description="PLG_LDAP_FIELD_EMAIL_DESC"
default="mail"
size="20"
/>
<field
name="ldap_uid"
type="text"
label="PLG_LDAP_FIELD_UID_LABEL"
description="PLG_LDAP_FIELD_UID_DESC"
default="uid"
size="20"
/>
<field
name="ldap_debug"
type="radio"
label="PLG_LDAP_FIELD_LDAPDEBUG_LABEL"
description="PLG_LDAP_FIELD_LDAPDEBUG_DESC"
default="0"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
captcha/recaptcha/postinstall/actions.php000064400000003026147357022230014634
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Captcha
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*
* This file contains the functions used by the com_postinstall code to
deliver
* the necessary post-installation messages for the end of life of
reCAPTCHA V1.
*/
/**
* Checks if the plugin is enabled and reCAPTCHA V1 is being used. If true
then the
* message about reCAPTCHA v1 EOL should be displayed.
*
* @return boolean
*
* @since 3.8.6
*/
function recaptcha_postinstall_condition()
{
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('1')
->from($db->qn('#__extensions'))
->where($db->qn('name') . ' = ' .
$db->q('plg_captcha_recaptcha'))
->where($db->qn('enabled') . ' = 1')
->where($db->qn('params') . ' LIKE ' .
$db->q('%1.0%'));
$db->setQuery($query);
$enabled_plugins = $db->loadObjectList();
return count($enabled_plugins) === 1;
}
/**
* Open the reCAPTCHA plugin so that they can update the settings to V2 and
new keys.
*
* @return void
*
* @since 3.8.6
*/
function recaptcha_postinstall_action()
{
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('extension_id')
->from($db->qn('#__extensions'))
->where($db->qn('name') . ' = ' .
$db->q('plg_captcha_recaptcha'));
$db->setQuery($query);
$e_id = $db->loadResult();
$url =
'index.php?option=com_plugins&task=plugin.edit&extension_id='
. $e_id;
JFactory::getApplication()->redirect($url);
}
captcha/recaptcha/recaptcha.php000064400000023126147357022230012555
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Captcha
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Captcha\Google\HttpBridgePostRequestMethod;
use Joomla\Utilities\IpHelper;
/**
* Recaptcha Plugin
* Based on the official recaptcha library(
https://packagist.org/packages/google/recaptcha )
*
* @since 2.5
*/
class PlgCaptchaRecaptcha extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Reports the privacy related capabilities for this plugin to site
administrators.
*
* @return array
*
* @since 3.9.0
*/
public function onPrivacyCollectAdminCapabilities()
{
$this->loadLanguage();
return array(
JText::_('PLG_CAPTCHA_RECAPTCHA') => array(
JText::_('PLG_RECAPTCHA_PRIVACY_CAPABILITY_IP_ADDRESS'),
)
);
}
/**
* Initialise the captcha
*
* @param string $id The id of the field.
*
* @return Boolean True on success, false otherwise
*
* @since 2.5
* @throws \RuntimeException
*/
public function onInit($id = 'dynamic_recaptcha_1')
{
$pubkey = $this->params->get('public_key', '');
if ($pubkey === '')
{
throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_ERROR_NO_PUBLIC_KEY'));
}
if ($this->params->get('version', '1.0') ===
'1.0')
{
JHtml::_('jquery.framework');
$theme = $this->params->get('theme',
'clean');
$file =
'https://www.google.com/recaptcha/api/js/recaptcha_ajax.js';
JHtml::_('script', $file);
JFactory::getDocument()->addScriptDeclaration('jQuery( document
).ready(function()
{Recaptcha.create("' . $pubkey . '", "' .
$id . '", {theme: "' . $theme . '",' .
$this->_getLanguage() . 'tabindex: 0});});');
}
else
{
// Load callback first for browser compatibility
JHtml::_('script',
'plg_captcha_recaptcha/recaptcha.min.js',
array('version' => 'auto', 'relative'
=> true));
$file =
'https://www.google.com/recaptcha/api.js?onload=JoomlaInitReCaptcha2&render=explicit&hl='
. JFactory::getLanguage()->getTag();
JHtml::_('script', $file);
}
return true;
}
/**
* Gets the challenge HTML
*
* @param string $name The name of the field. Not Used.
* @param string $id The id of the field.
* @param string $class The class of the field.
*
* @return string The HTML to be embedded in the form.
*
* @since 2.5
*/
public function onDisplay($name = null, $id =
'dynamic_recaptcha_1', $class = '')
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$ele = $dom->createElement('div');
$ele->setAttribute('id', $id);
if ($this->params->get('version', '1.0') ===
'1.0')
{
$ele->setAttribute('class', $class);
}
else
{
$ele->setAttribute('class', ((trim($class) == '')
? 'g-recaptcha' : ($class . ' g-recaptcha')));
$ele->setAttribute('data-sitekey',
$this->params->get('public_key', ''));
$ele->setAttribute('data-theme',
$this->params->get('theme2', 'light'));
$ele->setAttribute('data-size',
$this->params->get('size', 'normal'));
$ele->setAttribute('data-tabindex',
$this->params->get('tabindex', '0'));
$ele->setAttribute('data-callback',
$this->params->get('callback', ''));
$ele->setAttribute('data-expired-callback',
$this->params->get('expired_callback', ''));
$ele->setAttribute('data-error-callback',
$this->params->get('error_callback', ''));
}
$dom->appendChild($ele);
return $dom->saveHTML($ele);
}
/**
* Calls an HTTP POST function to verify if the user's guess was
correct
*
* @param string $code Answer provided by user. Not needed for the
Recaptcha implementation
*
* @return True if the answer is correct, false otherwise
*
* @since 2.5
* @throws \RuntimeException
*/
public function onCheckAnswer($code = null)
{
$input = \JFactory::getApplication()->input;
$privatekey = $this->params->get('private_key');
$version = $this->params->get('version',
'1.0');
$remoteip = IpHelper::getIp();
switch ($version)
{
case '1.0':
$challenge = $input->get('recaptcha_challenge_field',
'', 'string');
$response = $code ? $code :
$input->get('recaptcha_response_field', '',
'string');
$spam = ($challenge === '' || $response ===
'');
break;
case '2.0':
// Challenge Not needed in 2.0 but needed for getResponse call
$challenge = null;
$response = $code ? $code :
$input->get('g-recaptcha-response', '',
'string');
$spam = ($response === '');
break;
}
// Check for Private Key
if (empty($privatekey))
{
throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_ERROR_NO_PRIVATE_KEY'));
}
// Check for IP
if (empty($remoteip))
{
throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_ERROR_NO_IP'));
}
// Discard spam submissions
if ($spam)
{
throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_ERROR_EMPTY_SOLUTION'));
}
return $this->getResponse($privatekey, $remoteip, $response,
$challenge);
}
/**
* Get the reCaptcha response.
*
* @param string $privatekey The private key for authentication.
* @param string $remoteip The remote IP of the visitor.
* @param string $response The response received from Google.
* @param string $challenge The challenge field from the reCaptcha.
Only for 1.0
*
* @return bool True if response is good | False if response is bad.
*
* @since 3.4
* @throws \RuntimeException
*/
private function getResponse($privatekey, $remoteip, $response, $challenge
= null)
{
$version = $this->params->get('version',
'1.0');
switch ($version)
{
case '1.0':
$response = $this->_recaptcha_http_post(
'www.google.com', '/recaptcha/api/verify',
array(
'privatekey' => $privatekey,
'remoteip' => $remoteip,
'challenge' => $challenge,
'response' => $response
)
);
$answers = explode("\n", $response[1]);
if (trim($answers[0]) !== 'true')
{
// @todo use exceptions here
$this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_'
. strtoupper(str_replace('-', '_', $answers[1]))));
return false;
}
break;
case '2.0':
$reCaptcha = new \ReCaptcha\ReCaptcha($privatekey, new
HttpBridgePostRequestMethod);
$response = $reCaptcha->verify($response, $remoteip);
if (!$response->isSuccess())
{
foreach ($response->getErrorCodes() as $error)
{
throw new \RuntimeException($error);
}
return false;
}
break;
}
return true;
}
/**
* Encodes the given data into a query string format.
*
* @param array $data Array of string elements to be encoded
*
* @return string Encoded request
*
* @since 2.5
*/
private function _recaptcha_qsencode($data)
{
$req = '';
foreach ($data as $key => $value)
{
$req .= $key . '=' . urlencode(stripslashes($value)) .
'&';
}
// Cut the last '&'
$req = rtrim($req, '&');
return $req;
}
/**
* Submits an HTTP POST to a reCAPTCHA server.
*
* @param string $host Host name to POST to.
* @param string $path Path on host to POST to.
* @param array $data Data to be POSTed.
* @param int $port Optional port number on host.
*
* @return array Response
*
* @since 2.5
*/
private function _recaptcha_http_post($host, $path, $data, $port = 80)
{
$req = $this->_recaptcha_qsencode($data);
$http_request = "POST $path HTTP/1.0\r\n";
$http_request .= "Host: $host\r\n";
$http_request .= "Content-Type:
application/x-www-form-urlencoded;\r\n";
$http_request .= "Content-Length: " . strlen($req) .
"\r\n";
$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
$http_request .= "\r\n";
$http_request .= $req;
$response = '';
if (($fs = @fsockopen($host, $port, $errno, $errstr, 10)) === false)
{
die('Could not open socket');
}
fwrite($fs, $http_request);
while (!feof($fs))
{
// One TCP-IP packet
$response .= fgets($fs, 1160);
}
fclose($fs);
$response = explode("\r\n\r\n", $response, 2);
return $response;
}
/**
* Get the language tag or a custom translation
*
* @return string
*
* @since 2.5
*/
private function _getLanguage()
{
$language = JFactory::getLanguage();
$tag = explode('-', $language->getTag());
$tag = $tag[0];
$available = array('en', 'pt', 'fr',
'de', 'nl', 'ru', 'es',
'tr');
if (in_array($tag, $available))
{
return "lang : '" . $tag . "',";
}
// If the default language is not available, let's search for a
custom translation
if ($language->hasKey('PLG_RECAPTCHA_CUSTOM_LANG'))
{
$custom[] = 'custom_translations : {';
$custom[] = "\t" . 'instructions_visual : "' .
JText::_('PLG_RECAPTCHA_INSTRUCTIONS_VISUAL') .
'",';
$custom[] = "\t" . 'instructions_audio : "' .
JText::_('PLG_RECAPTCHA_INSTRUCTIONS_AUDIO') .
'",';
$custom[] = "\t" . 'play_again : "' .
JText::_('PLG_RECAPTCHA_PLAY_AGAIN') . '",';
$custom[] = "\t" . 'cant_hear_this : "' .
JText::_('PLG_RECAPTCHA_CANT_HEAR_THIS') . '",';
$custom[] = "\t" . 'visual_challenge : "' .
JText::_('PLG_RECAPTCHA_VISUAL_CHALLENGE') . '",';
$custom[] = "\t" . 'audio_challenge : "' .
JText::_('PLG_RECAPTCHA_AUDIO_CHALLENGE') . '",';
$custom[] = "\t" . 'refresh_btn : "' .
JText::_('PLG_RECAPTCHA_REFRESH_BTN') . '",';
$custom[] = "\t" . 'help_btn : "' .
JText::_('PLG_RECAPTCHA_HELP_BTN') . '",';
$custom[] = "\t" . 'incorrect_try_again : "' .
JText::_('PLG_RECAPTCHA_INCORRECT_TRY_AGAIN') .
'",';
$custom[] = '},';
$custom[] = "lang : '" . $tag . "',";
return implode("\n", $custom);
}
// If nothing helps fall back to english
return '';
}
}
captcha/recaptcha/recaptcha.xml000064400000007423147357022230012570
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.4" type="plugin"
group="captcha" method="upgrade">
<name>plg_captcha_recaptcha</name>
<version>3.4.0</version>
<creationDate>December 2011</creationDate>
<author>Joomla! Project</author>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<copyright>(C) 2011 Open Source Matters, Inc.</copyright>
<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
<description>PLG_CAPTCHA_RECAPTCHA_XML_DESCRIPTION</description>
<files>
<filename
plugin="recaptcha">recaptcha.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_captcha_recaptcha.ini</language>
<language
tag="en-GB">en-GB.plg_captcha_recaptcha.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="message"
type="note"
label="PLG_RECAPTCHA_VERSION_1_WARNING_LABEL"
showon="version:1.0"
/>
<field
name="version"
type="list"
label="PLG_RECAPTCHA_VERSION_LABEL"
description="PLG_RECAPTCHA_VERSION_DESC"
default="2.0"
size="1"
>
<option
value="1.0">PLG_RECAPTCHA_VERSION_V1</option>
<option
value="2.0">PLG_RECAPTCHA_VERSION_V2</option>
</field>
<field
name="public_key"
type="text"
label="PLG_RECAPTCHA_PUBLIC_KEY_LABEL"
description="PLG_RECAPTCHA_PUBLIC_KEY_DESC"
default=""
required="true"
filter="string"
size="100"
class="input-xxlarge"
/>
<field
name="private_key"
type="text"
label="PLG_RECAPTCHA_PRIVATE_KEY_LABEL"
description="PLG_RECAPTCHA_PRIVATE_KEY_DESC"
default=""
required="true"
filter="string"
size="100"
class="input-xxlarge"
/>
<field
name="theme"
type="list"
label="PLG_RECAPTCHA_THEME_LABEL"
description="PLG_RECAPTCHA_THEME_DESC"
default="clean"
showon="version:1.0"
filter=""
>
<option
value="clean">PLG_RECAPTCHA_THEME_CLEAN</option>
<option
value="white">PLG_RECAPTCHA_THEME_WHITE</option>
<option
value="blackglass">PLG_RECAPTCHA_THEME_BLACKGLASS</option>
<option
value="red">PLG_RECAPTCHA_THEME_RED</option>
</field>
<field
name="theme2"
type="list"
label="PLG_RECAPTCHA_THEME_LABEL"
description="PLG_RECAPTCHA_THEME_DESC"
default="light"
showon="version:2.0"
filter=""
>
<option
value="light">PLG_RECAPTCHA_THEME_LIGHT</option>
<option
value="dark">PLG_RECAPTCHA_THEME_DARK</option>
</field>
<field
name="size"
type="list"
label="PLG_RECAPTCHA_SIZE_LABEL"
description="PLG_RECAPTCHA_SIZE_DESC"
default="normal"
showon="version:2.0"
filter=""
>
<option
value="normal">PLG_RECAPTCHA_THEME_NORMAL</option>
<option
value="compact">PLG_RECAPTCHA_THEME_COMPACT</option>
</field>
<field
name="tabindex"
type="number"
label="PLG_RECAPTCHA_TABINDEX_LABEL"
description="PLG_RECAPTCHA_TABINDEX_DESC"
default="0"
showon="version:2.0"
min="0"
/>
<field
name="callback"
type="text"
label="PLG_RECAPTCHA_CALLBACK_LABEL"
description="PLG_RECAPTCHA_CALLBACK_DESC"
default=""
showon="version:2.0"
filter="string"
/>
<field
name="expired_callback"
type="text"
label="PLG_RECAPTCHA_EXPIRED_CALLBACK_LABEL"
description="PLG_RECAPTCHA_EXPIRED_CALLBACK_DESC"
default=""
showon="version:2.0"
filter="string"
/>
<field
name="error_callback"
type="text"
label="PLG_RECAPTCHA_ERROR_CALLBACK_LABEL"
description="PLG_RECAPTCHA_ERROR_CALLBACK_DESC"
default=""
showon="version:2.0"
filter="string"
/>
</fieldset>
</fields>
</config>
</extension>
captcha/recaptcha_invisible/recaptcha_invisible.php000064400000012704147357022230016665
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Captcha
*
* @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\Captcha\Google\HttpBridgePostRequestMethod;
use Joomla\Utilities\IpHelper;
/**
* Invisible reCAPTCHA Plugin.
*
* @since 3.9.0
*/
class PlgCaptchaRecaptcha_Invisible extends \JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.9.0
*/
protected $autoloadLanguage = true;
/**
* Reports the privacy related capabilities for this plugin to site
administrators.
*
* @return array
*
* @since 3.9.0
*/
public function onPrivacyCollectAdminCapabilities()
{
$this->loadLanguage();
return array(
JText::_('PLG_CAPTCHA_RECAPTCHA_INVISIBLE') => array(
JText::_('PLG_RECAPTCHA_INVISIBLE_PRIVACY_CAPABILITY_IP_ADDRESS'),
)
);
}
/**
* Initialise the captcha
*
* @param string $id The id of the field.
*
* @return boolean True on success, false otherwise
*
* @since 3.9.0
* @throws \RuntimeException
*/
public function onInit($id = 'dynamic_recaptcha_invisible_1')
{
$pubkey = $this->params->get('public_key', '');
if ($pubkey === '')
{
throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_INVISIBLE_ERROR_NO_PUBLIC_KEY'));
}
// Load callback first for browser compatibility
\JHtml::_(
'script',
'plg_captcha_recaptcha_invisible/recaptcha.min.js',
array('version' => 'auto', 'relative'
=> true),
array('async' => 'async', 'defer' =>
'defer')
);
// Load Google reCAPTCHA api js
$file = 'https://www.google.com/recaptcha/api.js'
. '?onload=JoomlaInitReCaptchaInvisible'
. '&render=explicit'
. '&hl=' . \JFactory::getLanguage()->getTag();
\JHtml::_(
'script',
$file,
array(),
array('async' => 'async', 'defer' =>
'defer')
);
return true;
}
/**
* Gets the challenge HTML
*
* @param string $name The name of the field. Not Used.
* @param string $id The id of the field.
* @param string $class The class of the field.
*
* @return string The HTML to be embedded in the form.
*
* @since 3.9.0
*/
public function onDisplay($name = null, $id =
'dynamic_recaptcha_invisible_1', $class = '')
{
$dom = new \DOMDocument('1.0', 'UTF-8');
$ele = $dom->createElement('div');
$ele->setAttribute('id', $id);
$ele->setAttribute('class', ((trim($class) == '')
? 'g-recaptcha' : ($class . ' g-recaptcha')));
$ele->setAttribute('data-sitekey',
$this->params->get('public_key', ''));
$ele->setAttribute('data-badge',
$this->params->get('badge', 'bottomright'));
$ele->setAttribute('data-size', 'invisible');
$ele->setAttribute('data-tabindex',
$this->params->get('tabindex', '0'));
$ele->setAttribute('data-callback',
$this->params->get('callback', ''));
$ele->setAttribute('data-expired-callback',
$this->params->get('expired_callback', ''));
$ele->setAttribute('data-error-callback',
$this->params->get('error_callback', ''));
$dom->appendChild($ele);
return $dom->saveHTML($ele);
}
/**
* Calls an HTTP POST function to verify if the user's guess was
correct
*
* @param string $code Answer provided by user. Not needed for the
Recaptcha implementation
*
* @return boolean True if the answer is correct, false otherwise
*
* @since 3.9.0
* @throws \RuntimeException
*/
public function onCheckAnswer($code = null)
{
$input = \JFactory::getApplication()->input;
$privatekey = $this->params->get('private_key');
$remoteip = IpHelper::getIp();
$response = $input->get('g-recaptcha-response',
'', 'string');
// Check for Private Key
if (empty($privatekey))
{
throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_INVISIBLE_ERROR_NO_PRIVATE_KEY'));
}
// Check for IP
if (empty($remoteip))
{
throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_INVISIBLE_ERROR_NO_IP'));
}
// Discard spam submissions
if (trim($response) == '')
{
throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_INVISIBLE_ERROR_EMPTY_SOLUTION'));
}
return $this->getResponse($privatekey, $remoteip, $response);
}
/**
* Method to react on the setup of a captcha field. Gives the possibility
* to change the field and/or the XML element for the field.
*
* @param \Joomla\CMS\Form\Field\CaptchaField $field Captcha field
instance
* @param \SimpleXMLElement $element XML form
definition
*
* @return void
*
* @since 3.9.0
*/
public function onSetupField(\Joomla\CMS\Form\Field\CaptchaField $field,
\SimpleXMLElement $element)
{
// Hide the label for the invisible recaptcha type
$element['hiddenLabel'] = true;
}
/**
* Get the reCaptcha response.
*
* @param string $privatekey The private key for authentication.
* @param string $remoteip The remote IP of the visitor.
* @param string $response The response received from Google.
*
* @return boolean True if response is good | False if response is bad.
*
* @since 3.9.0
* @throws \RuntimeException
*/
private function getResponse($privatekey, $remoteip, $response)
{
$reCaptcha = new \ReCaptcha\ReCaptcha($privatekey, new
HttpBridgePostRequestMethod);
$response = $reCaptcha->verify($response, $remoteip);
if (!$response->isSuccess())
{
foreach ($response->getErrorCodes() as $error)
{
throw new \RuntimeException($error);
}
return false;
}
return true;
}
}
captcha/recaptcha_invisible/recaptcha_invisible.xml000064400000005374147357022230016703
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.8" type="plugin"
group="captcha" method="upgrade">
<name>plg_captcha_recaptcha_invisible</name>
<version>3.8</version>
<creationDate>November 2017</creationDate>
<author>Joomla! Project</author>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<copyright>(C) 2017 Open Source Matters, Inc.</copyright>
<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
<description>PLG_CAPTCHA_RECAPTCHA_INVISIBLE_XML_DESCRIPTION</description>
<files>
<filename
plugin="recaptcha_invisible">recaptcha_invisible.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_captcha_recaptcha_invisible.ini</language>
<language
tag="en-GB">en-GB.plg_captcha_recaptcha_invisible.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="public_key"
type="text"
label="PLG_RECAPTCHA_INVISIBLE_PUBLIC_KEY_LABEL"
description="PLG_RECAPTCHA_INVISIBLE_PUBLIC_KEY_DESC"
default=""
required="true"
filter="string"
size="100"
class="input-xxlarge"
/>
<field
name="private_key"
type="text"
label="PLG_RECAPTCHA_INVISIBLE_PRIVATE_KEY_LABEL"
description="PLG_RECAPTCHA_INVISIBLE_PRIVATE_KEY_DESC"
default=""
required="true"
filter="string"
size="100"
class="input-xxlarge"
/>
<field
name="badge"
type="list"
label="PLG_RECAPTCHA_INVISIBLE_BADGE_LABEL"
description="PLG_RECAPTCHA_INVISIBLE_BADGE_DESC"
default="bottomright"
>
<option
value="bottomright">PLG_RECAPTCHA_INVISIBLE_BADGE_BOTTOMRIGHT</option>
<option
value="bottomleft">PLG_RECAPTCHA_INVISIBLE_BADGE_BOTTOMLEFT</option>
<option
value="inline">PLG_RECAPTCHA_INVISIBLE_BADGE_INLINE</option>
</field>
<field
name="tabindex"
type="number"
label="PLG_RECAPTCHA_INVISIBLE_TABINDEX_LABEL"
description="PLG_RECAPTCHA_INVISIBLE_TABINDEX_DESC"
default="0"
min="0"
filter="integer"
/>
<field
name="callback"
type="text"
label="PLG_RECAPTCHA_INVISIBLE_CALLBACK_LABEL"
description="PLG_RECAPTCHA_INVISIBLE_CALLBACK_DESC"
default=""
filter="string"
/>
<field
name="expired_callback"
type="text"
label="PLG_RECAPTCHA_INVISIBLE_EXPIRED_CALLBACK_LABEL"
description="PLG_RECAPTCHA_INVISIBLE_EXPIRED_CALLBACK_DESC"
default=""
filter="string"
/>
<field
name="error_callback"
type="text"
label="PLG_RECAPTCHA_INVISIBLE_ERROR_CALLBACK_LABEL"
description="PLG_RECAPTCHA_INVISIBLE_ERROR_CALLBACK_DESC"
default=""
filter="string"
/>
</fieldset>
</fields>
</config>
</extension>
content/confirmconsent/confirmconsent.php000064400000003746147357022230015024
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.confirmconsent
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;
/**
* The Joomla Core confirm consent plugin
*
* @since 3.9.0
*/
class PlgContentConfirmConsent extends CMSPlugin
{
/**
* The Application object
*
* @var JApplicationSite
* @since 3.9.0
*/
protected $app;
/**
* 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 = array(
'com_contact.contact',
'com_mailto.mailto',
'com_privacy.request',
);
/**
* Add additional fields to the supported forms
*
* @param JForm $form The form to be altered.
* @param mixed $data The associated data for the form.
*
* @return boolean
*
* @since 3.9.0
*/
public function onContentPrepareForm(JForm $form, $data)
{
if ($this->app->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',
Text::_('PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DEFAULT'));
$privacyArticle = $this->params->get('privacy_article',
false);
$form->load('
<form>
<fieldset name="default"
addfieldpath="/plugins/content/confirmconsent/fields">
<field
name="consentbox"
type="consentbox"
articleid="' . $privacyArticle . '"
label="PLG_CONTENT_CONFIRMCONSENT_CONSENTBOX_LABEL"
required="true"
>
<option value="0">' .
htmlspecialchars($consentboxText, ENT_COMPAT, 'UTF-8') .
'</option>
</field>
</fieldset>
</form>'
);
return true;
}
}
content/confirmconsent/confirmconsent.xml000064400000003067147357022230015031
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.9" type="plugin"
group="content" method="upgrade">
<name>plg_content_confirmconsent</name>
<author>Joomla! Project</author>
<creationDate>May 2018</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>
<files>
<filename
plugin="confirmconsent">confirmconsent.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_confirmconsent.ini</language>
<language
tag="en-GB">en-GB.plg_content_confirmconsent.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic"
addfieldpath="/administrator/components/com_content/models/fields">
<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"
class="span12"
rows="7"
cols="20"
filter="html"
/>
<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"
/>
</fieldset>
</fields>
</config>
</extension>
content/confirmconsent/fields/consentbox.php000064400000015164147357022230015422
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.confirmconsent
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
JFormHelper::loadFieldClass('Checkboxes');
/**
* Consentbox Field class for the Confirm Consent Plugin.
*
* @since 3.9.1
*/
class JFormFieldConsentBox extends JFormFieldCheckboxes
{
/**
* 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;
/**
* 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)
{
switch ($name)
{
case 'articleid':
return $this->$name;
}
return parent::__get($name);
}
/**
* Method to attach a JForm object to the field.
*
* @param SimpleXMLElement $element The SimpleXMLElement object
representing the `<field>` tag for the form field object.
* @param mixed $value The form field value to validate.
* @param string $group The field name group control
value. This acts as an array container for the field.
* For example if the field has
name="foo" and the group value is set to "bar" then the
* full field name would end up being
"bar[foo]".
*
* @return boolean True on success.
*
* @see JFormField::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'];
}
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-placement="bottom" ' : '';
// When we have an article let's add the modal and make the title
clickable
if ($data['articleid'])
{
$attribs['data-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 = array(
'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 3.9.2
*/
protected function getInput()
{
$modalHtml = '';
$layoutData = $this->getLayoutData();
if ($this->articleid)
{
$modalParams['title'] = $layoutData['label'];
$modalParams['url'] = $this->getAssignedArticleUrl();
$modalParams['height'] = 800;
$modalParams['width'] = '100%';
$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 = array(
'articleid' => (integer) $this->articleid,
);
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 = Factory::getDbo();
// Get the info from the article
$query = $db->getQuery(true)
->select($db->quoteName(array('id', 'catid',
'language')))
->from($db->quoteName('#__content'))
->where($db->quoteName('id') . ' = ' . (int)
$this->articleid);
$db->setQuery($query);
try
{
$article = $db->loadObject();
}
catch (JDatabaseExceptionExecuting $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'
);
}
// Register ContentHelperRoute
JLoader::register('ContentHelperRoute', JPATH_BASE .
'/components/com_content/helpers/route.php');
if (!Associations::isEnabled())
{
return Route::_(
ContentHelperRoute::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::_(
ContentHelperRoute::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
);
}
}
content/contact/contact.php000064400000006370147357022230012030
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.Contact
*
* @copyright (C) 2014 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Registry\Registry;
/**
* Contact Plugin
*
* @since 3.2
*/
class PlgContentContact extends JPlugin
{
/**
* Database object
*
* @var JDatabaseDriver
* @since 3.3
*/
protected $db;
/**
* 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 boolean True on success.
*/
public function onContentPrepare($context, &$row, $params, $page = 0)
{
$allowed_contexts = array('com_content.category',
'com_content.article', 'com_content.featured');
if (!in_array($context, $allowed_contexts))
{
return true;
}
// Return if we don't have valid params or don't link the
author
if (!($params instanceof Registry) ||
!$params->get('link_author'))
{
return true;
}
// Return if an alias is used
if ((int) $this->params->get('link_to_alias', 0) === 0
&& $row->created_by_alias != '')
{
return true;
}
// Return if we don't have a valid article id
if (!isset($row->id) || !(int) $row->id)
{
return true;
}
$contact = $this->getContactData($row->created_by);
$row->contactid = $contact->contactid;
$row->webpage = $contact->webpage;
$row->email = $contact->email_to;
$url = $this->params->get('url',
'url');
if ($row->contactid && $url === 'url')
{
JLoader::register('ContactHelperRoute', JPATH_SITE .
'/components/com_contact/helpers/route.php');
$row->contact_link =
JRoute::_(ContactHelperRoute::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 = '';
}
return true;
}
/**
* Retrieve Contact
*
* @param int $userId Id of the user who created the article
*
* @return mixed|null|integer
*/
protected function getContactData($userId)
{
static $contacts = array();
if (isset($contacts[$userId]))
{
return $contacts[$userId];
}
$query = $this->db->getQuery(true);
$query->select('MAX(contact.id) AS contactid, contact.alias,
contact.catid, contact.webpage, contact.email_to');
$query->from($this->db->quoteName('#__contact_details',
'contact'));
$query->where('contact.published = 1');
$query->where('contact.user_id = ' . (int) $userId);
if (JLanguageMultilang::isEnabled() === true)
{
$query->where('(contact.language in '
. '(' .
$this->db->quote(JFactory::getLanguage()->getTag()) .
',' . $this->db->quote('*') . ') '
. ' OR contact.language IS NULL)');
}
$this->db->setQuery($query);
$contacts[$userId] = $this->db->loadObject();
return $contacts[$userId];
}
}
content/contact/contact.xml000064400000003142147357022230012033
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.2" type="plugin"
group="content" method="upgrade">
<name>plg_content_contact</name>
<author>Joomla! Project</author>
<creationDate>January 2014</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>
<files>
<filename plugin="contact">contact.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_contact.ini</language>
<language
tag="en-GB">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"
>
<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"
class="btn-group btn-group-yesno"
filter="integer"
>
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
</fieldset>
</fields>
</config>
</extension>
content/emailcloak/emailcloak.php000064400000042375147357022230013151
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.emailcloak
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\String\StringHelper;
/**
* Email cloack plugin class.
*
* @since 1.5
*/
class PlgContentEmailcloak extends JPlugin
{
/**
* Plugin that cloaks all emails in content from spambots via Javascript.
*
* @param string $context The context of the content being passed to
the plugin.
* @param mixed &$row An object with a "text"
property or the string to be cloaked.
* @param mixed &$params Additional parameters. See {@see
PlgContentEmailcloak()}.
* @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;
}
if (is_object($row))
{
return $this->_cloak($row->text, $params);
}
return $this->_cloak($row, $params);
}
/**
* Generate a search pattern based on link and text.
*
* @param string $link The target of an email link.
* @param string $text The text enclosed by the link.
*
* @return string A regular expression that matches a link containing the
parameters.
*/
protected function _getPattern ($link, $text)
{
$pattern = '~(?:<a ([^>]*)href\s*=\s*"mailto:' .
$link . '"([^>]*))>' . $text .
'</a>~i';
return $pattern;
}
/**
* Adds an attributes to the js cloaked email.
*
* @param string $jsEmail Js cloaked email.
* @param string $before Attributes before email.
* @param string $after Attributes after email.
*
* @return string Js cloaked email with attributes.
*/
protected function _addAttributesToEmail($jsEmail, $before, $after)
{
if ($before !== '')
{
$before = str_replace("'", "\'", $before);
$jsEmail = str_replace(".innerHTML += '<a '",
".innerHTML += '<a {$before}'", $jsEmail);
}
if ($after !== '')
{
$after = str_replace("'", "\'", $after);
$jsEmail = str_replace("'\'>'",
"'\'{$after}>'", $jsEmail);
}
return $jsEmail;
}
/**
* Cloak all emails in text from spambots via Javascript.
*
* @param string &$text The string to be cloaked.
* @param mixed &$params Additional parameters. Parameter
"mode" (integer, default 1)
* replaces addresses with "mailto:"
links if nonzero.
*
* @return boolean True on success.
*/
protected function _cloak(&$text, &$params)
{
/*
* Check for presence of {emailcloak=off} which is explicits disables
this
* bot for the item.
*/
if (StringHelper::strpos($text, '{emailcloak=off}') !== false)
{
$text = StringHelper::str_ireplace('{emailcloak=off}',
'', $text);
return true;
}
// Simple performance check to determine whether bot should process
further.
if (StringHelper::strpos($text, '@') === false)
{
return true;
}
$mode = $this->params->def('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:',
'"http://mce_host([\x20-\x7f][^<>]+/)', $pattern);
while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
{
$mail = $regs[3][0];
$mailText = $regs[5][0];
// Check to see if mail text is different from mail addy
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);
// Ensure that attributes is not stripped out by email cloaking
$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]);
// 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:',
'"http://mce_host([\x20-\x7f][^<>]+/)', $pattern);
while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
{
$mail = $regs[3][0];
$mailText = $regs[5][0];
// Check to see if mail text is different from mail addy
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);
// Ensure that attributes is not stripped out by email cloaking
$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]);
// 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];
// Check to see if mail text is different from mail addy
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);
// Ensure that attributes is not stripped out by email cloaking
$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]);
// 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];
// Check to see if mail text is different from mail addy
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));
// 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] . addslashes($regs[5][0]) . $regs[6][0];
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));
// 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 = addslashes($regs[4][0]);
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);
// Ensure that attributes is not stripped out by email cloaking
$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]);
// 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];
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));
// 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];
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));
// 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] . addslashes($regs[5][0]);
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));
// 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];
// Needed for handling of Body parameter
$mail = str_replace('&', '&', $mail);
// Check to see if mail text is different from mail addy
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);
// Ensure that attributes is not stripped out by email cloaking
$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]);
// 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 = addslashes($regs[5][0]);
// Needed for handling of Body parameter
$mail = str_replace('&', '&', $mail);
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);
// Ensure that attributes is not stripped out by email cloaking
$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]);
// 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];
// Check to see if mail text is different from mail addy
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));
// 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] . addslashes($regs[6][0]) . $regs[7][0];
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));
// 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[1][0] . $regs[2][0] . $regs[3][0];
$mailText = $regs[5][0];
// Needed for handling of Body parameter
$mail = str_replace('&', '&', $mail);
// Check to see if mail text is different from mail addy
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));
// 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[1][0] . $regs[2][0] . $regs[3][0];
$mailText = $regs[4][0] . $regs[5][0] . $regs[6][0];
// Needed for handling of Body parameter
$mail = str_replace('&', '&', $mail);
// Check to see if mail text is different from mail addy
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));
// 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[1][0] . $regs[2][0] . $regs[3][0];
$mailText = $regs[4][0] . $regs[5][0] . addslashes($regs[6][0]);
// Needed for handling of Body parameter
$mail = str_replace('&', '&', $mail);
// Check to see if mail text is different from mail addy
$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);
// Ensure that attributes is not stripped out by email cloaking
$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));
// 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
not 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)|' . $searchEmail .
'~i';
while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
{
$mail = $regs[1][0];
$replacement = JHtml::_('email.cloak', $mail, $mode);
// Replace the found address with the js cloaked email
$text = substr_replace($text, $replacement, $regs[1][1], strlen($mail));
}
return true;
}
}
content/emailcloak/emailcloak.xml000064400000002325147357022230013151
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
<name>plg_content_emailcloak</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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>
<files>
<filename
plugin="emailcloak">emailcloak.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_emailcloak.ini</language>
<language
tag="en-GB">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"
description="PLG_CONTENT_EMAILCLOAK_MODE_DESC"
default="1"
filter="integer"
>
<option
value="0">PLG_CONTENT_EMAILCLOAK_NONLINKABLE</option>
<option
value="1">PLG_CONTENT_EMAILCLOAK_LINKABLE</option>
</field>
</fieldset>
</fields>
</config>
</extension>
content/fields/fields.php000064400000010140147357022240011445
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.Fields
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die();
/**
* Plug-in to show a custom field in eg an article
* This uses the {fields ID} syntax
*
* @since 3.7.0
*/
class PlgContentFields extends JPlugin
{
/**
* 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;
}
// Don't run if there is no text property (in case of bad calls) or
it is empty
if (empty($item->text))
{
return;
}
// Simple performance check to determine whether bot should process
further
if (strpos($item->text, 'field') === false)
{
return;
}
// Register FieldsHelper
JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR .
'/components/com_fields/helpers/fields.php');
// Prepare the text
if (isset($item->text))
{
$item->text = $this->prepare($item->text, $context, $item);
}
// Prepare the intro text
if (isset($item->introtext))
{
$item->introtext = $this->prepare($item->introtext, $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 (count($parts) < 2)
{
return $string;
}
$context = $parts[0] . '.' . $parts[1];
$fields = FieldsHelper::getFields($context, $item, true);
$fieldsById = array();
$groups = array();
// 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,
array(
'item' => $item,
'context' => $context,
'field' => $fieldsById[$id]
)
);
}
}
else
{
if ($match[2] === '*')
{
$match[0] = str_replace('*', '\*', $match[0]);
$renderFields = $fields;
}
else
{
$renderFields = isset($groups[$id]) ? $groups[$id] : '';
}
if ($renderFields)
{
$layout = !empty($explode[1]) ? trim($explode[1]) :
'render';
$output = FieldsHelper::render(
$context,
'fields.' . $layout,
array(
'item' => $item,
'context' => $context,
'fields' => $renderFields
)
);
}
}
$string = preg_replace("|$match[0]|", addcslashes($output,
'\\$'), $string, 1);
}
return $string;
}
}
content/fields/fields.xml000064400000001561147357022240011465
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.7.0" type="plugin"
group="content" method="upgrade">
<name>plg_content_fields</name>
<author>Joomla! Project</author>
<creationDate>February 2017</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>
<files>
<filename plugin="fields">fields.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_fields.ini</language>
<language
tag="en-GB">en-GB.plg_content_fields.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
</fieldset>
</fields>
</config>
</extension>
content/finder/finder.php000064400000007715147357022240011465
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.finder
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Smart Search Content Plugin
*
* @since 2.5
*/
class PlgContentFinder extends JPlugin
{
/**
* Smart Search after save content method.
* Content is passed by reference, but after the save, so no changes will
be saved.
* Method is called right after the content is saved.
*
* @param string $context The context of the content passed to the
plugin (added in 1.6)
* @param object $article A JTableContent object
* @param bool $isNew If the content has just been created
*
* @return void
*
* @since 2.5
*/
public function onContentAfterSave($context, $article, $isNew)
{
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('finder');
// Trigger the onFinderAfterSave event.
$dispatcher->trigger('onFinderAfterSave', array($context,
$article, $isNew));
}
/**
* Smart Search before save content method.
* Content is passed by reference. Method is called before the content is
saved.
*
* @param string $context The context of the content passed to the
plugin (added in 1.6).
* @param object $article A JTableContent object.
* @param bool $isNew If the content is just about to be created.
*
* @return void
*
* @since 2.5
*/
public function onContentBeforeSave($context, $article, $isNew)
{
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('finder');
// Trigger the onFinderBeforeSave event.
$dispatcher->trigger('onFinderBeforeSave', array($context,
$article, $isNew));
}
/**
* Smart Search after delete content method.
* Content is passed by reference, but after the deletion.
*
* @param string $context The context of the content passed to the
plugin (added in 1.6).
* @param object $article A JTableContent object.
*
* @return void
*
* @since 2.5
*/
public function onContentAfterDelete($context, $article)
{
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('finder');
// Trigger the onFinderAfterDelete event.
$dispatcher->trigger('onFinderAfterDelete', array($context,
$article));
}
/**
* Smart Search content state change method.
* Method to update the link information for items that have been changed
* from outside the edit screen. This is fired when the item is published,
* unpublished, archived, or unarchived from the list view.
*
* @param string $context The context for the content passed to the
plugin.
* @param array $pks A list of primary key ids of the content
that has changed state.
* @param integer $value The value of the state that the content has
been changed to.
*
* @return void
*
* @since 2.5
*/
public function onContentChangeState($context, $pks, $value)
{
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('finder');
// Trigger the onFinderChangeState event.
$dispatcher->trigger('onFinderChangeState', array($context,
$pks, $value));
}
/**
* Smart Search change category state content method.
* Method is called when the state of the category to which the
* content item belongs is changed.
*
* @param string $extension The extension whose category has been
updated.
* @param array $pks A list of primary key ids of the content
that has changed state.
* @param integer $value The value of the state that the content
has been changed to.
*
* @return void
*
* @since 2.5
*/
public function onCategoryChangeState($extension, $pks, $value)
{
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('finder');
// Trigger the onFinderCategoryChangeState event.
$dispatcher->trigger('onFinderCategoryChangeState',
array($extension, $pks, $value));
}
}
content/finder/finder.xml000064400000001506147357022240011466
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
<name>plg_content_finder</name>
<author>Joomla! Project</author>
<creationDate>December 2011</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>
<files>
<filename plugin="finder">finder.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_finder.ini</language>
<language
tag="en-GB">en-GB.plg_content_finder.sys.ini</language>
</languages>
<config>
<fields name="params">
</fields>
</config>
</extension>
content/joomla/joomla.php000064400000021365147357022240011506
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.joomla
*
* @copyright (C) 2010 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Example Content Plugin
*
* @since 1.6
*/
class PlgContentJoomla extends JPlugin
{
/**
* Example after save content method
* Article is passed by reference, but after the save, so no changes will
be saved.
* Method is called right after the content is saved
*
* @param string $context The context of the content passed to the
plugin (added in 1.6)
* @param object $article A JTableContent object
* @param boolean $isNew If the content is just about to be created
*
* @return boolean true if function not enabled, is in frontend or is
new. Else true or
* false depending on success of save function.
*
* @since 1.6
*/
public function onContentAfterSave($context, $article, $isNew)
{
// Check we are handling the frontend edit form.
if ($context !== 'com_content.form')
{
return true;
}
// Check if this function is enabled.
if (!$this->params->def('email_new_fe', 1))
{
return true;
}
// Check this is a new article.
if (!$isNew)
{
return true;
}
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('id'))
->from($db->quoteName('#__users'))
->where($db->quoteName('sendEmail') . ' = 1')
->where($db->quoteName('block') . ' = 0');
$db->setQuery($query);
$users = (array) $db->loadColumn();
if (empty($users))
{
return true;
}
$user = JFactory::getUser();
// Messaging for new items
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_messages/models', 'MessagesModel');
JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_messages/tables');
$default_language =
JComponentHelper::getParams('com_languages')->get('administrator');
$debug = JFactory::getConfig()->get('debug_lang');
$result = true;
foreach ($users as $user_id)
{
if ($user_id != $user->id)
{
// Load language for messaging
$receiver = JUser::getInstance($user_id);
$lang =
JLanguage::getInstance($receiver->getParam('admin_language',
$default_language), $debug);
$lang->load('com_content');
$message = array(
'user_id_to' => $user_id,
'subject' =>
$lang->_('COM_CONTENT_NEW_ARTICLE'),
'message' =>
sprintf($lang->_('COM_CONTENT_ON_NEW_CONTENT'),
$user->get('name'), $article->title)
);
$model_message = JModelLegacy::getInstance('Message',
'MessagesModel');
$result = $model_message->save($message);
}
}
return $result;
}
/**
* Don't allow categories to be deleted if they contain items or
subcategories with items
*
* @param string $context The context for the content passed to the
plugin.
* @param object $data The data relating to the content that was
deleted.
*
* @return boolean
*
* @since 1.6
*/
public function onContentBeforeDelete($context, $data)
{
// Skip plugin if we are deleting something other than categories
if ($context !== 'com_categories.category')
{
return true;
}
// Check if this function is enabled.
if (!$this->params->def('check_categories', 1))
{
return true;
}
$extension =
JFactory::getApplication()->input->getString('extension');
// Default to true if not a core extension
$result = true;
$tableInfo = array(
'com_banners' => array('table_name' =>
'#__banners'),
'com_contact' => array('table_name' =>
'#__contact_details'),
'com_content' => array('table_name' =>
'#__content'),
'com_newsfeeds' => array('table_name' =>
'#__newsfeeds'),
'com_weblinks' => array('table_name' =>
'#__weblinks')
);
// Now check to see if this is a known core extension
if (isset($tableInfo[$extension]))
{
// Get table name for known core extensions
$table = $tableInfo[$extension]['table_name'];
// See if this category has any content items
$count = $this->_countItemsInCategory($table,
$data->get('id'));
// Return false if db error
if ($count === false)
{
$result = false;
}
else
{
// Show error if items are found in the category
if ($count > 0)
{
$msg = JText::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED',
$data->get('title'))
. JText::plural('COM_CATEGORIES_N_ITEMS_ASSIGNED', $count);
JError::raiseWarning(403, $msg);
$result = false;
}
// Check for items in any child categories (if it is a leaf, there are
no child categories)
if (!$data->isLeaf())
{
$count = $this->_countItemsInChildren($table,
$data->get('id'), $data);
if ($count === false)
{
$result = false;
}
elseif ($count > 0)
{
$msg = JText::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED',
$data->get('title'))
. JText::plural('COM_CATEGORIES_HAS_SUBCATEGORY_ITEMS',
$count);
JError::raiseWarning(403, $msg);
$result = false;
}
}
}
return $result;
}
}
/**
* Get count of items in a category
*
* @param string $table table name of component table (column is
catid)
* @param integer $catid id of the category to check
*
* @return mixed count of items found or false if db error
*
* @since 1.6
*/
private function _countItemsInCategory($table, $catid)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
// Count the items in this category
$query->select('COUNT(id)')
->from($table)
->where('catid = ' . $catid);
$db->setQuery($query);
try
{
$count = $db->loadResult();
}
catch (RuntimeException $e)
{
JError::raiseWarning(500, $e->getMessage());
return false;
}
return $count;
}
/**
* Get count of items in a category's child categories
*
* @param string $table table name of component table (column is
catid)
* @param integer $catid id of the category to check
* @param object $data The data relating to the content that was
deleted.
*
* @return mixed count of items found or false if db error
*
* @since 1.6
*/
private function _countItemsInChildren($table, $catid, $data)
{
$db = JFactory::getDbo();
// Create subquery for list of child categories
$childCategoryTree = $data->getTree();
// First element in tree is the current category, so we can skip that one
unset($childCategoryTree[0]);
$childCategoryIds = array();
foreach ($childCategoryTree as $node)
{
$childCategoryIds[] = $node->id;
}
// Make sure we only do the query if we have some categories to look in
if (count($childCategoryIds))
{
// Count the items in this category
$query = $db->getQuery(true)
->select('COUNT(id)')
->from($table)
->where('catid IN (' . implode(',',
$childCategoryIds) . ')');
$db->setQuery($query);
try
{
$count = $db->loadResult();
}
catch (RuntimeException $e)
{
JError::raiseWarning(500, $e->getMessage());
return false;
}
return $count;
}
else
// If we didn't have any categories to check, return 0
{
return 0;
}
}
/**
* Change the state in core_content if the state in a table is changed
*
* @param string $context The context for the content passed to the
plugin.
* @param array $pks A list of primary key ids of the content
that has changed state.
* @param integer $value The value of the state that the content has
been changed to.
*
* @return boolean
*
* @since 3.1
*/
public function onContentChangeState($context, $pks, $value)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('core_content_id'))
->from($db->quoteName('#__ucm_content'))
->where($db->quoteName('core_type_alias') . ' =
' . $db->quote($context))
->where($db->quoteName('core_content_item_id') . '
IN (' . $pksImploded = implode(',', $pks) . ')');
$db->setQuery($query);
$ccIds = $db->loadColumn();
$cctable = new JTableCorecontent($db);
$cctable->publish($ccIds, $value);
return true;
}
/**
* The save event.
*
* @param string $context The context
* @param object $table The item
* @param boolean $isNew Is new item
*
* @return void
*
* @since 3.9.12
*/
public function onContentBeforeSave($context, $table, $isNew)
{
// Check we are handling the frontend edit form.
if ($context !== 'com_menus.item')
{
return true;
}
// Special case for Create article menu item
if ($table->link !==
'index.php?option=com_content&view=form&layout=edit')
{
return true;
}
// Display error if catid is not set when enable_category is enabled
$params = json_decode($table->params, true);
if ($params['enable_category'] == 1 &&
empty($params['catid']))
{
$table->setError(JText::_('COM_CONTENT_CREATE_ARTICLE_ERROR'));
return false;
}
}
}
content/joomla/joomla.xml000064400000003056147357022240011514
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
<name>plg_content_joomla</name>
<author>Joomla! Project</author>
<creationDate>November 2010</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>
<files>
<filename plugin="joomla">joomla.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_joomla.ini</language>
<language
tag="en-GB">en-GB.plg_content_joomla.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="check_categories"
type="radio"
label="PLG_CONTENT_JOOMLA_FIELD_CHECK_CATEGORIES_LABEL"
description="PLG_CONTENT_JOOMLA_FIELD_CHECK_CATEGORIES_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</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"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
content/loadmodule/loadmodule.php000064400000015306147357022240013214
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.loadmodule
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Plugin to enable loading modules into content (e.g. articles)
* This uses the {loadmodule} syntax
*
* @since 1.5
*/
class PlgContentLoadmodule extends JPlugin
{
protected static $modules = array();
protected static $mods = array();
/**
* 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 mixed true if there is an error. Void otherwise.
*
* @since 1.6
*/
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;
}
// Simple performance check to determine whether bot should process
further
if (strpos($article->text, 'loadposition') === false
&& strpos($article->text, 'loadmodule') === false)
{
return true;
}
// Expression to search for (positions)
$regex = '/{loadposition\s(.*?)}/i';
$style = $this->params->def('style', 'none');
// Expression to search for(modules)
$regexmod = '/{loadmodule\s(.*?)}/i';
$stylemod = $this->params->def('style',
'none');
// Expression to search for(id)
$regexmodid = '/{loadmoduleid\s([1-9][0-9]*)}/i';
// 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] = $style;
}
$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]));
}
$style = $this->params->def('style', 'none');
}
}
// 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]);
// We may not have a specific module so set to null
if (!array_key_exists(1, $matchesmodlist))
{
$matchesmodlist[1] = null;
}
// We may not have a module style so fall back to the plugin default.
if (!array_key_exists(2, $matchesmodlist))
{
$matchesmodlist[2] = $stylemod;
}
$module = trim($matchesmodlist[0]);
$name = htmlspecialchars_decode(trim($matchesmodlist[1]));
$stylemod = trim($matchesmodlist[2]);
// $match[0] is full pattern match, $match[1] is the module,$match[2]
is the title
$output = $this->_loadmod($module, $name, $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]));
}
$stylemod = $this->params->def('style',
'none');
}
}
// 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]));
}
$style = $this->params->def('style', 'none');
}
}
}
/**
* 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
*/
protected function _load($position, $style = 'none')
{
self::$modules[$position] = '';
$document = JFactory::getDocument();
$renderer = $document->loadRenderer('module');
$modules = JModuleHelper::getModules($position);
$params = array('style' => $style);
ob_start();
foreach ($modules as $module)
{
echo $renderer->render($module, $params);
}
self::$modules[$position] = ob_get_clean();
return self::$modules[$position];
}
/**
* 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
*/
protected function _loadmod($module, $title, $style = 'none')
{
self::$mods[$module] = '';
$document = JFactory::getDocument();
$renderer = $document->loadRenderer('module');
$mod = JModuleHelper::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 = JModuleHelper::getModule($name, $title);
}
$params = array('style' => $style);
ob_start();
if ($mod->id)
{
echo $renderer->render($mod, $params);
}
self::$mods[$module] = ob_get_clean();
return self::$mods[$module];
}
/**
* Loads and renders the module
*
* @param string $id The id of the module
*
* @return mixed
*
* @since 3.9.0
*/
protected function _loadid($id)
{
self::$modules[$id] = '';
$document = JFactory::getDocument();
$renderer = $document->loadRenderer('module');
$modules = JModuleHelper::getModuleById($id);
$params = array('style' => 'none');
ob_start();
if ($modules->id > 0)
{
echo $renderer->render($modules, $params);
}
self::$modules[$id] = ob_get_clean();
return self::$modules[$id];
}
}
content/loadmodule/loadmodule.xml000064400000002631147357022240013222
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
<name>plg_content_loadmodule</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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>
<files>
<filename
plugin="loadmodule">loadmodule.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_loadmodule.ini</language>
<language
tag="en-GB">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"
description="PLG_LOADMODULE_FIELD_STYLE_DESC"
default="table"
>
<option
value="table">PLG_LOADMODULE_FIELD_VALUE_TABLE</option>
<option
value="horz">PLG_LOADMODULE_FIELD_VALUE_HORIZONTAL</option>
<option
value="xhtml">PLG_LOADMODULE_FIELD_VALUE_DIVS</option>
<option
value="rounded">PLG_LOADMODULE_FIELD_VALUE_MULTIPLEDIVS</option>
<option
value="none">PLG_LOADMODULE_FIELD_VALUE_RAW</option>
</field>
</fieldset>
</fields>
</config>
</extension>
content/pagebreak/pagebreak.php000064400000022765147357022240012613
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.pagebreak
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\String\StringHelper;
jimport('joomla.utilities.utility');
JLoader::register('ContentHelperRoute', JPATH_SITE .
'/components/com_content/helpers/route.php');
/**
* Page break plugin
*
* <b>Usage:</b>
* <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
*/
class PlgContentPagebreak extends JPlugin
{
/**
* The navigation list with all page objects if parameter
'multipage_toc' is active.
*
* @var array
* @since 3.9.2
*/
protected $list = array();
/**
* 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 mixed Always returns void or true
*
* @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 = JFactory::getApplication()->input;
$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 true;
}
// 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(JText::_('JERROR_PAGE_NOT_FOUND'), 404);
}
return true;
}
$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 = array();
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 true;
}
// Split the text around the plugin.
$text = preg_split($regex, $row->text);
if (!isset($text[$page]))
{
throw new Exception(JText::_('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 = JUtility::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 JPagination($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];
$t[] = (string) JHtml::_($style . '.start',
'article' . $row->id . '-' . $style);
foreach ($text as $key => $subtext)
{
if ($key >= 1)
{
$match = $matches[$key - 1];
$match = (array) JUtility::parseAttributes($match[0]);
if (isset($match['alt']))
{
$title = stripslashes($match['alt']);
}
elseif (isset($match['title']))
{
$title = stripslashes($match['title']);
}
else
{
$title = JText::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM',
$key + 1);
}
$t[] = (string) JHtml::_($style . '.panel', $title,
'article' . $row->id . '-' . $style . $key);
}
$t[] = (string) $subtext;
}
$t[] = (string) JHtml::_($style . '.end');
$row->text = implode(' ', $t);
}
}
return true;
}
/**
* 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
*/
protected function _createToc(&$row, &$matches, &$page)
{
$heading = isset($row->title) ? $row->title :
JText::_('PLG_CONTENT_PAGEBREAK_NO_TITLE');
$input = JFactory::getApplication()->input;
$limitstart = $input->getUInt('limitstart', 0);
$showall = $input->getInt('showall', 0);
$headingtext = '';
if ($this->params->get('article_index', 1) == 1)
{
$headingtext =
JText::_('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]->liClass = ($limitstart === 0 && $showall
=== 0) ? 'toclink active' : 'toclink';
$this->list[1]->class = $this->list[1]->liClass;
$this->list[1]->link =
JRoute::_(ContentHelperRoute::getArticleRoute($row->slug,
$row->catid, $row->language));
$this->list[1]->title = $heading;
$i = 2;
foreach ($matches as $bot)
{
if (@$bot[0])
{
$attrs2 = JUtility::parseAttributes($bot[0]);
if (@$attrs2['alt'])
{
$title = stripslashes($attrs2['alt']);
}
elseif (@$attrs2['title'])
{
$title = stripslashes($attrs2['title']);
}
else
{
$title = JText::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM',
$i);
}
}
else
{
$title = JText::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM',
$i);
}
$this->list[$i] = new stdClass;
$this->list[$i]->link =
JRoute::_(ContentHelperRoute::getArticleRoute($row->slug,
$row->catid, $row->language) . '&limitstart=' . ($i -
1));
$this->list[$i]->title = $title;
$this->list[$i]->liClass = ($limitstart === $i - 1) ?
'active' : '';
$this->list[$i]->class = ($limitstart === $i - 1) ?
'toclink active' : 'toclink';
$i++;
}
if ($this->params->get('showall'))
{
$this->list[$i] = new stdClass;
$this->list[$i]->link =
JRoute::_(ContentHelperRoute::getArticleRoute($row->slug,
$row->catid, $row->language) . '&showall=1');
$this->list[$i]->liClass = ($showall === 1) ? 'active' :
'';
$this->list[$i]->class = ($showall === 1) ? 'toclink
active' : 'toclink';
$this->list[$i]->title =
JText::_('PLG_CONTENT_PAGEBREAK_ALL_PAGES');
}
$list = $this->list;
$path = JPluginHelper::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
*/
protected function _createNavigation(&$row, $page, $n)
{
$links = array(
'next' => '',
'previous' => ''
);
if ($page < $n - 1)
{
$links['next'] =
JRoute::_(ContentHelperRoute::getArticleRoute($row->slug,
$row->catid, $row->language) . '&limitstart=' . ($page
+ 1));
}
if ($page > 0)
{
$links['previous'] =
ContentHelperRoute::getArticleRoute($row->slug, $row->catid,
$row->language);
if ($page > 1)
{
$links['previous'] .= '&limitstart=' . ($page -
1);
}
$links['previous'] = JRoute::_($links['previous']);
}
$path = JPluginHelper::getLayoutPath('content',
'pagebreak', 'navigation');
ob_start();
include $path;
$row->text .= ob_get_clean();
}
}
content/pagebreak/pagebreak.xml000064400000005427147357022240012620
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
<name>plg_content_pagebreak</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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>
<files>
<filename
plugin="pagebreak">pagebreak.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_pagebreak.ini</language>
<language
tag="en-GB">en-GB.plg_content_pagebreak.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="title"
type="radio"
label="PLG_CONTENT_PAGEBREAK_SITE_TITLE_LABEL"
description="PLG_CONTENT_PAGEBREAK_SITE_TITLE_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JSHOW</option>
<option value="0">JHIDE</option>
</field>
<field
name="article_index"
type="radio"
label="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEX_LABEL"
description="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEX_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JSHOW</option>
<option value="0">JHIDE</option>
</field>
<field
name="article_index_text"
type="text"
label="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEXTEXT"
description="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEXTEXT_DESC"
showon="article_index:1"
/>
<field
name="multipage_toc"
type="radio"
label="PLG_CONTENT_PAGEBREAK_TOC_LABEL"
description="PLG_CONTENT_PAGEBREAK_TOC_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JSHOW</option>
<option value="0">JHIDE</option>
</field>
<field
name="showall"
type="radio"
label="PLG_CONTENT_PAGEBREAK_SHOW_ALL_LABEL"
description="PLG_CONTENT_PAGEBREAK_SHOW_ALL_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JSHOW</option>
<option value="0">JHIDE</option>
</field>
<field
name="style"
type="list"
label="PLG_CONTENT_PAGEBREAK_STYLE_LABEL"
description="PLG_CONTENT_PAGEBREAK_STYLE_DESC"
default="pages"
>
<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>
content/pagebreak/tmpl/navigation.php000064400000002663147357022240014000
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.pagebreak
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
$lang = JFactory::getLanguage();
?>
<ul>
<li>
<?php if ($links['previous']) :
$direction = $lang->isRtl() ? 'right' : 'left';
$title = htmlspecialchars($this->list[$page]->title, ENT_QUOTES,
'UTF-8');
$ariaLabel = JText::_('JPREVIOUS') . ': ' . $title .
' (' .
JText::sprintf('JLIB_HTML_PAGE_CURRENT_OF_TOTAL', $page, $n) .
')';
?>
<a href="<?php echo $links['previous']; ?>"
title="<?php echo $title; ?>" aria-label="<?php
echo $ariaLabel; ?>" rel="prev">
<?php echo '<span class="icon-chevron-' .
$direction . '" aria-hidden="true"></span>
' . JText::_('JPREV'); ?>
</a>
<?php endif; ?>
</li>
<li>
<?php if ($links['next']) :
$direction = $lang->isRtl() ? 'left' : 'right';
$title = htmlspecialchars($this->list[$page + 2]->title,
ENT_QUOTES, 'UTF-8');
$ariaLabel = JText::_('JNEXT') . ': ' . $title .
' (' .
JText::sprintf('JLIB_HTML_PAGE_CURRENT_OF_TOTAL', ($page + 2),
$n) . ')';
?>
<a href="<?php echo $links['next']; ?>"
title="<?php echo $title; ?>" aria-label="<?php
echo $ariaLabel; ?>" rel="next">
<?php echo JText::_('JNEXT') . ' <span
class="icon-chevron-' . $direction . '"
aria-hidden="true"></span>'; ?>
</a>
<?php endif; ?>
</li>
</ul>
content/pagebreak/tmpl/toc.php000064400000001366147357022240012425
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.pagebreak
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
?>
<div class="pull-right article-index">
<?php if ($headingtext) : ?>
<h3><?php echo $headingtext; ?></h3>
<?php endif; ?>
<ul class="nav nav-tabs nav-stacked">
<?php foreach ($list as $listItem) : ?>
<?php $class = $listItem->liClass ? ' class="' .
$listItem->liClass . '"' : ''; ?>
<li<?php echo $class; ?>>
<a href="<?php echo $listItem->link; ?>"
class="<?php echo $listItem->class; ?>">
<?php echo $listItem->title; ?>
</a>
</li>
<?php endforeach; ?>
</ul>
</div>
content/pagenavigation/pagenavigation.php000064400000016421147357022240014731
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.pagenavigation
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::register('ContentHelperRoute', JPATH_SITE .
'/components/com_content/helpers/route.php');
/**
* Pagenavigation plugin class.
*
* @since 1.5
*/
class PlgContentPagenavigation extends JPlugin
{
/**
* If in the article view and the parameter is enabled shows the page
navigation
*
* @param string $context The context of the content being passed to
the plugin
* @param object &$row The article object
* @param mixed &$params The article params
* @param integer $page The 'page' number
*
* @return mixed void or true
*
* @since 1.6
*/
public function onContentBeforeDisplay($context, &$row, &$params,
$page = 0)
{
$app = JFactory::getApplication();
$view = $app->input->get('view');
$print = $app->input->getBool('print');
if ($print)
{
return false;
}
if ($context === 'com_content.article' && $view ===
'article' &&
$params->get('show_item_navigation'))
{
$db = JFactory::getDbo();
$user = JFactory::getUser();
$lang = JFactory::getLanguage();
$nullDate = $db->getNullDate();
$date = JFactory::getDate();
$now = $date->toSql();
$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 = '';
}
// Get the order code
$orderDate = $params->get('order_date');
$queryDate = $this->getQueryDate($orderDate);
// Determine sort order.
switch ($order_method)
{
case 'date' :
$orderby = $queryDate;
break;
case 'rdate' :
$orderby = $queryDate . ' DESC ';
break;
case 'alpha' :
$orderby = 'a.title';
break;
case 'ralpha' :
$orderby = 'a.title DESC';
break;
case 'hits' :
$orderby = 'a.hits';
break;
case 'rhits' :
$orderby = 'a.hits DESC';
break;
case 'order' :
$orderby = 'a.ordering';
break;
case 'author' :
$orderby = 'a.created_by_alias, u.name';
break;
case 'rauthor' :
$orderby = 'a.created_by_alias DESC, u.name DESC';
break;
case 'front' :
$orderby = 'f.ordering';
break;
default :
$orderby = 'a.ordering';
break;
}
$xwhere = ' AND (a.state = 1 OR a.state = -1)'
. ' AND (publish_up = ' . $db->quote($nullDate) . '
OR publish_up <= ' . $db->quote($now) . ')'
. ' AND (publish_down = ' . $db->quote($nullDate) . '
OR publish_down >= ' . $db->quote($now) . ')';
// Array of articles in same category correctly ordered.
$query = $db->getQuery(true);
// Sqlsrv changes
$case_when = ' CASE WHEN ' .
$query->charLength('a.alias', '!=', '0');
$a_id = $query->castAsChar('a.id');
$case_when .= ' THEN ' . $query->concatenate(array($a_id,
'a.alias'), ':');
$case_when .= ' ELSE ' . $a_id . ' END as slug';
$case_when1 = ' CASE WHEN ' .
$query->charLength('cc.alias', '!=', '0');
$c_id = $query->castAsChar('cc.id');
$case_when1 .= ' THEN ' . $query->concatenate(array($c_id,
'cc.alias'), ':');
$case_when1 .= ' ELSE ' . $c_id . ' END as catslug';
$query->select('a.id, a.title, a.catid, a.language,' .
$case_when . ',' . $case_when1)
->from('#__content AS a')
->join('LEFT', '#__categories AS cc ON cc.id =
a.catid');
if ($order_method === 'author' || $order_method ===
'rauthor')
{
$query->select('a.created_by, u.name');
$query->join('LEFT', '#__users AS u ON u.id =
a.created_by');
}
$query->where(
'a.catid = ' . (int) $row->catid . ' AND a.state =
' . (int) $row->state
. ($canPublish ? '' : ' AND a.access IN (' .
implode(',', JAccess::getAuthorisedViewLevels($user->id)) .
') ') . $xwhere
);
$query->order($orderby);
if ($app->isClient('site') &&
$app->getLanguageFilter())
{
$query->where('a.language in (' .
$db->quote($lang->getTag()) . ',' .
$db->quote('*') . ')');
}
$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 = array();
}
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 postions.
$row->next = $rows[$location + 1];
}
if ($row->prev)
{
$row->prev_label = ($this->params->get('display', 0)
== 0) ? JText::_('JPREV') : $row->prev->title;
$row->prev =
JRoute::_(ContentHelperRoute::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) ? JText::_('JNEXT') : $row->next->title;
$row->next =
JRoute::_(ContentHelperRoute::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 = JPluginHelper::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);
}
}
}
/**
* Translate an order code to a field for primary ordering.
*
* @param string $orderDate The ordering code.
*
* @return string The SQL field(s) to order by.
*
* @since 3.3
*/
private static function getQueryDate($orderDate)
{
$db = JFactory::getDbo();
switch ($orderDate)
{
// Use created if modified is not set
case 'modified' :
$queryDate = ' CASE WHEN a.modified = ' .
$db->quote($db->getNullDate()) . ' THEN a.created ELSE
a.modified END';
break;
// Use created if publish_up is not set
case 'published' :
$queryDate = ' CASE WHEN a.publish_up = ' .
$db->quote($db->getNullDate()) . ' THEN a.created ELSE
a.publish_up END ';
break;
// Use created as default
case 'created' :
default :
$queryDate = ' a.created ';
break;
}
return $queryDate;
}
}
content/pagenavigation/pagenavigation.xml000064400000003742147357022240014744
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
<name>plg_content_pagenavigation</name>
<author>Joomla! Project</author>
<creationDate>January 2006</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>
<files>
<filename
plugin="pagenavigation">pagenavigation.php</filename>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_pagenavigation.ini</language>
<language
tag="en-GB">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"
description="PLG_PAGENAVIGATION_FIELD_POSITION_DESC"
default="1"
filter="integer"
>
<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"
description="PLG_PAGENAVIGATION_FIELD_RELATIVE_DESC"
default="1"
filter="integer"
>
<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"
description="PLG_PAGENAVIGATION_FIELD_DISPLAY_DESC"
default="0"
filter="integer"
>
<option
value="0">PLG_PAGENAVIGATION_FIELD_VALUE_NEXTPREV</option>
<option
value="1">PLG_PAGENAVIGATION_FIELD_VALUE_TITLE</option>
</field>
</fieldset>
</fields>
</config>
</extension>
content/pagenavigation/tmpl/default.php000064400000002577147357022240014344
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.pagenavigation
*
* @copyright (C) 2013 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JHtml::_('bootstrap.tooltip');
$lang = JFactory::getLanguage();
?>
<ul class="pager pagenav">
<?php if ($row->prev) :
$direction = $lang->isRtl() ? 'right' : 'left';
?>
<li class="previous">
<a class="hasTooltip" title="<?php echo
htmlspecialchars($rows[$location-1]->title); ?>"
aria-label="<?php echo JText::sprintf('JPREVIOUS_TITLE',
htmlspecialchars($rows[$location-1]->title)); ?>"
href="<?php echo $row->prev; ?>"
rel="prev">
<?php echo '<span class="icon-chevron-' .
$direction . '" aria-hidden="true"></span>
<span aria-hidden="true">' . $row->prev_label .
'</span>'; ?>
</a>
</li>
<?php endif; ?>
<?php if ($row->next) :
$direction = $lang->isRtl() ? 'left' : 'right';
?>
<li class="next">
<a class="hasTooltip" title="<?php echo
htmlspecialchars($rows[$location+1]->title); ?>"
aria-label="<?php echo JText::sprintf('JNEXT_TITLE',
htmlspecialchars($rows[$location+1]->title)); ?>"
href="<?php echo $row->next; ?>"
rel="next">
<?php echo '<span aria-hidden="true">' .
$row->next_label . '</span> <span
class="icon-chevron-' . $direction . '"
aria-hidden="true"></span>'; ?>
</a>
</li>
<?php endif; ?>
</ul>
content/vote/tmpl/rating.php000064400000003167147357022240012161
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.vote
*
* @copyright (C) 2016 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* 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;
}
$rating = (int) $row->rating;
$rcount = (int) $row->rating_count;
// Look for images in template if available
$starImageOn = JHtml::_('image',
'system/rating_star.png',
JText::_('PLG_VOTE_STAR_ACTIVE'), null, true);
$starImageOff = JHtml::_('image',
'system/rating_star_blank.png',
JText::_('PLG_VOTE_STAR_INACTIVE'), null, true);
$img = '';
for ($i = 0; $i < $rating; $i++)
{
$img .= $starImageOn;
}
for ($i = $rating; $i < 5; $i++)
{
$img .= $starImageOff;
}
?>
<div class="content_rating">
<?php if ($rcount) : ?>
<p class="unseen element-invisible"
itemprop="aggregateRating" itemscope
itemtype="https://schema.org/AggregateRating">
<?php echo JText::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>
<?php endif; ?>
<?php echo $img; ?>
</div>
content/vote/tmpl/vote.php000064400000003257147357022240011652
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.vote
*
* @copyright (C) 2016 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* 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 JUri::getInstance();
$uri->setVar('hitcount', '0');
// Create option list for voting select box
$options = array();
for ($i = 1; $i < 6; $i++)
{
$options[] = JHtml::_('select.option', $i,
JText::sprintf('PLG_VOTE_VOTE', $i));
}
?>
<form method="post" action="<?php echo
htmlspecialchars($uri->toString(), ENT_COMPAT, 'UTF-8');
?>" class="form-inline">
<span class="content_vote">
<label class="unseen element-invisible"
for="content_vote_<?php echo (int) $row->id;
?>"><?php echo JText::_('PLG_VOTE_LABEL');
?></label>
<?php echo JHtml::_('select.genericlist', $options,
'user_rating', null, 'value', 'text',
'5', 'content_vote_' . (int) $row->id); ?>
 <input class="btn btn-mini"
type="submit" name="submit_vote" value="<?php
echo JText::_('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 JHtml::_('form.token'); ?>
</span>
</form>
content/vote/vote.php000064400000007152147357022240010674 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Content.vote
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Vote plugin.
*
* @since 1.5
*/
class PlgContentVote extends JPlugin
{
/**
* Application object
*
* @var JApplicationCms
* @since 3.7.0
*/
protected $app;
/**
* The position the voting data is displayed in relative to the article.
*
* @var string
* @since 3.7.0
*/
protected $votingPosition;
/**
* Constructor.
*
* @param object &$subject The object to observe
* @param array $config An optional associative array of
configuration settings.
*
* @since 3.7.0
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
$this->votingPosition = $this->params->get('position',
'top');
}
/**
* 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->votingPosition !== '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->votingPosition !== 'bottom')
{
return '';
}
return $this->displayVotingData($context, $row, $params, $page);
}
/**
* Displays the voting area
*
* @param string $context The context of the content being passed to
the plugin
* @param object &$row The article object
* @param object &$params The article params
* @param integer $page The 'page' number
*
* @return string|boolean HTML string containing code for the votes if
in com_content else boolean false
*
* @since 3.7.0
*/
private function displayVotingData($context, &$row, &$params,
$page)
{
$parts = explode('.', $context);
if ($parts[0] !== 'com_content')
{
return false;
}
if (empty($params) || !$params->get('show_vote', null))
{
return '';
}
// Load plugin language files only when needed (ex: they are not needed
if show_vote is not active).
$this->loadLanguage();
// Get the path for the rating summary layout file
$path = JPluginHelper::getLayoutPath('content',
'vote', 'rating');
// Render the layout
ob_start();
include $path;
$html = ob_get_clean();
if ($this->app->input->getString('view', '')
=== 'article' && $row->state == 1)
{
// Get the path for the voting form layout file
$path = JPluginHelper::getLayoutPath('content',
'vote', 'vote');
// Render the layout
ob_start();
include $path;
$html .= ob_get_clean();
}
return $html;
}
}
content/vote/vote.xml000064400000002176147357022240010706 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
<name>plg_content_vote</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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>
<files>
<filename plugin="vote">vote.php</filename>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_content_vote.ini</language>
<language
tag="en-GB">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"
description="PLG_VOTE_POSITION_DESC"
default="top"
>
<option value="top">PLG_VOTE_TOP</option>
<option value="bottom">PLG_VOTE_BOTTOM</option>
</field>
</fieldset>
</fields>
</config>
</extension>
editors/codemirror/codemirror.php000064400000024473147357022240013260
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.codemirror
*
* @copyright (C) 2009 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
// No direct access
defined('_JEXEC') or die;
/**
* CodeMirror Editor Plugin.
*
* @since 1.6
*/
class PlgEditorCodemirror extends JPlugin
{
/**
* Affects constructor behavior. If true, language files will be loaded
automatically.
*
* @var boolean
* @since 3.1.4
*/
protected $autoloadLanguage = true;
/**
* Mapping of syntax to CodeMirror modes.
*
* @var array
*/
protected $modeAlias = array();
/**
* Initialises the Editor.
*
* @return void
*/
public function onInit()
{
static $done = false;
// Do this only once.
if ($done)
{
return;
}
$done = true;
// Most likely need this later
$doc = JFactory::getDocument();
// Codemirror shall have its own group of plugins to modify and extend
its behavior
JPluginHelper::importPlugin('editors_codemirror');
$dispatcher = JEventDispatcher::getInstance();
// At this point, params can be modified by a plugin before going to the
layout renderer.
$dispatcher->trigger('onCodeMirrorBeforeInit',
array(&$this->params));
$displayData = (object) array('params' =>
$this->params);
// We need to do output buffering here because layouts may actually
'echo' things which we do not want.
ob_start();
JLayoutHelper::render('editors.codemirror.init', $displayData,
__DIR__ . '/layouts');
ob_end_clean();
$font = $this->params->get('fontFamily', '0');
$fontInfo = $this->getFontInfo($font);
if (isset($fontInfo))
{
if (isset($fontInfo->url))
{
$doc->addStyleSheet($fontInfo->url);
}
if (isset($fontInfo->css))
{
$displayData->fontFamily = $fontInfo->css .
'!important';
}
}
// We need to do output buffering here because layouts may actually
'echo' things which we do not want.
ob_start();
JLayoutHelper::render('editors.codemirror.styles',
$displayData, __DIR__ . '/layouts');
ob_end_clean();
$dispatcher->trigger('onCodeMirrorAfterInit',
array(&$this->params));
}
/**
* Copy editor content to form field.
*
* @param string $id The id of the editor field.
*
* @return string Javascript
*
* @deprecated 4.0 Code executes directly on submit
*/
public function onSave($id)
{
return sprintf('document.getElementById(%1$s).value =
Joomla.editors.instances[%1$s].getValue();', json_encode((string)
$id));
}
/**
* Get the editor content.
*
* @param string $id The id of the editor field.
*
* @return string Javascript
*
* @deprecated 4.0 Use directly the returned code
*/
public function onGetContent($id)
{
return sprintf('Joomla.editors.instances[%1$s].getValue();',
json_encode((string) $id));
}
/**
* Set the editor content.
*
* @param string $id The id of the editor field.
* @param string $content The content to set.
*
* @return string Javascript
*
* @deprecated 4.0 Use directly the returned code
*/
public function onSetContent($id, $content)
{
return
sprintf('Joomla.editors.instances[%1$s].setValue(%2$s);',
json_encode((string) $id), json_encode((string) $content));
}
/**
* Adds the editor specific insert method.
*
* @return void
*
* @deprecated 4.0 Code is loaded in the init script
*/
public function onGetInsertMethod()
{
static $done = false;
// Do this only once.
if ($done)
{
return true;
}
$done = true;
JFactory::getDocument()->addScriptDeclaration("
;function jInsertEditorText(text, editor) {
Joomla.editors.instances[editor].replaceSelection(text); }
");
return true;
}
/**
* Display the editor area.
*
* @param string $name The control name.
* @param string $content The contents of the text area.
* @param string $width The width of the text area (px or %).
* @param string $height The height of the text area (px or %).
* @param int $col The number of columns for the textarea.
* @param int $row The number of rows for the textarea.
* @param boolean $buttons True and the editor buttons will be
displayed.
* @param string $id An optional ID for the textarea (note:
since 1.6). If not supplied the name is used.
* @param string $asset Not used.
* @param object $author Not used.
* @param array $params Associative array of editor parameters.
*
* @return string HTML
*/
public function onDisplay(
$name, $content, $width, $height, $col, $row, $buttons = true, $id =
null, $asset = null, $author = null, $params = array())
{
// True if a CodeMirror already has autofocus. Prevent multiple
autofocuses.
static $autofocused;
$id = empty($id) ? $name : $id;
// Must pass the field id to the buttons in this editor.
$buttons = $this->displayButtons($id, $buttons, $asset, $author);
// Only add "px" to width and height if they are not given as a
percentage.
$width .= is_numeric($width) ? 'px' : '';
$height .= is_numeric($height) ? 'px' : '';
// Options for the CodeMirror constructor.
$options = new stdClass;
// Is field readonly?
if (!empty($params['readonly']))
{
$options->readOnly = 'nocursor';
}
// Should we focus on the editor on load?
if (!$autofocused)
{
$options->autofocus = isset($params['autofocus']) ? (bool)
$params['autofocus'] : false;
$autofocused = $options->autofocus;
}
$options->lineWrapping = (boolean)
$this->params->get('lineWrapping', 1);
// Add styling to the active line.
$options->styleActiveLine = (boolean)
$this->params->get('activeLine', 1);
// Do we highlight selection matches?
if ($this->params->get('selectionMatches', 1))
{
$options->highlightSelectionMatches = array(
'showToken' => true,
'annotateScrollbar' => true,
);
}
// Do we use line numbering?
if ($options->lineNumbers = (boolean)
$this->params->get('lineNumbers', 1))
{
$options->gutters[] = 'CodeMirror-linenumbers';
}
// Do we use code folding?
if ($options->foldGutter = (boolean)
$this->params->get('codeFolding', 1))
{
$options->gutters[] = 'CodeMirror-foldgutter';
}
// Do we use a marker gutter?
if ($options->markerGutter = (boolean)
$this->params->get('markerGutter',
$this->params->get('marker-gutter', 1)))
{
$options->gutters[] = 'CodeMirror-markergutter';
}
// Load the syntax mode.
$syntax = !empty($params['syntax'])
? $params['syntax']
: $this->params->get('syntax', 'html');
$options->mode = isset($this->modeAlias[$syntax]) ?
$this->modeAlias[$syntax] : $syntax;
// Load the theme if specified.
if ($theme = $this->params->get('theme'))
{
$options->theme = $theme;
JHtml::_('stylesheet',
$this->params->get('basePath',
'media/editors/codemirror/') . 'theme/' . $theme .
'.css', array('version' => 'auto'));
}
// Special options for tagged modes (xml/html).
if (in_array($options->mode, array('xml', 'html',
'php')))
{
// Autogenerate closing tags (html/xml only).
$options->autoCloseTags = (boolean)
$this->params->get('autoCloseTags', 1);
// Highlight the matching tag when the cursor is in a tag (html/xml
only).
$options->matchTags = (boolean)
$this->params->get('matchTags', 1);
}
// Special options for non-tagged modes.
if (!in_array($options->mode, array('xml',
'html')))
{
// Autogenerate closing brackets.
$options->autoCloseBrackets = (boolean)
$this->params->get('autoCloseBrackets', 1);
// Highlight the matching bracket.
$options->matchBrackets = (boolean)
$this->params->get('matchBrackets', 1);
}
$options->scrollbarStyle =
$this->params->get('scrollbarStyle', 'native');
// KeyMap settings.
$options->keyMap = $this->params->get('keyMap',
false);
// Support for older settings.
if ($options->keyMap === false)
{
$options->keyMap =
$this->params->get('vimKeyBinding', 0) ? 'vim' :
'default';
}
if ($options->keyMap && $options->keyMap !=
'default')
{
$this->loadKeyMap($options->keyMap);
}
$displayData = (object) array(
'options' => $options,
'params' => $this->params,
'name' => $name,
'id' => $id,
'cols' => $col,
'rows' => $row,
'content' => $content,
'buttons' => $buttons
);
$dispatcher = JEventDispatcher::getInstance();
// At this point, displayData can be modified by a plugin before going to
the layout renderer.
$results = $dispatcher->trigger('onCodeMirrorBeforeDisplay',
array(&$displayData));
$results[] =
JLayoutHelper::render('editors.codemirror.element', $displayData,
__DIR__ . '/layouts', array('debug' => JDEBUG));
foreach ($dispatcher->trigger('onCodeMirrorAfterDisplay',
array(&$displayData)) as $result)
{
$results[] = $result;
}
return implode("\n", $results);
}
/**
* Displays the editor buttons.
*
* @param string $name Button name.
* @param mixed $buttons [array with button objects | boolean true to
display buttons]
* @param mixed $asset Unused.
* @param mixed $author Unused.
*
* @return string HTML
*/
protected function displayButtons($name, $buttons, $asset, $author)
{
$return = '';
$args = array(
'name' => $name,
'event' => 'onGetInsertMethod'
);
$results = (array) $this->update($args);
if ($results)
{
foreach ($results as $result)
{
if (is_string($result) && trim($result))
{
$return .= $result;
}
}
}
if (is_array($buttons) || (is_bool($buttons) && $buttons))
{
$buttons = $this->_subject->getButtons($name, $buttons, $asset,
$author);
$return .= JLayoutHelper::render('joomla.editors.buttons',
$buttons);
}
return $return;
}
/**
* Gets font info from the json data file
*
* @param string $font A key from the $fonts array.
*
* @return object
*/
protected function getFontInfo($font)
{
static $fonts;
if (!$fonts)
{
$fonts = json_decode(file_get_contents(__DIR__ .
'/fonts.json'), true);
}
return isset($fonts[$font]) ? (object) $fonts[$font] : null;
}
/**
* Loads a keyMap file
*
* @param string $keyMap The name of a keyMap file to load.
*
* @return void
*/
protected function loadKeyMap($keyMap)
{
$basePath = $this->params->get('basePath',
'media/editors/codemirror/');
$ext = JDEBUG ? '.js' : '.min.js';
JHtml::_('script', $basePath . 'keymap/' . $keyMap .
$ext, array('version' => 'auto'));
}
}
editors/codemirror/codemirror.xml000064400000024674147357022240013274
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.2" type="plugin"
group="editors" method="upgrade">
<name>plg_editors_codemirror</name>
<version>5.60.0</version>
<creationDate>28 March 2011</creationDate>
<author>Marijn Haverbeke</author>
<authorEmail>marijnh@gmail.com</authorEmail>
<authorUrl>https://codemirror.net/</authorUrl>
<copyright>Copyright (C) 2014 - 2021 by Marijn Haverbeke
<marijnh@gmail.com> and others</copyright>
<license>MIT license: https://codemirror.net/LICENSE</license>
<description>PLG_CODEMIRROR_XML_DESCRIPTION</description>
<files>
<filename
plugin="codemirror">codemirror.php</filename>
<filename>styles.css</filename>
<filename>styles.min.css</filename>
<filename>fonts.json</filename>
<filename>fonts.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors_codemirror.ini</language>
<language
tag="en-GB">en-GB.plg_editors_codemirror.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="lineNumbers"
type="radio"
label="PLG_CODEMIRROR_FIELD_LINENUMBERS_LABEL"
description="PLG_CODEMIRROR_FIELD_LINENUMBERS_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="codeFolding"
type="radio"
label="PLG_CODEMIRROR_FIELD_CODEFOLDING_LABEL"
description="PLG_CODEMIRROR_FIELD_CODEFOLDING_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="markerGutter"
type="radio"
label="PLG_CODEMIRROR_FIELD_MARKERGUTTER_LABEL"
description="PLG_CODEMIRROR_FIELD_MARKERGUTTER_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="lineWrapping"
type="radio"
label="PLG_CODEMIRROR_FIELD_LINEWRAPPING_LABEL"
description="PLG_CODEMIRROR_FIELD_LINEWRAPPING_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="activeLine"
type="radio"
label="PLG_CODEMIRROR_FIELD_ACTIVELINE_LABEL"
description="PLG_CODEMIRROR_FIELD_ACTIVELINE_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="selectionMatches"
type="radio"
label="PLG_CODEMIRROR_FIELD_SELECTIONMATCHES_LABEL"
description="PLG_CODEMIRROR_FIELD_SELECTIONMATCHES_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="matchTags"
type="radio"
label="PLG_CODEMIRROR_FIELD_MATCHTAGS_LABEL"
description="PLG_CODEMIRROR_FIELD_MATCHTAGS_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="matchBrackets"
type="radio"
label="PLG_CODEMIRROR_FIELD_MATCHBRACKETS_LABEL"
description="PLG_CODEMIRROR_FIELD_MATCHBRACKETS_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="autoCloseTags"
type="radio"
label="PLG_CODEMIRROR_FIELD_AUTOCLOSETAGS_LABEL"
description="PLG_CODEMIRROR_FIELD_AUTOCLOSETAGS_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="autoCloseBrackets"
type="radio"
label="PLG_CODEMIRROR_FIELD_AUTOCLOSEBRACKET_LABEL"
description="PLG_CODEMIRROR_FIELD_AUTOCLOSEBRACKET_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="keyMap"
type="list"
label="PLG_CODEMIRROR_FIELD_KEYMAP_LABEL"
description="PLG_CODEMIRROR_FIELD_KEYMAP_DESC"
default=""
>
<option value="">JDEFAULT</option>
<option
value="emacs">PLG_CODEMIRROR_FIELD_KEYMAP_EMACS</option>
<option
value="sublime">PLG_CODEMIRROR_FIELD_KEYMAP_SUBLIME</option>
<option
value="vim">PLG_CODEMIRROR_FIELD_KEYMAP_VIM</option>
</field>
<field
name="fullScreen"
type="list"
label="PLG_CODEMIRROR_FIELD_FULLSCREEN_LABEL"
description="PLG_CODEMIRROR_FIELD_FULLSCREEN_DESC"
default="F10"
>
<option value="F1">F1</option>
<option value="F2">F2</option>
<option value="F3">F3</option>
<option value="F4">F4</option>
<option value="F5">F5</option>
<option value="F6">F6</option>
<option value="F7">F7</option>
<option value="F8">F8</option>
<option value="F9">F9</option>
<option value="F10">F10</option>
<option value="F11">F11</option>
<option value="F12">F12</option>
</field>
<field
name="fullScreenMod"
type="checkboxes"
label="PLG_CODEMIRROR_FIELD_FULLSCREEN_MOD_LABEL"
description="PLG_CODEMIRROR_FIELD_FULLSCREEN_MOD_DESC"
>
<option
value="Shift">PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_SHIFT</option>
<option
value="Cmd">PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_CMD</option>
<option
value="Ctrl">PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_CTRL</option>
<option
value="Alt">PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_ALT</option>
</field>
<field
name="basePath"
type="hidden"
default="media/editors/codemirror/"
/>
<field
name="modePath"
type="hidden"
default="media/editors/codemirror/mode/%N/%N"
/>
</fieldset>
<fieldset name="appearance"
label="PLG_CODEMIRROR_FIELDSET_APPEARANCE_OPTIONS_LABEL"
addfieldpath="plugins/editors/codemirror">
<field
name="theme"
type="filelist"
label="PLG_CODEMIRROR_FIELD_THEME_LABEL"
description="PLG_CODEMIRROR_FIELD_THEME_DESC"
default=""
filter="\.css$"
stripext="true"
hide_none="true"
hide_default="false"
directory="media/editors/codemirror/theme"
/>
<field
name="activeLineColor"
type="color"
label="PLG_CODEMIRROR_FIELD_ACTIVELINE_COLOR_LABEL"
description="PLG_CODEMIRROR_FIELD_ACTIVELINE_COLOR_DESC"
default="#a4c2eb"
filter="color"
/>
<field
name="highlightMatchColor"
type="color"
label="PLG_CODEMIRROR_FIELD_HIGHLIGHT_MATCH_COLOR_LABEL"
description="PLG_CODEMIRROR_FIELD_HIGHLIGHT_MATCH_COLOR_DESC"
default="#fa542f"
filter="color"
/>
<field
name="fontFamily"
type="fonts"
label="PLG_CODEMIRROR_FIELD_FONT_FAMILY_LABEL"
description="PLG_CODEMIRROR_FIELD_FONT_FAMILY_DESC"
default="0"
>
<option
value="0">PLG_CODEMIRROR_FIELD_VALUE_FONT_FAMILY_DEFAULT</option>
</field>
<field
name="fontSize"
type="integer"
label="PLG_CODEMIRROR_FIELD_FONT_SIZE_LABEL"
description="PLG_CODEMIRROR_FIELD_FONT_SIZE_DESC"
first="6"
last="16"
step="1"
default="13"
filter="integer"
/>
<field
name="lineHeight"
type="list"
label="PLG_CODEMIRROR_FIELD_LINE_HEIGHT_LABEL"
description="PLG_CODEMIRROR_FIELD_LINE_HEIGHT_DESC"
default="1.2"
filter="float"
>
<option value="1">1</option>
<option value="1.1">1.1</option>
<option value="1.2">1.2</option>
<option value="1.3">1.3</option>
<option value="1.4">1.4</option>
<option value="1.5">1.5</option>
<option value="1.6">1.6</option>
<option value="1.7">1.7</option>
<option value="1.8">1.8</option>
<option value="1.9">1.9</option>
<option value="2">2</option>
</field>
<field
name="scrollbarStyle"
type="radio"
label="PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_LABEL"
description="PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_DESC"
class="btn-group btn-group-yesno"
default="native"
>
<option
value="native">PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_DEFAULT</option>
<option
value="simple">PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_SIMPLE</option>
<option
value="overlay">PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_OVERLAY</option>
</field>
<field
name="preview"
type="editor"
label="PLG_CODEMIRROR_FIELD_PREVIEW_LABEL"
description="PLG_CODEMIRROR_FIELD_PREVIEW_DESC"
editor="codemirror"
filter="unset"
buttons="false"
>
<default>
<![CDATA[
<script type="text/javascript">
jQuery(function ($) {
$('.hello').html('Hello World');
});
</script>
<style type="text/css">
h1 {
background-clip: border-box;
background-color: #cacaff;
background-image: linear-gradient(45deg, transparent 0px, transparent
30px, #ababff 30px, #ababff 60px, transparent 60px);
background-repeat: repeat-x;
background-size: 90px 100%;
border: 1px solid #8989ff;
border-radius: 10px;
color: #333;
padding: 0 15px;
}
</style>
<div>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam
a ornare lectus, quis semper urna. Vestibulum ante ipsum primis in faucibus
orci luctus et ultrices posuere cubilia Curae; Vivamus interdum metus id
elit rutrum sollicitudin. Pellentesque habitant morbi tristique senectus et
netus et malesuada fames ac turpis egestas. Aliquam in fermentum risus, id
facilisis nulla. Phasellus gravida erat sed ullamcorper accumsan. Donec
blandit sem eget sem congue, a varius sapien semper.</p>
<p>Integer euismod tempor convallis. Nullam porttitor et ex ac
fringilla. Quisque facilisis est ac erat condimentum malesuada. Aenean
commodo quam odio, tincidunt ultricies mauris suscipit et.</p>
<ul>
<li>Vivamus ultrices ligula a odio lacinia pellentesque.</li>
<li>Curabitur iaculis arcu pharetra, mollis turpis id, commodo
erat.</li>
<li>Etiam consequat enim quis faucibus interdum.</li>
<li>Morbi in ipsum pulvinar, eleifend lorem sit amet, euismod
magna.</li>
<li>Donec consectetur lacus vitae eros euismod porta.</li>
</ul>
</div>
]]>
</default>
</field>
</fieldset>
</fields>
</config>
</extension>
editors/codemirror/fonts.json000064400000006055147357022240012422 0ustar00{
"anonymous_pro": {
"name": "Anonymous Pro",
"url":
"https://fonts.googleapis.com/css?family=Anonymous+Pro",
"css": "'Anonymous Pro', monospace"
},
"cousine": {
"name": "Cousine",
"url":
"https://fonts.googleapis.com/css?family=Cousine",
"css": "Cousine, monospace"
},
"cutive_mono": {
"name": "Cutive Mono",
"url":
"https://fonts.googleapis.com/css?family=Cutive+Mono",
"css": "'Cutive Mono', monospace"
},
"droid_sans_mono": {
"name": "Droid Sans Mono",
"url":
"https://fonts.googleapis.com/css?family=Droid+Sans+Mono",
"css": "'Droid Sans Mono', monospace"
},
"fira_mono": {
"name": "Fira Mono",
"url":
"https://fonts.googleapis.com/css?family=Fira+Mono",
"css": "'Fira Mono', monospace"
},
"ibm_plex_mono": {
"name": "IBM Plex Mono",
"url":
"https://fonts.googleapis.com/css?family=IBM+Plex+Mono",
"css": "'IBM Plex Mono', monospace;"
},
"inconsolata": {
"name": "Inconsolata",
"url":
"https://fonts.googleapis.com/css?family=Inconsolata",
"css": "Inconsolata, monospace"
},
"lekton": {
"name": "Lekton",
"url":
"https://fonts.googleapis.com/css?family=Lekton",
"css": "Lekton, monospace"
},
"nanum_gothic_coding": {
"name": "Nanum Gothic Coding",
"url":
"https://fonts.googleapis.com/css?family=Nanum+Gothic+Coding",
"css": "'Nanum Gothic Coding', monospace"
},
"nova_mono": {
"name": "Nova Mono",
"url":
"https://fonts.googleapis.com/css?family=Nova+Mono",
"css": "'Nova Mono', monospace"
},
"overpass_mono": {
"name": "Overpass Mono",
"url":
"https://fonts.googleapis.com/css?family=Overpass+Mono",
"css": "'Overpass Mono', monospace"
},
"oxygen_mono": {
"name": "Oxygen Mono",
"url":
"https://fonts.googleapis.com/css?family=Oxygen+Mono",
"css": "'Oxygen Mono', monospace"
},
"press_start_2p": {
"name": "Press Start 2P",
"url":
"https://fonts.googleapis.com/css?family=Press+Start+2P",
"css": "'Press Start 2P', monospace"
},
"pt_mono": {
"name": "PT Mono",
"url":
"https://fonts.googleapis.com/css?family=PT+Mono",
"css": "'PT Mono', monospace"
},
"roboto_mono": {
"name": "Roboto Mono",
"url":
"https://fonts.googleapis.com/css?family=Roboto+Mono",
"css": "'Roboto Mono', monospace"
},
"rubik_mono_one": {
"name": "Rubik Mono One",
"url":
"https://fonts.googleapis.com/css?family=Rubik+Mono+One",
"css": "'Rubik Mono One', monospace"
},
"share_tech_mono": {
"name": "Share Tech Mono",
"url":
"https://fonts.googleapis.com/css?family=Share+Tech+Mono",
"css": "'Share Tech Mono', monospace"
},
"source_code_pro": {
"name": "Source Code Pro",
"url":
"https://fonts.googleapis.com/css?family=Source+Code+Pro",
"css": "'Source Code Pro', monospace"
},
"space_mono": {
"name": "Space Mono",
"url":
"https://fonts.googleapis.com/css?family=Space+Mono",
"css": "'Space Mono', monospace"
},
"ubuntu_mono": {
"name": "Ubuntu Mono",
"url":
"https://fonts.googleapis.com/css?family=Ubuntu+Mono",
"css": "'Ubuntu Mono', monospace"
},
"vt323": {
"name": "VT323",
"url":
"https://fonts.googleapis.com/css?family=VT323",
"css": "'VT323', monospace"
}
}
editors/codemirror/fonts.php000064400000002104147357022240012227
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.codemirror
*
* @copyright (C) 2014 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
// No direct access
defined('_JEXEC') or die;
JFormHelper::loadFieldClass('list');
/**
* Supports an HTML select list of fonts
*
* @package Joomla.Plugin
* @subpackage Editors.codemirror
* @since 3.4
*/
class JFormFieldFonts extends JFormFieldList
{
/**
* The form field type.
*
* @var string
* @since 3.4
*/
protected $type = 'Fonts';
/**
* Method to get the list of fonts field options.
*
* @return array The field option objects.
*
* @since 3.4
*/
protected function getOptions()
{
$fonts = json_decode(file_get_contents(__DIR__ .
'/fonts.json'));
$options = array();
foreach ($fonts as $key => $info)
{
$options[] = JHtml::_('select.option', $key, $info->name);
}
// Merge any additional options in the XML definition.
return array_merge(parent::getOptions(), $options);
}
}
editors/codemirror/layouts/editors/codemirror/element.php000064400000002052147357022240020047
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.codemirror
*
* @copyright (C) 2015 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
// No direct access
defined('_JEXEC') or die;
$options = $displayData->options;
$params = $displayData->params;
$name = $displayData->name;
$id = $displayData->id;
$cols = $displayData->cols;
$rows = $displayData->rows;
$content = $displayData->content;
$buttons = $displayData->buttons;
$modifier = $params->get('fullScreenMod', array()) ?
implode(' + ', $params->get('fullScreenMod',
array())) . ' + ' : '';
?>
<p class="label">
<?php echo
JText::sprintf('PLG_CODEMIRROR_TOGGLE_FULL_SCREEN', $modifier,
$params->get('fullScreen', 'F10')); ?>
</p>
<?php
echo '<textarea class="codemirror-source"
name="', $name,
'" id="', $id,
'" cols="', $cols,
'" rows="', $rows,
'" data-options="',
htmlspecialchars(json_encode($options)),
'">', $content, '</textarea>';
?>
<?php echo $buttons; ?>
editors/codemirror/layouts/editors/codemirror/init.php000064400000007243147357022240017370
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.codemirror
*
* @copyright (C) 2015 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
// No direct access
defined('_JEXEC') or die;
$params = $displayData->params;
$basePath = $params->get('basePath',
'media/editors/codemirror/');
$modePath = $params->get('modePath',
'media/editors/codemirror/mode/%N/%N');
$extJS = JDEBUG ? '.js' : '.min.js';
$extCSS = JDEBUG ? '.css' : '.min.css';
JHtml::_('script', $basePath . 'lib/codemirror' .
$extJS, array('version' => 'auto'));
JHtml::_('script', $basePath . 'lib/addons' . $extJS,
array('version' => 'auto'));
JHtml::_('stylesheet', $basePath . 'lib/codemirror' .
$extCSS, array('version' => 'auto'));
JHtml::_('stylesheet', $basePath . 'lib/addons' .
$extCSS, array('version' => 'auto'));
$fskeys = $params->get('fullScreenMod', array());
$fskeys[] = $params->get('fullScreen',
'F10');
$fullScreenCombo = implode('-', $fskeys);
$fsCombo = json_encode($fullScreenCombo);
$modPath = json_encode(JUri::root(true) . '/' . $modePath
. $extJS);
JFactory::getDocument()->addScriptDeclaration(
<<<JS
;(function (cm, $) {
cm.commands.toggleFullScreen = function (cm) {
cm.setOption('fullScreen',
!cm.getOption('fullScreen'));
};
cm.commands.closeFullScreen = function (cm) {
cm.getOption('fullScreen') &&
cm.setOption('fullScreen', false);
};
cm.keyMap.default['Ctrl-Q'] = 'toggleFullScreen';
cm.keyMap.default[$fsCombo] = 'toggleFullScreen';
cm.keyMap.default['Esc'] = 'closeFullScreen';
// For mode autoloading.
cm.modeURL = $modPath;
// Fire this function any time an editor is created.
cm.defineInitHook(function (editor)
{
// Try to set up the mode
var mode = cm.findModeByMIME(editor.options.mode || '') ||
cm.findModeByName(editor.options.mode || '') ||
cm.findModeByExtension(editor.options.mode || '');
cm.autoLoadMode(editor, mode ? mode.mode : editor.options.mode);
if (mode && mode.mime)
{
editor.setOption('mode', mode.mime);
}
// Handle gutter clicks (place or remove a marker).
editor.on('gutterClick', function (ed, n, gutter) {
if (gutter != 'CodeMirror-markergutter') { return; }
var info = ed.lineInfo(n),
hasMarker = !!info.gutterMarkers &&
!!info.gutterMarkers['CodeMirror-markergutter'];
ed.setGutterMarker(n, 'CodeMirror-markergutter', hasMarker ?
null : makeMarker());
});
// jQuery's ready function.
$(function () {
// Some browsers do something weird with the fieldset which
doesn't work well with CodeMirror. Fix it.
$(editor.getWrapperElement()).parent('fieldset').css('min-width',
0);
// Listen for Bootstrap's 'shown' event. If this editor
was in a hidden element when created, it may need to be refreshed.
$(document.body).on('shown shown.bs.tab shown.bs.modal',
function () { editor.refresh(); });
});
});
function makeMarker()
{
var marker = document.createElement('div');
marker.className = 'CodeMirror-markergutter-mark';
return marker;
}
// Initialize any CodeMirrors on page load and when a subform is added
$(function ($) {
initCodeMirror();
$('body').on('subform-row-add', initCodeMirror);
});
function initCodeMirror(event, container)
{
container = container || document;
$(container).find('textarea.codemirror-source').each(function
() {
var input = $(this).removeClass('codemirror-source');
var id = input.prop('id');
Joomla.editors.instances[id] = cm.fromTextArea(this,
input.data('options'));
});
}
}(CodeMirror, jQuery));
JS
);
editors/codemirror/layouts/editors/codemirror/styles.php000064400000004502147357022240017743
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.codemirror
*
* @copyright (C) 2015 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
// No direct access
defined('_JEXEC') or die;
$params = $displayData->params;
$fontFamily = isset($displayData->fontFamily) ?
$displayData->fontFamily : 'monospace';
$fontSize = $params->get('fontSize', 13) . 'px;';
$lineHeight = $params->get('lineHeight', 1.2) .
'em;';
// Set the active line color.
$color = $params->get('activeLineColor',
'#a4c2eb');
$r = hexdec($color[1] . $color[2]);
$g = hexdec($color[3] . $color[4]);
$b = hexdec($color[5] . $color[6]);
$activeLineColor = 'rgba(' . $r . ', ' . $g . ',
' . $b . ', .5)';
// Set the color for matched tags.
$color = $params->get('highlightMatchColor',
'#fa542f');
$r = hexdec($color[1] . $color[2]);
$g = hexdec($color[3] . $color[4]);
$b = hexdec($color[5] . $color[6]);
$highlightMatchColor = 'rgba(' . $r . ', ' . $g .
', ' . $b . ', .5)';
JFactory::getDocument()->addStyleDeclaration(
<<<CSS
.CodeMirror
{
font-family: $fontFamily;
font-size: $fontSize;
line-height: $lineHeight;
border: 1px solid #ccc;
}
/* In order to hid the Joomla menu */
.CodeMirror-fullscreen
{
z-index: 1040;
}
/* Make the fold marker a little more visible/nice */
.CodeMirror-foldmarker
{
background: rgb(255, 128, 0);
background: rgba(255, 128, 0, .5);
box-shadow: inset 0 0 2px rgba(255, 255, 255, .5);
font-family: serif;
font-size: 90%;
border-radius: 1em;
padding: 0 1em;
vertical-align: middle;
color: white;
text-shadow: none;
}
.CodeMirror-foldgutter, .CodeMirror-markergutter { width: 1.2em;
text-align: center; }
.CodeMirror-markergutter { cursor: pointer; }
.CodeMirror-markergutter-mark { cursor: pointer; text-align: center; }
.CodeMirror-markergutter-mark:after { content: "\25CF"; }
.CodeMirror-activeline-background { background: $activeLineColor; }
.CodeMirror-matchingtag { background: $highlightMatchColor; }
.cm-matchhighlight {background-color: $highlightMatchColor; }
.CodeMirror-selection-highlight-scrollbar {background-color:
$highlightMatchColor; }
CSS
);
editors/none/none.php000064400000007565147357022240010647 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.none
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Plain Textarea Editor Plugin
*
* @since 1.5
*/
class PlgEditorNone extends JPlugin
{
/**
* Method to handle the onInitEditor event.
* - Initialises the Editor
*
* @return void
*
* @since 1.5
*/
public function onInit()
{
JHtml::_('script', 'editors/none/none.min.js',
array('version' => 'auto', 'relative'
=> true));
}
/**
* Copy editor content to form field.
*
* Not applicable in this editor.
*
* @param string $editor the editor id
*
* @return void
*
* @deprecated 4.0 Use directly the returned code
*/
public function onSave($editor)
{
}
/**
* Get the editor content.
*
* @param string $id The id of the editor field.
*
* @return string
*
* @deprecated 4.0 Use directly the returned code
*/
public function onGetContent($id)
{
return 'Joomla.editors.instances[' . json_encode($id) .
'].getValue();';
}
/**
* Set the editor content.
*
* @param string $id The id of the editor field.
* @param string $html The content to set.
*
* @return string
*
* @deprecated 4.0 Use directly the returned code
*/
public function onSetContent($id, $html)
{
return 'Joomla.editors.instances[' . json_encode($id) .
'].setValue(' . json_encode($html) . ');';
}
/**
* Inserts html code into the editor
*
* @param string $id The id of the editor field
*
* @return void
*
* @deprecated 4.0
*/
public function onGetInsertMethod($id)
{
}
/**
* Display the editor area.
*
* @param string $name The control name.
* @param string $content The contents of the text area.
* @param string $width The width of the text area (px or %).
* @param string $height The height of the text area (px or %).
* @param integer $col The number of columns for the textarea.
* @param integer $row The number of rows for the textarea.
* @param boolean $buttons True and the editor buttons will be
displayed.
* @param string $id An optional ID for the textarea (note:
since 1.6). If not supplied the name is used.
* @param string $asset The object asset
* @param object $author The author.
* @param array $params Associative array of editor parameters.
*
* @return string
*/
public function onDisplay($name, $content, $width, $height, $col, $row,
$buttons = true,
$id = null, $asset = null, $author = null, $params = array())
{
if (empty($id))
{
$id = $name;
}
// Only add "px" to width and height if they are not given as a
percentage
if (is_numeric($width))
{
$width .= 'px';
}
if (is_numeric($height))
{
$height .= 'px';
}
$readonly = !empty($params['readonly']) ? ' readonly
disabled' : '';
$editor = '<div class="js-editor-none">'
. '<textarea name="' . $name . '"
id="' . $id . '" cols="' . $col .
'" rows="' . $row
. '" style="width: ' . $width . '; height:
' . $height . ';"' . $readonly . '>' .
$content . '</textarea>'
. $this->_displayButtons($id, $buttons, $asset, $author)
. '</div>';
return $editor;
}
/**
* Displays the editor buttons.
*
* @param string $name The control name.
* @param mixed $buttons [array with button objects | boolean true to
display buttons]
* @param string $asset The object asset
* @param object $author The author.
*
* @return void|string HTML
*/
public function _displayButtons($name, $buttons, $asset, $author)
{
if (is_array($buttons) || (is_bool($buttons) && $buttons))
{
$buttons = $this->_subject->getButtons($name, $buttons, $asset,
$author);
return JLayoutHelper::render('joomla.editors.buttons',
$buttons);
}
}
}
editors/none/none.xml000064400000001370147357022240010644 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="editors" method="upgrade">
<name>plg_editors_none</name>
<version>3.0.0</version>
<creationDate>September 2005</creationDate>
<author>Joomla! Project</author>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<copyright>(C) 2005 Open Source Matters, Inc.</copyright>
<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
<description>PLG_NONE_XML_DESCRIPTION</description>
<files>
<filename plugin="none">none.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors_none.ini</language>
<language
tag="en-GB">en-GB.plg_editors_none.sys.ini</language>
</languages>
</extension>
editors/tinymce/field/skins.php000064400000002740147357022240012621
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.tinymce
*
* @copyright (C) 2014 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
jimport('joomla.form.helper');
JFormHelper::loadFieldClass('list');
/**
* Generates the list of options for available skins.
*
* @package Joomla.Plugin
* @subpackage Editors.tinymce
* @since 3.4
*/
class JFormFieldSkins extends JFormFieldList
{
protected $type = 'skins';
/**
* Method to get the skins options.
*
* @return array The skins option objects.
*
* @since 3.4
*/
public function getOptions()
{
$options = array();
$directories = glob(JPATH_ROOT . '/media/editors/tinymce/skins'
. '/*', GLOB_ONLYDIR);
for ($i = 0, $iMax = count($directories); $i < $iMax; ++$i)
{
$dir = basename($directories[$i]);
$options[] = JHtml::_('select.option', $i, $dir);
}
$options = array_merge(parent::getOptions(), $options);
return $options;
}
/**
* Method to get the field input markup for the list of skins.
*
* @return string The field input markup.
*
* @since 3.4
*/
protected function getInput()
{
$html = array();
// Get the field options.
$options = (array) $this->getOptions();
// Create a regular list.
$html[] = JHtml::_('select.genericlist', $options,
$this->name, '', 'value', 'text',
$this->value, $this->id);
return implode($html);
}
}
editors/tinymce/field/tinymcebuilder.php000064400000017334147357022240014516
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.tinymce
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
extract($displayData);
/**
* Layout variables
* -----------------
* @var string $autocomplete Autocomplete attribute for the field.
* @var boolean $autofocus Is autofocus enabled?
* @var string $class Classes for the input.
* @var string $description Description of the field.
* @var boolean $disabled Is this field disabled?
* @var string $group Group the field belongs to.
<fields> section in form XML.
* @var boolean $hidden Is this field hidden in the form?
* @var string $hint Placeholder for the field.
* @var string $id DOM id of the field.
* @var string $label Label of the field.
* @var string $labelclass Classes to apply to the label.
* @var boolean $multiple Does this field support multiple values?
* @var string $name Name of the input field.
* @var string $onchange Onchange attribute for the field.
* @var string $onclick Onclick attribute for the field.
* @var string $pattern Pattern (Reg Ex) of value of the form
field.
* @var boolean $readonly Is this field read only?
* @var boolean $repeat Allows extensions to duplicate elements.
* @var boolean $required Is this field required?
* @var integer $size Size attribute of the input.
* @var boolean $spellcheck Spellcheck state for the form field.
* @var string $validate Validation rules to apply.
* @var array $value Value of the field.
*
* @var array $menus List of the menu items
* @var array $menubarSource Menu items for builder
* @var array $buttons List of the buttons
* @var array $buttonsSource Buttons by group, for the builder
* @var array $toolbarPreset Toolbar preset (default values)
* @var int $setsAmount Amount of sets
* @var array $setsNames List of Sets names
* @var JForm[] $setsForms Form with extra options for an each set
* @var string $languageFile TinyMCE language file to translate the
buttons
*
* @var JLayoutFile $this Context
*/
JHtml::_('behavior.core');
JHtml::_('stylesheet',
'media/editors/tinymce/skins/lightgray/skin.min.css',
array('version' => 'auto', 'relative'
=> false));
JHtml::_('jquery.ui', array('core',
'sortable'));
JHtml::_('script',
'editors/tinymce/tinymce-builder.js', array('version'
=> 'auto', 'relative' => true));
if ($languageFile)
{
JHtml::_('script', $languageFile, array('version'
=> 'auto', 'relative' => false));
}
$doc = JFactory::getDocument();
$doc->addScriptOptions('plg_editors_tinymce_builder', array(
'menus' => $menus,
'buttons' => $buttons,
'toolbarPreset' => $toolbarPreset,
'formControl' => $name . '[toolbars]',
)
);
$doc->addStyleDeclaration('
#joomla-tinymce-builder{
margin-left: -180px;
}
.mce-menubar,
.mce-panel {
min-height: 18px;
border-bottom: 1px solid rgba(217,217,217,0.52);
white-space: normal;
}
.mce-tinymce {
margin-bottom: 20px;
}
.mce-panel .drop-area-highlight{
background-color: #d0d0d0;
}
.mce-panel .mce-btn.ui-state-highlight{
height: 28px;
width: 40px;
background-color: #409740;
border: 1px solid #f0f0f0;
}
.timymce-builder-toolbar .mce-btn.ui-state-highlight{
height: 22px;
width: 28px;
}
');
?>
<div id="joomla-tinymce-builder">
<p><?php echo
JText::_('PLG_TINY_SET_SOURCE_PANEL_DESCRIPTION');
?></p>
<div class="mce-tinymce mce-container mce-panel">
<div class="mce-container-body mce-stack-layout">
<div class="mce-container mce-menubar mce-toolbar
mce-stack-layout-item">
<div class="mce-container-body mce-flow-layout
timymce-builder-menu source" data-group="menu"
data-value="<?php echo
$this->escape(json_encode($menubarSource)); ?>">
</div>
</div>
<div class="mce-toolbar-grp mce-container mce-panel
mce-stack-layout-item">
<div class="mce-container-body mce-flow-layout
timymce-builder-toolbar source" data-group="toolbar"
data-value="<?php echo
$this->escape(json_encode($buttonsSource)); ?>">
</div>
</div>
</div>
</div>
<hr />
<p><?php echo
JText::_('PLG_TINY_SET_TARGET_PANEL_DESCRIPTION');
?></p>
<!-- Render tabs for each set -->
<ul class="nav nav-tabs" id="set-tabs">
<?php foreach ( $setsNames as $num => $title ) : ?>
<li class="<?php echo $num === $setsAmount - 1 ?
'active' : ''; ?>">
<a href="#set-<?php echo $num; ?>"><?php echo
$title; ?></a>
</li>
<?php endforeach; ?>
</ul>
<!-- Render tab content for each set -->
<div class="tab-content">
<?php
$presetButtonClases = array(
'simple' => 'btn-success',
'medium' => 'btn-info',
'advanced' => 'btn-warning',
);
foreach ( $setsNames as $num => $title ) :
// Check whether the values exists, and if empty then use from preset
if (empty($value['toolbars'][$num]['menu'])
&&
empty($value['toolbars'][$num]['toolbar1'])
&&
empty($value['toolbars'][$num]['toolbar2']))
{
// Take the preset for default value
switch ($num) {
case 0:
$preset = $toolbarPreset['advanced'];
break;
case 1:
$preset = $toolbarPreset['medium'];
break;
default:
$preset = $toolbarPreset['simple'];
}
$value['toolbars'][$num] = $preset;
}
// Take existing values
$valMenu = empty($value['toolbars'][$num]['menu'])
? array() : $value['toolbars'][$num]['menu'];
$valBar1 =
empty($value['toolbars'][$num]['toolbar1']) ? array() :
$value['toolbars'][$num]['toolbar1'];
$valBar2 =
empty($value['toolbars'][$num]['toolbar2']) ? array() :
$value['toolbars'][$num]['toolbar2'];
?>
<div class="tab-pane <?php echo $num === $setsAmount - 1 ?
'active' : ''; ?>" id="set-<?php echo
$num; ?>">
<div class="btn-toolbar clearfix">
<div class="btn-group pull-right">
<?php foreach(array_keys($toolbarPreset) as $presetName) :
$btnClass = empty($presetButtonClases[$presetName]) ?
'btn-primary' : $presetButtonClases[$presetName];
?>
<button type="button" class="btn btn-mini <?php
echo $btnClass; ?> button-action"
data-action="setPreset" data-preset="<?php echo
$presetName; ?>" data-set="<?php echo $num; ?>">
<?php echo JText::_('PLG_TINY_SET_PRESET_BUTTON_' .
$presetName); ?>
</button>
<?php endforeach; ?>
<button type="button" class="btn btn-mini
btn-danger button-action"
data-action="clearPane" data-set="<?php echo
$num; ?>">
<?php echo JText::_('JCLEAR'); ?></button>
</div>
</div>
<div class="mce-tinymce mce-container mce-panel">
<div class="mce-container-body mce-stack-layout">
<div class="mce-container mce-menubar mce-toolbar
timymce-builder-menu target"
data-group="menu" data-set="<?php echo $num;
?>"
data-value="<?php echo
$this->escape(json_encode($valMenu)); ?>">
</div>
<div class="mce-toolbar-grp mce-container mce-panel
timymce-builder-toolbar target"
data-group="toolbar1" data-set="<?php echo
$num; ?>"
data-value="<?php echo
$this->escape(json_encode($valBar1)); ?>">
</div>
<div class="mce-toolbar-grp mce-container mce-panel
timymce-builder-toolbar target"
data-group="toolbar2" data-set="<?php echo
$num; ?>"
data-value="<?php echo
$this->escape(json_encode($valBar2)); ?>">
</div>
</div>
</div>
<!-- Render the form for extra options -->
<?php echo $this->sublayout('setoptions',
array('form' => $setsForms[$num])); ?>
</div>
<?php endforeach; ?>
</div>
</div>
editors/tinymce/field/uploaddirs.php000064400000004550147357022240013641
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.tinymce
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
jimport('joomla.form.helper');
JFormHelper::loadFieldClass('folderlist');
/**
* Generates the list of directories available for drag and drop upload.
*
* @package Joomla.Plugin
* @subpackage Editors.tinymce
* @since 3.7.0
*/
class JFormFieldUploaddirs extends JFormFieldFolderList
{
protected $type = 'uploaddirs';
/**
* Method to attach a JForm object to the field.
*
* @param SimpleXMLElement $element The SimpleXMLElement object
representing the `<field>` tag for the form field object.
* @param mixed $value The form field value to validate.
* @param string $group The field name group control
value. This acts as an array container for the field.
* For example if the field has
name="foo" and the group value is set to "bar" then the
* full field name would end up being
"bar[foo]".
*
* @return boolean True on success.
*
* @see JFormField::setup()
* @since 3.7.0
*/
public function setup(SimpleXMLElement $element, $value, $group = null)
{
$return = parent::setup($element, $value, $group);
// Get the path in which to search for file options.
$this->directory =
JComponentHelper::getParams('com_media')->get('image_path');
$this->recursive = true;
$this->hideDefault = true;
return $return;
}
/**
* Method to get the directories options.
*
* @return array The dirs option objects.
*
* @since 3.7.0
*/
public function getOptions()
{
return parent::getOptions();
}
/**
* Method to get the field input markup for the list of directories.
*
* @return string The field input markup.
*
* @since 3.7.0
*/
protected function getInput()
{
$html = array();
// Get the field options.
$options = (array) $this->getOptions();
// Reset the non selected value to null
if ($options[0]->value === '-1')
{
$options[0]->value = '';
}
// Create a regular list.
$html[] = JHtml::_('select.genericlist', $options,
$this->name, '', 'value', 'text',
$this->value, $this->id);
return implode($html);
}
}
editors/tinymce/form/setoptions.xml000064400000017641147357022240013600
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<field
name="access"
type="usergrouplist"
label="PLG_TINY_FIELD_SETACCESS_LABEL"
description="PLG_TINY_FIELD_SETACCESS_DESC"
multiple="true"
class="access-select"
labelclass="label label-success"
/>
<field
name="skins"
type="note"
label="PLG_TINY_FIELD_SKIN_INFO_LABEL"
description="PLG_TINY_FIELD_SKIN_INFO_DESC"
/>
<field
name="skin"
type="skins"
label="PLG_TINY_FIELD_SKIN_LABEL"
description="PLG_TINY_FIELD_SKIN_DESC"
/>
<field
name="skin_admin"
type="skins"
label="PLG_TINY_FIELD_SKIN_ADMIN_LABEL"
description="PLG_TINY_FIELD_SKIN_ADMIN_DESC"
/>
<field
name="mobile"
type="radio"
label="PLG_TINY_FIELD_MOBILE_LABEL"
description="PLG_TINY_FIELD_MOBILE_DESC"
class="btn-group btn-group-yesno"
default="0"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="drag_drop"
type="radio"
label="PLG_TINY_FIELD_DRAG_DROP_LABEL"
description="PLG_TINY_FIELD_DRAG_DROP_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="path"
type="uploaddirs"
label="PLG_TINY_FIELD_CUSTOM_PATH_LABEL"
description="PLG_TINY_FIELD_CUSTOM_PATH_DESC"
class="input-xxlarge"
showon="drag_drop:1"
/>
<field
name="entity_encoding"
type="list"
label="PLG_TINY_FIELD_ENCODING_LABEL"
description="PLG_TINY_FIELD_ENCODING_DESC"
default="raw"
>
<option
value="named">PLG_TINY_FIELD_VALUE_NAMED</option>
<option
value="numeric">PLG_TINY_FIELD_VALUE_NUMERIC</option>
<option
value="raw">PLG_TINY_FIELD_VALUE_RAW</option>
</field>
<field
name="lang_mode"
type="radio"
label="PLG_TINY_FIELD_LANGSELECT_LABEL"
description="PLG_TINY_FIELD_LANGSELECT_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="lang_code"
type="filelist"
label="PLG_TINY_FIELD_LANGCODE_LABEL"
description="PLG_TINY_FIELD_LANGCODE_DESC"
class="inputbox"
stripext="1"
directory="media/editors/tinymce/langs/"
hide_none="1"
default="en"
hide_default="1"
filter="\.js$"
size="10"
showon="lang_mode:0"
/>
<field
name="text_direction"
type="list"
label="PLG_TINY_FIELD_DIRECTION_LABEL"
description="PLG_TINY_FIELD_DIRECTION_DESC"
default="ltr"
>
<option
value="ltr">PLG_TINY_FIELD_VALUE_LTR</option>
<option
value="rtl">PLG_TINY_FIELD_VALUE_RTL</option>
</field>
<field
name="content_css"
type="radio"
label="PLG_TINY_FIELD_CSS_LABEL"
description="PLG_TINY_FIELD_CSS_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="content_css_custom"
type="text"
label="PLG_TINY_FIELD_CUSTOM_CSS_LABEL"
description="PLG_TINY_FIELD_CUSTOM_CSS_DESC"
class="input-xxlarge"
/>
<field
name="relative_urls"
type="list"
label="PLG_TINY_FIELD_URLS_LABEL"
description="PLG_TINY_FIELD_URLS_DESC"
default="1"
>
<option
value="0">PLG_TINY_FIELD_VALUE_ABSOLUTE</option>
<option
value="1">PLG_TINY_FIELD_VALUE_RELATIVE</option>
</field>
<field
name="newlines"
type="list"
label="PLG_TINY_FIELD_NEWLINES_LABEL"
description="PLG_TINY_FIELD_NEWLINES_DESC"
default="0"
>
<option
value="1">PLG_TINY_FIELD_VALUE_BR</option>
<option
value="0">PLG_TINY_FIELD_VALUE_P</option>
</field>
<field
name="use_config_textfilters"
type="radio"
label="PLG_TINY_CONFIG_TEXTFILTER_ACL_LABEL"
description="PLG_TINY_CONFIG_TEXTFILTER_ACL_DESC"
class="btn-group btn-group-yesno"
default="0"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="invalid_elements"
type="text"
label="PLG_TINY_FIELD_PROHIBITED_LABEL"
description="PLG_TINY_FIELD_PROHIBITED_DESC"
showon="use_config_textfilters:0"
default="script,applet,iframe"
class="input-xxlarge"
/>
<field
name="valid_elements"
type="text"
label="PLG_TINY_FIELD_VALIDELEMENTS_LABEL"
description="PLG_TINY_FIELD_VALIDELEMENTS_DESC"
showon="use_config_textfilters:0"
class="input-xxlarge"
/>
<field
name="extended_elements"
type="text"
label="PLG_TINY_FIELD_ELEMENTS_LABEL"
description="PLG_TINY_FIELD_ELEMENTS_DESC"
showon="use_config_textfilters:0"
class="input-xxlarge"
/>
<!-- Extra plugins -->
<field
name="resizing"
type="radio"
label="PLG_TINY_FIELD_RESIZING_LABEL"
description="PLG_TINY_FIELD_RESIZING_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="resize_horizontal"
type="radio"
label="PLG_TINY_FIELD_RESIZE_HORIZONTAL_LABEL"
description="PLG_TINY_FIELD_RESIZE_HORIZONTAL_DESC"
class="btn-group btn-group-yesno"
default="1"
showon="resizing:1"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="element_path"
type="radio"
label="PLG_TINY_FIELD_PATH_LABEL"
description="PLG_TINY_FIELD_PATH_DESC"
class="btn-group btn-group-yesno"
default="0"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="wordcount"
type="radio"
label="PLG_TINY_FIELD_WORDCOUNT_LABEL"
description="PLG_TINY_FIELD_WORDCOUNT_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="image_advtab"
type="radio"
label="PLG_TINY_FIELD_ADVIMAGE_LABEL"
description="PLG_TINY_FIELD_ADVIMAGE_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="advlist"
type="radio"
label="PLG_TINY_FIELD_ADVLIST_LABEL"
description="PLG_TINY_FIELD_ADVLIST_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="contextmenu"
type="radio"
label="PLG_TINY_FIELD_CONTEXTMENU_LABEL"
description="PLG_TINY_FIELD_CONTEXTMENU_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
<field
name="custom_plugin"
type="text"
label="PLG_TINY_FIELD_CUSTOMPLUGIN_LABEL"
description="PLG_TINY_FIELD_CUSTOMPLUGIN_DESC"
class="input-xxlarge"
/>
<field
name="custom_button"
type="text"
label="PLG_TINY_FIELD_CUSTOMBUTTON_LABEL"
description="PLG_TINY_FIELD_CUSTOMBUTTON_DESC"
class="input-xxlarge"
/>
</form>editors/tinymce/tinymce.php000064400000163176147357022240012072
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.tinymce
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\HTML\HTMLHelper;
/**
* TinyMCE Editor Plugin
*
* @since 1.5
*/
class PlgEditorTinymce extends JPlugin
{
/**
* Base path for editor files
*
* @since 3.5
*/
protected $_basePath = 'media/editors/tinymce';
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Loads the application object
*
* @var JApplicationCms
* @since 3.2
*/
protected $app = null;
/**
* Initialises the Editor.
*
* @return void
*
* @since 1.5
*/
public function onInit()
{
JHtml::_('behavior.core');
JHtml::_('behavior.polyfill', array('event'),
'lt IE 9');
JHtml::_('script', $this->_basePath .
'/tinymce.min.js', array('version' =>
'auto'));
JHtml::_('script', 'editors/tinymce/tinymce.min.js',
array('version' => 'auto', 'relative'
=> true));
}
/**
* TinyMCE WYSIWYG Editor - get the editor content
*
* @param string $id The name of the editor
*
* @since 1.5
*
* @return string
*
* @deprecated 4.0 Use directly the returned code
*/
public function onGetContent($id)
{
return 'Joomla.editors.instances[' . json_encode($id) .
'].getValue();';
}
/**
* TinyMCE WYSIWYG Editor - set the editor content
*
* @param string $id The name of the editor
* @param string $html The html to place in the editor
*
* @since 1.5
*
* @return string
*
* @deprecated 4.0 Use directly the returned code
*/
public function onSetContent($id, $html)
{
return 'Joomla.editors.instances[' . json_encode($id) .
'].setValue(' . json_encode($html) . ');';
}
/**
* TinyMCE WYSIWYG Editor - copy editor content to form field
*
* @param string $id The name of the editor
*
* @since 1.5
*
* @return void
*
* @deprecated 4.0 Use directly the returned code
*/
public function onSave($id)
{
}
/**
* Inserts html code into the editor
*
* @param string $name The name of the editor
*
* @since 1.5
*
* @return string
*
* @deprecated 3.5 tinyMCE (API v4) will get the content automatically
from the text area
*/
public function onGetInsertMethod($name)
{
}
/**
* Display the editor area.
*
* @param string $name The name of the editor area.
* @param string $content The content of the field.
* @param string $width The width of the editor area.
* @param string $height The height of the editor area.
* @param int $col The number of columns for the editor area.
* @param int $row The number of rows for the editor area.
* @param boolean $buttons True and the editor buttons will be
displayed.
* @param string $id An optional ID for the textarea. If not
supplied the name is used.
* @param string $asset The object asset
* @param object $author The author.
* @param array $params Associative array of editor parameters.
*
* @return string
*/
public function onDisplay(
$name, $content, $width, $height, $col, $row, $buttons = true, $id =
null, $asset = null, $author = null, $params = array())
{
$app = JFactory::getApplication();
// Check for old params for B/C
$config_warn_count =
$app->getUserState('plg_editors_tinymce.config_legacy_warn_count',
0);
if ($this->params->exists('mode') &&
$this->params->exists('alignment'))
{
if ($app->isClient('administrator') &&
$config_warn_count < 2)
{
$link =
JRoute::_('index.php?option=com_plugins&task=plugin.edit&extension_id='
. $this->getPluginId());
$app->enqueueMessage(JText::sprintf('PLG_TINY_LEGACY_WARNING',
$link), 'warning');
$app->setUserState('plg_editors_tinymce.config_legacy_warn_count',
++$config_warn_count);
}
return $this->onDisplayLegacy($name, $content, $width, $height, $col,
$row, $buttons, $id, $asset, $author, $params);
}
if (empty($id))
{
$id = $name;
}
$id = preg_replace('/(\s|[^A-Za-z0-9_])+/',
'_', $id);
$nameGroup = explode('[',
preg_replace('/\[\]|\]/', '', $name));
$fieldName = end($nameGroup);
$scriptOptions = array();
// Check for existing options
$doc = JFactory::getDocument();
$options = $doc->getScriptOptions('plg_editor_tinymce');
// Only add "px" to width and height if they are not given as a
percentage
if (is_numeric($width))
{
$width .= 'px';
}
if (is_numeric($height))
{
$height .= 'px';
}
// Data object for the layout
$textarea = new stdClass;
$textarea->name = $name;
$textarea->id = $id;
$textarea->class = 'mce_editable joomla-editor-tinymce';
$textarea->cols = $col;
$textarea->rows = $row;
$textarea->width = $width;
$textarea->height = $height;
$textarea->content = $content;
// Set editor to readonly mode
$textarea->readonly = !empty($params['readonly']);
// Render Editor markup
$editor = '<div class="js-editor-tinymce">';
$editor .= JLayoutHelper::render('joomla.tinymce.textarea',
$textarea);
$editor .= $this->_toogleButton($id);
$editor .= '</div>';
// Prepare the instance specific options, actually the ext-buttons
if
(empty($options['tinyMCE'][$fieldName]['joomlaExtButtons']))
{
$btns = $this->tinyButtons($id, $buttons);
if (!empty($btns['names']))
{
JHtml::_('script',
'editors/tinymce/tiny-close.min.js', array('version'
=> 'auto', 'relative' => true),
array('defer' => 'defer'));
}
// Set editor to readonly mode
if (!empty($params['readonly']))
{
$options['tinyMCE'][$fieldName]['readonly'] = 1;
}
$options['tinyMCE'][$fieldName]['joomlaMergeDefaults']
= true;
$options['tinyMCE'][$fieldName]['joomlaExtButtons']
= $btns;
$doc->addScriptOptions('plg_editor_tinymce', $options,
false);
}
// Setup Default (common) options for the Editor script
// Check whether we already have them
if (!empty($options['tinyMCE']['default']))
{
return $editor;
}
$user = JFactory::getUser();
$language = JFactory::getLanguage();
$theme = 'modern';
$ugroups = array_combine($user->getAuthorisedGroups(),
$user->getAuthorisedGroups());
// Prepare the parameters
$levelParams = new Joomla\Registry\Registry;
$extraOptions = new stdClass;
$toolbarParams = new stdClass;
$extraOptionsAll =
$this->params->get('configuration.setoptions', array());
$toolbarParamsAll =
$this->params->get('configuration.toolbars', array());
// Get configuration depend from User group
foreach ($extraOptionsAll as $set => $val)
{
$val->access = empty($val->access) ? array() : $val->access;
// Check whether User in one of allowed group
foreach ($val->access as $group)
{
if (isset($ugroups[$group]))
{
$extraOptions = $val;
$toolbarParams = $toolbarParamsAll->$set;
}
}
}
// Merge the params
$levelParams->loadObject($toolbarParams);
$levelParams->loadObject($extraOptions);
// List the skins
$skindirs = glob(JPATH_ROOT . '/media/editors/tinymce/skins' .
'/*', GLOB_ONLYDIR);
// Set the selected skin
$skin = 'lightgray';
$side = $app->isClient('administrator') ?
'skin_admin' : 'skin';
if ((int) $levelParams->get($side, 0) < count($skindirs))
{
$skin = basename($skindirs[(int) $levelParams->get($side, 0)]);
}
$langMode = $levelParams->get('lang_mode', 1);
$langPrefix = $levelParams->get('lang_code',
'en');
if ($langMode)
{
if (file_exists(JPATH_ROOT . '/media/editors/tinymce/langs/' .
$language->getTag() . '.js'))
{
$langPrefix = $language->getTag();
}
elseif (file_exists(JPATH_ROOT .
'/media/editors/tinymce/langs/' . substr($language->getTag(),
0, strpos($language->getTag(), '-')) . '.js'))
{
$langPrefix = substr($language->getTag(), 0,
strpos($language->getTag(), '-'));
}
else
{
$langPrefix = 'en';
}
}
$text_direction = 'ltr';
if ($language->isRtl())
{
$text_direction = 'rtl';
}
$use_content_css = $levelParams->get('content_css', 1);
$content_css_custom =
$levelParams->get('content_css_custom', '');
/*
* Lets get the default template for the site application
*/
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('template')
->from('#__template_styles')
->where('client_id=0 AND home=' .
$db->quote('1'));
$db->setQuery($query);
try
{
$template = $db->loadResult();
}
catch (RuntimeException $e)
{
$app->enqueueMessage(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'),
'error');
return '';
}
$content_css = null;
$templates_path = JPATH_SITE . '/templates';
// Loading of css file for 'styles' dropdown
if ($content_css_custom)
{
// If URL, just pass it to $content_css
if (strpos($content_css_custom, 'http') !== false)
{
$content_css = $content_css_custom;
}
// If it is not a URL, assume it is a file name in the current template
folder
else
{
$content_css = JUri::root(true) . '/templates/' . $template .
'/css/' . $content_css_custom;
// Issue warning notice if the file is not found (but pass name to
$content_css anyway to avoid TinyMCE error
if (!file_exists($templates_path . '/' . $template .
'/css/' . $content_css_custom))
{
$msg =
sprintf(JText::_('PLG_TINY_ERR_CUSTOMCSSFILENOTPRESENT'),
$content_css_custom);
JLog::add($msg, JLog::WARNING, 'jerror');
}
}
}
else
{
// Process when use_content_css is Yes and no custom file given
if ($use_content_css)
{
// First check templates folder for default template
// if no editor.css file in templates folder, check system template
folder
if (!file_exists($templates_path . '/' . $template .
'/css/editor.css'))
{
// If no editor.css file in system folder, show alert
if (!file_exists($templates_path .
'/system/css/editor.css'))
{
JLog::add(JText::_('PLG_TINY_ERR_EDITORCSSFILENOTPRESENT'),
JLog::WARNING, 'jerror');
}
else
{
$content_css = JUri::root(true) .
'/templates/system/css/editor.css';
}
}
else
{
$content_css = JUri::root(true) . '/templates/' . $template
. '/css/editor.css';
}
}
}
$ignore_filter = false;
// Text filtering
if ($levelParams->get('use_config_textfilters', 0))
{
// Use filters from com_config
$filter = static::getGlobalFilters();
$ignore_filter = $filter === false;
$tagBlacklist = !empty($filter->tagBlacklist) ?
$filter->tagBlacklist : array();
$attrBlacklist = !empty($filter->attrBlacklist) ?
$filter->attrBlacklist : array();
$tagArray = !empty($filter->tagArray) ? $filter->tagArray :
array();
$attrArray = !empty($filter->attrArray) ? $filter->attrArray :
array();
$invalid_elements = implode(',', array_merge($tagBlacklist,
$attrBlacklist, $tagArray, $attrArray));
// Valid elements are all whitelist entries in com_config, which are now
missing in the tagBlacklist
$default_filter = JFilterInput::getInstance();
$valid_elements = implode(',',
array_diff($default_filter->tagBlacklist, $tagBlacklist));
$extended_elements = '';
}
else
{
// Use filters from TinyMCE params
$invalid_elements =
trim($levelParams->get('invalid_elements',
'script,applet,iframe'));
$extended_elements =
trim($levelParams->get('extended_elements', ''));
$valid_elements =
trim($levelParams->get('valid_elements', ''));
}
$html_height = $this->params->get('html_height',
'550');
$html_width = $this->params->get('html_width',
'');
if ($html_width == 750)
{
$html_width = '';
}
// The param is true for vertical resizing only, false or both
$resizing = (bool) $levelParams->get('resizing',
true);
$resize_horizontal = (bool)
$levelParams->get('resize_horizontal', true);
if ($resizing && $resize_horizontal)
{
$resizing = 'both';
}
// Set of always available plugins
$plugins = array(
'autolink',
'lists',
'colorpicker',
'importcss',
);
// Allowed elements
$elements = array(
'hr[id|title|alt|class|width|size|noshade]',
);
if ($extended_elements)
{
$elements = array_merge($elements, explode(',',
$extended_elements));
}
// Prepare the toolbar/menubar
$knownButtons = static::getKnownButtons();
// Check if there no value at all
if (!$levelParams->get('menu') &&
!$levelParams->get('toolbar1') &&
!$levelParams->get('toolbar2'))
{
// Get from preset
$presets = static::getToolbarPreset();
/*
* Predefine group as:
* Set 0: for Administrator, Editor, Super Users (4,7,8)
* Set 1: for Registered, Manager (2,6), all else are public
*/
switch (true)
{
case isset($ugroups[4]) || isset($ugroups[7]) || isset($ugroups[8]):
$preset = $presets['advanced'];
break;
case isset($ugroups[2]) || isset($ugroups[6]):
$preset = $presets['medium'];
break;
default:
$preset = $presets['simple'];
}
$levelParams->loadArray($preset);
}
$menubar = (array) $levelParams->get('menu', array());
$toolbar1 = (array) $levelParams->get('toolbar1', array());
$toolbar2 = (array) $levelParams->get('toolbar2', array());
// Make an easy way to check which button is enabled
$allButtons = array_merge($toolbar1, $toolbar2);
$allButtons = array_combine($allButtons, $allButtons);
// Check for button-specific plugins
foreach ($allButtons as $btnName)
{
if (!empty($knownButtons[$btnName]['plugin']))
{
$plugins[] = $knownButtons[$btnName]['plugin'];
}
}
// Template
$templates = array();
if (!empty($allButtons['template']))
{
// Note this check for the template_list.js file will be removed in
Joomla 4.0
if (is_file(JPATH_ROOT .
'/media/editors/tinymce/templates/template_list.js'))
{
// If using the legacy file we need to include and input the files the
new way
$str = file_get_contents(JPATH_ROOT .
'/media/editors/tinymce/templates/template_list.js');
// Find from one [ to the last ]
$matches = array();
preg_match_all('/\[.*\]/', $str, $matches);
// Set variables
foreach ($matches['0'] as $match)
{
$values = array();
preg_match_all('/\".*\"/', $match, $values);
$result = trim($values['0']['0'],
'"');
$final_result = explode(',', $result);
$templates[] = array(
'title' => trim($final_result['0'], '
" '),
'description' => trim($final_result['2'],
' " '),
'url' => JUri::root(true) . '/' .
trim($final_result['1'], ' " '),
);
}
}
else
{
foreach (glob(JPATH_ROOT .
'/media/editors/tinymce/templates/*.html') as $filename)
{
$filename = basename($filename, '.html');
if ($filename !== 'index')
{
$lang = JFactory::getLanguage();
$title = $filename;
$description = ' ';
if ($lang->hasKey('PLG_TINY_TEMPLATE_' .
strtoupper($filename) . '_TITLE'))
{
$title = JText::_('PLG_TINY_TEMPLATE_' .
strtoupper($filename) . '_TITLE');
}
if ($lang->hasKey('PLG_TINY_TEMPLATE_' .
strtoupper($filename) . '_DESC'))
{
$description = JText::_('PLG_TINY_TEMPLATE_' .
strtoupper($filename) . '_DESC');
}
$templates[] = array(
'title' => $title,
'description' => $description,
'url' => JUri::root(true) .
'/media/editors/tinymce/templates/' . $filename .
'.html',
);
}
}
}
}
// Check for extra plugins, from the setoptions form
foreach (array('wordcount' => 1, 'advlist' =>
1, 'autosave' => 1, 'contextmenu' => 1) as $pName
=> $def)
{
if ($levelParams->get($pName, $def))
{
$plugins[] = $pName;
}
}
// User custom plugins and buttons
$custom_plugin = trim($levelParams->get('custom_plugin',
''));
$custom_button = trim($levelParams->get('custom_button',
''));
if ($custom_plugin)
{
$separator = strpos($custom_plugin, ',') !== false ?
',' : ' ';
$plugins = array_merge($plugins, explode($separator, $custom_plugin));
}
if ($custom_button)
{
$separator = strpos($custom_button, ',') !== false ?
',' : ' ';
$toolbar1 = array_merge($toolbar1, explode($separator,
$custom_button));
}
// Drag and drop Images
$allowImgPaste = false;
$dragdrop = $levelParams->get('drag_drop', 1);
if ($dragdrop && $user->authorise('core.create',
'com_media'))
{
$externalPlugins['jdragdrop'] = HTMLHelper::_(
'script',
'editors/tinymce/plugins/dragdrop/plugin.min.js',
array('relative' => true, 'version' =>
'auto', 'pathOnly' => true)
);
$allowImgPaste = true;
$isSubDir = '';
$session = JFactory::getSession();
$uploadUrl = JUri::base() .
'index.php?option=com_media&task=file.upload&tmpl=component&'
. $session->getName() . '=' . $session->getId()
. '&' . JSession::getFormToken() . '=1'
. '&asset=image&format=json';
if ($app->isClient('site'))
{
$uploadUrl = htmlentities($uploadUrl, 0, 'UTF-8', false);
}
// Is Joomla installed in subdirectory
if (JUri::root(true) !== '/')
{
$isSubDir = JUri::root(true);
}
JText::script('PLG_TINY_ERR_UNSUPPORTEDBROWSER');
$scriptOptions['setCustomDir'] = $isSubDir;
$scriptOptions['mediaUploadPath'] =
$levelParams->get('path', '');
$scriptOptions['uploadUri'] = $uploadUrl;
}
// Build the final options set
$scriptOptions = array_merge(
$scriptOptions,
array(
'suffix' => '.min',
'baseURL' => JUri::root(true) .
'/media/editors/tinymce',
'directionality' => $text_direction,
'language' => $langPrefix,
'autosave_restore_when_empty' => false,
'skin' => $skin,
'theme' => $theme,
'schema' => 'html5',
// Toolbars
'menubar' => empty($menubar) ? false : implode('
', array_unique($menubar)),
'toolbar1' => empty($toolbar1) ? null : implode('
', $toolbar1),
'toolbar2' => empty($toolbar2) ? null : implode('
', $toolbar2),
'plugins' => implode(',',
array_unique($plugins)),
// Cleanup/Output
'inline_styles' => true,
'gecko_spellcheck' => true,
'entity_encoding' =>
$levelParams->get('entity_encoding', 'raw'),
'verify_html' => !$ignore_filter,
'valid_elements' => $valid_elements,
'extended_valid_elements' => implode(',',
$elements),
'invalid_elements' => $invalid_elements,
// URL
'relative_urls' => (bool)
$levelParams->get('relative_urls', true),
'remove_script_host' => false,
// Layout
'content_css' => $content_css,
'document_base_url' => JUri::root(true) . '/',
'paste_data_images' => $allowImgPaste,
'importcss_append' => true,
'image_title' => true,
'height' => $html_height,
'width' => $html_width,
'resize' => $resizing,
'templates' => $templates,
'image_advtab' => (bool)
$levelParams->get('image_advtab', false),
'external_plugins' => empty($externalPlugins) ? null :
$externalPlugins,
'contextmenu' => (bool)
$levelParams->get('contextmenu', true) ? null : false,
'elementpath' => (bool)
$levelParams->get('element_path', true),
)
);
if ($levelParams->get('newlines'))
{
// Break
$scriptOptions['force_br_newlines'] = true;
$scriptOptions['force_p_newlines'] = false;
$scriptOptions['forced_root_block'] = '';
}
else
{
// Paragraph
$scriptOptions['force_br_newlines'] = false;
$scriptOptions['force_p_newlines'] = true;
$scriptOptions['forced_root_block'] = 'p';
}
$scriptOptions['rel_list'] = array(
array('title' => 'None', 'value' =>
''),
array('title' => 'Alternate', 'value'
=> 'alternate'),
array('title' => 'Author', 'value'
=> 'author'),
array('title' => 'Bookmark', 'value'
=> 'bookmark'),
array('title' => 'Help', 'value' =>
'help'),
array('title' => 'License', 'value'
=> 'license'),
array('title' => 'Lightbox', 'value'
=> 'lightbox'),
array('title' => 'Next', 'value' =>
'next'),
array('title' => 'No Follow', 'value'
=> 'nofollow'),
array('title' => 'No Referrer', 'value'
=> 'noreferrer'),
array('title' => 'Prefetch', 'value'
=> 'prefetch'),
array('title' => 'Prev', 'value' =>
'prev'),
array('title' => 'Search', 'value'
=> 'search'),
array('title' => 'Tag', 'value' =>
'tag'),
);
/**
* Shrink the buttons if not on a mobile or if mobile view is off.
* If mobile view is on force into simple mode and enlarge the buttons
**/
if (!$this->app->client->mobile)
{
$scriptOptions['toolbar_items_size'] = 'small';
}
elseif ($levelParams->get('mobile', 0))
{
$scriptOptions['menubar'] = false;
unset($scriptOptions['toolbar2']);
}
$options['tinyMCE']['default'] = $scriptOptions;
$doc->addStyleDeclaration('.mce-in { padding: 5px 10px
!important;}');
$doc->addScriptOptions('plg_editor_tinymce', $options);
return $editor;
}
/**
* Get the toggle editor button
*
* @param string $name Editor name
*
* @return string
*/
private function _toogleButton($name)
{
return JLayoutHelper::render('joomla.tinymce.togglebutton',
$name);
}
/**
* Get the XTD buttons and render them inside tinyMCE
*
* @param string $name the id of the editor field
* @param string $excluded the buttons that should be hidden
*
* @return array
*/
private function tinyButtons($name, $excluded)
{
// Get the available buttons
$buttons = $this->_subject->getButtons($name, $excluded);
// Init the arrays for the buttons
$tinyBtns = array();
$btnsNames = array();
// Build the script
foreach ($buttons as $i => $button)
{
if ($button->get('name'))
{
// Set some vars
$name = 'button-' . $i . str_replace(' ',
'', $button->get('text'));
$title = $button->get('text');
$onclick = $button->get('onclick') ?: null;
$options = $button->get('options');
$icon = $button->get('name');
if ($button->get('link') !== '#')
{
$href = JUri::base() . $button->get('link');
}
else
{
$href = null;
}
// We do some hack here to set the correct icon for 3PD buttons
$icon = 'none icon-' . $icon;
$tempConstructor = array();
// Now we can built the script
$tempConstructor[] = '!(function(){';
// Get the modal width/height
if ($options && is_scalar($options))
{
$tempConstructor[] = 'var getBtnOptions=new Function("return
' . addslashes($options) . '"),';
$tempConstructor[] = 'btnOptions=getBtnOptions(),';
$tempConstructor[] =
'modalWidth=btnOptions.size&&btnOptions.size.x?btnOptions.size.x:null,';
$tempConstructor[] =
'modalHeight=btnOptions.size&&btnOptions.size.y?btnOptions.size.y:null;';
}
else
{
$tempConstructor[] = 'var
btnOptions={},modalWidth=null,modalHeight=null;';
}
// Now we can built the script
// AddButton starts here
$tempConstructor[] = 'editor.addButton("' . $name .
'",{';
$tempConstructor[] = 'text:"' . $title .
'",';
$tempConstructor[] = 'title:"' . $title .
'",';
$tempConstructor[] = 'icon:"' . $icon .
'",';
// Onclick starts here
$tempConstructor[] = 'onclick:function(){';
if ($href || $button->get('modal'))
{
// TinyMCE standard modal options
$tempConstructor[] = 'var modalOptions={';
$tempConstructor[] = 'title:"' . $title .
'",';
$tempConstructor[] = 'url:"' . $href .
'",';
$tempConstructor[] = 'buttons:[{text:
"Close",onclick:"close"}]';
$tempConstructor[] = '};';
// Set width/height
$tempConstructor[] =
'if(modalWidth){modalOptions.width=modalWidth;}';
$tempConstructor[] = 'if(modalHeight){modalOptions.height =
modalHeight;}';
$tempConstructor[] = 'var
win=editor.windowManager.open(modalOptions);';
if (JFactory::getApplication()->client->mobile)
{
$tempConstructor[] = 'win.fullscreen(true);';
}
if ($onclick && ($button->get('modal') || $href))
{
// Adds callback for close button
$tempConstructor[] = $onclick . ';';
}
}
else
{
// Adds callback for the button, eg: readmore
$tempConstructor[] = $onclick . ';';
}
// Onclick ends here
$tempConstructor[] = '}';
// AddButton ends here
$tempConstructor[] = '});';
// IIFE ends here
$tempConstructor[] = '})();';
// The array with the toolbar buttons
$btnsNames[] = $name . ' | ';
// The array with code for each button
$tinyBtns[] = implode('', $tempConstructor);
}
}
return array(
'names' => $btnsNames,
'script' => $tinyBtns
);
}
/**
* Get the global text filters to arbitrary text as per settings for
current user groups
*
* @return JFilterInput
*
* @since 3.6
*/
protected static function getGlobalFilters()
{
// Filter settings
$config = JComponentHelper::getParams('com_config');
$user = JFactory::getUser();
$userGroups = JAccess::getGroupsByUser($user->get('id'));
$filters = $config->get('filters');
$blackListTags = array();
$blackListAttributes = array();
$customListTags = array();
$customListAttributes = array();
$whiteListTags = array();
$whiteListAttributes = array();
$whiteList = false;
$blackList = false;
$customList = false;
$unfiltered = false;
// Cycle through each of the user groups the user is in.
// Remember they are included in the public group as well.
foreach ($userGroups as $groupId)
{
// May have added a group but not saved the filters.
if (!isset($filters->$groupId))
{
continue;
}
// Each group the user is in could have different filtering properties.
$filterData = $filters->$groupId;
$filterType = strtoupper($filterData->filter_type);
if ($filterType === 'NH')
{
// Maximum HTML filtering.
}
elseif ($filterType === 'NONE')
{
// No HTML filtering.
$unfiltered = true;
}
else
{
// Blacklist or whitelist.
// Preprocess the tags and attributes.
$tags = explode(',', $filterData->filter_tags);
$attributes = explode(',',
$filterData->filter_attributes);
$tempTags = array();
$tempAttributes = array();
foreach ($tags as $tag)
{
$tag = trim($tag);
if ($tag)
{
$tempTags[] = $tag;
}
}
foreach ($attributes as $attribute)
{
$attribute = trim($attribute);
if ($attribute)
{
$tempAttributes[] = $attribute;
}
}
// Collect the blacklist or whitelist tags and attributes.
// Each list is cummulative.
if ($filterType === 'BL')
{
$blackList = true;
$blackListTags = array_merge($blackListTags, $tempTags);
$blackListAttributes = array_merge($blackListAttributes,
$tempAttributes);
}
elseif ($filterType === 'CBL')
{
// Only set to true if Tags or Attributes were added
if ($tempTags || $tempAttributes)
{
$customList = true;
$customListTags = array_merge($customListTags, $tempTags);
$customListAttributes = array_merge($customListAttributes,
$tempAttributes);
}
}
elseif ($filterType === 'WL')
{
$whiteList = true;
$whiteListTags = array_merge($whiteListTags, $tempTags);
$whiteListAttributes = array_merge($whiteListAttributes,
$tempAttributes);
}
}
}
// Remove duplicates before processing (because the blacklist uses both
sets of arrays).
$blackListTags = array_unique($blackListTags);
$blackListAttributes = array_unique($blackListAttributes);
$customListTags = array_unique($customListTags);
$customListAttributes = array_unique($customListAttributes);
$whiteListTags = array_unique($whiteListTags);
$whiteListAttributes = array_unique($whiteListAttributes);
// Unfiltered assumes first priority.
if ($unfiltered)
{
// Dont apply filtering.
return false;
}
else
{
// Custom blacklist precedes Default blacklist
if ($customList)
{
$filter = JFilterInput::getInstance(array(), array(), 1, 1);
// Override filter's default blacklist tags and attributes
if ($customListTags)
{
$filter->tagBlacklist = $customListTags;
}
if ($customListAttributes)
{
$filter->attrBlacklist = $customListAttributes;
}
}
// Blacklists take second precedence.
elseif ($blackList)
{
// Remove the white-listed tags and attributes from the black-list.
$blackListTags = array_diff($blackListTags, $whiteListTags);
$blackListAttributes = array_diff($blackListAttributes,
$whiteListAttributes);
$filter = JFilterInput::getInstance($blackListTags,
$blackListAttributes, 1, 1);
// Remove whitelisted tags from filter's default blacklist
if ($whiteListTags)
{
$filter->tagBlacklist = array_diff($filter->tagBlacklist,
$whiteListTags);
}
// Remove whitelisted attributes from filter's default blacklist
if ($whiteListAttributes)
{
$filter->attrBlacklist = array_diff($filter->attrBlacklist,
$whiteListAttributes);
}
}
// Whitelists take third precedence.
elseif ($whiteList)
{
// Turn off XSS auto clean
$filter = JFilterInput::getInstance($whiteListTags,
$whiteListAttributes, 0, 0, 0);
}
// No HTML takes last place.
else
{
$filter = JFilterInput::getInstance();
}
return $filter;
}
}
/**
* Return list of known TinyMCE buttons
*
* @return array
*
* @since 3.7.0
*/
public static function getKnownButtons()
{
// See https://www.tinymce.com/docs/demo/full-featured/
// And https://www.tinymce.com/docs/plugins/
$buttons = array(
// General buttons
'|' => array('label' =>
JText::_('PLG_TINY_TOOLBAR_BUTTON_SEPARATOR'), 'text'
=> '|'),
'undo' => array('label' =>
'Undo'),
'redo' => array('label' =>
'Redo'),
'bold' => array('label' =>
'Bold'),
'italic' => array('label' =>
'Italic'),
'underline' => array('label' =>
'Underline'),
'strikethrough' => array('label' =>
'Strikethrough'),
'styleselect' => array('label' =>
JText::_('PLG_TINY_TOOLBAR_BUTTON_STYLESELECT'), 'text'
=> 'Formats'),
'formatselect' => array('label' =>
JText::_('PLG_TINY_TOOLBAR_BUTTON_FORMATSELECT'),
'text' => 'Paragraph'),
'fontselect' => array('label' =>
JText::_('PLG_TINY_TOOLBAR_BUTTON_FONTSELECT'), 'text'
=> 'Font Family'),
'fontsizeselect' => array('label' =>
JText::_('PLG_TINY_TOOLBAR_BUTTON_FONTSIZESELECT'),
'text' => 'Font Sizes'),
'alignleft' => array('label' =>
'Align left'),
'aligncenter' => array('label' =>
'Align center'),
'alignright' => array('label' =>
'Align right'),
'alignjustify' => array('label' =>
'Justify'),
'outdent' => array('label' =>
'Decrease indent'),
'indent' => array('label' =>
'Increase indent'),
'bullist' => array('label' =>
'Bullet list'),
'numlist' => array('label' =>
'Numbered list'),
'link' => array('label' =>
'Insert/edit link', 'plugin' => 'link'),
'unlink' => array('label' =>
'Remove link', 'plugin' => 'link'),
'subscript' => array('label' =>
'Subscript'),
'superscript' => array('label' =>
'Superscript'),
'blockquote' => array('label' =>
'Blockquote'),
'cut' => array('label' =>
'Cut'),
'copy' => array('label' =>
'Copy'),
'paste' => array('label' =>
'Paste', 'plugin' => 'paste'),
'pastetext' => array('label' =>
'Paste as text', 'plugin' => 'paste'),
'removeformat' => array('label' =>
'Clear formatting'),
// Buttons from the plugins
'forecolor' => array('label' =>
'Text color', 'plugin' => 'textcolor'),
'backcolor' => array('label' =>
'Background color', 'plugin' =>
'textcolor'),
'anchor' => array('label' =>
'Anchor', 'plugin' => 'anchor'),
'hr' => array('label' =>
'Horizontal line', 'plugin' => 'hr'),
'ltr' => array('label' =>
'Left to right', 'plugin' =>
'directionality'),
'rtl' => array('label' =>
'Right to left', 'plugin' =>
'directionality'),
'code' => array('label' =>
'Source code', 'plugin' => 'code'),
'codesample' => array('label' =>
'Insert/Edit code sample', 'plugin' =>
'codesample'),
'table' => array('label' =>
'Table', 'plugin' => 'table'),
'charmap' => array('label' =>
'Special character', 'plugin' =>
'charmap'),
'visualchars' => array('label' =>
'Show invisible characters', 'plugin' =>
'visualchars'),
'visualblocks' => array('label' =>
'Show blocks', 'plugin' =>
'visualblocks'),
'nonbreaking' => array('label' =>
'Nonbreaking space', 'plugin' =>
'nonbreaking'),
'emoticons' => array('label' =>
'Emoticons', 'plugin' => 'emoticons'),
'image' => array('label' =>
'Insert/edit image', 'plugin' => 'image'),
'media' => array('label' =>
'Insert/edit video', 'plugin' => 'media'),
'pagebreak' => array('label' =>
'Page break', 'plugin' => 'pagebreak'),
'print' => array('label' =>
'Print', 'plugin' => 'print'),
'preview' => array('label' =>
'Preview', 'plugin' => 'preview'),
'fullscreen' => array('label' =>
'Fullscreen', 'plugin' => 'fullscreen'),
'template' => array('label' =>
'Insert template', 'plugin' =>
'template'),
'searchreplace' => array('label' =>
'Find and replace', 'plugin' =>
'searchreplace'),
'insertdatetime' => array('label' =>
'Insert date/time', 'plugin' =>
'insertdatetime'),
// 'spellchecker' => array('label' =>
'Spellcheck', 'plugin' => 'spellchecker'),
);
return $buttons;
}
/**
* Return toolbar presets
*
* @return array
*
* @since 3.7.0
*/
public static function getToolbarPreset()
{
$preset = array();
$preset['simple'] = array(
'menu' => array(),
'toolbar1' => array(
'bold', 'underline', 'strikethrough',
'|',
'undo', 'redo', '|',
'bullist', 'numlist', '|',
'pastetext'
),
'toolbar2' => array(),
);
$preset['medium'] = array(
'menu' => array('edit', 'insert',
'view', 'format', 'table',
'tools'),
'toolbar1' => array(
'bold', 'italic', 'underline',
'strikethrough', '|',
'alignleft', 'aligncenter', 'alignright',
'alignjustify', '|',
'formatselect', '|',
'bullist', 'numlist', '|',
'outdent', 'indent', '|',
'undo', 'redo', '|',
'link', 'unlink', 'anchor',
'code', '|',
'hr', 'table', '|',
'subscript', 'superscript', '|',
'charmap', 'pastetext' , 'preview'
),
'toolbar2' => array(),
);
$preset['advanced'] = array(
'menu' => array('edit', 'insert',
'view', 'format', 'table',
'tools'),
'toolbar1' => array(
'bold', 'italic', 'underline',
'strikethrough', '|',
'alignleft', 'aligncenter', 'alignright',
'alignjustify', '|',
'styleselect', '|',
'formatselect', 'fontselect',
'fontsizeselect', '|',
'searchreplace', '|',
'bullist', 'numlist', '|',
'outdent', 'indent', '|',
'undo', 'redo', '|',
'link', 'unlink', 'anchor',
'image', '|',
'code', '|',
'forecolor', 'backcolor', '|',
'fullscreen', '|',
'table', '|',
'subscript', 'superscript', '|',
'charmap', 'emoticons', 'media',
'hr', 'ltr', 'rtl', '|',
'cut', 'copy', 'paste',
'pastetext', '|',
'visualchars', 'visualblocks',
'nonbreaking', 'blockquote', 'template',
'|',
'print', 'preview', 'codesample',
'insertdatetime', 'removeformat',
),
'toolbar2' => array(),
);
return $preset;
}
/**
* Gets the plugin extension id.
*
* @return int The plugin id.
*
* @since 3.7.0
*/
private function getPluginId()
{
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('extension_id'))
->from($db->quoteName('#__extensions'))
->where($db->quoteName('folder') . ' = ' .
$db->quote($this->_type))
->where($db->quoteName('element') . ' = ' .
$db->quote($this->_name));
$db->setQuery($query);
return (int) $db->loadResult();
}
/**
* Display the editor area.
*
* @param string $name The name of the editor area.
* @param string $content The content of the field.
* @param string $width The width of the editor area.
* @param string $height The height of the editor area.
* @param int $col The number of columns for the editor area.
* @param int $row The number of rows for the editor area.
* @param boolean $buttons True and the editor buttons will be
displayed.
* @param string $id An optional ID for the textarea. If not
supplied the name is used.
* @param string $asset The object asset
* @param object $author The author.
* @param array $params Associative array of editor parameters.
*
* @return string
*
* @since 3.7.0
*
* @deprecated 4.0
*/
private function onDisplayLegacy(
$name, $content, $width, $height, $col, $row, $buttons = true, $id =
null, $asset = null, $author = null, $params = array())
{
if (empty($id))
{
$id = $name;
}
$id = preg_replace('/(\s|[^A-Za-z0-9_])+/',
'_', $id);
$nameGroup = explode('[',
preg_replace('/\[\]|\]/', '', $name));
$fieldName = end($nameGroup);
$scriptOptions = array();
// Check for existing options
$doc = JFactory::getDocument();
$options = $doc->getScriptOptions('plg_editor_tinymce');
// Only add "px" to width and height if they are not given as a
percentage
if (is_numeric($width))
{
$width .= 'px';
}
if (is_numeric($height))
{
$height .= 'px';
}
// Data object for the layout
$textarea = new stdClass;
$textarea->name = $name;
$textarea->id = $id;
$textarea->class = 'mce_editable joomla-editor-tinymce';
$textarea->cols = $col;
$textarea->rows = $row;
$textarea->width = $width;
$textarea->height = $height;
$textarea->content = $content;
// Set editor to readonly mode
$textarea->readonly = !empty($params['readonly']);
// Render Editor markup
$editor = '<div class="editor
js-editor-tinymce">';
$editor .= JLayoutHelper::render('joomla.tinymce.textarea',
$textarea);
$editor .= $this->_toogleButton($id);
$editor .= '</div>';
// Prepare instance specific options, actually the ext-buttons
if
(empty($options['tinyMCE'][$fieldName]['joomlaExtButtons']))
{
$btns = $this->tinyButtons($id, $buttons);
if (!empty($btns['names']))
{
JHtml::_('script',
'editors/tinymce/tiny-close.min.js', array('version'
=> 'auto', 'relative' => true),
array('defer' => 'defer'));
}
// Set editor to readonly mode
if (!empty($params['readonly']))
{
$options['tinyMCE'][$fieldName]['readonly'] = 1;
}
$options['tinyMCE'][$fieldName]['joomlaMergeDefaults']
= true;
$options['tinyMCE'][$fieldName]['joomlaExtButtons']
= $btns;
$doc->addScriptOptions('plg_editor_tinymce', $options,
false);
}
// Setup Default options for the Editor script
// Check whether we already have them
if (!empty($options['tinyMCE']['default']))
{
return $editor;
}
$app = JFactory::getApplication();
$user = JFactory::getUser();
$language = JFactory::getLanguage();
$mode = (int) $this->params->get('mode', 1);
$theme = 'modern';
// List the skins
$skindirs = glob(JPATH_ROOT . '/media/editors/tinymce/skins' .
'/*', GLOB_ONLYDIR);
// Set the selected skin
$skin = 'lightgray';
$side = $app->isClient('administrator') ?
'skin_admin' : 'skin';
if ((int) $this->params->get($side, 0) < count($skindirs))
{
$skin = basename($skindirs[(int) $this->params->get($side, 0)]);
}
$langMode = $this->params->get('lang_mode', 0);
$langPrefix = $this->params->get('lang_code',
'en');
if ($langMode)
{
if (file_exists(JPATH_ROOT . "/media/editors/tinymce/langs/" .
$language->getTag() . ".js"))
{
$langPrefix = $language->getTag();
}
elseif (file_exists(JPATH_ROOT .
"/media/editors/tinymce/langs/" . substr($language->getTag(),
0, strpos($language->getTag(), '-')) . ".js"))
{
$langPrefix = substr($language->getTag(), 0,
strpos($language->getTag(), '-'));
}
else
{
$langPrefix = "en";
}
}
$text_direction = 'ltr';
if ($language->isRtl())
{
$text_direction = 'rtl';
}
$use_content_css = $this->params->get('content_css',
1);
$content_css_custom =
$this->params->get('content_css_custom', '');
/*
* Lets get the default template for the site application
*/
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('template')
->from('#__template_styles')
->where('client_id=0 AND home=' .
$db->quote('1'));
$db->setQuery($query);
try
{
$template = $db->loadResult();
}
catch (RuntimeException $e)
{
$app->enqueueMessage(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'),
'error');
return;
}
$content_css = null;
$templates_path = JPATH_SITE . '/templates';
// Loading of css file for 'styles' dropdown
if ($content_css_custom)
{
// If URL, just pass it to $content_css
if (strpos($content_css_custom, 'http') !== false)
{
$content_css = $content_css_custom;
}
// If it is not a URL, assume it is a file name in the current template
folder
else
{
$content_css = JUri::root(true) . '/templates/' . $template .
'/css/' . $content_css_custom;
// Issue warning notice if the file is not found (but pass name to
$content_css anyway to avoid TinyMCE error
if (!file_exists($templates_path . '/' . $template .
'/css/' . $content_css_custom))
{
$msg =
sprintf(JText::_('PLG_TINY_ERR_CUSTOMCSSFILENOTPRESENT'),
$content_css_custom);
JLog::add($msg, JLog::WARNING, 'jerror');
}
}
}
else
{
// Process when use_content_css is Yes and no custom file given
if ($use_content_css)
{
// First check templates folder for default template
// if no editor.css file in templates folder, check system template
folder
if (!file_exists($templates_path . '/' . $template .
'/css/editor.css'))
{
// If no editor.css file in system folder, show alert
if (!file_exists($templates_path .
'/system/css/editor.css'))
{
JLog::add(JText::_('PLG_TINY_ERR_EDITORCSSFILENOTPRESENT'),
JLog::WARNING, 'jerror');
}
else
{
$content_css = JUri::root(true) .
'/templates/system/css/editor.css';
}
}
else
{
$content_css = JUri::root(true) . '/templates/' . $template
. '/css/editor.css';
}
}
}
$ignore_filter = false;
// Text filtering
if ($this->params->get('use_config_textfilters', 0))
{
// Use filters from com_config
$filter = static::getGlobalFilters();
$ignore_filter = $filter === false;
$tagBlacklist = !empty($filter->tagBlacklist) ?
$filter->tagBlacklist : array();
$attrBlacklist = !empty($filter->attrBlacklist) ?
$filter->attrBlacklist : array();
$tagArray = !empty($filter->tagArray) ? $filter->tagArray :
array();
$attrArray = !empty($filter->attrArray) ? $filter->attrArray :
array();
$invalid_elements = implode(',', array_merge($tagBlacklist,
$attrBlacklist, $tagArray, $attrArray));
// Valid elements are all whitelist entries in com_config, which are now
missing in the tagBlacklist
$default_filter = JFilterInput::getInstance();
$valid_elements = implode(',',
array_diff($default_filter->tagBlacklist, $tagBlacklist));
$extended_elements = '';
}
else
{
// Use filters from TinyMCE params
$invalid_elements =
$this->params->get('invalid_elements',
'script,applet,iframe');
$extended_elements =
$this->params->get('extended_elements', '');
$valid_elements =
$this->params->get('valid_elements', '');
}
// Advanced Options
$access = $user->getAuthorisedViewLevels();
// Flip for performance, so we can direct check for the key
isset($access[$key])
$access = array_flip($access);
$html_height = $this->params->get('html_height',
'550');
$html_width = $this->params->get('html_width',
'');
if ($html_width == 750)
{
$html_width = '';
}
// Image advanced options
$image_advtab = $this->params->get('image_advtab', true);
if (isset($access[$image_advtab]))
{
$image_advtab = true;
}
else
{
$image_advtab = false;
}
// The param is true for vertical resizing only, false or both
$resizing = $this->params->get('resizing',
'1');
$resize_horizontal =
$this->params->get('resize_horizontal', '1');
if ($resizing || $resizing == 'true')
{
if ($resize_horizontal || $resize_horizontal == 'true')
{
$resizing = 'both';
}
else
{
$resizing = true;
}
}
else
{
$resizing = false;
}
$toolbar1_add = array();
$toolbar2_add = array();
$toolbar3_add = array();
$toolbar4_add = array();
$elements = array();
$plugins = array(
'autolink',
'lists',
'image',
'charmap',
'print',
'preview',
'anchor',
'pagebreak',
'code',
'save',
'textcolor',
'colorpicker',
'importcss');
$toolbar1_add[] = 'bold';
$toolbar1_add[] = 'italic';
$toolbar1_add[] = 'underline';
$toolbar1_add[] = 'strikethrough';
// Alignment buttons
$alignment = $this->params->get('alignment', 1);
if (isset($access[$alignment]))
{
$toolbar1_add[] = '|';
$toolbar1_add[] = 'alignleft';
$toolbar1_add[] = 'aligncenter';
$toolbar1_add[] = 'alignright';
$toolbar1_add[] = 'alignjustify';
}
$toolbar1_add[] = '|';
$toolbar1_add[] = 'styleselect';
$toolbar1_add[] = '|';
$toolbar1_add[] = 'formatselect';
// Fonts
$fonts = $this->params->get('fonts', 1);
if (isset($access[$fonts]))
{
$toolbar1_add[] = 'fontselect';
$toolbar1_add[] = 'fontsizeselect';
}
// Search & replace
$searchreplace = $this->params->get('searchreplace', 1);
if (isset($access[$searchreplace]))
{
$plugins[] = 'searchreplace';
$toolbar2_add[] = 'searchreplace';
}
$toolbar2_add[] = '|';
$toolbar2_add[] = 'bullist';
$toolbar2_add[] = 'numlist';
$toolbar2_add[] = '|';
$toolbar2_add[] = 'outdent';
$toolbar2_add[] = 'indent';
$toolbar2_add[] = '|';
$toolbar2_add[] = 'undo';
$toolbar2_add[] = 'redo';
$toolbar2_add[] = '|';
// Insert date and/or time plugin
$insertdate = $this->params->get('insertdate', 1);
if (isset($access[$insertdate]))
{
$plugins[] = 'insertdatetime';
$toolbar4_add[] = 'inserttime';
}
// Link plugin
$link = $this->params->get('link', 1);
if (isset($access[$link]))
{
$plugins[] = 'link';
$toolbar2_add[] = 'link';
$toolbar2_add[] = 'unlink';
}
$toolbar2_add[] = 'anchor';
$toolbar2_add[] = 'image';
$toolbar2_add[] = '|';
$toolbar2_add[] = 'code';
// Colors
$colors = $this->params->get('colors', 1);
if (isset($access[$colors]))
{
$toolbar2_add[] = '|';
$toolbar2_add[] = 'forecolor,backcolor';
}
// Fullscreen
$fullscreen = $this->params->get('fullscreen', 1);
if (isset($access[$fullscreen]))
{
$plugins[] = 'fullscreen';
$toolbar2_add[] = '|';
$toolbar2_add[] = 'fullscreen';
}
// Table
$table = $this->params->get('table', 1);
if (isset($access[$table]))
{
$plugins[] = 'table';
$toolbar3_add[] = 'table';
$toolbar3_add[] = '|';
}
$toolbar3_add[] = 'subscript';
$toolbar3_add[] = 'superscript';
$toolbar3_add[] = '|';
$toolbar3_add[] = 'charmap';
// Emotions
$smilies = $this->params->get('smilies', 1);
if (isset($access[$smilies]))
{
$plugins[] = 'emoticons';
$toolbar3_add[] = 'emoticons';
}
// Media plugin
$media = $this->params->get('media', 1);
if (isset($access[$media]))
{
$plugins[] = 'media';
$toolbar3_add[] = 'media';
}
// Horizontal line
$hr = $this->params->get('hr', 1);
if (isset($access[$hr]))
{
$plugins[] = 'hr';
$elements[] = 'hr[id|title|alt|class|width|size|noshade]';
$toolbar3_add[] = 'hr';
}
else
{
$elements[] = 'hr[id|class|title|alt]';
}
// RTL/LTR buttons
$directionality = $this->params->get('directionality',
1);
if (isset($access[$directionality]))
{
$plugins[] = 'directionality';
$toolbar3_add[] = 'ltr rtl';
}
if ($extended_elements != "")
{
$elements = explode(',', $extended_elements);
}
$toolbar4_add[] = 'cut';
$toolbar4_add[] = 'copy';
// Paste
$paste = $this->params->get('paste', 1);
if (isset($access[$paste]))
{
$plugins[] = 'paste';
$toolbar4_add[] = 'paste';
}
$toolbar4_add[] = '|';
// Visualchars
$visualchars = $this->params->get('visualchars', 1);
if (isset($access[$visualchars]))
{
$plugins[] = 'visualchars';
$toolbar4_add[] = 'visualchars';
}
// Visualblocks
$visualblocks = $this->params->get('visualblocks', 1);
if (isset($access[$visualblocks]))
{
$plugins[] = 'visualblocks';
$toolbar4_add[] = 'visualblocks';
}
// Non-breaking
$nonbreaking = $this->params->get('nonbreaking', 1);
if (isset($access[$nonbreaking]))
{
$plugins[] = 'nonbreaking';
$toolbar4_add[] = 'nonbreaking';
}
// Blockquote
$blockquote = $this->params->get('blockquote', 1);
if (isset($access[$blockquote]))
{
$toolbar4_add[] = 'blockquote';
}
// Template
$template = $this->params->get('template', 1);
$templates = array();
if (isset($access[$template]))
{
$plugins[] = 'template';
$toolbar4_add[] = 'template';
// Note this check for the template_list.js file will be removed in
Joomla 4.0
if (is_file(JPATH_ROOT .
"/media/editors/tinymce/templates/template_list.js"))
{
// If using the legacy file we need to include and input the files the
new way
$str = file_get_contents(JPATH_ROOT .
"/media/editors/tinymce/templates/template_list.js");
// Find from one [ to the last ]
$matches = array();
preg_match_all('/\[.*\]/', $str, $matches);
// Set variables
foreach ($matches['0'] as $match)
{
$values = array();
preg_match_all('/\".*\"/', $match, $values);
$result = trim($values["0"]["0"],
'"');
$final_result = explode(',', $result);
$templates[] = array(
'title' => trim($final_result['0'], '
" '),
'description' => trim($final_result['2'],
' " '),
'url' => JUri::root(true) . '/' .
trim($final_result['1'], ' " '),
);
}
}
else
{
foreach (glob(JPATH_ROOT .
'/media/editors/tinymce/templates/*.html') as $filename)
{
$filename = basename($filename, '.html');
if ($filename !== 'index')
{
$lang = JFactory::getLanguage();
$title = $filename;
$description = ' ';
if ($lang->hasKey('PLG_TINY_TEMPLATE_' .
strtoupper($filename) . '_TITLE'))
{
$title = JText::_('PLG_TINY_TEMPLATE_' .
strtoupper($filename) . '_TITLE');
}
if ($lang->hasKey('PLG_TINY_TEMPLATE_' .
strtoupper($filename) . '_DESC'))
{
$description = JText::_('PLG_TINY_TEMPLATE_' .
strtoupper($filename) . '_DESC');
}
$templates[] = array(
'title' => $title,
'description' => $description,
'url' => JUri::root(true) .
'/media/editors/tinymce/templates/' . $filename .
'.html',
);
}
}
}
}
// Print
$print = $this->params->get('print', 1);
if (isset($access[$print]))
{
$plugins[] = 'print';
$toolbar4_add[] = '|';
$toolbar4_add[] = 'print';
$toolbar4_add[] = 'preview';
}
// Spellchecker
$spell = $this->params->get('spell', 0);
if (isset($access[$spell]))
{
$plugins[] = 'spellchecker';
$toolbar4_add[] = '|';
$toolbar4_add[] = 'spellchecker';
}
// Wordcount
$wordcount = $this->params->get('wordcount', 1);
if (isset($access[$wordcount]))
{
$plugins[] = 'wordcount';
}
// Advlist
$advlist = $this->params->get('advlist', 1);
if (isset($access[$advlist]))
{
$plugins[] = 'advlist';
}
// Codesample
$advlist = $this->params->get('code_sample', 1);
if (isset($access[$advlist]))
{
$plugins[] = 'codesample';
$toolbar4_add[] = 'codesample';
}
// Autosave
$autosave = $this->params->get('autosave', 1);
if (isset($access[$autosave]))
{
$plugins[] = 'autosave';
}
// Context menu
$contextmenu = $this->params->get('contextmenu', 1);
if (isset($access[$contextmenu]))
{
$plugins[] = 'contextmenu';
}
$custom_plugin = $this->params->get('custom_plugin',
'');
if ($custom_plugin != "")
{
$plugins[] = $custom_plugin;
}
$custom_button = $this->params->get('custom_button',
'');
if ($custom_button != "")
{
$toolbar4_add[] = $custom_button;
}
// Drag and drop Images
$externalPlugins = array();
$allowImgPaste = false;
$dragdrop = $this->params->get('drag_drop', 1);
if ($dragdrop && $user->authorise('core.create',
'com_media'))
{
$allowImgPaste = true;
$isSubDir = '';
$session = JFactory::getSession();
$uploadUrl = JUri::base() .
'index.php?option=com_media&task=file.upload&tmpl=component&'
. $session->getName() . '=' . $session->getId()
. '&' . JSession::getFormToken() . '=1'
. '&asset=image&format=json';
if ($app->isClient('site'))
{
$uploadUrl = htmlentities($uploadUrl, 0, 'UTF-8', false);
}
// Is Joomla installed in subdirectory
if (JUri::root(true) != '/')
{
$isSubDir = JUri::root(true);
}
JText::script('PLG_TINY_ERR_UNSUPPORTEDBROWSER');
$scriptOptions['setCustomDir'] = $isSubDir;
$scriptOptions['mediaUploadPath'] =
$this->params->get('path', '');
$scriptOptions['uploadUri'] = $uploadUrl;
$externalPlugins = array(
array(
'jdragdrop' => HTMLHelper::_(
'script',
'editors/tinymce/plugins/dragdrop/plugin.min.js',
array('relative' => true, 'version' =>
'auto', 'pathOnly' => true)
),
),
);
}
// Prepare config variables
$plugins = implode(',', $plugins);
$elements = implode(',', $elements);
// Prepare config variables
$toolbar1 = implode(' ', $toolbar1_add) . ' | '
. implode(' ', $toolbar2_add) . ' | '
. implode(' ', $toolbar3_add) . ' | '
. implode(' ', $toolbar4_add);
// See if mobileVersion is activated
$mobileVersion = $this->params->get('mobile', 0);
$scriptOptions = array_merge(
$scriptOptions,
array(
'suffix' => '.min',
'baseURL' => JUri::root(true) .
'/media/editors/tinymce',
'directionality' => $text_direction,
'language' => $langPrefix,
'autosave_restore_when_empty' => false,
'skin' => $skin,
'theme' => $theme,
'schema' => 'html5',
// Cleanup/Output
'inline_styles' => true,
'gecko_spellcheck' => true,
'entity_encoding' =>
$this->params->get('entity_encoding', 'raw'),
'verify_html' => !$ignore_filter,
// URL
'relative_urls' => (bool)
$this->params->get('relative_urls', true),
'remove_script_host' => false,
// Layout
'content_css' => $content_css,
'document_base_url' => JUri::root(true) . '/',
'paste_data_images' => $allowImgPaste,
'externalPlugins' => json_encode($externalPlugins),
)
);
if ($this->params->get('newlines'))
{
// Break
$scriptOptions['force_br_newlines'] = true;
$scriptOptions['force_p_newlines'] = false;
$scriptOptions['forced_root_block'] = '';
}
else
{
// Paragraph
$scriptOptions['force_br_newlines'] = false;
$scriptOptions['force_p_newlines'] = true;
$scriptOptions['forced_root_block'] = 'p';
}
/**
* Shrink the buttons if not on a mobile or if mobile view is off.
* If mobile view is on force into simple mode and enlarge the buttons
**/
if (!$this->app->client->mobile)
{
$scriptOptions['toolbar_items_size'] = 'small';
}
elseif ($mobileVersion)
{
$mode = 0;
}
switch ($mode)
{
case 0: /* Simple mode*/
$scriptOptions['menubar'] = false;
$scriptOptions['toolbar1'] = 'bold italic underline
strikethrough | undo redo | bullist numlist | code';
$scriptOptions['plugins'] = ' code';
break;
case 1:
default: /* Advanced mode*/
$toolbar1 = "bold italic underline strikethrough | alignleft
aligncenter alignright alignjustify | formatselect | bullist numlist "
. "| outdent indent | undo redo | link unlink anchor code | hr
table | subscript superscript | charmap";
$scriptOptions['valid_elements'] = $valid_elements;
$scriptOptions['extended_valid_elements'] = $elements;
$scriptOptions['invalid_elements'] = $invalid_elements;
$scriptOptions['plugins'] = 'table link code hr charmap
autolink lists importcss ';
$scriptOptions['toolbar1'] = $toolbar1;
$scriptOptions['removed_menuitems'] =
'newdocument';
$scriptOptions['importcss_append'] = true;
$scriptOptions['height'] = $html_height;
$scriptOptions['width'] = $html_width;
$scriptOptions['resize'] = $resizing;
break;
case 2: /* Extended mode*/
$scriptOptions['valid_elements'] = $valid_elements;
$scriptOptions['extended_valid_elements'] = $elements;
$scriptOptions['invalid_elements'] = $invalid_elements;
$scriptOptions['plugins'] = $plugins;
$scriptOptions['toolbar1'] = $toolbar1;
$scriptOptions['removed_menuitems'] =
'newdocument';
$scriptOptions['rel_list'] = array(
array('title' => 'None', 'value'
=> ''),
array('title' => 'Alternate', 'value'
=> 'alternate'),
array('title' => 'Author', 'value'
=> 'author'),
array('title' => 'Bookmark', 'value'
=> 'bookmark'),
array('title' => 'Help', 'value'
=> 'help'),
array('title' => 'License', 'value'
=> 'license'),
array('title' => 'Lightbox', 'value'
=> 'lightbox'),
array('title' => 'Next', 'value'
=> 'next'),
array('title' => 'No Follow', 'value'
=> 'nofollow'),
array('title' => 'No Referrer',
'value' => 'noreferrer'),
array('title' => 'Prefetch', 'value'
=> 'prefetch'),
array('title' => 'Prev', 'value'
=> 'prev'),
array('title' => 'Search', 'value'
=> 'search'),
array('title' => 'Tag', 'value' =>
'tag'),
);
$scriptOptions['importcss_append'] = true;
$scriptOptions['image_advtab'] = $image_advtab;
$scriptOptions['height'] = $html_height;
$scriptOptions['width'] = $html_width;
$scriptOptions['resize'] = $resizing;
$scriptOptions['templates'] = $templates;
break;
}
$options['tinyMCE']['default'] = $scriptOptions;
$doc->addStyleDeclaration(".mce-in { padding: 5px 10px
!important;}");
$doc->addScriptOptions('plg_editor_tinymce', $options);
return $editor;
}
}
editors/tinymce/tinymce.xml000064400000003267147357022240012075
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.2" type="plugin"
group="editors" method="upgrade">
<name>plg_editors_tinymce</name>
<version>4.5.12</version>
<creationDate>2005-2020</creationDate>
<author>Tiny Technologies, Inc</author>
<authorEmail>N/A</authorEmail>
<authorUrl>https://www.tiny.cloud</authorUrl>
<copyright>Tiny Technologies, Inc</copyright>
<license>LGPL</license>
<description>PLG_TINY_XML_DESCRIPTION</description>
<files>
<filename plugin="tinymce">tinymce.php</filename>
<folder>fields</folder>
<folder>form</folder>
</files>
<media destination="editors" folder="media">
<folder>tinymce</folder>
</media>
<languages>
<language
tag="en-GB">en-GB.plg_editors_tinymce.ini</language>
<language
tag="en-GB">en-GB.plg_editors_tinymce.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="configuration"
type="tinymcebuilder"
hiddenLabel="true"
/>
</fieldset>
<fieldset name="advanced"
label="PLG_TINY_FIELD_LABEL_ADVANCEDPARAMS">
<field
name="sets_amount"
type="number"
label="PLG_TINY_FIELD_NUMBER_OF_SETS_LABEL"
description="PLG_TINY_FIELD_NUMBER_OF_SETS_DESC"
filter="int"
validate="number"
min="3"
default="3"
/>
<field
name="html_height"
type="text"
label="PLG_TINY_FIELD_HTMLHEIGHT_LABEL"
description="PLG_TINY_FIELD_HTMLHEIGHT_DESC"
default="550px"
/>
<field
name="html_width"
type="text"
label="PLG_TINY_FIELD_HTMLWIDTH_LABEL"
description="PLG_TINY_FIELD_HTMLWIDTH_DESC"
default=""
/>
</fieldset>
</fields>
</config>
</extension>
editors-xtd/article/article.php000064400000003517147357022240012605
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors-xtd.article
*
* @copyright (C) 2009 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Editor Article button
*
* @since 1.5
*/
class PlgButtonArticle extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Display the button
*
* @param string $name The name of the button to add
*
* @return JObject The button options as JObject
*
* @since 1.5
*/
public function onDisplay($name)
{
$input = JFactory::getApplication()->input;
$user = JFactory::getUser();
// Can create in any category (component permission) or at least in one
category
$canCreateRecords = $user->authorise('core.create',
'com_content')
|| count($user->getAuthorisedCategories('com_content',
'core.create')) > 0;
// Instead of checking edit on all records, we can use **same** check as
the form editing view
$values = (array)
JFactory::getApplication()->getUserState('com_content.edit.article.id');
$isEditingRecords = count($values);
// This ACL check is probably a double-check (form view already performed
checks)
$hasAccess = $canCreateRecords || $isEditingRecords;
if (!$hasAccess)
{
return;
}
$link =
'index.php?option=com_content&view=articles&layout=modal&tmpl=component&'
. JSession::getFormToken() . '=1&editor=' . $name;
$button = new JObject;
$button->modal = true;
$button->class = 'btn';
$button->link = $link;
$button->text = JText::_('PLG_ARTICLE_BUTTON_ARTICLE');
$button->name = 'file-add';
$button->options = "{handler: 'iframe', size: {x: 800,
y: 500}}";
return $button;
}
}
editors-xtd/article/article.xml000064400000001430147357022240012606
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="editors-xtd" method="upgrade">
<name>plg_editors-xtd_article</name>
<author>Joomla! Project</author>
<creationDate>October 2009</creationDate>
<copyright>(C) 2009 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_ARTICLE_XML_DESCRIPTION</description>
<files>
<filename plugin="article">article.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors-xtd_article.ini</language>
<language
tag="en-GB">en-GB.plg_editors-xtd_article.sys.ini</language>
</languages>
</extension>
editors-xtd/contact/contact.php000064400000002622147357022240012621
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors-xtd.contact
*
* @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;
/**
* Editor Contact button
*
* @since 3.7.0
*/
class PlgButtonContact extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.7.0
*/
protected $autoloadLanguage = true;
/**
* Display the button
*
* @param string $name The name of the button to add
*
* @return JObject The button options as JObject
*
* @since 3.7.0
*/
public function onDisplay($name)
{
$user = JFactory::getUser();
if ($user->authorise('core.create', 'com_contact')
|| $user->authorise('core.edit', 'com_contact')
|| $user->authorise('core.edit.own',
'com_contact'))
{
// The URL for the contacts list
$link =
'index.php?option=com_contact&view=contacts&layout=modal&tmpl=component&'
. JSession::getFormToken() . '=1&editor=' . $name;
$button = new JObject;
$button->modal = true;
$button->class = 'btn';
$button->link = $link;
$button->text =
JText::_('PLG_EDITORS-XTD_CONTACT_BUTTON_CONTACT');
$button->name = 'address';
$button->options = "{handler: 'iframe', size: {x: 800,
y: 500}}";
return $button;
}
}
}
editors-xtd/contact/contact.xml000064400000001444147357022240012633
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.7" type="plugin"
group="editors-xtd" method="upgrade">
<name>plg_editors-xtd_contact</name>
<author>Joomla! Project</author>
<creationDate>October 2016</creationDate>
<copyright>(C) 2016 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_EDITORS-XTD_CONTACT_XML_DESCRIPTION</description>
<files>
<filename plugin="contact">contact.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors-xtd_contact.ini</language>
<language
tag="en-GB">en-GB.plg_editors-xtd_contact.sys.ini</language>
</languages>
</extension>
editors-xtd/fields/fields.php000064400000003317147357022240012251
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors-xtd.fields
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Editor Fields button
*
* @since 3.7.0
*/
class PlgButtonFields extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.7.0
*/
protected $autoloadLanguage = true;
/**
* Display the button
*
* @param string $name The name of the button to add
*
* @return JObject The button options as JObject
*
* @since 3.7.0
*/
public function onDisplay($name)
{
// Check if com_fields is enabled
if (!JComponentHelper::isEnabled('com_fields'))
{
return;
}
// Register FieldsHelper
JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR .
'/components/com_fields/helpers/fields.php');
// Guess the field context based on view.
$jinput = JFactory::getApplication()->input;
$context = $jinput->get('option') . '.' .
$jinput->get('view');
// Validate context.
$context = implode('.', FieldsHelper::extract($context));
if (!FieldsHelper::getFields($context))
{
return;
}
$link =
'index.php?option=com_fields&view=fields&layout=modal&tmpl=component&context='
. $context . '&editor=' . $name .
'&' . JSession::getFormToken() . '=1';
$button = new JObject;
$button->modal = true;
$button->class = 'btn';
$button->link = $link;
$button->text =
JText::_('PLG_EDITORS-XTD_FIELDS_BUTTON_FIELD');
$button->name = 'puzzle';
$button->options = "{handler: 'iframe', size: {x: 800,
y: 500}}";
return $button;
}
}
editors-xtd/fields/fields.xml000064400000001437147357022240012263
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.7" type="plugin"
group="editors-xtd" method="upgrade">
<name>plg_editors-xtd_fields</name>
<author>Joomla! Project</author>
<creationDate>February 2017</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_EDITORS-XTD_FIELDS_XML_DESCRIPTION</description>
<files>
<filename plugin="fields">fields.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors-xtd_fields.ini</language>
<language
tag="en-GB">en-GB.plg_editors-xtd_fields.sys.ini</language>
</languages>
</extension>
editors-xtd/image/image.php000064400000004175147357022240011704
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors-xtd.image
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Editor Image buton
*
* @since 1.5
*/
class PlgButtonImage extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Display the button.
*
* @param string $name The name of the button to display.
* @param string $asset The name of the asset being edited.
* @param integer $author The id of the author owning the asset being
edited.
*
* @return JObject The button options as JObject or false if not allowed
*
* @since 1.5
*/
public function onDisplay($name, $asset, $author)
{
$app = JFactory::getApplication();
$user = JFactory::getUser();
$extension = $app->input->get('option');
// For categories we check the extension (ex: component.section)
if ($extension === 'com_categories')
{
$parts = explode('.',
$app->input->get('extension', 'com_content'));
$extension = $parts[0];
}
$asset = $asset !== '' ? $asset : $extension;
if ($user->authorise('core.edit', $asset)
|| $user->authorise('core.create', $asset)
|| (count($user->getAuthorisedCategories($asset,
'core.create')) > 0)
|| ($user->authorise('core.edit.own', $asset) &&
$author === $user->id)
|| (count($user->getAuthorisedCategories($extension,
'core.edit')) > 0)
|| (count($user->getAuthorisedCategories($extension,
'core.edit.own')) > 0 && $author === $user->id))
{
$link =
'index.php?option=com_media&view=images&tmpl=component&e_name='
. $name . '&asset=' . $asset .
'&author=' . $author;
$button = new JObject;
$button->modal = true;
$button->class = 'btn';
$button->link = $link;
$button->text = JText::_('PLG_IMAGE_BUTTON_IMAGE');
$button->name = 'pictures';
$button->options = "{handler: 'iframe', size: {x: 800,
y: 500}}";
return $button;
}
return false;
}
}
editors-xtd/image/image.xml000064400000001413147357022240011705
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="editors-xtd" method="upgrade">
<name>plg_editors-xtd_image</name>
<author>Joomla! Project</author>
<creationDate>August 2004</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_IMAGE_XML_DESCRIPTION</description>
<files>
<filename plugin="image">image.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors-xtd_image.ini</language>
<language
tag="en-GB">en-GB.plg_editors-xtd_image.sys.ini</language>
</languages>
</extension>
editors-xtd/menu/menu.php000064400000002530147357022240011441
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors-xtd.menu
*
* @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;
/**
* Editor menu button
*
* @since 3.7.0
*/
class PlgButtonMenu extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.7.0
*/
protected $autoloadLanguage = true;
/**
* Display the button
*
* @param string $name The name of the button to add
*
* @since 3.7.0
* @return array
*/
public function onDisplay($name)
{
/*
* Use the built-in element view to select the menu item.
* Currently uses blank class.
*/
$user = JFactory::getUser();
if ($user->authorise('core.create', 'com_menus')
|| $user->authorise('core.edit', 'com_menus'))
{
$link =
'index.php?option=com_menus&view=items&layout=modal&tmpl=component&'
. JSession::getFormToken() . '=1&editor=' . $name;
$button = new JObject;
$button->modal = true;
$button->class = 'btn';
$button->link = $link;
$button->text =
JText::_('PLG_EDITORS-XTD_MENU_BUTTON_MENU');
$button->name = 'share-alt';
$button->options = "{handler: 'iframe', size: {x: 800,
y: 500}}";
return $button;
}
}
}
editors-xtd/menu/menu.xml000064400000001421147357022240011450
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.7" type="plugin"
group="editors-xtd" method="upgrade">
<name>plg_editors-xtd_menu</name>
<author>Joomla! Project</author>
<creationDate>August 2016</creationDate>
<copyright>(C) 2016 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_EDITORS-XTD_MENU_XML_DESCRIPTION</description>
<files>
<filename plugin="menu">menu.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors-xtd_menu.ini</language>
<language
tag="en-GB">en-GB.plg_editors-xtd_menu.sys.ini</language>
</languages>
</extension>
editors-xtd/module/module.php000064400000002702147357022240012304
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors-xtd.module
*
* @copyright (C) 2015 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Editor Module button
*
* @since 3.5
*/
class PlgButtonModule extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.5
*/
protected $autoloadLanguage = true;
/**
* Display the button
*
* @param string $name The name of the button to add
*
* @return JObject The button options as JObject
*
* @since 3.5
*/
public function onDisplay($name)
{
/*
* Use the built-in element view to select the module.
* Currently uses blank class.
*/
$user = JFactory::getUser();
if ($user->authorise('core.create', 'com_modules')
|| $user->authorise('core.edit', 'com_modules')
|| $user->authorise('core.edit.own',
'com_modules'))
{
$link =
'index.php?option=com_modules&view=modules&layout=modal&tmpl=component&editor='
. $name . '&' . JSession::getFormToken() .
'=1';
$button = new JObject;
$button->modal = true;
$button->class = 'btn';
$button->link = $link;
$button->text = JText::_('PLG_MODULE_BUTTON_MODULE');
$button->name = 'file-add';
$button->options = "{handler: 'iframe', size: {x: 800,
y: 500}}";
return $button;
}
}
}
editors-xtd/module/module.xml000064400000001422147357022240012313
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.6" type="plugin"
group="editors-xtd" method="upgrade">
<name>plg_editors-xtd_module</name>
<author>Joomla! Project</author>
<creationDate>October 2015</creationDate>
<copyright>(C) 2015 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.5.0</version>
<description>PLG_MODULE_XML_DESCRIPTION</description>
<files>
<filename plugin="module">module.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors-xtd_module.ini</language>
<language
tag="en-GB">en-GB.plg_editors-xtd_module.sys.ini</language>
</languages>
</extension>
editors-xtd/pagebreak/pagebreak.php000064400000003632147357022240013377
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors-xtd.pagebreak
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Editor Pagebreak button
*
* @since 1.5
*/
class PlgButtonPagebreak extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Display the button
*
* @param string $name The name of the button to add
*
* @return JObject The button options as JObject
*
* @since 1.5
*/
public function onDisplay($name)
{
$input = JFactory::getApplication()->input;
$user = JFactory::getUser();
// Can create in any category (component permission) or at least in one
category
$canCreateRecords = $user->authorise('core.create',
'com_content')
|| count($user->getAuthorisedCategories('com_content',
'core.create')) > 0;
// Instead of checking edit on all records, we can use **same** check as
the form editing view
$values = (array)
JFactory::getApplication()->getUserState('com_content.edit.article.id');
$isEditingRecords = count($values);
// This ACL check is probably a double-check (form view already performed
checks)
$hasAccess = $canCreateRecords || $isEditingRecords;
if (!$hasAccess)
{
return;
}
JFactory::getDocument()->addScriptOptions('xtd-pagebreak',
array('editor' => $name));
$link =
'index.php?option=com_content&view=article&layout=pagebreak&tmpl=component&e_name='
. $name;
$button = new JObject;
$button->modal = true;
$button->class = 'btn';
$button->link = $link;
$button->text =
JText::_('PLG_EDITORSXTD_PAGEBREAK_BUTTON_PAGEBREAK');
$button->name = 'copy';
$button->options = "{handler: 'iframe', size: {x: 500,
y: 300}}";
return $button;
}
}
editors-xtd/pagebreak/pagebreak.xml000064400000001456147357022240013412
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="editors-xtd" method="upgrade">
<name>plg_editors-xtd_pagebreak</name>
<author>Joomla! Project</author>
<creationDate>August 2004</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_EDITORSXTD_PAGEBREAK_XML_DESCRIPTION</description>
<files>
<filename
plugin="pagebreak">pagebreak.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors-xtd_pagebreak.ini</language>
<language
tag="en-GB">en-GB.plg_editors-xtd_pagebreak.sys.ini</language>
</languages>
</extension>
editors-xtd/readmore/readmore.php000064400000002507147357022240013131
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors-xtd.readmore
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Editor Readmore button
*
* @since 1.5
*/
class PlgButtonReadmore extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Readmore button
*
* @param string $name The name of the button to add
*
* @return JObject The button options as JObject
*
* @since 1.5
*/
public function onDisplay($name)
{
JHtml::_('script',
'com_content/admin-article-readmore.min.js',
array('version' => 'auto', 'relative'
=> true));
// Pass some data to javascript
JFactory::getDocument()->addScriptOptions(
'xtd-readmore',
array(
'editor' => $this->_subject->getContent($name),
'exists' =>
JText::_('PLG_READMORE_ALREADY_EXISTS', true),
)
);
$button = new JObject;
$button->modal = false;
$button->class = 'btn';
$button->onclick = 'insertReadmore(\'' . $name .
'\');return false;';
$button->text = JText::_('PLG_READMORE_BUTTON_READMORE');
$button->name = 'arrow-down';
$button->link = '#';
return $button;
}
}
editors-xtd/readmore/readmore.xml000064400000001434147357022240013140
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="editors-xtd" method="upgrade">
<name>plg_editors-xtd_readmore</name>
<author>Joomla! Project</author>
<creationDate>March 2006</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_READMORE_XML_DESCRIPTION</description>
<files>
<filename plugin="readmore">readmore.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_editors-xtd_readmore.ini</language>
<language
tag="en-GB">en-GB.plg_editors-xtd_readmore.sys.ini</language>
</languages>
</extension>
extension/joomla/joomla.php000064400000016167147357022240012054
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Extension.Joomla
*
* @copyright (C) 2010 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Joomla! master extension plugin.
*
* @since 1.6
*/
class PlgExtensionJoomla extends JPlugin
{
/**
* @var integer Extension Identifier
* @since 1.6
*/
private $eid = 0;
/**
* @var JInstaller Installer object
* @since 1.6
*/
private $installer = null;
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Adds an update site to the table if it doesn't exist.
*
* @param string $name The friendly name of the site
* @param string $type The type of site (e.g. collection or
extension)
* @param string $location The URI for the site
* @param boolean $enabled If this site is enabled
* @param string $extraQuery Any additional request query to use when
updating
*
* @return void
*
* @since 1.6
*/
private function addUpdateSite($name, $type, $location, $enabled,
$extraQuery = '')
{
$db = JFactory::getDbo();
// Look if the location is used already; doesn't matter what type
you can't have two types at the same address, doesn't make sense
$query = $db->getQuery(true)
->select('update_site_id')
->from('#__update_sites')
->where('location = ' . $db->quote($location));
$db->setQuery($query);
$update_site_id = (int) $db->loadResult();
// If it doesn't exist, add it!
if (!$update_site_id)
{
$query->clear()
->insert('#__update_sites')
->columns(
array(
$db->quoteName('name'),
$db->quoteName('type'),
$db->quoteName('location'),
$db->quoteName('enabled'),
$db->quoteName('extra_query')
)
)
->values(
$db->quote($name) . ', '
. $db->quote($type) . ', '
// Trim to remove any whitespace from the XML file before saving the
location to the db
. $db->quote(trim($location)) . ', '
. (int) $enabled . ', '
. $db->quote($extraQuery)
);
$db->setQuery($query);
if ($db->execute())
{
// Link up this extension to the update site
$update_site_id = $db->insertid();
}
}
// Check if it has an update site id (creation might have failed)
if ($update_site_id)
{
// Look for an update site entry that exists
$query->clear()
->select('update_site_id')
->from('#__update_sites_extensions')
->where('update_site_id = ' . $update_site_id)
->where('extension_id = ' . $this->eid);
$db->setQuery($query);
$tmpid = (int) $db->loadResult();
if (!$tmpid)
{
// Link this extension to the relevant update site
$query->clear()
->insert('#__update_sites_extensions')
->columns(array($db->quoteName('update_site_id'),
$db->quoteName('extension_id')))
->values($update_site_id . ', ' . $this->eid);
$db->setQuery($query);
$db->execute();
}
}
}
/**
* Handle post extension install update sites
*
* @param JInstaller $installer Installer object
* @param integer $eid Extension Identifier
*
* @return void
*
* @since 1.6
*/
public function onExtensionAfterInstall($installer, $eid)
{
if ($eid)
{
$this->installer = $installer;
$this->eid = $eid;
// After an install we only need to do update sites
$this->processUpdateSites();
}
}
/**
* Handle extension uninstall
*
* @param JInstaller $installer Installer instance
* @param integer $eid Extension id
* @param boolean $result Installation result
*
* @return void
*
* @since 1.6
*/
public function onExtensionAfterUninstall($installer, $eid, $result)
{
// If we have a valid extension ID and the extension was successfully
uninstalled wipe out any
// update sites for it
if ($eid && $result)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->delete('#__update_sites_extensions')
->where('extension_id = ' . $eid);
$db->setQuery($query);
$db->execute();
// Delete any unused update sites
$query->clear()
->select('update_site_id')
->from('#__update_sites_extensions');
$db->setQuery($query);
$results = $db->loadColumn();
if (is_array($results))
{
// So we need to delete the update sites and their associated updates
$updatesite_delete = $db->getQuery(true);
$updatesite_delete->delete('#__update_sites');
$updatesite_query = $db->getQuery(true);
$updatesite_query->select('update_site_id')
->from('#__update_sites');
// If we get results back then we can exclude them
if (count($results))
{
$updatesite_query->where('update_site_id NOT IN (' .
implode(',', $results) . ')');
$updatesite_delete->where('update_site_id NOT IN (' .
implode(',', $results) . ')');
}
// So let's find what update sites we're about to nuke and
remove their associated extensions
$db->setQuery($updatesite_query);
$update_sites_pending_delete = $db->loadColumn();
if (is_array($update_sites_pending_delete) &&
count($update_sites_pending_delete))
{
// Nuke any pending updates with this site before we delete it
// TODO: investigate alternative of using a query after the delete
below with a query and not in like above
$query->clear()
->delete('#__updates')
->where('update_site_id IN (' . implode(',',
$update_sites_pending_delete) . ')');
$db->setQuery($query);
$db->execute();
}
// Note: this might wipe out the entire table if there are no
extensions linked
$db->setQuery($updatesite_delete);
$db->execute();
}
// Last but not least we wipe out any pending updates for the extension
$query->clear()
->delete('#__updates')
->where('extension_id = ' . $eid);
$db->setQuery($query);
$db->execute();
}
}
/**
* After update of an extension
*
* @param JInstaller $installer Installer object
* @param integer $eid Extension identifier
*
* @return void
*
* @since 1.6
*/
public function onExtensionAfterUpdate($installer, $eid)
{
if ($eid)
{
$this->installer = $installer;
$this->eid = $eid;
// Handle any update sites
$this->processUpdateSites();
}
}
/**
* Processes the list of update sites for an extension.
*
* @return void
*
* @since 1.6
*/
private function processUpdateSites()
{
$manifest = $this->installer->getManifest();
$updateservers = $manifest->updateservers;
if ($updateservers)
{
$children = $updateservers->children();
}
else
{
$children = array();
}
if (count($children))
{
foreach ($children as $child)
{
$attrs = $child->attributes();
$this->addUpdateSite($attrs['name'],
$attrs['type'], trim($child), true,
$this->installer->extraQuery);
}
}
else
{
$data = trim((string) $updateservers);
if ($data !== '')
{
// We have a single entry in the update server line, let us presume
this is an extension line
$this->addUpdateSite(JText::_('PLG_EXTENSION_JOOMLA_UNKNOWN_SITE'),
'extension', $data, true);
}
}
}
}
extension/joomla/joomla.xml000064400000001420147357022240012047
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="extension" method="upgrade">
<name>plg_extension_joomla</name>
<author>Joomla! Project</author>
<creationDate>May 2010</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_EXTENSION_JOOMLA_XML_DESCRIPTION</description>
<files>
<filename plugin="joomla">joomla.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_extension_joomla.ini</language>
<language
tag="en-GB">en-GB.plg_extension_joomla.sys.ini</language>
</languages>
</extension>
fields/calendar/calendar.php000064400000002361147357022240012055
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Calendar
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Calendar Plugin
*
* @since 3.7.0
*/
class PlgFieldsCalendar extends FieldsPlugin
{
/**
* Transforms the field into a DOM XML element and appends it as a child
on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param JForm $form The form.
*
* @return DOMElement
*
* @since 3.7.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm
$form)
{
$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);
if (!$fieldNode)
{
return $fieldNode;
}
// Set filter to user UTC
$fieldNode->setAttribute('filter', 'USER_UTC');
// Set field to use translated formats
$fieldNode->setAttribute('translateformat', '1');
$fieldNode->setAttribute('showtime',
$field->fieldparams->get('showtime', 0) ? 'true'
: 'false');
return $fieldNode;
}
}
fields/calendar/calendar.xml000064400000001504147357022240012064
0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_calendar</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_CALENDAR_XML_DESCRIPTION</description>
<files>
<filename plugin="calendar">calendar.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_calendar.ini</language>
<language
tag="en-GB">en-GB.plg_fields_calendar.sys.ini</language>
</languages>
</extension>
fields/calendar/params/calendar.xml000064400000000720147357022240013346
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="showtime"
type="radio"
label="PLG_FIELDS_CALENDAR_PARAMS_SHOWTIME_LABEL"
description="PLG_FIELDS_CALENDAR_PARAMS_SHOWTIME_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</form>
fields/calendar/tmpl/calendar.php000064400000001044147357022240013026
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Calendar
*
* @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;
$value = $field->value;
if ($value == '')
{
return;
}
if (is_array($value))
{
$value = implode(', ', $value);
}
$formatString = $field->fieldparams->get('showtime', 0) ?
'DATE_FORMAT_LC5' : 'DATE_FORMAT_LC4';
echo htmlentities(JHtml::_('date', $value,
JText::_($formatString)));
fields/checkboxes/checkboxes.php000064400000000722147357022240012766
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Checkboxes
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldslistplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Checkboxes Plugin
*
* @since 3.7.0
*/
class PlgFieldsCheckboxes extends FieldsListPlugin
{
}
fields/checkboxes/checkboxes.xml000064400000003073147357022240013001
0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_checkboxes</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_CHECKBOXES_XML_DESCRIPTION</description>
<files>
<filename
plugin="checkboxes">checkboxes.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_checkboxes.ini</language>
<language
tag="en-GB">en-GB.plg_fields_checkboxes.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="options"
type="subform"
label="PLG_FIELDS_CHECKBOXES_PARAMS_OPTIONS_LABEL"
description="PLG_FIELDS_CHECKBOXES_PARAMS_OPTIONS_DESC"
layout="joomla.form.field.subform.repeatable-table"
icon="list"
multiple="true"
>
<form hidden="true" name="list_templates_modal"
repeat="true">
<field
name="name"
type="text"
label="PLG_FIELDS_CHECKBOXES_PARAMS_OPTIONS_NAME_LABEL"
size="30"
/>
<field
name="value"
type="text"
label="PLG_FIELDS_CHECKBOXES_PARAMS_OPTIONS_VALUE_LABEL"
size="30"
/>
</form>
</field>
</fieldset>
</fields>
</config>
</extension>
fields/checkboxes/params/checkboxes.xml000064400000001373147357022240014265
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="options"
type="subform"
label="PLG_FIELDS_CHECKBOXES_PARAMS_OPTIONS_LABEL"
description="PLG_FIELDS_CHECKBOXES_PARAMS_OPTIONS_DESC"
layout="joomla.form.field.subform.repeatable-table"
icon="list"
multiple="true"
>
<form hidden="true" name="list_templates_modal"
repeat="true">
<field
name="name"
type="text"
label="PLG_FIELDS_CHECKBOXES_PARAMS_OPTIONS_NAME_LABEL"
size="30"
/>
<field
name="value"
type="text"
label="PLG_FIELDS_CHECKBOXES_PARAMS_OPTIONS_VALUE_LABEL"
size="30"
/>
</form>
</field>
</fieldset>
</fields>
</form>
fields/checkboxes/tmpl/checkboxes.php000064400000001166147357022240013745
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Checkboxes
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
$fieldValue = $field->value;
if ($fieldValue === '' || $fieldValue === null)
{
return;
}
$fieldValue = (array) $fieldValue;
$texts = array();
$options = $this->getOptionsFromField($field);
foreach ($options as $value => $name)
{
if (in_array((string) $value, $fieldValue))
{
$texts[] = JText::_($name);
}
}
echo htmlentities(implode(', ', $texts));
fields/color/color.php000064400000002011147357022240010757 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Color
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Color Plugin
*
* @since 3.7.0
*/
class PlgFieldsColor extends FieldsPlugin
{
/**
* Transforms the field into a DOM XML element and appends it as a child
on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param JForm $form The form.
*
* @return DOMElement
*
* @since 3.7.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm
$form)
{
$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);
if (!$fieldNode)
{
return $fieldNode;
}
$fieldNode->setAttribute('validate', 'color');
return $fieldNode;
}
}
fields/color/color.xml000064400000001430147357022240010774 0ustar00<?xml
version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_color</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_COLOR_XML_DESCRIPTION</description>
<files>
<filename plugin="color">color.php</filename>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_color.ini</language>
<language
tag="en-GB">en-GB.plg_fields_color.sys.ini</language>
</languages>
</extension>
fields/color/tmpl/color.php000064400000000623147357022240011742
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Color
*
* @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;
$value = $field->value;
if ($value == '')
{
return;
}
if (is_array($value))
{
$value = implode(', ', $value);
}
echo htmlentities($value);
fields/editor/editor.php000064400000002271147357022240011307
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Editor
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Editor Plugin
*
* @since 3.7.0
*/
class PlgFieldsEditor extends FieldsPlugin
{
/**
* Transforms the field into a DOM XML element and appends it as a child
on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param JForm $form The form.
*
* @return DOMElement
*
* @since 3.7.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm
$form)
{
$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);
if (!$fieldNode)
{
return $fieldNode;
}
$fieldNode->setAttribute('buttons',
$field->fieldparams->get('buttons',
$this->params->get('buttons', 0)) ? 'true' :
'false');
$fieldNode->setAttribute('hide', implode(',',
$field->fieldparams->get('hide', array())));
return $fieldNode;
}
}
fields/editor/editor.xml000064400000004501147357022240011316
0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_editor</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_EDITOR_XML_DESCRIPTION</description>
<files>
<filename plugin="editor">editor.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_editor.ini</language>
<language
tag="en-GB">en-GB.plg_fields_editor.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="buttons"
type="radio"
label="PLG_FIELDS_EDITOR_PARAMS_SHOW_BUTTONS_LABEL"
description="PLG_FIELDS_EDITOR_PARAMS_SHOW_BUTTONS_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="hide"
type="plugins"
label="PLG_FIELDS_EDITOR_PARAMS_BUTTONS_HIDE_LABEL"
description="JGLOBAL_SELECT_SOME_OPTIONS"
folder="editors-xtd"
multiple="true"
/>
<field
name="width"
type="text"
label="PLG_FIELDS_EDITOR_PARAMS_WIDTH_LABEL"
description="PLG_FIELDS_EDITOR_PARAMS_WIDTH_DESC"
default="100%"
size="5"
/>
<field
name="height"
type="text"
label="PLG_FIELDS_EDITOR_PARAMS_HEIGHT_LABEL"
description="PLG_FIELDS_EDITOR_PARAMS_HEIGHT_DESC"
default="250px"
size="5"
/>
<field
name="filter"
type="list"
label="PLG_FIELDS_EDITOR_PARAMS_FILTER_LABEL"
description="PLG_FIELDS_EDITOR_PARAMS_FILTER_DESC"
class="btn-group"
default="JComponentHelper::filterText"
validate="options"
>
<option value="0">JNO</option>
<option
value="raw">JLIB_FILTER_PARAMS_RAW</option>
<option
value="safehtml">JLIB_FILTER_PARAMS_SAFEHTML</option>
<option
value="JComponentHelper::filterText">JLIB_FILTER_PARAMS_TEXT</option>
</field>
</fieldset>
</fields>
</config>
</extension>
fields/editor/params/editor.xml000064400000002746147357022240012612
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="buttons"
type="list"
label="PLG_FIELDS_EDITOR_PARAMS_SHOW_BUTTONS_LABEL"
description="PLG_FIELDS_EDITOR_PARAMS_SHOW_BUTTONS_DESC"
filter="integer"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="hide"
type="plugins"
label="PLG_FIELDS_EDITOR_PARAMS_BUTTONS_HIDE_LABEL"
description="JGLOBAL_SELECT_SOME_OPTIONS"
folder="editors-xtd"
multiple="true"
/>
<field
name="width"
type="text"
label="PLG_FIELDS_EDITOR_PARAMS_WIDTH_LABEL"
description="PLG_FIELDS_EDITOR_PARAMS_WIDTH_DESC"
size="5"
/>
<field
name="height"
type="text"
label="PLG_FIELDS_EDITOR_PARAMS_HEIGHT_LABEL"
description="PLG_FIELDS_EDITOR_PARAMS_HEIGHT_DESC"
size="5"
/>
<field
name="filter"
type="list"
label="PLG_FIELDS_TEXT_PARAMS_FILTER_LABEL"
description="PLG_FIELDS_TEXT_PARAMS_FILTER_DESC"
class="btn-group"
validate="options"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="0">JNO</option>
<option
value="raw">JLIB_FILTER_PARAMS_RAW</option>
<option
value="safehtml">JLIB_FILTER_PARAMS_SAFEHTML</option>
<option
value="JComponentHelper::filterText">JLIB_FILTER_PARAMS_TEXT</option>
</field>
</fieldset>
</fields>
</form>
fields/editor/tmpl/editor.php000064400000000546147357022240012266
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Editor
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
$value = $field->value;
if ($value == '')
{
return;
}
echo JHtml::_('content.prepare', $value);
fields/imagelist/imagelist.php000064400000002165147357022240012471
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Imagelist
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Imagelist Plugin
*
* @since 3.7.0
*/
class PlgFieldsImagelist extends FieldsPlugin
{
/**
* Transforms the field into a DOM XML element and appends it as a child
on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param JForm $form The form.
*
* @return DOMElement
*
* @since 3.7.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm
$form)
{
$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);
if (!$fieldNode)
{
return $fieldNode;
}
$fieldNode->setAttribute('hide_default', 'true');
$fieldNode->setAttribute('directory', '/images/' .
$fieldNode->getAttribute('directory'));
return $fieldNode;
}
}
fields/imagelist/imagelist.xml000064400000003436147357022240012504
0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_imagelist</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_IMAGELIST_XML_DESCRIPTION</description>
<files>
<filename
plugin="imagelist">imagelist.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_imagelist.ini</language>
<language
tag="en-GB">en-GB.plg_fields_imagelist.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="directory"
type="folderlist"
label="PLG_FIELDS_IMAGELIST_PARAMS_DIRECTORY_LABEL"
description="PLG_FIELDS_IMAGELIST_PARAMS_DIRECTORY_DESC"
directory="images"
hide_none="true"
hide_default="true"
recursive="true"
default="/"
>
<option value="/">/</option>
</field>
<field
name="multiple"
type="radio"
label="PLG_FIELDS_IMAGELIST_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_IMAGELIST_PARAMS_MULTIPLE_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="image_class"
type="textarea"
label="PLG_FIELDS_IMAGELIST_PARAMS_IMAGE_CLASS_LABEL"
description="PLG_FIELDS_IMAGELIST_PARAMS_IMAGE_CLASS_DESC"
size="40"
/>
</fieldset>
</fields>
</config>
</extension>
fields/imagelist/params/imagelist.xml000064400000002011147357022240013753
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="directory"
type="folderlist"
label="PLG_FIELDS_IMAGELIST_PARAMS_DIRECTORY_LABEL"
description="PLG_FIELDS_IMAGELIST_PARAMS_DIRECTORY_DESC"
directory="images"
hide_none="true"
hide_default="true"
recursive="true"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="/">/</option>
</field>
<field
name="multiple"
type="list"
label="PLG_FIELDS_IMAGELIST_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_IMAGELIST_PARAMS_MULTIPLE_DESC"
filter="integer"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="image_class"
type="textarea"
label="PLG_FIELDS_IMAGELIST_PARAMS_IMAGE_CLASS_LABEL"
description="PLG_FIELDS_IMAGELIST_PARAMS_IMAGE_CLASS_DESC"
size="40"
/>
</fieldset>
</fields>
</form>
fields/imagelist/tmpl/imagelist.php000064400000001711147357022240013441
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Imagelist
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
if ($field->value == '')
{
return;
}
$class = $fieldParams->get('image_class');
if ($class)
{
// space before, so if no class sprintf below works
$class = ' class="' . htmlentities($class, ENT_COMPAT,
'UTF-8', true) . '"';
}
$value = (array) $field->value;
$buffer = '';
foreach ($value as $path)
{
if (!$path || $path == '-1')
{
continue;
}
if ($fieldParams->get('directory', '/') !==
'/')
{
$buffer .= sprintf('<img
src="images/%s/%s"%s>',
$fieldParams->get('directory'),
htmlentities($path, ENT_COMPAT, 'UTF-8', true),
$class
);
}
else
{
$buffer .= sprintf('<img src="images/%s"%s>',
htmlentities($path, ENT_COMPAT, 'UTF-8', true),
$class
);
}
}
echo $buffer;
fields/integer/integer.php000064400000000701147357022240011621
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Integer
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Integer Plugin
*
* @since 3.7.0
*/
class PlgFieldsInteger extends FieldsPlugin
{
}
fields/integer/integer.xml000064400000003564147357022240011644
0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_integer</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_INTEGER_XML_DESCRIPTION</description>
<files>
<filename plugin="integer">integer.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_integer.ini</language>
<language
tag="en-GB">en-GB.plg_fields_integer.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="multiple"
type="radio"
label="PLG_FIELDS_INTEGER_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_INTEGER_PARAMS_MULTIPLE_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="first"
type="number"
label="PLG_FIELDS_INTEGER_PARAMS_FIRST_LABEL"
description="PLG_FIELDS_INTEGER_PARAMS_FIRST_DESC"
default="1"
filter="integer"
size="5"
/>
<field
name="last"
type="number"
label="PLG_FIELDS_INTEGER_PARAMS_LAST_LABEL"
description="PLG_FIELDS_INTEGER_PARAMS_LAST_DESC"
default="100"
filter="integer"
size="5"
/>
<field
name="step"
type="number"
label="PLG_FIELDS_INTEGER_PARAMS_STEP_LABEL"
description="PLG_FIELDS_INTEGER_PARAMS_STEP_DESC"
default="1"
filter="integer"
size="5"
/>
</fieldset>
</fields>
</config>
</extension>
fields/integer/params/integer.xml000064400000002010147357022240013110
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="multiple"
type="list"
label="PLG_FIELDS_INTEGER_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_INTEGER_PARAMS_MULTIPLE_DESC"
filter="integer"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="first"
type="number"
label="PLG_FIELDS_INTEGER_PARAMS_FIRST_LABEL"
description="PLG_FIELDS_INTEGER_PARAMS_FIRST_DESC"
filter="integer"
size="5"
/>
<field
name="last"
type="number"
label="PLG_FIELDS_INTEGER_PARAMS_LAST_LABEL"
description="PLG_FIELDS_INTEGER_PARAMS_LAST_DESC"
filter="integer"
size="5"
/>
<field
name="step"
type="number"
label="PLG_FIELDS_INTEGER_PARAMS_STEP_LABEL"
description="PLG_FIELDS_INTEGER_PARAMS_STEP_DESC"
filter="integer"
size="5"
/>
</fieldset>
</fields>
</form>
fields/integer/tmpl/integer.php000064400000000675147357022240012607
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Integer
*
* @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;
$value = $field->value;
if ($value == '')
{
return;
}
if (is_array($value))
{
$value = implode(', ', array_map('intval', $value));
}
else
{
$value = (int) $value;
}
echo $value;
fields/list/list.php000064400000002040147357022240010453 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.List
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldslistplugin',
JPATH_ADMINISTRATOR);
/**
* Fields list Plugin
*
* @since 3.7.0
*/
class PlgFieldsList extends FieldsListPlugin
{
/**
* Prepares the field
*
* @param string $context The context.
* @param stdclass $item The item.
* @param stdclass $field The field.
*
* @return object
*
* @since 3.9.2
*/
public function onCustomFieldsPrepareField($context, $item, $field)
{
// Check if the field should be processed
if (!$this->isTypeSupported($field->type))
{
return;
}
// The field's rawvalue should be an array
if (!is_array($field->rawvalue))
{
$field->rawvalue = (array) $field->rawvalue;
}
return parent::onCustomFieldsPrepareField($context, $item, $field);
}
}
fields/list/list.xml000064400000003426147357022240010475 0ustar00<?xml
version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_list</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_LIST_XML_DESCRIPTION</description>
<files>
<filename plugin="list">list.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_list.ini</language>
<language
tag="en-GB">en-GB.plg_fields_list.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="multiple"
type="radio"
label="PLG_FIELDS_LIST_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_LIST_PARAMS_MULTIPLE_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="options"
type="subform"
label="PLG_FIELDS_LIST_PARAMS_OPTIONS_LABEL"
description="PLG_FIELDS_LIST_PARAMS_OPTIONS_DESC"
layout="joomla.form.field.subform.repeatable-table"
icon="list"
multiple="true"
>
<form hidden="true" name="list_templates_modal"
repeat="true">
<field
name="name"
type="text"
label="PLG_FIELDS_LIST_PARAMS_OPTIONS_NAME_LABEL"
size="30"
/>
<field
name="value"
type="text"
label="PLG_FIELDS_LIST_PARAMS_OPTIONS_VALUE_LABEL"
size="30"
/>
</form>
</field>
</fieldset>
</fields>
</config>
</extension>
fields/list/params/list.xml000064400000002043147357022240011752
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="multiple"
type="list"
label="PLG_FIELDS_LIST_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_LIST_PARAMS_MULTIPLE_DESC"
filter="integer"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="options"
type="subform"
label="PLG_FIELDS_LIST_PARAMS_OPTIONS_LABEL"
description="PLG_FIELDS_LIST_PARAMS_OPTIONS_DESC"
layout="joomla.form.field.subform.repeatable-table"
icon="list"
multiple="true"
>
<form hidden="true" name="list_templates_modal"
repeat="true">
<field
name="name"
type="text"
label="PLG_FIELDS_LIST_PARAMS_OPTIONS_NAME_LABEL"
size="30"
/>
<field
name="value"
type="text"
label="PLG_FIELDS_LIST_PARAMS_OPTIONS_VALUE_LABEL"
size="30"
/>
</form>
</field>
</fieldset>
</fields>
</form>
fields/list/tmpl/list.php000064400000001130147357022240011426
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.List
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
$fieldValue = $field->value;
if ($fieldValue == '')
{
return;
}
$fieldValue = (array) $fieldValue;
$texts = array();
$options = $this->getOptionsFromField($field);
foreach ($options as $value => $name)
{
if (in_array((string) $value, $fieldValue))
{
$texts[] = JText::_($name);
}
}
echo htmlentities(implode(', ', $texts));
fields/media/media.php000064400000002014147357022240010664 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Media
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Media Plugin
*
* @since 3.7.0
*/
class PlgFieldsMedia extends FieldsPlugin
{
/**
* Transforms the field into a DOM XML element and appends it as a child
on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param JForm $form The form.
*
* @return DOMElement
*
* @since 3.7.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm
$form)
{
$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);
if (!$fieldNode)
{
return $fieldNode;
}
$fieldNode->setAttribute('hide_default', 'true');
return $fieldNode;
}
}
fields/media/media.xml000064400000003350147357022240010701 0ustar00<?xml
version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_media</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_MEDIA_XML_DESCRIPTION</description>
<files>
<filename plugin="media">media.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_media.ini</language>
<language
tag="en-GB">en-GB.plg_fields_media.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="directory"
type="folderlist"
label="PLG_FIELDS_MEDIA_PARAMS_DIRECTORY_LABEL"
description="PLG_FIELDS_MEDIA_PARAMS_DIRECTORY_DESC"
directory="images"
hide_none="true"
recursive="true"
/>
<field
name="preview"
type="list"
label="PLG_FIELDS_MEDIA_PARAMS_PREVIEW_LABEL"
description="PLG_FIELDS_MEDIA_PARAMS_PREVIEW_DESC"
class="btn-group"
default="tooltip"
>
<option
value="tooltip">PLG_FIELDS_MEDIA_PARAMS_PREVIEW_TOOLTIP</option>
<option
value="true">PLG_FIELDS_MEDIA_PARAMS_PREVIEW_INLINE</option>
<option value="false">JNO</option>
</field>
<field
name="image_class"
type="textarea"
label="PLG_FIELDS_MEDIA_PARAMS_IMAGE_CLASS_LABEL"
description="PLG_FIELDS_MEDIA_PARAMS_IMAGE_CLASS_DESC"
size="40"
/>
</fieldset>
</fields>
</config>
</extension>
fields/media/params/media.xml000064400000001720147357022240012163
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="directory"
type="folderlist"
label="PLG_FIELDS_MEDIA_PARAMS_DIRECTORY_LABEL"
description="PLG_FIELDS_MEDIA_PARAMS_DIRECTORY_DESC"
directory="images"
hide_none="true"
recursive="true"
/>
<field
name="preview"
type="list"
label="PLG_FIELDS_MEDIA_PARAMS_PREVIEW_LABEL"
description="PLG_FIELDS_MEDIA_PARAMS_PREVIEW_DESC"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option
value="tooltip">PLG_FIELDS_MEDIA_PARAMS_PREVIEW_TOOLTIP</option>
<option
value="true">PLG_FIELDS_MEDIA_PARAMS_PREVIEW_INLINE</option>
<option value="false">JNO</option>
</field>
<field
name="image_class"
type="textarea"
label="PLG_FIELDS_MEDIA_PARAMS_IMAGE_CLASS_LABEL"
description="PLG_FIELDS_MEDIA_PARAMS_IMAGE_CLASS_DESC"
size="40"
/>
</fieldset>
</fields>
</form>
fields/media/tmpl/media.php000064400000001230147357022240011637
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Media
*
* @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;
if ($field->value == '')
{
return;
}
$class = $fieldParams->get('image_class');
if ($class)
{
$class = ' class="' . htmlentities($class, ENT_COMPAT,
'UTF-8', true) . '"';
}
$value = (array) $field->value;
$buffer = '';
foreach ($value as $path)
{
if (!$path)
{
continue;
}
$buffer .= sprintf('<img src="%s"%s>',
htmlentities($path, ENT_COMPAT, 'UTF-8', true),
$class
);
}
echo $buffer;
fields/radio/params/radio.xml000064400000001777147357022240012235
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="options"
type="subform"
label="PLG_FIELDS_RADIO_PARAMS_OPTIONS_LABEL"
description="PLG_FIELDS_RADIO_PARAMS_OPTIONS_DESC"
layout="joomla.form.field.subform.repeatable-table"
icon="list"
multiple="true"
>
<form hidden="true" name="list_templates_modal"
repeat="true">
<field
name="name"
type="text"
label="PLG_FIELDS_RADIO_PARAMS_OPTIONS_NAME_LABEL"
size="30"
/>
<field
name="value"
type="text"
label="PLG_FIELDS_RADIO_PARAMS_OPTIONS_VALUE_LABEL"
size="30"
/>
</form>
</field>
</fieldset>
</fields>
<fields name="params">
<fieldset name="basic">
<field
name="class"
type="textarea"
label="COM_FIELDS_FIELD_CLASS_LABEL"
description="COM_FIELDS_FIELD_CLASS_DESC"
class="input-xxlarge"
size="40"
default="btn-group"
/>
</fieldset>
</fields>
</form>
fields/radio/radio.php000064400000000703147357022240010725 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Radio
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldslistplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Radio Plugin
*
* @since 3.7.0
*/
class PlgFieldsRadio extends FieldsListPlugin
{
}
fields/radio/radio.xml000064400000003011147357022240010731 0ustar00<?xml
version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_radio</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_RADIO_XML_DESCRIPTION</description>
<files>
<filename plugin="radio">radio.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_radio.ini</language>
<language
tag="en-GB">en-GB.plg_fields_radio.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="options"
type="subform"
label="PLG_FIELDS_RADIO_PARAMS_OPTIONS_LABEL"
description="PLG_FIELDS_RADIO_PARAMS_OPTIONS_DESC"
layout="joomla.form.field.subform.repeatable-table"
icon="list"
multiple="true"
>
<form hidden="true" name="list_templates_modal"
repeat="true">
<field
name="name"
type="text"
label="PLG_FIELDS_RADIO_PARAMS_OPTIONS_NAME_LABEL"
size="30"
/>
<field
name="value"
type="text"
label="PLG_FIELDS_RADIO_PARAMS_OPTIONS_VALUE_LABEL"
size="30"
/>
</form>
</field>
</fieldset>
</fields>
</config>
</extension>
fields/radio/tmpl/radio.php000064400000001124147357022240011677
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Radio
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
$value = $field->value;
if ($value == '')
{
return;
}
$value = (array) $value;
$texts = array();
$options = $this->getOptionsFromField($field);
foreach ($options as $optionValue => $optionText)
{
if (in_array((string) $optionValue, $value))
{
$texts[] = JText::_($optionText);
}
}
echo htmlentities(implode(', ', $texts));
fields/repeatable/params/repeatable.xml000064400000004710147357022240014237
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="fields"
type="subform"
label="PLG_FIELDS_REPEATABLE_PARAMS_FIELDS_LABEL"
description="PLG_FIELDS_REPEATABLE_PARAMS_FIELDS_DESC"
multiple="true">
<form>
<fields>
<fieldset>
<field
name="fieldname"
type="text"
label="PLG_FIELDS_REPEATABLE_PARAMS_FIELDNAME_NAME_LABEL"
description="PLG_FIELDS_REPEATABLE_PARAMS_FIELDNAME_NAME_DESC"
required="true"
/>
<field
name="fieldtype"
type="list"
label="PLG_FIELDS_REPEATABLE_PARAMS_FIELDNAME_TYPE_LABEL"
description="PLG_FIELDS_REPEATABLE_PARAMS_FIELDNAME_TYPE_DESC"
>
<option
value="editor">PLG_FIELDS_REPEATABLE_PARAMS_FIELDNAME_TYPE_EDITOR</option>
<option
value="media">PLG_FIELDS_REPEATABLE_PARAMS_FIELDNAME_TYPE_MEDIA</option>
<option
value="number">PLG_FIELDS_REPEATABLE_PARAMS_FIELDNAME_TYPE_NUMBER</option>
<option
value="text">PLG_FIELDS_REPEATABLE_PARAMS_FIELDNAME_TYPE_TEXT</option>
<option
value="textarea">PLG_FIELDS_REPEATABLE_PARAMS_FIELDNAME_TYPE_TEXTAREA</option>
</field>
<field
name="fieldfilter"
type="list"
label="PLG_FIELDS_TEXT_PARAMS_FILTER_LABEL"
description="PLG_FIELDS_TEXT_PARAMS_FILTER_DESC"
class="btn-group"
validate="options"
showon="fieldtype!:media,number"
>
<option value="0">JNO</option>
<option
showon="fieldtype:editor,text,textarea"
value="raw">JLIB_FILTER_PARAMS_RAW</option>
<option
showon="fieldtype:editor,text,textarea"
value="safehtml">JLIB_FILTER_PARAMS_SAFEHTML</option>
<option
showon="fieldtype:editor,text,textarea"
value="JComponentHelper::filterText">JLIB_FILTER_PARAMS_TEXT</option>
<option
showon="fieldtype:text,textarea"
value="alnum">JLIB_FILTER_PARAMS_ALNUM</option>
<option
showon="fieldtype:text,textarea"
value="integer">JLIB_FILTER_PARAMS_INTEGER</option>
<option
showon="fieldtype:text,textarea"
value="float">JLIB_FILTER_PARAMS_FLOAT</option>
<option
showon="fieldtype:text,textarea"
value="tel">JLIB_FILTER_PARAMS_TEL</option>
</field>
</fieldset>
</fields>
</form>
</field>
</fieldset>
</fields>
</form>
fields/repeatable/repeatable.php000064400000007333147357022240012747
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Repeatable
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Repeatable plugin.
*
* @since 3.9.0
*/
class PlgFieldsRepeatable extends FieldsPlugin
{
/**
* Transforms the field into a DOM XML element and appends it as a child
on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param JForm $form The form.
*
* @return DOMElement
*
* @since 3.9.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm
$form)
{
$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);
if (!$fieldNode)
{
return $fieldNode;
}
$readonly = false;
if (!FieldsHelper::canEditFieldValue($field))
{
$readonly = true;
}
$fieldNode->setAttribute('type', 'subform');
$fieldNode->setAttribute('multiple', 'true');
$fieldNode->setAttribute('layout',
'joomla.form.field.subform.repeatable-table');
// Build the form source
$fieldsXml = new SimpleXMLElement('<form/>');
$fields = $fieldsXml->addChild('fields');
// Get the form settings
$formFields = $field->fieldparams->get('fields');
// Add the fields to the form
foreach ($formFields as $index => $formField)
{
$child = $fields->addChild('field');
$child->addAttribute('name', $formField->fieldname);
$child->addAttribute('type', $formField->fieldtype);
$child->addAttribute('readonly', $readonly);
if (isset($formField->fieldfilter))
{
$child->addAttribute('filter',
$formField->fieldfilter);
}
}
$fieldNode->setAttribute('formsource',
$fieldsXml->asXML());
// Return the node
return $fieldNode;
}
/**
* The save event.
*
* @param string $context The context
* @param JTable $item The article data
* @param boolean $isNew Is new item
* @param array $data The validated data
*
* @return boolean
*
* @since 3.9.0
*/
public function onContentAfterSave($context, $item, $isNew, $data =
array())
{
// Create correct context for category
if ($context == 'com_categories.category')
{
$context = $item->get('extension') .
'.categories';
// Set the catid on the category to get only the fields which belong to
this category
$item->set('catid', $item->get('id'));
}
// Check the context
$parts = FieldsHelper::extract($context, $item);
if (!$parts)
{
return true;
}
// Compile the right context for the fields
$context = $parts[0] . '.' . $parts[1];
// Loading the fields
$fields = FieldsHelper::getFields($context, $item);
if (!$fields)
{
return true;
}
// Get the fields data
$fieldsData = !empty($data['com_fields']) ?
$data['com_fields'] : array();
// Loading the model
/** @var FieldsModelField $model */
$model = BaseDatabaseModel::getInstance('Field',
'FieldsModel', array('ignore_request' => true));
// Loop over the fields
foreach ($fields as $field)
{
// Find the field of this type repeatable
if ($field->type !== $this->_name)
{
continue;
}
// Determine the value if it is available from the data
$value = key_exists($field->name, $fieldsData) ?
$fieldsData[$field->name] : null;
// Handle json encoded values
if (!is_array($value))
{
$value = json_decode($value, true);
}
// Setting the value for the field and the item
$model->setFieldValue($field->id, $item->get('id'),
json_encode($value));
}
return true;
}
}
fields/repeatable/repeatable.xml000064400000001556147357022240012761
0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.8.0"
group="fields" method="upgrade">
<name>plg_fields_repeatable</name>
<author>Joomla! Project</author>
<creationDate>April 2018</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_FIELDS_REPEATABLE_XML_DESCRIPTION</description>
<files>
<filename
plugin="repeatable">repeatable.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages folder="language">
<language
tag="en-GB">en-GB/en-GB.plg_fields_repeatable.ini</language>
<language
tag="en-GB">en-GB/en-GB.plg_fields_repeatable.sys.ini</language>
</languages>
</extension>
fields/repeatable/tmpl/repeatable.php000064400000001077147357022240013722
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Repeatable
*
* @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;
$fieldValue = $field->value;
if ($fieldValue === '')
{
return;
}
// Get the values
$fieldValues = json_decode($fieldValue, true);
if (empty($fieldValues))
{
return;
}
$html = '<ul>';
foreach ($fieldValues as $value)
{
$html .= '<li>' . implode(', ', $value) .
'</li>';
}
$html .= '</ul>';
echo $html;
fields/sql/params/sql.xml000064400000001223147357022240011421
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="query"
type="textarea"
label="PLG_FIELDS_SQL_PARAMS_QUERY_LABEL"
description="PLG_FIELDS_SQL_PARAMS_QUERY_DESC"
filter="raw"
rows="10"
required="true"
/>
<field
name="multiple"
type="list"
label="PLG_FIELDS_SQL_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_SQL_PARAMS_MULTIPLE_DESC"
filter="integer"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</form>
fields/sql/sql.php000064400000003516147357022240010134 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Sql
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldslistplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Sql Plugin
*
* @since 3.7.0
*/
class PlgFieldsSql extends FieldsListPlugin
{
/**
* Transforms the field into a DOM XML element and appends it as a child
on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param JForm $form The form.
*
* @return DOMElement
*
* @since 3.7.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm
$form)
{
$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);
if (!$fieldNode)
{
return $fieldNode;
}
$fieldNode->setAttribute('value_field', 'text');
$fieldNode->setAttribute('key_field', 'value');
return $fieldNode;
}
/**
* The save event.
*
* @param string $context The context
* @param JTable $item The table
* @param boolean $isNew Is new item
* @param array $data The validated data
*
* @return boolean
*
* @since 3.7.0
*/
public function onContentBeforeSave($context, $item, $isNew, $data =
array())
{
// Only work on new SQL fields
if ($context != 'com_fields.field' || !isset($item->type) ||
$item->type != 'sql')
{
return true;
}
// If we are not a super admin, don't let the user create or update
a SQL field
if (!JAccess::getAssetRules(1)->allow('core.admin',
JFactory::getUser()->getAuthorisedGroups()))
{
$item->setError(JText::_('PLG_FIELDS_SQL_CREATE_NOT_POSSIBLE'));
return false;
}
return true;
}
}
fields/sql/sql.xml000064400000002643147357022240010145 0ustar00<?xml
version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_sql</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_SQL_XML_DESCRIPTION</description>
<files>
<filename plugin="sql">sql.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_sql.ini</language>
<language
tag="en-GB">en-GB.plg_fields_sql.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="query"
type="textarea"
label="PLG_FIELDS_SQL_PARAMS_QUERY_LABEL"
description="PLG_FIELDS_SQL_PARAMS_QUERY_DESC"
rows="10"
filter="raw"
required="true"
/>
<field
name="multiple"
type="radio"
label="PLG_FIELDS_SQL_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_SQL_PARAMS_MULTIPLE_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
fields/sql/tmpl/sql.php000064400000001754147357022240011112
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Sql
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
$value = $field->value;
if ($value == '')
{
return;
}
$db = JFactory::getDbo();
$value = (array) $value;
$condition = '';
foreach ($value as $v)
{
if (!$v)
{
continue;
}
$condition .= ', ' . $db->q($v);
}
$query = $fieldParams->get('query', '');
// Run the query with a having condition because it supports aliases
$db->setQuery($query . ' having value in (' . trim($condition,
',') . ')');
try
{
$items = $db->loadObjectlist();
}
catch (Exception $e)
{
// If the query failed, we fetch all elements
$db->setQuery($query);
$items = $db->loadObjectlist();
}
$texts = array();
foreach ($items as $item)
{
if (in_array($item->value, $value))
{
$texts[] = $item->text;
}
}
echo htmlentities(implode(', ', $texts));
fields/text/params/text.xml000064400000002055147357022240011777
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="filter"
type="list"
label="PLG_FIELDS_TEXT_PARAMS_FILTER_LABEL"
description="PLG_FIELDS_TEXT_PARAMS_FILTER_DESC"
class="btn-group"
validate="options"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="0">JNO</option>
<option
value="raw">JLIB_FILTER_PARAMS_RAW</option>
<option
value="safehtml">JLIB_FILTER_PARAMS_SAFEHTML</option>
<option
value="JComponentHelper::filterText">JLIB_FILTER_PARAMS_TEXT</option>
<option
value="alnum">JLIB_FILTER_PARAMS_ALNUM</option>
<option
value="integer">JLIB_FILTER_PARAMS_INTEGER</option>
<option
value="float">JLIB_FILTER_PARAMS_FLOAT</option>
<option
value="tel">JLIB_FILTER_PARAMS_TEL</option>
</field>
<field
name="maxlength"
type="number"
label="PLG_FIELDS_TEXT_PARAMS_MAXLENGTH_LABEL"
description="PLG_FIELDS_TEXT_PARAMS_MAXLENGTH_DESC"
filter="integer"
/>
</fieldset>
</fields>
</form>
fields/text/text.php000064400000000670147357022240010504 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Text
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Text Plugin
*
* @since 3.7.0
*/
class PlgFieldsText extends FieldsPlugin
{
}
fields/text/text.xml000064400000003473147357022240010521 0ustar00<?xml
version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_text</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_TEXT_XML_DESCRIPTION</description>
<files>
<filename plugin="text">text.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_text.ini</language>
<language
tag="en-GB">en-GB.plg_fields_text.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="filter"
type="list"
label="PLG_FIELDS_TEXT_PARAMS_FILTER_LABEL"
description="PLG_FIELDS_TEXT_PARAMS_FILTER_DESC"
class="btn-group"
default="JComponentHelper::filterText"
validate="options"
>
<option value="0">JNO</option>
<option
value="raw">JLIB_FILTER_PARAMS_RAW</option>
<option
value="safehtml">JLIB_FILTER_PARAMS_SAFEHTML</option>
<option
value="JComponentHelper::filterText">JLIB_FILTER_PARAMS_TEXT</option>
<option
value="alnum">JLIB_FILTER_PARAMS_ALNUM</option>
<option
value="integer">JLIB_FILTER_PARAMS_INTEGER</option>
<option
value="float">JLIB_FILTER_PARAMS_FLOAT</option>
<option
value="tel">JLIB_FILTER_PARAMS_TEL</option>
</field>
<field
name="maxlength"
type="number"
label="PLG_FIELDS_TEXT_PARAMS_MAXLENGTH_LABEL"
description="PLG_FIELDS_TEXT_PARAMS_MAXLENGTH_DESC"
filter="integer"
/>
</fieldset>
</fields>
</config>
</extension>
fields/text/tmpl/text.php000064400000000622147357022240011455
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Text
*
* @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;
$value = $field->value;
if ($value == '')
{
return;
}
if (is_array($value))
{
$value = implode(', ', $value);
}
echo htmlentities($value);
fields/textarea/params/textarea.xml000064400000002671147357022240013465
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="rows"
type="number"
label="PLG_FIELDS_TEXTAREA_PARAMS_ROWS_LABEL"
description="PLG_FIELDS_TEXTAREA_PARAMS_ROWS_DESC"
filter="integer"
size="5"
/>
<field
name="cols"
type="number"
label="PLG_FIELDS_TEXTAREA_PARAMS_COLS_LABEL"
description="PLG_FIELDS_TEXTAREA_PARAMS_COLS_DESC"
filter="integer"
size="5"
/>
<field
name="maxlength"
type="number"
label="PLG_FIELDS_TEXTAREA_PARAMS_MAXLENGTH_LABEL"
description="PLG_FIELDS_TEXTAREA_PARAMS_MAXLENGTH_DESC"
filter="integer"
/>
<field
name="filter"
type="list"
label="PLG_FIELDS_TEXTAREA_PARAMS_FILTER_LABEL"
description="PLG_FIELDS_TEXTAREA_PARAMS_FILTER_DESC"
class="btn-group"
validate="options"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="0">JNO</option>
<option
value="raw">JLIB_FILTER_PARAMS_RAW</option>
<option
value="safehtml">JLIB_FILTER_PARAMS_SAFEHTML</option>
<option
value="JComponentHelper::filterText">JLIB_FILTER_PARAMS_TEXT</option>
<option
value="alnum">JLIB_FILTER_PARAMS_ALNUM</option>
<option
value="integer">JLIB_FILTER_PARAMS_INTEGER</option>
<option
value="float">JLIB_FILTER_PARAMS_FLOAT</option>
<option
value="tel">JLIB_FILTER_PARAMS_TEL</option>
</field>
</fieldset>
</fields>
</form>
fields/textarea/textarea.php000064400000000704147357022240012164
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Textarea
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Textarea Plugin
*
* @since 3.7.0
*/
class PlgFieldsTextarea extends FieldsPlugin
{
}
fields/textarea/textarea.xml000064400000004423147357022240012177
0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_textarea</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_TEXTAREA_XML_DESCRIPTION</description>
<files>
<filename plugin="textarea">textarea.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_textarea.ini</language>
<language
tag="en-GB">en-GB.plg_fields_textarea.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="rows"
type="number"
label="PLG_FIELDS_TEXTAREA_PARAMS_ROWS_LABEL"
description="PLG_FIELDS_TEXTAREA_PARAMS_ROWS_DESC"
default="10"
filter="integer"
size="5"
/>
<field
name="cols"
type="number"
label="PLG_FIELDS_TEXTAREA_PARAMS_COLS_LABEL"
description="PLG_FIELDS_TEXTAREA_PARAMS_COLS_DESC"
default="10"
filter="integer"
size="5"
/>
<field
name="maxlength"
type="number"
label="PLG_FIELDS_TEXTAREA_PARAMS_MAXLENGTH_LABEL"
description="PLG_FIELDS_TEXTAREA_PARAMS_MAXLENGTH_DESC"
filter="integer"
/>
<field
name="filter"
type="list"
label="PLG_FIELDS_TEXTAREA_PARAMS_FILTER_LABEL"
description="PLG_FIELDS_TEXTAREA_PARAMS_FILTER_DESC"
class="btn-group"
default="JComponentHelper::filterText"
validate="options"
>
<option value="0">JNO</option>
<option
value="raw">JLIB_FILTER_PARAMS_RAW</option>
<option
value="safehtml">JLIB_FILTER_PARAMS_SAFEHTML</option>
<option
value="JComponentHelper::filterText">JLIB_FILTER_PARAMS_TEXT</option>
<option
value="alnum">JLIB_FILTER_PARAMS_ALNUM</option>
<option
value="integer">JLIB_FILTER_PARAMS_INTEGER</option>
<option
value="float">JLIB_FILTER_PARAMS_FLOAT</option>
<option
value="tel">JLIB_FILTER_PARAMS_TEL</option>
</field>
</fieldset>
</fields>
</config>
</extension>
fields/textarea/tmpl/textarea.php000064400000000550147357022240013137
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Textarea
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
$value = $field->value;
if ($value == '')
{
return;
}
echo JHtml::_('content.prepare', $value);
fields/url/params/url.xml000064400000001560147357022240011433
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="schemes"
type="list"
label="PLG_FIELDS_URL_PARAMS_SCHEMES_LABEL"
description="PLG_FIELDS_URL_PARAMS_SCHEMES_DESC"
multiple="true"
>
<option value="http">HTTP</option>
<option value="https">HTTPS</option>
<option value="ftp">FTP</option>
<option value="ftps">FTPS</option>
<option value="file">FILE</option>
<option value="mailto">MAILTO</option>
</field>
<field
name="relative"
type="list"
label="PLG_FIELDS_URL_PARAMS_RELATIVE_LABEL"
description="PLG_FIELDS_URL_PARAMS_RELATIVE_DESC"
filter="integer"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</form>
fields/url/tmpl/url.php000064400000001042147357022240011106
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.URL
*
* @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;
$value = $field->value;
if ($value == '')
{
return;
}
$attributes = '';
if (!JUri::isInternal($value))
{
$attributes = ' rel="nofollow noopener noreferrer"
target="_blank"';
}
echo sprintf('<a href="%s"%s>%s</a>',
htmlspecialchars($value),
$attributes,
htmlspecialchars($value)
);
fields/url/url.php000064400000002144147357022240010136 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.URL
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields URL Plugin
*
* @since 3.7.0
*/
class PlgFieldsUrl extends FieldsPlugin
{
/**
* Transforms the field into a DOM XML element and appends it as a child
on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param JForm $form The form.
*
* @return DOMElement
*
* @since 3.7.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm
$form)
{
$fieldNode = parent::onCustomFieldsPrepareDom($field, $parent, $form);
if (!$fieldNode)
{
return $fieldNode;
}
$fieldNode->setAttribute('validate', 'url');
if (! $fieldNode->getAttribute('relative'))
{
$fieldNode->removeAttribute('relative');
}
return $fieldNode;
}
}
fields/url/url.xml000064400000003205147357022240010146 0ustar00<?xml
version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_url</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_URL_XML_DESCRIPTION</description>
<files>
<filename plugin="url">url.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_url.ini</language>
<language
tag="en-GB">en-GB.plg_fields_url.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="schemes"
type="list"
label="PLG_FIELDS_URL_PARAMS_SCHEMES_LABEL"
description="PLG_FIELDS_URL_PARAMS_SCHEMES_DESC"
multiple="true"
>
<option value="http">HTTP</option>
<option value="https">HTTPS</option>
<option value="ftp">FTP</option>
<option value="ftps">FTPS</option>
<option value="file">FILE</option>
<option value="mailto">MAILTO</option>
</field>
<field
name="relative"
type="radio"
label="PLG_FIELDS_URL_PARAMS_RELATIVE_LABEL"
description="PLG_FIELDS_URL_PARAMS_RELATIVE_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
fields/user/params/user.xml000064400000000600147357022240011755
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<field
name="default_value"
type="user"
label="PLG_FIELDS_USER_DEFAULT_VALUE_LABEL"
description="PLG_FIELDS_USER_DEFAULT_VALUE_DESC"
/>
<fields name="params"
label="COM_FIELDS_FIELD_BASIC_LABEL">
<fieldset name="basic">
<field
name="show_on"
type="hidden"
filter="unset"
/>
</fieldset>
</fields>
</form>
fields/user/tmpl/user.php000064400000001230147357022240011435
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.User
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
$value = $field->value;
if ($value == '')
{
return;
}
$value = (array) $value;
$texts = array();
foreach ($value as $userId)
{
if (!$userId)
{
continue;
}
$user = JFactory::getUser($userId);
if ($user)
{
// Use the Username
$texts[] = $user->name;
continue;
}
// Fallback and add the User ID if we get no JUser Object
$texts[] = $userId;
}
echo htmlentities(implode(', ', $texts));
fields/user/user.php000064400000002004147357022240010461 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.User
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields User Plugin
*
* @since 3.7.0
*/
class PlgFieldsUser extends FieldsPlugin
{
/**
* Transforms the field into a DOM XML element and appends it as a child
on the given parent.
*
* @param stdClass $field The field.
* @param DOMElement $parent The field node parent.
* @param JForm $form The form.
*
* @return DOMElement
*
* @since 3.7.0
*/
public function onCustomFieldsPrepareDom($field, DOMElement $parent, JForm
$form)
{
if (JFactory::getApplication()->isClient('site'))
{
// The user field is not working on the front end
return;
}
return parent::onCustomFieldsPrepareDom($field, $parent, $form);
}
}
fields/user/user.xml000064400000001422147357022240010475 0ustar00<?xml
version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_user</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_USER_XML_DESCRIPTION</description>
<files>
<filename plugin="user">user.php</filename>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_user.ini</language>
<language
tag="en-GB">en-GB.plg_fields_user.sys.ini</language>
</languages>
</extension>
fields/usergrouplist/params/usergrouplist.xml000064400000000735147357022240015710
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="fieldparams">
<fieldset name="fieldparams">
<field
name="multiple"
type="list"
label="PLG_FIELDS_USERGROUPLIST_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_USERGROUPLIST_PARAMS_MULTIPLE_DESC"
filter="integer"
>
<option
value="">COM_FIELDS_FIELD_USE_GLOBAL</option>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</form>
fields/usergrouplist/tmpl/usergrouplist.php000064400000001245147357022240015365
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Usergrouplist
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
$value = $field->value;
if ($value == '')
{
return;
}
JLoader::register('UsersHelper', JPATH_ADMINISTRATOR .
'/components/com_users/helpers/users.php');
$value = (array) $value;
$texts = array();
$groups = UsersHelper::getGroups();
foreach ($groups as $group)
{
if (in_array($group->value, $value))
{
$texts[] = htmlentities(trim($group->text, '- '));
}
}
echo htmlentities(implode(', ', $texts));
fields/usergrouplist/usergrouplist.php000064400000000723147357022240014411
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Fields.Usergrouplist
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::import('components.com_fields.libraries.fieldsplugin',
JPATH_ADMINISTRATOR);
/**
* Fields Usergrouplist Plugin
*
* @since 3.7.0
*/
class PlgFieldsUsergrouplist extends FieldsPlugin
{
}
fields/usergrouplist/usergrouplist.xml000064400000002440147357022240014420
0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="fields" method="upgrade">
<name>plg_fields_usergrouplist</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_FIELDS_USERGROUPLIST_XML_DESCRIPTION</description>
<files>
<filename
plugin="usergrouplist">usergrouplist.php</filename>
<folder>params</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_fields_usergrouplist.ini</language>
<language
tag="en-GB">en-GB.plg_fields_usergrouplist.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="multiple"
type="radio"
label="PLG_FIELDS_USERGROUPLIST_PARAMS_MULTIPLE_LABEL"
description="PLG_FIELDS_USERGROUPLIST_PARAMS_MULTIPLE_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
finder/categories/categories.php000064400000025202147357022240013005
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Finder.Categories
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Registry\Registry;
JLoader::register('FinderIndexerAdapter', JPATH_ADMINISTRATOR .
'/components/com_finder/helpers/indexer/adapter.php');
/**
* Smart Search adapter for Joomla Categories.
*
* @since 2.5
*/
class PlgFinderCategories extends FinderIndexerAdapter
{
/**
* The plugin identifier.
*
* @var string
* @since 2.5
*/
protected $context = 'Categories';
/**
* The extension name.
*
* @var string
* @since 2.5
*/
protected $extension = 'com_categories';
/**
* The sublayout to use when rendering the results.
*
* @var string
* @since 2.5
*/
protected $layout = 'category';
/**
* The type of content that the adapter indexes.
*
* @var string
* @since 2.5
*/
protected $type_title = 'Category';
/**
* The table name.
*
* @var string
* @since 2.5
*/
protected $table = '#__categories';
/**
* The field the published state is stored in.
*
* @var string
* @since 2.5
*/
protected $state_field = 'published';
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Method to remove the link information for items that have been deleted.
*
* @param string $context The context of the action being performed.
* @param JTable $table A JTable object containing the record to be
deleted
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderDelete($context, $table)
{
if ($context === 'com_categories.category')
{
$id = $table->id;
}
elseif ($context === 'com_finder.index')
{
$id = $table->link_id;
}
else
{
return true;
}
// Remove item from the index.
return $this->remove($id);
}
/**
* Smart Search after save content method.
* Reindexes the link information for a category that has been saved.
* It also makes adjustments if the access level of the category has
changed.
*
* @param string $context The context of the category passed to the
plugin.
* @param JTable $row A JTable object.
* @param boolean $isNew True if the category has just been created.
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderAfterSave($context, $row, $isNew)
{
// We only want to handle categories here.
if ($context === 'com_categories.category')
{
// Check if the access levels are different.
if (!$isNew && $this->old_access != $row->access)
{
// Process the change.
$this->itemAccessChange($row);
}
// Reindex the category item.
$this->reindex($row->id);
// Check if the parent access level is different.
if (!$isNew && $this->old_cataccess != $row->access)
{
$this->categoryAccessChange($row);
}
}
return true;
}
/**
* Smart Search before content save method.
* This event is fired before the data is actually saved.
*
* @param string $context The context of the category passed to the
plugin.
* @param JTable $row A JTable object.
* @param boolean $isNew True if the category is just about to be
created.
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderBeforeSave($context, $row, $isNew)
{
// We only want to handle categories here.
if ($context === 'com_categories.category')
{
// Query the database for the old access level and the parent if the
item isn't new.
if (!$isNew)
{
$this->checkItemAccess($row);
$this->checkCategoryAccess($row);
}
}
return true;
}
/**
* 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 category passed to the
plugin.
* @param array $pks An array of primary key ids of the category
that has changed state.
* @param integer $value The value of the state that the category
has been changed to.
*
* @return void
*
* @since 2.5
*/
public function onFinderChangeState($context, $pks, $value)
{
// We only want to handle categories here.
if ($context === 'com_categories.category')
{
/*
* The category published state is tied to the parent category
* published state so we need to look up all published states
* before we change anything.
*/
foreach ($pks as $pk)
{
$query = clone $this->getStateQuery();
$query->where('a.id = ' . (int) $pk);
$this->db->setQuery($query);
$item = $this->db->loadObject();
// Translate the state.
$state = null;
if ($item->parent_id != 1)
{
$state = $item->cat_state;
}
$temp = $this->translateState($value, $state);
// Update the item.
$this->change($pk, 'state', $temp);
// Reindex the item.
$this->reindex($pk);
}
}
// Handle when the plugin is disabled.
if ($context === 'com_plugins.plugin' && $value === 0)
{
$this->pluginDisable($pks);
}
}
/**
* Method to index an item. The item must be a FinderIndexerResult object.
*
* @param FinderIndexerResult $item The item to index as a
FinderIndexerResult object.
* @param string $format The item format. Not used.
*
* @return void
*
* @since 2.5
* @throws Exception on database error.
*/
protected function index(FinderIndexerResult $item, $format =
'html')
{
// Check if the extension is enabled.
if (JComponentHelper::isEnabled($this->extension) === false)
{
return;
}
// Check if the extension that owns the category is also enabled.
if (JComponentHelper::isEnabled($item->extension) === false)
{
return;
}
$item->setLanguage();
$extension = ucfirst(substr($item->extension, 4));
// Initialize the item parameters.
$item->params = new Registry($item->params);
$item->metadata = new Registry($item->metadata);
/*
* Add the metadata processing instructions based on the category's
* configuration parameters.
*/
// Add the meta author.
$item->metaauthor = $item->metadata->get('author');
// Handle the link to the metadata.
$item->addInstruction(FinderIndexer::META_CONTEXT, 'link');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metakey');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metadesc');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metaauthor');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'author');
// Deactivated Methods
// $item->addInstruction(FinderIndexer::META_CONTEXT,
'created_by_alias');
// Trigger the onContentPrepare event.
$item->summary =
FinderIndexerHelper::prepareContent($item->summary, $item->params);
// Build the necessary route and path information.
$item->url = $this->getUrl($item->id, $item->extension,
$this->layout);
$class = $extension . 'HelperRoute';
// Need to import component route helpers dynamically, hence the reason
it's handled here.
JLoader::register($class, JPATH_SITE . '/components/' .
$item->extension . '/helpers/route.php');
if (class_exists($class) && method_exists($class,
'getCategoryRoute'))
{
$item->route = $class::getCategoryRoute($item->id,
$item->language);
}
else
{
$item->route = ContentHelperRoute::getCategoryRoute($item->id,
$item->language);
}
$item->path = FinderIndexerHelper::getContentPath($item->route);
// Get the menu title if it exists.
$title = $this->getItemMenuTitle($item->url);
// Adjust the title if necessary.
if (!empty($title) &&
$this->params->get('use_menu_title', true))
{
$item->title = $title;
}
// Translate the state. Categories should only be published if the parent
category is published.
$item->state = $this->translateState($item->state);
// Add the type taxonomy data.
$item->addTaxonomy('Type', 'Category');
// Add the language taxonomy data.
$item->addTaxonomy('Language', $item->language);
// Get content extras.
FinderIndexerHelper::getContentExtras($item);
// Index the item.
$this->indexer->index($item);
}
/**
* Method to setup the indexer to be run.
*
* @return boolean True on success.
*
* @since 2.5
*/
protected function setup()
{
// Load com_content route helper as it is the fallback for routing in the
indexer in this instance.
JLoader::register('ContentHelperRoute', JPATH_SITE .
'/components/com_content/helpers/route.php');
return true;
}
/**
* Method to get the SQL query used to retrieve the list of content items.
*
* @param mixed $query A JDatabaseQuery object or null.
*
* @return JDatabaseQuery A database object.
*
* @since 2.5
*/
protected function getListQuery($query = null)
{
$db = JFactory::getDbo();
// Check if we can use the supplied SQL query.
$query = $query instanceof JDatabaseQuery ? $query :
$db->getQuery(true)
->select('a.id, a.title, a.alias, a.description AS summary,
a.extension')
->select('a.created_user_id AS created_by, a.modified_time AS
modified, a.modified_user_id AS modified_by')
->select('a.metakey, a.metadesc, a.metadata, a.language, a.lft,
a.parent_id, a.level')
->select('a.created_time AS start_date, a.published AS state,
a.access, a.params');
// Handle the alias CASE WHEN portion of the query.
$case_when_item_alias = ' CASE WHEN ';
$case_when_item_alias .= $query->charLength('a.alias',
'!=', '0');
$case_when_item_alias .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when_item_alias .= $query->concatenate(array($a_id,
'a.alias'), ':');
$case_when_item_alias .= ' ELSE ';
$case_when_item_alias .= $a_id . ' END as slug';
$query->select($case_when_item_alias)
->from('#__categories AS a')
->where($db->quoteName('a.id') . ' > 1');
return $query;
}
/**
* Method to get a SQL query to load the published and access states for
* a category and its parents.
*
* @return JDatabaseQuery A database object.
*
* @since 2.5
*/
protected function getStateQuery()
{
$query = $this->db->getQuery(true)
->select($this->db->quoteName('a.id'))
->select($this->db->quoteName('a.parent_id'))
->select('a.' . $this->state_field . ' AS state,
c.published AS cat_state')
->select('a.access, c.access AS cat_access')
->from($this->db->quoteName('#__categories') . '
AS a')
->join('LEFT', '#__categories AS c ON c.id =
a.parent_id');
return $query;
}
}
finder/categories/categories.xml000064400000001472147357022240013021
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="finder" method="upgrade">
<name>plg_finder_categories</name>
<author>Joomla! Project</author>
<creationDate>August 2011</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_FINDER_CATEGORIES_XML_DESCRIPTION</description>
<files>
<filename
plugin="categories">categories.php</filename>
</files>
<languages>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_categories.ini</language>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_categories.sys.ini</language>
</languages>
</extension>
finder/contacts/contacts.php000064400000030067147357022240012174
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Finder.Contacts
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Registry\Registry;
JLoader::register('FinderIndexerAdapter', JPATH_ADMINISTRATOR .
'/components/com_finder/helpers/indexer/adapter.php');
/**
* Finder adapter for Joomla Contacts.
*
* @since 2.5
*/
class PlgFinderContacts extends FinderIndexerAdapter
{
/**
* The plugin identifier.
*
* @var string
* @since 2.5
*/
protected $context = 'Contacts';
/**
* The extension name.
*
* @var string
* @since 2.5
*/
protected $extension = 'com_contact';
/**
* The sublayout to use when rendering the results.
*
* @var string
* @since 2.5
*/
protected $layout = 'contact';
/**
* The type of content that the adapter indexes.
*
* @var string
* @since 2.5
*/
protected $type_title = 'Contact';
/**
* The table name.
*
* @var string
* @since 2.5
*/
protected $table = '#__contact_details';
/**
* The field the published state is stored in.
*
* @var string
* @since 2.5
*/
protected $state_field = 'published';
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Method to update the item link information when the item category is
* changed. This is fired when the item category is published or
unpublished
* from the list view.
*
* @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 onFinderCategoryChangeState($extension, $pks, $value)
{
// Make sure we're handling com_contact categories
if ($extension === 'com_contact')
{
$this->categoryStateChange($pks, $value);
}
}
/**
* Method to remove the link information for items that have been deleted.
*
* This event will fire when contacts are deleted and when an indexed item
is deleted.
*
* @param string $context The context of the action being performed.
* @param JTable $table A JTable object containing the record to be
deleted
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderAfterDelete($context, $table)
{
if ($context === 'com_contact.contact')
{
$id = $table->id;
}
elseif ($context === 'com_finder.index')
{
$id = $table->link_id;
}
else
{
return true;
}
// Remove the items.
return $this->remove($id);
}
/**
* Method to determine if the access level of an item changed.
*
* @param string $context The context of the content passed to the
plugin.
* @param JTable $row A JTable object
* @param boolean $isNew If the content has just been created
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderAfterSave($context, $row, $isNew)
{
// We only want to handle contacts here
if ($context === 'com_contact.contact')
{
// Check if the access levels are different
if (!$isNew && $this->old_access != $row->access)
{
// Process the change.
$this->itemAccessChange($row);
}
// Reindex the item
$this->reindex($row->id);
}
// Check for access changes in the category
if ($context === 'com_categories.category')
{
// Check if the access levels are different
if (!$isNew && $this->old_cataccess != $row->access)
{
$this->categoryAccessChange($row);
}
}
return true;
}
/**
* Method to reindex the link information for an item that has been saved.
* This event is fired before the data is actually saved so we are going
* to queue the item to be indexed later.
*
* @param string $context The context of the content passed to the
plugin.
* @param JTable $row A JTable object
* @param boolean $isNew If the content is just about to be created
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderBeforeSave($context, $row, $isNew)
{
// We only want to handle contacts here
if ($context === 'com_contact.contact')
{
// Query the database for the old access level if the item isn't
new
if (!$isNew)
{
$this->checkItemAccess($row);
}
}
// Check for access levels from the category
if ($context === 'com_categories.category')
{
// Query the database for the old access level if the item isn't
new
if (!$isNew)
{
$this->checkCategoryAccess($row);
}
}
return true;
}
/**
* 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 onFinderChangeState($context, $pks, $value)
{
// We only want to handle contacts here
if ($context === 'com_contact.contact')
{
$this->itemStateChange($pks, $value);
}
// Handle when the plugin is disabled
if ($context === 'com_plugins.plugin' && $value === 0)
{
$this->pluginDisable($pks);
}
}
/**
* Method to index an item. The item must be a FinderIndexerResult object.
*
* @param FinderIndexerResult $item The item to index as a
FinderIndexerResult object.
* @param string $format The item format
*
* @return void
*
* @since 2.5
* @throws Exception on database error.
*/
protected function index(FinderIndexerResult $item, $format =
'html')
{
// Check if the extension is enabled
if (JComponentHelper::isEnabled($this->extension) === false)
{
return;
}
$item->setLanguage();
// Initialize the item parameters.
$item->params = new Registry($item->params);
// Build the necessary route and path information.
$item->url = $this->getUrl($item->id, $this->extension,
$this->layout);
$item->route = ContactHelperRoute::getContactRoute($item->slug,
$item->catslug, $item->language);
$item->path = FinderIndexerHelper::getContentPath($item->route);
// Get the menu title if it exists.
$title = $this->getItemMenuTitle($item->url);
// Adjust the title if necessary.
if (!empty($title) &&
$this->params->get('use_menu_title', true))
{
$item->title = $title;
}
/*
* Add the metadata processing instructions based on the contact
* configuration parameters.
*/
// Handle the contact position.
if ($item->params->get('show_position', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT,
'position');
}
// Handle the contact street address.
if ($item->params->get('show_street_address', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT,
'address');
}
// Handle the contact city.
if ($item->params->get('show_suburb', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT, 'city');
}
// Handle the contact region.
if ($item->params->get('show_state', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT,
'region');
}
// Handle the contact country.
if ($item->params->get('show_country', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT,
'country');
}
// Handle the contact zip code.
if ($item->params->get('show_postcode', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT, 'zip');
}
// Handle the contact telephone number.
if ($item->params->get('show_telephone', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT,
'telephone');
}
// Handle the contact fax number.
if ($item->params->get('show_fax', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT, 'fax');
}
// Handle the contact email address.
if ($item->params->get('show_email', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT,
'email');
}
// Handle the contact mobile number.
if ($item->params->get('show_mobile', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT,
'mobile');
}
// Handle the contact webpage.
if ($item->params->get('show_webpage', true))
{
$item->addInstruction(FinderIndexer::META_CONTEXT,
'webpage');
}
// Handle the contact user name.
$item->addInstruction(FinderIndexer::META_CONTEXT, 'user');
// Add the type taxonomy data.
$item->addTaxonomy('Type', 'Contact');
// Add the category taxonomy data.
$item->addTaxonomy('Category', $item->category,
$item->cat_state, $item->cat_access);
// Add the language taxonomy data.
$item->addTaxonomy('Language', $item->language);
// Add the region taxonomy data.
if (!empty($item->region) &&
$this->params->get('tax_add_region', true))
{
$item->addTaxonomy('Region', $item->region);
}
// Add the country taxonomy data.
if (!empty($item->country) &&
$this->params->get('tax_add_country', true))
{
$item->addTaxonomy('Country', $item->country);
}
// Get content extras.
FinderIndexerHelper::getContentExtras($item);
// Index the item.
$this->indexer->index($item);
}
/**
* Method to setup the indexer to be run.
*
* @return boolean True on success.
*
* @since 2.5
*/
protected function setup()
{
// Load dependent classes.
JLoader::register('ContactHelperRoute', JPATH_SITE .
'/components/com_contact/helpers/route.php');
// This is a hack to get around the lack of a route helper.
FinderIndexerHelper::getContentPath('index.php?option=com_contact');
return true;
}
/**
* Method to get the SQL query used to retrieve the list of content items.
*
* @param mixed $query A JDatabaseQuery object or null.
*
* @return JDatabaseQuery A database object.
*
* @since 2.5
*/
protected function getListQuery($query = null)
{
$db = JFactory::getDbo();
// Check if we can use the supplied SQL query.
$query = $query instanceof JDatabaseQuery ? $query :
$db->getQuery(true)
->select('a.id, a.name AS title, a.alias, a.con_position AS
position, a.address, a.created AS start_date')
->select('a.created_by_alias, a.modified, a.modified_by')
->select('a.metakey, a.metadesc, a.metadata, a.language')
->select('a.sortname1, a.sortname2, a.sortname3')
->select('a.publish_up AS publish_start_date, a.publish_down AS
publish_end_date')
->select('a.suburb AS city, a.state AS region, a.country,
a.postcode AS zip')
->select('a.telephone, a.fax, a.misc AS summary, a.email_to AS
email, a.mobile')
->select('a.webpage, a.access, a.published AS state, a.ordering,
a.params, a.catid')
->select('c.title AS category, c.published AS cat_state,
c.access AS cat_access');
// Handle the alias CASE WHEN portion of the query
$case_when_item_alias = ' CASE WHEN ';
$case_when_item_alias .= $query->charLength('a.alias',
'!=', '0');
$case_when_item_alias .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when_item_alias .= $query->concatenate(array($a_id,
'a.alias'), ':');
$case_when_item_alias .= ' ELSE ';
$case_when_item_alias .= $a_id . ' END as slug';
$query->select($case_when_item_alias);
$case_when_category_alias = ' CASE WHEN ';
$case_when_category_alias .= $query->charLength('c.alias',
'!=', '0');
$case_when_category_alias .= ' THEN ';
$c_id = $query->castAsChar('c.id');
$case_when_category_alias .= $query->concatenate(array($c_id,
'c.alias'), ':');
$case_when_category_alias .= ' ELSE ';
$case_when_category_alias .= $c_id . ' END as catslug';
$query->select($case_when_category_alias)
->select('u.name')
->from('#__contact_details AS a')
->join('LEFT', '#__categories AS c ON c.id =
a.catid')
->join('LEFT', '#__users AS u ON u.id =
a.user_id');
return $query;
}
}
finder/contacts/contacts.xml000064400000001456147357022240012205
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="finder" method="upgrade">
<name>plg_finder_contacts</name>
<author>Joomla! Project</author>
<creationDate>August 2011</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_FINDER_CONTACTS_XML_DESCRIPTION</description>
<files>
<filename plugin="contacts">contacts.php</filename>
</files>
<languages>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_contacts.ini</language>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_contacts.sys.ini</language>
</languages>
</extension>
finder/content/content.php000064400000025400147357022240011657
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Finder.Content
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Registry\Registry;
JLoader::register('FinderIndexerAdapter', JPATH_ADMINISTRATOR .
'/components/com_finder/helpers/indexer/adapter.php');
/**
* Smart Search adapter for com_content.
*
* @since 2.5
*/
class PlgFinderContent extends FinderIndexerAdapter
{
/**
* The plugin identifier.
*
* @var string
* @since 2.5
*/
protected $context = 'Content';
/**
* The extension name.
*
* @var string
* @since 2.5
*/
protected $extension = 'com_content';
/**
* The sublayout to use when rendering the results.
*
* @var string
* @since 2.5
*/
protected $layout = 'article';
/**
* The type of content that the adapter indexes.
*
* @var string
* @since 2.5
*/
protected $type_title = 'Article';
/**
* The table name.
*
* @var string
* @since 2.5
*/
protected $table = '#__content';
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Method to update the item link information when the item category is
* changed. This is fired when the item category is published or
unpublished
* from the list view.
*
* @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 onFinderCategoryChangeState($extension, $pks, $value)
{
// Make sure we're handling com_content categories.
if ($extension === 'com_content')
{
$this->categoryStateChange($pks, $value);
}
}
/**
* Method to remove the link information for items that have been deleted.
*
* @param string $context The context of the action being performed.
* @param JTable $table A JTable object containing the record to be
deleted
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderAfterDelete($context, $table)
{
if ($context === 'com_content.article')
{
$id = $table->id;
}
elseif ($context === 'com_finder.index')
{
$id = $table->link_id;
}
else
{
return true;
}
// Remove item from the index.
return $this->remove($id);
}
/**
* Smart Search after save content method.
* Reindexes the link information for an article that has been saved.
* It also makes adjustments if the access level of an item or the
* category to which it belongs has changed.
*
* @param string $context The context of the content passed to the
plugin.
* @param JTable $row A JTable object.
* @param boolean $isNew True if the content has just been created.
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderAfterSave($context, $row, $isNew)
{
// We only want to handle articles here.
if ($context === 'com_content.article' || $context ===
'com_content.form')
{
// Check if the access levels are different.
if (!$isNew && $this->old_access != $row->access)
{
// Process the change.
$this->itemAccessChange($row);
}
// Reindex the item.
$this->reindex($row->id);
}
// Check for access changes in the category.
if ($context === 'com_categories.category')
{
// Check if the access levels are different.
if (!$isNew && $this->old_cataccess != $row->access)
{
$this->categoryAccessChange($row);
}
}
return true;
}
/**
* Smart Search before content save method.
* This event is fired before the data is actually saved.
*
* @param string $context The context of the content passed to the
plugin.
* @param JTable $row A JTable object.
* @param boolean $isNew If the content is just about to be created.
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderBeforeSave($context, $row, $isNew)
{
// We only want to handle articles here.
if ($context === 'com_content.article' || $context ===
'com_content.form')
{
// Query the database for the old access level if the item isn't
new.
if (!$isNew)
{
$this->checkItemAccess($row);
}
}
// Check for access levels from the category.
if ($context === 'com_categories.category')
{
// Query the database for the old access level if the item isn't
new.
if (!$isNew)
{
$this->checkCategoryAccess($row);
}
}
return true;
}
/**
* 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 An array 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 onFinderChangeState($context, $pks, $value)
{
// We only want to handle articles here.
if ($context === 'com_content.article' || $context ===
'com_content.form')
{
$this->itemStateChange($pks, $value);
}
// Handle when the plugin is disabled.
if ($context === 'com_plugins.plugin' && $value === 0)
{
$this->pluginDisable($pks);
}
}
/**
* Method to index an item. The item must be a FinderIndexerResult object.
*
* @param FinderIndexerResult $item The item to index as a
FinderIndexerResult object.
* @param string $format The item format. Not used.
*
* @return void
*
* @since 2.5
* @throws Exception on database error.
*/
protected function index(FinderIndexerResult $item, $format =
'html')
{
$item->setLanguage();
// Check if the extension is enabled.
if (JComponentHelper::isEnabled($this->extension) === false)
{
return;
}
$item->context = 'com_content.article';
// Initialise the item parameters.
$registry = new Registry($item->params);
$item->params = clone
JComponentHelper::getParams('com_content', true);
$item->params->merge($registry);
$item->metadata = new Registry($item->metadata);
// Trigger the onContentPrepare event.
$item->summary =
FinderIndexerHelper::prepareContent($item->summary, $item->params,
$item);
$item->body = FinderIndexerHelper::prepareContent($item->body,
$item->params, $item);
// Build the necessary route and path information.
$item->url = $this->getUrl($item->id, $this->extension,
$this->layout);
$item->route = ContentHelperRoute::getArticleRoute($item->slug,
$item->catid, $item->language);
$item->path = FinderIndexerHelper::getContentPath($item->route);
// Get the menu title if it exists.
$title = $this->getItemMenuTitle($item->url);
// Adjust the title if necessary.
if (!empty($title) &&
$this->params->get('use_menu_title', true))
{
$item->title = $title;
}
// Add the meta author.
$item->metaauthor = $item->metadata->get('author');
// Add the metadata processing instructions.
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metakey');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metadesc');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metaauthor');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'author');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'created_by_alias');
// Translate the state. Articles should only be published if the category
is published.
$item->state = $this->translateState($item->state,
$item->cat_state);
// Add the type taxonomy data.
$item->addTaxonomy('Type', 'Article');
// Add the author taxonomy data.
if (!empty($item->author) || !empty($item->created_by_alias))
{
$item->addTaxonomy('Author',
!empty($item->created_by_alias) ? $item->created_by_alias :
$item->author);
}
// Add the category taxonomy data.
$item->addTaxonomy('Category', $item->category,
$item->cat_state, $item->cat_access);
// Add the language taxonomy data.
$item->addTaxonomy('Language', $item->language);
// Get content extras.
FinderIndexerHelper::getContentExtras($item);
// Index the item.
$this->indexer->index($item);
}
/**
* Method to setup the indexer to be run.
*
* @return boolean True on success.
*
* @since 2.5
*/
protected function setup()
{
// Load dependent classes.
JLoader::register('ContentHelperRoute', JPATH_SITE .
'/components/com_content/helpers/route.php');
return true;
}
/**
* Method to get the SQL query used to retrieve the list of content items.
*
* @param mixed $query A JDatabaseQuery object or null.
*
* @return JDatabaseQuery A database object.
*
* @since 2.5
*/
protected function getListQuery($query = null)
{
$db = JFactory::getDbo();
// Check if we can use the supplied SQL query.
$query = $query instanceof JDatabaseQuery ? $query :
$db->getQuery(true)
->select('a.id, a.title, a.alias, a.introtext AS summary,
a.fulltext AS body')
->select('a.images')
->select('a.state, a.catid, a.created AS start_date,
a.created_by')
->select('a.created_by_alias, a.modified, a.modified_by,
a.attribs AS params')
->select('a.metakey, a.metadesc, a.metadata, a.language,
a.access, a.version, a.ordering')
->select('a.publish_up AS publish_start_date, a.publish_down AS
publish_end_date')
->select('c.title AS category, c.published AS cat_state,
c.access AS cat_access');
// Handle the alias CASE WHEN portion of the query
$case_when_item_alias = ' CASE WHEN ';
$case_when_item_alias .= $query->charLength('a.alias',
'!=', '0');
$case_when_item_alias .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when_item_alias .= $query->concatenate(array($a_id,
'a.alias'), ':');
$case_when_item_alias .= ' ELSE ';
$case_when_item_alias .= $a_id . ' END as slug';
$query->select($case_when_item_alias);
$case_when_category_alias = ' CASE WHEN ';
$case_when_category_alias .= $query->charLength('c.alias',
'!=', '0');
$case_when_category_alias .= ' THEN ';
$c_id = $query->castAsChar('c.id');
$case_when_category_alias .= $query->concatenate(array($c_id,
'c.alias'), ':');
$case_when_category_alias .= ' ELSE ';
$case_when_category_alias .= $c_id . ' END as catslug';
$query->select($case_when_category_alias)
->select('u.name AS author')
->from('#__content AS a')
->join('LEFT', '#__categories AS c ON c.id =
a.catid')
->join('LEFT', '#__users AS u ON u.id =
a.created_by');
return $query;
}
}
finder/content/content.xml000064400000001450147357022240011667
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="finder" method="upgrade">
<name>plg_finder_content</name>
<author>Joomla! Project</author>
<creationDate>August 2011</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_FINDER_CONTENT_XML_DESCRIPTION</description>
<files>
<filename plugin="content">content.php</filename>
</files>
<languages>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_content.ini</language>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_content.sys.ini</language>
</languages>
</extension>
finder/newsfeeds/newsfeeds.php000064400000023656147357022240012514
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Finder.Newsfeeds
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Registry\Registry;
JLoader::register('FinderIndexerAdapter', JPATH_ADMINISTRATOR .
'/components/com_finder/helpers/indexer/adapter.php');
/**
* Smart Search adapter for Joomla Newsfeeds.
*
* @since 2.5
*/
class PlgFinderNewsfeeds extends FinderIndexerAdapter
{
/**
* The plugin identifier.
*
* @var string
* @since 2.5
*/
protected $context = 'Newsfeeds';
/**
* The extension name.
*
* @var string
* @since 2.5
*/
protected $extension = 'com_newsfeeds';
/**
* The sublayout to use when rendering the results.
*
* @var string
* @since 2.5
*/
protected $layout = 'newsfeed';
/**
* The type of content that the adapter indexes.
*
* @var string
* @since 2.5
*/
protected $type_title = 'News Feed';
/**
* The table name.
*
* @var string
* @since 2.5
*/
protected $table = '#__newsfeeds';
/**
* The field the published state is stored in.
*
* @var string
* @since 2.5
*/
protected $state_field = 'published';
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Method to update the item link information when the item category is
* changed. This is fired when the item category is published or
unpublished
* from the list view.
*
* @param string $extension The extension whose category has been
updated.
* @param array $pks An array 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 onFinderCategoryChangeState($extension, $pks, $value)
{
// Make sure we're handling com_newsfeeds categories.
if ($extension === 'com_newsfeeds')
{
$this->categoryStateChange($pks, $value);
}
}
/**
* Method to remove the link information for items that have been deleted.
*
* @param string $context The context of the action being performed.
* @param JTable $table A JTable object containing the record to be
deleted.
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderAfterDelete($context, $table)
{
if ($context === 'com_newsfeeds.newsfeed')
{
$id = $table->id;
}
elseif ($context === 'com_finder.index')
{
$id = $table->link_id;
}
else
{
return true;
}
// Remove the item from the index.
return $this->remove($id);
}
/**
* Smart Search after save content method.
* Reindexes the link information for a newsfeed that has been saved.
* It also makes adjustments if the access level of a newsfeed item or
* the category to which it belongs has been changed.
*
* @param string $context The context of the content passed to the
plugin.
* @param JTable $row A JTable object.
* @param boolean $isNew True if the content has just been created.
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderAfterSave($context, $row, $isNew)
{
// We only want to handle newsfeeds here.
if ($context === 'com_newsfeeds.newsfeed')
{
// Check if the access levels are different.
if (!$isNew && $this->old_access != $row->access)
{
// Process the change.
$this->itemAccessChange($row);
}
// Reindex the item.
$this->reindex($row->id);
}
// Check for access changes in the category.
if ($context === 'com_categories.category')
{
// Check if the access levels are different.
if (!$isNew && $this->old_cataccess != $row->access)
{
$this->categoryAccessChange($row);
}
}
return true;
}
/**
* Smart Search before content save method.
* This event is fired before the data is actually saved.
*
* @param string $context The context of the content passed to the
plugin.
* @param JTable $row A JTable object.
* @param boolean $isNew True if the content is just about to be
created.
*
* @return boolean True on success.
*
* @since 2.5
* @throws Exception on database error.
*/
public function onFinderBeforeSave($context, $row, $isNew)
{
// We only want to handle newsfeeds here.
if ($context === 'com_newsfeeds.newsfeed')
{
// Query the database for the old access level if the item isn't
new.
if (!$isNew)
{
$this->checkItemAccess($row);
}
}
// Check for access levels from the category.
if ($context === 'com_categories.category')
{
// Query the database for the old access level if the item isn't
new.
if (!$isNew)
{
$this->checkCategoryAccess($row);
}
}
return true;
}
/**
* 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 An array 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 onFinderChangeState($context, $pks, $value)
{
// We only want to handle newsfeeds here.
if ($context === 'com_newsfeeds.newsfeed')
{
$this->itemStateChange($pks, $value);
}
// Handle when the plugin is disabled.
if ($context === 'com_plugins.plugin' && $value === 0)
{
$this->pluginDisable($pks);
}
}
/**
* Method to index an item. The item must be a FinderIndexerResult object.
*
* @param FinderIndexerResult $item The item to index as a
FinderIndexerResult object.
* @param string $format The item format. Not used.
*
* @return void
*
* @since 2.5
* @throws Exception on database error.
*/
protected function index(FinderIndexerResult $item, $format =
'html')
{
// Check if the extension is enabled.
if (JComponentHelper::isEnabled($this->extension) === false)
{
return;
}
$item->setLanguage();
// Initialize the item parameters.
$item->params = new Registry($item->params);
$item->metadata = new Registry($item->metadata);
// Build the necessary route and path information.
$item->url = $this->getUrl($item->id, $this->extension,
$this->layout);
$item->route = NewsfeedsHelperRoute::getNewsfeedRoute($item->slug,
$item->catslug, $item->language);
$item->path = FinderIndexerHelper::getContentPath($item->route);
/*
* Add the metadata processing instructions based on the newsfeeds
* configuration parameters.
*/
// Add the meta author.
$item->metaauthor = $item->metadata->get('author');
// Handle the link to the metadata.
$item->addInstruction(FinderIndexer::META_CONTEXT, 'link');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metakey');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metadesc');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metaauthor');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'author');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'created_by_alias');
// Add the type taxonomy data.
$item->addTaxonomy('Type', 'News Feed');
// Add the category taxonomy data.
$item->addTaxonomy('Category', $item->category,
$item->cat_state, $item->cat_access);
// Add the language taxonomy data.
$item->addTaxonomy('Language', $item->language);
// Get content extras.
FinderIndexerHelper::getContentExtras($item);
// Index the item.
$this->indexer->index($item);
}
/**
* Method to setup the indexer to be run.
*
* @return boolean True on success.
*
* @since 2.5
*/
protected function setup()
{
// Load dependent classes.
JLoader::register('NewsfeedsHelperRoute', JPATH_SITE .
'/components/com_newsfeeds/helpers/route.php');
return true;
}
/**
* Method to get the SQL query used to retrieve the list of content items.
*
* @param mixed $query A JDatabaseQuery object or null.
*
* @return JDatabaseQuery A database object.
*
* @since 2.5
*/
protected function getListQuery($query = null)
{
$db = JFactory::getDbo();
// Check if we can use the supplied SQL query.
$query = $query instanceof JDatabaseQuery ? $query :
$db->getQuery(true)
->select('a.id, a.catid, a.name AS title, a.alias, a.link AS
link')
->select('a.published AS state, a.ordering, a.created AS
start_date, a.params, a.access')
->select('a.publish_up AS publish_start_date, a.publish_down AS
publish_end_date')
->select('a.metakey, a.metadesc, a.metadata, a.language')
->select('a.created_by, a.created_by_alias, a.modified,
a.modified_by')
->select('c.title AS category, c.published AS cat_state,
c.access AS cat_access');
// Handle the alias CASE WHEN portion of the query.
$case_when_item_alias = ' CASE WHEN ';
$case_when_item_alias .= $query->charLength('a.alias',
'!=', '0');
$case_when_item_alias .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when_item_alias .= $query->concatenate(array($a_id,
'a.alias'), ':');
$case_when_item_alias .= ' ELSE ';
$case_when_item_alias .= $a_id . ' END as slug';
$query->select($case_when_item_alias);
$case_when_category_alias = ' CASE WHEN ';
$case_when_category_alias .= $query->charLength('c.alias',
'!=', '0');
$case_when_category_alias .= ' THEN ';
$c_id = $query->castAsChar('c.id');
$case_when_category_alias .= $query->concatenate(array($c_id,
'c.alias'), ':');
$case_when_category_alias .= ' ELSE ';
$case_when_category_alias .= $c_id . ' END as catslug';
$query->select($case_when_category_alias)
->from('#__newsfeeds AS a')
->join('LEFT', '#__categories AS c ON c.id =
a.catid');
return $query;
}
}
finder/newsfeeds/newsfeeds.xml000064400000001464147357022240012516
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="finder" method="upgrade">
<name>plg_finder_newsfeeds</name>
<author>Joomla! Project</author>
<creationDate>August 2011</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_FINDER_NEWSFEEDS_XML_DESCRIPTION</description>
<files>
<filename
plugin="newsfeeds">newsfeeds.php</filename>
</files>
<languages>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_newsfeeds.ini</language>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_newsfeeds.sys.ini</language>
</languages>
</extension>
finder/tags/tags.php000064400000022465147357022240010437 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Finder.Tags
*
* @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\Registry\Registry;
JLoader::register('FinderIndexerAdapter', JPATH_ADMINISTRATOR .
'/components/com_finder/helpers/indexer/adapter.php');
/**
* Finder adapter for Joomla Tag.
*
* @since 3.1
*/
class PlgFinderTags extends FinderIndexerAdapter
{
/**
* The plugin identifier.
*
* @var string
* @since 3.1
*/
protected $context = 'Tags';
/**
* The extension name.
*
* @var string
* @since 3.1
*/
protected $extension = 'com_tags';
/**
* The sublayout to use when rendering the results.
*
* @var string
* @since 3.1
*/
protected $layout = 'tag';
/**
* The type of content that the adapter indexes.
*
* @var string
* @since 3.1
*/
protected $type_title = 'Tag';
/**
* The table name.
*
* @var string
* @since 3.1
*/
protected $table = '#__tags';
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* The field the published state is stored in.
*
* @var string
* @since 3.1
*/
protected $state_field = 'published';
/**
* Method to remove the link information for items that have been deleted.
*
* @param string $context The context of the action being performed.
* @param JTable $table A JTable object containing the record to be
deleted
*
* @return boolean True on success.
*
* @since 3.1
* @throws Exception on database error.
*/
public function onFinderAfterDelete($context, $table)
{
if ($context === 'com_tags.tag')
{
$id = $table->id;
}
elseif ($context === 'com_finder.index')
{
$id = $table->link_id;
}
else
{
return true;
}
// Remove the items.
return $this->remove($id);
}
/**
* Method to determine if the access level of an item changed.
*
* @param string $context The context of the content passed to the
plugin.
* @param JTable $row A JTable object
* @param boolean $isNew If the content has just been created
*
* @return boolean True on success.
*
* @since 3.1
* @throws Exception on database error.
*/
public function onFinderAfterSave($context, $row, $isNew)
{
// We only want to handle tags here.
if ($context === 'com_tags.tag')
{
// Check if the access levels are different
if (!$isNew && $this->old_access != $row->access)
{
// Process the change.
$this->itemAccessChange($row);
}
// Reindex the item
$this->reindex($row->id);
}
return true;
}
/**
* Method to reindex the link information for an item that has been saved.
* This event is fired before the data is actually saved so we are going
* to queue the item to be indexed later.
*
* @param string $context The context of the content passed to the
plugin.
* @param JTable $row A JTable object
* @param boolean $isNew If the content is just about to be created
*
* @return boolean True on success.
*
* @since 3.1
* @throws Exception on database error.
*/
public function onFinderBeforeSave($context, $row, $isNew)
{
// We only want to handle news feeds here
if ($context === 'com_tags.tag')
{
// Query the database for the old access level if the item isn't
new
if (!$isNew)
{
$this->checkItemAccess($row);
}
}
return true;
}
/**
* 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 3.1
*/
public function onFinderChangeState($context, $pks, $value)
{
// We only want to handle tags here
if ($context === 'com_tags.tag')
{
$this->itemStateChange($pks, $value);
}
// Handle when the plugin is disabled
if ($context === 'com_plugins.plugin' && $value === 0)
{
$this->pluginDisable($pks);
}
}
/**
* Method to index an item. The item must be a FinderIndexerResult object.
*
* @param FinderIndexerResult $item The item to index as a
FinderIndexerResult object.
* @param string $format The item format
*
* @return void
*
* @since 3.1
* @throws Exception on database error.
*/
protected function index(FinderIndexerResult $item, $format =
'html')
{
// Check if the extension is enabled
if (JComponentHelper::isEnabled($this->extension) === false)
{
return;
}
$item->setLanguage();
// Initialize the item parameters.
$registry = new Registry($item->params);
$item->params = clone
JComponentHelper::getParams('com_tags', true);
$item->params->merge($registry);
$item->metadata = new Registry($item->metadata);
// Build the necessary route and path information.
$item->url = $this->getUrl($item->id, $this->extension,
$this->layout);
$item->route = TagsHelperRoute::getTagRoute($item->slug);
$item->path = FinderIndexerHelper::getContentPath($item->route);
// Get the menu title if it exists.
$title = $this->getItemMenuTitle($item->url);
// Adjust the title if necessary.
if (!empty($title) &&
$this->params->get('use_menu_title', true))
{
$item->title = $title;
}
// Add the meta author.
$item->metaauthor = $item->metadata->get('author');
// Handle the link to the metadata.
$item->addInstruction(FinderIndexer::META_CONTEXT, 'link');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metakey');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metadesc');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'metaauthor');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'author');
$item->addInstruction(FinderIndexer::META_CONTEXT,
'created_by_alias');
// Add the type taxonomy data.
$item->addTaxonomy('Type', 'Tag');
// Add the author taxonomy data.
if (!empty($item->author) || !empty($item->created_by_alias))
{
$item->addTaxonomy('Author',
!empty($item->created_by_alias) ? $item->created_by_alias :
$item->author);
}
// Add the language taxonomy data.
$item->addTaxonomy('Language', $item->language);
// Get content extras.
FinderIndexerHelper::getContentExtras($item);
// Index the item.
$this->indexer->index($item);
}
/**
* Method to setup the indexer to be run.
*
* @return boolean True on success.
*
* @since 3.1
*/
protected function setup()
{
// Load dependent classes.
JLoader::register('TagsHelperRoute', JPATH_SITE .
'/components/com_tags/helpers/route.php');
return true;
}
/**
* Method to get the SQL query used to retrieve the list of content items.
*
* @param mixed $query A JDatabaseQuery object or null.
*
* @return JDatabaseQuery A database object.
*
* @since 3.1
*/
protected function getListQuery($query = null)
{
$db = JFactory::getDbo();
// Check if we can use the supplied SQL query.
$query = $query instanceof JDatabaseQuery ? $query :
$db->getQuery(true)
->select('a.id, a.title, a.alias, a.description AS
summary')
->select('a.created_time AS start_date, a.created_user_id AS
created_by')
->select('a.metakey, a.metadesc, a.metadata, a.language,
a.access')
->select('a.modified_time AS modified, a.modified_user_id AS
modified_by')
->select('a.published AS state, a.access, a.created_time AS
start_date, a.params');
// Handle the alias CASE WHEN portion of the query
$case_when_item_alias = ' CASE WHEN ';
$case_when_item_alias .= $query->charLength('a.alias',
'!=', '0');
$case_when_item_alias .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when_item_alias .= $query->concatenate(array($a_id,
'a.alias'), ':');
$case_when_item_alias .= ' ELSE ';
$case_when_item_alias .= $a_id . ' END as slug';
$query->select($case_when_item_alias)
->from('#__tags AS a');
// Join the #__users table
$query->select('u.name AS author')
->join('LEFT', '#__users AS u ON u.id =
a.created_user_id');
// Exclude the ROOT item
$query->where($db->quoteName('a.id') . ' >
1');
return $query;
}
/**
* Method to get a SQL query to load the published and access states for
the given tag.
*
* @return JDatabaseQuery A database object.
*
* @since 3.1
*/
protected function getStateQuery()
{
$query = $this->db->getQuery(true);
$query->select($this->db->quoteName('a.id'))
->select($this->db->quoteName('a.' .
$this->state_field, 'state') . ', ' .
$this->db->quoteName('a.access'))
->select('NULL AS cat_state, NULL AS cat_access')
->from($this->db->quoteName($this->table, 'a'));
return $query;
}
/**
* Method to get the query clause for getting items to update by time.
*
* @param string $time The modified timestamp.
*
* @return JDatabaseQuery A database object.
*
* @since 3.1
*/
protected function getUpdateQueryByTime($time)
{
// Build an SQL query based on the modified time.
$query = $this->db->getQuery(true)
->where('a.date >= ' . $this->db->quote($time));
return $query;
}
}
finder/tags/tags.xml000064400000001430147357022240010435 0ustar00<?xml
version="1.0" encoding="UTF-8"?>
<extension version="3.1" type="plugin"
group="finder" method="upgrade">
<name>plg_finder_tags</name>
<author>Joomla! Project</author>
<creationDate>February 2013</creationDate>
<copyright>(C) 2013 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_FINDER_TAGS_XML_DESCRIPTION</description>
<files>
<filename plugin="tags">tags.php</filename>
</files>
<languages>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_tags.ini</language>
<language
tag="en-GB">language/en-GB/en-GB.plg_finder_tags.sys.ini</language>
</languages>
</extension>
index.html000064400000000037147357022240006547 0ustar00<!DOCTYPE
html><title></title>
installer/folderinstaller/folderinstaller.php000064400000001742147357022240015646
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Installer.folderInstaller
*
* @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;
/**
* FolderInstaller Plugin.
*
* @since 3.6.0
*/
class PlgInstallerFolderInstaller extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.6.0
*/
protected $autoloadLanguage = true;
/**
* Textfield or Form of the Plugin.
*
* @return array Returns an array with the tab information
*
* @since 3.6.0
*/
public function onInstallerAddInstallationTab()
{
$tab = array();
$tab['name'] = 'folder';
$tab['label'] =
JText::_('PLG_INSTALLER_FOLDERINSTALLER_TEXT');
// Render the input
ob_start();
include JPluginHelper::getLayoutPath('installer',
'folderinstaller');
$tab['content'] = ob_get_clean();
return $tab;
}
}
installer/folderinstaller/folderinstaller.xml000064400000001476147357022240015663
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.6" type="plugin"
group="installer">
<name>PLG_INSTALLER_FOLDERINSTALLER</name>
<author>Joomla! Project</author>
<creationDate>May 2016</creationDate>
<copyright>(C) 2016 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.6.0</version>
<description>PLG_INSTALLER_FOLDERINSTALLER_PLUGIN_XML_DESCRIPTION</description>
<files>
<filename
plugin="folderinstaller">folderinstaller.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_installer_folderinstaller.ini</language>
<language
tag="en-GB">en-GB.plg_installer_folderinstaller.sys.ini</language>
</languages>
</extension>
installer/folderinstaller/tmpl/default.php000064400000002665147357022240015062
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Installer.folderinstaller
*
* @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;
JHtml::_('bootstrap.tooltip');
$app = JFactory::getApplication('administrator');
JFactory::getDocument()->addScriptDeclaration('
Joomla.submitbuttonfolder = function()
{
var form = document.getElementById("adminForm");
// do field validation
if (form.install_directory.value == "")
{
alert("' .
JText::_('PLG_INSTALLER_FOLDERINSTALLER_NO_INSTALL_PATH', true) .
'");
}
else
{
JoomlaInstaller.showLoading();
form.installtype.value = "folder"
form.submit();
}
};
');
?>
<legend><?php echo
JText::_('PLG_INSTALLER_FOLDERINSTALLER_TEXT');
?></legend>
<div class="control-group">
<label for="install_directory"
class="control-label"><?php echo
JText::_('PLG_INSTALLER_FOLDERINSTALLER_TEXT');
?></label>
<div class="controls">
<input type="text" id="install_directory"
name="install_directory" class="span5 input_box"
size="70"
value="<?php echo
$app->input->get('install_directory',
$app->get('tmp_path')); ?>" />
</div>
</div>
<div class="form-actions">
<input type="button" class="btn btn-primary"
id="installbutton_directory"
value="<?php echo
JText::_('PLG_INSTALLER_FOLDERINSTALLER_BUTTON'); ?>"
onclick="Joomla.submitbuttonfolder()" />
</div>
installer/packageinstaller/packageinstaller.php000064400000001770147357022240016107
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Installer.packageInstaller
*
* @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;
/**
* PackageInstaller Plugin.
*
* @since 3.6.0
*/
class PlgInstallerPackageInstaller extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.6.0
*/
protected $autoloadLanguage = true;
/**
* Textfield or Form of the Plugin.
*
* @return array Returns an array with the tab information
*
* @since 3.6.0
*/
public function onInstallerAddInstallationTab()
{
$tab = array();
$tab['name'] = 'package';
$tab['label'] =
JText::_('PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_PACKAGE_FILE');
// Render the input
ob_start();
include JPluginHelper::getLayoutPath('installer',
'packageinstaller');
$tab['content'] = ob_get_clean();
return $tab;
}
}
installer/packageinstaller/packageinstaller.xml000064400000001504147357022240016113
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.6" type="plugin"
group="installer">
<name>plg_installer_packageinstaller</name>
<author>Joomla! Project</author>
<creationDate>May 2016</creationDate>
<copyright>(C) 2016 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.6.0</version>
<description>PLG_INSTALLER_PACKAGEINSTALLER_PLUGIN_XML_DESCRIPTION</description>
<files>
<filename
plugin="packageinstaller">packageinstaller.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_installer_packageinstaller.ini</language>
<language
tag="en-GB">en-GB.plg_installer_packageinstaller.sys.ini</language>
</languages>
</extension>
installer/packageinstaller/tmpl/default.php000064400000022161147357022240015173
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Installer.packageinstaller
*
* @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;
JHtml::_('bootstrap.tooltip');
JHtml::_('jquery.token');
JText::script('PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_ERROR_UNKNOWN');
JText::script('PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_ERROR_EMPTY');
JText::script('COM_INSTALLER_MSG_WARNINGS_UPLOADFILETOOBIG');
JFactory::getDocument()->addScriptDeclaration('
Joomla.submitbuttonpackage = function()
{
var form = document.getElementById("adminForm");
// do field validation
if (form.install_package.value == "")
{
alert("' .
JText::_('PLG_INSTALLER_PACKAGEINSTALLER_NO_PACKAGE', true) .
'");
}
else if (form.install_package.files[0].size >
form.max_upload_size.value)
{
alert("' .
JText::_('COM_INSTALLER_MSG_WARNINGS_UPLOADFILETOOBIG', true) .
'");
}
else
{
JoomlaInstaller.showLoading();
form.installtype.value = "upload"
form.submit();
}
};
');
// Drag and Drop installation scripts
$token = JSession::getFormToken();
$return =
JFactory::getApplication()->input->getBase64('return');
// Drag-drop installation
JFactory::getDocument()->addScriptDeclaration(
<<<JS
jQuery(document).ready(function($) {
if (typeof FormData === 'undefined') {
$('#legacy-uploader').show();
$('#uploader-wrapper').hide();
return;
}
var uploading = false;
var dragZone = $('#dragarea');
var fileInput = $('#install_package');
var fileSizeMax = $('#max_upload_size').val();
var button = $('#select-file-button');
var url =
'index.php?option=com_installer&task=install.ajax_upload';
var returnUrl = $('#installer-return').val();
var actions = $('.upload-actions');
var progress = $('.upload-progress');
var progressBar = progress.find('.bar');
var percentage = progress.find('.uploading-number');
if (returnUrl) {
url += '&return=' + returnUrl;
}
button.on('click', function(e) {
fileInput.click();
});
fileInput.on('change', function (e) {
if (uploading) {
return;
}
Joomla.submitbuttonpackage();
});
dragZone.on('dragenter', function(e) {
e.preventDefault();
e.stopPropagation();
dragZone.addClass('hover');
return false;
});
// Notify user when file is over the drop area
dragZone.on('dragover', function(e) {
e.preventDefault();
e.stopPropagation();
dragZone.addClass('hover');
return false;
});
dragZone.on('dragleave', function(e) {
e.preventDefault();
e.stopPropagation();
dragZone.removeClass('hover');
return false;
});
dragZone.on('drop', function(e) {
e.preventDefault();
e.stopPropagation();
dragZone.removeClass('hover');
if (uploading) {
return;
}
var files = e.originalEvent.target.files ||
e.originalEvent.dataTransfer.files;
if (!files.length) {
return;
}
var file = files[0];
var data = new FormData;
if (file.size > fileSizeMax) {
alert(Joomla.JText._('COM_INSTALLER_MSG_WARNINGS_UPLOADFILETOOBIG'),
true);
return;
}
data.append('install_package', file);
data.append('installtype', 'upload');
dragZone.attr('data-state', 'uploading');
uploading = true;
$.ajax({
url: url,
data: data,
type: 'post',
processData: false,
cache: false,
contentType: false,
xhr: function () {
var xhr = new window.XMLHttpRequest();
progressBar.css('width', 0);
progressBar.attr('aria-valuenow', 0);
percentage.text(0);
// Upload progress
xhr.upload.addEventListener("progress", function (evt) {
if (evt.lengthComputable) {
var percentComplete = evt.loaded / evt.total;
var number = Math.round(percentComplete * 100);
progressBar.css('width', number + '%');
progressBar.attr('aria-valuenow', number);
percentage.text(number);
if (number === 100) {
dragZone.attr('data-state', 'installing');
}
}
}, false);
return xhr;
}
})
.done(function (res) {
// Handle extension fatal error
if (!res || (!res.success && !res.data)) {
showError(res);
return;
}
// Always redirect that can show message queue from session
if (res.data.redirect) {
location.href = res.data.redirect;
} else {
location.href =
'index.php?option=com_installer&view=install';
}
}).error(function (error) {
uploading = false;
if (error.status === 200) {
var res = error.responseText || error.responseJSON;
showError(res);
} else {
showError(error.statusText);
}
});
function showError(res) {
dragZone.attr('data-state', 'pending');
var message =
Joomla.JText._('PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_ERROR_UNKNOWN');
if (res == null) {
message =
Joomla.JText._('PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_ERROR_EMPTY');
} else if (typeof res === 'string') {
// Let's remove unnecessary HTML
message = res.replace(/(<([^>]+)>|\s+)/g, ' ');
} else if (res.message) {
message = res.message;
}
Joomla.renderMessages({error: [message]});
}
});
});
JS
);
JFactory::getDocument()->addStyleDeclaration(
<<<CSS
#dragarea {
background-color: #fafbfc;
border: 1px dashed #999;
box-sizing: border-box;
padding: 5% 0;
transition: all 0.2s ease 0s;
width: 100%;
}
#dragarea p.lead {
color: #999;
}
#upload-icon {
font-size: 48px;
width: auto;
height: auto;
margin: 0;
line-height: 175%;
color: #999;
transition: all .2s;
}
#dragarea.hover {
border-color: #666;
background-color: #eee;
}
#dragarea.hover #upload-icon,
#dragarea p.lead {
color: #666;
}
.upload-progress, .install-progress {
width: 50%;
margin: 5px auto;
}
/* Default transition (.3s) is too slow, progress will not run to 100% */
.upload-progress .progress .bar {
-webkit-transition: width .1s;
-moz-transition: width .1s;
-o-transition: width .1s;
transition: width .1s;
}
#dragarea[data-state=pending] .upload-progress {
display: none;
}
#dragarea[data-state=pending] .install-progress {
display: none;
}
#dragarea[data-state=uploading] .install-progress {
display: none;
}
#dragarea[data-state=uploading] .upload-actions {
display: none;
}
#dragarea[data-state=installing] .upload-progress {
display: none;
}
#dragarea[data-state=installing] .upload-actions {
display: none;
}
CSS
);
$maxSizeBytes = JFilesystemHelper::fileUploadMaxSize(false);
$maxSize = JHtml::_('number.bytes', $maxSizeBytes);
?>
<legend><?php echo
JText::_('PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_INSTALL_JOOMLA_EXTENSION');
?></legend>
<div id="uploader-wrapper">
<div id="dragarea" data-state="pending">
<div id="dragarea-content" class="text-center">
<p>
<span id="upload-icon" class="icon-upload"
aria-hidden="true"></span>
</p>
<div class="upload-progress">
<div class="progress progress-striped active">
<div class="bar bar-success"
style="width: 0;"
role="progressbar"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
<p class="lead">
<span class="uploading-text">
<?php echo
JText::_('PLG_INSTALLER_PACKAGEINSTALLER_UPLOADING'); ?>
</span>
<span class="uploading-number">0</span><span
class="uploading-symbol">%</span>
</p>
</div>
<div class="install-progress">
<div class="progress progress-striped active">
<div class="bar" style="width:
100%;"></div>
</div>
<p class="lead">
<span class="installing-text">
<?php echo
JText::_('PLG_INSTALLER_PACKAGEINSTALLER_INSTALLING'); ?>
</span>
</p>
</div>
<div class="upload-actions">
<p class="lead">
<?php echo
JText::_('PLG_INSTALLER_PACKAGEINSTALLER_DRAG_FILE_HERE'); ?>
</p>
<p>
<button id="select-file-button" type="button"
class="btn btn-success">
<span class="icon-copy"
aria-hidden="true"></span>
<?php echo
JText::_('PLG_INSTALLER_PACKAGEINSTALLER_SELECT_FILE'); ?>
</button>
</p>
<p>
<?php echo
JText::sprintf('JGLOBAL_MAXIMUM_UPLOAD_SIZE_LIMIT', $maxSize);
?>
</p>
</div>
</div>
</div>
</div>
<div id="legacy-uploader" style="display: none;">
<div class="control-group">
<label for="install_package"
class="control-label"><?php echo
JText::_('PLG_INSTALLER_PACKAGEINSTALLER_EXTENSION_PACKAGE_FILE');
?></label>
<div class="controls">
<input class="input_box" id="install_package"
name="install_package" type="file" size="57"
/>
<input id="max_upload_size"
name="max_upload_size" type="hidden"
value="<?php echo $maxSizeBytes; ?>" /><br>
<?php echo
JText::sprintf('JGLOBAL_MAXIMUM_UPLOAD_SIZE_LIMIT', $maxSize);
?>
</div>
</div>
<div class="form-actions">
<button class="btn btn-primary" type="button"
id="installbutton_package"
onclick="Joomla.submitbuttonpackage()">
<?php echo
JText::_('PLG_INSTALLER_PACKAGEINSTALLER_UPLOAD_AND_INSTALL');
?>
</button>
</div>
<input id="installer-return" name="return"
type="hidden" value="<?php echo $return; ?>"
/>
<input id="installer-token" name="return"
type="hidden" value="<?php echo $token; ?>" />
</div>
installer/urlinstaller/tmpl/default.php000064400000002141147357022240014376
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Installer.urlinstaller
*
* @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;
JHtml::_('bootstrap.tooltip');
JFactory::getDocument()->addScriptDeclaration('
Joomla.submitbuttonurl = function()
{
var form = document.getElementById("adminForm");
JoomlaInstaller.showLoading();
form.installtype.value = "url"
form.submit();
};
');
?>
<legend><?php echo
JText::_('PLG_INSTALLER_URLINSTALLER_TEXT'); ?></legend>
<div class="control-group">
<label for="install_url"
class="control-label"><?php echo
JText::_('PLG_INSTALLER_URLINSTALLER_TEXT'); ?></label>
<div class="controls">
<input type="text" id="install_url"
name="install_url" class="span5 input_box"
size="70" placeholder="https://"/>
</div>
</div>
<div class="form-actions">
<input type="button" class="btn btn-primary"
id="installbutton_url"
value="<?php echo
JText::_('PLG_INSTALLER_URLINSTALLER_BUTTON'); ?>"
onclick="Joomla.submitbuttonurl()" />
</div>
installer/urlinstaller/urlinstaller.php000064400000001726147357022240014526
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Installer.urlinstaller
*
* @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;
/**
* UrlFolderInstaller Plugin.
*
* @since 3.6.0
*/
class PlgInstallerUrlInstaller extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.6.0
*/
protected $autoloadLanguage = true;
/**
* Textfield or Form of the Plugin.
*
* @return array Returns an array with the tab information
*
* @since 3.6.0
*/
public function onInstallerAddInstallationTab()
{
$tab = array();
$tab['name'] = 'url';
$tab['label'] =
JText::_('PLG_INSTALLER_URLINSTALLER_TEXT');
// Render the input
ob_start();
include JPluginHelper::getLayoutPath('installer',
'urlinstaller');
$tab['content'] = ob_get_clean();
return $tab;
}
}
installer/urlinstaller/urlinstaller.xml000064400000001454147357022240014535
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.6" type="plugin"
group="installer">
<name>PLG_INSTALLER_URLINSTALLER</name>
<author>Joomla! Project</author>
<creationDate>May 2016</creationDate>
<copyright>(C) 2016 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.6.0</version>
<description>PLG_INSTALLER_URLINSTALLER_PLUGIN_XML_DESCRIPTION</description>
<files>
<filename
plugin="urlinstaller">urlinstaller.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_installer_urlinstaller.ini</language>
<language
tag="en-GB">en-GB.plg_installer_urlinstaller.sys.ini</language>
</languages>
</extension>
privacy/actionlogs/actionlogs.php000064400000003334147357022240013247
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Privacy.actionlogs
*
* @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;
JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR .
'/components/com_actionlogs/helpers/actionlogs.php');
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/plugin.php');
/**
* Privacy plugin managing Joomla actionlogs data
*
* @since 3.9.0
*/
class PlgPrivacyActionlogs extends PrivacyPlugin
{
/**
* Processes an export request for Joomla core actionlog data
*
* @param PrivacyTableRequest $request The request record being
processed
* @param JUser $user The user account associated
with this request if available
*
* @return PrivacyExportDomain[]
*
* @since 3.9.0
*/
public function onPrivacyExportRequest(PrivacyTableRequest $request, JUser
$user = null)
{
if (!$user)
{
return array();
}
$domain = $this->createDomain('user_action_logs',
'joomla_user_action_logs_data');
$query = $this->db->getQuery(true)
->select('a.*, u.name')
->from('#__action_logs AS a')
->innerJoin('#__users AS u ON a.user_id = u.id')
->where($this->db->quoteName('a.user_id') . ' =
' . (int) $user->id);
$this->db->setQuery($query);
$data = $this->db->loadObjectList();
if (!count($data))
{
return array();
}
$data = ActionlogsHelper::getCsvData($data);
$isFirst = true;
foreach ($data as $item)
{
if ($isFirst)
{
$isFirst = false;
continue;
}
$domain->addItem($this->createItemFromArray($item));
}
return array($domain);
}
}
privacy/actionlogs/actionlogs.xml000064400000001437147357022240013262
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="privacy" method="upgrade">
<name>plg_privacy_actionlogs</name>
<author>Joomla! Project</author>
<creationDate>July 2018</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_PRIVACY_ACTIONLOGS_XML_DESCRIPTION</description>
<files>
<filename
plugin="actionlogs">actionlogs.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_privacy_actionlogs.ini</language>
<language
tag="en-GB">en-GB.plg_privacy_actionlogs.sys.ini</language>
</languages>
</extension>
privacy/consents/consents.php000064400000002761147357022240012436
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Privacy.consents
*
* @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;
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/plugin.php');
/**
* Privacy plugin managing Joomla user consent data
*
* @since 3.9.0
*/
class PlgPrivacyConsents extends PrivacyPlugin
{
/**
* Processes an export request for Joomla core user consent data
*
* This event will collect data for the core `#__privacy_consents` table
*
* @param PrivacyTableRequest $request The request record being
processed
* @param JUser $user The user account associated
with this request if available
*
* @return PrivacyExportDomain[]
*
* @since 3.9.0
*/
public function onPrivacyExportRequest(PrivacyTableRequest $request, JUser
$user = null)
{
if (!$user)
{
return array();
}
$domain = $this->createDomain('consents',
'joomla_consent_data');
$query = $this->db->getQuery(true)
->select('*')
->from($this->db->quoteName('#__privacy_consents'))
->where($this->db->quoteName('user_id') . ' =
' . (int) $user->id)
->order($this->db->quoteName('created') . '
ASC');
$items = $this->db->setQuery($query)->loadAssocList();
foreach ($items as $item)
{
$domain->addItem($this->createItemFromArray($item));
}
return array($domain);
}
}
privacy/consents/consents.xml000064400000001423147357022240012441
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.9" type="plugin"
group="privacy" method="upgrade">
<name>plg_privacy_consents</name>
<author>Joomla! Project</author>
<creationDate>July 2018</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_PRIVACY_CONSENTS_XML_DESCRIPTION</description>
<files>
<filename plugin="consents">consents.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_privacy_consents.ini</language>
<language
tag="en-GB">en-GB.plg_privacy_consents.sys.ini</language>
</languages>
</extension>
privacy/contact/contact.php000064400000003457147357022240012037
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Privacy.contact
*
* @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;
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/plugin.php');
/**
* Privacy plugin managing Joomla user contact data
*
* @since 3.9.0
*/
class PlgPrivacyContact extends PrivacyPlugin
{
/**
* Processes an export request for Joomla core user contact data
*
* This event will collect data for the contact core tables:
*
* - Contact custom fields
*
* @param PrivacyTableRequest $request The request record being
processed
* @param JUser $user The user account associated
with this request if available
*
* @return PrivacyExportDomain[]
*
* @since 3.9.0
*/
public function onPrivacyExportRequest(PrivacyTableRequest $request, JUser
$user = null)
{
if (!$user && !$request->email)
{
return array();
}
$domains = array();
$domain = $this->createDomain('user_contact',
'joomla_user_contact_data');
$domains[] = $domain;
$query = $this->db->getQuery(true)
->select('*')
->from($this->db->quoteName('#__contact_details'))
->order($this->db->quoteName('ordering') . '
ASC');
if ($user)
{
$query->where($this->db->quoteName('user_id') .
' = ' . (int) $user->id);
}
else
{
$query->where($this->db->quoteName('email_to') .
' = ' . $this->db->quote($request->email));
}
$items = $this->db->setQuery($query)->loadObjectList();
foreach ($items as $item)
{
$domain->addItem($this->createItemFromArray((array) $item));
}
$domains[] =
$this->createCustomFieldsDomain('com_contact.contact',
$items);
return $domains;
}
}
privacy/contact/contact.xml000064400000001415147357022240012040
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.9" type="plugin"
group="privacy" method="upgrade">
<name>plg_privacy_contact</name>
<author>Joomla! Project</author>
<creationDate>July 2018</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_PRIVACY_CONTACT_XML_DESCRIPTION</description>
<files>
<filename plugin="contact">contact.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_privacy_contact.ini</language>
<language
tag="en-GB">en-GB.plg_privacy_contact.sys.ini</language>
</languages>
</extension>
privacy/content/content.php000064400000003210147357022240012060
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Privacy.content
*
* @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;
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/plugin.php');
/**
* Privacy plugin managing Joomla user content data
*
* @since 3.9.0
*/
class PlgPrivacyContent extends PrivacyPlugin
{
/**
* Processes an export request for Joomla core user content data
*
* This event will collect data for the content core table
*
* - Content custom fields
*
* @param PrivacyTableRequest $request The request record being
processed
* @param JUser $user The user account associated
with this request if available
*
* @return PrivacyExportDomain[]
*
* @since 3.9.0
*/
public function onPrivacyExportRequest(PrivacyTableRequest $request, JUser
$user = null)
{
if (!$user)
{
return array();
}
$domains = array();
$domain = $this->createDomain('user_content',
'joomla_user_content_data');
$domains[] = $domain;
$query = $this->db->getQuery(true)
->select('*')
->from($this->db->quoteName('#__content'))
->where($this->db->quoteName('created_by') . ' =
' . (int) $user->id)
->order($this->db->quoteName('ordering') . '
ASC');
$items = $this->db->setQuery($query)->loadObjectList();
foreach ($items as $item)
{
$domain->addItem($this->createItemFromArray((array) $item));
}
$domains[] =
$this->createCustomFieldsDomain('com_content.article',
$items);
return $domains;
}
}
privacy/content/content.xml000064400000001415147357022240012076
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.9" type="plugin"
group="privacy" method="upgrade">
<name>plg_privacy_content</name>
<author>Joomla! Project</author>
<creationDate>July 2018</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_PRIVACY_CONTENT_XML_DESCRIPTION</description>
<files>
<filename plugin="content">content.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_privacy_content.ini</language>
<language
tag="en-GB">en-GB.plg_privacy_content.sys.ini</language>
</languages>
</extension>
privacy/message/message.php000064400000003045147357022240012012
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Privacy.message
*
* @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;
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/plugin.php');
/**
* Privacy plugin managing Joomla user messages
*
* @since 3.9.0
*/
class PlgPrivacyMessage extends PrivacyPlugin
{
/**
* Processes an export request for Joomla core user message
*
* This event will collect data for the message table
*
* @param PrivacyTableRequest $request The request record being
processed
* @param JUser $user The user account associated
with this request if available
*
* @return PrivacyExportDomain[]
*
* @since 3.9.0
*/
public function onPrivacyExportRequest(PrivacyTableRequest $request, JUser
$user = null)
{
if (!$user)
{
return array();
}
$domain = $this->createDomain('user_messages',
'joomla_user_messages_data');
$query = $this->db->getQuery(true)
->select('*')
->from($this->db->quoteName('#__messages'))
->where($this->db->quoteName('user_id_from') . '
= ' . (int) $user->id)
->orWhere($this->db->quoteName('user_id_to') . '
= ' . (int) $user->id)
->order($this->db->quoteName('date_time') . '
ASC');
$items = $this->db->setQuery($query)->loadAssocList();
foreach ($items as $item)
{
$domain->addItem($this->createItemFromArray($item));
}
return array($domain);
}
}
privacy/message/message.xml000064400000001415147357022240012022
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.9" type="plugin"
group="privacy" method="upgrade">
<name>plg_privacy_message</name>
<author>Joomla! Project</author>
<creationDate>July 2018</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_PRIVACY_MESSAGE_XML_DESCRIPTION</description>
<files>
<filename plugin="message">message.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_privacy_message.ini</language>
<language
tag="en-GB">en-GB.plg_privacy_message.sys.ini</language>
</languages>
</extension>
privacy/user/user.php000064400000013507147357022240010702 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Privacy.user
*
* @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\User\UserHelper;
use Joomla\Utilities\ArrayHelper;
JLoader::register('PrivacyPlugin', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/plugin.php');
JLoader::register('PrivacyRemovalStatus', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/removal/status.php');
/**
* Privacy plugin managing Joomla user data
*
* @since 3.9.0
*/
class PlgPrivacyUser extends PrivacyPlugin
{
/**
* Performs validation to determine if the data associated with a remove
information request can be processed
*
* This event will not allow a super user account to be removed
*
* @param PrivacyTableRequest $request The request record being
processed
* @param JUser $user The user account associated
with this request if available
*
* @return PrivacyRemovalStatus
*
* @since 3.9.0
*/
public function onPrivacyCanRemoveData(PrivacyTableRequest $request, JUser
$user = null)
{
$status = new PrivacyRemovalStatus;
if (!$user)
{
return $status;
}
if ($user->authorise('core.admin'))
{
$status->canRemove = false;
$status->reason =
JText::_('PLG_PRIVACY_USER_ERROR_CANNOT_REMOVE_SUPER_USER');
}
return $status;
}
/**
* Processes an export request for Joomla core user data
*
* This event will collect data for the following core tables:
*
* - #__users (excluding the password, otpKey, and otep columns)
* - #__user_notes
* - #__user_profiles
* - User custom fields
*
* @param PrivacyTableRequest $request The request record being
processed
* @param JUser $user The user account associated
with this request if available
*
* @return PrivacyExportDomain[]
*
* @since 3.9.0
*/
public function onPrivacyExportRequest(PrivacyTableRequest $request, JUser
$user = null)
{
if (!$user)
{
return array();
}
/** @var JTableUser $userTable */
$userTable = JUser::getTable();
$userTable->load($user->id);
$domains = array();
$domains[] = $this->createUserDomain($userTable);
$domains[] = $this->createNotesDomain($userTable);
$domains[] = $this->createProfileDomain($userTable);
$domains[] =
$this->createCustomFieldsDomain('com_users.user',
array($userTable));
return $domains;
}
/**
* Removes the data associated with a remove information request
*
* This event will pseudoanonymise the user account
*
* @param PrivacyTableRequest $request The request record being
processed
* @param JUser $user The user account associated
with this request if available
*
* @return void
*
* @since 3.9.0
*/
public function onPrivacyRemoveData(PrivacyTableRequest $request, JUser
$user = null)
{
// This plugin only processes data for registered user accounts
if (!$user)
{
return;
}
$pseudoanonymisedData = array(
'name' => 'User ID ' . $user->id,
'username' => bin2hex(random_bytes(12)),
'email' => 'UserID' . $user->id .
'removed@email.invalid',
'block' => true,
);
$user->bind($pseudoanonymisedData);
$user->save();
// Destroy all sessions for the user account
UserHelper::destroyUserSessions($user->id);
}
/**
* Create the domain for the user notes data
*
* @param JTableUser $user The JTableUser object to process
*
* @return PrivacyExportDomain
*
* @since 3.9.0
*/
private function createNotesDomain(JTableUser $user)
{
$domain = $this->createDomain('user_notes',
'joomla_user_notes_data');
$query = $this->db->getQuery(true)
->select('*')
->from($this->db->quoteName('#__user_notes'))
->where($this->db->quoteName('user_id') . ' =
' . $this->db->quote($user->id));
$items = $this->db->setQuery($query)->loadAssocList();
// Remove user ID columns
foreach (array('user_id', 'created_user_id',
'modified_user_id') as $column)
{
$items = ArrayHelper::dropColumn($items, $column);
}
foreach ($items as $item)
{
$domain->addItem($this->createItemFromArray($item,
$item['id']));
}
return $domain;
}
/**
* Create the domain for the user profile data
*
* @param JTableUser $user The JTableUser object to process
*
* @return PrivacyExportDomain
*
* @since 3.9.0
*/
private function createProfileDomain(JTableUser $user)
{
$domain = $this->createDomain('user_profile',
'joomla_user_profile_data');
$query = $this->db->getQuery(true)
->select('*')
->from($this->db->quoteName('#__user_profiles'))
->where($this->db->quoteName('user_id') . ' =
' . $this->db->quote($user->id))
->order($this->db->quoteName('ordering') . '
ASC');
$items = $this->db->setQuery($query)->loadAssocList();
foreach ($items as $item)
{
$domain->addItem($this->createItemFromArray($item));
}
return $domain;
}
/**
* Create the domain for the user record
*
* @param JTableUser $user The JTableUser object to process
*
* @return PrivacyExportDomain
*
* @since 3.9.0
*/
private function createUserDomain(JTableUser $user)
{
$domain = $this->createDomain('users',
'joomla_users_data');
$domain->addItem($this->createItemForUserTable($user));
return $domain;
}
/**
* Create an item object for a JTableUser object
*
* @param JTableUser $user The JTableUser object to convert
*
* @return PrivacyExportItem
*
* @since 3.9.0
*/
private function createItemForUserTable(JTableUser $user)
{
$data = array();
$exclude = array('password', 'otpKey',
'otep');
foreach (array_keys($user->getFields()) as $fieldName)
{
if (!in_array($fieldName, $exclude))
{
$data[$fieldName] = $user->$fieldName;
}
}
return $this->createItemFromArray($data, $user->id);
}
}
privacy/user/user.xml000064400000001372147357022240010710 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="privacy" method="upgrade">
<name>plg_privacy_user</name>
<author>Joomla! Project</author>
<creationDate>May 2018</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_PRIVACY_USER_XML_DESCRIPTION</description>
<files>
<filename plugin="user">user.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_privacy_user.ini</language>
<language
tag="en-GB">en-GB.plg_privacy_user.sys.ini</language>
</languages>
</extension>
quickicon/eos310/eos310.php000064400000025036147357022240011302
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Quickicon.eos310
*
* @copyright (C) 2021 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;
/**
* Joomla! end of support notification plugin
*
* @since 3.10.0
*/
class PlgQuickiconEos310 extends CMSPlugin
{
/**
* The EOS date for 3.10
*
* @var string
* @since 3.10.0
*/
const EOS_DATE = '2023-08-17';
/**
* Application object
*
* @var CMSApplication
* @since 3.10.0
*/
protected $app;
/**
* Database object
*
* @var DatabaseDriver
* @since 3.10.0
*/
protected $db;
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.10.0
*/
protected $autoloadLanguage = true;
/**
* Holding the current valid message to be shown
*
* @var boolean
* @since 3.10.0
*/
private $currentMessage = false;
/**
* Constructor.
*
* @param object &$subject The object to observe.
* @param array $config An optional associative array of
configuration settings.
*
* @since 3.10.0
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
$diff =
Factory::getDate()->diff(Factory::getDate(static::EOS_DATE));
$monthsUntilEOS = floor($diff->days / 30.417);
$this->currentMessage = $this->getMessageInfo($monthsUntilEOS,
$diff->invert);
}
/**
* Check and show the the alert and quickicon message
*
* @param string $context The calling context
*
* @return array|void A list of icon definition associative arrays,
consisting of the
* keys link, image, text and access, or void.
*
* @since 3.10.0
*/
public function onGetIcons($context)
{
if (!$this->shouldDisplayMessage())
{
return;
}
// No messages yet
if (!$this->currentMessage)
{
return;
}
// Show this only when not snoozed
if ($this->params->get('last_snoozed_id', 0) <
$this->currentMessage['id'])
{
// Load the snooze scripts.
HTMLHelper::_('jquery.framework');
HTMLHelper::_('script',
'plg_quickicon_eos310/snooze.js', array('version' =>
'auto', 'relative' => true));
// Build the message to be displayed in the cpanel
$messageText = Text::sprintf(
$this->currentMessage['messageText'],
HTMLHelper::_('date', static::EOS_DATE,
Text::_('DATE_FORMAT_LC3')),
$this->currentMessage['messageLink']
);
if ($this->currentMessage['snoozable'])
{
$messageText .=
'<p><button class="btn btn-warning
eosnotify-snooze-btn" type="button">' .
Text::_('PLG_QUICKICON_EOS310_SNOOZE_BUTTON') .
'</button></p>';
}
$this->app->enqueueMessage(
$messageText,
$this->currentMessage['messageType']
);
}
// The message as quickicon
$messageTextQuickIcon = Text::sprintf(
$this->currentMessage['quickiconText'],
HTMLHelper::_(
'date',
static::EOS_DATE,
Text::_('DATE_FORMAT_LC3')
)
);
// The message as quickicon
return array(array(
'link' =>
$this->currentMessage['messageLink'],
'target' => '_blank',
'rel' => 'noopener noreferrer',
'image' => $this->currentMessage['image'],
'text' => $messageTextQuickIcon,
'id' => 'plg_quickicon_eos310',
'group' =>
$this->currentMessage['groupText'],
));
}
/**
* User hit the snooze button
*
* @return void
*
* @since 3.10.0
*
* @throws JAccessExceptionNotallowed If user is not allowed.
*/
public function onAjaxSnoozeEOS()
{
// No messages yet so nothing to snooze
if (!$this->currentMessage)
{
return;
}
if (!$this->isAllowedUser() || !$this->isAjaxRequest())
{
throw new
JAccessExceptionNotallowed(Text::_('JGLOBAL_AUTH_ACCESS_DENIED'),
403);
}
// Make sure only snoozable messages can be snoozed
if ($this->currentMessage['snoozable'])
{
$this->params->set('last_snoozed_id',
$this->currentMessage['id']);
$this->saveParams();
}
}
/**
* Return the texts to be displayed based on the time until we reach EOS
*
* @param integer $monthsUntilEOS The months until we reach EOS
* @param integer $inverted Have we surpassed the EOS date
*
* @return array|bool An array with the message to be displayed or false
*
* @since 3.10.0
*/
private function getMessageInfo($monthsUntilEOS, $inverted)
{
// The EOS date has passed - Support has ended
if ($inverted === 1)
{
return array(
'id' => 5,
'messageText' =>
'PLG_QUICKICON_EOS310_MESSAGE_ERROR_SUPPORT_ENDED',
'quickiconText' =>
'PLG_QUICKICON_EOS310_MESSAGE_ERROR_SUPPORT_ENDED_SHORT',
'messageType' => 'error',
'image' => 'minus-circle',
'messageLink' =>
'https://docs.joomla.org/Special:MyLanguage/Planning_for_Mini-Migration_-_Joomla_3.10.x_to_4.x',
'groupText' =>
'PLG_QUICKICON_EOS310_GROUPNAME_EOS',
'snoozable' => false,
);
}
// The security support is ending in 6 months
if ($monthsUntilEOS < 6)
{
return array(
'id' => 4,
'messageText' =>
'PLG_QUICKICON_EOS310_MESSAGE_WARNING_SUPPORT_ENDING',
'quickiconText' =>
'PLG_QUICKICON_EOS310_MESSAGE_WARNING_SUPPORT_ENDING_SHORT',
'messageType' => 'warning',
'image' => 'warning-circle',
'messageLink' =>
'https://docs.joomla.org/Special:MyLanguage/Planning_for_Mini-Migration_-_Joomla_3.10.x_to_4.x',
'groupText' =>
'PLG_QUICKICON_EOS310_GROUPNAME_WARNING',
'snoozable' => true,
);
}
// We are in security only mode now, 12 month to go from now on
if ($monthsUntilEOS < 12)
{
return array(
'id' => 3,
'messageText' =>
'PLG_QUICKICON_EOS310_MESSAGE_WARNING_SECURITY_ONLY',
'quickiconText' =>
'PLG_QUICKICON_EOS310_MESSAGE_WARNING_SECURITY_ONLY_SHORT',
'messageType' => 'warning',
'image' => 'warning-circle',
'messageLink' =>
'https://docs.joomla.org/Special:MyLanguage/Planning_for_Mini-Migration_-_Joomla_3.10.x_to_4.x',
'groupText' =>
'PLG_QUICKICON_EOS310_GROUPNAME_WARNING',
'snoozable' => true,
);
}
// We still have 16 month to go, lets remind our users about the pre
upgrade checker
if ($monthsUntilEOS < 16)
{
return array(
'id' => 2,
'messageText' =>
'PLG_QUICKICON_EOS310_MESSAGE_INFO_02',
'quickiconText' =>
'PLG_QUICKICON_EOS310_MESSAGE_INFO_02_SHORT',
'messageType' => 'info',
'image' => 'info-circle',
'messageLink' =>
'https://docs.joomla.org/Special:MyLanguage/Pre-Update_Check',
'groupText' =>
'PLG_QUICKICON_EOS310_GROUPNAME_INFO',
'snoozable' => true,
);
}
// Lets start our messages 2 month after the initial release, still 22
month to go
if ($monthsUntilEOS < 22)
{
return array(
'id' => 1,
'messageText' =>
'PLG_QUICKICON_EOS310_MESSAGE_INFO_01',
'quickiconText' =>
'PLG_QUICKICON_EOS310_MESSAGE_INFO_01_SHORT',
'messageType' => 'info',
'image' => 'info-circle',
'messageLink' =>
'https://www.joomla.org/4/#features',
'groupText' =>
'PLG_QUICKICON_EOS310_GROUPNAME_INFO',
'snoozable' => true,
);
}
return false;
}
/**
* Determines if the message and quickicon should be displayed
*
* @return boolean
*
* @since 3.10.0
*/
private function shouldDisplayMessage()
{
// Only on admin app
if (!$this->app->isClient('administrator'))
{
return false;
}
// Only if authenticated
if (Factory::getUser()->guest)
{
return false;
}
// Only on HTML documents
if ($this->app->getDocument()->getType() !== 'html')
{
return false;
}
// Only on full page requests
if ($this->app->input->getCmd('tmpl',
'index') === 'component')
{
return false;
}
// Only to com_cpanel
if ($this->app->input->get('option') !==
'com_cpanel')
{
return false;
}
// Don't show anything in 4.0
if (version_compare(JVERSION, '4.0', '>='))
{
return false;
}
return true;
}
/**
* Check valid AJAX request
*
* @return boolean
*
* @since 3.10.0
*/
private function isAjaxRequest()
{
return
strtolower($this->app->input->server->get('HTTP_X_REQUESTED_WITH',
'')) === 'xmlhttprequest';
}
/**
* Check if current user is allowed to send the data
*
* @return boolean
*
* @since 3.10.0
*/
private function isAllowedUser()
{
return Factory::getUser()->authorise('core.login.admin');
}
/**
* Save the plugin parameters
*
* @return boolean
*
* @since 3.10.0
*/
private function saveParams()
{
$query = $this->db->getQuery(true)
->update($this->db->quoteName('#__extensions'))
->set($this->db->quoteName('params') . ' =
' .
$this->db->quote($this->params->toString('JSON')))
->where($this->db->quoteName('type') . ' =
' . $this->db->quote('plugin'))
->where($this->db->quoteName('folder') . ' =
' . $this->db->quote('quickicon'))
->where($this->db->quoteName('element') . ' =
' . $this->db->quote('eos310'));
try
{
// Lock the tables to prevent multiple plugin executions causing a race
condition
$this->db->lockTable('#__extensions');
}
catch (Exception $e)
{
// If we can't lock the tables it's too risky to continue
execution
return false;
}
try
{
// Update the plugin parameters
$result = $this->db->setQuery($query)->execute();
$this->clearCacheGroups(array('com_plugins'), array(0, 1));
}
catch (Exception $exc)
{
// If we failed to execute
$this->db->unlockTables();
$result = false;
}
try
{
// Unlock the tables after writing
$this->db->unlockTables();
}
catch (Exception $e)
{
// If we can't lock the tables assume we have somehow failed
$result = false;
}
return $result;
}
/**
* Clears cache groups. We use it to clear the plugins cache after we
update the last run timestamp.
*
* @param array $clearGroups The cache groups to clean
* @param array $cacheClients The cache clients (site, admin) to clean
*
* @return void
*
* @since 3.10.0
*/
private function clearCacheGroups(array $clearGroups, array $cacheClients
= array(0, 1))
{
foreach ($clearGroups as $group)
{
foreach ($cacheClients as $client_id)
{
try
{
$options = array(
'defaultgroup' => $group,
'cachebase' => $client_id ? JPATH_ADMINISTRATOR .
'/cache' : $this->app->get('cache_path',
JPATH_SITE . '/cache')
);
$cache = JCache::getInstance('callback', $options);
$cache->clean();
}
catch (Exception $e)
{
// Ignore it
}
}
}
}
}
quickicon/eos310/eos310.xml000064400000001670147357022240011311
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.10" type="plugin"
group="quickicon" method="upgrade">
<name>plg_quickicon_eos310</name>
<author>Joomla! Project</author>
<creationDate>June 2021</creationDate>
<copyright>(C) 2021 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.10.0</version>
<description>PLG_QUICKICON_EOS310_XML_DESCRIPTION</description>
<files>
<filename plugin="eos310">eos310.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_quickicon_eos310.ini</language>
<language
tag="en-GB">en-GB.plg_quickicon_eos310.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="last_snoozed_id"
type="hidden"
/>
</fieldset>
</fields>
</config>
</extension>
quickicon/extensionupdate/extensionupdate.php000064400000005161147357022240015711
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Quickicon.Extensionupdate
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Joomla! update notification plugin
*
* @since 2.5
*/
class PlgQuickiconExtensionupdate extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Returns an icon definition for an icon which looks for extensions
updates
* via AJAX and displays a notification when such updates are found.
*
* @param string $context The calling context
*
* @return array A list of icon definition associative arrays,
consisting of the
* keys link, image, text and access.
*
* @since 2.5
*/
public function onGetIcons($context)
{
if ($context !== $this->params->get('context',
'mod_quickicon') ||
!JFactory::getUser()->authorise('core.manage',
'com_installer'))
{
return;
}
JHtml::_('jquery.framework');
$token = JSession::getFormToken() . '=' . 1;
$url = JUri::base() .
'index.php?option=com_installer&view=update&task=update.find&'
. $token;
$ajax_url = JUri::base() .
'index.php?option=com_installer&view=update&task=update.ajax&'
. $token;
$script = array();
$script[] = 'var plg_quickicon_extensionupdate_url = \'' .
$url . '\';';
$script[] = 'var plg_quickicon_extensionupdate_ajax_url =
\'' . $ajax_url . '\';';
$script[] = 'var plg_quickicon_extensionupdate_text = {'
. '"UPTODATE" : "' .
JText::_('PLG_QUICKICON_EXTENSIONUPDATE_UPTODATE', true) .
'",'
. '"UPDATEFOUND": "' .
JText::_('PLG_QUICKICON_EXTENSIONUPDATE_UPDATEFOUND', true) .
'",'
. '"UPDATEFOUND_MESSAGE": "' .
JText::_('PLG_QUICKICON_EXTENSIONUPDATE_UPDATEFOUND_MESSAGE',
true) . '",'
. '"UPDATEFOUND_BUTTON": "' .
JText::_('PLG_QUICKICON_EXTENSIONUPDATE_UPDATEFOUND_BUTTON',
true) . '",'
. '"ERROR": "' .
JText::_('PLG_QUICKICON_EXTENSIONUPDATE_ERROR', true) .
'",'
. '};';
JFactory::getDocument()->addScriptDeclaration(implode("\n",
$script));
JHtml::_('script',
'plg_quickicon_extensionupdate/extensionupdatecheck.js',
array('version' => 'auto', 'relative'
=> true));
return array(
array(
'link' =>
'index.php?option=com_installer&view=update&task=update.find&'
. $token,
'image' => 'asterisk',
'icon' => 'header/icon-48-extension.png',
'text' =>
JText::_('PLG_QUICKICON_EXTENSIONUPDATE_CHECKING'),
'id' => 'plg_quickicon_extensionupdate',
'group' => 'MOD_QUICKICON_MAINTENANCE'
)
);
}
}
quickicon/extensionupdate/extensionupdate.xml000064400000002165147357022240015723
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="quickicon" method="upgrade">
<name>plg_quickicon_extensionupdate</name>
<author>Joomla! Project</author>
<creationDate>August 2011</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_QUICKICON_EXTENSIONUPDATE_XML_DESCRIPTION</description>
<files>
<filename
plugin="extensionupdate">extensionupdate.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_quickicon_extensionupdate.ini</language>
<language
tag="en-GB">en-GB.plg_quickicon_extensionupdate.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="context"
type="text"
label="PLG_QUICKICON_EXTENSIONUPDATE_GROUP_LABEL"
description="PLG_QUICKICON_EXTENSIONUPDATE_GROUP_DESC"
default="mod_quickicon"
/>
</fieldset>
</fields>
</config>
</extension>
quickicon/joomlaupdate/joomlaupdate.php000064400000006116147357022240014424
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Quickicon.Joomlaupdate
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Joomla! update notification plugin
*
* @since 2.5
*/
class PlgQuickiconJoomlaupdate extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* This method is called when the Quick Icons module is constructing its
set
* of icons. You can return an array which defines a single icon and it
will
* be rendered right after the stock Quick Icons.
*
* @param string $context The calling context
*
* @return array A list of icon definition associative arrays,
consisting of the
* keys link, image, text and access.
*
* @since 2.5
*/
public function onGetIcons($context)
{
if ($context !== $this->params->get('context',
'mod_quickicon') ||
!JFactory::getUser()->authorise('core.manage',
'com_joomlaupdate'))
{
return;
}
JHtml::_('jquery.framework');
$currentTemplate = JFactory::getApplication()->getTemplate();
$url = JUri::base() . 'index.php?option=com_joomlaupdate';
$ajaxUrl = JUri::base() .
'index.php?option=com_joomlaupdate&task=update.ajax&' .
JSession::getFormToken() . '=1';
$script = array();
$script[] = 'var plg_quickicon_joomlaupdate_url = \'' .
$url . '\';';
$script[] = 'var plg_quickicon_joomlaupdate_ajax_url = \''
. $ajaxUrl . '\';';
$script[] = 'var plg_quickicon_jupdatecheck_jversion = \''
. JVERSION . '\'';
$script[] = 'var plg_quickicon_joomlaupdate_text = {'
. '"UPTODATE" : "' .
JText::_('PLG_QUICKICON_JOOMLAUPDATE_UPTODATE', true) .
'",'
. '"UPDATEFOUND": "' .
JText::_('PLG_QUICKICON_JOOMLAUPDATE_UPDATEFOUND', true) .
'",'
. '"UPDATEFOUND_MESSAGE": "' .
JText::_('PLG_QUICKICON_JOOMLAUPDATE_UPDATEFOUND_MESSAGE', true)
. '",'
. '"UPDATEFOUND_BUTTON": "' .
JText::_('PLG_QUICKICON_JOOMLAUPDATE_UPDATEFOUND_BUTTON', true) .
'",'
. '"ERROR": "' .
JText::_('PLG_QUICKICON_JOOMLAUPDATE_ERROR', true) .
'",'
. '};';
$script[] = 'var plg_quickicon_joomlaupdate_img = {'
. '"UPTODATE" : "' . JUri::base(true) .
'/templates/' . $currentTemplate .
'/images/header/icon-48-jupdate-uptodate.png",'
. '"UPDATEFOUND": "' . JUri::base(true) .
'/templates/' . $currentTemplate .
'/images/header/icon-48-jupdate-updatefound.png",'
. '"ERROR": "' . JUri::base(true) .
'/templates/' . $currentTemplate .
'/images/header/icon-48-deny.png",'
. '};';
JFactory::getDocument()->addScriptDeclaration(implode("\n",
$script));
JHtml::_('script',
'plg_quickicon_joomlaupdate/jupdatecheck.js',
array('version' => 'auto', 'relative'
=> true));
return array(
array(
'link' => 'index.php?option=com_joomlaupdate',
'image' => 'joomla',
'icon' => 'header/icon-48-download.png',
'text' =>
JText::_('PLG_QUICKICON_JOOMLAUPDATE_CHECKING'),
'id' => 'plg_quickicon_joomlaupdate',
'group' => 'MOD_QUICKICON_MAINTENANCE'
)
);
}
}
quickicon/joomlaupdate/joomlaupdate.xml000064400000002134147357022240014431
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="quickicon" method="upgrade">
<name>plg_quickicon_joomlaupdate</name>
<author>Joomla! Project</author>
<creationDate>August 2011</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_QUICKICON_JOOMLAUPDATE_XML_DESCRIPTION</description>
<files>
<filename
plugin="joomlaupdate">joomlaupdate.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_quickicon_joomlaupdate.ini</language>
<language
tag="en-GB">en-GB.plg_quickicon_joomlaupdate.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="context"
type="text"
label="PLG_QUICKICON_JOOMLAUPDATE_GROUP_LABEL"
description="PLG_QUICKICON_JOOMLAUPDATE_GROUP_DESC"
default="mod_quickicon"
/>
</fieldset>
</fields>
</config>
</extension>
quickicon/phpversioncheck/phpversioncheck.php000064400000013707147357022240015646
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Quickicon.phpversioncheck
*
* @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;
/**
* Plugin to check the PHP version and display a warning about its support
status
*
* @since 3.7.0
*/
class PlgQuickiconPhpVersionCheck extends JPlugin
{
/**
* Constant representing the active PHP version being fully supported
*
* @var integer
* @since 3.7.0
*/
const PHP_SUPPORTED = 0;
/**
* Constant representing the active PHP version receiving security support
only
*
* @var integer
* @since 3.7.0
*/
const PHP_SECURITY_ONLY = 1;
/**
* Constant representing the active PHP version being unsupported
*
* @var integer
* @since 3.7.0
*/
const PHP_UNSUPPORTED = 2;
/**
* Application object.
*
* @var JApplicationCms
* @since 3.7.0
*/
protected $app;
/**
* Load plugin language files automatically
*
* @var boolean
* @since 3.7.0
*/
protected $autoloadLanguage = true;
/**
* Check the PHP version after the admin component has been dispatched.
*
* @param string $context The calling context
*
* @return void
*
* @since 3.7.0
*/
public function onGetIcons($context)
{
if (!$this->shouldDisplayMessage())
{
return;
}
$supportStatus = $this->getPhpSupport();
if ($supportStatus['status'] !== self::PHP_SUPPORTED)
{
// Enqueue the notification message; set a warning if receiving security
support or "error" if unsupported
switch ($supportStatus['status'])
{
case self::PHP_SECURITY_ONLY:
$this->app->enqueueMessage($supportStatus['message'],
'warning');
break;
case self::PHP_UNSUPPORTED:
$this->app->enqueueMessage($supportStatus['message'],
'error');
break;
}
}
}
/**
* Gets PHP support status.
*
* @return array Array of PHP support data
*
* @since 3.7.0
* @note The dates used in this method should correspond to the dates
given on PHP.net
* @link https://www.php.net/supported-versions.php
* @link https://www.php.net/eol.php
*/
private function getPhpSupport()
{
$phpSupportData = array(
'5.3' => array(
'security' => '2013-07-11',
'eos' => '2014-08-14',
),
'5.4' => array(
'security' => '2014-09-14',
'eos' => '2015-09-14',
),
'5.5' => array(
'security' => '2015-07-10',
'eos' => '2016-07-21',
),
'5.6' => array(
'security' => '2017-01-19',
'eos' => '2018-12-31',
),
'7.0' => array(
'security' => '2017-12-03',
'eos' => '2018-12-03',
),
'7.1' => array(
'security' => '2018-12-01',
'eos' => '2019-12-01',
),
'7.2' => array(
'security' => '2019-11-30',
'eos' => '2020-11-30',
),
'7.3' => array(
'security' => '2020-12-06',
'eos' => '2021-12-06',
),
'7.4' => array(
'security' => '2021-11-28',
'eos' => '2022-11-28',
),
'8.0' => array(
'security' => '2022-11-26',
'eos' => '2023-11-26',
),
'8.1' => array(
'security' => '2023-11-25',
'eos' => '2024-11-25',
),
);
// Fill our return array with default values
$supportStatus = array(
'status' => self::PHP_SUPPORTED,
'message' => null,
);
// Check the PHP version's support status using the minor version
$activePhpVersion = PHP_MAJOR_VERSION . '.' .
PHP_MINOR_VERSION;
// Do we have the PHP version's data?
if (isset($phpSupportData[$activePhpVersion]))
{
// First check if the version has reached end of support
$today = new JDate;
$phpEndOfSupport = new
JDate($phpSupportData[$activePhpVersion]['eos']);
if ($phpNotSupported = $today > $phpEndOfSupport)
{
/*
* Find the oldest PHP version still supported that is newer than the
current version,
* this is our recommendation for users on unsupported platforms
*/
foreach ($phpSupportData as $version => $versionData)
{
$versionEndOfSupport = new JDate($versionData['eos']);
if (version_compare($version, $activePhpVersion, 'ge')
&& ($today < $versionEndOfSupport))
{
$supportStatus['status'] = self::PHP_UNSUPPORTED;
$supportStatus['message'] = JText::sprintf(
'PLG_QUICKICON_PHPVERSIONCHECK_UNSUPPORTED',
PHP_VERSION,
$version,
$versionEndOfSupport->format(JText::_('DATE_FORMAT_LC4'))
);
return $supportStatus;
}
}
// PHP version is not supported and we don't know of any supported
versions.
$supportStatus['status'] = self::PHP_UNSUPPORTED;
$supportStatus['message'] =
JText::sprintf('PLG_QUICKICON_PHPVERSIONCHECK_UNSUPPORTED_JOOMLA_OUTDATED',
PHP_VERSION);
return $supportStatus;
}
// If the version is still supported, check if it has reached eol minus
3 month
$securityWarningDate = clone $phpEndOfSupport;
$securityWarningDate->sub(new DateInterval('P3M'));
if (!$phpNotSupported && $today > $securityWarningDate)
{
$supportStatus['status'] = self::PHP_SECURITY_ONLY;
$supportStatus['message'] = JText::sprintf(
'PLG_QUICKICON_PHPVERSIONCHECK_SECURITY_ONLY', PHP_VERSION,
$phpEndOfSupport->format(JText::_('DATE_FORMAT_LC4'))
);
}
}
return $supportStatus;
}
/**
* Determines if the message should be displayed
*
* @return boolean
*
* @since 3.7.0
*/
private function shouldDisplayMessage()
{
// Only on admin app
if (!$this->app->isClient('administrator'))
{
return false;
}
// Only if authenticated
if (JFactory::getUser()->guest)
{
return false;
}
// Only on HTML documents
if ($this->app->getDocument()->getType() !== 'html')
{
return false;
}
// Only on full page requests
if ($this->app->input->getCmd('tmpl',
'index') === 'component')
{
return false;
}
// Only to com_cpanel
if ($this->app->input->get('option') !==
'com_cpanel')
{
return false;
}
return true;
}
}
quickicon/phpversioncheck/phpversioncheck.xml000064400000001511147357022240015645
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.7" type="plugin"
group="quickicon" method="upgrade">
<name>plg_quickicon_phpversioncheck</name>
<author>Joomla! Project</author>
<creationDate>August 2016</creationDate>
<copyright>(C) 2016 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_QUICKICON_PHPVERSIONCHECK_XML_DESCRIPTION</description>
<files>
<filename
plugin="phpversioncheck">phpversioncheck.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_quickicon_phpversioncheck.ini</language>
<language
tag="en-GB">en-GB.plg_quickicon_phpversioncheck.sys.ini</language>
</languages>
</extension>
quickicon/privacycheck/privacycheck.php000064400000004624147357022240014404
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Quickicon.privacycheck
*
* @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\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Session\Session;
use Joomla\CMS\Uri\Uri;
/**
* Plugin to check privacy requests older than 14 days
*
* @since 3.9.0
*/
class PlgQuickiconPrivacyCheck extends JPlugin
{
/**
* Load plugin language files automatically
*
* @var boolean
* @since 3.9.0
*/
protected $autoloadLanguage = true;
/**
* Check privacy requests older than 14 days.
*
* @param string $context The calling context
*
* @return array A list of icon definition associative arrays
*
* @since 3.9.0
*/
public function onGetIcons($context)
{
if ($context !== $this->params->get('context',
'mod_quickicon') ||
!Factory::getUser()->authorise('core.admin'))
{
return;
}
JHtml::_('jquery.framework');
$token = Session::getFormToken() . '=' . 1;
$privacy = 'index.php?option=com_privacy';
$options = array(
'plg_quickicon_privacycheck_url' => Uri::base() .
$privacy .
'&view=requests&filter[status]=1&list[fullordering]=a.requested_at
ASC',
'plg_quickicon_privacycheck_ajax_url' => Uri::base() .
$privacy . '&task=getNumberUrgentRequests&' . $token,
'plg_quickicon_privacycheck_text' => array(
"NOREQUEST" =>
Text::_('PLG_QUICKICON_PRIVACYCHECK_NOREQUEST'),
"REQUESTFOUND" =>
Text::_('PLG_QUICKICON_PRIVACYCHECK_REQUESTFOUND'),
"REQUESTFOUND_MESSAGE" =>
Text::_('PLG_QUICKICON_PRIVACYCHECK_REQUESTFOUND_MESSAGE'),
"REQUESTFOUND_BUTTON" =>
Text::_('PLG_QUICKICON_PRIVACYCHECK_REQUESTFOUND_BUTTON'),
"ERROR" =>
Text::_('PLG_QUICKICON_PRIVACYCHECK_ERROR'),
)
);
Factory::getDocument()->addScriptOptions('js-privacy-check',
$options);
JHtml::_('script',
'plg_quickicon_privacycheck/privacycheck.js',
array('version' => 'auto', 'relative'
=> true));
return array(
array(
'link' => $privacy .
'&view=requests&filter[status]=1&list[fullordering]=a.requested_at
ASC',
'image' => 'users',
'icon' => 'header/icon-48-user.png',
'text' =>
Text::_('PLG_QUICKICON_PRIVACYCHECK_CHECKING'),
'id' => 'plg_quickicon_privacycheck',
'group' => 'MOD_QUICKICON_USERS'
)
);
}
}
quickicon/privacycheck/privacycheck.xml000064400000001465147357022240014415
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.9" type="plugin"
group="quickicon" method="upgrade">
<name>plg_quickicon_privacycheck</name>
<author>Joomla! Project</author>
<creationDate>June 2018</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_QUICKICON_PRIVACYCHECK_XML_DESCRIPTION</description>
<files>
<filename
plugin="privacycheck">privacycheck.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_quickicon_privacycheck.ini</language>
<language
tag="en-GB">en-GB.plg_quickicon_privacycheck.sys.ini</language>
</languages>
</extension>
sampledata/blog/blog.php000064400000076003147357022240011252
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Sampledata.Blog
*
* @copyright (C) 2017 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Session\Session;
/**
* Sampledata - Blog Plugin
*
* @since 3.8.0
*/
class PlgSampledataBlog extends JPlugin
{
/**
* Database object
*
* @var JDatabaseDriver
*
* @since 3.8.0
*/
protected $db;
/**
* Application object
*
* @var JApplicationCms
*
* @since 3.8.0
*/
protected $app;
/**
* Affects constructor behavior. If true, language files will be loaded
automatically.
*
* @var boolean
*
* @since 3.8.0
*/
protected $autoloadLanguage = true;
/**
* Holds the menuitem model
*
* @var MenusModelItem
*
* @since 3.8.0
*/
private $menuItemModel;
/**
* Get an overview of the proposed sampledata.
*
* @return boolean True on success.
*
* @since 3.8.0
*/
public function onSampledataGetOverview()
{
if (!Factory::getUser()->authorise('core.create',
'com_content'))
{
return;
}
$data = new stdClass;
$data->name = $this->_name;
$data->title =
JText::_('PLG_SAMPLEDATA_BLOG_OVERVIEW_TITLE');
$data->description =
JText::_('PLG_SAMPLEDATA_BLOG_OVERVIEW_DESC');
$data->icon = 'broadcast';
$data->steps = 3;
return $data;
}
/**
* First step to enter the sampledata. Content.
*
* @return array or void Will be converted into the JSON response to the
module.
*
* @since 3.8.0
*/
public function onAjaxSampledataApplyStep1()
{
if (!Session::checkToken('get') ||
$this->app->input->get('type') != $this->_name)
{
return;
};
if (!JComponentHelper::isEnabled('com_content') ||
!Factory::getUser()->authorise('core.create',
'com_content'))
{
$response = array();
$response['success'] = true;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_SKIPPED', 1,
'com_content');
return $response;
}
// Get some metadata.
$access = (int) $this->app->get('access', 1);
$user = JFactory::getUser();
// Detect language to be used.
$language = Multilanguage::isEnabled() ?
JFactory::getLanguage()->getTag() : '*';
$langSuffix = ($language !== '*') ? ' (' . $language
. ')' : '';
// Add Include Paths.
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_content/models/', 'ContentModel');
JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_content/tables/');
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_categories/models/',
'CategoriesModel');
JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_categories/tables/');
// Create "blog" category.
$categoryModel = JModelLegacy::getInstance('Category',
'CategoriesModel');
$catIds = array();
$categoryTitle =
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_CATEGORY_0_TITLE');
$alias = JApplicationHelper::stringURLSafe($categoryTitle);
// Set unicodeslugs if alias is empty
if (trim(str_replace('-', '', $alias) ==
''))
{
$unicode = JFactory::getConfig()->set('unicodeslugs', 1);
$alias = JApplicationHelper::stringURLSafe($categoryTitle);
JFactory::getConfig()->set('unicodeslugs', $unicode);
}
$category = array(
'title' => $categoryTitle . $langSuffix,
'parent_id' => 1,
'id' => 0,
'published' => 1,
'access' => $access,
'created_user_id' => $user->id,
'extension' => 'com_content',
'level' => 1,
'alias' => $alias . $langSuffix,
'associations' => array(),
'description' => '',
'language' => $language,
'params' => '',
);
try
{
if (!$categoryModel->save($category))
{
throw new Exception($categoryModel->getError());
}
}
catch (Exception $e)
{
$response = array();
$response['success'] = false;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_FAILED', 1,
$e->getMessage());
return $response;
}
// Get ID from category we just added
$catIds[] = $categoryModel->getItem()->id;
// Create "help" category.
$categoryTitle =
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_CATEGORY_1_TITLE');
$alias = JApplicationHelper::stringURLSafe($categoryTitle);
// Set unicodeslugs if alias is empty
if (trim(str_replace('-', '', $alias) ==
''))
{
$unicode = JFactory::getConfig()->set('unicodeslugs', 1);
$alias = JApplicationHelper::stringURLSafe($categoryTitle);
JFactory::getConfig()->set('unicodeslugs', $unicode);
}
$category = array(
'title' => $categoryTitle . $langSuffix,
'parent_id' => 1,
'id' => 0,
'published' => 1,
'access' => $access,
'created_user_id' => $user->id,
'extension' => 'com_content',
'level' => 1,
'alias' => $alias . $langSuffix,
'associations' => array(),
'description' => '',
'language' => $language,
'params' => '',
);
try
{
if (!$categoryModel->save($category))
{
throw new Exception($categoryModel->getError());
}
}
catch (Exception $e)
{
$response = array();
$response['success'] = false;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_FAILED', 1,
$e->getMessage());
return $response;
}
// Get ID from category we just added
$catIds[] = $categoryModel->getItem()->id;
// Create Articles.
$articleModel = JModelLegacy::getInstance('Article',
'ContentModel');
$articles = array(
array(
'catid' => $catIds[1],
'ordering' => 2,
),
array(
'catid' => $catIds[1],
'ordering' => 1,
'access' => 3,
),
array(
'catid' => $catIds[0],
'ordering' => 2,
),
array(
'catid' => $catIds[0],
'ordering' => 1,
),
array(
'catid' => $catIds[0],
'ordering' => 0,
),
array(
'catid' => $catIds[0],
'ordering' => 0,
),
);
foreach ($articles as $i => $article)
{
// Set values from language strings.
$title =
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_' . $i .
'_TITLE');
$alias = JApplicationHelper::stringURLSafe($title);
$article['title'] = $title . $langSuffix;
$article['introtext'] =
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_' . $i .
'_INTROTEXT');
$article['fulltext'] =
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_CONTENT_ARTICLE_' . $i .
'_FULLTEXT');
// Set values which are always the same.
$article['id'] = 0;
$article['created_user_id'] = $user->id;
$article['alias'] =
JApplicationHelper::stringURLSafe($article['title']);
// Set unicodeslugs if alias is empty
if (trim(str_replace('-', '', $alias) ==
''))
{
$unicode = JFactory::getConfig()->set('unicodeslugs', 1);
$article['alias'] =
JApplicationHelper::stringURLSafe($article['title']);
JFactory::getConfig()->set('unicodeslugs', $unicode);
}
$article['language'] = $language;
$article['associations'] = array();
$article['state'] = 1;
$article['featured'] = 0;
$article['images'] = '';
$article['metakey'] = '';
$article['metadesc'] = '';
$article['xreference'] = '';
if (!isset($article['access']))
{
$article['access'] = $access;
}
if (!$articleModel->save($article))
{
JFactory::getLanguage()->load('com_content');
$response = array();
$response['success'] = false;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_FAILED', 1,
JText::_($articleModel->getError()));
return $response;
}
// Get ID from article we just added
$ids[] = $articleModel->getItem()->id;
}
$this->app->setUserState('sampledata.blog.articles',
$ids);
$this->app->setUserState('sampledata.blog.articles.catids',
$catIds);
$response = new stdClass;
$response->success = true;
$response->message =
JText::_('PLG_SAMPLEDATA_BLOG_STEP1_SUCCESS');
return $response;
}
/**
* Second step to enter the sampledata. Menus.
*
* @return array or void Will be converted into the JSON response to the
module.
*
* @since 3.8.0
*/
public function onAjaxSampledataApplyStep2()
{
if (!Session::checkToken('get') ||
$this->app->input->get('type') != $this->_name)
{
return;
}
if (!JComponentHelper::isEnabled('com_menus') ||
!Factory::getUser()->authorise('core.create',
'com_menus'))
{
$response = array();
$response['success'] = true;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_SKIPPED', 2,
'com_menus');
return $response;
}
// Detect language to be used.
$language = Multilanguage::isEnabled() ?
JFactory::getLanguage()->getTag() : '*';
$langSuffix = ($language !== '*') ? ' (' . $language
. ')' : '';
// Create the menu types.
$menuTable = JTable::getInstance('Type',
'JTableMenu');
$menuTypes = array();
for ($i = 0; $i <= 2; $i++)
{
$menu = array(
'id' => 0,
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_MENU_' . $i .
'_TITLE') . $langSuffix,
'description' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_MENU_' . $i .
'_DESCRIPTION'),
);
// Calculate menutype. The number of characters allowed is 24.
$type = JHtml::_('string.truncate', $menu['title'],
23, true, false);
$menu['menutype'] = $i . $type;
try
{
$menuTable->load();
$menuTable->bind($menu);
if (!$menuTable->check())
{
throw new Exception($menuTable->getError());
}
$menuTable->store();
}
catch (Exception $e)
{
JFactory::getLanguage()->load('com_menus');
$response = array();
$response['success'] = false;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_FAILED', 2,
$e->getMessage());
return $response;
}
$menuTypes[] = $menuTable->menutype;
}
// Storing IDs in UserState for later usage.
$this->app->setUserState('sampledata.blog.menutypes',
$menuTypes);
// Get previously entered Data from UserStates.
$articleIds =
$this->app->getUserState('sampledata.blog.articles');
// Get MenuItemModel.
JLoader::register('MenusHelper', JPATH_ADMINISTRATOR .
'/components/com_menus/helpers/menus.php');
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_menus/models/', 'MenusModel');
JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_menus/tables/');
$this->menuItemModel = JModelLegacy::getInstance('Item',
'MenusModel');
// Get previously entered categories ids
$catids =
$this->app->getUserState('sampledata.blog.articles.catids');
// Insert menuitems level 1.
$menuItems = array(
array(
'menutype' => $menuTypes[0],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_0_TITLE'),
'link' =>
'index.php?option=com_content&view=category&layout=blog&id='
. $catids[0],
'component_id' => 22,
'params' => array(
'layout_type' => 'blog',
'show_category_title' => 0,
'num_leading_articles' => 4,
'num_intro_articles' => 0,
'num_columns' => 1,
'num_links' => 2,
'multi_column_order' => 1,
'orderby_sec' => 'rdate',
'order_date' => 'published',
'show_pagination' => 2,
'show_pagination_results' => 1,
'show_category' => 0,
'info_bloc_position' => 0,
'show_publish_date' => 0,
'show_hits' => 0,
'show_feed_link' => 1,
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
array(
'menutype' => $menuTypes[0],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_1_TITLE'),
'link' =>
'index.php?option=com_content&view=article&id=' .
$articleIds[0],
'component_id' => 22,
'params' => array(
'info_block_position' => 0,
'show_category' => 0,
'link_category' => 0,
'show_author' => 0,
'show_create_date' => 0,
'show_publish_date' => 0,
'show_hits' => 0,
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
array(
'menutype' => $menuTypes[0],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_2_TITLE'),
'link' =>
'index.php?option=com_users&view=login',
'component_id' => 25,
'params' => array(
'logindescription_show' => 1,
'logoutdescription_show' => 1,
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
array(
'menutype' => $menuTypes[1],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_3_TITLE'),
'link' =>
'index.php?option=com_content&view=form&layout=edit',
'component_id' => 22,
'access' => 3,
'params' => array(
'enable_category' => 1,
'catid' => $catids[0],
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
array(
'menutype' => $menuTypes[1],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_4_TITLE'),
'link' =>
'index.php?option=com_content&view=article&id=' .
$articleIds[1],
'component_id' => 22,
'params' => array(
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
array(
'menutype' => $menuTypes[1],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_5_TITLE'),
'link' => 'administrator',
'type' => 'url',
'component_id' => 0,
'browserNav' => 1,
'access' => 3,
'params' => array(
'menu_text' => 1,
),
),
array(
'menutype' => $menuTypes[1],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_6_TITLE'),
'link' =>
'index.php?option=com_users&view=profile&layout=edit',
'component_id' => 25,
'access' => 2,
'params' => array(
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
array(
'menutype' => $menuTypes[1],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_7_TITLE'),
'link' =>
'index.php?option=com_users&view=login',
'component_id' => 25,
'params' => array(
'logindescription_show' => 1,
'logoutdescription_show' => 1,
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
);
try
{
$menuIdsLevel1 = $this->addMenuItems($menuItems, 1);
}
catch (Exception $e)
{
$response = array();
$response['success'] = false;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_FAILED', 2,
$e->getMessage());
return $response;
}
// Insert another level 1.
$menuItems = array(
array(
'menutype' => $menuTypes[2],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_8_TITLE'),
'link' =>
'index.php?option=com_users&view=login',
'component_id' => 25,
'params' => array(
'login_redirect_url' => 'index.php?Itemid='
. $menuIdsLevel1[0],
'logindescription_show' => 1,
'logoutdescription_show' => 1,
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
);
try
{
$menuIdsLevel1 = array_merge($menuIdsLevel1,
$this->addMenuItems($menuItems, 1));
}
catch (Exception $e)
{
$response = array();
$response['success'] = false;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_FAILED', 2,
$e->getMessage());
return $response;
}
// Insert menuitems level 2.
$menuItems = array(
array(
'menutype' => $menuTypes[1],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_9_TITLE'),
'link' =>
'index.php?option=com_config&view=config&controller=config.display.config',
'parent_id' => $menuIdsLevel1[4],
'component_id' => 23,
'access' => 6,
'params' => array(
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
array(
'menutype' => $menuTypes[1],
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MENUS_ITEM_10_TITLE'),
'link' =>
'index.php?option=com_config&view=templates&controller=config.display.templates',
'parent_id' => $menuIdsLevel1[4],
'component_id' => 23,
'params' => array(
'menu_text' => 1,
'show_page_heading' => 0,
'secure' => 0,
),
),
);
try
{
$this->addMenuItems($menuItems, 2);
}
catch (Exception $e)
{
$response = array();
$response['success'] = false;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_FAILED', 2,
$e->getMessage());
return $response;
}
$response = array();
$response['success'] = true;
$response['message'] =
JText::_('PLG_SAMPLEDATA_BLOG_STEP2_SUCCESS');
return $response;
}
/**
* Third step to enter the sampledata. Modules.
*
* @return array or void Will be converted into the JSON response to the
module.
*
* @since 3.8.0
*/
public function onAjaxSampledataApplyStep3()
{
if (!Session::checkToken('get') ||
$this->app->input->get('type') != $this->_name)
{
return;
}
if (!JComponentHelper::isEnabled('com_modules') ||
!Factory::getUser()->authorise('core.create',
'com_modules'))
{
$response = array();
$response['success'] = true;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_SKIPPED', 3,
'com_modules');
return $response;
}
// Detect language to be used.
$language = Multilanguage::isEnabled() ?
JFactory::getLanguage()->getTag() : '*';
$langSuffix = ($language !== '*') ? ' (' . $language
. ')' : '';
// Add Include Paths.
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_modules/models/',
'ModulesModelModule');
JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_modules/tables/');
$model = JModelLegacy::getInstance('Module',
'ModulesModel');
$access = (int) $this->app->get('access', 1);
// Get previously entered Data from UserStates
$menuTypes =
$this->app->getUserState('sampledata.blog.menutypes');
$catids =
$this->app->getUserState('sampledata.blog.articles.catids');
$modules = array(
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_0_TITLE'),
'ordering' => 1,
'position' => 'position-1',
'module' => 'mod_menu',
'showtitle' => 0,
'params' => array(
'menutype' => $menuTypes[0],
'startLevel' => 1,
'endLevel' => 0,
'showAllChildren' => 0,
'class_sfx' => ' nav-pills',
'layout' => '_:default',
'cache' => 1,
'cache_time' => 900,
'cachemode' => 'itemid',
'module_tag' => 'div',
'bootstrap_size' => 0,
'header_tag' => 'h3',
'style' => 0,
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_1_TITLE'),
'ordering' => 1,
'position' => 'position-1',
'module' => 'mod_menu',
'access' => 3,
'showtitle' => 0,
'params' => array(
'menutype' => $menuTypes[1],
'startLevel' => 1,
'endLevel' => 0,
'showAllChildren' => 1,
'class_sfx' => ' nav-pills',
'layout' => '_:default',
'cache' => 1,
'cache_time' => 900,
'cachemode' => 'itemid',
'module_tag' => 'div',
'bootstrap_size' => 0,
'header_tag' => 'h3',
'style' => 0,
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_2_TITLE'),
'ordering' => 6,
'position' => 'position-7',
'module' => 'mod_syndicate',
'showtitle' => 0,
'params' => array(
'display_text' => 1,
'text' => 'My Blog',
'format' => 'rss',
'layout' => '_:default',
'cache' => 0,
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_3_TITLE'),
'ordering' => 4,
'position' => 'position-7',
'module' => 'mod_articles_archive',
'params' => array(
'count' => 10,
'layout' => '_:default',
'cache' => 1,
'cache_time' => 900,
'cachemode' => 'static',
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_4_TITLE'),
'ordering' => 5,
'position' => 'position-7',
'module' => 'mod_articles_popular',
'params' => array(
'catid' => $catids[0],
'count' => 5,
'show_front' => 1,
'layout' => '_:default',
'cache' => 1,
'cache_time' => 900,
'cachemode' => 'static',
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_5_TITLE'),
'ordering' => 2,
'position' => 'position-7',
'module' => 'mod_articles_category',
'params' => array(
'mode' => 'normal',
'show_on_article_page' => 0,
'show_front' => 'show',
'count' => 6,
'category_filtering_type' => 1,
'catid' => $catids[0],
'show_child_category_articles' => 0,
'levels' => 1,
'author_filtering_type' => 1,
'author_alias_filtering_type' => 1,
'date_filtering' => 'off',
'date_field' => 'a.created',
'relative_date' => 30,
'article_ordering' => 'a.created',
'article_ordering_direction' => 'DESC',
'article_grouping' => 'none',
'article_grouping_direction' => 'krsort',
'month_year_format' => 'F Y',
'item_heading' => 5,
'link_titles' => 1,
'show_date' => 0,
'show_date_field' => 'created',
'show_date_format' =>
JText::_('DATE_FORMAT_LC5'),
'show_category' => 0,
'show_hits' => 0,
'show_author' => 0,
'show_introtext' => 0,
'introtext_limit' => 100,
'show_readmore' => 0,
'show_readmore_title' => 1,
'readmore_limit' => 15,
'layout' => '_:default',
'owncache' => 1,
'cache_time' => 900,
'module_tag' => 'div',
'bootstrap_size' => 0,
'header_tag' => 'h3',
'style' => 0,
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_6_TITLE'),
'ordering' => 1,
'position' => 'footer',
'module' => 'mod_menu',
'showtitle' => 0,
'params' => array(
'menutype' => $menuTypes[2],
'startLevel' => 1,
'endLevel' => 0,
'showAllChildren' => 0,
'layout' => '_:default',
'cache' => 1,
'cache_time' => 900,
'cachemode' => 'itemid',
'module_tag' => 'div',
'bootstrap_size' => 0,
'header_tag' => 'h3',
'style' => 0,
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_7_TITLE'),
'ordering' => 1,
'position' => 'position-0',
'module' => 'mod_search',
'params' => array(
'width' => 20,
'button_pos' => 'right',
'opensearch' => 1,
'layout' => '_:default',
'cache' => 1,
'cache_time' => 900,
'cachemode' => 'itemid',
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_8_TITLE'),
'content' => '<p><img
src="images/headers/raindrops.jpg" alt=""
/></p>',
'ordering' => 1,
'position' => 'position-3',
'module' => 'mod_custom',
'showtitle' => 0,
'params' => array(
'prepare_content' => 1,
'layout' => '_:default',
'cache' => 1,
'cache_time' => 900,
'cachemode' => 'static',
'module_tag' => 'div',
'bootstrap_size' => 0,
'header_tag' => 'h3',
'style' => 0,
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_9_TITLE'),
'ordering' => 1,
'position' => 'position-7',
'module' => 'mod_tags_popular',
'params' => array(
'maximum' => 8,
'timeframe' => 'alltime',
'order_value' => 'count',
'order_direction' => 1,
'display_count' => 0,
'no_results_text' => 0,
'minsize' => 1,
'maxsize' => 2,
'layout' => '_:default',
'owncache' => 1,
'module_tag' => 'div',
'bootstrap_size' => 0,
'header_tag' => 'h3',
'style' => 0,
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_10_TITLE'),
'ordering' => 0,
'position' => '',
'module' => 'mod_tags_similar',
'params' => array(
'maximum' => 5,
'matchtype' => 'any',
'layout' => '_:default',
'owncache' => 1,
'module_tag' => 'div',
'bootstrap_size' => 0,
'header_tag' => 'h3',
'style' => 0,
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_11_TITLE'),
'ordering' => 4,
'position' => 'cpanel',
'module' => 'mod_stats_admin',
'access' => 6,
'client_id' => 1,
'params' => array(
'serverinfo' => 1,
'siteinfo' => 1,
'counter' => 0,
'increase' => 0,
'layout' => '_:default',
'cache' => 1,
'cache_time' => 900,
'cachemode' => 'static',
'module_tag' => 'div',
'bootstrap_size' => 6,
'header_tag' => 'h3',
'style' => 0,
),
),
array(
'title' =>
JText::_('PLG_SAMPLEDATA_BLOG_SAMPLEDATA_MODULES_MODULE_12_TITLE'),
'ordering' => 1,
'position' => 'postinstall',
'module' => 'mod_feed',
'client_id' => 1,
'params' => array(
'rssurl' =>
'https://www.joomla.org/announcements/release-news.feed',
'rssrtl' => 0,
'rsstitle' => 1,
'rssdesc' => 1,
'rssimage' => 1,
'rssitems' => 3,
'rssitemdesc' => 1,
'word_count' => 0,
'layout' => '_:default',
'cache' => 1,
'cache_time' => 900,
'module_tag' => 'div',
'bootstrap_size' => 0,
'header_tag' => 'h3',
'style' => 0,
),
),
);
foreach ($modules as $module)
{
// Append language suffix to title.
$module['title'] .= $langSuffix;
// Set values which are always the same.
$module['id'] = 0;
$module['asset_id'] = 0;
$module['language'] = $language;
$module['note'] = '';
$module['published'] = 1;
$module['assignment'] = 0;
if (!isset($module['content']))
{
$module['content'] = '';
}
if (!isset($module['access']))
{
$module['access'] = $access;
}
if (!isset($module['showtitle']))
{
$module['showtitle'] = 1;
}
if (!isset($module['client_id']))
{
$module['client_id'] = 0;
}
if (!$model->save($module))
{
JFactory::getLanguage()->load('com_modules');
$response = array();
$response['success'] = false;
$response['message'] =
JText::sprintf('PLG_SAMPLEDATA_BLOG_STEP_FAILED', 3,
JText::_($model->getError()));
return $response;
}
}
$response = array();
$response['success'] = true;
$response['message'] =
JText::_('PLG_SAMPLEDATA_BLOG_STEP3_SUCCESS');
return $response;
}
/**
* Adds menuitems.
*
* @param array $menuItems Array holding the menuitems arrays.
* @param integer $level Level in the category tree.
*
* @return array IDs of the inserted menuitems.
*
* @since 3.8.0
*
* @throws Exception
*/
private function addMenuItems(array $menuItems, $level)
{
$itemIds = array();
$access = (int) $this->app->get('access', 1);
$user = JFactory::getUser();
// Detect language to be used.
$language = Multilanguage::isEnabled() ?
JFactory::getLanguage()->getTag() : '*';
$langSuffix = ($language !== '*') ? ' (' . $language
. ')' : '';
foreach ($menuItems as $menuItem)
{
// Reset item.id in model state.
$this->menuItemModel->setState('item.id', 0);
// Set values which are always the same.
$menuItem['id'] = 0;
$menuItem['created_user_id'] = $user->id;
$menuItem['alias'] =
JApplicationHelper::stringURLSafe($menuItem['title']);
// Set unicodeslugs if alias is empty
if (trim(str_replace('-', '',
$menuItem['alias']) == ''))
{
$unicode = JFactory::getConfig()->set('unicodeslugs', 1);
$menuItem['alias'] =
JApplicationHelper::stringURLSafe($menuItem['title']);
JFactory::getConfig()->set('unicodeslugs', $unicode);
}
// Append language suffix to title.
$menuItem['title'] .= $langSuffix;
$menuItem['published'] = 1;
$menuItem['language'] = $language;
$menuItem['note'] = '';
$menuItem['img'] = '';
$menuItem['associations'] = array();
$menuItem['client_id'] = 0;
$menuItem['level'] = $level;
$menuItem['home'] = 0;
// Set browserNav to default if not set
if (!isset($menuItem['browserNav']))
{
$menuItem['browserNav'] = 0;
}
// Set access to default if not set
if (!isset($menuItem['access']))
{
$menuItem['access'] = $access;
}
// Set type to 'component' if not set
if (!isset($menuItem['type']))
{
$menuItem['type'] = 'component';
}
// Set template_style_id to global if not set
if (!isset($menuItem['template_style_id']))
{
$menuItem['template_style_id'] = 0;
}
// Set parent_id to root (1) if not set
if (!isset($menuItem['parent_id']))
{
$menuItem['parent_id'] = 1;
}
if (!$this->menuItemModel->save($menuItem))
{
// Try two times with another alias (-1 and -2).
$menuItem['alias'] .= '-1';
if (!$this->menuItemModel->save($menuItem))
{
$menuItem['alias'] =
substr_replace($menuItem['alias'], '2', -1);
if (!$this->menuItemModel->save($menuItem))
{
throw new Exception($menuItem['title'] . ' =>
' . $menuItem['alias'] . ' : ' .
$this->menuItemModel->getError());
}
}
}
// Get ID from menuitem we just added
$itemIds[] = $this->menuItemModel->getstate('item.id');
}
return $itemIds;
}
}
sampledata/blog/blog.xml000064400000001504147357022240011255
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.8" type="plugin"
group="sampledata" method="upgrade">
<name>plg_sampledata_blog</name>
<author>Joomla! Project</author>
<creationDate>July 2017</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.8.0</version>
<description>PLG_SAMPLEDATA_BLOG_XML_DESCRIPTION</description>
<files>
<filename plugin="blog">blog.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_sampledata_blog.ini</language>
<language
tag="en-GB">en-GB.plg_sampledata_blog.sys.ini</language>
</languages>
<config>
<fields name="params">
</fields>
</config>
</extension>
search/categories/categories.php000064400000011604147357022240013004
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Search.categories
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::register('ContentHelperRoute', JPATH_SITE .
'/components/com_content/helpers/route.php');
/**
* Categories search plugin.
*
* @since 1.6
*/
class PlgSearchCategories extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Determine areas searchable by this plugin.
*
* @return array An array of search areas.
*
* @since 1.6
*/
public function onContentSearchAreas()
{
static $areas = array(
'categories' =>
'PLG_SEARCH_CATEGORIES_CATEGORIES'
);
return $areas;
}
/**
* Search content (categories).
*
* The SQL must return the following fields that are used in a common
display
* routine: href, title, section, created, text, browsernav.
*
* @param string $text Target search string.
* @param string $phrase Matching option (possible values:
exact|any|all). Default is "any".
* @param string $ordering Ordering option (possible values:
newest|oldest|popular|alpha|category). Default is "newest".
* @param mixed $areas An array if the search is to be restricted
to areas or null to search all areas.
*
* @return array Search results.
*
* @since 1.6
*/
public function onContentSearch($text, $phrase = '', $ordering =
'', $areas = null)
{
$db = JFactory::getDbo();
$user = JFactory::getUser();
$app = JFactory::getApplication();
$groups = implode(',', $user->getAuthorisedViewLevels());
$searchText = $text;
if (is_array($areas) && !array_intersect($areas,
array_keys($this->onContentSearchAreas())))
{
return array();
}
$sContent = $this->params->get('search_content', 1);
$sArchived = $this->params->get('search_archived', 1);
$limit = $this->params->def('search_limit', 50);
$state = array();
if ($sContent)
{
$state[] = 1;
}
if ($sArchived)
{
$state[] = 2;
}
if (empty($state))
{
return array();
}
$text = trim($text);
if ($text === '')
{
return array();
}
/* TODO: The $where variable does not seem to be used at all
switch ($phrase)
{
case 'exact':
$text = $db->quote('%' . $db->escape($text, true) .
'%', false);
$wheres2 = array();
$wheres2[] = 'a.title LIKE ' . $text;
$wheres2[] = 'a.description LIKE ' . $text;
$where = '(' . implode(') OR (', $wheres2) .
')';
break;
case 'any':
case 'all';
default:
$words = explode(' ', $text);
$wheres = array();
foreach ($words as $word)
{
$word = $db->quote('%' . $db->escape($word, true) .
'%', false);
$wheres2 = array();
$wheres2[] = 'a.title LIKE ' . $word;
$wheres2[] = 'a.description LIKE ' . $word;
$wheres[] = implode(' OR ', $wheres2);
}
$where = '(' . implode(($phrase == 'all' ? ')
AND (' : ') OR ('), $wheres) . ')';
break;
}
*/
switch ($ordering)
{
case 'alpha':
$order = 'a.title ASC';
break;
case 'category':
case 'popular':
case 'newest':
case 'oldest':
default:
$order = 'a.title DESC';
}
$text = $db->quote('%' . $db->escape($text, true) .
'%', false);
$query = $db->getQuery(true);
// SQLSRV changes.
$case_when = ' CASE WHEN ';
$case_when .= $query->charLength('a.alias', '!=',
'0');
$case_when .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when .= $query->concatenate(array($a_id, 'a.alias'),
':');
$case_when .= ' ELSE ';
$case_when .= $a_id . ' END as slug';
$query->select('a.title, a.description AS text, a.created_time AS
created, \'2\' AS browsernav, a.id AS catid, ' . $case_when)
->from('#__categories AS a')
->where(
'(a.title LIKE ' . $text . ' OR a.description LIKE
' . $text . ') AND a.published IN (' .
implode(',', $state) . ') AND a.extension = '
. $db->quote('com_content') . 'AND a.access IN
(' . $groups . ')'
)
->group('a.id, a.title, a.description, a.alias,
a.created_time')
->order($order);
if ($app->isClient('site') &&
JLanguageMultilang::isEnabled())
{
$query->where('a.language in (' .
$db->quote(JFactory::getLanguage()->getTag()) . ',' .
$db->quote('*') . ')');
}
$db->setQuery($query, 0, $limit);
try
{
$rows = $db->loadObjectList();
}
catch (RuntimeException $e)
{
$rows = array();
JFactory::getApplication()->enqueueMessage(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'),
'error');
}
$return = array();
if ($rows)
{
foreach ($rows as $i => $row)
{
if (searchHelper::checkNoHtml($row, $searchText,
array('name', 'title', 'text')))
{
$row->href = ContentHelperRoute::getCategoryRoute($row->slug);
$row->section = JText::_('JCATEGORY');
$return[] = $row;
}
}
}
return $return;
}
}
search/categories/categories.xml000064400000003340147357022240013013
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="search" method="upgrade">
<name>plg_search_categories</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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_SEARCH_CATEGORIES_XML_DESCRIPTION</description>
<files>
<filename
plugin="categories">categories.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_search_categories.ini</language>
<language
tag="en-GB">en-GB.plg_search_categories.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="search_limit"
type="number"
label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
default="50"
filter="integer"
size="5"
/>
<field
name="search_content"
type="radio"
label="JFIELD_PLG_SEARCH_ALL_LABEL"
description="JFIELD_PLG_SEARCH_ALL_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="search_archived"
type="radio"
label="JFIELD_PLG_SEARCH_ARCHIVED_LABEL"
description="JFIELD_PLG_SEARCH_ARCHIVED_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
search/contacts/contacts.php000064400000012067147357022240012172
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Search.contacts
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Contacts search plugin.
*
* @since 1.6
*/
class PlgSearchContacts extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Determine areas searchable by this plugin.
*
* @return array An array of search areas.
*
* @since 1.6
*/
public function onContentSearchAreas()
{
static $areas = array(
'contacts' => 'PLG_SEARCH_CONTACTS_CONTACTS'
);
return $areas;
}
/**
* Search content (contacts).
*
* The SQL must return the following fields that are used in a common
display
* routine: href, title, section, created, text, browsernav.
*
* @param string $text Target search string.
* @param string $phrase Matching option (possible values:
exact|any|all). Default is "any".
* @param string $ordering Ordering option (possible values:
newest|oldest|popular|alpha|category). Default is "newest".
* @param string $areas An array if the search is to be restricted
to areas or null to search all areas.
*
* @return array Search results.
*
* @since 1.6
*/
public function onContentSearch($text, $phrase = '', $ordering =
'', $areas = null)
{
JLoader::register('ContactHelperRoute', JPATH_SITE .
'/components/com_contact/helpers/route.php');
$db = JFactory::getDbo();
$app = JFactory::getApplication();
$user = JFactory::getUser();
$groups = implode(',', $user->getAuthorisedViewLevels());
if (is_array($areas) && !array_intersect($areas,
array_keys($this->onContentSearchAreas())))
{
return array();
}
$sContent = $this->params->get('search_content', 1);
$sArchived = $this->params->get('search_archived', 1);
$limit = $this->params->def('search_limit', 50);
$state = array();
if ($sContent)
{
$state[] = 1;
}
if ($sArchived)
{
$state[] = 2;
}
if (empty($state))
{
return array();
}
$text = trim($text);
if ($text === '')
{
return array();
}
$section = JText::_('PLG_SEARCH_CONTACTS_CONTACTS');
switch ($ordering)
{
case 'alpha':
$order = 'a.name ASC';
break;
case 'category':
$order = 'c.title ASC, a.name ASC';
break;
case 'popular':
case 'newest':
case 'oldest':
default:
$order = 'a.name DESC';
}
$text = $db->quote('%' . $db->escape($text, true) .
'%', false);
$query = $db->getQuery(true);
// SQLSRV changes.
$case_when = ' CASE WHEN ';
$case_when .= $query->charLength('a.alias', '!=',
'0');
$case_when .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when .= $query->concatenate(array($a_id, 'a.alias'),
':');
$case_when .= ' ELSE ';
$case_when .= $a_id . ' END as slug';
$case_when1 = ' CASE WHEN ';
$case_when1 .= $query->charLength('c.alias', '!=',
'0');
$case_when1 .= ' THEN ';
$c_id = $query->castAsChar('c.id');
$case_when1 .= $query->concatenate(array($c_id, 'c.alias'),
':');
$case_when1 .= ' ELSE ';
$case_when1 .= $c_id . ' END as catslug';
$query->select(
'a.name AS title, \'\' AS created, a.con_position,
a.misc, '
. $case_when . ',' . $case_when1 . ', '
. $query->concatenate(array('a.name',
'a.con_position', 'a.misc'), ',') . ' AS
text,'
. $query->concatenate(array($db->quote($section),
'c.title'), ' / ') . ' AS section,'
. '\'2\' AS browsernav'
);
$query->from('#__contact_details AS a')
->join('INNER', '#__categories AS c ON c.id =
a.catid')
->where(
'(a.name LIKE ' . $text . ' OR a.misc LIKE ' .
$text . ' OR a.con_position LIKE ' . $text
. ' OR a.address LIKE ' . $text . ' OR a.suburb LIKE
' . $text . ' OR a.state LIKE ' . $text
. ' OR a.country LIKE ' . $text . ' OR a.postcode LIKE
' . $text . ' OR a.telephone LIKE ' . $text
. ' OR a.fax LIKE ' . $text . ') AND a.published IN
(' . implode(',', $state) . ') AND c.published=1 '
. ' AND a.access IN (' . $groups . ') AND c.access IN
(' . $groups . ')'
)
->order($order);
// Filter by language.
if ($app->isClient('site') &&
JLanguageMultilang::isEnabled())
{
$tag = JFactory::getLanguage()->getTag();
$query->where('a.language in (' . $db->quote($tag) .
',' . $db->quote('*') . ')')
->where('c.language in (' . $db->quote($tag) .
',' . $db->quote('*') . ')');
}
$db->setQuery($query, 0, $limit);
try
{
$rows = $db->loadObjectList();
}
catch (RuntimeException $e)
{
$rows = array();
JFactory::getApplication()->enqueueMessage(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'),
'error');
}
if ($rows)
{
foreach ($rows as $key => $row)
{
$rows[$key]->href =
ContactHelperRoute::getContactRoute($row->slug, $row->catslug);
$rows[$key]->text = $row->title;
$rows[$key]->text .= $row->con_position ? ', ' .
$row->con_position : '';
$rows[$key]->text .= $row->misc ? ', ' . $row->misc
: '';
}
}
return $rows;
}
}
search/contacts/contacts.xml000064400000003322147357022240012175
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="search" method="upgrade">
<name>plg_search_contacts</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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_SEARCH_CONTACTS_XML_DESCRIPTION</description>
<files>
<filename plugin="contacts">contacts.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_search_contacts.ini</language>
<language
tag="en-GB">en-GB.plg_search_contacts.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="search_limit"
type="number"
label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
default="50"
filter="integer"
size="5"
/>
<field
name="search_content"
type="radio"
label="JFIELD_PLG_SEARCH_ALL_LABEL"
description="JFIELD_PLG_SEARCH_ALL_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="search_archived"
type="radio"
label="JFIELD_PLG_SEARCH_ARCHIVED_LABEL"
description="JFIELD_PLG_SEARCH_ARCHIVED_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
search/content/content.php000064400000032177147357022240011666
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Search.content
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Content search plugin.
*
* @since 1.6
*/
class PlgSearchContent extends JPlugin
{
/**
* Determine areas searchable by this plugin.
*
* @return array An array of search areas.
*
* @since 1.6
*/
public function onContentSearchAreas()
{
static $areas = array(
'content' => 'JGLOBAL_ARTICLES'
);
return $areas;
}
/**
* Search content (articles).
* The SQL must return the following fields that are used in a common
display
* routine: href, title, section, created, text, browsernav.
*
* @param string $text Target search string.
* @param string $phrase Matching option (possible values:
exact|any|all). Default is "any".
* @param string $ordering Ordering option (possible values:
newest|oldest|popular|alpha|category). Default is "newest".
* @param mixed $areas An array if the search it to be restricted
to areas or null to search all areas.
*
* @return array Search results.
*
* @since 1.6
*/
public function onContentSearch($text, $phrase = '', $ordering =
'', $areas = null)
{
$db = JFactory::getDbo();
$serverType = $db->getServerType();
$app = JFactory::getApplication();
$user = JFactory::getUser();
$groups = implode(',',
$user->getAuthorisedViewLevels());
$tag = JFactory::getLanguage()->getTag();
JLoader::register('ContentHelperRoute', JPATH_SITE .
'/components/com_content/helpers/route.php');
JLoader::register('SearchHelper', JPATH_ADMINISTRATOR .
'/components/com_search/helpers/search.php');
$searchText = $text;
if (is_array($areas) && !array_intersect($areas,
array_keys($this->onContentSearchAreas())))
{
return array();
}
$sContent = $this->params->get('search_content', 1);
$sArchived = $this->params->get('search_archived', 1);
$limit = $this->params->def('search_limit', 50);
$nullDate = $db->getNullDate();
$date = JFactory::getDate();
$now = $date->toSql();
$text = trim($text);
if ($text === '')
{
return array();
}
switch ($phrase)
{
case 'exact':
$text = $db->quote('%' . $db->escape($text, true)
. '%', false);
$wheres2 = array();
$wheres2[] = 'a.title LIKE ' . $text;
$wheres2[] = 'a.introtext LIKE ' . $text;
$wheres2[] = 'a.fulltext LIKE ' . $text;
$wheres2[] = 'a.metakey LIKE ' . $text;
$wheres2[] = 'a.metadesc LIKE ' . $text;
$relevance[] = ' CASE WHEN ' . $wheres2[0] . ' THEN 5
ELSE 0 END ';
// Join over Fields.
$subQuery = $db->getQuery(true);
$subQuery->select("cfv.item_id")
->from("#__fields_values AS cfv")
->join('LEFT', '#__fields AS f ON f.id =
cfv.field_id')
->where('(f.context IS NULL OR f.context = ' .
$db->q('com_content.article') . ')')
->where('(f.state IS NULL OR f.state = 1)')
->where('(f.access IS NULL OR f.access IN (' . $groups .
'))')
->where('cfv.value LIKE ' . $text);
// Filter by language.
if ($app->isClient('site') &&
JLanguageMultilang::isEnabled())
{
$subQuery->where('(f.language IS NULL OR f.language in ('
. $db->quote($tag) . ',' . $db->quote('*') .
'))');
}
if ($serverType == "mysql")
{
/* This generates a dependent sub-query so do no use in MySQL prior to
version 6.0 !
* $wheres2[] = 'a.id IN( '. (string)
$subQuery.')';
*/
$db->setQuery($subQuery);
$fieldids = $db->loadColumn();
if (count($fieldids))
{
$wheres2[] = 'a.id IN(' . implode(",", $fieldids)
. ')';
}
}
else
{
$wheres2[] = $subQuery->castAsChar('a.id') . ' IN(
' . (string) $subQuery . ')';
}
$where = '(' . implode(') OR (', $wheres2) .
')';
break;
case 'all':
case 'any':
default:
$words = explode(' ', $text);
$wheres = array();
$cfwhere = array();
foreach ($words as $word)
{
$word = $db->quote('%' . $db->escape($word, true)
. '%', false);
$wheres2 = array();
$wheres2[] = 'LOWER(a.title) LIKE LOWER(' . $word .
')';
$wheres2[] = 'LOWER(a.introtext) LIKE LOWER(' . $word .
')';
$wheres2[] = 'LOWER(a.fulltext) LIKE LOWER(' . $word .
')';
$wheres2[] = 'LOWER(a.metakey) LIKE LOWER(' . $word .
')';
$wheres2[] = 'LOWER(a.metadesc) LIKE LOWER(' . $word .
')';
$relevance[] = ' CASE WHEN ' . $wheres2[0] . ' THEN 5
ELSE 0 END ';
if ($phrase === 'all')
{
// Join over Fields.
$subQuery = $db->getQuery(true);
$subQuery->select("cfv.item_id")
->from("#__fields_values AS cfv")
->join('LEFT', '#__fields AS f ON f.id =
cfv.field_id')
->where('(f.context IS NULL OR f.context = ' .
$db->q('com_content.article') . ')')
->where('(f.state IS NULL OR f.state = 1)')
->where('(f.access IS NULL OR f.access IN (' . $groups
. '))')
->where('LOWER(cfv.value) LIKE LOWER(' . $word .
')');
// Filter by language.
if ($app->isClient('site') &&
JLanguageMultilang::isEnabled())
{
$subQuery->where('(f.language IS NULL OR f.language in
(' . $db->quote($tag) . ',' .
$db->quote('*') . '))');
}
if ($serverType == "mysql")
{
$db->setQuery($subQuery);
$fieldids = $db->loadColumn();
if (count($fieldids))
{
$wheres2[] = 'a.id IN(' . implode(",",
$fieldids) . ')';
}
}
else
{
$wheres2[] = $subQuery->castAsChar('a.id') . ' IN(
' . (string) $subQuery . ')';
}
}
else
{
$cfwhere[] = 'LOWER(cfv.value) LIKE LOWER(' . $word .
')';
}
$wheres[] = implode(' OR ', $wheres2);
}
if ($phrase === 'any')
{
// Join over Fields.
$subQuery = $db->getQuery(true);
$subQuery->select("cfv.item_id")
->from("#__fields_values AS cfv")
->join('LEFT', '#__fields AS f ON f.id =
cfv.field_id')
->where('(f.context IS NULL OR f.context = ' .
$db->q('com_content.article') . ')')
->where('(f.state IS NULL OR f.state = 1)')
->where('(f.access IS NULL OR f.access IN (' . $groups .
'))')
->where('(' . implode(($phrase === 'all' ?
') AND (' : ') OR ('), $cfwhere) . ')');
// Filter by language.
if ($app->isClient('site') &&
JLanguageMultilang::isEnabled())
{
$subQuery->where('(f.language IS NULL OR f.language in
(' . $db->quote($tag) . ',' .
$db->quote('*') . '))');
}
if ($serverType == "mysql")
{
$db->setQuery($subQuery);
$fieldids = $db->loadColumn();
if (count($fieldids))
{
$wheres[] = 'a.id IN(' . implode(",", $fieldids)
. ')';
}
}
else
{
$wheres[] = $subQuery->castAsChar('a.id') . ' IN(
' . (string) $subQuery . ')';
}
}
$where = '(' . implode(($phrase === 'all' ? ')
AND (' : ') OR ('), $wheres) . ')';
break;
}
switch ($ordering)
{
case 'oldest':
$order = 'a.created ASC';
break;
case 'popular':
$order = 'a.hits DESC';
break;
case 'alpha':
$order = 'a.title ASC';
break;
case 'category':
$order = 'c.title ASC, a.title ASC';
break;
case 'newest':
default:
$order = 'a.created DESC';
break;
}
$rows = array();
$query = $db->getQuery(true);
// Search articles.
if ($sContent && $limit > 0)
{
$query->clear();
// SQLSRV changes.
$case_when = ' CASE WHEN ';
$case_when .= $query->charLength('a.alias', '!=',
'0');
$case_when .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when .= $query->concatenate(array($a_id, 'a.alias'),
':');
$case_when .= ' ELSE ';
$case_when .= $a_id . ' END as slug';
$case_when1 = ' CASE WHEN ';
$case_when1 .= $query->charLength('c.alias',
'!=', '0');
$case_when1 .= ' THEN ';
$c_id = $query->castAsChar('c.id');
$case_when1 .= $query->concatenate(array($c_id, 'c.alias'),
':');
$case_when1 .= ' ELSE ';
$case_when1 .= $c_id . ' END as catslug';
if (!empty($relevance))
{
$query->select(implode(' + ', $relevance) . ' AS
relevance');
$order = ' relevance DESC, ' . $order;
}
$query->select('a.title AS title, a.metadesc, a.metakey,
a.created AS created, a.language, a.catid')
->select($query->concatenate(array('a.introtext',
'a.fulltext')) . ' AS text')
->select('c.title AS section, ' . $case_when .
',' . $case_when1 . ', ' . '\'2\' AS
browsernav')
->from('#__content AS a')
->join('INNER', '#__categories AS c ON
c.id=a.catid')
->where(
'(' . $where . ') AND a.state=1 AND c.published = 1 AND
a.access IN (' . $groups . ') '
. 'AND c.access IN (' . $groups . ')'
. 'AND (a.publish_up = ' . $db->quote($nullDate) .
' OR a.publish_up <= ' . $db->quote($now) . ') '
. 'AND (a.publish_down = ' . $db->quote($nullDate) .
' OR a.publish_down >= ' . $db->quote($now) . ')'
)
->group('a.id, a.title, a.metadesc, a.metakey, a.created,
a.language, a.catid, a.introtext, a.fulltext, c.title, a.alias, c.alias,
c.id')
->order($order);
// Filter by language.
if ($app->isClient('site') &&
JLanguageMultilang::isEnabled())
{
$query->where('a.language in (' . $db->quote($tag) .
',' . $db->quote('*') . ')')
->where('c.language in (' . $db->quote($tag) .
',' . $db->quote('*') . ')');
}
$db->setQuery($query, 0, $limit);
try
{
$list = $db->loadObjectList();
}
catch (RuntimeException $e)
{
$list = array();
JFactory::getApplication()->enqueueMessage(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'),
'error');
}
$limit -= count($list);
if (isset($list))
{
foreach ($list as $key => $item)
{
$list[$key]->href =
ContentHelperRoute::getArticleRoute($item->slug, $item->catid,
$item->language);
}
}
$rows[] = $list;
}
// Search archived content.
if ($sArchived && $limit > 0)
{
$query->clear();
// SQLSRV changes.
$case_when = ' CASE WHEN ';
$case_when .= $query->charLength('a.alias', '!=',
'0');
$case_when .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when .= $query->concatenate(array($a_id, 'a.alias'),
':');
$case_when .= ' ELSE ';
$case_when .= $a_id . ' END as slug';
$case_when1 = ' CASE WHEN ';
$case_when1 .= $query->charLength('c.alias',
'!=', '0');
$case_when1 .= ' THEN ';
$c_id = $query->castAsChar('c.id');
$case_when1 .= $query->concatenate(array($c_id, 'c.alias'),
':');
$case_when1 .= ' ELSE ';
$case_when1 .= $c_id . ' END as catslug';
if (!empty($relevance))
{
$query->select(implode(' + ', $relevance) . ' AS
relevance');
$order = ' relevance DESC, ' . $order;
}
$query->select('a.title AS title, a.metadesc, a.metakey,
a.created AS created, a.language, a.catid')
->select($query->concatenate(array('a.introtext',
'a.fulltext')) . ' AS text')
->select('c.title AS section, ' . $case_when .
',' . $case_when1 . ', ' . '\'2\' AS
browsernav')
->from('#__content AS a')
->join('INNER', '#__categories AS c ON c.id=a.catid
AND c.access IN (' . $groups . ')')
->where(
'(' . $where . ') AND a.state = 2 AND c.published = 1
AND a.access IN (' . $groups
. ') AND c.access IN (' . $groups . ') '
. 'AND (a.publish_up = ' . $db->quote($nullDate) .
' OR a.publish_up <= ' . $db->quote($now) . ') '
. 'AND (a.publish_down = ' . $db->quote($nullDate) .
' OR a.publish_down >= ' . $db->quote($now) . ')'
)
->order($order);
// Join over Fields is no longer needed
// Filter by language.
if ($app->isClient('site') &&
JLanguageMultilang::isEnabled())
{
$query->where('a.language in (' . $db->quote($tag) .
',' . $db->quote('*') . ')')
->where('c.language in (' . $db->quote($tag) .
',' . $db->quote('*') . ')');
}
$db->setQuery($query, 0, $limit);
try
{
$list3 = $db->loadObjectList();
}
catch (RuntimeException $e)
{
$list3 = array();
JFactory::getApplication()->enqueueMessage(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'),
'error');
}
if (isset($list3))
{
foreach ($list3 as $key => $item)
{
$list3[$key]->href =
ContentHelperRoute::getArticleRoute($item->slug, $item->catid,
$item->language);
}
}
$rows[] = $list3;
}
$results = array();
if (count($rows))
{
foreach ($rows as $row)
{
$new_row = array();
foreach ($row as $article)
{
// Not efficient to get these ONE article at a TIME
// Lookup field values so they can be checked, GROUP_CONCAT would work
in above queries, but isn't supported by non-MySQL DBs.
$query = $db->getQuery(true);
$query->select('fv.value')
->from('#__fields_values as fv')
->join('left', '#__fields as f on fv.field_id =
f.id')
->where('f.context = ' .
$db->quote('com_content.article'))
->where('fv.item_id = ' . $db->quote((int)
$article->slug));
$db->setQuery($query);
$article->jcfields = implode(',', $db->loadColumn());
if (SearchHelper::checkNoHtml($article, $searchText,
array('text', 'title', 'jcfields',
'metadesc', 'metakey')))
{
$new_row[] = $article;
}
}
$results = array_merge($results, (array) $new_row);
}
}
return $results;
}
}
search/content/content.xml000064400000003377147357022240011677
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="search" method="upgrade">
<name>plg_search_content</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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_SEARCH_CONTENT_XML_DESCRIPTION</description>
<files>
<filename plugin="content">content.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_search_content.ini</language>
<language
tag="en-GB">en-GB.plg_search_content.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="search_limit"
type="number"
label="PLG_SEARCH_CONTENT_FIELD_SEARCHLIMIT_LABEL"
description="PLG_SEARCH_CONTENT_FIELD_SEARCHLIMIT_DESC"
default="50"
filter="integer"
size="5"
/>
<field
name="search_content"
type="radio"
label="PLG_SEARCH_CONTENT_FIELD_CONTENT_LABEL"
description="PLG_SEARCH_CONTENT_FIELD_CONTENT_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="search_archived"
type="radio"
label="PLG_SEARCH_CONTENT_FIELD_ARCHIVED_LABEL"
description="PLG_SEARCH_CONTENT_FIELD_ARCHIVED_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
search/newsfeeds/newsfeeds.php000064400000012022147357022240012473
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Search.newsfeeds
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Newsfeeds search plugin.
*
* @since 1.6
*/
class PlgSearchNewsfeeds extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Determine areas searchable by this plugin.
*
* @return array An array of search areas.
*
* @since 1.6
*/
public function onContentSearchAreas()
{
static $areas = array(
'newsfeeds' => 'PLG_SEARCH_NEWSFEEDS_NEWSFEEDS'
);
return $areas;
}
/**
* Search content (newsfeeds).
*
* The SQL must return the following fields that are used in a common
display
* routine: href, title, section, created, text, browsernav.
*
* @param string $text Target search string.
* @param string $phrase Matching option (possible values:
exact|any|all). Default is "any".
* @param string $ordering Ordering option (possible values:
newest|oldest|popular|alpha|category). Default is "newest".
* @param mixed $areas An array if the search it to be restricted
to areas or null to search all areas.
*
* @return array Search results.
*
* @since 1.6
*/
public function onContentSearch($text, $phrase = '', $ordering =
'', $areas = null)
{
$db = JFactory::getDbo();
$app = JFactory::getApplication();
$user = JFactory::getUser();
$groups = implode(',', $user->getAuthorisedViewLevels());
if (is_array($areas) && !array_intersect($areas,
array_keys($this->onContentSearchAreas())))
{
return array();
}
$sContent = $this->params->get('search_content', 1);
$sArchived = $this->params->get('search_archived', 1);
$limit = $this->params->def('search_limit', 50);
$state = array();
if ($sContent)
{
$state[] = 1;
}
if ($sArchived)
{
$state[] = 2;
}
if (empty($state))
{
return array();
}
$text = trim($text);
if ($text === '')
{
return array();
}
switch ($phrase)
{
case 'exact':
$text = $db->quote('%' . $db->escape($text, true) .
'%', false);
$wheres2 = array();
$wheres2[] = 'a.name LIKE ' . $text;
$wheres2[] = 'a.link LIKE ' . $text;
$where = '(' . implode(') OR (', $wheres2) .
')';
break;
case 'all':
case 'any':
default:
$words = explode(' ', $text);
$wheres = array();
foreach ($words as $word)
{
$word = $db->quote('%' . $db->escape($word, true) .
'%', false);
$wheres2 = array();
$wheres2[] = 'a.name LIKE ' . $word;
$wheres2[] = 'a.link LIKE ' . $word;
$wheres[] = implode(' OR ', $wheres2);
}
$where = '(' . implode(($phrase === 'all' ? ')
AND (' : ') OR ('), $wheres) . ')';
break;
}
switch ($ordering)
{
case 'alpha':
$order = 'a.name ASC';
break;
case 'category':
$order = 'c.title ASC, a.name ASC';
break;
case 'oldest':
case 'popular':
case 'newest':
default:
$order = 'a.name ASC';
}
$searchNewsfeeds = JText::_('PLG_SEARCH_NEWSFEEDS_NEWSFEEDS');
$query = $db->getQuery(true);
// SQLSRV changes.
$case_when = ' CASE WHEN ';
$case_when .= $query->charLength('a.alias', '!=',
'0');
$case_when .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when .= $query->concatenate(array($a_id, 'a.alias'),
':');
$case_when .= ' ELSE ';
$case_when .= $a_id . ' END as slug';
$case_when1 = ' CASE WHEN ';
$case_when1 .= $query->charLength('c.alias', '!=',
'0');
$case_when1 .= ' THEN ';
$c_id = $query->castAsChar('c.id');
$case_when1 .= $query->concatenate(array($c_id, 'c.alias'),
':');
$case_when1 .= ' ELSE ';
$case_when1 .= $c_id . ' END as catslug';
$query->select('a.name AS title, \'\' AS created,
a.link AS text, ' . $case_when . ',' . $case_when1)
->select($query->concatenate(array($db->quote($searchNewsfeeds),
'c.title'), ' / ') . ' AS section')
->select('\'1\' AS browsernav')
->from('#__newsfeeds AS a')
->join('INNER', '#__categories as c ON c.id =
a.catid')
->where('(' . $where . ') AND a.published IN (' .
implode(',', $state) . ') AND c.published = 1 AND c.access
IN (' . $groups . ')')
->order($order);
// Filter by language.
if ($app->isClient('site') &&
JLanguageMultilang::isEnabled())
{
$tag = JFactory::getLanguage()->getTag();
$query->where('a.language in (' . $db->quote($tag) .
',' . $db->quote('*') . ')')
->where('c.language in (' . $db->quote($tag) .
',' . $db->quote('*') . ')');
}
$db->setQuery($query, 0, $limit);
try
{
$rows = $db->loadObjectList();
}
catch (RuntimeException $e)
{
$rows = array();
JFactory::getApplication()->enqueueMessage(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'),
'error');
}
if ($rows)
{
foreach ($rows as $key => $row)
{
$rows[$key]->href =
'index.php?option=com_newsfeeds&view=newsfeed&catid=' .
$row->catslug . '&id=' . $row->slug;
}
}
return $rows;
}
}
search/newsfeeds/newsfeeds.xml000064400000003330147357022240012506
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="search" method="upgrade">
<name>plg_search_newsfeeds</name>
<author>Joomla! Project</author>
<creationDate>November 2005</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_SEARCH_NEWSFEEDS_XML_DESCRIPTION</description>
<files>
<filename
plugin="newsfeeds">newsfeeds.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_search_newsfeeds.ini</language>
<language
tag="en-GB">en-GB.plg_search_newsfeeds.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="search_limit"
type="number"
label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
default="50"
filter="integer"
size="5"
/>
<field
name="search_content"
type="radio"
label="JFIELD_PLG_SEARCH_ALL_LABEL"
description="JFIELD_PLG_SEARCH_ALL_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="search_archived"
type="radio"
label="JFIELD_PLG_SEARCH_ARCHIVED_LABEL"
description="JFIELD_PLG_SEARCH_ARCHIVED_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JON</option>
<option value="0">JOFF</option>
</field>
</fieldset>
</fields>
</config>
</extension>
search/tags/tags.php000064400000013342147357022240010427 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Search.tags
*
* @copyright (C) 2014 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Tags search plugin.
*
* @since 3.3
*/
class PlgSearchTags extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.3
*/
protected $autoloadLanguage = true;
/**
* Determine areas searchable by this plugin.
*
* @return array An array of search areas.
*
* @since 3.3
*/
public function onContentSearchAreas()
{
static $areas = array(
'tags' => 'PLG_SEARCH_TAGS_TAGS'
);
return $areas;
}
/**
* Search content (tags).
*
* The SQL must return the following fields that are used in a common
display
* routine: href, title, section, created, text, browsernav.
*
* @param string $text Target search string.
* @param string $phrase Matching option (possible values:
exact|any|all). Default is "any".
* @param string $ordering Ordering option (possible values:
newest|oldest|popular|alpha|category). Default is "newest".
* @param string $areas An array if the search is to be restricted
to areas or null to search all areas.
*
* @return array Search results.
*
* @since 3.3
*/
public function onContentSearch($text, $phrase = '', $ordering =
'', $areas = null)
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$app = JFactory::getApplication();
$user = JFactory::getUser();
$lang = JFactory::getLanguage();
$section = JText::_('PLG_SEARCH_TAGS_TAGS');
$limit = $this->params->def('search_limit', 50);
if (is_array($areas) && !array_intersect($areas,
array_keys($this->onContentSearchAreas())))
{
return array();
}
$text = trim($text);
if ($text === '')
{
return array();
}
$text = $db->quote('%' . $db->escape($text, true) .
'%', false);
switch ($ordering)
{
case 'alpha':
$order = 'a.title ASC';
break;
case 'newest':
$order = 'a.created_time DESC';
break;
case 'oldest':
$order = 'a.created_time ASC';
break;
case 'popular':
default:
$order = 'a.title DESC';
}
$query->select('a.id, a.title, a.alias, a.note, a.published,
a.access'
. ', a.checked_out, a.checked_out_time, a.created_user_id'
. ', a.path, a.parent_id, a.level, a.lft, a.rgt'
. ', a.language, a.created_time AS created, a.description');
$case_when_item_alias = ' CASE WHEN ';
$case_when_item_alias .= $query->charLength('a.alias',
'!=', '0');
$case_when_item_alias .= ' THEN ';
$a_id = $query->castAsChar('a.id');
$case_when_item_alias .= $query->concatenate(array($a_id,
'a.alias'), ':');
$case_when_item_alias .= ' ELSE ';
$case_when_item_alias .= $a_id . ' END as slug';
$query->select($case_when_item_alias);
$query->from('#__tags AS a');
$query->where('a.alias <> ' .
$db->quote('root'));
$query->where('(a.title LIKE ' . $text . ' OR a.alias
LIKE ' . $text . ')');
$query->where($db->qn('a.published') . ' = 1');
if (!$user->authorise('core.admin'))
{
$groups = implode(',', $user->getAuthorisedViewLevels());
$query->where('a.access IN (' . $groups . ')');
}
if ($app->isClient('site') &&
JLanguageMultilang::isEnabled())
{
$tag = JFactory::getLanguage()->getTag();
$query->where('a.language in (' . $db->quote($tag) .
',' . $db->quote('*') . ')');
}
$query->order($order);
$db->setQuery($query, 0, $limit);
try
{
$rows = $db->loadObjectList();
}
catch (RuntimeException $e)
{
$rows = array();
JFactory::getApplication()->enqueueMessage(JText::_('JERROR_AN_ERROR_HAS_OCCURRED'),
'error');
}
if ($rows)
{
JLoader::register('TagsHelperRoute', JPATH_SITE .
'/components/com_tags/helpers/route.php');
foreach ($rows as $key => $row)
{
$rows[$key]->href =
TagsHelperRoute::getTagRoute($row->slug);
$rows[$key]->text = ($row->description !== '' ?
$row->description : $row->title);
$rows[$key]->text .= $row->note;
$rows[$key]->section = $section;
$rows[$key]->created = $row->created;
$rows[$key]->browsernav = 0;
}
}
if (!$this->params->get('show_tagged_items', 0))
{
return $rows;
}
else
{
$final_items = $rows;
JModelLegacy::addIncludePath(JPATH_SITE .
'/components/com_tags/models');
$tag_model = JModelLegacy::getInstance('Tag',
'TagsModel');
$tag_model->getState();
foreach ($rows as $key => $row)
{
$tag_model->setState('tag.id', $row->id);
$tagged_items = $tag_model->getItems();
if ($tagged_items)
{
foreach ($tagged_items as $k => $item)
{
// For 3rd party extensions we need to load the component strings
from its sys.ini file
$parts = explode('.', $item->type_alias);
$comp = array_shift($parts);
$lang->load($comp, JPATH_SITE, null, false, true)
|| $lang->load($comp, JPATH_SITE . '/components/' .
$comp, null, false, true);
// Making up the type string
$type = implode('_', $parts);
$type = $comp . '_CONTENT_TYPE_' . $type;
$new_item = new stdClass;
$new_item->href = $item->link;
$new_item->title = $item->core_title;
$new_item->text = $item->core_body;
if ($lang->hasKey($type))
{
$new_item->section =
JText::sprintf('PLG_SEARCH_TAGS_ITEM_TAGGED_WITH',
JText::_($type), $row->title);
}
else
{
$new_item->section =
JText::sprintf('PLG_SEARCH_TAGS_ITEM_TAGGED_WITH',
$item->content_type_title, $row->title);
}
$new_item->created = $item->displayDate;
$new_item->browsernav = 0;
$final_items[] = $new_item;
}
}
}
return $final_items;
}
}
}
search/tags/tags.xml000064400000002630147357022240010436 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="search" method="upgrade">
<name>plg_search_tags</name>
<author>Joomla! Project</author>
<creationDate>March 2014</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.0.0</version>
<description>PLG_SEARCH_TAGS_XML_DESCRIPTION</description>
<files>
<filename plugin="tags">tags.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_search_tags.ini</language>
<language
tag="en-GB">en-GB.plg_search_tags.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="search_limit"
type="number"
label="JFIELD_PLG_SEARCH_SEARCHLIMIT_LABEL"
description="JFIELD_PLG_SEARCH_SEARCHLIMIT_DESC"
default="50"
filter="integer"
size="5"
/>
<field
name="show_tagged_items"
type="radio"
label="PLG_SEARCH_TAGS_FIELD_SHOW_TAGGED_ITEMS_LABEL"
description="PLG_SEARCH_TAGS_FIELD_SHOW_TAGGED_ITEMS_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
system/actionlogs/actionlogs.php000064400000027672147357022240013131
0ustar00<?php
/**
* @package Joomla.Plugins
* @subpackage System.actionlogs
*
* @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\Cache\Cache;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\CMS\User\User;
/**
* Joomla! Users Actions Logging Plugin.
*
* @since 3.9.0
*/
class PlgSystemActionLogs extends JPlugin
{
/**
* Application object.
*
* @var JApplicationCms
* @since 3.9.0
*/
protected $app;
/**
* Database object.
*
* @var JDatabaseDriver
* @since 3.9.0
*/
protected $db;
/**
* Load plugin language file automatically so that it can be used inside
component
*
* @var boolean
* @since 3.9.0
*/
protected $autoloadLanguage = true;
/**
* Constructor.
*
* @param object &$subject The object to observe.
* @param array $config An optional associative array of
configuration settings.
*
* @since 3.9.0
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
// Import actionlog plugin group so that these plugins will be triggered
for events
PluginHelper::importPlugin('actionlog');
}
/**
* Adds additional fields to the user editing form for logs e-mail
notifications
*
* @param JForm $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, $data)
{
if (!$form instanceof Form)
{
$this->subject->setError('JERROR_NOT_A_FORM');
return false;
}
$formName = $form->getName();
$allowedFormNames = array(
'com_users.profile',
'com_admin.profile',
'com_users.user',
);
if (!in_array($formName, $allowedFormNames))
{
return true;
}
/**
* We only allow users who has Super User permission change this setting
for himself or for other users
* who has same Super User permission
*/
$user = Factory::getUser();
if (!$user->authorise('core.admin'))
{
return true;
}
// If we are on the save command, no data is passed to $data variable, we
need to get it directly from request
$jformData = $this->app->input->get('jform', array(),
'array');
if ($jformData && !$data)
{
$data = $jformData;
}
if (is_array($data))
{
$data = (object) $data;
}
if (empty($data->id) ||
!User::getInstance($data->id)->authorise('core.admin'))
{
return true;
}
Form::addFormPath(__DIR__ . '/forms');
if ((!PluginHelper::isEnabled('actionlog', 'joomla'))
&&
(Factory::getApplication()->isClient('administrator')))
{
$form->loadFile('information', false);
return true;
}
if (!PluginHelper::isEnabled('actionlog', 'joomla'))
{
return true;
}
$form->loadFile('actionlogs', false);
}
/**
* Runs on content preparation
*
* @param string $context The context for the data
* @param object $data An object containing the data for the form.
*
* @return boolean
*
* @since 3.9.0
*/
public function onContentPrepareData($context, $data)
{
if (!in_array($context, array('com_users.profile',
'com_admin.profile', 'com_users.user')))
{
return true;
}
if (is_array($data))
{
$data = (object) $data;
}
if
(!User::getInstance($data->id)->authorise('core.admin'))
{
return true;
}
$query = $this->db->getQuery(true)
->select($this->db->quoteName(array('notify',
'extensions')))
->from($this->db->quoteName('#__action_logs_users'))
->where($this->db->quoteName('user_id') . ' =
' . (int) $data->id);
try
{
$values = $this->db->setQuery($query)->loadObject();
}
catch (JDatabaseExceptionExecuting $e)
{
return false;
}
if (!$values)
{
return true;
}
$data->actionlogs = new StdClass;
$data->actionlogs->actionlogsNotify = $values->notify;
$data->actionlogs->actionlogsExtensions = $values->extensions;
if (!HTMLHelper::isRegistered('users.actionlogsNotify'))
{
HTMLHelper::register('users.actionlogsNotify',
array(__CLASS__, 'renderActionlogsNotify'));
}
if (!HTMLHelper::isRegistered('users.actionlogsExtensions'))
{
HTMLHelper::register('users.actionlogsExtensions',
array(__CLASS__, 'renderActionlogsExtensions'));
}
return true;
}
/**
* Runs after the HTTP response has been sent to the client and delete log
records older than certain days
*
* @return void
*
* @since 3.9.0
*/
public function onAfterRespond()
{
$daysToDeleteAfter = (int)
$this->params->get('logDeletePeriod', 0);
if ($daysToDeleteAfter <= 0)
{
return;
}
// The delete frequency will be once per day
$deleteFrequency = 3600 * 24;
// Do we need to run? Compare the last run timestamp stored in the
plugin's options with the current
// timestamp. If the difference is greater than the cache timeout we
shall not execute again.
$now = time();
$last = (int) $this->params->get('lastrun', 0);
if (abs($now - $last) < $deleteFrequency)
{
return;
}
// Update last run status
$this->params->set('lastrun', $now);
$db = $this->db;
$query = $db->getQuery(true)
->update($db->qn('#__extensions'))
->set($db->qn('params') . ' = ' .
$db->q($this->params->toString('JSON')))
->where($db->qn('type') . ' = ' .
$db->q('plugin'))
->where($db->qn('folder') . ' = ' .
$db->q('system'))
->where($db->qn('element') . ' = ' .
$db->q('actionlogs'));
try
{
// Lock the tables to prevent multiple plugin executions causing a race
condition
$db->lockTable('#__extensions');
}
catch (Exception $e)
{
// If we can't lock the tables it's too risky to continue
execution
return;
}
try
{
// Update the plugin parameters
$result = $db->setQuery($query)->execute();
$this->clearCacheGroups(array('com_plugins'), array(0, 1));
}
catch (Exception $exc)
{
// If we failed to execute
$db->unlockTables();
$result = false;
}
try
{
// Unlock the tables after writing
$db->unlockTables();
}
catch (Exception $e)
{
// If we can't lock the tables assume we have somehow failed
$result = false;
}
// Abort on failure
if (!$result)
{
return;
}
$daysToDeleteAfter = (int)
$this->params->get('logDeletePeriod', 0);
$now = $db->quote(Factory::getDate()->toSql());
if ($daysToDeleteAfter > 0)
{
$conditions = array($db->quoteName('log_date') . '
< ' . $query->dateAdd($now, -1 * $daysToDeleteAfter, '
DAY'));
$query->clear()
->delete($db->quoteName('#__action_logs'))->where($conditions);
$db->setQuery($query);
try
{
$db->execute();
}
catch (RuntimeException $e)
{
// Ignore it
return;
}
}
}
/**
* Utility method to act on a user after it has been saved.
*
* @param array $user Holds the new user data.
* @param boolean $isNew True if a new user is stored.
* @param boolean $success True if user was successfully stored in the
database.
* @param string $msg Message.
*
* @return boolean
*
* @since 3.9.0
*/
public function onUserAfterSave($user, $isNew, $success, $msg)
{
if (!$success)
{
return false;
}
// Clear access rights in case user groups were changed.
$userObject = new User($user['id']);
$userObject->clearAccessRights();
$authorised = $userObject->authorise('core.admin');
$query = $this->db->getQuery(true)
->select('COUNT(*)')
->from($this->db->quoteName('#__action_logs_users'))
->where($this->db->quoteName('user_id') . ' =
' . (int) $user['id']);
try
{
$exists = (bool) $this->db->setQuery($query)->loadResult();
}
catch (JDatabaseExceptionExecuting $e)
{
return false;
}
// If preferences don't exist, insert.
if (!$exists && $authorised &&
isset($user['actionlogs']))
{
$values = array((int) $user['id'], (int)
$user['actionlogs']['actionlogsNotify']);
$columns = array('user_id', 'notify');
if
(isset($user['actionlogs']['actionlogsExtensions']))
{
$values[] =
$this->db->quote(json_encode($user['actionlogs']['actionlogsExtensions']));
$columns[] = 'extensions';
}
$query = $this->db->getQuery(true)
->insert($this->db->quoteName('#__action_logs_users'))
->columns($this->db->quoteName($columns))
->values(implode(',', $values));
}
elseif ($exists && $authorised &&
isset($user['actionlogs']))
{
// Update preferences.
$values = array($this->db->quoteName('notify') . '
= ' . (int)
$user['actionlogs']['actionlogsNotify']);
if
(isset($user['actionlogs']['actionlogsExtensions']))
{
$values[] = $this->db->quoteName('extensions') . '
= ' .
$this->db->quote(json_encode($user['actionlogs']['actionlogsExtensions']));
}
$query = $this->db->getQuery(true)
->update($this->db->quoteName('#__action_logs_users'))
->set($values)
->where($this->db->quoteName('user_id') . ' =
' . (int) $user['id']);
}
elseif ($exists && !$authorised)
{
// Remove preferences if user is not authorised.
$query = $this->db->getQuery(true)
->delete($this->db->quoteName('#__action_logs_users'))
->where($this->db->quoteName('user_id') . ' =
' . (int) $user['id']);
}
try
{
$this->db->setQuery($query)->execute();
}
catch (JDatabaseExceptionExecuting $e)
{
return false;
}
return true;
}
/**
* Removes user preferences
*
* Method is called after user data is deleted from the database
*
* @param array $user Holds the user data
* @param boolean $success True if user was successfully stored in the
database
* @param string $msg Message
*
* @return boolean
*
* @since 3.9.0
*/
public function onUserAfterDelete($user, $success, $msg)
{
if (!$success)
{
return false;
}
$query = $this->db->getQuery(true)
->delete($this->db->quoteName('#__action_logs_users'))
->where($this->db->quoteName('user_id') . ' =
' . (int) $user['id']);
try
{
$this->db->setQuery($query)->execute();
}
catch (JDatabaseExceptionExecuting $e)
{
return false;
}
return true;
}
/**
* Clears cache groups. We use it to clear the plugins cache after we
update the last run timestamp.
*
* @param array $clearGroups The cache groups to clean
* @param array $cacheClients The cache clients (site, admin) to clean
*
* @return void
*
* @since 3.9.0
*/
private function clearCacheGroups(array $clearGroups, array $cacheClients
= array(0, 1))
{
$conf = Factory::getConfig();
foreach ($clearGroups as $group)
{
foreach ($cacheClients as $clientId)
{
try
{
$options = array(
'defaultgroup' => $group,
'cachebase' => $clientId ? JPATH_ADMINISTRATOR .
'/cache' :
$conf->get('cache_path', JPATH_SITE .
'/cache')
);
$cache = Cache::getInstance('callback', $options);
$cache->clean();
}
catch (Exception $e)
{
// Ignore it
}
}
}
}
/**
* Method to render a value.
*
* @param integer|string $value The value (0 or 1).
*
* @return string The rendered value.
*
* @since 3.9.16
*/
public static function renderActionlogsNotify($value)
{
return Text::_($value ? 'JYES' : 'JNO');
}
/**
* Method to render a list of extensions.
*
* @param array|string $extensions Array of extensions or an empty
string if none selected.
*
* @return string The rendered value.
*
* @since 3.9.16
*/
public static function renderActionlogsExtensions($extensions)
{
// No extensions selected.
if (!$extensions)
{
return Text::_('JNONE');
}
// Load the helper.
JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR .
'/components/com_actionlogs/helpers/actionlogs.php');
foreach ($extensions as &$extension)
{
// Load extension language files and translate extension name.
ActionlogsHelper::loadTranslationFiles($extension);
$extension = Text::_($extension);
}
return implode(', ', $extensions);
}
}
system/actionlogs/actionlogs.xml000064400000002363147357022240013130
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<extension version="3.9" type="plugin"
group="system" method="upgrade">
<name>PLG_SYSTEM_ACTIONLOGS</name>
<author>Joomla! Project</author>
<creationDate>May 2018</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_SYSTEM_ACTIONLOGS_XML_DESCRIPTION</description>
<files>
<filename
plugin="actionlogs">actionlogs.php</filename>
<folder>forms</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_actionlogs.ini</language>
<language
tag="en-GB">en-GB.plg_system_actionlogs.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="logDeletePeriod"
type="number"
label="PLG_SYSTEM_ACTIONLOGS_LOG_DELETE_PERIOD"
description="PLG_SYSTEM_ACTIONLOGS_LOG_DELETE_PERIOD_DESC"
default="0"
min="0"
filter="int"
validate="number"
/>
<field
name="lastrun"
type="hidden"
default="0"
filter="integer"
/>
</fieldset>
</fields>
</config>
</extension>
system/actionlogs/forms/actionlogs.xml000064400000001537147357022250014261
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form>
<fieldset name="actionlogs"
label="PLG_SYSTEM_ACTIONLOGS_OPTIONS"
addfieldpath="/administrator/components/com_actionlogs/models/fields">
<fields name="actionlogs">
<field
name="actionlogsNotify"
type="radio"
label="PLG_SYSTEM_ACTIONLOGS_NOTIFICATIONS"
description="PLG_SYSTEM_ACTIONLOGS_NOTIFICATIONS_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
required="true"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="actionlogsExtensions"
type="logtype"
label="PLG_SYSTEM_ACTIONLOGS_EXTENSIONS_NOTIFICATIONS"
description="PLG_SYSTEM_ACTIONLOGS_EXTENSIONS_NOTIFICATIONS_DESC"
multiple="true"
validate="options"
showon="actionlogsNotify:1"
/>
</fields>
</fieldset>
</form>
system/actionlogs/forms/information.xml000064400000000617147357022250014442
0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form>
<fields name="params">
<fieldset name="information"
label="PLG_SYSTEM_ACTIONLOGS_OPTIONS"
addfieldpath="/administrator/components/com_actionlogs/models/fields">
<field
name="Information"
type="plugininfo"
label="PLG_SYSTEM_ACTIONLOGS_INFO_LABEL"
description="PLG_SYSTEM_ACTIONLOGS_INFO_DESC"
/>
</fieldset>
</fields>
</form>
system/cache/cache.php000064400000013143147357022250010720 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.cache
*
* @copyright (C) 2007 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Joomla! Page Cache Plugin.
*
* @since 1.5
*/
class PlgSystemCache extends JPlugin
{
/**
* Cache instance.
*
* @var JCache
* @since 1.5
*/
public $_cache;
/**
* Cache key
*
* @var string
* @since 3.0
*/
public $_cache_key;
/**
* Application object.
*
* @var JApplicationCms
* @since 3.8.0
*/
protected $app;
/**
* Constructor.
*
* @param object &$subject The object to observe.
* @param array $config An optional associative array of
configuration settings.
*
* @since 1.5
*/
public function __construct(& $subject, $config)
{
parent::__construct($subject, $config);
// Get the application if not done by JPlugin.
if (!isset($this->app))
{
$this->app = JFactory::getApplication();
}
// Set the cache options.
$options = array(
'defaultgroup' => 'page',
'browsercache' =>
$this->params->get('browsercache', 0),
'caching' => false,
);
// Instantiate cache with previous options and create the cache key
identifier.
$this->_cache = JCache::getInstance('page', $options);
$this->_cache_key = JUri::getInstance()->toString();
}
/**
* Get a cache key for the current page based on the url and possible
other factors.
*
* @return string
*
* @since 3.7
*/
protected function getCacheKey()
{
static $key;
if (!$key)
{
JPluginHelper::importPlugin('pagecache');
$parts =
JEventDispatcher::getInstance()->trigger('onPageCacheGetKey');
$parts[] = JUri::getInstance()->toString();
$key = md5(serialize($parts));
}
return $key;
}
/**
* After Initialise Event.
* Checks if URL exists in cache, if so dumps it directly and closes.
*
* @return void
*
* @since 1.5
*/
public function onAfterInitialise()
{
if ($this->app->isClient('administrator') ||
$this->app->get('offline', '0') ||
$this->app->getMessageQueue())
{
return;
}
// If any pagecache plugins return false for onPageCacheSetCaching, do
not use the cache.
JPluginHelper::importPlugin('pagecache');
$results =
JEventDispatcher::getInstance()->trigger('onPageCacheSetCaching');
$caching = !in_array(false, $results, true);
if ($caching && JFactory::getUser()->guest &&
$this->app->input->getMethod() === 'GET')
{
$this->_cache->setCaching(true);
}
$data = $this->_cache->get($this->getCacheKey());
// If page exist in cache, show cached page.
if ($data !== false)
{
// Set HTML page from cache.
$this->app->setBody($data);
// Dumps HTML page.
echo $this->app->toString((bool)
$this->app->get('gzip'));
// Mark afterCache in debug and run debug onAfterRespond events.
// e.g., show Joomla Debug Console if debug is active.
if (JDEBUG)
{
JProfiler::getInstance('Application')->mark('afterCache');
JEventDispatcher::getInstance()->trigger('onAfterRespond');
}
// Closes the application.
$this->app->close();
}
}
/**
* After Render Event.
* Verify if current page is not excluded from cache.
*
* @return void
*
* @since 3.9.12
*/
public function onAfterRender()
{
if ($this->_cache->getCaching() === false)
{
return;
}
// We need to check if user is guest again here, because auto-login
plugins have not been fired before the first aid check.
// Page is excluded if excluded in plugin settings.
if (!JFactory::getUser()->guest || $this->app->getMessageQueue()
|| $this->isExcluded() === true)
{
$this->_cache->setCaching(false);
return;
}
// Disable compression before caching the page.
$this->app->set('gzip', false);
}
/**
* After Respond Event.
* Stores page in cache.
*
* @return void
*
* @since 1.5
*/
public function onAfterRespond()
{
if ($this->_cache->getCaching() === false)
{
return;
}
// Saves current page in cache.
$this->_cache->store($this->app->getBody(),
$this->getCacheKey());
}
/**
* Check if the page is excluded from the cache or not.
*
* @return boolean True if the page is excluded else false
*
* @since 3.5
*/
protected function isExcluded()
{
// Check if menu items have been excluded.
if ($exclusions =
$this->params->get('exclude_menu_items', array()))
{
// Get the current menu item.
$active = $this->app->getMenu()->getActive();
if ($active && $active->id && in_array((int)
$active->id, (array) $exclusions))
{
return true;
}
}
// Check if regular expressions are being used.
if ($exclusions = $this->params->get('exclude',
''))
{
// Normalize line endings.
$exclusions = str_replace(array("\r\n", "\r"),
"\n", $exclusions);
// Split them.
$exclusions = explode("\n", $exclusions);
// Gets internal URI.
$internal_uri = '/index.php?' .
JUri::getInstance()->buildQuery($this->app->getRouter()->getVars());
// Loop through each pattern.
if ($exclusions)
{
foreach ($exclusions as $exclusion)
{
// Make sure the exclusion has some content
if ($exclusion !== '')
{
// Test both external and internal URI
if (preg_match('#' . $exclusion . '#i',
$this->_cache_key . ' ' . $internal_uri, $match))
{
return true;
}
}
}
}
}
// If any pagecache plugins return true for onPageCacheIsExcluded,
exclude.
JPluginHelper::importPlugin('pagecache');
$results =
JEventDispatcher::getInstance()->trigger('onPageCacheIsExcluded');
return in_array(true, $results, true);
}
}
system/cache/cache.xml000064400000003215147357022250010730 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_cache</name>
<author>Joomla! Project</author>
<creationDate>February 2007</creationDate>
<copyright>(C) 2007 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_CACHE_XML_DESCRIPTION</description>
<files>
<filename plugin="cache">cache.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_cache.ini</language>
<language
tag="en-GB">en-GB.plg_system_cache.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="browsercache"
type="radio"
label="PLG_CACHE_FIELD_BROWSERCACHE_LABEL"
description="PLG_CACHE_FIELD_BROWSERCACHE_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="exclude_menu_items"
type="menuitem"
label="PLG_CACHE_FIELD_EXCLUDE_MENU_ITEMS_LABEL"
description="PLG_CACHE_FIELD_EXCLUDE_MENU_ITEMS_DESC"
multiple="multiple"
filter="int_array"
/>
</fieldset>
<fieldset name="advanced">
<field
name="exclude"
type="textarea"
label="PLG_CACHE_FIELD_EXCLUDE_LABEL"
description="PLG_CACHE_FIELD_EXCLUDE_DESC"
class="input-xxlarge"
rows="15"
filter="raw"
/>
</fieldset>
</fields>
</config>
</extension>
system/debug/debug.php000064400000141542147357022250010773 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.Debug
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Utilities\ArrayHelper;
/**
* Joomla! Debug plugin.
*
* @since 1.5
*/
class PlgSystemDebug extends JPlugin
{
/**
* xdebug.file_link_format from the php.ini.
*
* @var string
* @since 1.7
*/
protected $linkFormat = '';
/**
* True if debug lang is on.
*
* @var boolean
* @since 3.0
*/
private $debugLang = false;
/**
* Holds log entries handled by the plugin.
*
* @var array
* @since 3.1
*/
private $logEntries = array();
/**
* Holds SHOW PROFILES of queries.
*
* @var array
* @since 3.1.2
*/
private $sqlShowProfiles = array();
/**
* Holds all SHOW PROFILE FOR QUERY n, indexed by n-1.
*
* @var array
* @since 3.1.2
*/
private $sqlShowProfileEach = array();
/**
* Holds all EXPLAIN EXTENDED for all queries.
*
* @var array
* @since 3.1.2
*/
private $explains = array();
/**
* Holds total amount of executed queries.
*
* @var int
* @since 3.2
*/
private $totalQueries = 0;
/**
* Application object.
*
* @var JApplicationCms
* @since 3.3
*/
protected $app;
/**
* Database object.
*
* @var JDatabaseDriver
* @since 3.8.0
*/
protected $db;
/**
* Container for callback functions to be triggered when rendering the
console.
*
* @var callable[]
* @since 3.7.0
*/
private static $displayCallbacks = array();
/**
* Constructor.
*
* @param object &$subject The object to observe.
* @param array $config An optional associative array of
configuration settings.
*
* @since 1.5
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
// Log the deprecated API.
if ($this->params->get('log-deprecated', 0))
{
JLog::addLogger(array('text_file' =>
'deprecated.php'), JLog::ALL, array('deprecated'));
}
// Log everything (except deprecated APIs, these are logged separately
with the option above).
if ($this->params->get('log-everything', 0))
{
JLog::addLogger(array('text_file' =>
'everything.php'), JLog::ALL, array('deprecated',
'databasequery'), true);
}
// Get the application if not done by JPlugin. This may happen during
upgrades from Joomla 2.5.
if (!$this->app)
{
$this->app = JFactory::getApplication();
}
// Get the db if not done by JPlugin. This may happen during upgrades
from Joomla 2.5.
if (!$this->db)
{
$this->db = JFactory::getDbo();
}
$this->debugLang = $this->app->get('debug_lang');
// Skip the plugin if debug is off
if ($this->debugLang == '0' &&
$this->app->get('debug') == '0')
{
return;
}
// Only if debugging or language debug is enabled.
if (JDEBUG || $this->debugLang)
{
JFactory::getConfig()->set('gzip', 0);
ob_start();
ob_implicit_flush(false);
}
$this->linkFormat = ini_get('xdebug.file_link_format');
if ($this->params->get('logs', 1))
{
$priority = 0;
foreach ($this->params->get('log_priorities', array())
as $p)
{
$const = 'JLog::' . strtoupper($p);
if (!defined($const))
{
continue;
}
$priority |= constant($const);
}
// Split into an array at any character other than alphabet, numbers, _,
., or -
$categories = preg_split('/[^\w.-]+/',
$this->params->get('log_categories', ''), -1,
PREG_SPLIT_NO_EMPTY);
$mode = $this->params->get('log_category_mode',
0);
JLog::addLogger(array('logger' => 'callback',
'callback' => array($this, 'logger')), $priority,
$categories, $mode);
}
// Prepare disconnect handler for SQL profiling.
$db = $this->db;
$db->addDisconnectHandler(array($this,
'mysqlDisconnectHandler'));
// Log deprecated class aliases
foreach (JLoader::getDeprecatedAliases() as $deprecation)
{
JLog::add(
sprintf(
'%1$s has been aliased to %2$s and the former class name is
deprecated. The alias will be removed in %3$s.',
$deprecation['old'],
$deprecation['new'],
$deprecation['version']
),
JLog::WARNING,
'deprecated'
);
}
}
/**
* Add the CSS for debug.
* We can't do this in the constructor because stuff breaks.
*
* @return void
*
* @since 2.5
*/
public function onAfterDispatch()
{
// Only if debugging or language debug is enabled.
if ((JDEBUG || $this->debugLang) &&
$this->isAuthorisedDisplayDebug())
{
JHtml::_('stylesheet', 'cms/debug.css',
array('version' => 'auto', 'relative'
=> true));
}
// Disable asset media version if needed.
if (JDEBUG && (int)
$this->params->get('refresh_assets', 1) === 0)
{
$this->app->getDocument()->setMediaVersion(null);
}
// Only if debugging is enabled for SQL query popovers.
if (JDEBUG && $this->isAuthorisedDisplayDebug())
{
JHtml::_('bootstrap.tooltip');
JHtml::_('bootstrap.popover', '.hasPopover',
array('placement' => 'top'));
}
}
/**
* Show the debug info.
*
* @return void
*
* @since 1.6
*/
public function onAfterRespond()
{
// Do not render if debugging or language debug is not enabled.
if (!JDEBUG && !$this->debugLang)
{
return;
}
// User has to be authorised to see the debug information.
if (!$this->isAuthorisedDisplayDebug())
{
return;
}
// Only render for HTML output.
if (JFactory::getDocument()->getType() !== 'html')
{
return;
}
// Capture output.
$contents = ob_get_contents();
if ($contents)
{
ob_end_clean();
}
// No debug for Safari and Chrome redirection.
if (strpos($contents, '<html><head><meta
http-equiv="refresh" content="0;') === 0
&&
strpos(strtolower(isset($_SERVER['HTTP_USER_AGENT']) ?
$_SERVER['HTTP_USER_AGENT'] : ''), 'webkit')
!== false)
{
echo $contents;
return;
}
// Load language.
$this->loadLanguage();
$html = array();
// Some "mousewheel protecting" JS.
$html[] = "<script>function toggleContainer(name)
{
var e = document.getElementById(name);// MooTools might not be available
;)
e.style.display = e.style.display === 'none' ?
'block' : 'none';
}</script>";
$html[] = '<div id="system-debug"
class="profiler">';
$html[] = '<h2>' . JText::_('PLG_DEBUG_TITLE')
. '</h2>';
if (JDEBUG)
{
if (JError::getErrors())
{
$html[] = $this->display('errors');
}
if ($this->params->get('session', 1))
{
$html[] = $this->display('session');
}
if ($this->params->get('profile', 1))
{
$html[] = $this->display('profile_information');
}
if ($this->params->get('memory', 1))
{
$html[] = $this->display('memory_usage');
}
if ($this->params->get('queries', 1))
{
$html[] = $this->display('queries');
}
if (!empty($this->logEntries) &&
$this->params->get('logs', 1))
{
$html[] = $this->display('logs');
}
}
if ($this->debugLang)
{
if ($this->params->get('language_errorfiles', 1))
{
$languageErrors = JFactory::getLanguage()->getErrorFiles();
$html[] =
$this->display('language_files_in_error', $languageErrors);
}
if ($this->params->get('language_files', 1))
{
$html[] = $this->display('language_files_loaded');
}
if ($this->params->get('language_strings', 1))
{
$html[] = $this->display('untranslated_strings');
}
}
foreach (self::$displayCallbacks as $name => $callable)
{
$html[] = $this->displayCallback($name, $callable);
}
$html[] = '</div>';
echo str_replace('</body>', implode('', $html)
. '</body>', $contents);
}
/**
* Add a display callback to be rendered with the debug console.
*
* @param string $name The name of the callable, this is used to
generate the section title.
* @param callable $callable The callback function to be added.
*
* @return boolean
*
* @since 3.7.0
* @throws InvalidArgumentException
*/
public static function addDisplayCallback($name, $callable)
{
// TODO - When PHP 5.4 is the minimum the parameter should be typehinted
"callable" and this check removed
if (!is_callable($callable))
{
throw new InvalidArgumentException('A valid callback function must
be given.');
}
self::$displayCallbacks[$name] = $callable;
return true;
}
/**
* Remove a registered display callback
*
* @param string $name The name of the callable.
*
* @return boolean
*
* @since 3.7.0
*/
public static function removeDisplayCallback($name)
{
unset(self::$displayCallbacks[$name]);
return true;
}
/**
* Method to check if the current user is allowed to see the debug
information or not.
*
* @return boolean True if access is allowed.
*
* @since 3.0
*/
private function isAuthorisedDisplayDebug()
{
static $result = null;
if ($result !== null)
{
return $result;
}
// If the user is not allowed to view the output then end here.
$filterGroups = (array)
$this->params->get('filter_groups', array());
if (!empty($filterGroups))
{
$userGroups = JFactory::getUser()->get('groups');
if (!array_intersect($filterGroups, $userGroups))
{
$result = false;
return false;
}
}
$result = true;
return true;
}
/**
* General display method.
*
* @param string $item The item to display.
* @param array $errors Errors occurred during execution.
*
* @return string
*
* @since 2.5
*/
protected function display($item, array $errors = array())
{
$title = JText::_('PLG_DEBUG_' . strtoupper($item));
$status = '';
if (count($errors))
{
$status = ' dbg-error';
}
$fncName = 'display' . ucfirst(str_replace('_',
'', $item));
if (!method_exists($this, $fncName))
{
return __METHOD__ . ' -- Unknown method: ' . $fncName .
'<br />';
}
$html = array();
$js = "toggleContainer('dbg_container_" . $item .
"');";
$class = 'dbg-header' . $status;
$html[] = '<div class="' . $class . '"
onclick="' . $js . '"><a
href="javascript:void(0);"><h3>' . $title .
'</h3></a></div>';
// @todo set with js.. ?
$style = ' style="display: none;"';
$html[] = '<div ' . $style . '
class="dbg-container" id="dbg_container_' . $item .
'">';
$html[] = $this->$fncName();
$html[] = '</div>';
return implode('', $html);
}
/**
* Display method for callback functions.
*
* @param string $name The name of the callable.
* @param callable $callable The callable function.
*
* @return string
*
* @since 3.7.0
*/
protected function displayCallback($name, $callable)
{
$title = JText::_('PLG_DEBUG_' . strtoupper($name));
$html = array();
$js = "toggleContainer('dbg_container_" . $name .
"');";
$class = 'dbg-header';
$html[] = '<div class="' . $class . '"
onclick="' . $js . '"><a
href="javascript:void(0);"><h3>' . $title .
'</h3></a></div>';
// @todo set with js.. ?
$style = ' style="display: none;"';
$html[] = '<div ' . $style . '
class="dbg-container" id="dbg_container_' . $name .
'">';
$html[] = call_user_func($callable);
$html[] = '</div>';
return implode('', $html);
}
/**
* Display session information.
*
* Called recursively.
*
* @param string $key A session key.
* @param mixed $session The session array, initially null.
* @param integer $id Used to identify the DIV for the JavaScript
toggling code.
*
* @return string
*
* @since 2.5
*/
protected function displaySession($key = '', $session = null,
$id = 0)
{
if (!$session)
{
$session = JFactory::getSession()->getData();
}
$html = array();
static $id;
if (!is_array($session))
{
$html[] = $key . '<pre>' .
$this->prettyPrintJSON($session) . '</pre>' . PHP_EOL;
}
else
{
foreach ($session as $sKey => $entries)
{
$display = true;
if (is_array($entries) && $entries)
{
$display = false;
}
if (is_object($entries))
{
$o = ArrayHelper::fromObject($entries);
if ($o)
{
$entries = $o;
$display = false;
}
}
if (!$display)
{
$js = "toggleContainer('dbg_container_session" . $id .
'_' . $sKey . "');";
$html[] = '<div class="dbg-header"
onclick="' . $js . '"><a
href="javascript:void(0);"><h3>' . $sKey .
'</h3></a></div>';
// @todo set with js.. ?
$style = ' style="display: none;"';
$html[] = '<div ' . $style . '
class="dbg-container" id="dbg_container_session' . $id
. '_' . $sKey . '">';
$id++;
// Recurse...
$this->displaySession($sKey, $entries, $id);
$html[] = '</div>';
continue;
}
if (is_array($entries))
{
$entries = implode($entries);
}
if (is_string($entries))
{
$html[] = $sKey . '<pre>' .
$this->prettyPrintJSON($entries) . '</pre>' . PHP_EOL;
}
}
}
return implode('', $html);
}
/**
* Display errors.
*
* @return string
*
* @since 2.5
*/
protected function displayErrors()
{
$html = array();
$html[] = '<ol>';
while ($error = JError::getError(true))
{
$col = (E_WARNING == $error->get('level')) ?
'red' : 'orange';
$html[] = '<li>';
$html[] = '<b style="color: ' . $col .
'">' . $error->getMessage() . '</b><br
/>';
$info = $error->get('info');
if ($info)
{
$html[] = '<pre>' . print_r($info, true) .
'</pre><br />';
}
$html[] = $this->renderBacktrace($error);
$html[] = '</li>';
}
$html[] = '</ol>';
return implode('', $html);
}
/**
* Display profile information.
*
* @return string
*
* @since 2.5
*/
protected function displayProfileInformation()
{
$html = array();
$htmlMarks = array();
$totalTime = 0;
$totalMem = 0;
$marks = array();
$bars = array();
$barsMem = array();
foreach (JProfiler::getInstance('Application')->getMarks()
as $mark)
{
$totalTime += $mark->time;
$totalMem += (float) $mark->memory;
$htmlMark = sprintf(
JText::_('PLG_DEBUG_TIME') . ': <span
class="label label-time">%.2f ms</span> /
<span class="label
label-default">%.2f ms</span>'
. ' ' . JText::_('PLG_DEBUG_MEMORY') . ':
<span class="label label-memory">%0.3f MB</span> /
<span class="label label-default">%0.2f
MB</span>'
. ' %s: %s',
$mark->time,
$mark->totalTime,
$mark->memory,
$mark->totalMemory,
$mark->prefix,
$mark->label
);
$marks[] = (object) array(
'time' => $mark->time,
'memory' => $mark->memory,
'html' => $htmlMark,
'tip' => $mark->label,
);
}
$avgTime = $totalTime / max(count($marks), 1);
$avgMem = $totalMem / max(count($marks), 1);
foreach ($marks as $mark)
{
if ($mark->time > $avgTime * 1.5)
{
$barClass = 'bar-danger';
$labelClass = 'label-important label-danger';
}
elseif ($mark->time < $avgTime / 1.5)
{
$barClass = 'bar-success';
$labelClass = 'label-success';
}
else
{
$barClass = 'bar-warning';
$labelClass = 'label-warning';
}
if ($mark->memory > $avgMem * 1.5)
{
$barClassMem = 'bar-danger';
$labelClassMem = 'label-important label-danger';
}
elseif ($mark->memory < $avgMem / 1.5)
{
$barClassMem = 'bar-success';
$labelClassMem = 'label-success';
}
else
{
$barClassMem = 'bar-warning';
$labelClassMem = 'label-warning';
}
$barClass .= " progress-$barClass";
$barClassMem .= " progress-$barClassMem";
$bars[] = (object) array(
'width' => round($mark->time / ($totalTime / 100), 4),
'class' => $barClass,
'tip' => $mark->tip . ' ' .
round($mark->time, 2) . ' ms',
);
$barsMem[] = (object) array(
'width' => round((float) $mark->memory / ($totalMem /
100), 4),
'class' => $barClassMem,
'tip' => $mark->tip . ' ' .
round($mark->memory, 3) . ' MB',
);
$htmlMarks[] = '<div>' .
str_replace('label-time', $labelClass,
str_replace('label-memory', $labelClassMem, $mark->html)) .
'</div>';
}
$html[] = '<h4>' . JText::_('PLG_DEBUG_TIME') .
'</h4>';
$html[] = $this->renderBars($bars, 'profile');
$html[] = '<h4>' . JText::_('PLG_DEBUG_MEMORY')
. '</h4>';
$html[] = $this->renderBars($barsMem, 'profile');
$html[] = '<div class="dbg-profile-list">' .
implode('', $htmlMarks) . '</div>';
$db = $this->db;
// fix for support custom shutdown function via
register_shutdown_function().
$db->disconnect();
$log = $db->getLog();
if ($log)
{
$timings = $db->getTimings();
if ($timings)
{
$totalQueryTime = 0.0;
$lastStart = null;
foreach ($timings as $k => $v)
{
if (!($k % 2))
{
$lastStart = $v;
}
else
{
$totalQueryTime += $v - $lastStart;
}
}
$totalQueryTime *= 1000;
if ($totalQueryTime > ($totalTime * 0.25))
{
$labelClass = 'label-important';
}
elseif ($totalQueryTime < ($totalTime * 0.15))
{
$labelClass = 'label-success';
}
else
{
$labelClass = 'label-warning';
}
$html[] = '<br /><div>' . JText::sprintf(
'PLG_DEBUG_QUERIES_TIME',
sprintf('<span class="label ' . $labelClass .
'">%.2f ms</span>', $totalQueryTime)
) . '</div>';
if ($this->params->get('log-executed-sql', 0))
{
$this->writeToFile();
}
}
}
return implode('', $html);
}
/**
* Display memory usage.
*
* @return string
*
* @since 2.5
*/
protected function displayMemoryUsage()
{
$bytes = memory_get_usage();
return '<span class="label label-default">' .
JHtml::_('number.bytes', $bytes) . '</span>'
. ' (<span class="label label-default">'
. number_format($bytes, 0, JText::_('DECIMALS_SEPARATOR'),
JText::_('THOUSANDS_SEPARATOR'))
. ' '
. JText::_('PLG_DEBUG_BYTES')
. '</span>)';
}
/**
* Display logged queries.
*
* @return string
*
* @since 2.5
*/
protected function displayQueries()
{
$db = $this->db;
$log = $db->getLog();
if (!$log)
{
return null;
}
$timings = $db->getTimings();
$callStacks = $db->getCallStacks();
$db->setDebug(false);
$selectQueryTypeTicker = array();
$otherQueryTypeTicker = array();
$timing = array();
$maxtime = 0;
if (isset($timings[0]))
{
$startTime = $timings[0];
$endTime = $timings[count($timings) - 1];
$totalBargraphTime = $endTime - $startTime;
if ($totalBargraphTime > 0)
{
foreach ($log as $id => $query)
{
if (isset($timings[$id * 2 + 1]))
{
// Compute the query time: $timing[$k] = array( queryTime,
timeBetweenQueries ).
$timing[$id] = array(
($timings[$id * 2 + 1] - $timings[$id * 2]) * 1000,
$id > 0 ? ($timings[$id * 2] - $timings[$id * 2 - 1]) * 1000 : 0,
);
$maxtime = max($maxtime, $timing[$id]['0']);
}
}
}
}
else
{
$startTime = null;
$totalBargraphTime = 1;
}
$bars = array();
$info = array();
$totalQueryTime = 0;
$duplicates = array();
foreach ($log as $id => $query)
{
$did = md5($query);
if (!isset($duplicates[$did]))
{
$duplicates[$did] = array();
}
$duplicates[$did][] = $id;
if ($timings && isset($timings[$id * 2 + 1]))
{
// Compute the query time.
$queryTime = ($timings[$id * 2 + 1] - $timings[$id * 2]) * 1000;
$totalQueryTime += $queryTime;
// Run an EXPLAIN EXTENDED query on the SQL query if possible.
$hasWarnings = false;
$hasWarningsInProfile = false;
if (isset($this->explains[$id]))
{
$explain = $this->tableToHtml($this->explains[$id],
$hasWarnings);
}
else
{
$explain =
JText::sprintf('PLG_DEBUG_QUERY_EXPLAIN_NOT_POSSIBLE',
htmlspecialchars($query));
}
// Run a SHOW PROFILE query.
$profile = '';
if (isset($this->sqlShowProfileEach[$id]) &&
$db->getServerType() === 'mysql')
{
$profileTable = $this->sqlShowProfileEach[$id];
$profile = $this->tableToHtml($profileTable,
$hasWarningsInProfile);
}
// How heavy should the string length count: 0 - 1.
$ratio = 0.5;
$timeScore = $queryTime / ((strlen($query) + 1) * $ratio) * 200;
// Determine color of bargraph depending on query speed and presence of
warnings in EXPLAIN.
if ($timeScore > 10)
{
$barClass = 'bar-danger';
$labelClass = 'label-important';
}
elseif ($hasWarnings || $timeScore > 5)
{
$barClass = 'bar-warning';
$labelClass = 'label-warning';
}
else
{
$barClass = 'bar-success';
$labelClass = 'label-success';
}
// Computes bargraph as follows: Position begin and end of the bar
relatively to whole execution time.
// TODO: $prevBar is not used anywhere. Remove?
$prevBar = $id && isset($bars[$id - 1]) ? $bars[$id - 1] : 0;
$barPre = round($timing[$id][1] / ($totalBargraphTime * 10), 4);
$barWidth = round($timing[$id][0] / ($totalBargraphTime * 10), 4);
$minWidth = 0.3;
if ($barWidth < $minWidth)
{
$barPre -= ($minWidth - $barWidth);
if ($barPre < 0)
{
$minWidth += $barPre;
$barPre = 0;
}
$barWidth = $minWidth;
}
$bars[$id] = (object) array(
'class' => $barClass,
'width' => $barWidth,
'pre' => $barPre,
'tip' => sprintf('%.2f ms', $queryTime),
);
$info[$id] = (object) array(
'class' => $labelClass,
'explain' => $explain,
'profile' => $profile,
'hasWarnings' => $hasWarnings,
);
}
}
// Remove single queries from $duplicates.
$total_duplicates = 0;
foreach ($duplicates as $did => $dups)
{
if (count($dups) < 2)
{
unset($duplicates[$did]);
}
else
{
$total_duplicates += count($dups);
}
}
// Fix first bar width.
$minWidth = 0.3;
if ($bars[0]->width < $minWidth && isset($bars[1]))
{
$bars[1]->pre -= ($minWidth - $bars[0]->width);
if ($bars[1]->pre < 0)
{
$minWidth += $bars[1]->pre;
$bars[1]->pre = 0;
}
$bars[0]->width = $minWidth;
}
$memoryUsageNow = memory_get_usage();
$list = array();
foreach ($log as $id => $query)
{
// Start query type ticker additions.
$fromStart = stripos($query, 'from');
$whereStart = stripos($query, 'where', $fromStart);
if ($whereStart === false)
{
$whereStart = stripos($query, 'order by', $fromStart);
}
if ($whereStart === false)
{
$whereStart = strlen($query) - 1;
}
$fromString = substr($query, 0, $whereStart);
$fromString = str_replace(array("\t", "\n"), '
', $fromString);
$fromString = trim($fromString);
// Initialise the select/other query type counts the first time.
if (!isset($selectQueryTypeTicker[$fromString]))
{
$selectQueryTypeTicker[$fromString] = 0;
}
if (!isset($otherQueryTypeTicker[$fromString]))
{
$otherQueryTypeTicker[$fromString] = 0;
}
// Increment the count.
if (stripos($query, 'select') === 0)
{
$selectQueryTypeTicker[$fromString]++;
unset($otherQueryTypeTicker[$fromString]);
}
else
{
$otherQueryTypeTicker[$fromString]++;
unset($selectQueryTypeTicker[$fromString]);
}
$text = $this->highlightQuery($query);
if ($timings && isset($timings[$id * 2 + 1]))
{
// Compute the query time.
$queryTime = ($timings[$id * 2 + 1] - $timings[$id * 2]) * 1000;
// Timing
// Formats the output for the query time with EXPLAIN query results as
tooltip:
$htmlTiming = '<div style="margin: 0 0
5px;"><span class="dbg-query-time">';
$htmlTiming .= JText::sprintf(
'PLG_DEBUG_QUERY_TIME',
sprintf(
'<span class="label
%s">%.2f ms</span>',
$info[$id]->class,
$timing[$id]['0']
)
);
if ($timing[$id]['1'])
{
$htmlTiming .= ' ' . JText::sprintf(
'PLG_DEBUG_QUERY_AFTER_LAST',
sprintf('<span class="label
label-default">%.2f ms</span>',
$timing[$id]['1'])
);
}
$htmlTiming .= '</span>';
if (isset($callStacks[$id][0]['memory']))
{
$memoryUsed = $callStacks[$id][0]['memory'][1] -
$callStacks[$id][0]['memory'][0];
$memoryBeforeQuery = $callStacks[$id][0]['memory'][0];
// Determine colour of query memory usage.
if ($memoryUsed > 0.1 * $memoryUsageNow)
{
$labelClass = 'label-important';
}
elseif ($memoryUsed > 0.05 * $memoryUsageNow)
{
$labelClass = 'label-warning';
}
else
{
$labelClass = 'label-success';
}
$htmlTiming .= ' ' . '<span
class="dbg-query-memory">'
. JText::sprintf(
'PLG_DEBUG_MEMORY_USED_FOR_QUERY',
sprintf('<span class="label ' . $labelClass .
'">%.3f MB</span>', $memoryUsed /
1048576),
sprintf('<span class="label
label-default">%.3f MB</span>',
$memoryBeforeQuery / 1048576)
)
. '</span>';
if ($callStacks[$id][0]['memory'][2] !== null)
{
// Determine colour of number or results.
$resultsReturned = $callStacks[$id][0]['memory'][2];
if ($resultsReturned > 3000)
{
$labelClass = 'label-important';
}
elseif ($resultsReturned > 1000)
{
$labelClass = 'label-warning';
}
elseif ($resultsReturned == 0)
{
$labelClass = '';
}
else
{
$labelClass = 'label-success';
}
$htmlResultsReturned = '<span class="label ' .
$labelClass . '">' . (int) $resultsReturned .
'</span>';
$htmlTiming .= ' <span
class="dbg-query-rowsnumber">'
. JText::sprintf('PLG_DEBUG_ROWS_RETURNED_BY_QUERY',
$htmlResultsReturned) . '</span>';
}
}
$htmlTiming .= '</div>';
// Bar.
$htmlBar = $this->renderBars($bars, 'query', $id);
// Profile query.
$title = JText::_('PLG_DEBUG_PROFILE');
if (!$info[$id]->profile)
{
$title = '<span class="dbg-noprofile">' .
$title . '</span>';
}
$htmlProfile = $info[$id]->profile ?:
JText::_('PLG_DEBUG_NO_PROFILE');
$htmlAccordions = JHtml::_(
'bootstrap.startAccordion', 'dbg_query_' . $id,
array(
'active' => $info[$id]->hasWarnings ?
('dbg_query_explain_' . $id) : '',
)
);
$htmlAccordions .= JHtml::_('bootstrap.addSlide',
'dbg_query_' . $id, JText::_('PLG_DEBUG_EXPLAIN'),
'dbg_query_explain_' . $id)
. $info[$id]->explain
. JHtml::_('bootstrap.endSlide');
$htmlAccordions .= JHtml::_('bootstrap.addSlide',
'dbg_query_' . $id, $title, 'dbg_query_profile_' . $id)
. $htmlProfile
. JHtml::_('bootstrap.endSlide');
// Call stack and back trace.
if (isset($callStacks[$id]))
{
$htmlAccordions .= JHtml::_('bootstrap.addSlide',
'dbg_query_' . $id, JText::_('PLG_DEBUG_CALL_STACK'),
'dbg_query_callstack_' . $id)
. $this->renderCallStack($callStacks[$id])
. JHtml::_('bootstrap.endSlide');
}
$htmlAccordions .= JHtml::_('bootstrap.endAccordion');
$did = md5($query);
if (isset($duplicates[$did]))
{
$dups = array();
foreach ($duplicates[$did] as $dup)
{
if ($dup != $id)
{
$dups[] = '<a class="alert-link"
href="#dbg-query-' . ($dup + 1) . '">#' . ($dup
+ 1) . '</a>';
}
}
$htmlQuery = '<div class="alert
alert-error">' .
JText::_('PLG_DEBUG_QUERY_DUPLICATES') . ': ' .
implode(' ', $dups) . '</div>'
. '<pre class="alert" title="' .
htmlspecialchars(JText::_('PLG_DEBUG_QUERY_DUPLICATES_FOUND'),
ENT_COMPAT, 'UTF-8') . '">' . $text .
'</pre>';
}
else
{
$htmlQuery = '<pre>' . $text .
'</pre>';
}
$list[] = '<a name="dbg-query-' . ($id + 1) .
'"></a>'
. $htmlTiming
. $htmlBar
. $htmlQuery
. $htmlAccordions;
}
else
{
$list[] = '<pre>' . $text . '</pre>';
}
}
$totalTime = 0;
foreach (JProfiler::getInstance('Application')->getMarks()
as $mark)
{
$totalTime += $mark->time;
}
if ($totalQueryTime > ($totalTime * 0.25))
{
$labelClass = 'label-important';
}
elseif ($totalQueryTime < ($totalTime * 0.15))
{
$labelClass = 'label-success';
}
else
{
$labelClass = 'label-warning';
}
if ($this->totalQueries === 0)
{
$this->totalQueries = $db->getCount();
}
$html = array();
$html[] = '<h4>' .
JText::sprintf('PLG_DEBUG_QUERIES_LOGGED',
$this->totalQueries)
. sprintf(' <span class="label ' . $labelClass .
'">%.2f ms</span>', $totalQueryTime) .
'</h4><br />';
if ($total_duplicates)
{
$html[] = '<div class="alert alert-error">'
. '<h4>' .
JText::sprintf('PLG_DEBUG_QUERY_DUPLICATES_TOTAL_NUMBER',
$total_duplicates) . '</h4>';
foreach ($duplicates as $dups)
{
$links = array();
foreach ($dups as $dup)
{
$links[] = '<a class="alert-link"
href="#dbg-query-' . ($dup + 1) . '">#' . ($dup
+ 1) . '</a>';
}
$html[] = '<div>' .
JText::sprintf('PLG_DEBUG_QUERY_DUPLICATES_NUMBER',
count($links)) . ': ' . implode(' ', $links)
. '</div>';
}
$html[] = '</div>';
}
$html[] = '<ol><li>' . implode('<hr
/></li><li>', $list) . '<hr
/></li></ol>';
if (!$this->params->get('query_types', 1))
{
return implode('', $html);
}
// Get the totals for the query types.
$totalSelectQueryTypes = count($selectQueryTypeTicker);
$totalOtherQueryTypes = count($otherQueryTypeTicker);
$totalQueryTypes = $totalSelectQueryTypes + $totalOtherQueryTypes;
$html[] = '<h4>' .
JText::sprintf('PLG_DEBUG_QUERY_TYPES_LOGGED', $totalQueryTypes)
. '</h4>';
if ($totalSelectQueryTypes)
{
$html[] = '<h5>' .
JText::_('PLG_DEBUG_SELECT_QUERIES') . '</h5>';
arsort($selectQueryTypeTicker);
$list = array();
foreach ($selectQueryTypeTicker as $query => $occurrences)
{
$list[] = '<pre>'
. JText::sprintf('PLG_DEBUG_QUERY_TYPE_AND_OCCURRENCES',
$this->highlightQuery($query), $occurrences)
. '</pre>';
}
$html[] = '<ol><li>' .
implode('</li><li>', $list) .
'</li></ol>';
}
if ($totalOtherQueryTypes)
{
$html[] = '<h5>' .
JText::_('PLG_DEBUG_OTHER_QUERIES') . '</h5>';
arsort($otherQueryTypeTicker);
$list = array();
foreach ($otherQueryTypeTicker as $query => $occurrences)
{
$list[] = '<pre>'
. JText::sprintf('PLG_DEBUG_QUERY_TYPE_AND_OCCURRENCES',
$this->highlightQuery($query), $occurrences)
. '</pre>';
}
$html[] = '<ol><li>' .
implode('</li><li>', $list) .
'</li></ol>';
}
return implode('', $html);
}
/**
* Render the bars.
*
* @param array &$bars Array of bar data
* @param string $class Optional class for items
* @param integer $id Id if the bar to highlight
*
* @return string
*
* @since 3.1.2
*/
protected function renderBars(&$bars, $class = '', $id =
null)
{
$html = array();
foreach ($bars as $i => $bar)
{
if (isset($bar->pre) && $bar->pre)
{
$html[] = '<div class="dbg-bar-spacer"
style="width:' . $bar->pre .
'%;"></div>';
}
$barClass = trim('bar dbg-bar progress-bar ' .
(isset($bar->class) ? $bar->class : ''));
if ($id !== null && $i == $id)
{
$barClass .= ' dbg-bar-active';
}
$tip = empty($bar->tip) ? '' : ' title="' .
htmlspecialchars($bar->tip, ENT_COMPAT, 'UTF-8') .
'"';
$html[] = '<a class="bar dbg-bar ' . $barClass .
'"' . $tip . ' style="width: '
. $bar->width . '%;" href="#dbg-' . $class .
'-' . ($i + 1) . '"></a>';
}
return '<div class="progress dbg-bars dbg-bars-' .
$class . '">' . implode('', $html) .
'</div>';
}
/**
* Render an HTML table based on a multi-dimensional array.
*
* @param array $table An array of tabular data.
* @param boolean &$hasWarnings Changes value to true if warnings
are displayed, otherwise untouched
*
* @return string
*
* @since 3.1.2
*/
protected function tableToHtml($table, &$hasWarnings)
{
if (!$table)
{
return null;
}
$html = array();
$html[] = '<table class="table table-striped
dbg-query-table">';
$html[] = '<thead>';
$html[] = '<tr>';
foreach (array_keys($table[0]) as $k)
{
$html[] = '<th>' . htmlspecialchars($k) .
'</th>';
}
$html[] = '</tr>';
$html[] = '</thead>';
$html[] = '<tbody>';
$durations = array();
foreach ($table as $tr)
{
if (isset($tr['Duration']))
{
$durations[] = $tr['Duration'];
}
}
rsort($durations, SORT_NUMERIC);
foreach ($table as $tr)
{
$html[] = '<tr>';
foreach ($tr as $k => $td)
{
if ($td === null)
{
// Display null's as 'NULL'.
$td = 'NULL';
}
// Treat special columns.
if ($k === 'Duration')
{
if ($td >= 0.001 && ($td == $durations[0] ||
(isset($durations[1]) && $td == $durations[1])))
{
// Duration column with duration value of more than 1 ms and within 2
top duration in SQL engine: Highlight warning.
$html[] = '<td class="dbg-warning">';
$hasWarnings = true;
}
else
{
$html[] = '<td>';
}
// Display duration in milliseconds with the unit instead of seconds.
$html[] = sprintf('%.2f ms', $td * 1000);
}
elseif ($k === 'Error')
{
// An error in the EXPLAIN query occurred, display it instead of the
result (means original query had syntax error most probably).
$html[] = '<td class="dbg-warning">' .
htmlspecialchars($td);
$hasWarnings = true;
}
elseif ($k === 'key')
{
if ($td === 'NULL')
{
// Displays query parts which don't use a key with warning:
$html[] = '<td><strong>' . '<span
class="dbg-warning" title="'
.
htmlspecialchars(JText::_('PLG_DEBUG_WARNING_NO_INDEX_DESC'),
ENT_COMPAT, 'UTF-8') . '">'
. JText::_('PLG_DEBUG_WARNING_NO_INDEX') .
'</span>' . '</strong>';
$hasWarnings = true;
}
else
{
$html[] = '<td><strong>' .
htmlspecialchars($td) . '</strong>';
}
}
elseif ($k === 'Extra')
{
$htmlTd = htmlspecialchars($td);
// Replace spaces with (non-breaking spaces) for less tall
tables displayed.
$htmlTd = preg_replace('/([^;]) /',
'\1 ', $htmlTd);
// Displays warnings for "Using filesort":
$htmlTdWithWarnings = str_replace(
'Using filesort',
'<span class="dbg-warning" title="'
.
htmlspecialchars(JText::_('PLG_DEBUG_WARNING_USING_FILESORT_DESC'),
ENT_COMPAT, 'UTF-8') . '">'
. JText::_('PLG_DEBUG_WARNING_USING_FILESORT') .
'</span>',
$htmlTd
);
if ($htmlTdWithWarnings !== $htmlTd)
{
$hasWarnings = true;
}
$html[] = '<td>' . $htmlTdWithWarnings;
}
else
{
$html[] = '<td>' . htmlspecialchars($td);
}
$html[] = '</td>';
}
$html[] = '</tr>';
}
$html[] = '</tbody>';
$html[] = '</table>';
return implode('', $html);
}
/**
* Disconnect handler for database to collect profiling and explain
information.
*
* @param JDatabaseDriver &$db Database object.
*
* @return void
*
* @since 3.1.2
*/
public function mysqlDisconnectHandler(&$db)
{
$db->setDebug(false);
$this->totalQueries = $db->getCount();
$dbVersion5037 = $db->getServerType() === 'mysql' &&
version_compare($db->getVersion(), '5.0.37',
'>=');
if ($dbVersion5037)
{
try
{
// Check if profiling is enabled.
$db->setQuery("SHOW VARIABLES LIKE
'have_profiling'");
$hasProfiling = $db->loadResult();
if ($hasProfiling)
{
// Run a SHOW PROFILE query.
$db->setQuery('SHOW PROFILES');
$this->sqlShowProfiles = $db->loadAssocList();
if ($this->sqlShowProfiles)
{
foreach ($this->sqlShowProfiles as $qn)
{
// Run SHOW PROFILE FOR QUERY for each query where a profile is
available (max 100).
$db->setQuery('SHOW PROFILE FOR QUERY ' . (int)
$qn['Query_ID']);
$this->sqlShowProfileEach[(int) ($qn['Query_ID'] - 1)]
= $db->loadAssocList();
}
}
}
else
{
$this->sqlShowProfileEach[0] = array(array('Error' =>
'MySql have_profiling = off'));
}
}
catch (Exception $e)
{
$this->sqlShowProfileEach[0] = array(array('Error' =>
$e->getMessage()));
}
}
if (in_array($db->getServerType(), array('mysql',
'postgresql'), true))
{
$log = $db->getLog();
foreach ($log as $k => $query)
{
$dbVersion56 = $db->getServerType() === 'mysql' &&
version_compare($db->getVersion(), '5.6', '>=');
$dbVersion80 = $db->getServerType() === 'mysql' &&
version_compare($db->getVersion(), '8.0', '>=');
if ($dbVersion80)
{
$dbVersion56 = false;
}
if ((stripos($query, 'select') === 0) || ($dbVersion56
&& ((stripos($query, 'delete') === 0) || (stripos($query,
'update') === 0))))
{
try
{
$db->setQuery('EXPLAIN ' . ($dbVersion56 ?
'EXTENDED ' : '') . $query);
$this->explains[$k] = $db->loadAssocList();
}
catch (Exception $e)
{
$this->explains[$k] = array(array('Error' =>
$e->getMessage()));
}
}
}
}
}
/**
* Displays errors in language files.
*
* @return string
*
* @since 2.5
*/
protected function displayLanguageFilesInError()
{
$errorfiles = JFactory::getLanguage()->getErrorFiles();
if (!count($errorfiles))
{
return '<p>' . JText::_('JNONE') .
'</p>';
}
$html = array();
$html[] = '<ul>';
foreach ($errorfiles as $file => $error)
{
$html[] = '<li>' . $this->formatLink($file) .
str_replace($file, '', $error) . '</li>';
}
$html[] = '</ul>';
return implode('', $html);
}
/**
* Display loaded language files.
*
* @return string
*
* @since 2.5
*/
protected function displayLanguageFilesLoaded()
{
$html = array();
$html[] = '<ul>';
foreach (JFactory::getLanguage()->getPaths() as /* $extension => */
$files)
{
foreach ($files as $file => $status)
{
$html[] = '<li>';
$html[] = $status
? JText::_('PLG_DEBUG_LANG_LOADED')
: JText::_('PLG_DEBUG_LANG_NOT_LOADED');
$html[] = ' : ';
$html[] = $this->formatLink($file);
$html[] = '</li>';
}
}
$html[] = '</ul>';
return implode('', $html);
}
/**
* Display untranslated language strings.
*
* @return string
*
* @since 2.5
*/
protected function displayUntranslatedStrings()
{
$stripFirst = $this->params->get('strip-first', 1);
$stripPref = $this->params->get('strip-prefix');
$stripSuff = $this->params->get('strip-suffix');
$orphans = JFactory::getLanguage()->getOrphans();
if (!count($orphans))
{
return '<p>' . JText::_('JNONE') .
'</p>';
}
ksort($orphans, SORT_STRING);
$guesses = array();
foreach ($orphans as $key => $occurance)
{
if (is_array($occurance) && isset($occurance[0]))
{
$info = $occurance[0];
$file = $info['file'] ?: '';
if (!isset($guesses[$file]))
{
$guesses[$file] = array();
}
// Prepare the key.
if (($pos = strpos($info['string'], '=')) > 0)
{
$parts = explode('=', $info['string']);
$key = $parts[0];
$guess = $parts[1];
}
else
{
$guess = str_replace('_', ' ',
$info['string']);
if ($stripFirst)
{
$parts = explode(' ', $guess);
if (count($parts) > 1)
{
array_shift($parts);
$guess = implode(' ', $parts);
}
}
$guess = trim($guess);
if ($stripPref)
{
$guess = trim(preg_replace(chr(1) . '^' . $stripPref .
chr(1) . 'i', '', $guess));
}
if ($stripSuff)
{
$guess = trim(preg_replace(chr(1) . $stripSuff . '$' .
chr(1) . 'i', '', $guess));
}
}
$key = strtoupper(trim($key));
$key = preg_replace('#\s+#', '_', $key);
$key = preg_replace('#\W#', '', $key);
// Prepare the text.
$guesses[$file][] = $key . '="' . $guess .
'"';
}
}
$html = array();
foreach ($guesses as $file => $keys)
{
$html[] = "\n\n# " . ($file ? $this->formatLink($file) :
JText::_('PLG_DEBUG_UNKNOWN_FILE')) . "\n\n";
$html[] = implode("\n", $keys);
}
return '<pre>' . implode('', $html) .
'</pre>';
}
/**
* Simple highlight for SQL queries.
*
* @param string $query The query to highlight.
*
* @return string
*
* @since 2.5
*/
protected function highlightQuery($query)
{
$newlineKeywords =
'#\b(FROM|LEFT|INNER|OUTER|WHERE|SET|VALUES|ORDER|GROUP|HAVING|LIMIT|ON|AND|CASE)\b#i';
$query = htmlspecialchars($query, ENT_QUOTES);
$query = preg_replace($newlineKeywords, '<br
/>  \\0', $query);
$regex = array(
// Tables are identified by the prefix.
'/(=)/' =>
'<b class="dbg-operator">$1</b>',
// All uppercase words have a special meaning.
'/(?<!\w|>)([A-Z_]{2,})(?!\w)/x' =>
'<span class="dbg-command">$1</span>',
// Tables are identified by the prefix.
'/(' . $this->db->getPrefix() . '[a-z_0-9]+)/'
=> '<span class="dbg-table">$1</span>',
);
$query = preg_replace(array_keys($regex), array_values($regex), $query);
$query = str_replace('*', '<b style="color:
red;">*</b>', $query);
return $query;
}
/**
* Render the backtrace.
*
* Stolen from JError to prevent it's removal.
*
* @param Exception $error The Exception object to be rendered.
*
* @return string Rendered backtrace.
*
* @since 2.5
*/
protected function renderBacktrace($error)
{
return JLayoutHelper::render('joomla.error.backtrace',
array('backtrace' => $error->getTrace()));
}
/**
* Replaces the Joomla! root with "JROOT" to improve
readability.
* Formats a link with a special value xdebug.file_link_format
* from the php.ini file.
*
* @param string $file The full path to the file.
* @param string $line The line number.
*
* @return string
*
* @since 2.5
*/
protected function formatLink($file, $line = '')
{
return JHtml::_('debug.xdebuglink', $file, $line);
}
/**
* Store log messages so they can be displayed later.
* This function is passed log entries by JLogLoggerCallback.
*
* @param JLogEntry $entry A log entry.
*
* @return void
*
* @since 3.1
*/
public function logger(JLogEntry $entry)
{
$this->logEntries[] = $entry;
}
/**
* Display log messages.
*
* @return string
*
* @since 3.1
*/
protected function displayLogs()
{
$priorities = array(
JLog::EMERGENCY => '<span class="badge
badge-important">EMERGENCY</span>',
JLog::ALERT => '<span class="badge
badge-important">ALERT</span>',
JLog::CRITICAL => '<span class="badge
badge-important">CRITICAL</span>',
JLog::ERROR => '<span class="badge
badge-important">ERROR</span>',
JLog::WARNING => '<span class="badge
badge-warning">WARNING</span>',
JLog::NOTICE => '<span class="badge
badge-info">NOTICE</span>',
JLog::INFO => '<span class="badge
badge-info">INFO</span>',
JLog::DEBUG => '<span
class="badge">DEBUG</span>',
);
$out = '';
$logEntriesTotal = count($this->logEntries);
// SQL log entries
$showExecutedSQL = $this->params->get('log-executed-sql',
0);
if (!$showExecutedSQL)
{
$logEntriesDatabasequery = count(
array_filter(
$this->logEntries, function ($logEntry)
{
return $logEntry->category === 'databasequery';
}
)
);
$logEntriesTotal -= $logEntriesDatabasequery;
}
// Deprecated log entries
$logEntriesDeprecated = count(
array_filter(
$this->logEntries, function ($logEntry)
{
return $logEntry->category === 'deprecated';
}
)
);
$showDeprecated =
$this->params->get('log-deprecated', 0);
if (!$showDeprecated)
{
$logEntriesTotal -= $logEntriesDeprecated;
}
$showEverything = $this->params->get('log-everything',
0);
$out .= '<h4>' .
JText::sprintf('PLG_DEBUG_LOGS_LOGGED', $logEntriesTotal) .
'</h4><br />';
if ($showDeprecated && $logEntriesDeprecated > 0)
{
$out .= '
<div class="alert alert-warning">
<h4>' .
JText::sprintf('PLG_DEBUG_LOGS_DEPRECATED_FOUND_TITLE',
$logEntriesDeprecated) . '</h4>
<div>' .
JText::_('PLG_DEBUG_LOGS_DEPRECATED_FOUND_TEXT') .
'</div>
</div>
<br />';
}
$out .= '<ol>';
$count = 1;
foreach ($this->logEntries as $entry)
{
// Don't show database queries if not selected.
if (!$showExecutedSQL && $entry->category ===
'databasequery')
{
continue;
}
// Don't show deprecated logs if not selected.
if (!$showDeprecated && $entry->category ===
'deprecated')
{
continue;
}
// Don't show everything logs if not selected.
if (!$showEverything && !in_array($entry->category,
array('deprecated', 'databasequery'), true))
{
continue;
}
$out .= '<li id="dbg_logs_' . $count .
'">';
$out .= '<h5>' . $priorities[$entry->priority] .
' ' . $entry->category . '</h5><br />
<pre>' . $entry->message . '</pre>';
if ($entry->callStack)
{
$out .= JHtml::_('bootstrap.startAccordion',
'dbg_logs_' . $count, array('active' =>
''));
$out .= JHtml::_('bootstrap.addSlide', 'dbg_logs_'
. $count, JText::_('PLG_DEBUG_CALL_STACK'),
'dbg_logs_backtrace_' . $count);
$out .= $this->renderCallStack($entry->callStack);
$out .= JHtml::_('bootstrap.endSlide');
$out .= JHtml::_('bootstrap.endAccordion');
}
$out .= '<hr /></li>';
$count++;
}
$out .= '</ol>';
return $out;
}
/**
* Renders call stack and back trace in HTML.
*
* @param array $callStack The call stack and back trace array.
*
* @return string The call stack and back trace in HMTL format.
*
* @since 3.5
*/
protected function renderCallStack(array $callStack = array())
{
$htmlCallStack = '';
if ($callStack !== null)
{
$htmlCallStack .= '<div>';
$htmlCallStack .= '<table class="table table-striped
dbg-query-table">';
$htmlCallStack .= '<thead>';
$htmlCallStack .= '<tr>';
$htmlCallStack .= '<th>#</th>';
$htmlCallStack .= '<th>' .
JText::_('PLG_DEBUG_CALL_STACK_CALLER') .
'</th>';
$htmlCallStack .= '<th>' .
JText::_('PLG_DEBUG_CALL_STACK_FILE_AND_LINE') .
'</th>';
$htmlCallStack .= '</tr>';
$htmlCallStack .= '</thead>';
$htmlCallStack .= '<tbody>';
$count = count($callStack);
foreach ($callStack as $call)
{
// Dont' back trace log classes.
if (isset($call['class']) &&
strpos($call['class'], 'JLog') !== false)
{
$count--;
continue;
}
$htmlCallStack .= '<tr>';
$htmlCallStack .= '<td>' . $count .
'</td>';
$htmlCallStack .= '<td>';
if (isset($call['class']))
{
// If entry has Class/Method print it.
$htmlCallStack .= htmlspecialchars($call['class'] .
$call['type'] . $call['function']) . '()';
}
else
{
if (isset($call['args']))
{
// If entry has args is a require/include.
$htmlCallStack .= htmlspecialchars($call['function']) .
' ' . $this->formatLink($call['args'][0]);
}
else
{
// It's a function.
$htmlCallStack .= htmlspecialchars($call['function']) .
'()';
}
}
$htmlCallStack .= '</td>';
$htmlCallStack .= '<td>';
// If entry doesn't have line and number the next is a
call_user_func.
if (!isset($call['file']) &&
!isset($call['line']))
{
$htmlCallStack .=
JText::_('PLG_DEBUG_CALL_STACK_SAME_FILE');
}
// If entry has file and line print it.
else
{
$htmlCallStack .=
$this->formatLink(htmlspecialchars($call['file']),
htmlspecialchars($call['line']));
}
$htmlCallStack .= '</td>';
$htmlCallStack .= '</tr>';
$count--;
}
$htmlCallStack .= '</tbody>';
$htmlCallStack .= '</table>';
$htmlCallStack .= '</div>';
if (!$this->linkFormat)
{
$htmlCallStack .= '<div>[<a
href="https://xdebug.org/docs/all_settings#file_link_format"
target="_blank" rel="noopener noreferrer">';
$htmlCallStack .= JText::_('PLG_DEBUG_LINK_FORMAT') .
'</a>]</div>';
}
}
return $htmlCallStack;
}
/**
* Pretty print JSON with colors.
*
* @param string $json The json raw string.
*
* @return string The json string pretty printed.
*
* @since 3.5
*/
protected function prettyPrintJSON($json = '')
{
// In PHP 5.4.0 or later we have pretty print option.
if (version_compare(PHP_VERSION, '5.4', '>='))
{
$json = json_encode($json, JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT);
}
// Escape HTML in session vars
$json = htmlentities($json);
// Add some colors
$json = preg_replace('#"([^"]+)":#',
'<span class=\'black\'>"</span><span
class=\'green\'>$1</span><span
class=\'black\'>"</span>:', $json);
$json = preg_replace('#"(|[^"]+)"(\n|\r\n|,)#',
'<span
class=\'grey\'>"$1"</span>$2', $json);
$json = str_replace('null,', '<span
class=\'blue\'>null</span>,', $json);
return $json;
}
/**
* Write query to the log file
*
* @return void
*
* @since 3.5
*/
protected function writeToFile()
{
$app = JFactory::getApplication();
$domain = $app->isClient('site') ? 'site' :
'admin';
$input = $app->input;
$file = $app->get('log_path') . '/' . $domain .
'_' . $input->get('option') .
$input->get('view') . $input->get('layout') .
'.sql.php';
// Get the queries from log.
$current = '';
$db = $this->db;
$log = $db->getLog();
$timings = $db->getTimings();
foreach ($log as $id => $query)
{
if (isset($timings[$id * 2 + 1]))
{
$temp = str_replace('`', '', $log[$id]);
$temp = str_replace(array("\t", "\n",
"\r\n"), ' ', $temp);
$current .= $temp . ";\n";
}
}
if (JFile::exists($file))
{
JFile::delete($file);
}
$head = array('#');
$head[] = '#<?php die(\'Forbidden.\'); ?>';
$head[] = '#Date: ' . gmdate('Y-m-d H:i:s') . '
UTC';
$head[] = '#Software: ' . \JPlatform::getLongVersion();
$head[] = "\n";
// Write new file.
JFile::write($file, implode("\n", $head) . $current);
}
}
system/debug/debug.xml000064400000017076147357022250011010 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_debug</name>
<author>Joomla! Project</author>
<creationDate>December 2006</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_DEBUG_XML_DESCRIPTION</description>
<files>
<filename plugin="debug">debug.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_debug.ini</language>
<language
tag="en-GB">en-GB.plg_system_debug.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="filter_groups"
type="usergrouplist"
label="PLG_DEBUG_FIELD_ALLOWED_GROUPS_LABEL"
description="PLG_DEBUG_FIELD_ALLOWED_GROUPS_DESC"
multiple="true"
filter="int_array"
size="10"
/>
<field
name="session"
type="radio"
label="PLG_DEBUG_FIELD_SESSION_LABEL"
description="PLG_DEBUG_FIELD_SESSION_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="profile"
type="radio"
label="PLG_DEBUG_FIELD_PROFILING_LABEL"
description="PLG_DEBUG_FIELD_PROFILING_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="queries"
type="radio"
label="PLG_DEBUG_FIELD_QUERIES_LABEL"
description="PLG_DEBUG_FIELD_QUERIES_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="query_types"
type="radio"
label="PLG_DEBUG_FIELD_QUERY_TYPES_LABEL"
description="PLG_DEBUG_FIELD_QUERY_TYPES_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="memory"
type="radio"
label="PLG_DEBUG_FIELD_MEMORY_LABEL"
description="PLG_DEBUG_FIELD_MEMORY_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="logs"
type="radio"
label="PLG_DEBUG_FIELD_LOGS_LABEL"
description="PLG_DEBUG_FIELD_LOGS_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="log_priorities"
type="list"
label="PLG_DEBUG_FIELD_LOG_PRIORITIES_LABEL"
description="PLG_DEBUG_FIELD_LOG_PRIORITIES_DESC"
multiple="true"
default="all"
>
<option
value="all">PLG_DEBUG_FIELD_LOG_PRIORITIES_ALL</option>
<option
value="emergency">PLG_DEBUG_FIELD_LOG_PRIORITIES_EMERGENCY</option>
<option
value="alert">PLG_DEBUG_FIELD_LOG_PRIORITIES_ALERT</option>
<option
value="critical">PLG_DEBUG_FIELD_LOG_PRIORITIES_CRITICAL</option>
<option
value="error">PLG_DEBUG_FIELD_LOG_PRIORITIES_ERROR</option>
<option
value="warning">PLG_DEBUG_FIELD_LOG_PRIORITIES_WARNING</option>
<option
value="notice">PLG_DEBUG_FIELD_LOG_PRIORITIES_NOTICE</option>
<option
value="info">PLG_DEBUG_FIELD_LOG_PRIORITIES_INFO</option>
<option
value="debug">PLG_DEBUG_FIELD_LOG_PRIORITIES_DEBUG</option>
</field>
<field
name="log_categories"
type="text"
label="PLG_DEBUG_FIELD_LOG_CATEGORIES_LABEL"
description="PLG_DEBUG_FIELD_LOG_CATEGORIES_DESC"
size="60"
/>
<field
name="log_category_mode"
type="radio"
label="PLG_DEBUG_FIELD_LOG_CATEGORY_MODE_LABEL"
description="PLG_DEBUG_FIELD_LOG_CATEGORY_MODE_DESC"
default="0"
filter="integer"
class="btn-group btn-group-yesno btn-group-reversed"
>
<option
value="0">PLG_DEBUG_FIELD_LOG_CATEGORY_MODE_INCLUDE</option>
<option
value="1">PLG_DEBUG_FIELD_LOG_CATEGORY_MODE_EXCLUDE</option>
</field>
<field
name="refresh_assets"
type="radio"
label="PLG_DEBUG_FIELD_REFRESH_ASSETS_LABEL"
description="PLG_DEBUG_FIELD_REFRESH_ASSETS_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
<fieldset
name="language"
label="PLG_DEBUG_LANGUAGE_FIELDSET_LABEL"
>
<field
name="language_errorfiles"
type="radio"
label="PLG_DEBUG_FIELD_LANGUAGE_ERRORFILES_LABEL"
description="PLG_DEBUG_FIELD_LANGUAGE_ERRORFILES_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="language_files"
type="radio"
label="PLG_DEBUG_FIELD_LANGUAGE_FILES_LABEL"
description="PLG_DEBUG_FIELD_LANGUAGE_FILES_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="language_strings"
type="radio"
label="PLG_DEBUG_FIELD_LANGUAGE_STRING_LABEL"
description="PLG_DEBUG_FIELD_LANGUAGE_STRING_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="strip-first"
type="radio"
label="PLG_DEBUG_FIELD_STRIP_FIRST_LABEL"
description="PLG_DEBUG_FIELD_STRIP_FIRST_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="strip-prefix"
type="textarea"
label="PLG_DEBUG_FIELD_STRIP_PREFIX_LABEL"
description="PLG_DEBUG_FIELD_STRIP_PREFIX_DESC"
cols="30"
rows="4"
/>
<field
name="strip-suffix"
type="textarea"
label="PLG_DEBUG_FIELD_STRIP_SUFFIX_LABEL"
description="PLG_DEBUG_FIELD_STRIP_SUFFIX_DESC"
cols="30"
rows="4"
/>
</fieldset>
<fieldset
name="logging"
label="PLG_DEBUG_LOGGING_FIELDSET_LABEL"
>
<field
name="log-deprecated"
type="radio"
label="PLG_DEBUG_FIELD_LOG_DEPRECATED_LABEL"
description="PLG_DEBUG_FIELD_LOG_DEPRECATED_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="log-everything"
type="radio"
label="PLG_DEBUG_FIELD_LOG_EVERYTHING_LABEL"
description="PLG_DEBUG_FIELD_LOG_EVERYTHING_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="log-executed-sql"
type="radio"
label="PLG_DEBUG_FIELD_EXECUTEDSQL_LABEL"
description="PLG_DEBUG_FIELD_EXECUTEDSQL_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
system/fields/fields.php000064400000031375147357022250011335
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.Fields
*
* @copyright (C) 2016 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Form\Form;
use Joomla\Registry\Registry;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Multilanguage;
JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR .
'/components/com_fields/helpers/fields.php');
/**
* Fields Plugin
*
* @since 3.7
*/
class PlgSystemFields extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.7.0
*/
protected $autoloadLanguage = true;
/**
* Normalizes the request data.
*
* @param string $context The context
* @param object $data The object
* @param Form $form The form
*
* @return void
*
* @since 3.8.7
*/
public function onContentNormaliseRequestData($context, $data, Form $form)
{
if (!FieldsHelper::extract($context, $data))
{
return true;
}
// Loop over all fields
foreach ($form->getGroup('com_fields') as $field)
{
if ($field->disabled === true)
{
/**
* Disabled fields should NEVER be added to the request as
* they should NEVER be added by the browser anyway so nothing to check
against
* as "disabled" means no interaction at all.
*/
// Make sure the data object has an entry before delete it
if (isset($data->com_fields[$field->fieldname]))
{
unset($data->com_fields[$field->fieldname]);
}
continue;
}
// Make sure the data object has an entry
if (isset($data->com_fields[$field->fieldname]))
{
continue;
}
// Set a default value for the field
$data->com_fields[$field->fieldname] = false;
}
}
/**
* The save event.
*
* @param string $context The context
* @param JTable $item The table
* @param boolean $isNew Is new item
* @param array $data The validated data
*
* @return boolean
*
* @since 3.7.0
*/
public function onContentAfterSave($context, $item, $isNew, $data =
array())
{
// Check if data is an array and the item has an id
if (!is_array($data) || empty($item->id) ||
empty($data['com_fields']))
{
return true;
}
// Create correct context for category
if ($context == 'com_categories.category')
{
$context = $item->extension . '.categories';
// Set the catid on the category to get only the fields which belong to
this category
$item->catid = $item->id;
}
// Check the context
$parts = FieldsHelper::extract($context, $item);
if (!$parts)
{
return true;
}
// Compile the right context for the fields
$context = $parts[0] . '.' . $parts[1];
// Loading the fields
$fields = FieldsHelper::getFields($context, $item);
if (!$fields)
{
return true;
}
// Loading the model
$model = JModelLegacy::getInstance('Field',
'FieldsModel', array('ignore_request' => true));
// Loop over the fields
foreach ($fields as $field)
{
// Determine the value if it is (un)available from the data
if (key_exists($field->name, $data['com_fields']))
{
$value = $data['com_fields'][$field->name] === false ?
null : $data['com_fields'][$field->name];
}
// Field not available on form, use stored value
else
{
$value = $field->rawvalue;
}
// If no value set (empty) remove value from database
if (is_array($value) ? !count($value) : !strlen($value))
{
$value = null;
}
// JSON encode value for complex fields
if (is_array($value) && (count($value, COUNT_NORMAL) !==
count($value, COUNT_RECURSIVE) || !count(array_filter(array_keys($value),
'is_numeric'))))
{
$value = json_encode($value);
}
// Setting the value for the field and the item
$model->setFieldValue($field->id, $item->id, $value);
}
return true;
}
/**
* The save event.
*
* @param array $userData The date
* @param boolean $isNew Is new
* @param boolean $success Is success
* @param string $msg The message
*
* @return boolean
*
* @since 3.7.0
*/
public function onUserAfterSave($userData, $isNew, $success, $msg)
{
// It is not possible to manipulate the user during save events
// Check if data is valid or we are in a recursion
if (!$userData['id'] || !$success)
{
return true;
}
$user = JFactory::getUser($userData['id']);
$task =
JFactory::getApplication()->input->getCmd('task');
// Skip fields save when we activate a user, because we will lose the
saved data
if (in_array($task, array('activate', 'block',
'unblock')))
{
return true;
}
// Trigger the events with a real user
$this->onContentAfterSave('com_users.user', $user, false,
$userData);
return true;
}
/**
* The delete event.
*
* @param string $context The context
* @param stdClass $item The item
*
* @return boolean
*
* @since 3.7.0
*/
public function onContentAfterDelete($context, $item)
{
$parts = FieldsHelper::extract($context, $item);
if (!$parts || empty($item->id))
{
return true;
}
$context = $parts[0] . '.' . $parts[1];
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_fields/models', 'FieldsModel');
$model = JModelLegacy::getInstance('Field',
'FieldsModel', array('ignore_request' => true));
$model->cleanupValues($context, $item->id);
return true;
}
/**
* The user delete event.
*
* @param stdClass $user The context
* @param boolean $succes Is success
* @param string $msg The message
*
* @return boolean
*
* @since 3.7.0
*/
public function onUserAfterDelete($user, $succes, $msg)
{
$item = new stdClass;
$item->id = $user['id'];
return $this->onContentAfterDelete('com_users.user', $item);
}
/**
* The form event.
*
* @param JForm $form The form
* @param stdClass $data The data
*
* @return boolean
*
* @since 3.7.0
*/
public function onContentPrepareForm(JForm $form, $data)
{
$context = $form->getName();
// When a category is edited, the context is
com_categories.categorycom_content
if (strpos($context, 'com_categories.category') === 0)
{
$context = str_replace('com_categories.category',
'', $context) . '.categories';
// Set the catid on the category to get only the fields which belong to
this category
if (is_array($data) && key_exists('id', $data))
{
$data['catid'] = $data['id'];
}
if (is_object($data) && isset($data->id))
{
$data->catid = $data->id;
}
}
$parts = FieldsHelper::extract($context, $form);
if (!$parts)
{
return true;
}
$input = JFactory::getApplication()->input;
// If we are on the save command we need the actual data
$jformData = $input->get('jform', array(),
'array');
if ($jformData && !$data)
{
$data = $jformData;
}
if (is_array($data))
{
$data = (object) $data;
}
FieldsHelper::prepareForm($parts[0] . '.' . $parts[1], $form,
$data);
return true;
}
/**
* The display event.
*
* @param string $context The context
* @param stdClass $item The item
* @param Registry $params The params
* @param integer $limitstart The start
*
* @return string
*
* @since 3.7.0
*/
public function onContentAfterTitle($context, $item, $params, $limitstart
= 0)
{
return $this->display($context, $item, $params, 1);
}
/**
* The display event.
*
* @param string $context The context
* @param stdClass $item The item
* @param Registry $params The params
* @param integer $limitstart The start
*
* @return string
*
* @since 3.7.0
*/
public function onContentBeforeDisplay($context, $item, $params,
$limitstart = 0)
{
return $this->display($context, $item, $params, 2);
}
/**
* The display event.
*
* @param string $context The context
* @param stdClass $item The item
* @param Registry $params The params
* @param integer $limitstart The start
*
* @return string
*
* @since 3.7.0
*/
public function onContentAfterDisplay($context, $item, $params,
$limitstart = 0)
{
return $this->display($context, $item, $params, 3);
}
/**
* Performs the display event.
*
* @param string $context The context
* @param stdClass $item The item
* @param Registry $params The params
* @param integer $displayType The type
*
* @return string
*
* @since 3.7.0
*/
private function display($context, $item, $params, $displayType)
{
$parts = FieldsHelper::extract($context, $item);
if (!$parts)
{
return '';
}
// If we have a category, set the catid field to fetch only the fields
which belong to it
if ($parts[1] == 'categories' &&
!isset($item->catid))
{
$item->catid = $item->id;
}
$context = $parts[0] . '.' . $parts[1];
// Convert tags
if ($context == 'com_tags.tag' &&
!empty($item->type_alias))
{
// Set the context
$context = $item->type_alias;
$item = $this->prepareTagItem($item);
}
if (is_string($params) || !$params)
{
$params = new Registry($params);
}
$fields = FieldsHelper::getFields($context, $item, $displayType);
if ($fields)
{
$app = Factory::getApplication();
if ($app->isClient('site') &&
Multilanguage::isEnabled() && isset($item->language) &&
$item->language == '*')
{
$lang = $app->getLanguage()->getTag();
foreach ($fields as $key => $field)
{
if ($field->language == '*' || $field->language ==
$lang)
{
continue;
}
unset($fields[$key]);
}
}
}
if ($fields)
{
foreach ($fields as $key => $field)
{
$fieldDisplayType = $field->params->get('display',
'2');
if ($fieldDisplayType == $displayType)
{
continue;
}
unset($fields[$key]);
}
}
if ($fields)
{
return FieldsHelper::render(
$context,
'fields.render',
array(
'item' => $item,
'context' => $context,
'fields' => $fields
)
);
}
return '';
}
/**
* Performs the display event.
*
* @param string $context The context
* @param stdClass $item The item
*
* @return void
*
* @since 3.7.0
*/
public function onContentPrepare($context, $item)
{
// Check property exists (avoid costly & useless recreation), if need
to recreate them, just unset the property!
if (isset($item->jcfields))
{
return;
}
$parts = FieldsHelper::extract($context, $item);
if (!$parts)
{
return;
}
$context = $parts[0] . '.' . $parts[1];
// Convert tags
if ($context == 'com_tags.tag' &&
!empty($item->type_alias))
{
// Set the context
$context = $item->type_alias;
$item = $this->prepareTagItem($item);
}
// Get item's fields, also preparing their value property for manual
display
// (calling plugins events and loading layouts to get their HTML display)
$fields = FieldsHelper::getFields($context, $item, true);
// Adding the fields to the object
$item->jcfields = array();
foreach ($fields as $key => $field)
{
$item->jcfields[$field->id] = $field;
}
}
/**
* The finder event.
*
* @param stdClass $item The item
*
* @return boolean
*
* @since 3.7.0
*/
public function onPrepareFinderContent($item)
{
$section = strtolower($item->layout);
$tax = $item->getTaxonomy('Type');
if ($tax)
{
foreach ($tax as $context => $value)
{
// This is only a guess, needs to be improved
$component = strtolower($context);
if (strpos($context, 'com_') !== 0)
{
$component = 'com_' . $component;
}
// Transform com_article to com_content
if ($component === 'com_article')
{
$component = 'com_content';
}
// Create a dummy object with the required fields
$tmp = new stdClass;
$tmp->id = $item->__get('id');
if ($item->__get('catid'))
{
$tmp->catid = $item->__get('catid');
}
// Getting the fields for the constructed context
$fields = FieldsHelper::getFields($component . '.' .
$section, $tmp, true);
if (is_array($fields))
{
foreach ($fields as $field)
{
// Adding the instructions how to handle the text
$item->addInstruction(FinderIndexer::TEXT_CONTEXT,
$field->name);
// Adding the field value as a field
$item->{$field->name} = $field->value;
}
}
}
}
return true;
}
/**
* Prepares a tag item to be ready for com_fields.
*
* @param stdClass $item The item
*
* @return object
*
* @since 3.8.4
*/
private function prepareTagItem($item)
{
// Map core fields
$item->id = $item->content_item_id;
$item->language = $item->core_language;
// Also handle the catid
if (!empty($item->core_catid))
{
$item->catid = $item->core_catid;
}
return $item;
}
}
system/fields/fields.xml000064400000001406147357022250011336
0ustar00<?xml version="1.0" encoding="utf-8" ?>
<extension type="plugin" version="3.7.0"
group="system" method="upgrade">
<name>plg_system_fields</name>
<author>Joomla! Project</author>
<creationDate>March 2016</creationDate>
<copyright>(C) 2016 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_SYSTEM_FIELDS_XML_DESCRIPTION</description>
<files>
<filename plugin="fields">fields.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_fields.ini</language>
<language
tag="en-GB">en-GB.plg_system_fields.sys.ini</language>
</languages>
</extension>
system/highlight/highlight.php000064400000004074147357022250012533
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.Highlight
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* System plugin to highlight terms.
*
* @since 2.5
*/
class PlgSystemHighlight extends JPlugin
{
/**
* Method to catch the onAfterDispatch event.
*
* This is where we setup the click-through content highlighting for.
* The highlighting is done with JavaScript so we just
* need to check a few parameters and the JHtml behavior will do the rest.
*
* @return boolean True on success
*
* @since 2.5
*/
public function onAfterDispatch()
{
// Check that we are in the site application.
if (JFactory::getApplication()->isClient('administrator'))
{
return true;
}
// Set the variables.
$input = JFactory::getApplication()->input;
$extension = $input->get('option', '',
'cmd');
// Check if the highlighter is enabled.
if
(!JComponentHelper::getParams($extension)->get('highlight_terms',
1))
{
return true;
}
// Check if the highlighter should be activated in this environment.
if ($input->get('tmpl', '', 'cmd') ===
'component' || JFactory::getDocument()->getType() !==
'html')
{
return true;
}
// Get the terms to highlight from the request.
$terms = $input->request->get('highlight', null,
'base64');
$terms = $terms ? json_decode(base64_decode($terms)) : null;
// Check the terms.
if (empty($terms))
{
return true;
}
// Clean the terms array.
$filter = JFilterInput::getInstance();
$cleanTerms = array();
foreach ($terms as $term)
{
$cleanTerms[] = htmlspecialchars($filter->clean($term,
'string'));
}
// Activate the highlighter.
JHtml::_('behavior.highlighter', $cleanTerms);
// Adjust the component buffer.
$doc = JFactory::getDocument();
$buf = $doc->getBuffer('component');
$buf = '<br id="highlighter-start" />' . $buf .
'<br id="highlighter-end" />';
$doc->setBuffer($buf, 'component');
return true;
}
}
system/highlight/highlight.xml000064400000001464147357022250012544
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_highlight</name>
<author>Joomla! Project</author>
<creationDate>August 2011</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_SYSTEM_HIGHLIGHT_XML_DESCRIPTION</description>
<files>
<filename
plugin="highlight">highlight.php</filename>
</files>
<languages>
<language
tag="en-GB">language/en-GB/en-GB.plg_system_highlight.ini</language>
<language
tag="en-GB">language/en-GB/en-GB.plg_system_highlight.sys.ini</language>
</languages>
</extension>
system/languagecode/language/en-GB/en-GB.plg_system_languagecode.ini000064400000001641147357022250021446
0ustar00; Joomla! Project
; (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
; License GNU General Public License version 2 or later; see LICENSE.txt
; Note : All ini files need to be saved as UTF-8
PLG_SYSTEM_LANGUAGECODE="System - Language Code"
PLG_SYSTEM_LANGUAGECODE_FIELD_DESC="Changes the language code used for
the <em>%s</em> language."
PLG_SYSTEM_LANGUAGECODE_FIELDSET_DESC="Changes the language code for
the generated HTML document. Example usage: You have installed the fr-FR
language pack and want the Search Engines to recognise the page as aimed at
French-speaking Canada. Add the tag 'fr-CA' to the corresponding
field for 'fr-FR' to resolve this."
PLG_SYSTEM_LANGUAGECODE_FIELDSET_LABEL="Language codes"
PLG_SYSTEM_LANGUAGECODE_XML_DESCRIPTION="Provides the ability to
change the language code in the generated HTML document to improve
SEO.<br />The fields will appear when the plugin is enabled and
saved."
system/languagecode/language/en-GB/en-GB.plg_system_languagecode.sys.ini000064400000000602147357022250022257
0ustar00; Joomla! Project
; (C) 2011 Open Source Matters, Inc. <https://www.joomla.org>
; License GNU General Public License version 2 or later; see LICENSE.txt
; Note : All ini files need to be saved as UTF-8
PLG_SYSTEM_LANGUAGECODE="System - Language Code"
PLG_SYSTEM_LANGUAGECODE_XML_DESCRIPTION="Provides ability to change
the language code in the generated HTML document to improve SEO"
system/languagecode/languagecode.php000064400000010013147357022250013637
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.languagecode
*
* @copyright (C) 2011 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Language Code plugin class.
*
* @since 2.5
*/
class PlgSystemLanguagecode extends JPlugin
{
/**
* Plugin that changes the language code used in the <html /> tag.
*
* @return void
*
* @since 2.5
*/
public function onAfterRender()
{
$app = JFactory::getApplication();
// Use this plugin only in site application.
if ($app->isClient('site'))
{
// Get the response body.
$body = $app->getBody();
// Get the current language code.
$code = JFactory::getDocument()->getLanguage();
// Get the new code.
$new_code = $this->params->get($code);
// Replace the old code by the new code in the <html /> tag.
if ($new_code)
{
// Replace the new code in the HTML document.
$patterns = array(
chr(1) . '(<html.*\s+xml:lang=")(' . $code .
')(".*>)' . chr(1) . 'i',
chr(1) . '(<html.*\s+lang=")(' . $code .
')(".*>)' . chr(1) . 'i',
);
$replace = array(
'${1}' . strtolower($new_code) . '${3}',
'${1}' . strtolower($new_code) . '${3}'
);
}
else
{
$patterns = array();
$replace = array();
}
// Replace codes in <link hreflang="" /> attributes.
preg_match_all(chr(1) .
'(<link.*\s+hreflang=")([0-9a-z\-]*)(".*\s+rel="alternate".*/>)'
. chr(1) . 'i', $body, $matches);
foreach ($matches[2] as $match)
{
$new_code = $this->params->get(strtolower($match));
if ($new_code)
{
$patterns[] = chr(1) . '(<link.*\s+hreflang=")(' .
$match . ')(".*\s+rel="alternate".*/>)' .
chr(1) . 'i';
$replace[] = '${1}' . $new_code . '${3}';
}
}
preg_match_all(chr(1) .
'(<link.*\s+rel="alternate".*\s+hreflang=")([0-9A-Za-z\-]*)(".*/>)'
. chr(1) . 'i', $body, $matches);
foreach ($matches[2] as $match)
{
$new_code = $this->params->get(strtolower($match));
if ($new_code)
{
$patterns[] = chr(1) .
'(<link.*\s+rel="alternate".*\s+hreflang=")(' .
$match . ')(".*/>)' . chr(1) . 'i';
$replace[] = '${1}' . $new_code . '${3}';
}
}
// Replace codes in itemprop content
preg_match_all(chr(1) .
'(<meta.*\s+itemprop="inLanguage".*\s+content=")([0-9A-Za-z\-]*)(".*/>)'
. chr(1) . 'i', $body, $matches);
foreach ($matches[2] as $match)
{
$new_code = $this->params->get(strtolower($match));
if ($new_code)
{
$patterns[] = chr(1) .
'(<meta.*\s+itemprop="inLanguage".*\s+content=")('
. $match . ')(".*/>)' . chr(1) . 'i';
$replace[] = '${1}' . $new_code . '${3}';
}
}
$app->setBody(preg_replace($patterns, $replace, $body));
}
}
/**
* Prepare form.
*
* @param JForm $form The form to be altered.
* @param mixed $data The associated data for the form.
*
* @return boolean
*
* @since 2.5
*/
public function onContentPrepareForm(JForm $form, $data)
{
// Check we are manipulating the languagecode plugin.
if ($form->getName() !== 'com_plugins.plugin' ||
!$form->getField('languagecodeplugin', 'params'))
{
return true;
}
// Get site languages.
if ($languages = JLanguageHelper::getKnownLanguages(JPATH_SITE))
{
// Inject fields into the form.
foreach ($languages as $tag => $language)
{
$form->load('
<form>
<fields name="params">
<fieldset
name="languagecode"
label="PLG_SYSTEM_LANGUAGECODE_FIELDSET_LABEL"
description="PLG_SYSTEM_LANGUAGECODE_FIELDSET_DESC"
>
<field
name="' . strtolower($tag) . '"
type="text"
label="' . $tag . '"
description="' .
htmlspecialchars(JText::sprintf('PLG_SYSTEM_LANGUAGECODE_FIELD_DESC',
$language['name']), ENT_COMPAT, 'UTF-8') . '"
translate_description="false"
translate_label="false"
size="7"
filter="cmd"
/>
</fieldset>
</fields>
</form>
');
}
}
return true;
}
}
system/languagecode/languagecode.xml000064400000001761147357022250013662
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_languagecode</name>
<author>Joomla! Project</author>
<creationDate>November 2011</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_SYSTEM_LANGUAGECODE_XML_DESCRIPTION</description>
<files>
<filename
plugin="languagecode">languagecode.php</filename>
<folder>language</folder>
</files>
<languages>
<language
tag="en-GB">language/en-GB/en-GB.plg_system_languagecode.ini</language>
<language
tag="en-GB">language/en-GB/en-GB.plg_system_languagecode.sys.ini</language>
</languages>
<config>
<fields name="params">
<field
name="languagecodeplugin"
type="hidden"
default="true"
/>
</fields>
</config>
</extension>
system/languagefilter/languagefilter.php000064400000061215147357022250014577
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.languagefilter
*
* @copyright (C) 2010 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
JLoader::register('MenusHelper', JPATH_ADMINISTRATOR .
'/components/com_menus/helpers/menus.php');
/**
* Joomla! Language Filter Plugin.
*
* @since 1.6
*/
class PlgSystemLanguageFilter extends JPlugin
{
/**
* The routing mode.
*
* @var boolean
* @since 2.5
*/
protected $mode_sef;
/**
* Available languages by sef.
*
* @var array
* @since 1.6
*/
protected $sefs;
/**
* Available languages by language codes.
*
* @var array
* @since 2.5
*/
protected $lang_codes;
/**
* The current language code.
*
* @var string
* @since 3.4.2
*/
protected $current_lang;
/**
* The default language code.
*
* @var string
* @since 2.5
*/
protected $default_lang;
/**
* The logged user language code.
*
* @var string
* @since 3.3.1
*/
private $user_lang_code;
/**
* Application object.
*
* @var JApplicationCms
* @since 3.3
*/
protected $app;
/**
* Constructor.
*
* @param object &$subject The object to observe
* @param array $config An optional associative array of
configuration settings.
*
* @since 1.6
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
$this->app = JFactory::getApplication();
// Setup language data.
$this->mode_sef = $this->app->get('sef', 0);
$this->sefs = JLanguageHelper::getLanguages('sef');
$this->lang_codes =
JLanguageHelper::getLanguages('lang_code');
$this->default_lang =
JComponentHelper::getParams('com_languages')->get('site',
'en-GB');
// If language filter plugin is executed in a site page.
if ($this->app->isClient('site'))
{
$levels = JFactory::getUser()->getAuthorisedViewLevels();
foreach ($this->sefs as $sef => $language)
{
// @todo: In Joomla 2.5.4 and earlier access wasn't set. Non
modified Content Languages got 0 as access value
// we also check if frontend language exists and is enabled
if (($language->access && !in_array($language->access,
$levels))
|| (!array_key_exists($language->lang_code,
JLanguageHelper::getInstalledLanguages(0))))
{
unset($this->lang_codes[$language->lang_code],
$this->sefs[$language->sef]);
}
}
}
// If language filter plugin is executed in an admin page (ex: JRoute
site).
else
{
// Set current language to default site language, fallback to en-GB if
there is no content language for the default site language.
$this->current_lang =
isset($this->lang_codes[$this->default_lang]) ?
$this->default_lang : 'en-GB';
foreach ($this->sefs as $sef => $language)
{
if (!array_key_exists($language->lang_code,
JLanguageHelper::getInstalledLanguages(0)))
{
unset($this->lang_codes[$language->lang_code]);
unset($this->sefs[$language->sef]);
}
}
}
}
/**
* After initialise.
*
* @return void
*
* @since 1.6
*/
public function onAfterInitialise()
{
$this->app->item_associations =
$this->params->get('item_associations', 0);
// We need to make sure we are always using the site router, even if the
language plugin is executed in admin app.
$router =
JApplicationCms::getInstance('site')->getRouter('site');
// Attach build rules for language SEF.
$router->attachBuildRule(array($this,
'preprocessBuildRule'), JRouter::PROCESS_BEFORE);
$router->attachBuildRule(array($this, 'buildRule'),
JRouter::PROCESS_DURING);
if ($this->mode_sef)
{
$router->attachBuildRule(array($this,
'postprocessSEFBuildRule'), JRouter::PROCESS_AFTER);
}
else
{
$router->attachBuildRule(array($this,
'postprocessNonSEFBuildRule'), JRouter::PROCESS_AFTER);
}
// Attach parse rules for language SEF.
$router->attachParseRule(array($this, 'parseRule'),
JRouter::PROCESS_DURING);
}
/**
* After route.
*
* @return void
*
* @since 3.4
*/
public function onAfterRoute()
{
// Add custom site name.
if ($this->app->isClient('site') &&
isset($this->lang_codes[$this->current_lang]) &&
$this->lang_codes[$this->current_lang]->sitename)
{
$this->app->set('sitename',
$this->lang_codes[$this->current_lang]->sitename);
}
}
/**
* Add build preprocess rule to router.
*
* @param JRouter &$router JRouter object.
* @param JUri &$uri JUri object.
*
* @return void
*
* @since 3.4
*/
public function preprocessBuildRule(&$router, &$uri)
{
$lang = $uri->getVar('lang', $this->current_lang);
$uri->setVar('lang', $lang);
if (isset($this->sefs[$lang]))
{
$lang = $this->sefs[$lang]->lang_code;
$uri->setVar('lang', $lang);
}
}
/**
* Add build rule to router.
*
* @param JRouter &$router JRouter object.
* @param JUri &$uri JUri object.
*
* @return void
*
* @since 1.6
*/
public function buildRule(&$router, &$uri)
{
$lang = $uri->getVar('lang');
if (isset($this->lang_codes[$lang]))
{
$sef = $this->lang_codes[$lang]->sef;
}
else
{
$sef = $this->lang_codes[$this->current_lang]->sef;
}
if ($this->mode_sef
&& (!$this->params->get('remove_default_prefix',
0)
|| $lang !== $this->default_lang
|| $lang !== $this->current_lang))
{
$uri->setPath($uri->getPath() . '/' . $sef .
'/');
}
}
/**
* postprocess build rule for SEF URLs
*
* @param JRouter &$router JRouter object.
* @param JUri &$uri JUri object.
*
* @return void
*
* @since 3.4
*/
public function postprocessSEFBuildRule(&$router, &$uri)
{
$uri->delVar('lang');
}
/**
* postprocess build rule for non-SEF URLs
*
* @param JRouter &$router JRouter object.
* @param JUri &$uri JUri object.
*
* @return void
*
* @since 3.4
*/
public function postprocessNonSEFBuildRule(&$router, &$uri)
{
$lang = $uri->getVar('lang');
if (isset($this->lang_codes[$lang]))
{
$uri->setVar('lang', $this->lang_codes[$lang]->sef);
}
}
/**
* Add parse rule to router.
*
* @param JRouter &$router JRouter object.
* @param JUri &$uri JUri object.
*
* @return void
*
* @since 1.6
*/
public function parseRule(&$router, &$uri)
{
// Did we find the current and existing language yet?
$found = false;
// Are we in SEF mode or not?
if ($this->mode_sef)
{
$path = $uri->getPath();
$parts = explode('/', $path);
$sef = StringHelper::strtolower($parts[0]);
// Do we have a URL Language Code ?
if (!isset($this->sefs[$sef]))
{
// Check if remove default URL language code is set
if ($this->params->get('remove_default_prefix', 0))
{
if ($parts[0])
{
// We load a default site language page
$lang_code = $this->default_lang;
}
else
{
// We check for an existing language cookie
$lang_code = $this->getLanguageCookie();
}
}
else
{
$lang_code = $this->getLanguageCookie();
}
// No language code. Try using browser settings or default site
language
if (!$lang_code &&
$this->params->get('detect_browser', 0) == 1)
{
$lang_code = JLanguageHelper::detectLanguage();
}
if (!$lang_code)
{
$lang_code = $this->default_lang;
}
if ($lang_code === $this->default_lang &&
$this->params->get('remove_default_prefix', 0))
{
$found = true;
}
}
else
{
// We found our language
$found = true;
$lang_code = $this->sefs[$sef]->lang_code;
// If we found our language, but its the default language and we
don't want a prefix for that, we are on a wrong URL.
// Or we try to change the language back to the default language. We
need a redirect to the proper URL for the default language.
if ($lang_code === $this->default_lang &&
$this->params->get('remove_default_prefix', 0))
{
// Create a cookie.
$this->setLanguageCookie($lang_code);
$found = false;
array_shift($parts);
$path = implode('/', $parts);
}
// We have found our language and the first part of our URL is the
language prefix
if ($found)
{
array_shift($parts);
// Empty parts array when "index.php" is the only part left.
if (count($parts) === 1 && $parts[0] ===
'index.php')
{
$parts = array();
}
$uri->setPath(implode('/', $parts));
}
}
}
// We are not in SEF mode
else
{
$lang_code = $this->getLanguageCookie();
if (!$lang_code &&
$this->params->get('detect_browser', 1))
{
$lang_code = JLanguageHelper::detectLanguage();
}
if (!isset($this->lang_codes[$lang_code]))
{
$lang_code = $this->default_lang;
}
}
$lang = $uri->getVar('lang', $lang_code);
if (isset($this->sefs[$lang]))
{
// We found our language
$found = true;
$lang_code = $this->sefs[$lang]->lang_code;
}
// We are called via POST or the nolangfilter url parameter was set. We
don't care about the language
// and simply set the default language as our current language.
if ($this->app->input->getMethod() === 'POST'
|| $this->app->input->get('nolangfilter', 0) == 1
|| count($this->app->input->post) > 0
|| count($this->app->input->files) > 0)
{
$found = true;
if (!isset($lang_code))
{
$lang_code = $this->getLanguageCookie();
}
if (!$lang_code &&
$this->params->get('detect_browser', 1))
{
$lang_code = JLanguageHelper::detectLanguage();
}
if (!isset($this->lang_codes[$lang_code]))
{
$lang_code = $this->default_lang;
}
}
// We have not found the language and thus need to redirect
if (!$found)
{
// Lets find the default language for this user
if (!isset($lang_code) || !isset($this->lang_codes[$lang_code]))
{
$lang_code = false;
if ($this->params->get('detect_browser', 1))
{
$lang_code = JLanguageHelper::detectLanguage();
if (!isset($this->lang_codes[$lang_code]))
{
$lang_code = false;
}
}
if (!$lang_code)
{
$lang_code = $this->default_lang;
}
}
if ($this->mode_sef)
{
// Use the current language sef or the default one.
if ($lang_code !== $this->default_lang
|| !$this->params->get('remove_default_prefix', 0))
{
$path = $this->lang_codes[$lang_code]->sef . '/' .
$path;
}
$uri->setPath($path);
if (!$this->app->get('sef_rewrite'))
{
$uri->setPath('index.php/' . $uri->getPath());
}
$redirectUri = $uri->base() .
$uri->toString(array('path', 'query',
'fragment'));
}
else
{
$uri->setVar('lang',
$this->lang_codes[$lang_code]->sef);
$redirectUri = $uri->base() . 'index.php?' .
$uri->getQuery();
}
// Set redirect HTTP code to "302 Found".
$redirectHttpCode = 302;
// If selected language is the default language redirect code is
"301 Moved Permanently".
if ($lang_code === $this->default_lang)
{
$redirectHttpCode = 301;
// We cannot cache this redirect in browser. 301 is cachable by default
so we need to force to not cache it in browsers.
$this->app->setHeader('Expires', 'Wed, 17 Aug 2005
00:00:00 GMT', true);
$this->app->setHeader('Last-Modified', gmdate('D,
d M Y H:i:s') . ' GMT', true);
$this->app->setHeader('Cache-Control', 'no-store,
no-cache, must-revalidate, post-check=0, pre-check=0', false);
$this->app->setHeader('Pragma', 'no-cache');
$this->app->sendHeaders();
}
// Redirect to language.
$this->app->redirect($redirectUri, $redirectHttpCode);
}
// We have found our language and now need to set the cookie and the
language value in our system
$array = array('lang' => $lang_code);
$this->current_lang = $lang_code;
// Set the request var.
$this->app->input->set('language', $lang_code);
$this->app->set('language', $lang_code);
$language = JFactory::getLanguage();
if ($language->getTag() !== $lang_code)
{
$language_new = JLanguage::getInstance($lang_code, (bool)
$this->app->get('debug_lang'));
foreach ($language->getPaths() as $extension => $files)
{
if (strpos($extension, 'plg_system') !== false)
{
$extension_name = substr($extension, 11);
$language_new->load($extension, JPATH_ADMINISTRATOR)
|| $language_new->load($extension, JPATH_PLUGINS .
'/system/' . $extension_name);
continue;
}
$language_new->load($extension);
}
JFactory::$language = $language_new;
$this->app->loadLanguage($language_new);
}
// Create a cookie.
if ($this->getLanguageCookie() !== $lang_code)
{
$this->setLanguageCookie($lang_code);
}
return $array;
}
/**
* Reports the privacy related capabilities for this plugin to site
administrators.
*
* @return array
*
* @since 3.9.0
*/
public function onPrivacyCollectAdminCapabilities()
{
$this->loadLanguage();
return array(
JText::_('PLG_SYSTEM_LANGUAGEFILTER') => array(
JText::_('PLG_SYSTEM_LANGUAGEFILTER_PRIVACY_CAPABILITY_LANGUAGE_COOKIE'),
)
);
}
/**
* Before store user method.
*
* Method is called before user data is stored in the database.
*
* @param array $user Holds the old user data.
* @param boolean $isnew True if a new user is stored.
* @param array $new Holds the new user data.
*
* @return void
*
* @since 1.6
*/
public function onUserBeforeSave($user, $isnew, $new)
{
if (array_key_exists('params', $user) &&
$this->params->get('automatic_change', 1) == 1)
{
$registry = new Registry($user['params']);
$this->user_lang_code = $registry->get('language');
if (empty($this->user_lang_code))
{
$this->user_lang_code = $this->current_lang;
}
}
}
/**
* After store user method.
*
* Method is called after user data is stored in the database.
*
* @param array $user Holds the new user data.
* @param boolean $isnew True if a new user is stored.
* @param boolean $success True if user was succesfully stored in the
database.
* @param string $msg Message.
*
* @return void
*
* @since 1.6
*/
public function onUserAfterSave($user, $isnew, $success, $msg)
{
if ($success && array_key_exists('params', $user)
&& $this->params->get('automatic_change', 1) == 1)
{
$registry = new Registry($user['params']);
$lang_code = $registry->get('language');
if (empty($lang_code))
{
$lang_code = $this->current_lang;
}
if ($lang_code === $this->user_lang_code ||
!isset($this->lang_codes[$lang_code]))
{
if ($this->app->isClient('site'))
{
$this->app->setUserState('com_users.edit.profile.redirect',
null);
}
}
else
{
if ($this->app->isClient('site'))
{
$this->app->setUserState('com_users.edit.profile.redirect',
'index.php?Itemid='
. $this->app->getMenu()->getDefault($lang_code)->id .
'&lang=' . $this->lang_codes[$lang_code]->sef
);
// Create a cookie.
$this->setLanguageCookie($lang_code);
}
}
}
}
/**
* Method to handle any login logic and report back to the subject.
*
* @param array $user Holds the user data.
* @param array $options Array holding options (remember,
autoregister, group).
*
* @return boolean True on success.
*
* @since 1.5
*/
public function onUserLogin($user, $options = array())
{
$menu = $this->app->getMenu();
if ($this->app->isClient('site'))
{
if ($this->params->get('automatic_change', 1))
{
$assoc = JLanguageAssociations::isEnabled();
$lang_code = $user['language'];
// If no language is specified for this user, we set it to the site
default language
if (empty($lang_code))
{
$lang_code = $this->default_lang;
}
jimport('joomla.filesystem.folder');
// The language has been deleted/disabled or the related content
language does not exist/has been unpublished
// or the related home page does not exist/has been unpublished
if (!array_key_exists($lang_code, $this->lang_codes)
|| !array_key_exists($lang_code,
JLanguageMultilang::getSiteHomePages())
|| !JFolder::exists(JPATH_SITE . '/language/' . $lang_code))
{
$lang_code = $this->current_lang;
}
// Try to get association from the current active menu item
$active = $menu->getActive();
$foundAssociation = false;
/**
* Looking for associations.
* If the login menu item form contains an internal URL redirection,
* This will override the automatic change to the user preferred site
language.
* In that case we use the redirect as defined in the menu item.
* Otherwise we redirect, when available, to the user preferred site
language.
*/
if ($active &&
!$active->params['login_redirect_url'])
{
if ($assoc)
{
$associations = MenusHelper::getAssociations($active->id);
}
// Retrieves the Itemid from a login form.
$uri = new
JUri($this->app->getUserState('users.login.form.return'));
if ($uri->getVar('Itemid'))
{
// The login form contains a menu item redirection. Try to get
associations from that menu item.
// If any association set to the user preferred site language,
redirect to that page.
if ($assoc)
{
$associations =
MenusHelper::getAssociations($uri->getVar('Itemid'));
}
if (isset($associations[$lang_code]) &&
$menu->getItem($associations[$lang_code]))
{
$associationItemid = $associations[$lang_code];
$this->app->setUserState('users.login.form.return',
'index.php?Itemid=' . $associationItemid);
$foundAssociation = true;
}
}
elseif (isset($associations[$lang_code]) &&
$menu->getItem($associations[$lang_code]))
{
/**
* The login form does not contain a menu item redirection.
* The active menu item has associations.
* We redirect to the user preferred site language associated page.
*/
$associationItemid = $associations[$lang_code];
$this->app->setUserState('users.login.form.return',
'index.php?Itemid=' . $associationItemid);
$foundAssociation = true;
}
elseif ($active->home)
{
// We are on a Home page, we redirect to the user preferred site
language Home page.
$item = $menu->getDefault($lang_code);
if ($item && $item->language !== $active->language
&& $item->language !== '*')
{
$this->app->setUserState('users.login.form.return',
'index.php?Itemid=' . $item->id);
$foundAssociation = true;
}
}
}
if ($foundAssociation && $lang_code !== $this->current_lang)
{
// Change language.
$this->current_lang = $lang_code;
// Create a cookie.
$this->setLanguageCookie($lang_code);
// Change the language code.
JFactory::getLanguage()->setLanguage($lang_code);
}
}
else
{
if
($this->app->getUserState('users.login.form.return'))
{
$this->app->setUserState('users.login.form.return',
JRoute::_($this->app->getUserState('users.login.form.return'),
false));
}
}
}
}
/**
* Method to add alternative meta tags for associated menu items.
*
* @return void
*
* @since 1.7
*/
public function onAfterDispatch()
{
$doc = JFactory::getDocument();
if ($this->app->isClient('site') &&
$this->params->get('alternate_meta', 1) &&
$doc->getType() === 'html')
{
$languages = $this->lang_codes;
$homes = JLanguageMultilang::getSiteHomePages();
$menu = $this->app->getMenu();
$active = $menu->getActive();
$levels =
JFactory::getUser()->getAuthorisedViewLevels();
$remove_default_prefix =
$this->params->get('remove_default_prefix', 0);
$server =
JUri::getInstance()->toString(array('scheme',
'host', 'port'));
$is_home = false;
$currentInternalUrl = 'index.php?' .
http_build_query($this->app->getRouter()->getVars());
if ($active)
{
$active_link = JRoute::_($active->link . '&Itemid=' .
$active->id);
$current_link = JRoute::_($currentInternalUrl);
// Load menu associations
if ($active_link === $current_link)
{
$associations = MenusHelper::getAssociations($active->id);
}
// Check if we are on the home page
$is_home = ($active->home
&& ($active_link === $current_link || $active_link ===
$current_link . 'index.php' || $active_link . '/' ===
$current_link));
}
// Load component associations.
$option = $this->app->input->get('option');
$cName = ucfirst(substr($option, 4)) . 'HelperAssociation';
JLoader::register($cName, JPath::clean(JPATH_SITE .
'/components/' . $option .
'/helpers/association.php'));
if (class_exists($cName) && is_callable(array($cName,
'getAssociations')))
{
$cassociations = call_user_func(array($cName,
'getAssociations'));
}
// For each language...
foreach ($languages as $i => $language)
{
switch (true)
{
// Language without frontend UI || Language without specific home menu
|| Language without authorized access level
case (!array_key_exists($i,
JLanguageHelper::getInstalledLanguages(0))):
case (!isset($homes[$i])):
case (isset($language->access) && $language->access
&& !in_array($language->access, $levels)):
unset($languages[$i]);
break;
// Home page
case ($is_home):
$language->link = JRoute::_('index.php?lang=' .
$language->sef . '&Itemid=' . $homes[$i]->id);
break;
// Current language link
case ($i === $this->current_lang):
$language->link = JRoute::_($currentInternalUrl);
break;
// Component association
case (isset($cassociations[$i])):
$language->link = JRoute::_($cassociations[$i] .
'&lang=' . $language->sef);
break;
// Menu items association
// Heads up! "$item = $menu" here below is an assignment,
*NOT* comparison
case (isset($associations[$i]) && ($item =
$menu->getItem($associations[$i]))):
$language->link = JRoute::_('index.php?Itemid=' .
$item->id . '&lang=' . $language->sef);
break;
// Too bad...
default:
unset($languages[$i]);
}
}
// If there are at least 2 of them, add the rel="alternate"
links to the <head>
if (count($languages) > 1)
{
// Remove the sef from the default language if "Remove URL
Language Code" is on
if ($remove_default_prefix &&
isset($languages[$this->default_lang]))
{
$languages[$this->default_lang]->link
= preg_replace('|/' .
$languages[$this->default_lang]->sef . '/|', '/',
$languages[$this->default_lang]->link, 1);
}
foreach ($languages as $i => $language)
{
$doc->addHeadLink($server . $language->link,
'alternate', 'rel', array('hreflang' =>
$i));
}
// Add x-default language tag
if ($this->params->get('xdefault', 1))
{
$xdefault_language =
$this->params->get('xdefault_language',
$this->default_lang);
$xdefault_language = ($xdefault_language === 'default') ?
$this->default_lang : $xdefault_language;
if (isset($languages[$xdefault_language]))
{
// Use a custom tag because addHeadLink is limited to one URI per tag
$doc->addCustomTag('<link href="' . $server .
$languages[$xdefault_language]->link . '"
rel="alternate" hreflang="x-default" />');
}
}
}
}
}
/**
* Set the language cookie
*
* @param string $languageCode The language code for which we want to
set the cookie
*
* @return void
*
* @since 3.4.2
*/
private function setLanguageCookie($languageCode)
{
// If is set to use language cookie for a year in plugin params, save the
user language in a new cookie.
if ((int) $this->params->get('lang_cookie', 0) === 1)
{
// Create a cookie with one year lifetime.
$this->app->input->cookie->set(
JApplicationHelper::getHash('language'),
$languageCode,
time() + 365 * 86400,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''),
$this->app->isHttpsForced(),
true
);
}
// If not, set the user language in the session (that is already saved in
a cookie).
else
{
JFactory::getSession()->set('plg_system_languagefilter.language',
$languageCode);
}
}
/**
* Get the language cookie
*
* @return string
*
* @since 3.4.2
*/
private function getLanguageCookie()
{
// Is is set to use a year language cookie in plugin params, get the user
language from the cookie.
if ((int) $this->params->get('lang_cookie', 0) === 1)
{
$languageCode =
$this->app->input->cookie->get(JApplicationHelper::getHash('language'));
}
// Else get the user language from the session.
else
{
$languageCode =
JFactory::getSession()->get('plg_system_languagefilter.language');
}
// Let's be sure we got a valid language code. Fallback to null.
if (!array_key_exists($languageCode, $this->lang_codes))
{
$languageCode = null;
}
return $languageCode;
}
}
system/languagefilter/languagefilter.xml000064400000007563147357022250014616
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_languagefilter</name>
<author>Joomla! Project</author>
<creationDate>July 2010</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_SYSTEM_LANGUAGEFILTER_XML_DESCRIPTION</description>
<files>
<filename
plugin="languagefilter">languagefilter.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_languagefilter.ini</language>
<language
tag="en-GB">en-GB.plg_system_languagefilter.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="detect_browser"
type="list"
label="PLG_SYSTEM_LANGUAGEFILTER_FIELD_DETECT_BROWSER_LABEL"
description="PLG_SYSTEM_LANGUAGEFILTER_FIELD_DETECT_BROWSER_DESC"
default="0"
filter="integer"
>
<option
value="0">PLG_SYSTEM_LANGUAGEFILTER_SITE_LANGUAGE</option>
<option
value="1">PLG_SYSTEM_LANGUAGEFILTER_BROWSER_SETTINGS</option>
</field>
<field
name="automatic_change"
type="radio"
label="PLG_SYSTEM_LANGUAGEFILTER_FIELD_AUTOMATIC_CHANGE_LABEL"
description="PLG_SYSTEM_LANGUAGEFILTER_FIELD_AUTOMATIC_CHANGE_DESC"
default="1"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="item_associations"
type="radio"
label="PLG_SYSTEM_LANGUAGEFILTER_FIELD_ITEM_ASSOCIATIONS_LABEL"
description="PLG_SYSTEM_LANGUAGEFILTER_FIELD_ITEM_ASSOCIATIONS_DESC"
default="1"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="alternate_meta"
type="radio"
label="PLG_SYSTEM_LANGUAGEFILTER_FIELD_ALTERNATE_META_LABEL"
description="PLG_SYSTEM_LANGUAGEFILTER_FIELD_ALTERNATE_META_DESC"
default="1"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="xdefault"
type="radio"
label="PLG_SYSTEM_LANGUAGEFILTER_FIELD_XDEFAULT_LABEL"
description="PLG_SYSTEM_LANGUAGEFILTER_FIELD_XDEFAULT_DESC"
default="1"
filter="integer"
class="btn-group btn-group-yesno"
showon="alternate_meta:1"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="xdefault_language"
type="contentlanguage"
label="PLG_SYSTEM_LANGUAGEFILTER_FIELD_XDEFAULT_LANGUAGE_LABEL"
description="PLG_SYSTEM_LANGUAGEFILTER_FIELD_XDEFAULT_LANGUAGE_DESC"
default="default"
showon="alternate_meta:1[AND]xdefault:1"
>
<option
value="default">PLG_SYSTEM_LANGUAGEFILTER_OPTION_DEFAULT_LANGUAGE</option>
</field>
<field
name="remove_default_prefix"
type="radio"
label="PLG_SYSTEM_LANGUAGEFILTER_FIELD_REMOVE_DEFAULT_PREFIX_LABEL"
description="PLG_SYSTEM_LANGUAGEFILTER_FIELD_REMOVE_DEFAULT_PREFIX_DESC"
default="0"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="lang_cookie"
type="list"
label="PLG_SYSTEM_LANGUAGEFILTER_FIELD_COOKIE_LABEL"
description="PLG_SYSTEM_LANGUAGEFILTER_FIELD_COOKIE_DESC"
default="0"
filter="integer"
>
<option
value="1">PLG_SYSTEM_LANGUAGEFILTER_OPTION_YEAR</option>
<option
value="0">PLG_SYSTEM_LANGUAGEFILTER_OPTION_SESSION</option>
</field>
</fieldset>
</fields>
</config>
</extension>system/log/log.php000064400000003010147357022250010144
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.log
*
* @copyright (C) 2007 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Joomla! System Logging Plugin.
*
* @since 1.5
*/
class PlgSystemLog extends JPlugin
{
/**
* Called if user fails to be logged in.
*
* @param array $response Array of response data.
*
* @return void
*
* @since 1.5
*/
public function onUserLoginFailure($response)
{
$errorlog = array();
switch ($response['status'])
{
case JAuthentication::STATUS_SUCCESS:
$errorlog['status'] = $response['type'] . '
CANCELED: ';
$errorlog['comment'] = $response['error_message'];
break;
case JAuthentication::STATUS_FAILURE:
$errorlog['status'] = $response['type'] . '
FAILURE: ';
if ($this->params->get('log_username', 0))
{
$errorlog['comment'] = $response['error_message']
. ' ("' . $response['username'] .
'")';
}
else
{
$errorlog['comment'] = $response['error_message'];
}
break;
default:
$errorlog['status'] = $response['type'] . '
UNKNOWN ERROR: ';
$errorlog['comment'] = $response['error_message'];
break;
}
JLog::addLogger(array(), JLog::INFO);
try
{
JLog::add($errorlog['comment'], JLog::INFO,
$errorlog['status']);
}
catch (Exception $e)
{
// If the log file is unwriteable during login then we should not go to
the error page
return;
}
}
}
system/log/log.xml000064400000002236147357022250010166 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_log</name>
<author>Joomla! Project</author>
<creationDate>April 2007</creationDate>
<copyright>(C) 2007 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_LOG_XML_DESCRIPTION</description>
<files>
<filename plugin="log">log.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_log.ini</language>
<language
tag="en-GB">en-GB.plg_system_log.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="log_username"
type="radio"
label="PLG_SYSTEM_LOG_FIELD_LOG_USERNAME_LABEL"
description="PLG_SYSTEM_LOG_FIELD_LOG_USERNAME_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
system/logout/logout.php000064400000005302147357022250011432
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.logout
*
* @copyright (C) 2010 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Plugin class for logout redirect handling.
*
* @since 1.6
*/
class PlgSystemLogout extends JPlugin
{
/**
* Application object.
*
* @var JApplicationCms
* @since 3.7.3
*/
protected $app;
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Constructor.
*
* @param object &$subject The object to observe -- event
dispatcher.
* @param object $config An optional associative array of
configuration settings.
*
* @since 1.6
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
// If we are on admin don't process.
if (!$this->app->isClient('site'))
{
return;
}
$hash = JApplicationHelper::getHash('PlgSystemLogout');
if ($this->app->input->cookie->getString($hash))
{
// Destroy the cookie.
$this->app->input->cookie->set($hash, '', 1,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''));
// Set the error handler for E_ALL to be the class handleError method.
JError::setErrorHandling(E_ALL, 'callback',
array('PlgSystemLogout', 'handleError'));
}
}
/**
* Method to handle any logout logic and report back to the subject.
*
* @param array $user Holds the user data.
* @param array $options Array holding options (client, ...).
*
* @return boolean Always returns true.
*
* @since 1.6
*/
public function onUserLogout($user, $options = array())
{
if ($this->app->isClient('site'))
{
// Create the cookie.
$this->app->input->cookie->set(
JApplicationHelper::getHash('PlgSystemLogout'),
true,
time() + 86400,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''),
$this->app->isHttpsForced(),
true
);
}
return true;
}
/**
* Method to handle an error condition.
*
* @param Exception &$error The Exception object to be handled.
*
* @return void
*
* @since 1.6
*/
public static function handleError(&$error)
{
// Get the application object.
$app = JFactory::getApplication();
// Make sure the error is a 403 and we are in the frontend.
if ($error->getCode() == 403 &&
$app->isClient('site'))
{
// Redirect to the home page.
$app->enqueueMessage(JText::_('PLG_SYSTEM_LOGOUT_REDIRECT'));
$app->redirect('index.php');
}
else
{
// Render the custom error page.
JError::customErrorPage($error);
}
}
}
system/logout/logout.xml000064400000001403147357022250011441
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_logout</name>
<author>Joomla! Project</author>
<creationDate>April 2009</creationDate>
<copyright>(C) 2009 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_SYSTEM_LOGOUT_XML_DESCRIPTION</description>
<files>
<filename plugin="logout">logout.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_logout.ini</language>
<language
tag="en-GB">en-GB.plg_system_logout.sys.ini</language>
</languages>
</extension>
system/logrotation/logrotation.php000064400000014202147357022250013511
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.logrotation
*
* @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\Filesystem\File;
use Joomla\Filesystem\Folder;
use Joomla\Filesystem\Path;
/**
* Joomla! Log Rotation plugin
*
* Rotate the log files created by Joomla core
*
* @since 3.9.0
*/
class PlgSystemLogrotation extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.9.0
*/
protected $autoloadLanguage = true;
/**
* Application object.
*
* @var JApplicationCms
* @since 3.9.0
*/
protected $app;
/**
* Database object.
*
* @var JDatabaseDriver
* @since 3.9.0
*/
protected $db;
/**
* The log check and rotation code is triggered after the page has fully
rendered.
*
* @return void
*
* @since 3.9.0
*/
public function onAfterRender()
{
// Get the timeout as configured in plugin parameters
/** @var \Joomla\Registry\Registry $params */
$cache_timeout = (int) $this->params->get('cachetimeout',
30);
$cache_timeout = 24 * 3600 * $cache_timeout;
$logsToKeep = (int) $this->params->get('logstokeep',
1);
// Do we need to run? Compare the last run timestamp stored in the
plugin's options with the current
// timestamp. If the difference is greater than the cache timeout we
shall not execute again.
$now = time();
$last = (int) $this->params->get('lastrun', 0);
if ((abs($now - $last) < $cache_timeout))
{
return;
}
// Update last run status
$this->params->set('lastrun', $now);
$db = $this->db;
$query = $db->getQuery(true)
->update($db->qn('#__extensions'))
->set($db->qn('params') . ' = ' .
$db->q($this->params->toString('JSON')))
->where($db->qn('type') . ' = ' .
$db->q('plugin'))
->where($db->qn('folder') . ' = ' .
$db->q('system'))
->where($db->qn('element') . ' = ' .
$db->q('logrotation'));
try
{
// Lock the tables to prevent multiple plugin executions causing a race
condition
$db->lockTable('#__extensions');
}
catch (Exception $e)
{
// If we can't lock the tables it's too risky to continue
execution
return;
}
try
{
// Update the plugin parameters
$result = $db->setQuery($query)->execute();
$this->clearCacheGroups(array('com_plugins'), array(0, 1));
}
catch (Exception $exc)
{
// If we failed to execute
$db->unlockTables();
$result = false;
}
try
{
// Unlock the tables after writing
$db->unlockTables();
}
catch (Exception $e)
{
// If we can't lock the tables assume we have somehow failed
$result = false;
}
// Abort on failure
if (!$result)
{
return;
}
// Get the log path
$logPath = Path::clean($this->app->get('log_path'));
// Invalid path, stop processing further
if (!is_dir($logPath))
{
return;
}
$logFiles = $this->getLogFiles($logPath);
// Sort log files by version number in reserve order
krsort($logFiles, SORT_NUMERIC);
foreach ($logFiles as $version => $files)
{
if ($version >= $logsToKeep)
{
// Delete files which has version greater than or equals $logsToKeep
foreach ($files as $file)
{
File::delete($logPath . '/' . $file);
}
}
else
{
// For files which has version smaller than $logsToKeep, rotate
(increase version number)
foreach ($files as $file)
{
$this->rotate($logPath, $file, $version);
}
}
}
}
/**
* Get log files from log folder
*
* @param string $path The folder to get log files
*
* @return array The log files in the given path grouped by version
number (not rotated files has number 0)
*
* @since 3.9.0
*/
private function getLogFiles($path)
{
$logFiles = array();
$files = Folder::files($path, '\.php$');
foreach ($files as $file)
{
$parts = explode('.', $file);
/*
* Rotated log file has this filename format [VERSION].[FILENAME].php.
So if $parts has at least 3 elements
* and the first element is a number, we know that it's a rotated
file and can get it's current version
*/
if (count($parts) >= 3 && is_numeric($parts[0]))
{
$version = (int) $parts[0];
}
else
{
$version = 0;
}
if (!isset($logFiles[$version]))
{
$logFiles[$version] = array();
}
$logFiles[$version][] = $file;
}
return $logFiles;
}
/**
* Method to rotate (increase version) of a log file
*
* @param string $path Path to file to rotate
* @param string $filename Name of file to rotate
* @param int $currentVersion The current version number
*
* @return void
*
* @since 3.9.0
*/
private function rotate($path, $filename, $currentVersion)
{
if ($currentVersion === 0)
{
$rotatedFile = $path . '/1.' . $filename;
}
else
{
/*
* Rotated log file has this filename format [VERSION].[FILENAME].php.
To rotate it, we just need to explode
* the filename into an array, increase value of first element (keep
version) and implode it back to get the
* rotated file name
*/
$parts = explode('.', $filename);
$parts[0] = $currentVersion + 1;
$rotatedFile = $path . '/' . implode('.', $parts);
}
File::move($path . '/' . $filename, $rotatedFile);
}
/**
* Clears cache groups. We use it to clear the plugins cache after we
update the last run timestamp.
*
* @param array $clearGroups The cache groups to clean
* @param array $cacheClients The cache clients (site, admin) to clean
*
* @return void
*
* @since 3.9.0
*/
private function clearCacheGroups(array $clearGroups, array $cacheClients
= array(0, 1))
{
$conf = JFactory::getConfig();
foreach ($clearGroups as $group)
{
foreach ($cacheClients as $client_id)
{
try
{
$options = array(
'defaultgroup' => $group,
'cachebase' => $client_id ? JPATH_ADMINISTRATOR .
'/cache' :
$conf->get('cache_path', JPATH_SITE .
'/cache')
);
$cache = JCache::getInstance('callback', $options);
$cache->clean();
}
catch (Exception $e)
{
// Ignore it
}
}
}
}
}
system/logrotation/logrotation.xml000064400000003043147357022250013523
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.9" type="plugin"
group="system" method="upgrade">
<name>plg_system_logrotation</name>
<author>Joomla! Project</author>
<creationDate>May 2018</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_SYSTEM_LOGROTATION_XML_DESCRIPTION</description>
<files>
<filename
plugin="logrotation">logrotation.php</filename>
</files>
<languages folder="language">
<language
tag="en-GB">en-GB.plg_system_logrotation.ini</language>
<language
tag="en-GB">en-GB.plg_system_logrotation.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="cachetimeout"
type="integer"
label="PLG_SYSTEM_LOGROTATION_CACHETIMEOUT_LABEL"
description="PLG_SYSTEM_LOGROTATION_CACHETIMEOUT_DESC"
first="0"
last="120"
step="1"
default="30"
filter="int"
validate="number"
/>
<field
name="logstokeep"
type="integer"
label="PLG_SYSTEM_LOGROTATION_LOGSTOKEEP_LABEL"
description="PLG_SYSTEM_LOGROTATION_LOGSTOKEEP_DESC"
first="1"
last="10"
step="1"
default="1"
filter="int"
validate="number"
/>
<field
name="lastrun"
type="hidden"
default="0"
filter="integer"
/>
</fieldset>
</fields>
</config>
</extension>
system/p3p/p3p.php000064400000001610147357022250010012 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.p3p
*
* @copyright (C) 2010 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Joomla! P3P Header Plugin.
*
* @since 1.6
* @deprecate 4.0 Obsolete
*/
class PlgSystemP3p extends JPlugin
{
/**
* After initialise.
*
* @return void
*
* @since 1.6
* @deprecate 4.0 Obsolete
*/
public function onAfterInitialise()
{
// Get the header.
$header = $this->params->get('header', 'NOI ADM DEV
PSAi COM NAV OUR OTRo STP IND DEM');
$header = trim($header);
// Bail out on empty header (why would anyone do that?!).
if (empty($header))
{
return;
}
// Replace any existing P3P headers in the response.
JFactory::getApplication()->setHeader('P3P',
'CP="' . $header . '"', true);
}
}
system/p3p/p3p.xml000064400000002044147357022250010025 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_p3p</name>
<author>Joomla! Project</author>
<creationDate>September 2010</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_P3P_XML_DESCRIPTION</description>
<files>
<filename plugin="p3p">p3p.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_p3p.ini</language>
<language
tag="en-GB">en-GB.plg_system_p3p.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="header"
type="text"
label="PLG_P3P_HEADER_LABEL"
description="PLG_P3P_HEADER_DESCRIPTION"
default="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
size="37"
/>
</fieldset>
</fields>
</config>
</extension>
system/privacyconsent/field/privacy.php000064400000005223147357022250014421
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.privacyconsent
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
JFormHelper::loadFieldClass('radio');
/**
* Provides input for privacy
*
* @since 3.9.0
*/
class JFormFieldprivacy extends JFormFieldRadio
{
/**
* The form field type.
*
* @var string
* @since 3.9.0
*/
protected $type = 'privacy';
/**
* Method to get the field input markup.
*
* @return string The field input markup.
*
* @since 3.9.0
*/
protected function getInput()
{
// Display the message before the field
echo
$this->getRenderer('plugins.system.privacyconsent.message')->render($this->getLayoutData());
return parent::getInput();
}
/**
* Method to get the field label markup.
*
* @return string The field label markup.
*
* @since 3.9.0
*/
protected function getLabel()
{
if ($this->hidden)
{
return '';
}
return
$this->getRenderer('plugins.system.privacyconsent.label')->render($this->getLayoutData());
}
/**
* Method to get the data to be passed to the layout for rendering.
*
* @return array
*
* @since 3.9.4
*/
protected function getLayoutData()
{
$data = parent::getLayoutData();
$article = false;
$privacyArticle = $this->element['article'] > 0 ? (int)
$this->element['article'] : 0;
if ($privacyArticle &&
Factory::getApplication()->isClient('site'))
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName(array('id', 'alias',
'catid', 'language')))
->from($db->quoteName('#__content'))
->where($db->quoteName('id') . ' = ' . (int)
$privacyArticle);
$db->setQuery($query);
$article = $db->loadObject();
JLoader::register('ContentHelperRoute', JPATH_BASE .
'/components/com_content/helpers/route.php');
$slug = $article->alias ? ($article->id . ':' .
$article->alias) : $article->id;
$article->link = ContentHelperRoute::getArticleRoute($slug,
$article->catid, $article->language);
}
$extraData = array(
'privacynote' =>
!empty($this->element['note']) ?
$this->element['note'] :
Text::_('PLG_SYSTEM_PRIVACYCONSENT_NOTE_FIELD_DEFAULT'),
'options' => $this->getOptions(),
'value' => (string) $this->value,
'translateLabel' => $this->translateLabel,
'translateDescription' => $this->translateDescription,
'translateHint' => $this->translateHint,
'privacyArticle' => $privacyArticle,
'article' => $article,
);
return array_merge($data, $extraData);
}
}
system/privacyconsent/privacyconsent/privacyconsent.xml000064400000001072147357022250020006
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="privacyconsent">
<fieldset
name="privacyconsent"
label="PLG_SYSTEM_PRIVACYCONSENT_LABEL"
>
<field
name="privacy"
type="privacy"
label="PLG_SYSTEM_PRIVACYCONSENT_FIELD_LABEL"
description="PLG_SYSTEM_PRIVACYCONSENT_FIELD_DESC"
default="0"
filter="integer"
required="true"
>
<option
value="1">PLG_SYSTEM_PRIVACYCONSENT_OPTION_AGREE</option>
<option
value="0">PLG_SYSTEM_PRIVACYCONSENT_OPTION_DO_NOT_AGREE</option>
</field>
</fieldset>
</fields>
</form>
system/privacyconsent/privacyconsent.php000064400000046406147357022250014740
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.privacyconsent
*
* @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\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\Utilities\ArrayHelper;
/**
* An example custom privacyconsent plugin.
*
* @since 3.9.0
*/
class PlgSystemPrivacyconsent extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.9.0
*/
protected $autoloadLanguage = true;
/**
* Application object.
*
* @var JApplicationCms
* @since 3.9.0
*/
protected $app;
/**
* Database object.
*
* @var JDatabaseDriver
* @since 3.9.0
*/
protected $db;
/**
* Constructor
*
* @param object &$subject The object to observe
* @param array $config An array that holds the plugin
configuration
*
* @since 3.9.0
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
JFormHelper::addFieldPath(__DIR__ . '/field');
}
/**
* Adds additional fields to the user editing form
*
* @param JForm $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, $data)
{
if (!($form instanceof JForm))
{
$this->_subject->setError('JERROR_NOT_A_FORM');
return false;
}
// Check we are manipulating a valid form - we only display this on user
registration form and user profile form.
$name = $form->getName();
if (!in_array($name, array('com_users.profile',
'com_users.registration')))
{
return true;
}
// We only display this if user has not consented before
if (is_object($data))
{
$userId = isset($data->id) ? $data->id : 0;
if ($userId > 0 && $this->isUserConsented($userId))
{
return true;
}
}
// Add the privacy policy fields to the form.
JForm::addFormPath(__DIR__ . '/privacyconsent');
$form->loadFile('privacyconsent');
$privacyArticleId = $this->getPrivacyArticleId();
$privacynote = $this->params->get('privacy_note');
// Push the privacy article ID into the privacy field.
$form->setFieldAttribute('privacy', 'article',
$privacyArticleId, 'privacyconsent');
$form->setFieldAttribute('privacy', 'note',
$privacynote, 'privacyconsent');
}
/**
* Method is called before user data is stored in the database
*
* @param array $user Holds the old user data.
* @param boolean $isNew True if a new user is stored.
* @param array $data Holds the new user data.
*
* @return boolean
*
* @since 3.9.0
* @throws InvalidArgumentException on missing required data.
*/
public function onUserBeforeSave($user, $isNew, $data)
{
// // Only check for front-end user creation/update profile
if ($this->app->isClient('administrator'))
{
return true;
}
$userId = ArrayHelper::getValue($user, 'id', 0,
'int');
// User already consented before, no need to check it further
if ($userId > 0 && $this->isUserConsented($userId))
{
return true;
}
// Check that the privacy is checked if required ie only in registration
from frontend.
$option = $this->app->input->getCmd('option');
$task = $this->app->input->get->getCmd('task');
$form = $this->app->input->post->get('jform',
array(), 'array');
if ($option == 'com_users' && in_array($task,
array('registration.register', 'profile.save'))
&&
empty($form['privacyconsent']['privacy']))
{
throw new
InvalidArgumentException(Text::_('PLG_SYSTEM_PRIVACYCONSENT_FIELD_ERROR'));
}
return true;
}
/**
* Saves user privacy confirmation
*
* @param array $data entered user data
* @param boolean $isNew true if this is a new user
* @param boolean $result true if saving the user worked
* @param string $error error message
*
* @return boolean
*
* @since 3.9.0
*/
public function onUserAfterSave($data, $isNew, $result, $error)
{
// Only create an entry on front-end user creation/update profile
if ($this->app->isClient('administrator'))
{
return true;
}
// Get the user's ID
$userId = ArrayHelper::getValue($data, 'id', 0,
'int');
// If user already consented before, no need to check it further
if ($userId > 0 && $this->isUserConsented($userId))
{
return true;
}
$option = $this->app->input->getCmd('option');
$task = $this->app->input->get->getCmd('task');
$form = $this->app->input->post->get('jform',
array(), 'array');
if ($option == 'com_users'
&&in_array($task, array('registration.register',
'profile.save'))
&&
!empty($form['privacyconsent']['privacy']))
{
$userId = ArrayHelper::getValue($data, 'id', 0,
'int');
// Get the user's IP address
$ip =
$this->app->input->server->get('REMOTE_ADDR',
'', 'string');
// Get the user agent string
$userAgent =
$this->app->input->server->get('HTTP_USER_AGENT',
'', 'string');
// Create the user note
$userNote = (object) array(
'user_id' => $userId,
'subject' =>
'PLG_SYSTEM_PRIVACYCONSENT_SUBJECT',
'body' =>
Text::sprintf('PLG_SYSTEM_PRIVACYCONSENT_BODY', $ip, $userAgent),
'created' => Factory::getDate()->toSql(),
);
try
{
$this->db->insertObject('#__privacy_consents',
$userNote);
}
catch (Exception $e)
{
// Do nothing if the save fails
}
$userId = ArrayHelper::getValue($data, 'id', 0,
'int');
$message = array(
'action' => 'consent',
'id' => $userId,
'title' => $data['name'],
'itemlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$userId,
'userid' => $userId,
'username' => $data['username'],
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$userId,
);
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_actionlogs/models',
'ActionlogsModel');
/* @var ActionlogsModelActionlog $model */
$model = JModelLegacy::getInstance('Actionlog',
'ActionlogsModel');
$model->addLog(array($message),
'PLG_SYSTEM_PRIVACYCONSENT_CONSENT',
'plg_system_privacyconsent', $userId);
}
return true;
}
/**
* Remove all user privacy consent information for the given user ID
*
* Method is called after user data is deleted from the database
*
* @param array $user Holds the user data
* @param boolean $success True if user was successfully stored in the
database
* @param string $msg Message
*
* @return boolean
*
* @since 3.9.0
*/
public function onUserAfterDelete($user, $success, $msg)
{
if (!$success)
{
return false;
}
$userId = ArrayHelper::getValue($user, 'id', 0,
'int');
if ($userId)
{
// Remove user's consent
try
{
$query = $this->db->getQuery(true)
->delete($this->db->quoteName('#__privacy_consents'))
->where($this->db->quoteName('user_id') . ' =
' . (int) $userId);
$this->db->setQuery($query);
$this->db->execute();
}
catch (Exception $e)
{
$this->_subject->setError($e->getMessage());
return false;
}
}
return true;
}
/**
* If logged in users haven't agreed to privacy consent, redirect
them to profile edit page, ask them to agree to
* privacy consent before allowing access to any other pages
*
* @return void
*
* @since 3.9.0
*/
public function onAfterRoute()
{
// Run this in frontend only
if ($this->app->isClient('administrator'))
{
return;
}
$userId = Factory::getUser()->id;
// Check to see whether user already consented, if not, redirect to user
profile page
if ($userId > 0)
{
// If user consented before, no need to check it further
if ($this->isUserConsented($userId))
{
return;
}
$option = $this->app->input->getCmd('option');
$task = $this->app->input->get('task');
$view = $this->app->input->getString('view',
'');
$layout = $this->app->input->getString('layout',
'');
$id = $this->app->input->getInt('id');
$privacyArticleId = $this->getPrivacyArticleId();
/*
* If user is already on edit profile screen or view privacy article
* or press update/apply button, or logout, do nothing to avoid infinite
redirect
*/
if ($option == 'com_users' && in_array($task,
array('profile.save', 'profile.apply',
'user.logout', 'user.menulogout'))
|| ($option == 'com_content' && $view ==
'article' && $id == $privacyArticleId)
|| ($option == 'com_users' && $view ==
'profile' && $layout == 'edit'))
{
return;
}
// Redirect to com_users profile edit
$this->app->enqueueMessage($this->getRedirectMessage(),
'notice');
$link =
'index.php?option=com_users&view=profile&layout=edit';
$this->app->redirect(\JRoute::_($link, false));
}
}
/**
* Event to specify whether a privacy policy has been published.
*
* @param array &$policy The privacy policy status data, passed by
reference, with keys "published", "editLink" and
"articlePublished".
*
* @return void
*
* @since 3.9.0
*/
public function onPrivacyCheckPrivacyPolicyPublished(&$policy)
{
// If another plugin has already indicated a policy is published, we
won't change anything here
if ($policy['published'])
{
return;
}
$articleId = $this->params->get('privacy_article');
if (!$articleId)
{
return;
}
// Check if the article exists in database and is published
$query = $this->db->getQuery(true)
->select($this->db->quoteName(array('id',
'state')))
->from($this->db->quoteName('#__content'))
->where($this->db->quoteName('id') . ' = '
. (int) $articleId);
$this->db->setQuery($query);
$article = $this->db->loadObject();
// Check if the article exists
if (!$article)
{
return;
}
// Check if the article is published
if ($article->state == 1)
{
$policy['articlePublished'] = true;
}
$policy['published'] = true;
$policy['editLink'] =
JRoute::_('index.php?option=com_content&task=article.edit&id='
. $articleId);
}
/**
* Returns the configured redirect message and falls back to the default
version.
*
* @return string redirect message
*
* @since 3.9.0
*/
private function getRedirectMessage()
{
$messageOnRedirect =
trim($this->params->get('messageOnRedirect',
''));
if (empty($messageOnRedirect))
{
return
Text::_('PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_DEFAULT');
}
return $messageOnRedirect;
}
/**
* Method to check if the given user has consented yet
*
* @param integer $userId ID of uer to check
*
* @return boolean
*
* @since 3.9.0
*/
private function isUserConsented($userId)
{
$query = $this->db->getQuery(true);
$query->select('COUNT(*)')
->from('#__privacy_consents')
->where('user_id = ' . (int) $userId)
->where('subject = ' .
$this->db->quote('PLG_SYSTEM_PRIVACYCONSENT_SUBJECT'))
->where('state = 1');
$this->db->setQuery($query);
return (int) $this->db->loadResult() > 0;
}
/**
* Get privacy article ID. If the site is a multilingual website and there
is associated article for the
* current language, ID of the associated article will be returned
*
* @return integer
*
* @since 3.9.0
*/
private function getPrivacyArticleId()
{
$privacyArticleId =
$this->params->get('privacy_article');
if ($privacyArticleId > 0 &&
JLanguageAssociations::isEnabled())
{
$privacyAssociated =
JLanguageAssociations::getAssociations('com_content',
'#__content', 'com_content.item', $privacyArticleId);
$currentLang = JFactory::getLanguage()->getTag();
if (isset($privacyAssociated[$currentLang]))
{
$privacyArticleId = $privacyAssociated[$currentLang]->id;
}
}
return $privacyArticleId;
}
/**
* The privacy consent expiration check code is triggered after the page
has fully rendered.
*
* @return void
*
* @since 3.9.0
*/
public function onAfterRender()
{
if (!$this->params->get('enabled', 0))
{
return;
}
$cacheTimeout = (int) $this->params->get('cachetimeout',
30);
$cacheTimeout = 24 * 3600 * $cacheTimeout;
// Do we need to run? Compare the last run timestamp stored in the
plugin's options with the current
// timestamp. If the difference is greater than the cache timeout we
shall not execute again.
$now = time();
$last = (int) $this->params->get('lastrun', 0);
if ((abs($now - $last) < $cacheTimeout))
{
return;
}
// Update last run status
$this->params->set('lastrun', $now);
$db = $this->db;
$query = $db->getQuery(true)
->update($db->quoteName('#__extensions'))
->set($db->quoteName('params') . ' = ' .
$db->quote($this->params->toString('JSON')))
->where($db->quoteName('type') . ' = ' .
$db->quote('plugin'))
->where($db->quoteName('folder') . ' = ' .
$db->quote('system'))
->where($db->quoteName('element') . ' = ' .
$db->quote('privacyconsent'));
try
{
// Lock the tables to prevent multiple plugin executions causing a race
condition
$db->lockTable('#__extensions');
}
catch (Exception $e)
{
// If we can't lock the tables it's too risky to continue
execution
return;
}
try
{
// Update the plugin parameters
$result = $db->setQuery($query)->execute();
$this->clearCacheGroups(array('com_plugins'), array(0, 1));
}
catch (Exception $exc)
{
// If we failed to execute
$db->unlockTables();
$result = false;
}
try
{
// Unlock the tables after writing
$db->unlockTables();
}
catch (Exception $e)
{
// If we can't lock the tables assume we have somehow failed
$result = false;
}
// Abort on failure
if (!$result)
{
return;
}
// Delete the expired privacy consents
$this->invalidateExpiredConsents();
// Remind for privacy consents near to expire
$this->remindExpiringConsents();
}
/**
* Method to send the remind for privacy consents renew
*
* @return integer
*
* @since 3.9.0
*/
private function remindExpiringConsents()
{
// Load the parameters.
$expire = (int) $this->params->get('consentexpiration',
365);
$remind = (int) $this->params->get('remind', 30);
$now = JFactory::getDate()->toSql();
$period = '-' . ($expire - $remind);
$db = $this->db;
$query = $db->getQuery(true)
->select($db->quoteName(array('r.id',
'r.user_id', 'u.email')))
->from($db->quoteName('#__privacy_consents',
'r'))
->leftJoin($db->quoteName('#__users', 'u') .
' ON u.id = r.user_id')
->where($db->quoteName('subject') . ' = ' .
$db->quote('PLG_SYSTEM_PRIVACYCONSENT_SUBJECT'))
->where($db->quoteName('remind') . ' = 0');
$query->where($query->dateAdd($db->quote($now), $period,
'DAY') . ' > ' .
$db->quoteName('created'));
try
{
$users = $db->setQuery($query)->loadObjectList();
}
catch (JDatabaseException $exception)
{
return false;
}
$app = JFactory::getApplication();
$linkMode = $app->get('force_ssl', 0) == 2 ?
Route::TLS_FORCE : Route::TLS_IGNORE;
foreach ($users as $user)
{
$token =
JApplicationHelper::getHash(JUserHelper::genRandomPassword());
$hashedToken = JUserHelper::hashPassword($token);
// The mail
try
{
$substitutions = array(
'[SITENAME]' => $app->get('sitename'),
'[URL]' => JUri::root(),
'[TOKENURL]' => JRoute::link('site',
'index.php?option=com_privacy&view=remind&remind_token='
. $token, false, $linkMode, true),
'[FORMURL]' => JRoute::link('site',
'index.php?option=com_privacy&view=remind', false, $linkMode,
true),
'[TOKEN]' => $token,
'\\n' => "\n",
);
$emailSubject =
JText::_('PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT');
$emailBody =
JText::_('PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_BODY');
foreach ($substitutions as $k => $v)
{
$emailSubject = str_replace($k, $v, $emailSubject);
$emailBody = str_replace($k, $v, $emailBody);
}
$mailer = JFactory::getMailer();
$mailer->setSubject($emailSubject);
$mailer->setBody($emailBody);
$mailer->addRecipient($user->email);
$mailResult = $mailer->Send();
if ($mailResult instanceof JException)
{
return false;
}
elseif ($mailResult === false)
{
return false;
}
// Update the privacy_consents item to not send the reminder again
$query->clear()
->update($db->quoteName('#__privacy_consents'))
->set($db->quoteName('remind') . ' = 1 ')
->set($db->quoteName('token') . ' = ' .
$db->quote($hashedToken))
->where($db->quoteName('id') . ' = ' . (int)
$user->id);
$db->setQuery($query);
try
{
$db->execute();
}
catch (RuntimeException $e)
{
return false;
}
}
catch (phpmailerException $exception)
{
return false;
}
}
}
/**
* Method to delete the expired privacy consents
*
* @return boolean
*
* @since 3.9.0
*/
private function invalidateExpiredConsents()
{
// Load the parameters.
$expire = (int) $this->params->get('consentexpiration',
365);
$now = JFactory::getDate()->toSql();
$period = '-' . $expire;
$db = $this->db;
$query = $db->getQuery(true);
$query->select($db->quoteName(array('id',
'user_id')))
->from($db->quoteName('#__privacy_consents'))
->where($query->dateAdd($db->quote($now), $period,
'DAY') . ' > ' .
$db->quoteName('created'))
->where($db->quoteName('subject') . ' = ' .
$db->quote('PLG_SYSTEM_PRIVACYCONSENT_SUBJECT'))
->where($db->quoteName('state') . ' = 1');
$db->setQuery($query);
try
{
$users = $db->loadObjectList();
}
catch (RuntimeException $e)
{
return false;
}
// Do not process further if no expired consents found
if (empty($users))
{
return true;
}
// Push a notification to the site's super users
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_messages/models', 'MessagesModel');
JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_messages/tables');
/** @var MessagesModelMessage $messageModel */
$messageModel = JModelLegacy::getInstance('Message',
'MessagesModel');
foreach ($users as $user)
{
$query = $db->getQuery(true)
->update($db->quoteName('#__privacy_consents'))
->set('state = 0')
->where($db->quoteName('id') . ' = ' . (int)
$user->id);
$db->setQuery($query);
try
{
$db->execute();
}
catch (RuntimeException $e)
{
return false;
}
$messageModel->notifySuperUsers(
JText::_('PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_SUBJECT'),
JText::sprintf('PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_MESSAGE',
JFactory::getUser($user->user_id)->username)
);
}
return true;
}
/**
* Clears cache groups. We use it to clear the plugins cache after we
update the last run timestamp.
*
* @param array $clearGroups The cache groups to clean
* @param array $cacheClients The cache clients (site, admin) to clean
*
* @return void
*
* @since 3.9.0
*/
private function clearCacheGroups(array $clearGroups, array $cacheClients
= array(0, 1))
{
$conf = JFactory::getConfig();
foreach ($clearGroups as $group)
{
foreach ($cacheClients as $client_id)
{
try
{
$options = array(
'defaultgroup' => $group,
'cachebase' => $client_id ? JPATH_ADMINISTRATOR .
'/cache' :
$conf->get('cache_path', JPATH_SITE .
'/cache')
);
$cache = JCache::getInstance('callback', $options);
$cache->clean();
}
catch (Exception $e)
{
// Ignore it
}
}
}
}
}
system/privacyconsent/privacyconsent.xml000064400000006512147357022250014743
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.9" type="plugin"
group="system" method="upgrade">
<name>plg_system_privacyconsent</name>
<author>Joomla! Project</author>
<creationDate>April 2018</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_SYSTEM_PRIVACYCONSENT_XML_DESCRIPTION</description>
<files>
<filename
plugin="privacyconsent">privacyconsent.php</filename>
<folder>privacyconsent</folder>
<folder>field</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_privacyconsent.ini</language>
<language
tag="en-GB">en-GB.plg_system_privacyconsent.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic"
addfieldpath="/administrator/components/com_content/models/fields">
<field
name="privacy_note"
type="textarea"
label="PLG_SYSTEM_PRIVACYCONSENT_NOTE_FIELD_LABEL"
description="PLG_SYSTEM_PRIVACYCONSENT_NOTE_FIELD_DESC"
hint="PLG_SYSTEM_PRIVACYCONSENT_NOTE_FIELD_DEFAULT"
class="span12"
rows="7"
cols="20"
filter="html"
/>
<field
name="privacy_article"
type="modal_article"
label="PLG_SYSTEM_PRIVACYCONSENT_FIELD_ARTICLE_LABEL"
description="PLG_SYSTEM_PRIVACYCONSENT_FIELD_ARTICLE_DESC"
select="true"
new="true"
edit="true"
clear="true"
filter="integer"
/>
<field
name="messageOnRedirect"
type="textarea"
label="PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_LABEL"
description="PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_DESC"
hint="PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_DEFAULT"
class="span12"
rows="7"
cols="20"
filter="html"
/>
</fieldset>
<fieldset
name="expiration"
label="PLG_SYSTEM_PRIVACYCONSENT_EXPIRATION_FIELDSET_LABEL"
>
<field
name="enabled"
type="radio"
label="PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_LABEL"
description="PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="cachetimeout"
type="integer"
label="PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_LABEL"
description="PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_DESC"
first="0"
last="120"
step="1"
default="30"
filter="int"
validate="number"
/>
<field
name="consentexpiration"
type="integer"
label="PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_LABEL"
description="PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_DESC"
first="180"
last="720"
step="30"
default="360"
filter="int"
validate="number"
/>
<field
name="remind"
type="integer"
label="PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_LABEL"
description="PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_DESC"
first="0"
last="120"
step="1"
default="30"
filter="int"
validate="number"
/>
<field
name="lastrun"
type="hidden"
default="0"
filter="integer"
/>
</fieldset>
</fields>
</config>
</extension>
system/redirect/form/excludes.xml000064400000000726147357022250013206
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset>
<field
name="term"
type="text"
label="PLG_SYSTEM_REDIRECT_FIELD_EXCLUDE_URLS_TERM_LABEL"
description="PLG_SYSTEM_REDIRECT_FIELD_EXCLUDE_URLS_TERM_DESC"
required="true"
/>
<field
name="regexp"
type="checkbox"
label="PLG_SYSTEM_REDIRECT_FIELD_EXCLUDE_URLS_REGEXP_LABEL"
description="PLG_SYSTEM_REDIRECT_FIELD_EXCLUDE_URLS_REGEXP_DESC"
filter="integer"
/>
</fieldset>
</form>
system/redirect/redirect.php000064400000023045147357022250012216
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.redirect
*
* @copyright (C) 2009 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\Registry\Registry;
use Joomla\String\StringHelper;
/**
* Plugin class for redirect handling.
*
* @since 1.6
*/
class PlgSystemRedirect extends JPlugin
{
/**
* Affects constructor behavior. If true, language files will be loaded
automatically.
*
* @var boolean
* @since 3.4
*/
protected $autoloadLanguage = false;
/**
* The global exception handler registered before the plugin was
instantiated
*
* @var callable
* @since 3.6
*/
private static $previousExceptionHandler;
/**
* Constructor.
*
* @param object &$subject The object to observe
* @param array $config An optional associative array of
configuration settings.
*
* @since 1.6
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
// Set the JError handler for E_ERROR to be the class' handleError
method.
JError::setErrorHandling(E_ERROR, 'callback',
array('PlgSystemRedirect', 'handleError'));
// Register the previously defined exception handler so we can forward
errors to it
self::$previousExceptionHandler =
set_exception_handler(array('PlgSystemRedirect',
'handleException'));
}
/**
* Method to handle an error condition from JError.
*
* @param JException $error The JException object to be handled.
*
* @return void
*
* @since 1.6
*/
public static function handleError(JException $error)
{
self::doErrorHandling($error);
}
/**
* Method to handle an uncaught exception.
*
* @param Exception|Throwable $exception The Exception or Throwable
object to be handled.
*
* @return void
*
* @since 3.5
* @throws InvalidArgumentException
*/
public static function handleException($exception)
{
// If this isn't a Throwable then bail out
if (!($exception instanceof Throwable) && !($exception instanceof
Exception))
{
throw new InvalidArgumentException(
sprintf('The error handler requires an Exception or Throwable
object, a "%s" object was given instead.',
get_class($exception))
);
}
self::doErrorHandling($exception);
}
/**
* Internal processor for all error handlers
*
* @param Exception|Throwable $error The Exception or Throwable object
to be handled.
*
* @return void
*
* @since 3.5
*/
private static function doErrorHandling($error)
{
$app = JFactory::getApplication();
if ($app->isClient('administrator') || ((int)
$error->getCode() !== 404))
{
// Proxy to the previous exception handler if available, otherwise just
render the error page
if (self::$previousExceptionHandler)
{
call_user_func_array(self::$previousExceptionHandler, array($error));
}
else
{
JErrorPage::render($error);
}
}
$uri = JUri::getInstance();
// These are the original URLs
$orgurl =
rawurldecode($uri->toString(array('scheme', 'host',
'port', 'path', 'query',
'fragment')));
$orgurlRel =
rawurldecode($uri->toString(array('path', 'query',
'fragment')));
// The above doesn't work for sub directories, so do this
$orgurlRootRel = str_replace(JUri::root(), '',
$orgurl);
// For when users have added / to the url
$orgurlRootRelSlash = str_replace(JUri::root(), '/',
$orgurl);
$orgurlWithoutQuery =
rawurldecode($uri->toString(array('scheme', 'host',
'port', 'path', 'fragment')));
$orgurlRelWithoutQuery =
rawurldecode($uri->toString(array('path',
'fragment')));
// These are the URLs we save and use
$url =
StringHelper::strtolower(rawurldecode($uri->toString(array('scheme',
'host', 'port', 'path', 'query',
'fragment'))));
$urlRel =
StringHelper::strtolower(rawurldecode($uri->toString(array('path',
'query', 'fragment'))));
// The above doesn't work for sub directories, so do this
$urlRootRel = str_replace(JUri::root(), '', $url);
// For when users have added / to the url
$urlRootRelSlash = str_replace(JUri::root(), '/', $url);
$urlWithoutQuery =
StringHelper::strtolower(rawurldecode($uri->toString(array('scheme',
'host', 'port', 'path',
'fragment'))));
$urlRelWithoutQuery =
StringHelper::strtolower(rawurldecode($uri->toString(array('path',
'fragment'))));
$plugin = JPluginHelper::getPlugin('system',
'redirect');
$params = new Registry($plugin->params);
$excludes = (array) $params->get('exclude_urls');
$skipUrl = false;
foreach ($excludes as $exclude)
{
if (empty($exclude->term))
{
continue;
}
if (!empty($exclude->regexp))
{
// Only check $url, because it includes all other sub urls
if (preg_match('/' . $exclude->term . '/i',
$orgurlRel))
{
$skipUrl = true;
break;
}
}
else
{
if (StringHelper::strpos($orgurlRel, $exclude->term) !== false)
{
$skipUrl = true;
break;
}
}
}
// Why is this (still) here?
if ($skipUrl || (strpos($url, 'mosConfig_') !== false) ||
(strpos($url, '=http://') !== false))
{
JErrorPage::render($error);
}
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('*')
->from($db->quoteName('#__redirect_links'))
->where(
'('
. $db->quoteName('old_url') . ' = ' .
$db->quote($url)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($urlRel)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($urlRootRel)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($urlRootRelSlash)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($urlWithoutQuery)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($urlRelWithoutQuery)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($orgurl)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($orgurlRel)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($orgurlRootRel)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($orgurlRootRelSlash)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($orgurlWithoutQuery)
. ' OR '
. $db->quoteName('old_url') . ' = ' .
$db->quote($orgurlRelWithoutQuery)
. ')'
);
$db->setQuery($query);
$redirect = null;
try
{
$redirects = $db->loadAssocList();
}
catch (Exception $e)
{
JErrorPage::render(new
Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'),
500, $e));
}
$possibleMatches = array_unique(
array(
$url,
$urlRel,
$urlRootRel,
$urlRootRelSlash,
$urlWithoutQuery,
$urlRelWithoutQuery,
$orgurl,
$orgurlRel,
$orgurlRootRel,
$orgurlRootRelSlash,
$orgurlWithoutQuery,
$orgurlRelWithoutQuery,
)
);
foreach ($possibleMatches as $match)
{
if (($index = array_search($match, array_column($redirects,
'old_url'))) !== false)
{
$redirect = (object) $redirects[$index];
if ((int) $redirect->published === 1)
{
break;
}
}
}
// A redirect object was found and, if published, will be used
if ($redirect !== null && ((int) $redirect->published === 1))
{
if (!$redirect->header || (bool)
JComponentHelper::getParams('com_redirect')->get('mode',
false) === false)
{
$redirect->header = 301;
}
if ($redirect->header < 400 && $redirect->header >=
300)
{
$urlQuery = $uri->getQuery();
$oldUrlParts = parse_url($redirect->old_url);
$newUrl = $redirect->new_url;
if ($urlQuery !== '' &&
empty($oldUrlParts['query']))
{
$newUrl .= '?' . $urlQuery;
}
$dest = JUri::isInternal($newUrl) || strpos($newUrl, 'http')
=== false ?
JRoute::_($newUrl) : $newUrl;
// In case the url contains double // lets remove it
$destination = str_replace(JUri::root() . '/', JUri::root(),
$dest);
// Always count redirect hits
$redirect->hits++;
try
{
$db->updateObject('#__redirect_links', $redirect,
'id');
}
catch (Exception $e)
{
// We don't log issues for now
}
$app->redirect($destination, (int) $redirect->header);
}
JErrorPage::render(new RuntimeException($error->getMessage(),
$redirect->header, $error));
}
// No redirect object was found so we create an entry in the redirect
table
elseif ($redirect === null)
{
$params = new Registry(JPluginHelper::getPlugin('system',
'redirect')->params);
if ((bool) $params->get('collect_urls', 1))
{
if (!$params->get('includeUrl', 1))
{
$url = $urlRel;
}
$data = (object) array(
'id' => 0,
'old_url' => $url,
'referer' =>
$app->input->server->getString('HTTP_REFERER',
''),
'hits' => 1,
'published' => 0,
'created_date' => JFactory::getDate()->toSql()
);
try
{
$db->insertObject('#__redirect_links', $data,
'id');
}
catch (Exception $e)
{
JErrorPage::render(new
Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'),
500, $e));
}
}
}
// We have an unpublished redirect object, increment the hit counter
else
{
$redirect->hits++;
try
{
$db->updateObject('#__redirect_links', $redirect,
'id');
}
catch (Exception $e)
{
JErrorPage::render(new
Exception(JText::_('PLG_SYSTEM_REDIRECT_ERROR_UPDATING_DATABASE'),
500, $e));
}
}
// Proxy to the previous exception handler if available, otherwise just
render the error page
if (self::$previousExceptionHandler)
{
call_user_func_array(self::$previousExceptionHandler, array($error));
}
else
{
JErrorPage::render($error);
}
}
}
system/redirect/redirect.xml000064400000003524147357022250012227
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_redirect</name>
<author>Joomla! Project</author>
<creationDate>April 2009</creationDate>
<copyright>(C) 2009 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_SYSTEM_REDIRECT_XML_DESCRIPTION</description>
<files>
<folder>form</folder>
<filename plugin="redirect">redirect.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_redirect.ini</language>
<language
tag="en-GB">en-GB.plg_system_redirect.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="collect_urls"
type="radio"
label="PLG_SYSTEM_REDIRECT_FIELD_COLLECT_URLS_LABEL"
description="PLG_SYSTEM_REDIRECT_FIELD_COLLECT_URLS_DESC"
default="1"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JENABLED</option>
<option value="0">JDISABLED</option>
</field>
<field
name="includeUrl"
type="radio"
label="PLG_SYSTEM_REDIRECT_FIELD_STORE_FULL_URL_LABEL"
description="PLG_SYSTEM_REDIRECT_FIELD_STORE_FULL_URL_DESC"
default="1"
filter="integer"
class="btn-group btn-group-yesno"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="exclude_urls"
type="subform"
label="PLG_SYSTEM_REDIRECT_FIELD_EXCLUDE_URLS_LABEL"
description="PLG_SYSTEM_REDIRECT_FIELD_EXCLUDE_URLS_DESC"
multiple="true"
formsource="plugins/system/redirect/form/excludes.xml"
/>
</fieldset>
</fields>
</config>
</extension>
system/remember/remember.php000064400000006607147357022250012215
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.remember
*
* @copyright (C) 2007 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Joomla! System Remember Me Plugin
*
* @since 1.5
*/
class PlgSystemRemember extends JPlugin
{
/**
* Application object.
*
* @var JApplicationCms
* @since 3.2
*/
protected $app;
/**
* Remember me method to run onAfterInitialise
* Only purpose is to initialise the login authentication process if a
cookie is present
*
* @return void
*
* @since 1.5
* @throws InvalidArgumentException
*/
public function onAfterInitialise()
{
// Get the application if not done by JPlugin. This may happen during
upgrades from Joomla 2.5.
if (!$this->app)
{
$this->app = JFactory::getApplication();
}
// No remember me for admin.
if ($this->app->isClient('administrator'))
{
return;
}
// Check for a cookie if user is not logged in
if (JFactory::getUser()->get('guest'))
{
$cookieName = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();
// Try with old cookieName (pre 3.6.0) if not found
if (!$this->app->input->cookie->get($cookieName))
{
$cookieName = JUserHelper::getShortHashedUserAgent();
}
// Check for the cookie
if ($this->app->input->cookie->get($cookieName))
{
$this->app->login(array('username' => ''),
array('silent' => true));
}
}
}
/**
* Imports the authentication plugin on user logout to make sure that the
cookie is destroyed.
*
* @param array $user Holds the user data.
* @param array $options Array holding options (remember,
autoregister, group).
*
* @return boolean
*/
public function onUserLogout($user, $options)
{
// No remember me for admin
if ($this->app->isClient('administrator'))
{
return true;
}
$cookieName = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();
// Check for the cookie
if ($this->app->input->cookie->get($cookieName))
{
// Make sure authentication group is loaded to process onUserAfterLogout
event
JPluginHelper::importPlugin('authentication');
}
return true;
}
/**
* Method is called before user data is stored in the database
* Invalidate all existing remember-me cookies after a password change
*
* @param array $user Holds the old user data.
* @param boolean $isnew True if a new user is stored.
* @param array $data Holds the new user data.
*
* @return boolean
*
* @since 3.8.6
*/
public function onUserBeforeSave($user, $isnew, $data)
{
// Irrelevant on new users
if ($isnew)
{
return true;
}
// Irrelevant, because password was not changed by user
if (empty($data['password_clear']))
{
return true;
}
/*
* But now, we need to do something
* Delete all tokens for this user!
*/
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->delete('#__user_keys')
->where($db->quoteName('user_id') . ' = ' .
$db->quote($user['username']));
try
{
$db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
// Log an alert for the site admin
JLog::add(
sprintf('Failed to delete cookie token for user %s with the
following error: %s', $user['username'],
$e->getMessage()),
JLog::WARNING,
'security'
);
}
return true;
}
}
system/remember/remember.xml000064400000001410147357022250012211
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_remember</name>
<author>Joomla! Project</author>
<creationDate>April 2007</creationDate>
<copyright>(C) 2007 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_REMEMBER_XML_DESCRIPTION</description>
<files>
<filename plugin="remember">remember.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_remember.ini</language>
<language
tag="en-GB">en-GB.plg_system_remember.sys.ini</language>
</languages>
</extension>
system/sef/sef.php000064400000016210147357022250010142 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.sef
*
* @copyright (C) 2007 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* Joomla! SEF Plugin.
*
* @since 1.5
*/
class PlgSystemSef extends JPlugin
{
/**
* Application object.
*
* @var JApplicationCms
* @since 3.5
*/
protected $app;
/**
* Add the canonical uri to the head.
*
* @return void
*
* @since 3.5
*/
public function onAfterDispatch()
{
$doc = $this->app->getDocument();
if (!$this->app->isClient('site') || $doc->getType()
!== 'html')
{
return;
}
$sefDomain = $this->params->get('domain', false);
// Don't add a canonical html tag if no alternative domain has added
in SEF plugin domain field.
if (empty($sefDomain))
{
return;
}
// Check if a canonical html tag already exists (for instance, added by a
component).
$canonical = '';
foreach ($doc->_links as $linkUrl => $link)
{
if (isset($link['relation']) &&
$link['relation'] === 'canonical')
{
$canonical = $linkUrl;
break;
}
}
// If a canonical html tag already exists get the canonical and change it
to use the SEF plugin domain field.
if (!empty($canonical))
{
// Remove current canonical link.
unset($doc->_links[$canonical]);
// Set the current canonical link but use the SEF system plugin domain
field.
$canonical = $sefDomain .
JUri::getInstance($canonical)->toString(array('path',
'query', 'fragment'));
}
// If a canonical html doesn't exists already add a canonical html
tag using the SEF plugin domain field.
else
{
$canonical = $sefDomain .
JUri::getInstance()->toString(array('path', 'query',
'fragment'));
}
// Add the canonical link.
$doc->addHeadLink(htmlspecialchars($canonical),
'canonical');
}
/**
* Convert the site URL to fit to the HTTP request.
*
* @return void
*/
public function onAfterRender()
{
if (!$this->app->isClient('site'))
{
return;
}
// Replace src links.
$base = JUri::base(true) . '/';
$buffer = $this->app->getBody();
// For feeds we need to search for the URL with domain.
$prefix = $this->app->getDocument()->getType() ===
'feed' ? JUri::root() : '';
// Replace index.php URI by SEF URI.
if (strpos($buffer, 'href="' . $prefix .
'index.php?') !== false)
{
preg_match_all('#href="' . $prefix .
'index.php\?([^"]+)"#m', $buffer, $matches);
foreach ($matches[1] as $urlQueryString)
{
$buffer = str_replace(
'href="' . $prefix . 'index.php?' .
$urlQueryString . '"',
'href="' . trim($prefix, '/') .
JRoute::_('index.php?' . $urlQueryString) . '"',
$buffer
);
}
$this->checkBuffer($buffer);
}
// Check for all unknown protocols (a protocol must contain at least one
alphanumeric character followed by a ":").
$protocols = '[a-zA-Z0-9\-]+:';
$attributes = array('href=', 'src=',
'poster=');
foreach ($attributes as $attribute)
{
if (strpos($buffer, $attribute) !== false)
{
$regex = '#\s' . $attribute . '"(?!/|' .
$protocols . '|\#|\')([^"]*)"#m';
$buffer = preg_replace($regex, ' ' . $attribute .
'"' . $base . '$1"', $buffer);
$this->checkBuffer($buffer);
}
}
if (strpos($buffer, 'srcset=') !== false)
{
$regex = '#\s+srcset="([^"]+)"#m';
$buffer = preg_replace_callback(
$regex,
function ($match) use ($base, $protocols)
{
preg_match_all('#(?:[^\s]+)\s*(?:[\d\.]+[wx])?(?:\,\s*)?#i',
$match[1], $matches);
foreach ($matches[0] as &$src)
{
$src = preg_replace('#^(?!/|' . $protocols .
'|\#|\')(.+)#', $base . '$1', $src);
}
return ' srcset="' . implode($matches[0]) .
'"';
},
$buffer
);
$this->checkBuffer($buffer);
}
// Replace all unknown protocols in javascript window open events.
if (strpos($buffer, 'window.open(') !== false)
{
$regex = '#onclick="window.open\(\'(?!/|' .
$protocols . '|\#)([^/]+[^\']*?\')#m';
$buffer = preg_replace($regex,
'onclick="window.open(\'' . $base . '$1',
$buffer);
$this->checkBuffer($buffer);
}
// Replace all unknown protocols in onmouseover and onmouseout
attributes.
$attributes = array('onmouseover=', 'onmouseout=');
foreach ($attributes as $attribute)
{
if (strpos($buffer, $attribute) !== false)
{
$regex = '#' . $attribute .
'"this.src=([\']+)(?!/|' . $protocols .
'|\#|\')([^"]+)"#m';
$buffer = preg_replace($regex, $attribute .
'"this.src=$1' . $base . '$2"', $buffer);
$this->checkBuffer($buffer);
}
}
// Replace all unknown protocols in CSS background image.
if (strpos($buffer, 'style=') !== false)
{
$regex_url =
'\s*url\s*\(([\'\"]|\&\#0?3[49];)?(?!/|\&\#0?3[49];|'
. $protocols .
'|\#)([^\)\'\"]+)([\'\"]|\&\#0?3[49];)?\)';
$regex = '#style=\s*([\'\"])(.*):' . $regex_url .
'#m';
$buffer = preg_replace($regex, 'style=$1$2: url($3' . $base .
'$4$5)', $buffer);
$this->checkBuffer($buffer);
}
// Replace all unknown protocols in OBJECT param tag.
if (strpos($buffer, '<param') !== false)
{
// OBJECT <param name="xx", value="yy"> -- fix
it only inside the <param> tag.
$regex =
'#(<param\s+)name\s*=\s*"(movie|src|url)"[^>]\s*value\s*=\s*"(?!/|'
. $protocols . '|\#|\')([^"]*)"#m';
$buffer = preg_replace($regex, '$1name="$2"
value="' . $base . '$3"', $buffer);
$this->checkBuffer($buffer);
// OBJECT <param value="xx", name="yy"> -- fix
it only inside the <param> tag.
$regex = '#(<param\s+[^>]*)value\s*=\s*"(?!/|' .
$protocols .
'|\#|\')([^"]*)"\s*name\s*=\s*"(movie|src|url)"#m';
$buffer = preg_replace($regex, '<param value="' .
$base . '$2" name="$3"', $buffer);
$this->checkBuffer($buffer);
}
// Replace all unknown protocols in OBJECT tag.
if (strpos($buffer, '<object') !== false)
{
$regex = '#(<object\s+[^>]*)data\s*=\s*"(?!/|' .
$protocols . '|\#|\')([^"]*)"#m';
$buffer = preg_replace($regex, '$1data="' . $base .
'$2"', $buffer);
$this->checkBuffer($buffer);
}
// Use the replaced HTML body.
$this->app->setBody($buffer);
}
/**
* Check the buffer.
*
* @param string $buffer Buffer to be checked.
*
* @return void
*/
private function checkBuffer($buffer)
{
if ($buffer === null)
{
switch (preg_last_error())
{
case PREG_BACKTRACK_LIMIT_ERROR:
$message = 'PHP regular expression limit reached
(pcre.backtrack_limit)';
break;
case PREG_RECURSION_LIMIT_ERROR:
$message = 'PHP regular expression limit reached
(pcre.recursion_limit)';
break;
case PREG_BAD_UTF8_ERROR:
$message = 'Bad UTF8 passed to PCRE function';
break;
default:
$message = 'Unknown PCRE error calling PCRE function';
}
throw new RuntimeException($message);
}
}
/**
* Replace the matched tags.
*
* @param array &$matches An array of matches (see
preg_match_all).
*
* @return string
*
* @deprecated 4.0 No replacement.
*/
protected static function route(&$matches)
{
JLog::add(__METHOD__ . ' is deprecated, no replacement.',
JLog::WARNING, 'deprecated');
$url = $matches[1];
$url = str_replace('&', '&', $url);
$route = JRoute::_('index.php?' . $url);
return 'href="' . $route;
}
}
system/sef/sef.xml000064400000002040147357022250010147 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="system" method="upgrade">
<name>plg_system_sef</name>
<author>Joomla! Project</author>
<creationDate>December 2007</creationDate>
<copyright>(C) 2007 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_SEF_XML_DESCRIPTION</description>
<files>
<filename plugin="sef">sef.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_system_sef.ini</language>
<language
tag="en-GB">en-GB.plg_system_sef.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="domain"
type="url"
label="PLG_SEF_DOMAIN_LABEL"
description="PLG_SEF_DOMAIN_DESCRIPTION"
hint="https://www.example.com"
filter="url"
validate="url"
/>
</fieldset>
</fields>
</config>
</extension>
system/sessiongc/sessiongc.php000064400000003311147357022250012600
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.sessiongc
*
* @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\Application\CMSApplication;
use Joomla\CMS\Factory;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Session\MetadataManager;
/**
* Garbage collection handler for session related data
*
* @since 3.8.6
*/
class PlgSystemSessionGc extends CMSPlugin
{
/**
* Application object
*
* @var CMSApplication
* @since 3.8.6
*/
protected $app;
/**
* Database driver
*
* @var JDatabaseDriver
* @since 3.8.6
*/
protected $db;
/**
* Runs after the HTTP response has been sent to the client and performs
garbage collection tasks
*
* @return void
*
* @since 3.8.6
*/
public function onAfterRespond()
{
$session = Factory::getSession();
if ($this->params->get('enable_session_gc', 1))
{
$probability = $this->params->get('gc_probability', 1);
$divisor = $this->params->get('gc_divisor', 100);
$random = $divisor * lcg_value();
if ($probability > 0 && $random < $probability)
{
$session->gc();
}
}
if ($this->app->get('session_handler', 'none')
!== 'database' &&
$this->params->get('enable_session_metadata_gc', 1))
{
$probability = $this->params->get('gc_probability', 1);
$divisor = $this->params->get('gc_divisor', 100);
$random = $divisor * lcg_value();
if ($probability > 0 && $random < $probability)
{
$metadataManager = new MetadataManager($this->app, $this->db);
$metadataManager->deletePriorTo(time() - $session->getExpire());
}
}
}
}
system/sessiongc/sessiongc.xml000064400000004340147357022250012614
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.8" type="plugin"
group="system" method="upgrade">
<name>plg_system_sessiongc</name>
<author>Joomla! Project</author>
<creationDate>February 2018</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.8.6</version>
<description>PLG_SYSTEM_SESSIONGC_XML_DESCRIPTION</description>
<files>
<filename
plugin="sessiongc">sessiongc.php</filename>
</files>
<languages folder="language">
<language
tag="en-GB">en-GB/en-GB.plg_system_sessiongc.ini</language>
<language
tag="en-GB">en-GB/en-GB.plg_system_sessiongc.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="enable_session_gc"
type="radio"
label="PLG_SYSTEM_SESSIONGC_ENABLE_SESSION_GC_LABEL"
description="PLG_SYSTEM_SESSIONGC_ENABLE_SESSION_GC_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="uint"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="enable_session_metadata_gc"
type="radio"
label="PLG_SYSTEM_SESSIONGC_ENABLE_SESSION_METADATA_GC_LABEL"
description="PLG_SYSTEM_SESSIONGC_ENABLE_SESSION_METADATA_GC_DESC"
class="btn-group btn-group-yesno"
default="1"
filter="uint"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="gc_probability"
type="number"
label="PLG_SYSTEM_SESSIONGC_GC_PROBABILITY_LABEL"
description="PLG_SYSTEM_SESSIONGC_GC_PROBABILITY_DESC"
filter="uint"
validate="number"
min="1"
default="1"
showon="enable_session_gc:1[OR]enable_session_metadata_gc:1"
/>
<field
name="gc_divisor"
type="number"
label="PLG_SYSTEM_SESSIONGC_GC_DIVISOR_LABEL"
description="PLG_SYSTEM_SESSIONGC_GC_DIVISOR_DESC"
filter="uint"
validate="number"
min="1"
default="100"
showon="enable_session_gc:1[OR]enable_session_metadata_gc:1"
/>
</fieldset>
</fields>
</config>
</extension>
system/stats/field/base.php000064400000001345147357022250011746
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @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;
/**
* Base field for the Stats Plugin.
*
* @since 3.5
*/
abstract class PlgSystemStatsFormFieldBase extends JFormField
{
/**
* Get the layouts paths
*
* @return array
*
* @since 3.5
*/
protected function getLayoutPaths()
{
$template = JFactory::getApplication()->getTemplate();
return array(
JPATH_ADMINISTRATOR . '/templates/' . $template .
'/html/layouts/plugins/system/stats',
dirname(__DIR__) . '/layouts',
JPATH_SITE . '/layouts'
);
}
}
system/stats/field/data.php000064400000002240147357022250011740
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @copyright (C) 2016 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::register('PlgSystemStatsFormFieldBase', __DIR__ .
'/base.php');
/**
* Unique ID Field class for the Stats Plugin.
*
* @since 3.5
*/
class PlgSystemStatsFormFieldData extends PlgSystemStatsFormFieldBase
{
/**
* The form field type.
*
* @var string
* @since 3.5
*/
protected $type = 'Data';
/**
* Name of the layout being used to render the field
*
* @var string
* @since 3.5
*/
protected $layout = 'field.data';
/**
* Method to get the data to be passed to the layout for rendering.
*
* @return array
*
* @since 3.5
*/
protected function getLayoutData()
{
$data = parent::getLayoutData();
$dispatcher = JEventDispatcher::getInstance();
JPluginHelper::importPlugin('system', 'stats');
$result = $dispatcher->trigger('onGetStatsData',
array('stats.field.data'));
$data['statsData'] = $result ? reset($result) : array();
return $data;
}
}
system/stats/field/uniqueid.php000064400000001334147357022250012655
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @copyright (C) 2016 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
JLoader::register('PlgSystemStatsFormFieldBase', __DIR__ .
'/base.php');
/**
* Unique ID Field class for the Stats Plugin.
*
* @since 3.5
*/
class PlgSystemStatsFormFieldUniqueid extends PlgSystemStatsFormFieldBase
{
/**
* The form field type.
*
* @var string
* @since 3.5
*/
protected $type = 'Uniqueid';
/**
* Name of the layout being used to render the field
*
* @var string
* @since 3.5
*/
protected $layout = 'field.uniqueid';
}
system/stats/layouts/field/data.php000064400000004332147357022250013444
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @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;
extract($displayData);
/**
* Layout variables
* -----------------
* @var string $autocomplete Autocomplete attribute for the field.
* @var boolean $autofocus Is autofocus enabled?
* @var string $class Classes for the input.
* @var string $description Description of the field.
* @var boolean $disabled Is this field disabled?
* @var string $group Group the field belongs to.
<fields> section in form XML.
* @var boolean $hidden Is this field hidden in the form?
* @var string $hint Placeholder for the field.
* @var string $id DOM id of the field.
* @var string $label Label of the field.
* @var string $labelclass Classes to apply to the label.
* @var boolean $multiple Does this field support multiple
values?
* @var string $name Name of the input field.
* @var string $onchange Onchange attribute for the field.
* @var string $onclick Onclick attribute for the field.
* @var string $pattern Pattern (Reg Ex) of value of the form
field.
* @var boolean $readonly Is this field read only?
* @var boolean $repeat Allows extensions to duplicate
elements.
* @var boolean $required Is this field required?
* @var integer $size Size attribute of the input.
* @var boolean $spellcheck Spellcheck state for the form field.
* @var string $validate Validation rules to apply.
* @var string $value Value attribute of the field.
* @var array $options Options available for this field.
* @var array $statsData Statistics that will be sent to the
stats server
*/
JHtml::_('jquery.framework');
?>
<a href="#" onclick="jQuery(this).next().toggle(200);
return false;"><?php echo
JText::_('PLG_SYSTEM_STATS_MSG_WHAT_DATA_WILL_BE_SENT');
?></a>
<?php
echo $field->render('stats', compact('statsData'));
system/stats/layouts/field/uniqueid.php000064400000004407147357022250014361
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @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;
extract($displayData);
/**
* Layout variables
* -----------------
* @var string $autocomplete Autocomplete attribute for the field.
* @var boolean $autofocus Is autofocus enabled?
* @var string $class Classes for the input.
* @var string $description Description of the field.
* @var boolean $disabled Is this field disabled?
* @var string $group Group the field belongs to.
<fields> section in form XML.
* @var boolean $hidden Is this field hidden in the form?
* @var string $hint Placeholder for the field.
* @var string $id DOM id of the field.
* @var string $label Label of the field.
* @var string $labelclass Classes to apply to the label.
* @var boolean $multiple Does this field support multiple
values?
* @var string $name Name of the input field.
* @var string $onchange Onchange attribute for the field.
* @var string $onclick Onclick attribute for the field.
* @var string $pattern Pattern (Reg Ex) of value of the form
field.
* @var boolean $readonly Is this field read only?
* @var boolean $repeat Allows extensions to duplicate
elements.
* @var boolean $required Is this field required?
* @var integer $size Size attribute of the input.
* @var boolean $spellcheck Spellcheck state for the form field.
* @var string $validate Validation rules to apply.
* @var string $value Value attribute of the field.
* @var array $options Options available for this field.
*/
?>
<input type="hidden" name="<?php echo $name;
?>" id="<?php echo $id; ?>" value="<?php
echo htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); ?>"
/>
<a class="btn"
onclick="document.getElementById('<?php echo $id;
?>').value='';Joomla.submitbutton('plugin.apply');">
<span class="icon-refresh"></span> <?php echo
JText::_('PLG_SYSTEM_STATS_RESET_UNIQUE_ID'); ?>
</a>system/stats/layouts/message.php000064400000003014147357022250013070
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @copyright (C) 2015 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
extract($displayData);
/**
* Layout variables
* -----------------
* @var PlgSystemStats $plugin Plugin rendering this
layout
* @var \Joomla\Registry\Registry $pluginParams Plugin parameters
* @var array $statsData Array containing the
data that will be sent to the stats server
*/
?>
<div class="alert alert-info js-pstats-alert"
style="display:none;">
<button data-dismiss="alert" class="close"
type="button">×</button>
<h2><?php echo
JText::_('PLG_SYSTEM_STATS_LABEL_MESSAGE_TITLE');
?></h2>
<p>
<?php echo
JText::_('PLG_SYSTEM_STATS_MSG_JOOMLA_WANTS_TO_SEND_DATA'); ?>
<a href="#" class="js-pstats-btn-details
alert-link"><?php echo
JText::_('PLG_SYSTEM_STATS_MSG_WHAT_DATA_WILL_BE_SENT');
?></a>
</p>
<?php
echo $plugin->render('stats',
compact('statsData'));
?>
<p><?php echo
JText::_('PLG_SYSTEM_STATS_MSG_ALLOW_SENDING_DATA');
?></p>
<p class="actions">
<a href="#" class="btn
js-pstats-btn-allow-always"><?php echo
JText::_('PLG_SYSTEM_STATS_BTN_SEND_ALWAYS'); ?></a>
<a href="#" class="btn
js-pstats-btn-allow-once"><?php echo
JText::_('PLG_SYSTEM_STATS_BTN_SEND_NOW'); ?></a>
<a href="#" class="btn
js-pstats-btn-allow-never"><?php echo
JText::_('PLG_SYSTEM_STATS_BTN_NEVER_SEND'); ?></a>
</p>
</div>
system/stats/layouts/stats.php000064400000001546147357022250012612
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @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;
extract($displayData);
/**
* Layout variables
* -----------------
* @var array $statsData Array containing the data that will be sent to
the stats server
*/
$versionFields = array('php_version', 'db_version',
'cms_version');
?>
<dl class="dl-horizontal js-pstats-data-details"
style="display:none;">
<?php foreach ($statsData as $key => $value) : ?>
<dt><?php echo JText::_('PLG_SYSTEM_STATS_LABEL_' .
strtoupper($key)); ?></dt>
<dd><?php echo in_array($key, $versionFields) ?
(preg_match('/\d+(?:\.\d+)+/', $value, $matches) ? $matches[0] :
$value) : $value; ?></dd>
<?php endforeach; ?>
</dl>
system/stats/stats.php000064400000030705147357022250011111 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.stats
*
* @copyright (C) 2015 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
// Uncomment the following line to enable debug mode for testing purposes.
Note: statistics will be sent on every page load
// define('PLG_SYSTEM_STATS_DEBUG', 1);
/**
* Statistics system plugin. This sends anonymous data back to the Joomla!
Project about the
* PHP, SQL, Joomla and OS versions
*
* @since 3.5
*/
class PlgSystemStats extends JPlugin
{
/**
* Indicates sending statistics is always allowed.
*
* @var integer
* @since 3.5
*/
const MODE_ALLOW_ALWAYS = 1;
/**
* Indicates sending statistics is only allowed one time.
*
* @var integer
* @since 3.5
*/
const MODE_ALLOW_ONCE = 2;
/**
* Indicates sending statistics is never allowed.
*
* @var integer
* @since 3.5
*/
const MODE_ALLOW_NEVER = 3;
/**
* Application object
*
* @var JApplicationCms
* @since 3.5
*/
protected $app;
/**
* Database object
*
* @var JDatabaseDriver
* @since 3.5
*/
protected $db;
/**
* URL to send the statistics.
*
* @var string
* @since 3.5
*/
protected $serverUrl =
'https://developer.joomla.org/stats/submit';
/**
* Unique identifier for this site
*
* @var string
* @since 3.5
*/
protected $uniqueId;
/**
* Listener for the `onAfterInitialise` event
*
* @return void
*
* @since 3.5
*/
public function onAfterInitialise()
{
if (!$this->app->isClient('administrator') ||
!$this->isAllowedUser())
{
return;
}
if (!$this->isDebugEnabled() && !$this->isUpdateRequired())
{
return;
}
if (JUri::getInstance()->getVar('tmpl') ===
'component')
{
return;
}
// Load plugin language files only when needed (ex: they are not needed
in site client).
$this->loadLanguage();
JHtml::_('jquery.framework');
JHtml::_('script', 'plg_system_stats/stats.js',
array('version' => 'auto', 'relative'
=> true));
}
/**
* User selected to always send data
*
* @return void
*
* @since 3.5
*
* @throws Exception If user is not allowed.
* @throws RuntimeException If there is an error saving the params or
sending the data.
*/
public function onAjaxSendAlways()
{
if (!$this->isAllowedUser() || !$this->isAjaxRequest())
{
throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'),
403);
}
$this->params->set('mode', static::MODE_ALLOW_ALWAYS);
if (!$this->saveParams())
{
throw new RuntimeException('Unable to save plugin settings',
500);
}
$this->sendStats();
echo json_encode(array('sent' => 1));
}
/**
* User selected to never send data.
*
* @return void
*
* @since 3.5
*
* @throws Exception If user is not allowed.
* @throws RuntimeException If there is an error saving the params.
*/
public function onAjaxSendNever()
{
if (!$this->isAllowedUser() || !$this->isAjaxRequest())
{
throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'),
403);
}
$this->params->set('mode', static::MODE_ALLOW_NEVER);
if (!$this->saveParams())
{
throw new RuntimeException('Unable to save plugin settings',
500);
}
echo json_encode(array('sent' => 0));
}
/**
* User selected to send data once.
*
* @return void
*
* @since 3.5
*
* @throws Exception If user is not allowed.
* @throws RuntimeException If there is an error saving the params or
sending the data.
*/
public function onAjaxSendOnce()
{
if (!$this->isAllowedUser() || !$this->isAjaxRequest())
{
throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'),
403);
}
$this->params->set('mode', static::MODE_ALLOW_ONCE);
if (!$this->saveParams())
{
throw new RuntimeException('Unable to save plugin settings',
500);
}
$this->sendStats();
echo json_encode(array('sent' => 1));
}
/**
* Send the stats to the server.
* On first load | on demand mode it will show a message asking users to
select mode.
*
* @return void
*
* @since 3.5
*
* @throws Exception If user is not allowed.
* @throws RuntimeException If there is an error saving the params or
sending the data.
*/
public function onAjaxSendStats()
{
if (!$this->isAllowedUser() || !$this->isAjaxRequest())
{
throw new Exception(JText::_('JGLOBAL_AUTH_ACCESS_DENIED'),
403);
}
// User has not selected the mode. Show message.
if ((int) $this->params->get('mode') !==
static::MODE_ALLOW_ALWAYS)
{
$data = array(
'sent' => 0,
'html' =>
$this->getRenderer('message')->render($this->getLayoutData())
);
echo json_encode($data);
return;
}
if (!$this->saveParams())
{
throw new RuntimeException('Unable to save plugin settings',
500);
}
$this->sendStats();
echo json_encode(array('sent' => 1));
}
/**
* Get the data through events
*
* @param string $context Context where this will be called from
*
* @return array
*
* @since 3.5
*/
public function onGetStatsData($context)
{
return $this->getStatsData();
}
/**
* Debug a layout of this plugin
*
* @param string $layoutId Layout identifier
* @param array $data Optional data for the layout
*
* @return string
*
* @since 3.5
*/
public function debug($layoutId, $data = array())
{
$data = array_merge($this->getLayoutData(), $data);
return $this->getRenderer($layoutId)->debug($data);
}
/**
* Get the data for the layout
*
* @return array
*
* @since 3.5
*/
protected function getLayoutData()
{
return array(
'plugin' => $this,
'pluginParams' => $this->params,
'statsData' => $this->getStatsData()
);
}
/**
* Get the layout paths
*
* @return array
*
* @since 3.5
*/
protected function getLayoutPaths()
{
$template = JFactory::getApplication()->getTemplate();
return array(
JPATH_ADMINISTRATOR . '/templates/' . $template .
'/html/layouts/plugins/' . $this->_type . '/' .
$this->_name,
__DIR__ . '/layouts',
);
}
/**
* Get the plugin renderer
*
* @param string $layoutId Layout identifier
*
* @return JLayout
*
* @since 3.5
*/
protected function getRenderer($layoutId = 'default')
{
$renderer = new JLayoutFile($layoutId);
$renderer->setIncludePaths($this->getLayoutPaths());
return $renderer;
}
/**
* Get the data that will be sent to the stats server.
*
* @return array
*
* @since 3.5
*/
private function getStatsData()
{
$data = array(
'unique_id' => $this->getUniqueId(),
'php_version' => PHP_VERSION,
'db_type' => $this->db->name,
'db_version' => $this->db->getVersion(),
'cms_version' => JVERSION,
'server_os' => php_uname('s') . ' ' .
php_uname('r')
);
// Check if we have a MariaDB version string and extract the proper
version from it
if
(preg_match('/^(?:5\.5\.5-)?(mariadb-)?(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)/i',
$data['db_version'], $versionParts))
{
$data['db_version'] = $versionParts['major'] .
'.' . $versionParts['minor'] . '.' .
$versionParts['patch'];
}
return $data;
}
/**
* Get the unique id. Generates one if none is set.
*
* @return integer
*
* @since 3.5
*/
private function getUniqueId()
{
if (null === $this->uniqueId)
{
$this->uniqueId = $this->params->get('unique_id',
hash('sha1', JUserHelper::genRandomPassword(28) . time()));
}
return $this->uniqueId;
}
/**
* Check if current user is allowed to send the data
*
* @return boolean
*
* @since 3.5
*/
private function isAllowedUser()
{
return JFactory::getUser()->authorise('core.admin');
}
/**
* Check if the debug is enabled
*
* @return boolean
*
* @since 3.5
*/
private function isDebugEnabled()
{
return defined('PLG_SYSTEM_STATS_DEBUG');
}
/**
* Check if last_run + interval > now
*
* @return boolean
*
* @since 3.5
*/
private function isUpdateRequired()
{
$last = (int) $this->params->get('lastrun', 0);
$interval = (int) $this->params->get('interval', 12);
$mode = (int) $this->params->get('mode', 0);
if ($mode === static::MODE_ALLOW_NEVER)
{
return false;
}
// Never updated or debug enabled
if (!$last || $this->isDebugEnabled())
{
return true;
}
return (abs(time() - $last) > $interval * 3600);
}
/**
* Check valid AJAX request
*
* @return boolean
*
* @since 3.5
*/
private function isAjaxRequest()
{
return
strtolower($this->app->input->server->get('HTTP_X_REQUESTED_WITH',
'')) === 'xmlhttprequest';
}
/**
* Render a layout of this plugin
*
* @param string $layoutId Layout identifier
* @param array $data Optional data for the layout
*
* @return string
*
* @since 3.5
*/
public function render($layoutId, $data = array())
{
$data = array_merge($this->getLayoutData(), $data);
return $this->getRenderer($layoutId)->render($data);
}
/**
* Save the plugin parameters
*
* @return boolean
*
* @since 3.5
*/
private function saveParams()
{
// Update params
$this->params->set('lastrun', time());
$this->params->set('unique_id', $this->getUniqueId());
$interval = (int) $this->params->get('interval', 12);
$this->params->set('interval', $interval ?: 12);
$query = $this->db->getQuery(true)
->update($this->db->quoteName('#__extensions'))
->set($this->db->quoteName('params') . ' =
' .
$this->db->quote($this->params->toString('JSON')))
->where($this->db->quoteName('type') . ' =
' . $this->db->quote('plugin'))
->where($this->db->quoteName('folder') . ' =
' . $this->db->quote('system'))
->where($this->db->quoteName('element') . ' =
' . $this->db->quote('stats'));
try
{
// Lock the tables to prevent multiple plugin executions causing a race
condition
$this->db->lockTable('#__extensions');
}
catch (Exception $e)
{
// If we can't lock the tables it's too risky to continue
execution
return false;
}
try
{
// Update the plugin parameters
$result = $this->db->setQuery($query)->execute();
$this->clearCacheGroups(array('com_plugins'), array(0, 1));
}
catch (Exception $exc)
{
// If we failed to execute
$this->db->unlockTables();
$result = false;
}
try
{
// Unlock the tables after writing
$this->db->unlockTables();
}
catch (Exception $e)
{
// If we can't lock the tables assume we have somehow failed
$result = false;
}
return $result;
}
/**
* Send the stats to the stats server
*
* @return boolean
*
* @since 3.5
*
* @throws RuntimeException If there is an error sending the data.
*/
private function sendStats()
{
try
{
// Don't let the request take longer than 2 seconds to avoid page
timeout issues
$response = JHttpFactory::getHttp()->post($this->serverUrl,
$this->getStatsData(), null, 2);
}
catch (UnexpectedValueException $e)
{
// There was an error sending stats. Should we do anything?
throw new RuntimeException('Could not send site statistics to
remote server: ' . $e->getMessage(), 500);
}
catch (RuntimeException $e)
{
// There was an error connecting to the server or in the post request
throw new RuntimeException('Could not connect to statistics server:
' . $e->getMessage(), 500);
}
catch (Exception $e)
{
// An unexpected error in processing; don't let this failure kill
the site
throw new RuntimeException('Unexpected error connecting to
statistics server: ' . $e->getMessage(), 500);
}
if ($response->code !== 200)
{
$data = json_decode($response->body);
throw new RuntimeException('Could not send site statistics to
remote server: ' . $data->message, $response->code);
}
return true;
}
/**
* Clears cache groups. We use it to clear the plugins cache after we
update the last run timestamp.
*
* @param array $clearGroups The cache groups to clean
* @param array $cacheClients The cache clients (site, admin) to clean
*
* @return void
*
* @since 3.5
*/
private function clearCacheGroups(array $clearGroups, array $cacheClients
= array(0, 1))
{
foreach ($clearGroups as $group)
{
foreach ($cacheClients as $client_id)
{
try
{
$options = array(
'defaultgroup' => $group,
'cachebase' => $client_id ? JPATH_ADMINISTRATOR .
'/cache' : $this->app->get('cache_path',
JPATH_SITE . '/cache')
);
$cache = JCache::getInstance('callback', $options);
$cache->clean();
}
catch (Exception $e)
{
// Ignore it
}
}
}
}
}
system/stats/stats.xml000064400000003542147357022250011121 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.6" type="plugin"
group="system" method="upgrade">
<name>plg_system_stats</name>
<author>Joomla! Project</author>
<creationDate>November 2013</creationDate>
<copyright>(C) 2013 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.5.0</version>
<description>PLG_SYSTEM_STATS_XML_DESCRIPTION</description>
<files>
<folder>field</folder>
<folder>layouts</folder>
<filename plugin="stats">stats.php</filename>
</files>
<languages folder="language">
<language
tag="en-GB">en-GB/en-GB.plg_system_stats.ini</language>
<language
tag="en-GB">en-GB/en-GB.plg_system_stats.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="data"
type="plgsystemstats.data"
label=""
/>
<field
name="unique_id"
type="plgsystemstats.uniqueid"
label="PLG_SYSTEM_STATS_UNIQUE_ID_LABEL"
description="PLG_SYSTEM_STATS_UNIQUE_ID_DESC"
size="10"
/>
<field
name="interval"
type="number"
label="PLG_SYSTEM_STATS_INTERVAL_LABEL"
description="PLG_SYSTEM_STATS_INTERVAL_DESC"
filter="integer"
default="12"
/>
<field
name="mode"
type="list"
label="PLG_SYSTEM_STATS_MODE_LABEL"
description="PLG_SYSTEM_STATS_MODE_DESC"
default="1"
>
<option
value="1">PLG_SYSTEM_STATS_MODE_OPTION_ALWAYS_SEND</option>
<option
value="2">PLG_SYSTEM_STATS_MODE_OPTION_ON_DEMAND</option>
<option
value="3">PLG_SYSTEM_STATS_MODE_OPTION_NEVER_SEND</option>
</field>
<field
name="lastrun"
type="hidden"
default="0"
size="15"
/>
</fieldset>
</fields>
</config>
</extension>
system/updatenotification/postinstall/updatecachetime.php000064400000002605147357022250020205
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.updatenotification
*
* @copyright (C) 2016 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
/**
* Checks if the com_installer config for the cache Hours are eq 0 and the
updatenotification Plugin is enabled
*
* @return boolean
*
* @since 3.6.3
*/
function updatecachetime_postinstall_condition()
{
$cacheTimeout = (int)
JComponentHelper::getComponent('com_installer')->params->get('cachetimeout',
6);
// Check if cachetimeout is eq zero
if ($cacheTimeout === 0 &&
JPluginHelper::isEnabled('system',
'updatenotification'))
{
return true;
}
return false;
}
/**
* Sets the cachetimeout back to the default (6 hours)
*
* @return void
*
* @since 3.6.3
*/
function updatecachetime_postinstall_action()
{
$installer = JComponentHelper::getComponent('com_installer');
// Sets the cachetimeout back to the default (6 hours)
$installer->params->set('cachetimeout', 6);
// Save the new parameters back to com_installer
$table = JTable::getInstance('extension');
$table->load($installer->id);
$table->bind(array('params' =>
$installer->params->toString()));
// Store the changes
if (!$table->store())
{
// If there is an error show it to the admin
JFactory::getApplication()->enqueueMessage($table->getError(),
'error');
}
}
system/updatenotification/updatenotification.php000064400000026526147357022250016405
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.updatenotification
*
* @copyright (C) 2015 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
// Uncomment the following line to enable debug mode (update notification
email sent every single time)
// define('PLG_SYSTEM_UPDATENOTIFICATION_DEBUG', 1);
/**
* Joomla! Update Notification plugin
*
* Sends out an email to all Super Users or a predefined email address when
a new Joomla! version is available.
*
* This plugin is a direct adaptation of the corresponding plugin in Akeeba
Ltd's Admin Tools. The author has
* consented to relicensing their plugin's code under GPLv2 or later
(the original version was licensed under
* GPLv3 or later) to allow its inclusion in the Joomla! CMS.
*
* @since 3.5
*/
class PlgSystemUpdatenotification extends JPlugin
{
/**
* Load plugin language files automatically
*
* @var boolean
* @since 3.6.3
*/
protected $autoloadLanguage = true;
/**
* The update check and notification email code is triggered after the
page has fully rendered.
*
* @return void
*
* @since 3.5
*/
public function onAfterRender()
{
// Get the timeout for Joomla! updates, as configured in
com_installer's component parameters
$component = JComponentHelper::getComponent('com_installer');
/** @var \Joomla\Registry\Registry $params */
$params = $component->params;
$cache_timeout = (int) $params->get('cachetimeout', 6);
$cache_timeout = 3600 * $cache_timeout;
// Do we need to run? Compare the last run timestamp stored in the
plugin's options with the current
// timestamp. If the difference is greater than the cache timeout we
shall not execute again.
$now = time();
$last = (int) $this->params->get('lastrun', 0);
if (!defined('PLG_SYSTEM_UPDATENOTIFICATION_DEBUG') &&
(abs($now - $last) < $cache_timeout))
{
return;
}
// Update last run status
// If I have the time of the last run, I can update, otherwise insert
$this->params->set('lastrun', $now);
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->update($db->qn('#__extensions'))
->set($db->qn('params') . ' = ' .
$db->q($this->params->toString('JSON')))
->where($db->qn('type') . ' = ' .
$db->q('plugin'))
->where($db->qn('folder') . ' = ' .
$db->q('system'))
->where($db->qn('element') . ' = ' .
$db->q('updatenotification'));
try
{
// Lock the tables to prevent multiple plugin executions causing a race
condition
$db->lockTable('#__extensions');
}
catch (Exception $e)
{
// If we can't lock the tables it's too risky to continue
execution
return;
}
try
{
// Update the plugin parameters
$result = $db->setQuery($query)->execute();
$this->clearCacheGroups(array('com_plugins'), array(0, 1));
}
catch (Exception $exc)
{
// If we failed to execute
$db->unlockTables();
$result = false;
}
try
{
// Unlock the tables after writing
$db->unlockTables();
}
catch (Exception $e)
{
// If we can't lock the tables assume we have somehow failed
$result = false;
}
// Abort on failure
if (!$result)
{
return;
}
// This is the extension ID for Joomla! itself
$eid = 700;
// Get any available updates
$updater = JUpdater::getInstance();
$results = $updater->findUpdates(array($eid), $cache_timeout);
// If there are no updates our job is done. We need BOTH this check AND
the one below.
if (!$results)
{
return;
}
// Unfortunately Joomla! MVC doesn't allow us to autoload classes
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_installer/models', 'InstallerModel');
// Get the update model and retrieve the Joomla! core updates
$model = JModelLegacy::getInstance('Update',
'InstallerModel');
$model->setState('filter.extension_id', $eid);
$updates = $model->getItems();
// If there are no updates we don't have to notify anyone about
anything. This is NOT a duplicate check.
if (empty($updates))
{
return;
}
// Get the available update
$update = array_pop($updates);
// Check the available version. If it's the same or less than the
installed version we have no updates to notify about.
if (version_compare($update->version, JVERSION, 'le'))
{
return;
}
// If we're here, we have updates. First, get a link to the Joomla!
Update component.
$baseURL = JUri::base();
$baseURL = rtrim($baseURL, '/');
$baseURL .= (substr($baseURL, -13) !== 'administrator') ?
'/administrator/' : '/';
$baseURL .= 'index.php?option=com_joomlaupdate';
$uri = new JUri($baseURL);
/**
* Some third party security solutions require a secret query parameter
to allow log in to the administrator
* backend of the site. The link generated above will be invalid and
could probably block the user out of their
* site, confusing them (they can't understand the third party
security solution is not part of Joomla! proper).
* So, we're calling the onBuildAdministratorLoginURL system plugin
event to let these third party solutions
* add any necessary secret query parameters to the URL. The plugins are
supposed to have a method with the
* signature:
*
* public function onBuildAdministratorLoginURL(JUri &$uri);
*
* The plugins should modify the $uri object directly and return null.
*/
JEventDispatcher::getInstance()->trigger('onBuildAdministratorLoginURL',
array(&$uri));
// Let's find out the email addresses to notify
$superUsers = array();
$specificEmail = $this->params->get('email',
'');
if (!empty($specificEmail))
{
$superUsers = $this->getSuperUsers($specificEmail);
}
if (empty($superUsers))
{
$superUsers = $this->getSuperUsers();
}
if (empty($superUsers))
{
return;
}
/*
* Load the appropriate language. We try to load English (UK), the
current user's language and the forced
* language preference, in this order. This ensures that we'll never
end up with untranslated strings in the
* update email which would make Joomla! seem bad. So, please, if you
don't fully understand what the
* following code does DO NOT TOUCH IT. It makes the difference between a
hobbyist CMS and a professional
* solution!
*/
$jLanguage = JFactory::getLanguage();
$jLanguage->load('plg_system_updatenotification',
JPATH_ADMINISTRATOR, 'en-GB', true, true);
$jLanguage->load('plg_system_updatenotification',
JPATH_ADMINISTRATOR, null, true, false);
// Then try loading the preferred (forced) language
$forcedLanguage = $this->params->get('language_override',
'');
if (!empty($forcedLanguage))
{
$jLanguage->load('plg_system_updatenotification',
JPATH_ADMINISTRATOR, $forcedLanguage, true, false);
}
// Set up the email subject and body
$email_subject =
JText::_('PLG_SYSTEM_UPDATENOTIFICATION_EMAIL_SUBJECT');
$email_body =
JText::_('PLG_SYSTEM_UPDATENOTIFICATION_EMAIL_BODY');
// Replace merge codes with their values
$newVersion = $update->version;
$jVersion = new JVersion;
$currentVersion = $jVersion->getShortVersion();
$jConfig = JFactory::getConfig();
$sitename = $jConfig->get('sitename');
$mailFrom = $jConfig->get('mailfrom');
$fromName = $jConfig->get('fromname');
$substitutions = array(
'[NEWVERSION]' => $newVersion,
'[CURVERSION]' => $currentVersion,
'[SITENAME]' => $sitename,
'[URL]' => JUri::base(),
'[LINK]' => $uri->toString(),
'[RELEASENEWS]' =>
'https://www.joomla.org/announcements/release-news/',
'\\n' => "\n",
);
foreach ($substitutions as $k => $v)
{
$email_subject = str_replace($k, $v, $email_subject);
$email_body = str_replace($k, $v, $email_body);
}
// Send the emails to the Super Users
foreach ($superUsers as $superUser)
{
$mailer = JFactory::getMailer();
$mailer->setSender(array($mailFrom, $fromName));
$mailer->addRecipient($superUser->email);
$mailer->setSubject($email_subject);
$mailer->setBody($email_body);
$mailer->Send();
}
}
/**
* Returns the Super Users email information. If you provide a comma
separated $email list
* we will check that these emails do belong to Super Users and that they
have not blocked
* system emails.
*
* @param null|string $email A list of Super Users to email
*
* @return array The list of Super User emails
*
* @since 3.5
*/
private function getSuperUsers($email = null)
{
// Get a reference to the database object
$db = JFactory::getDbo();
// Convert the email list to an array
if (!empty($email))
{
$temp = explode(',', $email);
$emails = array();
foreach ($temp as $entry)
{
$entry = trim($entry);
$emails[] = $db->q($entry);
}
$emails = array_unique($emails);
}
else
{
$emails = array();
}
// Get a list of groups which have Super User privileges
$ret = array();
try
{
$rootId = JTable::getInstance('Asset',
'JTable')->getRootId();
$rules = JAccess::getAssetRules($rootId)->getData();
$rawGroups = $rules['core.admin']->getData();
$groups = array();
if (empty($rawGroups))
{
return $ret;
}
foreach ($rawGroups as $g => $enabled)
{
if ($enabled)
{
$groups[] = $db->q($g);
}
}
if (empty($groups))
{
return $ret;
}
}
catch (Exception $exc)
{
return $ret;
}
// Get the user IDs of users belonging to the SA groups
try
{
$query = $db->getQuery(true)
->select($db->qn('user_id'))
->from($db->qn('#__user_usergroup_map'))
->where($db->qn('group_id') . ' IN(' .
implode(',', $groups) . ')');
$db->setQuery($query);
$rawUserIDs = $db->loadColumn(0);
if (empty($rawUserIDs))
{
return $ret;
}
$userIDs = array();
foreach ($rawUserIDs as $id)
{
$userIDs[] = $db->q($id);
}
}
catch (Exception $exc)
{
return $ret;
}
// Get the user information for the Super Administrator users
try
{
$query = $db->getQuery(true)
->select(
array(
$db->qn('id'),
$db->qn('username'),
$db->qn('email'),
)
)->from($db->qn('#__users'))
->where($db->qn('id') . ' IN(' .
implode(',', $userIDs) . ')')
->where($db->qn('block') . ' = 0')
->where($db->qn('sendEmail') . ' = ' .
$db->q('1'));
if (!empty($emails))
{
$query->where('LOWER(' . $db->qn('email') .
') IN(' . implode(',',
array_map('strtolower', $emails)) . ')');
}
$db->setQuery($query);
$ret = $db->loadObjectList();
}
catch (Exception $exc)
{
return $ret;
}
return $ret;
}
/**
* Clears cache groups. We use it to clear the plugins cache after we
update the last run timestamp.
*
* @param array $clearGroups The cache groups to clean
* @param array $cacheClients The cache clients (site, admin) to clean
*
* @return void
*
* @since 3.5
*/
private function clearCacheGroups(array $clearGroups, array $cacheClients
= array(0, 1))
{
$conf = JFactory::getConfig();
foreach ($clearGroups as $group)
{
foreach ($cacheClients as $client_id)
{
try
{
$options = array(
'defaultgroup' => $group,
'cachebase' => $client_id ? JPATH_ADMINISTRATOR .
'/cache' :
$conf->get('cache_path', JPATH_SITE .
'/cache')
);
$cache = JCache::getInstance('callback', $options);
$cache->clean();
}
catch (Exception $e)
{
// Ignore it
}
}
}
}
}
system/updatenotification/updatenotification.xml000064400000003072147357022250016405
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.6" type="plugin"
group="system" method="upgrade">
<name>plg_system_updatenotification</name>
<author>Joomla! Project</author>
<creationDate>May 2015</creationDate>
<copyright>(C) 2015 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.5.0</version>
<description>PLG_SYSTEM_UPDATENOTIFICATION_XML_DESCRIPTION</description>
<files>
<filename
plugin="updatenotification">updatenotification.php</filename>
</files>
<languages folder="language">
<language
tag="en-GB">en-GB.plg_system_updatenotification.ini</language>
<language
tag="en-GB">en-GB.plg_system_updatenotification.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="email"
type="text"
label="PLG_SYSTEM_UPDATENOTIFICATION_EMAIL_LBL"
description="PLG_SYSTEM_UPDATENOTIFICATION_EMAIL_DESC"
default=""
size="40"
/>
<field
name="language_override"
type="language"
label="PLG_SYSTEM_UPDATENOTIFICATION_LANGUAGE_OVERRIDE_LBL"
description="PLG_SYSTEM_UPDATENOTIFICATION_LANGUAGE_OVERRIDE_DESC"
default=""
client="administrator"
>
<option
value="">PLG_SYSTEM_UPDATENOTIFICATION_LANGUAGE_OVERRIDE_NONE</option>
</field>
<field
name="lastrun"
type="hidden"
default="0"
size="15"
/>
</fieldset>
</fields>
</config>
</extension>
twofactorauth/totp/postinstall/actions.php000064400000003525147357022250015165
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Twofactorauth.totp
*
* @copyright (C) 2013 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*
* This file contains the functions used by the com_postinstall code to
deliver
* the necessary post-installation messages concerning the activation of
the
* two-factor authentication code.
*/
/**
* Checks if the plugin is enabled. If not it returns true, meaning that
the
* message concerning two factor authentication should be displayed.
*
* @return integer
*
* @since 3.2
*/
function twofactorauth_postinstall_condition()
{
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->select('*')
->from($db->qn('#__extensions'))
->where($db->qn('type') . ' = ' .
$db->q('plugin'))
->where($db->qn('enabled') . ' = 1')
->where($db->qn('folder') . ' = ' .
$db->q('twofactorauth'));
$db->setQuery($query);
$enabled_plugins = $db->loadObjectList();
return count($enabled_plugins) === 0;
}
/**
* Enables the two factor authentication plugin and redirects the user to
their
* user profile page so that they can enable two factor authentication on
their
* account.
*
* @return void
*
* @since 3.2
*/
function twofactorauth_postinstall_action()
{
// Enable the plugin
$db = JFactory::getDbo();
$query = $db->getQuery(true)
->update($db->qn('#__extensions'))
->set($db->qn('enabled') . ' = 1')
->where($db->qn('type') . ' = ' .
$db->q('plugin'))
->where($db->qn('folder') . ' = ' .
$db->q('twofactorauth'));
$db->setQuery($query);
$db->execute();
// Clean cache.
JFactory::getCache()->clean('com_plugins');
// Redirect the user to their profile editor page
$url = 'index.php?option=com_users&task=user.edit&id=' .
JFactory::getUser()->id;
JFactory::getApplication()->redirect($url);
}
twofactorauth/totp/tmpl/form.php000064400000005756147357022250013100
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Twofactorauth.totp.tmpl
*
* @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\HTML\HTMLHelper;
use Joomla\CMS\Factory;
HTMLHelper::_('script',
'plg_twofactorauth_totp/qrcode.min.js', array('version'
=> 'auto', 'relative' => true));
$js = "
(function(document)
{
document.addEventListener('DOMContentLoaded', function()
{
var qr = qrcode(0, 'H');
qr.addData('" . $url . "');
qr.make();
document.getElementById('totp-qrcode').innerHTML =
qr.createImgTag(4);
});
})(document);
";
Factory::getDocument()->addScriptDeclaration($js);
?>
<input type="hidden"
name="jform[twofactor][totp][key]" value="<?php echo
$secret ?>" />
<div class="well">
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_INTRO') ?>
</div>
<fieldset>
<legend>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_HEAD')
?>
</legend>
<p>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_TEXT')
?>
</p>
<ul>
<li>
<a href="<?php echo
JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_ITEM1_LINK') ?>"
target="_blank" rel="noopener noreferrer">
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_ITEM1')
?>
</a>
</li>
<li>
<a href="<?php echo
JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_ITEM2_LINK') ?>"
target="_blank" rel="noopener noreferrer">
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_ITEM2')
?>
</a>
</li>
</ul>
<div class="alert">
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_WARN')
?>
</div>
</fieldset>
<fieldset>
<legend>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_HEAD')
?>
</legend>
<div class="span6">
<p>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_TEXT')
?>
</p>
<table class="table table-striped">
<tr>
<td>
<?php echo
JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_ACCOUNT') ?>
</td>
<td>
<?php echo $username ?>@<?php echo $hostname ?>
</td>
</tr>
<tr>
<td>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_KEY')
?>
</td>
<td>
<?php echo $secret ?>
</td>
</tr>
</table>
</div>
<div class="span6">
<p>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_ALTTEXT')
?>
<br />
<div id="totp-qrcode"></div>
</p>
</div>
<div class="clearfix"></div>
<div class="alert alert-info">
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_RESET')
?>
</div>
</fieldset>
<?php if ($new_totp): ?>
<fieldset>
<legend>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP3_HEAD')
?>
</legend>
<p>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP3_TEXT')
?>
</p>
<div class="control-group">
<label class="control-label"
for="totpsecuritycode">
<?php echo
JText::_('PLG_TWOFACTORAUTH_TOTP_STEP3_SECURITYCODE') ?>
</label>
<div class="controls">
<input type="text" class="input-small"
name="jform[twofactor][totp][securitycode]"
id="totpsecuritycode" autocomplete="0">
</div>
</div>
</fieldset>
<?php endif; ?>
twofactorauth/totp/totp.php000064400000017041147357022250012135
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Twofactorauth.totp
*
* @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;
/**
* Joomla! Two Factor Authentication using Google Authenticator TOTP Plugin
*
* @since 3.2
*/
class PlgTwofactorauthTotp extends JPlugin
{
/**
* Affects constructor behavior. If true, language files will be loaded
automatically.
*
* @var boolean
* @since 3.2
*/
protected $autoloadLanguage = true;
/**
* Method name
*
* @var string
* @since 3.2
*/
protected $methodName = 'totp';
/**
* This method returns the identification object for this two factor
* authentication plugin.
*
* @return stdClass An object with public properties method and title
*
* @since 3.2
*/
public function onUserTwofactorIdentify()
{
$section = (int) $this->params->get('section', 3);
$current_section = 0;
try
{
$app = JFactory::getApplication();
if ($app->isClient('administrator'))
{
$current_section = 2;
}
elseif ($app->isClient('site'))
{
$current_section = 1;
}
}
catch (Exception $exc)
{
$current_section = 0;
}
if (!($current_section & $section))
{
return false;
}
return (object) array(
'method' => $this->methodName,
'title' =>
JText::_('PLG_TWOFACTORAUTH_TOTP_METHOD_TITLE')
);
}
/**
* Shows the configuration page for this two factor authentication method.
*
* @param object $otpConfig The two factor auth configuration object
* @param integer $userId The numeric user ID of the user whose
form we'll display
*
* @return boolean|string False if the method is not ours, the HTML of
the configuration page otherwise
*
* @see UsersModelUser::getOtpConfig
* @since 3.2
*/
public function onUserTwofactorShowConfiguration($otpConfig, $userId =
null)
{
// Create a new TOTP class with Google Authenticator compatible settings
$totp = new FOFEncryptTotp(30, 6, 10);
if ($otpConfig->method === $this->methodName)
{
// This method is already activated. Reuse the same secret key.
$secret = $otpConfig->config['code'];
}
else
{
// This methods is not activated yet. Create a new secret key.
$secret = $totp->generateSecret();
}
// These are used by Google Authenticator to tell accounts apart
$username = JFactory::getUser($userId)->username;
$hostname = JUri::getInstance()->getHost();
// This is the URL to the QR code for Google Authenticator
$url = sprintf("otpauth://totp/%s@%s?secret=%s", $username,
$hostname, $secret);
// Is this a new TOTP setup? If so, we'll have to show the code
validation field.
$new_totp = $otpConfig->method !== 'totp';
// Start output buffering
@ob_start();
// Include the form.php from a template override. If none is found use
the default.
$path =
FOFPlatform::getInstance()->getTemplateOverridePath('plg_twofactorauth_totp',
true);
JLoader::import('joomla.filesystem.file');
if (JFile::exists($path . '/form.php'))
{
include_once $path . '/form.php';
}
else
{
include_once __DIR__ . '/tmpl/form.php';
}
// Stop output buffering and get the form contents
$html = @ob_get_clean();
// Return the form contents
return array(
'method' => $this->methodName,
'form' => $html
);
}
/**
* The save handler of the two factor configuration method's
configuration
* page.
*
* @param string $method The two factor auth method for which
we'll show the config page
*
* @return boolean|stdClass False if the method doesn't match or we
have an error, OTP config object if it succeeds
*
* @see UsersModelUser::setOtpConfig
* @since 3.2
*/
public function onUserTwofactorApplyConfiguration($method)
{
if ($method !== $this->methodName)
{
return false;
}
// Get a reference to the input data object
$input = JFactory::getApplication()->input;
// Load raw data
$rawData = $input->get('jform', array(), 'array');
if (!isset($rawData['twofactor']['totp']))
{
return false;
}
$data = $rawData['twofactor']['totp'];
// Warn if the securitycode is empty
if (array_key_exists('securitycode', $data) &&
empty($data['securitycode']))
{
try
{
$app = JFactory::getApplication();
$app->enqueueMessage(JText::_('PLG_TWOFACTORAUTH_TOTP_ERR_VALIDATIONFAILED'),
'error');
}
catch (Exception $exc)
{
// This only happens when we are in a CLI application. We cannot
// enqueue a message, so just do nothing.
}
return false;
}
// Create a new TOTP class with Google Authenticator compatible settings
$totp = new FOFEncryptTotp(30, 6, 10);
// Check the security code entered by the user (exact time slot match)
$code = $totp->getCode($data['key']);
$check = $code === $data['securitycode'];
/*
* If the check fails, test the previous 30 second slot. This allow the
* user to enter the security code when it's becoming red in Google
* Authenticator app (reaching the end of its 30 second lifetime)
*/
if (!$check)
{
$time = time() - 30;
$code = $totp->getCode($data['key'], $time);
$check = $code === $data['securitycode'];
}
/*
* If the check fails, test the next 30 second slot. This allows some
* time drift between the authentication device and the server
*/
if (!$check)
{
$time = time() + 30;
$code = $totp->getCode($data['key'], $time);
$check = $code === $data['securitycode'];
}
if (!$check)
{
// Check failed. Do not change two factor authentication settings.
return false;
}
// Check succeeded; return an OTP configuration object
$otpConfig = (object) array(
'method' => 'totp',
'config' => array(
'code' => $data['key']
),
'otep' => array()
);
return $otpConfig;
}
/**
* This method should handle any two factor authentication and report back
* to the subject.
*
* @param array $credentials Array holding the user credentials
* @param array $options Array of extra options
*
* @return boolean True if the user is authorised with this two-factor
authentication method
*
* @since 3.2
*/
public function onUserTwofactorAuthenticate($credentials, $options)
{
// Get the OTP configuration object
$otpConfig = $options['otp_config'];
// Make sure it's an object
if (empty($otpConfig) || !is_object($otpConfig))
{
return false;
}
// Check if we have the correct method
if ($otpConfig->method !== $this->methodName)
{
return false;
}
// Check if there is a security code
if (empty($credentials['secretkey']))
{
return false;
}
// Create a new TOTP class with Google Authenticator compatible settings
$totp = new FOFEncryptTotp(30, 6, 10);
// Check the code
$code = $totp->getCode($otpConfig->config['code']);
$check = $code === $credentials['secretkey'];
/*
* If the check fails, test the previous 30 second slot. This allow the
* user to enter the security code when it's becoming red in Google
* Authenticator app (reaching the end of its 30 second lifetime)
*/
if (!$check)
{
$time = time() - 30;
$code = $totp->getCode($otpConfig->config['code'],
$time);
$check = $code === $credentials['secretkey'];
}
/*
* If the check fails, test the next 30 second slot. This allows some
* time drift between the authentication device and the server
*/
if (!$check)
{
$time = time() + 30;
$code = $totp->getCode($otpConfig->config['code'],
$time);
$check = $code === $credentials['secretkey'];
}
return $check;
}
}
twofactorauth/totp/totp.xml000064400000002557147357022250012154
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="twofactorauth" method="upgrade">
<name>plg_twofactorauth_totp</name>
<author>Joomla! Project</author>
<creationDate>August 2013</creationDate>
<copyright>(C) 2013 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.0</version>
<description>PLG_TWOFACTORAUTH_TOTP_XML_DESCRIPTION</description>
<files>
<filename plugin="totp">totp.php</filename>
<folder>postinstall</folder>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_twofactorauth_totp.ini</language>
<language
tag="en-GB">en-GB.plg_twofactorauth_totp.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="section"
type="radio"
label="PLG_TWOFACTORAUTH_TOTP_SECTION_LABEL"
description="PLG_TWOFACTORAUTH_TOTP_SECTION_DESC"
default="3"
filter="integer"
class="btn-group"
>
<option
value="1">PLG_TWOFACTORAUTH_TOTP_SECTION_SITE</option>
<option
value="2">PLG_TWOFACTORAUTH_TOTP_SECTION_ADMIN</option>
<option
value="3">PLG_TWOFACTORAUTH_TOTP_SECTION_BOTH</option>
</field>
</fieldset>
</fields>
</config>
</extension>
twofactorauth/yubikey/tmpl/form.php000064400000002145147357022250013560
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Twofactorauth.yubikey.tmpl
*
* @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;
?>
<div class="well">
<?php echo JText::_('PLG_TWOFACTORAUTH_YUBIKEY_INTRO') ?>
</div>
<?php if ($new_totp): ?>
<fieldset>
<legend>
<?php echo JText::_('PLG_TWOFACTORAUTH_YUBIKEY_STEP1_HEAD')
?>
</legend>
<p>
<?php echo JText::_('PLG_TWOFACTORAUTH_YUBIKEY_STEP1_TEXT')
?>
</p>
<div class="control-group">
<label class="control-label"
for="yubikeysecuritycode">
<?php echo
JText::_('PLG_TWOFACTORAUTH_YUBIKEY_SECURITYCODE') ?>
</label>
<div class="controls">
<input type="text" class="input-medium"
name="jform[twofactor][yubikey][securitycode]"
id="yubikeysecuritycode" autocomplete="0">
</div>
</div>
</fieldset>
<?php else: ?>
<fieldset>
<legend>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_RESET_HEAD')
?>
</legend>
<p>
<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_RESET_TEXT')
?>
</p>
</fieldset>
<?php endif; ?>
twofactorauth/yubikey/yubikey.php000064400000020512147357022250013320
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Twofactorauth.yubikey
*
* @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;
/**
* Joomla! Two Factor Authentication using Yubikey Plugin
*
* @since 3.2
*/
class PlgTwofactorauthYubikey extends JPlugin
{
/**
* Affects constructor behavior. If true, language files will be loaded
automatically.
*
* @var boolean
* @since 3.2
*/
protected $autoloadLanguage = true;
/**
* Method name
*
* @var string
* @since 3.2
*/
protected $methodName = 'yubikey';
/**
* This method returns the identification object for this two factor
* authentication plugin.
*
* @return stdClass An object with public properties method and title
*
* @since 3.2
*/
public function onUserTwofactorIdentify()
{
$section = (int) $this->params->get('section',
3);
$current_section = 0;
try
{
$app = JFactory::getApplication();
if ($app->isClient('administrator'))
{
$current_section = 2;
}
elseif ($app->isClient('site'))
{
$current_section = 1;
}
}
catch (Exception $exc)
{
$current_section = 0;
}
if (!($current_section & $section))
{
return false;
}
return (object) array(
'method' => $this->methodName,
'title' =>
JText::_('PLG_TWOFACTORAUTH_YUBIKEY_METHOD_TITLE'),
);
}
/**
* Shows the configuration page for this two factor authentication method.
*
* @param object $otpConfig The two factor auth configuration object
* @param integer $userId The numeric user ID of the user whose
form we'll display
*
* @return boolean|string False if the method is not ours, the HTML of
the configuration page otherwise
*
* @see UsersModelUser::getOtpConfig
* @since 3.2
*/
public function onUserTwofactorShowConfiguration($otpConfig, $userId =
null)
{
if ($otpConfig->method === $this->methodName)
{
// This method is already activated. Reuse the same Yubikey ID.
$yubikey = $otpConfig->config['yubikey'];
}
else
{
// This methods is not activated yet. We'll need a Yubikey TOTP to
setup this Yubikey.
$yubikey = '';
}
// Is this a new TOTP setup? If so, we'll have to show the code
validation field.
$new_totp = $otpConfig->method !== $this->methodName;
// Start output buffering
@ob_start();
// Include the form.php from a template override. If none is found use
the default.
$path =
FOFPlatform::getInstance()->getTemplateOverridePath('plg_twofactorauth_yubikey',
true);
JLoader::import('joomla.filesystem.file');
if (JFile::exists($path . '/form.php'))
{
include_once $path . '/form.php';
}
else
{
include_once __DIR__ . '/tmpl/form.php';
}
// Stop output buffering and get the form contents
$html = @ob_get_clean();
// Return the form contents
return array(
'method' => $this->methodName,
'form' => $html,
);
}
/**
* The save handler of the two factor configuration method's
configuration
* page.
*
* @param string $method The two factor auth method for which
we'll show the config page
*
* @return boolean|stdClass False if the method doesn't match or we
have an error, OTP config object if it succeeds
*
* @see UsersModelUser::setOtpConfig
* @since 3.2
*/
public function onUserTwofactorApplyConfiguration($method)
{
if ($method !== $this->methodName)
{
return false;
}
// Get a reference to the input data object
$input = JFactory::getApplication()->input;
// Load raw data
$rawData = $input->get('jform', array(), 'array');
if (!isset($rawData['twofactor']['yubikey']))
{
return false;
}
$data = $rawData['twofactor']['yubikey'];
// Warn if the securitycode is empty
if (array_key_exists('securitycode', $data) &&
empty($data['securitycode']))
{
try
{
JFactory::getApplication()->enqueueMessage(JText::_('PLG_TWOFACTORAUTH_YUBIKEY_ERR_VALIDATIONFAILED'),
'error');
}
catch (Exception $exc)
{
// This only happens when we are in a CLI application. We cannot
// enqueue a message, so just do nothing.
}
return false;
}
// Validate the Yubikey OTP
$check = $this->validateYubikeyOtp($data['securitycode']);
if (!$check)
{
JFactory::getApplication()->enqueueMessage(JText::_('PLG_TWOFACTORAUTH_YUBIKEY_ERR_VALIDATIONFAILED'),
'error');
// Check failed. Do not change two factor authentication settings.
return false;
}
// Remove the last 32 digits and store the rest in the user configuration
parameters
$yubikey = substr($data['securitycode'], 0, -32);
// Check succeeded; return an OTP configuration object
$otpConfig = (object) array(
'method' => $this->methodName,
'config' => array(
'yubikey' => $yubikey
),
'otep' => array()
);
return $otpConfig;
}
/**
* This method should handle any two factor authentication and report back
* to the subject.
*
* @param array $credentials Array holding the user credentials
* @param array $options Array of extra options
*
* @return boolean True if the user is authorised with this two-factor
authentication method
*
* @since 3.2
*/
public function onUserTwofactorAuthenticate($credentials, $options)
{
// Get the OTP configuration object
$otpConfig = $options['otp_config'];
// Make sure it's an object
if (empty($otpConfig) || !is_object($otpConfig))
{
return false;
}
// Check if we have the correct method
if ($otpConfig->method !== $this->methodName)
{
return false;
}
// Check if there is a security code
if (empty($credentials['secretkey']))
{
return false;
}
// Check if the Yubikey starts with the configured Yubikey user string
$yubikey_valid = $otpConfig->config['yubikey'];
$yubikey = substr($credentials['secretkey'], 0, -32);
$check = $yubikey === $yubikey_valid;
if ($check)
{
$check =
$this->validateYubikeyOtp($credentials['secretkey']);
}
return $check;
}
/**
* Validates a Yubikey OTP against the Yubikey servers
*
* @param string $otp The OTP generated by your Yubikey
*
* @return boolean True if it's a valid OTP
*
* @since 3.2
*/
public function validateYubikeyOtp($otp)
{
$server_queue = array(
'api.yubico.com',
'api2.yubico.com',
'api3.yubico.com',
'api4.yubico.com',
'api5.yubico.com',
);
shuffle($server_queue);
$gotResponse = false;
$check = false;
$token = JSession::getFormToken();
$nonce = md5($token . uniqid(mt_rand()));
while (!$gotResponse && !empty($server_queue))
{
$server = array_shift($server_queue);
$uri = new JUri('https://' . $server .
'/wsapi/2.0/verify');
// I don't see where this ID is used?
$uri->setVar('id', 1);
// The OTP we read from the user
$uri->setVar('otp', $otp);
// This prevents a REPLAYED_OTP status of the token doesn't change
// after a user submits an invalid OTP
$uri->setVar('nonce', $nonce);
// Minimum service level required: 50% (at least 50% of the YubiCloud
// servers must reply positively for the OTP to validate)
$uri->setVar('sl', 50);
// Timeou waiting for YubiCloud servers to reply: 5 seconds.
$uri->setVar('timeout', 5);
try
{
$http = JHttpFactory::getHttp();
$response = $http->get($uri->toString(), null, 6);
if (!empty($response))
{
$gotResponse = true;
}
else
{
continue;
}
}
catch (Exception $exc)
{
// No response, continue with the next server
continue;
}
}
// No server replied; we can't validate this OTP
if (!$gotResponse)
{
return false;
}
// Parse response
$lines = explode("\n", $response->body);
$data = array();
foreach ($lines as $line)
{
$line = trim($line);
$parts = explode('=', $line, 2);
if (count($parts) < 2)
{
continue;
}
$data[$parts[0]] = $parts[1];
}
// Validate the response - We need an OK message reply
if ($data['status'] !== 'OK')
{
return false;
}
// Validate the response - We need a confidence level over 50%
if ($data['sl'] < 50)
{
return false;
}
// Validate the response - The OTP must match
if ($data['otp'] !== $otp)
{
return false;
}
// Validate the response - The token must match
if ($data['nonce'] !== $nonce)
{
return false;
}
return true;
}
}
twofactorauth/yubikey/yubikey.xml000064400000002564147357022250013340
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="twofactorauth" method="upgrade">
<name>plg_twofactorauth_yubikey</name>
<author>Joomla! Project</author>
<creationDate>September 2013</creationDate>
<copyright>(C) 2013 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.0</version>
<description>PLG_TWOFACTORAUTH_YUBIKEY_XML_DESCRIPTION</description>
<files>
<filename plugin="yubikey">yubikey.php</filename>
<folder>tmpl</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_twofactorauth_yubikey.ini</language>
<language
tag="en-GB">en-GB.plg_twofactorauth_yubikey.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="section"
type="radio"
label="PLG_TWOFACTORAUTH_YUBIKEY_SECTION_LABEL"
description="PLG_TWOFACTORAUTH_YUBIKEY_SECTION_DESC"
default="3"
filter="integer"
class="btn-group"
>
<option
value="1">PLG_TWOFACTORAUTH_YUBIKEY_SECTION_SITE</option>
<option
value="2">PLG_TWOFACTORAUTH_YUBIKEY_SECTION_ADMIN</option>
<option
value="3">PLG_TWOFACTORAUTH_YUBIKEY_SECTION_BOTH</option>
</field>
</fieldset>
</fields>
</config>
</extension>
user/contactcreator/contactcreator.php000064400000010207147357022250014270
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage User.contactcreator
*
* @copyright (C) 2010 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Table\Table;
use Joomla\String\StringHelper;
/**
* Class for Contact Creator
*
* A tool to automatically create and synchronise contacts with a user
*
* @since 1.6
*/
class PlgUserContactCreator extends JPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Utility method to act on a user after it has been saved.
*
* This method creates a contact for the saved user
*
* @param array $user Holds the new user data.
* @param boolean $isnew True if a new user is stored.
* @param boolean $success True if user was successfully stored in the
database.
* @param string $msg Message.
*
* @return boolean
*
* @since 1.6
*/
public function onUserAfterSave($user, $isnew, $success, $msg)
{
// If the user wasn't stored we don't resync
if (!$success)
{
return false;
}
// If the user isn't new we don't sync
if (!$isnew)
{
return false;
}
// Ensure the user id is really an int
$user_id = (int) $user['id'];
// If the user id appears invalid then bail out just in case
if (empty($user_id))
{
return false;
}
$categoryId = $this->params->get('category', 0);
if (empty($categoryId))
{
JError::raiseWarning('',
Text::_('PLG_CONTACTCREATOR_ERR_NO_CATEGORY'));
return false;
}
if ($contact = $this->getContactTable())
{
/**
* Try to pre-load a contact for this user. Apparently only possible if
other plugin creates it
* Note: $user_id is cleaned above
*/
if (!$contact->load(array('user_id' => (int) $user_id)))
{
$contact->published =
$this->params->get('autopublish', 0);
}
$contact->name = $user['name'];
$contact->user_id = $user_id;
$contact->email_to = $user['email'];
$contact->catid = $categoryId;
$contact->access = (int)
Factory::getConfig()->get('access');
$contact->language = '*';
$contact->generateAlias();
// Check if the contact already exists to generate new name & alias
if required
if ($contact->id == 0)
{
list($name, $alias) =
$this->generateAliasAndName($contact->alias, $contact->name,
$categoryId);
$contact->name = $name;
$contact->alias = $alias;
}
$autowebpage = $this->params->get('autowebpage',
'');
if (!empty($autowebpage))
{
// Search terms
$search_array = array('[name]', '[username]',
'[userid]', '[email]');
// Replacement terms, urlencoded
$replace_array = array_map('urlencode',
array($user['name'], $user['username'],
$user['id'], $user['email']));
// Now replace it in together
$contact->webpage = str_replace($search_array, $replace_array,
$autowebpage);
}
if ($contact->check() && $contact->store())
{
return true;
}
}
JError::raiseWarning('',
Text::_('PLG_CONTACTCREATOR_ERR_FAILED_CREATING_CONTACT'));
return false;
}
/**
* Method to change the name & alias if alias is already in use
*
* @param string $alias The alias.
* @param string $name The name.
* @param integer $categoryId Category identifier
*
* @return array Contains the modified title and alias.
*
* @since 3.2.3
*/
protected function generateAliasAndName($alias, $name, $categoryId)
{
$table = $this->getContactTable();
while ($table->load(array('alias' => $alias,
'catid' => $categoryId)))
{
if ($name === $table->name)
{
$name = StringHelper::increment($name);
}
$alias = StringHelper::increment($alias, 'dash');
}
return array($name, $alias);
}
/**
* Get an instance of the contact table
*
* @return ContactTableContact
*
* @since 3.2.3
*/
protected function getContactTable()
{
Table::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_contact/tables');
return Table::getInstance('contact', 'ContactTable');
}
}
user/contactcreator/contactcreator.xml000064400000003153147357022250014303
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="user" method="upgrade">
<name>plg_user_contactcreator</name>
<author>Joomla! Project</author>
<creationDate>August 2009</creationDate>
<copyright>(C) 2009 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_CONTACTCREATOR_XML_DESCRIPTION</description>
<files>
<filename
plugin="contactcreator">contactcreator.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_user_contactcreator.ini</language>
<language
tag="en-GB">en-GB.plg_user_contactcreator.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="autowebpage"
type="text"
label="PLG_CONTACTCREATOR_FIELD_AUTOMATIC_WEBPAGE_LABEL"
description="PLG_CONTACTCREATOR_FIELD_AUTOMATIC_WEBPAGE_DESC"
size="40"
/>
<field
name="category"
type="category"
label="JCATEGORY"
description="PLG_CONTACTCREATOR_FIELD_CATEGORY_DESC"
extension="com_contact"
filter="integer"
/>
<field
name="autopublish"
type="radio"
label="PLG_CONTACTCREATOR_FIELD_AUTOPUBLISH_LABEL"
description="PLG_CONTACTCREATOR_FIELD_AUTOPUBLISH_DESC"
class="btn-group btn-group-yesno"
default="0"
filter="integer"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
user/joomla/joomla.php000064400000024417147357022250011014 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage User.joomla
*
* @copyright (C) 2006 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\User\User;
use Joomla\CMS\User\UserHelper;
use Joomla\Registry\Registry;
/**
* Joomla User plugin
*
* @since 1.5
*/
class PlgUserJoomla extends JPlugin
{
/**
* Application object
*
* @var JApplicationCms
* @since 3.2
*/
protected $app;
/**
* Database object
*
* @var JDatabaseDriver
* @since 3.2
*/
protected $db;
/**
* Set as required the passwords fields when mail to user is set to No
*
* @param JForm $form The form to be altered.
* @param mixed $data The associated data for the form.
*
* @return boolean
*
* @since 3.9.2
*/
public function onContentPrepareForm($form, $data)
{
// Check we are manipulating a valid user form before modifying it.
$name = $form->getName();
if ($name === 'com_users.user')
{
// In case there is a validation error (like duplicated user), $data is
an empty array on save.
// After returning from error, $data is an array but populated
if (!$data)
{
$data = JFactory::getApplication()->input->get('jform',
array(), 'array');
}
if (is_array($data))
{
$data = (object) $data;
}
// Passwords fields are required when mail to user is set to No
if (empty($data->id) &&
!$this->params->get('mail_to_user', 1))
{
$form->setFieldAttribute('password', 'required',
'true');
$form->setFieldAttribute('password2',
'required', 'true');
}
}
return true;
}
/**
* Remove all sessions for the user name
*
* Method is called after user data is deleted from the database
*
* @param array $user Holds the user data
* @param boolean $success True if user was successfully stored in the
database
* @param string $msg Message
*
* @return boolean
*
* @since 1.6
*/
public function onUserAfterDelete($user, $success, $msg)
{
if (!$success)
{
return false;
}
$query = $this->db->getQuery(true)
->delete($this->db->quoteName('#__session'))
->where($this->db->quoteName('userid') . ' =
' . (int) $user['id']);
try
{
$this->db->setQuery($query)->execute();
}
catch (JDatabaseExceptionExecuting $e)
{
return false;
}
$query = $this->db->getQuery(true)
->delete($this->db->quoteName('#__messages'))
->where($this->db->quoteName('user_id_from') . '
= ' . (int) $user['id']);
try
{
$this->db->setQuery($query)->execute();
}
catch (JDatabaseExceptionExecuting $e)
{
return false;
}
return true;
}
/**
* Utility method to act on a user after it has been saved.
*
* This method sends a registration email to new users created in the
backend.
*
* @param array $user Holds the new user data.
* @param boolean $isnew True if a new user is stored.
* @param boolean $success True if user was successfully stored in the
database.
* @param string $msg Message.
*
* @return void
*
* @since 1.6
*/
public function onUserAfterSave($user, $isnew, $success, $msg)
{
$mail_to_user = $this->params->get('mail_to_user', 1);
if (!$isnew || !$mail_to_user)
{
return;
}
// TODO: Suck in the frontend registration emails here as well. Job for a
rainy day.
// The method check here ensures that if running as a CLI Application we
don't get any errors
if (method_exists($this->app, 'isClient') &&
!$this->app->isClient('administrator'))
{
return;
}
// Check if we have a sensible from email address, if not bail out as
mail would not be sent anyway
if (strpos($this->app->get('mailfrom'), '@')
=== false)
{
$this->app->enqueueMessage(Text::_('JERROR_SENDING_EMAIL'),
'warning');
return;
}
$lang = Factory::getLanguage();
$defaultLocale = $lang->getTag();
/**
* Look for user language. Priority:
* 1. User frontend language
* 2. User backend language
*/
$userParams = new Registry($user['params']);
$userLocale = $userParams->get('language',
$userParams->get('admin_language', $defaultLocale));
if ($userLocale !== $defaultLocale)
{
$lang->setLanguage($userLocale);
}
$lang->load('plg_user_joomla', JPATH_ADMINISTRATOR);
// Compute the mail subject.
$emailSubject = Text::sprintf(
'PLG_USER_JOOMLA_NEW_USER_EMAIL_SUBJECT',
$user['name'],
$this->app->get('sitename')
);
// Compute the mail body.
$emailBody = Text::sprintf(
'PLG_USER_JOOMLA_NEW_USER_EMAIL_BODY',
$user['name'],
$this->app->get('sitename'),
Uri::root(),
$user['username'],
$user['password_clear']
);
$res = Factory::getMailer()->sendMail(
$this->app->get('mailfrom'),
$this->app->get('fromname'),
$user['email'],
$emailSubject,
$emailBody
);
if ($res === false)
{
$this->app->enqueueMessage(Text::_('JERROR_SENDING_EMAIL'),
'warning');
}
// Set application language back to default if we changed it
if ($userLocale !== $defaultLocale)
{
$lang->setLanguage($defaultLocale);
}
}
/**
* This method should handle any login logic and report back to the
subject
*
* @param array $user Holds the user data
* @param array $options Array holding options (remember,
autoregister, group)
*
* @return boolean True on success
*
* @since 1.5
*/
public function onUserLogin($user, $options = array())
{
$instance = $this->_getUser($user, $options);
// If _getUser returned an error, then pass it back.
if ($instance instanceof Exception)
{
return false;
}
// If the user is blocked, redirect with an error
if ($instance->block == 1)
{
$this->app->enqueueMessage(Text::_('JERROR_NOLOGIN_BLOCKED'),
'warning');
return false;
}
// Authorise the user based on the group information
if (!isset($options['group']))
{
$options['group'] = 'USERS';
}
// Check the user can login.
$result = $instance->authorise($options['action']);
if (!$result)
{
$this->app->enqueueMessage(Text::_('JERROR_LOGIN_DENIED'),
'warning');
return false;
}
// Mark the user as logged in
$instance->guest = 0;
$session = Factory::getSession();
// Grab the current session ID
$oldSessionId = $session->getId();
// Fork the session
$session->fork();
$session->set('user', $instance);
// Ensure the new session's metadata is written to the database
$this->app->checkSession();
// Purge the old session
$query = $this->db->getQuery(true)
->delete('#__session')
->where($this->db->quoteName('session_id') . ' =
' . $this->db->quoteBinary($oldSessionId));
try
{
$this->db->setQuery($query)->execute();
}
catch (RuntimeException $e)
{
// The old session is already invalidated, don't let this block
logging in
}
// Hit the user last visit field
$instance->setLastVisit();
// Add "user state" cookie used for reverse caching proxies
like Varnish, Nginx etc.
if ($this->app->isClient('site'))
{
$this->app->input->cookie->set(
'joomla_user_state',
'logged_in',
0,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''),
$this->app->isHttpsForced(),
true
);
}
return true;
}
/**
* This method should handle any logout logic and report back to the
subject
*
* @param array $user Holds the user data.
* @param array $options Array holding options (client, ...).
*
* @return boolean True on success
*
* @since 1.5
*/
public function onUserLogout($user, $options = array())
{
$my = Factory::getUser();
$session = Factory::getSession();
// Make sure we're a valid user first
if ($user['id'] == 0 &&
!$my->get('tmp_user'))
{
return true;
}
$sharedSessions = $this->app->get('shared_session',
'0');
// Check to see if we're deleting the current session
if ($my->id == $user['id'] && ($sharedSessions ||
(!$sharedSessions && $options['clientid'] ==
$this->app->getClientId())))
{
// Hit the user last visit field
$my->setLastVisit();
// Destroy the php session for this user
$session->destroy();
}
// Enable / Disable Forcing logout all users with same userid
$forceLogout = $this->params->get('forceLogout', 1);
if ($forceLogout)
{
$clientId = (!$sharedSessions) ? (int) $options['clientid'] :
null;
UserHelper::destroyUserSessions($user['id'], false,
$clientId);
}
// Delete "user state" cookie used for reverse caching proxies
like Varnish, Nginx etc.
if ($this->app->isClient('site'))
{
$this->app->input->cookie->set('joomla_user_state',
'', 1, $this->app->get('cookie_path',
'/'), $this->app->get('cookie_domain',
''));
}
return true;
}
/**
* This method will return a user object
*
* If options['autoregister'] is true, if the user doesn't
exist yet they will be created
*
* @param array $user Holds the user data.
* @param array $options Array holding options (remember,
autoregister, group).
*
* @return User
*
* @since 1.5
*/
protected function _getUser($user, $options = array())
{
$instance = User::getInstance();
$id = (int) UserHelper::getUserId($user['username']);
if ($id)
{
$instance->load($id);
return $instance;
}
// TODO : move this out of the plugin
$params = ComponentHelper::getParams('com_users');
// Read the default user group option from com_users
$defaultUserGroup = $params->get('new_usertype',
$params->get('guest_usergroup', 1));
$instance->id = 0;
$instance->name = $user['fullname'];
$instance->username = $user['username'];
$instance->password_clear = $user['password_clear'];
// Result should contain an email (check).
$instance->email = $user['email'];
$instance->groups = array($defaultUserGroup);
// If autoregister is set let's register the user
$autoregister = isset($options['autoregister']) ?
$options['autoregister'] :
$this->params->get('autoregister', 1);
if ($autoregister)
{
if (!$instance->save())
{
JLog::add('Error in autoregistration for user ' .
$user['username'] . '.', JLog::WARNING,
'error');
}
}
else
{
// No existing user and autoregister off, this is a temporary user.
$instance->set('tmp_user', true);
}
return $instance;
}
}
user/joomla/joomla.xml000064400000003417147357022250011022 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="user" method="upgrade">
<name>plg_user_joomla</name>
<author>Joomla! Project</author>
<creationDate>December 2006</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_USER_JOOMLA_XML_DESCRIPTION</description>
<files>
<filename plugin="joomla">joomla.php</filename>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_user_joomla.ini</language>
<language
tag="en-GB">en-GB.plg_user_joomla.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="autoregister"
type="radio"
label="PLG_USER_JOOMLA_FIELD_AUTOREGISTER_LABEL"
description="PLG_USER_JOOMLA_FIELD_AUTOREGISTER_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="mail_to_user"
type="radio"
label="PLG_USER_JOOMLA_FIELD_MAILTOUSER_LABEL"
description="PLG_USER_JOOMLA_FIELD_MAILTOUSER_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field
name="forceLogout"
type="radio"
label="PLG_USER_JOOMLA_FIELD_FORCELOGOUT_LABEL"
description="PLG_USER_JOOMLA_FIELD_FORCELOGOUT_DESC"
class="btn-group btn-group-yesno"
default="1"
>
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</fields>
</config>
</extension>
user/profile/field/dob.php000064400000002720147357022250011532
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage User.profile
*
* @copyright (C) 2014 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('JPATH_PLATFORM') or die;
JFormHelper::loadFieldClass('calendar');
/**
* Provides input for "Date of Birth" field
*
* @package Joomla.Plugin
* @subpackage User.profile
* @since 3.3.7
*/
class JFormFieldDob extends JFormFieldCalendar
{
/**
* The form field type.
*
* @var string
* @since 3.3.7
*/
protected $type = 'Dob';
/**
* Method to get the field label markup.
*
* @return string The field label markup.
*
* @since 3.3.7
*/
protected function getLabel()
{
$label = parent::getLabel();
// Get the info text from the XML element, defaulting to empty.
$text = $this->element['info'] ? (string)
$this->element['info'] : '';
$text = $this->translateLabel ? JText::_($text) : $text;
if ($text)
{
$app = JFactory::getApplication();
$layout = new JLayoutFile('plugins.user.profile.fields.dob');
$view = $app->input->getString('view', '');
// Only display the tip when editing profile
if ($view === 'registration' || $view === 'profile'
|| $app->isClient('administrator'))
{
$layout = new JLayoutFile('plugins.user.profile.fields.dob');
$info = $layout->render(array('text' => $text));
$label = $info . $label;
}
}
return $label;
}
}
user/profile/field/tos.php000064400000007025147357022250011576
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage User.profile
*
* @copyright (C) 2012 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('JPATH_PLATFORM') or die;
JFormHelper::loadFieldClass('radio');
/**
* Provides input for TOS
*
* @since 2.5.5
*/
class JFormFieldTos extends JFormFieldRadio
{
/**
* The form field type.
*
* @var string
* @since 2.5.5
*/
protected $type = 'Tos';
/**
* Method to get the field label markup.
*
* @return string The field label markup.
*
* @since 2.5.5
*/
protected function getLabel()
{
$label = '';
if ($this->hidden)
{
return $label;
}
// Get the label text from the XML element, defaulting to the element
name.
$text = $this->element['label'] ? (string)
$this->element['label'] : (string)
$this->element['name'];
$text = $this->translateLabel ? JText::_($text) : $text;
// Set required to true as this field is not displayed at all if not
required.
$this->required = true;
// Build the class for the label.
$class = !empty($this->description) ? 'hasPopover' :
'';
$class = $class . ' required';
$class = !empty($this->labelClass) ? $class . ' ' .
$this->labelClass : $class;
// Add the opening label tag and main attributes attributes.
$label .= '<label id="' . $this->id .
'-lbl" for="' . $this->id . '"
class="' . $class . '"';
// If a description is specified, use it to build a tooltip.
if (!empty($this->description))
{
$label .= ' title="' . htmlspecialchars(trim($text,
':'), ENT_COMPAT, 'UTF-8') . '"';
$label .= ' data-content="' . htmlspecialchars(
$this->translateDescription ? JText::_($this->description) :
$this->description,
ENT_COMPAT,
'UTF-8'
) . '"';
if (JFactory::getLanguage()->isRtl())
{
$label .= ' data-placement="left"';
}
}
$tosArticle = $this->element['article'] > 0 ? (int)
$this->element['article'] : 0;
if ($tosArticle)
{
JHtml::_('behavior.modal');
JLoader::register('ContentHelperRoute', JPATH_BASE .
'/components/com_content/helpers/route.php');
$attribs = array();
$attribs['class'] = 'modal';
$attribs['rel'] = '{handler: \'iframe\',
size: {x:800, y:500}}';
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('id, alias, catid, language')
->from('#__content')
->where('id = ' . $tosArticle);
$db->setQuery($query);
$article = $db->loadObject();
if (JLanguageAssociations::isEnabled())
{
$tosAssociated =
JLanguageAssociations::getAssociations('com_content',
'#__content', 'com_content.item', $tosArticle);
}
$currentLang = JFactory::getLanguage()->getTag();
if (isset($tosAssociated) && $currentLang !==
$article->language && array_key_exists($currentLang,
$tosAssociated))
{
$url = ContentHelperRoute::getArticleRoute(
$tosAssociated[$currentLang]->id,
$tosAssociated[$currentLang]->catid,
$tosAssociated[$currentLang]->language
);
$link = JHtml::_('link', JRoute::_($url .
'&tmpl=component'), $text, $attribs);
}
else
{
$slug = $article->alias ? ($article->id . ':' .
$article->alias) : $article->id;
$url = ContentHelperRoute::getArticleRoute($slug, $article->catid,
$article->language);
$link = JHtml::_('link', JRoute::_($url .
'&tmpl=component'), $text, $attribs);
}
}
else
{
$link = $text;
}
// Add the label text and closing tag.
$label .= '>' . $link . '<span
class="star"> *</span></label>';
return $label;
}
}
user/profile/profile.php000064400000032073147357022250011347
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage User.profile
*
* @copyright (C) 2009 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Date\Date;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Form\FormHelper;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\String\PunycodeHelper;
use Joomla\Utilities\ArrayHelper;
/**
* An example custom profile plugin.
*
* @since 1.6
*/
class PlgUserProfile extends JPlugin
{
/**
* Date of birth.
*
* @var string
* @since 3.1
*/
private $date = '';
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.1
*/
protected $autoloadLanguage = true;
/**
* Constructor
*
* @param object &$subject The object to observe
* @param array $config An array that holds the plugin
configuration
*
* @since 1.5
*/
public function __construct(& $subject, $config)
{
parent::__construct($subject, $config);
FormHelper::addFieldPath(__DIR__ . '/field');
}
/**
* Runs on content preparation
*
* @param string $context The context for the data
* @param object $data An object containing the data for the form.
*
* @return boolean
*
* @since 1.6
*/
public function onContentPrepareData($context, $data)
{
// Check we are manipulating a valid form.
if (!in_array($context, array('com_users.profile',
'com_users.user', 'com_users.registration',
'com_admin.profile')))
{
return true;
}
if (is_object($data))
{
$userId = isset($data->id) ? $data->id : 0;
if (!isset($data->profile) && $userId > 0)
{
// Load the profile data from the database.
$db = Factory::getDbo();
$db->setQuery(
'SELECT profile_key, profile_value FROM #__user_profiles'
. ' WHERE user_id = ' . (int) $userId . " AND
profile_key LIKE 'profile.%'"
. ' ORDER BY ordering'
);
try
{
$results = $db->loadRowList();
}
catch (RuntimeException $e)
{
$this->_subject->setError($e->getMessage());
return false;
}
// Merge the profile data.
$data->profile = array();
foreach ($results as $v)
{
$k = str_replace('profile.', '', $v[0]);
$data->profile[$k] = json_decode($v[1], true);
if ($data->profile[$k] === null)
{
$data->profile[$k] = $v[1];
}
}
}
if (!HTMLHelper::isRegistered('users.url'))
{
HTMLHelper::register('users.url', array(__CLASS__,
'url'));
}
if (!HTMLHelper::isRegistered('users.calendar'))
{
HTMLHelper::register('users.calendar', array(__CLASS__,
'calendar'));
}
if (!HTMLHelper::isRegistered('users.tos'))
{
HTMLHelper::register('users.tos', array(__CLASS__,
'tos'));
}
if (!HTMLHelper::isRegistered('users.dob'))
{
HTMLHelper::register('users.dob', array(__CLASS__,
'dob'));
}
}
return true;
}
/**
* Returns an anchor tag generated from a given value
*
* @param string $value URL to use
*
* @return mixed|string
*/
public static function url($value)
{
if (empty($value))
{
return HTMLHelper::_('users.value', $value);
}
else
{
// Convert website URL to utf8 for display
$value = PunycodeHelper::urlToUTF8(htmlspecialchars($value));
if (strpos($value, 'http') === 0)
{
return '<a href="' . $value . '">'
. $value . '</a>';
}
else
{
return '<a href="http://' . $value .
'">' . $value . '</a>';
}
}
}
/**
* Returns html markup showing a date picker
*
* @param string $value valid date string
*
* @return mixed
*/
public static function calendar($value)
{
if (empty($value))
{
return HTMLHelper::_('users.value', $value);
}
else
{
return HTMLHelper::_('date', $value, null, null);
}
}
/**
* Returns the date of birth formatted and calculated using server
timezone.
*
* @param string $value valid date string
*
* @return mixed
*/
public static function dob($value)
{
if (!$value)
{
return '';
}
return HTMLHelper::_('date', $value,
Text::_('DATE_FORMAT_LC1'), false);
}
/**
* Return the translated strings yes or no depending on the value
*
* @param boolean $value input value
*
* @return string
*/
public static function tos($value)
{
if ($value)
{
return Text::_('JYES');
}
else
{
return Text::_('JNO');
}
}
/**
* Adds additional fields to the user editing form
*
* @param Form $form The form to be altered.
* @param mixed $data The associated data for the form.
*
* @return boolean
*
* @since 1.6
*/
public function onContentPrepareForm(Form $form, $data)
{
// Check we are manipulating a valid form.
$name = $form->getName();
if (!in_array($name, array('com_admin.profile',
'com_users.user', 'com_users.profile',
'com_users.registration')))
{
return true;
}
// Add the registration fields to the form.
Form::addFormPath(__DIR__ . '/profiles');
$form->loadFile('profile');
$fields = array(
'address1',
'address2',
'city',
'region',
'country',
'postal_code',
'phone',
'website',
'favoritebook',
'aboutme',
'dob',
'tos',
);
// Change fields description when displayed in frontend or backend
profile editing
$app = Factory::getApplication();
if ($app->isClient('site') || $name ===
'com_users.user' || $name === 'com_admin.profile')
{
$form->setFieldAttribute('address1',
'description', 'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE',
'profile');
$form->setFieldAttribute('address2',
'description', 'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE',
'profile');
$form->setFieldAttribute('city', 'description',
'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE', 'profile');
$form->setFieldAttribute('region', 'description',
'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE', 'profile');
$form->setFieldAttribute('country',
'description', 'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE',
'profile');
$form->setFieldAttribute('postal_code',
'description', 'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE',
'profile');
$form->setFieldAttribute('phone', 'description',
'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE', 'profile');
$form->setFieldAttribute('website',
'description', 'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE',
'profile');
$form->setFieldAttribute('favoritebook',
'description', 'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE',
'profile');
$form->setFieldAttribute('aboutme',
'description', 'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE',
'profile');
$form->setFieldAttribute('dob', 'description',
'PLG_USER_PROFILE_FILL_FIELD_DESC_SITE', 'profile');
$form->setFieldAttribute('tos', 'description',
'PLG_USER_PROFILE_FIELD_TOS_DESC_SITE', 'profile');
}
$tosArticle = $this->params->get('register_tos_article');
$tosEnabled = $this->params->get('register-require_tos',
0);
// We need to be in the registration form and field needs to be enabled
if ($name !== 'com_users.registration' || !$tosEnabled)
{
// We only want the TOS in the registration form
$form->removeField('tos', 'profile');
}
else
{
// Push the TOS article ID into the TOS field.
$form->setFieldAttribute('tos', 'article',
$tosArticle, 'profile');
}
foreach ($fields as $field)
{
// Case using the users manager in admin
if ($name === 'com_users.user')
{
// Toggle whether the field is required.
if ($this->params->get('profile-require_' . $field, 1)
> 0)
{
$form->setFieldAttribute($field, 'required',
($this->params->get('profile-require_' . $field) == 2) ?
'required' : '', 'profile');
}
// Remove the field if it is disabled in registration and profile
elseif ($this->params->get('register-require_' .
$field, 1) == 0
&& $this->params->get('profile-require_' .
$field, 1) == 0)
{
$form->removeField($field, 'profile');
}
}
// Case registration
elseif ($name === 'com_users.registration')
{
// Toggle whether the field is required.
if ($this->params->get('register-require_' . $field, 1)
> 0)
{
$form->setFieldAttribute($field, 'required',
($this->params->get('register-require_' . $field) == 2) ?
'required' : '', 'profile');
}
else
{
$form->removeField($field, 'profile');
}
}
// Case profile in site or admin
elseif ($name === 'com_users.profile' || $name ===
'com_admin.profile')
{
// Toggle whether the field is required.
if ($this->params->get('profile-require_' . $field, 1)
> 0)
{
$form->setFieldAttribute($field, 'required',
($this->params->get('profile-require_' . $field) == 2) ?
'required' : '', 'profile');
}
else
{
$form->removeField($field, 'profile');
}
}
}
// Drop the profile form entirely if there aren't any fields to
display.
$remainingfields = $form->getGroup('profile');
if (!count($remainingfields))
{
$form->removeGroup('profile');
}
return true;
}
/**
* Method is called before user data is stored in the database
*
* @param array $user Holds the old user data.
* @param boolean $isnew True if a new user is stored.
* @param array $data Holds the new user data.
*
* @return boolean
*
* @since 3.1
* @throws InvalidArgumentException on invalid date.
*/
public function onUserBeforeSave($user, $isnew, $data)
{
// Check that the date is valid.
if (!empty($data['profile']['dob']))
{
try
{
$date = new Date($data['profile']['dob']);
$this->date = $date->format('Y-m-d H:i:s');
}
catch (Exception $e)
{
// Throw an exception if date is not valid.
throw new
InvalidArgumentException(Text::_('PLG_USER_PROFILE_ERROR_INVALID_DOB'));
}
if (Date::getInstance('now') < $date)
{
// Throw an exception if dob is greater than now.
throw new
InvalidArgumentException(Text::_('PLG_USER_PROFILE_ERROR_INVALID_DOB_FUTURE_DATE'));
}
}
// Check that the tos is checked if required ie only in registration from
frontend.
$task =
Factory::getApplication()->input->getCmd('task');
$option =
Factory::getApplication()->input->getCmd('option');
$tosArticle = $this->params->get('register_tos_article');
$tosEnabled = ($this->params->get('register-require_tos',
0) == 2);
// Check that the tos is checked.
if ($task === 'register' && $tosEnabled &&
$tosArticle && $option === 'com_users' &&
!$data['profile']['tos'])
{
throw new
InvalidArgumentException(Text::_('PLG_USER_PROFILE_FIELD_TOS_DESC_SITE'));
}
return true;
}
/**
* Saves user profile data
*
* @param array $data entered user data
* @param boolean $isNew true if this is a new user
* @param boolean $result true if saving the user worked
* @param string $error error message
*
* @return boolean
*/
public function onUserAfterSave($data, $isNew, $result, $error)
{
$userId = ArrayHelper::getValue($data, 'id', 0,
'int');
if ($userId && $result &&
isset($data['profile']) &&
count($data['profile']))
{
try
{
$db = Factory::getDbo();
// Sanitize the date
if (!empty($data['profile']['dob']))
{
$data['profile']['dob'] = $this->date;
}
$keys = array_keys($data['profile']);
foreach ($keys as &$key)
{
$key = 'profile.' . $key;
$key = $db->quote($key);
}
$query = $db->getQuery(true)
->delete($db->quoteName('#__user_profiles'))
->where($db->quoteName('user_id') . ' = ' .
(int) $userId)
->where($db->quoteName('profile_key') . ' IN
(' . implode(',', $keys) . ')');
$db->setQuery($query);
$db->execute();
$query = $db->getQuery(true)
->select($db->quoteName('ordering'))
->from($db->quoteName('#__user_profiles'))
->where($db->quoteName('user_id') . ' = ' .
(int) $userId);
$db->setQuery($query);
$usedOrdering = $db->loadColumn();
$tuples = array();
$order = 1;
foreach ($data['profile'] as $k => $v)
{
while (in_array($order, $usedOrdering))
{
$order++;
}
$tuples[] = '(' . $userId . ', ' .
$db->quote('profile.' . $k) . ', ' .
$db->quote(json_encode($v)) . ', ' . ($order++) .
')';
}
$db->setQuery('INSERT INTO #__user_profiles VALUES ' .
implode(', ', $tuples));
$db->execute();
}
catch (RuntimeException $e)
{
$this->_subject->setError($e->getMessage());
return false;
}
}
return true;
}
/**
* Remove all user profile information for the given user ID
*
* Method is called after user data is deleted from the database
*
* @param array $user Holds the user data
* @param boolean $success True if user was successfully stored in the
database
* @param string $msg Message
*
* @return boolean
*/
public function onUserAfterDelete($user, $success, $msg)
{
if (!$success)
{
return false;
}
$userId = ArrayHelper::getValue($user, 'id', 0,
'int');
if ($userId)
{
try
{
$db = Factory::getDbo();
$db->setQuery(
'DELETE FROM #__user_profiles WHERE user_id = ' . $userId
. " AND profile_key LIKE 'profile.%'"
);
$db->execute();
}
catch (Exception $e)
{
$this->_subject->setError($e->getMessage());
return false;
}
}
return true;
}
}
user/profile/profile.xml000064400000023570147357022250011362
0ustar00<?xml version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="user" method="upgrade">
<name>plg_user_profile</name>
<author>Joomla! Project</author>
<creationDate>January 2008</creationDate>
<copyright>(C) 2008 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_USER_PROFILE_XML_DESCRIPTION</description>
<files>
<filename plugin="profile">profile.php</filename>
<folder>profiles</folder>
<folder>field</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_user_profile.ini</language>
<language
tag="en-GB">en-GB.plg_user_profile.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic"
addfieldpath="/administrator/components/com_content/models/fields">
<field
name="register-require-user"
type="spacer"
label="PLG_USER_PROFILE_FIELD_NAME_REGISTER_REQUIRE_USER"
class="text"
/>
<field
name="register-require_address1"
type="list"
label="PLG_USER_PROFILE_FIELD_ADDRESS1_LABEL"
description="PLG_USER_PROFILE_FIELD_ADDRESS1_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_address2"
type="list"
label="PLG_USER_PROFILE_FIELD_ADDRESS2_LABEL"
description="PLG_USER_PROFILE_FIELD_ADDRESS2_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_city"
type="list"
label="PLG_USER_PROFILE_FIELD_CITY_LABEL"
description="PLG_USER_PROFILE_FIELD_CITY_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_region"
type="list"
label="PLG_USER_PROFILE_FIELD_REGION_LABEL"
description="PLG_USER_PROFILE_FIELD_REGION_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_country"
type="list"
label="PLG_USER_PROFILE_FIELD_COUNTRY_LABEL"
description="PLG_USER_PROFILE_FIELD_COUNTRY_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_postal_code"
type="list"
label="PLG_USER_PROFILE_FIELD_POSTAL_CODE_LABEL"
description="PLG_USER_PROFILE_FIELD_POSTAL_CODE_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_phone"
type="list"
label="PLG_USER_PROFILE_FIELD_PHONE_LABEL"
description="PLG_USER_PROFILE_FIELD_PHONE_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_website"
type="list"
label="PLG_USER_PROFILE_FIELD_WEB_SITE_LABEL"
description="PLG_USER_PROFILE_FIELD_WEB_SITE_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_favoritebook"
type="list"
label="PLG_USER_PROFILE_FIELD_FAVORITE_BOOK_LABEL"
description="PLG_USER_PROFILE_FIELD_FAVORITE_BOOK_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_aboutme"
type="list"
label="PLG_USER_PROFILE_FIELD_ABOUT_ME_LABEL"
description="PLG_USER_PROFILE_FIELD_ABOUT_ME_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register-require_tos"
type="list"
label="PLG_USER_PROFILE_FIELD_TOS_LABEL"
description="PLG_USER_PROFILE_FIELD_TOS_DESC"
default="0"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="0">JDISABLED</option>
</field>
<field
name="register_tos_article"
type="modal_article"
label="PLG_USER_PROFILE_FIELD_TOS_ARTICLE_LABEL"
description="PLG_USER_PROFILE_FIELD_TOS_ARTICLE_DESC"
select="true"
new="true"
edit="true"
clear="true"
filter="integer"
/>
<field
name="register-require_dob"
type="list"
label="PLG_USER_PROFILE_FIELD_DOB_LABEL"
description="PLG_USER_PROFILE_FIELD_DOB_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="spacer1"
type="spacer"
hr="true"
/>
<field
name="profile-require-user"
type="spacer"
label="PLG_USER_PROFILE_FIELD_NAME_PROFILE_REQUIRE_USER"
class="text"
/>
<field
name="profile-require_address1"
type="list"
label="PLG_USER_PROFILE_FIELD_ADDRESS1_LABEL"
description="PLG_USER_PROFILE_FIELD_ADDRESS1_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_address2"
type="list"
label="PLG_USER_PROFILE_FIELD_ADDRESS2_LABEL"
description="PLG_USER_PROFILE_FIELD_ADDRESS2_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_city"
type="list"
label="PLG_USER_PROFILE_FIELD_CITY_LABEL"
description="PLG_USER_PROFILE_FIELD_CITY_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_region"
type="list"
label="PLG_USER_PROFILE_FIELD_REGION_LABEL"
description="PLG_USER_PROFILE_FIELD_REGION_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_country"
type="list"
label="PLG_USER_PROFILE_FIELD_COUNTRY_LABEL"
description="PLG_USER_PROFILE_FIELD_COUNTRY_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_postal_code"
type="list"
label="PLG_USER_PROFILE_FIELD_POSTAL_CODE_LABEL"
description="PLG_USER_PROFILE_FIELD_POSTAL_CODE_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_phone"
type="list"
label="PLG_USER_PROFILE_FIELD_PHONE_LABEL"
description="PLG_USER_PROFILE_FIELD_PHONE_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_website"
type="list"
label="PLG_USER_PROFILE_FIELD_WEB_SITE_LABEL"
description="PLG_USER_PROFILE_FIELD_WEB_SITE_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_favoritebook"
type="list"
label="PLG_USER_PROFILE_FIELD_FAVORITE_BOOK_LABEL"
description="PLG_USER_PROFILE_FIELD_FAVORITE_BOOK_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_aboutme"
type="list"
label="PLG_USER_PROFILE_FIELD_ABOUT_ME_LABEL"
description="PLG_USER_PROFILE_FIELD_ABOUT_ME_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
<field
name="profile-require_dob"
type="list"
label="PLG_USER_PROFILE_FIELD_DOB_LABEL"
description="PLG_USER_PROFILE_FIELD_DOB_DESC"
default="1"
filter="integer"
>
<option value="2">JOPTION_REQUIRED</option>
<option value="1">JOPTION_OPTIONAL</option>
<option value="0">JDISABLED</option>
</field>
</fieldset>
</fields>
</config>
</extension>
user/profile/profiles/profile.xml000064400000005417147357022250013205
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="profile">
<fieldset
name="profile"
label="PLG_USER_PROFILE_SLIDER_LABEL"
>
<field
name="address1"
type="text"
label="PLG_USER_PROFILE_FIELD_ADDRESS1_LABEL"
description="PLG_USER_PROFILE_FIELD_ADDRESS1_DESC"
id="address1"
filter="string"
size="30"
/>
<field
name="address2"
type="text"
label="PLG_USER_PROFILE_FIELD_ADDRESS2_LABEL"
description="PLG_USER_PROFILE_FIELD_ADDRESS2_DESC"
id="address2"
filter="string"
size="30"
/>
<field
name="city"
type="text"
label="PLG_USER_PROFILE_FIELD_CITY_LABEL"
description="PLG_USER_PROFILE_FIELD_CITY_DESC"
id="city"
filter="string"
size="30"
/>
<field
name="region"
type="text"
label="PLG_USER_PROFILE_FIELD_REGION_LABEL"
description="PLG_USER_PROFILE_FIELD_REGION_DESC"
id="region"
filter="string"
size="30"
/>
<field
name="country"
type="text"
label="PLG_USER_PROFILE_FIELD_COUNTRY_LABEL"
description="PLG_USER_PROFILE_FIELD_COUNTRY_DESC"
id="country"
filter="string"
size="30"
/>
<field
name="postal_code"
type="text"
label="PLG_USER_PROFILE_FIELD_POSTAL_CODE_LABEL"
description="PLG_USER_PROFILE_FIELD_POSTAL_CODE_DESC"
id="postal_code"
filter="string"
size="30"
/>
<field
name="phone"
type="tel"
label="PLG_USER_PROFILE_FIELD_PHONE_LABEL"
description="PLG_USER_PROFILE_FIELD_PHONE_DESC"
id="phone"
filter="string"
size="30"
/>
<field
name="website"
type="url"
label="PLG_USER_PROFILE_FIELD_WEB_SITE_LABEL"
description="PLG_USER_PROFILE_FIELD_WEB_SITE_DESC"
id="website"
filter="url"
size="30"
validate="url"
/>
<field
name="favoritebook"
type="text"
label="PLG_USER_PROFILE_FIELD_FAVORITE_BOOK_LABEL"
description="PLG_USER_PROFILE_FIELD_FAVORITE_BOOK_DESC"
filter="string"
size="30"
/>
<field
name="aboutme"
type="textarea"
label="PLG_USER_PROFILE_FIELD_ABOUT_ME_LABEL"
description="PLG_USER_PROFILE_FIELD_ABOUT_ME_DESC"
cols="30"
rows="5"
filter="safehtml"
/>
<field
name="dob"
type="dob"
label="PLG_USER_PROFILE_FIELD_DOB_LABEL"
description="PLG_USER_PROFILE_FIELD_DOB_DESC"
info="PLG_USER_PROFILE_SPACER_DOB"
translateformat="true"
showtime="false"
filter="server_utc"
/>
<field
name="tos"
type="tos"
label="PLG_USER_PROFILE_FIELD_TOS_LABEL"
description="PLG_USER_PROFILE_FIELD_TOS_DESC"
default="0"
filter="integer"
>
<option
value="1">PLG_USER_PROFILE_OPTION_AGREE</option>
<option
value="0">PLG_USER_PROFILE_OPTION_DO_NOT_AGREE</option>
</field>
</fieldset>
</fields>
</form>
user/terms/field/terms.php000064400000006324147357022250011616
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage User.terms
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('JPATH_PLATFORM') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormHelper;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Text;
FormHelper::loadFieldClass('radio');
/**
* Provides input for privacyterms
*
* @since 3.9.0
*/
class JFormFieldterms extends JFormFieldRadio
{
/**
* The form field type.
*
* @var string
* @since 3.9.0
*/
protected $type = 'terms';
/**
* Method to get the field input markup.
*
* @return string The field input markup.
*
* @since 3.9.0
*/
protected function getInput()
{
// Display the message before the field
echo
$this->getRenderer('plugins.user.terms.message')->render($this->getLayoutData());
return parent::getInput();
}
/**
* Method to get the field label markup.
*
* @return string The field label markup.
*
* @since 3.9.0
*/
protected function getLabel()
{
if ($this->hidden)
{
return '';
}
return
$this->getRenderer('plugins.user.terms.label')->render($this->getLayoutData());
}
/**
* Method to get the data to be passed to the layout for rendering.
*
* @return array
*
* @since 3.9.4
*/
protected function getLayoutData()
{
$data = parent::getLayoutData();
$article = false;
$termsArticle = $this->element['article'] > 0 ? (int)
$this->element['article'] : 0;
if ($termsArticle &&
Factory::getApplication()->isClient('site'))
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName(array('id', 'alias',
'catid', 'language')))
->from($db->quoteName('#__content'))
->where($db->quoteName('id') . ' = ' . (int)
$termsArticle);
$db->setQuery($query);
$article = $db->loadObject();
JLoader::register('ContentHelperRoute', JPATH_BASE .
'/components/com_content/helpers/route.php');
if (Associations::isEnabled())
{
$termsAssociated =
Associations::getAssociations('com_content',
'#__content', 'com_content.item', $termsArticle);
}
$currentLang = Factory::getLanguage()->getTag();
if (isset($termsAssociated) && $currentLang !==
$article->language && array_key_exists($currentLang,
$termsAssociated))
{
$article->link = ContentHelperRoute::getArticleRoute(
$termsAssociated[$currentLang]->id,
$termsAssociated[$currentLang]->catid,
$termsAssociated[$currentLang]->language
);
}
else
{
$slug = $article->alias ? ($article->id . ':' .
$article->alias) : $article->id;
$article->link = ContentHelperRoute::getArticleRoute($slug,
$article->catid, $article->language);
}
}
$extraData = array(
'termsnote' => !empty($this->element['note'])
? $this->element['note'] :
Text::_('PLG_USER_TERMS_NOTE_FIELD_DEFAULT'),
'options' => $this->getOptions(),
'value' => (string) $this->value,
'translateLabel' => $this->translateLabel,
'translateDescription' => $this->translateDescription,
'translateHint' => $this->translateHint,
'termsArticle' => $termsArticle,
'article' => $article,
);
return array_merge($data, $extraData);
}
}
user/terms/terms/terms.xml000064400000000755147357022250011700
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fields name="terms">
<fieldset
name="terms"
label="PLG_USER_TERMS_LABEL"
>
<field
name="terms"
type="terms"
label="PLG_USER_TERMS_FIELD_LABEL"
description="PLG_USER_TERMS_FIELD_DESC"
default="0"
filter="integer"
required="true"
>
<option
value="1">PLG_USER_TERMS_OPTION_AGREE</option>
<option
value="0">PLG_USER_TERMS_OPTION_DO_NOT_AGREE</option>
</field>
</fieldset>
</fields>
</form>
user/terms/terms.php000064400000011047147357022250010531 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage User.terms
*
* @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\Form\Form;
use Joomla\CMS\Form\FormHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Utilities\ArrayHelper;
/**
* An example custom terms and conditions plugin.
*
* @since 3.9.0
*/
class PlgUserTerms extends CMSPlugin
{
/**
* Load the language file on instantiation.
*
* @var boolean
* @since 3.9.0
*/
protected $autoloadLanguage = true;
/**
* Application object.
*
* @var JApplicationCms
* @since 3.9.0
*/
protected $app;
/**
* Database object.
*
* @var JDatabaseDriver
* @since 3.9.0
*/
protected $db;
/**
* Constructor
*
* @param object &$subject The object to observe
* @param array $config An array that holds the plugin
configuration
*
* @since 3.9.0
*/
public function __construct(&$subject, $config)
{
parent::__construct($subject, $config);
FormHelper::addFieldPath(__DIR__ . '/field');
}
/**
* Adds additional fields to the user registration form
*
* @param JForm $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, $data)
{
if (!($form instanceof JForm))
{
$this->_subject->setError('JERROR_NOT_A_FORM');
return false;
}
// Check we are manipulating a valid form - we only display this on user
registration form.
$name = $form->getName();
if (!in_array($name, array('com_users.registration')))
{
return true;
}
// Add the terms and conditions fields to the form.
Form::addFormPath(__DIR__ . '/terms');
$form->loadFile('terms');
$termsarticle = $this->params->get('terms_article');
$termsnote = $this->params->get('terms_note');
// Push the terms and conditions article ID into the terms field.
$form->setFieldAttribute('terms', 'article',
$termsarticle, 'terms');
$form->setFieldAttribute('terms', 'note',
$termsnote, 'terms');
}
/**
* Method is called before user data is stored in the database
*
* @param array $user Holds the old user data.
* @param boolean $isNew True if a new user is stored.
* @param array $data Holds the new user data.
*
* @return boolean
*
* @since 3.9.0
* @throws InvalidArgumentException on missing required data.
*/
public function onUserBeforeSave($user, $isNew, $data)
{
// // Only check for front-end user registration
if ($this->app->isClient('administrator'))
{
return true;
}
$userId = ArrayHelper::getValue($user, 'id', 0,
'int');
// User already registered, no need to check it further
if ($userId > 0)
{
return true;
}
// Check that the terms is checked if required ie only in registration
from frontend.
$option = $this->app->input->getCmd('option');
$task = $this->app->input->get->getCmd('task');
$form = $this->app->input->post->get('jform',
array(), 'array');
if ($option == 'com_users' && in_array($task,
array('registration.register')) &&
empty($form['terms']['terms']))
{
throw new
InvalidArgumentException(Text::_('PLG_USER_TERMS_FIELD_ERROR'));
}
return true;
}
/**
* Saves user profile data
*
* @param array $data entered user data
* @param boolean $isNew true if this is a new user
* @param boolean $result true if saving the user worked
* @param string $error error message
*
* @return boolean
*
* @since 3.9.0
*/
public function onUserAfterSave($data, $isNew, $result, $error)
{
if (!$isNew || !$result)
{
return true;
}
JLoader::register('ActionlogsModelActionlog',
JPATH_ADMINISTRATOR .
'/components/com_actionlogs/models/actionlog.php');
$userId = ArrayHelper::getValue($data, 'id', 0,
'int');
$message = array(
'action' => 'consent',
'id' => $userId,
'title' => $data['name'],
'itemlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$userId,
'userid' => $userId,
'username' => $data['username'],
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$userId,
);
/* @var ActionlogsModelActionlog $model */
$model = BaseDatabaseModel::getInstance('Actionlog',
'ActionlogsModel');
$model->addLog(array($message),
'PLG_USER_TERMS_LOGGING_CONSENT_TO_TERMS',
'plg_user_terms', $userId);
}
}
user/terms/terms.xml000064400000002747147357022250010551 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="user" method="upgrade">
<name>plg_user_terms</name>
<author>Joomla! Project</author>
<creationDate>June 2018</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_USER_TERMS_XML_DESCRIPTION</description>
<files>
<filename plugin="terms">terms.php</filename>
<folder>terms</folder>
<folder>field</folder>
</files>
<languages>
<language
tag="en-GB">en-GB.plg_user_terms.ini</language>
<language
tag="en-GB">en-GB.plg_user_terms.sys.ini</language>
</languages>
<config>
<fields name="params">
<fieldset name="basic"
addfieldpath="/administrator/components/com_content/models/fields">
<field
name="terms_note"
type="textarea"
label="PLG_USER_TERMS_NOTE_FIELD_LABEL"
description="PLG_USER_TERMS_NOTE_FIELD_DESC"
hint="PLG_USER_TERMS_NOTE_FIELD_DEFAULT"
class="span12"
rows="7"
cols="20"
filter="html"
/>
<field
name="terms_article"
type="modal_article"
label="PLG_USER_TERMS_FIELD_ARTICLE_LABEL"
description="PLG_USER_TERMS_FIELD_ARTICLE_DESC"
select="true"
new="true"
edit="true"
clear="true"
filter="integer"
/>
</fieldset>
</fields>
</config>
</extension>
editors/tinymce/field/tinymcebuilder/setoptions.php000064400000001151147366113750016722
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage Editors.tinymce
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
extract($displayData);
/**
* Layout variables
* -----------------
* @var JForm $form Form with extra options for the set
* @var JLayoutFile $this Context
*/
?>
<div class="setoptions-form-wrapper">
<?php foreach ($form->getGroup(null) as $field) : ?>
<?php echo $field->renderField(); ?>
<?php endforeach; ?>
</div>
system/privacyconsent/label.php000064400000007776147366113750012765
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.privacyconsent
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
extract($displayData);
/**
* Layout variables
* -----------------
* @var string $autocomplete Autocomplete attribute for the
field.
* @var boolean $autofocus Is autofocus enabled?
* @var string $class Classes for the input.
* @var string $description Description of the field.
* @var boolean $disabled Is this field disabled?
* @var string $group Group the field belongs to.
<fields> section in form XML.
* @var boolean $hidden Is this field hidden in the
form?
* @var string $hint Placeholder for the field.
* @var string $id DOM id of the field.
* @var string $label Label of the field.
* @var string $labelclass Classes to apply to the label.
* @var boolean $multiple Does this field support multiple
values?
* @var string $name Name of the input field.
* @var string $onchange Onchange attribute for the
field.
* @var string $onclick Onclick attribute for the field.
* @var string $pattern Pattern (Reg Ex) of value of the
form field.
* @var boolean $readonly Is this field read only?
* @var boolean $repeat Allows extensions to duplicate
elements.
* @var boolean $required Is this field required?
* @var integer $size Size attribute of the input.
* @var boolean $spellcheck Spellcheck state for the form
field.
* @var string $validate Validation rules to apply.
* @var string $value Value attribute of the field.
* @var array $options Options available for this
field.
* @var array $privacynote The privacy note that needs to
be displayed
* @var array $translateLabel Should the label be translated?
* @var array $translateDescription Should the description be
translated?
* @var array $translateHint Should the hint be translated?
* @var array $privacyArticle The Article ID holding the
Privacy Article
* $var object $article The Article object
*/
// Get the label text from the XML element, defaulting to the element name.
$text = $label ? (string) $label : (string) $name;
$text = $translateLabel ? Text::_($text) : $text;
// Set required to true as this field is not displayed at all if not
required.
$required = true;
JHtml::_('behavior.modal');
// Build the class for the label.
$class = !empty($description) ? 'hasPopover' : '';
$class = $class . ' required';
$class = !empty($labelclass) ? $class . ' ' . $labelclass :
$class;
// Add the opening label tag and main attributes.
$label = '<label id="' . $id . '-lbl"
for="' . $id . '" class="' . $class .
'"';
// If a description is specified, use it to build a tooltip.
if (!empty($description))
{
$label .= ' title="' . htmlspecialchars(trim($text,
':'), ENT_COMPAT, 'UTF-8') . '"';
$label .= ' data-content="' . htmlspecialchars(
$translateDescription ? Text::_($description) : $description,
ENT_COMPAT,
'UTF-8'
) . '"';
}
if (Factory::getLanguage()->isRtl())
{
$label .= ' data-placement="left"';
}
$attribs = array();
$attribs['class'] = 'modal';
$attribs['rel'] = '{handler: \'iframe\', size:
{x:800, y:500}}';
if ($article)
{
$link = JHtml::_('link', Route::_($article->link .
'&tmpl=component'), $text, $attribs);
}
else
{
$link = $text;
}
// Add the label text and closing tag.
$label .= '>' . $link . '<span
class="star"> *</span></label>';
echo $label;
system/privacyconsent/message.php000064400000005055147366113750013316
0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage System.privacyconsent
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
extract($displayData);
/**
* Layout variables
* -----------------
* @var string $autocomplete Autocomplete attribute for the
field.
* @var boolean $autofocus Is autofocus enabled?
* @var string $class Classes for the input.
* @var string $description Description of the field.
* @var boolean $disabled Is this field disabled?
* @var string $group Group the field belongs to.
<fields> section in form XML.
* @var boolean $hidden Is this field hidden in the
form?
* @var string $hint Placeholder for the field.
* @var string $id DOM id of the field.
* @var string $label Label of the field.
* @var string $labelclass Classes to apply to the label.
* @var boolean $multiple Does this field support multiple
values?
* @var string $name Name of the input field.
* @var string $onchange Onchange attribute for the
field.
* @var string $onclick Onclick attribute for the field.
* @var string $pattern Pattern (Reg Ex) of value of the
form field.
* @var boolean $readonly Is this field read only?
* @var boolean $repeat Allows extensions to duplicate
elements.
* @var boolean $required Is this field required?
* @var integer $size Size attribute of the input.
* @var boolean $spellcheck Spellcheck state for the form
field.
* @var string $validate Validation rules to apply.
* @var string $value Value attribute of the field.
* @var array $options Options available for this
field.
* @var array $privacynote The privacy note that needs to
be displayed
* @var array $translateLabel Should the label be translated?
* @var array $translateDescription Should the description be
translated?
* @var array $translateHint Should the hint be translated?
* @var array $privacyArticle The Article ID holding the
Privacy Article
*/
echo '<div class="alert alert-info">' .
$privacynote . '</div>';
user/profile/fields/dob.php000064400000001200147366113750011713
0ustar00<?php
/**
* @package Joomla.Site
* @subpackage Layout
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
/**
* $text string infotext to be displayed
*/
extract($displayData);
// Closing the opening .control-group and .control-label div so we can add
our info text on own line ?>
</div></div>
<div class="controls"><?php echo $text;
?></div>
<?php // Creating new .control-group and .control-label for the actual
field ?>
<div class="control-group"><div
class="control-label">
user/terms/label.php000064400000010024147366113750010456 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage User.terms
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
extract($displayData);
/**
* Layout variables
* -----------------
* @var string $autocomplete Autocomplete attribute for the
field.
* @var boolean $autofocus Is autofocus enabled?
* @var string $class Classes for the input.
* @var string $description Description of the field.
* @var boolean $disabled Is this field disabled?
* @var string $group Group the field belongs to.
<fields> section in form XML.
* @var boolean $hidden Is this field hidden in the
form?
* @var string $hint Placeholder for the field.
* @var string $id DOM id of the field.
* @var string $label Label of the field.
* @var string $labelclass Classes to apply to the label.
* @var boolean $multiple Does this field support multiple
values?
* @var string $name Name of the input field.
* @var string $onchange Onchange attribute for the
field.
* @var string $onclick Onclick attribute for the field.
* @var string $pattern Pattern (Reg Ex) of value of the
form field.
* @var boolean $readonly Is this field read only?
* @var boolean $repeat Allows extensions to duplicate
elements.
* @var boolean $required Is this field required?
* @var integer $size Size attribute of the input.
* @var boolean $spellcheck Spellcheck state for the form
field.
* @var string $validate Validation rules to apply.
* @var string $value Value attribute of the field.
* @var array $options Options available for this
field.
* @var array $termsnote The terms note that needs to be
displayed
* @var array $translateLabel Should the label be translated?
* @var array $translateDescription Should the description be
translated?
* @var array $translateHint Should the hint be translated?
* @var array $termsArticle The Article ID holding the Terms
Article
* $var object $article The Article object
*/
// Get the label text from the XML element, defaulting to the element name.
$text = $label ? (string) $label : (string) $name;
$text = $translateLabel ? Text::_($text) : $text;
// Set required to true as this field is not displayed at all if not
required.
$required = true;
JHtml::_('behavior.modal');
// Build the class for the label.
$class = !empty($description) ? 'hasPopover' : '';
$class = $class . ' required';
$class = !empty($labelclass) ? $class . ' ' . $labelclass :
$class;
// Add the opening label tag and main attributes.
$label = '<label id="' . $id . '-lbl"
for="' . $id . '" class="' . $class .
'"';
// If a description is specified, use it to build a tooltip.
if (!empty($description))
{
$label .= ' title="' . htmlspecialchars(trim($text,
':'), ENT_COMPAT, 'UTF-8') . '"';
$label .= ' data-content="' . htmlspecialchars(
$translateDescription ? Text::_($description) : $description,
ENT_COMPAT,
'UTF-8'
) . '"';
}
if (Factory::getLanguage()->isRtl())
{
$label .= ' data-placement="left"';
}
$attribs = array();
$attribs['class'] = 'modal';
$attribs['rel'] = '{handler: \'iframe\', size:
{x:800, y:500}}';
if ($article)
{
$link = HTMLHelper::_('link', Route::_($article->link .
'&tmpl=component'), $text, $attribs);
}
else
{
$link = $text;
}
// Add the label text and closing tag.
$label .= '>' . $link . '<span
class="star"> *</span></label>';
echo $label;
user/terms/message.php000064400000005033147366113750011027 0ustar00<?php
/**
* @package Joomla.Plugin
* @subpackage User.terms
*
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
extract($displayData);
/**
* Layout variables
* -----------------
* @var string $autocomplete Autocomplete attribute for the
field.
* @var boolean $autofocus Is autofocus enabled?
* @var string $class Classes for the input.
* @var string $description Description of the field.
* @var boolean $disabled Is this field disabled?
* @var string $group Group the field belongs to.
<fields> section in form XML.
* @var boolean $hidden Is this field hidden in the
form?
* @var string $hint Placeholder for the field.
* @var string $id DOM id of the field.
* @var string $label Label of the field.
* @var string $labelclass Classes to apply to the label.
* @var boolean $multiple Does this field support multiple
values?
* @var string $name Name of the input field.
* @var string $onchange Onchange attribute for the
field.
* @var string $onclick Onclick attribute for the field.
* @var string $pattern Pattern (Reg Ex) of value of the
form field.
* @var boolean $readonly Is this field read only?
* @var boolean $repeat Allows extensions to duplicate
elements.
* @var boolean $required Is this field required?
* @var integer $size Size attribute of the input.
* @var boolean $spellcheck Spellcheck state for the form
field.
* @var string $validate Validation rules to apply.
* @var string $value Value attribute of the field.
* @var array $options Options available for this
field.
* @var array $termsnote The terms note that needs to be
displayed
* @var array $translateLabel Should the label be translated?
* @var array $translateDescription Should the description be
translated?
* @var array $translateHint Should the hint be translated?
* @var array $termsArticle The Article ID holding the Terms
Article
*/
echo '<div class="alert alert-info">' .
$termsnote . '</div>';