Added docu headers to content(handler) files
[lhc/web/wiklou.git] / includes / content / ContentHandler.php
index 6d57e71..84800e3 100644 (file)
@@ -24,10 +24,39 @@ class MWContentSerializationException extends MWException {
  * type), but wikitext content may be represented by a DOM or AST structure in
  * the future.
  *
- * @since 1.WD
+ * 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 ContentHandler {
 
+       /**
+        * Switch for enabling deprecation warnings. Used by ContentHandler::deprecated()
+        * and ContentHandler::runLegacyHooks().
+        *
+        * Once the ContentHandler code has settled in a bit, this should be set to true to
+        * make extensions etc. show warnings when using deprecated functions and hooks.
+        */
+       protected static $enableDeprecationWarnings = false;
+
        /**
         * Convenience function for getting flat text from a Content object. This
         * should only be used in the context of backwards compatibility with code
@@ -49,8 +78,7 @@ abstract class ContentHandler {
         *   TextContent object, this method returns null.
         * - otherwise, the behaviour is undefined.
         *
-        * @since WD.1
-        * @deprecated since WD.1. Always try to use the content object.
+        * @since 1.21
         *
         * @static
         * @param $content Content|null
@@ -91,7 +119,7 @@ abstract class ContentHandler {
         * by $modelId (or, if that is not given, $title->getContentModel()) using
         * the given format.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @static
         *
@@ -152,7 +180,7 @@ abstract class ContentHandler {
         *
         * Note: this is used by, and may thus not use, Title::getContentModel()
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @static
         * @param $title Title
@@ -224,7 +252,7 @@ abstract class ContentHandler {
        /**
         * Returns the appropriate ContentHandler singleton for the given title.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @static
         * @param $title Title
@@ -239,7 +267,7 @@ abstract class ContentHandler {
         * Returns the appropriate ContentHandler singleton for the given Content
         * object.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @static
         * @param $content Content
@@ -272,7 +300,7 @@ abstract class ContentHandler {
         * ContentHandler may be provided by the ContentHandlerForModelID hook.
         * If no ContentHandler can be determined, an MWException is raised.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @static
         * @param $modelId String The ID of the content model for which to get a
@@ -294,7 +322,7 @@ abstract class ContentHandler {
                        wfRunHooks( 'ContentHandlerForModelID', array( $modelId, &$handler ) );
 
                        if ( $handler === null ) {
-                               throw new MWException( "No handler for model #$modelId registered in \$wgContentHandlers" );
+                               throw new MWException( "No handler for model '$modelId'' registered in \$wgContentHandlers" );
                        }
 
                        if ( !( $handler instanceof ContentHandler ) ) {
@@ -380,7 +408,7 @@ abstract class ContentHandler {
        /**
         * Serializes a Content object of the type supported by this ContentHandler.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @abstract
         * @param $content Content The Content object to serialize
@@ -392,7 +420,7 @@ abstract class ContentHandler {
        /**
         * Unserializes a Content object of the type supported by this ContentHandler.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @abstract
         * @param $blob string serialized form of the content
@@ -405,17 +433,34 @@ abstract class ContentHandler {
         * Creates an empty Content object of the type supported by this
         * ContentHandler.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @return Content
         */
        public abstract function makeEmptyContent();
 
+       /**
+        * Creates a new Content object that acts as a redirect to the given page,
+        * or null of redirects are not supported by this content model.
+        *
+        * This default implementation always returns null. Subclasses supporting redirects
+        * must override this method.
+        *
+        * @since 1.21
+        *
+        * @param Title $destination the page to redirect to.
+        *
+        * @return Content
+        */
+       public function makeRedirectContent( Title $destination ) {
+               return null;
+       }
+
        /**
         * Returns the model id that identifies the content model this
         * ContentHandler can handle. Use with the CONTENT_MODEL_XXX constants.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @return String The model ID
         */
@@ -427,7 +472,7 @@ abstract class ContentHandler {
         * Throws an MWException if $model_id is not the ID of the content model
         * supported by this ContentHandler.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @param String $model_id The model to check
         *
@@ -446,7 +491,7 @@ abstract class ContentHandler {
         * serializeContent() and unserializeContent() methods of this
         * ContentHandler.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @return array of serialization formats as MIME type like strings
         */
@@ -461,7 +506,7 @@ abstract class ContentHandler {
         * This default implementation will return the first element of the array
         * of formats that was passed to the constructor.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @return string the name of the default serialization format as a MIME type
         */
@@ -476,7 +521,7 @@ abstract class ContentHandler {
         * Note that if $format is null, this method always returns true, because
         * null means "use the default format".
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @param $format string the serialization format to check
         * @return bool
@@ -514,7 +559,7 @@ abstract class ContentHandler {
         * (and only when) $wgActions[$action] === true. This allows subclasses
         * to override the default action handlers.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @return Array
         */
@@ -525,7 +570,7 @@ abstract class ContentHandler {
        /**
         * Factory for creating an appropriate DifferenceEngine for this content model.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @param $context IContextSource context to use, anything else will be
         *    ignored
@@ -559,7 +604,7 @@ abstract class ContentHandler {
         * Also note that the page language may or may not depend on the actual content of the page,
         * that is, this method may load the content in order to determine the language.
         *
-        * @since 1.WD
+        * @since 1.21
         *
         * @param Title        $title the page to determine the language for.
         * @param Content|null $content the page's content, if you have it handy, to avoid reloading it.
@@ -591,7 +636,7 @@ abstract class ContentHandler {
         * Also note that the page language may or may not depend on the actual content of the page,
         * that is, this method may load the content in order to determine the language.
         *
-        * @since 1.WD
+        * @since 1.21
         *
         * @param Title        $title the page to determine the language for.
         * @param Content|null $content the page's content, if you have it handy, to avoid reloading it.
@@ -633,7 +678,7 @@ abstract class ContentHandler {
        /**
         * Returns the name of the diff engine to use.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @return string
         */
@@ -648,7 +693,7 @@ abstract class ContentHandler {
         *
         * This default implementation always returns false.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @param $oldContent Content|string  String
         * @param $myContent Content|string   String
@@ -663,7 +708,7 @@ abstract class ContentHandler {
        /**
         * Return an applicable auto-summary if one exists for the given edit.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @param $oldContent Content|null: the previous text of the page.
         * @param $newContent Content|null: The submitted text of the page.
@@ -737,7 +782,7 @@ abstract class ContentHandler {
        /**
         * Auto-generates a deletion reason
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @param $title Title: the page's title
         * @param &$hasHistory Boolean: whether the page has a history
@@ -844,7 +889,7 @@ abstract class ContentHandler {
         * between $undo and $undoafter. Revisions must belong to the same page,
         * must exist and must not be deleted.
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @param $current Revision The current text
         * @param $undo Revision The revision to undo
@@ -913,14 +958,14 @@ abstract class ContentHandler {
 
        /**
         * Returns true for content models that support caching using the
-        * ParserCache mechanism. See WikiPage::isParserCacheUser().
+        * ParserCache mechanism. See WikiPage::isParserCacheUsed().
         *
-        * @since WD.1
+        * @since 1.21
         *
         * @return bool
         */
        public function isParserCacheSupported() {
-               return true;
+               return false;
        }
 
        /**
@@ -934,6 +979,25 @@ abstract class ContentHandler {
                return false;
        }
 
+       /**
+        * Logs a deprecation warning, visible if $wgDevelopmentWarnings, but only if
+        * self::$enableDeprecationWarnings is set to true.
+        *
+        * @param String      $func The name of the deprecated function
+        * @param string      $version The version since the method is deprecated. Usually 1.21
+        *                    for ContentHandler related stuff.
+        * @param String|bool $component: Component to which the function belongs.
+        *                                If false, it is assumed the function is in MediaWiki core.
+        *
+        * @see ContentHandler::$enableDeprecationWarnings
+        * @see wfDeprecated
+        */
+       public static function deprecated( $func, $version, $component = false ) {
+               if ( self::$enableDeprecationWarnings ) {
+                       wfDeprecated( $func, $version, $component, 3 );
+               }
+       }
+
        /**
         * Call a legacy hook that uses text instead of Content objects.
         * Will log a warning when a matching hook function is registered.
@@ -943,18 +1007,60 @@ abstract class ContentHandler {
         *
         * @param $event String: event name
         * @param $args Array: parameters passed to hook functions
-        * @param $warn bool: whether to log a warning (default: true). Should generally be true,
-        *                    may be set to false for testing.
+        * @param $warn bool: whether to log a warning.
+        *                    Default to self::$enableDeprecationWarnings.
+        *                    May be set to false for testing.
         *
         * @return Boolean True if no handler aborted the hook
+        *
+        * @see ContentHandler::$enableDeprecationWarnings
         */
-       public static function runLegacyHooks( $event, $args = array(), $warn = true ) {
+       public static function runLegacyHooks( $event, $args = array(),
+                       $warn = null ) {
+
+               if ( $warn === null ) {
+                       $warn = self::$enableDeprecationWarnings;
+               }
+
                if ( !Hooks::isRegistered( $event ) ) {
                        return true; // nothing to do here
                }
 
                if ( $warn ) {
-                       wfWarn( "Using obsolete hook $event" );
+                       // Log information about which handlers are registered for the legacy hook,
+                       // so we can find and fix them.
+
+                       $handlers = Hooks::getHandlers( $event );
+                       $handlerInfo = array();
+
+                       wfSuppressWarnings();
+
+                       foreach ( $handlers as $handler ) {
+                               $info = '';
+
+                               if ( is_array( $handler ) ) {
+                                       if ( is_object( $handler[0] ) ) {
+                                               $info = get_class( $handler[0] );
+                                       } else {
+                                               $info = $handler[0];
+                                       }
+
+                                       if ( isset( $handler[1] ) ) {
+                                               $info .= '::' . $handler[1];
+                                       }
+                               } else if ( is_object( $handler ) ) {
+                                       $info = get_class( $handler[0] );
+                                       $info .= '::on' . $event;
+                               } else {
+                                       $info = $handler;
+                               }
+
+                               $handlerInfo[] = $info;
+                       }
+
+                       wfRestoreWarnings();
+
+                       wfWarn( "Using obsolete hook $event via ContentHandler::runLegacyHooks()! Handlers: " . implode(', ', $handlerInfo), 2 );
                }
 
                // convert Content objects to text
@@ -996,11 +1102,11 @@ abstract class ContentHandler {
 }
 
 /**
- * @since WD.1
+ * @since 1.21
  */
-abstract class TextContentHandler extends ContentHandler {
+class TextContentHandler extends ContentHandler {
 
-       public function __construct( $modelId, $formats ) {
+       public function __construct( $modelId = CONTENT_MODEL_TEXT, $formats = array( CONTENT_FORMAT_TEXT ) ) {
                parent::__construct( $modelId, $formats );
        }
 
@@ -1056,10 +1162,36 @@ abstract class TextContentHandler extends ContentHandler {
                return $mergedContent;
        }
 
+       /**
+        * Unserializes a Content object of the type supported by this ContentHandler.
+        *
+        * @since 1.21
+        *
+        * @param $text   string serialized form of the content
+        * @param $format null|String the format used for serialization
+        *
+        * @return Content the TextContent object wrapping $text
+        */
+       public function unserializeContent( $text, $format = null ) {
+               $this->checkFormat( $format );
+
+               return new TextContent( $text );
+       }
+
+       /**
+        * Creates an empty TextContent object.
+        *
+        * @since 1.21
+        *
+        * @return Content
+        */
+       public function makeEmptyContent() {
+               return new TextContent( '' );
+       }
 }
 
 /**
- * @since WD.1
+ * @since 1.21
  */
 class WikitextContentHandler extends TextContentHandler {
 
@@ -1073,10 +1205,32 @@ class WikitextContentHandler extends TextContentHandler {
                return new WikitextContent( $text );
        }
 
+       /**
+        * @see ContentHandler::makeEmptyContent
+        *
+        * @return Content
+        */
        public function makeEmptyContent() {
                return new WikitextContent( '' );
        }
 
+
+       /**
+        * Returns a WikitextContent object representing a redirect to the given destination page.
+        *
+        * @see ContentHandler::makeRedirectContent
+        *
+        * @param Title $destination the page to redirect to.
+        *
+        * @return Content
+        */
+       public function makeRedirectContent( Title $destination ) {
+               $mwRedir = MagicWord::get( 'redirect' );
+               $redirectText = $mwRedir->getSynonym( 0 ) . ' [[' . $destination->getPrefixedText() . "]]\n";
+
+               return new WikitextContent( $redirectText );
+       }
+
        /**
         * Returns true because wikitext supports sections.
         *
@@ -1085,12 +1239,23 @@ class WikitextContentHandler extends TextContentHandler {
        public function supportsSections() {
                return true;
        }
+
+       /**
+        * Returns true, because wikitext supports caching using the
+        * ParserCache mechanism.
+        *
+        * @since 1.21
+        * @return bool
+        */
+       public function isParserCacheSupported() {
+               return true;
+       }
 }
 
 # XXX: make ScriptContentHandler base class, do highlighting stuff there?
 
 /**
- * @since WD.1
+ * @since 1.21
  */
 class JavaScriptContentHandler extends TextContentHandler {
 
@@ -1132,7 +1297,7 @@ class JavaScriptContentHandler extends TextContentHandler {
 }
 
 /**
- * @since WD.1
+ * @since 1.21
  */
 class CssContentHandler extends TextContentHandler {