Completed
Push — master ( 441dfa...c879e5 )
by Iurii
01:21
created

Generator::createStructureLocale()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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