content; ?>
diff --git a/libraries/src/Document/Renderer/Html/ModulesRenderer.php b/libraries/src/Document/Renderer/Html/ModulesRenderer.php
index 70629c347e1fa..90f277bc08017 100644
--- a/libraries/src/Document/Renderer/Html/ModulesRenderer.php
+++ b/libraries/src/Document/Renderer/Html/ModulesRenderer.php
@@ -40,7 +40,7 @@ public function render($position, $params = array(), $content = null)
$app = Factory::getApplication();
$user = Factory::getUser();
- $frontediting = ($app->isClient('site') && $app->get('frontediting', 1) && !$user->guest);
+ $frontediting = ($app->isClient('site') && $app->get('frontediting', 1) && !$user->guest && !$app->input->get('pm'));
$menusEditing = ($app->get('frontediting', 1) == 2) && $user->authorise('core.edit', 'com_menus');
foreach (ModuleHelper::getModules($position) as $mod)
diff --git a/libraries/src/Extension/ExtensionHelper.php b/libraries/src/Extension/ExtensionHelper.php
index a13bcf45985ac..09a8d65b53651 100644
--- a/libraries/src/Extension/ExtensionHelper.php
+++ b/libraries/src/Extension/ExtensionHelper.php
@@ -270,6 +270,7 @@ class ExtensionHelper
// Core plugin extensions - system
array('plugin', 'accessibility', 'system', 0),
array('plugin', 'actionlogs', 'system', 0),
+ array('plugin', 'addmodulebutton', 'system', 0),
array('plugin', 'cache', 'system', 0),
array('plugin', 'debug', 'system', 0),
array('plugin', 'fields', 'system', 0),
diff --git a/libraries/src/Helper/ModuleHelper.php b/libraries/src/Helper/ModuleHelper.php
index b955e27646901..1efad8f7bae8c 100644
--- a/libraries/src/Helper/ModuleHelper.php
+++ b/libraries/src/Helper/ModuleHelper.php
@@ -15,6 +15,7 @@
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Filter\InputFilter;
+use Joomla\CMS\Helper\ContentHelper;
use Joomla\CMS\Language\LanguageHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Layout\LayoutHelper;
@@ -100,7 +101,7 @@ public static function &getModules($position)
if (\count($result) === 0)
{
- if ($input->getBool('tp') && ComponentHelper::getParams('com_templates')->get('template_positions_display'))
+ if ($input->getBool('pm') || ($input->getBool('tp') && ComponentHelper::getParams('com_templates')->get('template_positions_display')))
{
$result[0] = static::createDummyModule();
$result[0]->title = $position;
@@ -208,7 +209,7 @@ public static function renderModule($module, $attribs = array())
}
// Dynamically add outline style
- if ($app->input->getBool('tp') && ComponentHelper::getParams('com_templates')->get('template_positions_display'))
+ if (($app->input->getBool('tp') && ComponentHelper::getParams('com_templates')->get('template_positions_display')) || ($app->input->getBool('pm') && ContentHelper::getActions('com_modules')->get('core.create')))
{
$attribs['style'] .= ' outline';
}
diff --git a/plugins/system/addmodulebutton/addmodulebutton.php b/plugins/system/addmodulebutton/addmodulebutton.php
new file mode 100644
index 0000000000000..4f6455e8d6cd8
--- /dev/null
+++ b/plugins/system/addmodulebutton/addmodulebutton.php
@@ -0,0 +1,94 @@
+
+ * @license GNU General Public License version 2 or later; see LICENSE.txt
+ *
+ * @since __DEPLOY_VERSION__
+ */
+
+defined('_JEXEC') or die;
+use Joomla\CMS\Helper\ContentHelper;
+use Joomla\CMS\Language\Text;
+use Joomla\CMS\Plugin\CMSPlugin;
+use Joomla\CMS\WebAsset\WebAssetManager;
+
+/**
+ * Displays the Add Module button for Frontend Placement.
+ *
+ * @since __DEPLOY_VERSION__
+ */
+class PlgSystemAddModuleButton extends CMSPlugin
+{
+ /**
+ * Load plugin language files automatically
+ *
+ * @var boolean
+ * @since __DEPLOY_VERSION__
+ */
+ protected $autoloadLanguage = true;
+
+ /**
+ * Application object
+ *
+ * @var \Joomla\CMS\Application\CMSApplication
+ * @since __DEPLOY_VERSION__
+ */
+ protected $app;
+
+ /**
+ * Listener for the `onBeforeRender` event
+ *
+ * @return void
+ *
+ * @since __DEPLOY_VERSION__
+ */
+ public function onBeforeRender()
+ {
+
+ if ($this->app->isClient('administrator'))
+ {
+ return;
+ }
+
+ // Frontend Module Placement Variables
+ $canCreateModules = ContentHelper::getActions('com_modules')->get('core.create');
+ $canEditModules = ContentHelper::getActions('com_modules')->get('core.edit');
+ $placeModules = $this->app->input->getBool('pm');
+ $editPosition = $this->app->input->getBool('edit');
+ $showAddModuleBtn = $canCreateModules && !$this->app->input->getBool('tp') && !$placeModules;
+
+ // Display Warning message when user is not logged in or does not have permissions
+ if ($placeModules)
+ {
+ if ($editPosition && !$canEditModules)
+ {
+ $this->app->enqueueMessage(Text::sprintf('PLG_SYSTEM_ADD_MODULE_BUTTON_EDIT_MODULE_PERMISSIONS_WARNING'), 'warning');
+
+ return;
+ }
+ elseif (!$canCreateModules)
+ {
+ $this->app->enqueueMessage(Text::sprintf('PLG_SYSTEM_ADD_MODULE_BUTTON_CREATE_MODULE_PERMISSIONS_WARNING'), 'warning');
+
+ return;
+ }
+ }
+
+ // Display the Add Module Button
+ if ($showAddModuleBtn)
+ {
+ // Add Script Options to pass the Button label Language Constant
+ $config = array(
+ 'btnLabel' => Text::_('PLG_SYSTEM_ADD_MODULE_BUTTON_LABEL'),
+ 'btnDescription' => Text::_('PLG_SYSTEM_ADD_MODULE_BUTTON_DESCRIPTION')
+ );
+ $this->app->getDocument()->addScriptOptions('js-addModuleBtn', $config);
+
+ // Script for appending the Add Module Button
+ $this->app->getDocument()->getWebAssetManager()
+ ->registerAndUseScript('plg_system_addmodulebutton_js', 'media/plg_system_addmodulebutton/js/addmodulebutton.js', [], ['defer' => true]);
+ }
+ }
+}
diff --git a/plugins/system/addmodulebutton/addmodulebutton.xml b/plugins/system/addmodulebutton/addmodulebutton.xml
new file mode 100644
index 0000000000000..e0a44a2c51f17
--- /dev/null
+++ b/plugins/system/addmodulebutton/addmodulebutton.xml
@@ -0,0 +1,22 @@
+
+
+ plg_system_addmodulebutton
+ Joomla! Project
+ June 2021
+ (C) 2021 Open Source Matters, Inc.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ __DEPLOY_VERSION__
+ PLG_ADD_MODULE_BUTTON_XML_DESCRIPTION
+
+ addmodulebutton.php
+
+
+ language/en-GB/en-GB.plg_system_addmodulebutton.ini
+ language/en-GB/en-GB.plg_system_addmodulebutton.sys.ini
+
+
+ js
+
+
diff --git a/templates/cassiopeia/index.php b/templates/cassiopeia/index.php
index 6df33d64d46bd..acc624cec1e02 100644
--- a/templates/cassiopeia/index.php
+++ b/templates/cassiopeia/index.php
@@ -10,6 +10,7 @@
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
+use Joomla\CMS\Helper\ContentHelper;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
@@ -34,6 +35,10 @@
$menu = $app->getMenu()->getActive();
$pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : '';
+// Display inactive positions for Place Module View
+$modulesPermissions = ContentHelper::getActions('com_modules');
+$showAllPositions = $app->input->getBool('pm') && ($modulesPermissions->get('core.edit') || $modulesPermissions->get('core.create'));
+
// Template path
$templatePath = 'templates/' . $this->template;
@@ -87,12 +92,12 @@
$hasClass = '';
-if ($this->countModules('sidebar-left', true))
+if ($this->countModules('sidebar-left', true) || $showAllPositions)
{
$hasClass .= ' has-sidebar-left';
}
-if ($this->countModules('sidebar-right', true))
+if ($this->countModules('sidebar-right', true) || $showAllPositions)
{
$hasClass .= ' has-sidebar-right';
}
@@ -127,19 +132,19 @@
?>">