From 0ec057e73c4fd5a6089c0e8474071fbdf3b0071b Mon Sep 17 00:00:00 2001 From: Brad Jorsch Date: Fri, 28 Aug 2015 11:10:20 -0400 Subject: [PATCH] API: Add ApiResult::META_KVP_MERGE This allows for merging the KVP key into the value for the alternative output format. Specifically, { "key": { "foo": "bar" } } can now be turned into [{ "name": "key", "foo": "bar" }] instead of [{ "name": "key", "value": { "foo": "bar" } }] Change-Id: Ie1f9235893dbbcd2948c46e0356360b5635a3ddd --- RELEASE-NOTES-1.26 | 2 + includes/api/ApiResult.php | 58 ++++++++++++++++---- tests/phpunit/includes/api/ApiResultTest.php | 44 +++++++++++++++ 3 files changed, 93 insertions(+), 11 deletions(-) diff --git a/RELEASE-NOTES-1.26 b/RELEASE-NOTES-1.26 index 14d6c5801e..5b85bbcc7e 100644 --- a/RELEASE-NOTES-1.26 +++ b/RELEASE-NOTES-1.26 @@ -99,6 +99,8 @@ production. information about the relevant block. === Action API internal changes in 1.26 === +* New metadata item ApiResult::META_KVP_MERGE to allow for merging the KVP key + into the value when the value is an assoc. === Languages updated in 1.26 === diff --git a/includes/api/ApiResult.php b/includes/api/ApiResult.php index f0c7430140..267518553a 100644 --- a/includes/api/ApiResult.php +++ b/includes/api/ApiResult.php @@ -108,12 +108,24 @@ class ApiResult implements ApiSerializable { const META_TYPE = '_type'; /** - * Key (rather than "name" or other default) for when META_TYPE is 'kvp' or - * 'BCkvp'. Value is string. + * Key for the metatata item whose value specifies the name used for the + * kvp key in the alternative output format with META_TYPE 'kvp' or + * 'BCkvp', i.e. the "name" in value. + * Value is string. * @since 1.25 */ const META_KVP_KEY_NAME = '_kvpkeyname'; + /** + * Key for the metadata item that indicates that the KVP key should be + * added into an assoc value, i.e. {"key":{"val1":"a","val2":"b"}} + * transforms to {"name":"key","val1":"a","val2":"b"} rather than + * {"name":"key","value":{"val1":"a","val2":"b"}}. + * Value is boolean. + * @since 1.26 + */ + const META_KVP_MERGE = '_kvpmerge'; + /** * Key for the 'BC bools' metadata item. Value is string[]. * Note no setter is provided. @@ -941,19 +953,43 @@ class ApiResult implements ApiSerializable { : $transformTypes['ArmorKVP']; $valKey = isset( $transforms['BC'] ) ? '*' : 'value'; $assocAsObject = !empty( $transformTypes['AssocAsObject'] ); + $merge = !empty( $metadata[self::META_KVP_MERGE] ); $ret = array(); foreach ( $data as $k => $v ) { - $item = array( - $key => $k, - $valKey => $v, - ); - if ( $strip === 'none' ) { - $item += array( - self::META_PRESERVE_KEYS => array( $key ), - self::META_CONTENT => $valKey, - self::META_TYPE => 'assoc', + if ( $merge && ( is_array( $v ) || is_object( $v ) ) ) { + $vArr = (array)$v; + if ( isset( $vArr[self::META_TYPE] ) ) { + $mergeType = $vArr[self::META_TYPE]; + } elseif ( is_object( $v ) ) { + $mergeType = 'assoc'; + } else { + $keys = array_keys( $vArr ); + sort( $keys, SORT_NUMERIC ); + $mergeType = ( $keys === array_keys( $keys ) ) ? 'array' : 'assoc'; + } + } else { + $mergeType = 'n/a'; + } + if ( $mergeType === 'assoc' ) { + $item = $vArr + array( + $key => $k, + ); + if ( $strip === 'none' ) { + self::setPreserveKeysList( $item, array( $key ) ); + } + } else { + $item = array( + $key => $k, + $valKey => $v, ); + if ( $strip === 'none' ) { + $item += array( + self::META_PRESERVE_KEYS => array( $key ), + self::META_CONTENT => $valKey, + self::META_TYPE => 'assoc', + ); + } } $ret[] = $assocAsObject ? (object)$item : $item; } diff --git a/tests/phpunit/includes/api/ApiResultTest.php b/tests/phpunit/includes/api/ApiResultTest.php index f894f87b8c..affb0fa9a5 100644 --- a/tests/phpunit/includes/api/ApiResultTest.php +++ b/tests/phpunit/includes/api/ApiResultTest.php @@ -674,6 +674,10 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'BCkvp', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( 'x' => 'a', 'y' => array( 'b' ), 'z' => array( 'c' => 'd' ), + ApiResult::META_TYPE => 'kvp', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1 ), 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -858,6 +862,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'assoc', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( + 'x' => 'a', + 'y' => array( 'b', ApiResult::META_TYPE => 'array' ), + 'z' => array( 'c' => 'd', ApiResult::META_TYPE => 'assoc' ), + ApiResult::META_TYPE => 'assoc', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -889,6 +900,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'assoc', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => (object)array( + 'x' => 'a', + 'y' => array( 'b', ApiResult::META_TYPE => 'array' ), + 'z' => (object)array( 'c' => 'd', ApiResult::META_TYPE => 'assoc' ), + ApiResult::META_TYPE => 'assoc', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -920,6 +938,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'array', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( + $kvp( 'name', 'x', 'value', 'a' ), + $kvp( 'name', 'y', 'value', array( 'b', ApiResult::META_TYPE => 'array' ) ), + array( 'name' => 'z', 'c' => 'd', ApiResult::META_TYPE => 'assoc', ApiResult::META_PRESERVE_KEYS => array( 'name' ) ), + ApiResult::META_TYPE => 'array', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -951,6 +976,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'array', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( + $kvp( 'name', 'x', '*', 'a' ), + $kvp( 'name', 'y', '*', array( 'b', ApiResult::META_TYPE => 'array' ) ), + array( 'name' => 'z', 'c' => 'd', ApiResult::META_TYPE => 'assoc', ApiResult::META_PRESERVE_KEYS => array( 'name' ) ), + ApiResult::META_TYPE => 'array', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -986,6 +1018,13 @@ class ApiResultTest extends MediaWikiTestCase { ApiResult::META_TYPE => 'array', ApiResult::META_KVP_KEY_NAME => 'key', ), + 'kvpmerge' => array( + (object)$kvp( 'name', 'x', 'value', 'a' ), + (object)$kvp( 'name', 'y', 'value', array( 'b', ApiResult::META_TYPE => 'array' ) ), + (object)array( 'name' => 'z', 'c' => 'd', ApiResult::META_TYPE => 'assoc', ApiResult::META_PRESERVE_KEYS => array( 'name' ) ), + ApiResult::META_TYPE => 'array', + ApiResult::META_KVP_MERGE => true, + ), 'emptyDefault' => array( '_dummy' => 1, ApiResult::META_TYPE => 'array' ), 'emptyAssoc' => (object)array( '_dummy' => 1, ApiResult::META_TYPE => 'assoc' ), '_dummy' => 1, @@ -1025,6 +1064,11 @@ class ApiResultTest extends MediaWikiTestCase { (object)array( 'key' => 'x', 'value' => 'a' ), (object)array( 'key' => 'y', 'value' => 'b' ), ), + 'kvpmerge' => array( + (object)array( 'name' => 'x', 'value' => 'a' ), + (object)array( 'name' => 'y', 'value' => array( 'b' ) ), + (object)array( 'name' => 'z', 'c' => 'd' ), + ), 'emptyDefault' => array(), 'emptyAssoc' => (object)array(), '_dummy' => 1, -- 2.20.1