Skip to content

Instantly share code, notes, and snippets.

@damienlabat
Created September 13, 2012 16:24
Show Gist options
  • Save damienlabat/3715529 to your computer and use it in GitHub Desktop.
Save damienlabat/3715529 to your computer and use it in GitHub Desktop.
modified version of Laravel URL Class to get relative or absolute path
<?php
// bundles/url2/start.php
Autoloader::map(array(
'URL2' => Bundle::path('url2').'url2.php'
));
<?php
// /bundles/url2/url2.php
/**
*
* modified version of Laravel URL Class (https://github.com/laravel/laravel/blob/master/laravel/url.php)
* to get relative or absolute path
*
* add to your bundles.php array:
* 'url2'=> array('auto' => true)
*
* switch mode using URL2::set_url_mode('relative') or URL2::set_url_mode('fromroot') or URL2::set_url_mode('absolute')
*
*/
/* EXEMPLE
// current page is http://127.0.0.1/laravel/public/admin/param
URL2::set_url_mode('relative');
echo URL2::to('admin/logout').PHP_EOL; // -> ./logout
echo URL2::to('welcome').PHP_EOL; // -> ../welcome
echo URL2::home().PHP_EOL; // -> ..
echo URL2::to_secure('admin/login').PHP_EOL; // -> https://127.0.0.1/laravel/public/admin/login
URL2::set_url_mode('fromroot'); // now switch to fromroot url mode
echo URL2::to('admin/logout').PHP_EOL; // -> /laravel/public/admin/logout
echo URL2::to('welcome').PHP_EOL; // -> /laravel/public/welcome
echo URL2::home().PHP_EOL; // -> /laravel/public/
echo URL2::to_secure('admin/login').PHP_EOL; // -> https://127.0.0.1/laravel/public/admin/login
URL2::set_url_mode('absolute'); // now switch back to absolute url mode
echo URL2::to('admin/logout').PHP_EOL; // -> http://127.0.0.1/laravel/public/admin/logout (same as URL::to('admin/logout') )
echo URL2::to('welcome').PHP_EOL; // -> http://127.0.0.1/laravel/public/welcome (same as URL::to('welcome')') )
echo URL2::home().PHP_EOL; // -> http://127.0.0.1/laravel/public/ (same as URL::home() )
echo URL2::to_secure('admin/login').PHP_EOL; // -> https://127.0.0.1/laravel/public/admin/login (same as URL::to_secure('admin/login') )
*/
class URL2 {
/**
* The url mode
*
* @var string should be absolute|fromroot|relative
**/
private static $url_mode='relative';
/**
* Set url mode
*
* @param string $new_url_mode should be absolute|relative
*/
public static function set_url_mode($new_url_mode='absolute') {
static::$url_mode= $new_url_mode;
}
/**
* Get url mode
*
* @return string
*/
public static function get_url_mode() {
return static::$url_mode;
}
/**
* Return current page directory
*
* @return string
*/
private static function current_directory()
{
$current= URL::current();
if (substr($_SERVER['REQUEST_URI'],-1)!='/')
$current=substr($current, 0,strrpos($current,'/') );
return $current;
}
/**
* Return scheme+host
*
* @param string $url
* @return boolean
*/
private static function get_shemehost($url) {
$url_array=parse_url($url);
return $url_array['scheme'].'://'.$url_array['host'];
}
/**
* Check if the url is in the same scheme+host as the current page
*
* @param string $url
* @return boolean
*/
private static function check_ndd($url) {
return static::get_shemehost($url)==static::get_shemehost(static::current_directory());
}
/**
* Get relative path from full url
*
* @param string $url
* @return string
*/
private static function get_relative_path( $url ) {
$compareTo= static::current_directory(); // get current directory
if (!static::check_ndd($url)) return $url; // return full url if not in the same host
// Code taken from http://www.php.net/manual/fr/function.realpath.php#97885
// clean arguments by removing trailing and prefixing slashes
if ( substr( $url, -1 ) == '/' ) {
$url = substr( $url, 0, -1 );
}
if ( substr( $url, 0, 1 ) == '/' ) {
$url = substr( $url, 1 );
}
if ( substr( $compareTo, -1 ) == '/' ) {
$compareTo = substr( $compareTo, 0, -1 );
}
if ( substr( $compareTo, 0, 1 ) == '/' ) {
$compareTo = substr( $compareTo, 1 );
}
// simple case: $compareTo is in $path
if ( strpos( $url, $compareTo ) === 0 ) {
$offset = strlen( $compareTo ) + 1;
return './'.substr( $url, $offset );
}
$relative = array( );
$pathParts = explode( '/', $url );
$compareToParts = explode( '/', $compareTo );
foreach( $compareToParts as $index => $part ) {
if ( isset( $pathParts[$index] ) && $pathParts[$index] == $part ) {
continue;
}
$relative[] = '..';
}
foreach( $pathParts as $index => $part ) {
if ( isset( $compareToParts[$index] ) && $compareToParts[$index] == $part ) {
continue;
}
$relative[] = $part;
}
return implode( '/', $relative );
}
/**
* Get from root
*
* @param string $url
* @return string
*/
private static function get_from_root( $url ) {
return str_replace( static::get_shemehost($url), '', $url);
}
/**
* return res
*
* @param string $url
* @return string
*/
private static function result( $url ) {
if (static::$url_mode=='relative') return static::get_relative_path( $url );
if (static::$url_mode=='fromroot') return static::get_from_root( $url );
return $url;
}
/***************************************************************************************/
/***************************************************************************************/
/* Code taken from from https://github.com/laravel/laravel/blob/master/laravel/url.php */
/***************************************************************************************/
/***************************************************************************************/
/**
* The cached base URL.
*
* @var string
*/
public static $base;
/**
* Get the full URI including the query string.
*
* @return string
*/
public static function full()
{
return static::to(URI::full());
}
/**
* Get the full URL for the current request.
*
* @return string
*/
public static function current()
{
return static::to(URI::current(), null, false, false);
}
/**
* Get the URL for the application root.
*
* @param bool $https
* @return string
*/
public static function home($https = null)
{
$route = Router::find('home');
// If a route named "home" exists, we'll route to that instead of using
// the single slash root URI. This allows the HTTPS attribute to be
// respected instead of being hard-coded in the redirect.
if ( ! is_null($route))
{
return static::to_route('home');
}
return static::to('/', $https);
}
/**
* Get the base URL of the application.
*
* @return string
*/
public static function base()
{
if (isset(static::$base)) return static::$base;
$base = 'http://localhost';
// If the application's URL configuration is set, we will just use that
// instead of trying to guess the URL from the $_SERVER array's host
// and script variables as this is a more reliable method.
if (($url = Config::get('application.url')) !== '')
{
$base = $url;
}
else
{
$base = Request::foundation()->getRootUrl();
}
return static::$base = $base;
}
/**
* Generate an application URL.
*
* <code>
* // Create a URL to a location within the application
* $url = URL::to('user/profile');
*
* // Create a HTTPS URL to a location within the application
* $url = URL::to('user/profile', true);
* </code>
*
* @param string $url
* @param bool $https
* @param bool $asset
* @param bool $locale
* @return string
*/
public static function to($url = '', $https = null, $asset = false, $locale = true)
{
// If the given URL is already valid or begins with a hash, we'll just return
// the URL unchanged since it is already well formed. Otherwise we will add
// the base URL of the application and return the full URL.
if (static::valid($url) or starts_with($url, '#'))
{
return static::result( $url ); // replace result
}
// Unless $https is specified (true or false), we maintain the current request
// security for any new links generated. So https for all secure links.
if (is_null($https)) $https = Request::secure();
$root = static::base();
if ( ! $asset)
{
$root .= '/'.Config::get('application.index');
}
if ( ! $asset and $locale and count(Config::get('application.languages')) > 0)
{
$root .= '/'.Config::get('application.language');
}
// Since SSL is not often used while developing the application, we allow the
// developer to disable SSL on all framework generated links to make it more
// convenient to work with the site while developing locally.
if ($https and Config::get('application.ssl'))
{
$root = preg_replace('~http://~', 'https://', $root, 1);
}
else
{
$root = preg_replace('~https://~', 'http://', $root, 1);
}
return static::result( rtrim($root, '/').'/'.ltrim($url, '/') ); // replace result
}
/**
* Generate an application URL with HTTPS.
*
* @param string $url
* @return string
*/
public static function to_secure($url = '')
{
return static::to($url, true);
}
/**
* Generate a URL to a controller action.
*
* <code>
* // Generate a URL to the "index" method of the "user" controller
* $url = URL::to_action('user@index');
*
* // Generate a URL to http://example.com/user/profile/taylor
* $url = URL::to_action('user@profile', array('taylor'));
* </code>
*
* @param string $action
* @param array $parameters
* @return string
*/
public static function to_action($action, $parameters = array())
{
// This allows us to use true reverse routing to controllers, since
// URIs may be setup to handle the action that do not follow the
// typical Laravel controller URI conventions.
$route = Router::uses($action);
if ( ! is_null($route))
{
return static::explicit($route, $action, $parameters);
}
// If no route was found that handled the given action, we'll just
// generate the URL using the typical controller routing setup
// for URIs and turn SSL to false by default.
else
{
return static::convention($action, $parameters);
}
}
/**
* Generate an action URL from a route definition
*
* @param array $route
* @param string $action
* @param array $parameters
* @return string
*/
protected static function explicit($route, $action, $parameters)
{
$https = array_get(current($route), 'https', null);
return static::to(static::transpose(key($route), $parameters), $https);
}
/**
* Generate an action URI by convention.
*
* @param string $action
* @param array $parameters
* @return string
*/
protected static function convention($action, $parameters)
{
list($bundle, $action) = Bundle::parse($action);
$bundle = Bundle::get($bundle);
// If a bundle exists for the action, we will attempt to use its "handles"
// clause as the root of the generated URL, as the bundle can only handle
// URIs that begin with that string and no others.
$root = $bundle['handles'] ?: '';
$parameters = implode('/', $parameters);
// We'll replace both dots and @ signs in the URI since both are used
// to specify the controller and action, and by convention should be
// translated into URI slashes for the URL.
$uri = $root.'/'.str_replace(array('.', '@'), '/', $action);
$uri = static::to(str_finish($uri, '/').$parameters);
return trim($uri, '/');
}
/**
* Generate an application URL to an asset.
*
* @param string $url
* @param bool $https
* @return string
*/
public static function to_asset($url, $https = null)
{
if (static::valid($url)) return $url;
// If a base asset URL is defined in the configuration, use that and don't
// try and change the HTTP protocol. This allows the delivery of assets
// through a different server or third-party content delivery network.
if ($root = Config::get('application.asset_url', false))
{
return rtrim($root, '/').'/'.ltrim($url, '/');
}
$url = static::to($url, $https, true);
// Since assets are not served by Laravel, we do not need to come through
// the front controller. So, we'll remove the application index specified
// in the application config from the generated URL.
if (($index = Config::get('application.index')) !== '')
{
$url = str_replace($index.'/', '', $url);
}
return $url;
}
/**
* Generate a URL from a route name.
*
* <code>
* // Create a URL to the "profile" named route
* $url = URL::to_route('profile');
*
* // Create a URL to the "profile" named route with wildcard parameters
* $url = URL::to_route('profile', array($username));
* </code>
*
* @param string $name
* @param array $parameters
* @return string
*/
public static function to_route($name, $parameters = array())
{
if (is_null($route = Routing\Router::find($name)))
{
throw new \Exception("Error creating URL for undefined route [$name].");
}
// To determine whether the URL should be HTTPS or not, we look for the "https"
// value on the route action array. The route has control over whether the URL
// should be generated with an HTTPS protocol string or just HTTP.
$https = array_get(current($route), 'https', null);
$uri = trim(static::transpose(key($route), $parameters), '/');
return static::to($uri, $https);
}
/**
* Substitute the parameters in a given URI.
*
* @param string $uri
* @param array $parameters
* @return string
*/
public static function transpose($uri, $parameters)
{
// Spin through each route parameter and replace the route wildcard segment
// with the corresponding parameter passed to the method. Afterwards, we'll
// replace all of the remaining optional URI segments.
foreach ((array) $parameters as $parameter)
{
if ( ! is_null($parameter))
{
$uri = preg_replace('/\(.+?\)/', $parameter, $uri, 1);
}
}
// If there are any remaining optional place-holders, we'll just replace
// them with empty strings since not every optional parameter has to be
// in the array of parameters that were passed to us.
$uri = preg_replace('/\(.+?\)/', '', $uri);
return trim($uri, '/');
}
/**
* Determine if the given URL is valid.
*
* @param string $url
* @return bool
*/
public static function valid($url)
{
return filter_var($url, FILTER_VALIDATE_URL) !== false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment