Skip to content

Commit

Permalink
add check on constants and properties + tests
Browse files Browse the repository at this point in the history
  • Loading branch information
matthieu-rolland committed Sep 13, 2024
1 parent e77dec3 commit 27c5254
Show file tree
Hide file tree
Showing 11 changed files with 314 additions and 4 deletions.
94 changes: 92 additions & 2 deletions src/Core/Module/ModuleOverrideChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,36 @@ public function getErrors(): array
*/
private function hasConflictingMethod(string $moduleOverridePath, string $existingOverridePath): bool
{
$moduleMethods = $this->getClassMethodsFromContent(file_get_contents($moduleOverridePath));
$existingOverrideMethods = $this->getClassMethodsFromContent(file_get_contents($existingOverridePath));
$moduleOverrideContent = file_get_contents($moduleOverridePath);
$existingOverrideContent = file_get_contents($existingOverridePath);

$moduleMethods = $this->getClassMethodsFromContent($moduleOverrideContent);
$existingOverrideMethods = $this->getClassMethodsFromContent($existingOverrideContent);

foreach ($moduleMethods as $method) {
if (in_array($method, $existingOverrideMethods)) {
return true;
}
}

$moduleOverrideProperties = $this->getClassPropertiesFromContent($moduleOverrideContent);
$existingOverrideProperties = $this->getClassPropertiesFromContent($existingOverrideContent);

foreach ($moduleOverrideProperties as $property) {
if (in_array($property, $existingOverrideProperties)) {
return true;
}
}

$moduleOverrideConstants = $this->getClassConstantsFromContent($moduleOverrideContent);
$existingOverrideConstants = $this->getClassConstantsFromContent($existingOverrideContent);

foreach ($moduleOverrideConstants as $constants) {
if (in_array($constants, $existingOverrideConstants)) {
return true;
}
}

return false;
}

Expand Down Expand Up @@ -144,4 +165,73 @@ private function getClassMethodsFromContent(string $content): array

return $methods;
}

/*
* This function parses php file content and gets a list of properties from its content.
*/
private function getClassPropertiesFromContent(string $content): array
{
// Get the list of tokens, see https://www.php.net/manual/en/function.token-get-all.php
$tokens = token_get_all($content);
$properties = [];
$inClass = false;
$inFunction = false;

foreach ($tokens as $index => $token) {
// we only want variables that are inside a class AND outside a function
if (is_array($token) && $token[0] === T_CLASS) {
$inClass = true;
$inFunction = false;
}

// check that we are in the beginning of a function
if (is_array($token) && $token[0] === T_FUNCTION) {
$inFunction = true;
}

// check that this is the end of a function
if ($token === '}') {
$inFunction = false;
}

// Property name is gathered if we are inside a class and outside a function
if ($inClass && !$inFunction && is_array($token) && $token[0] === T_VARIABLE) {
$propertyName = $token[1]; // Token contains the variable name as the second element
$properties[] = $propertyName; // Add to the properties array
}
}

return $properties; // Return the list of property names
}

/*
* This function parses php file content and gets a list of constants from its content.
*/
private function getClassConstantsFromContent(string $content): array
{
// Get the list of tokens, see https://www.php.net/manual/en/function.token-get-all.php
$tokens = token_get_all($content);
$constants = [];
$inClass = false;

foreach ($tokens as $index => $token) {
// check that we are at the beginning of a class
if (is_array($token) && $token[0] === T_CLASS) {
$inClass = true;
}

// Check for constant declarations inside the class
if ($inClass && is_array($token) && $token[0] === T_CONST) {
// Loop ahead to find the constant name
for ($i = $index + 1; $i < count($tokens); ++$i) {
if (is_array($tokens[$i]) && $tokens[$i][0] === T_STRING) {
$constants[] = $tokens[$i][1]; // Save constant name
break;
}
}
}
}

return $constants;
}
}
22 changes: 20 additions & 2 deletions tests/Integration/Core/Addon/Module/ModuleManagerBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@ public static function setUpBeforeClass(): void
if (is_dir($dirResources . '/Resources/modules_tests/testtrickyconflict')) {
Tools::recurseCopy($dirResources . '/Resources/modules_tests/testtrickyconflict', _PS_MODULE_DIR_ . '/testtrickyconflict');
}
if (is_dir($dirResources . '/Resources/modules_tests/testconstantconflict')) {
Tools::recurseCopy($dirResources . '/Resources/modules_tests/testconstantconflict', _PS_MODULE_DIR_ . '/testconstantconflict');
}
if (is_dir($dirResources . '/Resources/modules_tests/testpropertyconflict')) {
Tools::recurseCopy($dirResources . '/Resources/modules_tests/testpropertyconflict', _PS_MODULE_DIR_ . '/testpropertyconflict');
}
}

public static function tearDownAfterClass(): void
Expand All @@ -98,6 +104,12 @@ public static function tearDownAfterClass(): void
if (Module::isInstalled('testtrickyconflict')) {
Module::getInstanceByName('testtrickyconflict')->uninstall();
}
if (Module::isInstalled('testpropertyconflict')) {
Module::getInstanceByName('testpropertyconflict')->uninstall();
}
if (Module::isInstalled('testconstantconflict')) {
Module::getInstanceByName('testconstantconflict')->uninstall();
}

