diff --git a/.drone.yml b/.drone.yml index 43154ab4e623b..c3de5d6d246db 100644 --- a/.drone.yml +++ b/.drone.yml @@ -416,7 +416,7 @@ steps: MATTERMOST_NIGHTLY_HOOK: from_secret: mattermost_nightly_hook commands: - - curl -i -X POST -H 'Content-Type:application/json' -d '{"text":"Nightly Build for [Joomla 5.2](https://developer.joomla.org/nightly-builds.html) FAILED to built."}' $MATTERMOST_NIGHTLY_HOOK + - curl -i -X POST -H 'Content-Type:application/json' -d '{"text":"Nightly Build for [Joomla 5.2](https://developer.joomla.org/nightly-builds.html) FAILED to build."}' $MATTERMOST_NIGHTLY_HOOK when: status: - failure @@ -430,6 +430,6 @@ trigger: --- kind: signature -hmac: 903759c59028cc757ba3faef044e3b9122d00f99ea0367caadceb710cb88030f +hmac: 92bc9a500addecbc0d8ea987a668bee4abeae8bbab444e7105ce134ba3ffe96b ... diff --git a/administrator/components/com_scheduler/src/Helper/ExecRuleHelper.php b/administrator/components/com_scheduler/src/Helper/ExecRuleHelper.php index 8e67ed3804a75..e8331afa97eb7 100644 --- a/administrator/components/com_scheduler/src/Helper/ExecRuleHelper.php +++ b/administrator/components/com_scheduler/src/Helper/ExecRuleHelper.php @@ -93,12 +93,46 @@ private function getFromTask(string $property, $default = null) */ public function nextExec(bool $string = true, bool $basisNow = false) { - // Exception handling here - switch ($this->type) { - case 'interval': - $lastExec = Factory::getDate($basisNow ? 'now' : $this->getFromTask('last_execution'), 'UTC'); - $interval = new \DateInterval($this->rule->exp); - $nextExec = $lastExec->add($interval); + $executionRules = $this->getFromTask('execution_rules'); + $type = $executionRules['rule-type']; + switch ($type) { + case 'interval-minutes': + $now = Factory::getDate('now', 'UTC'); + $intervalMinutes = (int) $executionRules['interval-minutes']; + $interval = new \DateInterval('PT' . $intervalMinutes . 'M'); + $nextExec = $now->add($interval); + $nextExec = $string ? $nextExec->toSql() : $nextExec; + break; + case 'interval-hours': + $now = Factory::getDate('now', 'UTC'); + $intervalHours = $executionRules['interval-hours']; + $interval = new \DateInterval('PT' . $intervalHours . 'H'); + $nextExec = $now->add($interval); + $nextExec = $string ? $nextExec->toSql() : $nextExec; + break; + case 'interval-days': + $now = Factory::getDate('now', 'UTC'); + $intervalDays = $executionRules['interval-days']; + $interval = new \DateInterval('P' . $intervalDays . 'D'); + $nextExec = $now->add($interval); + $execTime = $executionRules['exec-time']; + list($hour, $minute) = explode(':', $execTime); + $nextExec->setTime($hour, $minute); + $nextExec = $string ? $nextExec->toSql() : $nextExec; + break; + case 'interval-months': + $now = Factory::getDate('now', 'UTC'); + $intervalMonths = $executionRules['interval-months']; + $interval = new \DateInterval('P' . $intervalMonths . 'M'); + $nextExec = $now->add($interval); + $execDay = $executionRules['exec-day']; + $nextExecYear = $nextExec->format('Y'); + $nextExecMonth = $nextExec->format('n'); + $nextExec->setDate($nextExecYear, $nextExecMonth, $execDay); + + $execTime = $executionRules['exec-time']; + list($hour, $minute) = explode(':', $execTime); + $nextExec->setTime($hour, $minute); $nextExec = $string ? $nextExec->toSql() : $nextExec; break; case 'cron-expression': diff --git a/administrator/modules/mod_guidedtours/src/Helper/GuidedToursHelper.php b/administrator/modules/mod_guidedtours/src/Helper/GuidedToursHelper.php index bdc899a3a7290..e0ed9d33af7f8 100644 --- a/administrator/modules/mod_guidedtours/src/Helper/GuidedToursHelper.php +++ b/administrator/modules/mod_guidedtours/src/Helper/GuidedToursHelper.php @@ -59,6 +59,9 @@ public function getTours(Registry $params, AdministratorApplication $app) $uri = new Uri($item->url); if ($extension = $uri->getVar('option')) { + if ($extension === 'com_categories') { + $extension = $uri->getVar('extension'); + } if (!$user->authorise('core.manage', $extension)) { unset($items[$key]); } diff --git a/administrator/modules/mod_quickicon/src/Helper/QuickIconHelper.php b/administrator/modules/mod_quickicon/src/Helper/QuickIconHelper.php index ad63848b5c6bd..caad7839758ea 100644 --- a/administrator/modules/mod_quickicon/src/Helper/QuickIconHelper.php +++ b/administrator/modules/mod_quickicon/src/Helper/QuickIconHelper.php @@ -137,7 +137,7 @@ public function getButtons(Registry $params, ?CMSApplication $application = null $tmp = [ 'image' => 'icon-folder-open', 'link' => Route::_('index.php?option=com_categories&view=categories&extension=com_content'), - 'linkadd' => Route::_('index.php?option=com_categories&task=category.add'), + 'linkadd' => Route::_('index.php?option=com_categories&task=category.add&extension=com_content'), 'name' => 'MOD_QUICKICON_CATEGORY_MANAGER', 'access' => ['core.manage', 'com_content', 'core.create', 'com_content'], 'group' => 'MOD_QUICKICON_SITE', diff --git a/build/media_source/mod_menu/js/menu.es6.js b/build/media_source/mod_menu/js/menu.es6.js index ce72537f1317c..eca867aed5711 100644 --- a/build/media_source/mod_menu/js/menu.es6.js +++ b/build/media_source/mod_menu/js/menu.es6.js @@ -45,32 +45,32 @@ spanEl.addEventListener('mouseout', topLevelMouseOut(topLevelEl, settings)); } - topLevelEl.addEventListener('mouseover', ({ target }) => { - const ulChild = target.querySelector('ul'); + topLevelEl.addEventListener('mouseover', ({ currentTarget }) => { + const ulChild = currentTarget.querySelector('ul'); if (ulChild) { ulChild.setAttribute('aria-hidden', 'false'); ulChild.classList.add(settings.menuHoverClass); } }); - topLevelEl.addEventListener('mouseout', ({ target }) => { - const ulChild = target.querySelector('ul'); + topLevelEl.addEventListener('mouseout', ({ currentTarget }) => { + const ulChild = currentTarget.querySelector('ul'); if (ulChild) { ulChild.setAttribute('aria-hidden', 'true'); ulChild.classList.remove(settings.menuHoverClass); } }); - topLevelEl.addEventListener('focus', ({ target }) => { - const ulChild = target.querySelector('ul'); + topLevelEl.addEventListener('focus', ({ currentTarget }) => { + const ulChild = currentTarget.querySelector('ul'); if (ulChild) { ulChild.setAttribute('aria-hidden', 'true'); ulChild.classList.add(settings.menuHoverClass); } }); - topLevelEl.addEventListener('blur', ({ target }) => { - const ulChild = target.querySelector('ul'); + topLevelEl.addEventListener('blur', ({ currentTarget }) => { + const ulChild = currentTarget.querySelector('ul'); if (ulChild) { ulChild.setAttribute('aria-hidden', 'false'); ulChild.classList.remove(settings.menuHoverClass); diff --git a/libraries/src/Pagination/Pagination.php b/libraries/src/Pagination/Pagination.php index 3882d7c703146..c2b7656bcdb30 100644 --- a/libraries/src/Pagination/Pagination.php +++ b/libraries/src/Pagination/Pagination.php @@ -15,6 +15,7 @@ use Joomla\CMS\Language\Text; use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Router\Route; +use Joomla\Filter\InputFilter; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -96,6 +97,31 @@ class Pagination */ protected $additionalUrlParams = []; + /** + * List of parameters that will be added from request automatically. + * When exists they will be added to the $additionalUrlParams list, while pagination initialisation. + * + * In format key => filter + * + * @var string[] + * + * @since __DEPLOY_VERSION__ + */ + protected $paramsFromRequest = [ + 'format' => 'CMD', + 'option' => 'CMD', + 'controller' => 'CMD', + 'view' => 'CMD', + 'layout' => 'STRING', + 'task' => 'CMD', + 'template' => 'CMD', + 'templateStyle' => 'INT', + 'tmpl' => 'CMD', + 'tpl' => 'CMD', + 'id' => 'STRING', + 'Itemid' => 'INT', + ]; + /** * @var CMSApplication The application object * @since 3.4 @@ -177,6 +203,40 @@ public function __construct($total, $limitstart, $limit, $prefix = '', ?CMSAppli if ($limit === 0) { $this->viewall = true; } + + $this->setUrlParamsFromRequest(); + } + + /** + * Set URL parameters from request. + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + protected function setUrlParamsFromRequest() + { + // Get the requested parameters from the router + $client = $this->app->getName(); + $router = Factory::getContainer()->get(ucfirst($client) . 'Router'); + $filter = new InputFilter(); + + // It is applicable only for CMS router. API router works differently. + if (!$router instanceof \Joomla\CMS\Router\Router) { + return; + } + + // Filter them and add to the params list + foreach ($router->getVars() as $key => $value) { + // Check if the parameter is allowed + if (empty($this->paramsFromRequest[$key])) { + continue; + } + + $filterMethod = $this->paramsFromRequest[$key]; + + $this->setAdditionalUrlParam($key, $filter->clean($value, $filterMethod)); + } } /** @@ -663,36 +723,8 @@ protected function _buildDataObject() { $data = new \stdClass(); - // Platform defaults - $defaultUrlParams = [ - 'format' => 'CMD', - 'option' => 'CMD', - 'controller' => 'CMD', - 'view' => 'CMD', - 'layout' => 'STRING', - 'task' => 'CMD', - 'template' => 'CMD', - 'templateStyle' => 'INT', - 'tmpl' => 'CMD', - 'tpl' => 'CMD', - 'id' => 'STRING', - 'Itemid' => 'INT', - ]; - // Prepare the routes $params = []; - $input = $this->app->getInput(); - - // Use platform defaults if parameter doesn't already exist. - foreach ($defaultUrlParams as $param => $filter) { - $value = $input->get($param, null, $filter); - - if ($value === null) { - continue; - } - - $params[$param] = $value; - } if (!empty($this->additionalUrlParams)) { foreach ($this->additionalUrlParams as $key => $value) { diff --git a/libraries/src/Router/SiteRouter.php b/libraries/src/Router/SiteRouter.php index 6e92faf9641be..c94eb40d6a6d7 100644 --- a/libraries/src/Router/SiteRouter.php +++ b/libraries/src/Router/SiteRouter.php @@ -487,10 +487,11 @@ public function buildPaginationData(&$router, &$uri) { $limitstart = $uri->getVar('limitstart'); - if ($limitstart !== null) { - $uri->setVar('start', (int) $uri->getVar('limitstart')); - $uri->delVar('limitstart'); + if ($limitstart !== null && $limitstart !== '') { + $uri->setVar('start', (int) $limitstart); } + + $uri->delVar('limitstart'); } /**