Completed
Pull Request — master (#6733)
by Ingo
12:10 queued 04:21
created

Module::getResourcePath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Core\Manifest;
4
5
use Exception;
6
use Serializable;
7
8
class Module implements Serializable
9
{
10
    /**
11
     * Directory
12
     *
13
     * @var string
14
     */
15
    protected $path = null;
16
17
    /**
18
     * Base folder of application
19
     *
20
     * @var string
21
     */
22
    protected $basePath = null;
23
24
    /**
25
     * Cache of composer data
26
     *
27
     * @var array
28
     */
29
    protected $composerData = null;
30
31
    public function __construct($path, $base)
32
    {
33
        $this->path = rtrim($path, '/\\');
34
        $this->basePath = rtrim($base, '/\\');
35
        $this->loadComposer();
36
    }
37
38
    /**
39
     * Gets name of this module. Used as unique key and identifier for this module.
40
     *
41
     * If installed by composer, this will be the full composer name (vendor/name).
42
     * If not insalled by composer this will default to the basedir()
43
     *
44
     * @return string
45
     */
46
    public function getName()
47
    {
48
        return $this->getComposerName() ?: $this->getShortName();
49
    }
50
51
    /**
52
     * Get full composer name. Will be null if no composer.json is available
53
     *
54
     * @return string|null
55
     */
56
    public function getComposerName()
57
    {
58
        if (isset($this->composerData['name'])) {
59
            return $this->composerData['name'];
60
        }
61
        return null;
62
    }
63
64
    /**
65
     * Gets "short" name of this module. This is the base directory this module
66
     * is installed in.
67
     *
68
     * If installed in root, this will be generated from the composer name instead
69
     *
70
     * @return string
71
     */
72
    public function getShortName()
73
    {
74
        // If installed in the root directory we need to infer from composer
75
        if ($this->path === $this->basePath && $this->composerData) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->composerData of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
76
            // Sometimes we customise installer name
77
            if (isset($this->composerData['extra']['installer-name'])) {
78
                return $this->composerData['extra']['installer-name'];
79
            }
80
81
            // Strip from full composer name
82
            $composerName = $this->getComposerName();
83
            if ($composerName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $composerName of type string|null is loosely compared to true; 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...
84
                list(, $name) = explode('/', $composerName);
85
                return $name;
86
            }
87
        }
88
89
        // Base name of directory
90
        return basename($this->path);
91
    }
92
93
    /**
94
     * Get base path for this module
95
     *
96
     * @return string
97
     */
98
    public function getPath()
99
    {
100
        return $this->path;
101
    }
102
103
    /**
104
     * Get path relative to base dir.
105
     * If module path is base this will be empty string
106
     *
107
     * @return string
108
     */
109
    public function getRelativePath()
110
    {
111
        return ltrim(substr($this->path, strlen($this->basePath)), '/\\');
112
    }
113
114
    public function serialize()
115
    {
116
        return json_encode([$this->path, $this->basePath, $this->composerData]);
117
    }
118
119
    public function unserialize($serialized)
120
    {
121
        list($this->path, $this->basePath, $this->composerData) = json_decode($serialized, true);
122
    }
123
124
    /**
125
     * Activate _config.php for this module, if one exists
126
     */
127
    public function activate()
128
    {
129
        $config = "{$this->path}/_config.php";
130
        if (file_exists($config)) {
131
            require_once $config;
132
        }
133
    }
134
135
    /**
136
     * @throws Exception
137
     */
138
    protected function loadComposer()
139
    {
140
        // Load composer data
141
        $path = "{$this->path}/composer.json";
142
        if (file_exists($path)) {
143
            $content = file_get_contents($path);
144
            $result = json_decode($content, true);
145
            if (json_last_error()) {
146
                throw new Exception(json_last_error_msg());
147
            }
148
            $this->composerData = $result;
0 ignored issues
show
Documentation Bug introduced by
It seems like $result of type * is incompatible with the declared type array of property $composerData.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
149
        }
150
    }
151
152
    /**
153
     * Gets path to physical file resource relative to base directory.
154
     * Directories included
155
     *
156
     * This method makes no distinction between public / local resources,
157
     * which may change in the near future.
158
     *
159
     * @internal Experimental API and may change
160
     * @param string $path File or directory path relative to module directory
161
     * @return string Path relative to base directory
162
     */
163
    public function getResourcePath($path)
164
    {
165
        $base = rtrim($this->getRelativePath(), '/\\');
166
        $path = rtrim($path, '/\\');
167
        return "{$base}/{$path}";
168
    }
169
170
    /**
171
     * Check if this module has a given resource
172
     *
173
     * @internal Experimental API and may change
174
     * @param string $path
175
     * @return bool
176
     */
177
    public function hasResource($path)
178
    {
179
        $resource = $this->getResourcePath($path);
180
        return file_exists($this->basePath . '/' . $resource);
181
    }
182
}
183