Completed
Pull Request — master (#209)
by Ryan
07:12
created

ViewComposer::compose()   C

Complexity

Conditions 11
Paths 25

Size

Total Lines 38
Code Lines 21

Duplication

Lines 10
Ratio 26.32 %

Importance

Changes 0
Metric Value
dl 10
loc 38
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 21
nc 25
nop 1

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php namespace Anomaly\Streams\Platform\View;
2
3
use Anomaly\Streams\Platform\Addon\AddonCollection;
4
use Anomaly\Streams\Platform\Addon\Module\Module;
5
use Anomaly\Streams\Platform\Addon\Theme\Theme;
6
use Anomaly\Streams\Platform\View\Event\ViewComposed;
7
use Illuminate\Contracts\Events\Dispatcher;
8
use Illuminate\Contracts\View\Factory;
9
use Illuminate\Http\Request;
10
use Illuminate\View\View;
11
use Mobile_Detect;
12
13
/**
14
 * Class ViewComposer
15
 *
16
 * @link    http://anomaly.is/streams-platform
17
 * @author  AnomalyLabs, Inc. <[email protected]>
18
 * @author  Ryan Thompson <[email protected]>
19
 * @package Anomaly\Streams\Platform\Support
20
 */
21
class ViewComposer
22
{
23
24
    /**
25
     * Runtime cache.
26
     *
27
     * @var array
28
     */
29
    protected $cache = [];
30
31
    /**
32
     * The view factory.
33
     *
34
     * @var Factory
35
     */
36
    protected $view;
37
38
    /**
39
     * The agent utility.
40
     *
41
     * @var Mobile_Detect
42
     */
43
    protected $agent;
44
45
    /**
46
     * The event dispatcher.
47
     *
48
     * @var Dispatcher
49
     */
50
    protected $events;
51
52
    /**
53
     * The current theme.
54
     *
55
     * @var Theme|null
56
     */
57
    protected $theme;
58
59
    /**
60
     * The active module.
61
     *
62
     * @var Module|null
63
     */
64
    protected $module;
65
66
    /**
67
     * The addon collection.
68
     *
69
     * @var AddonCollection
70
     */
71
    protected $addons;
72
73
    /**
74
     * The request object.
75
     *
76
     * @var Request
77
     */
78
    protected $request;
79
80
    /**
81
     * The view overrides collection.
82
     *
83
     * @var ViewOverrides
84
     */
85
    protected $overrides;
86
87
    /**
88
     * The view mobile overrides.
89
     *
90
     * @var ViewMobileOverrides
91
     */
92
    protected $mobiles;
93
94
    /**
95
     * @param Factory             $view
96
     * @param Mobile_Detect       $agent
97
     * @param Dispatcher          $events
98
     * @param AddonCollection     $addons
99
     * @param Request             $request
100
     * @param ViewOverrides       $overrides
101
     * @param ViewMobileOverrides $mobiles
102
     */
103
    function __construct(
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
104
        Factory $view,
105
        Mobile_Detect $agent,
106
        Dispatcher $events,
107
        AddonCollection $addons,
108
        ViewOverrides $overrides,
109
        Request $request,
0 ignored issues
show
Bug introduced by
You have injected the Request via parameter $request. This is generally not recommended as there might be multiple instances during a request cycle (f.e. when using sub-requests). Instead, it is recommended to inject the RequestStack and retrieve the current request each time you need it via getCurrentRequest().
Loading history...
110
        ViewMobileOverrides $mobiles
111
    ) {
112
        $this->view      = $view;
113
        $this->agent     = $agent;
114
        $this->events    = $events;
115
        $this->addons    = $addons;
116
        $this->mobiles   = $mobiles;
117
        $this->request   = $request;
118
        $this->overrides = $overrides;
119
120
        $area = $request->segment(1) == 'admin' ? 'admin' : 'standard';
121
122
        $this->theme  = $this->addons->themes->active($area);
0 ignored issues
show
Documentation introduced by
The property themes does not exist on object<Anomaly\Streams\P...\Addon\AddonCollection>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
123
        $this->module = $this->addons->modules->active();
0 ignored issues
show
Documentation introduced by
The property modules does not exist on object<Anomaly\Streams\P...\Addon\AddonCollection>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
124
125
        $this->mobile = $this->agent->isMobile();
0 ignored issues
show
Bug introduced by
The property mobile does not seem to exist. Did you mean mobiles?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
126
    }
127
128
    /**
129
     * Compose the view before rendering.
130
     *
131
     * @param  View $view
132
     * @return View
133
     */
134
    public function compose(View $view)
135
    {
136
        if (!$this->theme || !env('APP_INSTALLED')) {
137
138
            $this->events->fire(new ViewComposed($view));
139
140
            return $view;
141
        }
142
143
        $mobile    = $this->mobiles->get($this->theme->getNamespace(), []);
144
        $overrides = $this->overrides->get($this->theme->getNamespace(), []);
145
146 View Code Duplication
        if ($this->mobile && $path = array_get($mobile, $view->getName(), null)) {
0 ignored issues
show
Bug introduced by
The property mobile does not seem to exist. Did you mean mobiles?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
            $view->setPath($path);
148
        } elseif ($path = array_get($overrides, $view->getName(), null)) {
149
            $view->setPath($path);
150
        }
151
152
        if ($this->module) {
153
154
            $mobile    = $this->mobiles->get($this->module->getNamespace(), []);
155
            $overrides = $this->overrides->get($this->module->getNamespace(), []);
156
157 View Code Duplication
            if ($this->mobile && $path = array_get($mobile, $view->getName(), null)) {
0 ignored issues
show
Bug introduced by
The property mobile does not seem to exist. Did you mean mobiles?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
158
                $view->setPath($path);
159
            } elseif ($path = array_get($overrides, $view->getName(), null)) {
160
                $view->setPath($path);
161
            }
162
        }
163
164
        if ($overload = $this->getOverloadPath($view)) {
165
            $view->setPath($overload);
166
        }
167
168
        $this->events->fire(new ViewComposed($view));
169
170
        return $view;
171
    }
172
173
    /**
174
     * Get the override view path.
175
     *
176
     * @param  $view
177
     * @return null|string
178
     */
179
    public function getOverloadPath(View $view)
180
    {
181
182
        /**
183
         * We can only overload namespaced
184
         * views right now.
185
         */
186
        if (!str_contains($view->getName(), '::')) {
187
            return null;
188
        }
189
190
        /**
191
         * Split the view into it's
192
         * namespace and path.
193
         */
194
        list($namespace, $path) = explode('::', $view->getName());
195
196
        $path = str_replace('.', '/', $path);
197
198
        /**
199
         * If the module is shorthand
200
         * then check to see if we have
201
         * an active module to use for it.
202
         */
203
        if ($namespace === 'module' && $this->module) {
204
            $namespace = $this->module->getNamespace();
205
        }
206
207
        /**
208
         * If the view is already in
209
         * the theme then skip it.
210
         */
211
        if ($namespace == 'theme' || str_is('*.theme.*', $namespace)) {
212
            return null;
213
        }
214
215
        /**
216
         * If the view is a streams view then
217
         * it's real easy to guess what the
218
         * override path should be.
219
         */
220
        if ($namespace == 'streams') {
221
            $path = $this->theme->getNamespace('streams/' . $path);
222
        }
223
224
        /**
225
         * If the view uses a dot syntax namespace then
226
         * transform it all into the override view path.
227
         */
228 View Code Duplication
        if ($addon = $this->addons->get($namespace)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
229
            $path = $this->theme->getNamespace(
230
                "addons/{$addon->getVendor()}/{$addon->getSlug()}-{$addon->getType()}/" . $path
231
            );
232
        }
233
234
        if ($this->view->exists($path)) {
235
            return $path;
236
        }
237
238
        /**
239
         * If the view uses a dot syntax namespace then
240
         * transform it all into the override view path.
241
         *
242
         * @deprecated since v3.0.0
243
         */
244 View Code Duplication
        if ($addon) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
245
            $path = $this->theme->getNamespace(
246
                "addon/{$addon->getVendor()}/{$addon->getSlug()}-{$addon->getType()}/" . $path
247
            );
248
        }
249
250
        if ($this->view->exists($path)) {
251
            return $path;
252
        }
253
254
        return null;
255
    }
256
}
257