Addon::getAppPath()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php namespace Anomaly\Streams\Platform\Addon;
2
3
use Anomaly\Streams\Platform\Traits\FiresCallbacks;
4
use Illuminate\Contracts\Support\Arrayable;
5
use Illuminate\Foundation\Bus\DispatchesJobs;
6
use Robbo\Presenter\PresentableInterface;
7
use Robbo\Presenter\Presenter;
8
9
/**
10
 * Class Addon
11
 *
12
 * @link   http://pyrocms.com/
13
 * @author PyroCMS, Inc. <[email protected]>
14
 * @author Ryan Thompson <[email protected]>
15
 */
16
class Addon implements PresentableInterface, Arrayable
17
{
18
19
    use FiresCallbacks;
20
    use DispatchesJobs;
21
22
    /**
23
     * Runtime cache.
24
     *
25
     * @var array
26
     */
27
    protected $cache = [];
28
29
    /**
30
     * The addon path.
31
     *
32
     * @var string
33
     */
34
    protected $path = null;
35
36
    /**
37
     * The addon type.
38
     *
39
     * @var string
40
     */
41
    protected $type = null;
42
43
    /**
44
     * The addon slug.
45
     *
46
     * @var string
47
     */
48
    protected $slug = null;
49
50
    /**
51
     * The addon vendor.
52
     *
53
     * @var string
54
     */
55
    protected $vendor = null;
56
57
    /**
58
     * The addon namespace.
59
     *
60
     * @var null|string
61
     */
62
    protected $namespace = null;
63
64
    /**
65
     * Get the addon's presenter.
66
     *
67
     * @return Presenter
68
     */
69
    public function getPresenter()
70
    {
71
        return app()->make('Anomaly\Streams\Platform\Addon\AddonPresenter', ['object' => $this]);
72
    }
73
74
    /**
75
     * Return a new service provider.
76
     *
77
     * @return AddonServiceProvider
78
     */
79
    public function newServiceProvider()
80
    {
81
        return app()->make($this->getServiceProvider(), [app(), $this]);
82
    }
83
84
    /**
85
     * Get the service provider class.
86
     *
87
     * @return string
88
     */
89
    public function getServiceProvider()
90
    {
91
        return get_class($this) . 'ServiceProvider';
92
    }
93
94
    /**
95
     * Return whether the addon is core or not.
96
     *
97
     * @return bool
98
     */
99
    public function isCore()
100
    {
101
        return str_contains($this->getPath(), 'core/' . $this->getVendor());
102
    }
103
104
    /**
105
     * Return whether the addon is shared or not.
106
     *
107
     * @return bool
108
     */
109
    public function isShared()
110
    {
111
        return str_contains($this->getPath(), 'addons/shared/' . $this->getVendor());
112
    }
113
114
    /**
115
     * Return whether the addon is for testing or not.
116
     *
117
     * @return bool
118
     */
119
    public function isTesting()
120
    {
121
        return str_contains($this->getPath(), 'vendor/anomaly/streams-platform/addons/' . $this->getVendor());
122
    }
123
124
    /**
125
     * Get the addon name string.
126
     *
127
     * @return string
128
     */
129
    public function getName()
130
    {
131
        return $this->getNamespace('addon.name');
132
    }
133
134
    /**
135
     * Get the addon title string.
136
     *
137
     * @return string
138
     */
139
    public function getTitle()
140
    {
141
        return trans()->has($this->getNamespace('addon.title')) ? $this->getNamespace('addon.title') : $this->getName();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Symfony\Component\Translation\TranslatorInterface as the method has() does only exist in the following implementations of said interface: Illuminate\Translation\Translator.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
142
    }
143
144
    /**
145
     * Get the addon description string.
146
     *
147
     * @return string
148
     */
149
    public function getDescription()
150
    {
151
        return $this->getNamespace('addon.description');
152
    }
153
154
    /**
155
     * Get a namespaced key string.
156
     *
157
     * @param  null $key
158
     * @return string
159
     */
160
    public function getNamespace($key = null)
161
    {
162
        if (!$this->namespace) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->namespace of type null|string is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
163
            $this->makeNamespace();
164
        }
165
166
        return $this->namespace . ($key ? '::' . $key : $key);
167
    }
168
169
    /**
170
     * Get the transformed
171
     * class to another suffix.
172
     *
173
     * @param  null $suffix
174
     * @return string
175
     */
176
    public function getTransformedClass($suffix = null)
177
    {
178
        $namespace = implode('\\', array_slice(explode('\\', get_class($this)), 0, -1));
179
180
        return $namespace . ($suffix ? '\\' . $suffix : $suffix);
181
    }
182
183
    /**
184
     * Return the ID representation (namespace).
185
     *
186
     * @return string
187
     */
188
    public function getId()
