Completed
Push — master ( 39c07f...aa04c1 )
by Jitendra
11s
created

TwigGenerator   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 68
dl 0
loc 154
rs 10
c 0
b 0
f 0
wmc 21

7 Methods

Rating   Name   Duplication   Size   Complexity  
A generate() 0 10 4
A __construct() 0 6 1
A generateTests() 0 22 4
A initTwig() 0 23 2
A shouldGenerate() 0 13 3
A doGenerate() 0 20 5
A findTemplates() 0 14 2
1
<?php
2
3
namespace Ahc\Phint\Generator;
4
5
use Ahc\Phint\Util\Inflector;
6
use Ahc\Phint\Util\Path;
7
use Symfony\Component\Finder\Finder;
8
9
class TwigGenerator implements GeneratorInterface
10
{
11
    /** @var \Twig_Environment */
12
    protected $twig;
13
14
    /** @var Path */
15
    protected $pathUtil;
16
17
    /** @var Inflector */
18
    protected $inflector;
19
20
    /** @var string|array */
21
    protected $templatePath;
22
23
    /** @var string */
24
    protected $cachePath;
25
26
    /** @var array Templates required for type 'project' only */
27
    protected $projectTemplates = [
28
        '.env.example' => true,
29
        'package.json' => true,
30
    ];
31
32
    /** @var array Templates only loaded by some specific commands */
33
    protected $commandTemplates = [
34
        'test' => true,
35
    ];
36
37
    public function __construct(string $templatePath, string $cachePath)
38
    {
39
        $this->templatePath = $templatePath;
40
        $this->cachePath    = $cachePath;
41
        $this->pathUtil     = new Path;
42
        $this->inflector    = new Inflector;
43
    }
44
45
    /**
46
     * {@inheritdoc}
47
     */
48
    public function generate(string $targetPath, array $parameters, CollisionHandlerInterface $handler = null)
49
    {
50
        if (!$this->twig) {
51
            $this->initTwig();
52
        }
53
54
        $templates = $this->findTemplates($this->templatePath);
0 ignored issues
show
Bug introduced by
It seems like $this->templatePath can also be of type array; however, parameter $templatePath of Ahc\Phint\Generator\TwigGenerator::findTemplates() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

54
        $templates = $this->findTemplates(/** @scrutinizer ignore-type */ $this->templatePath);
Loading history...
55
        foreach ($templates as $template) {
56
            if ($this->shouldGenerate($template, $parameters)) {
57
                $this->doGenerate($template, $targetPath, $parameters, $handler);
58
            }
59
        }
60
    }
61
62
    public function generateTests(array $testMetadata, array $parameters): int
63
    {
64
        if (!$this->twig) {
65
            $this->initTwig();
66
        }
67
68
        $generated = 0;
69
70
        foreach ($testMetadata as $metadata) {
71
            // Skip existing
72
            if (\is_file($targetFile = $metadata['testPath'])) {
73
                continue;
74
            }
75
76
            $generated++;
77
78
            $content = $this->twig->render('tests/test.twig', $metadata + $parameters);
79
80
            $this->pathUtil->writeFile($targetFile, $content);
81
        }
82
83
        return $generated;
84
    }
85
86
    protected function initTwig()
87
    {
88
        $options = [
89
            'auto_reload' => true,
90
            'cache'       => false,
91
        ];
92
93
        if ($this->cachePath) {
94
            $this->pathUtil->ensureDir($this->cachePath);
95
            $options['cache'] = $this->cachePath;
96
        }
97
98
        $this->twig = new \Twig_Environment(
99
            new \Twig_Loader_Filesystem($this->templatePath),
100
            $options
101
        );
102
103
        $this->twig->addFilter(new \Twig_SimpleFilter('snake', function ($x) {
104
            return $this->inflector->snakeCase($x);
105
        }));
106
107
        $this->twig->addFilter(new \Twig_SimpleFilter('lcfirst', function ($x) {
108
            return \lcfirst($x);
109
        }));
110
    }
111
112
    protected function findTemplates(string $templatePath)
113
    {
114
        $templates = [];
115
        $finder    = new Finder;
116
117
        $finder->files()->ignoreDotFiles(false)->filter(function ($file) {
118
            return \substr($file, -5) === '.twig';
119
        });
120
121
        foreach ($finder->in($templatePath) as $file) {
122
            $templates[] = (string) $file;
123
        }
124
125
        return $templates;
126
    }
127
128
    protected function doGenerate(string $template, string $targetPath, array $parameters, CollisionHandlerInterface $handler = null)
129
    {
130
        $relativePath = $this->pathUtil->getRelativePath($template, $this->templatePath);
131
        $targetFile   = $targetPath . '/' . \str_replace('.twig', '', $relativePath);
132
        $fileExists   = \is_file($targetFile);
133
        $targetDir    = \dirname($targetFile);
0 ignored issues
show
Unused Code introduced by
The assignment to $targetDir is dead and can be removed.
Loading history...
134
        $content      = $this->twig->render($relativePath, $parameters);
135
136
        if ($handler && $fileExists) {
137
            $handler->handle($targetFile, $content, $parameters);
138
139
            return;
140
        }
141
142
        // If using reference package then we dont overwrite!
143
        if (isset($parameters['using']) && $fileExists) {
144
            return;
145
        }
146
147
        $this->pathUtil->writeFile($targetFile, $content);
148
    }
149
150
    protected function shouldGenerate(string $template, array $parameters)
151
    {
152
        $name = \basename($template, '.twig');
153
154
        if (isset($this->projectTemplates[$name])) {
155
            return $parameters['type'] === 'project';
156
        }
157
158
        if (isset($this->commandTemplates[$name])) {
159
            return false;
160
        }
161
162
        return true;
163
    }
164
}
165