Skip to content

Commit

Permalink
replace token detection with regex
Browse files Browse the repository at this point in the history
  • Loading branch information
matthieu-rolland committed Sep 13, 2024
1 parent bc54297 commit 52bb96a
Show file tree
Hide file tree
Showing 6 changed files with 5,095 additions and 96 deletions.
93 changes: 19 additions & 74 deletions src/Core/Module/ModuleOverrideChecker.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,14 @@ public function hasOverrideConflict(string $moduleOverridePath): bool
$fileList[] = $file->getRelativePathname();
}



// module has overrides, let's check override files one by one
foreach ($fileList as $file) {
$moduleOverrideFile = $moduleOverridePath . DIRECTORY_SEPARATOR . $file;
$existingOverrideFile = $this->psOverrideDir . $file;

$moduleOverrideContent = file_get_contents($moduleOverrideFile);
$existingOverrideContent = file_get_contents($existingOverrideFile);

if (file_exists($existingOverrideFile)) {
if (file_exists($existingOverrideFile) && file_exists($moduleOverrideFile)) {
$moduleOverrideContent = file_get_contents($moduleOverrideFile);
$existingOverrideContent = file_get_contents($existingOverrideFile);
if (
$this->hasConflictingMethod($moduleOverrideContent, $existingOverrideContent)
|| $this->hasConflictingProperty($moduleOverrideContent, $existingOverrideContent)
Expand Down Expand Up @@ -157,95 +154,43 @@ private function hasConflictingMethod(string $moduleOverrideContent, string $exi
*/
private function getClassMethodsFromContent(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);
$methodPattern = '/(public|private|protected)\s+function\s+(\w+)/';

$methods = [];
foreach ($tokens as $index => $token) {
$methodName = null;
// filter method definitions
if (is_array($token) && $token[0] === T_FUNCTION) {
// This loop is necessary in case some additional spaces exist before the function name
for ($i = $index + 1; $i < count($tokens); ++$i) {
if (is_array($tokens[$i]) && $tokens[$i][0] === T_STRING) {
$methodName = $tokens[$i][1];
break;
}
}

// Collect method name
if ($methodName) {
$methods[] = $methodName; // Save method name
}
}
if (preg_match_all($methodPattern, $content, $matches)) {
$methods = $matches[2];
}

return $methods;
}

/*
* This function parses php file content and gets a list of properties from its content.
*/
* 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);
$propertyPattern = '/(public|private|protected)\s+\$(\w+)/';
$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
}
if (preg_match_all($propertyPattern, $content, $matches)) {
$properties = $matches[2];
}

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

/*
* This function parses php file content and gets a list of constants from its content.
*/
* This function parses php file content and gets a list of properties 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;
$constantPattern = '/const\s+(\w+)/';

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;
}
$constants = [];

// 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;
}
}
}
if (preg_match_all($constantPattern, $content, $matches)) {
$constants = $matches[1];
}

return $constants;
Expand Down
27 changes: 8 additions & 19 deletions tests/Integration/Core/Addon/Module/ModuleManagerBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,6 @@ 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');
}
Expand All @@ -107,9 +104,6 @@ public static function tearDownAfterClass(): void
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 @@ -127,9 +121,6 @@ public static function tearDownAfterClass(): void
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 @@ -153,7 +144,8 @@ protected function setUp(): void
'pscsx3241',
];

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

public function testInstall(): void
Expand All @@ -172,20 +164,17 @@ public function testInstall(): void
*/
$resource_path = dirname(__DIR__, 4) . '/Resources/modules_tests/override/';

$actual_override_cart = file_get_contents(_PS_ROOT_DIR_ . '/override/classes/Cart.php');
$expected_override_cart = file_get_contents($resource_path . '/classes/Cart.php');

$actual_override_cart = $this->cleanup($actual_override_cart);
$expected_override_cart = $this->cleanup($expected_override_cart);
$actual_override_cart = $this->cleanup(file_get_contents(_PS_ROOT_DIR_ . '/override/classes/Cart.php'));
$expected_override_cart = $this->cleanup(file_get_contents($resource_path . 'classes/Cart.php'));

$this->assertEquals($expected_override_cart, $actual_override_cart);

$actual_override_admin_product = file_get_contents(_PS_ROOT_DIR_ . '/override/controllers/admin/AdminProductsController.php');
$expected_override_admin_product = file_get_contents($resource_path . '/controllers/admin/AdminProductsController.php');
$actual_override_admin_product = $this->cleanup(file_get_contents(_PS_ROOT_DIR_ . '/override/controllers/admin/AdminProductsController.php'));
$expected_override_admin_product = $this->cleanup(file_get_contents($resource_path . '/controllers/admin/AdminProductsController.php'));

$this->assertEquals(
$this->cleanup($expected_override_admin_product),
$this->cleanup($actual_override_admin_product),
$actual_override_admin_product,
$expected_override_admin_product,
'AdminProductsController.php file different'
);

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

class Cart extends CartCore
{
public const BOTH = 999;

/*
* module: pscsx32412
* date: 2018-12-26 14:14:05
Expand Down
Loading

0 comments on commit 52bb96a

Please sign in to comment.