OverviewCommand::getRows()   A
last analyzed

Complexity

Conditions 5
Paths 1

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 19
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 31
ccs 0
cts 20
cp 0
crap 30
rs 9.3222
1
<?php declare(strict_types=1);
2
3
namespace DanielPieper\MergeReminder\Command;
4
5
use DanielPieper\MergeReminder\Exception\MergeRequestApprovalNotFoundException;
6
use DanielPieper\MergeReminder\Service\MergeRequestApprovalService;
7
use DanielPieper\MergeReminder\Service\MergeRequestService;
8
use DanielPieper\MergeReminder\Service\ProjectService;
9
use DanielPieper\MergeReminder\ValueObject\MergeRequestApproval;
10
use Symfony\Component\Console\Helper\Table;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Output\OutputInterface;
13
14
class OverviewCommand extends BaseCommand
15
{
16
    /** @var ProjectService */
17
    private $projectService;
18
19
    /** @var MergeRequestService */
20
    private $mergeRequestService;
21
22
    /** @var MergeRequestApprovalService */
23
    private $mergeRequestApprovalService;
24
25
    public function __construct(
26
        ProjectService $projectService,
27
        MergeRequestService $mergeRequestService,
28
        MergeRequestApprovalService $mergeRequestApprovalService
29
    ) {
30
        $this->projectService = $projectService;
31
        $this->mergeRequestService = $mergeRequestService;
32
        $this->mergeRequestApprovalService = $mergeRequestApprovalService;
33
        parent::__construct();
34
    }
35
36
    protected function configure()
37
    {
38
        $this
39
            ->setName('overview')
40
            ->setAliases(['o'])
41
            ->setDescription('Get an overview about all pending merge requests');
42
    }
43
44
    /**
45
     * @param array $mergeRequests
46
     * @return array
47
     * @throws MergeRequestApprovalNotFoundException
48
     */
49
    private function getMergeRequestApprovals(array $mergeRequests): array
50
    {
51
        $mergeRequestApprovals = [];
52
        foreach ($mergeRequests as $mergeRequest) {
53
            $mergeRequestApprovals[] = $this->mergeRequestApprovalService->get($mergeRequest);
54
        }
55
        return array_filter($mergeRequestApprovals, function (MergeRequestApproval $item) {
56
            $hasApprovalsLeft = $item->getApprovalsLeft() > 0;
57
            $isWorkInProgress = $item->getMergeRequest()->isWorkInProgress();
58
59
            return $hasApprovalsLeft && !$isWorkInProgress;
60
        });
61
    }
62
63
    /**
64
     * @param InputInterface $input
65
     * @param OutputInterface $output
66
     * @return int|null|void
67
     * @throws \Exception
68
     *
69
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
70
     */
71
    protected function execute(InputInterface $input, OutputInterface $output)
72
    {
73
        $mergeRequests = [];
74
        foreach ($this->projectService->all() as $project) {
75
            $mergeRequests += $this->mergeRequestService->allByProject($project);
76
        }
77
        if (count($mergeRequests) == 0) {
78
            $output->writeln('No pending merge requests.');
79
            return;
80
        }
81
82
        $mergeRequestApprovals = $this->getMergeRequestApprovals($mergeRequests);
83
        if (count($mergeRequestApprovals) == 0) {
84
            $output->writeln('No pending merge request approvals.');
85
            return;
86
        }
87
88
        $headers = $this->getHeaders($mergeRequestApprovals);
89
        $rows = $this->getRows($headers, $mergeRequestApprovals);
90
91
        $table = new Table($output);
92
        $table->setHeaders($headers);
93
        $table->setRows($rows);
94
        $table->render();
95
    }
96
97
    /**
98
     * @param array $mergeRequestApprovals
99
     * @return array
100
     */
101
    private function getHeaders(array $mergeRequestApprovals): array
102
    {
103
        $headers = array_unique(array_map(function (MergeRequestApproval $mergeRequestApproval) {
104
            return $mergeRequestApproval->getMergeRequest()->getProject()->getName();
105
        }, $mergeRequestApprovals));
106
        array_unshift($headers, 'Total');
107
        array_unshift($headers, 'Approver');
108
109
        return $headers;
110
    }
111
112
    /**
113
     * @param array $headers
114
     * @param array $mergeRequestApprovals
115
     * @return array
116
     */
117
    private function getRows(array $headers, array $mergeRequestApprovals): array
118
    {
119
        $headerIndices = array_flip($headers);
120
        $rows = array_reduce(
121
            $mergeRequestApprovals,
122
            function ($carry, MergeRequestApproval $mergeRequestApproval) use ($headerIndices) {
123
                $approverNames = $mergeRequestApproval->getApproverNames();
124
                foreach ($approverNames as $approverName) {
125
                    if (!isset($carry[$approverName])) {
126
                        $carry[$approverName] = array_fill(0, count($headerIndices) - 1, 0);
127
                        array_unshift($carry[$approverName], $approverName);
128
                    }
129
130
                    $project = $mergeRequestApproval->getMergeRequest()->getProject()->getName();
131
                    $index = $headerIndices[$project];
132
                    $carry[$approverName][$index]++;
133
                    $carry[$approverName][1]++;
134
                }
135
                return $carry;
136
            },
137
            []
138
        );
139
140
        usort($rows, function ($approverA, $approverB) {
141
            if ($approverA[1] == $approverB[1]) {
142
                return 0;
143
            }
144
            return ($approverA[1] > $approverB[1] ? -1 : 1);
145
        });
146
147
        return array_values($rows);
148
    }
149
}
150