first commit
This commit is contained in:
14
components/com_privacy/forms/confirm.xml
Normal file
14
components/com_privacy/forms/confirm.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?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>
|
||||
24
components/com_privacy/forms/remind.xml
Normal file
24
components/com_privacy/forms/remind.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?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>
|
||||
17
components/com_privacy/forms/request.xml
Normal file
17
components/com_privacy/forms/request.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?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>
|
||||
58
components/com_privacy/src/Controller/DisplayController.php
Normal file
58
components/com_privacy/src/Controller/DisplayController.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Privacy\Site\Controller;
|
||||
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Privacy Controller
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class DisplayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 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.
|
||||
* @see \Joomla\CMS\Filter\InputFilter::clean() for valid values.
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function display($cachable = false, $urlparams = [])
|
||||
{
|
||||
$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, ['confirm', 'request']) && $this->app->getIdentity()->guest) {
|
||||
$this->setRedirect(
|
||||
Route::_('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, ['confirm', 'remind'])) {
|
||||
$this->app->setHeader('Referrer-Policy', 'no-referrer', true);
|
||||
}
|
||||
|
||||
return parent::display($cachable, $urlparams);
|
||||
}
|
||||
}
|
||||
175
components/com_privacy/src/Controller/RequestController.php
Normal file
175
components/com_privacy/src/Controller/RequestController.php
Normal file
@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_privacy
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Privacy\Site\Controller;
|
||||
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Controller\BaseController;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\Component\Privacy\Site\Model\ConfirmModel;
|
||||
use Joomla\Component\Privacy\Site\Model\RemindModel;
|
||||
use Joomla\Component\Privacy\Site\Model\RequestModel;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Request action controller class.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class RequestController extends BaseController
|
||||
{
|
||||
/**
|
||||
* Method to confirm the information request.
|
||||
*
|
||||
* @return boolean
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function confirm()
|
||||
{
|
||||
// Check the request token.
|
||||
$this->checkToken('post');
|
||||
|
||||
/** @var ConfirmModel $model */
|
||||
$model = $this->getModel('Confirm', 'Site');
|
||||
$data = $this->input->post->get('jform', [], 'array');
|
||||
|
||||
$return = $model->confirmRequest($data);
|
||||
|
||||
// Check for a hard error.
|
||||
if ($return instanceof \Exception) {
|
||||
// Get the error message to display.
|
||||
if ($this->app->get('error_reporting')) {
|
||||
$message = $return->getMessage();
|
||||
} else {
|
||||
$message = Text::_('COM_PRIVACY_ERROR_CONFIRMING_REQUEST');
|
||||
}
|
||||
|
||||
// Go back to the confirm form.
|
||||
$this->setRedirect(Route::_('index.php?option=com_privacy&view=confirm', false), $message, 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($return === false) {
|
||||
// Confirm failed.
|
||||
// Go back to the confirm form.
|
||||
$message = Text::sprintf('COM_PRIVACY_ERROR_CONFIRMING_REQUEST_FAILED', $model->getError());
|
||||
$this->setRedirect(Route::_('index.php?option=com_privacy&view=confirm', false), $message, 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Confirm succeeded.
|
||||
$this->setRedirect(Route::_(Uri::root()), Text::_('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 RequestModel $model */
|
||||
$model = $this->getModel('Request', 'Site');
|
||||
$data = $this->input->post->get('jform', [], 'array');
|
||||
|
||||
$return = $model->createRequest($data);
|
||||
|
||||
// Check for a hard error.
|
||||
if ($return instanceof \Exception) {
|
||||
// Get the error message to display.
|
||||
if ($this->app->get('error_reporting')) {
|
||||
$message = $return->getMessage();
|
||||
} else {
|
||||
$message = Text::_('COM_PRIVACY_ERROR_CREATING_REQUEST');
|
||||
}
|
||||
|
||||
// Go back to the confirm form.
|
||||
$this->setRedirect(Route::_('index.php?option=com_privacy&view=request', false), $message, 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($return === false) {
|
||||
// Confirm failed.
|
||||
// Go back to the confirm form.
|
||||
$message = Text::sprintf('COM_PRIVACY_ERROR_CREATING_REQUEST_FAILED', $model->getError());
|
||||
$this->setRedirect(Route::_('index.php?option=com_privacy&view=request', false), $message, 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Confirm succeeded.
|
||||
$this->setRedirect(Route::_(Uri::root()), Text::_('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 RemindModel $model */
|
||||
$model = $this->getModel('Remind', 'Site');
|
||||
$data = $this->input->post->get('jform', [], 'array');
|
||||
|
||||
$return = $model->remindRequest($data);
|
||||
|
||||
// Check for a hard error.
|
||||
if ($return instanceof \Exception) {
|
||||
// Get the error message to display.
|
||||
if ($this->app->get('error_reporting')) {
|
||||
$message = $return->getMessage();
|
||||
} else {
|
||||
$message = Text::_('COM_PRIVACY_ERROR_REMIND_REQUEST');
|
||||
}
|
||||
|
||||
// Go back to the confirm form.
|
||||
$this->setRedirect(Route::_('index.php?option=com_privacy&view=remind', false), $message, 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($return === false) {
|
||||
// Confirm failed.
|
||||
// Go back to the confirm form.
|
||||
$message = Text::sprintf('COM_PRIVACY_ERROR_CONFIRMING_REMIND_FAILED', $model->getError());
|
||||
$this->setRedirect(Route::_('index.php?option=com_privacy&view=remind', false), $message, 'notice');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Confirm succeeded.
|
||||
$this->setRedirect(Route::_(Uri::root()), Text::_('COM_PRIVACY_CONFIRM_REMIND_SUCCEEDED'), 'info');
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
234
components/com_privacy/src/Model/ConfirmModel.php
Normal file
234
components/com_privacy/src/Model/ConfirmModel.php
Normal file
@ -0,0 +1,234 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Privacy\Site\Model;
|
||||
|
||||
use Joomla\CMS\Date\Date;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Model\AdminModel;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\CMS\User\UserHelper;
|
||||
use Joomla\Component\Actionlogs\Administrator\Model\ActionlogModel;
|
||||
use Joomla\Component\Messages\Administrator\Model\MessageModel;
|
||||
use Joomla\Component\Privacy\Administrator\Table\RequestTable;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Request confirmation model class.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class ConfirmModel extends AdminModel
|
||||
{
|
||||
/**
|
||||
* Confirms the information request.
|
||||
*
|
||||
* @param array $data The data expected for the form.
|
||||
*
|
||||
* @return mixed Exception | 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
|
||||
$email = $this->getCurrentUser()->email;
|
||||
|
||||
// Search for the information request
|
||||
/** @var RequestTable $table */
|
||||
$table = $this->getTable();
|
||||
|
||||
if (!$table->load(['email' => $email, 'status' => 0])) {
|
||||
$this->setError(Text::_('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 || $table->confirm_token_created_at === null) {
|
||||
$this->setError(Text::_('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 Date($table->confirm_token_created_at);
|
||||
$confirmTokenCreatedAt->add(new \DateInterval('P1D'));
|
||||
|
||||
$now = new Date('now');
|
||||
|
||||
if ($now > $confirmTokenCreatedAt) {
|
||||
// Invalidate the request
|
||||
$table->status = -1;
|
||||
$table->confirm_token = '';
|
||||
$table->confirm_token_created_at = null;
|
||||
|
||||
try {
|
||||
$table->store();
|
||||
} catch (ExecutionFailureException $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(Text::_('COM_PRIVACY_ERROR_CONFIRM_TOKEN_EXPIRED'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify the token
|
||||
if (!UserHelper::verifyPassword($data['confirm_token'], $table->confirm_token)) {
|
||||
$this->setError(Text::_('COM_PRIVACY_ERROR_NO_PENDING_REQUESTS'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Everything is good to go, transition the request to confirmed
|
||||
$saved = $this->save(
|
||||
[
|
||||
'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
|
||||
/** @var MessageModel $messageModel */
|
||||
$messageModel = Factory::getApplication()->bootComponent('com_messages')->getMVCFactory()->createModel('Message', 'Administrator');
|
||||
|
||||
$messageModel->notifySuperUsers(
|
||||
Text::_('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CONFIRMED_REQUEST_SUBJECT'),
|
||||
Text::sprintf('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CONFIRMED_REQUEST_MESSAGE', $table->email)
|
||||
);
|
||||
|
||||
$message = [
|
||||
'action' => 'request-confirmed',
|
||||
'subjectemail' => $table->email,
|
||||
'id' => $table->id,
|
||||
'itemlink' => 'index.php?option=com_privacy&view=request&id=' . $table->id,
|
||||
];
|
||||
|
||||
$this->getActionlogModel()->addLog([$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 Form|boolean A Form object on success, false on failure
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_privacy.confirm', 'confirm', ['control' => 'jform']);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$input = Factory::getApplication()->getInput();
|
||||
|
||||
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 Table A Table object
|
||||
*
|
||||
* @since 3.9.0
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getTable($name = 'Request', $prefix = 'Administrator', $options = [])
|
||||
{
|
||||
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 = Factory::getApplication()->getParams('com_privacy');
|
||||
|
||||
// Load the parameters.
|
||||
$this->setState('params', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to fetch an instance of the action log model.
|
||||
*
|
||||
* @return ActionlogModel
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function getActionlogModel(): ActionlogModel
|
||||
{
|
||||
return Factory::getApplication()->bootComponent('com_actionlogs')
|
||||
->getMVCFactory()->createModel('Actionlog', 'Administrator', ['ignore_request' => true]);
|
||||
}
|
||||
}
|
||||
191
components/com_privacy/src/Model/RemindModel.php
Normal file
191
components/com_privacy/src/Model/RemindModel.php
Normal file
@ -0,0 +1,191 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Privacy\Site\Model;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\Model\AdminModel;
|
||||
use Joomla\CMS\String\PunycodeHelper;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\CMS\User\UserHelper;
|
||||
use Joomla\Component\Privacy\Administrator\Table\ConsentTable;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Remind confirmation model class.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class RemindModel extends AdminModel
|
||||
{
|
||||
/**
|
||||
* 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'] = PunycodeHelper::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 ConsentTable $table */
|
||||
$table = $this->getTable();
|
||||
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select($db->quoteName(['r.id', 'r.user_id', 'r.token']));
|
||||
$query->from($db->quoteName('#__privacy_consents', 'r'));
|
||||
$query->join(
|
||||
'LEFT',
|
||||
$db->quoteName('#__users', 'u'),
|
||||
$db->quoteName('u.id') . ' = ' . $db->quoteName('r.user_id')
|
||||
);
|
||||
$query->where($db->quoteName('u.email') . ' = :email')
|
||||
->bind(':email', $data['email']);
|
||||
$query->where($db->quoteName('r.remind') . ' = 1');
|
||||
$db->setQuery($query);
|
||||
|
||||
try {
|
||||
$remind = $db->loadObject();
|
||||
} catch (ExecutionFailureException $e) {
|
||||
$this->setError(Text::_('COM_PRIVACY_ERROR_NO_PENDING_REMIND'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$remind) {
|
||||
$this->setError(Text::_('COM_PRIVACY_ERROR_NO_PENDING_REMIND'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify the token
|
||||
if (!UserHelper::verifyPassword($data['remind_token'], $remind->token)) {
|
||||
$this->setError(Text::_('COM_PRIVACY_ERROR_NO_REMIND_REQUESTS'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Everything is good to go, transition the request to extended
|
||||
$saved = $this->save(
|
||||
[
|
||||
'id' => $remind->id,
|
||||
'remind' => 0,
|
||||
'token' => '',
|
||||
'created' => Factory::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 Form|boolean A Form object on success, false on failure
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_privacy.remind', 'remind', ['control' => 'jform']);
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$input = Factory::getApplication()->getInput();
|
||||
|
||||
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 Table A Table object
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function getTable($name = 'Consent', $prefix = 'Administrator', $options = [])
|
||||
{
|
||||
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 = Factory::getApplication()->getParams('com_privacy');
|
||||
|
||||
// Load the parameters.
|
||||
$this->setState('params', $params);
|
||||
}
|
||||
}
|
||||
262
components/com_privacy/src/Model/RequestModel.php
Normal file
262
components/com_privacy/src/Model/RequestModel.php
Normal file
@ -0,0 +1,262 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Privacy\Site\Model;
|
||||
|
||||
use Joomla\CMS\Application\ApplicationHelper;
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Mail\Exception\MailDisabledException;
|
||||
use Joomla\CMS\Mail\MailTemplate;
|
||||
use Joomla\CMS\MVC\Model\AdminModel;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Table\Table;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
use Joomla\CMS\User\UserHelper;
|
||||
use Joomla\Component\Actionlogs\Administrator\Model\ActionlogModel;
|
||||
use Joomla\Component\Messages\Administrator\Model\MessageModel;
|
||||
use Joomla\Component\Privacy\Administrator\Table\RequestTable;
|
||||
use Joomla\Database\Exception\ExecutionFailureException;
|
||||
use PHPMailer\PHPMailer\Exception as phpmailerException;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Request model class.
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class RequestModel extends AdminModel
|
||||
{
|
||||
/**
|
||||
* Creates an information request.
|
||||
*
|
||||
* @param array $data The data expected for the form.
|
||||
*
|
||||
* @return mixed Exception | boolean
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function createRequest($data)
|
||||
{
|
||||
$app = Factory::getApplication();
|
||||
|
||||
// Creating requests requires the site's email sending be enabled
|
||||
if (!$app->get('mailonline', 1)) {
|
||||
$this->setError(Text::_('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;
|
||||
}
|
||||
|
||||
$data['email'] = $this->getCurrentUser()->email;
|
||||
|
||||
// Search for an open information request matching the email and type
|
||||
$db = $this->getDatabase();
|
||||
$query = $db->getQuery(true)
|
||||
->select('COUNT(id)')
|
||||
->from($db->quoteName('#__privacy_requests'))
|
||||
->where($db->quoteName('email') . ' = :email')
|
||||
->where($db->quoteName('request_type') . ' = :requesttype')
|
||||
->whereIn($db->quoteName('status'), [0, 1])
|
||||
->bind(':email', $data['email'])
|
||||
->bind(':requesttype', $data['request_type']);
|
||||
|
||||
try {
|
||||
$result = (int) $db->setQuery($query)->loadResult();
|
||||
} catch (ExecutionFailureException $exception) {
|
||||
// Can't check for existing requests, so don't create a new one
|
||||
$this->setError(Text::_('COM_PRIVACY_ERROR_CHECKING_FOR_EXISTING_REQUESTS'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($result > 0) {
|
||||
$this->setError(Text::_('COM_PRIVACY_ERROR_PENDING_REQUEST_OPEN'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Everything is good to go, create the request
|
||||
$token = ApplicationHelper::getHash(UserHelper::genRandomPassword());
|
||||
$hashedToken = UserHelper::hashPassword($token);
|
||||
|
||||
$data['confirm_token'] = $hashedToken;
|
||||
$data['confirm_token_created_at'] = Factory::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
|
||||
/** @var MessageModel $messageModel */
|
||||
$messageModel = $app->bootComponent('com_messages')->getMVCFactory()->createModel('Message', 'Administrator');
|
||||
|
||||
$messageModel->notifySuperUsers(
|
||||
Text::_('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CREATED_REQUEST_SUBJECT'),
|
||||
Text::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 {
|
||||
$linkMode = $app->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE;
|
||||
|
||||
$templateData = [
|
||||
'sitename' => $app->get('sitename'),
|
||||
'url' => Uri::root(),
|
||||
'tokenurl' => Route::link('site', 'index.php?option=com_privacy&view=confirm&confirm_token=' . $token, false, $linkMode, true),
|
||||
'formurl' => Route::link('site', 'index.php?option=com_privacy&view=confirm', false, $linkMode, true),
|
||||
'token' => $token,
|
||||
];
|
||||
|
||||
switch ($data['request_type']) {
|
||||
case 'export':
|
||||
$mailer = new MailTemplate('com_privacy.notification.export', $app->getLanguage()->getTag());
|
||||
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
$mailer = new MailTemplate('com_privacy.notification.remove', $app->getLanguage()->getTag());
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->setError(Text::_('COM_PRIVACY_ERROR_UNKNOWN_REQUEST_TYPE'));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$mailer->addTemplateData($templateData);
|
||||
$mailer->addRecipient($data['email']);
|
||||
|
||||
$mailer->send();
|
||||
|
||||
/** @var RequestTable $table */
|
||||
$table = $this->getTable();
|
||||
|
||||
if (!$table->load($this->getState($this->getName() . '.id'))) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log the request's creation
|
||||
$message = [
|
||||
'action' => 'request-created',
|
||||
'requesttype' => $table->request_type,
|
||||
'subjectemail' => $table->email,
|
||||
'id' => $table->id,
|
||||
'itemlink' => 'index.php?option=com_privacy&view=request&id=' . $table->id,
|
||||
];
|
||||
|
||||
$this->getActionlogModel()->addLog([$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 (MailDisabledException | 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 Form|boolean A Form object on success, false on failure
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function getForm($data = [], $loadData = true)
|
||||
{
|
||||
return $this->loadForm('com_privacy.request', 'request', ['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 Table A Table object
|
||||
*
|
||||
* @throws \Exception
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function getTable($name = 'Request', $prefix = 'Administrator', $options = [])
|
||||
{
|
||||
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 = Factory::getApplication()->getParams('com_privacy');
|
||||
|
||||
// Load the parameters.
|
||||
$this->setState('params', $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to fetch an instance of the action log model.
|
||||
*
|
||||
* @return ActionlogModel
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
private function getActionlogModel(): ActionlogModel
|
||||
{
|
||||
return Factory::getApplication()->bootComponent('com_actionlogs')
|
||||
->getMVCFactory()->createModel('Actionlog', 'Administrator', ['ignore_request' => true]);
|
||||
}
|
||||
}
|
||||
52
components/com_privacy/src/Service/Router.php
Normal file
52
components/com_privacy/src/Service/Router.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage com_privacy
|
||||
*
|
||||
* @copyright (C) 2019 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Privacy\Site\Service;
|
||||
|
||||
use Joomla\CMS\Application\CMSApplication;
|
||||
use Joomla\CMS\Component\Router\RouterView;
|
||||
use Joomla\CMS\Component\Router\RouterViewConfiguration;
|
||||
use Joomla\CMS\Component\Router\Rules\MenuRules;
|
||||
use Joomla\CMS\Component\Router\Rules\NomenuRules;
|
||||
use Joomla\CMS\Component\Router\Rules\StandardRules;
|
||||
use Joomla\CMS\Menu\AbstractMenu;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Routing class from com_privacy
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class Router extends RouterView
|
||||
{
|
||||
/**
|
||||
* Privacy Component router constructor
|
||||
*
|
||||
* @param CMSApplication $app The application object
|
||||
* @param AbstractMenu $menu The menu object to work with
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
public function __construct($app = null, $menu = null)
|
||||
{
|
||||
$this->registerView(new RouterViewConfiguration('confirm'));
|
||||
$this->registerView(new RouterViewConfiguration('request'));
|
||||
$this->registerView(new RouterViewConfiguration('remind'));
|
||||
|
||||
parent::__construct($app, $menu);
|
||||
|
||||
$this->attachRule(new MenuRules($this));
|
||||
$this->attachRule(new StandardRules($this));
|
||||
$this->attachRule(new NomenuRules($this));
|
||||
}
|
||||
}
|
||||
123
components/com_privacy/src/View/Confirm/HtmlView.php
Normal file
123
components/com_privacy/src/View/Confirm/HtmlView.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Privacy\Site\View\Confirm;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Request confirmation view class
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The form object
|
||||
*
|
||||
* @var Form
|
||||
* @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 \Joomla\Registry\Registry
|
||||
* @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 void
|
||||
*
|
||||
* @see BaseHtmlView::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 GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Escape strings for HTML output
|
||||
$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
$this->prepareDocument();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the document.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
protected function prepareDocument()
|
||||
{
|
||||
// Because the application sets a default page title,
|
||||
// we need to get it from the menu item itself
|
||||
$menu = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if ($menu) {
|
||||
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
|
||||
} else {
|
||||
$this->params->def('page_heading', Text::_('COM_PRIVACY_VIEW_CONFIRM_PAGE_TITLE'));
|
||||
}
|
||||
|
||||
$this->setDocumentTitle($this->params->get('page_title', ''));
|
||||
|
||||
if ($this->params->get('menu-meta_description')) {
|
||||
$this->getDocument()->setDescription($this->params->get('menu-meta_description'));
|
||||
}
|
||||
|
||||
if ($this->params->get('robots')) {
|
||||
$this->getDocument()->setMetaData('robots', $this->params->get('robots'));
|
||||
}
|
||||
}
|
||||
}
|
||||
123
components/com_privacy/src/View/Remind/HtmlView.php
Normal file
123
components/com_privacy/src/View/Remind/HtmlView.php
Normal file
@ -0,0 +1,123 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Privacy\Site\View\Remind;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Remind confirmation view class
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The form object
|
||||
*
|
||||
* @var Form
|
||||
* @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 \Joomla\Registry\Registry
|
||||
* @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 void
|
||||
*
|
||||
* @see BaseHtmlView::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 GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Escape strings for HTML output
|
||||
$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
$this->prepareDocument();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the document.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
protected function prepareDocument()
|
||||
{
|
||||
// Because the application sets a default page title,
|
||||
// we need to get it from the menu item itself
|
||||
$menu = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if ($menu) {
|
||||
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
|
||||
} else {
|
||||
$this->params->def('page_heading', Text::_('COM_PRIVACY_VIEW_REMIND_PAGE_TITLE'));
|
||||
}
|
||||
|
||||
$this->setDocumentTitle($this->params->get('page_title', ''));
|
||||
|
||||
if ($this->params->get('menu-meta_description')) {
|
||||
$this->getDocument()->setDescription($this->params->get('menu-meta_description'));
|
||||
}
|
||||
|
||||
if ($this->params->get('robots')) {
|
||||
$this->getDocument()->setMetaData('robots', $this->params->get('robots'));
|
||||
}
|
||||
}
|
||||
}
|
||||
132
components/com_privacy/src/View/Request/HtmlView.php
Normal file
132
components/com_privacy/src/View/Request/HtmlView.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?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
|
||||
*/
|
||||
|
||||
namespace Joomla\Component\Privacy\Site\View\Request;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Form\Form;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\MVC\View\GenericDataException;
|
||||
use Joomla\CMS\MVC\View\HtmlView as BaseHtmlView;
|
||||
use Joomla\Registry\Registry;
|
||||
|
||||
// phpcs:disable PSR1.Files.SideEffects
|
||||
\defined('_JEXEC') or die;
|
||||
// phpcs:enable PSR1.Files.SideEffects
|
||||
|
||||
/**
|
||||
* Request view class
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
class HtmlView extends BaseHtmlView
|
||||
{
|
||||
/**
|
||||
* The form object
|
||||
*
|
||||
* @var Form
|
||||
* @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 \Joomla\Registry\Registry
|
||||
* @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 void
|
||||
*
|
||||
* @see BaseHtmlView::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) Factory::getApplication()->get('mailonline', 1);
|
||||
|
||||
// Check for errors.
|
||||
if (\count($errors = $this->get('Errors'))) {
|
||||
throw new GenericDataException(implode("\n", $errors), 500);
|
||||
}
|
||||
|
||||
// Escape strings for HTML output
|
||||
$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''), ENT_COMPAT, 'UTF-8');
|
||||
|
||||
$this->prepareDocument();
|
||||
|
||||
parent::display($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the document.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.9.0
|
||||
*/
|
||||
protected function prepareDocument()
|
||||
{
|
||||
// Because the application sets a default page title,
|
||||
// we need to get it from the menu item itself
|
||||
$menu = Factory::getApplication()->getMenu()->getActive();
|
||||
|
||||
if ($menu) {
|
||||
$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
|
||||
} else {
|
||||
$this->params->def('page_heading', Text::_('COM_PRIVACY_VIEW_REQUEST_PAGE_TITLE'));
|
||||
}
|
||||
|
||||
$this->setDocumentTitle($this->params->get('page_title', ''));
|
||||
|
||||
if ($this->params->get('menu-meta_description')) {
|
||||
$this->getDocument()->setDescription($this->params->get('menu-meta_description'));
|
||||
}
|
||||
|
||||
if ($this->params->get('robots')) {
|
||||
$this->getDocument()->setMetaData('robots', $this->params->get('robots'));
|
||||
}
|
||||
}
|
||||
}
|
||||
51
components/com_privacy/tmpl/confirm/default.php
Normal file
51
components/com_privacy/tmpl/confirm/default.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Privacy\Site\View\Confirm\HtmlView $this */
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useScript('form.validate');
|
||||
|
||||
?>
|
||||
<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 Route::_('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 Text::_($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 Text::_('JSUBMIT'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</form>
|
||||
</div>
|
||||
11
components/com_privacy/tmpl/confirm/default.xml
Normal file
11
components/com_privacy/tmpl/confirm/default.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?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="Menu_Item:_Confirm_Request"
|
||||
/>
|
||||
<message>
|
||||
<![CDATA[COM_PRIVACY_CONFIRM_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
51
components/com_privacy/tmpl/remind/default.php
Normal file
51
components/com_privacy/tmpl/remind/default.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Privacy\Site\View\Remind\HtmlView $this */
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useScript('form.validate');
|
||||
|
||||
?>
|
||||
<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 Route::_('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 Text::_($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 Text::_('JSUBMIT'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</form>
|
||||
</div>
|
||||
11
components/com_privacy/tmpl/remind/default.xml
Normal file
11
components/com_privacy/tmpl/remind/default.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?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="Menu_Item:_Extend_Consent"
|
||||
/>
|
||||
<message>
|
||||
<![CDATA[COM_PRIVACY_REMIND_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
58
components/com_privacy/tmpl/request/default.php
Normal file
58
components/com_privacy/tmpl/request/default.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?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\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
|
||||
/** @var \Joomla\Component\Privacy\Site\View\Request\HtmlView $this */
|
||||
|
||||
/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */
|
||||
$wa = $this->document->getWebAssetManager();
|
||||
$wa->useScript('keepalive')
|
||||
->useScript('form.validate');
|
||||
|
||||
?>
|
||||
<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 Route::_('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 Text::_($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 Text::_('JSUBMIT'); ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php echo HTMLHelper::_('form.token'); ?>
|
||||
</form>
|
||||
<?php else : ?>
|
||||
<div class="alert alert-warning">
|
||||
<span class="icon-exclamation-circle" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('WARNING'); ?></span>
|
||||
<?php echo Text::_('COM_PRIVACY_WARNING_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED'); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
11
components/com_privacy/tmpl/request/default.xml
Normal file
11
components/com_privacy/tmpl/request/default.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?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="Menu_Item:_Create_Request"
|
||||
/>
|
||||
<message>
|
||||
<![CDATA[COM_PRIVACY_REQUEST_VIEW_DEFAULT_DESC]]>
|
||||
</message>
|
||||
</layout>
|
||||
</metadata>
|
||||
Reference in New Issue
Block a user