Skip to content

Commit b8a8ba7

Browse files
committed
Add UriComparisonMode
1 parent 88c8a46 commit b8a8ba7

13 files changed

+111
-169
lines changed

ext/standard/url.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ static void *parse_url_clone_uri(void *uri)
451451
return NULL;
452452
}
453453

454-
static void *parse_url_parse_uri(const zend_string *uri_str, const zend_string *base_uri_str, zval *errors)
454+
static void *parse_url_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors)
455455
{
456456
bool has_port;
457457

ext/uri/php_lexbor.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#endif
2525

2626
static zend_result lexbor_init_parser(void);
27-
static void *lexbor_parse_uri(const zend_string *url_str, const zend_string *base_url_str, zval *errors);
27+
static void *lexbor_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors);
2828
static void lexbor_create_invalid_uri_exception(zval *exception_zv, zval *errors);
2929
static void *lexbor_clone_uri(void *uri);
3030
static zend_string *lexbor_uri_to_string(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment);
@@ -521,20 +521,17 @@ static zend_result lexbor_init_parser(void)
521521
return SUCCESS;
522522
}
523523

524-
static void *lexbor_parse_uri(const zend_string *url_str, const zend_string *base_url_str, zval *errors)
524+
static void *lexbor_parse_uri(const zend_string *uri_str, const void *base_url, zval *errors)
525525
{
526526
lexbor_cleanup_parser();
527527

528-
lxb_url_t *url, *base_url = NULL;
528+
lxb_url_t *url, *lexbor_base_url = NULL;
529529

530-
if (base_url_str) {
531-
if ((base_url = lxb_url_parse(lexbor_parser, NULL, (unsigned char *) ZSTR_VAL(base_url_str), ZSTR_LEN(base_url_str))) == NULL) {
532-
fill_errors(errors);
533-
return NULL;
534-
}
530+
if (base_url) {
531+
lexbor_base_url = (lxb_url_t *) base_url;
535532
}
536533

537-
url = lxb_url_parse(lexbor_parser, base_url, (unsigned char *) ZSTR_VAL(url_str), ZSTR_LEN(url_str));
534+
url = lxb_url_parse(lexbor_parser, lexbor_base_url, (unsigned char *) ZSTR_VAL(uri_str), ZSTR_LEN(uri_str));
538535
fill_errors(errors);
539536

540537
return url;

ext/uri/php_uri.c

Lines changed: 35 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ zend_class_entry *rfc3986_uri_ce;
3434
zend_object_handlers rfc3986_uri_object_handlers;
3535
zend_class_entry *whatwg_url_ce;
3636
zend_object_handlers whatwg_uri_object_handlers;
37+
zend_class_entry *uri_comparison_mode_ce;
3738
zend_class_entry *uri_exception_ce;
3839
zend_class_entry *invalid_uri_exception_ce;
3940
zend_class_entry *whatwg_invalid_url_exception_ce;
@@ -353,13 +354,20 @@ static zend_result pass_errors_by_ref(zval *errors_zv, zval *errors)
353354
}
354355

355356
PHPAPI void php_uri_instantiate_uri(
356-
INTERNAL_FUNCTION_PARAMETERS, const uri_handler_t *handler, const zend_string *uri_str, const zend_string *base_url_str,
357+
INTERNAL_FUNCTION_PARAMETERS, const uri_handler_t *handler, const zend_string *uri_str, const zend_object *base_url_object,
357358
bool is_constructor, zval *errors_zv
358359
) {
359360
zval errors;
360361
ZVAL_UNDEF(&errors);
361362

362-
void *uri = handler->parse_uri(uri_str, base_url_str, is_constructor || errors_zv != NULL ? &errors : NULL);
363+
void *base_url = NULL;
364+
if (base_url_object != NULL) {
365+
uri_internal_t *internal_base_url = uri_internal_from_obj(base_url_object);
366+
URI_CHECK_INITIALIZATION(internal_base_url);
367+
base_url = internal_base_url->uri;
368+
}
369+
370+
void *uri = handler->parse_uri(uri_str, base_url, is_constructor || errors_zv != NULL ? &errors : NULL);
363371
if (UNEXPECTED(uri == NULL)) {
364372
if (is_constructor) {
365373
throw_invalid_uri_exception(handler, &errors);
@@ -389,25 +397,16 @@ PHPAPI void php_uri_instantiate_uri(
389397

390398
static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
391399
{
392-
zend_string *uri_str, *base_url_str = NULL;
400+
zend_string *uri_str;
401+
zend_object *base_url_object = NULL;
393402

394403
ZEND_PARSE_PARAMETERS_START(1, 2)
395404
Z_PARAM_PATH_STR(uri_str)
396405
Z_PARAM_OPTIONAL
397-
Z_PARAM_PATH_STR_OR_NULL(base_url_str)
406+
Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, rfc3986_uri_ce)
398407
ZEND_PARSE_PARAMETERS_END();
399408

400-
if (ZSTR_LEN(uri_str) == 0) {
401-
zend_argument_value_error(1, "cannot be empty");
402-
RETURN_THROWS();
403-
}
404-
405-
if (base_url_str && ZSTR_LEN(base_url_str) == 0) {
406-
zend_argument_value_error(2, "cannot be empty");
407-
RETURN_THROWS();
408-
}
409-
410-
php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &uriparser_uri_handler, uri_str, base_url_str, is_constructor, NULL);
409+
php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &uriparser_uri_handler, uri_str, base_url_object, is_constructor, NULL);
411410
}
412411

413412
PHP_METHOD(Uri_Rfc3986_Uri, parse)
@@ -422,27 +421,18 @@ PHP_METHOD(Uri_Rfc3986_Uri, __construct)
422421

423422
static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor)
424423
{
425-
zend_string *uri_str, *base_url_str = NULL;
424+
zend_string *uri_str;
425+
zend_object *base_url_object = NULL;
426426
zval *errors = NULL;
427427

428428
ZEND_PARSE_PARAMETERS_START(1, 3)
429429
Z_PARAM_PATH_STR(uri_str)
430430
Z_PARAM_OPTIONAL
431-
Z_PARAM_PATH_STR_OR_NULL(base_url_str)
431+
Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, whatwg_url_ce)
432432
Z_PARAM_ZVAL(errors)
433433
ZEND_PARSE_PARAMETERS_END();
434434

435-
if (ZSTR_LEN(uri_str) == 0) {
436-
zend_argument_value_error(1, "cannot be empty");
437-
RETURN_THROWS();
438-
}
439-
440-
if (base_url_str && ZSTR_LEN(base_url_str) == 0) {
441-
zend_argument_value_error(2, "cannot be empty");
442-
RETURN_THROWS();
443-
}
444-
445-
php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &lexbor_uri_handler, uri_str, base_url_str, is_constructor, errors);
435+
php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &lexbor_uri_handler, uri_str, base_url_object, is_constructor, errors);
446436
}
447437

