QueuePublishCommand   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 7

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 12
lcom 2
cbo 7
dl 0
loc 110
ccs 0
cts 63
cp 0
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 20 1
B execute() 0 40 6
A getMessagePublisher() 0 4 1
A entityToString() 0 10 2
A notify() 0 8 2
1
<?php
2
3
namespace TreeHouse\QueueBundle\Command;
4
5
use Doctrine\ORM\AbstractQuery;
6
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
7
use Symfony\Component\Console\Input\InputArgument;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Input\InputOption;
10
use Symfony\Component\Console\Output\OutputInterface;
11
use TreeHouse\Queue\Message\Message;
12
use TreeHouse\Queue\Message\Publisher\MessagePublisherInterface;
13
14
class QueuePublishCommand extends ContainerAwareCommand
15
{
16
    /**
17
     * @inheritdoc
18
     */
19
    protected function configure()
20
    {
21
        $this->setName('queue:publish');
22
        $this->addArgument('queue', InputArgument::REQUIRED, 'The name of the queue to publish to');
23
        $this->addArgument('payload', InputArgument::OPTIONAL | InputArgument::IS_ARRAY, 'The message payload');
24
        $this->addOption('dql', 'd', InputOption::VALUE_OPTIONAL, 'A DQL query to execute. The resulting entities will all be published. This does not work when also given a payload');
25
        $this->setDescription('Publishes a message to a queue. Optionally a query can be run for which the result set is published');
26
        $this->setHelp(<<<HELP
27
This utility command publishes messages to a specified queue. You can publish a single message by giving the queue name
28
and the payload:
29
30
    <comment>php app/console %command.name% mail.send "[email protected]" "This is a test subject" "This is the body"</comment>
31
32
Or you can perform a Doctrine query where the entiry result set is published:
33
34
    <comment>php app/console %command.name% article.publish -d "SELECT a FROM AcmeBlogBundle:Article a WHERE a.published = 0"</comment>
35
36
HELP
37
        );
38
    }
39
40
    /**
41
     * @inheritdoc
42
     */
43
    protected function execute(InputInterface $input, OutputInterface $output)
44
    {
45
        $name    = $input->getArgument('queue');
46
        $payload = $input->getArgument('payload');
47
        $dql     = $input->getOption('dql');
48
49
        if ($payload && $dql) {
50
            throw new \InvalidArgumentException('You cannot provide both a <comment>payload</comment> and a <comment>dql</comment> query.');
51
        }
52
53
        $publisher = $this->getMessagePublisher($name);
54
55
        if ($payload) {
56
            $message = $publisher->createMessage($payload);
57
            $publisher->publish($message);
58
59
            $this->notify($output, $message, json_encode($payload));
60
61
            return 0;
62
        }
63
64
        if ($dql) {
65
            $manager = $this->getContainer()->get('doctrine')->getManager();
66
67
            /** @var AbstractQuery $query */
68
            $query = $manager->createQuery($dql);
69
            foreach ($query->iterate() as list($entity)) {
70
                $message = $publisher->createMessage($entity);
71
                $publisher->publish($message);
72
73
                $this->notify($output, $message, $this->entityToString($entity));
74
75
                $manager->detach($entity);
76
            }
77
78
            return 0;
79
        }
80
81
        throw new \InvalidArgumentException('Specify either a <comment>payload</comment> or a <comment>dql</comment> query.');
82
    }
83
84
    /**
85
     * @param string $name
86
     *
87
     * @return MessagePublisherInterface
88
     */
89
    protected function getMessagePublisher($name)
90
    {
91
        return $this->getContainer()->get(sprintf('tree_house.queue.publisher.%s', $name));
92
    }
93
94
    /**
95
     * @param object $entity
96
     *
97
     * @return string
98
     */
99
    protected function entityToString($entity)
100
    {
101
        $class = get_class($entity);
102
        $meta  = $this->getContainer()->get('doctrine')->getManagerForClass($class)->getClassMetadata($class);
103
104
        $id    = $meta->getIdentifierValues($entity);
105
        $title = method_exists($entity, '__toString') ? (string)$entity : get_class($entity) . '@' . spl_object_hash($entity);
106
107
        return sprintf('%s %s', json_encode($id), $title);
108
    }
109
110
    /**
111
     * @param OutputInterface $output
112
     * @param Message         $message
113
     * @param string          $payload
114
     */
115
    protected function notify(OutputInterface $output, Message $message, $payload)
116
    {
117
        $output->writeln(sprintf('Published message for <info>%s</info>', json_encode($payload)));
118
119
        if ($output->getVerbosity() > $output::VERBOSITY_VERBOSE) {
120
            $output->writeln(sprintf('=> Message body: <comment>%s</comment>', $message->getBody()));
121
        }
122
    }
123
}
124