1<?php 2 3/** 4 * Hoa 5 * 6 * 7 * @license 8 * 9 * New BSD License 10 * 11 * Copyright © 2007-2017, Hoa community. All rights reserved. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions are met: 15 * * Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * * Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * * Neither the name of the Hoa nor the names of its contributors may be 21 * used to endorse or promote products derived from this software without 22 * specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE 28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37namespace Hoa\Protocol; 38 39use Hoa\Consistency; 40 41/** 42 * Class \Hoa\Protocol\Protocol. 43 * 44 * Root of the `hoa://` protocol. 45 * 46 * @copyright Copyright © 2007-2017 Hoa community 47 * @license New BSD License 48 */ 49class Protocol extends Node 50{ 51 /** 52 * No resolution value. 53 * 54 * @const string 55 */ 56 const NO_RESOLUTION = '/hoa/flatland'; 57 58 /** 59 * Singleton. 60 * 61 * @var \Hoa\Protocol\Protocol 62 */ 63 private static $_instance = null; 64 65 /** 66 * Cache of resolver. 67 * 68 * @var array 69 */ 70 private static $_cache = []; 71 72 73 74 /** 75 * Initialize the protocol. 76 * 77 */ 78 public function __construct() 79 { 80 $this->initialize(); 81 82 return; 83 } 84 85 /** 86 * Singleton. 87 * To use the `hoa://` protocol shared by everyone. 88 * 89 * @return \Hoa\Protocol\Protocol 90 */ 91 public static function getInstance() 92 { 93 if (null === static::$_instance) { 94 static::$_instance = new static(); 95 } 96 97 return static::$_instance; 98 } 99 100 /** 101 * Initialize the protocol. 102 * 103 * @return void 104 */ 105 protected function initialize() 106 { 107 $root = dirname(dirname(__DIR__)); 108 $cwd = 109 'cli' === PHP_SAPI 110 ? dirname(realpath($_SERVER['argv'][0])) 111 : getcwd(); 112 113 $this[] = new Node( 114 'Application', 115 $cwd . DS, 116 [ 117 new Node('Public', 'Public' . DS) 118 ] 119 ); 120 121 $this[] = new Node( 122 'Data', 123 dirname($cwd) . DS, 124 [ 125 new Node( 126 'Etc', 127 'Etc' . DS, 128 [ 129 new Node('Configuration', 'Configuration' . DS), 130 new Node('Locale', 'Locale' . DS) 131 ] 132 ), 133 new Node('Lost+found', 'Lost+found' . DS), 134 new Node('Temporary', 'Temporary' . DS), 135 new Node( 136 'Variable', 137 'Variable' . DS, 138 [ 139 new Node('Cache', 'Cache' . DS), 140 new Node('Database', 'Database' . DS), 141 new Node('Log', 'Log' . DS), 142 new Node('Private', 'Private' . DS), 143 new Node('Run', 'Run' . DS), 144 new Node('Test', 'Test' . DS) 145 ] 146 ) 147 ] 148 ); 149 150 $this[] = new Node\Library( 151 'Library', 152 $root . DS . 'Hoathis' . DS . RS . 153 $root . DS . 'Hoa' . DS 154 ); 155 156 return; 157 } 158 159 /** 160 * Resolve (unfold) an `hoa://` path to its real resource. 161 * 162 * @param string $path Path to resolve. 163 * @param bool $exists If `true`, try to find the first that exists, 164 * else return the first solution. 165 * @param bool $unfold Return all solutions instead of one. 166 * @return mixed 167 */ 168 public function resolve($path, $exists = true, $unfold = false) 169 { 170 if (substr($path, 0, 6) !== 'hoa://') { 171 if (true === is_dir($path)) { 172 $path = rtrim($path, '/\\'); 173 174 if (0 === strlen($path)) { 175 $path = '/'; 176 } 177 } 178 179 return $path; 180 } 181 182 if (isset(self::$_cache[$path])) { 183 $handle = self::$_cache[$path]; 184 } else { 185 $out = $this->_resolve($path, $handle); 186 187 // Not a path but a resource. 188 if (!is_array($handle)) { 189 return $out; 190 } 191 192 $handle = array_values(array_unique($handle, SORT_REGULAR)); 193 194 foreach ($handle as &$entry) { 195 if (true === is_dir($entry)) { 196 $entry = rtrim($entry, '/\\'); 197 198 if (0 === strlen($entry)) { 199 $entry = '/'; 200 } 201 } 202 } 203 204 self::$_cache[$path] = $handle; 205 } 206 207 if (true === $unfold) { 208 if (true !== $exists) { 209 return $handle; 210 } 211 212 $out = []; 213 214 foreach ($handle as $solution) { 215 if (file_exists($solution)) { 216 $out[] = $solution; 217 } 218 } 219 220 return $out; 221 } 222 223 if (true !== $exists) { 224 return $handle[0]; 225 } 226 227 foreach ($handle as $solution) { 228 if (file_exists($solution)) { 229 return $solution; 230 } 231 } 232 233 return static::NO_RESOLUTION; 234 } 235 236 /** 237 * Clear the cache. 238 * 239 * @return void 240 */ 241 public static function clearCache() 242 { 243 self::$_cache = []; 244 245 return; 246 } 247} 248 249/** 250 * Flex entity. 251 */ 252Consistency::flexEntity('Hoa\Protocol\Protocol'); 253