user->create(
array(
'role' => 'administrator',
)
);
self::$subscriber_id = $factory->user->create(
array(
'role' => 'subscriber',
)
);
}
public static function wpTearDownAfterClass() {
self::delete_user( self::$admin_id );
self::delete_user( self::$subscriber_id );
}
public function set_up() {
parent::set_up();
add_filter( 'pre_http_request', array( $this, 'mock_success_request_to_remote_url' ), 10, 3 );
// Disables usage of cache during major of tests.
add_filter( 'pre_site_transient_' . $this->get_transient_name(), '__return_null' );
}
public function tear_down() {
$this->request_args = array();
parent::tear_down();
}
/**
* @covers WP_REST_URL_Details_Controller::register_routes
*
* @ticket 54358
*/
public function test_register_routes() {
$routes = rest_get_server()->get_routes();
$this->assertArrayHasKey( static::REQUEST_ROUTE, $routes );
}
/**
* @covers WP_REST_URL_Details_Controller::parse_url_details
*
* @ticket 54358
*/
public function test_get_items() {
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => static::URL_PLACEHOLDER,
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
/*
* Note the data in the subset comes from the fixture HTML returned by
* the filter `pre_http_request` (see this class's `set_up` method).
*/
$this->assertSame(
array(
'title' => 'Example Website — - with encoded content.',
'icon' => 'https://placeholder-site.com/favicon.ico?querystringaddedfortesting',
'description' => 'Example description text here. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore.',
'image' => 'https://placeholder-site.com/images/home/screen-themes.png?3',
),
$data
);
}
/**
* @covers WP_REST_URL_Details_Controller::permissions_check
*
* @ticket 54358
*/
public function test_get_items_fails_for_unauthenticated_user() {
wp_set_current_user( 0 );
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => static::URL_PLACEHOLDER,
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertSame( WP_Http::UNAUTHORIZED, $response->get_status(), 'Response status is not ' . WP_Http::UNAUTHORIZED );
$this->assertSame( 'rest_cannot_view_url_details', $data['code'], 'Response "code" is not "rest_cannot_view_url_details"' );
$expected = 'you are not allowed to process remote urls';
$this->assertStringContainsString( $expected, strtolower( $data['message'] ), 'Response "message" does not contain "' . $expected . '"' );
}
/**
* @covers WP_REST_URL_Details_Controller::permissions_check
*
* @ticket 54358
*/
public function test_get_items_fails_for_user_with_insufficient_permissions() {
wp_set_current_user( self::$subscriber_id );
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => static::URL_PLACEHOLDER,
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertSame( WP_Http::FORBIDDEN, $response->get_status(), 'Response status is not ' . WP_Http::FORBIDDEN );
$this->assertSame( 'rest_cannot_view_url_details', $data['code'], 'Response "code" is not "rest_cannot_view_url_details"' );
$expected = 'you are not allowed to process remote urls';
$this->assertStringContainsString( $expected, strtolower( $data['message'] ), 'Response "message" does not contain "' . $expected . '"' );
}
/**
* @dataProvider data_get_items_fails_for_invalid_url
*
* @covers WP_REST_URL_Details_Controller::parse_url_details
*
* @ticket 54358
*
* @param mixed $invalid_url Given invalid URL to test.
*/
public function test_get_items_fails_for_invalid_url( $invalid_url ) {
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => $invalid_url,
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertSame( WP_Http::BAD_REQUEST, $response->get_status(), 'Response status is not ' . WP_Http::BAD_REQUEST );
$this->assertSame( 'rest_invalid_param', $data['code'], 'Response "code" is not "rest_invalid_param"' );
$expected = 'invalid parameter(s): url';
$this->assertStringContainsString( $expected, strtolower( $data['message'] ), 'Response "message" does not contain "' . $expected . '"' );
}
/**
* Data provider.
*
* @return array
*/
public function data_get_items_fails_for_invalid_url() {
return array(
'empty string' => array( '' ),
'numeric' => array( 1234456 ),
'invalid scheme' => array( 'invalid.proto://wordpress.org' ),
);
}
/**
* @covers WP_REST_URL_Details_Controller::parse_url_details
*
* @ticket 54358
*/
public function test_get_items_fails_for_url_which_returns_a_non_200_status_code() {
// Force HTTP request to remote site to fail.
remove_filter( 'pre_http_request', array( $this, 'mock_success_request_to_remote_url' ), 10 );
add_filter( 'pre_http_request', array( $this, 'mock_failed_request_to_remote_url' ), 10, 3 );
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => static::URL_PLACEHOLDER, // note: `pre_http_request` causes request to 404.
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertSame( 404, $response->get_status(), 'Response status is not 404' );
$this->assertSame( 'no_response', $data['code'], 'Response "code" is not "no_response"' );
$this->assertStringContainsString( 'not found', strtolower( $data['message'] ), 'Response "message" does not contain "not found"' );
}
/**
* @covers WP_REST_URL_Details_Controller::parse_url_details
*
* @ticket 54358
*/
public function test_get_items_fails_for_url_which_returns_empty_body_for_success() {
// Force HTTP request to remote site to return an empty body in response.
remove_filter( 'pre_http_request', array( $this, 'mock_success_request_to_remote_url' ) );
add_filter( 'pre_http_request', array( $this, 'mock_request_to_remote_url_with_empty_body_response' ), 10, 3 );
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => static::URL_PLACEHOLDER, // note: `pre_http_request` causes request to 404.
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertSame( 404, $response->get_status(), 'Response status is not 404' );
$this->assertSame( 'no_content', $data['code'], 'Response "code" is not "no_content"' );
$expected = strtolower( 'Unable to retrieve body from response at this URL' );
$this->assertStringContainsString( $expected, strtolower( $data['message'] ), 'Response "message" does not contain "' . $expected . '"' );
}
/**
* @covers WP_REST_URL_Details_Controller::parse_url_details
*
* @ticket 54358
*/
public function test_can_filter_http_request_args_via_filter() {
wp_set_current_user( self::$admin_id );
add_filter(
'rest_url_details_http_request_args',
static function( $args, $url ) {
return array_merge(
$args,
array(
'timeout' => 27, // modify default timeout.
'body' => $url, // add new and allow to assert on $url arg passed.
)
);
},
10,
2
);
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => static::URL_PLACEHOLDER,
)
);
rest_get_server()->dispatch( $request );
// Check the args were filtered as expected.
$this->assertArrayHasKey( 'timeout', $this->request_args, 'Request args do not contain a "timeout" key' );
$this->assertArrayHasKey( 'limit_response_size', $this->request_args, 'Request args do not contain a "limit_response_size" key' );
$this->assertArrayHasKey( 'body', $this->request_args, 'Request args do not contain a "body" key' );
$this->assertSame( 27, $this->request_args['timeout'], 'Request args "timeout" is not 27' );
$this->assertSame( 153600, $this->request_args['limit_response_size'], 'Request args "limit_response_size" is not 153600' );
$this->assertSame( static::URL_PLACEHOLDER, $this->request_args['body'], 'Request args "body" is not "' . static::URL_PLACEHOLDER . '"' );
}
/**
* @covers WP_REST_URL_Details_Controller::parse_url_details
*
* @ticket 54358
*/
public function test_will_return_from_cache_if_populated() {
$transient_name = $this->get_transient_name();
remove_filter( "pre_site_transient_{$transient_name}", '__return_null' );
// Force cache to return a known value as the remote URL http response body.
add_filter(
"pre_site_transient_{$transient_name}",
static function() {
return '
This value from cache.';
}
);
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => static::URL_PLACEHOLDER,
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
// Data should be that from cache not from mocked network response.
$this->assertStringContainsString( 'This value from cache', $data['title'] );
}
/**
* @covers WP_REST_URL_Details_Controller::parse_url_details
*
* @ticket 54358
*/
public function test_allows_filtering_data_retrieved_for_a_given_url() {
add_filter(
'rest_prepare_url_details',
static function( $response ) {
$data = $response->get_data();
$response->set_data(
array_merge(
$data,
array(
'og_title' => 'This was manually added to the data via filter',
)
)
);
return $response;
}
);
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => static::URL_PLACEHOLDER,
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
/*
* Instead of the default data retrieved we expect to see the modified
* data we provided via the filter.
*/
$expected = 'Example Website — - with encoded content.';
$this->assertSame( $expected, $data['title'], 'Response "title" is not "' . $expected . '"' );
$expected = 'This was manually added to the data via filter';
$this->assertSame( $expected, $data['og_title'], 'Response "og_title" is not "' . $expected . '"' );
}
/**
* @covers WP_REST_URL_Details_Controller::parse_url_details
*
* @ticket 54358
*/
public function test_allows_filtering_response() {
/*
* Filter the response to known set of values changing only
* based on whether the response came from the cache or not.
*/
add_filter(
'rest_prepare_url_details',
static function( $response, $url ) {
return new WP_REST_Response(
array(
'status' => 418,
'response' => "Response for URL $url altered via rest_prepare_url_details filter",
'body_response' => array(),
)
);
},
10,
3
);
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', static::REQUEST_ROUTE );
$request->set_query_params(
array(
'url' => static::URL_PLACEHOLDER,
)
);
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertSame( 418, $data['status'], 'Response "status" is not 418' );
$expected = 'Response for URL https://placeholder-site.com altered via rest_prepare_url_details filter';
$this->assertSame( $expected, $data['response'], 'Response "response" is not "' . $expected . '"' );
}
/**
* @covers WP_REST_URL_Details_Controller::get_item_schema
*
* @ticket 54358
*/
public function test_get_item_schema() {
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'OPTIONS', static::REQUEST_ROUTE );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$endpoint = $data['endpoints'][0];
$this->assertArrayHasKey( 'url', $endpoint['args'], 'Endpoint "args" does not contain a "url" key' );
$this->assertSame(
array(
'description' => 'The URL to process.',
'type' => 'string',
'format' => 'uri',
'required' => true,
),
$endpoint['args']['url'],
'Response endpoint "[args][url]" does not contain expected schema'
);
}
/**
* @dataProvider data_get_title
*
* @covers WP_REST_URL_Details_Controller::get_title
*
* @ticket 54358
*
* @param string $html Given HTML string.
* @param string $expected Expected found title.
*/
public function test_get_title( $html, $expected ) {
$controller = new WP_REST_URL_Details_Controller();
$method = $this->get_reflective_method( 'get_title' );
$actual = $method->invoke(
$controller,
$this->wrap_html_in_doc( $html )
);
$this->assertSame( $expected, $actual );
}
/**
* Data provider.
*
* @return array
*/
public function data_get_title() {
return array(
// Happy path for default.
'default' => array(
'Testing <title>',
'Testing',
),
'with attributes' => array(
'Testing <title>',
'Testing',
),
'with text whitespace' => array(
' Testing <title> ',
'Testing',
),
'with whitespace in opening tag' => array(
'Testing <title>: with whitespace in opening tag',
'Testing : with whitespace in opening tag',
),
'when whitepace in closing tag' => array(
'Testing <title>: with whitespace in closing tag title>',
'Testing : with whitespace in closing tag',
),
'with other elements' => array(
'
Testing <title>
',
'Testing',
),
'multiline' => array(
'
Testing <title>
',
'Testing',
),
// Unhappy paths.
'when opening tag is malformed' => array(
'< title>Testing <title>: when opening tag is invalid',
'',
),
);
}
/**
* @dataProvider data_get_icon
*
* @covers WP_REST_URL_Details_Controller::get_icon
*
* @ticket 54358
*
* @param string $html Given HTML string.
* @param string $expected Expected found icon.
* @param string $target_url Optional. Target URL. Default 'https://wordpress.org'.
*/
public function test_get_icon( $html, $expected, $target_url = 'https://wordpress.org' ) {
$controller = new WP_REST_URL_Details_Controller();
$method = $this->get_reflective_method( 'get_icon' );
$actual = $method->invoke(
$controller,
$this->wrap_html_in_doc( $html ),
$target_url
);
$this->assertSame( $expected, $actual );
}
/**
* Data provider.
*
* @return array
*/
public function data_get_icon() {
return array(
// Happy path for default.
'default' => array(
'',
'https://wordpress.org/favicon.ico',
),
'default with no closing whitespace' => array(
'',
'https://wordpress.org/favicon.ico',
),
'default without self-closing' => array(
'',
'https://wordpress.org/favicon.ico',
),
'default with href first' => array(
'',
'https://wordpress.org/favicon.ico',
),
'default with type last' => array(
'',
'https://wordpress.org/favicon.png',
),
'default with type first' => array(
'',
'https://wordpress.org/favicon.png',
),
'default with single quotes' => array(
'',
'https://wordpress.org/favicon.png',
),
// Happy paths.
'with query string' => array(
'',
'https://wordpress.org/favicon.ico?somequerystring=foo&another=bar',
),
'with another link' => array(
'',
'https://wordpress.org/favicon.ico',
),
'with multiple links' => array(
'
',
'https://wordpress.org/favicon.ico',
),
'relative url' => array(
'',
'https://wordpress.org/favicon.ico',
),
'relative url no slash' => array(
'',
'https://wordpress.org/favicon.ico',
),
'relative url with path' => array(
'',
'https://wordpress.org/favicon.ico',
'https://wordpress.org/my/path/here/',
),
'rel reverse order' => array(
'',
'https://wordpress.org/favicon.ico',
),
'rel icon only' => array(
'',
'https://wordpress.org/favicon.ico',
),
'rel icon only with whitespace' => array(
'',
'https://wordpress.org/favicon.ico',
),
'multiline attributes' => array(
'',
'https://wordpress.org/favicon.ico',
),
'multiline attributes in reverse order' => array(
'',
'https://wordpress.org/favicon.ico',
),
'multiline attributes with type' => array(
'',
'https://wordpress.org/favicon.ico',
),
'multiline with type first' => array(
'',
'https://wordpress.org/favicon.ico',
),
'with data URL x-icon type' => array(
'',
'data:image/x-icon;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQEAYAAABPYyMiAAAABmJLR0T///////8JWPfcAAAACXBIWXMAAABIAAAASABGyWs+AAAAF0lEQVRIx2NgGAWjYBSMglEwCkbBSAcACBAAAeaR9cIAAAAASUVORK5CYII=',
),
'with data URL png type' => array(
'',
'data:image/png;base64,iVBORw0KGgo=',
),
// Unhappy paths.
'empty rel' => array(
'',
'',
),
'empty href' => array(
'',
'',
),
'no rel' => array(
'',
'',
),
'link to external stylesheet' => array(
'',
'',
'https://example.com',
),
'multiline with no href' => array(
'',
'',
),
'multiline with no rel' => array(
'',
'',
),
);
}
/**
* @dataProvider data_get_description
*
* @covers WP_REST_URL_Details_Controller::get_description
*
* @ticket 54358
*
* @param string $html Given HTML string.
* @param string $expected Expected found icon.
*/
public function test_get_description( $html, $expected ) {
$controller = new WP_REST_URL_Details_Controller();
// Parse the meta elements from the given HTML.
$method = $this->get_reflective_method( 'get_meta_with_content_elements' );
$meta_elements = $method->invoke(
$controller,
$this->wrap_html_in_doc( $html )
);
$method = $this->get_reflective_method( 'get_description' );
$actual = $method->invoke( $controller, $meta_elements );
$this->assertSame( $expected, $actual );
}
/**
* Data provider.
*
* @return array
*/
public function data_get_description() {
return array(
// Happy paths.
'default' => array(
'',
'This is a description.',
),
'with whitespace' => array(
'',
'This is a description.',
),
'with self-closing' => array(
'',
'This is a description.',
),
'with self-closing and whitespace' => array(
'',
'This is a description.',
),
'with content first' => array(
'',
'Content is first',
),
'with single quotes' => array(
'',
'with single quotes',
),
'with another element' => array(
'',
'This is a description.',
),
'with multiple elements' => array(
'
',
'This is a description.',
),
'with other attributes' => array(
'',
'description with other attributes',
),
'with open graph' => array(
'
',
'This is a OG description.',
),
// Happy paths with multiline attributes.
'with multiline attributes' => array(
'',
'with multiline attributes',
),
'with multiline attributes in reverse order' => array(
'',
'with multiline attributes in reverse order',
),
'with multiline attributes and another element' => array(
'
',
'with multiline attributes',
),
'with multiline and other attributes' => array(
'',
'description with multiline and other attributes',
),
// Happy paths with HTML tags or entities in the description.
'with HTML tags' => array(
'',
'Description: has HTML tags',
),
'with content first and HTML tags' => array(
'',
'Description: has HTML tags',
),
'with HTML tags and other attributes' => array(
' array(
'',
'',
),
'with empty name' => array(
'',
'',
),
'without a name attribute' => array(
'',
'',
),
'without a content attribute' => array(
'',
'',
),
);
}
/**
* @dataProvider data_get_image
*
* @covers WP_REST_URL_Details_Controller::get_image
*
* @ticket 54358
*
* @param string $html Given HTML string.
* @param string $expected Expected found image.
* @param string $target_url Optional. Target URL. Default 'https://wordpress.org'.
*/
public function test_get_image( $html, $expected, $target_url = 'https://wordpress.org' ) {
$controller = new WP_REST_URL_Details_Controller();
// Parse the meta elements from the given HTML.
$method = $this->get_reflective_method( 'get_meta_with_content_elements' );
$meta_elements = $method->invoke(
$controller,
$this->wrap_html_in_doc( $html )
);
$method = $this->get_reflective_method( 'get_image' );
$actual = $method->invoke( $controller, $meta_elements, $target_url );
$this->assertSame( $expected, $actual );
}
/**
* Data provider.
*
* @return array
*/
public function data_get_image() {
return array(
// Happy paths.
'default' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with whitespace' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with self-closing' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with self-closing and whitespace' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with single quotes' => array(
"",
'https://wordpress.org/images/myimage.jpg',
),
'without quotes' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with url modifier' => array(
'
',
'https://wordpress.org/images/url-modifier.jpg',
),
'with query string' => array(
'',
'https://wordpress.org/images/withquerystring.jpg?foo=bar&bar=foo',
),
// Happy paths with changing attributes order or adding attributes.
'with content first' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with other attributes' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with other og meta' => array(
'
',
'https://wordpress.org/images/myimage.jpg',
),
// Happy paths with relative url.
'with relative url' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with relative url without starting slash' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with relative url and path' => array(
'',
'https://wordpress.org/images/myimage.jpg',
'https://wordpress.org/my/path/here/',
),
// Happy paths with multiline attributes.
'with multiline attributes' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with multiline attributes in reverse order' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
'with multiline attributes and other elements' => array(
'
',
'https://wordpress.org/images/myimage.jpg',
),
'with multiline and other attributes' => array(
'',
'https://wordpress.org/images/myimage.jpg',
),
// Happy paths with HTML tags in the content.
'with other og meta' => array(
'
',
'https://wordpress.org/images/myimage.jpg',
),
// Unhappy paths.
'with empty content' => array(
'',
'',
),
'without a property attribute' => array(
'',
'',
),
'without a content attribute empty property' => array(
'',
'',
),
);
}
/**
* @doesNotPerformAssertions
*/
public function test_context_param() {
// Controller does not use get_context_param().
}
/**
* @doesNotPerformAssertions
*/
public function test_get_item() {
// Controller does not implement get_item().
}
/**
* @doesNotPerformAssertions
*/
public function test_create_item() {
// Controller does not implement create_item().
}
/**
* @doesNotPerformAssertions
*/
public function test_update_item() {
// Controller does not implement update_item().
}
/**
* @doesNotPerformAssertions
*/
public function test_delete_item() {
// Controller does not implement delete_item().
}
/**
* @doesNotPerformAssertions
*/
public function test_prepare_item() {
// Controller does not implement prepare_item().
}
/**
* Mocks the HTTP response for the `wp_safe_remote_get()` which
* would otherwise make a call to a real website.
*
* @return array faux/mocked response.
*/
public function mock_success_request_to_remote_url( $response, $args ) {
return $this->mock_request_to_remote_url( 'success', $args );
}
public function mock_failed_request_to_remote_url( $response, $args ) {
return $this->mock_request_to_remote_url( 'failure', $args );
}
public function mock_request_to_remote_url_with_empty_body_response( $response, $args ) {
return $this->mock_request_to_remote_url( 'empty_body', $args );
}
private function mock_request_to_remote_url( $result_type, $args ) {
$this->request_args = $args;
$types = array(
'success',
'failure',
'empty_body',
);
// Default to success.
if ( ! in_array( $result_type, $types, true ) ) {
$result_type = $types[0];
}
// Both should return 200 for the HTTP response.
$should_200 = 'success' === $result_type || 'empty_body' === $result_type;
return array(
'headers' => array(),
'cookies' => array(),
'filename' => null,
'response' => array( 'code' => ( $should_200 ? 200 : 404 ) ),
'status_code' => $should_200 ? 200 : 404,
'success' => $should_200 ? 1 : 0,
'body' => 'success' === $result_type ? $this->get_example_website() : '',
);
}
private function get_example_website() {
return '
Example Website — - with encoded content.
Example Website
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
';
}
return $doc;
}
/**
* Gets the transient name.
*
* @return string
*/
private function get_transient_name() {
return 'g_url_details_response_' . md5( static::URL_PLACEHOLDER );
}
/**
* Get reflective access to a private/protected method on
* the WP_REST_URL_Details_Controller class.
*
* @param string $method_name Method name for which to gain access.
* @return ReflectionMethod
* @throws ReflectionException Throws an exception if method does not exist.
*/
protected function get_reflective_method( $method_name ) {
$class = new ReflectionClass( WP_REST_URL_Details_Controller::class );
$method = $class->getMethod( $method_name );
$method->setAccessible( true );
return $method;
}
}