Issues (10)

src/Command/BaseConsumerCommand.php (2 issues)

Labels
1
<?php
2
/**
3
 * Author: Joker
4
 * Date: 2020-05-08 13:57
5
 */
6
7
namespace JokerProject\LaravelAliyunAmqp\Command;
8
9
use Illuminate\Console\Command;
10
use Monolog\Handler\StreamHandler;
11
use Monolog\Logger;
12
use JokerProject\LaravelAliyunAmqp\ConsumerInterface;
13
use Psr\Log\LoggerAwareInterface;
14
use Psr\Log\LoggerInterface;
15
use Symfony\Component\Console\Output\OutputInterface;
16
17
/**
18
 * Class BaseConsumerCommand
19
 *
20
 * @package JokerProject\LaravelAliyunAmqp\Command
21
 */
22
class BaseConsumerCommand extends Command
23
{
24
    /**
25
     * The name and signature of the console command.
26
     *
27
     * @var string
28
     */
29
    protected $signature = 'rabbitmq:consume {consumer} {--time=60} {--messages=100} {--memory=64}';
30
31
    /**
32
     * The console command description.
33
     *
34
     * @var string
35
     */
36
    protected $description = 'Start consuming messages';
37
38
    /**
39
     * @param string $consumerAliasName
40
     * @return ConsumerInterface
41
     */
42
    protected function getConsumer(string $consumerAliasName): ConsumerInterface
43
    {
44
        return app()->makeWith(ConsumerInterface::class, [$consumerAliasName]);
45
    }
46
47
    /**
48
     * Execute the console command.
49
     * @return int
50
     */
51
    public function handle()
52
    {
53
        $messageCount = $this->input->getOption('messages');
54
        $waitTime = $this->input->getOption('time');
55
        $memoryLimit = $this->input->getOption('memory');
56
        $isVerbose = in_array(
57
            $this->output->getVerbosity(),
58
            [OutputInterface::VERBOSITY_VERBOSE, OutputInterface::VERBOSITY_VERY_VERBOSE]
59
        );
60
61
        /** @var ConsumerInterface $consumer */
62
        $consumer = $this->getConsumer($this->input->getArgument('consumer'));
0 ignored issues
show
It seems like $this->input->getArgument('consumer') can also be of type null and string[]; however, parameter $consumerAliasName of JokerProject\LaravelAliy...rCommand::getConsumer() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

62
        $consumer = $this->getConsumer(/** @scrutinizer ignore-type */ $this->input->getArgument('consumer'));
Loading history...
63
        if ($consumer instanceof LoggerAwareInterface && $isVerbose) {
64
            try {
65
                $this->injectCliLogger($consumer);
66
            } catch (\Throwable $e) {
67
                // Do nothing, we cannot inject a STDOUT logger
68
            }
69
        }
70
        try {
71
            return $consumer->startConsuming($messageCount, $waitTime, $memoryLimit);
72
        } catch (\Throwable $e) {
73
            $consumer->stopConsuming();
74
            $this->output->error($e->getMessage());
75
            return -1;
76
        }
77
    }
78
79
    /**
80
     * Inject a stdout logger
81
     *
82
     * This is a "hackish" method because we handle a interface to deduce an implementation
83
     * that exposes certain methods.
84
     *
85
     * @todo - Find a better way to inject a CLI logger when running in verbose mode
86
     *
87
     * @param LoggerAwareInterface $consumerWithLogger
88
     * @throws \Exception
89
     */
90
    protected function injectCliLogger(LoggerAwareInterface $consumerWithLogger)
91
    {
92
        $stdHandler = new StreamHandler('php://stdout');
93
        $class = new \ReflectionClass(get_class($consumerWithLogger));
94
        $property = $class->getProperty('logger');
95
        $property->setAccessible(true);
96
        /** @var LoggerInterface $logger */
97
        $logger = $property->getValue($consumerWithLogger);
98
        if ($logger instanceof \Illuminate\Log\LogManager) {
99
            /** @var Logger $logger */
100
            $logger = $logger->channel()->getLogger();
0 ignored issues
show
The method channel() does not exist on Monolog\Logger. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

100
            $logger = $logger->/** @scrutinizer ignore-call */ channel()->getLogger();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
101
            $logger->pushHandler($stdHandler);
102
        }
103
        $property->setAccessible(false);
104
    }
105
}
106