Skip to content

Commit

Permalink
Override : Create directory if not exists
Browse files Browse the repository at this point in the history
  • Loading branch information
Progi1984 committed Jan 31, 2022
1 parent e5f1187 commit 3c602eb
Show file tree
Hide file tree
Showing 31 changed files with 126 additions and 956 deletions.
2 changes: 1 addition & 1 deletion classes/ConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class ConfigurationTestCore
'/localization/fr.xml',
'/mails/index.php',
'/modules/index.php',
'/override/controllers/front/index.php',
'/override/index.php',
'/pdf/order-return.tpl',
'/translations/export/index.php',
'/webservice/dispatcher.php',
Expand Down
5 changes: 4 additions & 1 deletion classes/Meta.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ public static function getPages($excludeFilled = false, $addPage = false)
die(Tools::displayError(Context::getContext()->getTranslator()->trans('Cannot scan root directory', [], 'Admin.Notifications.Error')));
}

if (!$overrideFiles = Tools::scandir(_PS_CORE_DIR_ . DIRECTORY_SEPARATOR . 'override' . DIRECTORY_SEPARATOR . 'controllers' . DIRECTORY_SEPARATOR . 'front' . DIRECTORY_SEPARATOR, 'php', '', true)) {
$overrideDir = _PS_CORE_DIR_ . DIRECTORY_SEPARATOR . 'override' . DIRECTORY_SEPARATOR . 'controllers' . DIRECTORY_SEPARATOR . 'front' . DIRECTORY_SEPARATOR;
if (!is_dir($overrideDir)) {
$overrideFiles = [];
} elseif (!$overrideFiles = Tools::scandir($overrideDir, 'php', '', true)) {
die(Tools::displayError(Context::getContext()->getTranslator()->trans('Cannot scan "override" directory', [], 'Admin.Notifications.Error')));
}

Expand Down
5 changes: 4 additions & 1 deletion classes/PrestaShopAutoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,12 @@ public function dumpFile($filename, $content)
*/
protected function getClassesFromDir($path)
{
$classes = [];
$rootDir = $this->root_dir;
if (!is_dir($rootDir . $path)) {
return [];
}

$classes = [];
foreach (scandir($rootDir . $path, SCANDIR_SORT_NONE) as $file) {
if ($file[0] != '.') {
if (is_dir($rootDir . $path . $file)) {
Expand Down
125 changes: 117 additions & 8 deletions classes/module/Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\Filesystem\Filesystem as SfFileSystem;
use Symfony\Component\Finder\Finder;

abstract class ModuleCore implements ModuleInterface
Expand Down Expand Up @@ -2787,12 +2788,18 @@ public function addOverride($classname)
file_put_contents($path_override, preg_replace('#(\r\n|\r)#ism', "\n", file_get_contents($path_override)));
}

$psOverrideDir = _PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'override';

$pattern_escape_com = '#(^\s*?\/\/.*?\n|\/\*(?!\n\s+\* module:.*?\* date:.*?\* version:.*?\*\/).*?\*\/)#ism';
// Check if there is already an override file, if not, we just need to copy the file
if ($file = PrestaShopAutoload::getInstance()->getClassPath($classname)) {
// Check if override file is writable
$override_path = _PS_ROOT_DIR_ . '/' . $file;
$file = PrestaShopAutoload::getInstance()->getClassPath($classname);
$override_path = _PS_ROOT_DIR_ . '/' . $file;

if ($file && file_exists($override_path)) {
// Create directory if not exists
$this->createOverrideDirectory($psOverrideDir, dirname($override_path));

// Check if override file is writable
if ((!file_exists($override_path) && !is_writable(dirname($override_path))) || (file_exists($override_path) && !is_writable($override_path))) {
throw new Exception(Context::getContext()->getTranslator()->trans('file (%s) not writable', [$override_path], 'Admin.Notifications.Error'));
}
Expand Down Expand Up @@ -2866,6 +2873,7 @@ public function addOverride($classname)
}
}

// Check if none of the constants already exists in the override class
foreach ($module_class->getConstants() as $constant => $value) {
if ($override_class->hasConstant($constant)) {
throw new Exception(Context::getContext()->getTranslator()->trans('The constant %1$s in the class %2$s is already defined.', [$constant, $classname], 'Admin.Modules.Notification'));
Expand All @@ -2886,12 +2894,11 @@ public function addOverride($classname)
} else {
$override_src = $path_override;

$override_dest = _PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'override' . DIRECTORY_SEPARATOR . $path;
$override_dest = $psOverrideDir . DIRECTORY_SEPARATOR . $path;
$dir_name = dirname($override_dest);

if (!$orig_path && !is_dir($dir_name)) {
@mkdir($dir_name, FileSystem::DEFAULT_MODE_FOLDER);
}
// Create directory if not exists
$this->createOverrideDirectory($psOverrideDir, $dir_name);

if (!is_writable($dir_name)) {
throw new Exception(Context::getContext()->getTranslator()->trans('directory (%s) not writable', [$dir_name], 'Admin.Notifications.Error'));
Expand Down Expand Up @@ -2952,6 +2959,38 @@ public function addOverride($classname)
return true;
}

/**
* Create override directory and add index.php in all tree
*
* @param string $directoryOverride Absolute path of the override directory
* @param string $directoryPath Absolute path of the overriden file directory
*
* @return void
*/
private function createOverrideDirectory(string $directoryOverride, string $directoryPath): void
{
if (is_dir($directoryPath)) {
return;
}
$fs = new SfFileSystem();

// Create directory (in recursive mode)
$fs->mkdir($directoryPath, FileSystem::DEFAULT_MODE_FOLDER);

// Copy index.php to each directory
$splDir = new SplFileInfo($directoryPath . DIRECTORY_SEPARATOR . 'index.php');
do {
// Copy file
$fs->copy(
$directoryOverride . DIRECTORY_SEPARATOR . 'index.php',
$splDir->getPath() . DIRECTORY_SEPARATOR . 'index.php'
);

// Get Parent directory
$splDir = $splDir->getPathInfo();
} while ($splDir->getPath() !== $directoryOverride);
}

/**
* Remove all methods in a module override from the override class.
*
Expand Down Expand Up @@ -3038,7 +3077,6 @@ public function removeOverride($classname)
$length = $method->getEndLine() - $method->getStartLine() + 1;

$module_method = $module_class->getMethod($method->getName());
$module_length = $module_method->getEndLine() - $module_method->getStartLine() + 1;

$override_file_orig = $override_file;

Expand Down Expand Up @@ -3121,10 +3159,42 @@ public function removeOverride($classname)
}

$to_delete = preg_match('/<\?(?:php)?\s+(?:abstract|interface)?\s*?class\s+' . $classname . '\s+extends\s+' . $classname . 'Core\s*?[{]\s*?[}]/ism', $code);

if (!$to_delete) {
// To detect if the class has remaining code, we dynamically create a class which contains the remaining code.
eval(
preg_replace(
[
'#^\s*<\?(?:php)?#',
'#class\s+' . $classname . '\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?#i',
],
[
' ',
'class ' . $classname . 'OverrideOriginal_check' . $uniq . ' extends \stdClass',
],
$code
)
);

// Then we use ReflectionClass to analyze what this code actually contains
$override_class = new ReflectionClass($classname . 'OverrideOriginal_check' . $uniq);

// If no valuable code remains then we can delete it
$to_delete = $override_class->getConstants() === []
&& $override_class->getProperties() === []
&& $override_class->getMethods() === [];
}
}

if (!isset($to_delete) || $to_delete) {
// Remove file
unlink($override_path);

// Remove directory
$this->removeOverrideDirectory(
_PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'override',
dirname($override_path)
);
} else {
file_put_contents($override_path, $code);
}
Expand All @@ -3135,6 +3205,45 @@ public function removeOverride($classname)
return true;
}

/**
* Remove override directory tree if the tree is empty
*
* @param string $directoryOverride
* @param string $directoryPath
*
* @return void
*/
private function removeOverrideDirectory(string $directoryOverride, string $directoryPath): void
{
if (!is_dir($directoryPath)) {
return;
}

$fs = new SfFileSystem();

$splDir = new SplFileInfo($directoryPath);
do {
// Check if there is only index.php in directory
$finder = new Finder();
$finder
->files()
->in($splDir->getPathname())
->notName('index.php');
if ($finder->hasResults()) {
break;
}

// Remove index.php
$fs->remove($splDir->getPathname() . DIRECTORY_SEPARATOR . 'index.php');

// Remove directory
$fs->remove($splDir->getPathname());

// Get Parent directory
$splDir = $splDir->getPathInfo();
} while ($splDir->getPathname() !== $directoryOverride);
}

private function getWidgetHooks()
{
$hooks = array_values(Hook::getHooks(false, true));
Expand Down
35 changes: 0 additions & 35 deletions override/classes/Smarty/index.php

This file was deleted.

35 changes: 0 additions & 35 deletions override/classes/assets/index.php

This file was deleted.

35 changes: 0 additions & 35 deletions override/classes/cache/index.php

This file was deleted.

35 changes: 0 additions & 35 deletions override/classes/checkout/index.php

This file was deleted.

Loading

0 comments on commit 3c602eb

Please sign in to comment.