448438
PHP_METHOD(Uri_WhatWg_Url, parse)
@@ -575,7 +565,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, withFragment)
575565
URI_WITHER_STR_OR_NULL(ZSTR_KNOWN(ZEND_STR_FRAGMENT));
576566
}
577567

578-
static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, bool exclude_fragment)
568+
static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, zend_object *comparison_mode)
579569
{
580570
zend_object *this_object = Z_OBJ_P(ZEND_THIS);
581571
uri_internal_t *this_internal_uri = uri_internal_from_obj(this_object);
@@ -591,6 +581,14 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, b
591581
RETURN_FALSE;
592582
}
593583

584+
bool exclude_fragment = true;
585+
if (comparison_mode) {
586+
zval *case_name = zend_enum_fetch_case_name(comparison_mode);
587+
zend_string *comparison_mode_name = Z_STR_P(case_name);
588+
589+
exclude_fragment = ZSTR_VAL(comparison_mode_name)[0] + ZSTR_LEN(comparison_mode_name) == 'E' + sizeof("ExcludeFragment") - 1;
590+
}
591+
594592
zend_string *this_str = this_internal_uri->handler->uri_to_string(
595593
this_internal_uri->uri, URI_RECOMPOSITION_NORMALIZED_ASCII, exclude_fragment);
596594
if (this_str == NULL) {
@@ -614,15 +612,15 @@ static void uri_equals(INTERNAL_FUNCTION_PARAMETERS, zend_object *that_object, b
614612
PHP_METHOD(Uri_Rfc3986_Uri, equals)
615613
{
616614
zend_object *that_object;
617-
bool exclude_fragment = true;
615+
zend_object *comparison_mode = NULL;
618616

619617
ZEND_PARSE_PARAMETERS_START(1, 2)
620618
Z_PARAM_OBJ_OF_CLASS(that_object, rfc3986_uri_ce)
621619
Z_PARAM_OPTIONAL
622-
Z_PARAM_BOOL(exclude_fragment)
620+
Z_PARAM_OBJ_OF_CLASS(comparison_mode, uri_comparison_mode_ce);
623621
ZEND_PARSE_PARAMETERS_END();
624622

625-
uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, that_object, exclude_fragment);
623+
uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, that_object, comparison_mode);
626624
}
627625

