Completed
Push — master ( f0d869...a40c49 )
by Arman
57s queued 53s
created

ModuleManager::copyAssets()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
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\Libraries\Config\Exceptions\ConfigException;
20
use Quantum\Router\Exceptions\ModuleLoaderException;
21
use Quantum\Di\Exceptions\DiException;
22
use Quantum\Exceptions\BaseException;
23
use Quantum\Environment\Environment;
24
use Quantum\Router\ModuleLoader;
25
use ReflectionException;
26
use Exception;
27
28
class ModuleManager
29
{
30
    /**
31
     * @var mixed
32
     */
33
    protected $fs;
34
35
    /**
36
     * @var bool
37
     */
38
    protected $optionEnabled;
39
40
    /**
41
     * @var string
42
     */
43
    private $moduleName;
44
45
    /**
46
     * @var string
47
     */
48
    private $template;
49
50
    /**
51
     * @var string
52
     */
53
    private $modulePath;
54
55
    /**
56
     * @var string
57
     */
58
    private $assetsPath;
59
60
    /**
61
     * @var string
62
     */
63
    private $templatePath;
64
65
    /**
66
     * @var bool
67
     */
68
    private $withAssets;
69
70
    /**
71
     * @var string
72
     */
73
    private $modulesConfigPath;
74
75
    /**
76
     * @param string $moduleName
77
     * @param string $template
78
     * @param bool $enabled
79
     * @param bool $withAssets
80
     * @throws BaseException
81
     * @throws DiException
82
     * @throws ConfigException
83
     * @throws ReflectionException
84
     */
85
    public function __construct(string $moduleName, string $template, bool $enabled, bool $withAssets = false)
86
    {
87
        $this->fs = FileSystemFactory::get();
88
89
        $this->moduleName = $moduleName;
90
91
        $this->withAssets = $withAssets;
92
        $this->optionEnabled = $enabled;
93
        $this->template = $template;
94
95
        $this->assetsPath = assets_dir() . DS . $moduleName;
96
        $this->modulePath = modules_dir() . DS . $moduleName;
97
        $this->templatePath = __DIR__ . DS . 'Templates' . DS . ucfirst($template);
98
        $this->modulesConfigPath = base_dir() . DS . 'shared' . DS . 'config' . DS . 'modules.php';
99
    }
100
101
    /**
102
     * @return string
103
     */
104
    public function getModuleName(): string
105
    {
106
        return $this->moduleName;
107
    }
108
109
    /**
110
     * @return string
111
     */
112
    public function getBaseNamespace(): string
113
    {
114
        return Environment::getInstance()->getAppEnv() === 'testing'
115
            ? "Quantum\\Tests\\_root\\modules"
116
            : "Modules";
117
    }
118
119
    /**
120
     * @throws ModuleLoaderException
121
     * @throws ExceptionInterface
122
     * @throws Exception
123
     */
124
    public function addModuleConfig()
125
    {
126
        $moduleConfigs = ModuleLoader::getInstance()->getModuleConfigs();
127
128
        foreach ($moduleConfigs as $module => $options) {
129
            if ($module == $this->moduleName || $options['prefix'] == strtolower($this->moduleName)) {
130
                throw new Exception("A module or prefix named '" . $this->moduleName . "' already exists");
131
            }
132
        }
133
134
        $moduleConfigs[$this->moduleName] = $this->getModuleOptions($this->moduleName);
135
136
        $this->updateModuleConfigFile($moduleConfigs);
137
    }
138
139
    /**
140
     * @throws Exception
141
     */
142
    public function writeContents()
143
    {
144
        $this->copyDirectoryWithTemplates("$this->templatePath" . DS . "src", $this->modulePath);
145
146
        if ($this->withAssets) {
147
            $this->copyAssets("$this->templatePath" . DS . "assets", $this->assetsPath);
148
        }
149
    }
150
151
    /**
152
     * @throws Exception
153
     */
154
    private function copyDirectoryWithTemplates(string $src, string $dst)
155
    {
156
        $this->copyDirectory($src, $dst, true);
157
    }
158
159
    /**
160
     * @throws Exception
161
     */
162
    private function copyAssets(string $src, string $dst)
163
    {
164
        $this->copyDirectory($src, $dst, false);
165
    }
166
167
    /**
168
     * @throws Exception
169
     */
170
    private function copyDirectory(string $src, string $dst, bool $processTemplates)
171
    {
172
        if (!$this->fs->isDirectory($src)) {
173
            throw new Exception("Directory '$src' does not exist");
174
        }
175
176
        if (!$this->fs->isDirectory($dst)) {
177
            $this->fs->makeDirectory($dst);
178
        }
179
180
        $dir = $this->fs->listDirectory($src);
181
182
        foreach ($dir as $file) {
183
            $srcPath = $file;
184
            $dstPath = str_replace($src, $dst, $file);
185
186
            if ($this->fs->isDirectory($srcPath)) {
187
                $this->copyDirectory($srcPath, $dstPath, $processTemplates);
188
            } else {
189
                if ($processTemplates) {
190
                    $this->processTemplates($srcPath, $dstPath);
191
                }
192
                else {
193
                    $this->fs->copy($srcPath, $dstPath);
194
                }
195
            }
196
        }
197
    }
198
199
    /**
200
     * @param string $srcPath
201
     * @param string $dstPath
202
     */
203
    private function processTemplates(string $srcPath, string $dstPath){
204
        $dstPath = str_replace('.tpl', '.php', $dstPath);
205
        $content = $this->fs->get($srcPath);
206
        $processedContent = $this->replacePlaceholders($content);
207
        $this->fs->put($dstPath, $processedContent);
208
    }
209
210
    /**
211
     * @param string $content
212
     * @return string
213
     */
214
    private function replacePlaceholders(string $content): string
215
    {
216
        $placeholders = [
217
            '{{MODULE_NAMESPACE}}' => $this->getBaseNamespace() .'\\' . $this->getModuleName(),
218
            '{{MODULE_NAME}}' => $this->getModuleName(),
219
        ];
220
221
        return str_replace(array_keys($placeholders), array_values($placeholders), $content);
222
    }
223
224
    /**
225
     * @param string $module
226
     * @return array
227
     */
228
    private function getModuleOptions(string $module): array
229
    {
230
        return [
231
            'prefix' => $this->template == "DemoWeb" ? "" : strtolower($module),
232
            'enabled' => $this->optionEnabled,
233
        ];
234
    }
235
236
    /**
237
     * @param array $moduleConfigs
238
     * @return void
239
     * @throws ExceptionInterface
240
     */
241
    private function updateModuleConfigFile(array $moduleConfigs): void
242
    {
243
        $this->fs->put(
244
            $this->modulesConfigPath,
245
            "<?php\n\nreturn " . export($moduleConfigs) . ";\n"
246
        );
247
    }
248
}