Spade
Mini Shell
config.xml000064400000000547151165412120006537 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<config>
<fieldset
name="privacy"
label="COM_PRIVACY_OPTION_LABEL"
>
<field
name="notify"
type="integer"
label="COM_PRIVACY_NOTIFY_LABEL"
description="COM_PRIVACY_NOTIFY_DESC"
first="1"
last="29"
step="1"
default="14"
filter="int"
validate="number"
/>
</fieldset>
</config>
controller.php000064400000002646151165412120007446 0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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;
/**
* Privacy Controller
*
* @since 3.9.0
*/
class PrivacyController extends JControllerLegacy
{
/**
* Method to display a view.
*
* @param boolean $cachable If true, the view output will be cached
* @param array $urlparams An array of safe URL parameters and their
variable types, for valid values see {@link JFilterInput::clean()}.
*
* @return $this
*
* @since 3.9.0
*/
public function display($cachable = false, $urlparams = array())
{
$view = $this->input->get('view',
$this->default_view);
// Submitting information requests and confirmation through the frontend
is restricted to authenticated users at this time
if (in_array($view, array('confirm', 'request'))
&& JFactory::getUser()->guest)
{
$this->setRedirect(
JRoute::_('index.php?option=com_users&view=login&return='
. base64_encode('index.php?option=com_privacy&view=' .
$view), false)
);
return $this;
}
// Set a Referrer-Policy header for views which require it
if (in_array($view, array('confirm', 'remind')))
{
JFactory::getApplication()->setHeader('Referrer-Policy',
'no-referrer', true);
}
return parent::display($cachable, $urlparams);
}
}
controllers/consents.php000064400000004031151165412120011453
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Consents management controller class.
*
* @since 3.9.0
*/
class PrivacyControllerConsents extends JControllerForm
{
/**
* Method to invalidate specific consents.
*
* @return boolean
*
* @since 3.9.0
*/
public function invalidate($key = null, $urlVar = null)
{
// Check for request forgeries
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
$ids = $this->input->get('cid', array(),
'array');
if (empty($ids))
{
$this->setError(JText::_('JERROR_NO_ITEMS_SELECTED'));
}
else
{
// Get the model.
/** @var PrivacyModelConsents $model */
$model = $this->getModel();
// Publish the items.
if (!$model->invalidate($ids))
{
$this->setError($model->getError());
}
$message = JText::plural('COM_PRIVACY_N_CONSENTS_INVALIDATED',
count($ids));
}
$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=consents',
false), $message);
}
/**
* Method to invalidate all consents of a specific subject.
*
* @return boolean
*
* @since 3.9.0
*/
public function invalidateAll()
{
// Check for request forgeries
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
$filters = $this->input->get('filter', array(),
'array');
if (isset($filters['subject']) &&
$filters['subject'] != '')
{
$subject = $filters['subject'];
}
else
{
$this->setError(JText::_('JERROR_NO_ITEMS_SELECTED'));
}
// Get the model.
/** @var PrivacyModelConsents $model */
$model = $this->getModel();
// Publish the items.
if (!$model->invalidateAll($subject))
{
$this->setError($model->getError());
}
$message = JText::_('COM_PRIVACY_CONSENTS_INVALIDATED_ALL');
$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=consents',
false), $message);
}
}
controllers/request.php000064400000010443151165412120011313
0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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;
/**
* Request action controller class.
*
* @since 3.9.0
*/
class PrivacyControllerRequest extends JControllerLegacy
{
/**
* Method to confirm the information request.
*
* @return boolean
*
* @since 3.9.0
*/
public function confirm()
{
// Check the request token.
$this->checkToken('post');
/** @var PrivacyModelConfirm $model */
$model = $this->getModel('Confirm',
'PrivacyModel');
$data = $this->input->post->get('jform', array(),
'array');
$return = $model->confirmRequest($data);
// Check for a hard error.
if ($return instanceof Exception)
{
// Get the error message to display.
if (JFactory::getApplication()->get('error_reporting'))
{
$message = $return->getMessage();
}
else
{
$message = JText::_('COM_PRIVACY_ERROR_CONFIRMING_REQUEST');
}
// Go back to the confirm form.
$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=confirm',
false), $message, 'error');
return false;
}
elseif ($return === false)
{
// Confirm failed.
// Go back to the confirm form.
$message =
JText::sprintf('COM_PRIVACY_ERROR_CONFIRMING_REQUEST_FAILED',
$model->getError());
$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=confirm',
false), $message, 'notice');
return false;
}
else
{
// Confirm succeeded.
$this->setRedirect(JRoute::_(JUri::root()),
JText::_('COM_PRIVACY_CONFIRM_REQUEST_SUCCEEDED'),
'info');
return true;
}
}
/**
* Method to submit an information request.
*
* @return boolean
*
* @since 3.9.0
*/
public function submit()
{
// Check the request token.
$this->checkToken('post');
/** @var PrivacyModelRequest $model */
$model = $this->getModel('Request',
'PrivacyModel');
$data = $this->input->post->get('jform', array(),
'array');
$return = $model->createRequest($data);
// Check for a hard error.
if ($return instanceof Exception)
{
// Get the error message to display.
if (JFactory::getApplication()->get('error_reporting'))
{
$message = $return->getMessage();
}
else
{
$message = JText::_('COM_PRIVACY_ERROR_CREATING_REQUEST');
}
// Go back to the confirm form.
$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=request',
false), $message, 'error');
return false;
}
elseif ($return === false)
{
// Confirm failed.
// Go back to the confirm form.
$message =
JText::sprintf('COM_PRIVACY_ERROR_CREATING_REQUEST_FAILED',
$model->getError());
$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=request',
false), $message, 'notice');
return false;
}
else
{
// Confirm succeeded.
$this->setRedirect(JRoute::_(JUri::root()),
JText::_('COM_PRIVACY_CREATE_REQUEST_SUCCEEDED'),
'info');
return true;
}
}
/**
* Method to extend the privacy consent.
*
* @return boolean
*
* @since 3.9.0
*/
public function remind()
{
// Check the request token.
$this->checkToken('post');
/** @var PrivacyModelConfirm $model */
$model = $this->getModel('Remind',
'PrivacyModel');
$data = $this->input->post->get('jform', array(),
'array');
$return = $model->remindRequest($data);
// Check for a hard error.
if ($return instanceof Exception)
{
// Get the error message to display.
if (JFactory::getApplication()->get('error_reporting'))
{
$message = $return->getMessage();
}
else
{
$message = JText::_('COM_PRIVACY_ERROR_REMIND_REQUEST');
}
// Go back to the confirm form.
$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=remind',
false), $message, 'error');
return false;
}
elseif ($return === false)
{
// Confirm failed.
// Go back to the confirm form.
$message =
JText::sprintf('COM_PRIVACY_ERROR_CONFIRMING_REMIND_FAILED',
$model->getError());
$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=remind',
false), $message, 'notice');
return false;
}
else
{
// Confirm succeeded.
$this->setRedirect(JRoute::_(JUri::root()),
JText::_('COM_PRIVACY_CONFIRM_REMIND_SUCCEEDED'),
'info');
return true;
}
}
}
controllers/request.xml.php000064400000001137151165412120012112
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Request management controller class.
*
* @since 3.9.0
*/
class PrivacyControllerRequest extends JControllerLegacy
{
/**
* Method to export the data for a request.
*
* @return $this
*
* @since 3.9.0
*/
public function export()
{
$this->input->set('view', 'export');
return $this->display();
}
}
controllers/requests.php000064400000001670151165412120011500
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Requests management controller class.
*
* @since 3.9.0
*/
class PrivacyControllerRequests extends JControllerAdmin
{
/**
* Method to get a model object, loading it if required.
*
* @param string $name The model name. Optional.
* @param string $prefix The class prefix. Optional.
* @param array $config Configuration array for model. Optional.
*
* @return JModelLegacy|boolean Model object on success; otherwise false
on failure.
*
* @since 3.9.0
*/
public function getModel($name = 'Request', $prefix =
'PrivacyModel', $config = array('ignore_request' =>
true))
{
return parent::getModel($name, $prefix, $config);
}
}
helpers/export/domain.php000064400000002436151165412120011512
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
JLoader::register('PrivacyExportItem', __DIR__ .
'/item.php');
/**
* Data object representing all data contained in a domain.
*
* A domain is typically a single database table and the items within the
domain are separate rows from the table.
*
* @since 3.9.0
*/
class PrivacyExportDomain
{
/**
* The name of this domain
*
* @var string
* @since 3.9.0
*/
public $name;
/**
* A short description of the data in this domain
*
* @var string
* @since 3.9.0
*/
public $description;
/**
* The items belonging to this domain
*
* @var PrivacyExportItem[]
* @since 3.9.0
*/
protected $items = array();
/**
* Add an item to the domain
*
* @param PrivacyExportItem $item The item to add
*
* @return void
*
* @since 3.9.0
*/
public function addItem(PrivacyExportItem $item)
{
$this->items[] = $item;
}
/**
* Get the domain's items
*
* @return PrivacyExportItem[]
*
* @since 3.9.0
*/
public function getItems()
{
return $this->items;
}
}
helpers/export/field.php000064400000001071151165412120011320
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Data object representing a field within an item.
*
* @since 3.9.0
*/
class PrivacyExportField
{
/**
* The name of this field
*
* @var string
* @since 3.9.0
*/
public $name;
/**
* The field's value
*
* @var mixed
* @since 3.9.0
*/
public $value;
}
helpers/export/item.php000064400000002254151165412120011177
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
JLoader::register('PrivacyExportField', __DIR__ .
'/field.php');
/**
* Data object representing a single item within a domain.
*
* An item is typically a single row from a database table.
*
* @since 3.9.0
*/
class PrivacyExportItem
{
/**
* The primary identifier of this item, typically the primary key for a
database row.
*
* @var integer
* @since 3.9.0
*/
public $id;
/**
* The fields belonging to this item
*
* @var PrivacyExportField[]
* @since 3.9.0
*/
protected $fields = array();
/**
* Add a field to the item
*
* @param PrivacyExportField $field The field to add
*
* @return void
*
* @since 3.9.0
*/
public function addField(PrivacyExportField $field)
{
$this->fields[] = $field;
}
/**
* Get the item's fields
*
* @return PrivacyExportField[]
*
* @since 3.9.0
*/
public function getFields()
{
return $this->fields;
}
}
helpers/html/helper.php000064400000002033151165412120011136
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Privacy component HTML helper.
*
* @since 3.9.0
*/
class PrivacyHtmlHelper
{
/**
* Render a status label
*
* @param integer $status The item status
*
* @return string
*
* @since 3.9.0
*/
public static function statusLabel($status)
{
switch ($status)
{
case 2:
return '<span class="label label-success">' .
JText::_('COM_PRIVACY_STATUS_COMPLETED') .
'</span>';
case 1:
return '<span class="label label-info">' .
JText::_('COM_PRIVACY_STATUS_CONFIRMED') .
'</span>';
case -1:
return '<span class="label label-important">'
. JText::_('COM_PRIVACY_STATUS_INVALID') .
'</span>';
default:
case 0:
return '<span class="label label-warning">' .
JText::_('COM_PRIVACY_STATUS_PENDING') .
'</span>';
}
}
}
helpers/plugin.php000064400000007237151165412120010224 0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
JLoader::register('PrivacyExportDomain', __DIR__ .
'/export/domain.php');
JLoader::register('PrivacyExportField', __DIR__ .
'/export/field.php');
JLoader::register('PrivacyExportItem', __DIR__ .
'/export/item.php');
JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR .
'/components/com_fields/helpers/fields.php');
/**
* Base class for privacy plugins
*
* @since 3.9.0
*/
abstract class PrivacyPlugin extends JPlugin
{
/**
* Database object
*
* @var JDatabaseDriver
* @since 3.9.0
*/
protected $db;
/**
* Affects constructor behaviour. If true, language files will be loaded
automatically.
*
* @var boolean
* @since 3.9.0
*/
protected $autoloadLanguage = true;
/**
* Create a new domain object
*
* @param string $name The domain's name
* @param string $description The domain's description
*
* @return PrivacyExportDomain
*
* @since 3.9.0
*/
protected function createDomain($name, $description = '')
{
$domain = new PrivacyExportDomain;
$domain->name = $name;
$domain->description = $description;
return $domain;
}
/**
* Create an item object for an array
*
* @param array $data The array data to convert
* @param integer|null $itemId The ID of this item
*
* @return PrivacyExportItem
*
* @since 3.9.0
*/
protected function createItemFromArray(array $data, $itemId = null)
{
$item = new PrivacyExportItem;
$item->id = $itemId;
foreach ($data as $key => $value)
{
if (is_object($value))
{
$value = (array) $value;
}
if (is_array($value))
{
$value = print_r($value, true);
}
$field = new PrivacyExportField;
$field->name = $key;
$field->value = $value;
$item->addField($field);
}
return $item;
}
/**
* Create an item object for a JTable object
*
* @param JTable $table The JTable object to convert
*
* @return PrivacyExportItem
*
* @since 3.9.0
*/
protected function createItemForTable($table)
{
$data = array();
foreach (array_keys($table->getFields()) as $fieldName)
{
$data[$fieldName] = $table->$fieldName;
}
return $this->createItemFromArray($data,
$table->{$table->getKeyName(false)});
}
/**
* Helper function to create the domain for the items custom fields.
*
* @param string $context The context
* @param array $items The items
*
* @return PrivacyExportDomain
*
* @since 3.9.0
*/
protected function createCustomFieldsDomain($context, $items = array())
{
if (!is_array($items))
{
$items = array($items);
}
$parts = FieldsHelper::extract($context);
if (!$parts)
{
return array();
}
$type = str_replace('com_', '', $parts[0]);
$domain = $this->createDomain($type . '_' . $parts[1] .
'_custom_fields', 'joomla_' . $type . '_' .
$parts[1] . '_custom_fields_data');
foreach ($items as $item)
{
// Get item's fields, also preparing their value property for
manual display
$fields = FieldsHelper::getFields($parts[0] . '.' . $parts[1],
$item);
foreach ($fields as $field)
{
$fieldValue = is_array($field->value) ? implode(', ',
$field->value) : $field->value;
$data = array(
$type . '_id' => $item->id,
'field_name' => $field->name,
'field_title' => $field->title,
'field_value' => $fieldValue,
);
$domain->addItem($this->createItemFromArray($data));
}
}
return $domain;
}
}
helpers/privacy.php000064400000005454151165412120010402 0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Privacy component helper.
*
* @since 3.9.0
*/
class PrivacyHelper extends JHelperContent
{
/**
* Configure the Linkbar.
*
* @param string $vName The name of the active view.
*
* @return void
*
* @since 3.9.0
*/
public static function addSubmenu($vName)
{
JHtmlSidebar::addEntry(
JText::_('COM_PRIVACY_SUBMENU_DASHBOARD'),
'index.php?option=com_privacy&view=dashboard',
$vName === 'dashboard'
);
JHtmlSidebar::addEntry(
JText::_('COM_PRIVACY_SUBMENU_REQUESTS'),
'index.php?option=com_privacy&view=requests',
$vName === 'requests'
);
JHtmlSidebar::addEntry(
JText::_('COM_PRIVACY_SUBMENU_CAPABILITIES'),
'index.php?option=com_privacy&view=capabilities',
$vName === 'capabilities'
);
JHtmlSidebar::addEntry(
JText::_('COM_PRIVACY_SUBMENU_CONSENTS'),
'index.php?option=com_privacy&view=consents',
$vName === 'consents'
);
}
/**
* Render the data request as a XML document.
*
* @param PrivacyExportDomain[] $exportData The data to be exported.
*
* @return string
*
* @since 3.9.0
*/
public static function renderDataAsXml(array $exportData)
{
$export = new SimpleXMLElement('<?xml version="1.0"
encoding="utf-8"?><data-export />');
foreach ($exportData as $domain)
{
$xmlDomain = $export->addChild('domain');
$xmlDomain->addAttribute('name', $domain->name);
$xmlDomain->addAttribute('description',
$domain->description);
foreach ($domain->getItems() as $item)
{
$xmlItem = $xmlDomain->addChild('item');
if ($item->id)
{
$xmlItem->addAttribute('id', $item->id);
}
foreach ($item->getFields() as $field)
{
$xmlItem->{$field->name} = $field->value;
}
}
}
$dom = new DOMDocument;
$dom->loadXML($export->asXML());
$dom->formatOutput = true;
return $dom->saveXML();
}
/**
* Gets the privacyconsent system plugin extension id.
*
* @return integer The privacyconsent system plugin extension id.
*
* @since 3.9.2
*/
public static function getPrivacyConsentPluginId()
{
$db = Factory::getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('extension_id'))
->from($db->quoteName('#__extensions'))
->where($db->quoteName('folder') . ' = ' .
$db->quote('system'))
->where($db->quoteName('element') . ' = ' .
$db->quote('privacyconsent'));
$db->setQuery($query);
try
{
$result = (int) $db->loadResult();
}
catch (RuntimeException $e)
{
JError::raiseWarning(500, $e->getMessage());
}
return $result;
}
}
helpers/removal/status.php000064400000001511151165412120011703
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Data object communicating the status of whether the data for an
information request can be removed.
*
* Typically, this object will only be used to communicate data will be
removed.
*
* @since 3.9.0
*/
class PrivacyRemovalStatus
{
/**
* Flag indicating the status reported by the plugin on whether the
information can be removed
*
* @var boolean
* @since 3.9.0
*/
public $canRemove = true;
/**
* A status message indicating the reason data can or cannot be removed
*
* @var string
* @since 3.9.0
*/
public $reason;
}
models/capabilities.php000064400000006535151165412120011200
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Capabilities model class.
*
* @since 3.9.0
*/
class PrivacyModelCapabilities extends JModelLegacy
{
/**
* Retrieve the extension capabilities.
*
* @return array
*
* @since 3.9.0
*/
public function getCapabilities()
{
$app = JFactory::getApplication();
/*
* Capabilities will be collected in two parts:
*
* 1) Core capabilities - This will cover the core API, i.e. all library
level classes
* 2) Extension capabilities - This will be collected by a plugin hook to
select plugin groups
*
* Plugins which report capabilities should return an associative array
with a single root level key which is used as the title
* for the reporting section and an array with each value being a
separate capability. All capability messages should be translated
* by the extension when building the array. An example of the structure
expected to be returned from plugins can be found in the
* $coreCapabilities array below.
*/
$coreCapabilities = array(
JText::_('COM_PRIVACY_HEADING_CORE_CAPABILITIES') => array(
JText::_('COM_PRIVACY_CORE_CAPABILITY_SESSION_IP_ADDRESS_AND_COOKIE'),
JText::sprintf('COM_PRIVACY_CORE_CAPABILITY_LOGGING_IP_ADDRESS',
$app->get('log_path', JPATH_ADMINISTRATOR .
'/logs')),
JText::_('COM_PRIVACY_CORE_CAPABILITY_COMMUNICATION_WITH_JOOMLA_ORG'),
)
);
/*
* We will search for capabilities from the following plugin groups:
*
* - Authentication: These plugins by design process user information and
may have capabilities such as creating cookies
* - Captcha: These plugins may communicate information to third party
systems
* - Installer: These plugins can add additional install capabilities to
the Extension Manager, such as the Install from Web service
* - Privacy: These plugins are the primary integration point into this
component
* - User: These plugins are intended to extend the user management
system
*
* This is in addition to plugin groups which are imported before this
method is triggered, generally this is the system group.
*/
JPluginHelper::importPlugin('authentication');
JPluginHelper::importPlugin('captcha');
JPluginHelper::importPlugin('installer');
JPluginHelper::importPlugin('privacy');
JPluginHelper::importPlugin('user');
$pluginResults =
$app->triggerEvent('onPrivacyCollectAdminCapabilities');
// We are going to "cheat" here and include this
component's capabilities without using a plugin
$extensionCapabilities = array(
JText::_('COM_PRIVACY') => array(
JText::_('COM_PRIVACY_EXTENSION_CAPABILITY_PERSONAL_INFO'),
)
);
foreach ($pluginResults as $pluginResult)
{
$extensionCapabilities += $pluginResult;
}
// Sort the extension list alphabetically
ksort($extensionCapabilities);
// Always prepend the core capabilities to the array
return $coreCapabilities + $extensionCapabilities;
}
/**
* Method to auto-populate the model state.
*
* @return void
*
* @since 3.9.0
*/
protected function populateState()
{
// Load the parameters.
$this->setState('params',
JComponentHelper::getParams('com_privacy'));
}
}
models/consents.php000064400000012432151165412120010374 0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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\Utilities\ArrayHelper;
/**
* Consents management model class.
*
* @since 3.9.0
*/
class PrivacyModelConsents extends JModelList
{
/**
* Constructor.
*
* @param array $config An optional associative array of configuration
settings.
*
* @since 3.9.0
*/
public function __construct($config = array())
{
if (empty($config['filter_fields']))
{
$config['filter_fields'] = array(
'id', 'a.id',
'user_id', 'a.user_id',
'subject', 'a.subject',
'created', 'a.created',
'username', 'u.username',
'state', 'a.state'
);
}
parent::__construct($config);
}
/**
* Method to get a JDatabaseQuery object for retrieving the data set from
a database.
*
* @return JDatabaseQuery
*
* @since 3.9.0
*/
protected function getListQuery()
{
// Create a new query object.
$db = $this->getDbo();
$query = $db->getQuery(true);
// Select the required fields from the table.
$query->select($this->getState('list.select',
'a.*'));
$query->from($db->quoteName('#__privacy_consents',
'a'));
// Join over the users for the username.
$query->select($db->quoteName('u.username',
'username'));
$query->join('LEFT', $db->quoteName('#__users',
'u') . ' ON u.id = a.user_id');
// Filter by search in email
$search = $this->getState('filter.search');
if (!empty($search))
{
if (stripos($search, 'id:') === 0)
{
$query->where($db->quoteName('a.id') . ' = '
. (int) substr($search, 3));
}
elseif (stripos($search, 'uid:') === 0)
{
$query->where($db->quoteName('a.user_id') . ' =
' . (int) substr($search, 4));
}
else
{
$search = $db->quote('%' . $db->escape($search, true) .
'%');
$query->where('(' .
$db->quoteName('u.username') . ' LIKE ' . $search .
')');
}
}
$state = $this->getState('filter.state');
if ($state != '')
{
$query->where($db->quoteName('a.state') . ' =
' . (int) $state);
}
// Handle the list ordering.
$ordering = $this->getState('list.ordering');
$direction = $this->getState('list.direction');
if (!empty($ordering))
{
$query->order($db->escape($ordering) . ' ' .
$db->escape($direction));
}
return $query;
}
/**
* Method to get a store id based on model configuration state.
*
* This is necessary because the model is used by the component and
* different modules that might need different sets of data or different
* ordering requirements.
*
* @param string $id A prefix for the store id.
*
* @return string
*
* @since 3.9.0
*/
protected function getStoreId($id = '')
{
// Compile the store id.
$id .= ':' . $this->getState('filter.search');
return parent::getStoreId($id);
}
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @param string $ordering An optional ordering field.
* @param string $direction An optional direction (asc|desc).
*
* @return void
*
* @since 3.9.0
*/
protected function populateState($ordering = 'a.id', $direction
= 'desc')
{
// Load the filter state.
$this->setState(
'filter.search',
$this->getUserStateFromRequest($this->context .
'.filter.search', 'filter_search')
);
$this->setState(
'filter.subject',
$this->getUserStateFromRequest($this->context .
'.filter.subject', 'filter_subject')
);
$this->setState(
'filter.state',
$this->getUserStateFromRequest($this->context .
'.filter.state', 'filter_state')
);
// Load the parameters.
$this->setState('params',
JComponentHelper::getParams('com_privacy'));
// List state information.
parent::populateState($ordering, $direction);
}
/**
* Method to invalidate specific consents.
*
* @param array $pks The ids of the consents to invalidate.
*
* @return boolean True on success.
*/
public function invalidate($pks)
{
// Sanitize the ids.
$pks = (array) $pks;
$pks = ArrayHelper::toInteger($pks);
try
{
$db = $this->getDbo();
$query = $db->getQuery(true)
->update($db->quoteName('#__privacy_consents'))
->set($db->quoteName('state') . ' = -1')
->where($db->quoteName('id') . ' IN (' .
implode(',', $pks) . ')')
->where($db->quoteName('state') . ' = 1');
$db->setQuery($query);
$db->execute();
}
catch (JDatabaseExceptionExecuting $e)
{
$this->setError($e->getMessage());
return false;
}
return true;
}
/**
* Method to invalidate a group of specific consents.
*
* @param array $subject The subject of the consents to invalidate.
*
* @return boolean True on success.
*/
public function invalidateAll($subject)
{
try
{
$db = $this->getDbo();
$query = $db->getQuery(true)
->update($db->quoteName('#__privacy_consents'))
->set($db->quoteName('state') . ' = -1')
->where($db->quoteName('subject') . ' = ' .
$db->quote($subject))
->where($db->quoteName('state') . ' = 1');
$db->setQuery($query);
$db->execute();
}
catch (JDatabaseExceptionExecuting $e)
{
$this->setError($e->getMessage());
return false;
}
return true;
}
}
models/dashboard.php000064400000010115151165412120010463 0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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\Router\Route;
/**
* Dashboard model class.
*
* @since 3.9.0
*/
class PrivacyModelDashboard extends JModelLegacy
{
/**
* Get the information about the published privacy policy
*
* @return array Array containing a status of whether a privacy policy
is set and a link to the policy document for editing
*
* @since 3.9.0
*/
public function getPrivacyPolicyInfo()
{
$policy = array(
'published' => false,
'articlePublished' => false,
'editLink' => '',
);
/*
* Prior to 3.9.0 it was common for a plugin such as the User - Profile
plugin to define a privacy policy or
* terms of service article, therefore we will also import the user
plugin group to process this event.
*/
JPluginHelper::importPlugin('privacy');
JPluginHelper::importPlugin('user');
JFactory::getApplication()->triggerEvent('onPrivacyCheckPrivacyPolicyPublished',
array(&$policy));
return $policy;
}
/**
* Get a count of the active information requests grouped by type and
status
*
* @return array Array containing site privacy requests
*
* @since 3.9.0
*/
public function getRequestCounts()
{
$db = $this->getDbo();
$query = $db->getQuery(true)
->select(
array(
'COUNT(*) AS count',
$db->quoteName('status'),
$db->quoteName('request_type'),
)
)
->from($db->quoteName('#__privacy_requests'))
->group($db->quoteName('status'))
->group($db->quoteName('request_type'));
$db->setQuery($query);
return $db->loadObjectList();
}
/**
* Check whether there is a menu item for the request form
*
* @return array Array containing a status of whether a menu is
published for the request form and its current link
*
* @since 3.9.0
*/
public function getRequestFormPublished()
{
$status = array(
'exists' => false,
'published' => false,
'link' => '',
);
$db = $this->getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('id') . ', ' .
$db->quoteName('published') . ', ' .
$db->quoteName('language'))
->from($db->quoteName('#__menu'))
->where($db->quoteName('client_id') . ' = 0')
->where($db->quoteName('link') . ' = ' .
$db->quote('index.php?option=com_privacy&view=request'));
$db->setQuery($query);
$menuItem = $db->loadObject();
// Check if the menu item exists in database
if ($menuItem)
{
$status['exists'] = true;
// Check if the menu item is published
if ($menuItem->published == 1)
{
$status['published'] = true;
}
// Add language to the url if the site is multilingual
if (JLanguageMultilang::isEnabled() && $menuItem->language
&& $menuItem->language !== '*')
{
$lang = '&lang=' . $menuItem->language;
}
else
{
$lang = '';
}
}
$linkMode = JFactory::getApplication()->get('force_ssl', 0)
== 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;
if (!$menuItem)
{
if (JLanguageMultilang::isEnabled())
{
// Find the Itemid of the home menu item tagged to the site default
language
$params = JComponentHelper::getParams('com_languages');
$defaultSiteLanguage = $params->get('site');
$db = $this->getDbo();
$query = $db->getQuery(true)
->select($db->quoteName('id'))
->from($db->quoteName('#__menu'))
->where($db->quoteName('client_id') . ' =
0')
->where($db->quoteName('home') . ' = 1')
->where($db->quoteName('language') . ' = ' .
$db->quote($defaultSiteLanguage));
$db->setQuery($query);
$homeId = (int) $db->loadResult();
$itemId = $homeId ? '&Itemid=' . $homeId : '';
}
else
{
$itemId = '';
}
$status['link'] = JRoute::link('site',
'index.php?option=com_privacy&view=request' . $itemId, true,
$linkMode);
}
else
{
$status['link'] = JRoute::link('site',
'index.php?Itemid=' . $menuItem->id . $lang, true, $linkMode);
}
return $status;
}
}
models/export.php000064400000021303151165412120010056 0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
JLoader::register('PrivacyHelper', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/privacy.php');
/**
* Export model class.
*
* @since 3.9.0
*/
class PrivacyModelExport extends JModelLegacy
{
/**
* Create the export document for an information request.
*
* @param integer $id The request ID to process
*
* @return PrivacyExportDomain[]|boolean A SimpleXMLElement object for a
successful export or boolean false on an error
*
* @since 3.9.0
*/
public function collectDataForExportRequest($id = null)
{
$id = !empty($id) ? $id : (int) $this->getState($this->getName() .
'.request_id');
if (!$id)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_ID_REQUIRED_FOR_EXPORT'));
return false;
}
/** @var PrivacyTableRequest $table */
$table = $this->getTable();
if (!$table->load($id))
{
$this->setError($table->getError());
return false;
}
if ($table->request_type !== 'export')
{
$this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_TYPE_NOT_EXPORT'));
return false;
}
if ($table->status != 1)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_EXPORT_UNCONFIRMED_REQUEST'));
return false;
}
// If there is a user account associated with the email address, load it
here for use in the plugins
$db = $this->getDbo();
$userId = (int) $db->setQuery(
$db->getQuery(true)
->select('id')
->from($db->quoteName('#__users'))
->where('LOWER(' . $db->quoteName('email') .
') = LOWER(' . $db->quote($table->email) . ')'),
0,
1
)->loadResult();
$user = $userId ? JUser::getInstance($userId) : null;
// Log the export
$this->logExport($table);
JPluginHelper::importPlugin('privacy');
$pluginResults =
JFactory::getApplication()->triggerEvent('onPrivacyExportRequest',
array($table, $user));
$domains = array();
foreach ($pluginResults as $pluginDomains)
{
$domains = array_merge($domains, $pluginDomains);
}
return $domains;
}
/**
* Email the data export to the user.
*
* @param integer $id The request ID to process
*
* @return boolean
*
* @since 3.9.0
*/
public function emailDataExport($id = null)
{
$id = !empty($id) ? $id : (int) $this->getState($this->getName() .
'.request_id');
if (!$id)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_ID_REQUIRED_FOR_EXPORT'));
return false;
}
$exportData = $this->collectDataForExportRequest($id);
if ($exportData === false)
{
// Error is already set, we just need to bail
return false;
}
/** @var PrivacyTableRequest $table */
$table = $this->getTable();
if (!$table->load($id))
{
$this->setError($table->getError());
return false;
}
if ($table->request_type !== 'export')
{
$this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_TYPE_NOT_EXPORT'));
return false;
}
if ($table->status != 1)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_EXPORT_UNCONFIRMED_REQUEST'));
return false;
}
// Log the email
$this->logExportEmailed($table);
/*
* If there is an associated user account, we will attempt to send this
email in the user's preferred language.
* Because of this, it is expected that Language::_() is directly called
and that the Text class is NOT used
* for translating all messages.
*
* Error messages will still be displayed to the administrator, so those
messages should continue to use the Text class.
*/
$lang = JFactory::getLanguage();
$db = $this->getDbo();
$userId = (int) $db->setQuery(
$db->getQuery(true)
->select('id')
->from($db->quoteName('#__users'))
->where('LOWER(' . $db->quoteName('email') .
') = LOWER(' . $db->quote($table->email) . ')'),
0,
1
)->loadResult();
if ($userId)
{
$receiver = JUser::getInstance($userId);
/*
* We don't know if the user has admin access, so we will check if
they have an admin language in their parameters,
* falling back to the site language, falling back to the currently
active language
*/
$langCode = $receiver->getParam('admin_language',
'');
if (!$langCode)
{
$langCode = $receiver->getParam('language',
$lang->getTag());
}
$lang = JLanguage::getInstance($langCode, $lang->getDebug());
}
// Ensure the right language files have been loaded
$lang->load('com_privacy', JPATH_ADMINISTRATOR, null, false,
true)
|| $lang->load('com_privacy', JPATH_ADMINISTRATOR .
'/components/com_privacy', null, false, true);
// The mailer can be set to either throw Exceptions or return boolean
false, account for both
try
{
$app = JFactory::getApplication();
$substitutions = array(
'[SITENAME]' => $app->get('sitename'),
'[URL]' => JUri::root(),
'\\n' => "\n",
);
$emailSubject =
$lang->_('COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_SUBJECT');
$emailBody =
$lang->_('COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_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($table->email);
$mailer->addStringAttachment(
PrivacyHelper::renderDataAsXml($exportData),
'user-data_' .
JUri::getInstance()->toString(array('host')) .
'.xml'
);
$mailResult = $mailer->Send();
if ($mailResult instanceof JException)
{
// JError was already called so we just need to return now
return false;
}
elseif ($mailResult === false)
{
$this->setError($mailer->ErrorInfo);
return false;
}
return true;
}
catch (phpmailerException $exception)
{
$this->setError($exception->getMessage());
return false;
}
return true;
}
/**
* Method to get a table object, load it if necessary.
*
* @param string $name The table name. Optional.
* @param string $prefix The class prefix. Optional.
* @param array $options Configuration array for model. Optional.
*
* @return JTable A JTable object
*
* @since 3.9.0
* @throws \Exception
*/
public function getTable($name = 'Request', $prefix =
'PrivacyTable', $options = array())
{
return parent::getTable($name, $prefix, $options);
}
/**
* Log the data export to the action log system.
*
* @param PrivacyTableRequest $request The request record being
processed
*
* @return void
*
* @since 3.9.0
*/
public function logExport(PrivacyTableRequest $request)
{
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_actionlogs/models',
'ActionlogsModel');
$user = JFactory::getUser();
$message = array(
'action' => 'export',
'id' => $request->id,
'itemlink' =>
'index.php?option=com_privacy&view=request&id=' .
$request->id,
'userid' => $user->id,
'username' => $user->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
);
/** @var ActionlogsModelActionlog $model */
$model = JModelLegacy::getInstance('Actionlog',
'ActionlogsModel');
$model->addLog(array($message),
'COM_PRIVACY_ACTION_LOG_EXPORT', 'com_privacy.request',
$user->id);
}
/**
* Log the data export email to the action log system.
*
* @param PrivacyTableRequest $request The request record being
processed
*
* @return void
*
* @since 3.9.0
*/
public function logExportEmailed(PrivacyTableRequest $request)
{
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_actionlogs/models',
'ActionlogsModel');
$user = JFactory::getUser();
$message = array(
'action' => 'export_emailed',
'id' => $request->id,
'itemlink' =>
'index.php?option=com_privacy&view=request&id=' .
$request->id,
'userid' => $user->id,
'username' => $user->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
);
/** @var ActionlogsModelActionlog $model */
$model = JModelLegacy::getInstance('Actionlog',
'ActionlogsModel');
$model->addLog(array($message),
'COM_PRIVACY_ACTION_LOG_EXPORT_EMAILED',
'com_privacy.request', $user->id);
}
/**
* Method to auto-populate the model state.
*
* @return void
*
* @since 3.9.0
*/
protected function populateState()
{
// Get the pk of the record from the request.
$this->setState($this->getName() . '.request_id',
JFactory::getApplication()->input->getUint('id'));
// Load the parameters.
$this->setState('params',
JComponentHelper::getParams('com_privacy'));
}
}
models/fields/requeststatus.php000064400000001542151165412120012742
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
JFormHelper::loadFieldClass('predefinedlist');
/**
* Form Field to load a list of request statuses
*
* @since 3.9.0
*/
class PrivacyFormFieldRequeststatus extends JFormFieldPredefinedList
{
/**
* The form field type.
*
* @var string
* @since 3.9.0
*/
public $type = 'RequestStatus';
/**
* Available statuses
*
* @var array
* @since 3.9.0
*/
protected $predefinedOptions = array(
'-1' => 'COM_PRIVACY_STATUS_INVALID',
'0' => 'COM_PRIVACY_STATUS_PENDING',
'1' => 'COM_PRIVACY_STATUS_CONFIRMED',
'2' => 'COM_PRIVACY_STATUS_COMPLETED',
);
}
models/fields/requesttype.php000064400000001460151165412120012377
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
JFormHelper::loadFieldClass('predefinedlist');
/**
* Form Field to load a list of request types
*
* @since 3.9.0
*/
class PrivacyFormFieldRequesttype extends JFormFieldPredefinedList
{
/**
* The form field type.
*
* @var string
* @since 3.9.0
*/
public $type = 'RequestType';
/**
* Available types
*
* @var array
* @since 3.9.0
*/
protected $predefinedOptions = array(
'export' =>
'COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_EXPORT',
'remove' =>
'COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_REMOVE',
);
}
models/forms/filter_consents.xml000064400000004423151165412120013101
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset
addfieldpath="/administrator/components/com_privacy/models/fields"
/>
<fields name="filter">
<field
name="search"
type="text"
inputmode="search"
label="COM_PRIVACY_FILTER_SEARCH_LABEL"
description="COM_PRIVACY_SEARCH_IN_USERNAME"
hint="JSEARCH_FILTER"
/>
<field
name="state"
type="list"
label="COM_PRIVACY_CONSENTS_FILTER_STATE"
onchange="this.form.submit();"
>
<option value="">JOPTION_SELECT_PUBLISHED</option>
<option
value="1">COM_PRIVACY_CONSENTS_STATE_VALID</option>
<option
value="0">COM_PRIVACY_CONSENTS_STATE_OBSOLETE</option>
<option
value="-1">COM_PRIVACY_CONSENTS_STATE_INVALIDATED</option>
</field>
<field
name="subject"
type="sql"
label="COM_PRIVACY_CONSENTS_FILTER_SUBJECT"
sql_select="subject"
sql_from="#__privacy_consents"
sql_group="subject"
sql_order="subject ASC"
key_field="subject"
translate="true"
onchange="this.form.submit();"
>
<option
value="">COM_PRIVACY_CONSENTS_SUBJECT_DEFAULT</option>
</field>
</fields>
<fields name="list">
<field
name="fullordering"
type="list"
label="JGLOBAL_SORT_BY"
description="JGLOBAL_SORT_BY"
onchange="this.form.submit();"
default="a.id DESC"
validate="options"
>
<option value="a.state
ASC">COM_PRIVACY_HEADING_STATUS_ASC</option>
<option value="a.state
DESC">COM_PRIVACY_HEADING_STATUS_DESC</option>
<option value="u.username
ASC">COM_PRIVACY_HEADING_USERNAME_ASC</option>
<option value="u.username
DESC">COM_PRIVACY_HEADING_USERNAME_DESC</option>
<option value="a.user_id
ASC">COM_PRIVACY_HEADING_USERID_ASC</option>
<option value="a.user_id
DESC">COM_PRIVACY_HEADING_USERID_DESC</option>
<option value="a.subject
ASC">COM_PRIVACY_HEADING_SUBJECT_ASC</option>
<option value="a.subject
DESC">COM_PRIVACY_HEADING_SUBJECT_DESC</option>
<option value="a.created
ASC">COM_PRIVACY_HEADING_CREATED_ASC</option>
<option value="a.created
DESC">COM_PRIVACY_HEADING_CREATED_DESC</option>
<option value="a.id
ASC">JGRID_HEADING_ID_ASC</option>
<option value="a.id
DESC">JGRID_HEADING_ID_DESC</option>
</field>
<field
name="limit"
type="limitbox"
class="input-mini"
default="25"
onchange="this.form.submit();"
/>
</fields>
</form>
models/forms/filter_requests.xml000064400000003522151165412120013117
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset
addfieldpath="/administrator/components/com_privacy/models/fields"
/>
<fields name="filter">
<field
name="search"
type="text"
inputmode="search"
label="COM_PRIVACY_FILTER_SEARCH_LABEL"
description="COM_PRIVACY_SEARCH_IN_EMAIL"
hint="JSEARCH_FILTER"
/>
<field
name="status"
type="privacy.requeststatus"
label="COM_PRIVACY_FILTER_STATUS"
description="COM_PRIVACY_FILTER_STATUS_DESC"
onchange="this.form.submit();"
>
<option value="">JOPTION_SELECT_PUBLISHED</option>
</field>
<field
name="request_type"
type="privacy.requesttype"
label="COM_PRIVACY_FILTER_REQUEST_TYPE"
description="COM_PRIVACY_FILTER_REQUEST_TYPE_DESC"
onchange="this.form.submit();"
>
<option
value="">COM_PRIVACY_SELECT_REQUEST_TYPE</option>
</field>
</fields>
<fields name="list">
<field
name="fullordering"
type="list"
label="JGLOBAL_SORT_BY"
description="JGLOBAL_SORT_BY"
onchange="this.form.submit();"
default="a.id DESC"
validate="options"
>
<option value="">JGLOBAL_SORT_BY</option>
<option value="a.email
ASC">COM_PRIVACY_HEADING_EMAIL_ASC</option>
<option value="a.email
DESC">COM_PRIVACY_HEADING_EMAIL_DESC</option>
<option value="a.request_type
ASC">COM_PRIVACY_HEADING_REQUEST_TYPE_ASC</option>
<option value="a.request_type
DESC">COM_PRIVACY_HEADING_REQUEST_TYPE_DESC</option>
<option value="a.requested_at
ASC">COM_PRIVACY_HEADING_REQUESTED_AT_ASC</option>
<option value="a.requested_at
DESC">COM_PRIVACY_HEADING_REQUESTED_AT_DESC</option>
<option value="a.id
ASC">JGRID_HEADING_ID_ASC</option>
<option value="a.id
DESC">JGRID_HEADING_ID_DESC</option>
</field>
<field
name="limit"
type="limitbox"
class="input-mini"
default="25"
onchange="this.form.submit();"
/>
</fields>
</form>
models/forms/request.xml000064400000000705151165412120011367
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset name="default">
<field
name="request_type"
type="list"
label="COM_PRIVACY_FIELD_REQUEST_TYPE_LABEL"
description="COM_PRIVACY_FIELD_REQUEST_TYPE_DESC"
filter="string"
default="export"
validate="options"
>
<option
value="export">COM_PRIVACY_REQUEST_TYPE_EXPORT</option>
<option
value="remove">COM_PRIVACY_REQUEST_TYPE_REMOVE</option>
</field>
</fieldset>
</form>
models/remove.php000064400000012632151165412120010037 0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
JLoader::register('PrivacyHelper', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/privacy.php');
JLoader::register('PrivacyRemovalStatus', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/removal/status.php');
/**
* Remove model class.
*
* @since 3.9.0
*/
class PrivacyModelRemove extends JModelLegacy
{
/**
* Remove the user data.
*
* @param integer $id The request ID to process
*
* @return boolean
*
* @since 3.9.0
*/
public function removeDataForRequest($id = null)
{
$id = !empty($id) ? $id : (int) $this->getState($this->getName() .
'.request_id');
if (!$id)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_ID_REQUIRED_FOR_REMOVE'));
return false;
}
/** @var PrivacyTableRequest $table */
$table = $this->getTable();
if (!$table->load($id))
{
$this->setError($table->getError());
return false;
}
if ($table->request_type !== 'remove')
{
$this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_TYPE_NOT_REMOVE'));
return false;
}
if ($table->status != 1)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_REMOVE_UNCONFIRMED_REQUEST'));
return false;
}
// If there is a user account associated with the email address, load it
here for use in the plugins
$db = $this->getDbo();
$userId = (int) $db->setQuery(
$db->getQuery(true)
->select('id')
->from($db->quoteName('#__users'))
->where('LOWER(' . $db->quoteName('email') .
') = LOWER(' . $db->quote($table->email) . ')'),
0,
1
)->loadResult();
$user = $userId ? JUser::getInstance($userId) : null;
$canRemove = true;
JPluginHelper::importPlugin('privacy');
/** @var PrivacyRemovalStatus[] $pluginResults */
$pluginResults =
JFactory::getApplication()->triggerEvent('onPrivacyCanRemoveData',
array($table, $user));
foreach ($pluginResults as $status)
{
if (!$status->canRemove)
{
$this->setError($status->reason ?:
JText::_('COM_PRIVACY_ERROR_CANNOT_REMOVE_DATA'));
$canRemove = false;
}
}
if (!$canRemove)
{
$this->logRemoveBlocked($table, $this->getErrors());
return false;
}
// Log the removal
$this->logRemove($table);
JFactory::getApplication()->triggerEvent('onPrivacyRemoveData',
array($table, $user));
return true;
}
/**
* Method to get a table object, load it if necessary.
*
* @param string $name The table name. Optional.
* @param string $prefix The class prefix. Optional.
* @param array $options Configuration array for model. Optional.
*
* @return JTable A JTable object
*
* @since 3.9.0
* @throws \Exception
*/
public function getTable($name = 'Request', $prefix =
'PrivacyTable', $options = array())
{
return parent::getTable($name, $prefix, $options);
}
/**
* Log the data removal to the action log system.
*
* @param PrivacyTableRequest $request The request record being
processed
*
* @return void
*
* @since 3.9.0
*/
public function logRemove(PrivacyTableRequest $request)
{
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_actionlogs/models',
'ActionlogsModel');
$user = JFactory::getUser();
$message = array(
'action' => 'remove',
'id' => $request->id,
'itemlink' =>
'index.php?option=com_privacy&view=request&id=' .
$request->id,
'userid' => $user->id,
'username' => $user->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
);
/** @var ActionlogsModelActionlog $model */
$model = JModelLegacy::getInstance('Actionlog',
'ActionlogsModel');
$model->addLog(array($message),
'COM_PRIVACY_ACTION_LOG_REMOVE', 'com_privacy.request',
$user->id);
}
/**
* Log the data removal being blocked to the action log system.
*
* @param PrivacyTableRequest $request The request record being
processed
* @param string[] $reasons The reasons given why the
record could not be removed.
*
* @return void
*
* @since 3.9.0
*/
public function logRemoveBlocked(PrivacyTableRequest $request, array
$reasons)
{
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_actionlogs/models',
'ActionlogsModel');
$user = JFactory::getUser();
$message = array(
'action' => 'remove-blocked',
'id' => $request->id,
'itemlink' =>
'index.php?option=com_privacy&view=request&id=' .
$request->id,
'userid' => $user->id,
'username' => $user->username,
'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
'reasons' => implode('; ', $reasons),
);
/** @var ActionlogsModelActionlog $model */
$model = JModelLegacy::getInstance('Actionlog',
'ActionlogsModel');
$model->addLog(array($message),
'COM_PRIVACY_ACTION_LOG_REMOVE_BLOCKED',
'com_privacy.request', $user->id);
}
/**
* Method to auto-populate the model state.
*
* @return void
*
* @since 3.9.0
*/
protected function populateState()
{
// Get the pk of the record from the request.
$this->setState($this->getName() . '.request_id',
JFactory::getApplication()->input->getUint('id'));
// Load the parameters.
$this->setState('params',
JComponentHelper::getParams('com_privacy'));
}
}
models/request.php000064400000016533151165412120010236 0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @copyright (C) 2018 Open Source Matters, Inc.
<https://www.joomla.org>
* @license GNU General Public License version 2 or later; see
LICENSE.txt
*/
defined('_JEXEC') or die;
use Joomla\CMS\Router\Route;
/**
* Request model class.
*
* @since 3.9.0
*/
class PrivacyModelRequest extends JModelAdmin
{
/**
* Creates an information request.
*
* @param array $data The data expected for the form.
*
* @return mixed Exception | JException | boolean
*
* @since 3.9.0
*/
public function createRequest($data)
{
// Creating requests requires the site's email sending be enabled
if (!JFactory::getConfig()->get('mailonline', 1))
{
$this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED'));
return false;
}
// Get the form.
$form = $this->getForm();
// Check for an error.
if ($form instanceof Exception)
{
return $form;
}
// Filter and validate the form data.
$data = $form->filter($data);
$return = $form->validate($data);
// Check for an error.
if ($return instanceof Exception)
{
return $return;
}
// Check the validation results.
if ($return === false)
{
// Get the validation messages from the form.
foreach ($form->getErrors() as $formError)
{
$this->setError($formError->getMessage());
}
return false;
}
// Get the user email address
$data['email'] = JFactory::getUser()->email;
// Search for an open information request matching the email and type
$db = $this->getDbo();
$query = $db->getQuery(true)
->select('COUNT(id)')
->from('#__privacy_requests')
->where('email = ' .
$db->quote($data['email']))
->where('request_type = ' .
$db->quote($data['request_type']))
->where('status IN (0, 1)');
try
{
$result = (int) $db->setQuery($query)->loadResult();
}
catch (JDatabaseException $exception)
{
// Can't check for existing requests, so don't create a new
one
$this->setError(JText::_('COM_PRIVACY_ERROR_CHECKING_FOR_EXISTING_REQUESTS'));
return false;
}
if ($result > 0)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_PENDING_REQUEST_OPEN'));
return false;
}
// Everything is good to go, create the request
$token =
JApplicationHelper::getHash(JUserHelper::genRandomPassword());
$hashedToken = JUserHelper::hashPassword($token);
$data['confirm_token'] = $hashedToken;
$data['confirm_token_created_at'] =
JFactory::getDate()->toSql();
if (!$this->save($data))
{
// The save function will set the error message, so just return here
return false;
}
// Push a notification to the site's super users, deliberately
ignoring if this process fails so the below message goes out
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');
$messageModel->notifySuperUsers(
JText::_('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CREATED_REQUEST_SUBJECT'),
JText::sprintf('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CREATED_REQUEST_MESSAGE',
$data['email'])
);
// The mailer can be set to either throw Exceptions or return boolean
false, account for both
try
{
$app = JFactory::getApplication();
$linkMode = $app->get('force_ssl', 0) == 2 ?
Route::TLS_FORCE : Route::TLS_IGNORE;
$substitutions = array(
'[SITENAME]' => $app->get('sitename'),
'[URL]' => JUri::root(),
'[TOKENURL]' => JRoute::link('site',
'index.php?option=com_privacy&view=confirm&confirm_token='
. $token, false, $linkMode, true),
'[FORMURL]' => JRoute::link('site',
'index.php?option=com_privacy&view=confirm', false,
$linkMode, true),
'[TOKEN]' => $token,
'\\n' => "\n",
);
switch ($data['request_type'])
{
case 'export':
$emailSubject =
JText::_('COM_PRIVACY_EMAIL_REQUEST_SUBJECT_EXPORT_REQUEST');
$emailBody =
JText::_('COM_PRIVACY_EMAIL_REQUEST_BODY_EXPORT_REQUEST');
break;
case 'remove':
$emailSubject =
JText::_('COM_PRIVACY_EMAIL_REQUEST_SUBJECT_REMOVE_REQUEST');
$emailBody =
JText::_('COM_PRIVACY_EMAIL_REQUEST_BODY_REMOVE_REQUEST');
break;
default:
$this->setError(JText::_('COM_PRIVACY_ERROR_UNKNOWN_REQUEST_TYPE'));
return false;
}
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($data['email']);
$mailResult = $mailer->Send();
if ($mailResult instanceof JException)
{
// JError was already called so we just need to return now
return false;
}
elseif ($mailResult === false)
{
$this->setError($mailer->ErrorInfo);
return false;
}
/** @var PrivacyTableRequest $table */
$table = $this->getTable();
if (!$table->load($this->getState($this->getName() .
'.id')))
{
$this->setError($table->getError());
return false;
}
// Log the request's creation
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_actionlogs/models',
'ActionlogsModel');
$message = array(
'action' => 'request-created',
'requesttype' => $table->request_type,
'subjectemail' => $table->email,
'id' => $table->id,
'itemlink' =>
'index.php?option=com_privacy&view=request&id=' .
$table->id,
);
/** @var ActionlogsModelActionlog $model */
$model = JModelLegacy::getInstance('Actionlog',
'ActionlogsModel');
$model->addLog(array($message),
'COM_PRIVACY_ACTION_LOG_CREATED_REQUEST',
'com_privacy.request');
// The email sent and the record is saved, everything is good to go from
here
return true;
}
catch (phpmailerException $exception)
{
$this->setError($exception->getMessage());
return false;
}
}
/**
* Method for getting the form from the model.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data
(default case), false if not.
*
* @return JForm|boolean A JForm object on success, false on failure
*
* @since 3.9.0
*/
public function getForm($data = array(), $loadData = true)
{
return $this->loadForm('com_privacy.request',
'request', array('control' => 'jform'));
}
/**
* Method to get a table object, load it if necessary.
*
* @param string $name The table name. Optional.
* @param string $prefix The class prefix. Optional.
* @param array $options Configuration array for model. Optional.
*
* @return JTable A JTable object
*
* @since 3.9.0
* @throws \Exception
*/
public function getTable($name = 'Request', $prefix =
'PrivacyTable', $options = array())
{
return parent::getTable($name, $prefix, $options);
}
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @return void
*
* @since 3.9.0
*/
protected function populateState()
{
// Get the application object.
$params =
JFactory::getApplication()->getParams('com_privacy');
// Load the parameters.
$this->setState('params', $params);
}
}
models/requests.php000064400000011217151165412120010413 0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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\Component\ComponentHelper;
/**
* Requests management model class.
*
* @since 3.9.0
*/
class PrivacyModelRequests extends JModelList
{
/**
* Constructor.
*
* @param array $config An optional associative array of configuration
settings.
*
* @since 3.9.0
*/
public function __construct($config = array())
{
if (empty($config['filter_fields']))
{
$config['filter_fields'] = array(
'id', 'a.id',
'email', 'a.email',
'requested_at', 'a.requested_at',
'request_type', 'a.request_type',
'status', 'a.status',
);
}
parent::__construct($config);
}
/**
* Method to get a JDatabaseQuery object for retrieving the data set from
a database.
*
* @return JDatabaseQuery
*
* @since 3.9.0
*/
protected function getListQuery()
{
// Create a new query object.
$db = $this->getDbo();
$query = $db->getQuery(true);
// Select the required fields from the table.
$query->select($this->getState('list.select',
'a.*'));
$query->from($db->quoteName('#__privacy_requests',
'a'));
// Filter by status
$status = $this->getState('filter.status');
if (is_numeric($status))
{
$query->where('a.status = ' . (int) $status);
}
// Filter by request type
$requestType = $this->getState('filter.request_type',
'');
if ($requestType)
{
$query->where('a.request_type = ' .
$db->quote($db->escape($requestType, true)));
}
// Filter by search in email
$search = $this->getState('filter.search');
if (!empty($search))
{
if (stripos($search, 'id:') === 0)
{
$query->where($db->quoteName('a.id') . ' = '
. (int) substr($search, 3));
}
else
{
$search = $db->quote('%' . $db->escape($search, true) .
'%');
$query->where('(' . $db->quoteName('a.email')
. ' LIKE ' . $search . ')');
}
}
// Handle the list ordering.
$ordering = $this->getState('list.ordering');
$direction = $this->getState('list.direction');
if (!empty($ordering))
{
$query->order($db->escape($ordering) . ' ' .
$db->escape($direction));
}
return $query;
}
/**
* Method to get a store id based on model configuration state.
*
* This is necessary because the model is used by the component and
* different modules that might need different sets of data or different
* ordering requirements.
*
* @param string $id A prefix for the store id.
*
* @return string
*
* @since 3.9.0
*/
protected function getStoreId($id = '')
{
// Compile the store id.
$id .= ':' . $this->getState('filter.search');
$id .= ':' . $this->getState('filter.status');
$id .= ':' .
$this->getState('filter.request_type');
return parent::getStoreId($id);
}
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @param string $ordering An optional ordering field.
* @param string $direction An optional direction (asc|desc).
*
* @return void
*
* @since 3.9.0
*/
protected function populateState($ordering = 'a.id', $direction
= 'desc')
{
// Load the filter state.
$this->setState(
'filter.search',
$this->getUserStateFromRequest($this->context .
'.filter.search', 'filter_search')
);
$this->setState(
'filter.status',
$this->getUserStateFromRequest($this->context .
'.filter.status', 'filter_status', '',
'int')
);
$this->setState(
'filter.request_type',
$this->getUserStateFromRequest($this->context .
'.filter.request_type', 'filter_request_type',
'', 'string')
);
// Load the parameters.
$this->setState('params',
JComponentHelper::getParams('com_privacy'));
// List state information.
parent::populateState($ordering, $direction);
}
/**
* Method to return number privacy requests older than X days.
*
* @return integer
*
* @since 3.9.0
*/
public function getNumberUrgentRequests()
{
// Load the parameters.
$params =
ComponentHelper::getComponent('com_privacy')->getParams();
$notify = (int) $params->get('notify', 14);
$now = JFactory::getDate()->toSql();
$period = '-' . $notify;
$db = $this->getDbo();
$query = $db->getQuery(true)
->select('COUNT(*)');
$query->from($db->quoteName('#__privacy_requests'));
$query->where($db->quoteName('status') . ' = 1
');
$query->where($query->dateAdd($db->quote($now), $period,
'DAY') . ' > ' .
$db->quoteName('requested_at'));
$db->setQuery($query);
return (int) $db->loadResult();
}
}
privacy.php000064400000000630151165412120006727 0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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;
$controller = JControllerLegacy::getInstance('Privacy');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
privacy.xml000064400000002541151165412120006743 0ustar00<?xml
version="1.0" encoding="utf-8"?>
<extension type="component" version="3.9"
method="upgrade">
<name>com_privacy</name>
<author>Joomla! Project</author>
<creationDate>May 2018</creationDate>
<copyright>(C) 2005 - 2020 Open Source Matters. All rights
reserved.</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>COM_PRIVACY_XML_DESCRIPTION</description>
<files folder="site">
<filename>controller.php</filename>
<filename>privacy.php</filename>
<filename>router.php</filename>
<folder>controllers</folder>
<folder>models</folder>
<folder>views</folder>
</files>
<languages folder="site">
<language
tag="en-GB">language/en-GB.com_privacy.ini</language>
</languages>
<administration>
<files folder="admin">
<filename>config.xml</filename>
<filename>controller.php</filename>
<filename>privacy.php</filename>
<folder>controllers</folder>
<folder>helpers</folder>
<folder>models</folder>
<folder>tables</folder>
<folder>views</folder>
</files>
<languages folder="admin">
<language
tag="en-GB">language/en-GB.com_privacy.ini</language>
<language
tag="en-GB">language/en-GB.com_privacy.sys.ini</language>
</languages>
</administration>
</extension>
tables/consent.php000064400000003012151165412120010172 0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Table interface class for the #__privacy_consents table
*
* @property integer $id Item ID (primary key)
* @property integer $remind The status of the reminder request
* @property string $token Hashed token for the reminder request
* @property integer $user_id User ID (pseudo foreign key to the
#__users table) if the request is associated to a user account
*
* @since 3.9.0
*/
class PrivacyTableConsent extends JTable
{
/**
* The class constructor.
*
* @param JDatabaseDriver $db JDatabaseDriver connector object.
*
* @since 3.9.0
*/
public function __construct(JDatabaseDriver $db)
{
parent::__construct('#__privacy_consents', 'id',
$db);
}
/**
* Method to store a row in the database from the Table instance
properties.
*
* @param boolean $updateNulls True to update fields even if they are
null.
*
* @return boolean True on success.
*
* @since 3.9.0
*/
public function store($updateNulls = false)
{
$date = JFactory::getDate();
// Set default values for new records
if (!$this->id)
{
if (!$this->remind)
{
$this->remind = '0';
}
if (!$this->created)
{
$this->created = $date->toSql();
}
}
return parent::store($updateNulls);
}
}
tables/request.php000064400000003512151165412120010216 0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Table interface class for the #__privacy_requests table
*
* @property integer $id Item ID (primary key)
* @property string $email The email address of the
individual requesting the data
* @property string $requested_at The time the request was
created at
* @property integer $status The status of the
information request
* @property string $request_type The type of information
request
* @property string $confirm_token Hashed token for
confirming the information request
* @property string $confirm_token_created_at The time the
confirmation token was generated
*
* @since 3.9.0
*/
class PrivacyTableRequest extends JTable
{
/**
* The class constructor.
*
* @param JDatabaseDriver $db JDatabaseDriver connector object.
*
* @since 3.9.0
*/
public function __construct(JDatabaseDriver $db)
{
parent::__construct('#__privacy_requests', 'id',
$db);
}
/**
* Method to store a row in the database from the Table instance
properties.
*
* @param boolean $updateNulls True to update fields even if they are
null.
*
* @return boolean True on success.
*
* @since 3.9.0
*/
public function store($updateNulls = false)
{
$date = JFactory::getDate();
// Set default values for new records
if (!$this->id)
{
if (!$this->status)
{
$this->status = '0';
}
if (!$this->requested_at)
{
$this->requested_at = $date->toSql();
}
}
return parent::store($updateNulls);
}
}
views/capabilities/tmpl/default.php000064400000003363151165412120013446
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/** @var PrivacyViewCapabilities $this */
?>
<?php if (!empty($this->sidebar)) : ?>
<div id="j-sidebar-container" class="span2">
<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="span10">
<?php else : ?>
<div id="j-main-container">
<?php endif; ?>
<div class="alert alert-info">
<h4 class="alert-heading"><?php echo
JText::_('COM_PRIVACY_MSG_CAPABILITIES_ABOUT_THIS_INFORMATION');
?></h4>
<?php echo
JText::_('COM_PRIVACY_MSG_CAPABILITIES_INTRODUCTION'); ?>
</div>
<?php if (empty($this->capabilities)) : ?>
<div class="alert alert-no-items">
<?php echo
JText::_('COM_PRIVACY_MSG_CAPABILITIES_NO_CAPABILITIES'); ?>
</div>
<?php else : ?>
<?php $i = 0; ?>
<?php echo JHtml::_('bootstrap.startAccordion',
'slide-capabilities', array('active' =>
'slide-0')); ?>
<?php foreach ($this->capabilities as $extension =>
$capabilities) : ?>
<?php echo JHtml::_('bootstrap.addSlide',
'slide-capabilities', $extension, 'slide-' . $i); ?>
<?php if (empty($capabilities)) : ?>
<div class="alert alert-no-items">
<?php echo
JText::_('COM_PRIVACY_MSG_EXTENSION_NO_CAPABILITIES'); ?>
</div>
<?php else : ?>
<ul>
<?php foreach ($capabilities as $capability) : ?>
<li><?php echo $capability; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<?php echo JHtml::_('bootstrap.endSlide'); ?>
<?php $i++; ?>
<?php endforeach; ?>
<?php echo JHtml::_('bootstrap.endAccordion'); ?>
<?php endif; ?>
</div>
views/capabilities/view.html.php000064400000003346151165412120012764
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Capabilities view class
*
* @since 3.9.0
*/
class PrivacyViewCapabilities extends JViewLegacy
{
/**
* The reported extension capabilities
*
* @var array
* @since 3.9.0
*/
protected $capabilities;
/**
* The HTML markup for the sidebar
*
* @var string
* @since 3.9.0
*/
protected $sidebar;
/**
* The state information
*
* @var JObject
* @since 3.9.0
*/
protected $state;
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse;
automatically searches through the template paths.
*
* @return mixed A string if successful, otherwise an Error object.
*
* @see JViewLegacy::loadTemplate()
* @since 3.9.0
* @throws Exception
*/
public function display($tpl = null)
{
// Initialise variables
$this->capabilities = $this->get('Capabilities');
$this->state = $this->get('State');
// Check for errors.
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors), 500);
}
$this->addToolbar();
$this->sidebar = JHtmlSidebar::render();
return parent::display($tpl);
}
/**
* Add the page title and toolbar.
*
* @return void
*
* @since 3.9.0
*/
protected function addToolbar()
{
JToolbarHelper::title(JText::_('COM_PRIVACY_VIEW_CAPABILITIES'),
'lock');
JToolbarHelper::preferences('com_privacy');
JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_CAPABILITIES');
}
}
views/consents/tmpl/default.php000064400000010207151165412120012644
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/** @var PrivacyViewConsent $this */
// Load the tooltip behavior.
JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');
$user = JFactory::getUser();
$listOrder =
$this->escape($this->state->get('list.ordering'));
$listDirn =
$this->escape($this->state->get('list.direction'));
$now = JFactory::getDate();
$stateIcons = array(-1 => 'trash', 0 =>
'archive', 1 => 'publish');
$stateMsgs = array(-1 =>
JText::_('COM_PRIVACY_CONSENTS_STATE_INVALIDATED'), 0 =>
JText::_('COM_PRIVACY_CONSENTS_STATE_OBSOLETE'), 1 =>
JText::_('COM_PRIVACY_CONSENTS_STATE_VALID'));
?>
<form action="<?php echo
JRoute::_('index.php?option=com_privacy&view=consents');
?>" method="post" name="adminForm"
id="adminForm">
<?php if (!empty($this->sidebar)) : ?>
<div id="j-sidebar-container" class="span2">
<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="span10">
<?php else : ?>
<div id="j-main-container">
<?php endif; ?>
<?php echo
JLayoutHelper::render('joomla.searchtools.default',
array('view' => $this)); ?>
<div class="clearfix"> </div>
<?php if (empty($this->items)) : ?>
<div class="alert alert-no-items">
<?php echo
JText::_('COM_PRIVACY_MSG_CONSENTS_NO_CONSENTS'); ?>
</div>
<?php else : ?>
<table class="table table-striped"
id="consentList">
<thead>
<tr>
<th width="1%" class="center">
<?php echo JHtml::_('grid.checkall'); ?>
</th>
<th width="1%" class="nowrap center">
<?php echo JHtml::_('searchtools.sort',
'JSTATUS', 'a.state', $listDirn, $listOrder); ?>
</th>
<th width="10%" class="nowrap">
<?php echo JHtml::_('searchtools.sort',
'JGLOBAL_USERNAME', 'u.username', $listDirn,
$listOrder); ?>
</th>
<th width="1%" class="nowrap">
<?php echo JHtml::_('searchtools.sort',
'COM_PRIVACY_HEADING_USERID', 'a.user_id', $listDirn,
$listOrder); ?>
</th>
<th width="10%" class="nowrap">
<?php echo JHtml::_('searchtools.sort',
'COM_PRIVACY_HEADING_CONSENTS_SUBJECT', 'a.subject',
$listDirn, $listOrder); ?>
</th>
<th class="nowrap">
<?php echo
JText::_('COM_PRIVACY_HEADING_CONSENTS_BODY'); ?>
</th>
<th width="15%" class="nowrap">
<?php echo JHtml::_('searchtools.sort',
'COM_PRIVACY_HEADING_CONSENTS_CREATED', 'a.created',
$listDirn, $listOrder); ?>
</th>
<th width="1%" class="nowrap hidden-phone">
<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder);
?>
</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="9">
<?php echo $this->pagination->getListFooter(); ?>
</td>
</tr>
</tfoot>
<tbody>
<?php foreach ($this->items as $i => $item) : ?>
<tr class="row<?php echo $i % 2; ?>">
<td class="center">
<?php echo JHtml::_('grid.id', $i, $item->id);
?>
</td>
<td>
<span class="icon icon-<?php echo
$stateIcons[$item->state]; ?>" title="<?php echo
$stateMsgs[$item->state]; ?>"></span>
</td>
<td>
<?php echo $item->username; ?>
</td>
<td>
<?php echo $item->user_id; ?>
</td>
<td>
<?php echo JText::_($item->subject); ?>
</td>
<td>
<?php echo $item->body; ?>
</td>
<td class="break-word">
<span class="hasTooltip" title="<?php echo
JHtml::_('date', $item->created,
JText::_('DATE_FORMAT_LC6')); ?>">
<?php echo JHtml::_('date.relative', new
JDate($item->created), null, $now); ?>
</span>
</td>
<td class="hidden-phone">
<?php echo (int) $item->id; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<input type="hidden" name="task"
value="" />
<input type="hidden" name="boxchecked"
value="0" />
<?php echo JHtml::_('form.token'); ?>
</div>
</form>
views/consents/tmpl/default.xml000064400000000322151165412120012652
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_PRIVACY_CONSENTS_VIEW_DEFAULT_TITLE">
<message>
<![CDATA[COM_PRIVACY_CONSENTS_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>
views/consents/view.html.php000064400000005676151165412120012177
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Consents view class
*
* @since 3.9.0
*/
class PrivacyViewConsents extends JViewLegacy
{
/**
* The active search tools filters
*
* @var array
* @since 3.9.0
* @note Must be public to be accessed from the search tools layout
*/
public $activeFilters;
/**
* Form instance containing the search tools filter form
*
* @var JForm
* @since 3.9.0
* @note Must be public to be accessed from the search tools layout
*/
public $filterForm;
/**
* The items to display
*
* @var array
* @since 3.9.0
*/
protected $items;
/**
* The pagination object
*
* @var JPagination
* @since 3.9.0
*/
protected $pagination;
/**
* The HTML markup for the sidebar
*
* @var string
* @since 3.9.0
*/
protected $sidebar;
/**
* The state information
*
* @var JObject
* @since 3.9.0
*/
protected $state;
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse;
automatically searches through the template paths.
*
* @return mixed A string if successful, otherwise an Error object.
*
* @see JViewLegacy::loadTemplate()
* @since 3.9.0
* @throws Exception
*/
public function display($tpl = null)
{
// Initialise variables
$this->items = $this->get('Items');
$this->pagination = $this->get('Pagination');
$this->state = $this->get('State');
$this->filterForm = $this->get('FilterForm');
$this->activeFilters = $this->get('ActiveFilters');
// Check for errors.
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors), 500);
}
$this->addToolbar();
$this->sidebar = JHtmlSidebar::render();
return parent::display($tpl);
}
/**
* Add the page title and toolbar.
*
* @return void
*
* @since 3.9.0
*/
protected function addToolbar()
{
JToolbarHelper::title(JText::_('COM_PRIVACY_VIEW_CONSENTS'),
'lock');
$bar = JToolbar::getInstance('toolbar');
// Add a button to invalidate a consent
$bar->appendButton(
'Confirm',
'COM_PRIVACY_CONSENTS_TOOLBAR_INVALIDATE_CONFIRM_MSG',
'trash',
'COM_PRIVACY_CONSENTS_TOOLBAR_INVALIDATE',
'consents.invalidate',
true
);
// If the filter is restricted to a specific subject, show the
"Invalidate all" button
if ($this->state->get('filter.subject') != '')
{
$bar->appendButton(
'Confirm',
'COM_PRIVACY_CONSENTS_TOOLBAR_INVALIDATE_ALL_CONFIRM_MSG',
'cancel',
'COM_PRIVACY_CONSENTS_TOOLBAR_INVALIDATE_ALL',
'consents.invalidateAll',
false
);
}
JToolbarHelper::preferences('com_privacy');
JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_CONSENTS');
}
}
views/dashboard/tmpl/default.php000064400000020132151165412120012735
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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\Language\Text;
use Joomla\CMS\Router\Route;
/** @var PrivacyViewDashboard $this */
// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/html');
JHtml::_('bootstrap.tooltip');
$totalRequests = 0;
$activeRequests = 0;
?>
<?php if (!empty($this->sidebar)) : ?>
<div id="j-sidebar-container" class="span2">
<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="span10">
<?php else : ?>
<div id="j-main-container">
<?php endif; ?>
<div class="row-fluid">
<div class="span6">
<div class="well well-small">
<h3 class="module-title nav-header"><?php echo
Text::_('COM_PRIVACY_DASHBOARD_HEADING_TOTAL_REQUEST_COUNT');
?></h3>
<div class="row-striped">
<?php if (count($this->requestCounts)) : ?>
<div class="row-fluid">
<div class="span5"><strong><?php echo
Text::_('COM_PRIVACY_DASHBOARD_HEADING_REQUEST_TYPE');
?></strong></div>
<div class="span5"><strong><?php echo
Text::_('COM_PRIVACY_DASHBOARD_HEADING_REQUEST_STATUS');
?></strong></div>
<div class="span2"><strong><?php echo
Text::_('COM_PRIVACY_DASHBOARD_HEADING_REQUEST_COUNT');
?></strong></div>
</div>
<?php foreach ($this->requestCounts as $row) : ?>
<div class="row-fluid">
<div class="span5">
<a class="hasTooltip" href="<?php echo
JRoute::_('index.php?option=com_privacy&view=requests&filter[request_type]='
. $row->request_type . '&filter[status]=' .
$row->status); ?>" data-original-title="<?php echo
JText::_('COM_PRIVACY_DASHBOARD_VIEW_REQUESTS'); ?>">
<strong><?php echo
Text::_('COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_' .
$row->request_type); ?></strong>
</a>
</div>
<div class="span5"><?php echo
JHtml::_('PrivacyHtml.helper.statusLabel', $row->status);
?></div>
<div class="span2"><span class="badge
badge-info"><?php echo $row->count;
?></span></div>
</div>
<?php if (in_array($row->status, array(0, 1))) : ?>
<?php $activeRequests += $row->count; ?>
<?php endif; ?>
<?php $totalRequests += $row->count; ?>
<?php endforeach; ?>
<div class="row-fluid">
<div class="span5"><?php echo
Text::plural('COM_PRIVACY_DASHBOARD_BADGE_TOTAL_REQUESTS',
$totalRequests); ?></div>
<div class="span7"><?php echo
Text::plural('COM_PRIVACY_DASHBOARD_BADGE_ACTIVE_REQUESTS',
$activeRequests); ?></div>
</div>
<?php else : ?>
<div class="row-fluid">
<div class="span12">
<div class="alert"><?php echo
Text::_('COM_PRIVACY_DASHBOARD_NO_REQUESTS'); ?></div>
</div>
</div>
<?php endif; ?>
</div>
</div>
</div>
<div class="span6">
<div class="well well-small">
<h3 class="module-title nav-header"><?php echo
Text::_('COM_PRIVACY_DASHBOARD_HEADING_STATUS_CHECK');
?></h3>
<div class="row-striped">
<div class="row-fluid">
<div class="span3"><strong><?php echo
Text::_('COM_PRIVACY_DASHBOARD_HEADING_STATUS');
?></strong></div>
<div class="span9"><strong><?php echo
Text::_('COM_PRIVACY_DASHBOARD_HEADING_CHECK');
?></strong></div>
</div>
<div class="row-fluid">
<div class="span3">
<?php if ($this->privacyPolicyInfo['published']
&& $this->privacyPolicyInfo['articlePublished']) :
?>
<span class="label label-success">
<span class="icon-checkbox"
aria-hidden="true"></span>
<?php echo Text::_('JPUBLISHED'); ?>
</span>
<?php elseif ($this->privacyPolicyInfo['published']
&& !$this->privacyPolicyInfo['articlePublished']) :
?>
<span class="label label-warning">
<span class="icon-warning"
aria-hidden="true"></span>
<?php echo Text::_('JUNPUBLISHED'); ?>
</span>
<?php else : ?>
<span class="label label-warning">
<span class="icon-warning"
aria-hidden="true"></span>
<?php echo
Text::_('COM_PRIVACY_STATUS_CHECK_NOT_AVAILABLE'); ?>
</span>
<?php endif; ?>
</div>
<div class="span9">
<div><?php echo
Text::_('COM_PRIVACY_STATUS_CHECK_PRIVACY_POLICY_PUBLISHED');
?></div>
<?php if ($this->privacyPolicyInfo['editLink'] !==
'') : ?>
<small><a href="<?php echo
$this->privacyPolicyInfo['editLink']; ?>"><?php
echo Text::_('COM_PRIVACY_EDIT_PRIVACY_POLICY');
?></a></small>
<?php else : ?>
<?php $link =
Route::_('index.php?option=com_plugins&task=plugin.edit&extension_id='
. $this->privacyConsentPluginId); ?>
<small><a href="<?php echo $link;
?>"><?php echo
Text::_('COM_PRIVACY_EDIT_PRIVACY_CONSENT_PLUGIN');
?></a></small>
<?php endif; ?>
</div>
</div>
<div class="row-fluid">
<div class="span3">
<?php if ($this->requestFormPublished['published']
&& $this->requestFormPublished['exists']) : ?>
<span class="label label-success">
<span class="icon-checkbox"
aria-hidden="true"></span>
<?php echo Text::_('JPUBLISHED'); ?>
</span>
<?php elseif
(!$this->requestFormPublished['published'] &&
$this->requestFormPublished['exists']) : ?>
<span class="label label-warning">
<span class="icon-warning"
aria-hidden="true"></span>
<?php echo Text::_('JUNPUBLISHED'); ?>
</span>
<?php else : ?>
<span class="label label-warning">
<span class="icon-warning"
aria-hidden="true"></span>
<?php echo
Text::_('COM_PRIVACY_STATUS_CHECK_NOT_AVAILABLE'); ?>
</span>
<?php endif; ?>
</div>
<div class="span9">
<div><?php echo
Text::_('COM_PRIVACY_STATUS_CHECK_REQUEST_FORM_MENU_ITEM_PUBLISHED');
?></div>
<?php if ($this->requestFormPublished['link'] !==
'') : ?>
<small><a href="<?php echo
$this->requestFormPublished['link']; ?>"><?php
echo $this->requestFormPublished['link'];
?></a></small>
<?php endif; ?>
</div>
</div>
<div class="row-fluid">
<div class="span3">
<?php if ($this->numberOfUrgentRequests === 0) : ?>
<span class="label label-success">
<span class="icon-checkbox"
aria-hidden="true"></span>
<?php echo Text::_('JNONE'); ?>
</span>
<?php else : ?>
<span class="label label-important">
<span class="icon-warning"
aria-hidden="true"></span>
<?php echo Text::_('WARNING'); ?>
</span>
<?php endif; ?>
</div>
<div class="span9">
<div><?php echo
Text::_('COM_PRIVACY_STATUS_CHECK_OUTSTANDING_URGENT_REQUESTS');
?></div>
<small><?php echo
Text::plural('COM_PRIVACY_STATUS_CHECK_OUTSTANDING_URGENT_REQUESTS_DESCRIPTION',
$this->urgentRequestDays); ?></small>
<?php if ($this->numberOfUrgentRequests > 0) : ?>
<small><a href="<?php echo
Route::_('index.php?option=com_privacy&view=requests&filter[status]=1&list[fullordering]=a.requested_at
ASC'); ?>"><?php echo
JText::_('COM_PRIVACY_SHOW_URGENT_REQUESTS');
?></a></small>
<?php endif; ?>
</div>
</div>
<div class="row-fluid">
<div class="span3">
<?php if ($this->sendMailEnabled) : ?>
<span class="label label-success">
<span class="icon-checkbox"
aria-hidden="true"></span>
<?php echo Text::_('JENABLED'); ?>
</span>
<?php else : ?>
<span class="label label-important">
<span class="icon-warning"
aria-hidden="true"></span>
<?php echo Text::_('JDISABLED'); ?>
</span>
<?php endif; ?>
</div>
<div class="span9">
<?php if (!$this->sendMailEnabled) : ?>
<div><?php echo
Text::_('COM_PRIVACY_STATUS_CHECK_SENDMAIL_DISABLED');
?></div>
<small><?php echo
Text::_('COM_PRIVACY_STATUS_CHECK_SENDMAIL_DISABLED_DESCRIPTION');
?></small>
<?php else : ?>
<div><?php echo
Text::_('COM_PRIVACY_STATUS_CHECK_SENDMAIL_ENABLED');
?></div>
<?php endif; ?>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
views/dashboard/tmpl/default.xml000064400000000324151165412120012747
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_PRIVACY_DASHBOARD_VIEW_DEFAULT_TITLE">
<message>
<![CDATA[COM_PRIVACY_DASHBOARD_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>
views/dashboard/view.html.php000064400000005673151165412120012267
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
/**
* Dashboard view class
*
* @since 3.9.0
*/
class PrivacyViewDashboard extends JViewLegacy
{
/**
* Number of urgent requests based on the component configuration
*
* @var integer
* @since 3.9.0
*/
protected $numberOfUrgentRequests;
/**
* Information about whether a privacy policy is published
*
* @var array
* @since 3.9.0
*/
protected $privacyPolicyInfo;
/**
* The request counts
*
* @var array
* @since 3.9.0
*/
protected $requestCounts;
/**
* Information about whether a menu item for the request form is published
*
* @var array
* @since 3.9.0
*/
protected $requestFormPublished;
/**
* Flag indicating the site supports sending email
*
* @var boolean
* @since 3.9.0
*/
protected $sendMailEnabled;
/**
* The HTML markup for the sidebar
*
* @var string
* @since 3.9.0
*/
protected $sidebar;
/**
* Id of the system privacy consent plugin
*
* @var integer
* @since 3.9.2
*/
protected $privacyConsentPluginId;
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse;
automatically searches through the template paths.
*
* @return mixed A string if successful, otherwise an Error object.
*
* @see JViewLegacy::loadTemplate()
* @since 3.9.0
* @throws Exception
*/
public function display($tpl = null)
{
// Initialise variables
$this->privacyConsentPluginId =
PrivacyHelper::getPrivacyConsentPluginId();
$this->privacyPolicyInfo =
$this->get('PrivacyPolicyInfo');
$this->requestCounts =
$this->get('RequestCounts');
$this->requestFormPublished =
$this->get('RequestFormPublished');
$this->sendMailEnabled = (bool)
Factory::getConfig()->get('mailonline', 1);
/** @var PrivacyModelRequests $requestsModel */
$requestsModel = $this->getModel('requests');
$this->numberOfUrgentRequests =
$requestsModel->getNumberUrgentRequests();
// Check for errors.
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors), 500);
}
$this->urgentRequestDays = (int)
ComponentHelper::getParams('com_privacy')->get('notify',
14);
$this->addToolbar();
$this->sidebar = JHtmlSidebar::render();
return parent::display($tpl);
}
/**
* Add the page title and toolbar.
*
* @return void
*
* @since 3.9.0
*/
protected function addToolbar()
{
JToolbarHelper::title(Text::_('COM_PRIVACY_VIEW_DASHBOARD'),
'lock');
JToolbarHelper::preferences('com_privacy');
JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_DASHBOARD');
}
}
views/export/view.xml.php000064400000002655151165412120011512
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
JLoader::register('PrivacyHelper', JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/privacy.php');
/**
* Export view class
*
* @since 3.9.0
*
* @property-read \Joomla\CMS\Document\XmlDocument $document
*/
class PrivacyViewExport extends JViewLegacy
{
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse;
automatically searches through the template paths.
*
* @return mixed A string if successful, otherwise an Error object.
*
* @see JViewLegacy::loadTemplate()
* @since 3.9.0
* @throws Exception
*/
public function display($tpl = null)
{
/** @var PrivacyModelExport $model */
$model = $this->getModel();
$exportData = $model->collectDataForExportRequest();
// Check for errors.
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors), 500);
}
$requestId = $model->getState($model->getName() .
'.request_id');
// This document should always be downloaded
$this->document->setDownload(true);
$this->document->setName('export-request-' . $requestId);
echo PrivacyHelper::renderDataAsXml($exportData);
}
}
views/request/tmpl/default.php000064400000003114151165412120012477
0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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;
/** @var PrivacyViewRequest $this */
JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', 'select');
?>
<div class="request-form<?php echo $this->pageclass_sfx;
?>">
<?php if ($this->params->get('show_page_heading')) :
?>
<div class="page-header">
<h1>
<?php echo
$this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<?php if ($this->sendMailEnabled) : ?>
<form action="<?php echo
JRoute::_('index.php?option=com_privacy&task=request.submit');
?>" method="post" class="form-validate
form-horizontal well">
<?php foreach ($this->form->getFieldsets() as $fieldset) :
?>
<fieldset>
<?php if (!empty($fieldset->label)) : ?>
<legend><?php echo JText::_($fieldset->label);
?></legend>
<?php endif; ?>
<?php echo $this->form->renderFieldset($fieldset->name);
?>
</fieldset>
<?php endforeach; ?>
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-primary
validate">
<?php echo JText::_('JSUBMIT'); ?>
</button>
</div>
</div>
<?php echo JHtml::_('form.token'); ?>
</form>
<?php else : ?>
<div class="alert alert-warning">
<p><?php echo
JText::_('COM_PRIVACY_WARNING_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED');
?></p>
</div>
<?php endif; ?>
</div>
views/request/tmpl/edit.php000064400000002466151165412120012011
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/** @var PrivacyViewRequest $this */
JHtml::_('behavior.formvalidator');
JHtml::_('behavior.keepalive');
JHtml::_('formbehavior.chosen', 'select');
$js = <<< JS
Joomla.submitbutton = function(task) {
if (task === 'request.cancel' ||
document.formvalidator.isValid(document.getElementById('item-form')))
{
Joomla.submitform(task, document.getElementById('item-form'));
}
};
JS;
JFactory::getDocument()->addScriptDeclaration($js);
?>
<form action="<?php echo
JRoute::_('index.php?option=com_privacy&view=request&layout=edit&id='
. (int) $this->item->id); ?>" method="post"
name="adminForm" id="item-form"
class="form-validate">
<div class="form-horizontal">
<div class="row-fluid">
<div class="span9">
<fieldset class="adminform">
<?php echo $this->form->renderField('email'); ?>
<?php echo $this->form->renderField('status');
?>
<?php echo
$this->form->renderField('request_type'); ?>
</fieldset>
</div>
</div>
<input type="hidden" name="task"
value="" />
<?php echo JHtml::_('form.token'); ?>
</div>
</form>
views/request/view.html.php000064400000006330151165412120012017
0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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\Registry\Registry;
/**
* Request view class
*
* @since 3.9.0
*/
class PrivacyViewRequest extends JViewLegacy
{
/**
* The form object
*
* @var JForm
* @since 3.9.0
*/
protected $form;
/**
* The CSS class suffix to append to the view container
*
* @var string
* @since 3.9.0
*/
protected $pageclass_sfx;
/**
* The view parameters
*
* @var Registry
* @since 3.9.0
*/
protected $params;
/**
* Flag indicating the site supports sending email
*
* @var boolean
* @since 3.9.0
*/
protected $sendMailEnabled;
/**
* The state information
*
* @var JObject
* @since 3.9.0
*/
protected $state;
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse;
automatically searches through the template paths.
*
* @return mixed A string if successful, otherwise an Error object.
*
* @see JViewLegacy::loadTemplate()
* @since 3.9.0
* @throws Exception
*/
public function display($tpl = null)
{
// Initialise variables.
$this->form = $this->get('Form');
$this->state = $this->get('State');
$this->params = $this->state->params;
$this->sendMailEnabled = (bool)
JFactory::getConfig()->get('mailonline', 1);
// Check for errors.
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors), 500);
}
// Escape strings for HTML output
$this->pageclass_sfx =
htmlspecialchars($this->params->get('pageclass_sfx',
''), ENT_COMPAT, 'UTF-8');
$this->prepareDocument();
return parent::display($tpl);
}
/**
* Prepares the document.
*
* @return void
*
* @since 3.9.0
*/
protected function prepareDocument()
{
$app = JFactory::getApplication();
$menus = $app->getMenu();
$title = null;
// Because the application sets a default page title,
// we need to get it from the menu item itself
$menu = $menus->getActive();
if ($menu)
{
$this->params->def('page_heading',
$this->params->get('page_title', $menu->title));
}
else
{
$this->params->def('page_heading',
JText::_('COM_PRIVACY_VIEW_REQUEST_PAGE_TITLE'));
}
$title = $this->params->get('page_title', '');
if (empty($title))
{
$title = $app->get('sitename');
}
elseif ($app->get('sitename_pagetitles', 0) == 1)
{
$title = JText::sprintf('JPAGETITLE',
$app->get('sitename'), $title);
}
elseif ($app->get('sitename_pagetitles', 0) == 2)
{
$title = JText::sprintf('JPAGETITLE', $title,
$app->get('sitename'));
}
$this->document->setTitle($title);
if ($this->params->get('menu-meta_description'))
{
$this->document->setDescription($this->params->get('menu-meta_description'));
}
if ($this->params->get('menu-meta_keywords'))
{
$this->document->setMetadata('keywords',
$this->params->get('menu-meta_keywords'));
}
if ($this->params->get('robots'))
{
$this->document->setMetadata('robots',
$this->params->get('robots'));
}
}
}
views/requests/tmpl/default.php000064400000013366151165412120012674
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/** @var PrivacyViewRequests $this */
// Include the component HTML helpers.
JHtml::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_privacy/helpers/html');
// Load the tooltip behavior.
JHtml::_('bootstrap.tooltip');
JHtml::_('behavior.multiselect');
JHtml::_('formbehavior.chosen', 'select');
$user = JFactory::getUser();
$listOrder =
$this->escape($this->state->get('list.ordering'));
$listDirn =
$this->escape($this->state->get('list.direction'));
$now = JFactory::getDate();
$urgentRequestDate= clone $now;
$urgentRequestDate->sub(new DateInterval('P' .
$this->urgentRequestAge . 'D'));
?>
<form action="<?php echo
JRoute::_('index.php?option=com_privacy&view=requests');
?>" method="post" name="adminForm"
id="adminForm">
<?php if (!empty($this->sidebar)) : ?>
<div id="j-sidebar-container" class="span2">
<?php echo $this->sidebar; ?>
</div>
<div id="j-main-container" class="span10">
<?php else : ?>
<div id="j-main-container">
<?php endif; ?>
<?php echo
JLayoutHelper::render('joomla.searchtools.default',
array('view' => $this)); ?>
<div class="clearfix"> </div>
<?php if (empty($this->items)) : ?>
<div class="alert alert-no-items">
<?php echo
JText::_('COM_PRIVACY_MSG_REQUESTS_NO_REQUESTS'); ?>
</div>
<?php else : ?>
<table class="table table-striped"
id="requestList">
<thead>
<tr>
<th width="5%" class="nowrap center">
<?php echo JText::_('COM_PRIVACY_HEADING_ACTIONS');
?>
</th>
<th width="5%" class="nowrap center">
<?php echo JText::_('JSTATUS'); ?>
</th>
<th class="nowrap">
<?php echo JHtml::_('searchtools.sort',
'JGLOBAL_EMAIL', 'a.email', $listDirn, $listOrder);
?>
</th>
<th width="10%" class="nowrap">
<?php echo JHtml::_('searchtools.sort',
'COM_PRIVACY_HEADING_REQUEST_TYPE', 'a.request_type',
$listDirn, $listOrder); ?>
</th>
<th width="20%" class="nowrap">
<?php echo JHtml::_('searchtools.sort',
'COM_PRIVACY_HEADING_REQUESTED_AT', 'a.requested_at',
$listDirn, $listOrder); ?>
</th>
<th width="1%" class="nowrap hidden-phone">
<?php echo JHtml::_('searchtools.sort',
'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder);
?>
</th>
</tr>
</thead>
<tfoot>
<tr>
<td colspan="7">
<?php echo $this->pagination->getListFooter(); ?>
</td>
</tr>
</tfoot>
<tbody>
<?php foreach ($this->items as $i => $item) : ?>
<?php
$itemRequestedAt = new JDate($item->requested_at);
?>
<tr class="row<?php echo $i % 2; ?>">
<td class="center">
<div class="btn-group">
<?php if ($item->status == 1 &&
$item->request_type === 'export') : ?>
<a class="btn btn-micro hasTooltip"
href="<?php echo
JRoute::_('index.php?option=com_privacy&task=request.export&format=xml&id='
. (int) $item->id); ?>" title="<?php echo
JText::_('COM_PRIVACY_ACTION_EXPORT_DATA');
?>"><span class="icon-download"
aria-hidden="true"></span><span
class="element-invisible"><?php echo
JText::_('COM_PRIVACY_ACTION_EXPORT_DATA');
?></span></a>
<?php if ($this->sendMailEnabled) : ?>
<a class="btn btn-micro hasTooltip"
href="<?php echo
JRoute::_('index.php?option=com_privacy&task=request.emailexport&id='
. (int) $item->id . '&' .
JFactory::getSession()->getFormToken() . '=1'); ?>"
title="<?php echo
JText::_('COM_PRIVACY_ACTION_EMAIL_EXPORT_DATA');
?>"><span class="icon-mail"
aria-hidden="true"></span><span
class="element-invisible"><?php echo
JText::_('COM_PRIVACY_ACTION_EMAIL_EXPORT_DATA');
?></span></a>
<?php endif; ?>
<?php endif; ?>
<?php if ($item->status == 1 &&
$item->request_type === 'remove') : ?>
<a class="btn btn-micro hasTooltip"
href="<?php echo
JRoute::_('index.php?option=com_privacy&task=request.remove&id='
. (int) $item->id . '&' .
JFactory::getSession()->getFormToken() . '=1'); ?>"
title="<?php echo
JText::_('COM_PRIVACY_ACTION_DELETE_DATA');
?>"><span class="icon-delete"
aria-hidden="true"></span><span
class="element-invisible"><?php echo
JText::_('COM_PRIVACY_ACTION_DELETE_DATA');
?></span></a>
<?php endif; ?>
</div>
</td>
<td class="center">
<?php echo JHtml::_('PrivacyHtml.helper.statusLabel',
$item->status); ?>
</td>
<td>
<?php if ($item->status == 1 && $urgentRequestDate
>= $itemRequestedAt) : ?>
<span class="pull-right label
label-important"><?php echo
JText::_('COM_PRIVACY_BADGE_URGENT_REQUEST'); ?></span>
<?php endif; ?>
<a class="hasTooltip" href="<?php echo
JRoute::_('index.php?option=com_privacy&view=request&id='
. (int) $item->id); ?>" title="<?php echo
JText::_('COM_PRIVACY_ACTION_VIEW'); ?>">
<?php echo
JStringPunycode::emailToUTF8($this->escape($item->email)); ?>
</a>
</td>
<td class="break-word">
<?php echo
JText::_('COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_' .
$item->request_type); ?>
</td>
<td class="break-word">
<span class="hasTooltip" title="<?php echo
JHtml::_('date', $item->requested_at,
JText::_('DATE_FORMAT_LC6')); ?>">
<?php echo JHtml::_('date.relative',
$itemRequestedAt, null, $now); ?>
</span>
</td>
<td class="hidden-phone">
<?php echo (int) $item->id; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
<input type="hidden" name="task"
value="" />
<input type="hidden" name="boxchecked"
value="0" />
<?php echo JHtml::_('form.token'); ?>
</div>
</form>
views/requests/tmpl/default.xml000064400000000322151165412120012671
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_PRIVACY_REQUESTS_VIEW_DEFAULT_TITLE">
<message>
<![CDATA[COM_PRIVACY_REQUESTS_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>
views/requests/view.html.php000064400000005634151165412120012210
0ustar00<?php
/**
* @package Joomla.Administrator
* @subpackage com_privacy
*
* @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;
/**
* Requests view class
*
* @since 3.9.0
*/
class PrivacyViewRequests extends JViewLegacy
{
/**
* The active search tools filters
*
* @var array
* @since 3.9.0
* @note Must be public to be accessed from the search tools layout
*/
public $activeFilters;
/**
* Form instance containing the search tools filter form
*
* @var JForm
* @since 3.9.0
* @note Must be public to be accessed from the search tools layout
*/
public $filterForm;
/**
* The items to display
*
* @var array
* @since 3.9.0
*/
protected $items;
/**
* The pagination object
*
* @var JPagination
* @since 3.9.0
*/
protected $pagination;
/**
* Flag indicating the site supports sending email
*
* @var boolean
* @since 3.9.0
*/
protected $sendMailEnabled;
/**
* The HTML markup for the sidebar
*
* @var string
* @since 3.9.0
*/
protected $sidebar;
/**
* The state information
*
* @var JObject
* @since 3.9.0
*/
protected $state;
/**
* The age of urgent requests
*
* @var integer
* @since 3.9.0
*/
protected $urgentRequestAge;
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse;
automatically searches through the template paths.
*
* @return mixed A string if successful, otherwise an Error object.
*
* @see JViewLegacy::loadTemplate()
* @since 3.9.0
* @throws Exception
*/
public function display($tpl = null)
{
// Initialise variables
$this->items = $this->get('Items');
$this->pagination = $this->get('Pagination');
$this->state = $this->get('State');
$this->filterForm = $this->get('FilterForm');
$this->activeFilters = $this->get('ActiveFilters');
$this->urgentRequestAge = (int)
JComponentHelper::getParams('com_privacy')->get('notify',
14);
$this->sendMailEnabled = (bool)
JFactory::getConfig()->get('mailonline', 1);
// Check for errors.
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors), 500);
}
$this->addToolbar();
$this->sidebar = JHtmlSidebar::render();
return parent::display($tpl);
}
/**
* Add the page title and toolbar.
*
* @return void
*
* @since 3.9.0
*/
protected function addToolbar()
{
JToolbarHelper::title(JText::_('COM_PRIVACY_VIEW_REQUESTS'),
'lock');
// Requests can only be created if mail sending is enabled
if (JFactory::getConfig()->get('mailonline', 1))
{
JToolbarHelper::addNew('request.add');
}
JToolbarHelper::preferences('com_privacy');
JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_REQUESTS');
}
}
models/confirm.php000064400000013151151165776720010217 0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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;
/**
* Request confirmation model class.
*
* @since 3.9.0
*/
class PrivacyModelConfirm extends JModelAdmin
{
/**
* Confirms the information request.
*
* @param array $data The data expected for the form.
*
* @return mixed Exception | JException | boolean
*
* @since 3.9.0
*/
public function confirmRequest($data)
{
// Get the form.
$form = $this->getForm();
// Check for an error.
if ($form instanceof Exception)
{
return $form;
}
// Filter and validate the form data.
$data = $form->filter($data);
$return = $form->validate($data);
// Check for an error.
if ($return instanceof Exception)
{
return $return;
}
// Check the validation results.
if ($return === false)
{
// Get the validation messages from the form.
foreach ($form->getErrors() as $formError)
{
$this->setError($formError->getMessage());
}
return false;
}
// Get the user email address
$data['email'] = JFactory::getUser()->email;
// Search for the information request
/** @var PrivacyTableRequest $table */
$table = $this->getTable();
if (!$table->load(array('email' =>
$data['email'], 'status' => 0)))
{
$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REQUESTS'));
return false;
}
// A request can only be confirmed if it is in a pending status and has a
confirmation token
if ($table->status != '0' || !$table->confirm_token)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REQUESTS'));
return false;
}
// A request can only be confirmed if the token is less than 24 hours old
$confirmTokenCreatedAt = new JDate($table->confirm_token_created_at);
$confirmTokenCreatedAt->add(new DateInterval('P1D'));
$now = new JDate('now');
if ($now > $confirmTokenCreatedAt)
{
// Invalidate the request
$table->status = -1;
$table->confirm_token = '';
try
{
$table->store();
}
catch (JDatabaseException $exception)
{
// The error will be logged in the database API, we just need to catch
it here to not let things fatal out
}
$this->setError(JText::_('COM_PRIVACY_ERROR_CONFIRM_TOKEN_EXPIRED'));
return false;
}
// Verify the token
if (!JUserHelper::verifyPassword($data['confirm_token'],
$table->confirm_token))
{
$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REQUESTS'));
return false;
}
// Everything is good to go, transition the request to confirmed
$saved = $this->save(
array(
'id' => $table->id,
'status' => 1,
'confirm_token' => '',
)
);
if (!$saved)
{
// Error was set by the save method
return false;
}
// Push a notification to the site's super users, deliberately
ignoring if this process fails so the below message goes out
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');
$messageModel->notifySuperUsers(
JText::_('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CONFIRMED_REQUEST_SUBJECT'),
JText::sprintf('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CONFIRMED_REQUEST_MESSAGE',
$table->email)
);
JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_actionlogs/models',
'ActionlogsModel');
$message = array(
'action' => 'request-confirmed',
'subjectemail' => $table->email,
'id' => $table->id,
'itemlink' =>
'index.php?option=com_privacy&view=request&id=' .
$table->id,
);
/** @var ActionlogsModelActionlog $model */
$model = JModelLegacy::getInstance('Actionlog',
'ActionlogsModel');
$model->addLog(array($message),
'COM_PRIVACY_ACTION_LOG_CONFIRMED_REQUEST',
'com_privacy.request');
return true;
}
/**
* Method for getting the form from the model.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data
(default case), false if not.
*
* @return JForm|boolean A JForm object on success, false on failure
*
* @since 3.9.0
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm('com_privacy.confirm',
'confirm', array('control' => 'jform'));
if (empty($form))
{
return false;
}
$input = JFactory::getApplication()->input;
if ($input->getMethod() === 'GET')
{
$form->setValue('confirm_token', '',
$input->get->getAlnum('confirm_token'));
}
return $form;
}
/**
* Method to get a table object, load it if necessary.
*
* @param string $name The table name. Optional.
* @param string $prefix The class prefix. Optional.
* @param array $options Configuration array for model. Optional.
*
* @return JTable A JTable object
*
* @since 3.9.0
* @throws \Exception
*/
public function getTable($name = 'Request', $prefix =
'PrivacyTable', $options = array())
{
return parent::getTable($name, $prefix, $options);
}
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @return void
*
* @since 3.9.0
*/
protected function populateState()
{
// Get the application object.
$params =
JFactory::getApplication()->getParams('com_privacy');
// Load the parameters.
$this->setState('params', $params);
}
}
models/forms/confirm.xml000064400000000557151165776720011364
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset name="default"
label="COM_PRIVACY_CONFIRM_REQUEST_FIELDSET_LABEL">
<field
name="confirm_token"
type="text"
label="COM_PRIVACY_FIELD_CONFIRM_CONFIRM_TOKEN_LABEL"
description="COM_PRIVACY_FIELD_CONFIRM_CONFIRM_TOKEN_DESC"
filter="alnum"
required="true"
size="32"
/>
</fieldset>
</form>
models/forms/remind.xml000064400000001034151165776720011174
0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
<fieldset name="default"
label="COM_PRIVACY_REMIND_REQUEST_FIELDSET_LABEL">
<field
name="email"
type="text"
label="JGLOBAL_EMAIL"
description="COM_PRIVACY_FIELD_CONFIRM_EMAIL_DESC"
validate="email"
required="true"
size="30"
/>
<field
name="remind_token"
type="text"
label="COM_PRIVACY_FIELD_REMIND_CONFIRM_TOKEN_LABEL"
description="COM_PRIVACY_FIELD_REMIND_CONFIRM_TOKEN_DESC"
filter="alnum"
required="true"
size="32"
/>
</fieldset>
</form>
models/remind.php000064400000010055151165776720010040 0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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;
/**
* Remind confirmation model class.
*
* @since 3.9.0
*/
class PrivacyModelRemind extends JModelAdmin
{
/**
* Confirms the remind request.
*
* @param array $data The data expected for the form.
*
* @return mixed Exception | JException | boolean
*
* @since 3.9.0
*/
public function remindRequest($data)
{
// Get the form.
$form = $this->getForm();
$data['email'] =
JStringPunycode::emailToPunycode($data['email']);
// Check for an error.
if ($form instanceof Exception)
{
return $form;
}
// Filter and validate the form data.
$data = $form->filter($data);
$return = $form->validate($data);
// Check for an error.
if ($return instanceof Exception)
{
return $return;
}
// Check the validation results.
if ($return === false)
{
// Get the validation messages from the form.
foreach ($form->getErrors() as $formError)
{
$this->setError($formError->getMessage());
}
return false;
}
/** @var PrivacyTableConsent $table */
$table = $this->getTable();
$db = $this->getDbo();
$query = $db->getQuery(true)
->select($db->quoteName(array('r.id',
'r.user_id', 'r.token')));
$query->from($db->quoteName('#__privacy_consents',
'r'));
$query->join('LEFT', $db->quoteName('#__users',
'u') . ' ON u.id = r.user_id');
$query->where($db->quoteName('u.email') . ' = '
. $db->quote($data['email']));
$query->where($db->quoteName('r.remind') . ' =
1');
$db->setQuery($query);
try
{
$remind = $db->loadObject();
}
catch (RuntimeException $e)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REMIND'));
return false;
}
if (!$remind)
{
$this->setError(JText::_('COM_PRIVACY_ERROR_NO_PENDING_REMIND'));
return false;
}
// Verify the token
if (!JUserHelper::verifyPassword($data['remind_token'],
$remind->token))
{
$this->setError(JText::_('COM_PRIVACY_ERROR_NO_REMIND_REQUESTS'));
return false;
}
// Everything is good to go, transition the request to extended
$saved = $this->save(
array(
'id' => $remind->id,
'remind' => 0,
'token' => '',
'created' => JFactory::getDate()->toSql(),
)
);
if (!$saved)
{
// Error was set by the save method
return false;
}
return true;
}
/**
* Method for getting the form from the model.
*
* @param array $data Data for the form.
* @param boolean $loadData True if the form is to load its own data
(default case), false if not.
*
* @return JForm|boolean A JForm object on success, false on failure
*
* @since 3.9.0
*/
public function getForm($data = array(), $loadData = true)
{
// Get the form.
$form = $this->loadForm('com_privacy.remind',
'remind', array('control' => 'jform'));
if (empty($form))
{
return false;
}
$input = JFactory::getApplication()->input;
if ($input->getMethod() === 'GET')
{
$form->setValue('remind_token', '',
$input->get->getAlnum('remind_token'));
}
return $form;
}
/**
* Method to get a table object, load it if necessary.
*
* @param string $name The table name. Optional.
* @param string $prefix The class prefix. Optional.
* @param array $options Configuration array for model. Optional.
*
* @return JTable A JTable object
*
* @since 3.9.0
* @throws \Exception
*/
public function getTable($name = 'Consent', $prefix =
'PrivacyTable', $options = array())
{
return parent::getTable($name, $prefix, $options);
}
/**
* Method to auto-populate the model state.
*
* Note. Calling getState in this method will result in recursion.
*
* @return void
*
* @since 3.9.0
*/
protected function populateState()
{
// Get the application object.
$params =
JFactory::getApplication()->getParams('com_privacy');
// Load the parameters.
$this->setState('params', $params);
}
}
router.php000064400000003610151165776720006616 0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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;
/**
* Routing class from com_privacy
*
* @since 3.9.0
*/
class PrivacyRouter extends JComponentRouterView
{
/**
* Privacy Component router constructor
*
* @param JApplicationCms $app The application object
* @param JMenu $menu The menu object to work with
*
* @since 3.9.0
*/
public function __construct($app = null, $menu = null)
{
$this->registerView(new
JComponentRouterViewconfiguration('confirm'));
$this->registerView(new
JComponentRouterViewconfiguration('request'));
$this->registerView(new
JComponentRouterViewconfiguration('remind'));
parent::__construct($app, $menu);
$this->attachRule(new JComponentRouterRulesMenu($this));
$this->attachRule(new JComponentRouterRulesStandard($this));
$this->attachRule(new JComponentRouterRulesNomenu($this));
}
}
/**
* Privacy router functions
*
* These functions are proxies for the new router interface
* for old SEF extensions.
*
* @param array &$query REQUEST query
*
* @return array Segments of the SEF url
*
* @since 3.9.0
* @deprecated 4.0 Use Class based routers instead
*/
function privacyBuildRoute(&$query)
{
$app = JFactory::getApplication();
$router = new PrivacyRouter($app, $app->getMenu());
return $router->build($query);
}
/**
* Convert SEF URL segments into query variables
*
* @param array $segments Segments in the current URL
*
* @return array Query variables
*
* @since 3.9.0
* @deprecated 4.0 Use Class based routers instead
*/
function privacyParseRoute($segments)
{
$app = JFactory::getApplication();
$router = new PrivacyRouter($app, $app->getMenu());
return $router->parse($segments);
}
views/confirm/tmpl/default.php000064400000002466151165776720012500
0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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;
/** @var PrivacyViewConfirm $this */
JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');
?>
<div class="request-confirm<?php echo $this->pageclass_sfx;
?>">
<?php if ($this->params->get('show_page_heading')) :
?>
<div class="page-header">
<h1>
<?php echo
$this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<form action="<?php echo
JRoute::_('index.php?option=com_privacy&task=request.confirm');
?>" method="post" class="form-validate
form-horizontal well">
<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
<fieldset>
<?php if (!empty($fieldset->label)) : ?>
<legend><?php echo JText::_($fieldset->label);
?></legend>
<?php endif; ?>
<?php echo $this->form->renderFieldset($fieldset->name);
?>
</fieldset>
<?php endforeach; ?>
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-primary
validate">
<?php echo JText::_('JSUBMIT'); ?>
</button>
</div>
</div>
<?php echo JHtml::_('form.token'); ?>
</form>
</div>
views/confirm/tmpl/default.xml000064400000000505151165776720012501
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_PRIVACY_CONFIRM_VIEW_DEFAULT_TITLE"
option="COM_PRIVACY_CONFIRM_VIEW_DEFAULT_OPTION">
<help
key="JHELP_MENUS_MENU_ITEM_PRIVACY_CONFIRM_REQUEST"
/>
<message>
<![CDATA[COM_PRIVACY_CONFIRM_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>
views/confirm/view.html.php000064400000005765151165776720012022
0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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\Registry\Registry;
/**
* Request confirmation view class
*
* @since 3.9.0
*/
class PrivacyViewConfirm extends JViewLegacy
{
/**
* The form object
*
* @var JForm
* @since 3.9.0
*/
protected $form;
/**
* The CSS class suffix to append to the view container
*
* @var string
* @since 3.9.0
*/
protected $pageclass_sfx;
/**
* The view parameters
*
* @var Registry
* @since 3.9.0
*/
protected $params;
/**
* The state information
*
* @var JObject
* @since 3.9.0
*/
protected $state;
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse;
automatically searches through the template paths.
*
* @return mixed A string if successful, otherwise an Error object.
*
* @see JViewLegacy::loadTemplate()
* @since 3.9.0
* @throws Exception
*/
public function display($tpl = null)
{
// Initialise variables.
$this->form = $this->get('Form');
$this->state = $this->get('State');
$this->params = $this->state->params;
// Check for errors.
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors), 500);
}
// Escape strings for HTML output
$this->pageclass_sfx =
htmlspecialchars($this->params->get('pageclass_sfx',
''), ENT_COMPAT, 'UTF-8');
$this->prepareDocument();
return parent::display($tpl);
}
/**
* Prepares the document.
*
* @return void
*
* @since 3.9.0
*/
protected function prepareDocument()
{
$app = JFactory::getApplication();
$menus = $app->getMenu();
$title = null;
// Because the application sets a default page title,
// we need to get it from the menu item itself
$menu = $menus->getActive();
if ($menu)
{
$this->params->def('page_heading',
$this->params->get('page_title', $menu->title));
}
else
{
$this->params->def('page_heading',
JText::_('COM_PRIVACY_VIEW_CONFIRM_PAGE_TITLE'));
}
$title = $this->params->get('page_title', '');
if (empty($title))
{
$title = $app->get('sitename');
}
elseif ($app->get('sitename_pagetitles', 0) == 1)
{
$title = JText::sprintf('JPAGETITLE',
$app->get('sitename'), $title);
}
elseif ($app->get('sitename_pagetitles', 0) == 2)
{
$title = JText::sprintf('JPAGETITLE', $title,
$app->get('sitename'));
}
$this->document->setTitle($title);
if ($this->params->get('menu-meta_description'))
{
$this->document->setDescription($this->params->get('menu-meta_description'));
}
if ($this->params->get('menu-meta_keywords'))
{
$this->document->setMetadata('keywords',
$this->params->get('menu-meta_keywords'));
}
if ($this->params->get('robots'))
{
$this->document->setMetadata('robots',
$this->params->get('robots'));
}
}
}
views/remind/tmpl/default.php000064400000002464151165776720012317
0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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;
/** @var PrivacyViewConfirm $this */
JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');
?>
<div class="remind-confirm<?php echo $this->pageclass_sfx;
?>">
<?php if ($this->params->get('show_page_heading')) :
?>
<div class="page-header">
<h1>
<?php echo
$this->escape($this->params->get('page_heading')); ?>
</h1>
</div>
<?php endif; ?>
<form action="<?php echo
JRoute::_('index.php?option=com_privacy&task=request.remind');
?>" method="post" class="form-validate
form-horizontal well">
<?php foreach ($this->form->getFieldsets() as $fieldset) : ?>
<fieldset>
<?php if (!empty($fieldset->label)) : ?>
<legend><?php echo JText::_($fieldset->label);
?></legend>
<?php endif; ?>
<?php echo $this->form->renderFieldset($fieldset->name);
?>
</fieldset>
<?php endforeach; ?>
<div class="control-group">
<div class="controls">
<button type="submit" class="btn btn-primary
validate">
<?php echo JText::_('JSUBMIT'); ?>
</button>
</div>
</div>
<?php echo JHtml::_('form.token'); ?>
</form>
</div>
views/remind/tmpl/default.xml000064400000000501151165776720012316
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_PRIVACY_REMIND_VIEW_DEFAULT_TITLE"
option="COM_PRIVACY_REMIND_VIEW_DEFAULT_OPTION">
<help
key="JHELP_MENUS_MENU_ITEM_PRIVACY_REMIND_REQUEST"
/>
<message>
<![CDATA[COM_PRIVACY_REMIND_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>
views/remind/view.html.php000064400000005762151165776720011640
0ustar00<?php
/**
* @package Joomla.Site
* @subpackage com_privacy
*
* @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\Registry\Registry;
/**
* Remind confirmation view class
*
* @since 3.9.0
*/
class PrivacyViewRemind extends JViewLegacy
{
/**
* The form object
*
* @var JForm
* @since 3.9.0
*/
protected $form;
/**
* The CSS class suffix to append to the view container
*
* @var string
* @since 3.9.0
*/
protected $pageclass_sfx;
/**
* The view parameters
*
* @var Registry
* @since 3.9.0
*/
protected $params;
/**
* The state information
*
* @var JObject
* @since 3.9.0
*/
protected $state;
/**
* Execute and display a template script.
*
* @param string $tpl The name of the template file to parse;
automatically searches through the template paths.
*
* @return mixed A string if successful, otherwise an Error object.
*
* @see JViewLegacy::loadTemplate()
* @since 3.9.0
* @throws Exception
*/
public function display($tpl = null)
{
// Initialise variables.
$this->form = $this->get('Form');
$this->state = $this->get('State');
$this->params = $this->state->params;
// Check for errors.
if (count($errors = $this->get('Errors')))
{
throw new Exception(implode("\n", $errors), 500);
}
// Escape strings for HTML output
$this->pageclass_sfx =
htmlspecialchars($this->params->get('pageclass_sfx',
''), ENT_COMPAT, 'UTF-8');
$this->prepareDocument();
return parent::display($tpl);
}
/**
* Prepares the document.
*
* @return void
*
* @since 3.9.0
*/
protected function prepareDocument()
{
$app = JFactory::getApplication();
$menus = $app->getMenu();
$title = null;
// Because the application sets a default page title,
// we need to get it from the menu item itself
$menu = $menus->getActive();
if ($menu)
{
$this->params->def('page_heading',
$this->params->get('page_title', $menu->title));
}
else
{
$this->params->def('page_heading',
JText::_('COM_PRIVACY_VIEW_REMIND_PAGE_TITLE'));
}
$title = $this->params->get('page_title', '');
if (empty($title))
{
$title = $app->get('sitename');
}
elseif ($app->get('sitename_pagetitles', 0) == 1)
{
$title = JText::sprintf('JPAGETITLE',
$app->get('sitename'), $title);
}
elseif ($app->get('sitename_pagetitles', 0) == 2)
{
$title = JText::sprintf('JPAGETITLE', $title,
$app->get('sitename'));
}
$this->document->setTitle($title);
if ($this->params->get('menu-meta_description'))
{
$this->document->setDescription($this->params->get('menu-meta_description'));
}
if ($this->params->get('menu-meta_keywords'))
{
$this->document->setMetadata('keywords',
$this->params->get('menu-meta_keywords'));
}
if ($this->params->get('robots'))
{
$this->document->setMetadata('robots',
$this->params->get('robots'));
}
}
}
views/request/tmpl/default.xml000064400000000504151165776720012533
0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
<layout title="COM_PRIVACY_REQUEST_VIEW_DEFAULT_TITLE"
option="COM_PRIVACY_REQUEST_VIEW_DEFAULT_OPTION">
<help
key="JHELP_MENUS_MENU_ITEM_PRIVACY_CREATE_REQUEST"
/>
<message>
<![CDATA[COM_PRIVACY_REQUEST_VIEW_DEFAULT_DESC]]>
</message>
</layout>
</metadata>