CommandFactory::addOptions()   B
last analyzed

Complexity

Conditions 5
Paths 9

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 9
nop 2
dl 0
loc 19
rs 8.8571
c 0
b 0
f 0
1
<?php
2
/*
3
 * Copyright (c) 2015 Juan José Torroglosa Ramón
4
 *
5
 * This file is part of the Cliphar package.
6
 *
7
 * For the full copyright and license information, please view
8
 * the LICENSE file that was distributed with this source code.
9
 */
10
11
namespace Cliphar\Command;
12
13
use Cliphar\InputDefinition\InputDefinitionParser;
14
use Cliphar\InputDefinition\Model\InputDefinition;
15
use Interop\Container\ContainerInterface;
16
use ReflectionFunction;
17
use Symfony\Component\Console\Command\Command;
18
use Symfony\Component\Console\Input\InputArgument;
19
use Symfony\Component\Console\Input\InputInterface;
20
use Symfony\Component\Console\Input\InputOption;
21
use Symfony\Component\Console\Output\OutputInterface;
22
23
class CommandFactory
24
{
25
    /**
26
     * @var InputDefinitionParser
27
     */
28
    private $parser;
29
30
    /**
31
     * @var ContainerInterface
32
     */
33
    private $container;
34
35
    /**
36
     * CommandFactory constructor.
37
     * @param ContainerInterface $container
38
     * @param InputDefinitionParser $parser
39
     */
40
    public function __construct(ContainerInterface $container, InputDefinitionParser $parser)
41
    {
42
        $this->container = $container;
43
        $this->parser = $parser;
44
    }
45
46
    /**
47
     * @param string $name
48
     * @param string $definition
49
     * @param callable $callable
50
     * @return Command
51
     * @throws \Cliphar\InputDefinition\Exception\InputDefinitionParsingException
52
     */
53
    public function createCommand($name, $definition, $callable)
54
    {
55
        $inputDefinition = $this->parser->parse($definition);
56
57
        $command = new Command($name);
58
59
        $this->addArguments($inputDefinition, $command);
60
        $this->addOptions($inputDefinition, $command);
61
62
        $command->setCode($this->getCallableWrapperFor($callable));
63
64
        return $command;
65
    }
66
67
    /**
68
     * @param InputDefinition $inputDefinition
69
     * @param Command $command
70
     * @return array
71
     */
72
    private function addArguments($inputDefinition, $command)
73
    {
74
        foreach ($inputDefinition->getArguments() as $argument) {
75
            $mode = $argument->isRequired()
76
                ? InputArgument::REQUIRED
77
                : InputArgument::OPTIONAL;
78
79
            $defaultValue = $argument->hasDefaultValue()
80
                ? $argument->getDefaultValue()
81
                : null;
82
83
            $command->addArgument($argument->getName(), $mode, null, $defaultValue);
84
        }
85
    }
86
87
    /**
88
     * @param InputDefinition $inputDefinition
89
     * @param Command $command
90
     */
91
    private function addOptions($inputDefinition, $command)
92
    {
93
        foreach ($inputDefinition->getOptions() as $option) {
94
            $shortcut = $option->hasAbbreviatedName()
95
                ? $option->getAbbreviatedName()
96
                : null;
97
98
            $mode = null;
99
            if ($option->hasDefaultValue()) {
100
                $mode = InputOption::VALUE_REQUIRED;
101
            }
102
103
            $defaultValue = $option->hasDefaultValue()
104
                ? $option->getDefaultValue()
105
                : null;
106
107
            $command->addOption($option->getName(), $shortcut, $mode, null, $defaultValue);
108
        }
109
    }
110
111
    private function getCallableWrapperFor($callable)
112
    {
113
        return function (InputInterface $inputInterface, OutputInterface $outputInterface) use ($callable) {
0 ignored issues
show
Unused Code introduced by
The parameter $outputInterface is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
114
            $reflectionClosure = new ReflectionFunction($callable);
115
            $closureParameters = $reflectionClosure->getParameters();
116
            $parameters = array();
117
            $container = $this->container;
118
119
            foreach ($closureParameters as $p) {
120
                if ($p->getClass()->getName() === 'Symfony\Component\Console\Input\InputInterface') {
121
                    $parameters[] = $inputInterface;
122
                } else {
123
                    $parameters[] = $container->get($p->getClass()->getName());
124
                }
125
            }
126
127
            call_user_func_array($callable, $parameters);
128
        };
129
    }
130
}