Merge "Make sure that SQLite uses no prefix"
[lhc/web/wiklou.git] / includes / content / TextContent.php
index e98584f..872738b 100644 (file)
@@ -5,13 +5,40 @@
  *
  * TextContent instances are immutable
  *
+ * 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
+ *
  * @since 1.21
+ *
+ * @file
+ * @ingroup Content
+ *
+ * @author Daniel Kinzler
  */
-abstract class TextContent extends AbstractContent {
+class TextContent extends AbstractContent {
 
-       public function __construct( $text, $model_id = null ) {
+       public function __construct( $text, $model_id = CONTENT_MODEL_TEXT ) {
                parent::__construct( $model_id );
 
+               if ( $text === null || $text === false ) {
+                       wfWarn( "TextContent constructed with \$text = " . var_export( $text, true ) . "! "
+                                       . "This may indicate an error in the caller's scope." );
+
+                       $text = '';
+               }
+
                if ( !is_string( $text ) ) {
                        throw new MWException( "TextContent expects a string in the constructor." );
                }
@@ -71,7 +98,7 @@ abstract class TextContent extends AbstractContent {
        /**
         * Returns the text represented by this Content object, as a string.
         *
-        * @param   the raw text
+        * @return string: the raw text
         */
        public function getNativeData( ) {
                $text = $this->mText;
@@ -81,31 +108,57 @@ abstract class TextContent extends AbstractContent {
        /**
         * Returns the text represented by this Content object, as a string.
         *
-        * @param   the raw text
+        * @return string: the raw text
         */
        public function getTextForSearchIndex( ) {
                return $this->getNativeData();
        }
 
        /**
-        * Returns the text represented by this Content object, as a string.
+        * Returns attempts to convert this content object to wikitext,
+        * and then returns the text string. The conversion may be lossy.
+        *
+        * @note: this allows any text-based content to be transcluded as if it was wikitext.
         *
-        * @param   the raw text
+        * @return string|false: the raw text, or null if the conversion failed
         */
        public function getWikitextForTransclusion( ) {
-               return $this->getNativeData();
+               $wikitext = $this->convert( CONTENT_MODEL_WIKITEXT, 'lossy' );
+
+               if ( $wikitext ) {
+                       return $wikitext->getNativeData();
+               } else {
+                       return false;
+               }
+       }
+
+       /**
+        * Returns a Content object with pre-save transformations applied.
+        * This implementation just trims trailing whitespace.
+        *
+        * @param $title Title
+        * @param $user User
+        * @param $popts ParserOptions
+        * @return Content
+        */
+       public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
+               $text = $this->getNativeData();
+               $pst = rtrim( $text );
+
+               return ( $text === $pst ) ? $this : new WikitextContent( $pst );
        }
 
        /**
-        * Diff this content object with another content object..
+        * Diff this content object with another content object.
         *
         * @since 1.21diff
         *
-        * @param $that Content the other content object to compare this content object to
-        * @param $lang Language the language object to use for text segmentation.
+        * @param $that Content: The other content object to compare this content
+        * object to.
+        * @param $lang Language: The language object to use for text segmentation.
         *    If not given, $wgContentLang is used.
         *
-        * @return DiffResult a diff representing the changes that would have to be
+        * @return DiffResult: A diff representing the changes that would have to be
         *    made to this content object to make it equal to $that.
         */
        public function diff( Content $that, Language $lang = null ) {
@@ -144,7 +197,19 @@ abstract class TextContent extends AbstractContent {
                $revId = null,
                ParserOptions $options = null, $generateHtml = true
        ) {
-               # Generic implementation, relying on $this->getHtml()
+               global $wgParser, $wgTextModelsToParse;
+
+               if ( !$options ) {
+                       //NOTE: use canonical options per default to produce cacheable output
+                       $options = $this->getContentHandler()->makeParserOptions( 'canonical' );
+               }
+
+               if ( in_array( $this->getModel(), $wgTextModelsToParse ) ) {
+                       // parse just to get links etc into the database
+                       $po = $wgParser->parse( $this->getNativeData(), $title, $options, true, true, $revId );
+               } else {
+                       $po = new ParserOutput();
+               }
 
                if ( $generateHtml ) {
                        $html = $this->getHtml();
@@ -152,7 +217,7 @@ abstract class TextContent extends AbstractContent {
                        $html = '';
                }
 
-               $po = new ParserOutput( $html );
+               $po->setText( $html );
                return $po;
        }
 
@@ -181,4 +246,35 @@ abstract class TextContent extends AbstractContent {
                # TODO: make Highlighter interface, use highlighter here, if available
                return htmlspecialchars( $this->getNativeData() );
        }
-}
\ No newline at end of file
+
+       /**
+        * @see Content::convert()
+        *
+        * This implementation provides lossless conversion between content models based
+        * on TextContent.
+        *
+        * @param String  $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
+        * @param String  $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
+        * not allowed, full round-trip conversion is expected to work without losing information.
+        *
+        * @return Content|bool A content object with the content model $toModel, or false if
+        * that conversion is not supported.
+        */
+       public function convert( $toModel, $lossy = '' ) {
+               $converted = parent::convert( $toModel, $lossy );
+
+               if ( $converted !== false ) {
+                       return $converted;
+               }
+
+               $toHandler = ContentHandler::getForModelID( $toModel );
+
+               if ( $toHandler instanceof TextContentHandler ) {
+                       //NOTE: ignore content serialization format - it's just text anyway.
+                       $text = $this->getNativeData();
+                       $converted = $toHandler->unserializeContent( $text );
+               }
+
+               return $converted;
+       }
+}