Skip to content

Commit 3c602eb

Browse files
committed
Override : Create directory if not exists
1 parent e5f1187 commit 3c602eb

File tree

31 files changed

+126
-956
lines changed

31 files changed

+126
-956
lines changed

classes/ConfigurationTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class ConfigurationTestCore
3636
'/localization/fr.xml',
3737
'/mails/index.php',
3838
'/modules/index.php',
39-
'/override/controllers/front/index.php',
39+
'/override/index.php',
4040
'/pdf/order-return.tpl',
4141
'/translations/export/index.php',
4242
'/webservice/dispatcher.php',

classes/Meta.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ public static function getPages($excludeFilled = false, $addPage = false)
7373
die(Tools::displayError(Context::getContext()->getTranslator()->trans('Cannot scan root directory', [], 'Admin.Notifications.Error')));
7474
}
7575

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

classes/PrestaShopAutoload.php

+4-1
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,12 @@ public function dumpFile($filename, $content)
275275
*/
276276
protected function getClassesFromDir($path)
277277
{
278-
$classes = [];
279278
$rootDir = $this->root_dir;
279+
if (!is_dir($rootDir . $path)) {
280+
return [];
281+
}
280282

283+
$classes = [];
281284
foreach (scandir($rootDir . $path, SCANDIR_SORT_NONE) as $file) {
282285
if ($file[0] != '.') {
283286
if (is_dir($rootDir . $path . $file)) {

classes/module/Module.php

+117-8
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
use Symfony\Component\DependencyInjection\ContainerInterface;
3737
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
3838
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
39+
use Symfony\Component\Filesystem\Filesystem as SfFileSystem;
3940
use Symfony\Component\Finder\Finder;
4041

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

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

2798+
if ($file && file_exists($override_path)) {
2799+
// Create directory if not exists
2800+
$this->createOverrideDirectory($psOverrideDir, dirname($override_path));
2801+
2802+
// Check if override file is writable
27962803
if ((!file_exists($override_path) && !is_writable(dirname($override_path))) || (file_exists($override_path) && !is_writable($override_path))) {
27972804
throw new Exception(Context::getContext()->getTranslator()->trans('file (%s) not writable', [$override_path], 'Admin.Notifications.Error'));
27982805
}
@@ -2866,6 +2873,7 @@ public function addOverride($classname)
28662873
}
28672874
}
28682875

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

2889-
$override_dest = _PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'override' . DIRECTORY_SEPARATOR . $path;
2897+
$override_dest = $psOverrideDir . DIRECTORY_SEPARATOR . $path;
28902898
$dir_name = dirname($override_dest);
28912899

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

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

2962+
/**
2963+
* Create override directory and add index.php in all tree
2964+
*
2965+
* @param string $directoryOverride Absolute path of the override directory
2966+
* @param string $directoryPath Absolute path of the overriden file directory
2967+
*
2968+
* @return void
2969+
*/
2970+
private function createOverrideDirectory(string $directoryOverride, string $directoryPath): void
2971+
{
2972+
if (is_dir($directoryPath)) {
2973+
return;
2974+
}
2975+
$fs = new SfFileSystem();
2976+
2977+
// Create directory (in recursive mode)
2978+
$fs->mkdir($directoryPath, FileSystem::DEFAULT_MODE_FOLDER);
2979+
2980+
// Copy index.php to each directory
2981+
$splDir = new SplFileInfo($directoryPath . DIRECTORY_SEPARATOR . 'index.php');
2982+
do {
2983+
// Copy file
2984+
$fs->copy(
2985+
$directoryOverride . DIRECTORY_SEPARATOR . 'index.php',
2986+
$splDir->getPath() . DIRECTORY_SEPARATOR . 'index.php'
2987+
);
2988+
2989+
// Get Parent directory
2990+
$splDir = $splDir->getPathInfo();
2991+
} while ($splDir->getPath() !== $directoryOverride);
2992+
}
2993+
29552994
/**
29562995
* Remove all methods in a module override from the override class.
29572996
*
@@ -3038,7 +3077,6 @@ public function removeOverride($classname)
30383077
$length = $method->getEndLine() - $method->getStartLine() + 1;
30393078

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

30433081
$override_file_orig = $override_file;
30443082

@@ -3121,10 +3159,42 @@ public function removeOverride($classname)
31213159
}
31223160

31233161
$to_delete = preg_match('/<\?(?:php)?\s+(?:abstract|interface)?\s*?class\s+' . $classname . '\s+extends\s+' . $classname . 'Core\s*?[{]\s*?[}]/ism', $code);
3162+
3163+
if (!$to_delete) {
3164+
// To detect if the class has remaining code, we dynamically create a class which contains the remaining code.
3165+
eval(
3166+
preg_replace(
3167+
[
3168+
'#^\s*<\?(?:php)?#',
3169+
'#class\s+' . $classname . '\s+extends\s+([a-z0-9_]+)(\s+implements\s+([a-z0-9_]+))?#i',
3170+
],
3171+
[
3172+
' ',
3173+
'class ' . $classname . 'OverrideOriginal_check' . $uniq . ' extends \stdClass',
3174+
],
3175+
$code
3176+
)
3177+
);
3178+
3179+
// Then we use ReflectionClass to analyze what this code actually contains
3180+
$override_class = new ReflectionClass($classname . 'OverrideOriginal_check' . $uniq);
3181+
3182+
// If no valuable code remains then we can delete it
3183+
$to_delete = $override_class->getConstants() === []
3184+
&& $override_class->getProperties() === []
3185+
&& $override_class->getMethods() === [];
3186+
}
31243187
}
31253188

31263189
if (!isset($to_delete) || $to_delete) {
3190+
// Remove file
31273191
unlink($override_path);
3192+
3193+
// Remove directory
3194+
$this->removeOverrideDirectory(
3195+
_PS_ROOT_DIR_ . DIRECTORY_SEPARATOR . 'override',
3196+
dirname($override_path)
3197+
);
31283198
} else {
31293199
file_put_contents($override_path, $code);
31303200
}
@@ -3135,6 +3205,45 @@ public function removeOverride($classname)
31353205
return true;
31363206
}
31373207

3208+
/**
3209+
* Remove override directory tree if the tree is empty
3210+
*
3211+
* @param string $directoryOverride
3212+
* @param string $directoryPath
3213+
*
3214+
* @return void
3215+
*/
3216+
private function removeOverrideDirectory(string $directoryOverride, string $directoryPath): void
3217+
{
3218+
if (!is_dir($directoryPath)) {
3219+
return;
3220+
}
3221+
3222+
$fs = new SfFileSystem();
3223+
3224+
$splDir = new SplFileInfo($directoryPath);
3225+
do {
3226+
// Check if there is only index.php in directory
3227+
$finder = new Finder();
3228+
$finder
3229+
->files()
3230+
->in($splDir->getPathname())
3231+
->notName('index.php');
3232+
if ($finder->hasResults()) {
3233+
break;
3234+
}
3235+
3236+
// Remove index.php
3237+
$fs->remove($splDir->getPathname() . DIRECTORY_SEPARATOR . 'index.php');
3238+
3239+
// Remove directory
3240+
$fs->remove($splDir->getPathname());
3241+
3242+
// Get Parent directory
3243+
$splDir = $splDir->getPathInfo();
3244+
} while ($splDir->getPathname() !== $directoryOverride);
3245+
}
3246+
31383247
private function getWidgetHooks()
31393248
{
31403249
$hooks = array_values(Hook::getHooks(false, true));

override/classes/Smarty/index.php

-35
This file was deleted.

override/classes/assets/index.php

-35
This file was deleted.

override/classes/cache/index.php

-35
This file was deleted.

override/classes/checkout/index.php

-35
This file was deleted.

0 commit comments

Comments
 (0)