6672491992043db4a3be9957eb8d9f5a9b487402
[yaffs-website] / vendor / psy / psysh / src / Psy / ConfigPaths.php
1 <?php
2
3 /*
4  * This file is part of Psy Shell.
5  *
6  * (c) 2012-2017 Justin Hileman
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Psy;
13
14 use XdgBaseDir\Xdg;
15
16 /**
17  * A Psy Shell configuration path helper.
18  */
19 class ConfigPaths
20 {
21     /**
22      * Get potential config directory paths.
23      *
24      * Returns `~/.psysh`, `%APPDATA%/PsySH` (when on Windows), and all
25      * XDG Base Directory config directories:
26      *
27      *     http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
28      *
29      * @return string[]
30      */
31     public static function getConfigDirs()
32     {
33         $xdg = new Xdg();
34
35         return self::getDirNames($xdg->getConfigDirs());
36     }
37
38     /**
39      * Get potential home config directory paths.
40      *
41      * Returns `~/.psysh`, `%APPDATA%/PsySH` (when on Windows), and the
42      * XDG Base Directory home config directory:
43      *
44      *     http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
45      *
46      * @return string[]
47      */
48     public static function getHomeConfigDirs()
49     {
50         $xdg = new Xdg();
51
52         return self::getDirNames(array($xdg->getHomeConfigDir()));
53     }
54
55     /**
56      * Get the current home config directory.
57      *
58      * Returns the highest precedence home config directory which actually
59      * exists. If none of them exists, returns the highest precedence home
60      * config directory (`%APPDATA%/PsySH` on Windows, `~/.config/psysh`
61      * everywhere else).
62      *
63      * @see self::getHomeConfigDirs
64      *
65      * @return string
66      */
67     public static function getCurrentConfigDir()
68     {
69         $configDirs = self::getHomeConfigDirs();
70         foreach ($configDirs as $configDir) {
71             if (@is_dir($configDir)) {
72                 return $configDir;
73             }
74         }
75
76         return $configDirs[0];
77     }
78
79     /**
80      * Find real config files in config directories.
81      *
82      * @param string[] $names     Config file names
83      * @param string   $configDir Optionally use a specific config directory
84      *
85      * @return string[]
86      */
87     public static function getConfigFiles(array $names, $configDir = null)
88     {
89         $dirs = ($configDir === null) ? self::getConfigDirs() : array($configDir);
90
91         return self::getRealFiles($dirs, $names);
92     }
93
94     /**
95      * Get potential data directory paths.
96      *
97      * If a `dataDir` option was explicitly set, returns an array containing
98      * just that directory.
99      *
100      * Otherwise, it returns `~/.psysh` and all XDG Base Directory data directories:
101      *
102      *     http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
103      *
104      * @return string[]
105      */
106     public static function getDataDirs()
107     {
108         $xdg = new Xdg();
109
110         return self::getDirNames($xdg->getDataDirs());
111     }
112
113     /**
114      * Find real data files in config directories.
115      *
116      * @param string[] $names   Config file names
117      * @param string   $dataDir Optionally use a specific config directory
118      *
119      * @return string[]
120      */
121     public static function getDataFiles(array $names, $dataDir = null)
122     {
123         $dirs = ($dataDir === null) ? self::getDataDirs() : array($dataDir);
124
125         return self::getRealFiles($dirs, $names);
126     }
127
128     /**
129      * Get a runtime directory.
130      *
131      * Defaults to  `/psysh` inside the system's temp dir.
132      *
133      * @return string
134      */
135     public static function getRuntimeDir()
136     {
137         $xdg = new Xdg();
138
139         set_error_handler(array('Psy\Exception\ErrorException', 'throwException'));
140
141         try {
142             // XDG doesn't really work on Windows, sometimes complains about
143             // permissions, sometimes tries to remove non-empty directories.
144             // It's a bit flaky. So we'll give this a shot first...
145             $runtimeDir = $xdg->getRuntimeDir(false);
146         } catch (\Exception $e) {
147             // Well. That didn't work. Fall back to a boring old folder in the
148             // system temp dir.
149             $runtimeDir = sys_get_temp_dir();
150         }
151
152         restore_error_handler();
153
154         return strtr($runtimeDir, '\\', '/') . '/psysh';
155     }
156
157     private static function getDirNames(array $baseDirs)
158     {
159         $dirs = array_map(function ($dir) {
160             return strtr($dir, '\\', '/') . '/psysh';
161         }, $baseDirs);
162
163         // Add ~/.psysh
164         if ($home = getenv('HOME')) {
165             $dirs[] = strtr($home, '\\', '/') . '/.psysh';
166         }
167
168         // Add some Windows specific ones :)
169         if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
170             if ($appData = getenv('APPDATA')) {
171                 // AppData gets preference
172                 array_unshift($dirs, strtr($appData, '\\', '/') . '/PsySH');
173             }
174
175             $dir = strtr(getenv('HOMEDRIVE') . '/' . getenv('HOMEPATH'), '\\', '/') . '/.psysh';
176             if (!in_array($dir, $dirs)) {
177                 $dirs[] = $dir;
178             }
179         }
180
181         return $dirs;
182     }
183
184     private static function getRealFiles(array $dirNames, array $fileNames)
185     {
186         $files = array();
187         foreach ($dirNames as $dir) {
188             foreach ($fileNames as $name) {
189                 $file = $dir . '/' . $name;
190                 if (@is_file($file)) {
191                     $files[] = $file;
192                 }
193             }
194         }
195
196         return $files;
197     }
198
199     /**
200      * Ensure that $file exists and is writable, make the parent directory if necessary.
201      *
202      * Generates E_USER_NOTICE error if either $file or its directory is not writable.
203      *
204      * @param string $file
205      *
206      * @return string|false Full path to $file, or false if file is not writable
207      */
208     public static function touchFileWithMkdir($file)
209     {
210         if (file_exists($file)) {
211             if (is_writable($file)) {
212                 return $file;
213             }
214
215             trigger_error(sprintf('Writing to %s is not allowed.', $file), E_USER_NOTICE);
216
217             return false;
218         }
219
220         $dir = dirname($file);
221
222         if (!is_dir($dir)) {
223             // Just try making it and see if it works
224             @mkdir($dir, 0700, true);
225         }
226
227         if (!is_dir($dir) || !is_writable($dir)) {
228             trigger_error(sprintf('Writing to %s is not allowed.', $dir), E_USER_NOTICE);
229
230             return false;
231         }
232
233         touch($file);
234
235         return $file;
236     }
237 }