annotate vendor/psy/psysh/src/ConfigPaths.php @ 4:a9cd425dd02b

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