Completed
Branch master (893650)
by Markus
04:08
created

Package::__construct()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 7
Bugs 0 Features 0
Metric Value
cc 3
eloc 10
nc 3
nop 1
dl 0
loc 14
rs 9.4285
c 7
b 0
f 0
ccs 11
cts 11
cp 1
crap 3
1
<?php
2
3
namespace SSpkS\Package;
4
5
/**
6
 * SPK Package class
7
 *
8
 * @property string $spk Path to SPK file
9
 * @property string $spk_url URL to SPK file
10
 * @property string $displayname Pretty printed name of package (falls back to $package if not present)
11
 * @property string $package Package name
12
 * @property string $version Package version
13
 * @property string $description Package description
14
 * @property string $maintainer Package maintainer
15
 * @property string $maintainer_url URL of maintainer's web page
16
 * @property string $distributor Package distributor
17
 * @property string $distributor_url URL of distributor's web page
18
 * @property array $arch List of supported architectures, or 'noarch'
19
 * @property array $thumbnail List of thumbnail files
20
 * @property array $thumbnail_url List of thumbnail URLs
21
 * @property array $snapshot List of screenshot files
22
 * @property array $snapshot_url List of screenshot URLs
23
 * @property bool $beta TRUE if this is a beta package.
24
 * @property string $firmware Minimum firmware needed on device.
25
 * @property string $install_dep_services Dependencies required by this package.
26
 * @property bool $silent_install Allow silent install
27
 * @property bool $silent_uninstall Allow silent uninstall
28
 * @property bool $silent_upgrade Allow silent upgrade
29
 */