628626
PHP_METHOD(Uri_Rfc3986_Uri, toRawString)
@@ -671,14 +669,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, resolve)
671669
uri_internal_t *internal_uri = uri_internal_from_obj(this_object);
672670
URI_CHECK_INITIALIZATION(internal_uri);
673671

674-
zend_string *base_uri_str = internal_uri->handler->uri_to_string(
675-
internal_uri->uri, URI_RECOMPOSITION_RAW_ASCII, false); // TODO optimize by not reparsing the base URI
676-
if (base_uri_str == NULL) {
677-
zend_throw_exception_ex(NULL, 0, "Cannot recompose %s to string", ZSTR_VAL(this_object->ce->name));
678-
RETURN_THROWS();
679-
}
680-
681-
php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal_uri->handler, uri_str, base_uri_str, true, NULL);
672+
php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal_uri->handler, uri_str, this_object, true, NULL);
682673
}
683674

684675
PHP_METHOD(Uri_Rfc3986_Uri, __serialize)
@@ -832,15 +823,15 @@ PHP_METHOD(Uri_WhatWg_Url, withHost)
832823
PHP_METHOD(Uri_WhatWg_Url, equals)
833824
{
834825
zend_object *that_object;
835-
bool exclude_fragment = true;
826+
zend_object *comparison_mode = NULL;
836827

837828
ZEND_PARSE_PARAMETERS_START(1, 2)
838829
Z_PARAM_OBJ_OF_CLASS(that_object, whatwg_url_ce)
839830
Z_PARAM_OPTIONAL
840-
Z_PARAM_BOOL(exclude_fragment)
831+
Z_PARAM_OBJ_OF_CLASS(comparison_mode, uri_comparison_mode_ce);
841832
ZEND_PARSE_PARAMETERS_END();
842833

843-
uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, that_object, exclude_fragment);
834+
uri_equals(INTERNAL_FUNCTION_PARAM_PASSTHRU, that_object, comparison_mode);
844835
}
845836

846837
PHP_METHOD(Uri_WhatWg_Url, toUnicodeString)
@@ -955,6 +946,7 @@ static PHP_MINIT_FUNCTION(uri)
955946
whatwg_url_ce = register_class_Uri_WhatWg_Url();
956947
php_uri_implementation_set_object_handlers(whatwg_url_ce, &whatwg_uri_object_handlers);
957948

949+
uri_comparison_mode_ce = register_class_Uri_UriComparisonMode();
958950
uri_exception_ce = register_class_Uri_UriException(zend_ce_exception);
959951
invalid_uri_exception_ce = register_class_Uri_InvalidUriException(uri_exception_ce);
960952
whatwg_invalid_url_exception_ce = register_class_Uri_WhatWg_InvalidUrlException(invalid_uri_exception_ce);

ext/uri/php_uri.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ PHPAPI php_uri *php_uri_parse_to_struct(const uri_handler_t *uri_handler, zend_s
5252
PHPAPI void php_uri_struct_free(php_uri *uri);
5353

5454
PHPAPI void php_uri_instantiate_uri(
55-
INTERNAL_FUNCTION_PARAMETERS, const uri_handler_t *handler, const zend_string *uri_str, const zend_string *base_url_str,
55+
INTERNAL_FUNCTION_PARAMETERS, const uri_handler_t *handler, const zend_string *uri_str, const zend_object *base_url_object,
5656
bool is_constructor, zval *errors_zv
5757
);
5858
PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers);

ext/uri/php_uri.stub.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,21 @@ class UriException extends \Exception
1212
class InvalidUriException extends \Uri\UriException
1313
{
1414
}
15+
16+
enum UriComparisonMode
17+
{
18+
case IncludeFragment;
19+
case ExcludeFragment;
20+
}
1521
}
1622

