Passed
Pull Request — master (#194)
by
unknown
03:36
created

ModuleManager::replacePlaceholders()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 8
rs 10
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;
72
73
    /**
74
     * @param string $moduleName
75
     * @param string $template
76
     * @param string $demo
77
     * @param bool $enabled
78
     * @throws BaseException
79
     */
80
    private 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
     * @param string $moduleName
96
     * @param string $template
97
     * @param string $demo
98
     * @param bool $enabled
99
     * @return ModuleManager
100
     * @throws BaseException
101
     */
102
    public static function createInstance(string $moduleName, string $template, string $demo, bool $enabled): ModuleManager
103
    {
104
        if (self::$instance === null) {
105
            self::$instance = new self($moduleName, $template, $demo, $enabled);
106
        }
107
108
        return self::$instance;
109
    }
110
111
    /**
112
     * @return ModuleManager
113
     * @throws Exception
114
     */
115
    public static function getInstance(): ModuleManager
116
    {
117
        if (self::$instance === null) {
118
            throw new Exception("ModuleManager is not instantiated, call `createInstance()` first");
119
        }
120
121
        return self::$instance;
122
    }
123
124
    /**
125
     * @return string
126
     */
127
    public function getModuleName(): string
128
    {
129
        return $this->moduleName;
130
    }
131
132
    /**
133
     * @return string
134
     */
135
    public function getBaseNamespace(): string
136
    {
137
        return Environment::getInstance()->getAppEnv() === 'testing'
138
            ? "Quantum\\Tests\\_root\\modules"
139
            : "Modules";
140
    }
141
142
    /**
143
     * @return void
144
     * @throws Exception
145
     */
146
    public function writeContents()
147
    {
148
        if (!$this->fs->isDirectory(modules_dir())) {
149
            $this->fs->makeDirectory(modules_dir());
150
        }
151
152
        $this->copyDirectoryWithTemplates($this->templatePath, $this->modulePath);
153
    }
154
155
    /**
156
     * @throws ModuleLoaderException
157
     * @throws ExceptionInterface
158
     * @throws Exception
159
     */
160
    public function addModuleConfig()
161
    {
162
        $moduleConfigs = ModuleLoader::getInstance()->getModuleConfigs();
163
164
        foreach ($moduleConfigs as $module => $options) {
165
            if ($module == $this->moduleName || $options['prefix'] == strtolower($this->moduleName)) {
166
                throw new Exception("A module or prefix named '" . $this->moduleName . "' already exists");
167
            }
168
        }
169
170
        $moduleConfigs[$this->moduleName] = $this->getModuleOptions($this->moduleName);
171
172
        $this->updateModuleConfigFile($moduleConfigs);
173
    }
174
175
    /**
176
     * @param string $src
177
     * @param string $dst
178
     * @return void
179
     * @throws Exception
180
     */
181
    private function copyDirectoryWithTemplates(string $src, string $dst)
182
    {
183
        if (!$this->fs->isDirectory($src)) {
184
            throw new Exception("Directory '$src' does not exist");
185
        }
186
187
        if (!$this->fs->isDirectory($dst)) {
188
            $this->fs->makeDirectory($dst);
189
        }
190
191
        $dir = $this->fs->listDirectory($src);
192
193
        foreach ($dir as $file) {
194
            $srcPath = $file;
195
            $dstPath = str_replace($src, $dst, $file);
196
197
            if ($this->fs->isDirectory($srcPath)) {
198
                $this->copyDirectoryWithTemplates($srcPath, $dstPath);
199
            } else {
200
                $content = $this->fs->get($srcPath);
201
                $processedContent = $this->replacePlaceholders($content);
202
                $this->fs->put($dstPath, $processedContent);
203
            }
204
        }
205
    }
206
207
    /**
208
     * @param string $content
209
     * @return string
210
     */
211
    private function replacePlaceholders(string $content): string
212
    {
213
        $placeholders = [
214
            '{{MODULE_NAMESPACE}}' => $this->getBaseNamespace() .'\\' . $this->getModuleName(),
215
            '{{MODULE_NAME}}' => $this->getModuleName(),
216
        ];
217
218
        return str_replace(array_keys($placeholders), array_values($placeholders), $content);
219
    }
220
221
    /**
222
     * @param string $module
223
     * @return array
224
     */
225
    private function getModuleOptions(string $module): array
226
    {
227
        return [
228
            'prefix' => $this->template == "web" && $this->demo == "yes" ? "" : strtolower($module),
229
            'enabled' => $this->optionEnabled,
230
        ];
231
    }
232
233
    /**
234
     * @param array $moduleConfigs
235
     * @return void
236
     * @throws ExceptionInterface
237
     */
238
    private function updateModuleConfigFile(array $moduleConfigs): void
239
    {
240
        $this->fs->put(
241
            $this->modulesConfigPath,
242
            "<?php\n\nreturn " . export($moduleConfigs) . ";\n"
243
        );
244
    }
245
246
    /**
247
     * @param string $template
248
     * @param string $demo
249
     * @return string
250
     */
251
    private function generateTemplatePath(string $template, string $demo): string
252
    {
253
        $type = $demo === 'yes' ? 'Demo' : 'Default';
254
        return __DIR__ . DS . 'Templates' . DS . $type . DS . ucfirst($template);
255
    }
256
}