Yurik has uploaded a new change for review.

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


Change subject: Ability to get partial result from the API
......................................................................

Ability to get partial result from the API

* Small memory devices seem to have issues with large JSON blobs.
This patch allows clients to request a portion of the text by
providing an offset and a maximum length.

* All "text" strings are virtually joined together, and only the
range after offset and no longer than maxlen is actually returned.

* A "continue-offset" value is set if there is more data.

Change-Id: Ib71800c1afa057bf87fd652ecb650bc38e33df68
---
M includes/api/ApiMobileView.php
1 file changed, 54 insertions(+), 3 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MobileFrontend 
refs/changes/69/68869/1

diff --git a/includes/api/ApiMobileView.php b/includes/api/ApiMobileView.php
index a48cbd8..fe08f12 100644
--- a/includes/api/ApiMobileView.php
+++ b/includes/api/ApiMobileView.php
@@ -6,7 +6,8 @@
         */
        const CACHE_VERSION = 3;
 
-       private $followRedirects, $noHeadings, $mainPage, $noTransform, 
$variant;
+       private $followRedirects, $noHeadings, $mainPage, $noTransform, 
$variant, $offset, $maxlen;
+
        /**
         * @var File
         */
@@ -32,6 +33,14 @@
                $this->followRedirects = $params['redirect'] == 'yes';
                $this->noHeadings = $params['noheadings'];
                $this->noTransform = $params['notransform'];
+               $this->offset = $params['offset'];
+               $this->maxlen = $params['maxlen'];
+
+               if ( $this->offset === 0 && $this->maxlen === 0 ) {
+                       $this->offset = -1; // Disable text splitting
+               } elseif ( $this->maxlen === 0 ) {
+                       $this->maxlen = PHP_INT_MAX;
+               }
 
                $title = Title::newFromText( $params['page'] );
                if ( !$title ) {
@@ -73,7 +82,7 @@
                                }
                                $section['id'] = $i;
                                if ( isset( $prop['text'] ) && isset( 
$requestedSections[$i] ) && isset( $data['text'][$i] ) ) {
-                                       $section[$textElement] = 
$this->prepareSection( $data['text'][$i] );
+                                       $section[$textElement] = 
$this->stringSplitter( $this->prepareSection( $data['text'][$i] ) );
                                        unset( $requestedSections[$i] );
                                }
                                if ( isset( $data['refsections'][$i] ) ) {
@@ -86,7 +95,7 @@
                        foreach ( array_keys( $requestedSections ) as $index ) {
                                $section = array( 'id' => $index );
                                if ( isset( $data['text'][$index] ) ) {
-                                       $section[$textElement] = 
$data['text'][$index];
+                                       $section[$textElement] = 
$this->stringSplitter( $data['text'][$index] );
                                } else {
                                        $missingSections[] = $index;
                                }
@@ -96,9 +105,39 @@
                if ( count( $missingSections ) && isset( $prop['text'] ) ) {
                        $this->setWarning( 'Section(s) ' . implode( ', ', 
$missingSections ) . ' not found' );
                }
+               if ( $this->maxlen < 0 ) {
+                       // There is more data available
+                       $this->getResult()->addValue( null, 
$this->getModuleName(),
+                               array( 'continue-offset' => $params['offset'] + 
$params['maxlen'] )
+                       );
+               }
                $this->getResult()->setIndexedTagName( $result, 'section' );
                $this->getResult()->addValue( null, $this->getModuleName(), 
array( 'sections' => $result ) );
                wfProfileOut( __METHOD__ );
+       }
+
+       private function stringSplitter( $text ) {
+               if ( $this->offset < 0  ) {
+                       return $text; // NOOP - string splitting mode is off
+               } elseif ( $this->maxlen < 0 ) {
+                       return ''; // Limit exceeded
+               }
+               $textLen = mb_strlen( $text );
+               $start = $this->offset;
+               $len = $textLen - $start;
+               if ( $len > 0 ) {
+                       // At least part of the $text should be included
+                       if ( $len > $this->maxlen ) {
+                               $len = $this->maxlen;
+                               $this->maxlen = -1;
+                       } else {
+                               $this->maxlen -= $len;
+                       }
+                       $this->offset = 0;
+                       return mb_substr( $text, $start, $len );
+               }
+               $this->offset -= $textLen;
+               return '';
        }
 
        private function prepareSection( $html ) {
@@ -269,6 +308,16 @@
                        'noimages' => false,
                        'noheadings' => false,
                        'notransform' => false,
+                       'offset' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_MIN => 0,
+                               ApiBase::PARAM_DFLT => 0,
+                       ),
+                       'maxlen' => array(
+                               ApiBase::PARAM_TYPE => 'integer',
+                               ApiBase::PARAM_MIN => 0,
+                               ApiBase::PARAM_DFLT => 0,
+                       ),
                );
        }
 
@@ -289,6 +338,8 @@
                        'noimages' => 'Return HTML without images',
                        'noheadings' => "Don't include headings in output",
                        'notransform' => "Don't transform HTML into 
mobile-specific version",
+                       'offset' => 'Pretend all text result is one string, and 
return the substring starting at this point',
+                       'maxlen' => 'Pretend all text result is one string, and 
limit result to this length',
                );
        }
 

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib71800c1afa057bf87fd652ecb650bc38e33df68
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Yurik <yu...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to