FindCommandHandler::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
ccs 4
cts 4
cp 1
rs 9.4285
cc 1
eloc 3
nc 1
nop 2
crap 1
1
<?php
2
3
/*
4
 * This file is part of the puli/cli package.
5
 *
6
 * (c) Bernhard Schussek <[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
namespace Puli\Cli\Handler;
13
14
use Puli\Cli\Util\StringUtil;
15
use Puli\Discovery\Api\Discovery;
16
use Puli\Discovery\Binding\ResourceBinding;
17
use Puli\Repository\Api\ResourceRepository;
18
use RuntimeException;
19
use Webmozart\Console\Api\Args\Args;
20
use Webmozart\Console\Api\IO\IO;
21
use Webmozart\Console\UI\Component\Table;
22
use Webmozart\Console\UI\Style\TableStyle;
23
use Webmozart\Expression\Expr;
24
25
/**
26
 * Handles the "find" command.
27
 *
28
 * @since  1.0
29
 *
30
 * @author Bernhard Schussek <[email protected]>
31
 */
32
class FindCommandHandler
33
{
34
    /**
35
     * @var ResourceRepository
36
     */
37
    private $repo;
38
39
    /**
40
     * @var Discovery
41
     */
42
    private $discovery;
43
44
    /**
45
     * Creates the handler.
46
     *
47
     * @param ResourceRepository $repo      The resource repository.
48
     * @param Discovery          $discovery The discovery.
49
     */
50 11
    public function __construct(ResourceRepository $repo, Discovery $discovery)
51
    {
52 11
        $this->repo = $repo;
53 11
        $this->discovery = $discovery;
54 11
    }
55
56
    /**
57
     * Handles the "find" command.
58
     *
59
     * @param Args $args The console arguments.
60
     * @param IO   $io   The I/O.
61
     *
62
     * @return int The status code.
63
     */
64 11
    public function handle(Args $args, IO $io)
65
    {
66 11
        $criteria = array();
67
68 11
        if ($args->isOptionSet('path')) {
69 6
            $criteria['path'] = $args->getOption('path');
70 6
            $criteria['language'] = $args->getOption('language');
71
        }
72
73 11
        if ($args->isOptionSet('name')) {
74 2
            if (isset($criteria['path'])) {
75 1
                throw new RuntimeException('The options --name and --path cannot be combined.');
76
            }
77
78 1
            $criteria['path'] = '/**/'.$args->getOption('name');
79 1
            $criteria['language'] = $args->getOption('language');
80
        }
81
82 10
        if ($args->isOptionSet('class')) {
83 3
            $criteria['class'] = $args->getOption('class');
84
        }
85
86 10
        if ($args->isOptionSet('type')) {
87 3
            $criteria['bindingType'] = $args->getOption('type');
88
        }
89
90 10
        if (empty($criteria)) {
91 1
            throw new RuntimeException('No search criteria specified.');
92
        }
93
94 9
        return $this->listMatches($io, $criteria);
95
    }
96
97
    /**
98
     * Lists the matches for the given search criteria.
99
     *
100
     * @param IO    $io       The I/O.
101
     * @param array $criteria The array with the optional keys "pattern",
102
     *                        "shortClass" and "bindingType".
103
     *
104
     * @return int The status code.
105
     */
106 9
    private function listMatches(IO $io, array $criteria)
107
    {
108 9
        if (isset($criteria['path']) && isset($criteria['bindingType'])) {
109 1
            $matches = array_intersect_key(
110 1
                $this->findByPath($criteria['path'], $criteria['language']),
111 1
                $this->findByBindingType($criteria['bindingType'])
112
            );
113 8
        } elseif (isset($criteria['path'])) {
114 5
            $matches = $this->findByPath($criteria['path'], $criteria['language']);
115 3
        } elseif (isset($criteria['bindingType'])) {
116 2
            $matches = $this->findByBindingType($criteria['bindingType']);
117
        } else {
118 1
            $matches = $this->findByPath('/*');
119
        }
120
121 9
        if (isset($criteria['class'])) {
122 3
            $shortClass = $criteria['class'];
123
124 3
            $matches = array_filter($matches, function ($value) use ($shortClass) {
125 3
                return $value === $shortClass;
126 3
            });
127
        }
128
129 9
        $this->printTable($io, $matches);
130
131 9
        return 0;
132
    }
133
134
    /**
135
     * Finds the resources for a given path pattern.
136
     *
137
     * @param string $query    The resource query.
138
     * @param string $language The language of the query.
139
     *
140
     * @return string[] An array of short resource class names indexed by
141
     *                  the resource path.
142
     */
143 7
    private function findByPath($query, $language = 'glob')
144
    {
145 7
        $matches = array();
146 7
        $query = '/'.ltrim($query, '/');
147
148 7
        foreach ($this->repo->find($query, $language) as $resource) {
149 7
            $matches[$resource->getPath()] = StringUtil::getShortClassName(get_class($resource));
150
        }
151
152 7
        return $matches;
153
    }
154
155
    /**
156
     * Finds the resources for a given binding type.
157
     *
158
     * @param string $typeName The type name.
159
     *
160
     * @return string[] An array of short resource class names indexed by
161
     *                  the resource path.
162
     */
163 3
    private function findByBindingType($typeName)
164
    {
165 3
        $matches = array();
166
167 3
        $expr = Expr::isInstanceOf('Puli\Discovery\Binding\ResourceBinding');
168
169 3
        foreach ($this->discovery->findBindings($typeName, $expr) as $binding) {
170
            /** @var ResourceBinding $binding */
171 3
            foreach ($binding->getResources() as $resource) {
172 3
                $matches[$resource->getPath()] = StringUtil::getShortClassName(get_class($resource));
173
            }
174
        }
175
176 3
        ksort($matches);
177
178 3
        return $matches;
179
    }
180
181
    /**
182
     * Prints the given resources.
183
     *
184
     * @param IO       $io      The I/O.
185
     * @param string[] $matches An array of short resource class names indexed
186
     *                          by the resource path.
187
     */
188 9
    private function printTable(IO $io, array $matches)
189
    {
190 9
        $table = new Table(TableStyle::borderless());
191
192 9
        foreach ($matches as $path => $shortClass) {
193 9
            $table->addRow(array($shortClass, sprintf('<c1>%s</c1>', $path)));
194
        }
195
196 9
        $table->render($io);
197 9
    }
198
}
199