Skip to content

Commit 38c7689

Browse files
committed
Merge branch '5.2-dev' into 5.3-dev-upmerge-2024-10-03
2 parents 744a665 + b067fe7 commit 38c7689

File tree

43 files changed

+1437
-897
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1437
-897
lines changed

administrator/components/com_actionlogs/src/Helper/ActionlogsHelper.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,12 @@ public static function getContentTypeLink($component, $contentType, $id, $urlVar
274274
*/
275275
public static function loadActionLogPluginsLanguage()
276276
{
277+
static $loaded;
278+
if ($loaded) {
279+
return;
280+
}
281+
$loaded = true;
282+
277283
$lang = Factory::getLanguage();
278284
$db = Factory::getDbo();
279285

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
UPDATE `#__guidedtour_steps`
2+
SET `ordering` = `ordering` + 1
3+
WHERE `title` IN ('COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_SAVECLOSE_TITLE', 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_CONGRATULATIONS_TITLE');
4+
5+
INSERT INTO `#__guidedtour_steps` (`title`, `description`, `position`, `target`, `type`, `interactive_type`, `url`, `published`, `language`, `note`, `tour_id`, `created`, `created_by`, `modified`, `modified_by`, `ordering`)
6+
SELECT 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_AUTOSTART_TITLE', 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_AUTOSTART_DESCRIPTION', 'bottom', '#jform_autostart0', 2, 3, '', 1, '*', '', `tour_id`, CURRENT_TIMESTAMP(), 0, CURRENT_TIMESTAMP(), 0, `ordering` + 1
7+
FROM `#__guidedtour_steps`
8+
WHERE `title` = 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_COMPONENT_TITLE';
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
--
22
-- Add the Guided Tours selectable option to the User Action Logs
33
--
4-
INSERT INTO "#__action_logs_extensions" ("extension") VALUES ("com_guidedtours");
4+
INSERT INTO "#__action_logs_extensions" ("extension") VALUES ('com_guidedtours');
55

66
INSERT INTO "#__action_log_config" ("type_title", "type_alias", "id_holder", "title_holder", "table_name", "text_prefix") VALUES
77
('guidedtour', 'com_guidedtours.state', 'id', 'title', '#__guidedtours', 'PLG_ACTIONLOG_JOOMLA');
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
UPDATE "#__guidedtour_steps"
2+
SET "ordering" = "ordering" + 1
3+
WHERE "title" IN ('COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_SAVECLOSE_TITLE', 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_CONGRATULATIONS_TITLE');
4+
5+
INSERT INTO "#__guidedtour_steps" ("title", "description", "position", "target", "type", "interactive_type", "url", "published", "language", "note", "tour_id", "created", "created_by", "modified", "modified_by", "ordering")
6+
SELECT 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_AUTOSTART_TITLE', 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_AUTOSTART_DESCRIPTION', 'bottom', '#jform_autostart0', 2, 3, '', 1, '*', '', "tour_id", CURRENT_TIMESTAMP, 0, CURRENT_TIMESTAMP, 0, "ordering" + 1
7+
FROM "#__guidedtour_steps"
8+
WHERE "title" = 'COM_GUIDEDTOURS_TOUR_GUIDEDTOURS_STEP_COMPONENT_TITLE';

administrator/components/com_guidedtours/config.xml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@
1717

1818
<field
1919
name="delayed_time"
20-
type="text"
20+
type="number"
2121
label="COM_GUIDEDTOURS_CONFIG_DELAYED_TIME_LABEL"
2222
description="COM_GUIDEDTOURS_CONFIG_DELAYED_TIME_DESCRIPTION"
2323
default="60"
24-
size="small"
24+
min="1"
25+
filter="integer"
26+
validate="number"
2527
showon="allowTourAutoStart:1"
2628
/>
2729
</fieldset>

administrator/components/com_guidedtours/src/Controller/AjaxController.php

Lines changed: 77 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -38,87 +38,90 @@ public function fetchUserState()
3838
$user = $this->app->getIdentity();
3939

4040
$tourId = $this->app->input->getInt('tid', 0);
41-
$stepNumber = $this->app->input->getString('sid', '');
41+
$stepNumber = $this->app->input->getInt('sid', 0);
4242
$context = $this->app->input->getString('context', '');
4343

44-
if ($user != null && $user->id > 0) {
45-
$actionState = '';
46-
47-
switch ($context) {
48-
case 'tour.complete':
49-
$actionState = 'completed';
50-
break;
51-
case 'tour.cancel':
52-
$actionState = 'delayed';
53-
break;
54-
case 'tour.skip':
55-
$actionState = 'skipped';
56-
break;
57-
}
44+
if ($user == null || $user->id <= 0) {
45+
echo new JsonResponse(['success' => false, 'tourId' => $tourId], Text::_('COM_GUIDEDTOURS_USERSTATE_CONNECTEDONLY'), true);
46+
$this->app->close();
47+
}
48+
49+
if (!\in_array($context, ['tour.complete', 'tour.cancel', 'tour.skip'])) {
50+
echo new JsonResponse(['success' => false, 'tourId' => $tourId], Text::_('COM_GUIDEDTOURS_USERSTATE_WRONGCONTEXT'), true);
51+
$this->app->close();
52+
}
5853

59-
PluginHelper::importPlugin('guidedtours');
60-
61-
// event onBeforeTourSaveUserState before save user tour state
62-
$beforeEvent = AbstractEvent::create(
63-
'onBeforeTourSaveUserState',
64-
[
65-
'subject' => new \stdClass(),
66-
'tourId' => $tourId,
67-
'actionState' => $actionState,
68-
'stepNumber' => $stepNumber,
69-
]
70-
);
71-
72-
$this->app->getDispatcher()->dispatch('onBeforeTourSaveUserState', $beforeEvent);
73-
74-
// Save the tour state only when the tour auto-starts.
75-
$tourModel = $this->getModel('Tour', 'Administrator');
76-
if ($tourModel->isAutostart($tourId)) {
77-
$result = $tourModel->saveTourUserState($tourId, $actionState);
78-
if ($result) {
79-
$message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATESAVED', $user->id, $tourId);
80-
} else {
81-
$message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATENOTSAVED', $user->id, $tourId);
82-
}
54+
if ($tourId <= 0) {
55+
echo new JsonResponse(['success' => false, 'tourId' => $tourId], Text::_('COM_GUIDEDTOURS_USERSTATE_BADTOURID'), true);
56+
$this->app->close();
57+
}
58+
59+
$actionState = '';
60+
61+
switch ($context) {
62+
case 'tour.complete':
63+
$actionState = 'completed';
64+
break;
65+
case 'tour.cancel':
66+
$actionState = 'delayed';
67+
break;
68+
case 'tour.skip':
69+
$actionState = 'skipped';
70+
break;
71+
}
72+
73+
PluginHelper::importPlugin('guidedtours');
74+
75+
// event onBeforeTourSaveUserState before save user tour state
76+
$beforeEvent = AbstractEvent::create(
77+
'onBeforeTourSaveUserState',
78+
[
79+
'subject' => new \stdClass(),
80+
'tourId' => $tourId,
81+
'actionState' => $actionState,
82+
'stepNumber' => $stepNumber,
83+
]
84+
);
85+
86+
$this->app->getDispatcher()->dispatch('onBeforeTourSaveUserState', $beforeEvent);
87+
88+
// Save the tour state only when the tour auto-starts.
89+
$tourModel = $this->getModel('Tour', 'Administrator');
90+
if ($tourModel->isAutostart($tourId)) {
91+
$result = $tourModel->saveTourUserState($tourId, $actionState);
92+
if ($result) {
93+
$message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATESAVED', $user->id, $tourId);
8394
} else {
84-
$result = false;
8595
$message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATENOTSAVED', $user->id, $tourId);
8696
}
87-
88-
// event onAfterTourSaveUserState after save user tour state (may override message)
89-
$afterEvent = AbstractEvent::create(
90-
'onAfterTourSaveUserState',
91-
[
92-
'subject' => new \stdClass(),
93-
'tourId' => $tourId,
94-
'actionState' => $actionState,
95-
'stepNumber' => $stepNumber,
96-
'result' => $result,
97-
'message' => &$message,
98-
]
99-
);
100-
101-
$this->app->getDispatcher()->dispatch('onAfterTourSaveUserState', $afterEvent);
102-
103-
// Construct the response data
104-
$data = [
105-
'tourId' => $tourId,
106-
'stepId' => $stepNumber,
107-
'context' => $context,
108-
'state' => $actionState,
109-
];
110-
echo new JsonResponse($data, $message);
111-
$this->app->close();
11297
} else {
113-
// Construct the response data
114-
$data = [
115-
'success' => false,
116-
'tourId' => $tourId,
117-
];
118-
119-
$message = Text::_('COM_GUIDEDTOURS_USERSTATE_CONNECTEDONLY');
120-
echo new JsonResponse($data, $message, true);
121-
$this->app->close();
98+
$result = false;
99+
$message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATENOTSAVED', $user->id, $tourId);
122100
}
101+
102+
// event onAfterTourSaveUserState after save user tour state (may override message)
103+
$afterEvent = AbstractEvent::create(
104+
'onAfterTourSaveUserState',
105+
[
106+
'subject' => new \stdClass(),
107+
'tourId' => $tourId,
108+
'actionState' => $actionState,
109+
'stepNumber' => $stepNumber,
110+
'result' => $result,
111+
'message' => &$message,
112+
]
113+
);
114+
115+
$this->app->getDispatcher()->dispatch('onAfterTourSaveUserState', $afterEvent);
116+
117+
// Construct the response data
118+
$data = [
119+
'tourId' => $tourId,
120+
'stepId' => $stepNumber,
121+
'context' => $context,
122+
'state' => $actionState,
123+
];
124+
echo new JsonResponse($data, $message);
125+
$this->app->close();
123126
}
124127
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
/**
4+
* @package Joomla.Administrator
5+
* @subpackage com_guidedtours
6+
*
7+
* @copyright (C) 2024 Open Source Matters, Inc. <https://www.joomla.org>
8+
* @license GNU General Public License version 2 or later; see LICENSE.txt
9+
*/
10+
11+
namespace Joomla\Component\Guidedtours\Administrator\Dispatcher;
12+
13+
use Joomla\CMS\Access\Exception\NotAllowed;
14+
use Joomla\CMS\Dispatcher\ComponentDispatcher;
15+
16+
// phpcs:disable PSR1.Files.SideEffects
17+
\defined('_JEXEC') or die;
18+
// phpcs:enable PSR1.Files.SideEffects
19+
20+
/**
21+
* ComponentDispatcher class for com_guidedtours
22+
*
23+
* @since 5.2.0
24+
*/
25+
class Dispatcher extends ComponentDispatcher
26+
{
27+
/**
28+
* Method to check component access permission
29+
*
30+
* @return void
31+
*
32+
* @throws \Exception|NotAllowed
33+
*/
34+
protected function checkAccess()
35+
{
36+
$command = $this->input->getCmd('task', 'display');
37+
if ($this->app->isClient('administrator') && $command == 'ajax.fetchUserState') {
38+
return;
39+
}
40+
41+
parent::checkAccess();
42+
}
43+
}

administrator/components/com_media/src/Controller/ApiController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ public function putFiles()
270270
$move = $content->get('move', true);
271271

272272
if ($mediaContent != null) {
273-
$this->checkContent();
273+
$this->checkFileSize(\strlen($mediaContent));
274274

275275
$this->getModel()->updateFile($adapter, $name, str_replace($name, '', $path), $mediaContent);
276276
}

administrator/components/com_menus/src/Model/ItemModel.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,7 @@ protected function populateState()
998998

999999
$this->setState('item.type', $type);
10001000

1001-
$link = $app->isClient('api') ? $app->getInput()->get('link') :
1001+
$link = $app->isClient('api') ? $app->getInput()->get('link', null, 'string') :
10021002
$app->getUserState('com_menus.edit.item.link');
10031003

10041004
if ($link) {

administrator/components/com_scheduler/src/Helper/ExecRuleHelper.php

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,12 +93,46 @@ private function getFromTask(string $property, $default = null)
9393
*/
9494
public function nextExec(bool $string = true, bool $basisNow = false)
9595
{
96-
// Exception handling here
97-
switch ($this->type) {
98-
case 'interval':
99-
$lastExec = Factory::getDate($basisNow ? 'now' : $this->getFromTask('last_execution'), 'UTC');
100-
$interval = new \DateInterval($this->rule->exp);
101-
$nextExec = $lastExec->add($interval);
96+
$executionRules = $this->getFromTask('execution_rules');
97+
$type = $executionRules['rule-type'];
98+
switch ($type) {
99+
case 'interval-minutes':
100+
$now = Factory::getDate('now', 'UTC');
101+
$intervalMinutes = (int) $executionRules['interval-minutes'];
102+
$interval = new \DateInterval('PT' . $intervalMinutes . 'M');
103+
$nextExec = $now->add($interval);
104+
$nextExec = $string ? $nextExec->toSql() : $nextExec;
105+
break;
106+
case 'interval-hours':
107+
$now = Factory::getDate('now', 'UTC');
108+
$intervalHours = $executionRules['interval-hours'];
109+
$interval = new \DateInterval('PT' . $intervalHours . 'H');
110+
$nextExec = $now->add($interval);
111+
$nextExec = $string ? $nextExec->toSql() : $nextExec;
112+
break;
113+
case 'interval-days':
114+
$now = Factory::getDate('now', 'UTC');
115+
$intervalDays = $executionRules['interval-days'];
116+
$interval = new \DateInterval('P' . $intervalDays . 'D');
117+
$nextExec = $now->add($interval);
118+
$execTime = $executionRules['exec-time'];
119+
list($hour, $minute) = explode(':', $execTime);
120+
$nextExec->setTime($hour, $minute);
121+
$nextExec = $string ? $nextExec->toSql() : $nextExec;
122+
break;
123+
case 'interval-months':
124+
$now = Factory::getDate('now', 'UTC');
125+
$intervalMonths = $executionRules['interval-months'];
126+
$interval = new \DateInterval('P' . $intervalMonths . 'M');
127+
$nextExec = $now->add($interval);
128+
$execDay = $executionRules['exec-day'];
129+
$nextExecYear = $nextExec->format('Y');
130+
$nextExecMonth = $nextExec->format('n');
131+
$nextExec->setDate($nextExecYear, $nextExecMonth, $execDay);
132+
133+
$execTime = $executionRules['exec-time'];
134+
list($hour, $minute) = explode(':', $execTime);
135+
$nextExec->setTime($hour, $minute);
102136
$nextExec = $string ? $nextExec->toSql() : $nextExec;
103137
break;
104138
case 'cron-expression':

0 commit comments

Comments
 (0)