Improve serialization of Message, Title
authorBrad Jorsch <bjorsch@wikimedia.org>
Thu, 2 Jul 2015 16:21:58 +0000 (12:21 -0400)
committerBrad Jorsch <bjorsch@wikimedia.org>
Tue, 7 Jul 2015 19:56:47 +0000 (15:56 -0400)
This allows them to be stored in the session, for example.

Note that properly serializing a Message requires that all its
parameters be serializable as well; we don't attempt to account for that
here.

Change-Id: I3a42a2a883e8eef900eeb02355fc3b064411f642

includes/Message.php
includes/Title.php
includes/api/ApiMessage.php
tests/phpunit/includes/MessageTest.php
tests/phpunit/includes/api/ApiMessageTest.php

index 329d97a..ee41db0 100644 (file)
  *
  * @since 1.17
  */
-class Message implements MessageSpecifier {
+class Message implements MessageSpecifier, Serializable {
 
        /**
         * In which language to get this message. True, which is the default,
@@ -252,6 +252,41 @@ class Message implements MessageSpecifier {
                $this->language = $language ?: $wgLang;
        }
 
+       /**
+        * @see Serializable::serialize()
+        * @since 1.26
+        * @return string
+        */
+       public function serialize() {
+               return serialize( array(
+                       'interface' => $this->interface,
+                       'language' => $this->language->getCode(),
+                       'key' => $this->key,
+                       'keysToTry' => $this->keysToTry,
+                       'parameters' => $this->parameters,
+                       'format' => $this->format,
+                       'useDatabase' => $this->useDatabase,
+                       'title' => $this->title,
+               ) );
+       }
+
+       /**
+        * @see Serializable::unserialize()
+        * @since 1.26
+        * @param string $serialized
+        */
+       public function unserialize( $serialized ) {
+               $data = unserialize( $serialized );
+               $this->interface = $data['interface'];
+               $this->key = $data['key'];
+               $this->keysToTry = $data['keysToTry'];
+               $this->parameters = $data['parameters'];
+               $this->format = $data['format'];
+               $this->useDatabase = $data['useDatabase'];
+               $this->language = Language::factory( $data['language'] );
+               $this->title = $data['title'];
+       }
+
        /**
         * @since 1.24
         *
index 9c8ed47..902d58f 100644 (file)
@@ -4759,4 +4759,26 @@ class Title {
                Hooks::run( 'TitleGetEditNotices', array( $this, $oldid, &$notices ) );
                return $notices;
        }
+
+       /**
+        * @return array
+        */
+       public function __sleep() {
+               return array(
+                       'mNamespace',
+                       'mDbkeyform',
+                       'mFragment',
+                       'mInterwiki',
+                       'mLocalInterwiki',
+                       'mUserCaseDBKey',
+                       'mDefaultNamespace',
+               );
+       }
+
+       public function __wakeup() {
+               $this->mArticleID = ( $this->mNamespace >= 0 ) ? -1 : 0;
+               $this->mUrlform = wfUrlencode( $this->mDbkeyform );
+               $this->mTextform = strtr( $this->mDbkeyform, '_', ' ' );
+       }
+
 }
index 6717c39..db826a6 100644 (file)
@@ -132,6 +132,21 @@ class ApiMessage extends Message implements IApiMessage {
        public function setApiData( array $data ) {
                $this->apiData = $data;
        }
+
+       public function serialize() {
+               return serialize( array(
+                       'parent' => parent::serialize(),
+                       'apiCode' => $this->apiCode,
+                       'apiData' => $this->apiData,
+               ) );
+       }
+
+       public function unserialize( $serialized ) {
+               $data = unserialize( $serialized );
+               parent::unserialize( $data['parent'] );
+               $this->apiCode = $data['apiCode'];
+               $this->apiData = $data['apiData'];
+       }
 }
 
 /**
@@ -188,4 +203,19 @@ class ApiRawMessage extends RawMessage implements IApiMessage {
        public function setApiData( array $data ) {
                $this->apiData = $data;
        }
+
+       public function serialize() {
+               return serialize( array(
+                       'parent' => parent::serialize(),
+                       'apiCode' => $this->apiCode,
+                       'apiData' => $this->apiData,
+               ) );
+       }
+
+       public function unserialize( $serialized ) {
+               $data = unserialize( $serialized );
+               parent::unserialize( $data['parent'] );
+               $this->apiCode = $data['apiCode'];
+               $this->apiData = $data['apiData'];
+       }
 }
index 99ec2e4..cf08dbe 100644 (file)
@@ -548,4 +548,26 @@ class MessageTest extends MediaWikiLangTestCase {
        public function testInLanguageThrows() {
                wfMessage( 'foo' )->inLanguage( 123 );
        }
+
+       /**
+        * @covers Message::serialize
+        * @covers Message::unserialize
+        */
+       public function testSerialization() {
+               $msg = new Message( 'parentheses' );
+               $msg->rawParams( '<a>foo</a>' );
+               $msg->title( Title::newFromText( 'Testing' ) );
+               $this->assertEquals( '(<a>foo</a>)', $msg->parse(), 'Sanity check' );
+               $msg = unserialize( serialize( $msg ) );
+               $this->assertEquals( '(<a>foo</a>)', $msg->parse() );
+               $title = TestingAccessWrapper::newFromObject( $msg )->title;
+               $this->assertInstanceOf( 'Title', $title );
+               $this->assertEquals( 'Testing', $title->getFullText() );
+
+               $msg = new Message( 'mainpage' );
+               $msg->inLanguage( 'de' );
+               $this->assertEquals( 'Hauptseite', $msg->plain(), 'Sanity check' );
+               $msg = unserialize( serialize( $msg ) );
+               $this->assertEquals( 'Hauptseite', $msg->plain() );
+       }
 }
