diff --git a/administrator/language/en-GB/plg_content_confirmconsent.ini b/administrator/language/en-GB/plg_content_confirmconsent.ini index 0818359b2238c..ebe9600666c26 100644 --- a/administrator/language/en-GB/plg_content_confirmconsent.ini +++ b/administrator/language/en-GB/plg_content_confirmconsent.ini @@ -7,7 +7,11 @@ PLG_CONTENT_CONFIRMCONSENT="Content - Confirm Consent" 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_MENU_ITEM_LABEL="Privacy Menu Item" 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" +PLG_CONTENT_CONFIRMCONSENT_FIELD_TYPE_ARTICLE="Article" +PLG_CONTENT_CONFIRMCONSENT_FIELD_TYPE_LABEL="Privacy Type" +PLG_CONTENT_CONFIRMCONSENT_FIELD_TYPE_MENU_ITEM="Menu Item" 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/plg_system_privacyconsent.ini b/administrator/language/en-GB/plg_system_privacyconsent.ini index d0fd53cb401ae..23d5922a6b3a5 100644 --- a/administrator/language/en-GB/plg_system_privacyconsent.ini +++ b/administrator/language/en-GB/plg_system_privacyconsent.ini @@ -27,6 +27,10 @@ PLG_SYSTEM_PRIVACYCONSENT_FIELD_ENABLED_DESC="When enabled it performs checks fo 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_FIELD_MENU_ITEM_LABEL="Privacy Menu Item" +PLG_SYSTEM_PRIVACYCONSENT_FIELD_TYPE_ARTICLE="Article" +PLG_SYSTEM_PRIVACYCONSENT_FIELD_TYPE_LABEL="Privacy Type" +PLG_SYSTEM_PRIVACYCONSENT_FIELD_TYPE_MENU_ITEM="Menu Item" PLG_SYSTEM_PRIVACYCONSENT_LABEL="Website Privacy" PLG_SYSTEM_PRIVACYCONSENT_NOTE_FIELD_DEFAULT="By signing up to this website and agreeing to the Privacy Policy you agree to this website 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." diff --git a/layouts/plugins/system/privacyconsent/label.php b/layouts/plugins/system/privacyconsent/label.php index 27c5c53c25ee2..1e57ed60a3aad 100644 --- a/layouts/plugins/system/privacyconsent/label.php +++ b/layouts/plugins/system/privacyconsent/label.php @@ -47,8 +47,9 @@ * @var array $translateLabel Should the label be translated? * @var array $translateDescription Should the description be translated? * @var array $translateHint Should the hint be translated? - * @var array $privacyArticle The Article ID holding the Privacy Article - * @var object $article The Article object + * @var array $privacyArticle The Article ID holding the Privacy Article. + * @var object $article The Article object. + * @var object $privacyLink Link to the privacy article or menu item. */ // Get the label text from the XML element, defaulting to the element name. @@ -82,20 +83,20 @@ $label .= ' data-placement="left"'; } -if ($article) +if ($privacyLink) { $attribs = [ 'data-toggle' => 'modal', 'data-target' => '#consentModal', ]; - $link = HTMLHelper::_('link', Route::_($article->link . '&tmpl=component'), $text, $attribs); + $link = HTMLHelper::_('link', Route::_($privacyLink . '&tmpl=component'), $text, $attribs); echo HTMLHelper::_( 'bootstrap.renderModal', 'consentModal', [ - 'url' => Route::_($article->link . '&tmpl=component'), + 'url' => Route::_($privacyLink . '&tmpl=component'), 'title' => $text, 'height' => '100%', 'width' => '100%', diff --git a/plugins/content/confirmconsent/confirmconsent.php b/plugins/content/confirmconsent/confirmconsent.php index 05d40dc69a9be..34a0d045b35d7 100644 --- a/plugins/content/confirmconsent/confirmconsent.php +++ b/plugins/content/confirmconsent/confirmconsent.php @@ -67,6 +67,8 @@ public function onContentPrepareForm(Form $form, $data) // Get the consent box Text & the selected privacyarticle $consentboxText = (string) $this->params->get('consentbox_text', Text::_('PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DEFAULT')); $privacyArticle = $this->params->get('privacy_article', false); + $privacyType = $this->params->get('privacy_type', 'article'); + $privacyMenuItem = $this->params->get('privacy_menu_item', false); $form->load('
@@ -75,6 +77,8 @@ public function onContentPrepareForm(Form $form, $data) name="consentbox" type="ConsentBox" articleid="' . $privacyArticle . '" + menu_item_id="' . $privacyMenuItem . '" + privacy_type="' . $privacyType . '" label="PLG_CONTENT_CONFIRMCONSENT_CONSENTBOX_LABEL" required="true" > diff --git a/plugins/content/confirmconsent/confirmconsent.xml b/plugins/content/confirmconsent/confirmconsent.xml index 6b7d498f72b15..87c0dd563d232 100644 --- a/plugins/content/confirmconsent/confirmconsent.xml +++ b/plugins/content/confirmconsent/confirmconsent.xml @@ -32,6 +32,16 @@ filter="html" /> + + + + + diff --git a/plugins/content/confirmconsent/src/Field/ConsentBoxField.php b/plugins/content/confirmconsent/src/Field/ConsentBoxField.php index 9f20c66da4811..08b56cb6375d5 100644 --- a/plugins/content/confirmconsent/src/Field/ConsentBoxField.php +++ b/plugins/content/confirmconsent/src/Field/ConsentBoxField.php @@ -15,9 +15,11 @@ use Joomla\CMS\Form\Field\CheckboxesField; use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Associations; +use Joomla\CMS\Language\Multilanguage; use Joomla\CMS\Router\Route; use Joomla\Component\Content\Site\Helper\RouteHelper; use Joomla\Database\Exception\ExecutionFailureException; +use Joomla\Database\ParameterType; /** * Consentbox Field class for the Confirm Consent Plugin. @@ -50,6 +52,22 @@ class ConsentBoxField extends CheckboxesField */ protected $articleid; + /** + * The menu item ID. + * + * @var integer + * @since __DEPLOY_VERSION__ + */ + protected $menuItemId; + + /** + * Type of the privacy policy. + * + * @var string + * @since __DEPLOY_VERSION__ + */ + protected $privacyType; + /** * Method to set certain otherwise inaccessible properties of the form field object. * @@ -114,6 +132,8 @@ public function setup(\SimpleXMLElement $element, $value, $group = null) if ($return) { $this->articleid = (int) $this->element['articleid']; + $this->menuItemId = (int) $this->element['menu_item_id']; + $this->privacyType = (string) $this->element['privacy_type']; } return $return; @@ -139,7 +159,10 @@ protected function getLabel() $position = $this->element['name'] == 'alias' ? ' data-placement="bottom" ' : ''; // When we have an article let's add the modal and make the title clickable - if ($data['articleid']) + $hasLink = ($data['privacyType'] === 'article' && $data['articleid']) + || ($data['privacyType'] === 'menu_item' && $data['menuItemId']); + + if ($hasLink) { $attribs['data-toggle'] = 'modal'; @@ -174,10 +197,13 @@ protected function getInput() $modalHtml = ''; $layoutData = $this->getLayoutData(); - if ($this->articleid) + $hasLink = ($this->privacyType === 'article' && $this->articleid) + || ($this->privacyType === 'menu_item' && $this->menuItemId); + + if ($hasLink) { $modalParams['title'] = $layoutData['label']; - $modalParams['url'] = $this->getAssignedArticleUrl(); + $modalParams['url'] = ($this->privacyType === 'menu_item') ? $this->getAssignedMenuItemUrl() : $this->getAssignedArticleUrl(); $modalParams['height'] = 800; $modalParams['width'] = '100%'; $modalHtml = HTMLHelper::_('bootstrap.renderModal', 'modal-' . $this->id, $modalParams); @@ -199,6 +225,8 @@ protected function getLayoutData() $extraData = array( 'articleid' => (integer) $this->articleid, + 'menuItemId' => (integer) $this->menuItemId, + 'privacyType' => (string) $this->privacyType, ); return array_merge($data, $extraData); @@ -276,4 +304,47 @@ private function getAssignedArticleUrl() . '&tmpl=component&lang=' . $article->language ); } + + /** + * Get privacy menu item URL. If the site is a multilingual website and there is associated menu item for the + * current language, the URL of the associated menu item will be returned. + * + * @return string + * + * @since __DEPLOY_VERSION__ + */ + private function getAssignedMenuItemUrl() + { + $itemId = $this->menuItemId; + $languageSuffix = ''; + + if ($itemId > 0 && Associations::isEnabled()) + { + $privacyAssociated = Associations::getAssociations('com_menus', '#__menu', 'com_menus.item', $itemId, 'id', '', ''); + $currentLang = Factory::getLanguage()->getTag(); + + if (isset($privacyAssociated[$currentLang])) + { + $itemId = $privacyAssociated[$currentLang]->id; + } + + if (Multilanguage::isEnabled()) + { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName(['id', 'language'])) + ->from($db->quoteName('#__menu')) + ->where($db->quoteName('id') . ' = :id') + ->bind(':id', $itemId, ParameterType::INTEGER); + $db->setQuery($query); + $menuItem = $db->loadObject(); + + $languageSuffix = '&lang=' . $menuItem->language; + } + } + + return Route::_( + 'index.php?Itemid=' . (int) $itemId . '&tmpl=component' . $languageSuffix + ); + } } diff --git a/plugins/system/privacyconsent/privacyconsent.php b/plugins/system/privacyconsent/privacyconsent.php index b1e2d6dc276a9..95921257aff59 100644 --- a/plugins/system/privacyconsent/privacyconsent.php +++ b/plugins/system/privacyconsent/privacyconsent.php @@ -94,11 +94,12 @@ public function onContentPrepareForm(Form $form, $data) FormHelper::addFormPath(__DIR__ . '/forms'); $form->loadFile('privacyconsent'); - $privacyArticleId = $this->getPrivacyArticleId(); - $privacynote = $this->params->get('privacy_note'); + $privacyType = $this->params->get('privacy_type', 'article'); + $privacyId = ($privacyType == 'menu_item') ? $this->getPrivacyItemId() : $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', $privacyType, $privacyId, 'privacyconsent'); $form->setFieldAttribute('privacy', 'note', $privacynote, 'privacyconsent'); } @@ -439,6 +440,32 @@ private function getPrivacyArticleId() return $privacyArticleId; } + /** + * Get privacy menu item ID. If the site is a multilingual website and there is associated menu item for the + * current language, ID of the associated menu item will be returned. + * + * @return integer + * + * @since __DEPLOY_VERSION__ + */ + private function getPrivacyItemId() + { + $itemId = $this->params->get('privacy_menu_item'); + + if ($itemId > 0 && Associations::isEnabled()) + { + $privacyAssociated = Associations::getAssociations('com_menus', '#__menu', 'com_menus.item', $itemId, 'id', '', ''); + $currentLang = Factory::getLanguage()->getTag(); + + if (isset($privacyAssociated[$currentLang])) + { + $itemId = $privacyAssociated[$currentLang]->id; + } + } + + return $itemId; + } + /** * The privacy consent expiration check code is triggered after the page has fully rendered. * diff --git a/plugins/system/privacyconsent/privacyconsent.xml b/plugins/system/privacyconsent/privacyconsent.xml index 640b2ba1083fd..d7bafc89e5054 100644 --- a/plugins/system/privacyconsent/privacyconsent.xml +++ b/plugins/system/privacyconsent/privacyconsent.xml @@ -32,6 +32,16 @@ cols="20" filter="html" /> + + + + + element['article'] > 0 ? (int) $this->element['article'] : 0; if ($privacyArticle && Factory::getApplication()->isClient('site')) @@ -92,6 +94,28 @@ protected function getLayoutData() $slug = $article->alias ? ($article->id . ':' . $article->alias) : $article->id; $article->link = RouteHelper::getArticleRoute($slug, $article->catid, $article->language); + $link = $article->link; + } + + $privacyMenuItem = $this->element['menu_item'] > 0 ? (int) $this->element['menu_item'] : 0; + + if ($privacyMenuItem && Factory::getApplication()->isClient('site')) + { + $link = 'index.php?Itemid=' . $privacyMenuItem; + + if (Multilanguage::isEnabled()) + { + $db = Factory::getDbo(); + $query = $db->getQuery(true) + ->select($db->quoteName(['id', 'language'])) + ->from($db->quoteName('#__menu')) + ->where($db->quoteName('id') . ' = :id') + ->bind(':id', $privacyMenuItem, ParameterType::INTEGER); + $db->setQuery($query); + $menuItem = $db->loadObject(); + + $link .= '&lang=' . $menuItem->language; + } } $extraData = [ @@ -103,6 +127,7 @@ protected function getLayoutData() 'translateHint' => $this->translateHint, 'privacyArticle' => $privacyArticle, 'article' => $article, + 'privacyLink' => $link, ]; return array_merge($data, $extraData);