Builder::findQualifiedName()   B
last analyzed

Complexity

Conditions 6
Paths 9

Size

Total Lines 28
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6.0073

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 28
ccs 16
cts 17
cp 0.9412
rs 8.439
cc 6
eloc 15
nc 9
nop 3
crap 6.0073
1
<?php
2
3
/*
4
 * This file is part of Rocketeer
5
 *
6
 * (c) Maxime Fabre <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 */
12
13
namespace Rocketeer\Services\Builders;
14
15
use League\Container\ContainerAwareInterface;
16
use Rocketeer\Services\Builders\Modules\BinariesBuilder;
17
use Rocketeer\Services\Builders\Modules\CommandsBuilder;
18
use Rocketeer\Services\Builders\Modules\StrategiesBuilder;
19
use Rocketeer\Services\Builders\Modules\TasksBuilder;
20
use Rocketeer\Services\Connections\Shell\Modules\Binaries;
21
use Rocketeer\Services\Connections\Shell\Modules\Core;
22
use Rocketeer\Services\Connections\Shell\Modules\Filesystem;
23
use Rocketeer\Services\Connections\Shell\Modules\Flow;
24
use Rocketeer\Services\Connections\Shell\Modules\Statuses;
25
use Rocketeer\Services\Container\Container;
26
use Rocketeer\Services\Modules\ModulableInterface;
27
use Rocketeer\Services\Modules\ModulableTrait;
28
use Rocketeer\Traits\ContainerAwareTrait;
29
30
/**
31
 * @mixin BinariesBuilder
32
 * @mixin CommandsBuilder
33
 * @mixin StrategiesBuilder
34
 * @mixin TasksBuilder
35
 */
36
class Builder implements ModulableInterface, ContainerAwareInterface
37
{
38
    use ContainerAwareTrait;
39
    use ModulableTrait;
40
41
    /**
42
     * The possible locations of
43
     * the various types.
44
     *
45
     * @var array
46
     */
47
    protected $lookups = [
48
        'binaries' => [
49
            'Rocketeer\Binaries\PackageManagers\%s',
50
            'Rocketeer\Binaries\Vcs\%s',
51
            'Rocketeer\Binaries\%s',
52
        ],
53
        'tasks' => [
54
            'Rocketeer\Tasks\%s',
55
            'Rocketeer\Tasks\Subtasks\%s',
56
        ],
57
        'commands' => [
58
            'Rocketeer\Console\Commands\%sCommand',
59
            'Rocketeer\Console\Commands\BaseTaskCommand',
60
        ],
61
        'strategies' => [
62
            'Rocketeer\Strategies\%sStrategy',
63
        ],
64
    ];
65
66
    /**
67
     * @var array
68
     */
69
    protected $lookedUp = [];
70
71
    /**
72
     * @param Container $container
73
     */
74 442
    public function __construct(Container $container)
75
    {
76 442
        $this->container = $container;
77 442
        $namespace = $this->bootstrapper->getUserNamespace();
0 ignored issues
show
Documentation Bug introduced by Maxime Fabre
The method getUserNamespace does not exist on object<Rocketeer\Service...tstrapper\Bootstrapper>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
78
79 442
        $this->registerLookups([
80 442
            'tasks' => $namespace.'\Tasks\%s',
81 442
            'strategies' => $namespace.'\Strategies\%s',
82 442
        ]);
83 442
    }
84
85
    ////////////////////////////////////////////////////////////////////////////////
86
    /////////////////////////////////// MODULES ////////////////////////////////////
87
    ////////////////////////////////////////////////////////////////////////////////
88
89
    /**
90
     * @param ModulableInterface $modulable
91
     *
92
     * @return ModulableInterface
93
     */
94 442
    public function registerBashModulesOn(ModulableInterface $modulable)
95
    {
96 442
        if (!$modulable->getRegistered()) {
97 442
            $modulable->register(new Binaries());
98 442
            $modulable->register(new Core());
99 442
            $modulable->register(new Filesystem());
100 442
            $modulable->register(new Flow());
101 442
            $modulable->register(new Statuses());
102 442
        }
103
104 442
        return $modulable;
105
    }
106
107
    ////////////////////////////////////////////////////////////////////////////////
108
    /////////////////////////////////// LOOKUPS ////////////////////////////////////
109
    ////////////////////////////////////////////////////////////////////////////////
110
111
    /**
112
     * Get the lookups for a type.
113
     *
114
     * @param string $type
115
     *
116
     * @return array
117
     */
118 217
    public function getLookups($type)
119
    {
120 217
        return (array) isset($this->lookups[$type]) ? $this->lookups[$type] : [];
121
    }
122
123
    /**
124
     * Add additional places to look for classes.
125
     *
126
     * @param string       $type
127
     * @param string|array $lookups
128
     */
129 442
    public function registerLookup($type, $lookups = [])
130
    {
131 442
        $lookups = (array) $lookups;
132
133 442
        $this->lookups[$type] = array_unique(array_merge($this->lookups[$type], $lookups));
134 442
    }
135
136
    /**
137
     * Add additional places to look for multiple types.
138
     *
139
     * @param array $lookups
140
     */
141 442
    public function registerLookups(array $lookups)
142
    {
143 442
        $this->lookedUp = [];
144 442
        foreach ($lookups as $type => $lookup) {
145 442
            $this->registerLookup($type, $lookup);
146 442
        }
147 442
    }
148
149
    //////////////////////////////////////////////////////////////////////
150
    ////////////////////////////// HELPERS ///////////////////////////////
151
    //////////////////////////////////////////////////////////////////////
152
153
    /**
154
     * Find a class in various predefined namespaces.
155
     *
156
     * @param string      $class
157
     * @param string      $type
158
     * @param string|null $namespace
159
     *
160
     * @return false|string
161
     */
162 216
    public function findQualifiedName($class, $type, $namespace = null)
163
    {
164
        // Check if we already resolved that name
165 216
        if (array_key_exists($class, $this->lookedUp)) {
166
            return $this->lookedUp[$type][$class];
167
        }
168
169 216
        $paths = $this->getLookups($type);
170 216
        $paths[] = '%s';
171
172
        // Create classes array
173 216
        $class = ucfirst($class);
174 216
        $classes = $namespace ? [ucfirst($namespace).'\\'.$class, $class] : [$class];
175
176
        // Search for first existing class
177 216
        $qualified = false;
178 216
        foreach ($classes as $class) {
179 216
            foreach ($paths as $path) {
180 216
                $path = sprintf($path, $class);
181 216
                if (class_exists($path)) {
182 184
                    $qualified = $path;
183 184
                    break 2;
184
                }
185 204
            }
186 216
        }
187
188 216
        return $this->lookedUp[$type][$class] = $qualified;
189
    }
190
}
191