Passed
Push — master ( de68c3...70f98a )
by Fran
03:25
created

GeneratorService::generateBaseApiTemplate()   C

Complexity

Conditions 7
Paths 4

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 16
nc 4
nop 4
dl 0
loc 22
rs 6.9811
c 0
b 0
f 0
1
<?php
2
namespace PSFS\Services;
3
4
use PSFS\base\Cache;
5
use PSFS\base\config\Config;
6
use PSFS\base\exception\ConfigException;
7
use PSFS\base\Service;
8
9
class GeneratorService extends Service
10
{
11
    /**
12
     * @Inyectable
13
     * @var \PSFS\base\config\Config Servicio de configuración
14
     */
15
    protected $config;
16
    /**
17
     * @Inyectable
18
     * @var \PSFS\base\Security Servicio de autenticación
19
     */
20
    protected $security;
21
    /**
22
     * @Inyectable
23
     * @var \PSFS\base\Template Servicio de gestión de plantillas
24
     */
25
    protected $tpl;
26
27
    /**
28
     * Método que revisa las traducciones directorio a directorio
29
     * @param $path
30
     * @param $locale
31
     * @return array
32
     */
33
    public static function findTranslations($path, $locale)
34
    {
35
        $locale_path = realpath(BASE_DIR . DIRECTORY_SEPARATOR . 'locale');
36
        $locale_path .= DIRECTORY_SEPARATOR . $locale . DIRECTORY_SEPARATOR . 'LC_MESSAGES' . DIRECTORY_SEPARATOR;
37
38
        $translations = array();
39
        if (file_exists($path)) {
40
            $d = dir($path);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $d. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
41
            while (false !== ($dir = $d->read())) {
42
                Config::createDir($locale_path);
43
                if (!file_exists($locale_path . 'translations.po')) {
44
                    file_put_contents($locale_path . 'translations.po', '');
45
                }
46
                $inspect_path = realpath($path . DIRECTORY_SEPARATOR . $dir);
47
                $cmd_php = "export PATH=\$PATH:/opt/local/bin; xgettext " .
48
                    $inspect_path . DIRECTORY_SEPARATOR .
49
                    "*.php --from-code=UTF-8 -j -L PHP --debug --force-po -o {$locale_path}translations.po";
50
                if (is_dir($path . DIRECTORY_SEPARATOR . $dir) && preg_match('/^\./', $dir) == 0) {
51
                    $res = _('Revisando directorio: ') . $inspect_path;
52
                    $res .= _('Comando ejecutado: ') . $cmd_php;
53
                    $res .= shell_exec($cmd_php);
54
                    usleep(10);
55
                    $translations[] = $res;
56
                    $translations = array_merge($translations, self::findTranslations($inspect_path, $locale));
57
                }
58
            }
59
        }
60
        return $translations;
61
    }
62
63
    /**
64
     * Servicio que genera la estructura de un módulo o lo actualiza en caso de ser necesario
65
     * @param string $module
66
     * @param boolean $force
67
     * @param string $type
68
     * @param boolean $isModule
69
     * @return mixed
70
     */
71
    public function createStructureModule($module, $force = false, $type = "", $isModule = false)
72
    {
73
        $mod_path = CORE_DIR . DIRECTORY_SEPARATOR;
74
        $module = ucfirst($module);
75
        $this->createModulePath($module, $mod_path, $isModule);
76
        $this->createModulePathTree($module, $mod_path, $isModule);
77
        $this->createModuleBaseFiles($module, $mod_path, $force, $type, $isModule);
78
        $this->createModuleModels($module, $mod_path, $isModule);
79
        $this->generateBaseApiTemplate($module, $mod_path, $force, $isModule);
80
        //Redireccionamos al home definido
81
        $this->log->infoLog("Módulo generado correctamente");
82
    }
83
84
    /**
85
     * Service that creates the root paths for the modules
86
     * @param string $module
87
     * @param string $mod_path
88
     * @param boolean $isModule
89
     */
90
    private function createModulePath($module, $mod_path, $isModule = false)
91
    {
92
        // Creates the src folder
93
        Config::createDir($mod_path);
94
        // Create module path
95
        if (false === $isModule) {
96
            Config::createDir($mod_path . $module);
97
        }
98
    }
99
100
    /**
101
     * Servicio que genera la estructura base
102
     * @param $module
103
     * @param $mod_path
104
     * @param boolean $isModule
105
     */
106
    private function createModulePathTree($module, $mod_path, $isModule = false)
107
    {
108
        //Creamos las carpetas CORE del módulo
109
        $this->log->infoLog("Generamos la estructura");
110
        $paths = [
111
            "Api", "Api/base", "Config", "Controller", "Form", "Models", "Public", "Templates", "Services", "Test"
112
        ];
113
        $module_path = $isModule ? $mod_path : $mod_path . $module;
114
        foreach ($paths as $path) {
115
            Config::createDir($module_path . DIRECTORY_SEPARATOR . $path);
116
        }
117
        //Creamos las carpetas de los assets
118
        $htmlPaths = array("css", "js", "img", "media", "font");
119
        foreach ($htmlPaths as $path) {
120
            Config::createDir($module_path . DIRECTORY_SEPARATOR . "Public" . DIRECTORY_SEPARATOR . $path);
121
        }
122
123
        if ($isModule) {
124
            return $this->writeTemplateToFile(json_encode([
125
                "module" => "\\" . preg_replace('/(\\\|\/)/', '\\\\', $module),
126
            ], JSON_PRETTY_PRINT), $mod_path . DIRECTORY_SEPARATOR . "module.json", true);
127
        }
128
    }
129
130
    /**
131
     * Servicio que genera las plantillas básicas de ficheros del módulo
132
     * @param string $module
133
     * @param string $mod_path
134
     * @param boolean $force
135
     * @param string $controllerType
136
     * @param boolean $isModule
137
     */
138
    private function createModuleBaseFiles($module, $mod_path, $force = false, $controllerType = '', $isModule = false)
139
    {
140
        $module_path = $isModule ? $mod_path : $mod_path . $module;
141
        $this->generateControllerTemplate($module, $module_path, $force, $controllerType);
142
        $this->generateServiceTemplate($module, $module_path, $force);
143
        $this->genereateAutoloaderTemplate($module, $module_path, $force, $isModule);
144
        $this->generateSchemaTemplate($module, $module_path, $force);
145
        $this->generatePropertiesTemplate($module, $module_path, $force);
146
        $this->generateConfigTemplate($module_path, $force);
147
        $this->generateIndexTemplate($module, $module_path, $force);
148
        $this->generatePublicTemplates($module_path, $force);
149
    }
150
151
    /**
152
     * Servicio que ejecuta Propel y genera el modelo de datos
153
     * @param string $module
154
     * @param string $path
155
     * @param boolean $isModule
156
     */
157
    private function createModuleModels($module, $path, $isModule = false)
158
    {
159
        $module_path = $isModule ? $path : $path . $module;
160
        $module_path = str_replace(CORE_DIR . DIRECTORY_SEPARATOR, '', $module_path);
161
        //Generamos las clases de propel y la configuración
162
        $exec = "export PATH=\$PATH:/opt/local/bin; " . BASE_DIR . DIRECTORY_SEPARATOR .
163
            "vendor" . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "propel ";
164
        $schemaOpt = " --schema-dir=" . CORE_DIR . DIRECTORY_SEPARATOR . $module_path .
165
            DIRECTORY_SEPARATOR . "Config";
166
        $opt = " --config-dir=" . CORE_DIR . DIRECTORY_SEPARATOR . $module_path . DIRECTORY_SEPARATOR .
167
            "Config --output-dir=" . CORE_DIR . " --verbose";
168
        $this->log->infoLog("[GENERATOR] Ejecutamos propel:\n" . $exec . "build" . $opt . $schemaOpt);
169
        $ret = shell_exec($exec . "build" . $opt . $schemaOpt);
170
171
        $this->log->infoLog("[GENERATOR] Generamos clases invocando a propel:\n $ret");
172
        $ret = shell_exec($exec . "sql:build" . $opt . " --output-dir=" . CORE_DIR . DIRECTORY_SEPARATOR .
173
            $module_path . DIRECTORY_SEPARATOR . "Config" . $schemaOpt);
174
        $this->log->infoLog("[GENERATOR] Generamos sql invocando a propel:\n $ret");
175
        $ret = shell_exec($exec . "config:convert" . $opt . " --output-dir=" . CORE_DIR . DIRECTORY_SEPARATOR .
176
            $module_path . DIRECTORY_SEPARATOR . "Config");
177
        $this->log->infoLog("[GENERATOR] Generamos configuración invocando a propel:\n $ret");
178
    }
179
180
    /**
181
     * @param string $module
182
     * @param string $mod_path
183
     * @param boolean $force
184
     * @param string $controllerType
185
     * @return boolean
186
     */
187
    private function generateControllerTemplate($module, $mod_path, $force = false, $controllerType = "")
188
    {
189
        //Generamos el controlador base
190
        $this->log->infoLog("Generamos el controlador BASE");
191
        $class = preg_replace('/(\\\|\/)/', '', $module);
192
        $controllerBody = $this->tpl->dump("generator/controller.template.twig", array(
193
            "module" => $module,
194
            "namespace" => preg_replace('/(\\\|\/)/', '\\', $module),
195
            "url" => preg_replace('/(\\\|\/)/', '/', $module),
196
            "class" => $class,
197
            "controllerType" => $class . "Base",
198
            "is_base" => false
199
        ));
200
        $controller = $this->writeTemplateToFile($controllerBody, $mod_path . DIRECTORY_SEPARATOR . "Controller" .
201
            DIRECTORY_SEPARATOR . "{$class}Controller.php", $force);
202
203
        $controllerBody = $this->tpl->dump("generator/controller.template.twig", array(
204
            "module" => $module,
205
            "namespace" => preg_replace('/(\\\|\/)/', '\\', $module),
206
            "url" => preg_replace('/(\\\|\/)/', '/', $module),
207
            "class" => $class . "Base",
208
            "service" => $class,
209
            "controllerType" => $controllerType,
210
            "is_base" => true
211
        ));
212
        $controllerBase = $this->writeTemplateToFile($controllerBody, $mod_path . DIRECTORY_SEPARATOR . "Controller" .
213
            DIRECTORY_SEPARATOR . "base" . DIRECTORY_SEPARATOR . "{$class}BaseController.php", true);
214
        return ($controller && $controllerBase);
215
    }
216
217
    /**
218
     * @param string $module
219
     * @param string $mod_path
220
     * @param boolean $force
221
     * @param boolean $isModule
222
     * @return boolean
223
     */
224
    private function generateBaseApiTemplate($module, $mod_path, $force = false, $isModule = false)
225
    {
226
        $created = true;
227
        $modelPath = $isModule ?
228
            $mod_path . DIRECTORY_SEPARATOR . 'Models' :
229
            $mod_path . $module . DIRECTORY_SEPARATOR . 'Models';
230
        if (file_exists($modelPath)) {
231
            $dir = dir($modelPath);
232
            while ($file = $dir->read()) {
233
                if (!in_array($file, array('.', '..'))
234
                    && !preg_match('/Query\.php$/i', $file)
235
                    && preg_match('/\.php$/i', $file)
236
                ) {
237
                    $filename = str_replace(".php", "", $file);
238
                    $this->log->infoLog("Generamos Api BASES para {$filename}");
239
                    $this->createApiBaseFile($module, $mod_path, $filename);
240
                    $this->createApi($module, $mod_path, $force, $filename);
241
                }
242
            }
243
        }
244
        return $created;
245
    }
246
247
    /**
248
     * @param string $mod_path
249
     * @param boolean $force
250
     * @return boolean
251
     */
252
    private function generateConfigTemplate($mod_path, $force = false)
253
    {
254
        //Generamos el fichero de configuración
255
        $this->log->infoLog("Generamos fichero vacío de configuración");
256
        return $this->writeTemplateToFile("<?php\n\t",
257
            $mod_path . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . "config.php",
258
            $force);
259
    }
260
261
    /**
262
     * @param string $mod_path
263
     * @param string $mod_path
264
     * @param boolean $force
265
     * @return boolean
266
     */
267
    private function generatePublicTemplates($mod_path, $force = false)
268
    {
269
        //Generamos el fichero de configuración
270
        $this->log->infoLog("Generamos ficheros para assets base");
271
        $css = $this->writeTemplateToFile("/* CSS3 STYLES */\n\n",
272
            $mod_path . DIRECTORY_SEPARATOR . "Public" . DIRECTORY_SEPARATOR . "css" . DIRECTORY_SEPARATOR . "styles.css",
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 122 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
273
            $force);
274
        $js = $this->writeTemplateToFile("/* APP MODULE JS */\n\n(function() {\n\t'use strict';\n})();",
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $js. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
275
            $mod_path . DIRECTORY_SEPARATOR . "Public" . DIRECTORY_SEPARATOR . "js" . DIRECTORY_SEPARATOR . "app.js",
276
            $force);
277
        return ($css && $js);
278
    }
279
280
    /**
281
     * @param string $module
282
     * @param string $mod_path
283
     * @param boolean $force
284
     * @return boolean
285
     */
286
    private function generateServiceTemplate($module, $mod_path, $force = false)
287
    {
288
        //Generamos el controlador base
289
        $this->log->infoLog("Generamos el servicio BASE");
290
        $class = preg_replace('/(\\\|\/)/', '', $module);
291
        $controller = $this->tpl->dump("generator/service.template.twig", array(
292
            "module" => $module,
293
            "namespace" => preg_replace('/(\\\|\/)/', '\\', $module),
294
            "class" => $class,
295
        ));
296
        return $this->writeTemplateToFile($controller,
297
            $mod_path . DIRECTORY_SEPARATOR . "Services" . DIRECTORY_SEPARATOR . "{$class}Service.php",
298
            $force);
299
    }
300
301
    /**
302
     * @param string $module
303
     * @param string $mod_path
304
     * @param boolean $force
305
     * @param boolean $isModule
306
     * @return boolean
307
     */
308
    private function genereateAutoloaderTemplate($module, $mod_path, $force = false, $isModule = false)
309
    {
310
        //Generamos el autoloader del módulo
311
        $this->log->infoLog("Generamos el autoloader");
312
        $autoloader = $this->tpl->dump("generator/autoloader.template.twig", array(
313
            "module" => $module,
314
            "autoloader" => preg_replace('/(\\\|\/)/', '_', $module),
315
            "regex" => preg_replace('/(\\\|\/)/m', '\\\\\\\\\\\\', $module),
316
            "is_module" => $isModule,
317
        ));
318
        return $this->writeTemplateToFile($autoloader, $mod_path . DIRECTORY_SEPARATOR . "autoload.php", $force);
319
    }
320
321
    /**
322
     * @param string $module
323
     * @param string $mod_path
324
     * @param boolean $force
325
     * @return boolean
326
     */
327
    private function generateSchemaTemplate($module, $mod_path, $force = false)
328
    {
329
        //Generamos el autoloader del módulo
330
        $this->log->infoLog("Generamos el schema");
331
        $schema = $this->tpl->dump("generator/schema.propel.twig", array(
332
            "module" => $module,
333
            "namespace" => preg_replace('/(\\\|\/)/', '\\', $module),
334
            "prefix" => preg_replace('/(\\\|\/)/', '', $module),
335
            "db" => $this->config->get("db_name"),
336
        ));
337
        return $this->writeTemplateToFile($schema,
338
            $mod_path . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . "schema.xml",
339
            $force);
340
    }
341
342
    /**
343
     * @param string $module
344
     * @param string $mod_path
345
     * @param boolean $force
346
     * @return boolean
347
     */
348
    private function generatePropertiesTemplate($module, $mod_path, $force = false)
349
    {
350
        $this->log->infoLog("Generamos la configuración de Propel");
351
        $build_properties = $this->tpl->dump("generator/build.properties.twig", array(
352
            "module" => $module,
353
            "host" => $this->config->get("db_host"),
354
            "port" => $this->config->get("db_port"),
355
            "user" => $this->config->get("db_user"),
356
            "pass" => $this->config->get("db_password"),
357
            "db" => $this->config->get("db_name"),
358
            "namespace" => preg_replace('/(\\\|\/)/', '', $module),
359
        ));
360
        return $this->writeTemplateToFile($build_properties,
361
            $mod_path . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . "propel.yml",
362
            $force);
363
    }
364
365
    /**
366
     * @param string $module
367
     * @param string $mod_path
368
     * @param boolean $force
369
     * @return boolean
370
     */
371
    private function generateIndexTemplate($module, $mod_path, $force = false)
372
    {
373
        //Generamos la plantilla de index
374
        $this->log->infoLog("Generamos una plantilla base por defecto");
375
        $index = $this->tpl->dump("generator/index.template.twig", array(
376
            "module" => $module,
377
        ));
378
        return $this->writeTemplateToFile($index,
379
            $mod_path . DIRECTORY_SEPARATOR . "Templates" . DIRECTORY_SEPARATOR . "index.html.twig",
380
            $force);
381
    }
382
383
    /**
384
     * Método que graba el contenido de una plantilla en un fichero
385
     * @param string $fileContent
386
     * @param string $filename
387
     * @param boolean $force
388
     * @return boolean
389
     */
390
    private function writeTemplateToFile($fileContent, $filename, $force = false)
391
    {
392
        $created = false;
393
        if ($force || !file_exists($filename)) {
394
            try {
395
                $this->cache->storeData($filename, $fileContent, Cache::TEXT, true);
396
                $created = true;
397
            } catch (\Exception $e) {
398
                $this->log->errorLog($e->getMessage());
399
            }
400
        } else {
401
            $this->log->errorLog($filename . _(' not exists or cant write'));
402
        }
403
        return $created;
404
    }
405
406
    /**
407
     * Create ApiBase
408
     * @param string $module
409
     * @param string $mod_path
410
     * @param string $api
411
     *
412
     * @return bool
413
     */
414
    private function createApiBaseFile($module, $mod_path, $api)
415
    {
416
        $class = preg_replace('/(\\\|\/)/', '', $module);
417
        $controller = $this->tpl->dump("generator/api.base.template.twig", array(
418
            "module" => $module,
419
            "api" => $api,
420
            "namespace" => preg_replace('/(\\\|\/)/', '\\', $module),
421
            "url" => preg_replace('/(\\\|\/)/', '/', $module),
422
            "class" => $class,
423
        ));
424
425
        return $this->writeTemplateToFile($controller,
426
            $mod_path . DIRECTORY_SEPARATOR . "Api" . DIRECTORY_SEPARATOR . 'base' . DIRECTORY_SEPARATOR . "{$api}BaseApi.php", true);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 134 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
427
    }
428
429
    /**
430
     * Create Api
431
     * @param string $module
432
     * @param string $mod_path
433
     * @param bool $force
434
     * @param string $api
435
     *
436
     * @return bool
437
     */
438
    private function createApi($module, $mod_path, $force, $api)
439
    {
440
        $class = preg_replace('/(\\\|\/)/', '', $module);
441
        $controller = $this->tpl->dump("generator/api.template.twig", array(
442
            "module" => $module,
443
            "api" => $api,
444
            "namespace" => preg_replace('/(\\\|\/)/', '\\', $module),
445
            "url" => preg_replace('/(\\\|\/)/', '/', $module),
446
            "class" => $class,
447
        ));
448
449
        return $this->writeTemplateToFile($controller, $mod_path . DIRECTORY_SEPARATOR . "Api" . DIRECTORY_SEPARATOR . "{$api}.php", $force);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 141 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
450
    }
451
452
    /**
453
     * Method that copy resources recursively
454
     * @param string $dest
455
     * @param boolean $force
456
     * @param $filename_path
457
     * @param boolean $debug
458
     */
459
    public static function copyResources($dest, $force, $filename_path, $debug)
460
    {
461
        if (file_exists($filename_path)) {
462
            $destfolder = basename($filename_path);
463
            if (!file_exists(WEB_DIR . $dest . DIRECTORY_SEPARATOR . $destfolder) || $debug || $force) {
464
                if (is_dir($filename_path)) {
465
                    self::copyr($filename_path, WEB_DIR . $dest . DIRECTORY_SEPARATOR . $destfolder);
466
                } else {
467
                    if (@copy($filename_path, WEB_DIR . $dest . DIRECTORY_SEPARATOR . $destfolder) === FALSE) {
468
                        throw new ConfigException("Can't copy " . $filename_path . " to " . WEB_DIR . $dest . DIRECTORY_SEPARATOR . $destfolder);
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 145 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
469
                    }
470
                }
471
            }
472
        }
473
    }
474
475
    /**
476
     * Method that copy a resource
477
     * @param string $src
478
     * @param string $dst
479
     * @throws ConfigException
480
     */
481
    public static function copyr($src, $dst)
482
    {
483
        $dir = opendir($src);
484
        Config::createDir($dst);
485
        while (false !== ($file = readdir($dir))) {
486
            if (($file != '.') && ($file != '..')) {
487
                if (is_dir($src . '/' . $file)) {
488
                    self::copyr($src . '/' . $file, $dst . '/' . $file);
489
                } elseif (@copy($src . '/' . $file, $dst . '/' . $file) === false) {
490
                    throw new ConfigException("Can't copy " . $src . " to " . $dst);
491
                }
492
            }
493
        }
494
        closedir($dir);
495
    }
496
}
497