Passed
Push — master ( e67480...0070a2 )
by Daniel
02:05
created

MergeRequestApprovalService::getByMergeRequests()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 2
dl 0
loc 10
ccs 0
cts 5
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace DanielPieper\MergeReminder\Service;
4
5
use DanielPieper\MergeReminder\Exception\MergeRequestApprovalNotFoundException;
6
use DanielPieper\MergeReminder\Filter\MergeRequestApprovalFilter;
7
use DanielPieper\MergeReminder\ValueObject\MergeRequest;
8
use DanielPieper\MergeReminder\ValueObject\MergeRequestApproval;
9
use DanielPieper\MergeReminder\ValueObject\User;
10
use DanielPieper\MergeReminder\ValueObject\Group;
11
12
class MergeRequestApprovalService
13
{
14
    /** @var \Gitlab\Client */
15
    private $gitlabClient;
16
17 5
    public function __construct(\Gitlab\Client $gitlabClient)
18
    {
19 5
        $this->gitlabClient = $gitlabClient;
20 5
    }
21
22
    /**
23
     * @param MergeRequest $mergeRequest
24
     * @return MergeRequestApproval|null
25
     * @throws \Exception
26
     */
27 5
    public function find(MergeRequest $mergeRequest): ?MergeRequestApproval
28
    {
29 5
        $mergeRequestApproval = $this->gitlabClient->mergeRequests()->approvals(
30 5
            $mergeRequest->getProject()->getId(),
31 5
            $mergeRequest->getIid()
32
        );
33 5
        if (!is_array($mergeRequestApproval)) {
34 1
            return null;
35
        }
36 4
        return $this->transform($mergeRequest, $mergeRequestApproval);
37
    }
38
39
    /**
40
     * @param MergeRequest $mergeRequest
41
     * @return MergeRequestApproval
42
     * @throws MergeRequestApprovalNotFoundException
43
     * @throws \Exception
44
     */
45 2
    public function get(MergeRequest $mergeRequest): MergeRequestApproval
46
    {
47 2
        $mergeRequestApproval = $this->find($mergeRequest);
48 2
        if (!$mergeRequestApproval) {
49 1
            throw new MergeRequestApprovalNotFoundException();
50
        }
51 1
        return $mergeRequestApproval;
52
    }
53
54
    /**
55
     * @param array $mergeRequests
56
     * @param MergeRequestApprovalFilter $filter
57
     * @return array
58
     * @throws MergeRequestApprovalNotFoundException
59
     */
60
    public function findByMergeRequests(
61
        array $mergeRequests,
62
        MergeRequestApprovalFilter $filter
63
    ): array {
64
        $mergeRequestApprovals = [];
65
        foreach ($mergeRequests as $mergeRequest) {
66
            $mergeRequestApprovals[] = $this->get($mergeRequest);
67
        }
68
        $mergeRequestApprovals = array_filter($mergeRequestApprovals, $filter);
69
        $this->sortByCreatedAt($mergeRequestApprovals);
70
71
        return $mergeRequestApprovals;
72
    }
73
74
    /**
75
     * @param array $mergeRequests
76
     * @param MergeRequestApprovalFilter $filter
77
     * @return array
78
     * @throws MergeRequestApprovalNotFoundException
79
     */
80
    public function getByMergeRequests(
81
        array $mergeRequests,
82
        MergeRequestApprovalFilter $filter
83
    ): array {
84
        $mergeRequestApprovals = $this->findByMergeRequests($mergeRequests, $filter);
85
86
        if (count($mergeRequestApprovals) == 0) {
87
            throw new MergeRequestApprovalNotFoundException('No pending merge request approvals.');
88
        }
89
        return $mergeRequestApprovals;
90
    }
91
92
    /**
93
     * @param array $mergeRequestApprovals
94
     */
95
    private function sortByCreatedAt(array &$mergeRequestApprovals): void
96
    {
97
        usort($mergeRequestApprovals, function (MergeRequestApproval $approvalA, MergeRequestApproval $approvalB) {
98
            if ($approvalA->getCreatedAt()->equalTo($approvalB->getCreatedAt())) {
99
                return 0;
100
            }
101
            return ($approvalA->getCreatedAt()->lessThan($approvalB->getCreatedAt()) ? -1 : 1);
102
        });
103
    }
104
105
    /**
106
     * @param MergeRequest $mergeRequest
107
     * @param array $mergeRequestApproval
108
     * @return MergeRequestApproval
109
     * @throws \Exception
110
     */
111 4
    private function transform(MergeRequest $mergeRequest, array $mergeRequestApproval): MergeRequestApproval
112
    {
113 4
        $mergeRequestApproval['merge_request'] = $mergeRequest;
114
115 4
        $this->transformApprovers($mergeRequestApproval['approved_by']);
116 4
        $this->transformApprovers($mergeRequestApproval['approvers']);
117 4
        $this->transformApprovers($mergeRequestApproval['suggested_approvers']);
118
119 4
        $mergeRequestApproval['suggested_approvers'] = array_udiff(
120 4
            $mergeRequestApproval['suggested_approvers'],
121 4
            $mergeRequestApproval['approvers'],
122
            function (User $userA, User $userB) {
123 2
                return $userA->getId() <=> $userB->getId();
124 4
            }
125
        );
126 4
        $mergeRequestApproval['approvers'] = array_udiff(
127 4
            $mergeRequestApproval['approvers'],
128 4
            $mergeRequestApproval['approved_by'],
129
            function (User $userA, User $userB) {
130 1
                return $userA->getId() <=> $userB->getId();
131 4
            }
132
        );
133
134
        array_walk($mergeRequestApproval['approver_groups'], function (&$approverGroup) {
135 1
            $approverGroup = Group::fromArray($approverGroup['group']);
136 4
        });
137
138 4
        return MergeRequestApproval::fromArray($mergeRequestApproval);
139
    }
140
141
    /**
142
     * @param array $approvers
143
     * @return void
144
     */
145 4
    private function transformApprovers(array &$approvers): void
146
    {
147
        array_walk($approvers, function (&$approver) {
148
            // suggested_approvers are not encapsulated in 'user'...
149 2
            if (isset($approver['user'])) {
150 2
                $approver = $approver['user'];
151
            }
152 2
            $approver = User::fromArray($approver);
153 4
        });
154 4
    }
155
}
156