Passed
Push — master ( a589f8...1929d3 )
by Alexis
01:42 queued 11s
created

src/Command/StatusesHomeTimelineCommand.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace AlexisLefebvre\Bundle\AsyncTweetsBundle\Command;
4
5
use Abraham\TwitterOAuth\TwitterOAuth;
6
use AlexisLefebvre\Bundle\AsyncTweetsBundle\Entity\Tweet;
7
use AlexisLefebvre\Bundle\AsyncTweetsBundle\Entity\TweetRepository;
8
use AlexisLefebvre\Bundle\AsyncTweetsBundle\Utils\PersistTweet;
9
use Symfony\Component\Console\Helper\ProgressBar;
10
use Symfony\Component\Console\Helper\Table;
11
use Symfony\Component\Console\Input\InputInterface;
12
use Symfony\Component\Console\Input\InputOption;
13
use Symfony\Component\Console\Output\OutputInterface;
14
15
class StatusesHomeTimelineCommand extends BaseCommand
16
{
17
    /** @var bool */
18
    private $displayTable;
19
    /** @var Table */
20
    private $table;
21
    /** @var ProgressBar */
22
    private $progress;
23
24
    /**
25
     * @var array<bool|int>
26
     *
27
     * @see https://dev.twitter.com/rest/reference/get/statuses/home_timeline
28
     */
29
    private $parameters = [
30
        'count'           => 200,
31
        'exclude_replies' => true,
32
    ];
33
34 7
    protected function configure(): void
35
    {
36 7
        parent::configure();
37
38
        $this
39 7
            ->setName('statuses:hometimeline')
40 7
            ->setDescription('Fetch home timeline')
41
            // http://symfony.com/doc/2.3/cookbook/console/console_command.html#automatically-registering-commands
42 7
            ->addOption(
43 7
                'table',
44 7
                null,
45 7
                InputOption::VALUE_NONE,
46 7
                'Display a table with tweets'
47
            );
48 7
    }
49
50 7
    protected function execute(InputInterface $input, OutputInterface $output): int
51
    {
52 7
        $this->setAndDisplayLastTweet($output);
53
54 7
        $content = $this->getContent($input);
55
56 7
        if (!is_array($content)) {
57 2
            $this->displayContentNotArrayError($output, $content);
58
59 2
            return 1;
60
        }
61
62 5
        $numberOfTweets = count($content);
63
64 5
        if ($numberOfTweets == 0) {
65 2
            $output->writeln('<comment>No new tweet.</comment>');
66
67 2
            return 0;
68
        }
69
70 3
        $this->addAndDisplayTweets($input, $output, $content, $numberOfTweets);
71
72 3
        return 0;
73
    }
74
75 7
    protected function setAndDisplayLastTweet(OutputInterface $output): void
76
    {
77
        /** @var TweetRepository $tweetRepository */
78 7
        $tweetRepository = $this->em
79 7
            ->getRepository(Tweet::class);
80
81
        // Get the last tweet
82 7
        $lastTweet = $tweetRepository->getLastTweet();
83
84
        // And use it in the request if it exists
85 7
        if ($lastTweet) {
86 1
            $this->parameters['since_id'] = $lastTweet->getId();
87
88 1
            $comment = 'last tweet = '.$this->parameters['since_id'];
89
        } else {
90 6
            $comment = 'no last tweet';
91
        }
92
93 7
        $output->writeln('<comment>'.$comment.'</comment>');
94 7
    }
95
96
    /**
97
     * @return array<\stdClass>|object
0 ignored issues
show
Should the return type not be array|object?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
98
     */
99 1
    protected function getContent(InputInterface $input)
100
    {
101 1
        $connection = new TwitterOAuth(
102 1
            $this->container->getParameter('twitter_consumer_key'),
103 1
            $this->container->getParameter('twitter_consumer_secret'),
104 1
            $this->container->getParameter('twitter_token'),
105 1
            $this->container->getParameter('twitter_token_secret')
106
        );
107
108 1
        return $connection->get(
109 1
            'statuses/home_timeline',
110 1
            $this->parameters
111
        );
112
    }
113
114
    /**
115
     * @param array<string>|object $content
116
     */
117 2
    protected function displayContentNotArrayError(
118
        OutputInterface $output,
119
        $content
120
    ): void {
121 2
        $formatter = $this->getHelper('formatter');
122
123 2
        $errorMessages = ['Error!', 'Something went wrong, $content is not an array.'];
124 2
        $formattedBlock = $formatter->formatBlock($errorMessages, 'error');
125 2
        $output->writeln($formattedBlock);
126 2
        $output->writeln(print_r($content, true));
127 2
    }
128
129
    /**
130
     * @param array<\stdClass> $content
131
     */
132 3
    protected function addAndDisplayTweets(
133
        InputInterface $input,
134
        OutputInterface $output,
135
        array $content,
136
        int $numberOfTweets
137
    ): void {
138 3
        $output->writeln('<comment>Number of tweets: '.$numberOfTweets.'</comment>');
139
140
        // Iterate through $content in order to add the oldest tweet first,
141
        //  if there is an error the oldest tweet will still be saved
142
        //  and newer tweets can be saved next time the command is launched
143 3
        $tweets = array_reverse($content);
144
145 3
        $this->setProgressBar($output, $numberOfTweets);
146 3
        $this->setTable($input, $output);
147 3
        $this->iterateTweets($tweets);
148
149 3
        $this->progress->finish();
150 3
        $output->writeln('');
151
152 3
        if ($this->displayTable) {
153 2
            $this->table->render();
154
        }
155 3
    }
156
157 3
    protected function setProgressBar(
158
        OutputInterface $output,
159
        int $numberOfTweets
160
    ): void {
161 3
        $this->progress = new ProgressBar($output, $numberOfTweets);
162 3
        $this->progress->setBarCharacter('<comment>=</comment>');
163 3
        $this->progress->start();
164 3
    }
165
166 3
    protected function setTable(
167
        InputInterface $input,
168
        OutputInterface $output
169
    ): void {
170 3
        $this->displayTable = (bool) $input->getOption('table');
171
172
        // Display
173 3
        if ($this->displayTable) {
174 2
            $this->table = new Table($output);
175 2
            $this->table
176 2
                ->setHeaders(['Datetime', 'Text excerpt', 'Name']);
177
        }
178 3
    }
179
180
    /**
181
     * @param array<\stdClass> $tweets
182
     */
183 3
    protected function iterateTweets(array $tweets): void
184
    {
185 3
        $persistTweet = new PersistTweet(
186 3
            $this->em,
187 3
            $this->displayTable,
188 3
            $this->table
189
        );
190
191 3
        foreach ($tweets as $tweetTmp) {
192 3
            $persistTweet->addTweet($tweetTmp, true);
193
194 3
            $this->progress->advance();
195
        }
196 3
    }
197
}
198