123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- <?php
- /**
- * Application file system directories dictionary.
- *
- * Provides information about what directories are available in the application.
- * Serves as a customization point to specify different directories or add your own.
- *
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\Framework\Filesystem;
- /**
- * A list of directories
- *
- * Each list item consists of:
- * - a directory path in the filesystem
- * - optionally, a URL path
- *
- * This object is intended to be immutable (a "value object").
- * The defaults are pre-defined and can be modified only by inheritors of this class.
- * Through the constructor, it is possible to inject custom paths or URL paths, but impossible to inject new types.
- */
- class DirectoryList
- {
- /**#@+
- * Keys of directory configuration
- */
- const PATH = 'path';
- const URL_PATH = 'uri';
- /**#@- */
- /**
- * System base temporary directory
- */
- const SYS_TMP = 'sys_tmp';
- /**
- * Root path
- *
- * @var string
- */
- private $root;
- /**
- * Directories configurations
- *
- * @var array
- */
- private $directories;
- /**
- * Predefined types/paths
- *
- * @return array
- */
- public static function getDefaultConfig()
- {
- return [self::SYS_TMP => [self::PATH => '']];
- }
- /**
- * Validates format and contents of given configuration
- *
- * @param array $config
- * @return void
- * @throws \InvalidArgumentException
- */
- public static function validate($config)
- {
- if (!is_array($config)) {
- throw new \InvalidArgumentException('Unexpected value type.');
- }
- $defaultConfig = static::getDefaultConfig();
- foreach ($config as $type => $row) {
- if (!is_array($row)) {
- throw new \InvalidArgumentException('Unexpected value type.');
- }
- if (!isset($defaultConfig[$type])) {
- throw new \InvalidArgumentException("Unknown type: {$type}");
- }
- if (!isset($row[self::PATH]) && !isset($row[self::URL_PATH])) {
- throw new \InvalidArgumentException("Missing required keys at: {$type}");
- }
- }
- }
- /**
- * Constructor
- *
- * @param string $root
- * @param array $config
- */
- public function __construct($root, array $config = [])
- {
- static::validate($config);
- $this->root = $this->normalizePath($root);
- $this->directories = static::getDefaultConfig();
- $this->directories[self::SYS_TMP] = [self::PATH => realpath(sys_get_temp_dir())];
- // inject custom values from constructor
- foreach ($this->directories as $code => $dir) {
- foreach ([self::PATH, self::URL_PATH] as $key) {
- if (isset($config[$code][$key])) {
- $this->directories[$code][$key] = $config[$code][$key];
- }
- }
- }
- // filter/validate values
- foreach ($this->directories as $code => $dir) {
- $path = $this->normalizePath($dir[self::PATH]);
- if (!$this->isAbsolute($path)) {
- $path = $this->prependRoot($path);
- }
- $this->directories[$code][self::PATH] = $path;
- if (isset($dir[self::URL_PATH])) {
- $this->assertUrlPath($dir[self::URL_PATH]);
- }
- }
- }
- /**
- * Converts slashes in path to a conventional unix-style
- *
- * @param string $path
- * @return string
- */
- private function normalizePath($path)
- {
- return str_replace('\\', '/', $path);
- }
- /**
- * Validates a URL path
- *
- * Path must be usable as a fragment of a URL path.
- * For interoperability and security purposes, no uppercase or "upper directory" paths like "." or ".."
- *
- * @param string $urlPath
- * @return void
- * @throws \InvalidArgumentException
- */
- private function assertUrlPath($urlPath)
- {
- if (!preg_match('/^([a-z0-9_]+[a-z0-9\._]*(\/[a-z0-9_]+[a-z0-9\._]*)*)?$/', $urlPath)) {
- throw new \InvalidArgumentException(
- "URL path must be relative directory path in lowercase with '/' directory separator: '{$urlPath}'"
- );
- }
- }
- /**
- * Concatenates root directory path with a relative path
- *
- * @param string $path
- * @return string
- */
- protected function prependRoot($path)
- {
- $root = $this->getRoot();
- return $root . ($root && $path ? '/' : '') . $path;
- }
- /**
- * Determine if a path is absolute
- *
- * @param string $path
- * @return bool
- */
- protected function isAbsolute($path)
- {
- $path = strtr($path, '\\', '/');
- if (strpos($path, '/') === 0) {
- //is UnixRoot
- return true;
- } elseif (preg_match('#^\w{1}:/#', $path)) {
- //is WindowsRoot
- return true;
- } elseif (parse_url($path, PHP_URL_SCHEME) !== null) {
- //is WindowsLetter
- return true;
- }
- return false;
- }
- /**
- * Gets a filesystem path of the root directory
- *
- * @return string
- */
- public function getRoot()
- {
- return $this->root;
- }
- /**
- * Gets a filesystem path of a directory
- *
- * @param string $code
- * @return string
- * @throws \Magento\Framework\Exception\FileSystemException
- */
- public function getPath($code)
- {
- $this->assertCode($code);
- return $this->directories[$code][self::PATH];
- }
- /**
- * Gets URL path of a directory
- *
- * @param string $code
- * @return string|bool
- */
- public function getUrlPath($code)
- {
- $this->assertCode($code);
- if (!isset($this->directories[$code][self::URL_PATH])) {
- return false;
- }
- return $this->directories[$code][self::URL_PATH];
- }
- /**
- * Asserts that specified directory code is in the registry
- *
- * @param string $code
- * @throws \Magento\Framework\Exception\FileSystemException
- * @return void
- */
- private function assertCode($code)
- {
- if (!isset($this->directories[$code])) {
- throw new \Magento\Framework\Exception\FileSystemException(
- new \Magento\Framework\Phrase('Unknown directory type: \'%1\'', [$code])
- );
- }
- }
- }
|