Skip to content
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,8 @@ PHP 8.6 UPGRADE NOTES
RFC: https://wiki.php.net/rfc/uri_followup#host_type_detection
. Added Uri\Rfc3986\UriBuilder.
RFC: https://wiki.php.net/rfc/uri_followup#uri_building
. Added Uri\WhatWg\UrlBuilder.
RFC: https://wiki.php.net/rfc/uri_followup#uri_building

========================================
3. Changes in SAPI modules
Expand Down
147 changes: 147 additions & 0 deletions ext/uri/php_uri.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ zend_class_entry *php_uri_ce_rfc3986_uri_builder;
zend_class_entry *php_uri_ce_rfc3986_uri;
zend_class_entry *php_uri_ce_rfc3986_uri_type;
zend_class_entry *php_uri_ce_rfc3986_uri_host_type;
zend_class_entry *php_uri_ce_whatwg_url_builder;
zend_class_entry *php_uri_ce_whatwg_url;
zend_class_entry *php_uri_ce_comparison_mode;
zend_class_entry *php_uri_ce_exception;
Expand Down Expand Up @@ -75,6 +76,17 @@ static zend_always_inline zval *php_uri_deref(zval *zv)
#define Z_RFC3986_URI_PROP_QUERY_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 5))
#define Z_RFC3986_URI_PROP_FRAGMENT_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6))

#define Z_WHATWG_URL_PROP_SCHEME_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 0)
#define Z_WHATWG_URL_PROP_SCHEME_DEREF_P(zv) php_uri_deref(Z_WHATWG_URL_PROP_SCHEME_P(zv))
#define Z_WHATWG_URL_PROP_USERNAME_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 1))
#define Z_WHATWG_URL_PROP_PASSWORD_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 2))
#define Z_WHATWG_URL_PROP_HOST_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 3))
#define Z_WHATWG_URL_PROP_PORT_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 4))
#define Z_WHATWG_URL_PROP_PATH_P(zv) OBJ_PROP_NUM(Z_OBJ_P(zv), 5)
#define Z_WHATWG_URL_PROP_PATH_DEREF_P(zv) php_uri_deref(Z_WHATWG_URL_PROP_PATH_P(zv))
#define Z_WHATWG_URL_PROP_QUERY_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6))
#define Z_WHATWG_URL_PROP_FRAGMENT_DEREF_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 7))

static HashTable *uri_get_debug_properties(php_uri_object *object)
{
const HashTable *std_properties = zend_std_get_properties(&object->std);
Expand Down Expand Up @@ -1249,6 +1261,139 @@ PHP_METHOD(Uri_Rfc3986_UriBuilder, build)
uri_object->uri = uriparser_uris;
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, reset)
Comment thread
kocsismate marked this conversation as resolved.
{
ZEND_PARSE_PARAMETERS_NONE();

zend_object *object = Z_OBJ_P(ZEND_THIS);
zval *property = object->properties_table;
const zval *end = property + object->ce->default_properties_count;

while (property != end) {
zend_object_dtor_property(object, property);
ZVAL_NULL(property);
property++;
}

ZVAL_EMPTY_STRING(Z_WHATWG_URL_PROP_SCHEME_P(ZEND_THIS));
ZVAL_EMPTY_STRING(Z_WHATWG_URL_PROP_PATH_P(ZEND_THIS));

RETVAL_COPY(ZEND_THIS);
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, setScheme)
{
php_uri_builder_set_component_string(
INTERNAL_FUNCTION_PARAM_PASSTHRU,
ZEND_STRL("scheme"),
php_uri_parser_whatwg_validate_scheme
);
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, setUsername)
{
php_uri_builder_set_component_string_or_null(
INTERNAL_FUNCTION_PARAM_PASSTHRU,
ZEND_STRL("username"),
php_uri_parser_whatwg_validate_none
);
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, setPassword)
{
php_uri_builder_set_component_string_or_null(
INTERNAL_FUNCTION_PARAM_PASSTHRU,
ZEND_STRL("password"),
php_uri_parser_whatwg_validate_none
);
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, setHost)
{
php_uri_builder_set_component_string_or_null(
INTERNAL_FUNCTION_PARAM_PASSTHRU,
ZEND_STRL("host"),
php_uri_parser_whatwg_validate_host
);
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, setPort)
{
php_uri_builder_set_component_long_or_null(
INTERNAL_FUNCTION_PARAM_PASSTHRU,
ZEND_STRL("port"),
php_uri_parser_whatwg_validate_port
);
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, setPath)
{
php_uri_builder_set_component_string(
INTERNAL_FUNCTION_PARAM_PASSTHRU,
ZEND_STRL("path"),
php_uri_parser_whatwg_validate_none
);
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, setQuery)
{
php_uri_builder_set_component_string_or_null(
INTERNAL_FUNCTION_PARAM_PASSTHRU,
ZEND_STRL("query"),
php_uri_parser_whatwg_validate_none
);
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, setFragment)
{
php_uri_builder_set_component_string_or_null(
INTERNAL_FUNCTION_PARAM_PASSTHRU,
ZEND_STRL("fragment"),
php_uri_parser_whatwg_validate_none
);
}

