Projekt

Obecné

Profil

Stáhnout (4.37 KB) Statistiky
| Větev: | Tag: | Revize:
18ac9009 Ondřej Fibich
<?php

/*
* This file is a part of PHPAX-RS framework, released under terms of GPL-3.0
* licence. Copyright (c) 2014, UnArt Slavičín, o.s. All rights reserved.
*/

namespace phpaxrs\common;

use \InvalidArgumentException;

/**
* The "PathUtil" class that provides tools for working with URL paths.
*
* @author Ondřej Fibich <ondrej.fibich@gmail.com>
*/
class PathUtil {
/**
* Checks validity of given URL path.
*
* @param string $path
* @return bool
*/
public static function is_valid($path) {
return preg_match('/^(\/[a-zA-Z0-9_\-.]*)+$/', $path) == 1;
}

/**
* Checks validity of given URL path template.
*
* @param string $template
* @return bool
*/
public static function is_valid_template($template) {
$regex = '/^(\/([a-zA-Z0-9_\-.]|\{[a-zA-Z]+(:[^}.]+)?\})*)+$/';
return preg_match($regex, $template) == 1;
}
/**
* Normalizes path which means that it adds "/" to the start or to the end
* of path if the are missing.
*
* @param string $path Path to be nomalized
* @return string normalized path
*/
public static function normalize($path) {
return '/' . ltrim(rtrim($path, '/') . '/', '/');
}
/**
* Gets relative path from absolute path by removing path prefix that is
* given.
*
* @param string $prefix_path
* @param string $absolute_path
* @return null|string null if absolute path does not start with prefix
* relative path otherwise
*/
public static function relative($prefix_path, $absolute_path) {
$prefix_path = self::normalize($prefix_path);
$na_path = self::normalize($absolute_path);
if (strncmp($na_path, $prefix_path, mb_strlen($prefix_path)) != 0) {
return NULL;
}
return self::normalize(substr($na_path, mb_strlen($prefix_path)));
}
/**
* Tries to match path template agains a path and gets attributes values
* from path. Path template is a path string that may contain arguments that
* are denoted by {argumentName}.
*
* @example path "/abs/23/34-a" will be matched agains template
* "/abs/{id}/{sid}-a" and arguments array('23', '34') will
* be retrieved
*
* @param string $path_template path teplate that may contain arguments
* @param string $path real path that will be matched agains template
* @param array $args reference for passing arguments from path using template
* @return bool|array FALSE on no match otherwise array of gained arguments
* @throws InvalidArgumentException on invalid path template
*/
public static function match($path_template, $path) {
// check input
if (!self::is_valid($path)) {
throw new InvalidArgumentException('invalid path passed');
}
if (!self::is_valid_template($path_template)) {
throw new InvalidArgumentException('invalid path template');
}
// normalize paths
$path = self::normalize($path);
$path_template = self::normalize($path_template);
// replace / . and arguments in path teplate and transform them
// for their usage in regex (order of patterns is important!)
$transformations = array(
'/\{[a-zA-Z]+:([^}]+)\}/' => '($1)', // 1: arguments with regex
'/{[^}]+}/' => '([^\/]+)', // 2: simple arguments
'/[.]/' => '[.]' // 3: dot in path
);
$path_regex = preg_replace(array_keys($transformations),
array_values($transformations), $path_template);
if ($path_regex === NULL) {
throw new InvalidArgumentException('invalid @Path arg.');
}
// wrap regex with delimiters | that is not present in URL
$path_regex = '|^' . $path_regex . '$|';
// check path
$args = array();
if (($rm = preg_match($path_regex, $path, $args)) === FALSE) {
throw new InvalidArgumentException('invalid @Path arg.');
}
// matched?
if ($rm > 0) {
if (empty($args) || !count($args)) {
return array();
}
// shift matched string
array_shift($args);
return $args;
}
// no match
return FALSE;
}

}