Generator::prepareFolder()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 1
1
<?php
2
3
/**
4
 * @package Skeleton module
5
 * @author Iurii Makukh <[email protected]>
6
 * @copyright Copyright (c) 2015, Iurii Makukh
7
 * @license https://www.gnu.org/licenses/gpl.html GNU/GPLv3
8
 */
9
10
namespace gplcart\modules\skeleton\models;
11
12
use gplcart\core\helpers\Zip;
13
use gplcart\core\Module;
14
15
/**
16
 * Methods to generate module skeletons
17
 */
18
class Generator
19
{
20
21
    /**
22
     * Module class instance
23
     * @var \gplcart\core\Module $module
24
     */
25
    protected $module;
26
27
    /**
28
     * Zip class instance
29
     * @var \gplcart\core\helpers\Zip $zip
30
     */
31
    protected $zip;
32
33
    /**
34
     * Full path to a ZIP file containing generated module
35
     * @var string
36
     */
37
    protected $file;
38
39
    /**
40
     * The current module directory
41
     * @var string
42
     */
43
    protected $directory;
44
45
    /**
46
     * An array of module data
47
     * @var array
48
     */
49
    protected $data = array();
50
51
    /**
52
     * Generator constructor.
53
     * @param Module $module
54
     * @param Zip $zip
55
     */
56
    public function __construct(Module $module, Zip $zip)
57
    {
58
        $this->zip = $zip;
59
        $this->module = $module;
60
    }
61
62
    /**
63
     * Returns an array of licenses and their URLs
64
     * @return array
65
     */
66
    public function getLicenses()
67
    {
68
        return array(
69
            'GPL-3.0-or-later' => 'https://www.gnu.org/licenses/gpl-3.0.en.html',
70
            'MIT' => 'https://opensource.org/licenses/MIT',
71
            'Apache-2.0' => 'https://www.apache.org/licenses/LICENSE-2.0',
72
            'BSD-3-Clause' => 'https://opensource.org/licenses/BSD-3-Clause'
73
        );
74
    }
75
76
    /**
77
     * Generates module files and folders
78
     * @param array $data
79
     * @return bool
80
     */
81
    public function generate(array $data)
82
    {
83
        $this->setData($data);
84
85
        $this->createMainClass();
86
        $this->createManifest();
87
        $this->createStructure();
88
89
        return $this->createZip();
90
    }
91
92
    /**
93
     * Create module manifest file
94
     */
95
    protected function createManifest()
96
    {
97
        $data = array(
98
            'name' => $this->data['module']['name'],
99
            'core' => $this->data['module']['core'],
100
            'author' => $this->data['module']['author'],
101
            'license' => $this->data['module']['license'],
102
            'version' => $this->data['module']['version'],
103
            'description' => $this->data['module']['description']
104
        );
105
106
        if (!empty($this->data['structure']) && in_array('configurable', $this->data['structure'])) {
107
            $data['configure'] = 'admin/module/settings/' . $this->data['module']['id'];
108
            $data['settings'] = array();
109
        }
110
111
        $json = json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
112
        file_put_contents("$this->directory/module.json", $json);
113
    }
114
115
    /**
116
     * Creates various structure elements
117
     */
118
    protected function createStructure()
119
    {
120
        $this->write("$this->directory/README.md", 'readme');
121
        $this->write("$this->directory/.gitignore", 'gitignore');
122
        $this->write("$this->directory/composer.json", 'composer');
123
        $this->write("$this->directory/.scrutinizer.yml", 'scrutinizer');
124
125
        if (empty($this->data['structure'])) {
126
            return null;
127
        }
128
129
        foreach ($this->data['structure'] as $element) {
130
            switch ($element) {
131
                case 'controller':
132
                    $this->createStructureController();
133
                    break;
134
                case 'model':
135
                    $this->createStructureModel();
136
                    break;
137
                case 'helper':
138
                    $this->createStructureHelper();
139
                    break;
140
                case 'handler':
141
                    $this->createStructureHandler();
142
                    break;
143
                case 'override':
144
                    $this->createStructureOverride();
145
                    break;
146
                case 'template':
147
                    $this->createStructureTemplate();
148
                    break;
149
                case 'asset':
150
                    $this->createStructureAsset();
151
                    break;
152
                case 'locale':
153
                    $this->createStructureTranslation();
154
                    break;
155
                case 'tests':
156
                    $this->createStructureTests();
157
                    break;
158
                case 'config_files':
159
                    $this->createStructureConfigFiles();
160
                    break;
161
            }
162
        }
163
    }
164
165
    /**
166
     * Creates asset structure
167
     */
168
    protected function createStructureAsset()
169
    {
170
        foreach (array('css', 'js') as $folder) {
171
            if ($this->prepareFolder("$this->directory/$folder")) {
172
                $this->write("$this->directory/$folder/common.$folder", $folder);
173
            }
174
        }
175
176
        $this->generateImage();
177
    }
178
179
    /**
180
     * Generate an image sample
181
     * @return bool
182
     */
183
    protected function generateImage()
184
    {
185
        $directory = "$this->directory/image";
186
187
        if (!mkdir($directory, 0775, true)) {
188
            return false;
189
        }
190
191
        $im = imagecreate(100, 100);
192
        imagecolorallocate($im, 255, 255, 255);
193
        $text = imagecolorallocate($im, 0, 0, 255);
194
        imagestring($im, 5, 0, 0, $this->data['module']['name'], $text);
195
        $result = imagepng($im, "$directory/image.png");
196
        imagedestroy($im);
197
        return $result;
198
    }
199
200
    /**
201
     * Creates translations structure
202
     */
203
    protected function createStructureTranslation()
204
    {
205
        $folder = "$this->directory/translations";
206
207
        if ($this->prepareFolder($folder)) {
208
            $name = $this->data['module']['name'];
209
            gplcart_file_csv("$folder/en.csv", array($name, $name));
210
        }
211
    }
212
213
    /**
214
     * Creates a controller class
215
     */
216
    protected function createStructureController()
217
    {
218
        $folder = "$this->directory/controllers";
219
220
        if ($this->prepareFolder($folder)) {
221
            $this->write("$folder/Settings.php", 'controller');
222
        }
223
    }
224
225
    /**
226
     * Creates module main class
227
     */
228
    protected function createMainClass()
229
    {
230
        if ($this->prepareFolder($this->directory)) {
231
            $this->write("$this->directory/{$this->data['module']['class_name']}.php", 'main');
232
        }
233
    }
234
235
    /**
236
     * Creates a model class
237
     */
238
    protected function createStructureModel()
239
    {
240
        $folder = "$this->directory/models";
241
242
        if ($this->prepareFolder($folder)) {
243
            $this->write("$folder/{$this->data['module']['class_name']}.php", 'model');
244
        }
245
    }
246
247
    /**
248
     * Creates a helper class
249
     */
250
    protected function createStructureHelper()
251
    {
252
        $folder = "$this->directory/helpers";
253
254
        if ($this->prepareFolder($folder)) {
255
            $this->write("$folder/{$this->data['module']['class_name']}.php", 'helper');
256
        }
257
    }
258
259
    /**
260
     * Creates a handler class
261
     */
262
    protected function createStructureHandler()
263
    {
264
        $folder = "$this->directory/handlers";
265
266
        if ($this->prepareFolder($folder)) {
267
            $this->write("$folder/{$this->data['module']['class_name']}.php", 'handler');
268
        }
269
    }
270
271
    /**
272
     * Creates module overrides
273
     */
274
    protected function createStructureOverride()
275
    {
276
        $folder = "$this->directory/override/classes/modules/{$this->data['module']['id']}";
277
278
        if ($this->prepareFolder($folder)) {
279
            $this->write("$folder/{$this->data['module']['class_name']}Override.php", 'override');
280
        }
281
    }
282
283
    /**
284
     * Creates a template sample
285
     */
286
    protected function createStructureTemplate()
287
    {
288
        $folder = "$this->directory/templates";
289
290
        if ($this->prepareFolder($folder)) {
291
            $this->write("$folder/settings.php", 'template');
292
        }
293
    }
294
295
    /**
296
     * Creates files for unit testing
297
     */
298
    protected function createStructureTests()
299
    {
300
        $dir = "$this->directory/tests";
301
302
        if ($this->prepareFolder($dir)) {
303
            $this->prepareFolder("$dir/support");
304
            $this->write("$this->directory/phpunit.xml", 'test_xml');
305
            $this->write("$dir/support/bootstrap.php", 'test_bootstrap');
306
            $this->write("$dir/{$this->data['module']['class_name']}.php", 'test');
307
        }
308
    }
309
310
    /**
311
     * Creates config files structure
312
     */
313
    protected function createStructureConfigFiles()
314
    {
315
        $dir = "$this->directory/config";
316
317
        if ($this->prepareFolder($dir)) {
318
            $this->write("$dir/common.php", 'config');
319
        }
320
    }
321
322
    /**
323
     * Pack module folder into zip file
324
     * @return bool
325
     */
326
    protected function createZip()
327
    {
328
        $this->file = "$this->directory.zip";
329
330
        if (is_file($this->file)) {
331
            unlink($this->file);
332
        }
333
334
        $result = $this->zip->directory($this->directory, $this->file, $this->data['module']['id']);
335
        gplcart_file_delete_recursive($this->directory);
336
        return $result;
337
    }
338
339
    /**
340
     * Returns a path to zip file
341
     * @return string
342
     */
343
    public function getZip()
344
    {
345
        return $this->file;
346
    }
347
348
    /**
349
     * Recursively creates folders
350
     * @param string $folder
351
     * @return bool
352
     */
353
    protected function prepareFolder($folder)
354
    {
355
        return !file_exists($folder) && mkdir($folder, 0775, true);
356
    }
357
358
    /**
359
     * Prepares an array of data before rendering
360
     * @param array $data
361
     * @return array
362
     */
363
    protected function setData(array &$data)
364
    {
365
        $licenses = $this->getLicenses();
366
        $class = $this->module->getClass($data['module']['id']);
367
368
        $data['module']['namespace'] = $class;
369
        $data['module']['class_name'] = substr($class, strrpos($class, '\\') + 1);
370
        $data['module']['license_url'] = $licenses[$data['module']['license']] . ' ' . $data['module']['license'];
371
372
        $this->directory = gplcart_file_private_module('skeleton', $data['module']['id'], true);
373
        return $this->data = $data;
374
    }
375
376
    /**
377
     * Renders a template
378
     * @param string $template
379
     * @return string|null
380
     */
381
    protected function render($template)
382
    {
383
        $file = GC_DIR_MODULE . "/skeleton/templates/code/$template.php";
384
385
        if (!is_file($file)) {
386
            return null;
387
        }
388
389
        extract($this->data, EXTR_SKIP);
390
        ob_start();
391
        include $file;
392
        return ob_get_clean();
393
    }
394
395
    /**
396
     * Writes to a file using a template as an source
397
     * @param string $file
398
     * @param string $template
399
     * @return null|bool
400
     */
401
    protected function write($file, $template)
402
    {
403
        $content = $this->render($template);
404
405
        if (!isset($content)) {
406
            return null;
407
        }
408
409
        if (pathinfo($file, PATHINFO_EXTENSION) === 'php') {
410
            $content = "<?php\n\n$content";
411
        }
412
413
        return file_put_contents($file, $content) !== false;
414
    }
415
416
}
417