PHP_METHOD(Uri_WhatWg_UrlBuilder, build)
{
zval *base_url_zv = NULL;
zval *errors = NULL;

ZEND_PARSE_PARAMETERS_START(0, 2)
Z_PARAM_OPTIONAL
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(base_url_zv, php_uri_ce_whatwg_url)
Comment thread
kocsismate marked this conversation as resolved.
Z_PARAM_ZVAL(errors)
ZEND_PARSE_PARAMETERS_END();

const zval *scheme = Z_WHATWG_URL_PROP_SCHEME_DEREF_P(ZEND_THIS);
const zval *username = Z_WHATWG_URL_PROP_USERNAME_DEREF_P(ZEND_THIS);
const zval *password = Z_WHATWG_URL_PROP_PASSWORD_DEREF_P(ZEND_THIS);
const zval *host = Z_WHATWG_URL_PROP_HOST_DEREF_P(ZEND_THIS);
const zval *port = Z_WHATWG_URL_PROP_PORT_DEREF_P(ZEND_THIS);
const zval *path = Z_WHATWG_URL_PROP_PATH_DEREF_P(ZEND_THIS);
const zval *query = Z_WHATWG_URL_PROP_QUERY_DEREF_P(ZEND_THIS);
const zval *fragment = Z_WHATWG_URL_PROP_FRAGMENT_DEREF_P(ZEND_THIS);

lxb_url_t *base_url = NULL;
if (base_url_zv != NULL) {
zend_argument_error(NULL, 1, "is not supported yet, and therefore, null must be passed");
RETURN_THROWS();
base_url = Z_URI_OBJECT_P(base_url_zv)->uri;
}

lxb_url_t *lexbor_url = php_uri_parser_whatwg_build_from_zval(
base_url, scheme, username, password, host, port, path, query, fragment,
errors
);
if (lexbor_url == NULL) {
RETURN_THROWS();
}

object_init_ex(return_value, php_uri_ce_whatwg_url);
php_uri_object *uri_object = Z_URI_OBJECT_P(return_value);
uri_object->parser = &php_uri_parser_whatwg;
uri_object->uri = lexbor_url;
}

PHPAPI php_uri_object *php_uri_object_create(zend_class_entry *class_type, const php_uri_parser *parser)
{
php_uri_object *uri_object = zend_object_alloc(sizeof(*uri_object), class_type);
Expand Down Expand Up @@ -1331,6 +1476,8 @@ static PHP_MINIT_FUNCTION(uri)
php_uri_ce_rfc3986_uri_type = register_class_Uri_Rfc3986_UriType();
php_uri_ce_rfc3986_uri_host_type = register_class_Uri_Rfc3986_UriHostType();

php_uri_ce_whatwg_url_builder = register_class_Uri_WhatWg_UrlBuilder();

php_uri_ce_whatwg_url = register_class_Uri_WhatWg_Url();
php_uri_ce_whatwg_url->create_object = php_uri_object_create_whatwg;
php_uri_ce_whatwg_url->default_object_handlers = &object_handlers_whatwg_uri;
Expand Down
33 changes: 33 additions & 0 deletions ext/uri/php_uri.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,39 @@ enum UrlHostType
case Empty;
}

final class UrlBuilder
{
private string $scheme = "";
private ?string $username = null;
private ?string $password = null;
private ?string $host = null;
private ?int $port = null;
private string $path = "";
private ?string $query = null;
private ?string $fragment = null;

public function reset(): static {}

public function setScheme(string $scheme): static {}

public function setUsername(?string $username): static {}

public function setPassword(#[\SensitiveParameter] ?string $password): static {}

public function setHost(?string $host): static {}

public function setPort(?int $port): static {}

public function setPath(string $path): static {}

public function setQuery(?string $query): static {}

public function setFragment(?string $fragment): static {}

/** @param array $errors */
public function build(?\Uri\WhatWg\Url $baseUrl = null, &$errors = null): \Uri\WhatWg\Url {}
}

/** @strict-properties */
final readonly class Url
{
Expand Down
112 changes: 102 additions & 10 deletions ext/uri/php_uri_arginfo.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading