diff --git a/CHANGELOG-4.0.md b/CHANGELOG-4.0.md index 7f299f3c1de..ce547632104 100644 --- a/CHANGELOG-4.0.md +++ b/CHANGELOG-4.0.md @@ -23,6 +23,7 @@ The implementation offers PSR-7/PSR-17 compatible components in a different name - `Phalcon\Helper\Number` [#13889](https://github.com/phalcon/cphalcon/pull/13889) - Added `Phalcon\Collection`, an object implementing `ArrayAccess`, `Countable`, `IteratorAggregate`, `JsonSerializable`, `Serializable`, offering an easy way to handle collections of data such as arrays, superglobals etc. [#13886](https://github.com/phalcon/cphalcon/issues/13886) +- Added `Phalcon\Collection`, in `Phalcon\Http\Message\Request` and `Phalcon\Http\Message\ServerRequest` to handle the headers [#13907](https://github.com/phalcon/cphalcon/issues/13907) ## Fixed - Fixed `Phalcon\Image\Adapter\Imagick::_watermark`, `setImageAlpha()` fills the alpha channel with black before execution (replaced by `evaluateImage()`). Improved imagick compatibility. [#13911](https://github.com/phalcon/cphalcon/pull/13911) diff --git a/phalcon/collection.zep b/phalcon/collection.zep index d78a9a418f4..a04e5cdab83 100644 --- a/phalcon/collection.zep +++ b/phalcon/collection.zep @@ -91,12 +91,12 @@ class Collection implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonS /** * Get the element from the collection */ - public function get(string! element, var defaultValue = null, bool insensitive = true) -> var | bool + public function get(string! element, var defaultValue = null, bool insensitive = true) -> var { var value; if likely insensitive { - let element = strtolower(element); + let element = element->lower(); } if likely fetch value, this->lowerKeys[element] { @@ -120,7 +120,7 @@ class Collection implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonS public function has(string! element, bool insensitive = true) -> bool { if likely insensitive { - let element = strtolower(element); + let element = element->lower(); } return isset this->lowerKeys[element]; @@ -209,7 +209,7 @@ class Collection implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonS if this->has(element) { if likely insensitive { - let element = strtolower(element); + let element = element->lower(); } let value = lowerKeys[element]; @@ -239,7 +239,7 @@ class Collection implements \ArrayAccess, \Countable, \IteratorAggregate, \JsonS { var key; - let key = strtolower(element); + let key = element->lower(); let this->data[element] = value, this->lowerKeys[key] = element; diff --git a/phalcon/http/message/request.zep b/phalcon/http/message/request.zep index 0594a65cb37..ef85275b557 100644 --- a/phalcon/http/message/request.zep +++ b/phalcon/http/message/request.zep @@ -14,7 +14,7 @@ namespace Phalcon\Http\Message; -use Phalcon\Helper\Arr; +use Phalcon\Collection; use Phalcon\Http\Message\Stream\Input; use Phalcon\Http\Message\Uri; use Psr\Http\Message\RequestInterface; @@ -50,9 +50,9 @@ class Request implements RequestInterface private body { get }; /** - * @var array + * @var */ - private headers = []; + private headers; /** * Retrieves the HTTP method of the request. @@ -93,21 +93,16 @@ class Request implements RequestInterface /** * Constructor */ - public function __construct(string method = "GET", var uri = null, var body = "php://temp", array headers = []) + public function __construct(string method = "GET", var uri = null, var body = "php://memory", var headers = []) { if "php://input" === body { let body = new Input(); } - this - ->processHeaders(headers) - ->processUri(uri); - - this->checkMethod(method); - - let - this->method = method, - this->body = this->processBody(body, "w+b"); + let this->headers = this->processHeaders(headers), + this->uri = this->processUri(uri), + this->method = this->processMethod(method), + this->body = this->processBody(body, "w+b"); } /** @@ -121,12 +116,9 @@ class Request implements RequestInterface */ public function getHeader(var name) -> array { - var element, key; + let name = (string) name; - let key = strtolower(name), - element = Arr::get(this->headers, key, []); - - return Arr::get(element, "value", []); + return this->headers->get(name, []); } /** @@ -179,16 +171,7 @@ class Request implements RequestInterface */ public function getHeaders() -> array { - var element, headers; - array headerData; - - let headers = this->headers, - headerData = []; - for element in headers { - let headerData[element["name"]] = element["value"]; - } - - return headerData; + return this->headers->toArray(); } /** @@ -227,7 +210,7 @@ class Request implements RequestInterface */ public function hasHeader(var name) -> bool { - return isset this->headers[strtolower(name)]; + return this->headers->has(name); } /** @@ -243,21 +226,16 @@ class Request implements RequestInterface */ public function withAddedHeader(var name, var value) -> { - var existing, headers, key; + var existing, headers; this->checkHeaderName(name); - let key = strtolower(name), - headers = this->headers, - existing = Arr::get(headers, key, []), - existing = Arr::get(existing, "value", []), + let headers = clone this->headers, + existing = headers->get(name, []), value = this->getHeaderValue(value), - existing = array_merge(existing, value); + value = array_merge(existing, value); - let headers[key] = [ - "name" : name, - "value" : existing - ]; + headers->set(name, value); return this->cloneInstance(headers, "headers"); } @@ -296,18 +274,14 @@ class Request implements RequestInterface */ public function withHeader(var name, var value) -> { - var headers, key; + var headers; this->checkHeaderName(name); - let key = strtolower(name), - headers = this->headers, + let headers = clone this->headers, value = this->getHeaderValue(value); - let headers[key] = [ - "name" : name, - "value" : value - ]; + headers->set(name, value); return this->cloneInstance(headers, "headers"); } @@ -327,7 +301,7 @@ class Request implements RequestInterface */ public function withMethod(var method) -> { - this->checkMethod(method); + this->processMethod(method); return this->cloneInstance(method, "method"); } @@ -344,7 +318,7 @@ class Request implements RequestInterface */ public function withProtocolVersion(var version) -> { - this->checkProtocol(version); + this->processProtocol(version); return this->cloneInstance(version, "protocolVersion"); } @@ -407,20 +381,17 @@ class Request implements RequestInterface var headers, host, newInstance; let preserveHost = (bool) preserveHost, - headers = this->headers, + headers = clone this->headers, newInstance = clone this, newInstance->uri = uri; if !(true === preserveHost && - true === this->hasHeader("Host") && + true === headers->has("Host") && "" !== uri->getHost()) { let host = this->getUriHost(uri); - let headers["host"] = [ - "name" : "Host", - "value" : [host] - ]; + headers->set("Host", [host]); let newInstance->headers = headers; } @@ -439,12 +410,11 @@ class Request implements RequestInterface */ public function withoutHeader(var name) -> { - var headers, key; + var headers; - let key = strtolower(name), - headers = this->headers; + let headers = clone this->headers; - unset headers[key]; + headers->remove(name); return this->cloneInstance(headers, "headers"); } @@ -520,70 +490,19 @@ class Request implements RequestInterface } } - /** - * Check the method - */ - private function checkMethod(var method = "") -> - { - array methods; - - let methods = [ - "GET" : 1, - "CONNECT" : 1, - "DELETE" : 1, - "HEAD" : 1, - "OPTIONS" : 1, - "PATCH" : 1, - "POST" : 1, - "PUT" : 1, - "TRACE" : 1 - ]; - - if !(!empty(method) && typeof method === "string" && isset methods[method]) { - throw new \InvalidArgumentException("Invalid or unsupported method " . method); - } - - return this; - } - - /** - * Checks the protocol - */ - private function checkProtocol(var protocol = "") -> - { - array protocols; - - let protocols = [ - "1.0" : 1, - "1.1" : 1, - "2.0" : 1, - "3.0" : 1 - ]; - - if (empty(protocol)) || typeof protocol !== "string" { - throw new \InvalidArgumentException("Invalid protocol value"); - } - - if !isset protocols[protocol] { - throw new \InvalidArgumentException("Unsupported protocol " . protocol); - } - - return this; - } - /** * Returns a new instance having set the parameter */ private function cloneInstance(var element, string property) -> { - var newInstance; + var newInstance; - let newInstance = clone this; + let newInstance = clone this; if element !== this->{property} { - let newInstance->{property} = element; - } + let newInstance->{property} = element; + } - return newInstance; + return newInstance; } /** @@ -647,43 +566,106 @@ class Request implements RequestInterface /** * Sets the headers */ - private function processHeaders(array headers) -> + private function processHeaders(var headers) -> { - var key, name, value; - array headerData; + var collection, host, name, value; + + if typeof headers === "array" { + let collection = new Collection(); + for name, value in headers { + + this->checkHeaderName(name); + + let name = (string) name, + value = this->getHeaderValue(value); + + collection->set(name, value); + } + + if true === collection->has("host") && "" !== this->uri->getHost() { + let host = this->getUriHost(this->uri); + + collection->set("Host", [host]); + } + } else { + if headers instanceof Collection { + let collection = headers; + } else { + throw new \InvalidArgumentException( + "Headers needs to be either an array or instance of Phalcon\Collection" + ); + } + } + + return collection; + } + + /** + * Check the method + */ + private function processMethod(var method = "") -> string + { + array methods; + + let methods = [ + "GET" : 1, + "CONNECT" : 1, + "DELETE" : 1, + "HEAD" : 1, + "OPTIONS" : 1, + "PATCH" : 1, + "POST" : 1, + "PUT" : 1, + "TRACE" : 1 + ]; - let headerData = []; - for name, value in headers { + if !(!empty(method) && typeof method === "string" && isset methods[method]) { + throw new \InvalidArgumentException("Invalid or unsupported method " . method); + } - this->checkHeaderName(name); + return method; + } - let key = strtolower(name), - value = this->getHeaderValue(value); + /** + * Checks the protocol + */ + private function processProtocol(var protocol = "") -> string + { + array protocols; - let headerData[key] = [ - "name" : name, - "value" : value - ]; + let protocols = [ + "1.0" : 1, + "1.1" : 1, + "2.0" : 1, + "3.0" : 1 + ]; + + if (empty(protocol)) || typeof protocol !== "string" { + throw new \InvalidArgumentException("Invalid protocol value"); } - let this->headers = headerData; + if !isset protocols[protocol] { + throw new \InvalidArgumentException("Unsupported protocol " . protocol); + } - return this; + return protocol; } /** * Sets a valid Uri */ - private function processUri(var uri) -> + private function processUri(var uri) -> { + var localUri; + if uri instanceof UriInterface { - let this->uri = uri; + let localUri = uri; } elseif typeof uri === "string" || null === uri { - let this->uri = new Uri(uri); + let localUri = new Uri(uri); } else { throw new \InvalidArgumentException("Invalid uri passed as a parameter"); } - return this; + return localUri; } } diff --git a/phalcon/http/message/response.zep b/phalcon/http/message/response.zep index bdfce43a35d..eade144a0fc 100644 --- a/phalcon/http/message/response.zep +++ b/phalcon/http/message/response.zep @@ -14,7 +14,7 @@ namespace Phalcon\Http\Message; -use Phalcon\Helper\Arr; +use Phalcon\Collection; use Phalcon\Http\Message\Stream; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\StreamInterface; @@ -44,9 +44,9 @@ class Response implements ResponseInterface private body { get }; /** - * @var array + * @var */ - private headers = []; + private headers; /** * Retrieves the HTTP protocol version as a string. @@ -88,11 +88,10 @@ class Response implements ResponseInterface */ public function __construct(var body = "php://memory", int code = 200, array headers = []) { - this - ->processHeaders(headers) - ->processCode(code); + this->processCode(code); - let this->body = this->processBody(body, "w+b"); + let this->headers = this->processHeaders(headers), + this->body = this->processBody(body, "w+b"); } /** @@ -106,12 +105,9 @@ class Response implements ResponseInterface */ public function getHeader(var name) -> array { - var element, key; + let name = (string) name; - let key = strtolower(name), - element = Arr::get(this->headers, key, []); - - return Arr::get(element, "value", []); + return this->headers->get(name, []); } /** @@ -164,16 +160,7 @@ class Response implements ResponseInterface */ public function getHeaders() -> array { - var element, headers; - array headerData; - - let headers = this->headers, - headerData = []; - for element in headers { - let headerData[element["name"]] = element["value"]; - } - - return headerData; + return this->headers->toArray(); } /** @@ -181,7 +168,7 @@ class Response implements ResponseInterface */ public function hasHeader(var name) -> bool { - return isset this->headers[strtolower(name)]; + return this->headers->has(name); } /** @@ -197,21 +184,16 @@ class Response implements ResponseInterface */ public function withAddedHeader(var name, var value) -> { - var existing, headers, key; + var existing, headers; this->checkHeaderName(name); - let key = strtolower(name), - headers = this->headers, - existing = Arr::get(headers, key, []), - existing = Arr::get(existing, "value", []), + let headers = clone this->headers, + existing = headers->get(name, []), value = this->getHeaderValue(value), - existing = array_merge(existing, value); + value = array_merge(existing, value); - let headers[key] = [ - "name" : name, - "value" : existing - ]; + headers->set(name, value); return this->cloneInstance(headers, "headers"); } @@ -250,18 +232,14 @@ class Response implements ResponseInterface */ public function withHeader(var name, var value) -> { - var headers, key; + var headers; this->checkHeaderName(name); - let key = strtolower(name), - headers = this->headers, + let headers = clone this->headers, value = this->getHeaderValue(value); - let headers[key] = [ - "name" : name, - "value" : value - ]; + headers->set(name, value); return this->cloneInstance(headers, "headers"); } @@ -278,7 +256,7 @@ class Response implements ResponseInterface */ public function withProtocolVersion(var version) -> { - this->checkProtocol(version); + this->processProtocol(version); return this->cloneInstance(version, "protocolVersion"); } @@ -301,10 +279,6 @@ class Response implements ResponseInterface { var newInstance; - if code === this->statusCode { - return this; - } - /** * Immutable - need to send a new object back */ @@ -326,12 +300,11 @@ class Response implements ResponseInterface */ public function withoutHeader(var name) -> { - var headers, key; + var headers; - let key = strtolower(name), - headers = this->headers; + let headers = clone this->headers; - unset headers[key]; + headers->remove(name); return this->cloneInstance(headers, "headers"); } @@ -405,31 +378,6 @@ class Response implements ResponseInterface } } - /** - * Checks the protocol - */ - private function checkProtocol(var protocol = "") -> - { - array protocols; - - let protocols = [ - "1.0" : 1, - "1.1" : 1, - "2.0" : 1, - "3.0" : 1 - ]; - - if (empty(protocol)) || typeof protocol !== "string" { - throw new \InvalidArgumentException("Invalid protocol value"); - } - - if !isset protocols[protocol] { - throw new \InvalidArgumentException("Unsupported protocol " . protocol); - } - - return this; - } - /** * Returns a new instance having set the parameter */ @@ -621,27 +569,46 @@ class Response implements ResponseInterface /** * Sets the headers */ - private function processHeaders(array headers) -> + private function processHeaders(array headers) -> { - var key, name, value; - array headerData; + var collection, name, value; - let headerData = []; + let collection = new Collection(); for name, value in headers { this->checkHeaderName(name); - let key = strtolower(name), + let name = (string) name, value = this->getHeaderValue(value); - let headerData[key] = [ - "name" : name, - "value" : value - ]; + collection->set(name, value); } - let this->headers = headerData; + return collection; + } + + /** + * Checks the protocol + */ + private function processProtocol(var protocol = "") -> string + { + array protocols; + + let protocols = [ + "1.0" : 1, + "1.1" : 1, + "2.0" : 1, + "3.0" : 1 + ]; + + if (empty(protocol)) || typeof protocol !== "string" { + throw new \InvalidArgumentException("Invalid protocol value"); + } + + if !isset protocols[protocol] { + throw new \InvalidArgumentException("Unsupported protocol " . protocol); + } - return this; + return protocol; } } diff --git a/phalcon/http/message/serverrequest.zep b/phalcon/http/message/serverrequest.zep index 42a3671daef..21eff55c802 100644 --- a/phalcon/http/message/serverrequest.zep +++ b/phalcon/http/message/serverrequest.zep @@ -14,7 +14,7 @@ namespace Phalcon\Http\Message; -use Phalcon\Helper\Arr; +use Phalcon\Collection; use Phalcon\Http\Message\Stream\Input; use Phalcon\Http\Message\Uri; use Psr\Http\Message\MessageInterface; @@ -65,17 +65,9 @@ use Psr\Http\Message\UriInterface; class ServerRequest implements ServerRequestInterface { /** - * Retrieve attributes derived from the request. - * - * The request "attributes" may be used to allow injection of any - * parameters derived from the request: e.g., the results of path - * match operations; the results of decrypting cookies; the results of - * deserializing non-form-encoded message bodies; etc. Attributes - * will be application and request specific, and CAN be mutable. - * - * @var array + * @var */ - private attributes = [] { get }; + private attributes; /** * Gets the body of the message. @@ -97,9 +89,9 @@ class ServerRequest implements ServerRequestInterface private cookieParams = [] { get }; /** - * @var array + * @var */ - private headers = []; + private headers; /** * Retrieves the HTTP method of the request. @@ -199,7 +191,7 @@ class ServerRequest implements ServerRequestInterface var uri = null, array serverParams = [], var body = "php://input", - array headers = [], + var headers = [], array cookies = [], array queryParams = [], array uploadFiles = [], @@ -211,24 +203,20 @@ class ServerRequest implements ServerRequestInterface let body = new Input(); } - this - ->processHeaders(headers) - ->processUri(uri); - - this - ->checkProtocol(protocol) - ->checkMethod(method) - ->checkUploadedFiles(uploadFiles); + this->checkUploadedFiles(uploadFiles); - let - this->protocolVersion = protocol, - this->method = method, - this->uploadedFiles = uploadFiles, + let this->protocolVersion = this->processProtocol(protocol), + this->method = this->processMethod(method), + this->headers = this->processHeaders(headers), + this->uri = this->processUri(uri), this->body = this->processBody(body, "w+b"), + this->uploadedFiles = uploadFiles, this->parsedBody = parsedBody, this->serverParams = serverParams, this->cookieParams = cookies, - this->queryParams = queryParams; + this->queryParams = queryParams, + this->attributes = new Collection() + ; } /** @@ -243,7 +231,21 @@ class ServerRequest implements ServerRequestInterface */ public function getAttribute(var name, var defaultValue = null) -> var { - return Arr::get(this->attributes, name, defaultValue); + return this->attributes->get(name, defaultValue); + } + + /** + * Retrieve attributes derived from the request. + * + * The request "attributes" may be used to allow injection of any + * parameters derived from the request: e.g., the results of path + * match operations; the results of decrypting cookies; the results of + * deserializing non-form-encoded message bodies; etc. Attributes + * will be application and request specific, and CAN be mutable. + */ + public function getAttributes() -> array + { + return this->attributes->toArray(); } /** @@ -257,12 +259,9 @@ class ServerRequest implements ServerRequestInterface */ public function getHeader(var name) -> array { - var element, key; - - let key = strtolower(name), - element = Arr::get(this->headers, key, []); + let name = (string) name; - return Arr::get(element, "value", []); + return this->headers->get(name, []); } /** @@ -315,16 +314,7 @@ class ServerRequest implements ServerRequestInterface */ public function getHeaders() -> array { - var element, headers; - array headerData; - - let headers = this->headers, - headerData = []; - for element in headers { - let headerData[element["name"]] = element["value"]; - } - - return headerData; + return this->headers->toArray(); } /** @@ -363,7 +353,7 @@ class ServerRequest implements ServerRequestInterface */ public function hasHeader(var name) -> bool { - return isset this->headers[strtolower(name)]; + return this->headers->has(name); } /** @@ -379,24 +369,18 @@ class ServerRequest implements ServerRequestInterface */ public function withAddedHeader(var name, var value) -> { - var existing, headers, key; + var existing, headers; this->checkHeaderName(name); - let key = strtolower(name), - headers = this->headers, - existing = Arr::get(headers, key, []), - existing = Arr::get(existing, "value", []), + let headers = clone this->headers, + existing = headers->get(name, []), value = this->getHeaderValue(value), - existing = array_merge(existing, value); + value = array_merge(existing, value); - let headers[key] = [ - "name" : name, - "value" : existing - ]; + headers->set(name, value); return this->cloneInstance(headers, "headers"); - } /** @@ -413,8 +397,9 @@ class ServerRequest implements ServerRequestInterface { var attributes; - let attributes = this->attributes, - attributes[name] = value; + let attributes = clone this->attributes; + + attributes->set(name, value); return this->cloneInstance(attributes, "attributes"); } @@ -472,18 +457,14 @@ class ServerRequest implements ServerRequestInterface */ public function withHeader(var name, var value) -> { - var headers, key; + var headers; this->checkHeaderName(name); - let key = strtolower(name), - headers = this->headers, + let headers = clone this->headers, value = this->getHeaderValue(value); - let headers[key] = [ - "name" : name, - "value" : value - ]; + headers->set(name, value); return this->cloneInstance(headers, "headers"); } @@ -503,7 +484,7 @@ class ServerRequest implements ServerRequestInterface */ public function withMethod(var method) -> { - this->checkMethod(method); + this->processMethod(method); return this->cloneInstance(method, "method"); } @@ -550,7 +531,7 @@ class ServerRequest implements ServerRequestInterface */ public function withProtocolVersion(var version) -> { - this->checkProtocol(version); + this->processProtocol(version); return this->cloneInstance(version, "protocolVersion"); } @@ -652,17 +633,17 @@ class ServerRequest implements ServerRequestInterface var headers, host, newInstance; let preserveHost = (bool) preserveHost, - headers = this->headers, + headers = clone this->headers, newInstance = clone this, newInstance->uri = uri; - if !(preserveHost && true === this->hasHeader("Host") && "" !== uri->getHost()) { + if !(true === preserveHost && + true === headers->has("Host") && + "" !== uri->getHost()) { + let host = this->getUriHost(uri); - let headers["host"] = [ - "name" : "Host", - "value" : [host] - ]; + headers->set("Host", [host]); let newInstance->headers = headers; } @@ -684,9 +665,9 @@ class ServerRequest implements ServerRequestInterface { var attributes; - let attributes = this->attributes; + let attributes = clone this->attributes; - unset attributes[name]; + attributes->remove(name); return this->cloneInstance(attributes, "attributes"); } @@ -702,12 +683,11 @@ class ServerRequest implements ServerRequestInterface */ public function withoutHeader(var name) -> { - var headers, key; + var headers; - let key = strtolower(name), - headers = this->headers; + let headers = clone this->headers; - unset headers[key]; + headers->remove(name); return this->cloneInstance(headers, "headers"); } @@ -783,61 +763,10 @@ class ServerRequest implements ServerRequestInterface } } - /** - * Check the method - */ - private function checkMethod(var method = "") -> - { - array methods; - - let methods = [ - "GET" : 1, - "CONNECT" : 1, - "DELETE" : 1, - "HEAD" : 1, - "OPTIONS" : 1, - "PATCH" : 1, - "POST" : 1, - "PUT" : 1, - "TRACE" : 1 - ]; - - if !(!empty(method) && typeof method === "string" && isset methods[method]) { - throw new \InvalidArgumentException("Invalid or unsupported method " . method); - } - - return this; - } - - /** - * Checks the protocol - */ - private function checkProtocol(var protocol = "") -> - { - array protocols; - - let protocols = [ - "1.0" : 1, - "1.1" : 1, - "2.0" : 1, - "3.0" : 1 - ]; - - if (empty(protocol)) || typeof protocol !== "string" { - throw new \InvalidArgumentException("Invalid protocol value"); - } - - if !isset protocols[protocol] { - throw new \InvalidArgumentException("Unsupported protocol " . protocol); - } - - return this; - } - /** * Checks the uploaded files */ - private function checkUploadedFiles(array files) -> + private function checkUploadedFiles(array files) -> void { var file; @@ -851,8 +780,6 @@ class ServerRequest implements ServerRequestInterface } } - - return this; } /** @@ -931,52 +858,106 @@ class ServerRequest implements ServerRequestInterface /** * Sets the headers */ - private function processHeaders(array headers) -> + private function processHeaders(var headers) -> { - var host, key, name, value; - array headerData; + var collection, host, name, value; + + if typeof headers === "array" { + let collection = new Collection(); + for name, value in headers { + + this->checkHeaderName(name); + + let name = (string) name, + value = this->getHeaderValue(value); + + collection->set(name, value); + } + + if true === collection->has("host") && "" !== this->uri->getHost() { + let host = this->getUriHost(this->uri); - let headerData = []; - for name, value in headers { + collection->set("Host", [host]); + } + } else { + if headers instanceof Collection { + let collection = headers; + } else { + throw new \InvalidArgumentException( + "Headers need to be either an array or instance of Phalcon\Collection" + ); + } + } + + return collection; + } - this->checkHeaderName(name); + /** + * Check the method + */ + private function processMethod(var method = "") -> string + { + array methods; - let key = strtolower(name), - value = this->getHeaderValue(value); + let methods = [ + "GET" : 1, + "CONNECT" : 1, + "DELETE" : 1, + "HEAD" : 1, + "OPTIONS" : 1, + "PATCH" : 1, + "POST" : 1, + "PUT" : 1, + "TRACE" : 1 + ]; - let headerData[key] = [ - "name" : name, - "value" : value - ]; + if !(!empty(method) && typeof method === "string" && isset methods[method]) { + throw new \InvalidArgumentException("Invalid or unsupported method " . method); } - if isset headerData["host"] && "" !== this->uri->getHost() { - let host = this->getUriHost(this->uri); + return method; + } - let headerData["host"] = [ - "name" : "Host", - "value" : [host] - ]; + /** + * Checks the protocol + */ + private function processProtocol(var protocol = "") -> string + { + array protocols; + + let protocols = [ + "1.0" : 1, + "1.1" : 1, + "2.0" : 1, + "3.0" : 1 + ]; + + if (empty(protocol)) || typeof protocol !== "string" { + throw new \InvalidArgumentException("Invalid protocol value"); } - let this->headers = headerData; + if !isset protocols[protocol] { + throw new \InvalidArgumentException("Unsupported protocol " . protocol); + } - return this; + return protocol; } /** * Sets a valid Uri */ - private function processUri(var uri) -> + private function processUri(var uri) -> { + var localUri; + if uri instanceof UriInterface { - let this->uri = uri; + let localUri = uri; } elseif typeof uri === "string" || null === uri { - let this->uri = new Uri(uri); + let localUri = new Uri(uri); } else { throw new \InvalidArgumentException("Invalid uri passed as a parameter"); } - return this; + return localUri; } } diff --git a/phalcon/registry.zep b/phalcon/registry.zep index 43154054025..1fc6bd0451b 100644 --- a/phalcon/registry.zep +++ b/phalcon/registry.zep @@ -125,7 +125,7 @@ final class Registry extends Collection /** * Get the element from the collection */ - public final function get(string! element, var defaultValue = null, bool insensitive = true) -> var | bool + public final function get(string! element, var defaultValue = null, bool insensitive = true) -> var { return parent::get(element, defaultValue, insensitive); } diff --git a/tests/unit/Http/Message/Request/GetHeadersCest.php b/tests/unit/Http/Message/Request/GetHeadersCest.php index 0a3865c56a0..817a3c62fe7 100644 --- a/tests/unit/Http/Message/Request/GetHeadersCest.php +++ b/tests/unit/Http/Message/Request/GetHeadersCest.php @@ -12,6 +12,7 @@ namespace Phalcon\Test\Unit\Http\Message\Request; +use Phalcon\Collection; use Phalcon\Http\Message\Request; use UnitTester; @@ -45,6 +46,32 @@ public function httpMessageRequestGetHeaders(UnitTester $I) $I->assertEquals($expected, $actual); } + /** + * Tests Phalcon\Http\Message\Request :: getHeaders() - collection + * + * @param UnitTester $I + * + * @author Phalcon Team + * @since 2019-02-10 + */ + public function httpMessageRequestGetHeadersCollection(UnitTester $I) + { + $I->wantToTest('Http\Message\Request - getHeaders()'); + $data = [ + 'Cache-Control' => ['max-age=0'], + 'Accept' => ['text/html'], + ]; + $headers = new Collection($data); + $request = new Request('GET', null, 'php://memory', $headers); + + $expected = [ + 'Accept' => ['text/html'], + 'Cache-Control' => ['max-age=0'], + ]; + $actual = $request->getHeaders(); + $I->assertEquals($expected, $actual); + } + /** * Tests Phalcon\Http\Message\Request :: getHeaders() - empty * diff --git a/tests/unit/Http/Message/ServerRequest/GetHeadersCest.php b/tests/unit/Http/Message/ServerRequest/GetHeadersCest.php index afd568e5fe2..36913966e0b 100644 --- a/tests/unit/Http/Message/ServerRequest/GetHeadersCest.php +++ b/tests/unit/Http/Message/ServerRequest/GetHeadersCest.php @@ -12,6 +12,7 @@ namespace Phalcon\Test\Unit\Http\Message\ServerRequest; +use Phalcon\Collection; use Phalcon\Http\Message\ServerRequest; use UnitTester; @@ -45,6 +46,32 @@ public function httpMessageServerRequestGetHeaders(UnitTester $I) $I->assertEquals($expected, $actual); } + /** + * Tests Phalcon\Http\Message\ServerRequest :: getHeaders() - collection + * + * @param UnitTester $I + * + * @author Phalcon Team + * @since 2019-02-10 + */ + public function httpMessageServerRequestGetHeadersCollection(UnitTester $I) + { + $I->wantToTest('Http\Message\ServerRequest - getHeaders() - collection'); + $data = [ + 'Cache-Control' => ['max-age=0'], + 'Accept' => ['text/html'], + ]; + $headers = new Collection($data); + $request = new ServerRequest('GET', null, [], 'php://input', $headers); + + $expected = [ + 'Accept' => ['text/html'], + 'Cache-Control' => ['max-age=0'], + ]; + $actual = $request->getHeaders(); + $I->assertEquals($expected, $actual); + } + /** * Tests Phalcon\Http\Message\ServerRequest :: getHeaders() - empty *