30
class Package
31
{
32
    private $filepath;
33
    private $filepathNoExt;
34
    private $filename;
35
    private $filenameNoExt;
36
    private $metafile;
37
    private $metadata;
38
39
    /**
40
     * @param string $filename Filename of SPK file
41
     */
42 17
    public function __construct($filename)
43
    {
44 17
        if (!preg_match('/\.spk$/', $filename)) {
45 1
            throw new \Exception('File ' . $filename . ' doesn\'t have .spk extension!');
46
        }
47 16
        if (!file_exists($filename)) {
48 1
            throw new \Exception('File ' . $filename . ' not found!');
49
        }
50 15
        $this->filepath      = $filename;
51 15
        $this->filepathNoExt = substr($filename, 0, -4);
52 15
        $this->filename      = basename($filename);
53 15
        $this->filenameNoExt = basename($filename, '.spk');
54 15
        $this->metafile      = $this->filepathNoExt . '.nfo';
55 15
    }
56
57
    /**
58
     * Getter magic method.
59
     *
60
     * @param string $name Name of requested value.
61
     * @return mixed Requested value.
62
     */
63 10
    public function __get($name)
64
    {
65 10
        $this->collectMetadata();
66 10
        return $this->metadata[$name];
67
    }
68
69
    /**
70
     * Setter magic method.
71
     *
72
     * @param string $name Name of variable to set.
73
     * @param mixed $value Value to set.
74
     */
75 5
    public function __set($name, $value)
76
    {
77 5
        $this->collectMetadata();
78 5
        $this->metadata[$name] = $value;
79 5
    }
80
81
    /**
82
     * Isset feature magic method.
83
     *
84
     * @param string $name Name of requested value.
85
     * @return bool TRUE if value exists, FALSE otherwise.
86
     */
87 6
    public function __isset($name)
88
    {
89 6
        $this->collectMetadata();
90 6
        return isset($this->metadata[$name]);
91
    }
92
93
    /**
94
     * Unset feature magic method.
95
     *
96
     * @param string $name Name of value to unset.
97
     */
98 1
    public function __unset($name)
99
    {
100 1
        $this->collectMetadata();
101 1
        unset($this->metadata[$name]);
102 1
    }
103
104
    /**
105
     * Parses boolean value ('yes', '1', 'true') into
106
     * boolean type.
107
     *
108
     * @param mixed $value Input value
109
     * @return bool Boolean interpretation of $value.
110
     */
111 8
    public function parseBool($value)
112
    {
113 8
        return in_array($value, array('true', 'yes', '1', 1));
114
    }
115
116
    /**
117
     * Checks if given property $prop exists and converts it
118
     * into a boolean value.
119
     *
120
     * @param string $prop Property to convert
121
     */
122 12
    private function fixBoolIfExist($prop)
123
    {
124 12
        if (isset($this->metadata[$prop])) {
125 8
            $this->metadata[$prop] = $this->parseBool($this->metadata[$prop]);
126 8
        }
127 12
    }
128
129
    /**
130
     * Gathers metadata from package. Extracts INFO file if neccessary.
131
     */
132 12
    private function collectMetadata()
133
    {
134 12
        if (!is_null($this->metadata)) {
135
            // metadata already collected
136 11
            return;
137
        }
138 12
        $this->extractIfMissing('INFO', $this->metafile);
139 12
        $this->metadata = parse_ini_file($this->metafile);
140 12
        if (!isset($this->metadata['displayname'])) {
141 12
            $this->metadata['displayname'] = $this->metadata['package'];
142 12
        }
143 12
        $this->metadata['spk'] = $this->filepath;
144
145
        // Convert architecture(s) to array, as multiple architectures can be specified
146 12
        $this->metadata['arch'] = explode(' ', $this->metadata['arch']);
147
148 12
        $this->fixBoolIfExist('silent_install');
149 12
        $this->fixBoolIfExist('silent_uninstall');
150 12
        $this->fixBoolIfExist('silent_upgrade');
151
152 12
        if (isset($this->metadata['beta']) && in_array($this->metadata['beta'], array('true', '1', 'beta'))) {
153 4
            $this->metadata['beta'] = true;
154 4
        } else {
155 12
            $this->metadata['beta'] = false;
156
        }
157
158 12
        $this->metadata['thumbnail'] = $this->getThumbnails();
159 12
        $this->metadata['snapshot']  = $this->getSnapshots();
160 12
    }
161
162
    /**
163
     * Returns metadata for this package.
164
     *
165
     * @return array Metadata.
166
     */
167 3
    public function getMetadata()
168
    {
169 3
        $this->collectMetadata();
170 3
        return $this->metadata;
171
    }
172
173
    /**
174
     * Extracts $inPkgName from package to $targetFile, if it doesn't
175
     * already exist. Needs the phar.so extension and allow_url_fopen.
176
     *
177
     * @param string $inPkgName Filename in package
178
     * @param string $targetFile Path to destination
179
     * @throws \Exception if the file couldn't get extracted.
180
     * @return bool TRUE if successful or no action needed.
181
     */
182 13
    public function extractIfMissing($inPkgName, $targetFile)
183
    {
184 13
        if (file_exists($targetFile)) {
185
            // Everything in working order
186 1
            return true;
187
        }
188
        // Try to extract file
189 13
        $tmp_dir = sys_get_temp_dir();
190 13
        $p = new \PharData($this->filepath, \Phar::CURRENT_AS_FILEINFO | \Phar::KEY_AS_FILENAME);
191 13
        $p->extractTo($tmp_dir, $inPkgName);
192 13
        rename($tmp_dir . DIRECTORY_SEPARATOR . $inPkgName, $targetFile);
193 13
        return true;
194
    }
195
196
    /**
197
     * Returns a list of thumbnails for the specified package.
198
     *
199
     * @param string $pathPrefix Prefix to put before file path
200
     * @return array List of thumbnail urls
201
     */
202 12
    public function getThumbnails($pathPrefix = '')
203
    {
204
        try {
205 12
            $this->extractIfMissing('PACKAGE_ICON.PNG', $this->filepathNoExt . '_thumb_72.png');
206 12
        } catch (\Exception $e) {
207
            // Check if icon is in metadata
208 9
            $this->collectMetadata();
209 9
            if (isset($this->metadata['package_icon'])) {
210 9
                file_put_contents($this->filepathNoExt . '_thumb_72.png', base64_decode($this->metadata['package_icon']));
211 9
            }
212
        }
213 12
        $thumbnails = array();
214 12
        foreach (array('72', '120') as $size) {
215 12
            $thumb_name = $this->filepathNoExt . '_thumb_' . $size . '.png';
216
            // Use $size px thumbnail, if available
217 12
            if (file_exists($thumb_name)) {
218 12
                $thumbnails[] = $pathPrefix . $thumb_name;
219 12
            } else {
220 12
                $thumbnails[] = $pathPrefix . dirname($thumb_name) . '/default_package_icon_' . $size . '.png';
221
            }
222 12
        }
223 12
        return $thumbnails;
224
    }
225
226
    /**
227
     * Returns a list of screenshots for the specified package.
228
     *
229
     * @param string $pathPrefix Prefix to put before file path
230
     * @return array List of screenshots
231
     */
232 12
    public function getSnapshots($pathPrefix = '')
233
    {
234 12
        $snapshots = array();
235
        // Add screenshots, if available
236 12
        foreach (glob($this->filepathNoExt . '*_screen_*.png') as $snapshot) {
237 7
            $snapshots[] = $pathPrefix . $snapshot;
238 12
        }
239 12
        return $snapshots;
240
    }
241
242
    /**
243
     * Checks compatibility to the given $arch-itecture.
244
     *
245
     * @param string $arch Architecture to check against (or "noarch")
246
     * @return bool TRUE if compatible, otherwise FALSE.
247
     */
248 1
    public function isCompatibleToArch($arch)
249
    {
250
        // Make sure we have metadata available
251 1
        $this->collectMetadata();
252 1
        return (in_array($arch, $this->metadata['arch']) || in_array('noarch', $this->metadata['arch']));
253
    }
254
255
    /**
256
     * Checks compatibility to the given firmware $version.
257
     *
258
     * @param string $version Target firmware version.
259
     * @return bool TRUE if compatible, otherwise FALSE.
260
     */
261 1
    public function isCompatibleToFirmware($version)
262
    {
263 1
        $this->collectMetadata();
264 1
        return version_compare($this->metadata['firmware'], $version, '<=');
265
    }
266
267
    /**
268
     * Checks if this package is a beta version or not.
269
     *
270
     * @return bool TRUE if this is a beta version, FALSE otherwise.
271
     */
272 1
    public function isBeta()
273
    {
274 1
        $this->collectMetadata();
275 1
        return (isset($this->metadata['beta']) && $this->metadata['beta'] == true);
276
    }
277
}
278