+
+
+
+ $this)); ?>
+
+ items)) : ?>
+
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
+
+
+
+
+
+ pagination->getListFooter(); ?>
+ |
+
+
+
+ items as $i => $item) : ?>
+ requested_at);
+ ?>
+
+
+
+ status == 1 && $item->request_type === 'export') : ?>
+
+ sendMailEnabled) : ?>
+
+
+
+ status == 1 && $item->request_type === 'remove') : ?>
+
+
+
+ |
+
+ status); ?>
+ |
+
+
+ escape($item->email)); ?>
+
+ status == 1 && $urgentRequestDate >= $itemRequestedAt) : ?>
+
+
+ |
+
+ request_type); ?>
+ |
+
+
+
+
+ |
+
+ id; ?>
+ |
+
+
+
+
+
+
+
+
+
+
+
diff --git a/administrator/components/com_privacy/views/requests/tmpl/default.xml b/administrator/components/com_privacy/views/requests/tmpl/default.xml
new file mode 100644
index 0000000000000..4c624d279a747
--- /dev/null
+++ b/administrator/components/com_privacy/views/requests/tmpl/default.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/administrator/components/com_privacy/views/requests/view.html.php b/administrator/components/com_privacy/views/requests/view.html.php
new file mode 100644
index 0000000000000..c5122d3e895d0
--- /dev/null
+++ b/administrator/components/com_privacy/views/requests/view.html.php
@@ -0,0 +1,141 @@
+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 __DEPLOY_VERSION__
+ */
+ 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');
+
+ }
+}
diff --git a/administrator/help/en-GB/toc.json b/administrator/help/en-GB/toc.json
index b2cf6954bc995..e48d7359b2a5a 100644
--- a/administrator/help/en-GB/toc.json
+++ b/administrator/help/en-GB/toc.json
@@ -1 +1 @@
-{ "COMPONENTS_ASSOCIATIONS": "COMPONENTS_ASSOCIATIONS", "COMPONENTS_ASSOCIATIONS_EDIT": "COMPONENTS_ASSOCIATIONS_EDIT", "COMPONENTS_BANNERS_BANNERS": "COMPONENTS_BANNERS_BANNERS", "COMPONENTS_BANNERS_BANNERS_EDIT": "COMPONENTS_BANNERS_BANNERS_EDIT", "COMPONENTS_BANNERS_CATEGORIES": "COMPONENTS_BANNERS_CATEGORIES", "COMPONENTS_BANNERS_CATEGORY_EDIT": "COMPONENTS_BANNERS_CATEGORIES_EDIT", "COMPONENTS_BANNERS_CLIENTS": "COMPONENTS_BANNERS_CLIENTS", "COMPONENTS_BANNERS_CLIENTS_EDIT": "COMPONENTS_BANNERS_CLIENTS_EDIT", "COMPONENTS_BANNERS_TRACKS": "COMPONENTS_BANNERS_TRACKS", "COMPONENTS_CONTACTS_CONTACTS": "COMPONENTS_CONTACTS_CONTACTS", "COMPONENTS_CONTACTS_CONTACTS_EDIT": "COMPONENTS_CONTACTS_CONTACTS_EDIT", "COMPONENTS_CONTACT_CATEGORIES": "COMPONENTS_CONTACT_CATEGORIES", "COMPONENTS_CONTACT_CATEGORY_EDIT": "COMPONENTS_CONTACT_CATEGORIES_EDIT", "COMPONENTS_CONTENT_CATEGORIES": "COMPONENTS_CONTENT_CATEGORIES", "COMPONENTS_CONTENT_CATEGORY_EDIT": "COMPONENTS_CONTENT_CATEGORIES_EDIT", "COMPONENTS_FIELDS_FIELDS": "COMPONENTS_FIELDS_FIELDS", "COMPONENTS_FIELDS_FIELDS_EDIT": "COMPONENTS_FIELDS_FIELDS_EDIT", "COMPONENTS_FIELDS_FIELD_GROUPS": "COMPONENTS_FIELDS_FIELD_GROUPS", "COMPONENTS_FIELDS_FIELD_GROUPS_EDIT": "COMPONENTS_FIELDS_FIELD_GROUPS_EDIT", "COMPONENTS_FINDER_MANAGE_CONTENT_MAPS": "COMPONENTS_FINDER_MANAGE_CONTENT_MAPS", "COMPONENTS_FINDER_MANAGE_INDEXED_CONTENT": "COMPONENTS_FINDER_MANAGE_INDEXED_CONTENT", "COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS": "COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS", "COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS_EDIT": "COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS_EDIT", "COMPONENTS_JOOMLA_UPDATE": "COMPONENTS_JOOMLA_UPDATE", "COMPONENTS_MESSAGING_INBOX": "COMPONENTS_MESSAGING_INBOX", "COMPONENTS_MESSAGING_READ": "COMPONENTS_MESSAGING_READ", "COMPONENTS_MESSAGING_WRITE": "COMPONENTS_MESSAGING_WRITE", "COMPONENTS_NEWSFEEDS_CATEGORIES": "COMPONENTS_NEWSFEEDS_CATEGORIES", "COMPONENTS_NEWSFEEDS_CATEGORY_EDIT": "COMPONENTS_NEWSFEEDS_CATEGORIES_EDIT", "COMPONENTS_NEWSFEEDS_FEEDS": "COMPONENTS_NEWSFEEDS_FEEDS", "COMPONENTS_NEWSFEEDS_FEEDS_EDIT": "COMPONENTS_NEWSFEEDS_FEEDS_EDIT", "COMPONENTS_POST_INSTALLATION_MESSAGES": "COMPONENTS_POST_INSTALLATION_MESSAGES", "COMPONENTS_REDIRECT_MANAGER": "COMPONENTS_REDIRECT_MANAGER", "COMPONENTS_REDIRECT_MANAGER_EDIT": "COMPONENTS_REDIRECT_MANAGER_EDIT", "COMPONENTS_SEARCH": "COMPONENTS_SEARCH", "COMPONENTS_TAGS_MANAGER": "COMPONENTS_TAGS_MANAGER", "COMPONENTS_TAGS_MANAGER_EDIT": "COMPONENTS_TAGS_MANAGER_EDIT", "COMPONENTS_WEBLINKS_CATEGORIES": "COMPONENTS_WEBLINKS_CATEGORIES", "COMPONENTS_WEBLINKS_CATEGORY_EDIT": "COMPONENTS_WEBLINKS_CATEGORIES_EDIT", "COMPONENTS_WEBLINKS_LINKS": "COMPONENTS_WEBLINKS_LINKS", "COMPONENTS_WEBLINKS_LINKS_EDIT": "COMPONENTS_WEBLINKS_LINKS_EDIT", "CONTENT_ARTICLE_MANAGER": "CONTENT_ARTICLE_MANAGER", "CONTENT_ARTICLE_MANAGER_EDIT": "CONTENT_ARTICLE_MANAGER_EDIT", "CONTENT_FEATURED_ARTICLES": "CONTENT_FEATURED_ARTICLES", "CONTENT_MEDIA_MANAGER": "CONTENT_MEDIA_MANAGER", "EXTENSIONS_EXTENSION_MANAGER_DATABASE": "EXTENSIONS_EXTENSION_MANAGER_DATABASE", "EXTENSIONS_EXTENSION_MANAGER_DISCOVER": "EXTENSIONS_EXTENSION_MANAGER_DISCOVER", "EXTENSIONS_EXTENSION_MANAGER_INSTALL": "EXTENSIONS_EXTENSION_MANAGER_INSTALL", "EXTENSIONS_EXTENSION_MANAGER_MANAGE": "EXTENSIONS_EXTENSION_MANAGER_MANAGE", "EXTENSIONS_EXTENSION_MANAGER_UPDATE": "EXTENSIONS_EXTENSION_MANAGER_UPDATE", "EXTENSIONS_EXTENSION_MANAGER_WARNINGS": "EXTENSIONS_EXTENSION_MANAGER_WARNINGS", "EXTENSIONS_LANGUAGE_MANAGER_CONTENT": "EXTENSIONS_LANGUAGE_MANAGER_CONTENT", "EXTENSIONS_LANGUAGE_MANAGER_EDIT": "EXTENSIONS_LANGUAGE_MANAGER_EDIT", "EXTENSIONS_LANGUAGE_MANAGER_INSTALLED": "EXTENSIONS_LANGUAGE_MANAGER_INSTALLED", "EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES": "EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES", "EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES_EDIT": "EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES_EDIT", "EXTENSIONS_MODULE_MANAGER": "EXTENSIONS_MODULE_MANAGER", "EXTENSIONS_MODULE_MANAGER_EDIT": "EXTENSIONS_MODULE_MANAGER_EDIT", "EXTENSIONS_PLUGIN_MANAGER": "EXTENSIONS_PLUGIN_MANAGER", "EXTENSIONS_PLUGIN_MANAGER_EDIT": "EXTENSIONS_PLUGIN_MANAGER_EDIT", "EXTENSIONS_TEMPLATE_MANAGER_STYLES": "EXTENSIONS_TEMPLATE_MANAGER_STYLES", "EXTENSIONS_TEMPLATE_MANAGER_STYLES_EDIT": "EXTENSIONS_TEMPLATE_MANAGER_STYLES_EDIT", "EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES": "EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES", "EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES_EDIT": "EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES_EDIT", "EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES_EDIT_SOURCE": "EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES_EDIT_SOURCE", "MENUS_MENU_ITEM_MANAGER": "MENUS_MENU_ITEM_MANAGER", "MENUS_MENU_ITEM_MANAGER_EDIT": "MENUS_MENU_ITEM_MANAGER_EDIT", "MENUS_MENU_MANAGER": "MENUS_MENU_MANAGER", "MENUS_MENU_MANAGER_EDIT": "MENUS_MENU_MANAGER_EDIT", "SITE_GLOBAL_CONFIGURATION": "SITE_GLOBAL_CONFIGURATION", "SITE_MAINTENANCE_CLEAR_CACHE": "SITE_MAINTENANCE_CLEAR_CACHE", "SITE_MAINTENANCE_GLOBAL_CHECK-IN": "SITE_MAINTENANCE_GLOBAL_CHECK-IN", "SITE_MAINTENANCE_PURGE_EXPIRED_CACHE": "SITE_MAINTENANCE_PURGE_EXPIRED_CACHE", "SITE_SYSTEM_INFORMATION": "SITE_SYSTEM_INFORMATION", "START_HERE": "START_HERE", "USERS_ACCESS_LEVELS": "USERS_ACCESS_LEVELS", "USERS_ACCESS_LEVELS_EDIT": "USERS_ACCESS_LEVELS_EDIT", "USERS_DEBUG_USERS": "USERS_DEBUG_USER", "USERS_GROUPS": "USERS_GROUPS", "USERS_GROUPS_EDIT": "USERS_GROUPS_EDIT", "USERS_MASS_MAIL_USERS": "USERS_MASS_MAIL_USERS", "USERS_USER_MANAGER": "USERS_USER_MANAGER", "USERS_USER_MANAGER_EDIT": "USERS_USER_MANAGER_EDIT", "USERS_USER_NOTES": "USERS_USER_NOTES", "USERS_USER_NOTES_EDIT": "USERS_USER_NOTES_EDIT" }
\ No newline at end of file
+{"COMPONENTS_ASSOCIATIONS":"COMPONENTS_ASSOCIATIONS","COMPONENTS_ASSOCIATIONS_EDIT":"COMPONENTS_ASSOCIATIONS_EDIT","COMPONENTS_BANNERS_BANNERS":"COMPONENTS_BANNERS_BANNERS","COMPONENTS_BANNERS_BANNERS_EDIT":"COMPONENTS_BANNERS_BANNERS_EDIT","COMPONENTS_BANNERS_CATEGORIES":"COMPONENTS_BANNERS_CATEGORIES","COMPONENTS_BANNERS_CATEGORY_EDIT":"COMPONENTS_BANNERS_CATEGORIES_EDIT","COMPONENTS_BANNERS_CLIENTS":"COMPONENTS_BANNERS_CLIENTS","COMPONENTS_BANNERS_CLIENTS_EDIT":"COMPONENTS_BANNERS_CLIENTS_EDIT","COMPONENTS_BANNERS_TRACKS":"COMPONENTS_BANNERS_TRACKS","COMPONENTS_CONTACTS_CONTACTS":"COMPONENTS_CONTACTS_CONTACTS","COMPONENTS_CONTACTS_CONTACTS_EDIT":"COMPONENTS_CONTACTS_CONTACTS_EDIT","COMPONENTS_CONTACT_CATEGORIES":"COMPONENTS_CONTACT_CATEGORIES","COMPONENTS_CONTACT_CATEGORY_EDIT":"COMPONENTS_CONTACT_CATEGORIES_EDIT","COMPONENTS_CONTENT_CATEGORIES":"COMPONENTS_CONTENT_CATEGORIES","COMPONENTS_CONTENT_CATEGORY_EDIT":"COMPONENTS_CONTENT_CATEGORIES_EDIT","COMPONENTS_FIELDS_FIELDS":"COMPONENTS_FIELDS_FIELDS","COMPONENTS_FIELDS_FIELDS_EDIT":"COMPONENTS_FIELDS_FIELDS_EDIT","COMPONENTS_FIELDS_FIELD_GROUPS":"COMPONENTS_FIELDS_FIELD_GROUPS","COMPONENTS_FIELDS_FIELD_GROUPS_EDIT":"COMPONENTS_FIELDS_FIELD_GROUPS_EDIT","COMPONENTS_FINDER_MANAGE_CONTENT_MAPS":"COMPONENTS_FINDER_MANAGE_CONTENT_MAPS","COMPONENTS_FINDER_MANAGE_INDEXED_CONTENT":"COMPONENTS_FINDER_MANAGE_INDEXED_CONTENT","COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS":"COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS","COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS_EDIT":"COMPONENTS_FINDER_MANAGE_SEARCH_FILTERS_EDIT","COMPONENTS_JOOMLA_UPDATE":"COMPONENTS_JOOMLA_UPDATE","COMPONENTS_MESSAGING_INBOX":"COMPONENTS_MESSAGING_INBOX","COMPONENTS_MESSAGING_READ":"COMPONENTS_MESSAGING_READ","COMPONENTS_MESSAGING_WRITE":"COMPONENTS_MESSAGING_WRITE","COMPONENTS_NEWSFEEDS_CATEGORIES":"COMPONENTS_NEWSFEEDS_CATEGORIES","COMPONENTS_NEWSFEEDS_CATEGORY_EDIT":"COMPONENTS_NEWSFEEDS_CATEGORIES_EDIT","COMPONENTS_NEWSFEEDS_FEEDS":"COMPONENTS_NEWSFEEDS_FEEDS","COMPONENTS_NEWSFEEDS_FEEDS_EDIT":"COMPONENTS_NEWSFEEDS_FEEDS_EDIT","COMPONENTS_REDIRECT_MANAGER":"COMPONENTS_REDIRECT_MANAGER","COMPONENTS_REDIRECT_MANAGER_EDIT":"COMPONENTS_REDIRECT_MANAGER_EDIT","COMPONENTS_SEARCH":"COMPONENTS_SEARCH","COMPONENTS_TAGS_MANAGER":"COMPONENTS_TAGS_MANAGER","COMPONENTS_TAGS_MANAGER_EDIT":"COMPONENTS_TAGS_MANAGER_EDIT","COMPONENTS_WEBLINKS_CATEGORIES":"COMPONENTS_WEBLINKS_CATEGORIES","COMPONENTS_WEBLINKS_CATEGORY_EDIT":"COMPONENTS_WEBLINKS_CATEGORIES_EDIT","COMPONENTS_WEBLINKS_LINKS":"COMPONENTS_WEBLINKS_LINKS","COMPONENTS_WEBLINKS_LINKS_EDIT":"COMPONENTS_WEBLINKS_LINKS_EDIT","CONTENT_ARTICLE_MANAGER":"CONTENT_ARTICLE_MANAGER","CONTENT_ARTICLE_MANAGER_EDIT":"CONTENT_ARTICLE_MANAGER_EDIT","CONTENT_FEATURED_ARTICLES":"CONTENT_FEATURED_ARTICLES","CONTENT_MEDIA_MANAGER":"CONTENT_MEDIA_MANAGER","EXTENSIONS_EXTENSION_MANAGER_DATABASE":"EXTENSIONS_EXTENSION_MANAGER_DATABASE","EXTENSIONS_EXTENSION_MANAGER_DISCOVER":"EXTENSIONS_EXTENSION_MANAGER_DISCOVER","EXTENSIONS_EXTENSION_MANAGER_INSTALL":"EXTENSIONS_EXTENSION_MANAGER_INSTALL","EXTENSIONS_EXTENSION_MANAGER_LANGUAGES":"EXTENSIONS_EXTENSION_MANAGER_LANGUAGES","EXTENSIONS_EXTENSION_MANAGER_MANAGE":"EXTENSIONS_EXTENSION_MANAGER_MANAGE","EXTENSIONS_EXTENSION_MANAGER_UPDATE":"EXTENSIONS_EXTENSION_MANAGER_UPDATE","EXTENSIONS_EXTENSION_MANAGER_WARNINGS":"EXTENSIONS_EXTENSION_MANAGER_WARNINGS","EXTENSIONS_LANGUAGE_MANAGER_CONTENT":"EXTENSIONS_LANGUAGE_MANAGER_CONTENT","EXTENSIONS_LANGUAGE_MANAGER_EDIT":"EXTENSIONS_LANGUAGE_MANAGER_EDIT","EXTENSIONS_LANGUAGE_MANAGER_INSTALLED":"EXTENSIONS_LANGUAGE_MANAGER_INSTALLED","EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES":"EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES","EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES_EDIT":"EXTENSIONS_LANGUAGE_MANAGER_OVERRIDES_EDIT","EXTENSIONS_MODULE_MANAGER":"EXTENSIONS_MODULE_MANAGER","EXTENSIONS_MODULE_MANAGER_EDIT":"EXTENSIONS_MODULE_MANAGER_EDIT","EXTENSIONS_PLUGIN_MANAGER":"EXTENSIONS_PLUGIN_MANAGER","EXTENSIONS_PLUGIN_MANAGER_EDIT":"EXTENSIONS_PLUGIN_MANAGER_EDIT","EXTENSIONS_TEMPLATE_MANAGER_STYLES":"EXTENSIONS_TEMPLATE_MANAGER_STYLES","EXTENSIONS_TEMPLATE_MANAGER_STYLES_EDIT":"EXTENSIONS_TEMPLATE_MANAGER_STYLES_EDIT","EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES":"EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES","EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES_EDIT":"EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES_EDIT","EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES_EDIT_SOURCE":"EXTENSIONS_TEMPLATE_MANAGER_TEMPLATES_EDIT_SOURCE","MENUS_MENU_ITEM_MANAGER":"MENUS_MENU_ITEM_MANAGER","MENUS_MENU_ITEM_MANAGER_EDIT":"MENUS_MENU_ITEM_MANAGER_EDIT","MENUS_MENU_MANAGER":"MENUS_MENU_MANAGER","MENUS_MENU_MANAGER_EDIT":"MENUS_MENU_MANAGER_EDIT","SITE_GLOBAL_CONFIGURATION":"SITE_GLOBAL_CONFIGURATION","SITE_MAINTENANCE_CLEAR_CACHE":"SITE_MAINTENANCE_CLEAR_CACHE","SITE_MAINTENANCE_GLOBAL_CHECK-IN":"SITE_MAINTENANCE_GLOBAL_CHECK-IN","SITE_MAINTENANCE_PURGE_EXPIRED_CACHE":"SITE_MAINTENANCE_PURGE_EXPIRED_CACHE","SITE_SYSTEM_INFORMATION":"SITE_SYSTEM_INFORMATION","START_HERE":"START_HERE","USERS_ACCESS_LEVELS":"USERS_ACCESS_LEVELS","USERS_ACCESS_LEVELS_EDIT":"USERS_ACCESS_LEVELS_EDIT","USERS_DEBUG_USERS":"USERS_DEBUG_USER","USERS_GROUPS_EDIT":"USERS_GROUPS_EDIT","USERS_MASS_MAIL_USERS":"USERS_MASS_MAIL_USERS","USERS_USER_MANAGER_EDIT":"USERS_USER_MANAGER_EDIT","USERS_USER_NOTES":"USERS_USER_NOTES","USERS_USER_NOTES_EDIT":"USERS_USER_NOTES_EDIT"}
\ No newline at end of file
diff --git a/administrator/language/en-GB/en-GB.com_actionlogs.ini b/administrator/language/en-GB/en-GB.com_actionlogs.ini
new file mode 100644
index 0000000000000..6b6d09dda4b7c
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.com_actionlogs.ini
@@ -0,0 +1,61 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+COM_ACTIONLOGS="User Actions Log"
+COM_ACTIONLOGS_ACTION_VIEWLOGS="View logs"
+COM_ACTIONLOGS_ACTION_VIEWLOGS_DESC="Allows users in the group to view the logs."
+COM_ACTIONLOGS_CONFIGURATION="User Actions Log: Options"
+COM_ACTIONLOGS_CSV_DELIMITER="CSV delimiter"
+COM_ACTIONLOGS_CSV_DELIMITER_DESC="Set the separator for values in the CSV export."
+COM_ACTIONLOGS_COMMA="Comma"
+COM_ACTIONLOGS_DATE="Date"
+COM_ACTIONLOGS_DISABLED="Disabled"
+COM_ACTIONLOGS_EMAIL_DESC="This is the latest action performed by a user on your website."
+COM_ACTIONLOGS_EMAIL_SUBJECT="Latest User Actions"
+COM_ACTIONLOGS_EXPORT_ALL_CSV="Export All as CSV"
+COM_ACTIONLOGS_EXPORT_CSV="Export Selected as CSV"
+COM_ACTIONLOGS_EXTENSION="Extension"
+COM_ACTIONLOGS_EXTENSION_ASC="Extension ascending"
+COM_ACTIONLOGS_EXTENSION_DESC="Extension descending"
+COM_ACTIONLOGS_EXTENSION_FILTER_DESC="Search in the User Action logs by extension"
+COM_ACTIONLOGS_IP_ADDRESS="IP Address"
+COM_ACTIONLOGS_IP_ADDRESS_ASC="IP Address ascending"
+COM_ACTIONLOGS_IP_ADDRESS_DESC="IP Address descending"
+COM_ACTIONLOGS_IP_INVALID="Invalid IP"
+COM_ACTIONLOGS_IP_LOGGING="IP logging"
+COM_ACTIONLOGS_IP_LOGGING_DESC="Enable logging the IP address of users."
+COM_ACTIONLOGS_LOG_EXTENSIONS="Select events to be logged"
+COM_ACTIONLOGS_LOG_EXTENSIONS_DESC="Select events to be logged"
+COM_ACTIONLOGS_MANAGER_USERLOGS="User Actions Log"
+COM_ACTIONLOGS_ACTION="Action"
+COM_ACTIONLOGS_ACTION_ASC="Action ascending"
+COM_ACTIONLOGS_ACTION_DESC="Action descending"
+COM_ACTIONLOGS_NAME="Name"
+COM_ACTIONLOGS_NAME_ASC="Name ascending"
+COM_ACTIONLOGS_NAME_DESC="Name descending"
+COM_ACTIONLOGS_N_ITEMS_DELETED="%s logs deleted."
+COM_ACTIONLOGS_N_ITEMS_DELETED_1="%s log deleted."
+COM_ACTIONLOGS_NO_LOGS_TO_EXPORT="There are no User Action logs to export."
+COM_ACTIONLOGS_NO_ITEM_SELECTED="Please first make a selection from the list."
+COM_ACTIONLOGS_OPTION_FILTER_DATE="- Select Date -"
+COM_ACTIONLOGS_OPTION_RANGE_NEVER="Never"
+COM_ACTIONLOGS_OPTION_RANGE_PAST_1MONTH="In the last month"
+COM_ACTIONLOGS_OPTION_RANGE_PAST_3MONTH="In the last 3 months"
+COM_ACTIONLOGS_OPTION_RANGE_PAST_6MONTH="In the last 6 months"
+COM_ACTIONLOGS_OPTION_RANGE_PAST_WEEK="In the last week"
+COM_ACTIONLOGS_OPTION_RANGE_PAST_YEAR="In the last year"
+COM_ACTIONLOGS_OPTION_RANGE_POST_YEAR="More than a year ago"
+COM_ACTIONLOGS_OPTION_RANGE_TODAY="Today"
+COM_ACTIONLOGS_OPTIONS="Options"
+COM_ACTIONLOGS_POSTINSTALL_TITLE="User Actions Can Now Be Logged"
+COM_ACTIONLOGS_POSTINSTALL_BODY="
With the release of Joomla 3.9.0 you can now log all administrative actions performed by your users in supported extensions. It is now easy to see who did what and when they did it.
The logs can be reviewed in Joomla or exported for external use.
For further information on this new feature read the User Action Logs documentation.
"
+COM_ACTIONLOGS_PURGE_CONFIRM="Are you sure want to delete all User Action logs?"
+COM_ACTIONLOGS_PURGE_FAIL="Failed to delete all User Action logs."
+COM_ACTIONLOGS_PURGE_SUCCESS="All User Action logs have been deleted."
+COM_ACTIONLOGS_SELECT_EXTENSION="- Select Extension -"
+COM_ACTIONLOGS_SELECT_USER="- Select User -"
+COM_ACTIONLOGS_SEMICOLON="Semicolon"
+COM_ACTIONLOGS_TOOLBAR_PURGE="Purge"
+COM_ACTIONLOGS_XML_DESCRIPTION="Displays a log of actions performed by users on your website."
diff --git a/administrator/language/en-GB/en-GB.com_actionlogs.sys.ini b/administrator/language/en-GB/en-GB.com_actionlogs.sys.ini
new file mode 100644
index 0000000000000..db27ad08cf0d0
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.com_actionlogs.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+COM_ACTIONLOGS="User Actions Log"
+COM_ACTIONLOGS_XML_DESCRIPTION="Displays a log of actions performed by users on your website."
diff --git a/administrator/language/en-GB/en-GB.com_admin.ini b/administrator/language/en-GB/en-GB.com_admin.ini
index 3ff9f0a5be4ad..2d11e446889a8 100644
--- a/administrator/language/en-GB/en-GB.com_admin.ini
+++ b/administrator/language/en-GB/en-GB.com_admin.ini
@@ -23,6 +23,7 @@ COM_ADMIN_FILE_UPLOADS="File Uploads"
COM_ADMIN_GLOSSARY="Glossary"
COM_ADMIN_GO="Go"
COM_ADMIN_HELP="Joomla! Help"
+COM_ADMIN_HELP_COMPONENTS_ACTIONLOGS="Action Logs"
COM_ADMIN_HELP_COMPONENTS_ASSOCIATIONS="Multilingual Associations"
COM_ADMIN_HELP_COMPONENTS_ASSOCIATIONS_EDIT="Multilingual Associations: Select"
COM_ADMIN_HELP_COMPONENTS_BANNERS_BANNERS="Banners"
@@ -55,6 +56,12 @@ COM_ADMIN_HELP_COMPONENTS_NEWSFEEDS_CATEGORIES_EDIT="News Feeds: Categories - Ne
COM_ADMIN_HELP_COMPONENTS_NEWSFEEDS_FEEDS="News Feeds"
COM_ADMIN_HELP_COMPONENTS_NEWSFEEDS_FEEDS_EDIT="News Feeds: New/Edit"
COM_ADMIN_HELP_COMPONENTS_POST_INSTALLATION_MESSAGES="Post-Installation Messages"
+COM_ADMIN_HELP_COMPONENTS_PRIVACY_CAPABILITIES="Privacy: Extension Capabilities"
+COM_ADMIN_HELP_COMPONENTS_PRIVACY_CONSENTS="Privacy: Consents"
+COM_ADMIN_HELP_COMPONENTS_PRIVACY_DASHBOARD="Privacy: Dashboard"
+COM_ADMIN_HELP_COMPONENTS_PRIVACY_REQUEST="Privacy: Review Information Request"
+COM_ADMIN_HELP_COMPONENTS_PRIVACY_REQUEST_EDIT="Privacy: New Information Request"
+COM_ADMIN_HELP_COMPONENTS_PRIVACY_REQUESTS="Privacy: Information Requests"
COM_ADMIN_HELP_COMPONENTS_REDIRECT_MANAGER="Redirect: Links"
COM_ADMIN_HELP_COMPONENTS_REDIRECT_MANAGER_EDIT="Redirect: Links - New/Edit"
COM_ADMIN_HELP_COMPONENTS_SEARCH="Search"
diff --git a/administrator/language/en-GB/en-GB.com_config.ini b/administrator/language/en-GB/en-GB.com_config.ini
index 1e5ce8a813741..1b576403d9363 100644
--- a/administrator/language/en-GB/en-GB.com_config.ini
+++ b/administrator/language/en-GB/en-GB.com_config.ini
@@ -37,6 +37,7 @@ COM_CONFIG_ERROR_ROOT_ASSET_NOT_FOUND="The asset for global configuration could
COM_CONFIG_ERROR_SSL_NOT_AVAILABLE="HTTPS has not been enabled as it is not available on this server. HTTPS connection test failed with the following error:
%s"
COM_CONFIG_ERROR_SSL_NOT_AVAILABLE_HTTP_CODE="HTTPS version of the site returned an invalid HTTP status code."
COM_CONFIG_ERROR_REMOVING_SUPER_ADMIN="You can't remove your own Super User permissions."
+COM_CONFIG_ERROR_UNKNOWN_BEFORE_SAVING="A plugin reported an unknown error before saving the configuration."
COM_CONFIG_ERROR_WRITE_FAILED="Could not write to the configuration file"
COM_CONFIG_FIELD_CACHE_HANDLER_DESC="Choose the cache handler. Native caching mechanism is file-based. Please make sure the cache folders are writable."
COM_CONFIG_FIELD_CACHE_HANDLER_LABEL="Cache Handler"
diff --git a/administrator/language/en-GB/en-GB.com_messages.ini b/administrator/language/en-GB/en-GB.com_messages.ini
index 210960ed434ab..676051f87e302 100644
--- a/administrator/language/en-GB/en-GB.com_messages.ini
+++ b/administrator/language/en-GB/en-GB.com_messages.ini
@@ -15,6 +15,9 @@ COM_MESSAGES_ERROR_INVALID_FROM_USER="Invalid sender"
COM_MESSAGES_ERROR_INVALID_MESSAGE="Invalid message content"
COM_MESSAGES_ERROR_INVALID_SUBJECT="Invalid subject"
COM_MESSAGES_ERROR_INVALID_TO_USER="Invalid recipient"
+COM_MESSAGES_ERROR_MISSING_ROOT_ASSET_GROUPS="Missing root asset groups to send notification."
+COM_MESSAGES_ERROR_NO_GROUPS_SET_AS_SUPER_USER="There are no groups set with super user permissions."
+COM_MESSAGES_ERROR_NO_USERS_SET_AS_SUPER_USER="There are no users set with super user permissions."
COM_MESSAGES_FIELD_AUTO_PURGE_DESC="Automatically delete private messages after the given number of days."
COM_MESSAGES_FIELD_AUTO_PURGE_LABEL="Auto-delete Messages (days)"
COM_MESSAGES_FIELD_DATE_TIME_LABEL="Posted"
diff --git a/administrator/language/en-GB/en-GB.com_privacy.ini b/administrator/language/en-GB/en-GB.com_privacy.ini
new file mode 100644
index 0000000000000..551bf57655c0d
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.com_privacy.ini
@@ -0,0 +1,149 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+COM_PRIVACY="Privacy"
+COM_PRIVACY_ACTION_DELETE_DATA="Delete Data"
+COM_PRIVACY_ACTION_EMAIL_EXPORT_DATA="Email Data Export"
+COM_PRIVACY_ACTION_EXPORT_DATA="Export Data"
+COM_PRIVACY_ACTION_LOG_ADMIN_COMPLETED_REQUEST="User
{username} completed
request #{id} for {subjectemail}"
+COM_PRIVACY_ACTION_LOG_ADMIN_CREATED_REQUEST="User
{username} created
request #{id} for {subjectemail}"
+COM_PRIVACY_ACTION_LOG_ADMIN_INVALIDATED_REQUEST="User
{username} invalidated
request #{id} for {subjectemail}"
+COM_PRIVACY_ACTION_LOG_CONFIRMED_REQUEST="{subjectemail} has confirmed
request #{id}"
+COM_PRIVACY_ACTION_LOG_CREATED_REQUEST="{subjectemail} has submitted
request #{id}"
+COM_PRIVACY_ACTION_LOG_EXPORT="User
{username} exported the data for
request #{id}"
+COM_PRIVACY_ACTION_LOG_EXPORT_EMAILED="User
{username} emailed the data export for
request #{id} to the recipient"
+COM_PRIVACY_ACTION_LOG_REMOVE="User
{username} removed the data for
request #{id}"
+COM_PRIVACY_ACTION_LOG_REMOVE_BLOCKED="User
{username} attempted to remove the data for
request #{id} however this action was blocked"
+COM_PRIVACY_ACTION_VIEW="View Request"
+COM_PRIVACY_BADGE_URGENT_REQUEST="Urgent"
+COM_PRIVACY_CONFIGURATION="Privacy: Options"
+COM_PRIVACY_CORE_CAPABILITY_COMMUNICATION_WITH_JOOMLA_ORG="When a network connection is available, a Joomla installation will attempt to communicate with the joomla.org servers for various capabilities, to include:
- Checking for updates for the Joomla application
- Help screens for core Joomla extensions
- The Install from Web service (opt-in)
- The statistics collection server (opt-in)
As with all HTTP requests, the IP address of your server will be transmitted as part of the request. For information on how Joomla processes data on its servers, please review our
privacy policy."
+; The placeholder for this key is the configured log path for the site.
+COM_PRIVACY_CORE_CAPABILITY_LOGGING_IP_ADDRESS="Joomla's logging system records the IP address of the visitor which led to a message being written to its log files. These log files are used to record various activity on a Joomla site, including information related to core updates, invalid login attempts, unhandled errors, and development information such as the use of deprecated APIs. The format of these log files may be customised by any extension which configures a logger, therefore you are encouraged to download and review the log files for your website which may be found at `%s`."
+COM_PRIVACY_CORE_CAPABILITY_SESSION_IP_ADDRESS_AND_COOKIE="All requests to a Joomla website start a session which stores the IP address in the session data and creates a session cookie in the user's browser. The IP address is used as a security measure to help protect against potential session hijacking attacks and this information is deleted once the session has expired and its data purged. The session cookie's name is based on a randomly generated hash and therefore does not have a constant identifier. The session cookie is destroyed once the session has expired or the user has exited their browser."
+COM_PRIVACY_DASHBOARD_BADGE_ACTIVE_REQUESTS_0="
%d Active Requests"
+COM_PRIVACY_DASHBOARD_BADGE_ACTIVE_REQUESTS_1="
%d Active Request"
+COM_PRIVACY_DASHBOARD_BADGE_ACTIVE_REQUESTS_MORE="
%d Active Requests"
+COM_PRIVACY_DASHBOARD_BADGE_TOTAL_REQUESTS_0="
%d Total Requests"
+COM_PRIVACY_DASHBOARD_BADGE_TOTAL_REQUESTS_1="
%d Total Request"
+COM_PRIVACY_DASHBOARD_BADGE_TOTAL_REQUESTS_MORE="
%d Total Requests"
+COM_PRIVACY_DASHBOARD_HEADING_CHECK="Check"
+COM_PRIVACY_DASHBOARD_HEADING_REQUEST_COUNT="# of Requests"
+COM_PRIVACY_DASHBOARD_HEADING_REQUEST_STATUS="Status"
+COM_PRIVACY_DASHBOARD_HEADING_REQUEST_TYPE="Request Type"
+COM_PRIVACY_DASHBOARD_HEADING_STATUS="Status"
+COM_PRIVACY_DASHBOARD_HEADING_STATUS_CHECK="Status Check"
+COM_PRIVACY_DASHBOARD_HEADING_TOTAL_REQUEST_COUNT="Total Request Count"
+COM_PRIVACY_DASHBOARD_NO_REQUESTS="There are no requests."
+COM_PRIVACY_DASHBOARD_VIEW_REQUESTS="View Requests"
+COM_PRIVACY_DATA_REMOVED="Data removed"
+COM_PRIVACY_EDIT_PRIVACY_POLICY="Edit Privacy Policy"
+COM_PRIVACY_EXTENSION_CAPABILITY_PERSONAL_INFO="In order to process information requests, information about the user must be collected and logged for the purposes of retaining an audit log. The request system is based on an individual's email address which will be used to link the request to an existing site user if able."
+; You can use the following merge codes for all COM_PRIVACY_EMAIL strings:
+; [SITENAME] Site name, as set in Global Configuration.
+; [URL] URL of the site's frontend page.
+; [TOKENURL] URL of the confirm page with the token prefilled.
+; [FORMURL] URL of the confirm page where the user can paste their token.
+; [TOKEN] The confirmation token.
+; \n Newline character. Use it to start a new line in the email.
+COM_PRIVACY_EMAIL_ADMIN_REQUEST_BODY_EXPORT_REQUEST="An administrator for [URL] has created a request to export personal information related to this email address. As a security measure, you must confirm that this is a valid request for your personal information from this website.\n\nIn order to confirm this request, you can complete one of the following tasks:\n\n1. Visit the following URL: [TOKENURL]\n\n2. Copy your token from this email, visit the referenced URL, and paste your token into the form.\nURL: [FORMURL]\nToken: [TOKEN]\n\nPlease note that this token is only valid for 24 hours from the time this email was sent."
+COM_PRIVACY_EMAIL_ADMIN_REQUEST_BODY_REMOVE_REQUEST="An administrator for [URL] has created a request to remove all personal information related to this email address. As a security measure, you must confirm that this is a valid request for your personal information to be removed from this website.\n\nIn order to confirm this request, you can complete one of the following tasks:\n\n1. Visit the following URL: [TOKENURL]\n\n2. Copy your token from this email, visit the referenced URL, and paste your token into the form.\nURL: [FORMURL]\nToken: [TOKEN]\n\nPlease note that this token is only valid for 24 hours from the time this email was sent."
+COM_PRIVACY_EMAIL_ADMIN_REQUEST_SUBJECT_EXPORT_REQUEST="Information Request Created at [SITENAME]"
+COM_PRIVACY_EMAIL_ADMIN_REQUEST_SUBJECT_REMOVE_REQUEST="Information Deletion Request Created at [SITENAME]"
+COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_BODY="An administrator for [URL] has completed the data export you requested and a copy of the information can be found in the file attached to this message."
+COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_SUBJECT="Data Export for [SITENAME]"
+COM_PRIVACY_ERROR_ACTIVE_REQUEST_FOR_EMAIL="There is already an active information request for this email address, the active request should be completed before starting a new one."
+COM_PRIVACY_ERROR_CANNOT_CREATE_REQUEST_FOR_SELF="You can't create an information request for yourself."
+COM_PRIVACY_ERROR_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED="Information requests can't be created when sending mail is disabled."
+COM_PRIVACY_ERROR_CANNOT_EXPORT_UNCONFIRMED_REQUEST="The data for an unconfirmed request can't be exported."
+COM_PRIVACY_ERROR_CANNOT_REMOVE_DATA="The data for this request can't be removed."
+COM_PRIVACY_ERROR_CANNOT_REMOVE_UNCONFIRMED_REQUEST="The data for an unconfirmed request can't be removed."
+COM_PRIVACY_ERROR_COMPLETE_TRANSITION_NOT_PERMITTED="This record can't be updated to \"Completed\" status."
+COM_PRIVACY_ERROR_EXPORT_EMAIL_FAILED="Export failed with the following error: %s"
+COM_PRIVACY_ERROR_INVALID_TRANSITION_NOT_PERMITTED="This record can't be updated to \"Invalid\" status."
+COM_PRIVACY_ERROR_REMOVE_DATA_FAILED="Removal failed with the following error: %s"
+COM_PRIVACY_ERROR_REQUEST_ID_REQUIRED_FOR_EXPORT="A request ID is required to export data."
+COM_PRIVACY_ERROR_REQUEST_ID_REQUIRED_FOR_REMOVE="A request ID is required to remove data."
+COM_PRIVACY_ERROR_REQUEST_TYPE_NOT_EXPORT="Only export requests may be exported."
+COM_PRIVACY_ERROR_REQUEST_TYPE_NOT_REMOVE="Only removal requests may have their data removed."
+COM_PRIVACY_ERROR_UNKNOWN_REQUEST_TYPE="Unknown information request type."
+COM_PRIVACY_EXPORT_EMAILED="The data export has been emailed."
+COM_PRIVACY_FIELD_REQUESTED_AT_LABEL="Date Requested"
+COM_PRIVACY_FIELD_REQUEST_TYPE_DESC="The type of information request."
+COM_PRIVACY_FIELD_REQUEST_TYPE_LABEL="Request Type"
+COM_PRIVACY_FIELD_STATUS_DESC="The status of the information request."
+COM_PRIVACY_FILTER_SEARCH_LABEL="Search Requests"
+COM_PRIVACY_HEADING_ACTION_LOG="Action Log"
+COM_PRIVACY_HEADING_ACTIONS="Actions"
+COM_PRIVACY_HEADING_CONSENTS_BODY="Body"
+COM_PRIVACY_HEADING_CONSENTS_CREATED="Created"
+COM_PRIVACY_HEADING_CONSENTS_SUBJECT="Subject"
+COM_PRIVACY_HEADING_CORE_CAPABILITIES="Joomla Core Capabilities"
+COM_PRIVACY_HEADING_CREATED_ASC="Created ascending"
+COM_PRIVACY_HEADING_CREATED_DESC="Created descending"
+COM_PRIVACY_HEADING_EMAIL_ASC="Email ascending"
+COM_PRIVACY_HEADING_EMAIL_DESC="Email descending"
+COM_PRIVACY_HEADING_REQUEST_INFORMATION="Request Information"
+COM_PRIVACY_HEADING_REQUEST_TYPE="Request Type"
+COM_PRIVACY_HEADING_REQUEST_TYPE_ASC="Request Type ascending"
+COM_PRIVACY_HEADING_REQUEST_TYPE_DESC="Request Type descending"
+COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_EXPORT="Export"
+COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_REMOVE="Remove"
+COM_PRIVACY_HEADING_REQUESTED_AT="Requested"
+COM_PRIVACY_HEADING_REQUESTED_AT_ASC="Requested ascending"
+COM_PRIVACY_HEADING_REQUESTED_AT_DESC="Requested descending"
+COM_PRIVACY_HEADING_STATUS_ASC="Status ascending"
+COM_PRIVACY_HEADING_STATUS_DESC="Status descending"
+COM_PRIVACY_HEADING_USERID="User ID"
+COM_PRIVACY_HEADING_USERID_ASC="User ID ascending"
+COM_PRIVACY_HEADING_USERID_DESC="User ID descending"
+COM_PRIVACY_HEADING_USERNAME_ASC="Username descending"
+COM_PRIVACY_HEADING_USERNAME_DESC="Username descending"
+COM_PRIVACY_MSG_CAPABILITIES_ABOUT_THIS_INFORMATION="About This Information"
+COM_PRIVACY_MSG_CAPABILITIES_INTRODUCTION="The information on this screen is collected from extensions which report their privacy related capabilities to this system. It is intended to help site owners be aware of the capabilities of installed extensions and provide information to help owners create local site policies such as a privacy policy. As this screen requires extensions to support its reporting system, and only displays information from enabled extensions, this should not be considered a complete list and you are encouraged to consult each extension's documentation for more information."
+COM_PRIVACY_MSG_CAPABILITIES_NO_CAPABILITIES="There are no reported extension capabilities."
+COM_PRIVACY_MSG_CONFIRM_EMAIL_SENT_TO_USER="A confirmation email for this request has been sent to the user."
+COM_PRIVACY_MSG_CONSENTS_NO_CONSENTS="There are no stored consents."
+COM_PRIVACY_MSG_EXTENSION_NO_CAPABILITIES="This extension does not report any capabilities."
+COM_PRIVACY_MSG_REQUESTS_NO_REQUESTS="There are no information requests matching your query."
+COM_PRIVACY_NOTIFY_DESC="Show a notification when there are requests older than the specified number of days."
+COM_PRIVACY_NOTIFY_LABEL="Days To Consider Request Urgent"
+COM_PRIVACY_OPTION_LABEL="Options"
+COM_PRIVACY_POSTINSTALL_TITLE="Increased Management Of Users Privacy"
+COM_PRIVACY_POSTINSTALL_BODY="
With the introduction of GDPR for EU citizens and similar regulations elsewhere in the world it may be necessary for you to request consent before storing any Personal Information of a user.
Joomla 3.9 introduces new capabilities to assist you in creating site privacy policies and collecting user consent. In addition a workflow is available to help you manage user information requests such as requests for removing their personal data from your site.
For further information on this new feature read the Privacy documentation.
"
+COM_PRIVACY_REQUEST_COMPLETED="The request has been completed."
+COM_PRIVACY_REQUEST_INVALIDATED="The request has been invalidated."
+COM_PRIVACY_SHOW_URGENT_REQUESTS="Show Urgent Requests"
+COM_PRIVACY_SELECT_REQUEST_TYPE="- Select Request Type -"
+COM_PRIVACY_STATUS_CHECK_OUTSTANDING_URGENT_REQUESTS="Outstanding Urgent Requests"
+COM_PRIVACY_STATUS_CHECK_OUTSTANDING_URGENT_REQUESTS_DESCRIPTION="Requests which are older than %d days, as set in the component configuration."
+COM_PRIVACY_STATUS_CHECK_REQUEST_FORM_MENU_ITEM_PUBLISHED="Request Form Menu Item Published"
+COM_PRIVACY_STATUS_CHECK_PRIVACY_POLICY_PUBLISHED="Privacy Policy Published"
+COM_PRIVACY_STATUS_CHECK_SENDMAIL_DISABLED="Mail Sending Disabled"
+COM_PRIVACY_STATUS_CHECK_SENDMAIL_DISABLED_DESCRIPTION="Mail Sending must be enabled, it is a requirement to use the request system"
+COM_PRIVACY_STATUS_CHECK_SENDMAIL_ENABLED="Mail Sending Enabled"
+COM_PRIVACY_STATUS_CHECK_SUCCESSFUL="Check Successful"
+COM_PRIVACY_STATUS_CHECK_UNSUCCESSFUL="Check Unsuccessful"
+COM_PRIVACY_STATUS_COMPLETED="Completed"
+COM_PRIVACY_STATUS_CONFIRMED="Confirmed"
+COM_PRIVACY_STATUS_INVALID="Invalid"
+COM_PRIVACY_STATUS_PENDING="Pending"
+COM_PRIVACY_SEARCH_IN_EMAIL="Search in requestor email address. Prefix with ID: to search for a request ID."
+COM_PRIVACY_SEARCH_IN_USERNAME="Search in username. Prefix with ID: to search for a consent ID. Prefix with UID: to search for a User ID."
+COM_PRIVACY_SUBMENU_CAPABILITIES="Capabilities"
+COM_PRIVACY_SUBMENU_CONSENTS="Consents"
+COM_PRIVACY_SUBMENU_DASHBOARD="Dashboard"
+COM_PRIVACY_SUBMENU_REQUESTS="Requests"
+COM_PRIVACY_TOOLBAR_COMPLETE="Complete"
+COM_PRIVACY_TOOLBAR_INVALIDATE="Invalidate"
+COM_PRIVACY_USER_FIELD_EMAIL_DESC="The email address of the individual owning the information being requested."
+COM_PRIVACY_VIEW_CAPABILITIES="Privacy: Extension Capabilities"
+COM_PRIVACY_VIEW_CONSENTS="Privacy: Consents"
+COM_PRIVACY_VIEW_DASHBOARD="Privacy: Dashboard"
+COM_PRIVACY_VIEW_REQUEST_ADD_REQUEST="Privacy: New Information Request"
+COM_PRIVACY_VIEW_REQUEST_SHOW_REQUEST="Privacy: Review Information Request"
+COM_PRIVACY_VIEW_REQUESTS="Privacy: Information Requests"
+COM_PRIVACY_WARNING_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED="Information requests can't be created when sending mail is disabled."
+COM_PRIVACY_XML_DESCRIPTION="Component for managing privacy related actions."
diff --git a/administrator/language/en-GB/en-GB.com_privacy.sys.ini b/administrator/language/en-GB/en-GB.com_privacy.sys.ini
new file mode 100644
index 0000000000000..a2bf34df661e4
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.com_privacy.sys.ini
@@ -0,0 +1,21 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+COM_PRIVACY="Privacy"
+COM_PRIVACY_CONFIRM_VIEW_DEFAULT_DESC="Displays a form to confirm an information request."
+COM_PRIVACY_CONFIRM_VIEW_DEFAULT_OPTION="Default"
+COM_PRIVACY_CONFIRM_VIEW_DEFAULT_TITLE="Confirm Request"
+COM_PRIVACY_CONSENTS_VIEW_DEFAULT_DESC="Shows a list of user consents"
+COM_PRIVACY_CONSENTS_VIEW_DEFAULT_TITLE="Privacy: Consents"
+COM_PRIVACY_DASHBOARD_VIEW_DEFAULT_DESC="A dashboard related to the site's privacy settings and information requests."
+COM_PRIVACY_DASHBOARD_VIEW_DEFAULT_TITLE="Privacy: Dashboard"
+COM_PRIVACY_REMIND_VIEW_DEFAULT_DESC="Displays a form to extend the privacy consent"
+COM_PRIVACY_REMIND_VIEW_DEFAULT_TITLE="Extend Consent"
+COM_PRIVACY_REQUEST_VIEW_DEFAULT_DESC="Displays a form to submit an information request."
+COM_PRIVACY_REQUEST_VIEW_DEFAULT_OPTION="Default"
+COM_PRIVACY_REQUEST_VIEW_DEFAULT_TITLE="Create Request"
+COM_PRIVACY_REQUESTS_VIEW_DEFAULT_DESC="Shows a list of user information requests"
+COM_PRIVACY_REQUESTS_VIEW_DEFAULT_TITLE="Privacy: Information Requests"
+COM_PRIVACY_XML_DESCRIPTION="Component for managing privacy related actions."
diff --git a/administrator/language/en-GB/en-GB.ini b/administrator/language/en-GB/en-GB.ini
index 4a6315d720534..f4a19e2c08e01 100644
--- a/administrator/language/en-GB/en-GB.ini
+++ b/administrator/language/en-GB/en-GB.ini
@@ -481,6 +481,7 @@ JGLOBAL_NO_ITEM_SELECTED="No items selected"
JGLOBAL_NO_ORDER="No Order"
JGLOBAL_NOINDEX_FOLLOW="No index, follow"
JGLOBAL_NOINDEX_NOFOLLOW="No index, no follow"
+JGLOBAL_NONAPPLICABLE="N/A"
JGLOBAL_NUM_COLUMNS_DESC="The number of columns in which to show Intro Articles. Normally 1, 2, or 3."
JGLOBAL_NUM_COLUMNS_LABEL="# Columns"
JGLOBAL_NUM_INTRO_ARTICLES_DESC="Number of articles to show after the leading article. Articles will be shown in columns."
@@ -653,6 +654,7 @@ JGRID_HEADING_ORDERING="Ordering"
JGRID_HEADING_ORDERING_ASC="Ordering ascending"
JGRID_HEADING_ORDERING_DESC="Ordering descending"
+JHELP_COMPONENTS_ACTIONLOGS="Components_Actionlogs"
JHELP_COMPONENTS_ASSOCIATIONS="Components_Associations"
JHELP_COMPONENTS_ASSOCIATIONS_EDIT="Components_Associations_Edit"
JHELP_COMPONENTS_BANNERS_BANNERS_EDIT="Components_Banners_Banners_Edit"
@@ -665,8 +667,9 @@ JHELP_COMPONENTS_BANNERS_CLIENTS="Components_Banners_Clients"
JHELP_COMPONENTS_BANNERS_TRACKS="Components_Banners_Tracks"
JHELP_COMPONENTS_CACHE_MANAGER_SETTINGS="Components_Cache_Manager_Settings"
JHELP_COMPONENTS_CHECK-IN_CONFIGURATION="Components_Check-in_Configuration"
-JHELP_COMPONENTS_COM_BANNERS_OPTIONS="Components_Banner_Manager_Options"
+JHELP_COMPONENTS_COM_ACTIONLOGS_OPTIONS="Components_Actionlogs"
JHELP_COMPONENTS_COM_ASSOCIATIONS_OPTIONS="Components_Associations_Options"
+JHELP_COMPONENTS_COM_BANNERS_OPTIONS="Components_Banner_Manager_Options"
JHELP_COMPONENTS_COM_CACHE_OPTIONS="Components_Cache_Manager_Settings"
JHELP_COMPONENTS_COM_CHECKIN_OPTIONS="Components_Check_in_Configuration"
JHELP_COMPONENTS_COM_CONTACT_OPTIONS="Components_Contact_Manager_Options"
@@ -681,6 +684,7 @@ JHELP_COMPONENTS_COM_MESSAGES_OPTIONS="Components_Messages_Configuration"
JHELP_COMPONENTS_COM_MODULES_OPTIONS="Components_Module_Manager_Options"
JHELP_COMPONENTS_COM_NEWSFEEDS_OPTIONS="Components_News_Feed_Manager_Options"
JHELP_COMPONENTS_COM_PLUGINS_OPTIONS="Components_Plugin_Manager_Options"
+JHELP_COMPONENTS_COM_PRIVACY_OPTIONS="Components_Privacy_Options"
JHELP_COMPONENTS_COM_POSTINSTALL_OPTIONS="Components_Post_installation_Messages_Configuration"
JHELP_COMPONENTS_COM_REDIRECT_OPTIONS="Components_Redirect_Manager_Options"
JHELP_COMPONENTS_COM_SEARCH_OPTIONS="Components_Search_Manager_Options"
@@ -718,6 +722,12 @@ JHELP_COMPONENTS_NEWSFEEDS_CATEGORY_EDIT="Components_Newsfeeds_Categories_Edit"
JHELP_COMPONENTS_NEWSFEEDS_FEEDS_EDIT="Components_Newsfeeds_Feeds_Edit"
JHELP_COMPONENTS_NEWSFEEDS_FEEDS="Components_Newsfeeds_Feeds"
JHELP_COMPONENTS_POST_INSTALLATION_MESSAGES="Components_Post_installation_Messages"
+JHELP_COMPONENTS_PRIVACY_CAPABILITIES="Components_Privacy_Capabilities"
+JHELP_COMPONENTS_PRIVACY_CONSENTS="Components_Privacy_Consents"
+JHELP_COMPONENTS_PRIVACY_DASHBOARD="Components_Privacy_Dashboard"
+JHELP_COMPONENTS_PRIVACY_REQUEST="Components_Privacy_Request"
+JHELP_COMPONENTS_PRIVACY_REQUEST_EDIT="Components_Privacy_Request_Edit"
+JHELP_COMPONENTS_PRIVACY_REQUESTS="Components_Privacy_Requests"
JHELP_COMPONENTS_REDIRECT_MANAGER_EDIT="Components_Redirect_Manager_Edit"
JHELP_COMPONENTS_REDIRECT_MANAGER="Components_Redirect_Manager"
JHELP_COMPONENTS_SEARCH="Components_Search"
@@ -753,12 +763,14 @@ JHELP_EXTENSIONS_MODULE_MANAGER="Extensions_Module_Manager"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_CUSTOM="Extensions_Module_Manager_Admin_Custom"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_FEED="Extensions_Module_Manager_Admin_Feed"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_LATEST="Extensions_Module_Manager_Admin_Latest"
+JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_LATESTACTIONS="Extensions_Module_Manager_Admin_Latestactions"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_LOGGED="Extensions_Module_Manager_Admin_Logged"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_LOGIN="Extensions_Module_Manager_Admin_Login"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_MENU="Extensions_Module_Manager_Admin_Menu"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_MULTILANG="Extensions_Module_Manager_Admin_Multilang"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_ONLINE="Extensions_Module_Manager_Admin_Online"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_POPULAR="Extensions_Module_Manager_Admin_Popular"
+JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_PRIVACY_DASHBOARD="Extensions_Module_Manager_Admin_Privacy_Dashboard"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_QUICKICON="Extensions_Module_Manager_Admin_Quickicon"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_STATUS="Extensions_Module_Manager_Admin_Status"
JHELP_EXTENSIONS_MODULE_MANAGER_ADMIN_SUBMENU="Extensions_Module_Manager_Admin_Submenu"
@@ -822,6 +834,9 @@ JHELP_MENUS_MENU_ITEM_MENU_ITEM_HEADING="Menus_Menu_Item_Menu_Item_Heading"
JHELP_MENUS_MENU_ITEM_NEWSFEED_CATEGORIES="Menus_Menu_Item_Newsfeed_Categories"
JHELP_MENUS_MENU_ITEM_NEWSFEED_CATEGORY="Menus_Menu_Item_Newsfeed_Category"
JHELP_MENUS_MENU_ITEM_NEWSFEED_SINGLE_NEWSFEED="Menus_Menu_Item_Newsfeed_Single_Newsfeed"
+JHELP_MENUS_MENU_ITEM_PRIVACY_CONFIRM_REQUEST="Menus_Menu_Item_Privacy_Confirm_Request"
+JHELP_MENUS_MENU_ITEM_PRIVACY_CREATE_REQUEST=" Menus_Menu_Item_Privacy_Create_Request"
+JHELP_MENUS_MENU_ITEM_PRIVACY_REMIND_REQUEST="Menus_Menu_Item_Privacy_Remind_Request"
JHELP_MENUS_MENU_ITEM_SEARCH_RESULTS="Menus_Menu_Item_Search_Results"
JHELP_MENUS_MENU_ITEM_TAGS_ITEMS_COMPACT_LIST="Menus_Menu_Item_Tags_Items_Compact_List"
JHELP_MENUS_MENU_ITEM_TAGS_ITEMS_LIST="Menus_Menu_Item_Tags_Items_List"
diff --git a/administrator/language/en-GB/en-GB.mod_latestactions.ini b/administrator/language/en-GB/en-GB.mod_latestactions.ini
new file mode 100644
index 0000000000000..093c175dca254
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.mod_latestactions.ini
@@ -0,0 +1,11 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+MOD_LATESTACTIONS="Action Logs - Latest"
+MOD_LATESTACTIONS_FIELD_COUNT_LABEL="Count"
+MOD_LATESTACTIONS_FIELD_COUNT_DESC="The number of items to display (default 5)."
+MOD_LATESTACTIONS_LAYOUT_DEFAULT="Default"
+MOD_LATEST_ACTIONS_NO_MATCHING_RESULTS="No Matching Results"
+MOD_LATESTACTIONS_XML_DESCRIPTION="This module shows a list of the most recent actions."
diff --git a/administrator/language/en-GB/en-GB.mod_latestactions.sys.ini b/administrator/language/en-GB/en-GB.mod_latestactions.sys.ini
new file mode 100644
index 0000000000000..2535518ba3835
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.mod_latestactions.sys.ini
@@ -0,0 +1,9 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+
+MOD_LATESTACTIONS="Action Logs - Latest"
+MOD_LATESTACTIONS_XML_DESCRIPTION="This module shows a list of the most recent actions."
+
diff --git a/administrator/language/en-GB/en-GB.mod_menu.ini b/administrator/language/en-GB/en-GB.mod_menu.ini
index df62a5794cc8b..9778511f6d332 100644
--- a/administrator/language/en-GB/en-GB.mod_menu.ini
+++ b/administrator/language/en-GB/en-GB.mod_menu.ini
@@ -6,6 +6,7 @@
MOD_MENU="Administrator Menu"
MOD_MENU_CLEAR_CACHE="Clear Cache"
MOD_MENU_COMPONENTS="Components"
+MOD_MENU_COM_ACTIONLOGS="User Actions Log"
MOD_MENU_COM_CONTENT="Content"
MOD_MENU_COM_CONTENT_ARTICLE_MANAGER="Articles"
MOD_MENU_COM_CONTENT_CATEGORY_MANAGER="Categories"
@@ -15,6 +16,7 @@ MOD_MENU_COM_CONTENT_NEW_CATEGORY="Add New Category"
MOD_MENU_COM_LANGUAGES_SUBMENU_CONTENT="Content Languages"
MOD_MENU_COM_LANGUAGES_SUBMENU_INSTALLED="Installed"
MOD_MENU_COM_LANGUAGES_SUBMENU_OVERRIDES="Overrides"
+MOD_MENU_COM_PRIVACY="Privacy"
MOD_MENU_COM_TEMPLATES_SUBMENU_STYLES="Styles"
MOD_MENU_COM_TEMPLATES_SUBMENU_TEMPLATES="Templates"
MOD_MENU_COM_USERS="Users"
diff --git a/administrator/language/en-GB/en-GB.mod_privacy_dashboard.ini b/administrator/language/en-GB/en-GB.mod_privacy_dashboard.ini
new file mode 100644
index 0000000000000..fde5ee95b941d
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.mod_privacy_dashboard.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+MOD_PRIVACY_DASHBOARD="Privacy Dashboard"
+MOD_PRIVACY_DASHBOARD_XML_DESCRIPTION="The Privacy Dashboard Module shows information about privacy requests."
diff --git a/administrator/language/en-GB/en-GB.mod_privacy_dashboard.sys.ini b/administrator/language/en-GB/en-GB.mod_privacy_dashboard.sys.ini
new file mode 100644
index 0000000000000..22ea11c29cc1f
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.mod_privacy_dashboard.sys.ini
@@ -0,0 +1,9 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+MOD_PRIVACY_DASHBOARD="Privacy Dashboard"
+MOD_PRIVACY_DASHBOARD_XML_DESCRIPTION="The Privacy Dashboard Module shows information about privacy requests."
+MOD_PRIVACY_DASHBOARD_LAYOUT_DEFAULT="Default"
+
diff --git a/administrator/language/en-GB/en-GB.plg_actionlog_joomla.ini b/administrator/language/en-GB/en-GB.plg_actionlog_joomla.ini
new file mode 100644
index 0000000000000..cc1943480ab09
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_actionlog_joomla.ini
@@ -0,0 +1,49 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_ACTIONLOG_JOOMLA="Action Log - Joomla"
+PLG_ACTIONLOG_JOOMLA_XML_DESCRIPTION="Record the actions of users on the site for Joomla core extensions so they can be reviewed if required."
+PLG_ACTIONLOG_JOOMLA_APPLICATION_SITE="site"
+PLG_ACTIONLOG_JOOMLA_APPLICATION_ADMINISTRATOR="admin"
+; Content types title
+PLG_ACTIONLOG_JOOMLA_TYPE_ACCESS_LEVEL="access level"
+PLG_ACTIONLOG_JOOMLA_TYPE_APPLICATION_CONFIG="Global Configuration"
+PLG_ACTIONLOG_JOOMLA_TYPE_ARTICLE="article"
+PLG_ACTIONLOG_JOOMLA_TYPE_BANNER="banner"
+PLG_ACTIONLOG_JOOMLA_TYPE_BANNER_CLIENT="banner client"
+PLG_ACTIONLOG_JOOMLA_TYPE_CATEGORY="category"
+PLG_ACTIONLOG_JOOMLA_TYPE_COMPONENT="component"
+PLG_ACTIONLOG_JOOMLA_TYPE_COMPONENT_CONFIG="Component Configuration"
+PLG_ACTIONLOG_JOOMLA_TYPE_CONTACT="contact"
+PLG_ACTIONLOG_JOOMLA_TYPE_FILE="file"
+PLG_ACTIONLOG_JOOMLA_TYPE_LANGUAGE="language"
+PLG_ACTIONLOG_JOOMLA_TYPE_LIBRARY="library"
+PLG_ACTIONLOG_JOOMLA_TYPE_LINK="link redirect"
+PLG_ACTIONLOG_JOOMLA_TYPE_LINK_REDIRECT="link redirect"
+PLG_ACTIONLOG_JOOMLA_TYPE_MEDIA="media"
+PLG_ACTIONLOG_JOOMLA_TYPE_MENU="menu"
+PLG_ACTIONLOG_JOOMLA_TYPE_MENU_ITEM="menu item"
+PLG_ACTIONLOG_JOOMLA_TYPE_MODULE="module"
+PLG_ACTIONLOG_JOOMLA_TYPE_NEWSFEED="newsfeed"
+PLG_ACTIONLOG_JOOMLA_TYPE_PACKAGE="package"
+PLG_ACTIONLOG_JOOMLA_TYPE_PLUGIN="plugin"
+PLG_ACTIONLOG_JOOMLA_TYPE_STYLE="template style"
+PLG_ACTIONLOG_JOOMLA_TYPE_TAG="tag"
+PLG_ACTIONLOG_JOOMLA_TYPE_TEMPLATE="template"
+PLG_ACTIONLOG_JOOMLA_TYPE_USER="user"
+PLG_ACTIONLOG_JOOMLA_USER_LOGIN_FAILED="User
{username} tried to login to {app}"
+PLG_ACTIONLOG_JOOMLA_USER_LOGGED_IN="User
{username} logged in to {app}"
+PLG_ACTIONLOG_JOOMLA_USER_LOGGED_OUT="User
{username} logged out from {app}"
+PLG_ACTIONLOG_JOOMLA_USER_REGISTERED="User
{username} registered for an account"
+PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP="user group"
+PLG_ACTIONLOG_JOOMLA_TYPE_USER_NOTE="user note"
+; Component
+PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED="User
{username} changed settings of the application configuration"
+PLG_ACTIONLOG_JOOMLA_COMPONENT_CONFIG_UPDATED="User
{username} changed settings of the component {extension_name}"
+; Extensions
+PLG_ACTIONLOG_JOOMLA_EXTENSION_INSTALLED="User
{username} installed the {type} {extension_name}"
+PLG_ACTIONLOG_JOOMLA_EXTENSION_UNINSTALLED="User
{username} uninstalled the {type} {extension_name}"
+PLG_ACTIONLOG_JOOMLA_EXTENSION_UPDATED="User
{username} updated the {type} {extension_name}"
+PLG_ACTIONLOG_JOOMLA_PLUGIN_INSTALLED="User
{username} installed the plugin
{extension_name}"
diff --git a/administrator/language/en-GB/en-GB.plg_actionlog_joomla.sys.ini b/administrator/language/en-GB/en-GB.plg_actionlog_joomla.sys.ini
new file mode 100644
index 0000000000000..df2e8d05681ae
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_actionlog_joomla.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_ACTIONLOG_JOOMLA="Action Log - Joomla"
+PLG_ACTIONLOG_JOOMLA_XML_DESCRIPTION="Record the actions of users on the site for Joomla core extensions so they can be reviewed if required."
diff --git a/administrator/language/en-GB/en-GB.plg_authentication_cookie.ini b/administrator/language/en-GB/en-GB.plg_authentication_cookie.ini
index 8d02e7fe9fbf7..114cea9dd3da1 100644
--- a/administrator/language/en-GB/en-GB.plg_authentication_cookie.ini
+++ b/administrator/language/en-GB/en-GB.plg_authentication_cookie.ini
@@ -9,5 +9,6 @@ PLG_AUTH_COOKIE_FIELD_COOKIE_LIFETIME_DESC="The number of days until the authent
PLG_AUTH_COOKIE_FIELD_COOKIE_LIFETIME_LABEL="Cookie Lifetime"
PLG_AUTH_COOKIE_FIELD_KEY_LENGTH_DESC="The length of the key to use to encrypt the cookie. Longer lengths are more secure, but they will slow performance."
PLG_AUTH_COOKIE_FIELD_KEY_LENGTH_LABEL="Key Length"
+PLG_AUTH_COOKIE_PRIVACY_CAPABILITY_COOKIE="In conjunction with a plugin which supports a \"Remember Me\" feature, such as the \"System - Remember Me\" plugin, this plugin creates a cookie on the user's client if a \"Remember Me\" checkbox is selected when logging into the website. This cookie can be identified with the prefix `joomla_remember_me` and is used to automatically log users into the website when they visit and are not already logged in."
PLG_AUTH_COOKIE_XML_DESCRIPTION="Handles Joomla's cookie User authentication.
Warning! You must have at least one other authentication plugin enabled. You will also need a plugin such as the System - Remember Me plugin to implement cookie login."
PLG_AUTHENTICATION_COOKIE="Authentication - Cookie"
diff --git a/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.ini b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.ini
index 29821c12ebe7c..8a501818501b4 100644
--- a/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.ini
+++ b/administrator/language/en-GB/en-GB.plg_captcha_recaptcha.ini
@@ -50,6 +50,8 @@ PLG_RECAPTCHA_ERROR_VERIFY_PARAMS_INCORRECT="The parameters to verify were incor
PLG_RECAPTCHA_ERROR_INVALID_REFERRER="reCAPTCHA API keys are tied to a specific domain name for security reasons."
PLG_RECAPTCHA_ERROR_RECAPTCHA_NOT_REACHABLE="Unable to contact the reCAPTCHA verify server."
+PLG_RECAPTCHA_PRIVACY_CAPABILITY_IP_ADDRESS="The reCAPTCHA plugin integrates with Google's reCAPTCHA system as a spam protection service. As part of this service, the IP of the user who is answering the captcha challenge is transmitted to Google."
+
; Uncomment(remove the ";" from the beginning of the line) the following lines if reCAPTCHA is not available in your language
; When uncommenting, do NOT translate PLG_RECAPTCHA_CUSTOM_LANG
; As of 01/01/2012, the following languages do not need translation: en, nl, fr, de, pt, ru, es, tr
diff --git a/administrator/language/en-GB/en-GB.plg_content_confirmconsent.ini b/administrator/language/en-GB/en-GB.plg_content_confirmconsent.ini
new file mode 100644
index 0000000000000..38c7f59fb893c
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_content_confirmconsent.ini
@@ -0,0 +1,11 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_CONTENT_CONFIRMCONSENT_CONSENTBOX_LABEL="Privacy Note"
+PLG_CONTENT_CONFIRMCONSENT_FIELD_ARTICLE_DESC="Select the article from the list or create a new one."
+PLG_CONTENT_CONFIRMCONSENT_FIELD_ARTICLE_LABEL="Privacy Article"
+PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DEFAULT="By submitting this form you agree to the Privacy Policy of this website and the storing of the submitted information."
+PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DESC="A summary of the site's privacy policy. If left blank then the default message will be used."
+PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_LABEL="Short Privacy Policy"
diff --git a/administrator/language/en-GB/en-GB.plg_content_confirmconsent.sys.ini b/administrator/language/en-GB/en-GB.plg_content_confirmconsent.sys.ini
new file mode 100644
index 0000000000000..ef4ab8ac9e238
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_content_confirmconsent.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_CONTENT_CONFIRMCONSENT="Content - Confirm Consent"
+PLG_CONTENT_CONFIRMCONSENT_XML_DESCRIPTION="This plugin adds a required consent checkbox to a form eg the core contact component."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_actionlogs.ini b/administrator/language/en-GB/en-GB.plg_privacy_actionlogs.ini
new file mode 100644
index 0000000000000..e6faefd882185
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_actionlogs.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_ACTIONLOGS="Privacy - Action Logs"
+PLG_PRIVACY_ACTIONLOGS_XML_DESCRIPTION="Responsible for exporting the action log data for a user's privacy request. Since the action logs are an audit log, these can not be deleted from the system."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_actionlogs.sys.ini b/administrator/language/en-GB/en-GB.plg_privacy_actionlogs.sys.ini
new file mode 100644
index 0000000000000..e6faefd882185
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_actionlogs.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_ACTIONLOGS="Privacy - Action Logs"
+PLG_PRIVACY_ACTIONLOGS_XML_DESCRIPTION="Responsible for exporting the action log data for a user's privacy request. Since the action logs are an audit log, these can not be deleted from the system."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_contact.ini b/administrator/language/en-GB/en-GB.plg_privacy_contact.ini
new file mode 100644
index 0000000000000..190cbd446351a
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_contact.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_CONTACT="Privacy - Contacts"
+PLG_PRIVACY_CONTACT_XML_DESCRIPTION="Responsible for processing privacy related requests for the core Joomla contact data."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_contact.sys.ini b/administrator/language/en-GB/en-GB.plg_privacy_contact.sys.ini
new file mode 100644
index 0000000000000..190cbd446351a
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_contact.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_CONTACT="Privacy - Contacts"
+PLG_PRIVACY_CONTACT_XML_DESCRIPTION="Responsible for processing privacy related requests for the core Joomla contact data."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_content.ini b/administrator/language/en-GB/en-GB.plg_privacy_content.ini
new file mode 100644
index 0000000000000..5d50613c7019e
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_content.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_CONTENT="Privacy - Content"
+PLG_PRIVACY_CONTENT_XML_DESCRIPTION="Responsible for processing privacy related requests for the core Joomla content data."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_content.sys.ini b/administrator/language/en-GB/en-GB.plg_privacy_content.sys.ini
new file mode 100644
index 0000000000000..5d50613c7019e
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_content.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_CONTENT="Privacy - Content"
+PLG_PRIVACY_CONTENT_XML_DESCRIPTION="Responsible for processing privacy related requests for the core Joomla content data."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_message.ini b/administrator/language/en-GB/en-GB.plg_privacy_message.ini
new file mode 100644
index 0000000000000..c67d1908f89aa
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_message.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_MESSAGE="Privacy - User Messages"
+PLG_PRIVACY_MESSAGE_XML_DESCRIPTION="Responsible for processing privacy related requests for the core Joomla user messages data."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_message.sys.ini b/administrator/language/en-GB/en-GB.plg_privacy_message.sys.ini
new file mode 100644
index 0000000000000..c67d1908f89aa
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_message.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_MESSAGE="Privacy - User Messages"
+PLG_PRIVACY_MESSAGE_XML_DESCRIPTION="Responsible for processing privacy related requests for the core Joomla user messages data."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_user.ini b/administrator/language/en-GB/en-GB.plg_privacy_user.ini
new file mode 100644
index 0000000000000..d1f733954efba
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_user.ini
@@ -0,0 +1,8 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_USER="Privacy - User Accounts"
+PLG_PRIVACY_USER_ERROR_CANNOT_REMOVE_SUPER_USER="Cannot remove a super user account."
+PLG_PRIVACY_USER_XML_DESCRIPTION="Responsible for processing privacy related requests for the core Joomla user data."
diff --git a/administrator/language/en-GB/en-GB.plg_privacy_user.sys.ini b/administrator/language/en-GB/en-GB.plg_privacy_user.sys.ini
new file mode 100644
index 0000000000000..ba043e9af9d9b
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_privacy_user.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_PRIVACY_USER="Privacy - User Accounts"
+PLG_PRIVACY_USER_XML_DESCRIPTION="Responsible for processing privacy related requests for the core Joomla user data."
diff --git a/administrator/language/en-GB/en-GB.plg_quickicon_privacycheck.ini b/administrator/language/en-GB/en-GB.plg_quickicon_privacycheck.ini
new file mode 100644
index 0000000000000..4ea2634846cfd
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_quickicon_privacycheck.ini
@@ -0,0 +1,15 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_QUICKICON_PRIVACYCHECK="Quick Icon - Joomla! Privacy Requests Notification"
+PLG_QUICKICON_PRIVACYCHECK_CHECKING="Checking requests ..."
+PLG_QUICKICON_PRIVACYCHECK_ERROR="Unknown requests ..."
+PLG_QUICKICON_PRIVACYCHECK_GROUP_DESC="The group of this plugin (this value is compared with the group value used in
Quick Icons modules to inject icons)."
+PLG_QUICKICON_PRIVACYCHECK_GROUP_LABEL="Group"
+PLG_QUICKICON_PRIVACYCHECK_REQUESTFOUND="Urgent Privacy Requests"
+PLG_QUICKICON_PRIVACYCHECK_REQUESTFOUND_BUTTON="View Requests"
+PLG_QUICKICON_PRIVACYCHECK_REQUESTFOUND_MESSAGE="Urgent Privacy Request(s) to manage."
+PLG_QUICKICON_PRIVACYCHECK_NOREQUEST="No Urgent Requests."
+PLG_QUICKICON_PRIVACYCHECK_XML_DESCRIPTION="Checks for privacy requests that need to be handled and notifies you when you visit the Control Panel page."
diff --git a/administrator/language/en-GB/en-GB.plg_quickicon_privacycheck.sys.ini b/administrator/language/en-GB/en-GB.plg_quickicon_privacycheck.sys.ini
new file mode 100644
index 0000000000000..f00ff9298b984
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_quickicon_privacycheck.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_QUICKICON_PRIVACYCHECK="Quick Icon - Joomla! Privacy Requests Notification"
+PLG_QUICKICON_PRIVACYCHECK_XML_DESCRIPTION="Checks for privacy requests that need to be handled and notifies you when you visit the Control Panel page."
diff --git a/administrator/language/en-GB/en-GB.plg_system_actionlogs.ini b/administrator/language/en-GB/en-GB.plg_system_actionlogs.ini
new file mode 100644
index 0000000000000..cd8d760f59c94
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_system_actionlogs.ini
@@ -0,0 +1,21 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_SYSTEM_ACTIONLOGS="System - User Actions Log"
+PLG_SYSTEM_ACTIONLOGS_EXTENSIONS_NOTIFICATIONS="Select events to be notified for"
+PLG_SYSTEM_ACTIONLOGS_EXTENSIONS_NOTIFICATIONS_DESC="Select events to be sent to your email as notifications"
+PLG_SYSTEM_ACTIONLOGS_LOG_DELETE_PERIOD="Days to delete logs after"
+PLG_SYSTEM_ACTIONLOGS_LOG_DELETE_PERIOD_DESC="Enter how many days logs should be kept before they are deleted. Enter 0 if you don't want to delete the logs."
+PLG_SYSTEM_ACTIONLOGS_NOTIFICATIONS="Send notifications for User Actions Log"
+PLG_SYSTEM_ACTIONLOGS_NOTIFICATIONS_DESC="Send a notifications of users' actions log to your email"
+PLG_SYSTEM_ACTIONLOGS_OPTIONS="User Actions Log Options"
+PLG_SYSTEM_ACTIONLOGS_XML_DESCRIPTION="Record the actions of users on the site so they can be reviewed if required."
+; Common content type log messages
+PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED="User
{username} added new {type}
{title}"
+PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED="User
{username} updated the {type}
{title}"
+PLG_SYSTEM_ACTIONLOGS_CONTENT_PUBLISHED="User
{username} published the {type}
{title}"
+PLG_SYSTEM_ACTIONLOGS_CONTENT_UNPUBLISHED="User
{username} unpublished the {type}
{title}"
+PLG_SYSTEM_ACTIONLOGS_CONTENT_TRASHED="User
{username} trashed the {type}
{title}"
+PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED="User
{username} deleted the {type} {title}"
diff --git a/administrator/language/en-GB/en-GB.plg_system_actionlogs.sys.ini b/administrator/language/en-GB/en-GB.plg_system_actionlogs.sys.ini
new file mode 100644
index 0000000000000..d7a6d3ac86077
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_system_actionlogs.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_SYSTEM_ACTIONLOGS="System - Actions Log"
+PLG_SYSTEM_ACTIONLOGS_XML_DESCRIPTION="To record actions of users within the CMS, to know who to blame when something wrong happens."
diff --git a/administrator/language/en-GB/en-GB.plg_system_languagefilter.ini b/administrator/language/en-GB/en-GB.plg_system_languagefilter.ini
index 9d957af004674..bd4c481bad64e 100644
--- a/administrator/language/en-GB/en-GB.plg_system_languagefilter.ini
+++ b/administrator/language/en-GB/en-GB.plg_system_languagefilter.ini
@@ -24,5 +24,6 @@ PLG_SYSTEM_LANGUAGEFILTER_FIELD_REMOVE_DEFAULT_PREFIX_DESC="Remove the defined U
PLG_SYSTEM_LANGUAGEFILTER_FIELD_REMOVE_DEFAULT_PREFIX_LABEL="Remove URL Language Code"
PLG_SYSTEM_LANGUAGEFILTER_OPTION_SESSION="Session"
PLG_SYSTEM_LANGUAGEFILTER_OPTION_YEAR="Year"
+PLG_SYSTEM_LANGUAGEFILTER_PRIVACY_CAPABILITY_LANGUAGE_COOKIE="On a site which supports multiple languages, this plugin can be configured to set a cookie on the user's browser which remembers their language preference. This cookie is used to redirect users to their preferred language when visiting the site and creating a new session. The cookie's name is based on a randomly generated hash and therefore does not have a constant identifier."
PLG_SYSTEM_LANGUAGEFILTER_SITE_LANGUAGE="Site Language"
PLG_SYSTEM_LANGUAGEFILTER_XML_DESCRIPTION="This plugin filters the displayed content depending on language.
This plugin is to be enabled only when the Language Switcher module is published.If this plugin is activated, it is recommended to also publish the Administrator multilingual status module."
diff --git a/administrator/language/en-GB/en-GB.plg_system_logrotation.ini b/administrator/language/en-GB/en-GB.plg_system_logrotation.ini
new file mode 100644
index 0000000000000..d25b74b27274c
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_system_logrotation.ini
@@ -0,0 +1,11 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_SYSTEM_LOGROTATION="System - Log Rotation"
+PLG_SYSTEM_LOGROTATION_XML_DESCRIPTION="This plugin periodically rotates system log files."
+PLG_SYSTEM_LOGROTATION_CACHETIMEOUT_LABEL="Log Rotation (in days)"
+PLG_SYSTEM_LOGROTATION_CACHETIMEOUT_DESC="How often should the logs be rotated."
+PLG_SYSTEM_LOGROTATION_LOGSTOKEEP_DESC="The maximum number of old logs to keep."
+PLG_SYSTEM_LOGROTATION_LOGSTOKEEP_LABEL="Maximum Logs"
diff --git a/administrator/language/en-GB/en-GB.plg_system_logrotation.sys.ini b/administrator/language/en-GB/en-GB.plg_system_logrotation.sys.ini
new file mode 100644
index 0000000000000..c03ea875d9b6d
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_system_logrotation.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_SYSTEM_LOGROTATION="System - Log Rotation"
+PLG_SYSTEM_LOGROTATION_XML_DESCRIPTION="This plugin periodically rotates system log files."
diff --git a/administrator/language/en-GB/en-GB.plg_system_privacyconsent.ini b/administrator/language/en-GB/en-GB.plg_system_privacyconsent.ini
new file mode 100644
index 0000000000000..74da392cafd19
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_system_privacyconsent.ini
@@ -0,0 +1,42 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_SYSTEM_PRIVACYCONSENT="System - Privacy Consent"
+PLG_SYSTEM_PRIVACYCONSENT_BODY="
The user consented to storing their user information using the IP address %s
The user agent string of the user's browser was:
%s
This information was automatically recorded when the user submitted their details on the web site and checked the confirm box
"
+PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_DESC="How often the check is performed"
+PLG_SYSTEM_PRIVACYCONSENT_CACHETIMEOUT_LABEL="Periodic check (days)"
+PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_DESC="Number of days after which the privacy consent shall expire."
+PLG_SYSTEM_PRIVACYCONSENT_CONSENTEXPIRATION_LABEL="Expiration"
+; You can use the following merge codes for the EMAIL strings:
+; [SITENAME] Site name, as set in Global Configuration.
+; [URL] URL of the site's frontend page.
+; [TOKENURL] URL of the remind page with the token prefilled.
+; [FORMURL] URL of the remind page where the user can paste their token.
+; [TOKEN] The remind token.
+; \n Newline character. Use it to start a new line in the email.
+PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_BODY="Your Privacy Consent given at [URL] will expire in few days, you can renew the privacy consent for this website.\n\nIn order to do this, you can complete one of the following tasks:\n\n1. Visit the following URL: [TOKENURL]\n\n2. Copy your token from this email, visit the referenced URL, and paste your token into the form.\nURL: [FORMURL]\nToken: [TOKEN]\n\nPlease note that this token is only valid for this account."
+PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT="Privacy Consent at [SITENAME]"
+PLG_SYSTEM_PRIVACYCONSENT_EXPIRATION_FIELDSET_LABEL="Expiration"
+PLG_SYSTEM_PRIVACYCONSENT_FIELD_ARTICLE_DESC="Select the article from the list or create a new one."
+PLG_SYSTEM_PRIVACYCONSENT_FIELD_ARTICLE_LABEL="Privacy Article"
+PLG_SYSTEM_PRIVACYCONSENT_FIELD_DESC="Read the full privacy policy"
+PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_DESC="When enabled it performs checks for consent expiration"
+PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_LABEL="Enable"
+PLG_SYSTEM_PRIVACYCONSENT_FIELD_ERROR="Agreement to the site's Privacy Policy is required."
+PLG_SYSTEM_PRIVACYCONSENT_FIELD_LABEL="Privacy Policy"
+PLG_SYSTEM_PRIVACYCONSENT_LABEL="Web Site Privacy"
+PLG_SYSTEM_PRIVACYCONSENT_NOTE_FIELD_DEFAULT="By signing up to this web site and agreeing to the Privacy Policy you agree to this web site storing your information."
+PLG_SYSTEM_PRIVACYCONSENT_NOTE_FIELD_DESC="A summary of the site's privacy policy. If left blank then the default message will be used."
+PLG_SYSTEM_PRIVACYCONSENT_NOTE_FIELD_LABEL="Short Privacy Policy"
+PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_SUBJECT="Privacy Consent Expired"
+PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_MESSAGE="Privacy consent has expired for %1$s."
+PLG_SYSTEM_PRIVACYCONSENT_OPTION_AGREE="I agree"
+PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_DEFAULT="Please confirm that you consent to this web site storing your information by agreeing to the privacy policy."
+PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_DESC="Custom message to be displayed on redirect. If left blank then the default message will be used."
+PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_LABEL="Redirect Message"
+PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_DESC="Number of days to send a reminder before the expiration of the privacy consent."
+PLG_SYSTEM_PRIVACYCONSENT_REMINDBEFORE_LABEL="Remind"
+PLG_SYSTEM_PRIVACYCONSENT_SUBJECT="Privacy Policy"
+PLG_SYSTEM_PRIVACYCONSENT_XML_DESCRIPTION="Basic plugin to request user's consent to the site's privacy policy. Existing users who have not consented yet will be redirected on login to update their profile."
diff --git a/administrator/language/en-GB/en-GB.plg_system_privacyconsent.sys.ini b/administrator/language/en-GB/en-GB.plg_system_privacyconsent.sys.ini
new file mode 100644
index 0000000000000..9e5e187496742
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_system_privacyconsent.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_SYSTEM_PRIVACYCONSENT="System - Privacy Consent"
+PLG_SYSTEM_PRIVACYCONSENT_XML_DESCRIPTION="Basic plugin to request user's consent to the site's privacy policy. Existing users who have not consented yet will be redirected on login to update their profile."
\ No newline at end of file
diff --git a/administrator/language/en-GB/en-GB.plg_user_terms.ini b/administrator/language/en-GB/en-GB.plg_user_terms.ini
new file mode 100644
index 0000000000000..7ddb767a6fed8
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_user_terms.ini
@@ -0,0 +1,19 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_USER_TERMS="User - Terms and Conditions"
+PLG_USER_TERMS_FIELD_ARTICLE_DESC="Select the article from the list or create a new one."
+PLG_USER_TERMS_FIELD_ARTICLE_LABEL="Terms & Conditions Article"
+PLG_USER_TERMS_FIELD_DESC="Read the full terms and conditions."
+PLG_USER_TERMS_FIELD_ERROR="Agreement to the site's Terms & Conditions is required."
+PLG_USER_TERMS_FIELD_LABEL="Terms & Conditions"
+PLG_USER_TERMS_LABEL="Terms & Conditions"
+PLG_USER_TERMS_LOGGING_CONSENT_TO_TERMS="User
{username} consented to the terms and conditions during registration."
+PLG_USER_TERMS_NOTE_FIELD_DEFAULT="By signing up to this web site you accept the Terms & Conditions."
+PLG_USER_TERMS_NOTE_FIELD_DESC="A summary of the site's terms & conditions. If left blank then the default message will be used."
+PLG_USER_TERMS_NOTE_FIELD_LABEL="Short Terms & Conditions"
+PLG_USER_TERMS_OPTION_AGREE="I agree"
+PLG_USER_TERMS_SUBJECT="Privacy Policy"
+PLG_USER_TERMS_XML_DESCRIPTION="Basic plugin to request user's consent to the site's terms and conditions."
diff --git a/administrator/language/en-GB/en-GB.plg_user_terms.sys.ini b/administrator/language/en-GB/en-GB.plg_user_terms.sys.ini
new file mode 100644
index 0000000000000..334230cb3885f
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_user_terms.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_USER_TERMS="User - Terms and Conditions"
+PLG_USER_TERMS_XML_DESCRIPTION="Basic plugin to request user's consent to the site's terms and conditions."
\ No newline at end of file
diff --git a/administrator/modules/mod_latestactions/helper.php b/administrator/modules/mod_latestactions/helper.php
new file mode 100644
index 0000000000000..8f2fce6a095eb
--- /dev/null
+++ b/administrator/modules/mod_latestactions/helper.php
@@ -0,0 +1,52 @@
+ true));
+
+ // Set the Start and Limit
+ $model->setState('list.start', 0);
+ $model->setState('list.limit', $params->get('count', 5));
+ $model->setState('list.ordering', 'a.id');
+ $model->setState('list.direction', 'DESC');
+
+ $rows = $model->getItems();
+
+ // Load all actionlog plugins language files
+ ActionlogsHelper::loadActionLogPluginsLanguage();
+
+ foreach ($rows as $row)
+ {
+ $row->message = ActionlogsHelper::getHumanReadableLogMessage($row);
+ }
+
+ return $rows;
+ }
+}
diff --git a/administrator/modules/mod_latestactions/mod_latestactions.php b/administrator/modules/mod_latestactions/mod_latestactions.php
new file mode 100644
index 0000000000000..b198b637e7820
--- /dev/null
+++ b/administrator/modules/mod_latestactions/mod_latestactions.php
@@ -0,0 +1,22 @@
+get('automatic_title', 0))
+{
+ $module->title = ModLatestHelper::getTitle($params);
+}
+
+require JModuleHelper::getLayoutPath('mod_latestactions', $params->get('layout', 'default'));
diff --git a/administrator/modules/mod_latestactions/mod_latestactions.xml b/administrator/modules/mod_latestactions/mod_latestactions.xml
new file mode 100644
index 0000000000000..708aee6b32aa5
--- /dev/null
+++ b/administrator/modules/mod_latestactions/mod_latestactions.xml
@@ -0,0 +1,94 @@
+
+
+ mod_latestactions
+ Joomla! Project
+ May 2018
+ Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ MOD_LATESTACTIONS_XML_DESCRIPTION
+
+ mod_latestactions.php
+ helper.php
+ tmpl
+
+
+ en-GB.mod_latestactions.ini
+ en-GB.mod_latestactions.sys.ini
+
+
+
+
+
+
+
+
+
diff --git a/administrator/modules/mod_latestactions/tmpl/default.php b/administrator/modules/mod_latestactions/tmpl/default.php
new file mode 100644
index 0000000000000..31e684ac936d1
--- /dev/null
+++ b/administrator/modules/mod_latestactions/tmpl/default.php
@@ -0,0 +1,35 @@
+
+
+
+ $item) : ?>
+
+
+ message; ?>
+
+
+
+ log_date, JText::_('DATE_FORMAT_LC5')); ?>
+
+
+
+
+
+
+
+
diff --git a/administrator/modules/mod_menu/menu.php b/administrator/modules/mod_menu/menu.php
index 882ee939227e2..108433068fb9e 100644
--- a/administrator/modules/mod_menu/menu.php
+++ b/administrator/modules/mod_menu/menu.php
@@ -314,7 +314,8 @@ protected function preprocess($items)
list($assetName) = isset($query['context']) ? explode('.', $query['context'], 2) : array('com_fields');
}
- elseif ($item->element === 'com_config' && !$user->authorise('core.admin'))
+ // Special case for components which only allow super user access
+ elseif (in_array($item->element, array('com_config', 'com_privacy', 'com_actionlogs'), true) && !$user->authorise('core.admin'))
{
continue;
}
diff --git a/administrator/modules/mod_privacy_dashboard/helper.php b/administrator/modules/mod_privacy_dashboard/helper.php
new file mode 100644
index 0000000000000..48d550bf13b8e
--- /dev/null
+++ b/administrator/modules/mod_privacy_dashboard/helper.php
@@ -0,0 +1,42 @@
+getRequestCounts();
+ }
+ catch (JDatabaseException $e)
+ {
+ return array();
+ }
+ }
+}
diff --git a/administrator/modules/mod_privacy_dashboard/mod_privacy_dashboard.php b/administrator/modules/mod_privacy_dashboard/mod_privacy_dashboard.php
new file mode 100644
index 0000000000000..58b1d8f1057dd
--- /dev/null
+++ b/administrator/modules/mod_privacy_dashboard/mod_privacy_dashboard.php
@@ -0,0 +1,24 @@
+load('com_privacy', JPATH_ADMINISTRATOR, null, false, true)
+ || $lang->load('com_privacy', JPATH_ADMINISTRATOR . '/components/com_privacy', null, false, true);
+
+JHtml::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/html');
+
+JLoader::register('ModPrivacyDashboardHelper', __DIR__ . '/helper.php');
+
+$list = ModPrivacyDashboardHelper::getData();
+$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx'), ENT_COMPAT, 'UTF-8');
+
+require JModuleHelper::getLayoutPath('mod_privacy_dashboard', $params->get('layout', 'default'));
diff --git a/administrator/modules/mod_privacy_dashboard/mod_privacy_dashboard.xml b/administrator/modules/mod_privacy_dashboard/mod_privacy_dashboard.xml
new file mode 100644
index 0000000000000..0075c4777b9c8
--- /dev/null
+++ b/administrator/modules/mod_privacy_dashboard/mod_privacy_dashboard.xml
@@ -0,0 +1,73 @@
+
+
+ mod_privacy_dashboard
+ Joomla! Project
+ June 2018
+ Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ MOD_PRIVACY_DASHBOARD_XML_DESCRIPTION
+
+ mod_privacy_dashboard.php
+ tmpl
+ helper.php
+
+
+ en-GB.mod_privacy_dashboard.ini
+ en-GB.mod_privacy_dashboard.sys.ini
+
+
+
+
+
+
+
+
+
diff --git a/administrator/modules/mod_privacy_dashboard/tmpl/default.php b/administrator/modules/mod_privacy_dashboard/tmpl/default.php
new file mode 100644
index 0000000000000..b1258b7cb016a
--- /dev/null
+++ b/administrator/modules/mod_privacy_dashboard/tmpl/default.php
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
status); ?>
+
count; ?>
+
+ status, array(0, 1))) : ?>
+ count; ?>
+
+ count; ?>
+
+
+
+
+
+
diff --git a/build/helpTOC.php b/build/helpTOC.php
index 5ef5744a606a5..725e74b59fe8c 100644
--- a/build/helpTOC.php
+++ b/build/helpTOC.php
@@ -59,7 +59,7 @@ public function doExecute()
{
// Get the version data for the script
$minorVersion = Version::MAJOR_VERSION . '.' . Version::MINOR_VERSION;
- $namespace = 'Help' . $minorVersion . ':';
+ $namespace = 'Help' . str_replace('.', '', $minorVersion) . ':';
// Set up options for JMediawiki
$options = new Registry;
diff --git a/components/com_privacy/controller.php b/components/com_privacy/controller.php
new file mode 100644
index 0000000000000..bd5d6bfb55015
--- /dev/null
+++ b/components/com_privacy/controller.php
@@ -0,0 +1,43 @@
+input->get('view', $this->default_view);
+
+ // Submitting information requests through the frontend is restricted to authenticated users at this time
+ if ($view === 'request' && JFactory::getUser()->guest)
+ {
+ $this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));
+
+ return $this;
+ }
+
+ return parent::display($cachable, $urlparams);
+ }
+}
diff --git a/components/com_privacy/controllers/request.php b/components/com_privacy/controllers/request.php
new file mode 100644
index 0000000000000..9f31e90a24435
--- /dev/null
+++ b/components/com_privacy/controllers/request.php
@@ -0,0 +1,180 @@
+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 __DEPLOY_VERSION__
+ */
+ 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 __DEPLOY_VERSION__
+ */
+ 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;
+ }
+ }
+}
diff --git a/components/com_privacy/models/confirm.php b/components/com_privacy/models/confirm.php
new file mode 100644
index 0000000000000..48399cbdea5d4
--- /dev/null
+++ b/components/com_privacy/models/confirm.php
@@ -0,0 +1,220 @@
+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;
+ }
+
+ // 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;
+
+ 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,
+ )
+ );
+
+ 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 __DEPLOY_VERSION__
+ */
+ 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 __DEPLOY_VERSION__
+ * @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 __DEPLOY_VERSION__
+ */
+ protected function populateState()
+ {
+ // Get the application object.
+ $params = JFactory::getApplication()->getParams('com_privacy');
+
+ // Load the parameters.
+ $this->setState('params', $params);
+ }
+}
diff --git a/components/com_privacy/models/forms/confirm.xml b/components/com_privacy/models/forms/confirm.xml
new file mode 100644
index 0000000000000..6113c06056b4d
--- /dev/null
+++ b/components/com_privacy/models/forms/confirm.xml
@@ -0,0 +1,24 @@
+
+
diff --git a/components/com_privacy/models/forms/remind.xml b/components/com_privacy/models/forms/remind.xml
new file mode 100644
index 0000000000000..f97926394bdfc
--- /dev/null
+++ b/components/com_privacy/models/forms/remind.xml
@@ -0,0 +1,24 @@
+
+
diff --git a/components/com_privacy/models/forms/request.xml b/components/com_privacy/models/forms/request.xml
new file mode 100644
index 0000000000000..195e7c79e3c1b
--- /dev/null
+++ b/components/com_privacy/models/forms/request.xml
@@ -0,0 +1,27 @@
+
+
diff --git a/components/com_privacy/models/remind.php b/components/com_privacy/models/remind.php
new file mode 100644
index 0000000000000..e7aeb3ee98e3d
--- /dev/null
+++ b/components/com_privacy/models/remind.php
@@ -0,0 +1,183 @@
+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 __DEPLOY_VERSION__
+ */
+ 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 __DEPLOY_VERSION__
+ * @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 __DEPLOY_VERSION__
+ */
+ protected function populateState()
+ {
+ // Get the application object.
+ $params = JFactory::getApplication()->getParams('com_privacy');
+
+ // Load the parameters.
+ $this->setState('params', $params);
+ }
+}
diff --git a/components/com_privacy/models/request.php b/components/com_privacy/models/request.php
new file mode 100644
index 0000000000000..5c40aa4ce5352
--- /dev/null
+++ b/components/com_privacy/models/request.php
@@ -0,0 +1,269 @@
+get('mailonline', 1))
+ {
+ $this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED'));
+
+ return false;
+ }
+
+ // 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;
+ }
+
+ // 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 ? 1 : -1;
+
+ $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),
+ '[FORMURL]' => JRoute::link('site', 'index.php?option=com_privacy&view=confirm', false, $linkMode),
+ '[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 __DEPLOY_VERSION__
+ */
+ 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 __DEPLOY_VERSION__
+ * @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 __DEPLOY_VERSION__
+ */
+ protected function populateState()
+ {
+ // Get the application object.
+ $params = JFactory::getApplication()->getParams('com_privacy');
+
+ // Load the parameters.
+ $this->setState('params', $params);
+ }
+}
diff --git a/components/com_privacy/privacy.php b/components/com_privacy/privacy.php
new file mode 100644
index 0000000000000..48eb01941972c
--- /dev/null
+++ b/components/com_privacy/privacy.php
@@ -0,0 +1,14 @@
+execute(JFactory::getApplication()->input->get('task'));
+$controller->redirect();
diff --git a/components/com_privacy/router.php b/components/com_privacy/router.php
new file mode 100644
index 0000000000000..f445ff44ca4f6
--- /dev/null
+++ b/components/com_privacy/router.php
@@ -0,0 +1,78 @@
+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 proxys for the new router interface
+ * for old SEF extensions.
+ *
+ * @param array &$query REQUEST query
+ *
+ * @return array Segments of the SEF url
+ *
+ * @since __DEPLOY_VERSION__
+ * @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 __DEPLOY_VERSION__
+ * @deprecated 4.0 Use Class based routers instead
+ */
+function privacyParseRoute($segments)
+{
+ $app = JFactory::getApplication();
+ $router = new PrivacyRouter($app, $app->getMenu());
+
+ return $router->parse($segments);
+}
diff --git a/components/com_privacy/views/confirm/tmpl/default.php b/components/com_privacy/views/confirm/tmpl/default.php
new file mode 100644
index 0000000000000..8cbf6e703037b
--- /dev/null
+++ b/components/com_privacy/views/confirm/tmpl/default.php
@@ -0,0 +1,44 @@
+
+
+ params->get('show_page_heading')) : ?>
+
+
+
+
diff --git a/components/com_privacy/views/confirm/tmpl/default.xml b/components/com_privacy/views/confirm/tmpl/default.xml
new file mode 100644
index 0000000000000..e25592846aa3f
--- /dev/null
+++ b/components/com_privacy/views/confirm/tmpl/default.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/com_privacy/views/confirm/view.html.php b/components/com_privacy/views/confirm/view.html.php
new file mode 100644
index 0000000000000..3a8a38105fd13
--- /dev/null
+++ b/components/com_privacy/views/confirm/view.html.php
@@ -0,0 +1,143 @@
+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 __DEPLOY_VERSION__
+ */
+ 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'));
+ }
+ }
+}
diff --git a/components/com_privacy/views/remind/tmpl/default.php b/components/com_privacy/views/remind/tmpl/default.php
new file mode 100644
index 0000000000000..a438c89616713
--- /dev/null
+++ b/components/com_privacy/views/remind/tmpl/default.php
@@ -0,0 +1,44 @@
+
+
+ params->get('show_page_heading')) : ?>
+
+
+
+
diff --git a/components/com_privacy/views/remind/tmpl/default.xml b/components/com_privacy/views/remind/tmpl/default.xml
new file mode 100644
index 0000000000000..9b0e5b83a7f67
--- /dev/null
+++ b/components/com_privacy/views/remind/tmpl/default.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/com_privacy/views/remind/view.html.php b/components/com_privacy/views/remind/view.html.php
new file mode 100644
index 0000000000000..2fbd63a0892fa
--- /dev/null
+++ b/components/com_privacy/views/remind/view.html.php
@@ -0,0 +1,143 @@
+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 __DEPLOY_VERSION__
+ */
+ 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'));
+ }
+ }
+}
diff --git a/components/com_privacy/views/request/tmpl/default.php b/components/com_privacy/views/request/tmpl/default.php
new file mode 100644
index 0000000000000..8eb9a1bbb256f
--- /dev/null
+++ b/components/com_privacy/views/request/tmpl/default.php
@@ -0,0 +1,51 @@
+
+
+ params->get('show_page_heading')) : ?>
+
+
+ sendMailEnabled) : ?>
+
+
+
+
+
diff --git a/components/com_privacy/views/request/tmpl/default.xml b/components/com_privacy/views/request/tmpl/default.xml
new file mode 100644
index 0000000000000..b4d2efda6551d
--- /dev/null
+++ b/components/com_privacy/views/request/tmpl/default.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
diff --git a/components/com_privacy/views/request/view.html.php b/components/com_privacy/views/request/view.html.php
new file mode 100644
index 0000000000000..df35c1341f307
--- /dev/null
+++ b/components/com_privacy/views/request/view.html.php
@@ -0,0 +1,152 @@
+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 __DEPLOY_VERSION__
+ */
+ 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'));
+ }
+ }
+}
diff --git a/installation/sql/mysql/joomla.sql b/installation/sql/mysql/joomla.sql
index a8ac578924e05..57c8e9227fe9f 100644
--- a/installation/sql/mysql/joomla.sql
+++ b/installation/sql/mysql/joomla.sql
@@ -31,7 +31,7 @@ CREATE TABLE IF NOT EXISTS `#__assets` (
--
INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `title`, `rules`) VALUES
-(1, 0, 0, 105, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 113, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -48,25 +48,25 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl
(15, 1, 33, 34, 1, 'com_media', 'com_media', '{"core.admin":{"7":1},"core.manage":{"6":1},"core.create":{"3":1},"core.delete":{"5":1}}'),
(16, 1, 35, 38, 1, 'com_menus', 'com_menus', '{"core.admin":{"7":1}}'),
(17, 1, 39, 40, 1, 'com_messages', 'com_messages', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
-(18, 1, 41, 74, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'),
-(19, 1, 75, 78, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
-(20, 1, 79, 80, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'),
-(21, 1, 81, 82, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'),
-(22, 1, 83, 84, 1, 'com_search', 'com_search', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
-(23, 1, 85, 86, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'),
-(24, 1, 87, 90, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'),
-(26, 1, 91, 92, 1, 'com_wrapper', 'com_wrapper', '{}'),
+(18, 1, 41, 78, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'),
+(19, 1, 79, 82, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
+(20, 1, 83, 84, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'),
+(21, 1, 85, 86, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'),
+(22, 1, 87, 88, 1, 'com_search', 'com_search', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
+(23, 1, 89, 90, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'),
+(24, 1, 91, 94, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'),
+(26, 1, 95, 96, 1, 'com_wrapper', 'com_wrapper', '{}'),
(27, 8, 18, 19, 2, 'com_content.category.2', 'Uncategorised', '{}'),
(28, 3, 4, 5, 2, 'com_banners.category.3', 'Uncategorised', '{}'),
(29, 7, 14, 15, 2, 'com_contact.category.4', 'Uncategorised', '{}'),
-(30, 19, 76, 77, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'),
-(32, 24, 88, 89, 2, 'com_users.category.7', 'Uncategorised', '{}'),
-(33, 1, 93, 94, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
-(34, 1, 95, 96, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'),
-(35, 1, 97, 98, 1, 'com_tags', 'com_tags', '{}'),
-(36, 1, 99, 100, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
-(37, 1, 101, 102, 1, 'com_ajax', 'com_ajax', '{}'),
-(38, 1, 103, 104, 1, 'com_postinstall', 'com_postinstall', '{}'),
+(30, 19, 80, 81, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'),
+(32, 24, 92, 93, 2, 'com_users.category.7', 'Uncategorised', '{}'),
+(33, 1, 97, 98, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
+(34, 1, 99, 100, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'),
+(35, 1, 101, 102, 1, 'com_tags', 'com_tags', '{}'),
+(36, 1, 103, 104, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
+(37, 1, 105, 106, 1, 'com_ajax', 'com_ajax', '{}'),
+(38, 1, 107, 108, 1, 'com_postinstall', 'com_postinstall', '{}'),
(39, 18, 42, 43, 2, 'com_modules.module.1', 'Main Menu', '{}'),
(40, 18, 44, 45, 2, 'com_modules.module.2', 'Login', '{}'),
(41, 18, 46, 47, 2, 'com_modules.module.3', 'Popular Articles', '{}'),
@@ -83,7 +83,12 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl
(52, 18, 68, 69, 2, 'com_modules.module.79', 'Multilanguage status', '{}'),
(53, 18, 70, 71, 2, 'com_modules.module.86', 'Joomla Version', '{}'),
(54, 16, 36, 37, 2, 'com_menus.menu.1', 'Main Menu', '{}'),
-(55, 18, 72, 73, 2, 'com_modules.module.87', 'Sample Data', '{}');
+(55, 18, 72, 73, 2, 'com_modules.module.87', 'Sample Data', '{}'),
+(56, 1, 109, 110, 1, 'com_privacy', 'com_privacy', '{}'),
+(57, 1, 111, 112, 1, 'com_actionlogs', 'com_actionlogs', '{}'),
+(58, 18, 74, 75, 2, 'com_modules.module.88', 'Latest Actions', '{}'),
+(59, 18, 76, 77, 2, 'com_modules.module.89', 'Privacy Dashboard', '{}');
+
-- --------------------------------------------------------
@@ -520,6 +525,8 @@ INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `elem
(32, 0, 'com_postinstall', 'component', 'com_postinstall', '', 1, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(33, 0, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(34, 0, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(35, 0, 'com_privacy', 'component', 'com_privacy', '', 1, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(36, 0, 'com_actionlogs', 'component', 'com_actionlogs', '', 1, 1, 1, 1, '', '{"ip_logging":0,"csv_delimiter":",","loggable_extensions":["com_banners","com_cache","com_categories","com_config","com_contact","com_content","com_installer","com_media","com_menus","com_messages","com_modules","com_newsfeeds","com_plugins","com_redirect","com_tags","com_templates","com_users"]}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(102, 0, 'phputf8', 'library', 'phputf8', '', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(103, 0, 'Joomla! Platform', 'library', 'joomla', '', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(104, 0, 'IDNA Convert', 'library', 'idna_convert', '', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
@@ -566,6 +573,8 @@ INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `elem
(316, 0, 'mod_tags_popular', 'module', 'mod_tags_popular', '', 0, 1, 1, 0, '', '{"maximum":"5","timeframe":"alltime","owncache":"1"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(317, 0, 'mod_tags_similar', 'module', 'mod_tags_similar', '', 0, 1, 1, 0, '', '{"maximum":"5","matchtype":"any","owncache":"1"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(318, 0, 'mod_sampledata', 'module', 'mod_sampledata', '', 1, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(319, 0, 'mod_latestactions', 'module', 'mod_latestactions', '', 1, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(320, 0, 'mod_privacy_dashboard', 'module', 'mod_privacy_dashboard', '', 1, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(400, 0, 'plg_authentication_gmail', 'plugin', 'gmail', 'authentication', 0, 0, 1, 0, '', '{"applysuffix":"0","suffix":"","verifypeer":"1","user_blacklist":""}', '', '', 0, '0000-00-00 00:00:00', 1, 0),
(401, 0, 'plg_authentication_joomla', 'plugin', 'joomla', 'authentication', 0, 1, 1, 1, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(402, 0, 'plg_authentication_ldap', 'plugin', 'ldap', 'authentication', 0, 0, 1, 0, '', '{"host":"","port":"389","use_ldapV3":"0","negotiate_tls":"0","no_referrals":"0","auth_method":"bind","base_dn":"","search_string":"","users_dn":"","username":"admin","password":"bobby7","ldap_fullname":"fullName","ldap_email":"mail","ldap_uid":"uid"}', '', '', 0, '0000-00-00 00:00:00', 3, 0),
@@ -645,6 +654,18 @@ INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `elem
(479, 0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(480, 0, 'plg_system_sessiongc', 'plugin', 'sessiongc', 'system', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(481, 0, 'plg_fields_repeatable', 'plugin', 'repeatable', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(482, 0, 'plg_content_confirmconsent', 'plugin', 'confirmconsent', 'content', 0, 0, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(483, 0, 'plg_system_actionlogs', 'plugin', 'actionlogs', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(484, 0, 'plg_actionlog_joomla', 'plugin', 'joomla', 'actionlog', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(485, 0, 'plg_system_privacyconsent', 'plugin', 'privacyconsent', 'system', 0, 0, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(486, 0, 'plg_system_logrotation', 'plugin', 'logrotation', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(487, 0, 'plg_privacy_user', 'plugin', 'user', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(488, 0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(489, 0, 'plg_user_terms', 'plugin', 'terms', 'user', 0, 0, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(490, 0, 'plg_privacy_contact', 'plugin', 'contact', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(491, 0, 'plg_privacy_content', 'plugin', 'content', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(492, 0, 'plg_privacy_message', 'plugin', 'message', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
+(493, 0, 'plg_privacy_actionlogs', 'plugin', 'actionlogs', 'privacy', 0, 0, 1, 0, '', '{}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(503, 0, 'beez3', 'template', 'beez3', '', 0, 1, 1, 0, '', '{"wrapperSmall":"53","wrapperLarge":"72","sitetitle":"","sitedescription":"","navposition":"center","templatecolor":"nature"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(504, 0, 'hathor', 'template', 'hathor', '', 1, 1, 1, 0, '', '{"showSiteName":"0","colourChoice":"0","boldText":"0"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
(506, 0, 'protostar', 'template', 'protostar', '', 0, 1, 1, 0, '', '{"templateColor":"","logoFile":"","googleFont":"1","googleFontName":"Open+Sans","fluidContainer":"0"}', '', '', 0, '0000-00-00 00:00:00', 0, 0),
@@ -1512,7 +1533,9 @@ INSERT INTO `#__modules` (`id`, `asset_id`, `title`, `note`, `content`, `orderin
(17, 51, 'Breadcrumbs', '', '', 1, 'position-2', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_breadcrumbs', 1, 1, '{"moduleclass_sfx":"","showHome":"1","homeText":"","showComponent":"1","separator":"","cache":"0","cache_time":"0","cachemode":"itemid"}', 0, '*'),
(79, 52, 'Multilanguage status', '', '', 1, 'status', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 0, 'mod_multilangstatus', 3, 1, '{"layout":"_:default","moduleclass_sfx":"","cache":"0"}', 1, '*'),
(86, 53, 'Joomla Version', '', '', 1, 'footer', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_version', 3, 1, '{"format":"short","product":"1","layout":"_:default","moduleclass_sfx":"","cache":"0"}', 1, '*'),
-(87, 55, 'Sample Data', '', '', 0, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_sampledata', 6, 1, '{}', 1, '*');
+(87, 55, 'Sample Data', '', '', 0, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_sampledata', 6, 1, '{}', 1, '*'),
+(88, 58, 'Latest Actions', '', '', 0, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*'),
+(89, 59, 'Privacy Dashboard', '', '', 0, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_privacy_dashboard', 6, 1, '{}', 1, '*');
-- --------------------------------------------------------
@@ -1548,7 +1571,9 @@ INSERT INTO `#__modules_menu` (`moduleid`, `menuid`) VALUES
(17, 0),
(79, 0),
(86, 0),
-(87, 0);
+(87, 0),
+(88, 0),
+(89, 0);
-- --------------------------------------------------------
@@ -1646,7 +1671,41 @@ INSERT INTO `#__postinstall_messages` (`extension_id`, `title_key`, `description
(700, 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_BODY', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_ACTION', 'plg_system_updatenotification', 1, 'action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_condition', '3.6.3', 1),
(700, 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_TITLE', 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/joomla40checks.php', 'admin_postinstall_joomla40checks_condition', '3.7.0', 1),
(700, 'TPL_HATHOR_MESSAGE_POSTINSTALL_TITLE', 'TPL_HATHOR_MESSAGE_POSTINSTALL_BODY', 'TPL_HATHOR_MESSAGE_POSTINSTALL_ACTION', 'tpl_hathor', 1, 'action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_condition', '3.7.0', 1),
-(700, 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_TITLE', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_BODY', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_ACTION', 'plg_captcha_recaptcha', 1, 'action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_condition', '3.8.6', 1);
+(700, 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_TITLE', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_BODY', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_ACTION', 'plg_captcha_recaptcha', 1, 'action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_condition', '3.8.6', 1),
+(700, 'COM_ACTIONLOGS_POSTINSTALL_TITLE', 'COM_ACTIONLOGS_POSTINSTALL_BODY', '', 'com_actionlogs', 1, 'message', '', '', '', '', '3.9.0', 1),
+(700, 'COM_PRIVACY_POSTINSTALL_TITLE', 'COM_PRIVACY_POSTINSTALL_BODY', '', 'com_privacy', 1, 'message', '', '', '', '', '3.9.0', 1);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `#__privacy_requests`
+--
+
+CREATE TABLE IF NOT EXISTS `#__privacy_requests` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `email` varchar(100) NOT NULL DEFAULT '',
+ `requested_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `status` tinyint(4) NOT NULL DEFAULT '0',
+ `request_type` varchar(25) NOT NULL DEFAULT '',
+ `confirm_token` varchar(100) NOT NULL DEFAULT '',
+ `confirm_token_created_at` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `checked_out` int(11) NOT NULL DEFAULT '0',
+ `checked_out_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ PRIMARY KEY (`id`),
+ KEY `idx_checkout` (`checked_out`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
+
+CREATE TABLE IF NOT EXISTS `#__privacy_consents` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `user_id` int(10) unsigned NOT NULL DEFAULT '0',
+ `created` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `subject` varchar(255) NOT NULL DEFAULT '',
+ `body` text NOT NULL,
+ `remind` tinyint(4) NOT NULL DEFAULT '0',
+ `token` varchar(100) NOT NULL DEFAULT '',
+ PRIMARY KEY (`id`),
+ KEY `idx_user_id` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
-- --------------------------------------------------------
@@ -2083,6 +2142,87 @@ CREATE TABLE IF NOT EXISTS `#__user_usergroup_map` (
PRIMARY KEY (`user_id`,`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
+--
+-- Table structure for table `#__action_logs`
+--
+
+CREATE TABLE IF NOT EXISTS `#__action_logs` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `message_language_key` varchar(255) NOT NULL DEFAULT '',
+ `message` text NOT NULL,
+ `log_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+ `extension` varchar(50) NOT NULL DEFAULT '',
+ `user_id` int(11) NOT NULL DEFAULT 0,
+ `item_id` int(11) NOT NULL DEFAULT 0,
+ `ip_address` VARCHAR(40) NOT NULL DEFAULT '0.0.0.0',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
+
+--
+-- Table structure for table `#__action_logs_extensions`
+--
+
+CREATE TABLE IF NOT EXISTS `#__action_logs_extensions` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `extension` varchar(255) NOT NULL DEFAULT '',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
+
+INSERT INTO `#__action_logs_extensions` (`id`, `extension`) VALUES
+(1, 'com_banners'),
+(2, 'com_cache'),
+(3, 'com_categories'),
+(4, 'com_config'),
+(5, 'com_contact'),
+(6, 'com_content'),
+(7, 'com_installer'),
+(8, 'com_media'),
+(9, 'com_menus'),
+(10, 'com_messages'),
+(11, 'com_modules'),
+(12, 'com_newsfeeds'),
+(13, 'com_plugins'),
+(14, 'com_redirect'),
+(15, 'com_tags'),
+(16, 'com_templates'),
+(17, 'com_users');
+
+--
+-- Table structure for table `#__action_log_config`
+--
+
+CREATE TABLE IF NOT EXISTS `#__action_log_config` (
+ `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
+ `type_title` varchar(255) NOT NULL DEFAULT '',
+ `type_alias` varchar(255) NOT NULL DEFAULT '',
+ `id_holder` varchar(255),
+ `title_holder` varchar(255),
+ `table_name` varchar(255),
+ `text_prefix` varchar(255),
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 DEFAULT COLLATE=utf8mb4_unicode_ci;
+
+INSERT INTO `#__action_log_config` (`id`, `type_title`, `type_alias`, `id_holder`, `title_holder`, `table_name`, `text_prefix`) VALUES
+(1, 'article', 'com_content.article', 'id' ,'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
+(2, 'article', 'com_content.form', 'id', 'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
+(3, 'banner', 'com_banners.banner', 'id' ,'name' , '#__banners', 'PLG_ACTIONLOG_JOOMLA'),
+(4, 'user_note', 'com_users.note', 'id', 'subject' ,'#__user_notes', 'PLG_ACTIONLOG_JOOMLA'),
+(5, 'media', 'com_media.file', '' , 'name' , '', 'PLG_ACTIONLOG_JOOMLA'),
+(6, 'category', 'com_categories.category', 'id' , 'title' , '#__categories', 'PLG_ACTIONLOG_JOOMLA'),
+(7, 'menu', 'com_menus.menu', 'id' ,'title' , '#__menu_types', 'PLG_ACTIONLOG_JOOMLA'),
+(8, 'menu_item', 'com_menus.item', 'id' , 'title' , '#__menu', 'PLG_ACTIONLOG_JOOMLA'),
+(9, 'newsfeed', 'com_newsfeeds.newsfeed', 'id' ,'name' , '#__newsfeeds', 'PLG_ACTIONLOG_JOOMLA'),
+(10, 'link', 'com_redirect.link', 'id', 'old_url' , '#__redirect_links', 'PLG_ACTIONLOG_JOOMLA'),
+(11, 'tag', 'com_tags.tag', 'id', 'title' , '#__tags', 'PLG_ACTIONLOG_JOOMLA'),
+(12, 'style', 'com_templates.style', 'id' , 'title' , '#__template_styles', 'PLG_ACTIONLOG_JOOMLA'),
+(13, 'plugin', 'com_plugins.plugin', 'extension_id' , 'name' , '#__extensions', 'PLG_ACTIONLOG_JOOMLA'),
+(14, 'component_config', 'com_config.component', 'extension_id' , 'name', '', 'PLG_ACTIONLOG_JOOMLA'),
+(15, 'contact', 'com_contact.contact', 'id', 'name', '#__contact_details', 'PLG_ACTIONLOG_JOOMLA'),
+(16, 'module', 'com_modules.module', 'id' ,'title', '#__modules', 'PLG_ACTIONLOG_JOOMLA'),
+(17, 'access_level', 'com_users.level', 'id' , 'title', '#__viewlevels', 'PLG_ACTIONLOG_JOOMLA'),
+(18, 'banner_client', 'com_banners.client', 'id', 'name', '#__banner_clients', 'PLG_ACTIONLOG_JOOMLA'),
+(19, 'application_config', 'com_config.application', '', 'name', '', 'PLG_ACTIONLOG_JOOMLA');
+
--
-- Table structure for table `#__utf8_conversion`
--
diff --git a/installation/sql/mysql/sample_blog.sql b/installation/sql/mysql/sample_blog.sql
index 2bf75905edc37..19c67b54da37e 100644
--- a/installation/sql/mysql/sample_blog.sql
+++ b/installation/sql/mysql/sample_blog.sql
@@ -18,7 +18,7 @@ TRUNCATE `#__modules_menu`;
--
INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `title`, `rules`) VALUES
-(1, 0, 0, 87, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 91, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -61,7 +61,9 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl
(44, 1, 79, 80, 1, 'com_tags', 'com_tags', '{"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(45, 1, 81, 82, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
(46, 1, 83, 84, 1, 'com_ajax', 'com_ajax', '{}'),
-(47, 1, 85, 86, 1, 'com_postinstall', 'com_postinstall', '{}');
+(47, 1, 85, 86, 1, 'com_postinstall', 'com_postinstall', '{}'),
+(48, 1, 87, 88, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(49, 1, 89, 90, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
--
-- Dumping data for table `#__categories`
@@ -165,7 +167,8 @@ INSERT INTO `#__modules` (`id`, `title`, `note`, `content`, `ordering`, `positio
(89, 'Popular Tags', '', '', 1, 'position-7', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_tags_popular', 1, 1, '{"maximum":"8","timeframe":"alltime","order_value":"count","order_direction":"1","display_count":0,"no_results_text":"0","minsize":1,"maxsize":2,"layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(90, 'Similar Items', '', '', 0, '', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(91, 'Site Information', '', '', 4, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_stats_admin', 6, 1, '{"serverinfo":"1","siteinfo":"1","counter":"0","increase":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"6","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
-(92, 'Release News', '', '', 1, 'postinstall', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\\/\\/www.joomla.org\\/announcements\\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*');
+(92, 'Release News', '', '', 1, 'postinstall', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\\/\\/www.joomla.org\\/announcements\\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
+(93, 'Latest Actions', '', '', 0, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
--
-- Dumping data for table `#__modules_menu`
@@ -199,6 +202,7 @@ INSERT INTO `#__modules_menu` (`moduleid`, `menuid`) VALUES
(89, 0),
(90, 0),
(91, 0),
-(92, 0);
+(92, 0),
+(93, 0);
SET FOREIGN_KEY_CHECKS=1;
diff --git a/installation/sql/mysql/sample_brochure.sql b/installation/sql/mysql/sample_brochure.sql
index bf4e062101df8..8220fcbcf003e 100644
--- a/installation/sql/mysql/sample_brochure.sql
+++ b/installation/sql/mysql/sample_brochure.sql
@@ -19,7 +19,7 @@ TRUNCATE `#__template_styles`;
--
INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `title`, `rules`) VALUES
-(1, 0, 0, 91, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 95, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -64,7 +64,9 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl
(50, 18, 52, 53, 2, 'com_modules.module.4', 'Recently Added Articles', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(51, 18, 54, 55, 2, 'com_modules.module.89', 'Site Information', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(52, 18, 56, 57, 2, 'com_modules.module.88', 'Image', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
-(53, 18, 58, 59, 2, 'com_modules.module.90', 'Release News', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}');
+(53, 18, 58, 59, 2, 'com_modules.module.90', 'Release News', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
+(54, 1, 91, 92, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(55, 1, 93, 94, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
--
-- Dumping data for table `#__categories`
@@ -165,7 +167,8 @@ INSERT INTO `#__modules` (`id`, `asset_id`, `title`, `note`, `content`, `orderin
(87, 0, 'Footer', '', '', 1, 'footer', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_footer', 1, 1, '{"layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(88, 52, 'Image', '', '
', 1, 'position-3', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_custom', 1, 0, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(89, 51, 'Site Information', '', '', 4, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_stats_admin', 6, 1, '{"serverinfo":"1","siteinfo":"1","counter":"1","increase":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"6","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
-(90, 53, 'Release News', '', '', 0, 'postinstall', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\\/\\/www.joomla.org\\/announcements\\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*');
+(90, 53, 'Release News', '', '', 0, 'postinstall', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\\/\\/www.joomla.org\\/announcements\\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
+(91, 54, 'Latest Actions', '', '', 0, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
--
-- Dumping data for table `#__modules_menu`
@@ -192,7 +195,8 @@ INSERT INTO `#__modules_menu` (`moduleid`, `menuid`) VALUES
(83, 0),
(85, 0),
(86, 0),
-(88, 0);
+(88, 0),
+(91, 0);
--
-- Dumping data for table `#__template_styles`
diff --git a/installation/sql/mysql/sample_data.sql b/installation/sql/mysql/sample_data.sql
index d1da076fdf7a8..1f8d240e9ab1f 100644
--- a/installation/sql/mysql/sample_data.sql
+++ b/installation/sql/mysql/sample_data.sql
@@ -18,7 +18,7 @@ TRUNCATE `#__tags`;
--
INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `title`, `rules`) VALUES
-(1, 0, 0, 119, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 123, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -77,7 +77,9 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl
(59, 18, 82, 83, 2, 'com_modules.module.92', 'Image Module', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(60, 18, 84, 85, 2, 'com_modules.module.93', 'Search', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(61, 27, 19, 20, 3, 'com_content.article.1', 'Getting Started', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
-(62, 1, 117, 118, 1, '#__ucm_content.1', '#__ucm_content.1', '{}');
+(62, 1, 117, 118, 1, '#__ucm_content.1', '#__ucm_content.1', '{}'),
+(63, 1, 119, 120, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(64, 1, 121, 122, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
--
-- Dumping data for table `#__content`
@@ -160,7 +162,8 @@ INSERT INTO `#__modules` (`id`, `asset_id`, `title`, `note`, `content`, `orderin
(90, 57, 'Latest Articles', '', '', 1, 'position-7', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_articles_latest', 1, 1, '{"catid":[""],"count":"5","show_featured":"","ordering":"c_dsc","user_id":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(91, 58, 'User Menu', '', '', 3, 'position-7', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_menu', 1, 1, '{"menutype":"usermenu","base":"","startLevel":"1","endLevel":"0","showAllChildren":"1","tag_id":"","class_sfx":"","window_open":"","layout":"_:default","moduleclass_sfx":"_menu","cache":"1","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(92, 59, 'Image Module', '', '
', 0, 'position-3', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_custom', 1, 0, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
-(93, 60, 'Search', '', '', 0, 'position-0', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_search', 1, 1, '{"label":"","width":"20","text":"","button":"0","button_pos":"right","imagebutton":"1","button_text":"","opensearch":"1","opensearch_title":"","set_itemid":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*');
+(93, 60, 'Search', '', '', 0, 'position-0', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_search', 1, 1, '{"label":"","width":"20","text":"","button":"0","button_pos":"right","imagebutton":"1","button_text":"","opensearch":"1","opensearch_title":"","set_itemid":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
+(94, 61, 'Latest Actions', '', '', 0, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
--
-- Dumping data for table `#__modules_menu`
@@ -190,7 +193,8 @@ INSERT INTO `#__modules_menu` (`moduleid`, `menuid`) VALUES
(90, 0),
(91, 0),
(92, 0),
-(93, 0);
+(93, 0),
+(94, 0);
--
-- Dumping data for table `#__tags`
diff --git a/installation/sql/mysql/sample_learn.sql b/installation/sql/mysql/sample_learn.sql
index 6d9653261f65b..ecdb6d6d487b9 100644
--- a/installation/sql/mysql/sample_learn.sql
+++ b/installation/sql/mysql/sample_learn.sql
@@ -21,7 +21,7 @@ TRUNCATE `#__viewlevels`;
--
INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `title`, `rules`) VALUES
-(1, 0, 1, 430, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 1, 434, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 2, 3, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 4, 11, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 12, 13, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -180,7 +180,9 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl
(175, 1, 422, 423, 1, 'com_tags', 'com_tags', '{"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(176, 1, 424, 425, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
(177, 1, 426, 427, 1, 'com_ajax', 'com_ajax', '{}'),
-(178, 1, 428, 429, 1, 'com_postinstall', 'com_postinstall', '{}');
+(178, 1, 428, 429, 1, 'com_postinstall', 'com_postinstall', '{}'),
+(179, 1, 430, 431, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(180, 1, 432, 433, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
--
-- Dumping data for table `#__banners`
@@ -577,7 +579,8 @@ INSERT INTO `#__modules` (`id`, `title`, `note`, `content`, `ordering`, `positio
(87, 'Fruit Shop', '', '', 1, 'position-7', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_menu', 1, 1, '{"menutype":"fruitshop","startLevel":"1","endLevel":"0","showAllChildren":"1","tag_id":"","class_sfx":"","window_open":"","layout":"_:default","moduleclass_sfx":"","cache":"0","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(88, 'Image Module', '', '
', 1, 'position-3', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_custom', 1, 0, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(89, 'Custom', '', '
In this module you can put whatever text or other content you would like.
', 1, '', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_custom', 1, 1, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
-(90, 'Parks Image Module', '', '
', 1, 'position-3', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_custom', 1, 1, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*');
+(90, 'Parks Image Module', '', '
', 1, 'position-3', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_custom', 1, 1, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
+(91, 'Latest Actions', '', '', 0, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
--
-- Dumping data for table `#__modules_menu`
@@ -774,7 +777,8 @@ INSERT INTO `#__modules_menu` (`moduleid`, `menuid`) VALUES
(90, 244),
(90, 296),
(90, 399),
-(90, 400);
+(90, 400),
+(91, 0);
--
-- Dumping data for table `#__newsfeeds`
diff --git a/installation/sql/mysql/sample_testing.sql b/installation/sql/mysql/sample_testing.sql
index 108873dbe436f..46eefb3bab864 100644
--- a/installation/sql/mysql/sample_testing.sql
+++ b/installation/sql/mysql/sample_testing.sql
@@ -21,7 +21,7 @@ TRUNCATE `#__viewlevels`;
--
INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `title`, `rules`) VALUES
-(1, 0, 1, 437, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 1, 441, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 2, 3, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 4, 11, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 12, 13, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -184,7 +184,9 @@ INSERT INTO `#__assets` (`id`, `parent_id`, `lft`, `rgt`, `level`, `name`, `titl
(177, 1, 433, 434, 1, 'com_postinstall', 'com_postinstall', '{}'),
(178, 93, 144, 145, 7, 'com_content.article.71', 'Similar Tags', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(179, 1, 435, 436, 1, '#__ucm_content.3', '#__ucm_content.3', '{}'),
-(180, 93, 146, 147, 7, 'com_content.article.72', 'Popular Tags', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}');
+(180, 93, 146, 147, 7, 'com_content.article.72', 'Popular Tags', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
+(181, 1, 437, 438, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(182, 1, 439, 440, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
--
-- Dumping data for table `#__banners`
@@ -612,7 +614,8 @@ INSERT INTO `#__modules` (`id`, `title`, `note`, `content`, `ordering`, `positio
(93, 'Popular Tags', '', '', 1, '', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_tags_popular', 1, 1, '{"maximum":"5","timeframe":"alltime","order_value":"count","order_direction":"1","display_count":0,"no_results_text":"0","minsize":1,"maxsize":2,"layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(94, 'Similar Tags', '', '', 1, '', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(95, 'Syndicate Feeds', '', '', 1, 'position-8', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_syndicate', 1, 1, '{"display_text":1,"text":"Feed Entries","format":"rss","layout":"_:default","moduleclass_sfx":"","cache":"0","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
-(97, 'Similar Tags 2', '', '', 1, 'position-8', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*');
+(97, 'Similar Tags 2', '', '', 1, 'position-8', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
+(98, 'Latest Actions', '', '', 0, 'cpanel', 0, '0000-00-00 00:00:00', '0000-00-00 00:00:00', '0000-00-00 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
--
-- Dumping data for table `#__modules_menu`
@@ -798,7 +801,8 @@ INSERT INTO `#__modules_menu` (`moduleid`, `menuid`) VALUES
(93, 0),
(94, 0),
(95, 0),
-(97, 0);
+(97, 0),
+(98, 0);
--
-- Dumping data for table `#__newsfeeds`
diff --git a/installation/sql/postgresql/joomla.sql b/installation/sql/postgresql/joomla.sql
index cce24c6630c51..d023601f47b2a 100644
--- a/installation/sql/postgresql/joomla.sql
+++ b/installation/sql/postgresql/joomla.sql
@@ -35,7 +35,7 @@ COMMENT ON COLUMN "#__assets"."rules" IS 'JSON encoded access control.';
--
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 0, 105, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 113, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -52,25 +52,25 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(15, 1, 33, 34, 1, 'com_media', 'com_media', '{"core.admin":{"7":1},"core.manage":{"6":1},"core.create":{"3":1},"core.delete":{"5":1}}'),
(16, 1, 35, 38, 1, 'com_menus', 'com_menus', '{"core.admin":{"7":1}}'),
(17, 1, 39, 40, 1, 'com_messages', 'com_messages', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
-(18, 1, 41, 74, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'),
-(19, 1, 75, 77, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
-(20, 1, 79, 80, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'),
-(21, 1, 81, 82, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'),
-(22, 1, 83, 84, 1, 'com_search', 'com_search', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
-(23, 1, 85, 86, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'),
-(24, 1, 87, 90, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'),
-(26, 1, 91, 92, 1, 'com_wrapper', 'com_wrapper', '{}'),
+(18, 1, 41, 78, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'),
+(19, 1, 79, 82, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
+(20, 1, 83, 84, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'),
+(21, 1, 85, 86, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'),
+(22, 1, 87, 88, 1, 'com_search', 'com_search', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
+(23, 1, 89, 90, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'),
+(24, 1, 91, 94, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'),
+(26, 1, 95, 96, 1, 'com_wrapper', 'com_wrapper', '{}'),
(27, 8, 18, 19, 2, 'com_content.category.2', 'Uncategorised', '{}'),
(28, 3, 4, 5, 2, 'com_banners.category.3', 'Uncategorised', '{}'),
(29, 7, 14, 15, 2, 'com_contact.category.4', 'Uncategorised', '{}'),
-(30, 19, 76, 77, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'),
-(32, 24, 88, 89, 2, 'com_users.category.7', 'Uncategorised', '{}'),
-(33, 1, 93, 94, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
-(34, 1, 95, 96, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'),
-(35, 1, 97, 98, 1, 'com_tags', 'com_tags', '{}'),
-(36, 1, 99, 100, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
-(37, 1, 101, 102, 1, 'com_ajax', 'com_ajax', '{}'),
-(38, 1, 103, 104, 1, 'com_postinstall', 'com_postinstall', '{}'),
+(30, 19, 80, 81, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'),
+(32, 24, 92, 93, 2, 'com_users.category.7', 'Uncategorised', '{}'),
+(33, 1, 97, 98, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
+(34, 1, 99, 100, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'),
+(35, 1, 101, 102, 1, 'com_tags', 'com_tags', '{}'),
+(36, 1, 103, 104, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
+(37, 1, 105, 106, 1, 'com_ajax', 'com_ajax', '{}'),
+(38, 1, 107, 108, 1, 'com_postinstall', 'com_postinstall', '{}'),
(39, 18, 42, 43, 2, 'com_modules.module.1', 'Main Menu', '{}'),
(40, 18, 44, 45, 2, 'com_modules.module.2', 'Login', '{}'),
(41, 18, 46, 47, 2, 'com_modules.module.3', 'Popular Articles', '{}'),
@@ -87,9 +87,13 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(52, 18, 68, 69, 2, 'com_modules.module.79', 'Multilanguage status', '{}'),
(53, 18, 70, 71, 2, 'com_modules.module.86', 'Joomla Version', '{}'),
(54, 16, 36, 37, 2, 'com_menus.menu.1', 'Main Menu', '{}'),
-(55, 18, 72, 73, 2, 'com_modules.module.87', 'Sample Data', '{}');
+(55, 18, 72, 73, 2, 'com_modules.module.87', 'Sample Data', '{}'),
+(56, 1, 109, 110, 1, 'com_privacy', 'com_privacy', '{}'),
+(57, 1, 111, 112, 1, 'com_actionlogs', 'com_actionlogs', '{}'),
+(58, 18, 74, 75, 2, 'com_modules.module.88', 'Latest Actions', '{}'),
+(59, 18, 76, 77, 2, 'com_modules.module.89', 'Privacy Dashboard', '{}');
-SELECT setval('#__assets_id_seq', 56, false);
+SELECT setval('#__assets_id_seq', 60, false);
--
-- Table structure for table `#__associations`
@@ -534,6 +538,8 @@ INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "elem
(32, 0, 'com_postinstall', 'component', 'com_postinstall', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(33, 0, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(34, 0, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(35, 0, 'com_privacy', 'component', 'com_privacy', '', 1, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(36, 0, 'com_actionlogs', 'component', 'com_actionlogs', '', 1, 1, 1, 1, '', '{"ip_logging":0,"csv_delimiter":",","loggable_extensions":["com_banners","com_cache","com_categories","com_config","com_contact","com_content","com_installer","com_media","com_menus","com_messages","com_modules","com_newsfeeds","com_plugins","com_redirect","com_tags","com_templates","com_users"]}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(102, 0, 'phputf8', 'library', 'phputf8', '', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(103, 0, 'Joomla! Platform', 'library', 'joomla', '', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(104, 0, 'IDNA Convert', 'library', 'idna_convert', '', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
@@ -580,6 +586,8 @@ INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "elem
(316, 0, 'mod_tags_popular', 'module', 'mod_tags_popular', '', 0, 1, 1, 0, '', '{"maximum":"5","timeframe":"alltime","owncache":"1"}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(317, 0, 'mod_tags_similar', 'module', 'mod_tags_similar', '', 0, 1, 1, 0, '', '{"maximum":"5","matchtype":"any","owncache":"1"}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(318, 0, 'mod_sampledata', 'module', 'mod_sampledata', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(319, 0, 'mod_latestactions', 'module', 'mod_latestactions', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(320, 0, 'mod_privacy_dashboard', 'module', 'mod_privacy_dashboard', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(400, 0, 'plg_authentication_gmail', 'plugin', 'gmail', 'authentication', 0, 0, 1, 0, '', '{"applysuffix":"0","suffix":"","verifypeer":"1","user_blacklist":""}', '', '', 0, '1970-01-01 00:00:00', 1, 0),
(401, 0, 'plg_authentication_joomla', 'plugin', 'joomla', 'authentication', 0, 1, 1, 1, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(402, 0, 'plg_authentication_ldap', 'plugin', 'ldap', 'authentication', 0, 0, 1, 0, '', '{"host":"","port":"389","use_ldapV3":"0","negotiate_tls":"0","no_referrals":"0","auth_method":"bind","base_dn":"","search_string":"","users_dn":"","username":"admin","password":"bobby7","ldap_fullname":"fullName","ldap_email":"mail","ldap_uid":"uid"}', '', '', 0, '1970-01-01 00:00:00', 3, 0),
@@ -659,6 +667,18 @@ INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "elem
(479, 0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(480, 0, 'plg_system_sessiongc', 'plugin', 'sessiongc', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(481, 0, 'plg_fields_repeatable', 'plugin', 'repeatable', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(482, 0, 'plg_content_confirmconsent', 'plugin', 'confirmconsent', 'content', 0, 0, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(483, 0, 'plg_system_actionlogs', 'plugin', 'actionlogs', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(484, 0, 'plg_actionlog_joomla', 'plugin', 'joomla', 'actionlog', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(485, 0, 'plg_system_privacyconsent', 'plugin', 'privacyconsent', 'system', 0, 0, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(486, 0, 'plg_system_logrotation', 'plugin', 'logrotation', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(487, 0, 'plg_privacy_user', 'plugin', 'user', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(488, 0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(489, 0, 'plg_user_terms', 'plugin', 'terms', 'user', 0, 0, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(490, 0, 'plg_privacy_contact', 'plugin', 'contact', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(491, 0, 'plg_privacy_content', 'plugin', 'content', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(492, 0, 'plg_privacy_message', 'plugin', 'message', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
+(493, 0, 'plg_privacy_actionlogs', 'plugin', 'actionlogs', 'privacy', 0, 0, 1, 0, '', '{}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(503, 0, 'beez3', 'template', 'beez3', '', 0, 1, 1, 0, '', '{"wrapperSmall":"53","wrapperLarge":"72","sitetitle":"","sitedescription":"","navposition":"center","templatecolor":"nature"}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(504, 0, 'hathor', 'template', 'hathor', '', 1, 1, 1, 0, '', '{"showSiteName":"0","colourChoice":"0","boldText":"0"}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
(506, 0, 'protostar', 'template', 'protostar', '', 0, 1, 1, 0, '', '{"templateColor":"","logoFile":"","googleFont":"1","googleFontName":"Open+Sans","fluidContainer":"0"}', '', '', 0, '1970-01-01 00:00:00', 0, 0),
@@ -1486,9 +1506,11 @@ INSERT INTO "#__modules" ("id", "asset_id", "title", "note", "content", "orderin
(17, 51, 'Breadcrumbs', '', '', 1, 'position-2', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_breadcrumbs', 1, 1, '{"moduleclass_sfx":"","showHome":"1","homeText":"","showComponent":"1","separator":"","cache":"0","cache_time":"0","cachemode":"itemid"}', 0, '*'),
(79, 52, 'Multilanguage status', '', '', 1, 'status', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 0, 'mod_multilangstatus', 3, 1, '{"layout":"_:default","moduleclass_sfx":"","cache":"0"}', 1, '*'),
(86, 53, 'Joomla Version', '', '', 1, 'footer', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_version', 3, 1, '{"format":"short","product":"1","layout":"_:default","moduleclass_sfx":"","cache":"0"}', 1, '*'),
-(87, 55, 'Sample Data', '', '', 0, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_sampledata', 6, 1, '{}', 1, '*');
+(87, 55, 'Sample Data', '', '', 0, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_sampledata', 6, 1, '{}', 1, '*'),
+(88, 58, 'Latest Actions', '', '', 0, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*'),
+(89, 59, 'Privacy Dashboard', '', '', 0, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_privacy_dashboard', 6, 1, '{}', 1, '*');
-SELECT setval('#__modules_id_seq', 88, false);
+SELECT setval('#__modules_id_seq', 90, false);
--
-- Table structure for table `#__modules_menu`
@@ -1522,7 +1544,9 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(17, 0),
(79, 0),
(86, 0),
-(87, 0);
+(87, 0),
+(88, 0),
+(89, 0);
--
-- Table structure for table `#__newsfeeds`
@@ -1629,7 +1653,43 @@ INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description
(700, 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_BODY', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_ACTION', 'plg_system_updatenotification', 1, 'action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_condition', '3.6.3', 1),
(700, 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_TITLE', 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/joomla40checks.php', 'admin_postinstall_joomla40checks_condition', '3.7.0', 1),
(700, 'TPL_HATHOR_MESSAGE_POSTINSTALL_TITLE', 'TPL_HATHOR_MESSAGE_POSTINSTALL_BODY', 'TPL_HATHOR_MESSAGE_POSTINSTALL_ACTION', 'tpl_hathor', 1, 'action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_condition', '3.7.0', 1),
-(700, 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_TITLE', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_BODY', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_ACTION', 'plg_captcha_recaptcha', 1, 'action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_condition', '3.8.6', 1);
+(700, 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_TITLE', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_BODY', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_ACTION', 'plg_captcha_recaptcha', 1, 'action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_condition', '3.8.6', 1),
+(700, 'COM_ACTIONLOGS_POSTINSTALL_TITLE', 'COM_ACTIONLOGS_POSTINSTALL_BODY', '', 'com_actionlogs', 1, 'message', '', '', '', '', '3.9.0', 1),
+(700, 'COM_PRIVACY_POSTINSTALL_TITLE', 'COM_PRIVACY_POSTINSTALL_BODY', '', 'com_privacy', 1, 'message', '', '', '', '', '3.9.0', 1);
+
+--
+-- Table structure for table `#__privacy_requests`
+--
+
+CREATE TABLE "#__privacy_requests" (
+ "id" serial NOT NULL,
+ "email" varchar(100) DEFAULT '' NOT NULL,
+ "requested_at" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
+ "status" smallint DEFAULT 0 NOT NULL,
+ "request_type" varchar(25) DEFAULT '' NOT NULL,
+ "confirm_token" varchar(100) DEFAULT '' NOT NULL,
+ "confirm_token_created_at" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
+ "checked_out" integer DEFAULT 0 NOT NULL,
+ "checked_out_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
+ PRIMARY KEY ("id")
+);
+CREATE INDEX "#__privacy_requests_idx_checked_out" ON "#__privacy_requests" ("checked_out");
+
+--
+-- Table structure for table `#__privacy_consents`
+--
+
+CREATE TABLE "#__privacy_consents" (
+ "id" serial NOT NULL,
+ "user_id" bigint DEFAULT 0 NOT NULL,
+ "created" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
+ "subjext" varchar(255) DEFAULT '' NOT NULL,
+ "body" text NOT NULL,
+ "remind" smallint DEFAULT 0 NOT NULL,
+ "token" varchar(100) DEFAULT '' NOT NULL,
+ PRIMARY KEY ("id")
+);
+CREATE INDEX "#__privacy_consents_idx_user_id" ON "#__privacy_consents" ("user_id");
--
-- Table structure for table `#__redirect_links`
@@ -2067,6 +2127,95 @@ CREATE TABLE "#__user_usergroup_map" (
COMMENT ON COLUMN "#__user_usergroup_map"."user_id" IS 'Foreign Key to #__users.id';
COMMENT ON COLUMN "#__user_usergroup_map"."group_id" IS 'Foreign Key to #__usergroups.id';
+--
+-- Table: #__action_logs
+--
+CREATE TABLE "#__action_logs" (
+ "id" serial NOT NULL,
+ "message_language_key" varchar(255) NOT NULL DEFAULT '',
+ "message" text NOT NULL DEFAULT '',
+ "log_date" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL,
+ "extension" varchar(50) NOT NULL DEFAULT '',
+ "user_id" integer DEFAULT 0 NOT NULL,
+ "item_id" integer DEFAULT 0 NOT NULL,
+ "ip_address" varchar(40) NOT NULL DEFAULT '0.0.0.0',
+ PRIMARY KEY ("id")
+);
+
+-- Table: #__action_logs_extensions
+--
+CREATE TABLE "#__action_logs_extensions" (
+ "id" serial NOT NULL,
+ "extension" varchar(50) NOT NULL DEFAULT '',
+ PRIMARY KEY ("id")
+);
+
+--
+-- Dumping data for table '#__action_logs_extensions'
+--
+INSERT INTO "#__action_logs_extensions" ("id", "extension") VALUES
+(1, 'com_banners'),
+(2, 'com_cache'),
+(3, 'com_categories'),
+(4, 'com_config'),
+(5, 'com_contact'),
+(6, 'com_content'),
+(7, 'com_installer'),
+(8, 'com_media'),
+(9, 'com_menus'),
+(10, 'com_messages'),
+(11, 'com_modules'),
+(12, 'com_newsfeeds'),
+(13, 'com_plugins'),
+(14, 'com_redirect'),
+(15, 'com_tags'),
+(16, 'com_templates'),
+(17, 'com_users');
+
+SELECT setval('#__action_logs_extensions_id_seq', 18, false);
+-- --------------------------------------------------------
+
+--
+-- Table: #__action_log_config
+--
+CREATE TABLE "#__action_log_config" (
+ "id" serial NOT NULL,
+ "type_title" varchar(255) NOT NULL DEFAULT '',
+ "type_alias" varchar(255) NOT NULL DEFAULT '',
+ "id_holder" varchar(255) NULL,
+ "title_holder" varchar(255) NULL,
+ "table_name" varchar(255) NULL,
+ "text_prefix" varchar(255) NULL,
+ PRIMARY KEY ("id")
+);
+
+--
+-- Dumping data for table #__action_log_config
+--
+INSERT INTO "#__action_log_config" ("id", "type_title", "type_alias", "id_holder", "title_holder", "table_name", "text_prefix") VALUES
+(1, 'article', 'com_content.article', 'id' ,'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
+(2, 'article', 'com_content.form', 'id', 'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'),
+(3, 'banner', 'com_banners.banner', 'id' ,'name' , '#__banners', 'PLG_ACTIONLOG_JOOMLA'),
+(4, 'user_note', 'com_users.note', 'id', 'subject' ,'#__user_notes', 'PLG_ACTIONLOG_JOOMLA'),
+(5, 'media', 'com_media.file', '' , 'name' , '', 'PLG_ACTIONLOG_JOOMLA'),
+(6, 'category', 'com_categories.category', 'id' , 'title' , '#__categories', 'PLG_ACTIONLOG_JOOMLA'),
+(7, 'menu', 'com_menus.menu', 'id' ,'title' , '#__menu_types', 'PLG_ACTIONLOG_JOOMLA'),
+(8, 'menu_item', 'com_menus.item', 'id' , 'title' , '#__menu', 'PLG_ACTIONLOG_JOOMLA'),
+(9, 'newsfeed', 'com_newsfeeds.newsfeed', 'id' ,'name' , '#__newsfeeds', 'PLG_ACTIONLOG_JOOMLA'),
+(10, 'link', 'com_redirect.link', 'id', 'old_url' , '#__redirect_links', 'PLG_ACTIONLOG_JOOMLA'),
+(11, 'tag', 'com_tags.tag', 'id', 'title' , '#__tags', 'PLG_ACTIONLOG_JOOMLA'),
+(12, 'style', 'com_templates.style', 'id' , 'title' , '#__template_styles', 'PLG_ACTIONLOG_JOOMLA'),
+(13, 'plugin', 'com_plugins.plugin', 'extension_id' , 'name' , '#__extensions', 'PLG_ACTIONLOG_JOOMLA'),
+(14, 'component_config', 'com_config.component', 'extension_id' , 'name', '', 'PLG_ACTIONLOG_JOOMLA'),
+(15, 'contact', 'com_contact.contact', 'id', 'name', '#__contact_details', 'PLG_ACTIONLOG_JOOMLA'),
+(16, 'module', 'com_modules.module', 'id' ,'title', '#__modules', 'PLG_ACTIONLOG_JOOMLA'),
+(17, 'access_level', 'com_users.level', 'id' , 'title', '#__viewlevels', 'PLG_ACTIONLOG_JOOMLA'),
+(18, 'banner_client', 'com_banners.client', 'id', 'name', '#__banner_clients', 'PLG_ACTIONLOG_JOOMLA'),
+(19, 'application_config', 'com_config.application', '', 'name', '', 'PLG_ACTIONLOG_JOOMLA');
+
+
+SELECT setval('#__action_log_config_id_seq', 18, false);
+
--
-- Table structure for table `#__viewlevels`
--
diff --git a/installation/sql/postgresql/sample_blog.sql b/installation/sql/postgresql/sample_blog.sql
index c74fd4c27c851..5452f37b43f43 100644
--- a/installation/sql/postgresql/sample_blog.sql
+++ b/installation/sql/postgresql/sample_blog.sql
@@ -14,7 +14,7 @@ TRUNCATE "#__modules_menu" RESTART IDENTITY;
--
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 0, 87, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 91, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -57,7 +57,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(44, 1, 79, 80, 1, 'com_tags', 'com_tags', '{"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(45, 1, 81, 82, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
(46, 1, 83, 84, 1, 'com_ajax', 'com_ajax', '{}'),
-(47, 1, 85, 86, 1, 'com_postinstall', 'com_postinstall', '{}');
+(47, 1, 85, 86, 1, 'com_postinstall', 'com_postinstall', '{}'),
+(48, 1, 87, 88, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(49, 1, 89, 90, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
SELECT setval('#__assets_id_seq', max(id)) FROM "#__assets";
@@ -171,7 +173,8 @@ INSERT INTO "#__modules" ("id", "title", "note", "content", "ordering", "positio
(89, 'Popular Tags', '', '', 1, 'position-7', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_tags_popular', 1, 1, '{"maximum":"8","timeframe":"alltime","order_value":"count","order_direction":"1","display_count":0,"no_results_text":"0","minsize":1,"maxsize":2,"layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(90, 'Similar Items', '', '', 0, '', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(91, 'Site Information', '', '', 4, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_stats_admin', 6, 1, '{"serverinfo":"1","siteinfo":"1","counter":"0","increase":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"6","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
-(92, 'Release News', '', '', 1, 'postinstall', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\\/\\/www.joomla.org\\/announcements\\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*');
+(92, 'Release News', '', '', 1, 'postinstall', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\\/\\/www.joomla.org\\/announcements\\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
+(93, 'Latest Actions', '', '', 0, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
SELECT setval('#__modules_id_seq', max(id)) FROM "#__modules";
@@ -207,4 +210,5 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(89, 0),
(90, 0),
(91, 0),
-(92, 0);
+(92, 0),
+(93, 0);
diff --git a/installation/sql/postgresql/sample_brochure.sql b/installation/sql/postgresql/sample_brochure.sql
index bb8058d0b9b51..195b6d629010b 100644
--- a/installation/sql/postgresql/sample_brochure.sql
+++ b/installation/sql/postgresql/sample_brochure.sql
@@ -15,7 +15,7 @@ TRUNCATE "#__template_styles" RESTART IDENTITY;
--
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 0, 91, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 95, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -60,7 +60,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(50, 18, 52, 53, 2, 'com_modules.module.4', 'Recently Added Articles', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(51, 18, 54, 55, 2, 'com_modules.module.89', 'Site Information', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(52, 18, 56, 57, 2, 'com_modules.module.88', 'Image', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
-(53, 18, 58, 59, 2, 'com_modules.module.90', 'Release News', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}');
+(53, 18, 58, 59, 2, 'com_modules.module.90', 'Release News', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
+(54, 1, 91, 92, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(55, 1, 93, 94, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
--
-- Dumping data for table `#__categories`
@@ -161,7 +163,8 @@ INSERT INTO "#__modules" ("id", "asset_id", "title", "note", "content", "orderin
(87, 0, 'Footer', '', '', 1, 'footer', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_footer', 1, 1, '{"layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(88, 52, 'Image', '', '
', 1, 'position-3', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_custom', 1, 0, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(89, 51, 'Site Information', '', '', 4, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_stats_admin', 6, 1, '{"serverinfo":"1","siteinfo":"1","counter":"1","increase":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"6","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
-(90, 53, 'Release News', '', '', 0, 'postinstall', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\\/\\/www.joomla.org\\/announcements\\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*');
+(90, 53, 'Release News', '', '', 0, 'postinstall', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\\/\\/www.joomla.org\\/announcements\\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
+(91, 54, 'Latest Actions', '', '', 0, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
--
-- Dumping data for table `#__modules_menu`
@@ -188,7 +191,8 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(83, 0),
(85, 0),
(86, 0),
-(88, 0);
+(88, 0),
+(91,54);
--
-- Dumping data for table `#__template_styles`
diff --git a/installation/sql/postgresql/sample_data.sql b/installation/sql/postgresql/sample_data.sql
index 750b2c982e8b5..692d79354e8e3 100644
--- a/installation/sql/postgresql/sample_data.sql
+++ b/installation/sql/postgresql/sample_data.sql
@@ -14,7 +14,7 @@ TRUNCATE "#__tags" RESTART IDENTITY;
--
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 0, 119, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 123, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -73,7 +73,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(59, 18, 82, 83, 2, 'com_modules.module.92', 'Image Module', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(60, 18, 84, 85, 2, 'com_modules.module.93', 'Search', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(61, 27, 19, 20, 3, 'com_content.article.1', 'Getting Started', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
-(62, 1, 117, 118, 1, '#__ucm_content.1', '#__ucm_content.1', '{}');
+(62, 1, 117, 118, 1, '#__ucm_content.1', '#__ucm_content.1', '{}'),
+(63, 1, 119, 120, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(64, 1, 121, 122, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
SELECT setval('#__assets_id_seq', max(id)) FROM "#__assets";
@@ -162,7 +164,8 @@ INSERT INTO "#__modules" ("id", "asset_id", "title", "note", "content", "orderin
(90, 57, 'Latest Articles', '', '', 1, 'position-7', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_articles_latest', 1, 1, '{"catid":[""],"count":"5","show_featured":"","ordering":"c_dsc","user_id":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(91, 58, 'User Menu', '', '', 3, 'position-7', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_menu', 1, 1, '{"menutype":"usermenu","base":"","startLevel":"1","endLevel":"0","showAllChildren":"1","tag_id":"","class_sfx":"","window_open":"","layout":"_:default","moduleclass_sfx":"_menu","cache":"1","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(92, 59, 'Image Module', '', '
', 0, 'position-3', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_custom', 1, 0, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
-(93, 60, 'Search', '', '', 0, 'position-0', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_search', 1, 1, '{"label":"","width":"20","text":"","button":"0","button_pos":"right","imagebutton":"1","button_text":"","opensearch":"1","opensearch_title":"","set_itemid":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*');
+(93, 60, 'Search', '', '', 0, 'position-0', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_search', 1, 1, '{"label":"","width":"20","text":"","button":"0","button_pos":"right","imagebutton":"1","button_text":"","opensearch":"1","opensearch_title":"","set_itemid":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
+(94, 61, 'Latest Actions', '', '', 0, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
SELECT setval('#__menu_types_id_seq', max(id)) FROM "#__menu_types";
@@ -194,7 +197,8 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(90, 0),
(91, 0),
(92, 0),
-(93, 0);
+(93, 0),
+(94, 0);
SELECT setval('#__modules_id_seq', max(id)) FROM "#__modules";
diff --git a/installation/sql/postgresql/sample_learn.sql b/installation/sql/postgresql/sample_learn.sql
index 4e600e3afa561..8a8533beb7bdf 100644
--- a/installation/sql/postgresql/sample_learn.sql
+++ b/installation/sql/postgresql/sample_learn.sql
@@ -17,7 +17,7 @@ TRUNCATE "#__viewlevels" RESTART IDENTITY;
--
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 1, 430, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 1, 434, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 2, 3, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 4, 11, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 12, 13, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -176,7 +176,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(175, 1, 422, 423, 1, 'com_tags', 'com_tags', '{"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(176, 1, 424, 425, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
(177, 1, 426, 427, 1, 'com_ajax', 'com_ajax', '{}'),
-(178, 1, 428, 429, 1, 'com_postinstall', 'com_postinstall', '{}');
+(178, 1, 428, 429, 1, 'com_postinstall', 'com_postinstall', '{}'),
+(179, 1, 430, 431, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(180, 1, 432, 433, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
SELECT setval('#__assets_id_seq', max(id)) FROM "#__assets";
@@ -589,7 +591,8 @@ INSERT INTO "#__modules" ("id", "title", "note", "content", "ordering", "positio
(87, 'Fruit Shop', '', '', 1, 'position-7', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_menu', 1, 1, '{"menutype":"fruitshop","startLevel":"1","endLevel":"0","showAllChildren":"1","tag_id":"","class_sfx":"","window_open":"","layout":"_:default","moduleclass_sfx":"","cache":"0","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(88, 'Image Module', '', '
', 1, 'position-3', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_custom', 1, 0, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(89, 'Custom', '', '
In this module you can put whatever text or other content you would like.
', 1, '', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_custom', 1, 1, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
-(90, 'Parks Image Module', '', '
', 1, 'position-3', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_custom', 1, 1, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*');
+(90, 'Parks Image Module', '', '
', 1, 'position-3', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_custom', 1, 1, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
+(91, 'Latest Actions', '', '', 0, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
SELECT setval('#__modules_id_seq', max(id)) FROM "#__modules";
@@ -788,7 +791,8 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(90, 244),
(90, 296),
(90, 399),
-(90, 400);
+(90, 400),
+(91, 0);
--
-- Dumping data for table `#__newsfeeds`
diff --git a/installation/sql/postgresql/sample_testing.sql b/installation/sql/postgresql/sample_testing.sql
index 9e5f1e03443b4..cbaf424f1c306 100644
--- a/installation/sql/postgresql/sample_testing.sql
+++ b/installation/sql/postgresql/sample_testing.sql
@@ -17,7 +17,7 @@ TRUNCATE "#__viewlevels" RESTART IDENTITY;
--
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 1, 437, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 1, 441, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 2, 3, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 4, 11, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 12, 13, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -180,7 +180,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(177, 1, 433, 434, 1, 'com_postinstall', 'com_postinstall', '{}'),
(178, 93, 144, 145, 7, 'com_content.article.71', 'Similar Tags', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(179, 1, 435, 436, 1, '#__ucm_content.3', '#__ucm_content.3', '{}'),
-(180, 93, 146, 147, 7, 'com_content.article.72', 'Popular Tags', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}');
+(180, 93, 146, 147, 7, 'com_content.article.72', 'Popular Tags', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
+(181, 1, 437, 438, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(182, 1, 439, 440, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
SELECT setval('#__assets_id_seq', max(id)) FROM "#__assets";
@@ -624,7 +626,8 @@ INSERT INTO "#__modules" ("id", "title", "note", "content", "ordering", "positio
(93, 'Popular Tags', '', '', 1, '', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_tags_popular', 1, 1, '{"maximum":"5","timeframe":"alltime","order_value":"count","order_direction":"1","display_count":0,"no_results_text":"0","minsize":1,"maxsize":2,"layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(94, 'Similar Tags', '', '', 1, '', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(95, 'Syndicate Feeds', '', '', 1, 'position-8', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_syndicate', 1, 1, '{"display_text":1,"text":"Feed Entries","format":"rss","layout":"_:default","moduleclass_sfx":"","cache":"0","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
-(97, 'Similar Tags 2', '', '', 1, 'position-8', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*');
+(97, 'Similar Tags 2', '', '', 1, 'position-8', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
+(98, 'Latest Actions', '', '', 0, 'cpanel', 0, '1970-01-01 00:00:00', '1970-01-01 00:00:00', '1970-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
SELECT setval('#__modules_id_seq', max(id)) FROM "#__modules";
@@ -812,7 +815,8 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(93, 0),
(94, 0),
(95, 0),
-(97, 0);
+(97, 0),
+(98, 0);
--
-- Dumping data for table `#__newsfeeds`
diff --git a/installation/sql/sqlazure/joomla.sql b/installation/sql/sqlazure/joomla.sql
index 7534256e54889..89ed11b34daa6 100644
--- a/installation/sql/sqlazure/joomla.sql
+++ b/installation/sql/sqlazure/joomla.sql
@@ -43,7 +43,7 @@ CREATE NONCLUSTERED INDEX "idx_parent_id" ON "#__assets"
SET IDENTITY_INSERT "#__assets" ON;
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 0, 105, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 113, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -60,25 +60,25 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(15, 1, 33, 34, 1, 'com_media', 'com_media', '{"core.admin":{"7":1},"core.manage":{"6":1},"core.create":{"3":1},"core.delete":{"5":1}}'),
(16, 1, 35, 38, 1, 'com_menus', 'com_menus', '{"core.admin":{"7":1}}'),
(17, 1, 39, 40, 1, 'com_messages', 'com_messages', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
-(18, 1, 41, 74, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'),
-(19, 1, 75, 78, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
-(20, 1, 79, 80, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'),
-(21, 1, 81, 82, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'),
-(22, 1, 83, 84, 1, 'com_search', 'com_search', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
-(23, 1, 85, 86, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'),
-(24, 1, 87, 90, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'),
-(26, 1, 91, 92, 1, 'com_wrapper', 'com_wrapper', '{}'),
+(18, 1, 41, 78, 1, 'com_modules', 'com_modules', '{"core.admin":{"7":1}}'),
+(19, 1, 79, 82, 1, 'com_newsfeeds', 'com_newsfeeds', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
+(20, 1, 83, 84, 1, 'com_plugins', 'com_plugins', '{"core.admin":{"7":1}}'),
+(21, 1, 85, 86, 1, 'com_redirect', 'com_redirect', '{"core.admin":{"7":1}}'),
+(22, 1, 87, 88, 1, 'com_search', 'com_search', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
+(23, 1, 89, 90, 1, 'com_templates', 'com_templates', '{"core.admin":{"7":1}}'),
+(24, 1, 91, 94, 1, 'com_users', 'com_users', '{"core.admin":{"7":1}}'),
+(26, 1, 95, 96, 1, 'com_wrapper', 'com_wrapper', '{}'),
(27, 8, 18, 19, 2, 'com_content.category.2', 'Uncategorised', '{}'),
(28, 3, 4, 5, 2, 'com_banners.category.3', 'Uncategorised', '{}'),
(29, 7, 14, 15, 2, 'com_contact.category.4', 'Uncategorised', '{}'),
-(30, 19, 76, 77, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'),
-(32, 24, 88, 89, 2, 'com_users.category.7', 'Uncategorised', '{}'),
-(33, 1, 93, 94, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
-(34, 1, 95, 96, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'),
-(35, 1, 97, 98, 1, 'com_tags', 'com_tags', '{}'),
-(36, 1, 99, 100, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
-(37, 1, 101, 102, 1, 'com_ajax', 'com_ajax', '{}'),
-(38, 1, 103, 104, 1, 'com_postinstall', 'com_postinstall', '{}'),
+(30, 19, 80, 81, 2, 'com_newsfeeds.category.5', 'Uncategorised', '{}'),
+(32, 24, 92, 93, 2, 'com_users.category.7', 'Uncategorised', '{}'),
+(33, 1, 97, 98, 1, 'com_finder', 'com_finder', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
+(34, 1, 99, 100, 1, 'com_joomlaupdate', 'com_joomlaupdate', '{}'),
+(35, 1, 101, 102, 1, 'com_tags', 'com_tags', '{}'),
+(36, 1, 103, 104, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
+(37, 1, 105, 106, 1, 'com_ajax', 'com_ajax', '{}'),
+(38, 1, 107, 108, 1, 'com_postinstall', 'com_postinstall', '{}'),
(39, 18, 42, 43, 2, 'com_modules.module.1', 'Main Menu', '{}'),
(40, 18, 44, 45, 2, 'com_modules.module.2', 'Login', '{}'),
(41, 18, 46, 47, 2, 'com_modules.module.3', 'Popular Articles', '{}'),
@@ -95,7 +95,11 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(52, 18, 68, 69, 2, 'com_modules.module.79', 'Multilanguage status', '{}'),
(53, 18, 70, 71, 2, 'com_modules.module.86', 'Joomla Version', '{}'),
(54, 16, 36, 37, 2, 'com_menus.menu.1', 'Main Menu', '{}'),
-(55, 18, 72, 73, 2, 'com_modules.module.87', 'Sample Data', '{}');
+(55, 18, 72, 73, 2, 'com_modules.module.87', 'Sample Data', '{}'),
+(56, 1, 109, 110, 1, 'com_privacy', 'com_privacy', '{}'),
+(57, 1, 111, 112, 1, 'com_actionlogs', 'com_actionlogs', '{}'),
+(58, 18, 74, 75, 2, 'com_modules.module.88', 'Latest Actions', '{}');
+(59, 18, 76, 77, 2, 'com_modules.module.89', 'Privacy Dashboard', '{}');
SET IDENTITY_INSERT "#__assets" OFF;
@@ -749,6 +753,8 @@ INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "elem
(32, 0, 'com_postinstall', 'component', 'com_postinstall', '', 1, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(33, 0, 'com_fields', 'component', 'com_fields', '', 1, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(34, 0, 'com_associations', 'component', 'com_associations', '', 1, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(35, 0, 'com_privacy', 'component', 'com_privacy', '', 1, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(36, 0, 'com_actionlogs', 'component', 'com_actionlogs', '', 1, 1, 1, 1, '', '{"ip_logging":0,"csv_delimiter":",","loggable_extensions":["com_banners","com_cache","com_categories","com_config","com_contact","com_content","com_installer","com_media","com_menus","com_messages","com_modules","com_newsfeeds","com_plugins","com_redirect","com_tags","com_templates","com_users"]}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(102, 0, 'phputf8', 'library', 'phputf8', '', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(103, 0, 'Joomla! Platform', 'library', 'joomla', '', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(104, 0, 'IDNA Convert', 'library', 'idna_convert', '', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
@@ -795,6 +801,8 @@ INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "elem
(316, 0, 'mod_tags_popular', 'module', 'mod_tags_popular', '', 0, 1, 1, 0, '', '{"maximum":"5","timeframe":"alltime","owncache":"1"}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(317, 0, 'mod_tags_similar', 'module', 'mod_tags_similar', '', 0, 1, 1, 0, '', '{"maximum":"5","matchtype":"any","owncache":"1"}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(318, 0, 'mod_sampledata', 'module', 'mod_sampledata', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(319, 0, 'mod_latestactions', 'module', 'mod_latestactions', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(320, 0, 'mod_privacy_dashboard', 'module', 'mod_privacy_dashboard', '', 1, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(400, 0, 'plg_authentication_gmail', 'plugin', 'gmail', 'authentication', 0, 0, 1, 0, '', '{"applysuffix":"0","suffix":"","verifypeer":"1","user_blacklist":""}', '', '', 0, '1900-01-01 00:00:00', 1, 0),
(401, 0, 'plg_authentication_joomla', 'plugin', 'joomla', 'authentication', 0, 1, 1, 1, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(402, 0, 'plg_authentication_ldap', 'plugin', 'ldap', 'authentication', 0, 0, 1, 0, '', '{"host":"","port":"389","use_ldapV3":"0","negotiate_tls":"0","no_referrals":"0","auth_method":"bind","base_dn":"","search_string":"","users_dn":"","username":"admin","password":"bobby7","ldap_fullname":"fullName","ldap_email":"mail","ldap_uid":"uid"}', '', '', 0, '1900-01-01 00:00:00', 3, 0),
@@ -874,6 +882,18 @@ INSERT INTO "#__extensions" ("extension_id", "package_id", "name", "type", "elem
(479, 0, 'plg_sampledata_blog', 'plugin', 'blog', 'sampledata', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(480, 0, 'plg_system_sessiongc', 'plugin', 'sessiongc', 'system', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(481, 0, 'plg_fields_repeatable', 'plugin', 'repeatable', 'fields', 0, 1, 1, 0, '', '', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(482, 0, 'plg_content_confirmconsent', 'plugin', 'confirmconsent', 'content', 0, 0, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(483, 0, 'plg_system_actionlogs', 'plugin', 'actionlogs', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(484, 0, 'plg_actionlog_joomla', 'plugin', 'joomla', 'actionlog', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(485, 0, 'plg_system_privacyconsent', 'plugin', 'privacyconsent', 'system', 0, 0, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(486, 0, 'plg_system_logrotation', 'plugin', 'logrotation', 'system', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(487, 0, 'plg_privacy_user', 'plugin', 'user', 'privacy', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(488, 0, 'plg_quickicon_privacycheck', 'plugin', 'privacycheck', 'quickicon', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(489, 0, 'plg_user_terms', 'plugin', 'terms', 'user', 0, 0, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(490, 0, 'plg_privacy_contact', 'plugin', 'user', 'contact', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(491, 0, 'plg_privacy_content', 'plugin', 'user', 'content', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(492, 0, 'plg_privacy_message', 'plugin', 'user', 'message', 0, 1, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
+(493, 0, 'plg_privacy_actionlogs', 'plugin', 'actionlogs', 'privacy', 0, 0, 1, 0, '', '{}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(503, 0, 'beez3', 'template', 'beez3', '', 0, 1, 1, 0, '', '{"wrapperSmall":"53","wrapperLarge":"72","sitetitle":"","sitedescription":"","navposition":"center","templatecolor":"nature"}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(504, 0, 'hathor', 'template', 'hathor', '', 1, 1, 1, 0, '', '{"showSiteName":"0","colourChoice":"0","boldText":"0"}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
(506, 0, 'protostar', 'template', 'protostar', '', 0, 1, 1, 0, '', '{"templateColor":"","logoFile":"","googleFont":"1","googleFontName":"Open+Sans","fluidContainer":"0"}', '', '', 0, '1900-01-01 00:00:00', 0, 0),
@@ -2175,7 +2195,9 @@ INSERT INTO "#__modules" ("id", "asset_id", "title", "note", "content", "orderin
(17, 51, 'Breadcrumbs', '', '', 1, 'position-2', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_breadcrumbs', 1, 1, '{"moduleclass_sfx":"","showHome":"1","homeText":"","showComponent":"1","separator":"","cache":"0","cache_time":"0","cachemode":"itemid"}', 0, '*'),
(79, 52, 'Multilanguage status', '', '', 1, 'status', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 0, 'mod_multilangstatus', 3, 1, '{"layout":"_:default","moduleclass_sfx":"","cache":"0"}', 1, '*'),
(86, 53, 'Joomla Version', '', '', 1, 'footer', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_version', 3, 1, '{"format":"short","product":"1","layout":"_:default","moduleclass_sfx":"","cache":"0"}', 1, '*'),
-(87, 55, 'Sample Data', '', '', 0, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_sampledata', 6, 1, '{}', 1, '*');
+(87, 55, 'Sample Data', '', '', 0, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_sampledata', 6, 1, '{}', 1, '*'),
+(88, 58, 'Latest Actions', '', '', 0, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*'),
+(89, 59, 'Privacy Dashboard', '', '', 0, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_privacy_dashboard', 6, 1, '{}', 1, '*');
SET IDENTITY_INSERT "#__modules" OFF;
@@ -2215,7 +2237,9 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(17, 0),
(79, 0),
(86, 0),
-(87, 0);
+(87, 0),
+(88, 0),
+(89, 0);
--
-- Table structure for table `#__newsfeeds`
@@ -2344,7 +2368,53 @@ INSERT INTO "#__postinstall_messages" ("extension_id", "title_key", "description
(700, 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_BODY', 'PLG_SYSTEM_UPDATENOTIFICATION_POSTINSTALL_UPDATECACHETIME_ACTION', 'plg_system_updatenotification', 1, 'action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_action', 'site://plugins/system/updatenotification/postinstall/updatecachetime.php', 'updatecachetime_postinstall_condition', '3.6.3', 1),
(700, 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_TITLE', 'COM_CPANEL_MSG_JOOMLA40_PRE_CHECKS_BODY', '', 'com_cpanel', 1, 'message', '', '', 'admin://components/com_admin/postinstall/joomla40checks.php', 'admin_postinstall_joomla40checks_condition', '3.7.0', 1),
(700, 'TPL_HATHOR_MESSAGE_POSTINSTALL_TITLE', 'TPL_HATHOR_MESSAGE_POSTINSTALL_BODY', 'TPL_HATHOR_MESSAGE_POSTINSTALL_ACTION', 'tpl_hathor', 1, 'action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_action', 'admin://templates/hathor/postinstall/hathormessage.php', 'hathormessage_postinstall_condition', '3.7.0', 1),
-(700, 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_TITLE', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_BODY', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_ACTION', 'plg_captcha_recaptcha', 1, 'action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_condition', '3.8.6', 1);
+(700, 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_TITLE', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_BODY', 'PLG_PLG_RECAPTCHA_VERSION_1_POSTINSTALL_ACTION', 'plg_captcha_recaptcha', 1, 'action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_action', 'site://plugins/captcha/recaptcha/postinstall/actions.php', 'recaptcha_postinstall_condition', '3.8.6', 1),
+(700, 'COM_ACTIONLOGS_POSTINSTALL_TITLE', 'COM_ACTIONLOGS_POSTINSTALL_BODY', '', 'com_actionlogs', 1, 'message', '', '', '', '', '3.9.0', 1),
+(700, 'COM_PRIVACY_POSTINSTALL_TITLE', 'COM_PRIVACY_POSTINSTALL_BODY', '', 'com_privacy', 1, 'message', '', '', '', '', '3.9.0', 1);
+
+--
+-- Table structure for table `#__privacy_requests`
+--
+
+CREATE TABLE "#__privacy_requests" (
+ "id" int IDENTITY(1,1) NOT NULL,
+ "email" nvarchar(100) NOT NULL DEFAULT '',
+ "requested_at" datetime2(0) NOT NULL DEFAULT '1900-01-01 00:00:00',
+ "status" smallint NOT NULL,
+ "request_type" nvarchar(25) NOT NULL DEFAULT '',
+ "confirm_token" nvarchar(100) NOT NULL DEFAULT '',
+ "confirm_token_created_at" datetime2(0) NOT NULL DEFAULT '1900-01-01 00:00:00',
+ "checked_out" bigint NOT NULL DEFAULT 0,
+ "checked_out_time" datetime2(0) NOT NULL DEFAULT '1900-01-01 00:00:00',
+CONSTRAINT "PK_#__privacy_requests_id" PRIMARY KEY CLUSTERED(
+ "id" ASC)
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
+) ON [PRIMARY]) ON [PRIMARY];
+
+CREATE NONCLUSTERED INDEX "idx_checkout" ON "#__privacy_requests" (
+ "checked_out" ASC)
+WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
+
+--
+-- Table structure for table `#__privacy_consents`
+--
+
+CREATE TABLE "#__privacy_consents" (
+ "id" int IDENTITY(1,1) NOT NULL,
+ "user_id" bigint NOT NULL DEFAULT 0,
+ "created" datetime2(0) NOT NULL DEFAULT '1900-01-01 00:00:00',
+ "subject" nvarchar(255) NOT NULL DEFAULT '',
+ "body" nvarchar(max) NOT NULL,
+ "remind" smallint NOT NULL,
+ "token" nvarchar(100) NOT NULL DEFAULT '',
+CONSTRAINT "PK_#__privacy_consents_id" PRIMARY KEY CLUSTERED(
+ "id" ASC)
+WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
+) ON [PRIMARY]) ON [PRIMARY];
+
+CREATE NONCLUSTERED INDEX "idx_user_id" ON "#__privacy_consents" (
+ "user_id" ASC)
+WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF);
--
-- Table structure for table `#__redirect_links`
@@ -2995,6 +3065,132 @@ CREATE TABLE "#__user_usergroup_map" (
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY];
+/****** Object: Table [#__action_logs] ******/
+SET QUOTED_IDENTIFIER ON;
+
+CREATE TABLE [#__action_logs](
+ [id] [int] IDENTITY(1,1) NOT NULL,
+ [message_language_key] [nvarchar](255) NOT NULL DEFAULT '',
+ [message] [nvarchar](max) NOT NULL DEFAULT '',
+ [log_date] [datetime] NOT NULL DEFAULT '1900-01-01 00:00:00',
+ [extension] [nvarchar](255) NOT NULL DEFAULT '',
+ [user_id] [bigint] NOT NULL DEFAULT 0,
+ [item_id] [bigint] NOT NULL DEFAULT 0,
+ [ip_address] [nvarchar](40) NOT NULL DEFAULT '0.0.0.0',
+ CONSTRAINT [PK_#__action_logs_id] PRIMARY KEY CLUSTERED
+ (
+ [id] ASC
+ )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+ ) ON [PRIMARY];
+
+/****** Object: Table [#__action_logs_extensions] ******/
+SET QUOTED_IDENTIFIER ON;
+
+CREATE TABLE [#__action_logs_extensions](
+ [id] [int] IDENTITY(1,1) NOT NULL,
+ [extension] [nvarchar](255) NOT NULL DEFAULT '',
+ CONSTRAINT [PK_#__action_logs_extensions_id] PRIMARY KEY CLUSTERED
+ (
+ [id] ASC
+ )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+ ) ON [PRIMARY];
+SET IDENTITY_INSERT [#__action_logs_extensions] ON;
+INSERT INTO [#__action_logs_extensions] ([id], [extension])
+SELECT 1, 'com_banners'
+UNION ALL
+SELECT 2, 'com_cache'
+UNION ALL
+SELECT 3, 'com_categories'
+UNION ALL
+SELECT 4, 'com_config'
+UNION ALL
+SELECT 5, 'com_contact'
+UNION ALL
+SELECT 6, 'com_content'
+UNION ALL
+SELECT 7, 'com_installer'
+UNION ALL
+SELECT 8, 'com_media'
+UNION ALL
+SELECT 9, 'com_menus'
+UNION ALL
+SELECT 10, 'com_messages'
+UNION ALL
+SELECT 11, 'com_modules'
+UNION ALL
+SELECT 12, 'com_newsfeeds'
+UNION ALL
+SELECT 13, 'com_plugins'
+UNION ALL
+SELECT 14, 'com_redirect'
+UNION ALL
+SELECT 15, 'com_tags'
+UNION ALL
+SELECT 16, 'com_templates'
+UNION ALL
+SELECT 17, 'com_users';
+
+SET IDENTITY_INSERT [#__action_logs_extensions] OFF;
+/****** Object: Table [#__action_log_config] ******/
+SET QUOTED_IDENTIFIER ON;
+
+CREATE TABLE [#__action_log_config](
+ [id] [int] IDENTITY(1,1) NOT NULL,
+ [type_title] [nvarchar](255) NOT NULL DEFAULT '',
+ [type_alias] [nvarchar](255) NOT NULL DEFAULT '',
+ [id_holder] [nvarchar](255) NULL,
+ [title_holder] [nvarchar](255) NULL,
+ [table_name] [nvarchar](255) NULL,
+ [text_prefix] [nvarchar](255) NULL
+ CONSTRAINT [PK_#__action_log_config_id] PRIMARY KEY CLUSTERED
+ (
+ [id] ASC
+ )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
+ ) ON [PRIMARY];
+
+SET IDENTITY_INSERT [#__action_log_config] ON;
+
+INSERT INTO [#__action_log_config] ([id], [type_title], [type_alias], [id_holder], [title_holder], [table_name], [text_prefix])
+SELECT 1, 'article', 'com_content.article', 'id' ,'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 2, 'article', 'com_content.form', 'id', 'title' , '#__content', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 3, 'banner', 'com_banners.banner', 'id' ,'name' , '#__banners', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 4, 'user_note', 'com_users.note', 'id', 'subject' ,'#__user_notes', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 5, 'media', 'com_media.file', '' , 'name' , '', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 6, 'category', 'com_categories.category', 'id' , 'title' , '#__categories', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 7, 'menu', 'com_menus.menu', 'id' ,'title' , '#__menu_types', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 8, 'menu_item', 'com_menus.item', 'id' , 'title' , '#__menu', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 9, 'newsfeed', 'com_newsfeeds.newsfeed', 'id' ,'name' , '#__newsfeeds', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 10, 'link', 'com_redirect.link', 'id', 'old_url' , '#__redirect_links', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 11, 'tag', 'com_tags.tag', 'id', 'title' , '#__tags', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 12, 'style', 'com_templates.style', 'id' , 'title' , '#__template_styles', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 13, 'plugin', 'com_plugins.plugin', 'extension_id' , 'name' , '#__extensions', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 14, 'component_config', 'com_config.component', 'extension_id' , 'name', '', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 15, 'contact', 'com_contact.contact', 'id', 'name', '#__contact_details', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 16, 'module', 'com_modules.module', 'id' ,'title', '#__modules', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 17, 'access_level', 'com_users.level', 'id' , 'title', '#__viewlevels', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 18, 'banner_client', 'com_banners.client', 'id', 'name', '#__banner_clients', 'PLG_ACTIONLOG_JOOMLA'
+UNION ALL
+SELECT 19, 'application_config', 'com_config.application', '', 'name', '', 'PLG_ACTIONLOG_JOOMLA';
+
+SET IDENTITY_INSERT [#__action_log_config] OFF;
+
--
-- Table structure for table `#__viewlevels`
--
diff --git a/installation/sql/sqlazure/sample_blog.sql b/installation/sql/sqlazure/sample_blog.sql
index 3ac5714abec02..3ca86fbe28875 100644
--- a/installation/sql/sqlazure/sample_blog.sql
+++ b/installation/sql/sqlazure/sample_blog.sql
@@ -16,7 +16,7 @@ TRUNCATE TABLE "#__modules_menu";
SET IDENTITY_INSERT "#__assets" ON;
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 0, 87, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 91, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -59,7 +59,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(44, 1, 79, 80, 1, 'com_tags', 'com_tags', '{"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(45, 1, 81, 82, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
(46, 1, 83, 84, 1, 'com_ajax', 'com_ajax', '{}'),
-(47, 1, 85, 86, 1, 'com_postinstall', 'com_postinstall', '{}');
+(47, 1, 85, 86, 1, 'com_postinstall', 'com_postinstall', '{}'),
+(48, 1, 87, 88, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(49, 1, 89, 90, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
SET IDENTITY_INSERT "#__assets" OFF;
@@ -183,7 +185,8 @@ INSERT INTO "#__modules" ("id", "title", "note", "content", "ordering", "positio
(89, 'Popular Tags', '', '', 1, 'position-7', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_tags_popular', 1, 1, '{"maximum":"8","timeframe":"alltime","order_value":"count","order_direction":"1","display_count":0,"no_results_text":"0","minsize":1,"maxsize":2,"layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(90, 'Similar Items', '', '', 0, '', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(91, 'Site Information', '', '', 4, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_stats_admin', 6, 1, '{"serverinfo":"1","siteinfo":"1","counter":"0","increase":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"6","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
-(92, 'Release News', '', '', 1, 'postinstall', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\/\/www.joomla.org\/announcements\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*');
+(92, 'Release News', '', '', 1, 'postinstall', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\/\/www.joomla.org\/announcements\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
+(93, 'Latest Actions', '', '', 0, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
SET IDENTITY_INSERT "#__modules" OFF;
@@ -219,4 +222,5 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(89, 0),
(90, 0),
(91, 0),
-(92, 0);
+(92, 0),
+(93, 0);
diff --git a/installation/sql/sqlazure/sample_brochure.sql b/installation/sql/sqlazure/sample_brochure.sql
index 1800e89cade07..2c864c3882544 100644
--- a/installation/sql/sqlazure/sample_brochure.sql
+++ b/installation/sql/sqlazure/sample_brochure.sql
@@ -17,7 +17,7 @@ TRUNCATE TABLE "#__template_styles";
SET IDENTITY_INSERT "#__assets" ON;
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 0, 91, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 95, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -62,7 +62,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(50, 18, 52, 53, 2, 'com_modules.module.4', 'Recently Added Articles', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(51, 18, 54, 55, 2, 'com_modules.module.89', 'Site Information', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(52, 18, 56, 57, 2, 'com_modules.module.88', 'Image', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
-(53, 18, 58, 59, 2, 'com_modules.module.90', 'Release News', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}');
+(53, 18, 58, 59, 2, 'com_modules.module.90', 'Release News', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
+(54, 1, 91, 92, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(55, 1, 93, 94, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
SET IDENTITY_INSERT "#__assets" OFF;
@@ -187,7 +189,8 @@ INSERT INTO "#__modules" ("id", "asset_id", "title", "note", "content", "orderin
(87, 0, 'Footer', '', '', 1, 'footer', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_footer', 1, 1, '{"layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(88, 52, 'Image', '', '
', 1, 'position-3', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_custom', 1, 0, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(89, 51, 'Site Information', '', '', 4, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_stats_admin', 6, 1, '{"serverinfo":"1","siteinfo":"1","counter":"1","increase":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"6","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
-(90, 53, 'Release News', '', '', 0, 'postinstall', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\/\/www.joomla.org\/announcements\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*');
+(90, 53, 'Release News', '', '', 0, 'postinstall', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_feed', 1, 1, '{"rssurl":"https:\/\/www.joomla.org\/announcements\/release-news.feed","rssrtl":"0","rsstitle":"1","rssdesc":"1","rssimage":"1","rssitems":"3","rssitemdesc":"1","word_count":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 1, '*'),
+(91, 54, 'Latest Actions', '', '', 0, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
SET IDENTITY_INSERT "#__modules" OFF;
@@ -216,7 +219,8 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(83, 0),
(85, 0),
(86, 0),
-(88, 0);
+(88, 0),
+(91, 54);
--
-- Dumping data for table `#__template_styles`
diff --git a/installation/sql/sqlazure/sample_data.sql b/installation/sql/sqlazure/sample_data.sql
index e9d17a380561f..62f36caeaa1a2 100644
--- a/installation/sql/sqlazure/sample_data.sql
+++ b/installation/sql/sqlazure/sample_data.sql
@@ -16,7 +16,7 @@ TRUNCATE TABLE "#__tags";
SET IDENTITY_INSERT "#__assets" ON;
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 0, 119, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 0, 123, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.login.offline":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 1, 2, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 3, 6, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 7, 8, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -75,7 +75,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(59, 18, 82, 83, 2, 'com_modules.module.92', 'Image Module', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(60, 18, 84, 85, 2, 'com_modules.module.93', 'Search', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(61, 27, 19, 20, 3, 'com_content.article.1', 'Getting Started', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
-(62, 1, 117, 118, 1, '#__ucm_content.1', '#__ucm_content.1', '{}');
+(62, 1, 117, 118, 1, '#__ucm_content.1', '#__ucm_content.1', '{}'),
+(63, 1, 119, 120, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(64, 1, 121, 122, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
SET IDENTITY_INSERT "#__assets" OFF;
@@ -174,7 +176,8 @@ INSERT INTO "#__modules" ("id", "asset_id", "title", "note", "content", "orderin
(90, 57, 'Latest Articles', '', '', 1, 'position-7', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_articles_latest', 1, 1, '{"catid":[""],"count":"5","show_featured":"","ordering":"c_dsc","user_id":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(91, 58, 'User Menu', '', '', 3, 'position-7', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_menu', 1, 1, '{"menutype":"usermenu","base":"","startLevel":"1","endLevel":"0","showAllChildren":"1","tag_id":"","class_sfx":"","window_open":"","layout":"_:default","moduleclass_sfx":"_menu","cache":"1","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(92, 59, 'Image Module', '', '
', 0, 'position-3', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_custom', 1, 0, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
-(93, 60, 'Search', '', '', 0, 'position-0', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_search', 1, 1, '{"label":"","width":"20","text":"","button":"0","button_pos":"right","imagebutton":"1","button_text":"","opensearch":"1","opensearch_title":"","set_itemid":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*');
+(93, 60, 'Search', '', '', 0, 'position-0', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_search', 1, 1, '{"label":"","width":"20","text":"","button":"0","button_pos":"right","imagebutton":"1","button_text":"","opensearch":"1","opensearch_title":"","set_itemid":"0","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
+(94, 61, 'Latest Actions', '', '', 0, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
SET IDENTITY_INSERT "#__modules" OFF;
@@ -206,7 +209,8 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(90, 0),
(91, 0),
(92, 0),
-(93, 0);
+(93, 0),
+(94, 0);
--
-- Dumping data for table `#__tags`
diff --git a/installation/sql/sqlazure/sample_learn.sql b/installation/sql/sqlazure/sample_learn.sql
index 0cef0e24cbea0..c292dcd1099d7 100644
--- a/installation/sql/sqlazure/sample_learn.sql
+++ b/installation/sql/sqlazure/sample_learn.sql
@@ -19,7 +19,7 @@ TRUNCATE TABLE "#__viewlevels";
SET IDENTITY_INSERT "#__assets" ON;
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 1, 430, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 1, 434, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 2, 3, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 4, 11, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 12, 13, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -178,7 +178,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(175, 1, 422, 423, 1, 'com_tags', 'com_tags', '{"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(176, 1, 424, 425, 1, 'com_contenthistory', 'com_contenthistory', '{}'),
(177, 1, 426, 427, 1, 'com_ajax', 'com_ajax', '{}'),
-(178, 1, 428, 429, 1, 'com_postinstall', 'com_postinstall', '{}');
+(178, 1, 428, 429, 1, 'com_postinstall', 'com_postinstall', '{}'),
+(179, 1, 430, 431, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(180, 1, 432, 433, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
SET IDENTITY_INSERT "#__assets" OFF;
@@ -607,7 +609,8 @@ INSERT INTO "#__modules" ("id", "title", "note", "content", "ordering", "positio
(87, 'Fruit Shop', '', '', 1, 'position-7', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_menu', 1, 1, '{"menutype":"fruitshop","startLevel":"1","endLevel":"0","showAllChildren":"1","tag_id":"","class_sfx":"","window_open":"","layout":"_:default","moduleclass_sfx":"","cache":"0","cache_time":"900","cachemode":"itemid","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(88, 'Image Module', '', '
', 1, 'position-3', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_custom', 1, 0, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(89, 'Custom', '', '
In this module you can put whatever text or other content you would like.
', 1, '', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_custom', 1, 1, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
-(90, 'Parks Image Module', '', '
', 1, 'position-3', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_custom', 1, 1, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*');
+(90, 'Parks Image Module', '', '
', 1, 'position-3', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_custom', 1, 1, '{"prepare_content":"1","backgroundimage":"","layout":"_:default","moduleclass_sfx":"","cache":"1","cache_time":"900","cachemode":"static","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
+(91, 'Latest Actions', '', '', 0, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
SET IDENTITY_INSERT "#__modules" OFF;
@@ -806,7 +809,8 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(90, 244),
(90, 296),
(90, 399),
-(90, 400);
+(90, 400),
+(91, 0);
--
-- Dumping data for table `#__newsfeeds`
diff --git a/installation/sql/sqlazure/sample_testing.sql b/installation/sql/sqlazure/sample_testing.sql
index 0c294984a988c..ba7b8a5bf59f6 100644
--- a/installation/sql/sqlazure/sample_testing.sql
+++ b/installation/sql/sqlazure/sample_testing.sql
@@ -19,7 +19,7 @@ TRUNCATE TABLE [#__viewlevels];
SET IDENTITY_INSERT "#__assets" ON;
INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "title", "rules") VALUES
-(1, 0, 1, 437, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
+(1, 0, 1, 441, 0, 'root.1', 'Root Asset', '{"core.login.site":{"6":1,"2":1},"core.login.admin":{"6":1},"core.admin":{"8":1},"core.manage":{"7":1},"core.create":{"6":1,"3":1},"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1},"core.edit.own":{"6":1,"3":1}}'),
(2, 1, 2, 3, 1, 'com_admin', 'com_admin', '{}'),
(3, 1, 4, 11, 1, 'com_banners', 'com_banners', '{"core.admin":{"7":1},"core.manage":{"6":1}}'),
(4, 1, 12, 13, 1, 'com_cache', 'com_cache', '{"core.admin":{"7":1},"core.manage":{"7":1}}'),
@@ -182,7 +182,9 @@ INSERT INTO "#__assets" ("id", "parent_id", "lft", "rgt", "level", "name", "titl
(177, 1, 433, 434, 1, 'com_postinstall', 'com_postinstall', '{}'),
(178, 93, 144, 145, 7, 'com_content.article.71', 'Similar Tags', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
(179, 1, 435, 436, 1, '#__ucm_content.3', '#__ucm_content.3', '{}'),
-(180, 93, 146, 147, 7, 'com_content.article.72', 'Popular Tags', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}');
+(180, 93, 146, 147, 7, 'com_content.article.72', 'Popular Tags', '{"core.delete":{"6":1},"core.edit":{"6":1,"4":1},"core.edit.state":{"6":1,"5":1}}'),
+(181, 1, 437, 438, 1, 'com_privacy', 'com_privacy', '{"core.admin":{"7":1}}'),
+(182, 1, 439, 440, 1, 'com_actionlogs', 'com_actionlogs', '{"core.admin":{"7":1}}');
SET IDENTITY_INSERT "#__assets" OFF;
@@ -641,7 +643,8 @@ INSERT INTO "#__modules" ("id", "title", "note", "content", "ordering", "positio
(93, 'Popular Tags', '', '', 1, '', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_tags_popular', 1, 1, '{"maximum":"5","timeframe":"alltime","order_value":"count","order_direction":"1","display_count":0,"no_results_text":"0","minsize":1,"maxsize":2,"layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(94, 'Similar Tags', '', '', 1, '', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
(95, 'Syndicate Feeds', '', '', 1, 'position-8', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_syndicate', 1, 1, '{"display_text":1,"text":"Feed Entries","format":"rss","layout":"_:default","moduleclass_sfx":"","cache":"0","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
-(97, 'Similar Tags 2', '', '', 1, 'position-8', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*');
+(97, 'Similar Tags 2', '', '', 1, 'position-8', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_tags_similar', 1, 1, '{"maximum":"5","matchtype":"any","layout":"_:default","moduleclass_sfx":"","owncache":"1","module_tag":"div","bootstrap_size":"0","header_tag":"h3","header_class":"","style":"0"}', 0, '*'),
+(98, 'Latest Actions', '', '', 0, 'cpanel', 0, '1900-01-01 00:00:00', '1900-01-01 00:00:00', '1900-01-01 00:00:00', 1, 'mod_latestactions', 6, 1, '{}', 1, '*');
SET IDENTITY_INSERT "#__modules" OFF;
@@ -829,7 +832,8 @@ INSERT INTO "#__modules_menu" ("moduleid", "menuid") VALUES
(93, 0),
(94, 0),
(95, 0),
-(97, 0);
+(97, 0),
+(98, 0);
--
-- Dumping data for table `#__newsfeeds`
diff --git a/language/en-GB/en-GB.com_privacy.ini b/language/en-GB/en-GB.com_privacy.ini
new file mode 100644
index 0000000000000..4f93e9774eecf
--- /dev/null
+++ b/language/en-GB/en-GB.com_privacy.ini
@@ -0,0 +1,53 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+COM_PRIVACY="Privacy"
+COM_PRIVACY_ADMIN_NOTIFICATION_USER_CONFIRMED_REQUEST_MESSAGE="User %1$s has confirmed their information request."
+COM_PRIVACY_ADMIN_NOTIFICATION_USER_CONFIRMED_REQUEST_SUBJECT="Information Request Confirmed By User"
+COM_PRIVACY_ADMIN_NOTIFICATION_USER_CREATED_REQUEST_MESSAGE="A new information request has been submitted by %1$s."
+COM_PRIVACY_ADMIN_NOTIFICATION_USER_CREATED_REQUEST_SUBJECT="Information Request Submitted"
+COM_PRIVACY_CONFIRM_REMIND_SUCCEEDED="Your consent to this web site's Privacy Policy has been extended."
+COM_PRIVACY_CONFIRM_REQUEST_FIELDSET_LABEL="An email has been sent to your email address. The email has a confirmation token, please confirm your email address again and paste the confirmation token in the field below to prove that you are the owner of the information being requested."
+COM_PRIVACY_CONFIRM_REQUEST_SUCCEEDED="Your information request has been confirmed."
+COM_PRIVACY_CREATE_REQUEST_SUCCEEDED="Your information request has been created. Before it can be processed, you must verify this request. An email has been sent to your address with additional instructions to complete this verification."
+; You can use the following merge codes for all COM_PRIVACY_EMAIL strings:
+; [SITENAME] Site name, as set in Global Configuration.
+; [URL] URL of the site's frontend page.
+; [TOKENURL] URL of the confirm page with the token prefilled.
+; [FORMURL] URL of the confirm page where the user can paste their token.
+; [TOKEN] The confirmation token.
+; \n Newline character. Use it to start a new line in the email.
+COM_PRIVACY_EMAIL_REQUEST_BODY_EXPORT_REQUEST="Someone has created a request to export all personal information related to this email address at [URL]. As a security measure, you must confirm that this is a valid request for your personal information from this website.\n\nIn order to confirm this request, you can complete one of the following tasks:\n\n1. Visit the following URL: [TOKENURL]\n\n2. Copy your token from this email, visit the referenced URL, and paste your token into the form.\nURL: [FORMURL]\nToken: [TOKEN]\n\nPlease note that this token is only valid for 24 hours from the time this email was sent."
+COM_PRIVACY_EMAIL_REQUEST_BODY_REMOVE_REQUEST="Someone has created a request to remove all personal information related to this email address at [URL]. As a security measure, you must confirm that this is a valid request for your personal information to be removed from this website.\n\nIn order to confirm this request, you can complete one of the following tasks:\n\n1. Visit the following URL: [TOKENURL]\n\n2. Copy your token from this email, visit the referenced URL, and paste your token into the form.\nURL: [FORMURL]\nToken: [TOKEN]\n\nPlease note that this token is only valid for 24 hours from the time this email was sent."
+COM_PRIVACY_EMAIL_REQUEST_SUBJECT_EXPORT_REQUEST="Information Request Created at [SITENAME]"
+COM_PRIVACY_EMAIL_REQUEST_SUBJECT_REMOVE_REQUEST="Information Deletion Request Created at [SITENAME]"
+COM_PRIVACY_ERROR_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED="An information request can't be created when email support is disabled."
+COM_PRIVACY_ERROR_CHECKING_FOR_EXISTING_REQUESTS="There was an error checking for existing information requests, please try submitting this request again."
+COM_PRIVACY_ERROR_CONFIRM_TOKEN_EXPIRED="The confirmation token for your information request has expired. You will need to submit a new request."
+COM_PRIVACY_ERROR_CONFIRMING_REMIND_FAILED="No expiration reminder was found."
+COM_PRIVACY_ERROR_CONFIRMING_REQUEST="Error while confirming the information request."
+COM_PRIVACY_ERROR_CONFIRMING_REQUEST_FAILED="Your information request confirmation failed. %s"
+COM_PRIVACY_ERROR_CREATING_REQUEST="Error while creating the information request."
+COM_PRIVACY_ERROR_CREATING_REQUEST_FAILED="Your information request could not be created. %s"
+COM_PRIVACY_ERROR_NO_PENDING_REMIND="No expiration reminder has been sent yet."
+COM_PRIVACY_ERROR_NO_PENDING_REQUESTS="There are no information requests for this email address requiring confirmation."
+COM_PRIVACY_ERROR_NO_REMIND_REQUESTS="Please re-check the token"
+COM_PRIVACY_ERROR_PENDING_REQUEST_OPEN="There is already an active information request for this email address and request type. Please contact the site owner for updates on this request."
+COM_PRIVACY_ERROR_REMIND_REQUEST="An error occurred while processing your request."
+COM_PRIVACY_ERROR_UNKNOWN_REQUEST_TYPE="Unknown information request type."
+COM_PRIVACY_FIELD_CONFIRM_CONFIRM_TOKEN_DESC="Enter the confirmation token you received by email."
+COM_PRIVACY_FIELD_CONFIRM_CONFIRM_TOKEN_LABEL="Confirmation Token"
+COM_PRIVACY_FIELD_CONFIRM_EMAIL_DESC="Enter your email address."
+COM_PRIVACY_FIELD_REMIND_CONFIRM_TOKEN_DESC="Enter the confirmation token you received by email."
+COM_PRIVACY_FIELD_REMIND_CONFIRM_TOKEN_LABEL="Confirmation Token"
+COM_PRIVACY_FIELD_REQUEST_TYPE_DESC="The type of information request."
+COM_PRIVACY_FIELD_REQUEST_TYPE_LABEL="Request Type"
+COM_PRIVACY_FIELD_STATUS_DESC="The status of the information request."
+COM_PRIVACY_REMIND_REQUEST_FIELDSET_LABEL="Renew Privacy Consent"
+COM_PRIVACY_REQUEST_TYPE_EXPORT="Export"
+COM_PRIVACY_REQUEST_TYPE_REMOVE="Remove"
+COM_PRIVACY_VIEW_CONFIRM_PAGE_TITLE="Confirm Information Request"
+COM_PRIVACY_VIEW_REQUEST_PAGE_TITLE="Submit Information Request"
+COM_PRIVACY_WARNING_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED="We're sorry, you can't submit an information request at this time."
diff --git a/libraries/src/Document/XmlDocument.php b/libraries/src/Document/XmlDocument.php
index 1ed2a73f915ed..e7a7b9b428e70 100644
--- a/libraries/src/Document/XmlDocument.php
+++ b/libraries/src/Document/XmlDocument.php
@@ -25,6 +25,14 @@ class XmlDocument extends Document
*/
protected $name = 'joomla';
+ /**
+ * Flag indicating the document should be downloaded (Content-Disposition = attachment) versus displayed inline
+ *
+ * @var boolean
+ * @since __DEPLOY_VERSION__
+ */
+ protected $isDownload = false;
+
/**
* Class constructor
*
@@ -57,7 +65,9 @@ public function render($cache = false, $params = array())
{
parent::render();
- \JFactory::getApplication()->setHeader('Content-disposition', 'inline; filename="' . $this->getName() . '.xml"', true);
+ $disposition = $this->isDownload ? 'attachment' : 'inline';
+
+ \JFactory::getApplication()->setHeader('Content-disposition', $disposition . '; filename="' . $this->getName() . '.xml"', true);
return $this->getBuffer();
}
@@ -89,4 +99,32 @@ public function setName($name = 'joomla')
return $this;
}
+
+ /**
+ * Check if this document is intended for download
+ *
+ * @return string
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function isDownload()
+ {
+ return $this->isDownload;
+ }
+
+ /**
+ * Sets the document's download state
+ *
+ * @param boolean $download If true, this document will be downloaded; if false, this document will be displayed inline
+ *
+ * @return XmlDocument instance of $this to allow chaining
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function setDownload($download = false)
+ {
+ $this->isDownload = $download;
+
+ return $this;
+ }
}
diff --git a/libraries/src/Extension/ExtensionHelper.php b/libraries/src/Extension/ExtensionHelper.php
index e1e4baf3bba0c..c90592aeba472 100644
--- a/libraries/src/Extension/ExtensionHelper.php
+++ b/libraries/src/Extension/ExtensionHelper.php
@@ -31,6 +31,7 @@ class ExtensionHelper
// Format: `type`, `element`, `folder`, `client_id`
// Core component extensions
+ array('component', 'com_actionlogs', '', 1),
array('component', 'com_admin', '', 1),
array('component', 'com_ajax', '', 1),
array('component', 'com_associations', '', 1),
@@ -57,6 +58,7 @@ class ExtensionHelper
array('component', 'com_newsfeeds', '', 1),
array('component', 'com_plugins', '', 1),
array('component', 'com_postinstall', '', 1),
+ array('component', 'com_privacy', '', 1),
array('component', 'com_redirect', '', 1),
array('component', 'com_search', '', 1),
array('component', 'com_tags', '', 1),
@@ -84,11 +86,13 @@ class ExtensionHelper
array('module', 'mod_custom', '', 1),
array('module', 'mod_feed', '', 1),
array('module', 'mod_latest', '', 1),
+ array('module', 'mod_latestactions', '', 1),
array('module', 'mod_logged', '', 1),
array('module', 'mod_login', '', 1),
array('module', 'mod_menu', '', 1),
array('module', 'mod_multilangstatus', '', 1),
array('module', 'mod_popular', '', 1),
+ array('module', 'mod_privacy_dashboard', '', 1),
array('module', 'mod_quickicon', '', 1),
array('module', 'mod_sampledata', '', 1),
array('module', 'mod_stats_admin', '', 1),
@@ -128,6 +132,9 @@ class ExtensionHelper
// Core package extensions
array('package', 'pkg_en-GB', '', 0),
+ // Core plugin extensions - actionlog
+ array('plugin', 'joomla', 'actionlog', 0),
+
// Core plugin extensions - authentication
array('plugin', 'cookie', 'authentication', 0),
array('plugin', 'gmail', 'authentication', 0),
@@ -138,6 +145,7 @@ class ExtensionHelper
array('plugin', 'recaptcha', 'captcha', 0),
// Core plugin extensions - content
+ array('plugin', 'confirmconsent', 'content', 0),
array('plugin', 'contact', 'content', 0),
array('plugin', 'emailcloak', 'content', 0),
array('plugin', 'fields', 'content', 0),
@@ -196,10 +204,17 @@ class ExtensionHelper
array('plugin', 'packageinstaller', 'installer', 0),
array('plugin', 'urlinstaller', 'installer', 0),
+ // Core plugin extensions - privacy
+ array('plugin', 'contact', 'privacy', 0),
+ array('plugin', 'content', 'privacy', 0),
+ array('plugin', 'message', 'privacy', 0),
+ array('plugin', 'user', 'privacy', 0),
+
// Core plugin extensions - quick icon
array('plugin', 'extensionupdate', 'quickicon', 0),
array('plugin', 'joomlaupdate', 'quickicon', 0),
array('plugin', 'phpversioncheck', 'quickicon', 0),
+ array('plugin', 'privacycheck', 'quickicon', 0),
// Core plugin extensions - sample data
array('plugin', 'blog', 'sampledata', 0),
@@ -212,6 +227,7 @@ class ExtensionHelper
array('plugin', 'tags', 'search', 0),
// Core plugin extensions - system
+ array('plugin', 'actionlogs', 'system', 0),
array('plugin', 'cache', 'system', 0),
array('plugin', 'debug', 'system', 0),
array('plugin', 'fields', 'system', 0),
@@ -220,7 +236,9 @@ class ExtensionHelper
array('plugin', 'languagefilter', 'system', 0),
array('plugin', 'log', 'system', 0),
array('plugin', 'logout', 'system', 0),
+ array('plugin', 'logrotation', 'system', 0),
array('plugin', 'p3p', 'system', 0),
+ array('plugin', 'privacyconsent', 'system', 0),
array('plugin', 'redirect', 'system', 0),
array('plugin', 'remember', 'system', 0),
array('plugin', 'sef', 'system', 0),
@@ -236,6 +254,7 @@ class ExtensionHelper
array('plugin', 'contactcreator', 'user', 0),
array('plugin', 'joomla', 'user', 0),
array('plugin', 'profile', 'user', 0),
+ array('plugin', 'terms', 'user', 0),
// Core template extensions - administrator
array('template', 'hathor', '', 1),
diff --git a/libraries/src/Form/Form.php b/libraries/src/Form/Form.php
index c2af7618cf1d2..b4f81655935d7 100644
--- a/libraries/src/Form/Form.php
+++ b/libraries/src/Form/Form.php
@@ -322,7 +322,7 @@ public function getFieldAttribute($name, $attribute, $default = null, $group = n
*
* @param string $set The optional name of the fieldset.
*
- * @return array The array of JFormField objects in the fieldset.
+ * @return \JFormField[] The array of JFormField objects in the fieldset.
*
* @since 11.1
*/
@@ -497,7 +497,7 @@ public function getFormControl()
* @param boolean $nested True to also include fields in nested groups that are inside of the
* group for which to find fields.
*
- * @return array The array of JFormField objects in the field group.
+ * @return \JFormField[] The array of JFormField objects in the field group.
*
* @since 11.1
*/
diff --git a/media/plg_quickicon_privacycheck/js/privacycheck.js b/media/plg_quickicon_privacycheck/js/privacycheck.js
new file mode 100644
index 0000000000000..221fb20036f96
--- /dev/null
+++ b/media/plg_quickicon_privacycheck/js/privacycheck.js
@@ -0,0 +1,53 @@
+/**
+ * @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
+ * @license GNU General Public License version 2 or later; see LICENSE.txt
+ */
+
+jQuery(document).ready(function() {
+ var variables = Joomla.getOptions('js-privacy-check'),
+ plg_quickicon_privacycheck_ajax_url = variables.plg_quickicon_privacycheck_ajax_url,
+ plg_quickicon_privacycheck_url = variables.plg_quickicon_privacycheck_url,
+ plg_quickicon_privacycheck_text = variables.plg_quickicon_privacycheck_text;
+ var ajax_structure = {
+ success: function(data, textStatus, jqXHR) {
+ var link = jQuery('#plg_quickicon_privacycheck').find('span.j-links-link');
+
+ try {
+ var requestList = jQuery.parseJSON(data);
+ } catch (e) {
+ // An error occurred
+ link.html(plg_quickicon_privacycheck_text.ERROR);
+ }
+
+ if (requestList.data.number_urgent_requests == 0) {
+ // No requests
+ link.html(plg_quickicon_privacycheck_text.NOREQUEST);
+ } else {
+ // Requests
+ var msgString = '
'
+ + requestList.data.number_urgent_requests + ' '
+ + plg_quickicon_privacycheck_text.REQUESTFOUND_MESSAGE;
+
+ jQuery('#system-message-container').prepend(
+ '
'
+ + msgString
+ + ' '
+ + '
'
+ );
+
+ var msgString = plg_quickicon_privacycheck_text.REQUESTFOUND
+ + '
'
+ + requestList.data.number_urgent_requests + ''
+
+ link.html(msgString);
+ }
+ },
+ error: function(jqXHR, textStatus, errorThrown) {
+ // An error occurred
+ jQuery('#plg_quickicon_privacycheck').find('span.j-links-link').html(plg_quickicon_privacycheck_text.ERROR);
+ },
+ url: plg_quickicon_privacycheck_ajax_url
+ };
+ ajax_object = new jQuery.ajax(ajax_structure);
+});
diff --git a/plugins/actionlog/joomla/joomla.php b/plugins/actionlog/joomla/joomla.php
new file mode 100644
index 0000000000000..c7ae9f661e349
--- /dev/null
+++ b/plugins/actionlog/joomla/joomla.php
@@ -0,0 +1,934 @@
+getParams();
+
+ $this->loggableExtensions = $params->get('loggable_extensions', array());
+ }
+
+ /**
+ * After save content logging method
+ * This method adds a record to #__action_logs contains (message, date, context, user)
+ * Method is called right after the content is saved
+ *
+ * @param string $context The context of the content passed to the plugin
+ * @param object $article A JTableContent object
+ * @param boolean $isNew If the content is just about to be created
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onContentAfterSave($context, $article, $isNew)
+ {
+ $option = $this->app->input->getCmd('option');
+
+ if (!$this->checkLoggable($option))
+ {
+ return;
+ }
+
+ $params = ActionlogsHelper::getLogContentTypeParams($context);
+
+ // Not found a valid content type, don't process further
+ if ($params === null)
+ {
+ return;
+ }
+
+ $user = JFactory::getUser();
+ $contentTypeTitle = strtoupper($params->type_title);
+ list(, $contentType) = explode('.', $params->type_alias);
+
+ if ($isNew)
+ {
+ $messageLanguageKey = strtoupper($params->text_prefix . '_' . $contentTypeTitle . '_ADDED');
+ $defaultLanguageKey = strtoupper('PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED');
+
+ $action = 'add';
+ }
+ else
+ {
+ $messageLanguageKey = strtoupper($params->text_prefix . '_' . $contentTypeTitle . '_UPDATED');
+ $defaultLanguageKey = strtoupper('PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED');
+
+ $action = 'update';
+ }
+
+ // If the content type doesn't has it own language key, use default language key
+ if (!JFactory::getLanguage()->hasKey($messageLanguageKey))
+ {
+ $messageLanguageKey = $defaultLanguageKey;
+ }
+
+ $id = empty($params->id_holder) ? 0 : $article->get($params->id_holder);
+
+ $message = array(
+ 'action' => $action,
+ 'type' => strtoupper($params->text_prefix . '_TYPE_' . $contentTypeTitle),
+ 'id' => $id,
+ 'title' => $article->get($params->title_holder),
+ 'itemlink' => ActionlogsHelper::getContentTypeLink($option, $contentType, $id),
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * After delete content logging method
+ * This method adds a record to #__action_logs contains (message, date, context, user)
+ * Method is called right after the content is deleted
+ *
+ * @param string $context The context of the content passed to the plugin
+ * @param object $article A JTableContent object
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onContentAfterDelete($context, $article)
+ {
+ $option = $this->app->input->get('option');
+
+ if (!$this->checkLoggable($option))
+ {
+ return;
+ }
+
+ $params = ActionlogsHelper::getLogContentTypeParams($context);
+
+ // Not found a valid content type, don't process further
+ if ($params === null)
+ {
+ return;
+ }
+
+ $language = JFactory::getLanguage();
+ $user = JFactory::getUser();
+ $contentTypeTitle = strtoupper($params->type_title);
+
+ // If the content type has it own language key, use it, otherwise, use default language key
+ if ($language->hasKey(strtoupper($params->text_prefix . '_' . $contentTypeTitle . '_DELETED')))
+ {
+ $messageLanguageKey = strtoupper($params->text_prefix . '_' . $contentTypeTitle . '_DELETED');
+ }
+ else
+ {
+ $messageLanguageKey = strtoupper('PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED');
+ }
+
+ $id = empty($params->id_holder) ? 0 : $article->get($params->id_holder);
+
+ $message = array(
+ 'action' => 'delete',
+ 'type' => strtoupper($params->text_prefix . '_TYPE_' . $contentTypeTitle),
+ 'id' => $id,
+ 'title' => $article->get($params->title_holder),
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * On content change status logging method
+ * This method adds a record to #__action_logs contains (message, date, context, user)
+ * Method is called when the status of the article is changed
+ *
+ * @param string $context The context of the content passed to the plugin
+ * @param array $pks An array of primary key ids of the content that has changed state.
+ * @param integer $value The value of the state that the content has been changed to.
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onContentChangeState($context, $pks, $value)
+ {
+ $option = $this->app->input->getCmd('option');
+
+ if (!$this->checkLoggable($option))
+ {
+ return;
+ }
+
+ $params = ActionlogsHelper::getLogContentTypeParams($context);
+
+ // Not found a valid content type, don't process further
+ if ($params === null)
+ {
+ return;
+ }
+
+ $user = JFactory::getUser();
+ $contentTypeTitle = strtoupper($params->type_title);
+ list(, $contentType) = explode('.', $params->type_alias);
+
+ switch ($value)
+ {
+ case 0:
+ $messageLanguageKey = strtoupper($params->text_prefix . '_' . $contentTypeTitle . '_UNPUBLISHED');
+ $defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UNPUBLISHED';
+ $action = 'unpublish';
+ break;
+ case 1:
+ $messageLanguageKey = strtoupper($params->text_prefix . '_' . $contentTypeTitle . '_PUBLISHED');
+ $defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_PUBLISHED';
+ $action = 'publish';
+ break;
+ case 2:
+ $messageLanguageKey = strtoupper($params->text_prefix . '_' . $contentTypeTitle . '_ARCHIVED');
+ $defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ARCHIVED';
+ $action = 'archive';
+ break;
+ case -2:
+ $messageLanguageKey = strtoupper($params->text_prefix . '_' . $contentTypeTitle . '_TRASHED');
+ $defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_TRASHED';
+ $action = 'trash';
+ break;
+ default:
+ $messageLanguageKey = '';
+ $defaultLanguageKey = '';
+ $action = '';
+ break;
+ }
+
+ // If the content type doesn't has it own language key, use default language key
+ if (!JFactory::getLanguage()->hasKey($messageLanguageKey))
+ {
+ $messageLanguageKey = $defaultLanguageKey;
+ }
+
+ $db = JFactory::getDbo();
+ $query = $db->getQuery(true)
+ ->select($db->quoteName(array($params->title_holder, $params->id_holder)))
+ ->from($db->quoteName($params->table_name))
+ ->where($db->quoteName($params->id_holder) . ' IN (' . implode(',', ArrayHelper::toInteger($pks)) . ')');
+ $db->setQuery($query);
+
+ try
+ {
+ $items = $db->loadObjectList($params->id_holder);
+ }
+ catch (RuntimeException $e)
+ {
+ $items = array();
+ }
+
+ $messages = array();
+
+ foreach ($pks as $pk)
+ {
+ $message = array(
+ 'action' => $action,
+ 'type' => strtoupper($params->text_prefix . '_TYPE_' . $params->type_title),
+ 'id' => $pk,
+ 'title' => $items[$pk]->{$params->title_holder},
+ 'itemlink' => ActionlogsHelper::getContentTypeLink($option, $contentType, $pk),
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $messages[] = $message;
+ }
+
+ $this->addLog($messages, $messageLanguageKey, $context);
+ }
+
+ /**
+ * On Saving application configuration logging method
+ * Method is called when the application config is being saved
+ *
+ * @param JRegistry $config JRegistry object with the new config
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onApplicationAfterSave($config)
+ {
+ $option = $this->app->input->getCmd('option');
+
+ if (!$this->checkLoggable($option))
+ {
+ return;
+ }
+
+ $messageLanguageKey = strtoupper('PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED');
+ $action = 'update';
+
+ $user = JFactory::getUser();
+
+ $message = array(
+ 'action' => $action,
+ 'type' => strtoupper('PLG_ACTIONLOG_JOOMLA_TYPE_APPLICATION_CONFIG'),
+ 'extension_name' => 'com_config.application',
+ 'itemlink' => 'index.php?option=com_config',
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, 'com_config.application');
+ }
+
+ /**
+ * On installing extensions logging method
+ * This method adds a record to #__action_logs contains (message, date, context, user)
+ * Method is called when an extension is installed
+ *
+ * @param JInstaller $installer Installer object
+ * @param integer $eid Extension Identifier
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onExtensionAfterInstall($installer, $eid)
+ {
+ $context = $this->app->input->get('option');
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ $language = JFactory::getLanguage();
+ $user = JFactory::getUser();
+ $manifest = $installer->get('manifest');
+ $extensionType = $manifest->attributes()->type;
+
+ // If the extension type has it own language key, use it, otherwise, use default language key
+ if ($language->hasKey(strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_INSTALLED')))
+ {
+ $messageLanguageKey = strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_INSTALLED');
+ }
+ else
+ {
+ $messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_EXTENSION_INSTALLED';
+ }
+
+ $message = array(
+ 'action' => 'install',
+ 'type' => strtoupper('PLG_ACTIONLOG_JOOMLA_TYPE_' . $extensionType),
+ 'id' => $eid,
+ 'name' => (string) $manifest->name,
+ 'extension_name' => (string) $manifest->name,
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * On uninstalling extensions logging method
+ * This method adds a record to #__action_logs contains (message, date, context, user)
+ * Method is called when an extension is uninstalled
+ *
+ * @param JInstaller $installer Installer instance
+ * @param integer $eid Extension id
+ * @param integer $result Installation result
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onExtensionAfterUninstall($installer, $eid, $result)
+ {
+ $context = $this->app->input->get('option');
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ // If the process failed, we don't have manifest data, stop process to avoid fatal error
+ if ($result === false)
+ {
+ return;
+ }
+
+ $language = JFactory::getLanguage();
+ $user = JFactory::getUser();
+ $manifest = $installer->get('manifest');
+ $extensionType = $manifest->attributes()->type;
+
+ // If the extension type has it own language key, use it, otherwise, use default language key
+ if ($language->hasKey(strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_UNINSTALLED')))
+ {
+ $messageLanguageKey = strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_UNINSTALLED');
+ }
+ else
+ {
+ $messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_EXTENSION_UNINSTALLED';
+ }
+
+ $message = array(
+ 'action' => 'install',
+ 'type' => strtoupper('PLG_ACTIONLOG_JOOMLA_TYPE_' . $extensionType),
+ 'id' => $eid,
+ 'name' => (string) $manifest->name,
+ 'extension_name' => (string) $manifest->name,
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * On updating extensions logging method
+ * This method adds a record to #__action_logs contains (message, date, context, user)
+ * Method is called when an extension is updated
+ *
+ * @param JInstaller $installer Installer instance
+ * @param integer $eid Extension id
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onExtensionAfterUpdate($installer, $eid)
+ {
+ $context = $this->app->input->get('option');
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ $language = JFactory::getLanguage();
+ $user = JFactory::getUser();
+ $manifest = $installer->get('manifest');
+ $extensionType = $manifest->attributes()->type;
+
+ // If the extension type has it own language key, use it, otherwise, use default language key
+ if ($language->hasKey(strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_UPDATED')))
+ {
+ $messageLanguageKey = strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_UPDATED');
+ }
+ else
+ {
+ $messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_EXTENSION_UPDATED';
+ }
+
+ $message = array(
+ 'action' => 'update',
+ 'type' => strtoupper('PLG_ACTIONLOG_JOOMLA_TYPE_' . $extensionType),
+ 'id' => $eid,
+ 'name' => (string) $manifest->name,
+ 'extension_name' => (string) $manifest->name,
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * On Saving extensions logging method
+ * Method is called when an extension is being saved
+ *
+ * @param string $context The extension
+ * @param JTable $table DataBase Table object
+ * @param boolean $isNew If the extension is new or not
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onExtensionAfterSave($context, $table, $isNew)
+ {
+ $option = $this->app->input->getCmd('option');
+
+ if (!$this->checkLoggable($option))
+ {
+ return;
+ }
+
+ $params = ActionlogsHelper::getLogContentTypeParams($context);
+
+ // Not found a valid content type, don't process further
+ if ($params === null)
+ {
+ return;
+ }
+
+ $extensionType = $params->type_title;
+ list(, $contentType) = explode('.', $params->type_alias);
+
+ if ($isNew)
+ {
+ $messageLanguageKey = strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_ADDED');
+ $defaultLanguageKey = strtoupper('PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED');
+ $action = 'add';
+ }
+ else
+ {
+ $messageLanguageKey = strtoupper('PLG_ACTIONLOG_JOOMLA_' . $extensionType . '_UPDATED');
+ $defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
+ $action = 'update';
+ }
+
+ // If the extension type doesn't have it own language key, use default language key
+ if (!JFactory::getLanguage()->hasKey($messageLanguageKey))
+ {
+ $messageLanguageKey = $defaultLanguageKey;
+ }
+
+ $user = JFactory::getUser();
+
+ $message = array(
+ 'action' => $action,
+ 'type' => strtoupper('PLG_ACTIONLOG_JOOMLA_TYPE_' . $extensionType),
+ 'id' => $table->get($params->id_holder),
+ 'title' => $table->get($params->title_holder),
+ 'extension_name' => $table->get($params->title_holder),
+ 'itemlink' => ActionlogsHelper::getContentTypeLink($option, $contentType, $table->get($params->id_holder), $params->id_holder),
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * On Deleting extensions logging method
+ * Method is called when an extension is being deleted
+ *
+ * @param string $context The extension
+ * @param JTable $table DataBase Table object
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onExtensionAfterDelete($context, $table)
+ {
+ if (!$this->checkLoggable($this->app->input->get('option')))
+ {
+ return;
+ }
+
+ $params = ActionlogsHelper::getLogContentTypeParams($context);
+
+ // Not found a valid content type, don't process further
+ if ($params === null)
+ {
+ return;
+ }
+
+ $messageLanguageKey = strtoupper('PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED');
+ $user = JFactory::getUser();
+
+ $message = array(
+ 'action' => 'delete',
+ 'type' => strtoupper('PLG_ACTIONLOG_JOOMLA_TYPE_' . $params->type_title),
+ 'title' => $table->get($params->title_holder),
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * On saving user data logging method
+ *
+ * Method is called after user data is stored in the database.
+ * This method logs who created/edited any user's data
+ *
+ * @param array $user Holds the new user data.
+ * @param boolean $isnew True if a new user is stored.
+ * @param boolean $success True if user was succesfully stored in the database.
+ * @param string $msg Message.
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserAfterSave($user, $isnew, $success, $msg)
+ {
+ $context = $this->app->input->get('option');
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ $jUser = JFactory::getUser();
+
+ if (!$jUser->id)
+ {
+ $messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_REGISTERED';
+ $action = 'register';
+ }
+ elseif ($isnew)
+ {
+ $messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
+ $action = 'add';
+ }
+ else
+ {
+ $messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
+ $action = 'update';
+ }
+
+ $userId = $jUser->id ?: $user['id'];
+ $username = $jUser->username ?: $user['username'];
+
+ $message = array(
+ 'action' => $action,
+ 'type' => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
+ 'id' => $user['id'],
+ 'title' => $user['name'],
+ 'itemlink' => 'index.php?option=com_users&task=user.edit&id=' . $user['id'],
+ 'userid' => $userId,
+ 'username' => $username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $userId,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context, $userId);
+ }
+
+ /**
+ * On deleting user data logging method
+ *
+ * Method is called after user data is deleted from the database
+ *
+ * @param array $user Holds the user data
+ * @param boolean $success True if user was succesfully stored in the database
+ * @param string $msg Message
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserAfterDelete($user, $success, $msg)
+ {
+ $context = $this->app->input->get('option');
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ $messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';
+ $jUser = JFactory::getUser();
+
+ $message = array(
+ 'action' => 'delete',
+ 'type' => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
+ 'id' => $user['id'],
+ 'title' => $user['name'],
+ 'userid' => $jUser->id,
+ 'username' => $jUser->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $jUser->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * On after save user group data logging method
+ *
+ * Method is called after user data is deleted from the database
+ *
+ * @param string $context The context
+ * @param JTable $table DataBase Table object
+ * @param boolean $isNew Is new or not
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserAfterSaveGroup($context, $table, $isNew)
+ {
+ $context = $this->app->input->get('option');
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ if ($isNew)
+ {
+ $messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
+ $action = 'add';
+ }
+ else
+ {
+ $messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
+ $action = 'update';
+ }
+
+ $user = JFactory::getUser();
+
+ $message = array(
+ 'action' => $action,
+ 'type' => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP',
+ 'id' => $table->id,
+ 'title' => $table->title,
+ 'itemlink' => 'index.php?option=com_users&task=group.edit&id=' . $table->id,
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * On deleting user group data logging method
+ *
+ * Method is called after user data is deleted from the database
+ *
+ * @param array $group Holds the group data
+ * @param boolean $success True if user was succesfully stored in the database
+ * @param string $msg Message
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserAfterDeleteGroup($group, $success, $msg)
+ {
+ $context = $this->app->input->get('option');
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ $user = JFactory::getUser();
+
+ $messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';
+
+ $message = array(
+ 'action' => 'delete',
+ 'type' => 'PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP',
+ 'id' => $group['id'],
+ 'title' => $group['title'],
+ 'userid' => $user->id,
+ 'username' => $user->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id,
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * Method to log user login success action
+ *
+ * @param array $options Array holding options (user, responseType)
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserAfterLogin($options)
+ {
+ $context = 'com_users';
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ $loggedInUser = $options['user'];
+ $messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGGED_IN';
+
+ $message = array(
+ 'action' => 'login',
+ 'username' => $loggedInUser->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $loggedInUser->id,
+ 'app' => strtoupper('PLG_ACTIONLOG_JOOMLA_APPLICATION_' . $this->app->getName()),
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context, $loggedInUser->id);
+ }
+
+ /**
+ * Method to log user login failed action
+ *
+ * @param array $response Array of response data.
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserLoginFailure($response)
+ {
+ $context = 'com_users';
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ $loggedInUser = JUser::getInstance($response['username']);
+
+ // Not a valid user, return
+ if (!$loggedInUser->id)
+ {
+ return;
+ }
+
+ $messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGIN_FAILED';
+
+ $message = array(
+ 'action' => 'login',
+ 'id' => $loggedInUser->id,
+ 'username' => $loggedInUser->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $loggedInUser->id,
+ 'app' => strtoupper('PLG_ACTIONLOG_JOOMLA_APPLICATION_' . $this->app->getName()),
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context, $loggedInUser->id);
+ }
+
+ /**
+ * Method to log user's logout action
+ *
+ * @param array $user Holds the user data
+ * @param array $options Array holding options (remember, autoregister, group)
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserLogout($user, $options = array())
+ {
+ $context = 'com_users';
+
+ if (!$this->checkLoggable($context))
+ {
+ return;
+ }
+
+ $loggedOutUser = JUser::getInstance($user['id']);
+ $messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGGED_OUT';
+
+ $message = array(
+ 'action' => 'logout',
+ 'id' => $loggedOutUser->id,
+ 'username' => $loggedOutUser->username,
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $loggedOutUser->id,
+ 'app' => strtoupper('PLG_ACTIONLOG_JOOMLA_APPLICATION_' . $this->app->getName()),
+ );
+
+ $this->addLog(array($message), $messageLanguageKey, $context);
+ }
+
+ /**
+ * Proxy for ActionlogsModelUserlog addLog method
+ *
+ * This method adds a record to #__action_logs contains (message_language_key, message, date, context, user)
+ *
+ * @param array $messages The contents of the messages to be logged
+ * @param string $messageLanguageKey The language key of the message
+ * @param string $context The context of the content passed to the plugin
+ * @param int $userId ID of user perform the action, usually ID of current logged in user
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ protected function addLog($messages, $messageLanguageKey, $context, $userId = null)
+ {
+ JLoader::register('ActionlogsModelActionlog', JPATH_ADMINISTRATOR . '/components/com_actionlogs/models/actionlog.php');
+
+ /* @var ActionlogsModelActionlog $model */
+ $model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel');
+ $model->addLog($messages, $messageLanguageKey, $context, $userId);
+ }
+
+ /**
+ * Function to check if a component is loggable or not
+ *
+ * @param string $extension The extension that triggered the event
+ *
+ * @return boolean
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ protected function checkLoggable($extension)
+ {
+ return in_array($extension, $this->loggableExtensions);
+ }
+}
diff --git a/plugins/actionlog/joomla/joomla.xml b/plugins/actionlog/joomla/joomla.xml
new file mode 100644
index 0000000000000..e38fa5ea1d973
--- /dev/null
+++ b/plugins/actionlog/joomla/joomla.xml
@@ -0,0 +1,16 @@
+
+
+ PLG_ACTIONLOG_JOOMLA
+ Joomla! Project
+ May 2018
+ Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ __DEPLOY_VERSION__
+ PLG_ACTIONLOG_JOOMLA_XML_DESCRIPTION
+
+ joomla.php
+
+
+
diff --git a/plugins/authentication/cookie/cookie.php b/plugins/authentication/cookie/cookie.php
index 9a2effc87ff71..7d86105aa54f7 100644
--- a/plugins/authentication/cookie/cookie.php
+++ b/plugins/authentication/cookie/cookie.php
@@ -34,6 +34,24 @@ class PlgAuthenticationCookie extends JPlugin
*/
protected $db;
+ /**
+ * Reports the privacy related capabilities for this plugin to site administrators.
+ *
+ * @return array
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onPrivacyCollectAdminCapabilities()
+ {
+ $this->loadLanguage();
+
+ return array(
+ JText::_('PLG_AUTHENTICATION_COOKIE') => array(
+ JText::_('PLG_AUTH_COOKIE_PRIVACY_CAPABILITY_COOKIE'),
+ )
+ );
+ }
+
/**
* This method should handle any authentication and report back to the subject
*
diff --git a/plugins/captcha/recaptcha/recaptcha.php b/plugins/captcha/recaptcha/recaptcha.php
index 6aae275f18ddf..213879d281a07 100644
--- a/plugins/captcha/recaptcha/recaptcha.php
+++ b/plugins/captcha/recaptcha/recaptcha.php
@@ -25,6 +25,24 @@ class PlgCaptchaRecaptcha extends JPlugin
*/
protected $autoloadLanguage = true;
+ /**
+ * Reports the privacy related capabilities for this plugin to site administrators.
+ *
+ * @return array
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onPrivacyCollectAdminCapabilities()
+ {
+ $this->loadLanguage();
+
+ return array(
+ JText::_('PLG_CAPTCHA_RECAPTCHA') => array(
+ JText::_('PLG_RECAPTCHA_PRIVACY_CAPABILITY_IP_ADDRESS'),
+ )
+ );
+ }
+
/**
* Initialise the captcha
*
diff --git a/plugins/content/confirmconsent/confirmconsent.php b/plugins/content/confirmconsent/confirmconsent.php
new file mode 100644
index 0000000000000..c7e0688130cec
--- /dev/null
+++ b/plugins/content/confirmconsent/confirmconsent.php
@@ -0,0 +1,200 @@
+app->isClient('administrator') || !in_array($form->getName(), $this->supportedContext))
+ {
+ return true;
+ }
+
+ // Get the consent box Text & the selected privacyarticle
+ $consentboxLabel = JText::_('PLG_CONTENT_CONFIRMCONSENT_CONSENTBOX_LABEL');
+ $consentboxText = (string) $this->params->get('consentbox_text', Text::_('PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DEFAULT'));
+ $privacyArticle = $this->params->get('privacy_article', false);
+
+ // When we have a article just add it arround to the text
+ if ($privacyArticle)
+ {
+ HTMLHelper::_('behavior.modal');
+
+ $consentboxLabel = $this->getAssignedArticleUrl($privacyArticle, $consentboxLabel);
+ }
+
+ $form->load('
+
'
+ );
+
+ return true;
+ }
+
+ /**
+ * Return the url of the assigned article based on the current user language
+ *
+ * @param integer $articleId The form to be altered.
+ * @param string $consentboxLabel The consent box label
+ *
+ * @return string Returns the a tag containing everything for the modal
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function getAssignedArticleUrl($articleId, $consentboxLabel)
+ {
+ // Get the info from the article
+ $query = $this->db->getQuery(true)
+ ->select($this->db->quoteName(array('id', 'catid', 'language')))
+ ->from($this->db->quoteName('#__content'))
+ ->where($this->db->quoteName('id') . ' = ' . (int) $articleId);
+ $this->db->setQuery($query);
+
+ $attribs = array();
+ $attribs['class'] = 'modal';
+ $attribs['rel'] = '{handler: \'iframe\', size: {x:800, y:500}}';
+
+ try
+ {
+ $article = $this->db->loadObject();
+ }
+ catch (JDatabaseExceptionExecuting $e)
+ {
+ // Something at the database layer went wrong
+ return HTMLHelper::_(
+ 'link',
+ Route::_(
+ 'index.php?option=com_content&view=article&id='
+ . $articleId . '&tmpl=component'
+ ),
+ $consentboxLabel,
+ $attribs
+ );
+ }
+
+ // Register ContentHelperRoute
+ JLoader::register('ContentHelperRoute', JPATH_BASE . '/components/com_content/helpers/route.php');
+
+ if (!Associations::isEnabled())
+ {
+ return HTMLHelper::_('link',
+ Route::_(
+ ContentHelperRoute::getArticleRoute(
+ $article->id,
+ $article->catid,
+ $article->language
+ ) . '&tmpl=component'
+ ),
+ $consentboxLabel,
+ $attribs
+ );
+ }
+
+ $associatedArticles = Associations::getAssociations('com_content', '#__content', 'com_content.item', $article->id);
+ $currentLang = Factory::getLanguage()->getTag();
+
+ if (isset($associatedArticles) && $currentLang !== $article->language && array_key_exists($currentLang, $associatedArticles))
+ {
+ return HTMLHelper::_('link',
+ Route::_(
+ ContentHelperRoute::getArticleRoute(
+ $associatedArticles[$currentLang]->id,
+ $associatedArticles[$currentLang]->catid,
+ $associatedArticles[$currentLang]->language
+ ) . '&tmpl=component'
+ ),
+ $consentboxLabel,
+ $attribs
+ );
+ }
+
+ // Association is enabled but this article is not associated
+ return HTMLHelper::_(
+ 'link',
+ Route::_(
+ 'index.php?option=com_content&view=article&id='
+ . $article->id . '&catid=' . $article->catid
+ . '&tmpl=component&lang=' . $article->language
+ ),
+ $consentboxLabel,
+ $attribs
+ );
+ }
+}
diff --git a/plugins/content/confirmconsent/confirmconsent.xml b/plugins/content/confirmconsent/confirmconsent.xml
new file mode 100644
index 0000000000000..961b08a164db8
--- /dev/null
+++ b/plugins/content/confirmconsent/confirmconsent.xml
@@ -0,0 +1,44 @@
+
+
+ plg_content_confirmconsent
+ Joomla! Project
+ May 2018
+ Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ __DEPLOY_VERSION__
+ PLG_CONTENT_CONFIRMCONSENT_XML_DESCRIPTION
+
+ confirmconsent.php
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/privacy/actionlogs/actionlogs.php b/plugins/privacy/actionlogs/actionlogs.php
new file mode 100644
index 0000000000000..f6db3ceca4743
--- /dev/null
+++ b/plugins/privacy/actionlogs/actionlogs.php
@@ -0,0 +1,85 @@
+createDomain('actionlog', 'Logged actions of the user');
+
+ $query = $this->db->getQuery(true)
+ ->select('a.*, u.name')
+ ->from('#__action_logs AS a')
+ ->innerJoin('#__users AS u ON a.user_id = u.id')
+ ->where($this->db->quoteName('a.user_id') . ' = ' . $user->id);
+
+ $this->db->setQuery($query);
+
+ $data = $this->db->loadObjectList();
+
+ if (!count($data))
+ {
+ return array();
+ }
+
+ $data = ActionlogsHelper::getCsvData($data);
+ array_shift($data);
+
+ foreach ($data as $item)
+ {
+ $domain->addItem($this->createItemFromArray($item));
+ }
+
+ return array($domain);
+ }
+}
diff --git a/plugins/privacy/actionlogs/actionlogs.xml b/plugins/privacy/actionlogs/actionlogs.xml
new file mode 100644
index 0000000000000..f37879f35e81b
--- /dev/null
+++ b/plugins/privacy/actionlogs/actionlogs.xml
@@ -0,0 +1,19 @@
+
+
+ plg_privacy_actionlogs
+ Joomla! Project
+ July 2018
+ (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ PLG_PRIVACY_ACTIONLOGS_XML_DESCRIPTION
+
+ actionlogs.php
+
+
+ en-GB.plg_privacy_actionlogs.ini
+ en-GB.plg_privacy_actionlogs.sys.ini
+
+
diff --git a/plugins/privacy/contact/contact.php b/plugins/privacy/contact/contact.php
new file mode 100644
index 0000000000000..8bf8fd9e1f3cb
--- /dev/null
+++ b/plugins/privacy/contact/contact.php
@@ -0,0 +1,155 @@
+email))
+ {
+ return array();
+ }
+
+ $domains = array();
+ $domains[] = $this->createContactDomain($request, $user);
+
+ // An user may have more than 1 contact linked to them
+ foreach ($this->contacts as $contact)
+ {
+ $domains[] = $this->createContactCustomFieldsDomain($contact);
+ }
+
+ return $domains;
+ }
+
+ /**
+ * Create the domain for the user contact data
+ *
+ * @param PrivacyTableRequest $request The request record being processed
+ * @param JUser $user The user account associated with this request if available
+ *
+ * @return PrivacyExportDomain
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createContactDomain(PrivacyTableRequest $request, JUser $user = null)
+ {
+ $domain = $this->createDomain('user contact', 'Joomla! user contact data');
+
+ if ($user)
+ {
+ $query = $this->db->getQuery(true)
+ ->select('*')
+ ->from($this->db->quoteName('#__contact_details'))
+ ->where($this->db->quoteName('user_id') . ' = ' . (int) $user->id)
+ ->order($this->db->quoteName('ordering') . ' ASC');
+ }
+ else
+ {
+ $query = $this->db->getQuery(true)
+ ->select('*')
+ ->from($this->db->quoteName('#__contact_details'))
+ ->where($this->db->quoteName('email_to') . ' = ' . $this->db->quote($request->email))
+ ->order($this->db->quoteName('ordering') . ' ASC');
+ }
+
+ $items = $this->db->setQuery($query)->loadAssocList();
+
+ foreach ($items as $item)
+ {
+ $domain->addItem($this->createItemFromArray($item));
+ $this->contacts[] = (object) $item;
+ }
+
+ return $domain;
+ }
+
+ /**
+ * Create the domain for the contact custom fields
+ *
+ * @param Object $contact The contact to process
+ *
+ * @return PrivacyExportDomain
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createContactCustomFieldsDomain($contact)
+ {
+ $domain = $this->createDomain('contact custom fields', 'Joomla! contact custom fields data');
+
+ // Get item's fields, also preparing their value property for manual display
+ $fields = FieldsHelper::getFields('com_contact.contact', $contact);
+
+ foreach ($fields as $field)
+ {
+ $fieldValue = is_array($field->value) ? implode(', ', $field->value) : $field->value;
+
+ $data = array(
+ 'contact_id' => $contact->id,
+ 'field_name' => $field->name,
+ 'field_title' => $field->title,
+ 'field_value' => $fieldValue,
+ );
+
+ $domain->addItem($this->createItemFromArray($data));
+ }
+
+ return $domain;
+ }
+}
diff --git a/plugins/privacy/contact/contact.xml b/plugins/privacy/contact/contact.xml
new file mode 100644
index 0000000000000..2de5eed47f655
--- /dev/null
+++ b/plugins/privacy/contact/contact.xml
@@ -0,0 +1,19 @@
+
+
+ plg_privacy_contact
+ Joomla! Project
+ July 2018
+ (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ PLG_PRIVACY_CONTACT_XML_DESCRIPTION
+
+ contact.php
+
+
+ en-GB.plg_privacy_contact.ini
+ en-GB.plg_privacy_contact.sys.ini
+
+
diff --git a/plugins/privacy/content/content.php b/plugins/privacy/content/content.php
new file mode 100644
index 0000000000000..ddfecde902cb1
--- /dev/null
+++ b/plugins/privacy/content/content.php
@@ -0,0 +1,142 @@
+createContentDomain($user);
+
+ foreach ($this->contents as $content)
+ {
+ $domains[] = $this->createContentCustomFieldsDomain($content);
+ }
+
+ return $domains;
+ }
+
+ /**
+ * Create the domain for the user content data
+ *
+ * @param JUser $user The user account associated with this request
+ *
+ * @return PrivacyExportDomain
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createContentDomain(JUser $user)
+ {
+ $domain = $this->createDomain('user content', 'Joomla! user content data');
+
+ $query = $this->db->getQuery(true)
+ ->select('*')
+ ->from($this->db->quoteName('#__content'))
+ ->where($this->db->quoteName('created_by') . ' = ' . (int) $user->id)
+ ->order($this->db->quoteName('ordering') . ' ASC');
+
+ $items = $this->db->setQuery($query)->loadAssocList();
+
+ foreach ($items as $item)
+ {
+ $domain->addItem($this->createItemFromArray($item));
+ $this->contents[] = (object) $item;
+ }
+
+ return $domain;
+ }
+
+ /**
+ * Create the domain for the content custom fields
+ *
+ * @param Object $content The content to process
+ *
+ * @return PrivacyExportDomain
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createContentCustomFieldsDomain($content)
+ {
+ $domain = $this->createDomain('content custom fields', 'Joomla! content custom fields data');
+
+ // Get item's fields, also preparing their value property for manual display
+ $fields = FieldsHelper::getFields('com_content.article', $content);
+
+ foreach ($fields as $field)
+ {
+ $fieldValue = is_array($field->value) ? implode(', ', $field->value) : $field->value;
+
+ $data = array(
+ 'content_id' => $content->id,
+ 'field_name' => $field->name,
+ 'field_title' => $field->title,
+ 'field_value' => $fieldValue,
+ );
+
+ $domain->addItem($this->createItemFromArray($data));
+ }
+
+ return $domain;
+ }
+}
diff --git a/plugins/privacy/content/content.xml b/plugins/privacy/content/content.xml
new file mode 100644
index 0000000000000..a2114f106c31c
--- /dev/null
+++ b/plugins/privacy/content/content.xml
@@ -0,0 +1,19 @@
+
+
+ plg_privacy_content
+ Joomla! Project
+ July 2018
+ (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ PLG_PRIVACY_CONTENT_XML_DESCRIPTION
+
+ content.php
+
+
+ en-GB.plg_privacy_content.ini
+ en-GB.plg_privacy_content.sys.ini
+
+
diff --git a/plugins/privacy/message/message.php b/plugins/privacy/message/message.php
new file mode 100644
index 0000000000000..023d5e6845567
--- /dev/null
+++ b/plugins/privacy/message/message.php
@@ -0,0 +1,94 @@
+createMessageDomain($user);
+
+ return $domains;
+ }
+
+ /**
+ * Create the domain for the user message data
+ *
+ * @param JUser $user The user account associated with this request
+ *
+ * @return PrivacyExportDomain
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createMessageDomain(JUser $user)
+ {
+ $domain = $this->createDomain('user message', 'Joomla! user message data');
+
+ $query = $this->db->getQuery(true)
+ ->select('*')
+ ->from($this->db->quoteName('#__messages'))
+ ->where($this->db->quoteName('user_id_from') . ' = ' . (int) $user->id)
+ ->orWhere($this->db->quoteName('user_id_to') . ' = ' . (int) $user->id)
+ ->order($this->db->quoteName('date_time') . ' ASC');
+
+ $items = $this->db->setQuery($query)->loadAssocList();
+
+ foreach ($items as $item)
+ {
+ $domain->addItem($this->createItemFromArray($item));
+ }
+
+ return $domain;
+ }
+}
diff --git a/plugins/privacy/message/message.xml b/plugins/privacy/message/message.xml
new file mode 100644
index 0000000000000..9a7f19f6f1548
--- /dev/null
+++ b/plugins/privacy/message/message.xml
@@ -0,0 +1,19 @@
+
+
+ plg_privacy_message
+ Joomla! Project
+ July 2018
+ (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ PLG_PRIVACY_MESSAGE_XML_DESCRIPTION
+
+ message.php
+
+
+ en-GB.plg_privacy_message.ini
+ en-GB.plg_privacy_message.sys.ini
+
+
diff --git a/plugins/privacy/user/user.php b/plugins/privacy/user/user.php
new file mode 100644
index 0000000000000..496ff358b0809
--- /dev/null
+++ b/plugins/privacy/user/user.php
@@ -0,0 +1,308 @@
+authorise('core.admin'))
+ {
+ $status->canRemove = false;
+ $status->reason = JText::_('PLG_PRIVACY_USER_ERROR_CANNOT_REMOVE_SUPER_USER');
+ }
+
+ return $status;
+ }
+
+ /**
+ * Processes an export request for Joomla core user data
+ *
+ * This event will collect data for the following core tables:
+ *
+ * - #__users (excluding the password, otpKey, and otep columns)
+ * - #__user_notes
+ * - #__user_profiles
+ * - User custom fields
+ *
+ * @param PrivacyTableRequest $request The request record being processed
+ * @param JUser $user The user account associated with this request if available
+ *
+ * @return PrivacyExportDomain[]
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onPrivacyExportRequest(PrivacyTableRequest $request, JUser $user = null)
+ {
+ if (!$user)
+ {
+ return array();
+ }
+
+ /** @var JTableUser $userTable */
+ $userTable = JUser::getTable();
+ $userTable->load($user->id);
+
+ $domains = array();
+ $domains[] = $this->createUserDomain($userTable);
+ $domains[] = $this->createNotesDomain($userTable);
+ $domains[] = $this->createProfileDomain($userTable);
+ $domains[] = $this->createUserCustomFieldsDomain($userTable);
+
+ return $domains;
+ }
+
+ /**
+ * Removes the data associated with a remove information request
+ *
+ * This event will pseudoanonymise the user account
+ *
+ * @param PrivacyTableRequest $request The request record being processed
+ * @param JUser $user The user account associated with this request if available
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onPrivacyRemoveData(PrivacyTableRequest $request, JUser $user = null)
+ {
+ // This plugin only processes data for registered user accounts
+ if (!$user)
+ {
+ return;
+ }
+
+ $pseudoanonymisedData = array(
+ 'name' => 'User ID ' . $user->id,
+ 'username' => bin2hex(random_bytes(12)),
+ 'email' => 'UserID' . $user->id . 'removed@email.invalid',
+ 'block' => true,
+ );
+
+ $user->bind($pseudoanonymisedData);
+
+ $user->save();
+
+ // Destroy all sessions for the user account
+ $sessionIds = $this->db->setQuery(
+ $this->db->getQuery(true)
+ ->select($this->db->quoteName('session_id'))
+ ->from($this->db->quoteName('#__session'))
+ ->where($this->db->quoteName('userid') . ' = ' . (int) $user->id)
+ )->loadColumn();
+
+ // If there aren't any active sessions then there's nothing to do here
+ if (empty($sessionIds))
+ {
+ return;
+ }
+
+ $storeName = JFactory::getConfig()->get('session_handler', 'none');
+ $store = JSessionStorage::getInstance($storeName);
+ $quotedIds = array();
+
+ // Destroy the sessions and quote the IDs to purge the session table
+ foreach ($sessionIds as $sessionId)
+ {
+ $store->destroy($sessionId);
+ $quotedIds[] = $this->db->quote($sessionId);
+ }
+
+ $this->db->setQuery(
+ $this->db->getQuery(true)
+ ->delete($this->db->quoteName('#__session'))
+ ->where($this->db->quoteName('session_id') . ' IN (' . implode(', ', $quotedIds) . ')')
+ )->execute();
+ }
+
+ /**
+ * Create the domain for the user notes data
+ *
+ * @param JTableUser $user The JTableUser object to process
+ *
+ * @return PrivacyExportDomain
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createNotesDomain(JTableUser $user)
+ {
+ $domain = $this->createDomain('user notes', 'Joomla! user notes data');
+
+ $query = $this->db->getQuery(true)
+ ->select('*')
+ ->from($this->db->quoteName('#__user_notes'))
+ ->where($this->db->quoteName('user_id') . ' = ' . $this->db->quote($user->id));
+
+ $items = $this->db->setQuery($query)->loadAssocList();
+
+ // Remove user ID columns
+ foreach (array('user_id', 'created_user_id', 'modified_user_id') as $column)
+ {
+ $items = ArrayHelper::dropColumn($items, $column);
+ }
+
+ foreach ($items as $item)
+ {
+ $domain->addItem($this->createItemFromArray($item, $item['id']));
+ }
+
+ return $domain;
+ }
+
+ /**
+ * Create the domain for the user profile data
+ *
+ * @param JTableUser $user The JTableUser object to process
+ *
+ * @return PrivacyExportDomain
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createProfileDomain(JTableUser $user)
+ {
+ $domain = $this->createDomain('user profile', 'Joomla! user profile data');
+
+ $query = $this->db->getQuery(true)
+ ->select('*')
+ ->from($this->db->quoteName('#__user_profiles'))
+ ->where($this->db->quoteName('user_id') . ' = ' . $this->db->quote($user->id))
+ ->order($this->db->quoteName('ordering') . ' ASC');
+
+ $items = $this->db->setQuery($query)->loadAssocList();
+
+ foreach ($items as $item)
+ {
+ $domain->addItem($this->createItemFromArray($item));
+ }
+
+ return $domain;
+ }
+
+ /**
+ * Create the domain for the user record
+ *
+ * @param JTableUser $user The JTableUser object to process
+ *
+ * @return PrivacyExportDomain
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createUserDomain(JTableUser $user)
+ {
+ $domain = $this->createDomain('users', 'Joomla! users table data');
+ $domain->addItem($this->createItemForUserTable($user));
+
+ return $domain;
+ }
+
+ /**
+ * Create an item object for a JTableUser object
+ *
+ * @param JTableUser $user The JTableUser object to convert
+ *
+ * @return PrivacyExportItem
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createItemForUserTable(JTableUser $user)
+ {
+ $data = array();
+ $exclude = array('password', 'otpKey', 'otep');
+
+ foreach (array_keys($user->getFields()) as $fieldName)
+ {
+ if (!in_array($fieldName, $exclude))
+ {
+ $data[$fieldName] = $user->$fieldName;
+ }
+ }
+
+ return $this->createItemFromArray($data, $user->id);
+ }
+
+ /**
+ * Create the domain for the user custom fields
+ *
+ * @param JTableUser $user The JTableUser object to process
+ *
+ * @return PrivacyExportDomain
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function createUserCustomFieldsDomain(JTableUser $user)
+ {
+ $domain = $this->createDomain('user custom fields', 'Joomla! user custom fields data');
+
+ // Get item's fields, also preparing their value property for manual display
+ $fields = FieldsHelper::getFields('com_users.user', $user);
+
+ foreach ($fields as $field)
+ {
+ $fieldValue = is_array($field->value) ? implode(', ', $field->value) : $field->value;
+
+ $data = array(
+ 'user_id' => $user->id,
+ 'field_name' => $field->name,
+ 'field_title' => $field->title,
+ 'field_value' => $fieldValue,
+ );
+
+ $domain->addItem($this->createItemFromArray($data));
+ }
+
+ return $domain;
+ }
+}
diff --git a/plugins/privacy/user/user.xml b/plugins/privacy/user/user.xml
new file mode 100644
index 0000000000000..06277aad43f93
--- /dev/null
+++ b/plugins/privacy/user/user.xml
@@ -0,0 +1,19 @@
+
+
+ plg_privacy_user
+ Joomla! Project
+ May 2018
+ (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ PLG_PRIVACY_USER_XML_DESCRIPTION
+
+ user.php
+
+
+ en-GB.plg_privacy_user.ini
+ en-GB.plg_privacy_user.sys.ini
+
+
diff --git a/plugins/quickicon/privacycheck/privacycheck.php b/plugins/quickicon/privacycheck/privacycheck.php
new file mode 100644
index 0000000000000..f78fabd4286de
--- /dev/null
+++ b/plugins/quickicon/privacycheck/privacycheck.php
@@ -0,0 +1,80 @@
+params->get('context', 'mod_quickicon') || !Factory::getUser()->authorise('core.admin', 'com_privacy'))
+ {
+ return;
+ }
+
+ JHtml::_('jquery.framework');
+
+ $token = Session::getFormToken() . '=' . 1;
+ $privacy = 'index.php?option=com_privacy';
+
+ $options = array(
+ 'plg_quickicon_privacycheck_url' => Uri::base() . $privacy . '&view=requests&filter[status]=1&list[fullordering]=a.requested_at ASC',
+ 'plg_quickicon_privacycheck_ajax_url' => Uri::base() . $privacy . '&task=getNumberUrgentRequests&' . $token,
+ 'plg_quickicon_privacycheck_text' => array(
+ "NOREQUEST" => Text::_('PLG_QUICKICON_PRIVACYCHECK_NOREQUEST', true),
+ "REQUESTFOUND" => Text::_('PLG_QUICKICON_PRIVACYCHECK_REQUESTFOUND', true),
+ "REQUESTFOUND_MESSAGE" => Text::_('PLG_QUICKICON_PRIVACYCHECK_REQUESTFOUND_MESSAGE', true),
+ "REQUESTFOUND_BUTTON" => Text::_('PLG_QUICKICON_PRIVACYCHECK_REQUESTFOUND_BUTTON', true),
+ "ERROR" => Text::_('PLG_QUICKICON_PRIVACYCHECK_ERROR', true),
+ )
+ );
+
+ Factory::getDocument()->addScriptOptions('js-privacy-check', $options);
+
+ JHtml::_('script', 'plg_quickicon_privacycheck/privacycheck.js', array('version' => 'auto', 'relative' => true));
+
+ return array(
+ array(
+ 'link' => $privacy . '&view=requests&filter[status]=1&list[fullordering]=a.requested_at ASC',
+ 'image' => 'users',
+ 'icon' => 'header/icon-48-user.png',
+ 'text' => Text::_('PLG_QUICKICON_PRIVACYCHECK_CHECKING'),
+ 'id' => 'plg_quickicon_privacycheck',
+ 'group' => 'MOD_QUICKICON_USERS'
+ )
+ );
+ }
+}
diff --git a/plugins/quickicon/privacycheck/privacycheck.xml b/plugins/quickicon/privacycheck/privacycheck.xml
new file mode 100644
index 0000000000000..4825bf588eaa5
--- /dev/null
+++ b/plugins/quickicon/privacycheck/privacycheck.xml
@@ -0,0 +1,19 @@
+
+
+ plg_quickicon_privacycheck
+ Joomla! Project
+ June 2018
+ Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ PLG_QUICKICON_PRIVACYCHECK_XML_DESCRIPTION
+
+ privacycheck.php
+
+
+ en-GB.plg_quickicon_privacycheck.ini
+ en-GB.plg_quickicon_privacycheck.sys.ini
+
+
diff --git a/plugins/system/actionlogs/actionlogs.php b/plugins/system/actionlogs/actionlogs.php
new file mode 100644
index 0000000000000..00b5e6ced8f56
--- /dev/null
+++ b/plugins/system/actionlogs/actionlogs.php
@@ -0,0 +1,265 @@
+subject->setError('JERROR_NOT_A_FORM');
+
+ return false;
+ }
+
+ $formName = $form->getName();
+
+ $allowedFormNames = array(
+ 'com_users.profile',
+ 'com_admin.profile',
+ 'com_users.user',
+ );
+
+ if (!in_array($formName, $allowedFormNames))
+ {
+ return true;
+ }
+
+ /**
+ * We only allow users who has Super User permission change this setting for himself or for other users
+ * who has same Super User permission
+ */
+
+ $user = JFactory::getUser();
+
+ if (!$user->authorise('core.admin'))
+ {
+ return true;
+ }
+
+ // If we are on the save command, no data is passed to $data variable, we need to get it directly from request
+ $jformData = $this->app->input->get('jform', array(), 'array');
+
+ if ($jformData && !$data)
+ {
+ $data = $jformData;
+ }
+
+ if (is_array($data))
+ {
+ $data = (object) $data;
+ }
+
+ if (!empty($data->id) && !JUser::getInstance($data->id)->authorise('core.admin'))
+ {
+ return true;
+ }
+
+ JForm::addFormPath(dirname(__FILE__) . '/forms');
+ $form->loadFile('actionlogs', false);
+ }
+
+ /**
+ * Runs after the HTTP response has been sent to the client and delete log records older than certain days
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onAfterRespond()
+ {
+ $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0);
+
+ if ($daysToDeleteAfter <= 0)
+ {
+ return;
+ }
+
+ // The delete frequency will be once per day
+ $deleteFrequency = 3600 * 24;
+
+ // Do we need to run? Compare the last run timestamp stored in the plugin's options with the current
+ // timestamp. If the difference is greater than the cache timeout we shall not execute again.
+ $now = time();
+ $last = (int) $this->params->get('lastrun', 0);
+
+ if (abs($now - $last) < $deleteFrequency)
+ {
+ return;
+ }
+
+ // Update last run status
+ $this->params->set('lastrun', $now);
+
+ $db = $this->db;
+ $query = $db->getQuery(true)
+ ->update($db->qn('#__extensions'))
+ ->set($db->qn('params') . ' = ' . $db->q($this->params->toString('JSON')))
+ ->where($db->qn('type') . ' = ' . $db->q('plugin'))
+ ->where($db->qn('folder') . ' = ' . $db->q('system'))
+ ->where($db->qn('element') . ' = ' . $db->q('actionlogs'));
+
+ try
+ {
+ // Lock the tables to prevent multiple plugin executions causing a race condition
+ $db->lockTable('#__extensions');
+ }
+ catch (Exception $e)
+ {
+ // If we can't lock the tables it's too risky to continue execution
+ return;
+ }
+
+ try
+ {
+ // Update the plugin parameters
+ $result = $db->setQuery($query)->execute();
+
+ $this->clearCacheGroups(array('com_plugins'), array(0, 1));
+ }
+ catch (Exception $exc)
+ {
+ // If we failed to execite
+ $db->unlockTables();
+ $result = false;
+ }
+
+ try
+ {
+ // Unlock the tables after writing
+ $db->unlockTables();
+ }
+ catch (Exception $e)
+ {
+ // If we can't lock the tables assume we have somehow failed
+ $result = false;
+ }
+
+ // Abort on failure
+ if (!$result)
+ {
+ return;
+ }
+
+ $daysToDeleteAfter = (int) $this->params->get('logDeletePeriod', 0);
+
+ if ($daysToDeleteAfter > 0)
+ {
+ $conditions = array($db->quoteName('log_date') . ' < DATE_SUB(NOW(), INTERVAL ' . $daysToDeleteAfter . ' DAY)');
+
+ $query->clear()
+ ->delete($db->quoteName('#__action_logs'))->where($conditions);
+ $db->setQuery($query);
+
+ try
+ {
+ $db->execute();
+ }
+ catch (RuntimeException $e)
+ {
+ // Ignore it
+ return;
+ }
+ }
+ }
+
+ /**
+ * Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp.
+ *
+ * @param array $clearGroups The cache groups to clean
+ * @param array $cacheClients The cache clients (site, admin) to clean
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function clearCacheGroups(array $clearGroups, array $cacheClients = array(0, 1))
+ {
+ $conf = JFactory::getConfig();
+
+ foreach ($clearGroups as $group)
+ {
+ foreach ($cacheClients as $client_id)
+ {
+ try
+ {
+ $options = array(
+ 'defaultgroup' => $group,
+ 'cachebase' => $client_id ? JPATH_ADMINISTRATOR . '/cache' :
+ $conf->get('cache_path', JPATH_SITE . '/cache')
+ );
+
+ $cache = JCache::getInstance('callback', $options);
+ $cache->clean();
+ }
+ catch (Exception $e)
+ {
+ // Ignore it
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/system/actionlogs/actionlogs.xml b/plugins/system/actionlogs/actionlogs.xml
new file mode 100644
index 0000000000000..d40bf67394489
--- /dev/null
+++ b/plugins/system/actionlogs/actionlogs.xml
@@ -0,0 +1,40 @@
+
+
+ PLG_SYSTEM_ACTIONLOGS
+ Joomla! Project
+ May 2018
+ Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ __DEPLOY_VERSION__
+ PLG_SYSTEM_ACTIONLOGS_XML_DESCRIPTION
+
+ actionlogs.php
+ forms
+
+
+
+
+
+
+
diff --git a/plugins/system/actionlogs/forms/actionlogs.xml b/plugins/system/actionlogs/forms/actionlogs.xml
new file mode 100644
index 0000000000000..1aef8b6157a56
--- /dev/null
+++ b/plugins/system/actionlogs/forms/actionlogs.xml
@@ -0,0 +1,27 @@
+
+
diff --git a/plugins/system/languagefilter/languagefilter.php b/plugins/system/languagefilter/languagefilter.php
index a04d7c4791a69..57b854e444fa5 100644
--- a/plugins/system/languagefilter/languagefilter.php
+++ b/plugins/system/languagefilter/languagefilter.php
@@ -518,6 +518,24 @@ public function parseRule(&$router, &$uri)
return $array;
}
+ /**
+ * Reports the privacy related capabilities for this plugin to site administrators.
+ *
+ * @return array
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onPrivacyCollectAdminCapabilities()
+ {
+ $this->loadLanguage();
+
+ return array(
+ JText::_('PLG_SYSTEM_LANGUAGEFILTER') => array(
+ JText::_('PLG_SYSTEM_LANGUAGEFILTER_PRIVACY_CAPABILITY_LANGUAGE_COOKIE'),
+ )
+ );
+ }
+
/**
* Before store user method.
*
diff --git a/plugins/system/logrotation/logrotation.php b/plugins/system/logrotation/logrotation.php
new file mode 100644
index 0000000000000..542f13e17e23c
--- /dev/null
+++ b/plugins/system/logrotation/logrotation.php
@@ -0,0 +1,274 @@
+params->get('cachetimeout', 30);
+ $cache_timeout = 24 * 3600 * $cache_timeout;
+ $logsToKeep = (int) $this->params->get('logstokeep', 1);
+
+ // Do we need to run? Compare the last run timestamp stored in the plugin's options with the current
+ // timestamp. If the difference is greater than the cache timeout we shall not execute again.
+ $now = time();
+ $last = (int) $this->params->get('lastrun', 0);
+
+ if ((abs($now - $last) < $cache_timeout))
+ {
+ return;
+ }
+
+ // Update last run status
+ $this->params->set('lastrun', $now);
+
+ $db = $this->db;
+ $query = $db->getQuery(true)
+ ->update($db->qn('#__extensions'))
+ ->set($db->qn('params') . ' = ' . $db->q($this->params->toString('JSON')))
+ ->where($db->qn('type') . ' = ' . $db->q('plugin'))
+ ->where($db->qn('folder') . ' = ' . $db->q('system'))
+ ->where($db->qn('element') . ' = ' . $db->q('logrotation'));
+
+ try
+ {
+ // Lock the tables to prevent multiple plugin executions causing a race condition
+ $db->lockTable('#__extensions');
+ }
+ catch (Exception $e)
+ {
+ // If we can't lock the tables it's too risky to continue execution
+ return;
+ }
+
+ try
+ {
+ // Update the plugin parameters
+ $result = $db->setQuery($query)->execute();
+
+ $this->clearCacheGroups(array('com_plugins'), array(0, 1));
+ }
+ catch (Exception $exc)
+ {
+ // If we failed to execite
+ $db->unlockTables();
+ $result = false;
+ }
+
+ try
+ {
+ // Unlock the tables after writing
+ $db->unlockTables();
+ }
+ catch (Exception $e)
+ {
+ // If we can't lock the tables assume we have somehow failed
+ $result = false;
+ }
+
+ // Abort on failure
+ if (!$result)
+ {
+ return;
+ }
+
+ // Get the log path
+ $logPath = Path::clean($this->app->get('log_path'));
+
+ // Invalid path, stop processing further
+ if (!is_dir($logPath))
+ {
+ return;
+ }
+
+ $logFiles = $this->getLogFiles($logPath);
+
+ // Sort log files by version number in reserve order
+ krsort($logFiles, SORT_NUMERIC);
+
+ foreach ($logFiles as $version => $files)
+ {
+ if ($version >= $logsToKeep)
+ {
+ // Delete files which has version greater than or equals $logsToKeep
+ foreach ($files as $file)
+ {
+ File::delete($logPath . '/' . $file);
+ }
+ }
+ else
+ {
+ // For files which has version smaller than $logsToKeep, rotate (increase version number)
+ foreach ($files as $file)
+ {
+ $this->rotate($logPath, $file, $version);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get log files from log folder
+ *
+ * @param string $path The folder to get log files
+ *
+ * @return array The log files in the given path grouped by version number (not rotated files has number 0)
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function getLogFiles($path)
+ {
+ $logFiles = array();
+ $files = Folder::files($path, '\.php$');
+
+ foreach ($files as $file)
+ {
+ $parts = explode('.', $file);
+
+ /*
+ * Rotated log file has this filename format [VERSION].[FILENAME].php. So if $parts has at least 3 elements
+ * and the first element is a number, we know that it's a rotated file and can get it's current version
+ */
+ if (count($parts) >= 3 && is_numeric($parts[0]))
+ {
+ $version = (int) $parts[0];
+ }
+ else
+ {
+ $version = 0;
+ }
+
+ if (!isset($logFiles[$version]))
+ {
+ $logFiles[$version] = array();
+ }
+
+ $logFiles[$version][] = $file;
+ }
+
+ return $logFiles;
+ }
+
+ /**
+ * Method to rotate (increase version) of a log file
+ *
+ * @param string $path Path to file to rotate
+ * @param string $filename Name of file to rotate
+ * @param int $currentVersion The current version number
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function rotate($path, $filename, $currentVersion)
+ {
+ if ($currentVersion === 0)
+ {
+ $rotatedFile = $path . '/1.' . $filename;
+ }
+ else
+ {
+ /*
+ * Rotated log file has this filename format [VERSION].[FILENAME].php. To rotate it, we just need to explode
+ * the filename into an array, increase value of first element (keep version) and implode it back to get the
+ * rotated file name
+ */
+ $parts = explode('.', $filename);
+ $parts[0] = $currentVersion + 1;
+
+ $rotatedFile = $path . '/' . implode('.', $parts);
+ }
+
+ File::move($path . '/' . $filename, $rotatedFile);
+ }
+
+ /**
+ * Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp.
+ *
+ * @param array $clearGroups The cache groups to clean
+ * @param array $cacheClients The cache clients (site, admin) to clean
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function clearCacheGroups(array $clearGroups, array $cacheClients = array(0, 1))
+ {
+ $conf = JFactory::getConfig();
+
+ foreach ($clearGroups as $group)
+ {
+ foreach ($cacheClients as $client_id)
+ {
+ try
+ {
+ $options = array(
+ 'defaultgroup' => $group,
+ 'cachebase' => $client_id ? JPATH_ADMINISTRATOR . '/cache' :
+ $conf->get('cache_path', JPATH_SITE . '/cache')
+ );
+
+ $cache = JCache::getInstance('callback', $options);
+ $cache->clean();
+ }
+ catch (Exception $e)
+ {
+ // Ignore it
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/system/logrotation/logrotation.xml b/plugins/system/logrotation/logrotation.xml
new file mode 100644
index 0000000000000..6b826a8d800f7
--- /dev/null
+++ b/plugins/system/logrotation/logrotation.xml
@@ -0,0 +1,57 @@
+
+
+ plg_system_logrotation
+ Joomla! Project
+ May 2018
+ Copyright (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ PLG_SYSTEM_LOGROTATION_XML_DESCRIPTION
+
+ logrotation.php
+
+
+ en-GB.plg_system_logrotation.ini
+ en-GB.plg_system_logrotation.sys.ini
+
+
+
+
+
+
+
diff --git a/plugins/system/privacyconsent/field/privacy.php b/plugins/system/privacyconsent/field/privacy.php
new file mode 100644
index 0000000000000..6a86c260a956a
--- /dev/null
+++ b/plugins/system/privacyconsent/field/privacy.php
@@ -0,0 +1,127 @@
+element['note']) ? $this->element['note'] : Text::_('PLG_SYSTEM_PRIVACYCONSENT_NOTE_FIELD_DEFAULT');
+
+ echo '
' . $privacynote . '
';
+
+ return parent::getInput();
+ }
+
+ /**
+ * Method to get the field label markup.
+ *
+ * @return string The field label markup.
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ protected function getLabel()
+ {
+ if ($this->hidden)
+ {
+ return '';
+ }
+
+ // Get the label text from the XML element, defaulting to the element name.
+ $text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
+ $text = $this->translateLabel ? Text::_($text) : $text;
+
+ // Set required to true as this field is not displayed at all if not required.
+ $this->required = true;
+
+ JHtml::_('behavior.modal');
+
+ // Build the class for the label.
+ $class = !empty($this->description) ? 'hasPopover' : '';
+ $class = $class . ' required';
+ $class = !empty($this->labelClass) ? $class . ' ' . $this->labelClass : $class;
+
+ // Add the opening label tag and main attributes.
+ $label = '
';
+
+ return $label;
+ }
+}
diff --git a/plugins/system/privacyconsent/privacyconsent.php b/plugins/system/privacyconsent/privacyconsent.php
new file mode 100644
index 0000000000000..8172594f03ad6
--- /dev/null
+++ b/plugins/system/privacyconsent/privacyconsent.php
@@ -0,0 +1,701 @@
+_subject->setError('JERROR_NOT_A_FORM');
+
+ return false;
+ }
+
+ // Check we are manipulating a valid form - we only display this on user registration form and user profile form.
+ $name = $form->getName();
+
+ if (!in_array($name, array('com_users.profile', 'com_users.registration')))
+ {
+ return true;
+ }
+
+ // We only display this if user has not consented before
+ if (is_object($data))
+ {
+ $userId = isset($data->id) ? $data->id : 0;
+
+ if ($userId > 0 && $this->isUserConsented($userId))
+ {
+ return true;
+ }
+ }
+
+ // Add the privacy policy fields to the form.
+ JForm::addFormPath(__DIR__ . '/privacyconsent');
+ $form->loadFile('privacyconsent');
+
+ $privacyArticleId = $this->getPrivacyArticleId();
+ $privacynote = $this->params->get('privacy_note');
+
+ // Push the privacy article ID into the privacy field.
+ $form->setFieldAttribute('privacy', 'article', $privacyArticleId, 'privacyconsent');
+ $form->setFieldAttribute('privacy', 'note', $privacynote, 'privacyconsent');
+ }
+
+ /**
+ * Method is called before user data is stored in the database
+ *
+ * @param array $user Holds the old user data.
+ * @param boolean $isNew True if a new user is stored.
+ * @param array $data Holds the new user data.
+ *
+ * @return boolean
+ *
+ * @since __DEPLOY_VERSION__
+ * @throws InvalidArgumentException on missing required data.
+ */
+ public function onUserBeforeSave($user, $isNew, $data)
+ {
+ // // Only check for front-end user creation/update profile
+ if ($this->app->isClient('administrator'))
+ {
+ return true;
+ }
+
+ $userId = ArrayHelper::getValue($user, 'id', 0, 'int');
+
+ // User already consented before, no need to check it further
+ if ($userId > 0 && $this->isUserConsented($userId))
+ {
+ return true;
+ }
+
+ // Check that the privacy is checked if required ie only in registration from frontend.
+ $option = $this->app->input->getCmd('option');
+ $task = $this->app->input->get->getCmd('task');
+ $form = $this->app->input->post->get('jform', array(), 'array');
+
+ if ($option == 'com_users' && in_array($task, array('registration.register', 'profile.save'))
+ && empty($form['privacyconsent']['privacy']))
+ {
+ throw new InvalidArgumentException(Text::_('PLG_SYSTEM_PRIVACYCONSENT_FIELD_ERROR'));
+ }
+
+ return true;
+ }
+
+ /**
+ * Saves user privacy confirmation
+ *
+ * @param array $data entered user data
+ * @param boolean $isNew true if this is a new user
+ * @param boolean $result true if saving the user worked
+ * @param string $error error message
+ *
+ * @return boolean
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserAfterSave($data, $isNew, $result, $error)
+ {
+ // Only create an entry on front-end user creation/update profile
+ if ($this->app->isClient('administrator'))
+ {
+ return true;
+ }
+
+ // Get the user's ID
+ $userId = ArrayHelper::getValue($data, 'id', 0, 'int');
+
+ // If user already consented before, no need to check it further
+ if ($userId > 0 && $this->isUserConsented($userId))
+ {
+ return true;
+ }
+
+ $option = $this->app->input->getCmd('option');
+ $task = $this->app->input->get->getCmd('task');
+ $form = $this->app->input->post->get('jform', array(), 'array');
+
+ if ($option == 'com_users'
+ &&in_array($task, array('registration.register', 'profile.save'))
+ && !empty($form['privacyconsent']['privacy']))
+ {
+ $userId = ArrayHelper::getValue($data, 'id', 0, 'int');
+
+ // Get the user's IP address
+ $ip = $this->app->input->server->get('REMOTE_ADDR', '', 'string');
+
+ // Get the user agent string
+ $userAgent = $this->app->input->server->get('HTTP_USER_AGENT', '', 'string');
+
+ // Create the user note
+ $userNote = (object) array(
+ 'user_id' => $userId,
+ 'subject' => Text::_('PLG_SYSTEM_PRIVACYCONSENT_SUBJECT'),
+ 'body' => Text::sprintf('PLG_SYSTEM_PRIVACYCONSENT_BODY', $ip, $userAgent),
+ 'created' => Factory::getDate()->toSql(),
+ );
+
+ try
+ {
+ $this->db->insertObject('#__privacy_consents', $userNote);
+ }
+ catch (Exception $e)
+ {
+ // Do nothing if the save fails
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Remove all user privacy consent information for the given user ID
+ *
+ * Method is called after user data is deleted from the database
+ *
+ * @param array $user Holds the user data
+ * @param boolean $success True if user was succesfully stored in the database
+ * @param string $msg Message
+ *
+ * @return boolean
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserAfterDelete($user, $success, $msg)
+ {
+ if (!$success)
+ {
+ return false;
+ }
+
+ $userId = ArrayHelper::getValue($user, 'id', 0, 'int');
+
+ if ($userId)
+ {
+ // Remove user's consent
+ try
+ {
+ $query = $this->db->getQuery(true)
+ ->delete($this->db->quoteName('#__privacy_consents'))
+ ->where($this->db->quoteName('user_id') . ' = ' . (int) $userId);
+ $this->db->setQuery($query);
+ $this->db->execute();
+ }
+ catch (Exception $e)
+ {
+ $this->_subject->setError($e->getMessage());
+
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * If logged in users haven't agreed to privacy consent, redirect them to profile edit page, ask them to agree to
+ * privacy consent before allowing access to any other pages
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onAfterRoute()
+ {
+ // Run this in frontend only
+ if ($this->app->isClient('administrator'))
+ {
+ return;
+ }
+
+ $userId = Factory::getUser()->id;
+
+ // Check to see whether user already consented, if not, redirect to user profile page
+ if ($userId > 0)
+ {
+ // If user consented before, no need to check it further
+ if ($this->isUserConsented($userId))
+ {
+ return;
+ }
+
+ $option = $this->app->input->getCmd('option');
+ $task = $this->app->input->get('task');
+ $view = $this->app->input->getString('view', '');
+ $layout = $this->app->input->getString('layout', '');
+ $id = $this->app->input->getInt('id');
+
+ $privacyArticleId = $this->getPrivacyArticleId();
+
+ /*
+ * If user is already on edit profile screen or view privacy article
+ * or press update/apply button, or logout, do nothing to avoid infinite redirect
+ */
+ if ($option == 'com_users' && in_array($task, array('profile.save', 'profile.apply', 'user.logout'))
+ || ($option == 'com_content' && $view == 'article' && $id == $privacyArticleId)
+ || ($option == 'com_users' && $view == 'profile' && $layout == 'edit'))
+ {
+ return;
+ }
+
+ // Redirect to com_users profile edit
+ $this->app->enqueueMessage($this->getRedirectMessage(), 'notice');
+ $link = 'index.php?option=com_users&view=profile&layout=edit';
+ $this->app->redirect(\JRoute::_($link, false));
+ }
+ }
+
+ /**
+ * Event to specify whether a privacy policy has been published.
+ *
+ * @param array &$policy The privacy policy status data, passed by reference, with keys "published" and "editLink"
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onPrivacyCheckPrivacyPolicyPublished(&$policy)
+ {
+ // If another plugin has already indicated a policy is published, we won't change anything here
+ if ($policy['published'])
+ {
+ return;
+ }
+
+ $articleId = $this->params->get('privacy_article');
+
+ if (!$articleId)
+ {
+ return;
+ }
+
+ $policy['published'] = true;
+ $policy['editLink'] = JRoute::_('index.php?option=com_content&task=article.edit&id=' . $articleId);
+ }
+
+ /**
+ * Returns the configured redirect message and falls back to the default version.
+ *
+ * @return string redirect message
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function getRedirectMessage()
+ {
+ $messageOnRedirect = trim($this->params->get('messageOnRedirect', ''));
+
+ if (empty($messageOnRedirect))
+ {
+ return Text::_('PLG_SYSTEM_PRIVACYCONSENT_REDIRECT_MESSAGE_DEFAULT');
+ }
+
+ return $messageOnRedirect;
+ }
+
+ /**
+ * Method to check if the given user has consented yet
+ *
+ * @param integer $userId ID of uer to check
+ *
+ * @return boolean
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function isUserConsented($userId)
+ {
+ $query = $this->db->getQuery(true);
+ $query->select('COUNT(*)')
+ ->from('#__privacy_consents')
+ ->where('user_id = ' . (int) $userId);
+ $this->db->setQuery($query);
+
+ return (int) $this->db->loadResult() > 0;
+ }
+
+ /**
+ * Get privacy article ID. If the site is a multilingual website and there is associated article for the
+ * current language, ID of the associlated article will be returned
+ *
+ * @return integer
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function getPrivacyArticleId()
+ {
+ $privacyArticleId = $this->params->get('privacy_article');
+
+ if ($privacyArticleId > 0 && JLanguageAssociations::isEnabled())
+ {
+ $privacyAssociated = JLanguageAssociations::getAssociations('com_content', '#__content', 'com_content.item', $privacyArticleId);
+ $currentLang = JFactory::getLanguage()->getTag();
+
+ if (isset($privacyAssociated[$currentLang]))
+ {
+ $privacyArticleId = $privacyAssociated[$currentLang]->id;
+ }
+ }
+
+ return $privacyArticleId;
+ }
+
+ /**
+ * The privacy consent expiration check code is triggered after the page has fully rendered.
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onAfterRender()
+ {
+ if (!$this->params->get('enabled', 0))
+ {
+ return;
+ }
+
+ $cacheTimeout = (int) $this->params->get('cachetimeout', 30);
+ $cacheTimeout = 24 * 3600 * $cacheTimeout;
+
+ // Do we need to run? Compare the last run timestamp stored in the plugin's options with the current
+ // timestamp. If the difference is greater than the cache timeout we shall not execute again.
+ $now = time();
+ $last = (int) $this->params->get('lastrun', 0);
+
+ if ((abs($now - $last) < $cacheTimeout))
+ {
+ return;
+ }
+
+ // Update last run status
+ $this->params->set('lastrun', $now);
+ $db = $this->db;
+ $query = $db->getQuery(true)
+ ->update($db->quoteName('#__extensions'))
+ ->set($db->quoteName('params') . ' = ' . $db->quote($this->params->toString('JSON')))
+ ->where($db->quoteName('type') . ' = ' . $db->quote('plugin'))
+ ->where($db->quoteName('folder') . ' = ' . $db->quote('system'))
+ ->where($db->quoteName('element') . ' = ' . $db->quote('privacyconsent'));
+
+ try
+ {
+ // Lock the tables to prevent multiple plugin executions causing a race condition
+ $db->lockTable('#__extensions');
+ }
+ catch (Exception $e)
+ {
+ // If we can't lock the tables it's too risky to continue execution
+ return;
+ }
+
+ try
+ {
+ // Update the plugin parameters
+ $result = $db->setQuery($query)->execute();
+ $this->clearCacheGroups(array('com_plugins'), array(0, 1));
+ }
+ catch (Exception $exc)
+ {
+ // If we failed to execute
+ $db->unlockTables();
+ $result = false;
+ }
+
+ try
+ {
+ // Unlock the tables after writing
+ $db->unlockTables();
+ }
+ catch (Exception $e)
+ {
+ // If we can't lock the tables assume we have somehow failed
+ $result = false;
+ }
+
+ // Abort on failure
+ if (!$result)
+ {
+ return;
+ }
+
+ // Delete the expired privacy consents
+ $this->deleteExpiredConsents();
+
+ // Remind for privacy consents near to expire
+ $this->remindExpiringConsents();
+
+ }
+
+ /**
+ * Method to send the remind for privacy consents renew
+ *
+ * @return integer
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function remindExpiringConsents()
+ {
+ // Load the parameters.
+ $expire = (int) $this->params->get('consentexpiration', 365);
+ $remind = (int) $this->params->get('remind', 30);
+ $now = JFactory::getDate()->toSql();
+ $period = '-' . ($expire - $remind);
+
+ $db = $this->db;
+ $query = $db->getQuery(true)
+ ->select($db->quoteName(array('r.id', 'r.user_id', 'u.email')))
+ ->from($db->quoteName('#__privacy_consents', 'r'))
+ ->leftJoin($db->quoteName('#__users', 'u') . ' ON u.id = r.user_id')
+ ->where($db->quoteName('remind') . ' = 0');
+ $query->where($query->dateAdd($now, $period, 'DAY') . ' > ' . $db->quoteName('created'));
+
+ try
+ {
+ $users = $db->setQuery($query)->loadObjectList();
+ }
+ catch (JDatabaseException $exception)
+ {
+ return false;
+ }
+
+ $app = JFactory::getApplication();
+ $linkMode = $app->get('force_ssl', 0) == 2 ? 1 : -1;
+
+ foreach ($users as $user)
+ {
+ $token = JApplicationHelper::getHash(JUserHelper::genRandomPassword());
+ $hashedToken = JUserHelper::hashPassword($token);
+
+ // The mail
+ try
+ {
+ $substitutions = array(
+ '[SITENAME]' => $app->get('sitename'),
+ '[URL]' => JUri::root(),
+ '[TOKENURL]' => JRoute::link('site', 'index.php?option=com_privacy&view=remind&remind_token=' . $token, false, $linkMode),
+ '[FORMURL]' => JRoute::link('site', 'index.php?option=com_privacy&view=remind', false, $linkMode),
+ '[TOKEN]' => $token,
+ '\\n' => "\n",
+ );
+
+ $emailSubject = JText::_('PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_SUBJECT');
+ $emailBody = JText::_('PLG_SYSTEM_PRIVACYCONSENT_EMAIL_REMIND_BODY');
+
+ foreach ($substitutions as $k => $v)
+ {
+ $emailSubject = str_replace($k, $v, $emailSubject);
+ $emailBody = str_replace($k, $v, $emailBody);
+ }
+
+ $mailer = JFactory::getMailer();
+ $mailer->setSubject($emailSubject);
+ $mailer->setBody($emailBody);
+ $mailer->addRecipient($user->email);
+
+ $mailResult = $mailer->Send();
+
+ if ($mailResult instanceof JException)
+ {
+ return false;
+ }
+ elseif ($mailResult === false)
+ {
+ return false;
+ }
+
+ // Update the privacy_consents item to not send the reminder again
+ $query->clear()
+ ->update($db->quoteName('#__privacy_consents'))
+ ->set($db->quoteName('remind') . ' = 1 ')
+ ->set($db->quoteName('token') . ' = ' . $db->quote($hashedToken))
+ ->where($db->quoteName('id') . ' = ' . $db->quote($user->id));
+ $db->setQuery($query);
+
+ try
+ {
+ $db->execute();
+ }
+ catch (RuntimeException $e)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ catch (phpmailerException $exception)
+ {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Method to delete the expired privacy consents
+ *
+ * @return boolean
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function deleteExpiredConsents()
+ {
+ // Load the parameters.
+ $expire = (int) $this->params->get('consentexpiration', 365);
+ $now = JFactory::getDate()->toSql();
+ $period = '-' . $expire;
+
+ $db = $this->db;
+ $query = $db->getQuery(true)
+ ->select($db->quoteName(array('id', 'user_id')))
+ ->from($db->quoteName('#__privacy_consents'));
+ $query->where($query->dateAdd($now, $period, 'DAY') . ' > ' . $db->quoteName('created'));
+ $db->setQuery($query);
+
+ try
+ {
+ $users = $db->loadObjectList();
+ }
+ catch (RuntimeException $e)
+ {
+ return false;
+ }
+
+ // Do not process further if no expired consents found
+ if (empty($users))
+ {
+ return true;
+ }
+
+ // Push a notification to the site's super users
+ JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_messages/models', 'MessagesModel');
+ JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_messages/tables');
+ /** @var MessagesModelMessage $messageModel */
+ $messageModel = JModelLegacy::getInstance('Message', 'MessagesModel');
+
+ foreach ($users as $user)
+ {
+ $query = $db->getQuery(true)
+ ->delete($db->quoteName('#__privacy_consents'));
+ $query->where($db->quoteName('id') . ' = ' . $user->id);
+ $db->setQuery($query);
+
+ try
+ {
+ $db->execute();
+ }
+ catch (RuntimeException $e)
+ {
+ return false;
+ }
+
+ $messageModel->notifySuperUsers(
+ JText::_('PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_SUBJECT'),
+ JText::sprintf('PLG_SYSTEM_PRIVACYCONSENT_NOTIFICATION_USER_PRIVACY_EXPIRED_MESSAGE', $user->user_id)
+ );
+ }
+
+ return true;
+ }
+ /**
+ * Clears cache groups. We use it to clear the plugins cache after we update the last run timestamp.
+ *
+ * @param array $clearGroups The cache groups to clean
+ * @param array $cacheClients The cache clients (site, admin) to clean
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ private function clearCacheGroups(array $clearGroups, array $cacheClients = array(0, 1))
+ {
+ $conf = JFactory::getConfig();
+
+ foreach ($clearGroups as $group)
+ {
+ foreach ($cacheClients as $client_id)
+ {
+ try
+ {
+ $options = array(
+ 'defaultgroup' => $group,
+ 'cachebase' => $client_id ? JPATH_ADMINISTRATOR . '/cache' :
+ $conf->get('cache_path', JPATH_SITE . '/cache')
+ );
+
+ $cache = JCache::getInstance('callback', $options);
+ $cache->clean();
+ }
+ catch (Exception $e)
+ {
+ // Ignore it
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/system/privacyconsent/privacyconsent.xml b/plugins/system/privacyconsent/privacyconsent.xml
new file mode 100644
index 0000000000000..f995ddc8686b2
--- /dev/null
+++ b/plugins/system/privacyconsent/privacyconsent.xml
@@ -0,0 +1,119 @@
+
+
+ plg_system_privacyconsent
+ Joomla! Project
+ April 2018
+ (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ PLG_SYSTEM_PRIVACYCONSENT_XML_DESCRIPTION
+
+ privacyconsent.php
+ privacyconsent
+ field
+
+
+ en-GB.plg_system_privacyconsent.ini
+ en-GB.plg_system_privacyconsent.sys.ini
+
+
+
+
+
+
+
+
diff --git a/plugins/system/privacyconsent/privacyconsent/privacyconsent.xml b/plugins/system/privacyconsent/privacyconsent/privacyconsent.xml
new file mode 100644
index 0000000000000..f86b54faaf58c
--- /dev/null
+++ b/plugins/system/privacyconsent/privacyconsent/privacyconsent.xml
@@ -0,0 +1,21 @@
+
+
diff --git a/plugins/user/terms/field/terms.php b/plugins/user/terms/field/terms.php
new file mode 100644
index 0000000000000..e82996b800703
--- /dev/null
+++ b/plugins/user/terms/field/terms.php
@@ -0,0 +1,146 @@
+element['note']) ? $this->element['note'] : Text::_('PLG_USER_TERMS_NOTE_FIELD_DEFAULT');
+
+ echo '
' . $termsnote . '
';
+
+ return parent::getInput();
+ }
+
+ /**
+ * Method to get the field label markup.
+ *
+ * @return string The field label markup.
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ protected function getLabel()
+ {
+ if ($this->hidden)
+ {
+ return '';
+ }
+
+ // Get the label text from the XML element, defaulting to the element name.
+ $text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
+ $text = $this->translateLabel ? Text::_($text) : $text;
+
+ // Set required to true
+ $this->required = true;
+
+ JHtml::_('behavior.modal');
+
+ // Build the class for the label.
+ $class = !empty($this->description) ? 'hasPopover' : '';
+ $class = $class . ' required';
+ $class = !empty($this->labelClass) ? $class . ' ' . $this->labelClass : $class;
+
+ // Add the opening label tag and main attributes.
+ $label = '
';
+
+ return $label;
+ }
+}
diff --git a/plugins/user/terms/terms.php b/plugins/user/terms/terms.php
new file mode 100644
index 0000000000000..a5e4e3b7e5d82
--- /dev/null
+++ b/plugins/user/terms/terms.php
@@ -0,0 +1,178 @@
+_subject->setError('JERROR_NOT_A_FORM');
+
+ return false;
+ }
+
+ // Check we are manipulating a valid form - we only display this on user registration form.
+ $name = $form->getName();
+
+ if (!in_array($name, array('com_users.registration')))
+ {
+ return true;
+ }
+
+ // Add the terms and conditions fields to the form.
+ JForm::addFormPath(__DIR__ . '/terms');
+ $form->loadFile('terms');
+
+ $termsarticle = $this->params->get('terms_article');
+ $termsnote = $this->params->get('terms_note');
+
+ // Push the terms and conditions article ID into the terms field.
+ $form->setFieldAttribute('terms', 'article', $termsarticle, 'terms');
+ $form->setFieldAttribute('terms', 'note', $termsnote, 'terms');
+ }
+
+ /**
+ * Method is called before user data is stored in the database
+ *
+ * @param array $user Holds the old user data.
+ * @param boolean $isNew True if a new user is stored.
+ * @param array $data Holds the new user data.
+ *
+ * @return boolean
+ *
+ * @since __DEPLOY_VERSION__
+ * @throws InvalidArgumentException on missing required data.
+ */
+ public function onUserBeforeSave($user, $isNew, $data)
+ {
+ // // Only check for front-end user registration
+ if ($this->app->isClient('administrator'))
+ {
+ return true;
+ }
+
+ $userId = ArrayHelper::getValue($user, 'id', 0, 'int');
+
+ // User already registered, no need to check it further
+ if ($userId > 0)
+ {
+ return true;
+ }
+
+ // Check that the terms is checked if required ie only in registration from frontend.
+ $option = $this->app->input->getCmd('option');
+ $task = $this->app->input->get->getCmd('task');
+ $form = $this->app->input->post->get('jform', array(), 'array');
+
+ if ($option == 'com_users' && in_array($task, array('registration.register')) && empty($form['terms']['terms']))
+ {
+ throw new InvalidArgumentException(Text::_('PLG_USER_TERMS_FIELD_ERROR'));
+ }
+
+ return true;
+ }
+
+ /**
+ * Saves user profile data
+ *
+ * @param array $data entered user data
+ * @param boolean $isNew true if this is a new user
+ * @param boolean $result true if saving the user worked
+ * @param string $error error message
+ *
+ * @return boolean
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onUserAfterSave($data, $isNew, $result, $error)
+ {
+ if (!$isNew || !$result)
+ {
+ return true;
+ }
+
+ JLoader::register('ActionlogsModelActionlog', JPATH_ADMINISTRATOR . '/components/com_actionlogs/models/actionlog.php');
+ $userId = ArrayHelper::getValue($data, 'id', 0, 'int');
+
+ $message = array(
+ 'action' => 'consent',
+ 'id' => $userId,
+ 'title' => $data['name'],
+ 'itemlink' => 'index.php?option=com_users&task=user.edit&id=' . $userId,
+ 'userid' => $userId,
+ 'username' => $data['username'],
+ 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $userId,
+ );
+
+ /* @var ActionlogsModelActionlog $model */
+ $model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel');
+ $model->addLog(array($message), 'PLG_USER_TERMS_LOGGING_CONSENT_TO_TERMS', 'plg_user_terms', $userId);
+ }
+}
diff --git a/plugins/user/terms/terms.xml b/plugins/user/terms/terms.xml
new file mode 100644
index 0000000000000..f3c8a9286bd03
--- /dev/null
+++ b/plugins/user/terms/terms.xml
@@ -0,0 +1,49 @@
+
+
+ plg_user_terms
+ Joomla! Project
+ June 2018
+ (C) 2005 - 2018 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 3.9.0
+ PLG_USER_TERMS_XML_DESCRIPTION
+
+ terms.php
+ terms
+ field
+
+
+ en-GB.plg_user_terms.ini
+ en-GB.plg_user_terms.sys.ini
+
+
+
+
+
+
+
diff --git a/plugins/user/terms/terms/terms.xml b/plugins/user/terms/terms/terms.xml
new file mode 100644
index 0000000000000..c654e3cc3e44a
--- /dev/null
+++ b/plugins/user/terms/terms/terms.xml
@@ -0,0 +1,21 @@
+
+