[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/content/ -> WikitextContent.php (source)

   1  <?php
   2  /**
   3   * Content object for wiki text pages.
   4   *
   5   * This program is free software; you can redistribute it and/or modify
   6   * it under the terms of the GNU General Public License as published by
   7   * the Free Software Foundation; either version 2 of the License, or
   8   * (at your option) any later version.
   9   *
  10   * This program is distributed in the hope that it will be useful,
  11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13   * GNU General Public License for more details.
  14   *
  15   * You should have received a copy of the GNU General Public License along
  16   * with this program; if not, write to the Free Software Foundation, Inc.,
  17   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18   * http://www.gnu.org/copyleft/gpl.html
  19   *
  20   * @since 1.21
  21   *
  22   * @file
  23   * @ingroup Content
  24   *
  25   * @author Daniel Kinzler
  26   */
  27  
  28  /**
  29   * Content object for wiki text pages.
  30   *
  31   * @ingroup Content
  32   */
  33  class WikitextContent extends TextContent {
  34      private $redirectTargetAndText = null;
  35  
  36  	public function __construct( $text ) {
  37          parent::__construct( $text, CONTENT_MODEL_WIKITEXT );
  38      }
  39  
  40      /**
  41       * @param string|number $sectionId
  42       *
  43       * @return Content|bool|null
  44       *
  45       * @see Content::getSection()
  46       */
  47  	public function getSection( $sectionId ) {
  48          global $wgParser;
  49  
  50          $text = $this->getNativeData();
  51          $sect = $wgParser->getSection( $text, $sectionId, false );
  52  
  53          if ( $sect === false ) {
  54              return false;
  55          } else {
  56              return new static( $sect );
  57          }
  58      }
  59  
  60      /**
  61       * @param string|number|null|bool $sectionId
  62       * @param Content $with
  63       * @param string $sectionTitle
  64       *
  65       * @throws MWException
  66       * @return Content
  67       *
  68       * @see Content::replaceSection()
  69       */
  70  	public function replaceSection( $sectionId, Content $with, $sectionTitle = '' ) {
  71          wfProfileIn( __METHOD__ );
  72  
  73          $myModelId = $this->getModel();
  74          $sectionModelId = $with->getModel();
  75  
  76          if ( $sectionModelId != $myModelId ) {
  77              wfProfileOut( __METHOD__ );
  78              throw new MWException( "Incompatible content model for section: " .
  79                  "document uses $myModelId but " .
  80                  "section uses $sectionModelId." );
  81          }
  82  
  83          $oldtext = $this->getNativeData();
  84          $text = $with->getNativeData();
  85  
  86          if ( strval( $sectionId ) === '' ) {
  87              wfProfileOut( __METHOD__ );
  88  
  89              return $with; # XXX: copy first?
  90          }
  91  
  92          if ( $sectionId === 'new' ) {
  93              # Inserting a new section
  94              $subject = $sectionTitle ? wfMessage( 'newsectionheaderdefaultlevel' )
  95                      ->rawParams( $sectionTitle )->inContentLanguage()->text() . "\n\n" : '';
  96              if ( wfRunHooks( 'PlaceNewSection', array( $this, $oldtext, $subject, &$text ) ) ) {
  97                  $text = strlen( trim( $oldtext ) ) > 0
  98                      ? "{$oldtext}\n\n{$subject}{$text}"
  99                      : "{$subject}{$text}";
 100              }
 101          } else {
 102              # Replacing an existing section; roll out the big guns
 103              global $wgParser;
 104  
 105              $text = $wgParser->replaceSection( $oldtext, $sectionId, $text );
 106          }
 107  
 108          $newContent = new static( $text );
 109  
 110          wfProfileOut( __METHOD__ );
 111  
 112          return $newContent;
 113      }
 114  
 115      /**
 116       * Returns a new WikitextContent object with the given section heading
 117       * prepended.
 118       *
 119       * @param string $header
 120       *
 121       * @return Content
 122       */
 123  	public function addSectionHeader( $header ) {
 124          $text = wfMessage( 'newsectionheaderdefaultlevel' )
 125              ->rawParams( $header )->inContentLanguage()->text();
 126          $text .= "\n\n";
 127          $text .= $this->getNativeData();
 128  
 129          return new static( $text );
 130      }
 131  
 132      /**
 133       * Returns a Content object with pre-save transformations applied using
 134       * Parser::preSaveTransform().
 135       *
 136       * @param Title $title
 137       * @param User $user
 138       * @param ParserOptions $popts
 139       *
 140       * @return Content
 141       */
 142  	public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
 143          global $wgParser;
 144  
 145          $text = $this->getNativeData();
 146          $pst = $wgParser->preSaveTransform( $text, $title, $user, $popts );
 147          rtrim( $pst );
 148  
 149          return ( $text === $pst ) ? $this : new static( $pst );
 150      }
 151  
 152      /**
 153       * Returns a Content object with preload transformations applied (or this
 154       * object if no transformations apply).
 155       *
 156       * @param Title $title
 157       * @param ParserOptions $popts
 158       * @param array $params
 159       *
 160       * @return Content
 161       */
 162  	public function preloadTransform( Title $title, ParserOptions $popts, $params = array() ) {
 163          global $wgParser;
 164  
 165          $text = $this->getNativeData();
 166          $plt = $wgParser->getPreloadText( $text, $title, $popts, $params );
 167  
 168          return new static( $plt );
 169      }
 170  
 171      /**
 172       * Extract the redirect target and the remaining text on the page.
 173       *
 174       * @note migrated here from Title::newFromRedirectInternal()
 175       *
 176       * @since 1.23
 177       *
 178       * @return array List of two elements: Title|null and string.
 179       */
 180  	protected function getRedirectTargetAndText() {
 181          global $wgMaxRedirects;
 182  
 183          if ( $this->redirectTargetAndText !== null ) {
 184              return $this->redirectTargetAndText;
 185          }
 186  
 187          if ( $wgMaxRedirects < 1 ) {
 188              // redirects are disabled, so quit early
 189              $this->redirectTargetAndText = array( null, $this->getNativeData() );
 190              return $this->redirectTargetAndText;
 191          }
 192  
 193          $redir = MagicWord::get( 'redirect' );
 194          $text = ltrim( $this->getNativeData() );
 195          if ( $redir->matchStartAndRemove( $text ) ) {
 196              // Extract the first link and see if it's usable
 197              // Ensure that it really does come directly after #REDIRECT
 198              // Some older redirects included a colon, so don't freak about that!
 199              $m = array();
 200              if ( preg_match( '!^\s*:?\s*\[{2}(.*?)(?:\|.*?)?\]{2}\s*!', $text, $m ) ) {
 201                  // Strip preceding colon used to "escape" categories, etc.
 202                  // and URL-decode links
 203                  if ( strpos( $m[1], '%' ) !== false ) {
 204                      // Match behavior of inline link parsing here;
 205                      $m[1] = rawurldecode( ltrim( $m[1], ':' ) );
 206                  }
 207                  $title = Title::newFromText( $m[1] );
 208                  // If the title is a redirect to bad special pages or is invalid, return null
 209                  if ( !$title instanceof Title || !$title->isValidRedirectTarget() ) {
 210                      $this->redirectTargetAndText = array( null, $this->getNativeData() );
 211                      return $this->redirectTargetAndText;
 212                  }
 213  
 214                  $this->redirectTargetAndText = array( $title, substr( $text, strlen( $m[0] ) ) );
 215                  return $this->redirectTargetAndText;
 216              }
 217          }
 218  
 219          $this->redirectTargetAndText = array( null, $this->getNativeData() );
 220          return $this->redirectTargetAndText;
 221      }
 222  
 223      /**
 224       * Implement redirect extraction for wikitext.
 225       *
 226       * @return Title|null
 227       *
 228       * @see Content::getRedirectTarget
 229       */
 230  	public function getRedirectTarget() {
 231          list( $title, ) = $this->getRedirectTargetAndText();
 232  
 233          return $title;
 234      }
 235  
 236      /**
 237       * This implementation replaces the first link on the page with the given new target
 238       * if this Content object is a redirect. Otherwise, this method returns $this.
 239       *
 240       * @since 1.21
 241       *
 242       * @param Title $target
 243       *
 244       * @return Content
 245       *
 246       * @see Content::updateRedirect()
 247       */
 248  	public function updateRedirect( Title $target ) {
 249          if ( !$this->isRedirect() ) {
 250              return $this;
 251          }
 252  
 253          # Fix the text
 254          # Remember that redirect pages can have categories, templates, etc.,
 255          # so the regex has to be fairly general
 256          $newText = preg_replace( '/ \[ \[  [^\]]*  \] \] /x',
 257              '[[' . $target->getFullText() . ']]',
 258              $this->getNativeData(), 1 );
 259  
 260          return new static( $newText );
 261      }
 262  
 263      /**
 264       * Returns true if this content is not a redirect, and this content's text
 265       * is countable according to the criteria defined by $wgArticleCountMethod.
 266       *
 267       * @param bool $hasLinks If it is known whether this content contains
 268       *    links, provide this information here, to avoid redundant parsing to
 269       *    find out (default: null).
 270       * @param Title $title Optional title, defaults to the title from the current main request.
 271       *
 272       * @return bool
 273       */
 274  	public function isCountable( $hasLinks = null, Title $title = null ) {
 275          global $wgArticleCountMethod;
 276  
 277          if ( $this->isRedirect() ) {
 278              return false;
 279          }
 280  
 281          $text = $this->getNativeData();
 282  
 283          switch ( $wgArticleCountMethod ) {
 284              case 'any':
 285                  return true;
 286              case 'comma':
 287                  return strpos( $text, ',' ) !== false;
 288              case 'link':
 289                  if ( $hasLinks === null ) { # not known, find out
 290                      if ( !$title ) {
 291                          $context = RequestContext::getMain();
 292                          $title = $context->getTitle();
 293                      }
 294  
 295                      $po = $this->getParserOutput( $title, null, null, false );
 296                      $links = $po->getLinks();
 297                      $hasLinks = !empty( $links );
 298                  }
 299  
 300                  return $hasLinks;
 301          }
 302  
 303          return false;
 304      }
 305  
 306      /**
 307       * @param int $maxlength
 308       * @return string
 309       */
 310  	public function getTextForSummary( $maxlength = 250 ) {
 311          $truncatedtext = parent::getTextForSummary( $maxlength );
 312  
 313          # clean up unfinished links
 314          # XXX: make this optional? wasn't there in autosummary, but required for
 315          # deletion summary.
 316          $truncatedtext = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $truncatedtext );
 317  
 318          return $truncatedtext;
 319      }
 320  
 321      /**
 322       * Returns a ParserOutput object resulting from parsing the content's text
 323       * using $wgParser.
 324       *
 325       * @param Title $title
 326       * @param int $revId Revision to pass to the parser (default: null)
 327       * @param ParserOptions $options (default: null)
 328       * @param bool $generateHtml (default: true)
 329       * @param ParserOutput &$output ParserOutput representing the HTML form of the text,
 330       *           may be manipulated or replaced.
 331       */
 332  	protected function fillParserOutput( Title $title, $revId,
 333              ParserOptions $options, $generateHtml, ParserOutput &$output
 334      ) {
 335          global $wgParser;
 336  
 337          list( $redir, $text ) = $this->getRedirectTargetAndText();
 338          $output = $wgParser->parse( $text, $title, $options, true, true, $revId );
 339  
 340          // Add redirect indicator at the top
 341          if ( $redir ) {
 342              // Make sure to include the redirect link in pagelinks
 343              $output->addLink( $redir );
 344              if ( $generateHtml ) {
 345                  $chain = $this->getRedirectChain();
 346                  $output->setText(
 347                      Article::getRedirectHeaderHtml( $title->getPageLanguage(), $chain, false ) .
 348                      $output->getText()
 349                  );
 350                  $output->addModuleStyles( 'mediawiki.action.view.redirectPage' );
 351              }
 352          }
 353      }
 354  
 355      /**
 356       * @throws MWException
 357       */
 358  	protected function getHtml() {
 359          throw new MWException(
 360              "getHtml() not implemented for wikitext. "
 361                  . "Use getParserOutput()->getText()."
 362          );
 363      }
 364  
 365      /**
 366       * This implementation calls $word->match() on the this TextContent object's text.
 367       *
 368       * @param MagicWord $word
 369       *
 370       * @return bool
 371       *
 372       * @see Content::matchMagicWord()
 373       */
 374  	public function matchMagicWord( MagicWord $word ) {
 375          return $word->match( $this->getNativeData() );
 376      }
 377  
 378  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1