Completed
Push — master ( 957772...1146bb )
by Greg
02:43
created

Changelog::setHeader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
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();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->generateBody() can also be of type object<Robo\Result>. However, the property $body is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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