Skip to content

Commit 97cb0bf

Browse files
committed
Implement "Followup improvements for ext/uri" RFC - WHATWG URL building
RFC: https://wiki.php.net/rfc/uri_followup#uri_building
1 parent 4ccd652 commit 97cb0bf

56 files changed

Lines changed: 2030 additions & 25 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ext/uri/php_uri.c

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
+----------------------------------------------------------------------+
1313
*/
1414

15+
#include "zend_smart_str.h"
1516
#ifdef HAVE_CONFIG_H
1617
# include <config.h>
1718
#endif
@@ -34,6 +35,7 @@ zend_class_entry *php_uri_ce_rfc3986_uri_builder;
3435
zend_class_entry *php_uri_ce_rfc3986_uri;
3536
zend_class_entry *php_uri_ce_rfc3986_uri_type;
3637
zend_class_entry *php_uri_ce_rfc3986_uri_host_type;
38+
zend_class_entry *php_uri_ce_whatwg_url_builder;
3739
zend_class_entry *php_uri_ce_whatwg_url;
3840
zend_class_entry *php_uri_ce_comparison_mode;
3941
zend_class_entry *php_uri_ce_exception;
@@ -74,6 +76,15 @@ static zend_always_inline zval *php_uri_deref(zval *zv)
7476
#define Z_RFC3986_URI_PROP_QUERY_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 5))
7577
#define Z_RFC3986_URI_PROP_FRAGMENT_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6))
7678

79+
#define Z_WHATWG_URL_PROP_SCHEME_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 0))
80+
#define Z_WHATWG_URL_PROP_USERNAME_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 1))
81+
#define Z_WHATWG_URL_PROP_PASSWORD_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 2))
82+
#define Z_WHATWG_URL_PROP_HOST_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 3))
83+
#define Z_WHATWG_URL_PROP_PORT_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 4))
84+
#define Z_WHATWG_URL_PROP_PATH_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 5))
85+
#define Z_WHATWG_URL_PROP_QUERY_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 6))
86+
#define Z_WHATWG_URL_PROP_FRAGMENT_P(zv) php_uri_deref(OBJ_PROP_NUM(Z_OBJ_P(zv), 7))
87+
7788
static HashTable *uri_get_debug_properties(php_uri_object *object)
7889
{
7990
const HashTable *std_properties = zend_std_get_properties(&object->std);
@@ -1245,6 +1256,138 @@ PHP_METHOD(Uri_Rfc3986_UriBuilder, build)
12451256
uri_object->uri = uriparser_uris;
12461257
}
12471258

