Completed
Push — master ( d3a073...5737c8 )
by Greg
02:21
created

src/Task/Development/Changelog.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Robo\Task\Development;
3
4
use Robo\Task\BaseTask;
5
use Robo\Result;
6
use Robo\Contract\BuilderAwareInterface;
7
use Robo\Common\BuilderAwareTrait;
8
9
/**
10
 * Helps to manage changelog file.
11
 * Creates or updates `changelog.md` file with recent changes in current version.
12
 *
13
 * ``` php
14
 * <?php
15
 * $version = "0.1.0";
16
 * $this->taskChangelog()
17
 *  ->version($version)
18
 *  ->change("released to github")
19
 *  ->run();
20
 * ?>
21
 * ```
22
 *
23
 * Changes can be asked from Console
24
 *
25
 * ``` php
26
 * <?php
27
 * $this->taskChangelog()
28
 *  ->version($version)
29
 *  ->askForChanges()
30
 *  ->run();
31
 * ?>
32
 * ```
33
 */
34
class Changelog extends BaseTask implements BuilderAwareInterface
35
{
36
    use BuilderAwareTrait;
37
38
    /**
39
     * @var string
40
     */
41
    protected $filename;
42
43
    /**
44
     * @var array
45
     */
46
    protected $log = [];
47
48
    /**
49
     * @var string
50
     */
51
    protected $anchor = "# Changelog";
52
53
    /**
54
     * @var string
55
     */
56
    protected $version = "";
57
58
    /**
59
     * @var string
60
     */
61
    protected $body = "";
62
63
    /**
64
     * @var string
65
     */
66
    protected $header = "";
67
68
    /**
69
     * @param string $filename
70
     *
71
     * @return $this
72
     */
73
    public function filename($filename)
74
    {
75
        $this->filename = $filename;
76
        return $this;
77
    }
78
79
    /**
80
     * Sets the changelog body text.
81
     *
82
     * This method permits the raw changelog text to be set directly If this is set, $this->log changes will be ignored.
83
     *
84
     * @param string $body
85
     *
86
     * @return $this
87
     */
88
    public function setBody($body)
89
    {
90
        $this->body = $body;
91
        return $this;
92
    }
93
94
    /**
95
     * @param string $header
96
     *
97
     * @return $this
98
     */
99
    public function setHeader($header)
100
    {
101
        $this->header = $header;
102
        return $this;
103
    }
104
105
    /**
106
     * @param string $item
107
     *
108
     * @return $this
109
     */
110
    public function log($item)
111
    {
112
        $this->log[] = $item;
113
        return $this;
114
    }
115
116
    /**
117
     * @param string $anchor
118
     *
119
     * @return $this
120
     */
121
    public function anchor($anchor)
122
    {
123
        $this->anchor = $anchor;
124
        return $this;
125
    }
126
127
    /**
128
     * @param string $version
129
     *
130
     * @return $this
131
     */
132
    public function version($version)
133
    {
134
        $this->version = $version;
135
        return $this;
136
    }
137
138
    /**
139
     * @param string $filename
140
     */
141
    public function __construct($filename)
142
    {
143
        $this->filename = $filename;
144
    }
145
146
    /**
147
     * @param array $data
148
     *
149
     * @return $this
150
     */
151
    public function changes(array $data)
152
    {
153
        $this->log = array_merge($this->log, $data);
154
        return $this;
155
    }
156
157
    /**
158
     * @param string $change
159
     *
160
     * @return $this
161
     */
162
    public function change($change)
163
    {
164
        $this->log[] = $change;
165
        return $this;
166
    }
167
168
    /**
169
     * @return array
170
     */
171
    public function getChanges()
172
    {
173
        return $this->log;
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     */
179
    public function run()
180
    {
181
        if (empty($this->body)) {
182
            if (empty($this->log)) {
183
                return Result::error($this, "Changelog is empty");
184
            }
185
            $this->body = $this->generateBody();
186
        }
187
        if (empty($this->header)) {
188
            $this->header = $this->generateHeader();
189
        }
190
191
        $text = $this->header . $this->body;
192
193
        if (!file_exists($this->filename)) {
194
            $this->printTaskInfo('Creating {filename}', ['filename' => $this->filename]);
195
            $res = file_put_contents($this->filename, $this->anchor);
196
            if ($res === false) {
197
                return Result::error($this, "File {filename} cant be created", ['filename' => $this->filename]);
198
            }
199
        }
200
201
        /** @var \Robo\Result $result */
202
        // trying to append to changelog for today
203
        $result = $this->collectionBuilder()->taskReplaceInFile($this->filename)
0 ignored issues
show
Documentation Bug introduced by
The method taskReplaceInFile does not exist on object<Robo\Collection\CollectionBuilder>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
204
            ->from($this->header)
205
            ->to($text)
206
            ->run();
207
208
        if (!isset($result['replaced']) || !$result['replaced']) {
209
            $result = $this->collectionBuilder()->taskReplaceInFile($this->filename)
0 ignored issues
show
Documentation Bug introduced by
The method taskReplaceInFile does not exist on object<Robo\Collection\CollectionBuilder>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
210
                ->from($this->anchor)
211
                ->to($this->anchor . "\n\n" . $text)
212
                ->run();
213
        }
214
215
        return new Result($this, $result->getExitCode(), $result->getMessage(), $this->log);
216
    }
217
218
    /**
219
     * @return \Robo\Result|string
220
     */
221
    protected function generateBody()
222
    {
223
        $text = implode("\n", array_map([$this, 'processLogRow'], $this->log));
224
        $text .= "\n";
225
226
        return $text;
227
    }
228
229
    /**
230
     * @return string
231
     */
232
    protected function generateHeader()
233
    {
234
        return "#### {$this->version}\n\n";
235
    }
236
237
    /**
238
     * @param $i
239
     *
240
     * @return string
241
     */
242
    public function processLogRow($i)
243
    {
244
        return "* $i *" . date('Y-m-d') . "*";
245
    }
246
}
247