189
    {
190
        return $this->getNamespace();
191
    }
192
193
    /**
194
     * Return whether an addon has
195
     * config matching the key.
196
     *
197
     * @param  string $key
198
     * @return boolean
199
     */
200
    public function hasConfig($key = '*')
201
    {
202
        return (bool)config($this->getNamespace($key));
203
    }
204
205
    /**
206
     * Return whether an addon has
207
     * config matching any key.
208
     *
209
     * @param  array $keys
210
     * @return bool
211
     */
212
    public function hasAnyConfig(array $keys = ['*'])
213
    {
214
        foreach ($keys as $key) {
215
            if ($this->hasConfig($key)) {
216
                return true;
217
            }
218
        }
219
220
        return false;
221
    }
222
223
    /**
224
     * Get the composer json contents.
225
     *
226
     * @return mixed|null
227
     */
228
    public function getComposerJson()
229
    {
230
        $json = $this->getPath('composer.json');
231
232
        if (!file_exists($json)) {
233
            return null;
234
        }
235
236
        return json_decode(file_get_contents($json));
237
    }
238
239
    /**
240
     * @param $path
241
     * @return $this
242
     */
243
    public function setPath($path)
244
    {
245
        $this->path = $path;
246
247
        return $this;
248
    }
249
250
    /**
251
     * Get the addon path.
252
     *
253
     * @return string
254
     */
255
    public function getPath($path = null)
256
    {
257
        return $this->path . ($path ? '/' . $path : $path);
258
    }
259
260
    /**
261
     * Return the app path.
262
     *
263
     * @param null $path
264
     */
265
    public function getAppPath($path = null)
266
    {
267
        return ltrim(str_replace(base_path(), '', $this->getPath($path)), DIRECTORY_SEPARATOR);
268
    }
269
270
    /**
271
     * Set the addon slug.
272
     *
273
     * @param  $slug
274
     * @return $this
275
     */
276
    public function setSlug($slug)
277
    {
278
        $this->slug = $slug;
279
280
        return $this;
281
    }
282
283
    /**
284
     * Get the addon slug.
285
     *
286
     * @return string
287
     */
288
    public function getSlug()
289
    {
290
        return $this->slug;
291
    }
292
293
    /**
294
     * Set the addon type.
295
     *
296
     * @param  $type
297
     * @return $this
298
     */
299
    public function setType($type)
300
    {
301
        $this->type = $type;
302
303
        return $this;
304
    }
305
306
    /**
307
     * Get the addon type.
308
     *
309
     * @return string
310
     */
311
    public function getType()
312
    {
313
        return $this->type;
314
    }
315
316
    /**
317
     * Set the vendor.
318
     *
319
     * @param $vendor
320
     * @return $this
321
     */
322
    public function setVendor($vendor)
323
    {
324
        $this->vendor = $vendor;
325
326
        return $this;
327
    }
328
329
    /**
330
     * Get the vendor.
331
     *
332
     * @return string
333
     */
334
    public function getVendor()
335
    {
336
        return $this->vendor;
337
    }
338
339
    /**
340
     * Make the addon namespace.
341
     */
342
    protected function makeNamespace()
343
    {
344
        $this->namespace = "{$this->getVendor()}.{$this->getType()}.{$this->getSlug()}";
345
    }
346
347
    /**
348
     * Get a property value from the object.
349
     *
350
     * @param $name
351
     * @return mixed
352
     */
353
    public function __get($name)
354
    {
355
        $method = camel_case('get_' . $name);
356
357
        if (method_exists($this, $method)) {
358
            return $this->{$method}();
359
        }
360
361
        $method = camel_case('is_' . $name);
362
363
        if (method_exists($this, $method)) {
364
            return $this->{$method}();
365
        }
366
367
        return $this->{$name};
368
    }
369
370
    /**
371
     * Return whether a property is set or not.
372
     *
373
     * @param $name
374
     * @return bool
375
     */
376
    public function __isset($name)
377
    {
378
        $method = camel_case('get_' . $name);
379
380
        if (method_exists($this, $method)) {
381
            return true;
382
        }
383
384
        $method = camel_case('is_' . $name);
385
386
        if (method_exists($this, $method)) {
387
            return true;
388
        }
389
390
        return isset($this->{$name});
391
    }
392
393
    /**
394
     * Return the addon as a string.
395
     *
396
     * @return string
397
     */
398
    public function __toString()
399
    {
400
        return $this->getNamespace();
401
    }
402
403
    /**
404
     * Get the instance as an array.
405
     *
406
     * @return array
407
     */
408
    public function toArray()
409
    {
410
        return [
411
            'id'        => $this->getNamespace(),
412
            'name'      => $this->getName(),
413
            'namespace' => $this->getNamespace(),
414
            'type'      => $this->getType(),
415
        ];
416
    }
417
}
418