Skip to content
Permalink
Browse files

ESDEV-4341 Fix handling of not loadable module classes

If a module class within a namespace is not loadable for whatever reason, this class was not included in the "Problematic files" section in OXID eShop Admin -> Extensions -> Modules -> Installed Modules.
This commit fixes this bug and adds regression tests
  • Loading branch information...
robertblank committed Mar 14, 2017
1 parent 8c45860 commit b5268a80e2b730a10760a21e68c3c67dd190b4ac
@@ -16,7 +16,7 @@
* along with OXID eShop Community Edition. If not, see <http://www.gnu.org/licenses/>.
*
* @link http://www.oxid-esales.com
* @copyright (C) OXID eSales AG 2003-2016
* @copyright (C) OXID eSales AG 2003-2017
* @version OXID eShop CE
*/
@@ -34,6 +34,7 @@
*/
class ModuleList extends \OxidEsales\Eshop\Core\Base
{
const MODULE_KEY_PATHS = 'Paths';
const MODULE_KEY_EVENTS = 'Events';
const MODULE_KEY_VERSIONS = 'Versions';
@@ -674,6 +675,7 @@ protected function _isVendorDir($sModuleDir)
return true;
}
}
return false;
}
@@ -752,10 +754,30 @@ private function _getInvalidExtensions($sModuleId)
if (!file_exists($sExtPath)) {
$aDeletedExt[$sOxClass][] = $sModulePath;
}
} else {
/** Note: $aDeletedExt is passed by reference */
$this->_backwardsCompatibleGetInvalidExtensions($sModulePath, $aDeletedExt, $sOxClass);
}
}
}
return $aDeletedExt;
}
/**
* Backwards compatible version of self::_getInvalidExtensions()
*
* @param string $sModulePath
* @param array $aDeletedExt Note: This parameter is passed by reference
* @param string $sOxClass
*
* @deprecated since v6.0 (2017-03-14); This method will be removed in the future.
*/
private function _backwardsCompatibleGetInvalidExtensions($sModulePath, &$aDeletedExt, $sOxClass)
{
$sExtPath = $this->getConfig()->getModulesDir() . $sModulePath . '.php';
if (!file_exists($sExtPath)) {
$aDeletedExt[$sOxClass][] = $sModulePath;
}
}
}
@@ -114,7 +114,7 @@
/**
* Register the module autoload.
* It will load classes like YourModule_parent or classes defined in the metadata key 'extends'
* It will load classes classes defined in the metadata key 'files'
* When this autoloader is called a database connection will be triggered
*/
require_once CORE_AUTOLOADER_PATH . 'ModuleAutoload.php';
@@ -164,6 +164,35 @@ public function testModulesHandlingExtendingClass()
$this->assertTextNotPresent("About Us + info1 + info2 + info7 + namespace1");
}
/**
* @covers \OxidEsales\EshopCommunity\Core\Module\ModuleList::_getInvalidExtensions()
*/
public function testGetDeletedExtensionsForNamespaceModuleShowErrorForNonLoadableClasses()
{
$testConfig = $this->getTestConfig();
if ($testConfig->isSubShop()) {
$this->markTestSkipped('Test is not for SubShop');
}
$this->loginAdmin('Extensions', 'Modules');
/** The metadata.php of module 'Invalid Namespaced Module #1' refers to 2 non loadable classes */
$this->activateModuleAndCheck('Invalid Namespaced Module #1');
//checking if all expected non loadable classes are displayed
$this->openTab("Installed Shop Modules");
$this->assertTextPresent("Problematic Files");
$this->assertTextPresent('NonExistentClass');
$this->assertTextPresent('NonExistentFile');
//checking if clicking "Yes" fixes the problematic files
$this->clickAndWait("yesButton");
$this->openTab("Installed Shop Modules");
$this->assertTextNotPresent("Problematic Files");
$this->assertTextNotPresent('NonExistentClass');
$this->assertTextNotPresent('NonExistentFile');
}
/**
* Test, that the module deactivation works in the non demo mode.
*
@@ -0,0 +1,30 @@
<?php
/**
* This file is part of OXID eShop Community Edition.
*
* OXID eShop Community Edition is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OXID eShop Community Edition is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OXID eShop Community Edition. If not, see <http://www.gnu.org/licenses/>.
*
* @link http://www.oxid-esales.com
* @copyright (C) OXID eSales AG 2003-2017
* @version OXID eShop CE
*/
/*
* As class name and file name do not match, this class will not be loaded by any PSR-4 autoloader and it is as it does
* not exist.
* (E.g. do not think just checking for the existance o a fine is enough)
*/
class _NonExistentClass
{
}
@@ -0,0 +1,44 @@
<?php
/**
* This file is part of OXID eShop Community Edition.
*
* OXID eShop Community Edition is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OXID eShop Community Edition is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OXID eShop Community Edition. If not, see <http://www.gnu.org/licenses/>.
*
* @link http://www.oxid-esales.com
* @copyright (C) OXID eSales AG 2003-2017
* @version OXID eShop CE
*/
/**
* Module information
*/
$aModule = array(
'id' => 'InvalidNamespaceModule1',
'title' => 'Invalid Namespaced Module #1',
'description' => 'Test module validation for modules, which use namespaces',
'thumbnail' => 'module.png',
'version' => '1.0',
'author' => 'OXID',
'extend' => [
/**
* In this test case the file with the proper name is present, but it contains the wrong class.
* This means the class cannot be loaded properly
*/
\OxidEsales\Eshop\Application\Controller\ContentController::class => \OxidEsales\EshopCommunity\Tests\Acceptance\Admin\testData\modules\oxid\InvalidNamespaceModule1\Controller\NonExistentClass::class,
/**
* In this test case the class file does not exist at all and thus the class cannot be loaded
*/
\OxidEsales\Eshop\Application\Model\Article::class => \OxidEsales\EshopCommunity\Tests\Acceptance\Admin\testData\modules\oxid\InvalidNamespaceModule1\Model\NonExistentFile::class
],
);
Binary file not shown.
@@ -22,21 +22,22 @@
namespace Unit\Core;
use \oxDb;
use OxidEsales\Eshop\Core\Module\ModuleMetadataValidator;
use OxidEsales\EshopCommunity\Core\Module\ModuleList;
/**
* @group module
* @package Unit\Core
*/
class ModulelistTest extends \OxidTestCase
class ModuleListTest extends \OxidTestCase
{
/**
* test setup
*
* @return null
*/
public function setup()
public function setUp()
{
parent::setUp();
}
@@ -878,6 +879,58 @@ public function testGetDeletedExtensionsWithMissingExtensions()
$this->assertEquals($aDeletedExt, $aDeletedExtensions);
}
/**
* Non loadable classes should be listed in the "PROBLEMATIC FILES" section in
* OXID eShop Admin -> Extensions -> Modules -> "Installed Shop Modules" Tab and therefore they must form part of
* the so called "deleted extensions"
*
* The return value of the method covered by this test is independent from the session variable
* "blSkipDeletedExtChecking", the rendering of the error message is not.
*
* @see \OxidEsales\EshopCommunity\Tests\Acceptance\Admin\ModuleTest::testGetDeletedExtensionsForNamespaceModuleShowErrorForNonLoadableClasses
*
* @covers \OxidEsales\EshopCommunity\Core\Module\ModuleList::getDeletedExtensions
*/
public function testGetDeletedExtensionsForNonLoadableClasses()
{
$expectedDeletedExtensions = [
'SomeVendor\SomeModule\Application\Model\Article' => [
'extensions' => [
'OxidEsales\Eshop\Application\Model\Article' => [
'SomeVendor\SomeModule\Application\Model\Article'
]
]
]
];
/** @var array $aModules Contains a class, which is not loadable - in this case - as it does not exist */
$aModules = [\OxidEsales\Eshop\Application\Model\Article::class => \SomeVendor\SomeModule\Application\Model\Article::class];
$this->setConfigParam("aModules", $aModules);
$moduleMetadataValidatorMock = $this->getMock(
\OxidEsales\EshopCommunity\Core\Module\ModuleMetadataValidator::class,
['validate']
);
$moduleMetadataValidatorMock->expects($this->any())->method('validate')->will($this->returnValue(true));
$moduleValidatorFactoryMock = $this->getMock(
\OxidEsales\EshopCommunity\Core\Module\ModuleValidatorFactory::class,
['getModuleMetadataValidator']
);
$moduleValidatorFactoryMock->expects($this->any())->method('getModuleMetadataValidator')->will($this->returnValue($moduleMetadataValidatorMock));
/** @var \OxidEsales\EshopCommunity\Core\Module\ModuleList|\PHPUnit_Framework_MockObject_MockObject $moduleListMock */
$moduleListMock = $this->getMock(
\OxidEsales\EshopCommunity\Core\Module\ModuleList::class,
['getModuleValidatorFactory']
);
$moduleListMock->expects($this->any())->method('getModuleValidatorFactory')->will($this->returnValue($moduleValidatorFactoryMock));
$actualDeletedExtensions = $moduleListMock->getDeletedExtensions();
$this->assertEquals($expectedDeletedExtensions, $actualDeletedExtensions);
}
public function testGetModuleIds()
{
$oModuleList = oxNew('oxModuleList');

0 comments on commit b5268a8

Please sign in to comment.
You can’t perform that action at this time.