diff --git a/src/Helper/ServerUrl.php b/src/Helper/ServerUrl.php index 1de22fe8f..72de35fbc 100644 --- a/src/Helper/ServerUrl.php +++ b/src/Helper/ServerUrl.php @@ -15,12 +15,20 @@ /** * Helper for returning the current server URL (optionally with request URI) + * + * @psalm-suppress DeprecatedProperty,DeprecatedMethod + * @final */ class ServerUrl extends AbstractHelper { + use DeprecatedAbstractHelperHierarchyTrait; + /** * Host (including port) * + * @deprecated since 2.21.0, this property will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @var string|null */ protected $host; @@ -28,6 +36,9 @@ class ServerUrl extends AbstractHelper /** * Port * + * @deprecated since 2.21.0, this property will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @var int|null */ protected $port; @@ -35,6 +46,9 @@ class ServerUrl extends AbstractHelper /** * Scheme * + * @deprecated since 2.21.0, this property will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @var string|null */ protected $scheme; @@ -42,10 +56,20 @@ class ServerUrl extends AbstractHelper /** * Whether or not to query proxy servers for address * + * @deprecated since 2.21.0, this property will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @var bool */ protected $useProxy = false; + private ?string $serverUrl; + + public function __construct(?string $serverUrl = null) + { + $this->serverUrl = $serverUrl; + } + /** * View helper entry point: * Returns the current host's URL like http://site.com @@ -60,19 +84,28 @@ class ServerUrl extends AbstractHelper public function __invoke($requestUri = null) { if ($requestUri === true) { - $path = $_SERVER['REQUEST_URI']; - } elseif (is_string($requestUri)) { - $path = $requestUri; - } else { - $path = ''; + /** @var string|null $requestUri */ + $requestUri = $_SERVER['REQUEST_URI'] ?? null; } - return $this->getScheme() . '://' . $this->getHost() . $path; + $path = is_string($requestUri) ? $requestUri : ''; + $serverUrl = $this->serverUrl ?: $this->legacyServerUrlDetection(); + + return $serverUrl . $path; + } + + private function legacyServerUrlDetection(): string + { + /** @psalm-suppress DeprecatedMethod */ + return $this->getScheme() . '://' . $this->getHost(); } /** * Detect the host based on headers * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @return void */ protected function detectHost() @@ -118,6 +151,9 @@ protected function detectHost() /** * Detect the port + * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. */ protected function detectPort(): void { @@ -136,6 +172,9 @@ protected function detectPort(): void /** * Detect the scheme + * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. */ protected function detectScheme(): void { @@ -158,6 +197,10 @@ protected function detectScheme(): void $this->setScheme($scheme); } + /** + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + */ protected function isReversedProxy(): bool { return isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https'; @@ -166,6 +209,9 @@ protected function isReversedProxy(): bool /** * Detect if a proxy is in use, and, if so, set the host based on it * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @return bool */ protected function setHostFromProxy() @@ -194,6 +240,9 @@ protected function setHostFromProxy() /** * Set port based on detected proxy headers * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @return bool */ protected function setPortFromProxy() @@ -215,6 +264,9 @@ protected function setPortFromProxy() /** * Set the current scheme based on detected proxy headers * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @return bool */ protected function setSchemeFromProxy() @@ -248,6 +300,9 @@ protected function setSchemeFromProxy() /** * Sets host * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @param string $host * @return ServerUrl */ @@ -272,6 +327,9 @@ public function setHost($host) /** * Returns host * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @return string */ public function getHost() @@ -286,6 +344,9 @@ public function getHost() /** * Set server port * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @param int|numeric-string $port * @return ServerUrl */ @@ -299,6 +360,9 @@ public function setPort($port) /** * Retrieve the server port * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @return int|null */ public function getPort() @@ -313,6 +377,9 @@ public function getPort() /** * Sets scheme (typically http or https) * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @param string $scheme * @return ServerUrl */ @@ -326,6 +393,9 @@ public function setScheme($scheme) /** * Returns scheme (typically http or https) * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @return string */ public function getScheme() @@ -340,6 +410,9 @@ public function getScheme() /** * Set flag indicating whether or not to query proxy servers * + * @deprecated since 2.21.0, this method will be removed in version 3.0.0 of this component. + * The server url should be given to the constructor. + * * @param bool $useProxy * @return ServerUrl */ diff --git a/test/Helper/ServerUrlTest.php b/test/Helper/ServerUrlTest.php index 0ee10a40e..2dfade543 100644 --- a/test/Helper/ServerUrlTest.php +++ b/test/Helper/ServerUrlTest.php @@ -4,7 +4,7 @@ namespace LaminasTest\View\Helper; -use Laminas\View\Helper; +use Laminas\View\Helper\ServerUrl; use PHPUnit\Framework\TestCase; use stdClass; @@ -17,9 +17,6 @@ class ServerUrlTest extends TestCase */ protected $serverBackup; - /** - * Prepares the environment before running a test. - */ protected function setUp(): void { $this->serverBackup = $_SERVER; @@ -27,183 +24,218 @@ protected function setUp(): void unset($_SERVER['SERVER_PORT']); } - /** - * Cleans up the environment after running a test. - */ protected function tearDown(): void { $_SERVER = $this->serverBackup; } + public function testConfiguredServerUrlWillBeUsed(): void + { + $helper = new ServerUrl('https://example.com'); + self::assertEquals('https://example.com', $helper()); + } + + public function testPathWillBeAppendedToConfiguredServerUrl(): void + { + $helper = new ServerUrl('https://example.com'); + self::assertEquals('https://example.com/foo', $helper('/foo')); + } + + public function testRequestUriWillBeAppendedWhenArgumentIsTrue(): void + { + $helper = new ServerUrl('https://example.com'); + $_SERVER['REQUEST_URI'] = '/baz'; + self::assertEquals('https://example.com/baz', $helper(true)); + } + + /** @deprecated */ public function testConstructorWithOnlyHost(): void { $_SERVER['HTTP_HOST'] = 'example.com'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://example.com', $url->__invoke()); } + /** @deprecated */ public function testConstructorWithOnlyHostIncludingPort(): void { $_SERVER['HTTP_HOST'] = 'example.com:8000'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://example.com:8000', $url->__invoke()); } + /** @deprecated */ public function testConstructorWithHostAndHttpsOn(): void { $_SERVER['HTTP_HOST'] = 'example.com'; $_SERVER['HTTPS'] = 'on'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('https://example.com', $url->__invoke()); } + /** @deprecated */ public function testConstructorWithHostAndHttpsTrue(): void { $_SERVER['HTTP_HOST'] = 'example.com'; $_SERVER['HTTPS'] = true; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('https://example.com', $url->__invoke()); } + /** @deprecated */ public function testConstructorWithHostIncludingPortAndHttpsTrue(): void { $_SERVER['HTTP_HOST'] = 'example.com:8181'; $_SERVER['HTTPS'] = true; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('https://example.com:8181', $url->__invoke()); } + /** @deprecated */ public function testConstructorWithHostReversedProxyHttpsTrue(): void { $_SERVER['HTTP_HOST'] = 'example.com'; $_SERVER['HTTP_X_FORWARDED_PROTO'] = 'https'; $_SERVER['SERVER_PORT'] = 80; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('https://example.com', $url->__invoke()); } + /** @deprecated */ public function testConstructorWithHttpHostIncludingPortAndPortSet(): void { $_SERVER['HTTP_HOST'] = 'example.com:8181'; $_SERVER['SERVER_PORT'] = 8181; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://example.com:8181', $url->__invoke()); } + /** @deprecated */ public function testConstructorWithHttpHostAndServerNameAndPortSet(): void { $_SERVER['HTTP_HOST'] = 'example.com'; $_SERVER['SERVER_NAME'] = 'example.org'; $_SERVER['SERVER_PORT'] = 8080; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://example.com:8080', $url->__invoke()); } + /** @deprecated */ public function testConstructorWithNoHttpHostButServerNameAndPortSet(): void { unset($_SERVER['HTTP_HOST']); $_SERVER['SERVER_NAME'] = 'example.org'; $_SERVER['SERVER_PORT'] = 8080; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://example.org:8080', $url->__invoke()); } + /** @deprecated */ public function testServerUrlWithTrueParam(): void { $_SERVER['HTTPS'] = 'off'; $_SERVER['HTTP_HOST'] = 'example.com'; $_SERVER['REQUEST_URI'] = '/foo.html'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://example.com/foo.html', $url->__invoke(true)); } + /** @deprecated */ public function testServerUrlWithInteger(): void { $_SERVER['HTTPS'] = 'off'; $_SERVER['HTTP_HOST'] = 'example.com'; $_SERVER['REQUEST_URI'] = '/foo.html'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://example.com', $url->__invoke(1337)); } + /** @deprecated */ public function testServerUrlWithObject(): void { $_SERVER['HTTPS'] = 'off'; $_SERVER['HTTP_HOST'] = 'example.com'; $_SERVER['REQUEST_URI'] = '/foo.html'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://example.com', $url->__invoke(new stdClass())); } + /** @deprecated */ public function testServerUrlWithScheme(): void { $_SERVER['HTTP_SCHEME'] = 'https'; $_SERVER['HTTP_HOST'] = 'example.com'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('https://example.com', $url->__invoke()); } + /** @deprecated */ public function testServerUrlWithPort(): void { $_SERVER['SERVER_PORT'] = 443; $_SERVER['HTTP_HOST'] = 'example.com'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('https://example.com', $url->__invoke()); } + /** @deprecated */ public function testServerUrlWithProxy(): void { $_SERVER['HTTP_HOST'] = 'proxyserver.com'; $_SERVER['HTTP_X_FORWARDED_HOST'] = 'www.firsthost.org'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $url->setUseProxy(true); $this->assertEquals('http://www.firsthost.org', $url->__invoke()); } + /** @deprecated */ public function testServerUrlWithMultipleProxies(): void { $_SERVER['HTTP_HOST'] = 'proxyserver.com'; $_SERVER['HTTP_X_FORWARDED_HOST'] = 'www.firsthost.org, www.secondhost.org'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $url->setUseProxy(true); $this->assertEquals('http://www.secondhost.org', $url->__invoke()); } + /** @deprecated */ public function testDoesNotUseProxyByDefault(): void { $_SERVER['HTTP_HOST'] = 'proxyserver.com'; $_SERVER['HTTP_X_FORWARDED_HOST'] = 'www.firsthost.org, www.secondhost.org'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://proxyserver.com', $url->__invoke()); } + /** @deprecated */ public function testCanUseXForwardedPortIfProvided(): void { $_SERVER['HTTP_HOST'] = 'proxyserver.com'; $_SERVER['HTTP_X_FORWARDED_HOST'] = 'www.firsthost.org, www.secondhost.org'; $_SERVER['HTTP_X_FORWARDED_PORT'] = '8888'; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $url->setUseProxy(true); $this->assertEquals('http://www.secondhost.org:8888', $url->__invoke()); } + /** @deprecated */ public function testUsesHostHeaderWhenPortForwardingDetected(): void { $_SERVER['HTTP_HOST'] = 'localhost:10088'; $_SERVER['SERVER_PORT'] = 10081; - $url = new Helper\ServerUrl(); + $url = new ServerUrl(); $this->assertEquals('http://localhost:10088', $url->__invoke()); } }