MediaWiki  master
WikitextContent.php
Go to the documentation of this file.
1 <?php
30 
38  private $redirectTargetAndText = null;
39 
43  private $preSaveTransformFlags = [];
44 
50  public function __construct( $text ) {
51  parent::__construct( $text, CONTENT_MODEL_WIKITEXT );
52  }
53 
61  public function getSection( $sectionId ) {
62  $text = $this->getText();
63  $sect = MediaWikiServices::getInstance()->getParserFactory()->getInstance()
64  ->getSection( $text, $sectionId, false );
65 
66  if ( $sect === false ) {
67  return false;
68  } else {
69  return new static( $sect );
70  }
71  }
72 
83  public function replaceSection( $sectionId, Content $with, $sectionTitle = '' ) {
84  // @phan-suppress-previous-line PhanParamSignatureMismatch False positive
85  $myModelId = $this->getModel();
86  $sectionModelId = $with->getModel();
87 
88  if ( $sectionModelId != $myModelId ) {
89  throw new MWException( "Incompatible content model for section: " .
90  "document uses $myModelId but " .
91  "section uses $sectionModelId." );
92  }
94  '@phan-var self $with';
95 
96  $oldtext = $this->getText();
97  $text = $with->getText();
98 
99  if ( strval( $sectionId ) === '' ) {
100  return $with; # XXX: copy first?
101  }
102 
103  if ( $sectionId === 'new' ) {
104  # Inserting a new section
105  $subject = strval( $sectionTitle ) !== '' ? wfMessage( 'newsectionheaderdefaultlevel' )
106  ->plaintextParams( $sectionTitle )->inContentLanguage()->text() . "\n\n" : '';
107  if ( Hooks::runner()->onPlaceNewSection( $this, $oldtext, $subject, $text ) ) {
108  $text = strlen( trim( $oldtext ) ) > 0
109  ? "{$oldtext}\n\n{$subject}{$text}"
110  : "{$subject}{$text}";
111  }
112  } else {
113  # Replacing an existing section; roll out the big guns
114  $text = MediaWikiServices::getInstance()->getParserFactory()->getInstance()
115  ->replaceSection( $oldtext, $sectionId, $text );
116  }
117 
118  $newContent = new static( $text );
119 
120  return $newContent;
121  }
122 
131  public function addSectionHeader( $header ) {
132  $text = strval( $header ) !== '' ? wfMessage( 'newsectionheaderdefaultlevel' )
133  ->plaintextParams( $header )->inContentLanguage()->text() . "\n\n" : '';
134  $text .= $this->getText();
135 
136  return new static( $text );
137  }
138 
148  public function getRedirectTargetAndText() {
149  if ( $this->redirectTargetAndText !== null ) {
150  return $this->redirectTargetAndText;
151  }
152 
153  $redir = MediaWikiServices::getInstance()->getMagicWordFactory()->get( 'redirect' );
154  $text = ltrim( $this->getText() );
155  if ( $redir->matchStartAndRemove( $text ) ) {
156  // Extract the first link and see if it's usable
157  // Ensure that it really does come directly after #REDIRECT
158  // Some older redirects included a colon, so don't freak about that!
159  $m = [];
160  if ( preg_match( '!^\s*:?\s*\[{2}(.*?)(?:\|.*?)?\]{2}\s*!', $text, $m ) ) {
161  // Strip preceding colon used to "escape" categories, etc.
162  // and URL-decode links
163  if ( strpos( $m[1], '%' ) !== false ) {
164  // Match behavior of inline link parsing here;
165  $m[1] = rawurldecode( ltrim( $m[1], ':' ) );
166  }
167  $title = Title::newFromText( $m[1] );
168  // If the title is a redirect to bad special pages or is invalid, return null
169  if ( !$title instanceof Title || !$title->isValidRedirectTarget() ) {
170  $this->redirectTargetAndText = [ null, $this->getText() ];
171  return $this->redirectTargetAndText;
172  }
173 
174  $this->redirectTargetAndText = [ $title, substr( $text, strlen( $m[0] ) ) ];
175  return $this->redirectTargetAndText;
176  }
177  }
178 
179  $this->redirectTargetAndText = [ null, $this->getText() ];
180  return $this->redirectTargetAndText;
181  }
182 
190  public function getRedirectTarget() {
191  list( $title, ) = $this->getRedirectTargetAndText();
192 
193  return $title;
194  }
195 
208  public function updateRedirect( Title $target ) {
209  if ( !$this->isRedirect() ) {
210  return $this;
211  }
212 
213  # Fix the text
214  # Remember that redirect pages can have categories, templates, etc.,
215  # so the regex has to be fairly general
216  $newText = preg_replace( '/ \[ \[ [^\]]* \] \] /x',
217  '[[' . $target->getFullText() . ']]',
218  $this->getText(), 1 );
219 
220  return new static( $newText );
221  }
222 
234  public function isCountable( $hasLinks = null, Title $title = null ) {
235  $articleCountMethod = MediaWikiServices::getInstance()->getMainConfig()
236  ->get( MainConfigNames::ArticleCountMethod );
237 
238  if ( $this->isRedirect() ) {
239  return false;
240  }
241 
242  if ( $articleCountMethod === 'link' ) {
243  if ( $hasLinks === null ) { # not known, find out
244  // @TODO: require an injected title
245  if ( !$title ) {
246  $context = RequestContext::getMain();
247  $title = $context->getTitle();
248  }
249  $contentRenderer = MediaWikiServices::getInstance()->getContentRenderer();
250  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable getTitle does not return null here
251  $po = $contentRenderer->getParserOutput( $this, $title, null, null, false );
252  $links = $po->getLinks();
253  $hasLinks = !empty( $links );
254  }
255 
256  return $hasLinks;
257  }
258 
259  return true;
260  }
261 
266  public function getTextForSummary( $maxlength = 250 ) {
267  $truncatedtext = parent::getTextForSummary( $maxlength );
268 
269  # clean up unfinished links
270  # XXX: make this optional? wasn't there in autosummary, but required for
271  # deletion summary.
272  $truncatedtext = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $truncatedtext );
273 
274  return $truncatedtext;
275  }
276 
286  public function matchMagicWord( MagicWord $word ) {
287  return $word->match( $this->getText() );
288  }
289 
295  public function setPreSaveTransformFlags( array $flags ) {
296  $this->preSaveTransformFlags = $flags;
297  }
298 
304  public function getPreSaveTransformFlags() {
305  return $this->preSaveTransformFlags;
306  }
307 }
const CONTENT_MODEL_WIKITEXT
Definition: Defines.php:211
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
static runner()
Get a HookRunner instance for calling hooks using the new interfaces.
Definition: Hooks.php:173
MediaWiki exception.
Definition: MWException.php:29
This class encapsulates "magic words" such as "#redirect", NOTOC, etc.
Definition: MagicWord.php:60
match( $text)
Returns true if the text contains the word.
Definition: MagicWord.php:246
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
static getMain()
Get the RequestContext object associated with the main request.
Content object implementation for representing flat text.
Definition: TextContent.php:40
getText()
Returns the text represented by this Content object, as a string.
Represents a title within MediaWiki.
Definition: Title.php:49
getFullText()
Get the prefixed title with spaces, plus any fragment (part beginning with '#')
Definition: Title.php:1912
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:370
Content object for wiki text pages.
updateRedirect(Title $target)
This implementation replaces the first link on the page with the given new target if this Content obj...
setPreSaveTransformFlags(array $flags)
Records flags set by preSaveTransform.
getRedirectTarget()
Implement redirect extraction for wikitext.
getTextForSummary( $maxlength=250)
getPreSaveTransformFlags()
Records flags set by preSaveTransform.
getRedirectTargetAndText()
Extract the redirect target and the remaining text on the page.
addSectionHeader( $header)
Returns a new WikitextContent object with the given section heading prepended.
isCountable( $hasLinks=null, Title $title=null)
Returns true if this content is not a redirect, and this content's text is countable according to the...
getSection( $sectionId)
matchMagicWord(MagicWord $word)
This implementation calls $word->match() on the this TextContent object's text.
replaceSection( $sectionId, Content $with, $sectionTitle='')
Base interface for content objects.
Definition: Content.php:35
getModel()
Returns the ID of the content model used by this Content object.
$header