1723
namespace Uri\Rfc3986 {
1824
/** @strict-properties */
1925
final readonly class Uri
2026
{
21-
public static function parse(string $uri, ?string $baseUrl = null): ?static {}
27+
public static function parse(string $uri, ?\Uri\Rfc3986\Uri $baseUrl = null): ?static {}
2228

23-
public function __construct(string $uri, ?string $baseUrl = null) {}
29+
public function __construct(string $uri, ?\Uri\Rfc3986\Uri $baseUrl = null) {}
2430

2531
public function getScheme(): ?string {}
2632

@@ -70,7 +76,7 @@ public function getRawFragment(): ?string {}
7076

7177
public function withFragment(?string $fragment): static {}
7278

73-
public function equals(\Uri\Rfc3986\Uri $uri, bool $excludeFragment = true): bool {}
79+
public function equals(\Uri\Rfc3986\Uri $uri, \Uri\UriComparisonMode $comparisonMode = \Uri\UriComparisonMode::ExcludeFragment): bool {}
7480

7581
public function toString(): string {}
7682

@@ -140,10 +146,10 @@ public function __construct(string $context, \Uri\WhatWg\UrlValidationErrorType
140146
final readonly class Url
141147
{
142148
/** @param array $errors */
143-
public static function parse(string $uri, ?string $baseUrl = null, &$errors = null): ?static {}
149+
public static function parse(string $uri, ?\Uri\WhatWg\Url $baseUrl = null, &$errors = null): ?static {}
144150

145151
/** @param array $softErrors */
146-
public function __construct(string $uri, ?string $baseUrl = null, &$softErrors = null) {}
152+
public function __construct(string $uri, ?\Uri\WhatWg\Url $baseUrl = null, &$softErrors = null) {}
147153

148154
public function getScheme(): string {}
149155

@@ -189,7 +195,7 @@ public function getFragment(): ?string {}
189195
/** @implementation-alias Uri\Rfc3986\Uri::withFragment */
190196
public function withFragment(?string $fragment): static {}
191197

192-
public function equals(\Uri\WhatWg\Url $url, bool $excludeFragment = true): bool {}
198+
public function equals(\Uri\WhatWg\Url $url, \Uri\UriComparisonMode $comparisonMode = \Uri\UriComparisonMode::ExcludeFragment): bool {}
193199

194200
public function toAsciiString(): string {}
195201

ext/uri/php_uri_arginfo.h

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

ext/uri/php_uri_common.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extern zend_class_entry *rfc3986_uri_ce;
2121
extern zend_object_handlers rfc3986_uri_object_handlers;
2222
extern zend_class_entry *whatwg_url_ce;
2323
extern zend_object_handlers whatwg_uri_object_handlers;
24+
extern zend_class_entry *uri_comparison_mode_ce;
2425
extern zend_class_entry *uri_exception_ce;
2526
extern zend_class_entry *invalid_uri_exception_ce;
2627
extern zend_class_entry *whatwg_invalid_url_exception_ce;
@@ -44,7 +45,7 @@ typedef struct uri_handler_t {
4445
const char *name;
4546

4647
zend_result (*init_parser)(void);
47-
void *(*parse_uri)(const zend_string *uri_str, const zend_string *base_url_str, zval *errors);
48+
void *(*parse_uri)(const zend_string *uri_str, const void *base_url, zval *errors);
4849
void (*create_invalid_uri_exception)(zval *exception_zv, zval *errors);
4950
void *(*clone_uri)(void *uri);
5051
zend_string *(*uri_to_string)(void *uri, uri_recomposition_mode_t recomposition_mode, bool exclude_fragment);
@@ -63,11 +64,11 @@ typedef struct uri_object_t {
6364
zend_object std;
6465
} uri_object_t;
6566

66-
static inline uri_object_t *uri_object_from_obj(zend_object *object) {
67+
static inline uri_object_t *uri_object_from_obj(const zend_object *object) {
6768
return (uri_object_t*)((char*)(object) - XtOffsetOf(uri_object_t, std));
6869
}
6970

70-
static inline uri_internal_t *uri_internal_from_obj(zend_object *object) {
71+
static inline uri_internal_t *uri_internal_from_obj(const zend_object *object) {
7172
return &(uri_object_from_obj(object)->internal);
7273
}
7374

0 commit comments

Comments
 (0)