Overview

Namespaces

  • Charcoal
    • App
      • Action
      • Config
      • Handler
      • Middleware
      • Module
      • Route
      • Script
      • ServiceProvider
      • Template

Classes

  • Charcoal\App\Action\AbstractAction
  • Charcoal\App\App
  • Charcoal\App\AppConfig
  • Charcoal\App\AppContainer
  • Charcoal\App\Config\CacheConfig
  • Charcoal\App\Config\DatabaseConfig
  • Charcoal\App\Config\FilesystemConfig
  • Charcoal\App\Config\LoggerConfig
  • Charcoal\App\Config\MemcacheCacheConfig
  • Charcoal\App\Config\MemcacheCacheServerConfig
  • Charcoal\App\Handler\AbstractHandler
  • Charcoal\App\Handler\Error
  • Charcoal\App\Handler\HandlerConfig
  • Charcoal\App\Handler\NotAllowed
  • Charcoal\App\Handler\NotFound
  • Charcoal\App\Handler\PhpError
  • Charcoal\App\Handler\Shutdown
  • Charcoal\App\Middleware\CacheMiddleware
  • Charcoal\App\Module\AbstractModule
  • Charcoal\App\Module\ModuleConfig
  • Charcoal\App\Module\ModuleManager
  • Charcoal\App\Route\ActionRoute
  • Charcoal\App\Route\ActionRouteConfig
  • Charcoal\App\Route\RouteConfig
  • Charcoal\App\Route\RouteManager
  • Charcoal\App\Route\ScriptRoute
  • Charcoal\App\Route\ScriptRouteConfig
  • Charcoal\App\Route\TemplateRoute
  • Charcoal\App\Route\TemplateRouteConfig
  • Charcoal\App\Script\AbstractScript
  • Charcoal\App\ServiceProvider\AppServiceProvider
  • Charcoal\App\ServiceProvider\CacheServiceProvider
  • Charcoal\App\ServiceProvider\DatabaseServiceProvider
  • Charcoal\App\ServiceProvider\FilesystemServiceProvider
  • Charcoal\App\ServiceProvider\LoggerServiceProvider
  • Charcoal\App\ServiceProvider\ViewServiceProvider
  • Charcoal\App\Template\AbstractTemplate
  • Charcoal\App\Template\AbstractWidget
  • Charcoal\App\Template\WidgetBuilder

Interfaces

  • Charcoal\App\Action\ActionInterface
  • Charcoal\App\AppAwareInterface
  • Charcoal\App\Handler\HandlerInterface
  • Charcoal\App\Module\ModuleInterface
  • Charcoal\App\Route\RouteInterface
  • Charcoal\App\Script\CronScriptInterface
  • Charcoal\App\Script\ScriptInterface
  • Charcoal\App\Template\TemplateInterface
  • Charcoal\App\Template\WidgetInterface

