Completed
Pull Request — master (#318)
by
unknown
06:51
created

ViewComposer   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 278
Duplicated Lines 3.6 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 0
Metric Value
dl 10
loc 278
rs 10
c 0
b 0
f 0
wmc 29
lcom 1
cbo 11

4 Methods

Rating   Name   Duplication   Size   Complexity  
B __construct() 0 26 2
A compose() 0 16 3
D getOverloadPath() 10 86 13
C setPath() 0 39 11

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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
     * Get the override view path.
165
     *
166
     * @param  $view
167
     * @return null|string
168
     */
169
    public function getOverloadPath(View $view)
170
    {
171
172
        /*
173
         * We can only overload namespaced
174
         * views right now.
175
         */
176
        if (!str_contains($view->getName(), '::')) {
177
            return null;
178
        }
179
180
        /*
181
         * Split the view into it's
182
         * namespace and path.
183
         */
184
        list($namespace, $path) = explode('::', $view->getName());
185
186
        $override = null;
187
188
        $path = str_replace('.', '/', $path);
189
190
        /*
191
         * If the namespace is shorthand
192
         * then check to see if we have
193
         * an active addon to use for it.
194
         */
195
        if ($namespace === 'module' && $this->module) {
196
            $namespace = $this->module->getNamespace();
197
        }
198
199
        if ($namespace === 'theme' && $this->theme) {
200
            $namespace = $this->theme->getNamespace();
201
        }
202
203
        /*
204
         * If the view is a streams view then
205
         * it's real easy to guess what the
206
         * override path should be.
207
         */
208
        if ($namespace == 'streams') {
209
            $path = $this->theme->getNamespace('streams/' . $path);
210
        }
211
212
        /*
213
         * If the view uses a dot syntax namespace then
214
         * transform it all into the override view path.
215
         */
216 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...
217
            $override = $this->theme->getNamespace(
218
                "addons/{$addon->getVendor()}/{$addon->getSlug()}-{$addon->getType()}/" . $path
219
            );
220
        }
221
222
        if ($this->view->exists($override)) {
223
            return $override;
224
        }
225
226
        /**
227
         * Check if a published override exists.
228
         */
229
        if ($addon) {
230
            $override = "app::addons/{$addon->getVendor()}/{$addon->getSlug()}-{$addon->getType()}/views/" . $path;
231
        }
232
233
        if ($this->view->exists($override)) {
234
            return $override;
235
        }
236
237
        /*
238
         * If the view uses a dot syntax namespace then
239
         * transform it all into the override view path.
240
         *
241
         * @deprecated since v3.0.0
242
         */
243 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...
244
            $override = $this->theme->getNamespace(
245
                "addon/{$addon->getVendor()}/{$addon->getSlug()}-{$addon->getType()}/" . $path
246
            );
247
        }
248
249
        if ($this->view->exists($override)) {
250
            return $override;
251
        }
252
253
        return null;
254
    }
255
256
    /**
257
     * @param View $view
258
     */
259
    protected function setPath(View $view)
260
    {
261
        /**
262
         * If view path is already in internal cache,
263
         * use it.
264
         */
265
        if ($path = array_get($this->cache, $view->getName())) {
266
            $view->setPath($path);
267
268
            return;
269
        }
270
        $mobile = $this->mobiles->get($this->theme->getNamespace(), []);
271
        $overrides = $this->overrides->get($this->theme->getNamespace(), []);
272
273
        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...
274
            $view->setPath($path);
275
        } elseif ($path = array_get($overrides, $view->getName(), null)) {
276
            $view->setPath($path);
277
        }
278
279
        if ($this->module) {
280
            $mobile = $this->mobiles->get($this->module->getNamespace(), []);
281
            $overrides = $this->overrides->get($this->module->getNamespace(), []);
282
283
            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...
284
                $view->setPath($path);
285
            } elseif ($path = array_get($overrides, $view->getName(), null)) {
286
                $view->setPath($path);
287
            } elseif ($path = array_get(config('streams.overrides'), $view->getName(), null)) {
288
                $view->setPath($path);
289
            }
290
        }
291
292
        if ($overload = $this->getOverloadPath($view)) {
293
            $view->setPath($overload);
294
        }
295
296
        $this->cache[$view->getName()] = $view->getPath();
297
    }
298
}
299