Passed
Push — master ( 88282a...da8bdb )
by Alexander
03:04
created

ApplicationDescription::getCommand()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 3
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Lenevor Framework
5
 *
6
 * LICENSE
7
 *
8
 * This source file is subject to the new BSD license that is bundled
9
 * with this package in the file license.md.
10
 * It is also available through the world-wide-web at this URL:
11
 * https://lenevor.com/license
12
 * If you did not receive a copy of the license and are unable to
13
 * obtain it through the world-wide-web, please send an email
14
 * to [email protected] so we can send you a copy immediately.
15
 *
16
 * @package     Lenevor
17
 * @subpackage  Base
18
 * @link        https://lenevor.com
19
 * @copyright   Copyright (c) 2019 - 2023 Alexander Campo <[email protected]>
20
 * @license     https://opensource.org/licenses/BSD-3-Clause New BSD license or see https://lenevor.com/license or see /license.md
21
 */
22
23
namespace Syscodes\Components\Console\Helper\Description;
24
25
use Syscodes\Components\Console\Application;
26
use Syscodes\Components\Console\Command\Command;
27
use Syscodes\Components\Console\Exceptions\CommandNotFoundException;
28
29
/**
30
 * @internal
31
 */
32
class ApplicationDescription
33
{
34
    public const G_NAMESPACE = '_global';
35
36
    /**
37
     * Get the aliases of the commands.
38
     * 
39
     * @var array $aliases
40
     */
41
    protected $aliases = [];
42
43
    /**
44
     * The application console.
45
     * 
46
     * @var \Syscodes\Components\Console\Application $application
47
     */
48
    protected $application;
49
50
    /**
51
     * Get the commands.
52
     * 
53
     * @var array $commands
54
     */
55
    protected array $commands;
56
57
    /**
58
     * Get the namespace of commands.
59
     * 
60
     * @var string|null $namespace
61
     */
62
    protected ?string $namespace;
63
64
    /**
65
     * Get the namespaces.
66
     * 
67
     * @var array $namespaces
68
     */
69
    protected array $namespaces;
70
71
    /**
72
     * Get the hidden data in boolean.
73
     * 
74
     * @var bool $hidden
75
     */
76
    protected bool $hidden;
77
78
    /**
79
     * Constructor. Create a new ApplicationDescription instance.
80
     * 
81
     * @param  \Syscodes\Components\Console\Application  $application
82
     * @param  string|null  $namespace
83
     * @param  bool  $hidden
84
     * 
85
     * @return void
86
     */
87
    public function __construct(Application $application, string $namespace = null, bool $hidden = false)
88
    {
89
        $this->application = $application;
90
        $this->namespace = $namespace;
91
        $this->hidden = $hidden;
92
    }
93
94
    /**
95
     * Get all the commands of console.
96
     * 
97
     * @return array|\Syscodes\Components\Console\Command\Command
98
     */
99
    public function getCommands(): array
100
    {
101
        if ( ! isset($this->commands)) {
102
            return $this->initAplication();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->initAplication() returns the type void which is incompatible with the type-hinted return array.
Loading history...
Bug introduced by
Are you sure the usage of $this->initAplication() targeting Syscodes\Components\Cons...ption::initAplication() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
103
        }
104
105
        return $this->commands;
106
    }
107
108
    /**
109
     * Get a command of console.
110
     * 
111
     * @param  string  $name
112
     * 
113
     * @return \Syscodes\Components\Console\Command\Command
114
     */
115
    public function getCommand(string $name): Command
116
    {
117
        if ( ! isset($this->commands[$name]) && ! isset($this->aliases[$name])) {
118
            throw new CommandNotFoundException(sprintf('Command "%s" does not exist', $name));
119
        }
120
        
121
        return $this->commands[$name] ?? $this->aliases[$name];
122
    }
123
124
    /**
125
     * Get all the namespaces of commands.
126
     * 
127
     * @return array
128
     */
129
    public function getNamespaces(): array
130
    {
131
        if ( ! isset($this->namespaces)) {
132
            return $this->initAplication();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->initAplication() targeting Syscodes\Components\Cons...ption::initAplication() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug Best Practice introduced by
The expression return $this->initAplication() returns the type void which is incompatible with the type-hinted return array.
Loading history...
133
        }
134
135
        return $this->namespaces;
136
    }
137
138
    /**
139
     * Get the initialize to application of console.
140
     * 
141
     * @return void
142
     */
143
    private function initAplication(): void
144
    {
145
        $this->commands = [];
146
        $this->namespaces = [];
147
        
148
        $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
149
        
150
        foreach ($this->sortCommands($all) as $namespace => $commands) {
151
            $names = [];
152
            
153
            /** @var \Syscodes\Components\Console\Command\Command $command */
154
            foreach ($commands as $name => $command) {
155
                if ( ! $command->getName() || (!$this->hidden && $command->isHidden())) {
156
                    continue;
157
                }
158
                
159
                if ($command->getName() === $name) {
160
                    $this->commands[$name] = $command;
161
                } else {
162
                    $this->aliases[$name] = $command;
163
                }
164
                
165
                $names[] = $name;
166
            }
167
            
168
            $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names];
169
        }
170
    }
171
172
    /**
173
     * Get the sort commands order.
174
     * 
175
     * @param  array  $commands
176
     * 
177
     * @return array
178
     */
179
    private function sortCommands(array $commands): array
180
    {
181
        $namespacedCommands = [];
182
        $globalCommands = [];
183
        $sortedCommands = [];
184
        
185
        foreach ($commands as $name => $command) {
186
            $key = $this->application->extractNamespace($name, 1);
187
            
188
            if (in_array($key, ['', self::G_NAMESPACE], true)) {
189
                $globalCommands[$name] = $command;
190
            } else {
191
                $namespacedCommands[$key][$name] = $command;
192
            }
193
        }
194
        
195
        if ($globalCommands) {
196
            ksort($globalCommands);
197
            $sortedCommands[self::G_NAMESPACE] = $globalCommands;
198
        }
199
        
200
        if ($namespacedCommands) {
201
            ksort($namespacedCommands, SORT_STRING);
202
            
203
            foreach ($namespacedCommands as $key => $commandsSet) {
204
                ksort($commandsSet);
205
                $sortedCommands[$key] = $commandsSet;
206
            }
207
        }
208
        
209
        return $sortedCommands;
210
    }
211
}