Passed
Pull Request — master (#20)
by Jitendra
02:01
created

TwigGenerator   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 66
dl 0
loc 150
rs 10
c 0
b 0
f 0
wmc 21

7 Methods

Rating   Name   Duplication   Size   Complexity  
A initTwig() 0 19 2
A generate() 0 10 4
A shouldGenerate() 0 13 3
A __construct() 0 6 1
A generateTests() 0 22 4
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
108
    protected function findTemplates(string $templatePath)
109
    {
110
        $templates = [];
111
        $finder    = new Finder;
112
113
        $finder->files()->ignoreDotFiles(false)->filter(function ($file) {
114
            return \substr($file, -5) === '.twig';
115
        });
116
117
        foreach ($finder->in($templatePath) as $file) {
118
            $templates[] = (string) $file;
119
        }
120
121
        return $templates;
122
    }
123
124
    protected function doGenerate(string $template, string $targetPath, array $parameters, CollisionHandlerInterface $handler = null)
125
    {
126
        $relativePath = $this->pathUtil->getRelativePath($template, $this->templatePath);
127
        $targetFile   = $targetPath . '/' . \str_replace('.twig', '', $relativePath);
128
        $fileExists   = \is_file($targetFile);
129
        $targetDir    = \dirname($targetFile);
0 ignored issues
show
Unused Code introduced by
The assignment to $targetDir is dead and can be removed.
Loading history...
130
        $content      = $this->twig->render($relativePath, $parameters);
131
132
        if ($handler && $fileExists) {
133
            $handler->handle($targetFile, $content, $parameters);
134
135
            return;
136
        }
137
138
        // If using reference package then we dont overwrite!
139
        if (isset($parameters['using']) && $fileExists) {
140
            return;
141
        }
142
143
        $this->pathUtil->writeFile($targetFile, $content);
144
    }
145
146
    protected function shouldGenerate(string $template, array $parameters)
147
    {
148
        $name = \basename($template, '.twig');
149
150
        if (isset($this->projectTemplates[$name])) {
151
            return $parameters['type'] === 'project';
152
        }
153
154
        if (isset($this->commandTemplates[$name])) {
155
            return false;
156
        }
157
158
        return true;
159
    }
160
}
161