Completed
Push — master ( 332cce...b3eb75 )
by Biao
04:23
created

ListPropertiesCommand::allControllerProperties()   A

Complexity

Conditions 4
Paths 1

Size

Total Lines 31
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 20
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 31
rs 9.6
1
<?php
2
3
namespace Hhxsv5\LaravelS\Illuminate;
4
5
use Illuminate\Console\Command;
6
7
/**
8
 * This command is writing for those who want to know if there's any controller properties defined.
9
 * As controller is a singleton in laravel-s, all properties defined in controller will be retained after the request is finished.
10
 * So if you want to migrate to laravel-s, or just debug your app to find out potential problems, you can try this.
11
 */
12
class ListPropertiesCommand extends Command
13
{
14
    public $signature = 'laravels:list-properties';
15
16
    public $description = 'List all properties of all controllers.';
17
18
    /**
19
     * @throws \ReflectionException
20
     */
21
    public function fire()
22
    {
23
        return $this->handle();
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->handle() targeting Hhxsv5\LaravelS\Illumina...ertiesCommand::handle() 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...
24
    }
25
26
    /**
27
     * @throws \ReflectionException
28
     */
29
    public function handle()
30
    {
31
        $this->outputTable();
32
    }
33
34
    /**
35
     * Output all properties of all controllers as table.
36
     *
37
     * @throws \ReflectionException
38
     */
39
    private function outputTable()
40
    {
41
        $allProperties = $this->allControllerProperties();
42
        foreach ($allProperties as $controller => $properties) {
43
            if (empty($properties)) {
44
                continue;
45
            }
46
47
            $this->table(
48
                ['Controller', 'Property', 'Property Modifier'],
49
                $properties
50
            );
51
        }
52
    }
53
54
    /**
55
     * Get all properties of all controllers.
56
     *
57
     * @return array
58
     * @throws \ReflectionException
59
     */
60
    private function allControllerProperties()
61
    {
62
        $controllers = $this->allControllers();
63
        array_walk($controllers, function (&$properties, $controller) {
64
            $properties = [];
65
            // Get parent's properties
66
            $parent = get_parent_class($controller);
67
            if ($parent) {
68
                $reflectParentController = new \ReflectionClass($parent);
69
                $parentProperties = $reflectParentController->getProperties();
70
                foreach ($parentProperties as $property) {
71
                    $properties[$property->getName()] = [
72
                        $controller         => $controller,
73
                        'Property'          => $property->getName(),
74
                        'Property Modifier' => $this->resolveModifiers($property),
75
                    ];
76
                }
77
            }
78
79
            // Get sub controller's properties, override the parent properties.
80
            $reflectController = new \ReflectionClass($controller);
81
            $subProperties = $reflectController->getProperties();
82
            foreach ($subProperties as $property) {
83
                $properties[$property->getName()] = [
84
                    $controller         => $controller,
85
                    'Property'          => $property->getName(),
86
                    'Property Modifier' => $this->resolveModifiers($property),
87
                ];
88
            }
89
        });
90
        return $controllers;
91
    }
92
93
    /**
94
     * Get all controllers
95
     *
96
     * @return array
97
     * @throws \ReflectionException
98
     */
99
    private function allControllers()
100
    {
101
        $controllers = [];
102
        $router = isset(app()->router) ? app()->router : (app()->offsetExists('router') ? app('router') : app());
103
        $routes = $router->getRoutes();
0 ignored issues
show
Bug introduced by
The method getRoutes() does not exist on Illuminate\Container\Container. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

103
        /** @scrutinizer ignore-call */ 
104
        $routes = $router->getRoutes();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
104
        if (is_array($routes)) {
0 ignored issues
show
introduced by
The condition is_array($routes) is always false.
Loading history...
105
            $uses = array_column(array_column($routes, 'action'), 'uses');
106
        } else {
107
            $property = new \ReflectionProperty(get_class($routes), 'actionList');
108
            $property->setAccessible(true);
109
            $uses = array_keys($property->getValue($routes));
110
        }
111
112
        foreach ($uses as $use) {
113
            list($controller,) = explode('@', $use);
114
            $controllers[$controller] = $controller;
115
        }
116
        return $controllers;
117
    }
118
119
    /**
120
     * Resolve modifiers from \ReflectionProperty
121
     *
122
     * @param \ReflectionProperty $property
123
     * @return string
124
     */
125
    private function resolveModifiers(\ReflectionProperty $property)
126
    {
127
        if ($property->isPublic()) {
128
            $modifier = 'public';
129
        } elseif ($property->isProtected()) {
130
            $modifier = 'protected';
131
        } elseif ($property->isPrivate()) {
132
            $modifier = 'private';
133
        } else {
134
            $modifier = ' ';
135
        }
136
        if ($property->isStatic()) {
137
            $modifier .= ' static';
138
        }
139
        return $modifier;
140
    }
141
}