// Remove modules
if (is_dir(_PS_MODULE_DIR_ . '/pscsx3241')) {
Expand All @@ -112,6 +124,12 @@ public static function tearDownAfterClass(): void
if (is_dir(_PS_MODULE_DIR_ . '/testtrickyconflict')) {
Tools::deleteDirectory(_PS_MODULE_DIR_ . '/testtrickyconflict');
}
if (is_dir(_PS_MODULE_DIR_ . '/testpropertyconflict')) {
Tools::deleteDirectory(_PS_MODULE_DIR_ . '/testpropertyconflict');
}
if (is_dir(_PS_MODULE_DIR_ . '/testconstantconflict')) {
Tools::deleteDirectory(_PS_MODULE_DIR_ . '/testconstantconflict');
}

// Remove overrides
@unlink(_PS_ROOT_DIR_ . '/override/controllers/admin/AdminProductsController.php');
Expand All @@ -135,7 +153,7 @@ protected function setUp(): void
'pscsx3241',
];

$this->conflictModuleNames = ['testbasicconflict', 'testtrickyconflict'];
$this->conflictModuleNames = ['testbasicconflict', 'testtrickyconflict', 'testpropertyconflict', 'testconstantconflict'];
}

public function testInstall(): void
Expand Down Expand Up @@ -195,7 +213,7 @@ public function testOverrideConflictAtInstall(): void
* adds several spaces in function definition (it must still be detected as a conflicting method)
*/
foreach ($this->conflictModuleNames as $name) {
$this->assertFalse($this->moduleManager->install($name));
$this->assertFalse($this->moduleManager->install($name), 'module test on ' . $name . ' failed');
}
}

Expand Down
2 changes: 2 additions & 0 deletions tests/Resources/modules_tests/override/classes/Cart.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

class Cart extends CartCore
{
public const BOTH = 999;

/*
* module: pscsx32412
* date: 2018-12-26 14:14:05
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
*/
class Cart extends CartCore
{
public const BOTH = 111;

public $delivery_option;

/** @var bool Allow to seperate order in multiple package in order to recieve as soon as possible the available products */
Expand Down
12 changes: 12 additions & 0 deletions tests/Resources/modules_tests/testconstantconflict/config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<module>
<name>testconstantconflict</name>
<displayName><![CDATA[test constant conflict]]></displayName>
<version><![CDATA[1]]></version>
<description><![CDATA[A module to test constant override conflict]]></description>
<author><![CDATA[fake_author]]></author>
<tab><![CDATA[front_office_features]]></tab>
<is_configurable>0</is_configurable>
<need_instance>0</need_instance>
<limited_countries></limited_countries>
</module>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
class Cart extends CartCore
{
/**
* this should trigger a constant override conflict
*/
public const BOTH = 111;

/**
* this function override does not trigger any conflict
*/
public function isCarrierInRange($id_carrier, $id_zone)
{
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
if (!defined('_PS_VERSION_')) {
exit;
}

class testconstantconflict extends Module
{
public function __construct()
{
$this->name = 'testconstantconflict';
$this->tab = 'front_office_features';
$this->version = 1.0;
$this->author = 'fake author';
$this->need_instance = 0;
parent::__construct();
$this->displayName = $this->l('constant conflict');
$this->description = $this->l('A module to test constant override conflict');
}
}
12 changes: 12 additions & 0 deletions tests/Resources/modules_tests/testpropertyconflict/config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<module>
<name>testpropertyconflict</name>
<displayName><![CDATA[test property conflict]]></displayName>
<version><![CDATA[1]]></version>
<description><![CDATA[A module to test property override conflict]]></description>
<author><![CDATA[fake_author]]></author>
<tab><![CDATA[front_office_features]]></tab>
<is_configurable>0</is_configurable>
<need_instance>0</need_instance>
<limited_countries></limited_countries>
</module>
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
class Cart extends CartCore
{
/**
* this should trigger a property override conflict
*/
protected $_products = ['fake_value'];

/**
* this function override does not trigger any conflict
*/
public function isCarrierInRange($id_carrier, $id_zone)
{
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
if (!defined('_PS_VERSION_')) {
exit;
}

class testpropertyconflict extends Module
{
public function __construct()
{
$this->name = 'testpropertyconflict';
$this->tab = 'front_office_features';
$this->version = 1.0;
$this->author = 'fake author';
$this->need_instance = 0;
parent::__construct();
$this->displayName = $this->l('property conflict');
$this->description = $this->l('A module to test property override conflict');
}
}
8 changes: 8 additions & 0 deletions tests/Unit/Core/Module/ModuleOverrideCheckerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ public function provideTestData(): array
'testtrickyconflict',
true,
],
[
'testpropertyconflict',
true,
],
[
'testconstantconflict',
true,
],
];
}
}

0 comments on commit 27c5254

Please sign in to comment.