Skip to content

Commit

Permalink
Code Modernization: Remove xml_set_object() in IXR_Message::parse().
Browse files Browse the repository at this point in the history
The XML Parser extension still supports a quite dated mechanism for method based callbacks, where the object is first set via `xml_set_object()` and the callbacks are then set by passing only the name of the method to the relevant parameters on any of the `xml_set_*_handler()` functions.

{{{
xml_set_object( $parser, $my_obj );
xml_set_character_data_handler( $parser, 'method_name_on_my_obj' );
}}}

Passing proper callables to the `xml_set_*_handler()` functions has been supported for the longest time and is cross-version compatible. So the above code is 100% equivalent to:

{{{
xml_set_character_data_handler( $parser, [$my_obj, 'method_name_on_my_obj'] );
}}}

The mechanism of setting the callbacks with `xml_set_object()` has now been deprecated as of PHP 8.4, in favour of passing proper callables to the `xml_set_*_handler()` functions. This is also means that calling the `xml_set_object()` function is deprecated as well.

This commit fixes this deprecation for the `IXR_Message::parse()` method.

This change is safeguarded via the new`Tests_XMLRPC_Message::test_parse_sets_handlers()` test method.

Note: Though this is "officially" an external library, this package is no longer externally maintained. The code style of the fix in the source file is in line with the existing code style for the file.

Refs:
* https://wiki.php.net/rfc/deprecations_php_8_4#xml_set_object_and_xml_set_handler_with_string_method_names
* https://www.php.net/manual/en/function.xml-set-object.php
* https://www.php.net/manual/en/ref.xml.php

Follow-up to [15612], [1346].

Props jrf, hellofromTonya.
See #62061.

git-svn-id: https://develop.svn.wordpress.org/trunk@59056 602fd350-edb4-49c9-b593-d223f7449a82
  • Loading branch information
hellofromtonya committed Sep 18, 2024
1 parent 224e2c1 commit baff405
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
5 changes: 2 additions & 3 deletions src/wp-includes/IXR/class-IXR-message.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,8 @@ function parse()
// Set XML parser to take the case of tags in to account
xml_parser_set_option($this->_parser, XML_OPTION_CASE_FOLDING, false);
// Set XML parser callback functions
xml_set_object($this->_parser, $this);
xml_set_element_handler($this->_parser, 'tag_open', 'tag_close');
xml_set_character_data_handler($this->_parser, 'cdata');
xml_set_element_handler($this->_parser, array($this, 'tag_open'), array($this, 'tag_close'));
xml_set_character_data_handler($this->_parser, array($this, 'cdata'));

// 256Kb, parse in chunks to avoid the RAM usage on very large messages
$chunk_size = 262144;
Expand Down
33 changes: 33 additions & 0 deletions tests/phpunit/tests/xmlrpc/message.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,37 @@ public function test_tag_open_does_not_create_dynamic_property() {
$this->assertSame( 'methodResponse', $message->messageType ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$this->assertSame( array( '1' ), $message->params );
}

/**
* Test that the `IXR_Message::parse()` method correctly sets callback functions to handle certain parts of the XML.
*
* Safeguards handling of the PHP 8.4 deprecation of `xml_set_object()`.
*
* @covers IXR_Message::parse
*/
public function test_parse_sets_handlers() {
$xml = '<methodResponse><params><param><value>1</value></param></params></methodResponse>';
$message = new class( $xml ) extends IXR_Message {
public $tag_open_call_counter = 0;
public $tag_close_call_counter = 0;
public $cdata_call_counter = 0;

public function tag_open( $parser, $tag, $attr ) {
++$this->tag_open_call_counter;
}
public function cdata( $parser, $cdata ) {
++$this->cdata_call_counter;
}
public function tag_close( $parser, $tag ) {
++$this->tag_close_call_counter;
}
};

$this->assertTrue( $message->parse(), 'XML parsing failed' );

$msg = '%s() handler did not get called expected nr of times';
$this->assertSame( 4, $message->tag_open_call_counter, sprintf( $msg, 'tag_open' ) );
$this->assertSame( 4, $message->tag_close_call_counter, sprintf( $msg, 'tag_close' ) );
$this->assertSame( 1, $message->cdata_call_counter, sprintf( $msg, 'cdata' ) );
}
}

0 comments on commit baff405

Please sign in to comment.