1259+
PHP_METHOD(Uri_WhatWg_UrlBuilder, __construct)
1260+
{
1261+
ZEND_PARSE_PARAMETERS_NONE();
1262+
}
1263+
1264+
PHP_METHOD(Uri_WhatWg_UrlBuilder, reset)
1265+
{
1266+
zval_ptr_dtor(Z_WHATWG_URL_PROP_SCHEME_P(ZEND_THIS));
1267+
ZVAL_EMPTY_STRING(Z_WHATWG_URL_PROP_SCHEME_P(ZEND_THIS));
1268+
convert_to_null(Z_WHATWG_URL_PROP_USERNAME_P(ZEND_THIS));
1269+
convert_to_null(Z_WHATWG_URL_PROP_PASSWORD_P(ZEND_THIS));
1270+
convert_to_null(Z_WHATWG_URL_PROP_HOST_P(ZEND_THIS));
1271+
convert_to_null(Z_WHATWG_URL_PROP_PORT_P(ZEND_THIS));
1272+
zval_ptr_dtor(Z_WHATWG_URL_PROP_PATH_P(ZEND_THIS));
1273+
ZVAL_EMPTY_STRING(Z_WHATWG_URL_PROP_PATH_P(ZEND_THIS));
1274+
convert_to_null(Z_WHATWG_URL_PROP_QUERY_P(ZEND_THIS));
1275+
convert_to_null(Z_WHATWG_URL_PROP_FRAGMENT_P(ZEND_THIS));
1276+
1277+
RETVAL_COPY(ZEND_THIS);
1278+
}
1279+
1280+
PHP_METHOD(Uri_WhatWg_UrlBuilder, setScheme)
1281+
{
1282+
php_uri_builder_set_component_string(
1283+
INTERNAL_FUNCTION_PARAM_PASSTHRU,
1284+
ZEND_STRL("scheme"),
1285+
php_uri_parser_whatwg_validate_scheme
1286+
);
1287+
}
1288+
1289+
PHP_METHOD(Uri_WhatWg_UrlBuilder, setUsername)
1290+
{
1291+
php_uri_builder_set_component_string_or_null(
1292+
INTERNAL_FUNCTION_PARAM_PASSTHRU,
1293+
ZEND_STRL("username"),
1294+
php_uri_parser_whatwg_validate_none
1295+
);
1296+
}
1297+
1298+
PHP_METHOD(Uri_WhatWg_UrlBuilder, setPassword)
1299+
{
1300+
php_uri_builder_set_component_string_or_null(
1301+
INTERNAL_FUNCTION_PARAM_PASSTHRU,
1302+
ZEND_STRL("password"),
1303+
php_uri_parser_whatwg_validate_none
1304+
);
1305+
}
1306+
1307+
PHP_METHOD(Uri_WhatWg_UrlBuilder, setHost)
1308+
{
1309+
php_uri_builder_set_component_string_or_null(
1310+
INTERNAL_FUNCTION_PARAM_PASSTHRU,
1311+
ZEND_STRL("host"),
1312+
php_uri_parser_whatwg_validate_none
1313+
);
1314+
}
1315+
1316+
PHP_METHOD(Uri_WhatWg_UrlBuilder, setPort)
1317+
{
1318+
php_uri_builder_set_component_long_or_null(
1319+
INTERNAL_FUNCTION_PARAM_PASSTHRU,
1320+
ZEND_STRL("port"),
1321+
php_uri_parser_whatwg_validate_port
1322+
);
1323+
}
1324+
1325+
PHP_METHOD(Uri_WhatWg_UrlBuilder, setPath)
1326+
{
1327+
php_uri_builder_set_component_string(
1328+
INTERNAL_FUNCTION_PARAM_PASSTHRU,
1329+
ZEND_STRL("path"),
1330+
php_uri_parser_whatwg_validate_none
1331+
);
1332+
}
1333+
1334+
PHP_METHOD(Uri_WhatWg_UrlBuilder, setQuery)
1335+
{
1336+
php_uri_builder_set_component_string_or_null(
1337+
INTERNAL_FUNCTION_PARAM_PASSTHRU,
1338+
ZEND_STRL("query"),
1339+
php_uri_parser_whatwg_validate_none
1340+
);
1341+
}
1342+
1343+
PHP_METHOD(Uri_WhatWg_UrlBuilder, setFragment)
1344+
{
1345+
php_uri_builder_set_component_string_or_null(
1346+
INTERNAL_FUNCTION_PARAM_PASSTHRU,
1347+
ZEND_STRL("fragment"),
1348+
php_uri_parser_whatwg_validate_none
1349+
);
1350+
}
1351+
1352+
PHP_METHOD(Uri_WhatWg_UrlBuilder, build)
1353+
{
1354+
zval *base_url_zv = NULL;
1355+
zval *errors = NULL;
1356+
1357+
ZEND_PARSE_PARAMETERS_START(0, 2)
1358+
Z_PARAM_OPTIONAL
1359+
Z_PARAM_OBJECT_OF_CLASS_OR_NULL(base_url_zv, php_uri_ce_whatwg_url)
1360+
Z_PARAM_ZVAL(errors)
1361+
ZEND_PARSE_PARAMETERS_END();
1362+
1363+
const zval *scheme = Z_WHATWG_URL_PROP_SCHEME_P(ZEND_THIS);
1364+
const zval *username = Z_WHATWG_URL_PROP_USERNAME_P(ZEND_THIS);
1365+
const zval *password = Z_WHATWG_URL_PROP_PASSWORD_P(ZEND_THIS);
1366+
const zval *host = Z_WHATWG_URL_PROP_HOST_P(ZEND_THIS);
1367+
const zval *port = Z_WHATWG_URL_PROP_PORT_P(ZEND_THIS);
1368+
const zval *path = Z_WHATWG_URL_PROP_PATH_P(ZEND_THIS);
1369+
const zval *query = Z_WHATWG_URL_PROP_QUERY_P(ZEND_THIS);
1370+
const zval *fragment = Z_WHATWG_URL_PROP_FRAGMENT_P(ZEND_THIS);
1371+
1372+
lxb_url_t *base_url = NULL;
1373+
if (base_url_zv != NULL) {
1374+
base_url = Z_URI_OBJECT_P(base_url_zv)->uri;
1375+
}
1376+
1377+
lxb_url_t *lexbor_url = php_uri_parser_whatwg_build_from_zval(
1378+
base_url, scheme, username, password, host, port, path, query, fragment,
1379+
errors
1380+
);
1381+
if (lexbor_url == NULL) {
1382+
RETURN_THROWS();
1383+
}
1384+
1385+
object_init_ex(return_value, php_uri_ce_whatwg_url);
1386+
php_uri_object *uri_object = Z_URI_OBJECT_P(return_value);
1387+
uri_object->parser = &php_uri_parser_whatwg;
1388+
uri_object->uri = lexbor_url;
1389+
}
1390+
12481391
PHPAPI php_uri_object *php_uri_object_create(zend_class_entry *class_type, const php_uri_parser *parser)
12491392
{
12501393
php_uri_object *uri_object = zend_object_alloc(sizeof(*uri_object), class_type);
@@ -1327,6 +1470,8 @@ static PHP_MINIT_FUNCTION(uri)
13271470
php_uri_ce_rfc3986_uri_type = register_class_Uri_Rfc3986_UriType();
13281471
php_uri_ce_rfc3986_uri_host_type = register_class_Uri_Rfc3986_UriHostType();
13291472

1473+
php_uri_ce_whatwg_url_builder = register_class_Uri_WhatWg_UrlBuilder();
1474+
13301475
php_uri_ce_whatwg_url = register_class_Uri_WhatWg_Url();
13311476
php_uri_ce_whatwg_url->create_object = php_uri_object_create_whatwg;
13321477
php_uri_ce_whatwg_url->default_object_handlers = &object_handlers_whatwg_uri;

ext/uri/php_uri.stub.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,41 @@ enum UrlHostType
210210
case Empty;
211211
}
212212

213+
final class UrlBuilder
214+
{
215+
private string $scheme = "";
216+
private ?string $username = null;
217+
private ?string $password = null;
218+
private ?string $host = null;
219+
private ?int $port = null;
220+
private string $path = "";
221+
private ?string $query = null;
222+
private ?string $fragment = null;
223+
224+
public function __construct() {}
225+
226+
public function reset(): static {}
227+
228+
public function setScheme(string $scheme): static {}
229+
230+
public function setUsername(?string $username): static {}
231+
232+
public function setPassword(#[\SensitiveParameter] ?string $password): static {}
233+
234+
public function setHost(?string $host): static {}
235+
236+
public function setPort(?int $port): static {}
237+
238+
public function setPath(string $path): static {}
239+
240+
public function setQuery(?string $query): static {}
241+
242+
public function setFragment(?string $fragment): static {}
243+
244+
/** @param array $errors */
245+
public function build(?\Uri\WhatWg\Url $baseUrl = null, &$errors = null): \Uri\WhatWg\Url {}
246+
}
247+
213248
/** @strict-properties */
214249
final readonly class Url
215250
{

ext/uri/php_uri_arginfo.h

Lines changed: 107 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)