Completed
Push — master ( 631b00...2fe979 )
by Alex
01:43
created

CheckCommand::printResult()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 3
nc 4
nop 3
1
<?php declare(strict_types=1);
2
3
namespace FeedIo\Command;
4
5
use FeedIo\Adapter\Guzzle\Client;
6
use FeedIo\Check\CheckAvailability;
7
use FeedIo\Check\CheckLastModified;
8
use FeedIo\Check\CheckPublicIds;
9
use FeedIo\Check\CheckReadSince;
10
use FeedIo\Check\Processor;
11
use FeedIo\Check\Result;
12
use FeedIo\FeedIo;
13
use Psr\Log\NullLogger;
14
use Symfony\Component\Console\Command\Command;
15
use Symfony\Component\Console\Formatter\OutputFormatterStyle;
16
use Symfony\Component\Console\Helper\Table;
17
use Symfony\Component\Console\Input\InputArgument;
18
use Symfony\Component\Console\Input\InputInterface;
19
use Symfony\Component\Console\Output\OutputInterface;
20
use Symfony\Component\Console\Style\SymfonyStyle;
21
22
/**
23
 * Class CheckCommand
24
 * @codeCoverageIgnore
25
 */
26
class CheckCommand extends Command
27
{
28
    private $ok;
29
30
    private $notOk;
31
32
    private $feedIo;
33
34
    public function __construct(string $name = null)
35
    {
36
        parent::__construct($name);
37
38
        $client = new Client(new \GuzzleHttp\Client());
39
        $this->feedIo = new FeedIo($client, new NullLogger());
40
    }
41
42
    protected function getFeedIo(): FeedIo
43
    {
44
        return $this->feedIo;
45
    }
46
47
    protected function configure()
48
    {
49
        $this->setName('check')
50
            ->setDescription('checks if a feed gets correctly updated')
51
            ->addArgument(
52
                'url',
53
                InputArgument::REQUIRED,
54
                'Please provide an URL or a file to read'
55
            );
56
    }
57
58
    protected function execute(InputInterface $input, OutputInterface $output)
59
    {
60
        $this->configureOutput($output);
61
        $io = new SymfonyStyle($input, $output);
62
        $urls = $this->getUrls($input);
63
64
        $results = [];
65
        $return = 0;
66
67
        foreach ($urls as $url) {
68
            if (empty($url)) {
69
                continue;
70
            }
71
            $result = $this->runChecks($io, trim($url));
72
            $results[] = iterator_to_array($this->renderValues($output, $result->toArray()));
73
            if (!$result->isUpdateable()) {
74
                $return++;
75
            }
76
        }
77
78
        $table = new Table($output);
79
        $table
80
            ->setHeaders(['URL', 'Accessible', 'readSince', 'Last modified', '# items', 'unique IDs', 'Date Flow'])
81
            ->setRows($results)
82
            ->setColumnWidth(0, 48);
83
        $table->render();
84
85
        if ($return > 0) {
86
            $io->error("Some feeds were marked as not updateable. Two possible explanations: a feed you tried to consumed doesn't match the specification or FeedIo has a bug.");
87
        }
88
        return $return;
89
    }
90
91
    protected function getUrls(InputInterface $input): array
92
    {
93
        $arg = $input->getArgument('url');
94
        if (filter_var($arg, FILTER_VALIDATE_URL)) {
95
            return [$arg];
96
        }
97
        if (!file_exists($arg)) {
98
            throw new \UnexpectedValueException("$arg must contain a valid URL or a file to read");
99
        }
100
        $content = file_get_contents($arg);
101
        return explode("\n", $content);
102
    }
103
104
    protected function renderValues(OutputInterface $output, array $values): \Generator
105
    {
106
        foreach ($values as $value) {
107
            if (is_bool($value)) {
108
                yield $value ? $this->ok : $this->notOk;
109
            } elseif ($value === 0 || $value === 'null') {
110
                yield $output->getFormatter()->format("<ko>$value</ko>");
111
            } else {
112
                yield $output->getFormatter()->format("<ok>$value</ok>");
113
            }
114
        }
115
    }
116
117
    protected function runChecks(SymfonyStyle $io, string $url): Result
118
    {
119
        $io->section("reading {$url}");
120
        $processor = new Processor($this->getFeedIo());
121
        $processor
122
            ->add(new CheckAvailability())
123
            ->add(new CheckPublicIds())
124
            ->add(new CheckLastModified())
125
            ->add(new CheckReadSince());
126
127
        return $processor->run($url);
128
    }
129
130
    private function configureOutput(OutputInterface $output): void
131
    {
132
        $output->getFormatter()->setStyle(
133
            'ko',
134
            new OutputFormatterStyle('red', null, ['bold'])
135
        );
136
137
        $output->getFormatter()->setStyle(
138
            'ok',
139
            new OutputFormatterStyle('green', null, ['bold'])
140
        );
141
142
        $this->ok = $output->getFormatter()->format('<ok>OK</ok>');
143
        $this->notOk = $output->getFormatter()->format("<ko>NOT OK</ko>");
144
    }
145
}
146