Skip to content

Commit 98729a5

Browse files
committed
Merge remote-tracking branch 'upstream/5.4-dev' into upmerges/2025-07-02
2 parents 8d3c59c + 89502fd commit 98729a5

File tree

35 files changed

+820
-279
lines changed

35 files changed

+820
-279
lines changed

.github/workflows/ci.yml

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
name: CI Joomla
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
9+
cancel-in-progress: true
10+
11+
jobs:
12+
composer:
13+
name: Install PHP dependencies
14+
runs-on: ubuntu-latest
15+
container: joomlaprojects/docker-images:php8.4
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: actions/cache@v4
19+
id: cache-php
20+
with:
21+
path: libraries/vendor
22+
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
23+
- name: Install PHP dependencies
24+
if: steps.cache-php.outputs.cache-hit != 'true'
25+
run: |
26+
git config --global --add safe.directory $GITHUB_WORKSPACE
27+
composer config --global home
28+
composer validate --no-check-all --strict
29+
composer install --no-progress --ignore-platform-reqs
30+
31+
npm:
32+
name: Install JS/CSS dependencies and build assets
33+
runs-on: ubuntu-latest
34+
container: joomlaprojects/docker-images:php8.4
35+
needs: [composer]
36+
steps:
37+
- uses: actions/setup-node@v4
38+
with:
39+
node-version: latest
40+
- uses: actions/checkout@v4
41+
- uses: actions/cache@v4
42+
id: cache-assets
43+
with:
44+
path: |
45+
node_modules
46+
media
47+
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/media_source/**', 'administrator/components/com_media/resources/**') }}
48+
- uses: actions/cache/restore@v4
49+
with:
50+
path: libraries/vendor
51+
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
52+
- name: Build assets
53+
if: steps.cache-assets.outputs.cache-hit != 'true'
54+
run: npm ci --unsafe-perm
55+
56+
code-style-php:
57+
name: Check PHP code style
58+
runs-on: ubuntu-latest
59+
container: joomlaprojects/docker-images:php8.4
60+
needs: [composer]
61+
strategy:
62+
matrix:
63+
command: ['php-cs-fixer fix -vvv --dry-run --diff', 'phpcs --extensions=php -p --standard=ruleset.xml .']
64+
steps:
65+
- uses: actions/checkout@v4
66+
- uses: actions/cache/restore@v4
67+
with:
68+
path: libraries/vendor
69+
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
70+
- name: Check PHP code style
71+
env:
72+
PHP_CS_FIXER_IGNORE_ENV: true
73+
run: ./libraries/vendor/bin/${{ matrix.command }}
74+
75+
code-style-js-css:
76+
name: Check Javascript & CSS code style
77+
runs-on: ubuntu-latest
78+
container: joomlaprojects/docker-images:php8.4
79+
needs: [composer, npm]
80+
strategy:
81+
matrix:
82+
check: ['lint:js', 'lint:testjs', 'lint:css']
83+
steps:
84+
- uses: actions/setup-node@v4
85+
with:
86+
node-version: latest
87+
- uses: actions/checkout@v4
88+
- uses: actions/cache/restore@v4
89+
with:
90+
path: |
91+
node_modules
92+
media
93+
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/media_source/**', 'administrator/components/com_media/resources/**') }}
94+
- name: Check code style
95+
run: npm run ${{ matrix.check }}
96+
97+
phpstan:
98+
name: Run PHPstan
99+
runs-on: ubuntu-latest
100+
container: joomlaprojects/docker-images:php8.4
101+
needs: [code-style-php]
102+
steps:
103+
- uses: actions/checkout@v4
104+
- uses: actions/cache/restore@v4
105+
with:
106+
path: libraries/vendor
107+
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
108+
- name: Run PHPstan
109+
run: |
110+
./libraries/vendor/bin/phpstan --error-format=github || :
111+
112+
tests-unit:
113+
name: Run Unit tests
114+
runs-on: ubuntu-latest
115+
container: joomlaprojects/docker-images:php${{ matrix.php_version }}
116+
needs: [code-style-php]
117+
strategy:
118+
matrix:
119+
php_version: ['8.1', '8.2', '8.3', '8.4']
120+
steps:
121+
- uses: actions/checkout@v4
122+
- uses: actions/cache/restore@v4
123+
with:
124+
path: libraries/vendor
125+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
126+
- name: Run Unit tests
127+
run: ./libraries/vendor/bin/phpunit --testsuite Unit
128+
129+
tests-integration:
130+
name: Run integration tests
131+
runs-on: ubuntu-latest
132+
container: joomlaprojects/docker-images:php${{ matrix.php_version }}
133+
needs: [code-style-php]
134+
strategy:
135+
matrix:
136+
php_version: ['8.1', '8.2', '8.3', '8.4']
137+
config: ['phpunit.xml.dist', 'phpunit-pgsql.xml.dist']
138+
steps:
139+
- uses: actions/checkout@v4
140+
- name: Start LDAP container
141+
uses: docker://docker
142+
with:
143+
args: docker run -d --name openldap --network ${{ job.container.network }} --network-alias openldap -e "LDAP_ADMIN_USERNAME=admin" -e "LDAP_ADMIN_PASSWORD=adminpassword" -e "LDAP_USERS=customuser" -e "LDAP_PASSWORDS=custompassword" -e "LDAP_ENABLE_TLS=yes" -e "LDAP_TLS_CERT_FILE=/certs/openldap.crt" -e "LDAP_TLS_KEY_FILE=/certs/openldap.key" -e "LDAP_TLS_CA_FILE=/certs/CA.crt" -e "BITNAMI_DEBUG=true" -e "LDAP_CONFIG_ADMIN_ENABLED=yes" -e "LDAP_CONFIG_ADMIN_USERNAME=admin" -e "LDAP_CONFIG_ADMIN_PASSWORD=configpassword" -v "${{ github.workspace }}/tests/certs/openldap.crt":"/certs/openldap.crt" -v "${{ github.workspace }}/tests/certs/openldap.key":"/certs/openldap.key" -v "${{ github.workspace }}/tests/certs/CA.crt":"/certs/CA.crt" bitnami/openldap:latest
144+
- uses: actions/cache/restore@v4
145+
with:
146+
path: libraries/vendor
147+
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
148+
- name: Run Integration tests
149+
run: |
150+
sleep 3
151+
./libraries/vendor/bin/phpunit --testsuite Integration --configuration ${{ matrix.config }}
152+
- name: Stop LDAP container
153+
uses: docker://docker
154+
with:
155+
args: docker kill openldap
156+
services:
157+
mysql:
158+
image: mariadb
159+
env:
160+
MARIADB_USER: joomla_ut
161+
MARIADB_PASSWORD: joomla_ut
162+
MARIADB_ROOT_PASSWORD: joomla_ut
163+
MARIADB_DATABASE: test_joomla
164+
postgres:
165+
image: postgres:12-alpine
166+
env:
167+
POSTGRES_USER: root
168+
POSTGRES_PASSWORD: joomla_ut
169+
POSTGRES_DB: test_joomla
170+
171+
tests-system-prepare:
172+
name: Prepare system tests
173+
runs-on: ubuntu-latest
174+
container: joomlaprojects/docker-images:cypress8.4
175+
needs: [composer, npm]
176+
env:
177+
CYPRESS_VERIFY_TIMEOUT: 100000
178+
steps:
179+
- uses: actions/checkout@v4
180+
- uses: actions/cache/restore@v4
181+
with:
182+
path: |
183+
node_modules
184+
media
185+
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/media_source/**', 'administrator/components/com_media/resources/**') }}
186+
- uses: actions/cache@v4
187+
id: cache-cypress
188+
with:
189+
path: |
190+
/root/.cache/Cypress
191+
/github/home/.cache/Cypress
192+
key: ${{ runner.os }}-cypress-${{ hashFiles('package-lock.json') }}
193+
- name: Install Cypress dependencies
194+
if: steps.cache-cypress.outputs.cache-hit != 'true'
195+
run: |
196+
npx cypress install
197+
npx cypress verify
198+
199+
tests-system:
200+
name: Run system tests
201+
runs-on: ubuntu-latest
202+
container: joomlaprojects/docker-images:cypress${{ matrix.config.php_version }}
203+
needs: [tests-system-prepare]
204+
strategy:
205+
matrix:
206+
browser: ['chrome', 'edge']
207+
config:
208+
- php_version: '8.4'
209+
test_group: cmysqlmax
210+
db_engine: mysqli
211+
db_host: mysql
212+
- php_version: '8.1'
213+
test_group: cmysql
214+
db_engine: mysqli
215+
db_host: mysql
216+
- php_version: '8.1'
217+
test_group: cpostgres
218+
db_engine: pgsql
219+
db_host: postgres
220+
- php_version: '8.4'
221+
test_group: cpostgresmax
222+
db_engine: pgsql
223+
db_host: postgres
224+
env:
225+
JOOMLA_INSTALLATION_DISABLE_LOCALHOST_CHECK: 1
226+
steps:
227+
- uses: actions/checkout@v4
228+
- uses: actions/cache/restore@v4
229+
with:
230+
path: libraries/vendor
231+
key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }}
232+
- uses: actions/cache/restore@v4
233+
with:
234+
path: |
235+
node_modules
236+
media
237+
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json', 'build/media_source/**', 'administrator/components/com_media/resources/**') }}
238+
- uses: actions/cache/restore@v4
239+
with:
240+
path: |
241+
/root/.cache/Cypress
242+
/github/home/.cache/Cypress
243+
key: ${{ runner.os }}-cypress-${{ hashFiles('package-lock.json') }}
244+
- name: Run System tests
245+
run: bash tests/System/entrypoint.sh "$(pwd)" ${{ matrix.config.test_group }} ${{ matrix.config.db_engine }} ${{ matrix.config.db_host }} ${{ matrix.browser }}
246+
- name: Archive test results results
247+
uses: actions/upload-artifact@v4
248+
if: always()
249+
with:
250+
name: system-test-output
251+
path: tests/System/output
252+
if-no-files-found: ignore
253+
services:
254+
mysql:
255+
image: mariadb
256+
env:
257+
MARIADB_USER: joomla_ut
258+
MARIADB_PASSWORD: joomla_ut
259+
MARIADB_ROOT_PASSWORD: joomla_ut
260+
MARIADB_DATABASE: test_joomla
261+
postgres:
262+
image: postgres:12-alpine
263+
env:
264+
POSTGRES_USER: root
265+
POSTGRES_PASSWORD: joomla_ut
266+
POSTGRES_DB: test_joomla

administrator/components/com_content/src/View/Articles/HtmlView.php

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -111,29 +111,28 @@ public function display($tpl = null)
111111
{
112112
/** @var ArticlesModel $model */
113113
$model = $this->getModel();
114+
$model->setUseExceptions(true);
115+
116+
try {
117+
$this->items = $model->getItems();
118+
$this->pagination = $model->getPagination();
119+
$this->state = $model->getState();
120+
$this->filterForm = $model->getFilterForm();
121+
$this->activeFilters = $model->getActiveFilters();
122+
$this->vote = PluginHelper::isEnabled('content', 'vote');
123+
$this->hits = ComponentHelper::getParams('com_content')->get('record_hits', 1) == 1;
124+
125+
if (!\count($this->items) && $this->isEmptyState = $model->getIsEmptyState()) {
126+
$this->setLayout('emptystate');
127+
}
114128

115-
$this->items = $model->getItems();
116-
$this->pagination = $model->getPagination();
117-
$this->state = $model->getState();
118-
$this->filterForm = $model->getFilterForm();
119-
$this->activeFilters = $model->getActiveFilters();
120-
$this->vote = PluginHelper::isEnabled('content', 'vote');
121-
$this->hits = ComponentHelper::getParams('com_content')->get('record_hits', 1) == 1;
122-
123-
if (!\count($this->items) && $this->isEmptyState = $model->getIsEmptyState()) {
124-
$this->setLayout('emptystate');
125-
}
126-
127-
if (ComponentHelper::getParams('com_content')->get('workflow_enabled')) {
128-
PluginHelper::importPlugin('workflow');
129-
130-
$this->transitions = $model->getTransitions();
131-
}
132-
133-
// Check for errors.
129+
if (ComponentHelper::getParams('com_content')->get('workflow_enabled')) {
130+
PluginHelper::importPlugin('workflow');
134131

135-
if (\count($errors = $model->getErrors()) || $this->transitions === false) {
136-
throw new GenericDataException(implode("\n", $errors), 500);
132+
$this->transitions = $model->getTransitions();
133+
}
134+
} catch (\Exception $e) {
135+
throw new GenericDataException($e->getMessage(), 500, $e);
137136
}
138137

139138
// We don't need toolbar in the modal window.

administrator/components/com_joomlaupdate/src/Model/UpdateModel.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,8 +614,8 @@ public function changeAutoUpdateRegistration(AutoupdateRegisterState $targetStat
614614
Factory::getApplication()->enqueueMessage(
615615
Text::sprintf(
616616
'COM_JOOMLAUPDATE_AUTOUPDATE_REGISTER_ERROR',
617-
$result['message'] ?: '',
618-
$result['status'] ?: ''
617+
$result['message'] ?? '',
618+
$result['status'] ?? ''
619619
),
620620
'error'
621621
);

administrator/components/com_media/resources/scripts/components/modals/confirm-delete-modal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<template #body>
1818
<div class="p-3">
1919
<div class="desc">
20-
{{ translate('JGLOBAL_CONFIRM_DELETE') }}
20+
{{ translate('COM_MEDIA_DELETE') }}
2121
</div>
2222
</div>
2323
</template>

administrator/components/com_media/tmpl/media/default_texts.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
'COM_MEDIA_CREATE_NEW_FOLDER_RELATIVE_PATH_ERROR',
3333
'COM_MEDIA_CREATE_NEW_FOLDER_UNEXPECTED_CHARACTER',
3434
'COM_MEDIA_DECREASE_GRID',
35+
'COM_MEDIA_DELETE',
3536
'COM_MEDIA_DELETE_ERROR',
3637
'COM_MEDIA_DELETE_SUCCESS',
3738
'COM_MEDIA_DROP_FILE',
@@ -79,7 +80,6 @@
7980
'JACTION_CREATE',
8081
'JAPPLY',
8182
'JCANCEL',
82-
'JGLOBAL_CONFIRM_DELETE',
8383
'JGLOBAL_NO_MATCHING_RESULTS',
8484
'JLIB_FORM_FIELD_REQUIRED_VALUE',
8585
'MESSAGE',

administrator/language/en-GB/com_media.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ COM_MEDIA_CREATE_NEW_FOLDER_RELATIVE_PATH_ERROR="Use of relative paths not permi
2929
COM_MEDIA_CREATE_NEW_FOLDER_SUCCESS="Folder created."
3030
COM_MEDIA_CREATE_NEW_FOLDER_UNEXPECTED_CHARACTER="Invalid folder name. Please choose a folder name with a-z, A-Z, 0-9, ., - and _."
3131
COM_MEDIA_DECREASE_GRID="Decrease grid size"
32+
COM_MEDIA_DELETE="Are you sure you want to delete the selected item(s)? This action is permanent and cannot be undone. If you delete a folder, all of its contents will be permanently removed as well."
3233
COM_MEDIA_DELETE_ERROR="Error deleting the item."
3334
COM_MEDIA_DELETE_NOT_POSSIBLE="Delete not possible!"
3435
COM_MEDIA_DELETE_SUCCESS="Item deleted."

administrator/language/en-GB/plg_quickicon_autoupdate.ini

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
; License GNU General Public License version 2 or later; see LICENSE.txt
44
; Note : All ini files need to be saved as UTF-8
55

6-
PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Automated Update Health Notification"
6+
PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Automated Update Status Notification"
77
PLG_QUICKICON_AUTOUPDATE_CHECKING="Checking Automated Update &hellip;"
88
PLG_QUICKICON_AUTOUPDATE_DISABLED="Automated Updates are disabled."
9-
PLG_QUICKICON_AUTOUPDATE_ERROR="Unknown Health status &hellip;"
9+
PLG_QUICKICON_AUTOUPDATE_ERROR="Unknown Automated Update status &hellip;"
1010
PLG_QUICKICON_AUTOUPDATE_GROUP_DESC="The group of this plugin (this value is compared with the group value used in <strong>Quick Icons</strong> modules to inject icons)."
1111
PLG_QUICKICON_AUTOUPDATE_GROUP_LABEL="Group"
1212
PLG_QUICKICON_AUTOUPDATE_OK="Automated Updates are enabled."
1313
PLG_QUICKICON_AUTOUPDATE_OUTDATED="Automated Updates connection broken."
1414
PLG_QUICKICON_AUTOUPDATE_UNAVAILABLE="Automated Updates unavailable."
15-
PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of automated updates and notifies you when you visit the Home Dashboard page."
15+
PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Monitors the status of automated updates and notifies you when you visit the Home Dashboard page."

administrator/language/en-GB/plg_quickicon_autoupdate.sys.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
; License GNU General Public License version 2 or later; see LICENSE.txt
44
; Note : All ini files need to be saved as UTF-8
55

6-
PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Automated Update Health Notification"
7-
PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Checks the health status of automated updates and notifies you when you visit the Home Dashboard page."
6+
PLG_QUICKICON_AUTOUPDATE="Quick Icon - Joomla! Automated Update Status Notification"
7+
PLG_QUICKICON_AUTOUPDATE_XML_DESCRIPTION="Monitors the status of automated updates and notifies you when you visit the Home Dashboard page."

0 commit comments

Comments
 (0)