index 6c3ce60..08a984e 100644 (file)
@@ -14,9 +14,13 @@ class ApiMessageTest extends MediaWikiTestCase {
 
                $msg = TestingAccessWrapper::newFromObject( $msg );
                $msg2 = TestingAccessWrapper::newFromObject( $msg2 );
-               foreach ( array( 'interface', 'useDatabase', 'title' ) as $key ) {
-                       $this->assertSame( $msg->$key, $msg2->$key, $key );
-               }
+               $this->assertSame( $msg->interface, $msg2->interface, 'interface' );
+               $this->assertSame( $msg->useDatabase, $msg2->useDatabase, 'useDatabase' );
+               $this->assertSame(
+                       $msg->title ? $msg->title->getFullText() : null,
+                       $msg2->title ? $msg2->title->getFullText() : null,
+                       'title'
+               );
        }
 
        /**
@@ -30,6 +34,11 @@ class ApiMessageTest extends MediaWikiTestCase {
                $this->assertEquals( 'code', $msg2->getApiCode() );
                $this->assertEquals( array( 'data' ), $msg2->getApiData() );
 
+               $msg2 = unserialize( serialize( $msg2 ) );
+               $this->compareMessages( $msg, $msg2 );
+               $this->assertEquals( 'code', $msg2->getApiCode() );
+               $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
                $msg = new Message( array( 'foo', 'bar' ), array( 'baz' ) );
                $msg2 = new ApiMessage( array( array( 'foo', 'bar' ), 'baz' ), 'code', array( 'data' ) );
                $this->compareMessages( $msg, $msg2 );
@@ -63,6 +72,11 @@ class ApiMessageTest extends MediaWikiTestCase {
                $this->assertEquals( 'code', $msg2->getApiCode() );
                $this->assertEquals( array( 'data' ), $msg2->getApiData() );
 
+               $msg2 = unserialize( serialize( $msg2 ) );
+               $this->compareMessages( $msg, $msg2 );
+               $this->assertEquals( 'code', $msg2->getApiCode() );
+               $this->assertEquals( array( 'data' ), $msg2->getApiData() );
+
                $msg = new RawMessage( 'foo', array( 'baz' ) );
                $msg2 = new ApiRawMessage( array( 'foo', 'baz' ), 'code', array( 'data' ) );
                $this->compareMessages( $msg, $msg2 );