Traits

  • Charcoal\App\AppAwareTrait
  • Charcoal\App\CallableResolverAwareTrait
  • Charcoal\App\Script\ArgScriptTrait
  • Charcoal\App\Script\CronScriptTrait
  • Charcoal\App\Script\PathScriptTrait
  • Overview
  • Namespace
  • Class
  1: <?php
  2: 
  3: namespace Charcoal\App\Script;
  4: 
  5: use \InvalidArgumentException;
  6: 
  7: /**
  8:  * Path-handling utilities
  9:  *
 10:  * Requirements:
 11:  * - `DIRECTORY_SEPARATORS` class constant.
 12:  * - `DEFAULT_BASENAME` class constant.
 13:  * - `self::parseAsArray()`
 14:  */
 15: trait PathScriptTrait
 16: {
 17:     /**
 18:      * The cache of globbed paths.
 19:      *
 20:      * @var array
 21:      */
 22:     protected static $globCache = [];
 23: 
 24:     /**
 25:      * Retrieve the base path.
 26:      *
 27:      * @return string|null
 28:      */
 29:     abstract public function basePath();
 30: 
 31:     /**
 32:      * Process multiple paths.
 33:      *
 34:      * @param  string|string[] $paths One or many paths to scan.
 35:      * @throws InvalidArgumentException If the paths are invalid.
 36:      * @return string[]
 37:      */
 38:     public function processMultiplePaths($paths)
 39:     {
 40:         $paths = $this->parseAsArray($paths);
 41:         $paths = array_map([ $this, 'filterPath' ], $paths);
 42:         $paths = array_filter($paths, [ $this, 'pathExists' ]);
 43: 
 44:         if ($paths === false) {
 45:             throw new InvalidArgumentException('Received invalid paths.');
 46:         }
 47: 
 48:         if (empty($paths)) {
 49:             throw new InvalidArgumentException('Received empty paths.');
 50:         }
 51: 
 52:         return $paths;
 53:     }
 54: 
 55:     /**
 56:      * Determine if the path exists.
 57:      *
 58:      * @param  string $path Path to the file or directory.
 59:      * @throws InvalidArgumentException If the path is invalid.
 60:      * @return boolean Returns TRUE if the path exists.
 61:      */
 62:     public function pathExists($path)
 63:     {
 64:         if (!is_string($path)) {
 65:             throw new InvalidArgumentException('The path must be a string.');
 66:         }
 67: 
 68:         return $this->globRecursive($this->basePath().'/'.$path, GLOB_BRACE);
 69:     }
 70: 
 71:     /**
 72:      * Filter the given path.
 73:      *
 74:      * Trims leading and trailing directory paths
 75:      *
 76:      * @param  string      $path Path to the file or directory.
 77:      * @param  string|null $trim The characters to strip from the $path.
 78:      * @throws InvalidArgumentException If the path is invalid.
 79:      * @return string Returns the filtered path.
 80:      */
 81:     public function filterPath($path, $trim = null)
 82:     {
 83:         if (!is_string($path)) {
 84:             throw new InvalidArgumentException('The path must be a string.');
 85:         }
 86: 
 87:         if ($trim === null && defined(get_called_class().'::DIRECTORY_SEPARATORS')) {
 88:             $trim = static::DIRECTORY_SEPARATORS;
 89:         }
 90: 
 91:         if ($trim) {
 92:             if (!is_string($trim)) {
 93:                 throw new InvalidArgumentException(
 94:                     'The characters to strip must be a string or use static::DIRECTORY_SEPARATORS.'
 95:                 );
 96:             }
 97: 
 98:             $path = trim($path, $trim);
 99:         }
100: 
101:         return trim($path);
102:     }
103: 
104:     /**
105:      * Filter the given path to be writable.
106:      *
107:      * @param  string      $path A writable path to a file or directory.
108:      * @param  string|null $name The target file name.
109:      * @throws InvalidArgumentException If the path is invalid.
110:      * @return string Returns the filtered path.
111:      */
112:     public function filterWritablePath($path, $name = null)
113:     {
114:         if ($name === null && defined(get_called_class().'::DEFAULT_BASENAME')) {
115:             $name = static::DEFAULT_BASENAME;
116:         }
117: 
118:         if (!is_string($name)) {
119:             throw new InvalidArgumentException(
120:                 'The target file name must be a string or use static::DEFAULT_BASENAME.'
121:             );
122:         }
123: 
124:         $path = $this->filterPath($path);
125:         $test = $this->basePath().'/'.$path;
126: 
127:         if (is_dir($test)) {
128:             if (is_writable($test)) {
129:                 $path .= '/'.$name;
130:             } else {
131:                 throw new InvalidArgumentException('The target path is not writeable.');
132:             }
133:         } elseif (is_file($test)) {
134:             if (!is_writable($test)) {
135:                 throw new InvalidArgumentException('The target file is not writeable.');
136:             }
137:         } else {
138:             $info = pathinfo($path);
139:             $path = $this->filterWritablePath($info['dirname'], $info['basename']);
140:         }
141: 
142:         return $path;
143:     }
144: 
145:     /**
146:      * Recursively find pathnames matching a pattern.
147:      *
148:      * @see    http://in.php.net/manual/en/function.glob.php#106595
149:      * @param  string  $pattern The search pattern.
150:      * @param  integer $flags   Bitmask of {@see glob()} options.
151:      * @return array
152:      */
153:     public function globRecursive($pattern, $flags = 0)
154:     {
155:         $maxDepth = $this->maxDepth();
156:         $depthKey = strval($maxDepth);
157: 
158:         if (isset(static::$globCache[$pattern][$depthKey])) {
159:             return static::$globCache[$pattern][$depthKey];
160:         }
161: 
162:         $depth = 1;
163:         $files = glob($pattern, $flags);
164:         foreach (glob(dirname($pattern).'/*', (GLOB_ONLYDIR|GLOB_NOSORT)) as $dir) {
165:             $files = array_merge($files, $this->globRecursive($dir.'/'.basename($pattern), $flags));
166:             $depth++;
167:             if ($maxDepth > 0 && $depth >= $maxDepth) {
168:                 break;
169:             }
170:         }
171: 
172:         static::$globCache[$pattern][$depthKey] = array_filter($files, 'is_file');
173: 
174:         return $files;
175:     }
176: }
177: 
API documentation generated by ApiGen