ProjectCommand::execute()   A
last analyzed

Complexity

Conditions 5
Paths 6

Size

Total Lines 30
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 5
eloc 20
c 3
b 0
f 0
nc 6
nop 2
dl 0
loc 30
ccs 0
cts 18
cp 0
crap 30
rs 9.2888
1
<?php declare(strict_types=1);
2
3
namespace DanielPieper\MergeReminder\Command;
4
5
use DanielPieper\MergeReminder\Exception\MergeRequestNotFoundException;
6
use DanielPieper\MergeReminder\Exception\ProjectNotFoundException;
7
use DanielPieper\MergeReminder\Filter\MergeRequestApprovalFilter;
8
use DanielPieper\MergeReminder\Service\MergeRequestApprovalService;
9
use DanielPieper\MergeReminder\Service\MergeRequestService;
10
use DanielPieper\MergeReminder\Service\ProjectService;
11
use DanielPieper\MergeReminder\SlackServiceAwareInterface;
12
use DanielPieper\MergeReminder\SlackServiceAwareTrait;
13
use DanielPieper\MergeReminder\ValueObject\Project;
14
use Symfony\Component\Console\Input\InputArgument;
15
use Symfony\Component\Console\Input\InputInterface;
16
use Symfony\Component\Console\Input\InputOption;
17
use Symfony\Component\Console\Output\OutputInterface;
18
19
class ProjectCommand extends BaseCommand implements SlackServiceAwareInterface
20
{
21
    use SlackServiceAwareTrait;
22
23
    /** @var ProjectService */
24
    private $projectService;
25
26
    /** @var MergeRequestService */
27
    private $mergeRequestService;
28
29
    /** @var MergeRequestApprovalService */
30
    private $mergeRequestApprovalService;
31
32
    /** @var MergeRequestApprovalFilter */
33
    private $mergeRequestApprovalFilter;
34
35
    public function __construct(
36
        ProjectService $projectService,
37
        MergeRequestService $mergeRequestService,
38
        MergeRequestApprovalService $mergeRequestApprovalService,
39
        MergeRequestApprovalFilter $mergeRequestApprovalFilter
40
    ) {
41
        $this->projectService = $projectService;
42
        $this->mergeRequestService = $mergeRequestService;
43
        $this->mergeRequestApprovalService = $mergeRequestApprovalService;
44
        $this->mergeRequestApprovalFilter = $mergeRequestApprovalFilter;
45
        parent::__construct();
46
    }
47
48
    protected function configure()
49
    {
50
        $this
51
            ->setName('project')
52
            ->setAliases(['p'])
53
            ->setDescription('Get pending merge-requests by projects')
54
            ->addArgument(
55
                'names',
56
                InputArgument::IS_ARRAY | InputArgument::REQUIRED,
57
                'Gitlab project names (separate by space)'
58
            )->addOption(
59
                'slack',
60
                's',
61
                InputOption::VALUE_NONE,
62
                'Post to slack channel'
63
            );
64
    }
65
66
    /**
67
     * @param array $names
68
     * @return array
69
     * @throws ProjectNotFoundException
70
     */
71
    private function getProjects(array $names): array
72
    {
73
        $projects = $this->projectService->all();
74
        $projects = array_filter($projects, function (Project $project) use ($names) {
75
            return in_array($project->getName(), $names);
76
        });
77
        if (count($projects) == 0) {
78
            throw new ProjectNotFoundException('Projects not found.');
79
        }
80
        return $projects;
81
    }
82
83
    /**
84
     * @param array $projects
85
     * @return array
86
     * @throws MergeRequestNotFoundException
87
     */
88
    private function getMergeRequests(array $projects): array
89
    {
90
        $mergeRequests = [];
91
        foreach ($projects as $project) {
92
            $mergeRequests = array_merge($mergeRequests, $this->mergeRequestService->allByProject($project));
93
        }
94
        if (count($mergeRequests) == 0) {
95
            throw new MergeRequestNotFoundException('No pending merge requests.');
96
        }
97
        return $mergeRequests;
98
    }
99
100
    /**
101
     * @param InputInterface $input
102
     * @param OutputInterface $output
103
     * @return int|null|void
104
     * @throws \Exception
105
     */
106
    protected function execute(InputInterface $input, OutputInterface $output)
107
    {
108
        $projectNames = $input->getArgument('names');
109
        $projects = $this->getProjects(/** @scrutinizer ignore-type */ $projectNames);
110
        $mergeRequests = $this->getMergeRequests($projects);
111
        $mergeRequestApprovals = $this->mergeRequestApprovalService->getAll(
112
            $mergeRequests,
113
            $this->mergeRequestApprovalFilter
114
        );
115
116
        $messageText = sprintf(
117
            '%u Pending merge requests for projects %s:',
118
            count($mergeRequestApprovals),
119
            implode(', ', $projectNames)
120
        );
121
122
        if (!$output->isQuiet()) {
123
            $output->writeln([$messageText, '']);
124
            foreach ($mergeRequestApprovals as $mergeRequestApproval) {
125
                $this->printMergeRequestApproval($output, $mergeRequestApproval);
126
            }
127
        }
128
129
        if ($input->getOption('slack')) {
130
            if (!$this->slackService) {
131
                $output->writeln('<error>Slack is not configured,'
132
                    . ' please specify SLACK_WEBHOOK_URL and SLACK_CHANNEL environment variables.</error>');
133
                return;
134
            }
135
            $this->slackService->postMessage($mergeRequestApprovals, $messageText);
136
        }
137
    }
138
}
139