Completed
Push — master ( 27f167...51621d )
by Ryan
06:10
created

ViewComposer::setPath()   C

Complexity

Conditions 11
Paths 31

Size

Total Lines 41
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 22
nc 31
nop 1
dl 0
loc 41
rs 5.2653
c 0
b 0
f 0

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\Application\Application;
7
use Anomaly\Streams\Platform\View\Event\ViewComposed;
8
use Illuminate\Contracts\Events\Dispatcher;
9
use Illuminate\Contracts\View\Factory;
10
use Illuminate\Http\Request;
11
use Illuminate\View\View;
12
use Mobile_Detect;
13
14
/**
15
 * Class ViewComposer
16
 *
17
 * @link    http://pyrocms.com/
18
 * @author  PyroCMS, Inc. <[email protected]>
19
 * @author  Ryan Thompson <[email protected]>
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 application instance.
89
     *
90
     * @var Application
91
     */
92
    protected $application;
93
94
    /**
95
     * The view mobile overrides.
96
     *
97
     * @var ViewMobileOverrides
98
     */
99
    protected $mobiles;
100
101
    /**
102
     * Create a new ViewComposer instance.
103
     *
104
     * @param Factory $view
105
     * @param Mobile_Detect $agent
106
     * @param Dispatcher $events
107
     * @param AddonCollection $addons
108
     * @param ViewOverrides $overrides
109
     * @param Request $request
110
     * @param ViewMobileOverrides $mobiles
111
     * @param Application $application
112
     */
113
    public function __construct(
114
        Factory $view,
115
        Mobile_Detect $agent,
116
        Dispatcher $events,
117
        AddonCollection $addons,
118
        ViewOverrides $overrides,
119
        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...
120
        ViewMobileOverrides $mobiles,
121
        Application $application
122
    ) {
123
        $this->view        = $view;
124
        $this->agent       = $agent;
125
        $this->events      = $events;
126
        $this->addons      = $addons;
127
        $this->mobiles     = $mobiles;
128
        $this->request     = $request;
129
        $this->overrides   = $overrides;
130
        $this->application = $application;
131
132
        $area = $request->segment(1) == 'admin' ? 'admin' : 'standard';
133
134
        $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...
135
        $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...
136
137
        $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...
138
    }
139
140
    /**
141
     * Compose the view before rendering.
142
     *
143
     * @param  View $view
144
     * @return View
145
     */
146
    public function compose(View $view)
147
    {
148
149
        if (!$this->theme || !env('INSTALLED')) {
150
151
            $this->events->fire(new ViewComposed($view));
152
153
            return $view;
154
        }
155
156
        $this->setPath($view);
157
158
        $this->events->fire(new ViewComposed($view));
159
160
        return $view;
161
    }
162
163
    /**
164
     * Set the view path.
165
     *
166
     * @param View $view
167
     */
168
    protected function setPath(View $view)
169
    {
170
        /**
171
         * If view path is already in internal cache use it.
172
         */
173
        if ($path = array_get($this->cache, $view->getName())) {
174
175
            $view->setPath($path);
176
177
            return;
178
        }
179
180
        $mobile    = $this->mobiles->get($this->theme->getNamespace(), []);
181
        $overrides = $this->overrides->get($this->theme->getNamespace(), []);
182
183
        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...
184
            $view->setPath($path);
185
        } elseif ($path = array_get($overrides, $view->getName(), null)) {
186
            $view->setPath($path);
187
        }
188
189
        if ($this->module) {
190
191
            $mobile    = $this->mobiles->get($this->module->getNamespace(), []);
192
            $overrides = $this->overrides->get($this->module->getNamespace(), []);
193
194
            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...
195
                $view->setPath($path);
196
            } elseif ($path = array_get($overrides, $view->getName(), null)) {
197
                $view->setPath($path);
198
            } elseif ($path = array_get(config('streams.overrides'), $view->getName(), null)) {
199
                $view->setPath($path);
200
            }
201
        }
202
203
        if ($overload = $this->getOverloadPath($view)) {
204
            $view->setPath($overload);
205
        }
206
207
        $this->cache[$view->getName()] = $view->getPath();
208
    }
209
210
    /**
211
     * Get the override view path.
212
     *
213
     * @param  $view
214
     * @return null|string
215
     */
216
    public function getOverloadPath(View $view)
217
    {
218
219
        /*
220
         * We can only overload namespaced
221
         * views right now.
222
         */
223
        if (!str_contains($view->getName(), '::')) {
224
            return null;
225
        }
226
227
        /*
228
         * Split the view into it's
229
         * namespace and path.
230
         */
231
        list($namespace, $path) = explode('::', $view->getName());
232
233
        $override = null;
234
235
        $path = str_replace('.', '/', $path);
236
237
        /*
238
         * If the namespace is shorthand
239
         * then check to see if we have
240
         * an active addon to use for it.
241
         */
242
        if ($namespace === 'module' && $this->module) {
243
            $namespace = $this->module->getNamespace();
244
        }
245
246
        if ($namespace === 'theme' && $this->theme) {
247
            $namespace = $this->theme->getNamespace();
248
        }
249
250
        /*
251
         * If the view is a streams view then
252
         * it's real easy to guess what the
253
         * override path should be.
254
         */
255
        if ($namespace == 'streams') {
256
            $path = $this->theme->getNamespace('streams/' . $path);
257
        }
258
259
        /*
260
         * If the view uses a dot syntax namespace then
261
         * transform it all into the override view path.
262
         */
263 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...
264
            $override = $this->theme->getNamespace(
265
                "addons/{$addon->getVendor()}/{$addon->getSlug()}-{$addon->getType()}/" . $path
266
            );
267
        }
268
269
        if ($this->view->exists($override)) {
270
            return $override;
271
        }
272
273
        /**
274
         * Check if a published override exists.
275
         */
276
        if ($addon) {
277
            $override = "app::addons/{$addon->getVendor()}/{$addon->getSlug()}-{$addon->getType()}/views/" . $path;
278
        }
279
280
        if ($this->view->exists($override)) {
281
            return $override;
282
        }
283
284
        /*
285
         * If the view uses a dot syntax namespace then
286
         * transform it all into the override view path.
287
         *
288
         * @deprecated since v3.0.0
289
         */
290 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...
291
            $override = $this->theme->getNamespace(
292
                "addon/{$addon->getVendor()}/{$addon->getSlug()}-{$addon->getType()}/" . $path
293
            );
294
        }
295
296
        if ($this->view->exists($override)) {
297
            return $override;
298
        }
299
300
        return null;
301
    }
302
}
303