123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842 |
- <?php
- /**
- * Testing Ajax handler for exporting personal data.
- *
- * @package WordPress\UnitTests
- * @since 5.2.0
- */
- /**
- * Tests_Ajax_PrivacyExportPersonalData class.
- *
- * @since 5.2.0
- *
- * @group ajax
- * @group privacy
- *
- * @covers ::wp_ajax_wp_privacy_export_personal_data
- */
- class Tests_Ajax_PrivacyExportPersonalData extends WP_Ajax_UnitTestCase {
- /**
- * User Request ID.
- *
- * @since 5.2.0
- *
- * @var int $request_id
- */
- protected static $request_id;
- /**
- * User Request Email.
- *
- * @since 5.2.0
- *
- * @var string $request_email
- */
- protected static $request_email;
- /**
- * Ajax Action.
- *
- * @since 5.2.0
- *
- * @var string $action
- */
- protected static $action;
- /**
- * Exporter Index.
- *
- * @since 5.2.0
- *
- * @var int $exporter
- */
- protected static $exporter;
- /**
- * Exporter Key.
- *
- * @since 5.2.0
- *
- * @var string $exporter_key
- */
- protected static $exporter_key;
- /**
- * Exporter Friendly Name.
- *
- * @since 5.2.0
- *
- * @var string $exporter_friendly_name
- */
- protected static $exporter_friendly_name;
- /**
- * Page Index.
- *
- * @since 5.2.0
- *
- * @var int $page
- */
- protected static $page;
- /**
- * Send As Email.
- *
- * @since 5.2.0
- *
- * @var bool $send_as_email
- */
- protected static $send_as_email;
- /**
- * Last response parsed.
- *
- * @since 5.2.0
- *
- * @var array $_last_response_parsed
- */
- protected $_last_response_parsed;
- /**
- * An array key in the test exporter to unset.
- *
- * @since 5.2.0
- *
- * @var string $key_to_unset
- */
- protected $key_to_unset;
- /**
- * A value to change the test exporter callback to.
- *
- * @since 5.2.0
- *
- * @var string $new_callback_value
- */
- protected $new_callback_value;
- /**
- * Create user export request fixtures.
- *
- * @since 5.2.0
- *
- * @param WP_UnitTest_Factory $factory Factory.
- */
- public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
- self::$request_email = 'requester@example.com';
- self::$request_id = wp_create_user_request( self::$request_email, 'export_personal_data' );
- self::$action = 'wp-privacy-export-personal-data';
- self::$exporter = 1;
- self::$exporter_key = 'custom-exporter';
- self::$exporter_friendly_name = 'Custom Exporter';
- self::$page = 1;
- self::$send_as_email = false;
- }
- /**
- * Setup before each test method.
- *
- * @since 5.2.0
- */
- public function setUp() {
- parent::setUp();
- $this->key_to_unset = '';
- $this->new_callback_value = '';
- // Make sure the exporter response is not modified and avoid e.g. writing export file to disk.
- remove_all_filters( 'wp_privacy_personal_data_export_page' );
- // Only use our custom privacy personal data exporter.
- remove_all_filters( 'wp_privacy_personal_data_exporters' );
- add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_register_custom_personal_data_exporter' ) );
- $this->_setRole( 'administrator' );
- // `export_others_personal_data` meta cap in Multisite installation is only granted to those with `manage_network` capability.
- if ( is_multisite() ) {
- grant_super_admin( get_current_user_id() );
- }
- }
- /**
- * Clean up after each test method.
- */
- public function tearDown() {
- remove_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_register_custom_personal_data_exporter' ) );
- if ( is_multisite() ) {
- revoke_super_admin( get_current_user_id() );
- }
- parent::tearDown();
- }
- /**
- * Helper method for changing the test exporter's callback function.
- *
- * @param string|array $callback New test exporter callback function.
- */
- protected function _set_exporter_callback( $callback ) {
- $this->new_callback_value = $callback;
- add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_exporter_callback_value' ), 20 );
- }
- /**
- * Change the test exporter callback to a specified value.
- *
- * @since 5.2.0
- *
- * @param array $exporters List of data exporters.
- * @return array List of data exporters.
- */
- public function filter_exporter_callback_value( $exporters ) {
- $exporters[ self::$exporter_key ]['callback'] = $this->new_callback_value;
- return $exporters;
- }
- /**
- * Helper method for unsetting an array index in the test exporter.
- *
- * @param string $key Test exporter key to unset.
- */
- protected function _unset_exporter_key( $key ) {
- $this->key_to_unset = $key;
- add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'filter_unset_exporter_key' ), 20 );
- }
- /**
- * Unset a specified key in the test exporter array.
- *
- * @param array $exporters List of data exporters.
- *
- * @return array List of data exporters.
- */
- public function filter_unset_exporter_key( $exporters ) {
- if ( false === $this->key_to_unset ) {
- $exporters[ self::$exporter_key ] = false;
- } elseif ( ! empty( $this->key_to_unset ) ) {
- unset( $exporters[ self::$exporter_key ][ $this->key_to_unset ] );
- }
- return $exporters;
- }
- /**
- * The function should send an error when the request ID is missing.
- *
- * @since 5.2.0
- */
- public function test_error_when_missing_request_id() {
- $this->_make_ajax_call(
- array(
- 'id' => null, // Missing request ID.
- )
- );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Missing request ID.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when the request ID is less than 1.
- *
- * @since 5.2.0
- */
- public function test_error_when_invalid_id() {
- $this->_make_ajax_call(
- array(
- 'id' => -1, // Invalid request ID, less than 1.
- )
- );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Invalid request ID.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when the current user is missing the required capability.
- *
- * @since 5.2.0
- */
- public function test_error_when_current_user_missing_required_capability() {
- $this->_setRole( 'author' );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertFalse( current_user_can( 'export_others_personal_data' ) );
- $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
- }
- /**
- * Test requests do not succeed on multisite when the current user is not a network admin.
- *
- * @ticket 43438
- * @group multisite
- * @group ms-required
- */
- public function test_error_when_current_user_missing_required_capability_multisite() {
- revoke_super_admin( get_current_user_id() );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Sorry, you are not allowed to perform this action.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when the nonce does not validate.
- *
- * @since 5.2.0
- */
- public function test_failure_with_invalid_nonce() {
- $this->expectException( 'WPAjaxDieStopException' );
- $this->expectExceptionMessage( '-1' );
- $this->_make_ajax_call(
- array(
- 'security' => 'invalid-nonce',
- )
- );
- }
- /**
- * The function should send an error when the request type is incorrect.
- *
- * @since 5.2.0
- */
- public function test_error_when_incorrect_request_type() {
- $request_id = wp_create_user_request(
- 'erase-request@example.com',
- 'remove_personal_data' // Incorrect request type, expects 'export_personal_data'.
- );
- $this->_make_ajax_call(
- array(
- 'security' => wp_create_nonce( 'wp-privacy-export-personal-data-' . $request_id ),
- 'id' => $request_id,
- )
- );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Invalid request type.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when the requester's email address is invalid.
- *
- * @since 5.2.0
- */
- public function test_error_when_invalid_email_address() {
- wp_update_post(
- array(
- 'ID' => self::$request_id,
- 'post_title' => '', // Invalid requester's email address.
- )
- );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'A valid email address must be given.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when the exporter index is missing.
- *
- * @since 5.2.0
- */
- public function test_error_when_missing_exporter_index() {
- $this->_make_ajax_call(
- array(
- 'exporter' => null, // Missing exporter index.
- )
- );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Missing exporter index.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when the page index is missing.
- *
- * @since 5.2.0
- */
- public function test_error_when_missing_page_index() {
- $this->_make_ajax_call(
- array(
- 'page' => null, // Missing page index.
- )
- );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Missing page index.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when an exporter has improperly used the `wp_privacy_personal_data_exporters` filter.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_has_improperly_used_exporters_filter() {
- // Improper filter usage: returns false instead of an expected array.
- add_filter( 'wp_privacy_personal_data_exporters', '__return_false', 999 );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'An exporter has improperly used the registration filter.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when the exporter index is negative.
- *
- * @since 5.2.0
- */
- public function test_error_when_negative_exporter_index() {
- $this->_make_ajax_call(
- array(
- 'exporter' => -1, // Negative exporter index.
- )
- );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Exporter index cannot be negative.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when the exporter index is out of range.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_index_out_of_range() {
- $this->_make_ajax_call(
- array(
- 'exporter' => PHP_INT_MAX, // Out of range exporter index.
- )
- );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Exporter index is out of range.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when the page index is less than one.
- *
- * @since 5.2.0
- */
- public function test_error_when_page_index_less_than_one() {
- $this->_make_ajax_call(
- array(
- 'page' => 0, // Page index less than one.
- )
- );
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'Page index cannot be less than one.', $this->_last_response_parsed['data'] );
- }
- /**
- * The function should send an error when an exporter is not an array.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_not_array() {
- $this->_unset_exporter_key( false );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected an array describing the exporter at index %s.',
- self::$exporter_key
- ),
- $this->_last_response_parsed['data']
- );
- }
- /**
- * The function should send an error when an exporter is missing a friendly name.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_missing_friendly_name() {
- $this->_unset_exporter_key( 'exporter_friendly_name' );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Exporter array at index %s does not include a friendly name.',
- self::$exporter_key
- ),
- $this->_last_response_parsed['data']
- );
- }
- /**
- * The function should send an error when an exporter is missing a callback.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_missing_callback() {
- $this->_unset_exporter_key( 'callback' );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Exporter does not include a callback: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
- /**
- * The function should send an error when an exporter, at a given index, has an invalid callback.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_index_invalid_callback() {
- $this->_set_exporter_callback( false );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Exporter callback is not a valid callback: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
- /**
- * When an exporter callback returns a WP_Error, it should be passed as the error.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_callback_returns_wp_error() {
- $this->_set_exporter_callback( array( $this, 'callback_return_wp_error' ) );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame( 'passed_message', $this->_last_response_parsed['data'][0]['code'] );
- $this->assertSame( 'This is a WP_Error message.', $this->_last_response_parsed['data'][0]['message'] );
- }
- /**
- * Callback for exporter's response.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- * @return WP_Error WP_Error instance.
- */
- public function callback_return_wp_error( $email_address, $page = 1 ) {
- return new WP_Error( 'passed_message', 'This is a WP_Error message.' );
- }
- /**
- * The function should send an error when an exporter, at a given index, is missing an array response.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_index_invalid_response() {
- $this->_set_exporter_callback( '__return_null' );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected response as an array from exporter: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
- /**
- * The function should send an error when an exporter is missing data in array response.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_missing_data_response() {
- $this->_set_exporter_callback( array( $this, 'callback_missing_data_response' ) );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected data in response array from exporter: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
- /**
- * Callback for exporter's response.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data.
- */
- public function callback_missing_data_response( $email_address, $page = 1 ) {
- $response = $this->callback_custom_personal_data_exporter( $email_address, $page );
- unset( $response['data'] ); // Missing data part of response.
- return $response;
- }
- /**
- * The function should send an error when an exporter is missing 'data' array in array response.
- *
- * @since 5.2.0
- */
- public function test_function_should_error_when_exporter_missing_data_array_response() {
- $this->_set_exporter_callback( array( $this, 'callback_missing_data_array_response' ) );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected data array in response array from exporter: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
- /**
- * Callback for exporter's response.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data.
- */
- public function callback_missing_data_array_response( $email_address, $page = 1 ) {
- $response = $this->callback_custom_personal_data_exporter( $email_address, $page );
- $response['data'] = false; // Not an array.
- return $response;
- }
- /**
- * The function should send an error when an exporter is missing 'done' in array response.
- *
- * @since 5.2.0
- */
- public function test_error_when_exporter_missing_done_response() {
- $this->_set_exporter_callback( array( $this, 'callback_missing_done_response' ) );
- $this->_make_ajax_call();
- $this->assertFalse( $this->_last_response_parsed['success'] );
- $this->assertSame(
- sprintf(
- 'Expected done (boolean) in response array from exporter: %s.',
- self::$exporter_friendly_name
- ),
- $this->_last_response_parsed['data']
- );
- }
- /**
- * Remove the response's done flag.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data.
- */
- public function callback_missing_done_response( $email_address, $page = 1 ) {
- $response = $this->callback_custom_personal_data_exporter( $email_address, $page );
- unset( $response['done'] );
- return $response;
- }
- /**
- * The function should successfully send exporter data response when the current user has the required capability.
- *
- * @since 5.2.0
- */
- public function test_succeeds_when_current_user_has_required_capability() {
- $this->assertTrue( current_user_can( 'export_others_personal_data' ) );
- $this->_make_ajax_call();
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( 'custom-exporter-item-id', $this->_last_response_parsed['data']['data']['item_id'] );
- $this->assertSame( 'Email', $this->_last_response_parsed['data']['data']['data'][0]['name'] );
- $this->assertSame( self::$request_email, $this->_last_response_parsed['data']['data']['data'][0]['value'] );
- }
- /**
- * The function should successfully send exporter data response when no items to export.
- *
- * @since 5.2.0
- */
- public function test_success_when_no_items_to_export() {
- $this->_make_ajax_call( array( 'page' => 2 ) );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertEmpty( $this->_last_response_parsed['data']['data'] );
- $this->assertTrue( $this->_last_response_parsed['data']['done'] );
- }
- /**
- * The function's output should be filterable with the `wp_privacy_personal_data_export_page` filter.
- *
- * @since 5.2.0
- */
- public function test_output_should_be_filterable() {
- add_filter( 'wp_privacy_personal_data_export_page', array( $this, 'filter_exporter_data_response' ), 20, 7 );
- $this->_make_ajax_call();
- $expected_group_label = sprintf(
- '%s-%s-%s-%s-%s-%s',
- self::$exporter,
- self::$page,
- self::$request_email,
- self::$request_id,
- self::$send_as_email,
- self::$exporter_key
- );
- $this->assertTrue( $this->_last_response_parsed['success'] );
- $this->assertSame( $expected_group_label, $this->_last_response_parsed['data']['group_label'] );
- $this->assertSame( 'filtered_group_id', $this->_last_response_parsed['data']['group_id'] );
- $this->assertSame( 'filtered_item_id', $this->_last_response_parsed['data']['item_id'] );
- $this->assertSame( 'filtered_name', $this->_last_response_parsed['data']['data'][0]['name'] );
- $this->assertSame( 'filtered_value', $this->_last_response_parsed['data']['data'][0]['value'] );
- }
- /**
- * Filter exporter's data response.
- *
- * @since 5.2.0
- *
- * @param array $response The personal data for the given exporter and page.
- * @param int $exporter_index The index of the exporter that provided this data.
- * @param string $email_address The email address associated with this personal data.
- * @param int $page The page for this response.
- * @param int $request_id The privacy request post ID associated with this request.
- * @param bool $send_as_email Whether the final results of the export should be emailed to the user.
- * @param string $exporter_key The key (slug) of the exporter that provided this data.
- *
- * @return array The personal data for the given exporter and page.
- */
- public function filter_exporter_data_response( $response, $exporter_index, $email_address, $page, $request_id, $send_as_email, $exporter_key ) {
- $group_label = sprintf(
- '%s-%s-%s-%s-%s-%s',
- $exporter_index,
- $page,
- $email_address,
- $request_id,
- $send_as_email,
- $exporter_key
- );
- $response['group_label'] = $group_label;
- $response['group_id'] = 'filtered_group_id';
- $response['item_id'] = 'filtered_item_id';
- $response['data'][0]['name'] = 'filtered_name';
- $response['data'][0]['value'] = 'filtered_value';
- return $response;
- }
- /**
- * Filter to register a custom personal data exporter.
- *
- * @since 5.2.0
- *
- * @param array $exporters An array of personal data exporters.
- *
- * @return array An array of personal data exporters.
- */
- public function filter_register_custom_personal_data_exporter( $exporters ) {
- $exporters[ self::$exporter_key ] = array(
- 'exporter_friendly_name' => self::$exporter_friendly_name,
- 'callback' => array( $this, 'callback_custom_personal_data_exporter' ),
- );
- return $exporters;
- }
- /**
- * Callback for a custom personal data exporter.
- *
- * @since 5.2.0
- *
- * @param string $email_address The requester's email address.
- * @param int $page Page number.
- *
- * @return array Export data response.
- */
- public function callback_custom_personal_data_exporter( $email_address, $page = 1 ) {
- $data_to_export = array();
- if ( 1 === $page ) {
- $data_to_export = array(
- 'group_id' => self::$exporter_key . '-group-id',
- 'group_label' => self::$exporter_key . '-group-label',
- 'item_id' => self::$exporter_key . '-item-id',
- 'data' => array(
- array(
- 'name' => 'Email',
- 'value' => $email_address,
- ),
- ),
- );
- }
- return array(
- 'data' => $data_to_export,
- 'done' => true,
- );
- }
- /**
- * Helper function for Ajax handler.
- *
- * @since 5.2.0
- *
- * @param array $args Ajax request arguments.
- */
- protected function _make_ajax_call( $args = array() ) {
- $this->_last_response_parsed = null;
- $this->_last_response = '';
- $defaults = array(
- 'action' => self::$action,
- 'security' => wp_create_nonce( self::$action . '-' . self::$request_id ),
- 'exporter' => self::$exporter,
- 'page' => self::$page,
- 'sendAsEmail' => self::$send_as_email,
- 'id' => self::$request_id,
- );
- $_POST = wp_parse_args( $args, $defaults );
- try {
- $this->_handleAjax( self::$action );
- } catch ( WPAjaxDieContinueException $e ) {
- unset( $e );
- }
- if ( $this->_last_response ) {
- $this->_last_response_parsed = json_decode( $this->_last_response, true );
- }
- }
- }
|