1 | <?php |
||||
2 | /** |
||||
3 | * Automation tool mixed with code generator for easier continuous development |
||||
4 | * |
||||
5 | * @link https://github.com/hiqdev/hidev |
||||
6 | * @package hidev |
||||
7 | * @license BSD-3-Clause |
||||
8 | * @copyright Copyright (c) 2015-2018, HiQDev (http://hiqdev.com/) |
||||
9 | */ |
||||
10 | |||||
11 | namespace hidev\base; |
||||
12 | |||||
13 | use hidev\helpers\FileHelper; |
||||
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\BaseObject |
||||
23 | { |
||||
24 | /** |
||||
25 | * @var Goal |
||||
0 ignored issues
–
show
|
|||||
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 | /** |
||||
103 | * Create plain file (with plain handler). |
||||
104 | * @param string $path |
||||
105 | * @return File |
||||
106 | */ |
||||
107 | public static function plain($path) |
||||
108 | { |
||||
109 | return Yii::createObject([ |
||||
110 | 'class' => get_called_class(), |
||||
111 | 'type' => 'plain', |
||||
112 | 'path' => $path, |
||||
113 | ]); |
||||
114 | } |
||||
115 | |||||
116 | public function getMinimalPath() |
||||
117 | { |
||||
118 | return Yii::getAlias($this->minimal); |
||||
119 | } |
||||
120 | |||||
121 | /** |
||||
122 | * @var array type to extension correspondance |
||||
123 | */ |
||||
124 | protected static $_extension2type = [ |
||||
125 | 'json' => 'json', |
||||
126 | 'yml' => 'yaml', /// first one is preferred |
||||
127 | 'yaml' => 'yaml', |
||||
128 | 'xml' => 'xml', |
||||
129 | 'xml.dist' => 'xml', |
||||
130 | 'gitignore' => 'gitignore', |
||||
131 | ]; |
||||
132 | |||||
133 | public function getExtensionByType($type) |
||||
134 | { |
||||
135 | static $type2extension; |
||||
136 | if ($type2extension === null) { |
||||
137 | foreach (static::$_extension2type as $e => $t) { |
||||
138 | if (!$type2extension[$t]) { |
||||
139 | $type2extension[$t] = $e; |
||||
140 | } |
||||
141 | } |
||||
142 | } |
||||
143 | |||||
144 | return $type2extension[$type]; |
||||
145 | } |
||||
146 | |||||
147 | 3 | public function getTypeByExtension($extension) |
|||
148 | { |
||||
149 | 3 | return isset(static::$_extension2type[$extension]) ? static::$_extension2type[$extension] : null; |
|||
150 | } |
||||
151 | |||||
152 | 3 | public function findType() |
|||
153 | { |
||||
154 | 3 | if ($this->type === 'plain') { |
|||
155 | return $this->type; |
||||
156 | } |
||||
157 | |||||
158 | 3 | return ($this->goal ? $this->goal->fileType : null) ?: static::getTypeByExtension($this->_extension) ?: 'template'; |
|||
0 ignored issues
–
show
The method
hidev\base\File::getTypeByExtension() is not static, but was called statically.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
159 | } |
||||
160 | |||||
161 | 3 | public function setPath($path) |
|||
162 | { |
||||
163 | 3 | $path = Yii::getAlias($path); |
|||
164 | 3 | $info = pathinfo($path); |
|||
165 | 3 | $this->_path = $path; |
|||
0 ignored issues
–
show
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 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;
}
![]() |
|||||
166 | 3 | $this->_dirname = isset($info['dirname']) ? $info['dirname'] : null; |
|||
167 | 3 | $this->_basename = isset($info['basename']) ? $info['basename'] : null; |
|||
168 | 3 | $this->_filename = isset($info['filename']) ? $info['filename'] : null; |
|||
169 | 3 | $this->_extension = isset($info['extension']) ? $info['extension'] : null; |
|||
170 | 3 | $this->type = $this->findType(); |
|||
171 | 3 | } |
|||
172 | |||||
173 | public function getAbspath() |
||||
174 | { |
||||
175 | $path = $this->getPath(); |
||||
176 | if (strncmp($path, '/', 1)) { |
||||
177 | $path = getcwd() . '/' . $path; |
||||
178 | } |
||||
179 | |||||
180 | return $path; |
||||
181 | } |
||||
182 | |||||
183 | 3 | public function getPath() |
|||
184 | { |
||||
185 | 3 | return $this->_path; |
|||
186 | } |
||||
187 | |||||
188 | public function setBasename($basename) |
||||
189 | { |
||||
190 | $this->setPath($this->_dirname . '/' . $basename); |
||||
191 | } |
||||
192 | |||||
193 | public function getBasename() |
||||
194 | { |
||||
195 | return $this->_basename; |
||||
196 | } |
||||
197 | |||||
198 | public function setDirname($dirname) |
||||
199 | { |
||||
200 | $this->setPath($dirname . '/' . $this->_basename); |
||||
201 | } |
||||
202 | |||||
203 | public function getDirname() |
||||
204 | { |
||||
205 | return $this->_dirname; |
||||
206 | } |
||||
207 | |||||
208 | public function setFilename($filename) |
||||
209 | { |
||||
210 | $this->setPath($this->_dirname . '/' . $filename . '.' . $this->_extension); |
||||
211 | } |
||||
212 | |||||
213 | public function getFilename() |
||||
214 | { |
||||
215 | return $this->_filename; |
||||
216 | } |
||||
217 | |||||
218 | public function setExtension($extension) |
||||
219 | { |
||||
220 | $this->setPath($this->_dirname . '/' . $this->_filename . '.' . $extension); |
||||
221 | } |
||||
222 | |||||
223 | public function getExtension() |
||||
224 | { |
||||
225 | return $this->_extension; |
||||
226 | } |
||||
227 | |||||
228 | 3 | public function getCtype() |
|||
229 | { |
||||
230 | 3 | return Helper::id2camel($this->type); |
|||
231 | } |
||||
232 | |||||
233 | /** |
||||
234 | * Save file. |
||||
235 | * @param mixed $data |
||||
236 | * @return bool true if file was changed |
||||
237 | */ |
||||
238 | 3 | public function save($data = null) |
|||
239 | { |
||||
240 | 3 | if ($data !== null) { |
|||
241 | 3 | $this->data = $data; |
|||
242 | } |
||||
243 | |||||
244 | 3 | return $this->getHandler()->renderPath($this->getPath(), $this->data); |
|||
0 ignored issues
–
show
The method
renderPath() does not exist on hidev\base\File . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
245 | } |
||||
246 | |||||
247 | public function write($content) |
||||
248 | { |
||||
249 | return $this->getHandler()->write($this->getPath(), $content); |
||||
0 ignored issues
–
show
The call to
hidev\base\File::write() has too many arguments starting with $content .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
250 | } |
||||
251 | |||||
252 | public function load() |
||||
253 | { |
||||
254 | return $this->data = $this->getHandler()->parsePath($this->getPath(), $this->getMinimalPath()); |
||||
0 ignored issues
–
show
The method
parsePath() does not exist on hidev\base\File . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
255 | } |
||||
256 | |||||
257 | public function read() |
||||
258 | { |
||||
259 | return $this->getHandler()->read($this->getPath()); |
||||
0 ignored issues
–
show
The call to
hidev\base\File::read() has too many arguments starting with $this->getPath() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
260 | } |
||||
261 | |||||
262 | public function readArray() |
||||
263 | { |
||||
264 | return $this->getHandler()->readArray($this->getPath()); |
||||
0 ignored issues
–
show
The call to
hidev\base\File::readArray() has too many arguments starting with $this->getPath() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
265 | } |
||||
266 | |||||
267 | 3 | public function getHandler() |
|||
268 | { |
||||
269 | 3 | if (!is_object($this->_handler)) { |
|||
270 | 3 | $this->_handler = Yii::createObject([ |
|||
271 | 3 | 'class' => 'hidev\handlers\\' . $this->getCtype() . 'Handler', |
|||
272 | 3 | 'template' => $this->template, |
|||
273 | 3 | 'goal' => $this->goal, |
|||
274 | ]); |
||||
275 | } |
||||
276 | |||||
277 | 3 | return $this->_handler; |
|||
278 | } |
||||
279 | |||||
280 | public static function file_exists($path) |
||||
281 | { |
||||
282 | return file_exists(Yii::getAlias($path)); |
||||
283 | } |
||||
284 | |||||
285 | public function exists() |
||||
286 | { |
||||
287 | return file_exists($this->getPath()); |
||||
288 | } |
||||
289 | |||||
290 | public function find(array $types = []) |
||||
291 | { |
||||
292 | if (empty($types)) { |
||||
293 | $types = $this->types; |
||||
294 | } |
||||
295 | foreach ($types as $type) { |
||||
296 | foreach (static::$_extension2type as $e => $t) { |
||||
297 | if ($t === $type) { |
||||
298 | $this->setExtension($e); |
||||
299 | if ($this->exists()) { |
||||
300 | return true; |
||||
301 | } |
||||
302 | } |
||||
303 | } |
||||
304 | } |
||||
305 | |||||
306 | return false; |
||||
307 | } |
||||
308 | |||||
309 | public function get($name) |
||||
310 | { |
||||
311 | return $this->data[$name]; |
||||
312 | } |
||||
313 | |||||
314 | public function getStat($field = null) |
||||
315 | { |
||||
316 | if ($this->_stat === null) { |
||||
317 | $this->_stat = stat($this->getPath()); |
||||
0 ignored issues
–
show
It seems like
stat($this->getPath()) can also be of type false . However, the property $_stat is declared as type array . 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 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;
}
![]() |
|||||
318 | } |
||||
319 | |||||
320 | return is_null($field) ? $this->_stat : $this->_stat[$field]; |
||||
321 | } |
||||
322 | |||||
323 | public function getUid() |
||||
324 | { |
||||
325 | return (string) $this->getStat(4); |
||||
326 | } |
||||
327 | |||||
328 | public function getOwner() |
||||
329 | { |
||||
330 | if (!isset($this->_stat['owner'])) { |
||||
331 | $this->_stat['owner'] = posix_getpwuid($this->getUid()); |
||||
0 ignored issues
–
show
$this->getUid() of type string is incompatible with the type integer expected by parameter $uid of posix_getpwuid() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
332 | } |
||||
333 | |||||
334 | return $this->getStat('owner')['name']; |
||||
335 | } |
||||
336 | |||||
337 | public function getGid() |
||||
338 | { |
||||
339 | return (string) $this->getStat(5); |
||||
340 | } |
||||
341 | |||||
342 | public function getGroup() |
||||
343 | { |
||||
344 | if (!isset($this->_stat['group'])) { |
||||
345 | $this->_stat['group'] = posix_getgrgid($this->getGid()); |
||||
0 ignored issues
–
show
$this->getGid() of type string is incompatible with the type integer expected by parameter $gid of posix_getgrgid() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
346 | } |
||||
347 | |||||
348 | return $this->getStat('group')['name']; |
||||
349 | } |
||||
350 | |||||
351 | public function getPermissions() |
||||
352 | { |
||||
353 | return static::formatOctal($this->getStat(2)); |
||||
354 | } |
||||
355 | |||||
356 | public static function formatOctal($value) |
||||
357 | { |
||||
358 | return substr(sprintf('%o', $value), -4); |
||||
359 | } |
||||
360 | |||||
361 | public function chmod($value) |
||||
362 | { |
||||
363 | $value = is_int($value) ? static::formatOctal($value) : (string) $value; |
||||
364 | if ($value === $this->getPermissions()) { |
||||
365 | return; |
||||
366 | } |
||||
367 | $path = $this->getPath(); |
||||
368 | passthru("chmod $value $path"); |
||||
369 | Yii::warning("chmod $path '$value'", 'file'); |
||||
370 | } |
||||
371 | |||||
372 | public function chown($value) |
||||
373 | { |
||||
374 | $ownergroup = $this->getOwner() . ':' . $this->getGroup(); |
||||
375 | if (in_array((string) $value, [$ownergroup, $this->getOwner(), $this->getUid()], true)) { |
||||
376 | return; |
||||
377 | } |
||||
378 | $path = $this->getPath(); |
||||
379 | passthru("chown $value $path"); |
||||
380 | Yii::warning("chown $path '$value'", 'file'); |
||||
381 | } |
||||
382 | |||||
383 | public function chgrp($value) |
||||
384 | { |
||||
385 | if (in_array((string) $value, [$this->getGroup(), $this->getGid()], true)) { |
||||
386 | return; |
||||
387 | } |
||||
388 | $path = $this->getPath(); |
||||
389 | passthru("chgrp $value $path"); |
||||
390 | Yii::warning("chgrp $path '$value'", 'file'); |
||||
391 | } |
||||
392 | |||||
393 | public function symlink($dest) |
||||
394 | { |
||||
395 | if (file_exists($dest)) { |
||||
396 | return true; |
||||
397 | } |
||||
398 | FileHelper::symlink($this->path, $dest); |
||||
0 ignored issues
–
show
The property
path does not exist on hidev\base\File . Since you implemented __get , consider adding a @property annotation.
![]() |
|||||
399 | Yii::warning("Symlinked $this->path $dest", 'file'); |
||||
400 | } |
||||
401 | } |
||||
402 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths