Completed
Push — master ( e0cd62...080a96 )
by Andrii
03:16
created

File::formatOctal()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 2
1
<?php
2
3
/*
4
 * Task runner, code generator and build tool for easier continuos integration
5
 *
6
 * @link      https://github.com/hiqdev/hidev
7
 * @package   hidev
8
 * @license   BSD-3-Clause
9
 * @copyright Copyright (c) 2015-2016, HiQDev (http://hiqdev.com/)
10
 */
11
12
namespace hidev\base;
13
14
use hidev\helpers\Helper;
15
use Yii;
16
17
/**
18
 * A file to be processed with hidev.
19
 *
20
 * @property string $minimalPath path to minimal example file
21
 */
22
class File extends \yii\base\Object
23
{
24
    /**
25
     * @var Goal
26
     */
27
    public $goal;
28
29
    /**
30
     * @var file hanler: renderer and parser
31
     */
32
    protected $_handler;
33
34
    /**
35
     * @var string absolute path
36
     */
37
    protected $_path;
38
39
    /**
40
     * @var string directory
41
     */
42
    protected $_dirname;
43
44
    /**
45
     * @var string name with extension
46
     */
47
    protected $_basename;
48
49
    /**
50
     * @var string name only, without extension
51
     */
52
    protected $_filename;
53
54
    /**
55
     * @var string extension
56
     */
57
    protected $_extension;
58
59
    /**
60
     * @var array file stat
61
     */
62
    protected $_stat;
63
64
    /**
65
     * @var array possible types
66
     */
67
    public $types = [];
68
69
    /**
70
     * @var string type
71
     */
72
    public $type;
73
74
    /**
75
     * @var string template
76
     */
77
    public $template;
78
79
    /**
80
     * @var mixed data
81
     */
82
    protected $data;
83
84
    /**
85
     * @var string path to minimal example file
86
     */
87
    public $minimal;
88
89
    /**
90
     * Create file object.
91
     * @param string|array $path or config
92
     * @return File
93
     */
94
    public static function create($path)
95
    {
96
        $config = is_array($path) ? $path : compact('path');
97
        $config['class'] = get_called_class();
98
99
        return Yii::createObject($config);
100
    }
101
102
    public function getMinimalPath()
103
    {
104
        return Yii::getAlias($this->minimal);
105
    }
106
107
    /**
108
     * @var array type to extension correspondance
109
     */
110
    protected static $_extension2type = [
111
        'json'      => 'json',
112
        'yml'       => 'yaml',  /// first one is preferred
113
        'yaml'      => 'yaml',
114
        'xml'       => 'xml',
115
        'xml.dist'  => 'xml',
116
    ];
117
118
    public function getExtensionByType($type)
119
    {
120
        static $type2extension;
121
        if ($type2extension === null) {
122
            foreach (static::$_extension2type as $e => $t) {
123
                if (!$type2extension[$t]) {
124
                    $type2extension[$t] = $e;
125
                }
126
            }
127
        }
128
129
        return $type2extension[$type];
130
    }
131
132
    public function getTypeByExtension($extension)
133
    {
134
        return static::$_extension2type[$extension];
135
    }
136
137
    public function findType()
138
    {
139
        return ($this->goal ? $this->goal->fileType : null) ?: static::getTypeByExtension($this->_extension) ?: 'template';
140
    }
141
142
    public function setPath($path)
143
    {
144
        $path             = Yii::getAlias($path);
145
        $info             = pathinfo($path);
146
        $this->_path      = $path;
0 ignored issues
show
Documentation Bug introduced by
It seems like $path can also be of type boolean. However, the property $_path is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
147
        $this->_dirname   = $info['dirname'];
148
        $this->_basename  = $info['basename'];
149
        $this->_filename  = $info['filename'];
150
        $this->_extension = $info['extension'];
151
        $this->type       = $this->findType();
152
    }
153
154
    public function getPath()
155
    {
156
        return $this->_path;
157
    }
158
159
    public function setBasename($basename)
160
    {
161
        $this->setPath($this->_dirname . '/' . $basename);
162
    }
163
164
    public function getBasename()
165
    {
166
        return $this->_basename;
167
    }
168
169
    public function setDirname($dirname)
170
    {
171
        $this->setPath($dirname . '/' . $this->_basename);
172
    }
173
174
    public function getDirname()
175
    {
176
        return $this->_dirname;
177
    }
178
179
    public function setFilename($filename)
180
    {
181
        $this->setPath($this->_dirname . '/' . $filename . '.' . $this->_extension);
182
    }
183
184
    public function getFilename()
185
    {
186
        return $this->_filename;
187
    }
188
189
    public function setExtension($extension)
190
    {
191
        $this->setPath($this->_dirname . '/' . $this->_filename . '.' . $extension);
192
    }
193
194
    public function getExtension()
195
    {
196
        return $this->_extension;
197
    }
198
199
    public function getCtype()
200
    {
201
        return Helper::id2camel($this->type);
202
    }
203
204
    /**
205
     * Save file.
206
     * @param mixed $data
207
     * @return bool true if file was changed
208
     */
209
    public function save($data = null)
210
    {
211
        if ($data !== null) {
212
            $this->data = $data;
213
        }
214
215
        return $this->getHandler()->renderPath($this->getPath(), $this->data);
216
    }
217
218
    public function write($content)
219
    {
220
        return $this->getHandler()->write($this->getPath(), $content);
221
    }
222
223
    public function load()
224
    {
225
        return $this->data = $this->getHandler()->parsePath($this->getPath(), $this->getMinimalPath());
226
    }
227
228
    public function read()
229
    {
230
        return $this->getHandler()->read($this->getPath());
231
    }
232
233
    public function readArray()
234
    {
235
        return $this->getHandler()->readArray($this->getPath());
236
    }
237
238
    public function getHandler()
239
    {
240
        if (!is_object($this->_handler)) {
241
            $this->_handler = Yii::createObject([
242
                'class'    => 'hidev\handlers\\' . $this->getCtype() . 'Handler',
243
                'template' => $this->template,
244
                'goal'     => $this->goal,
245
            ]);
246
        }
247
248
        return $this->_handler;
249
    }
250
251
    public static function file_exists($path)
252
    {
253
        return file_exists(Yii::getAlias($path));
254
    }
255
256
    public function exists()
257
    {
258
        return file_exists($this->getPath());
259
    }
260
261
    public function find(array $types = [])
262
    {
263
        if (empty($types)) {
264
            $types = $this->types;
265
        }
266
        foreach ($types as $type) {
267
            foreach (static::$_extension2type as $e => $t) {
268
                if ($t === $type) {
269
                    $this->setExtension($e);
270
                    if ($this->exists()) {
271
                        return true;
272
                    }
273
                }
274
            }
275
        }
276
277
        return false;
278
    }
279
280
    public function get($name)
281
    {
282
        return $this->data[$name];
283
    }
284
285
    public function getStat($field = null)
286
    {
287
        if ($this->_stat === null) {
288
            $this->_stat = stat($this->getPath());
289
        }
290
291
        return is_null($field) ? $this->_stat : $this->_stat[$field];
292
    }
293
294
    public function getUid()
295
    {
296
        return (string) $this->getStat(4);
297
    }
298
299 View Code Duplication
    public function getOwner()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
300
    {
301
        if (!isset($this->_stat['owner'])) {
302
            $this->_stat['owner'] = posix_getpwuid($this->getUid());
303
        }
304
305
        return $this->getStat('owner')['name'];
306
    }
307
308
    public function getGid()
309
    {
310
        return (string) $this->getStat(5);
311
    }
312
313 View Code Duplication
    public function getGroup()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
314
    {
315
        if (!isset($this->_stat['group'])) {
316
            $this->_stat['group'] = posix_getgrgid($this->getGid());
317
        }
318
319
        return $this->getStat('group')['name'];
320
    }
321
322
    public function getPermissions()
323
    {
324
        return static::formatOctal($this->getStat(2));
325
    }
326
327
    public static function formatOctal($value)
328
    {
329
        return substr(sprintf('%o', $value), -4);
330
    }
331
332
    public function chmod($value)
333
    {
334
        $value = is_int($value) ? static::formatOctal($value) : (string) $value;
335
        if ($value === $this->getPermissions()) {
336
            return;
337
        }
338
        $path = $this->getPath();
339
        passthru("chmod $value $path");
340
        Yii::warning("chmod $path '$value'", 'file');
341
    }
342
343
    public function chown($value)
344
    {
345
        $ownergroup = $this->getOwner() . ':' . $this->getGroup();
346
        if (in_array((string) $value, [$ownergroup, $this->getOwner(), $this->getUid()], true)) {
347
            return;
348
        }
349
        $path = $this->getPath();
350
        passthru("chown $value $path");
351
        Yii::warning("chown $path '$value'", 'file');
352
    }
353
354
    public function chgrp($value)
355
    {
356
        if (in_array((string) $value, [$this->getGroup(), $this->getGid()], true)) {
357
            return;
358
        }
359
        $path = $this->getPath();
360
        passthru("chgrp $value $path");
361
        Yii::warning("chgrp $path '$value'", 'file');
362
    }
363
}
364