SpecificationMethodGenerator::informExampleAdded()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 2
1
<?php
2
3
namespace RMiller\BehatSpec\Extension\ExemplifyExtension\Generator;
4
5
use PhpSpec\CodeGenerator\Generator\Generator;
6
use PhpSpec\Console\ConsoleIO;
7
use PhpSpec\CodeGenerator\TemplateRenderer;
8
use PhpSpec\Util\Filesystem;
9
use PhpSpec\Locator\Resource;
10
use RMiller\Caser\Cased;
11
12
/**
13
 * Generates class methods from a resource
14
 */
15
class SpecificationMethodGenerator implements Generator
16
{
17
    /**
18
     * @var \PhpSpec\Console\IO
19
     */
20
    private $io;
21
22
    /**
23
     * @var \PhpSpec\CodeGenerator\TemplateRenderer
24
     */
25
    private $templates;
26
27
    /**
28
     * @var \PhpSpec\Util\Filesystem
29
     */
30
    private $filesystem;
31
32
    /**
33
     * @param ConsoleIO        $io
34
     * @param TemplateRenderer $templates
35
     * @param Filesystem       $filesystem
36
     */
37
    public function __construct(ConsoleIO $io, TemplateRenderer $templates, Filesystem $filesystem = null)
38
    {
39
        $this->io         = $io;
0 ignored issues
show
Documentation Bug introduced by
It seems like $io of type object<PhpSpec\Console\ConsoleIO> is incompatible with the declared type object<PhpSpec\Console\IO> of property $io.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
40
        $this->templates  = $templates;
41
        $this->filesystem = $filesystem ?: new Filesystem();
42
    }
43
44
    /**
45
     * @param Resource $resource
46
     * @param string            $generation
47
     * @param array             $data
48
     *
49
     * @return bool
50
     */
51
    public function supports(Resource $resource, $generation, array $data)
52
    {
53
        return 'specification_method' === $generation;
54
    }
55
56
    /**
57
     * @param Resource $resource
58
     * @param array             $data
59
     */
60
    public function generate(Resource $resource, array $data = [])
61
    {
62
        $method = Cased::fromCamelCase($data['method']);
63
        $spec = $this->filesystem->getFileContents($resource->getSpecFilename());
64
65
        if ($this->exampleAlreadyExists($spec, $method)) {
66
            $this->informExampleAlreadyExists($resource, $method);
67
68
            return;
69
        }
70
71
        $this->addExampleToSpec($resource, $spec, $method, $data['type']);
72
    }
73
74
    /**
75
     * @return int
76
     */
77
    public function getPriority()
78
    {
79
        return 0;
80
    }
81
82
    /**
83
     * @param $type
84
     * @return string
85
     */
86
    protected function getTemplate($type)
87
    {
88
        return file_get_contents(__DIR__.'/templates/'.$type.'.template');
89
    }
90
91
    /**
92
     * @param string $spec
93
     * @param \RMiller\Caser\Cased $method
94
     * @return bool
95
     */
96
    private function exampleAlreadyExists($spec, Cased $method)
97
    {
98
        $camelCaseMethod = $method->asCamelCase();
99
100
        $methodStrings = [
101
            '$this->' . $camelCaseMethod . '(',
102
            '$this::' . $camelCaseMethod . '(',
103
            '$this->beConstructedThrough(\'' . $camelCaseMethod . '\'',
104
        ];
105
106
        foreach ($methodStrings as $existingMethodString) {
107
            if (strpos($spec, $existingMethodString) !== false) {
108
                return true;
109
            }
110
        }
111
112
        return false;
113
    }
114
115
    /**
116
     * @param \RMiller\Caser\Cased $method
117
     * @param $type
118
     * @return string
119
     */
120
    private function renderContent(Cased $method, $type)
121
    {
122
        return $this->templates->renderString($this->getTemplate($type), [
123
            '%method%' => $method->asCamelCase(),
124
            '%example_name%' => 'it_should_' . $method->asSnakeCase(),
125
            '%constructor_example_name%' => 'it_should_be_constructed_through_' . $method->asSnakeCase(),
126
        ]);
127
    }
128
129
    /**
130
     * @param \PhpSpec\Locator\Resource $resource
131
     * @param string $spec
132
     * @param \RMiller\Caser\Cased $method
133
     * @param $type
134
     */
135
    private function addExampleToSpec(Resource $resource, $spec, Cased $method, $type)
136
    {
137
        $spec = preg_replace('/}[ \n]*$/', rtrim($this->renderContent($method, $type)) . "\n}\n", trim($spec));
138
        $this->filesystem->putFileContents($resource->getSpecFilename(), $spec);
139
        $this->informExampleAdded($resource, $method);
140
    }
141
142
    /**
143
     * @param Resource $resource
144
     * @param $method
145
     */
146
    private function informExampleAdded(Resource $resource, Cased $method)
147
    {
148
        $this->io->writeln(sprintf(
149
            "\nExample for <info>Method <value>%s::%s()</value> has been created.</info>",
150
            $resource->getSrcClassname(), $method->asCamelCase()
151
        ), 2);
152
    }
153
154
    /**
155
     * @param Resource $resource
156
     * @param $method
157
     */
158
    private function informExampleAlreadyExists(Resource $resource, Cased $method)
159
    {
160
        $this->io->writeln(sprintf(
161
            "\nExample for <info>Method <value>%s::%s()</value> already exists.</info> Try the <info>phpspec run</info> command",
162
            $resource->getSrcClassname(), $method->asCamelCase()
163
        ), 2);
164
    }
165
}
166