* 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
* 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
* by $modelId (or, if that is not given, $title->getContentModel()) using
* the given format.
*
- * @since WD.1
+ * @since 1.21
*
* @static
*
*
* Note: this is used by, and may thus not use, Title::getContentModel()
*
- * @since WD.1
+ * @since 1.21
*
* @static
* @param $title Title
/**
* Returns the appropriate ContentHandler singleton for the given title.
*
- * @since WD.1
+ * @since 1.21
*
* @static
* @param $title Title
* Returns the appropriate ContentHandler singleton for the given Content
* object.
*
- * @since WD.1
+ * @since 1.21
*
* @static
* @param $content Content
* 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
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 ) ) {
public static function getLocalizedName( $name ) {
$key = "content-model-$name";
- if ( wfEmptyMsg( $key ) ) return $name;
- else return wfMsg( $key );
+ $msg = wfMessage( $key );
+
+ return $msg->exists() ? $msg->plain() : $name;
}
public static function getContentModels() {
/**
* 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
/**
* 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
* 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
*/
* 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
*
* serializeContent() and unserializeContent() methods of this
* ContentHandler.
*
- * @since WD.1
+ * @since 1.21
*
* @return array of serialization formats as MIME type like strings
*/
* 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
*/
* 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
* (and only when) $wgActions[$action] === true. This allows subclasses
* to override the default action handlers.
*
- * @since WD.1
+ * @since 1.21
*
* @return Array
*/
/**
* 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
* 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.
* 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.
/**
* Returns the name of the diff engine to use.
*
- * @since WD.1
+ * @since 1.21
*
* @return string
*/
*
* This default implementation always returns false.
*
- * @since WD.1
+ * @since 1.21
*
* @param $oldContent Content|string String
* @param $myContent Content|string String
/**
* 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.
/**
* 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
* 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
/**
* 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;
}
/**
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.
*
* @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
}
/**
- * @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 );
}
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 {
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.
*
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 {
}
/**
- * @since WD.1
+ * @since 1.21
*/
class CssContentHandler extends TextContentHandler {