Merge pull request #1317 from lorenzo/feature/full-base-url

Adding App.fullbaseURL as a recognized Configure value
This commit is contained in:
José Lorenzo Rodríguez 2013-06-05 15:12:27 -07:00
commit 3b4a4fde31
13 changed files with 106 additions and 37 deletions

View file

@ -108,6 +108,15 @@
*/ */
//Configure::write('App.baseUrl', env('SCRIPT_NAME')); //Configure::write('App.baseUrl', env('SCRIPT_NAME'));
/**
* To configure CakePHP to use a particular domain URL
* for any URL generation inside the application, set the following
* configuration variable to the http(s) address to your domain. This
* will override the automatic detection of full base URL and can be
* useful when generating links from the CLI (e.g. sending emails)
*/
//Configure::write('App.fullBaseURL', 'http://example.com');
/** /**
* Uncomment the define below to use CakePHP prefix routes. * Uncomment the define below to use CakePHP prefix routes.
* *

View file

@ -137,7 +137,9 @@ class ShellDispatcher {
$this->setErrorHandlers(); $this->setErrorHandlers();
if (!defined('FULL_BASE_URL')) { if (!defined('FULL_BASE_URL')) {
define('FULL_BASE_URL', 'http://localhost'); $url = Configure::read('App.fullBaseURL');
define('FULL_BASE_URL', $url ? $url : 'http://localhost');
Configure::write('App.fullBaseURL', FULL_BASE_URL);
} }
return true; return true;

View file

@ -99,6 +99,15 @@
*/ */
//Configure::write('App.baseUrl', env('SCRIPT_NAME')); //Configure::write('App.baseUrl', env('SCRIPT_NAME'));
/**
* To configure CakePHP to use a particular domain URL
* for any URL generation inside the application, set the following
* configuration variable to the http(s) address to your domain. This
* will override the automatic detection of full base URL and can be
* useful when generating links from the CLI (e.g. sending emails)
*/
//Configure::write('App.fullBaseURL', 'http://example.com');
/** /**
* Uncomment the define below to use CakePHP prefix routes. * Uncomment the define below to use CakePHP prefix routes.
* *

View file

@ -16,6 +16,7 @@
App::uses('CakeLog', 'Log'); App::uses('CakeLog', 'Log');
App::uses('Dispatcher', 'Routing'); App::uses('Dispatcher', 'Routing');
App::uses('Router', 'Routing');
App::uses('Set', 'Utility'); App::uses('Set', 'Utility');
App::uses('CakeLog', 'Log'); App::uses('CakeLog', 'Log');
@ -87,8 +88,8 @@ class Object {
$data = isset($extra['data']) ? $extra['data'] : null; $data = isset($extra['data']) ? $extra['data'] : null;
unset($extra['data']); unset($extra['data']);
if (is_string($url) && strpos($url, FULL_BASE_URL) === 0) { if (is_string($url) && strpos($url, Router::baseURL()) === 0) {
$url = Router::normalize(str_replace(FULL_BASE_URL, '', $url)); $url = Router::normalize(str_replace(Router::baseURL(), '', $url));
} }
if (is_string($url)) { if (is_string($url)) {
$request = new CakeRequest($url); $request = new CakeRequest($url);

View file

@ -238,7 +238,7 @@ class CakeRequest implements ArrayAccess {
if ($qPosition !== false && strpos($_SERVER['REQUEST_URI'], '://') > $qPosition) { if ($qPosition !== false && strpos($_SERVER['REQUEST_URI'], '://') > $qPosition) {
$uri = $_SERVER['REQUEST_URI']; $uri = $_SERVER['REQUEST_URI'];
} else { } else {
$uri = substr($_SERVER['REQUEST_URI'], strlen(FULL_BASE_URL)); $uri = substr($_SERVER['REQUEST_URI'], strlen(Configure::read('App.fullBaseURL')));
} }
} elseif (isset($_SERVER['PHP_SELF']) && isset($_SERVER['SCRIPT_NAME'])) { } elseif (isset($_SERVER['PHP_SELF']) && isset($_SERVER['SCRIPT_NAME'])) {
$uri = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PHP_SELF']); $uri = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PHP_SELF']);
@ -406,10 +406,7 @@ class CakeRequest implements ArrayAccess {
$ref = $forwarded; $ref = $forwarded;
} }
$base = ''; $base = Configure::read('App.fullBaseURL') . $this->webroot;
if (defined('FULL_BASE_URL')) {
$base = FULL_BASE_URL . $this->webroot;
}
if (!empty($ref) && !empty($base)) { if (!empty($ref) && !empty($base)) {
if ($local && strpos($ref, $base) === 0) { if ($local && strpos($ref, $base) === 0) {
$ref = substr($ref, strlen($base)); $ref = substr($ref, strlen($base));

View file

@ -56,6 +56,14 @@ class Router {
*/ */
public static $initialized = false; public static $initialized = false;
/**
* Contains the base string that will be applied to all generated URLs
* For example `https://example.com`
*
* @var string
*/
protected static $_baseURL;
/** /**
* List of action prefixes used in connected routes. * List of action prefixes used in connected routes.
* Includes admin prefix * Includes admin prefix
@ -759,7 +767,7 @@ class Router {
* cake relative URLs are required when using requestAction. * cake relative URLs are required when using requestAction.
* - `?` - Takes an array of query string parameters * - `?` - Takes an array of query string parameters
* - `#` - Allows you to set URL hash fragments. * - `#` - Allows you to set URL hash fragments.
* - `full_base` - If true the `FULL_BASE_URL` constant will be prepended to generated URLs. * - `full_base` - If true the `Router::baseURL()` value will be prepended to generated URLs.
* *
* @param string|array $url Cake-relative URL, like "/products/edit/92" or "/presidents/elect/4" * @param string|array $url Cake-relative URL, like "/products/edit/92" or "/presidents/elect/4"
* or an array specifying any of the following: 'controller', 'action', * or an array specifying any of the following: 'controller', 'action',
@ -796,8 +804,8 @@ class Router {
if (empty($url)) { if (empty($url)) {
$output = isset($path['here']) ? $path['here'] : '/'; $output = isset($path['here']) ? $path['here'] : '/';
if ($full && defined('FULL_BASE_URL')) { if ($full) {
$output = FULL_BASE_URL . $output; $output = self::baseURL() . $output;
} }
return $output; return $output;
} elseif (is_array($url)) { } elseif (is_array($url)) {
@ -884,8 +892,8 @@ class Router {
if ($protocol === 0) { if ($protocol === 0) {
$output = str_replace('//', '/', $base . '/' . $output); $output = str_replace('//', '/', $base . '/' . $output);
if ($full && defined('FULL_BASE_URL')) { if ($full) {
$output = FULL_BASE_URL . $output; $output = self::baseURL() . $output;
} }
if (!empty($extension)) { if (!empty($extension)) {
$output = rtrim($output, '/'); $output = rtrim($output, '/');
@ -894,6 +902,32 @@ class Router {
return $output . $extension . self::queryString($q, array(), $escape) . $frag; return $output . $extension . self::queryString($q, array(), $escape) . $frag;
} }
/**
* Sets the full base url that will be used as a prefix for generating
* fully qualified URLs for this application. If not parameters are passed,
* the currently configured value is returned
*
* ## Note:
*
* If you change during runtime the configuration value ``App.fullBaseURL``
* and expect the router to produce links using the new setting, you are
* required to call this method passing such value again.
*
* @param string $base the prefix for URLs generated containing the domain.
* For example: ``http://example.com``
* @return string
*/
public static function baseURL($base = null) {
if ($base !== null) {
self::$_baseURL = $base;
Configure::write('App.fullBaseURL', $base);
}
if (empty(self::$_baseURL)) {
self::$_baseURL = Configure::read('App.fullBaseURL');
}
return self::$_baseURL;
}
/** /**
* A special fallback method that handles URL arrays that cannot match * A special fallback method that handles URL arrays that cannot match
* any defined routes. * any defined routes.

View file

@ -467,7 +467,9 @@ class ObjectTest extends CakeTestCase {
$expected = 'This is a test'; $expected = 'This is a test';
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);
$result = $this->object->requestAction(FULL_BASE_URL . '/request_action/test_request_action'); $result = $this->object->requestAction(
Configure::read('App.fullBaseURL') . '/request_action/test_request_action'
);
$expected = 'This is a test'; $expected = 'This is a test';
$this->assertEquals($expected, $result); $this->assertEquals($expected, $result);

View file

@ -147,7 +147,7 @@ class CakeRequestTest extends CakeTestCase {
$request = new CakeRequest(); $request = new CakeRequest();
$this->assertEquals('some/path', $request->url); $this->assertEquals('some/path', $request->url);
$_SERVER['REQUEST_URI'] = FULL_BASE_URL . '/other/path?url=http://cakephp.org'; $_SERVER['REQUEST_URI'] = Configure::read('App.fullBaseURL') . '/other/path?url=http://cakephp.org';
$request = new CakeRequest(); $request = new CakeRequest();
$this->assertEquals('other/path', $request->url); $this->assertEquals('other/path', $request->url);
} }
@ -679,19 +679,19 @@ class CakeRequestTest extends CakeTestCase {
$result = $request->referer(); $result = $request->referer();
$this->assertSame($result, '/'); $this->assertSame($result, '/');
$_SERVER['HTTP_REFERER'] = FULL_BASE_URL . '/some/path'; $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseURL') . '/some/path';
$result = $request->referer(true); $result = $request->referer(true);
$this->assertSame($result, '/some/path'); $this->assertSame($result, '/some/path');
$_SERVER['HTTP_REFERER'] = FULL_BASE_URL . '/some/path'; $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseURL') . '/some/path';
$result = $request->referer(false); $result = $request->referer(false);
$this->assertSame($result, FULL_BASE_URL . '/some/path'); $this->assertSame($result, Configure::read('App.fullBaseURL') . '/some/path');
$_SERVER['HTTP_REFERER'] = FULL_BASE_URL . '/some/path'; $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseURL') . '/some/path';
$result = $request->referer(true); $result = $request->referer(true);
$this->assertSame($result, '/some/path'); $this->assertSame($result, '/some/path');
$_SERVER['HTTP_REFERER'] = FULL_BASE_URL . '/recipes/add'; $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseURL') . '/recipes/add';
$result = $request->referer(true); $result = $request->referer(true);
$this->assertSame($result, '/recipes/add'); $this->assertSame($result, '/recipes/add');
@ -1717,7 +1717,7 @@ class CakeRequestTest extends CakeTestCase {
'SERVER_NAME' => 'localhost', 'SERVER_NAME' => 'localhost',
'DOCUMENT_ROOT' => '/Library/WebServer/Documents', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents',
'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/index.php', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/index.php',
'REQUEST_URI' => FULL_BASE_URL . '/site/posts/index', 'REQUEST_URI' => '/site/posts/index',
'SCRIPT_NAME' => '/site/app/webroot/index.php', 'SCRIPT_NAME' => '/site/app/webroot/index.php',
'PHP_SELF' => '/site/app/webroot/index.php', 'PHP_SELF' => '/site/app/webroot/index.php',
), ),

View file

@ -49,6 +49,8 @@ class RouterTest extends CakeTestCase {
public function tearDown() { public function tearDown() {
parent::tearDown(); parent::tearDown();
CakePlugin::unload(); CakePlugin::unload();
Router::baseURL('');
Configure::write('App.fullBaseURL', 'http://localhost');
} }
/** /**
@ -57,16 +59,27 @@ class RouterTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testFullBaseURL() { public function testFullBaseURL() {
$skip = PHP_SAPI === 'cli';
if ($skip) {
$this->markTestSkipped('Cannot validate base URLs in CLI');
}
$this->assertRegExp('/^http(s)?:\/\//', Router::url('/', true)); $this->assertRegExp('/^http(s)?:\/\//', Router::url('/', true));
$this->assertRegExp('/^http(s)?:\/\//', Router::url(null, true)); $this->assertRegExp('/^http(s)?:\/\//', Router::url(null, true));
$this->assertRegExp('/^http(s)?:\/\//', Router::url(array('full_base' => true))); $this->assertRegExp('/^http(s)?:\/\//', Router::url(array('full_base' => true)));
$this->assertSame(FULL_BASE_URL . '/', Router::url(array('full_base' => true))); $this->assertSame(FULL_BASE_URL . '/', Router::url(array('full_base' => true)));
} }
/**
* Tests that the base URL can be changed at runtime
*
* @return void
*/
public function testBaseURL() {
$this->assertEquals(FULL_BASE_URL, Router::baseUrl());
Router::baseURL('http://example.com');
$this->assertEquals('http://example.com/', Router::url('/', true));
$this->assertEquals('http://example.com', Configure::read('App.fullBaseURL'));
Router::baseURL('https://example.com');
$this->assertEquals('https://example.com/', Router::url('/', true));
$this->assertEquals('https://example.com', Configure::read('App.fullBaseURL'));
}
/** /**
* testRouteDefaultParams method * testRouteDefaultParams method
* *

View file

@ -210,7 +210,7 @@ class HtmlHelperTest extends CakeTestCase {
Router::reload(); Router::reload();
$result = $this->Html->link('Posts', array('controller' => 'posts', 'action' => 'index', 'full_base' => true)); $result = $this->Html->link('Posts', array('controller' => 'posts', 'action' => 'index', 'full_base' => true));
$expected = array('a' => array('href' => FULL_BASE_URL . '/posts'), 'Posts', '/a'); $expected = array('a' => array('href' => Router::baseURL() . '/posts'), 'Posts', '/a');
$this->assertTags($result, $expected); $this->assertTags($result, $expected);
$result = $this->Html->link('Home', '/home', array('confirm' => 'Are you sure you want to do this?')); $result = $this->Html->link('Home', '/home', array('confirm' => 'Are you sure you want to do this?'));

View file

@ -644,13 +644,13 @@ class HelperTest extends CakeTestCase {
), ),
array('fullBase' => true) array('fullBase' => true)
); );
$this->assertEquals(FULL_BASE_URL . '/js/post.js', $result); $this->assertEquals(Router::baseURL() . '/js/post.js', $result);
$result = $this->Helper->assetUrl('foo.jpg', array('pathPrefix' => 'img/')); $result = $this->Helper->assetUrl('foo.jpg', array('pathPrefix' => 'img/'));
$this->assertEquals('img/foo.jpg', $result); $this->assertEquals('img/foo.jpg', $result);
$result = $this->Helper->assetUrl('foo.jpg', array('fullBase' => true)); $result = $this->Helper->assetUrl('foo.jpg', array('fullBase' => true));
$this->assertEquals(FULL_BASE_URL . '/foo.jpg', $result); $this->assertEquals(Router::baseURL() . '/foo.jpg', $result);
$result = $this->Helper->assetUrl('style', array('ext' => '.css')); $result = $this->Helper->assetUrl('style', array('ext' => '.css'));
$this->assertEquals('style.css', $result); $this->assertEquals('style.css', $result);

View file

@ -328,7 +328,7 @@ class Helper extends Object {
$path = $this->_encodeUrl($this->assetTimestamp($this->webroot($path))); $path = $this->_encodeUrl($this->assetTimestamp($this->webroot($path)));
if (!empty($options['fullBase'])) { if (!empty($options['fullBase'])) {
$path = rtrim(FULL_BASE_URL, '/') . '/' . ltrim($path, '/'); $path = rtrim(Router::baseURL(), '/') . '/' . ltrim($path, '/');
} }
return $path; return $path;
} }

View file

@ -141,6 +141,15 @@ require CAKE . 'basics.php';
require CAKE . 'Core' . DS . 'App.php'; require CAKE . 'Core' . DS . 'App.php';
require CAKE . 'Error' . DS . 'exceptions.php'; require CAKE . 'Error' . DS . 'exceptions.php';
spl_autoload_register(array('App', 'load'));
App::uses('ErrorHandler', 'Error');
App::uses('Configure', 'Core');
App::uses('CakePlugin', 'Core');
App::uses('Cache', 'Cache');
App::uses('Object', 'Core');
App::uses('Multibyte', 'I18n');
/** /**
* Full URL prefix * Full URL prefix
*/ */
@ -154,18 +163,11 @@ if (!defined('FULL_BASE_URL')) {
if (isset($httpHost)) { if (isset($httpHost)) {
define('FULL_BASE_URL', 'http' . $s . '://' . $httpHost); define('FULL_BASE_URL', 'http' . $s . '://' . $httpHost);
Configure::write('App.fullBaseURL', FULL_BASE_URL);
} }
unset($httpHost, $s); unset($httpHost, $s);
} }
spl_autoload_register(array('App', 'load'));
App::uses('ErrorHandler', 'Error');
App::uses('Configure', 'Core');
App::uses('CakePlugin', 'Core');
App::uses('Cache', 'Cache');
App::uses('Object', 'Core');
App::uses('Multibyte', 'I18n');
App::$bootstrapping = true; App::$bootstrapping = true;
Configure::bootstrap(isset($boot) ? $boot : true); Configure::bootstrap(isset($boot) ? $boot : true);