Completed
Pull Request — master (#43)
by Jitendra
02:09
created

Path::read()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 1
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the PHINT package.
5
 *
6
 * (c) Jitendra Adhikari <[email protected]>
7
 *     <https://github.com/adhocore>
8
 *
9
 * Licensed under MIT license.
10
 */
11
12
namespace Ahc\Phint\Util;
13
14
use Ahc\Json\Comment;
15
use Symfony\Component\Finder\Finder;
16
17
class Path
18
{
19
    /** @var string */
20
    protected $phintPath;
21
22
    /**
23
     * Platform agnostic absolute path detection.
24
     *
25
     * @param string $path
26
     *
27
     * @return bool
28
     */
29
    public function isAbsolute(string $path): bool
30
    {
31
        if (\DIRECTORY_SEPARATOR === '\\') {
32
            return strpos($path, ':') === 1;
33
        }
34
35
        return isset($path[0]) && $path[0] === '/';
36
    }
37
38
    public function getRelativePath($fullPath, $basePath): string
39
    {
40
        if (strpos($fullPath, $basePath) === 0) {
41
            return substr($fullPath, strlen($basePath));
42
        }
43
44
        // Hmm!
45
        return $fullPath;
46
    }
47
48
    public function ensureDir(string $dir): bool
49
    {
50
        if (!\is_dir($dir)) {
51
            return \mkdir($dir, 0777, true);
52
        }
53
54
        return true;
55
    }
56
57
    public function getExtension(string $filePath): string
58
    {
59
        return \pathinfo($filePath, \PATHINFO_EXTENSION);
60
    }
61
62
    public function readAsJson(string $filePath, bool $asArray = true)
63
    {
64
        return (new Comment)->decode($this->read($filePath) ?? 'null', $asArray);
65
    }
66
67
    public function read(string $filePath): ?string
68
    {
69
        if (\is_file($filePath)) {
70
            return \file_get_contents($filePath);
71
        }
72
73
        return null;
74
    }
75
76
    public function writeFile(string $file, $content, int $mode = null): bool
77
    {
78
        $this->ensureDir(\dirname($file));
79
80
        if (!\is_string($content)) {
81
            $content = \json_encode($content, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES);
82
        }
83
84
        return \file_put_contents($file, $content, $mode) > 0;
85
    }
86
87
    public function getPhintPath(string $subpath = ''): string
88
    {
89
        $this->initPhintPath();
90
91
        if ($subpath && $this->phintPath) {
92
            return $this->phintPath . '/' . \ltrim($subpath, '/');
93
        }
94
95
        return $this->phintPath;
96
    }
97
98
    public function createBinaries(array $bins, string $basePath)
99
    {
100
        foreach ($bins as $bin) {
101
            $bin = $this->join($basePath, $bin);
102
103
            if ($this->writeFile($bin, "#!/usr/bin/env php\n<?php\n")) {
104
                @\chmod($bin, 0755);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for chmod(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

104
                /** @scrutinizer ignore-unhandled */ @\chmod($bin, 0755);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
105
            }
106
        }
107
    }
108
109
    public function join(...$paths): string
110
    {
111
        if (\is_array($paths[0] ?? '')) {
112
            $paths = $paths[0];
113
        }
114
115
        $join = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $join is dead and can be removed.
Loading history...
116
        foreach ($paths as $i => &$path) {
117
            $path = $i === 0 ? \rtrim($path, '\\/') : \trim($path, '\\/');
118
        }
119
120
        return \implode('/', $paths);
121
    }
122
123
    public function findFiles(array $inPaths, string $ext, bool $dotfiles = false): array
124
    {
125
        $finder = new Finder;
126
127
        if ($ext !== '*') {
128
            $ext = '.' . \ltrim($ext, '.');
129
            $len = \strlen($ext);
130
131
            $finder->filter(function ($file) use ($ext, $len) {
132
                return \substr($file, -$len) === $ext;
133
            });
134
        }
135
136
        foreach ($inPaths as $path) {
137
            $finder->in($path);
138
        }
139
140
        $files = [];
141
        foreach ($finder->files()->ignoreDotFiles($dotfiles) as $file) {
142
            $files[] = (string) $file;
143
        }
144
145
        return $files;
146
    }
147
148
    public function loadClasses(array $inPaths, array $namespaces, string $ext = 'php'): array
149
    {
150
        foreach ($this->findFiles($inPaths, $ext) as $file) {
151
            _require($file);
152
        }
153
154
        $namespaces = \implode('\|', $namespaces);
155
        $allClasses = \array_merge(\get_declared_interfaces(), \get_declared_classes(), \get_declared_traits());
156
157
        return \preg_grep('~^' . \preg_quote($namespaces) . '~', $allClasses);
158
    }
159
160
    protected function initPhintPath()
161
    {
162
        if (null !== $this->phintPath) {
163
            return;
164
        }
165
166
        $this->phintPath = '';
167
168
        if (false !== $home = ($_SERVER['HOME'] ?? \getenv('HOME'))) {
169
            $path = \rtrim($home, '/') . '/.phint';
170
171
            if ($this->ensureDir($path)) {
172
                $this->phintPath = $path;
173
            }
174
        }
175
    }
176
}
177
178
/**
179
 * Isolated file require.
180
 *
181
 * @param string $file
182
 *
183
 * @return void
184
 */
185
function _require(string $file)
186
{
187
    require_once $file;
188
}
189