MediaWiki  REL1_23
ApiQueryContinueTestBase.php
Go to the documentation of this file.
00001 <?php
00025 require_once 'ApiQueryTestBase.php';
00026 
00027 abstract class ApiQueryContinueTestBase extends ApiQueryTestBase {
00028 
00032     protected $mVerbose = false;
00033 
00037     protected function checkC( $expected, $params, $expectedCount, $id, $continue = true ) {
00038         $result = $this->query( $params, $expectedCount, $id, $continue );
00039         $this->assertResult( $expected, $result, $id );
00040     }
00041 
00051     protected function query( $params, $expectedCount, $id, $useContinue = true ) {
00052         if ( isset( $params['action'] ) ) {
00053             $this->assertEquals( 'query', $params['action'], 'Invalid query action' );
00054         } else {
00055             $params['action'] = 'query';
00056         }
00057         if ( $useContinue && !isset( $params['continue'] ) ) {
00058             $params['continue'] = '';
00059         }
00060         $count = 0;
00061         $result = array();
00062         $continue = array();
00063         do {
00064             $request = array_merge( $params, $continue );
00065             uksort( $request, function ( $a, $b ) {
00066                 // put 'continue' params at the end - lazy method
00067                 $a = strpos( $a, 'continue' ) !== false ? 'zzz ' . $a : $a;
00068                 $b = strpos( $b, 'continue' ) !== false ? 'zzz ' . $b : $b;
00069 
00070                 return strcmp( $a, $b );
00071             } );
00072             $reqStr = http_build_query( $request );
00073             //$reqStr = str_replace( '&', ' & ', $reqStr );
00074             $this->assertLessThan( $expectedCount, $count, "$id more data: $reqStr" );
00075             if ( $this->mVerbose ) {
00076                 print "$id (#$count): $reqStr\n";
00077             }
00078             try {
00079                 $data = $this->doApiRequest( $request );
00080             } catch ( Exception $e ) {
00081                 throw new Exception( "$id on $count", 0, $e );
00082             }
00083             $data = $data[0];
00084             if ( isset( $data['warnings'] ) ) {
00085                 $warnings = json_encode( $data['warnings'] );
00086                 $this->fail( "$id Warnings on #$count in $reqStr\n$warnings" );
00087             }
00088             $this->assertArrayHasKey( 'query', $data, "$id no 'query' on #$count in $reqStr" );
00089             if ( isset( $data['continue'] ) ) {
00090                 $continue = $data['continue'];
00091                 unset( $data['continue'] );
00092             } else {
00093                 $continue = array();
00094             }
00095             if ( $this->mVerbose ) {
00096                 $this->printResult( $data );
00097             }
00098             $this->mergeResult( $result, $data );
00099             $count++;
00100             if ( empty( $continue ) ) {
00101                 // $this->assertEquals( $expectedCount, $count, "$id finished early" );
00102                 if ( $expectedCount > $count ) {
00103                     print "***** $id Finished early in $count turns. $expectedCount was expected\n";
00104                 }
00105 
00106                 return $result;
00107             } elseif ( !$useContinue ) {
00108                 $this->assertFalse( 'Non-smart query must be requested all at once' );
00109             }
00110         } while ( true );
00111     }
00112 
00116     private function printResult( $data ) {
00117         $q = $data['query'];
00118         $print = array();
00119         if ( isset( $q['pages'] ) ) {
00120             foreach ( $q['pages'] as $p ) {
00121                 $m = $p['title'];
00122                 if ( isset( $p['links'] ) ) {
00123                     $m .= '/[' . implode( ',', array_map(
00124                         function ( $v ) {
00125                             return $v['title'];
00126                         },
00127                         $p['links'] ) ) . ']';
00128                 }
00129                 if ( isset( $p['categories'] ) ) {
00130                     $m .= '/(' . implode( ',', array_map(
00131                         function ( $v ) {
00132                             return str_replace( 'Category:', '', $v['title'] );
00133                         },
00134                         $p['categories'] ) ) . ')';
00135                 }
00136                 $print[] = $m;
00137             }
00138         }
00139         if ( isset( $q['allcategories'] ) ) {
00140             $print[] = '*Cats/(' . implode( ',', array_map(
00141                 function ( $v ) {
00142                     return $v['*'];
00143                 },
00144                 $q['allcategories'] ) ) . ')';
00145         }
00146         self::GetItems( $q, 'allpages', 'Pages', $print );
00147         self::GetItems( $q, 'alllinks', 'Links', $print );
00148         self::GetItems( $q, 'alltransclusions', 'Trnscl', $print );
00149         print ' ' . implode( '  ', $print ) . "\n";
00150     }
00151 
00152     private static function GetItems( $q, $moduleName, $name, &$print ) {
00153         if ( isset( $q[$moduleName] ) ) {
00154             $print[] = "*$name/[" . implode( ',',
00155                 array_map(
00156                     function ( $v ) {
00157                         return $v['title'];
00158                     },
00159                     $q[$moduleName] ) ) . ']';
00160         }
00161     }
00162 
00169     protected function mergeResult( &$results, $newResult, $numericIds = false ) {
00170         $this->assertEquals( is_array( $results ), is_array( $newResult ), 'Type of result and data do not match' );
00171         if ( !is_array( $results ) ) {
00172             $this->assertEquals( $results, $newResult, 'Repeated result must be the same as before' );
00173         } else {
00174             $sort = null;
00175             foreach ( $newResult as $key => $value ) {
00176                 if ( !$numericIds && $sort === null ) {
00177                     if ( !is_array( $value ) ) {
00178                         $sort = false;
00179                     } elseif ( array_key_exists( 'title', $value ) ) {
00180                         $sort = function ( $a, $b ) {
00181                             return strcmp( $a['title'], $b['title'] );
00182                         };
00183                     } else {
00184                         $sort = false;
00185                     }
00186                 }
00187                 $keyExists = array_key_exists( $key, $results );
00188                 if ( is_numeric( $key ) ) {
00189                     if ( $numericIds ) {
00190                         if ( !$keyExists ) {
00191                             $results[$key] = $value;
00192                         } else {
00193                             $this->mergeResult( $results[$key], $value );
00194                         }
00195                     } else {
00196                         $results[] = $value;
00197                     }
00198                 } elseif ( !$keyExists ) {
00199                     $results[$key] = $value;
00200                 } else {
00201                     $this->mergeResult( $results[$key], $value, $key === 'pages' );
00202                 }
00203             }
00204             if ( $numericIds ) {
00205                 ksort( $results, SORT_NUMERIC );
00206             } elseif ( $sort !== null && $sort !== false ) {
00207                 usort( $results, $sort );
00208             }
00209         }
00210     }
00211 }