BryanDavis has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/234194

Change subject: API: Force 'required' to use bools in nested elements
......................................................................

API: Force 'required' to use bools in nested elements

Fix formatversion=1 api output to treat 'required' values as booleans in
schema elements that are nested (array and object types).

Bug: T97487
Change-Id: Iba26be02949224f80d590e9b84492b099981aa1d
---
M includes/ApiJsonSchema.php
A tests/ApiJsonSchemaTest.php
2 files changed, 188 insertions(+), 4 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/EventLogging 
refs/changes/94/234194/1

diff --git a/includes/ApiJsonSchema.php b/includes/ApiJsonSchema.php
index ab4dea2..f6a6d49 100644
--- a/includes/ApiJsonSchema.php
+++ b/includes/ApiJsonSchema.php
@@ -129,16 +129,39 @@
 
                $this->markCacheable( $rev );
                $schema = $content->getJsonData( true );
+               static::addOutputMetadata( $schema );
 
                $result = $this->getResult();
                $result->addValue( null, 'title', $title->getText() );
                foreach ( $schema as $k => &$v ) {
-                       if ( $k === 'properties' ) {
-                               foreach ( $v as &$properties ) {
-                                       $properties[ApiResult::META_BC_BOOLS] = 
array( 'required' );
+                       $result->addValue( null, $k, $v );
+               }
+       }
+
+       /**
+        * Add ApiResult metadata to the given array.
+        *
+        * Items in 'properties' or 'items' collections will be annotated so 
that
+        * the API knows that their 'required' values should be output as
+        * booleans.
+        *
+        * @param array &$typeDescription
+        */
+       public static function addOutputMetadata( array &$typeDescription ) {
+               foreach ( $typeDescription as $key => &$value ) {
+                       if ( $key === 'properties' || $key === 'items' ) {
+                               foreach ( $value as &$type ) {
+                                       $type[ApiResult::META_BC_BOOLS] = 
array( 'required' );
+
+                                       if ( $type['type'] === 'object' ) {
+                                               // Objects contain additional 
properties
+                                               static::addOutputMetadata( 
$type );
+
+                                       } elseif ( $type['type'] === 'array' ) {
+                                               static::addOutputMetadata( 
$type );
+                                       }
                                }
                        }
-                       $result->addValue( null, $k, $v );
                }
        }
 }
diff --git a/tests/ApiJsonSchemaTest.php b/tests/ApiJsonSchemaTest.php
new file mode 100644
index 0000000..2faedc2
--- /dev/null
+++ b/tests/ApiJsonSchemaTest.php
@@ -0,0 +1,161 @@
+<?php
+/**
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Extensions
+ *
+ * @author Bryan Davis <[email protected]>
+ * @copyright © 2015 Bryan Davis and Wikimedia Foundation.
+ */
+
+/**
+ * @group EventLogging
+ * @covers ApiJsonSchema
+ */
+class ApiJsonSchemaTest extends MediaWikiTestCase {
+
+       public function testAddOutputMetadata() {
+               $schema = array(
+                       'description' => 'test',
+                       'properties' => array(
+                               'n' => array(
+                                       'type' => 'number',
+                                       'required' => false,
+                                       'description' => 'number',
+                               ),
+                               'i' => array(
+                                       'type' => 'integer',
+                                       'required' => false,
+                                       'description' => 'integer',
+                               ),
+                               'a' => array(
+                                       'type' => 'array',
+                                       'required' => false,
+                                       'description' => 'array',
+                                       'items' => array(
+                                               array(
+                                                       'type' => 'object',
+                                                       'required' => false,
+                                                       'description' => 
'object',
+                                                       'properties' => array(
+                                                               'n' => array(
+                                                                       'type' 
=> 'number',
+                                                                       
'required' => false,
+                                                                       
'description' => 'number',
+                                                               ),
+                                                               'i' => array(
+                                                                       'type' 
=> 'integer',
+                                                                       
'required' => false,
+                                                                       
'description' => 'integer',
+                                                               ),
+                                                       ),
+                                               ),
+                                       ),
+                               ),
+                               'o' => array(
+                                       'type' => 'object',
+                                       'required' => false,
+                                       'description' => 'object',
+                                       'properties' => array(
+                                               'oo' => array(
+                                                       'type' => 'object',
+                                                       'required' => false,
+                                                       'description' => 
'object',
+                                                       'properties' => array(
+                                                               'n' => array(
+                                                                       'type' 
=> 'number',
+                                                                       
'required' => false,
+                                                                       
'description' => 'number',
+                                                               ),
+                                                               'i' => array(
+                                                                       'type' 
=> 'integer',
+                                                                       
'required' => false,
+                                                                       
'description' => 'integer',
+                                                               ),
+                                                       ),
+                                               )
+                                       ),
+                               ),
+                       ),
+               );
+
+               ApiJsonSchema::addOutputMetadata( $schema );
+
+               $this->assertArrayHasKey( '_BC_bools',
+                       $schema['properties']['n']
+               );
+               $this->assertArrayHasKey( '_BC_bools',
+                       $schema['properties']['i']
+               );
+               $this->assertArrayHasKey( '_BC_bools',
+                       $schema['properties']['a']
+               );
+               $this->assertArrayHasKey( '_BC_bools',
+                       $schema['properties']['a']['items'][0]
+);
+               $this->assertArrayHasKey( '_BC_bools',
+                       
$schema['properties']['a']['items'][0]['properties']['n']
+               );
+               $this->assertArrayHasKey( '_BC_bools',
+                       
$schema['properties']['a']['items'][0]['properties']['i']
+               );
+               $this->assertArrayHasKey( '_BC_bools',
+                       $schema['properties']['o']
+               );
+               $this->assertArrayHasKey( '_BC_bools',
+                       $schema['properties']['o']['properties']['oo']
+               );
+               $this->assertArrayHasKey( '_BC_bools',
+                       
$schema['properties']['o']['properties']['oo']['properties']['n']
+               );
+               $this->assertArrayHasKey( '_BC_bools',
+                       
$schema['properties']['o']['properties']['oo']['properties']['i']
+               );
+
+               // make sure there are no extra '_BC_bools' keys
+               $bcBoolCount = 0;
+               $this->visitAllRecursive( $schema,
+                       function ( $v, $k ) use ( &$bcBoolCount ) {
+                               if ( $k === '_BC_bools' ) {
+                                       $bcBoolCount = $bcBoolCount + 1;
+                               }
+                       }
+               );
+               $this->assertSame( 10, $bcBoolCount );
+       }
+
+       /**
+        * Visit all the elements of an array recursively.
+        *
+        * Works like array_walk_recursive() except that elements which are 
arrays
+        * are visited as well rather than stepping into them and ignoring the
+        * array itself.
+        *
+        * @param array &$a Array to visit
+        * @param Callable $callback Function to call for each element. Will be
+        *     passed two arguments: $value and $key (goofy order taken from
+        *     array_walk_recursive())
+        */
+       protected function visitAllRecursive( array &$a, $callback ) {
+               foreach ( $a as $key => $value ) {
+                       $callback( $value, $key );
+                       if ( is_array( $value ) ) {
+                               $this->visitAllRecursive( $value, $callback );
+                       }
+               }
+       }
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/234194
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iba26be02949224f80d590e9b84492b099981aa1d
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/EventLogging
Gerrit-Branch: master
Gerrit-Owner: BryanDavis <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to