Last active
December 22, 2015 03:28
-
-
Save jrnickell/6410227 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class ResourceLocator implements ResourceLocatorInterface | |
{ | |
protected $defaultMap; | |
protected $schemes = []; | |
public function __construct(UriPathMapInterface $defaultMap = null) | |
{ | |
$this->defaultMap = $defaultMap ?: new UriPathMap(); | |
} | |
public function addScheme($scheme, $separator) | |
{ | |
if (array_key_exists($scheme, $this->schemes)) { | |
$message = sprintf('Scheme name "%s" is already registered', $scheme); | |
throw new InvalidArgumentException($message); | |
} | |
$pathMap = clone $this->defaultMap; | |
$pathMap->setSeparator($separator); | |
$this->schemes[$scheme] = $pathMap; | |
} | |
public function getSchemes() | |
{ | |
return array_keys($this->schemes); | |
} | |
public function hasScheme($scheme) | |
{ | |
return array_key_exists($scheme, $this->schemes); | |
} | |
public function addPath($scheme, $prefix, $path, $prepend = false) | |
{ | |
$this->verifyScheme($scheme); | |
$this->schemes[$scheme]->addPath($prefix, $path, $prepend); | |
} | |
public function getPaths($scheme, $prefix = null) | |
{ | |
$this->verifyScheme($scheme); | |
return $this->schemes[$scheme]->getPaths($prefix); | |
} | |
public function hasPaths($scheme, $prefix = null) | |
{ | |
if (!array_key_exists($scheme, $this->schemes)) { | |
return false; | |
} | |
return $this->schemes[$scheme]->hasPaths($prefix); | |
} | |
public function removePath($scheme, $prefix, $path) | |
{ | |
if (!array_key_exists($scheme, $this->schemes)) { | |
return; | |
} | |
$this->schemes[$scheme]->removePath($prefix, $path); | |
} | |
public function findResource($uri) | |
{ | |
return $this->matchUri($uri); | |
} | |
public function findResourceVariants($uri) | |
{ | |
return $this->matchUri($uri, false); | |
} | |
protected function parseUri($uri) | |
{ | |
$index = strpos($uri, ':///'); | |
$scheme = substr($uri, 0, $index); | |
$path = substr($uri, $index + 4); | |
return [$scheme, $path]; | |
} | |
protected function matchUri($uri, $first = true) | |
{ | |
list($scheme, $path) = $this->parseUri($uri); | |
$this->verifyScheme($scheme); | |
$pathMappings = $this->schemes[$scheme]->getPaths(); | |
$separator = $this->schemes[$scheme]->getSeparator(); | |
$path = strtr($path, '/', $separator); | |
return $this->match($path, $pathMappings, $separator, $first); | |
} | |
protected function match($path, array $pathMappings, $separator, $first) | |
{ | |
$pathLength = strlen($path); | |
$pathPrefix = $path; | |
$relativePath = ''; | |
$cursor = -1; | |
$matches = []; | |
while (abs($cursor) !== $pathLength) { | |
if (isset($pathMappings[$pathPrefix])) { | |
foreach ((array) $pathMappings[$pathPrefix] as $basePath) { | |
$relativePath = strtr($relativePath, $separator, DIRECTORY_SEPARATOR); | |
$potential = $basePath.$relativePath; | |
if (is_readable($potential)) { | |
if ($first) { | |
return $potential; | |
} else { | |
$matches[] = $potential; | |
} | |
} | |
} | |
} | |
$cursor = strrpos($path, $separator, $cursor - 1) - $pathLength; | |
$relativePath = substr($path, $cursor); | |
$pathPrefix = substr($path, 0, max($cursor, -$pathLength + 1)); | |
} | |
if ($first) { | |
return null; | |
} | |
return $matches; | |
} | |
protected function verifyScheme($scheme) | |
{ | |
if (!array_key_exists($scheme, $this->schemes)) { | |
$message = sprintf('Scheme name "%s" is undefined', $scheme); | |
throw new InvalidArgumentException($message); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class UriPathMap implements UriPathMapInterface | |
{ | |
protected $separator; | |
protected $paths = []; | |
public function __construct($separator = '/') | |
{ | |
$this->separator = (string) $separator; | |
} | |
public function setSeparator($separator) | |
{ | |
$this->separator = (string) $separator; | |
} | |
public function getSeparator() | |
{ | |
return $this->separator; | |
} | |
public function addPath($prefix, $path, $prepend = false) | |
{ | |
if (!array_key_exists($prefix, $this->paths)) { | |
$this->paths[$prefix] = []; | |
} | |
if ($prepend) { | |
array_unshift($this->paths[$prefix], $path); | |
} else { | |
$this->paths[$prefix][] = $path; | |
} | |
} | |
public function getPaths($prefix = null) | |
{ | |
if (null === $prefix) { | |
return $this->paths; | |
} | |
if (!array_key_exists($prefix, $this->paths)) { | |
return []; | |
} | |
return $this->paths[$prefix]; | |
} | |
public function hasPaths($prefix = null) | |
{ | |
return count($this->getPaths($prefix)) > 0; | |
} | |
public function removePath($prefix, $path) | |
{ | |
if (!array_key_exists($prefix, $this->paths)) { | |
return $this; | |
} | |
$key = array_search($path, $this->paths[$prefix]); | |
if (false !== $key) { | |
unset($this->paths[$prefix][$key]); | |
if (empty($this->paths[$prefix])) { | |
unset($this->paths[$prefix]); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment