diff --git a/app/code/core/Mage/Cms/Helper/Page.php b/app/code/core/Mage/Cms/Helper/Page.php
index 710b0a86658..1cd1f559e5e 100644
--- a/app/code/core/Mage/Cms/Helper/Page.php
+++ b/app/code/core/Mage/Cms/Helper/Page.php
@@ -174,4 +174,66 @@ public static function getUsedInStoreConfigPaths(?array $paths = []): array
return $searchPaths;
}
+
+ /**
+ * @param self::XML_PATH_* $path
+ */
+ public static function getConfigLabelFromConfigPath(string $path): string
+ {
+ return match ($path) {
+ self::XML_PATH_NO_ROUTE_PAGE => Mage::helper('cms')->__('No Route Page'),
+ self::XML_PATH_NO_COOKIES_PAGE => Mage::helper('cms')->__('No Cookies Page'),
+ self::XML_PATH_HOME_PAGE => Mage::helper('cms')->__('Home Page'),
+ default => $path,
+ };
+ }
+
+ /**
+ * @param Mage_Adminhtml_Block_System_Config_Form::SCOPE_* $scope
+ * @throws Mage_Core_Exception
+ */
+ public static function getScopeInfoFromConfigScope(string $scope, string $scopeId): string
+ {
+ return match ($scope) {
+ Mage_Adminhtml_Block_System_Config_Form::SCOPE_DEFAULT => Mage::helper('cms')->__('Default Config'),
+ Mage_Adminhtml_Block_System_Config_Form::SCOPE_WEBSITES => Mage::app()->getWebsite($scopeId)->getName(),
+ Mage_Adminhtml_Block_System_Config_Form::SCOPE_STORES => sprintf(
+ '%s "%s"',
+ Mage::app()->getStore($scopeId)->getGroup()->getName(),
+ Mage::app()->getStore($scopeId)->getName(),
+ ),
+ };
+ }
+
+ /**
+ * @throws Mage_Core_Exception
+ */
+ public static function getValidateConfigErrorMessage(Mage_Core_Model_Resource_Db_Collection_Abstract $isUsedInConfig): string
+ {
+ $messages = [];
+
+ $data = $isUsedInConfig->getData();
+ foreach ($data as $key => $item) {
+ $path = $item['path'];
+ unset($item['config_id'], $item['path'], $item['updated_at'], $item['value']);
+ $data[$path][] = $item;
+ unset($data[$key], $key, $path);
+ }
+
+ foreach ($data as $path => $items) {
+ $scopes = [];
+ foreach ($items as $item) {
+ $scopes[] = self::getScopeInfoFromConfigScope($item['scope'], $item['scope_id']);
+ }
+
+ $messages[] = sprintf(
+ '"%s" (%s)',
+ self::getConfigLabelFromConfigPath($path),
+ implode(', ', $scopes),
+ );
+ }
+ unset($data, $path, $items, $item, $scopes);
+
+ return implode(', ', $messages);
+ }
}
diff --git a/app/code/core/Mage/Cms/Model/Resource/Page.php b/app/code/core/Mage/Cms/Model/Resource/Page.php
index fe70583a913..09ef2627598 100644
--- a/app/code/core/Mage/Cms/Model/Resource/Page.php
+++ b/app/code/core/Mage/Cms/Model/Resource/Page.php
@@ -39,8 +39,9 @@ protected function _beforeDelete(Mage_Core_Model_Abstract $object)
$object->setId(null);
Mage::throwException(
Mage::helper('cms')->__(
- 'Cannot delete page, it is used in "%s".',
- implode(', ', $isUsedInConfig->getColumnValues('path')),
+ 'Cannot delete page, it is used in configuration for %s.',
+ Mage::helper('adminhtml')->getUrl('adminhtml/system_config/edit', ['section' => 'web']),
+ Mage_Cms_Helper_Page::getValidateConfigErrorMessage($isUsedInConfig),
),
);
}
@@ -79,8 +80,9 @@ protected function _beforeSave(Mage_Core_Model_Abstract $object)
$object->setIsActive(true);
Mage::getSingleton('adminhtml/session')->addWarning(
Mage::helper('cms')->__(
- 'Cannot disable page, it is used in configuration "%s".',
- implode(', ', $isUsedInConfig->getColumnValues('path')),
+ 'Cannot disable page, it is used in configuration for %s.',
+ Mage::helper('adminhtml')->getUrl('adminhtml/system_config/edit', ['section' => 'web']),
+ Mage_Cms_Helper_Page::getValidateConfigErrorMessage($isUsedInConfig),
),
);
}
@@ -281,7 +283,9 @@ protected function isValidPageIdentifier(Mage_Core_Model_Abstract $object)
public function getUsedInStoreConfigCollection(Mage_Cms_Model_Page $page, ?array $paths = []): Mage_Core_Model_Resource_Db_Collection_Abstract
{
- $storeIds = (array) $page->getStoreId();
+ $storeId = (array) $page->getStoreId(); # null on save
+ $stores = (array) $page->getStores(); # null on delete
+ $storeIds = array_merge($storeId, $stores);
$storeIds[] = Mage_Core_Model_App::ADMIN_STORE_ID;
$config = Mage::getResourceModel('core/config_data_collection')
->addFieldToFilter('value', $page->getIdentifier())
diff --git a/app/code/core/Mage/Cms/etc/system.xml b/app/code/core/Mage/Cms/etc/system.xml
index 78438587b9e..bf6806e043a 100644
--- a/app/code/core/Mage/Cms/etc/system.xml
+++ b/app/code/core/Mage/Cms/etc/system.xml
@@ -17,7 +17,7 @@
select
adminhtml/system_config_source_cms_page
- 1
+ 21
1
1
1
@@ -26,7 +26,7 @@
select
adminhtml/system_config_source_cms_page
- 2
+ 22
1
1
1
@@ -35,7 +35,7 @@
select
adminhtml/system_config_source_cms_page
- 3
+ 23
1
1
1
@@ -44,7 +44,7 @@
select
adminhtml/system_config_source_yesno
- 5
+ 25
1
1
1
diff --git a/app/locale/en_US/Mage_Cms.csv b/app/locale/en_US/Mage_Cms.csv
index 52f813fe13d..d106bdd764f 100644
--- a/app/locale/en_US/Mage_Cms.csv
+++ b/app/locale/en_US/Mage_Cms.csv
@@ -27,10 +27,10 @@
"CMS Static Block","CMS Static Block"
"CMS Static Block Default Template","CMS Static Block Default Template"
"Cannot create new directory.","Cannot create new directory."
-"Cannot delete page, it is used in ""%s"".","Cannot delete page, it is used in ""%s""."
+"Cannot delete page, it is used in configuration %s.","Cannot delete page, it is used in configuration %s."
"Cannot delete directory %s.","Cannot delete directory %s."
"Cannot delete root directory %s.","Cannot delete root directory %s."
-"Cannot disable page, it is used in configuration ""%s"".","Cannot disable page, it is used in configuration ""%s""."
+"Cannot disable page, it is used in configuration %s.","Cannot disable page, it is used in configuration %s."
"Cannot upload file.","Cannot upload file."
"Collapse All","Collapse All"
"Content","Content"
diff --git a/cypress/e2e/openmage/backend/cms/page.cy.js b/cypress/e2e/openmage/backend/cms/page.cy.js
index c0f43f81f0f..ebd15a65641 100644
--- a/cypress/e2e/openmage/backend/cms/page.cy.js
+++ b/cypress/e2e/openmage/backend/cms/page.cy.js
@@ -1,4 +1,5 @@
const route = cy.testRoutes.backend.cms.page;
+const validation = cy.openmage.validation;
describe(`Checks admin system "${route.h3}"`, () => {
beforeEach('Log in the user', () => {
@@ -9,4 +10,31 @@ describe(`Checks admin system "${route.h3}"`, () => {
it(`tests classes and title`, () => {
cy.adminTestRoute(route);
});
+
+ it('tests to disable a CMS page that is used in config', () => {
+ cy.log('Select a CMS page');
+ cy.get(route._gridTable)
+ .contains('td', 'no-route')
+ .click();
+
+ cy.log('Disable the CMS page');
+ cy.get('#page_is_active')
+ .select('Disabled');
+
+ validation.saveAction(route._buttonSaveAndContinue);
+ cy.get(validation._warningMessage).should('include.text', 'Cannot disable page, it is used in configuration');
+ cy.get(validation._successMessage).should('include.text', 'The page has been saved.');
+ cy.get('#messages').screenshot('error-disable-active-page', { overwrite: true});
+ });
+
+ it('tests to delete a CMS page that is used in config', () => {
+ cy.log('Select a CMS page');
+ cy.get(route._gridTable)
+ .contains('td', 'no-route')
+ .click();
+
+ validation.saveAction(route._buttonDelete);
+ cy.get(validation._errorMessage).should('include.text', 'Cannot delete page');
+ cy.get('#messages').screenshot('error-delete-active-page', { overwrite: true});
+ });
});
\ No newline at end of file
diff --git a/cypress/support/openmage.js b/cypress/support/openmage.js
index e4c67926cc9..c7e5a0c56e0 100644
--- a/cypress/support/openmage.js
+++ b/cypress/support/openmage.js
@@ -82,7 +82,7 @@ cy.openmage = {
},
saveAction: (selector) => {
cy.log('Clicking on Save button');
- cy.get(selector).click({force: true, multiple: true});
+ cy.get(selector).first().click({force: true, multiple: false});
},
validateFields: (fields, validation) =>{
cy.log('Checking for error messages');
diff --git a/cypress/support/openmage/config/paths.js b/cypress/support/openmage/config/paths.js
index 2470f01ecf2..337c497f3d2 100644
--- a/cypress/support/openmage/config/paths.js
+++ b/cypress/support/openmage/config/paths.js
@@ -73,6 +73,11 @@ cy.testRoutes = {
url: 'cms_page/index',
h3: 'Manage Pages',
_h3: adminPage._h3,
+ _gridTable: '#cmsPageGrid_table',
+ _buttonDelete: '.form-buttons button[title="Delete Page"]',
+ _buttonReset: '.form-buttons button[title="Reset"]',
+ _buttonSave: '.form-buttons button[title="Save Page"]',
+ _buttonSaveAndContinue: '.form-buttons button[title="Save and Continue Edit"]',
},
widget: {
_id_parent: adminNav.cms,
diff --git a/tests/unit/Mage/Cms/Helper/PageTest.php b/tests/unit/Mage/Cms/Helper/PageTest.php
index 284e0dea6ed..f54b712a50a 100644
--- a/tests/unit/Mage/Cms/Helper/PageTest.php
+++ b/tests/unit/Mage/Cms/Helper/PageTest.php
@@ -20,6 +20,7 @@ final class PageTest extends OpenMageTest
use CmsTrait;
/**
+ * @covers Mage_Cms_Helper_Page::getUsedInStoreConfigPaths()
* @dataProvider provideGetUsedInStoreConfigPaths
* @group Helper
*/
@@ -27,4 +28,24 @@ public function testGetUsedInStoreConfigPaths(array $expectedResult, ?array $pat
{
self::assertSame($expectedResult, Subject::getUsedInStoreConfigPaths($path));
}
+
+ /**
+ * @covers Mage_Cms_Helper_Page::getConfigLabelFromConfigPath()
+ * @dataProvider provideGetConfigLabelFromConfigPath
+ * @group Helper
+ */
+ public function testGetConfigLabelFromConfigPath(string $expectedResult, string $paths): void
+ {
+ self::assertSame($expectedResult, Subject::getConfigLabelFromConfigPath($paths));
+ }
+
+ /**
+ * @covers Mage_Cms_Helper_Page::getScopeInfoFromConfigScope()
+ * @dataProvider provideGetScopeInfoFromConfigScope
+ * @group Helper
+ */
+ public function testGetScopeInfoFromConfigScope(string $expectedResult, string $scope, string $scopeId): void
+ {
+ self::assertStringStartsWith($expectedResult, Subject::getScopeInfoFromConfigScope($scope, $scopeId));
+ }
}
diff --git a/tests/unit/Traits/DataProvider/Mage/Cms/CmsTrait.php b/tests/unit/Traits/DataProvider/Mage/Cms/CmsTrait.php
index 9b02b997d0e..d6df9624f30 100644
--- a/tests/unit/Traits/DataProvider/Mage/Cms/CmsTrait.php
+++ b/tests/unit/Traits/DataProvider/Mage/Cms/CmsTrait.php
@@ -11,6 +11,7 @@
namespace OpenMage\Tests\Unit\Traits\DataProvider\Mage\Cms;
use Generator;
+use Mage_Adminhtml_Block_System_Config_Form;
use Mage_Cms_Helper_Page;
trait CmsTrait
@@ -45,6 +46,45 @@ public function provideGetUsedInStoreConfigPaths(): Generator
];
}
+ public function provideGetConfigLabelFromConfigPath(): Generator
+ {
+ yield 'home page' => [
+ 'Home Page',
+ Mage_Cms_Helper_Page::XML_PATH_HOME_PAGE,
+ ];
+
+ yield 'no cookie page' => [
+ 'No Cookies Page',
+ Mage_Cms_Helper_Page::XML_PATH_NO_COOKIES_PAGE,
+ ];
+
+ yield 'no route page' => [
+ 'No Route Page',
+ Mage_Cms_Helper_Page::XML_PATH_NO_ROUTE_PAGE,
+ ];
+ }
+
+ public function provideGetScopeInfoFromConfigScope(): Generator
+ {
+ yield 'default' => [
+ 'Default Config',
+ Mage_Adminhtml_Block_System_Config_Form::SCOPE_DEFAULT,
+ '1',
+ ];
+
+ yield 'websites' => [
+ 'Main Website',
+ Mage_Adminhtml_Block_System_Config_Form::SCOPE_WEBSITES,
+ '1',
+ ];
+
+ yield 'stores' => [
+ 'Main Website',
+ Mage_Adminhtml_Block_System_Config_Form::SCOPE_STORES,
+ '1',
+ ];
+ }
+
public function provideGetShortFilename(): Generator
{
yield 'full length' => [