*
*/
abstract class Content {
-
- public function __construct( $modelName = null ) {
- $this->mModelName = $modelName;
- }
-
- public function getModelName() {
- return $this->mModelName;
- }
-
- public function getContentHandler() {
- return ContentHandler::getForContent( $this );
- }
- public function serialize( $format = null ) {
- return $this->getContentHandler()->serialize( $this, $format );
- }
+ // TODO: create actual fields and document them
+ /**
+ * @return String a string representing the content in a way useful for building a full text search index.
+ * If no useful representation exists, this method returns an empty string.
+ */
public abstract function getTextForSearchIndex( );
- public abstract function getWikitextForTransclusion( );
+ /**
+ * @return String the wikitext to include when another page includes this content, or false if the content is not
+ * includable in a wikitext page.
+ */
+ #TODO: allow native handling, bypassing wikitext representation, like for includable special pages.
+ public abstract function getWikitextForTransclusion( ); #FIXME: use in parser, etc!
+ /**
+ * Returns a textual representation of the content suitable for use in edit summaries and log messages.
+ *
+ * @param int $maxlength maximum length of the summary text
+ * @return String the summary text
+ */
public abstract function getTextForSummary( $maxlength = 250 );
/**
*/
public abstract function getSize( );
+ /**
+ * TODO: do we really need to pass a $modelName here?
+ * Seems odd and makes lots of stuff hard (ie having a newEmpty static method in TextContent)
+ *
+ * @param $modelName
+ */
+ public function __construct( $modelName = null ) {
+ $this->mModelName = $modelName;
+ }
+
+ public function getModelName() {
+ return $this->mModelName;
+ }
+
+ protected function checkModelName( $modelName ) {
+ if ( $modelName !== $this->mModelName ) {
+ throw new MWException( "Bad content model: expected " . $this->mModelName . " but got found " . $modelName );
+ }
+ }
+
+ public function getContentHandler() {
+ return ContentHandler::getForContent( $this );
+ }
+
+ public function getDefaultFormat() {
+ return $this->getContentHandler()->getDefaultFormat();
+ }
+
+ public function getSupportedFormats() {
+ return $this->getContentHandler()->getSupportedFormats();
+ }
+
+ public function isSupportedFormat( $format ) {
+ if ( !$format ) return true; # this means "use the default"
+
+ return $this->getContentHandler()->isSupportedFormat( $format );
+ }
+
+ protected function checkFormat( $format ) {
+ if ( !$this->isSupportedFormat( $format ) ) {
+ throw new MWException( "Format $format is not supported for content model " . $this->getModelName() );
+ }
+ }
+
+ public function serialize( $format = null ) {
+ return $this->getContentHandler()->serialize( $this, $format );
+ }
+
public function isEmpty() {
return $this->getSize() == 0;
}
*/
public abstract function isCountable( $hasLinks = null ) ;
+ /**
+ * @param null|Title $title
+ * @param null $revId
+ * @param null|ParserOptions $options
+ * @return ParserOutput
+ */
public abstract function getParserOutput( Title $title = null, $revId = null, ParserOptions $options = NULL );
- public function getRedirectChain() { #TODO: document!
+ /**
+ * Construct the redirect destination from this content and return an
+ * array of Titles, or null if this content doesn't represent a redirect.
+ * The last element in the array is the final destination after all redirects
+ * have been resolved (up to $wgMaxRedirects times).
+ *
+ * @return Array of Titles, with the destination last
+ */
+ public function getRedirectChain() {
return null;
}
+ /**
+ * Construct the redirect destination from this content and return an
+ * array of Titles, or null if this content doesn't represent a redirect.
+ * This will only return the immediate redirect target, useful for
+ * the redirect table and other checks that don't need full recursion.
+ *
+ * @return Title: The corresponding Title
+ */
public function getRedirectTarget() {
return null;
}
+ /**
+ * Construct the redirect destination from this content and return the
+ * Title, or null if this content doesn't represent a redirect.
+ * This will recurse down $wgMaxRedirects times or until a non-redirect target is hit
+ * in order to provide (hopefully) the Title of the final destination instead of another redirect.
+ *
+ * @return Title
+ */
+ public function getUltimateRedirectTarget() {
+ return null;
+ }
+
public function isRedirect() {
return $this->getRedirectTarget() != null;
}
return $this;
}
- #TODO: implement specialized ParserOutput for Wikidata model
- #TODO: provide "combined" ParserOutput for Multipart... somehow.
+ /**
+ * Returns a new WikitextContent object with the given section heading prepended, if supported.
+ * The default implementation just returns this Content object unmodified, ignoring the section header.
+ *
+ * @param $header String
+ * @return Content
+ */
+ public function addSectionHeader( $header ) {
+ return $this;
+ }
- # XXX: isCacheable( ) # can/should we do this here?
+ /**
+ * Returns a Content object with preload transformations applied (or this object if no transformations apply).
+ *
+ * @param Title $title
+ * @param null|ParserOptions $popts
+ * @return Content
+ */
+ public function preloadTransform( Title $title, ParserOptions $popts = null ) {
+ return $this;
+ }
- # TODO: EditPage::getPreloadedText( $preload ) // $wgParser->getPreloadText
- # TODO: tie into EditPage, make it use Content-objects throughout, make edit form aware of content model and format
- # TODO: tie into WikiPage, make it use Content-objects throughout, especially in doEditUpdates(), doDelete(), updateRevisionOn(), etc
- # TODO: make model-aware diff view!
+ # TODO: minimize special cases for CSS/JS; how to handle extra message for JS/CSS previews??
# TODO: handle ImagePage and CategoryPage
+ # TODO: hook into dump generation to serialize and record model and format!
+
+ # TODO: make sure we cover lucene search / wikisearch.
+ # TODO: make sure ReplaceTemplates still works
+ # TODO: nice&sane integration of GeSHi syntax highlighting
+ # [11:59] <vvv> Hooks are ugly; make CodeHighlighter interface and a config to set the class which handles syntax highlighting
+ # [12:00] <vvv> And default it to a DummyHighlighter
- # TODO: Title::newFromRedirectRecurse( $this->getRawText() );
+ # TODO: make sure we cover the external editor interface (does anyone actually use that?!)
# TODO: tie into API to provide contentModel for Revisions
# TODO: tie into API to provide serialized version and contentFormat for Revisions
# TODO: tie into API edit interface
+ # TODO: make EditForm plugin for EditPage
+ # XXX: isCacheable( ) # can/should we do this here?
}
/**
* Content object implementation for representing flat text. The
*/
abstract class TextContent extends Content {
+
public function __construct( $text, $modelName = null ) {
- parent::__construct($modelName);
+ parent::__construct( $modelName );
$this->mText = $text;
}
}
class WikitextContent extends TextContent {
+
public function __construct( $text ) {
parent::__construct($text, CONTENT_MODEL_WIKITEXT);
* @return string Complete article text, or null if error
*/
public function replaceSection( $section, Content $with, $sectionTitle = '' ) {
- global $wgParser;
-
wfProfileIn( __METHOD__ );
$myModelName = $this->getModelName();
return $newContent;
}
+ /**
+ * Returns a new WikitextContent object with the given section heading prepended.
+ *
+ * @param $header String
+ * @return Content
+ */
+ public function addSectionHeader( $header ) {
+ $text = wfMsgForContent( 'newsectionheaderdefaultlevel', $this->sectiontitle ) . "\n\n" . $this->getNativeData();
+
+ return new WikitextContent( $text );
+ }
+
/**
* Returns a Content object with pre-save transformations applied (or this object if no transformations apply).
*
public function preSaveTransform( Title $title, User $user, ParserOptions $popts = null ) {
global $wgParser;
+ if ( $popts == null ) $popts = $this->getDefaultParserOptions();
+
$text = $this->getNativeData();
$pst = $wgParser->preSaveTransform( $text, $title, $user, $popts );
return new WikitextContent( $pst );
}
+ /**
+ * Returns a Content object with preload transformations applied (or this object if no transformations apply).
+ *
+ * @param Title $title
+ * @param null|ParserOptions $popts
+ * @return Content
+ */
+ public function preloadTransform( Title $title, ParserOptions $popts = null ) {
+ global $wgParser;
+
+ if ( $popts == null ) $popts = $this->getDefaultParserOptions();
+
+ $text = $this->getNativeData();
+ $plt = $wgParser->getPreloadText( $text, $title, $popts );
+
+ return new WikitextContent( $plt );
+ }
+
public function getRedirectChain() {
$text = $this->getNativeData();
return Title::newFromRedirectArray( $text );
return Title::newFromRedirect( $text );
}
+ public function getUltimateRedirectTarget() {
+ $text = $this->getNativeData();
+ return Title::newFromRedirectRecurse( $text );
+ }
+
/**
* Returns true if this content is not a redirect, and this content's text is countable according to
* the criteria defiend by $wgArticleCountMethod.
class MessageContent extends TextContent {
public function __construct( $msg_key, $params = null, $options = null ) {
- parent::__construct(null, CONTENT_MODEL_WIKITEXT);
+ parent::__construct(null, CONTENT_MODEL_WIKITEXT); #XXX: messages may be wikitext, html or plain text! and maybe even something else entirely.
$this->mMessageKey = $msg_key;