sterzycom/kirby/toolkit/lib/url.php

391 lines
10 KiB
PHP

<?php
/**
* Url
*
* A bunch of handy methods to work with URLs
*
* @package Kirby Toolkit
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
class Url {
public static $home = '/';
public static $to = null;
public static $current = null;
public static function scheme($url = null) {
if(is_null($url)) {
if(
(isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off') ||
server::get('SERVER_PORT') == '443' ||
server::get('HTTP_X_FORWARDED_PORT') == '443' ||
server::get('HTTP_X_FORWARDED_PROTO') == 'https' ||
server::get('HTTP_X_FORWARDED_PROTO') == 'https, http'
) {
return 'https';
} else {
return 'http';
}
}
return parse_url($url, PHP_URL_SCHEME);
}
/**
* Returns the current url with all bells and whistles
*
* @return string
*/
public static function current() {
if(!is_null(static::$current)) return static::$current;
return static::$current = static::base() . server::get('REQUEST_URI');
}
/**
* Returns the url for the current directory
*
* @return string
*/
public static function currentDir() {
return dirname(static::current());
}
/**
*/
public static function host($url = null) {
if(is_null($url)) $url = static::current();
return parse_url($url, PHP_URL_HOST);
}
/**
* Returns the port for the given url
*
* @return mixed
*/
public static function port($url = null) {
if(is_null($url)) $url = static::current();
$port = intval(parse_url($url, PHP_URL_PORT));
return v::between($port, 1, 65535) ? $port : false;
}
/**
* Returns only the cleaned path of the url
*/
public static function path($url = null) {
if(is_null($url)) $url = static::current();
// if a path is passed, let's pretend this is an absolute url
// to trick the url parser. It's a bit hacky but it works
if(!static::isAbsolute($url)) $url = 'http://0.0.0.0/' . $url;
return trim(parse_url($url, PHP_URL_PATH), '/');
}
/**
* Returns the correct separator for parameters
* depending on the operating system
*
* @return string
*/
public static function paramSeparator() {
return detect::windows() ? ';' : ':';
}
/**
* Returns the params in the url
*/
public static function params($url = null) {
if(is_null($url)) $url = static::current();
$path = static::path($url);
if(empty($path)) return array();
$params = array();
foreach(explode('/', $path) as $part) {
$pos = strpos($part, static::paramSeparator());
if($pos === false) continue;
$params[substr($part, 0, $pos)] = urldecode(substr($part, $pos+1));
}
return $params;
}
/**
* Returns the path without params
*/
public static function fragments($url = null) {
if(is_null($url)) $url = static::current();
$path = static::path($url);
if(empty($path)) return null;
$frag = array();
foreach(explode('/', $path) as $part) {
if(strpos($part, static::paramSeparator()) === false) $frag[] = $part;
}
return $frag;
}
/**
* Returns the query as array
*/
public static function query($url = null) {
if(is_null($url)) $url = static::current();
parse_str(parse_url($url, PHP_URL_QUERY), $array);
return $array;
}
/**
* Checks if the url contains a query string
*/
public static function hasQuery($url = null) {
if(is_null($url)) $url = static::current();
return str::contains($url, '?');
}
/**
*/
public static function hash($url = null) {
if(is_null($url)) $url = static::current();
return parse_url($url, PHP_URL_FRAGMENT);
}
public static function build($parts = array(), $url = null) {
if(is_null($url)) $url = static::current();
$defaults = array(
'scheme' => static::scheme($url),
'host' => static::host($url),
'port' => static::port($url),
'fragments' => static::fragments($url),
'params' => static::params($url),
'query' => static::query($url),
'hash' => static::hash($url),
);
$parts = array_merge($defaults, $parts);
$result = array(r(!empty($parts['scheme']), $parts['scheme'] . '://') . $parts['host'] . r(!empty($parts['port']), ':' . $parts['port']));
if(!empty($parts['fragments'])) $result[] = implode('/', $parts['fragments']);
if(!empty($parts['params'])) $result[] = static::paramsToString($parts['params']);
if(!empty($parts['query'])) $result[] = '?' . static::queryToString($parts['query']);
return implode('/', $result) . (!empty($parts['hash']) ? '#' . $parts['hash'] : '');
}
public static function queryToString($query = null) {
if(is_null($query)) $query = url::query();
return http_build_query($query);
}
public static function paramsToString($params = null) {
if(is_null($params)) $params = url::params();
$result = array();
foreach($params as $key => $val) $result[] = $key . static::paramSeparator() . $val;
return implode('/', $result);
}
public static function stripPath($url = null) {
if(is_null($url)) $url = static::current();
return static::build(array('fragments' => array(), 'params' => array()), $url);
}
public static function stripFragments($url = null) {
if(is_null($url)) $url = static::current();
return static::build(array('fragments' => array()), $url);
}
public static function stripParams($url = null) {
if(is_null($url)) $url = static::current();
return static::build(array('params' => array()), $url);
}
/**
* Strips the query from the URL
*
* <code>
*
* echo url::stripQuery('http://www.youtube.com/watch?v=9q_aXttJduk');
* // output: http://www.youtube.com/watch
*
* </code>
*
* @param string $url
* @return string
*/
public static function stripQuery($url = null) {
if(is_null($url)) $url = static::current();
return static::build(array('query' => array()), $url);
}
/**
* Strips a hash value from the URL
*
* <code>
*
* echo url::stripHash('http://testurl.com/#somehash');
* // output: http://testurl.com/
*
* </code>
*
* @param string $url
* @return string
*/
public static function stripHash($url) {
if(is_null($url)) $url = static::current();
return static::build(array('hash' => ''), $url);
}
/**
* Checks if an URL is absolute
*
* @return boolean
*/
public static function isAbsolute($url) {
// don't convert absolute urls
return (str::startsWith($url, 'http://') || str::startsWith($url, 'https://') || str::startsWith($url, '//'));
}
/**
* Convert a relative path into an absolute URL
*
* @param string $path
* @param string $home
* @return string
*/
public static function makeAbsolute($path, $home = null) {
if(static::isAbsolute($path)) return $path;
// build the full url
$path = ltrim($path, '/');
$home = is_null($home) ? static::$home : $home;
if(empty($path)) return $home;
return $home == '/' ? '/' . $path : $home . '/' . $path;
}
/**
* Tries to fix a broken url without protocol
*
* @param string $url
* @return string
*/
public static function fix($url) {
// make sure to not touch absolute urls
return (!preg_match('!^(https|http|ftp)\:\/\/!i', $url)) ? 'http://' . $url : $url;
}
/**
* Returns the home url if defined
*
* @return string
*/
public static function home() {
return static::$home;
}
/**
* The url smart handler. Must be defined before
*
* @return string
*/
public static function to() {
return call_user_func_array(static::$to, func_get_args());
}
/**
* Return the last url the user has been on if detectable
*
* @return string
*/
public static function last() {
return r::referer();
}
/**
* Returns the base url
*
* @param string $url
* @return string
*/
public static function base($url = null) {
if(is_null($url)) {
$port = server::get('SERVER_PORT');
$port = in_array($port, array(80, 443)) ? null : $port;
return static::scheme() . '://' . server::get('SERVER_NAME', server::get('SERVER_ADDR')) . r($port, ':' . $port);
} else {
$port = static::port($url);
$scheme = static::scheme($url);
$host = static::host($url) . r(is_int($port), ':' . $port);
return r($scheme, $scheme . '://') . $host;
}
}
/**
* Shortens a URL
* It removes http:// or https:// and uses str::short afterwards
*
* <code>
*
* echo url::short('http://veryveryverylongurl.com', 30);
* // output: veryveryverylongurl.com
*
* </code>
*
* @param string $url The URL to be shortened
* @param int $length The final number of characters the URL should have
* @param boolean $base True: only take the base of the URL.
* @param string $rep The element, which should be added if the string is too long. Ellipsis is the default.
* @return string The shortened URL
*/
public static function short($url, $length = false, $base = false, $rep = '…') {
if($base) $url = static::base($url);
// replace all the nasty stuff from the url
$url = str_replace(array('http://', 'https://', 'ftp://', 'www.'), '', $url);
// try to remove the last / after the url
$url = rtrim($url, '/');
return ($length) ? str::short($url, $length, $rep) : $url;
}
/**
* Returns the URL for document root no
* matter what the path is.
*
* @return string
*/
public static function index() {
if(r::cli()) {
return '/';
} else {
return static::base() . preg_replace('!\/index\.php$!i', '', server::get('SCRIPT_NAME'));
}
}
}
// basic home url setup
url::$home = url::base();
// basic url generator setup
url::$to = function($path = '/') {
if(url::isAbsolute($path)) return $path;
$path = ltrim($path, '/');
if(empty($path)) return url::home();
return url::home() . '/' . $path;
};