Completed
Push — master ( b50ff5...3d8326 )
by Arman
19s queued 16s
created

ModuleManager::copyDirectoryWithTemplates()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 5
eloc 15
c 2
b 0
f 0
nc 7
nop 2
dl 0
loc 23
rs 9.4555
1
<?php
2
3
/**
4
 * Quantum PHP Framework
5
 *
6
 * An open source software development framework for PHP
7
 *
8
 * @package Quantum
9
 * @author Arman Ag. <[email protected]>
10
 * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org)
11
 * @link http://quantum.softberg.org/
12
 * @since 2.9.5
13
 */
14
15
namespace Quantum\Libraries\Module;
16
17
use Symfony\Component\VarExporter\Exception\ExceptionInterface;
18
use Quantum\Libraries\Storage\Factories\FileSystemFactory;
19
use Quantum\Router\Exceptions\ModuleLoaderException;
20
use Quantum\Exceptions\BaseException;
21
use Quantum\Environment\Environment;
22
use Quantum\Router\ModuleLoader;
23
use Exception;
24
25
class ModuleManager
26
{
27
28
    /**
29
     * @var mixed
30
     */
31
    protected $fs;
32
33
    /**
34
     * @var bool
35
     */
36
    protected $optionEnabled;
37
38
    /**
39
     * @var string
40
     */
41
    private $moduleName;
42
43
    /**
44
     * @var string
45
     */
46
    private $template;
47
48
    /**
49
     * @var string
50
     */
51
    private $demo;
52
53
    /**
54
     * @var string
55
     */
56
    private $modulePath;
57
58
    /**
59
     * @var string
60
     */
61
    private $templatePath;
62
63
    /**
64
     * @var string
65
     */
66
    private $modulesConfigPath;
67
68
    /**
69
     * @var ModuleManager|null
70
     */
71
    private static $instance = null;
0 ignored issues
show
introduced by
The private property $instance is not used, and could be removed.
Loading history...
72
73
    /**
74
     * @param string $moduleName
75
     * @param string $template
76
     * @param string $demo
77
     * @param bool $enabled
78
     * @throws BaseException
79
     */
80
    public function __construct(string $moduleName, string $template, string $demo, bool $enabled)
81
    {
82
        $this->fs = FileSystemFactory::get();
83
84
        $this->moduleName = $moduleName;
85
        $this->optionEnabled = $enabled;
86
        $this->template = $template;
87
        $this->demo = $demo;
88
89
        $this->modulePath = modules_dir() . DS . $moduleName;
90
        $this->templatePath = $this->generateTemplatePath($template, $demo);
91
        $this->modulesConfigPath = base_dir() . DS . 'shared' . DS . 'config' . DS . 'modules.php';
92
    }
93
94
    /**
95
     * @return string
96
     */
97
    public function getModuleName(): string
98
    {
99
        return $this->moduleName;
100
    }
101
102
    /**
103
     * @return string
104
     */
105
    public function getBaseNamespace(): string
106
    {
107
        return Environment::getInstance()->getAppEnv() === 'testing'
108
            ? "Quantum\\Tests\\_root\\modules"
109
            : "Modules";
110
    }
111
112
    /**
113
     * @return void
114
     * @throws Exception
115
     */
116
    public function writeContents()
117
    {
118
        if (!$this->fs->isDirectory(modules_dir())) {
119
            $this->fs->makeDirectory(modules_dir());
120
        }
121
122
        $this->copyDirectoryWithTemplates($this->templatePath, $this->modulePath);
123
    }
124
125
    /**
126
     * @throws ModuleLoaderException
127
     * @throws ExceptionInterface
128
     * @throws Exception
129
     */
130
    public function addModuleConfig()
131
    {
132
        $moduleConfigs = ModuleLoader::getInstance()->getModuleConfigs();
133
134
        foreach ($moduleConfigs as $module => $options) {
135
            if ($module == $this->moduleName || $options['prefix'] == strtolower($this->moduleName)) {
136
                throw new Exception("A module or prefix named '" . $this->moduleName . "' already exists");
137
            }
138
        }
139
140
        $moduleConfigs[$this->moduleName] = $this->getModuleOptions($this->moduleName);
141
142
        $this->updateModuleConfigFile($moduleConfigs);
143
    }
144
145
    /**
146
     * @param string $src
147
     * @param string $dst
148
     * @return void
149
     * @throws Exception
150
     */
151
    private function copyDirectoryWithTemplates(string $src, string $dst)
152
    {
153
        if (!$this->fs->isDirectory($src)) {
154
            throw new Exception("Directory '$src' does not exist");
155
        }
156
157
        if (!$this->fs->isDirectory($dst)) {
158
            $this->fs->makeDirectory($dst);
159
        }
160
161
        $dir = $this->fs->listDirectory($src);
162
163
        foreach ($dir as $file) {
164
            $srcPath = $file;
165
            $dstPath = str_replace($src, $dst, $file);
166
167
            if ($this->fs->isDirectory($srcPath)) {
168
                $this->copyDirectoryWithTemplates($srcPath, $dstPath);
169
            } else {
170
                $dstPath = str_replace('.tpl', '.php', $dstPath);
171
                $content = $this->fs->get($srcPath);
172
                $processedContent = $this->replacePlaceholders($content);
173
                $this->fs->put($dstPath, $processedContent);
174
            }
175
        }
176
    }
177
178
    /**
179
     * @param string $content
180
     * @return string
181
     */
182
    private function replacePlaceholders(string $content): string
183
    {
184
        $placeholders = [
185
            '{{MODULE_NAMESPACE}}' => $this->getBaseNamespace() .'\\' . $this->getModuleName(),
186
            '{{MODULE_NAME}}' => $this->getModuleName(),
187
        ];
188
189
        return str_replace(array_keys($placeholders), array_values($placeholders), $content);
190
    }
191
192
    /**
193
     * @param string $module
194
     * @return array
195
     */
196
    private function getModuleOptions(string $module): array
197
    {
198
        return [
199
            'prefix' => $this->template == "web" && $this->demo == "yes" ? "" : strtolower($module),
200
            'enabled' => $this->optionEnabled,
201
        ];
202
    }
203
204
    /**
205
     * @param array $moduleConfigs
206
     * @return void
207
     * @throws ExceptionInterface
208
     */
209
    private function updateModuleConfigFile(array $moduleConfigs): void
210
    {
211
        $this->fs->put(
212
            $this->modulesConfigPath,
213
            "<?php\n\nreturn " . export($moduleConfigs) . ";\n"
214
        );
215
    }
216
217
    /**
218
     * @param string $template
219
     * @param string $demo
220
     * @return string
221
     */
222
    private function generateTemplatePath(string $template, string $demo): string
223
    {
224
        $type = $demo === 'yes' ? 'Demo' : 'Default';
225
        return __DIR__ . DS . 'Templates' . DS . $type . DS . ucfirst($template);
226
    }
227
}