ViewComposer::getOverloadPath()   B
last analyzed

Complexity

Conditions 5
Paths 9

Size

Total Lines 46
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 14
nc 9
nop 1
dl 0
loc 46
rs 8.4751
c 0
b 0
f 0
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
182
        /**
183
         * Merge system configured overrides
184
         * with the overrides from the addon.
185
         */
186
        $overrides = array_merge(
187
            $this->overrides->get($this->theme->getNamespace(), []),
188
            config('streams.overrides', [])
189
        );
190
191
        $name = str_replace('theme::', $this->theme->getNamespace() . '::', $view->getName());
192
193
        if ($this->mobile && $path = array_get($mobile, $name, 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...
194
            $view->setPath($path);
195
        } elseif ($path = array_get($overrides, $name, null)) {
196
            $view->setPath($path);
197
        }
198
199
        if ($this->module) {
200
201
            $mobile    = $this->mobiles->get($this->module->getNamespace(), []);
202
            $overrides = $this->overrides->get($this->module->getNamespace(), []);
203
204
            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...
205
                $view->setPath($path);
206
            } elseif ($path = array_get($overrides, $view->getName(), null)) {
207
                $view->setPath($path);
208
            } elseif ($path = array_get(config('streams.overrides'), $view->getName(), null)) {
209
                $view->setPath($path);
210
            }
211
        }
212
213
        if ($overload = $this->getOverloadPath($view)) {
214
            $view->setPath($overload);
215
        }
216
217
        $this->cache[$view->getName()] = $view->getPath();
218
    }
219
220
    /**
221
     * Get the override view path.
222
     *
223
     * @param  $view
224
     * @return null|string
225
     */
226
    public function getOverloadPath(View $view)
227
    {
228
229
        /*
230
         * We can only overload namespaced
231
         * views right now.
232
         */
233
        if (!str_contains($view->getName(), '::')) {
234
            return null;
235
        }
236
237
        /*
238
         * Split the view into it's
239
         * namespace and path.
240
         */
241
        list($namespace, $path) = explode('::', $view->getName());
242
243
        $override = null;
244
245
        $path = str_replace('.', '/', $path);
246
247
        /*
248
         * If the view is a streams view then
249
         * it's real easy to guess what the
250
         * override path should be.
251
         */
252
        if ($namespace == 'streams') {
253
            $path = $this->theme->getNamespace('streams/' . $path);
254
        }
255
256
        /*
257
         * If the view uses a dot syntax namespace then
258
         * transform it all into the override view path.
259
         */
260
        if ($addon = $this->addons->get($namespace)) {
261
            $override = $this->theme->getNamespace(
262
                "addons/{$addon->getVendor()}/{$addon->getSlug()}-{$addon->getType()}/" . $path
263
            );
264
        }
265
266
        if ($this->view->exists($override)) {
267
            return $override;
268
        }
269
270
        return null;
271
    }
272
}
273