Completed
Push — master ( a68eb8...eb5798 )
by Vitaly
03:48
created

CloudReporter::report()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 0
1
<?php declare(strict_types = 1);
2
/**
3
 * Created by Vitaly Iegorov <[email protected]>.
4
 * on 22.09.16 at 09:26
5
 */
6
namespace samsonframework\bitbucket;
7
8
use Bitbucket\API\Authentication\AuthenticationInterface;
9
use Bitbucket\API\Repositories\Changesets;
10
use Bitbucket\API\Repositories\PullRequests;
11
use Buzz\Message\MessageInterface;
12
use Psr\Log\LoggerAwareInterface;
13
use Symfony\Component\Console\Logger\ConsoleLogger;
14
15
/**
16
 * Class BitBucketCloudReporter.
17
 *
18
 * @author Vitaly Egorov <[email protected]>
19
 */
20
class CloudReporter
21
{
22
    /** @var PullRequests */
23
    protected $pullRequests;
24
25
    /** @var Changesets */
26
    protected $changeSets;
27
28
    /** @var string BitBucket account name */
29
    protected $accountName;
30
31
    /** @var string BitBucket repository name */
32
    protected $repoName;
33
34
    /** @var int BitBucket pull request id */
35
    protected $pullRequestId;
36
37
    /** @var ConsoleLogger */
38
    protected $logger;
39
40
    /** @var string Pull request author */
41
    protected $author;
42
43
    /** @var ReporterInterface[] */
44
    protected $reporters = [];
45
46
    public function __construct(
47
        AuthenticationInterface $credentials,
48
        ConsoleLogger $logger,
49
        string $accountName,
50
        string $repoName,
51
        int $pullRequestId
52
    ) {
53
        $this->accountName = trim($accountName);
54
        $this->repoName = trim($repoName);
55
        $this->pullRequestId = $pullRequestId;
56
        $this->logger = $logger;
57
58
        $this->pullRequests = new PullRequests();
59
        $this->pullRequests->setCredentials($credentials);
60
61
        $this->changesets = new Changesets();
0 ignored issues
show
Bug introduced by
The property changesets does not seem to exist. Did you mean changeSets?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
62
        $this->changesets->setCredentials(clone $credentials);
0 ignored issues
show
Bug introduced by
The property changesets does not seem to exist. Did you mean changeSets?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
63
64
        $this->author = $this->getPullRequestAuthor();
65
    }
66
67
    /**
68
     * Add reporter.
69
     *
70
     * @param ReporterInterface $reporter Reporter instance
71
     */
72
    public function addReporter(ReporterInterface $reporter)
73
    {
74
        $this->reporters[] = $reporter;
75
    }
76
77
    /**
78
     * Report violations to BitBucket pull request.
79
     */
80
    public function report()
81
    {
82
        foreach ($this->reporters as $reporter) {
83
            $reporter->report($this, $this->logger);
84
        }
85
    }
86
87
    /**
88
     * Get pull request author username.
89
     *
90
     * @return string Pull request author username
91
     */
92
    public function getPullRequestAuthor()
93
    {
94
        $responseString = $this->pullRequests->get($this->accountName, $this->repoName, $this->pullRequestId);
95
        try {
96
            $responseObject = json_decode($responseString->getContent());
97
98
            if (isset($responseObject->error)) {
99
                $this->logger->critical($responseObject->error->message);
100
            } elseif (isset($responseObject->author)) {
101
                return $responseObject->author->username;
102
            } else {
103
                $this->logger->log(ConsoleLogger::INFO, 'BitBucket response has no values');
104
            }
105
        } catch (\InvalidArgumentException $exception) {
106
            $this->logger->critical('Cannot json_decode BitBucket response');
107
        }
108
    }
109
110
    /**
111
     * Collection of changed files in pull request.
112
     *
113
     * @return string[] Collection of changed files
114
     */
115
    public function getChangedFiles()
116
    {
117
        $files = [];
118
        $responseString = $this->pullRequests->commits($this->accountName, $this->repoName, $this->pullRequestId);
119
120
        try {
121
            $responseObject = json_decode($responseString->getContent());
122
123
            if (isset($responseObject->error)) {
124
                $this->logger->critical($responseObject->error->message);
125
            } elseif (isset($responseObject->values) && is_array($responseObject->values)) {
126
                foreach ($responseObject->values as $commit) {
127
                    $changeSet = $this->changesets->diffstat($this->accountName, $this->repoName, $commit->hash);
0 ignored issues
show
Bug introduced by
The property changesets does not seem to exist. Did you mean changeSets?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
128
                    $files[] = json_decode($changeSet->getContent())[0]->file;
129
                }
130
            } else {
131
                $this->logger->log(ConsoleLogger::INFO, 'BitBucket response has no values');
132
            }
133
        } catch (\InvalidArgumentException $exception) {
134
            $this->logger->critical('Cannot json_decode BitBucket response');
135
        }
136
137
        return $files;
138
    }
139
140
    /**
141
     * Create general pull request comment.
142
     *
143
     * @param string $content The comment content
144
     *
145
     * @return MessageInterface
146
     */
147
    public function createGeneralComment(string $content)
148
    {
149
        return $this->postComment(['content' => $content]);
150
    }
151
152
    /**
153
     * Add a new comment to pull request.
154
     *
155
     * @param string      $content  The comment content
156
     * @param null|string $filename File name
157
     * @param int|null    $lineFrom Source code line number
158
     *
159
     * @return MessageInterface
160
     */
161
    public function createFileComment(string $content, string $filename = null, int $lineFrom = null) : MessageInterface
162
    {
163
        $this->logger->log(ConsoleLogger::INFO, 'Creating comment in: '.$filename.'#'.$lineFrom.' - '.$content);
164
165
        return $this->postComment([
166
            'content' => $content,
167
            'filename' => $filename,
168
            'line_from' => $lineFrom
169
        ]);
170
    }
171
172
    /**
173
     * Low level post request for creating pull request comment.
174
     *
175
     * @param array $commentData Comment data
176
     *
177
     * @return MessageInterface
178
     */
179
    protected function postComment(array $commentData)
180
    {
181
        // Add pull request author
182
        $commentData['content'] = '@'.$this->author.' '.$commentData['content'];
183
184
        // Switch to old API version
185
        $this->pullRequests->getClient()->setApiVersion('1.0');
186
187
        return $this->pullRequests->comments()->requestPost(
188
            sprintf('repositories/%s/%s/pullrequests/%d/comments', $this->accountName, $this->repoName, $this->pullRequestId),
189
            $commentData
190
        );
191
    }
192
}
193