Issues (3627)

Command/MonitorTwitterBaseCommand.php (3 issues)

1
<?php
2
3
/*
4
 * @copyright   2016 Mautic, Inc. All rights reserved
5
 * @author      Mautic, Inc
6
 *
7
 * @link        https://mautic.org
8
 *
9
 * @license     GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
10
 */
11
12
namespace MauticPlugin\MauticSocialBundle\Command;
13
14
use Mautic\CoreBundle\Helper\CoreParametersHelper;
15
use Mautic\PluginBundle\Helper\IntegrationHelper;
16
use MauticPlugin\MauticSocialBundle\Entity\Monitoring;
17
use MauticPlugin\MauticSocialBundle\Event\SocialMonitorEvent;
18
use MauticPlugin\MauticSocialBundle\Helper\TwitterCommandHelper;
19
use MauticPlugin\MauticSocialBundle\Integration\TwitterIntegration;
20
use MauticPlugin\MauticSocialBundle\SocialEvents;
21
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
22
use Symfony\Component\Console\Input\InputInterface;
23
use Symfony\Component\Console\Input\InputOption;
24
use Symfony\Component\Console\Output\OutputInterface;
25
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
26
use Symfony\Component\Translation\TranslatorInterface;
27
28
abstract class MonitorTwitterBaseCommand extends ContainerAwareCommand
29
{
30
    /**
31
     * @var TwitterIntegration
32
     */
33
    protected $twitter;
34
35
    /**
36
     * @var TranslatorInterface
37
     */
38
    protected $translator;
39
40
    /**
41
     * @var EventDispatcherInterface
42
     */
43
    protected $dispatcher;
44
45
    /**
46
     * @var IntegrationHelper
47
     */
48
    protected $integrationHelper;
49
50
    /**
51
     * @var TwitterCommandHelper
52
     */
53
    private $twitterCommandHelper;
54
55
    /**
56
     * @var InputInterface
57
     */
58
    protected $input;
59
60
    /**
61
     * @var OutputInterface
62
     */
63
    protected $output;
64
65
    /**
66
     * @var int
67
     */
68
    protected $maxRuns = 5;
69
70
    /**
71
     * @var int
72
     */
73
    protected $runCount = 0;
74
75
    /**
76
     * @var int
77
     */
78
    protected $queryCount = 100;
79
80
    /**
81
     * MonitorTwitterBaseCommand constructor.
82
     */
83
    public function __construct(
84
        EventDispatcherInterface $dispatcher,
85
        TranslatorInterface $translator,
86
        IntegrationHelper $integrationHelper,
87
        TwitterCommandHelper $twitterCommandHelper,
88
        CoreParametersHelper $coreParametersHelper
89
    ) {
90
        $this->dispatcher           = $dispatcher;
91
        $this->translator           = $translator;
92
        $this->integrationHelper    = $integrationHelper;
93
        $this->twitterCommandHelper = $twitterCommandHelper;
94
95
        $this->translator->setLocale($coreParametersHelper->get('locale', 'en_US'));
96
97
        parent::__construct();
98
    }
99
100
    /**
101
     * Command configuration. Set the name, description, and options here.
102
     */
103
    protected function configure()
104
    {
105
        $this
106
            ->addOption(
107
                'mid',
108
                'i',
109
                InputOption::VALUE_REQUIRED,
110
                'The id of the monitor record'
111
            )
112
            ->addOption(
113
                'max-runs',
114
                null,
115
                InputOption::VALUE_REQUIRED,
116
                'The maximum number of recursive iterations permitted',
117
                5
118
            )
119
            ->addOption(
120
                'query-count',
121
                null,
122
                InputOption::VALUE_OPTIONAL,
123
                'The number of records to search for per iteration.',
124
                100
125
            )
126
            ->addOption(
127
                'show-posts',
128
                null,
129
                InputOption::VALUE_NONE,
130
                'Use this option to display the posts retrieved'
131
            )
132
            ->addOption(
133
                'show-stats',
134
                null,
135
                InputOption::VALUE_NONE,
136
                'Use this option to display the stats of the tweets fetched'
137
            );
138
    }
139
140
    /**
141
     * Used in various areas to set name of the network being searched.
142
     *
143
     * @return string twitter|facebook|linkedin etc..
144
     */
145
    abstract public function getNetworkName();
146
147
    /**
148
     * Search for tweets by creating your own search criteria.
149
     *
150
     * @param Monitoring $monitor
151
     *
152
     * @return array The results of makeRequest
153
     */
154
    abstract protected function getTweets($monitor);
155
156
    /**
157
     * Main execution method. Gets the integration settings, processes the search criteria.
158
     *
159
     * @return int|null
160
     */
161
    protected function execute(InputInterface $input, OutputInterface $output)
162
    {
163
        $this->input      = $input;
164
        $this->output     = $output;
165
        $this->maxRuns    = $this->input->getOption('max-runs');
166
        $this->queryCount = $this->input->getOption('query-count');
167
        $this->twitter    = $this->integrationHelper->getIntegrationObject('Twitter');
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->integrationHelper...rationObject('Twitter') of type boolean is incompatible with the declared type MauticPlugin\MauticSocia...tion\TwitterIntegration of property $twitter.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
168
169
        if (false === $this->twitter || false === $this->twitter->getIntegrationSettings()->getIsPublished()) {
170
            $this->output->writeln($this->translator->trans('mautic.social.monitoring.twitter.not.published'));
171
172
            return 1;
173
        }
174
175
        if (!$this->twitter->isAuthorized()) {
176
            $this->output->writeln($this->translator->trans('mautic.social.monitoring.twitter.not.configured'));
177
178
            return 1;
179
        }
180
181
        // get the mid from the cli
182
        $mid = $input->getOption('mid');
183
184
        if (!$mid) {
185
            $this->output->writeln($this->translator->trans('mautic.social.monitoring.twitter.mid.empty'));
186
187
            return 1;
188
        }
189
190
        $this->twitterCommandHelper->setOutput($output);
191
192
        $monitor = $this->twitterCommandHelper->getMonitor($mid);
193
194
        if (!$monitor || !$monitor->getId()) {
195
            $this->output->writeln($this->translator->trans('mautic.social.monitoring.twitter.monitor.does.not.exist', ['%id%' => $mid]));
196
197
            return 1;
198
        }
199
200
        // process the monitor
201
        $this->processMonitor($monitor);
202
203
        $this->dispatcher->dispatch(
204
            SocialEvents::MONITOR_POST_PROCESS,
205
            new SocialMonitorEvent($this->getNetworkName(), $monitor, $this->twitterCommandHelper->getManipulatedLeads(), $this->twitterCommandHelper->getNewLeadsCount(), $this->twitterCommandHelper->getUpdatedLeadsCount())
206
        );
207
208
        return 0;
209
    }
210
211
    /**
212
     * Process the monitor record.
213
     *
214
     * @Note: Keeping this method here instead of in the twitterCommandHelper
215
     *        so that the hashtag and mention commands can easily extend it.
216
     *
217
     * @param Monitoring $monitor
218
     *
219
     * @return bool
220
     */
221
    protected function processMonitor($monitor)
222
    {
223
        $results = $this->getTweets($monitor);
224
225
        if (false === $results || !isset($results['statuses'])) {
226
            $this->output->writeln('No statuses found');
227
228
            if (!empty($results['errors'])) {
229
                foreach ($results['errors'] as $error) {
230
                    $this->output->writeln($error['code'].': '.$error['message']);
231
                }
232
            }
233
234
            return 0;
0 ignored issues
show
Bug Best Practice introduced by
The expression return 0 returns the type integer which is incompatible with the documented return type boolean.
Loading history...
235
        }
236
237
        if (count($results['statuses'])) {
238
            $this->twitterCommandHelper->createLeadsFromStatuses($results['statuses'], $monitor);
239
        } else {
240
            $this->output->writeln($this->translator->trans('mautic.social.monitoring.twitter.no.new.tweets'));
241
        }
242
243
        $this->twitterCommandHelper->setMonitorStats($monitor, $results['search_metadata']);
244
        $this->printInformation($monitor, $results);
245
246
        // get stats after being updated
247
        $stats = $monitor->getStats();
248
249
        ++$this->runCount;
250
251
        // if we have stats and a next results request, process it here
252
        // @todo add a check for max iterations
253
        if (is_array($stats) && array_key_exists('max_id_str', $stats)
254
            && ($this->runCount < $this->maxRuns)
255
            && count($results['statuses'])
256
        ) {
257
            // recursive
258
            $this->processMonitor($monitor);
259
        }
260
261
        return 0;
0 ignored issues
show
Bug Best Practice introduced by
The expression return 0 returns the type integer which is incompatible with the documented return type boolean.
Loading history...
262
    }
263
264
    /**
265
     * Prints all the returned tweets.
266
     *
267
     * @param array $statuses
268
     */
269
    protected function printTweets($statuses)
270
    {
271
        if (!$this->input->getOption('show-posts') && $this->output->getVerbosity() < OutputInterface::VERBOSITY_VERY_VERBOSE) {
272
            return;
273
        }
274
275
        foreach ($statuses as $status) {
276
            $this->output->writeln('-- tweet -- ');
277
            $this->output->writeln('ID: '.$status['id']);
278
            $this->output->writeln('Message: '.$status['text']);
279
            $this->output->writeln('Handle: '.$status['user']['screen_name']);
280
            $this->output->writeln('Name: '.$status['user']['name']);
281
            $this->output->writeln('Location: '.$status['user']['location']);
282
            $this->output->writeln('Profile Img: '.$status['user']['profile_image_url']);
283
            $this->output->writeln('Profile Description: '.$status['user']['description']);
284
            $this->output->writeln('// tweet // ');
285
        }
286
    }
287
288
    /**
289
     * Prints the search query metadata from twitter.
290
     * Only shows stats if explicitly requested or if we're in verbose mode.
291
     *
292
     * @param array $metadata
293
     */
294
    protected function printQueryMetadata($metadata)
295
    {
296
        if (!$this->input->getOption('show-stats') && $this->output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE) {
297
            return;
298
        }
299
300
        $this->output->writeln('-- search meta -- ');
301
        $this->output->writeln('max_id_str: '.$metadata['max_id_str']);
302
        $this->output->writeln('since_id_str: '.$metadata['since_id_str']);
303
        $this->output->writeln('Page Count: '.$metadata['count']);
304
        $this->output->writeln('query: '.$metadata['query']);
305
306
        if (array_key_exists('next_results', $metadata)) {
307
            $this->output->writeln('next results: '.$metadata['next_results']);
308
        }
309
310
        $this->output->writeln('// search meta // ');
311
    }
312
313
    /**
314
     * Prints a summary of the search query.
315
     * Only shows stats if explicitly requested or if we're in verbose mode.
316
     *
317
     * @param Monitoring $monitor
318
     * @param array      $results
319
     */
320
    protected function printInformation($monitor, $results)
321
    {
322
        if (!$this->input->getOption('show-stats') && $this->output->getVerbosity() < OutputInterface::VERBOSITY_VERBOSE) {
323
            return;
324
        }
325
326
        $this->output->writeln('------------------------');
327
        $this->output->writeln($monitor->getTitle());
328
        $this->output->writeln('Published '.$monitor->isPublished());
329
        $this->output->writeln($monitor->getNetworkType());
330
        $this->output->writeln('New Leads '.$this->twitterCommandHelper->getNewLeadsCount());
331
        $this->output->writeln('Updated Leads '.$this->twitterCommandHelper->getUpdatedLeadsCount());
332
        $this->printQueryMetadata($results['search_metadata']);
333
        $this->printTweets($results['statuses']);
334
        $this->output->writeln('------------------------');
335
    }
336
}
337