MediaWiki  master
WikitextContent.php
Go to the documentation of this file.
1 <?php
33 
41  private $redirectTargetAndText = null;
42 
46  private $preSaveTransformFlags = [];
47 
53  public function __construct( $text ) {
54  parent::__construct( $text, CONTENT_MODEL_WIKITEXT );
55  }
56 
64  public function getSection( $sectionId ) {
65  $text = $this->getText();
66  $sect = MediaWikiServices::getInstance()->getParserFactory()->getInstance()
67  ->getSection( $text, $sectionId, false );
68 
69  if ( $sect === false ) {
70  return false;
71  } else {
72  return new static( $sect );
73  }
74  }
75 
86  public function replaceSection( $sectionId, Content $with, $sectionTitle = '' ) {
87  // @phan-suppress-previous-line PhanParamSignatureMismatch False positive
88  $myModelId = $this->getModel();
89  $sectionModelId = $with->getModel();
90 
91  if ( $sectionModelId != $myModelId ) {
92  throw new MWException( "Incompatible content model for section: " .
93  "document uses $myModelId but " .
94  "section uses $sectionModelId." );
95  }
97  '@phan-var self $with';
98 
99  $oldtext = $this->getText();
100  $text = $with->getText();
101 
102  if ( strval( $sectionId ) === '' ) {
103  return $with; # XXX: copy first?
104  }
105 
106  if ( $sectionId === 'new' ) {
107  # Inserting a new section
108  $subject = strval( $sectionTitle ) !== '' ? wfMessage( 'newsectionheaderdefaultlevel' )
109  ->plaintextParams( $sectionTitle )->inContentLanguage()->text() . "\n\n" : '';
110  $hookRunner = ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) );
111  if ( $hookRunner->onPlaceNewSection( $this, $oldtext, $subject, $text ) ) {
112  $text = strlen( trim( $oldtext ) ) > 0
113  ? "{$oldtext}\n\n{$subject}{$text}"
114  : "{$subject}{$text}";
115  }
116  } else {
117  # Replacing an existing section; roll out the big guns
118  $text = MediaWikiServices::getInstance()->getParserFactory()->getInstance()
119  ->replaceSection( $oldtext, $sectionId, $text );
120  }
121 
122  $newContent = new static( $text );
123 
124  return $newContent;
125  }
126 
135  public function addSectionHeader( $header ) {
136  $text = strval( $header ) !== '' ? wfMessage( 'newsectionheaderdefaultlevel' )
137  ->plaintextParams( $header )->inContentLanguage()->text() . "\n\n" : '';
138  $text .= $this->getText();
139 
140  return new static( $text );
141  }
142 
152  public function getRedirectTargetAndText() {
153  if ( $this->redirectTargetAndText !== null ) {
154  return $this->redirectTargetAndText;
155  }
156 
157  $redir = MediaWikiServices::getInstance()->getMagicWordFactory()->get( 'redirect' );
158  $text = ltrim( $this->getText() );
159  if ( $redir->matchStartAndRemove( $text ) ) {
160  // Extract the first link and see if it's usable
161  // Ensure that it really does come directly after #REDIRECT
162  // Some older redirects included a colon, so don't freak about that!
163  $m = [];
164  if ( preg_match( '!^\s*:?\s*\[{2}(.*?)(?:\|.*?)?\]{2}\s*!', $text, $m ) ) {
165  // Strip preceding colon used to "escape" categories, etc.
166  // and URL-decode links
167  if ( strpos( $m[1], '%' ) !== false ) {
168  // Match behavior of inline link parsing here;
169  $m[1] = rawurldecode( ltrim( $m[1], ':' ) );
170  }
171  $title = Title::newFromText( $m[1] );
172  // If the title is a redirect to bad special pages or is invalid, return null
173  if ( !$title instanceof Title || !$title->isValidRedirectTarget() ) {
174  $this->redirectTargetAndText = [ null, $this->getText() ];
175  return $this->redirectTargetAndText;
176  }
177 
178  $this->redirectTargetAndText = [ $title, substr( $text, strlen( $m[0] ) ) ];
179  return $this->redirectTargetAndText;
180  }
181  }
182 
183  $this->redirectTargetAndText = [ null, $this->getText() ];
184  return $this->redirectTargetAndText;
185  }
186 
194  public function getRedirectTarget() {
195  [ $title, ] = $this->getRedirectTargetAndText();
196 
197  return $title;
198  }
199 
212  public function updateRedirect( Title $target ) {
213  if ( !$this->isRedirect() ) {
214  return $this;
215  }
216 
217  # Fix the text
218  # Remember that redirect pages can have categories, templates, etc.,
219  # so the regex has to be fairly general
220  $newText = preg_replace( '/ \[ \[ [^\]]* \] \] /x',
221  '[[' . $target->getFullText() . ']]',
222  $this->getText(), 1 );
223 
224  return new static( $newText );
225  }
226 
238  public function isCountable( $hasLinks = null, Title $title = null ) {
239  $articleCountMethod = MediaWikiServices::getInstance()->getMainConfig()
240  ->get( MainConfigNames::ArticleCountMethod );
241 
242  if ( $this->isRedirect() ) {
243  return false;
244  }
245 
246  if ( $articleCountMethod === 'link' ) {
247  if ( $hasLinks === null ) { # not known, find out
248  // @TODO: require an injected title
249  if ( !$title ) {
250  $context = RequestContext::getMain();
251  $title = $context->getTitle();
252  }
253  $contentRenderer = MediaWikiServices::getInstance()->getContentRenderer();
254  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable getTitle does not return null here
255  $po = $contentRenderer->getParserOutput( $this, $title, null, null, false );
256  $links = $po->getLinks();
257  $hasLinks = $links !== [];
258  }
259 
260  return $hasLinks;
261  }
262 
263  return true;
264  }
265 
270  public function getTextForSummary( $maxlength = 250 ) {
271  $truncatedtext = parent::getTextForSummary( $maxlength );
272 
273  # clean up unfinished links
274  # XXX: make this optional? wasn't there in autosummary, but required for
275  # deletion summary.
276  $truncatedtext = preg_replace( '/\[\[([^\]]*)\]?$/', '$1', $truncatedtext );
277 
278  return $truncatedtext;
279  }
280 
290  public function matchMagicWord( MagicWord $word ) {
291  return $word->match( $this->getText() );
292  }
293 
299  public function setPreSaveTransformFlags( array $flags ) {
300  $this->preSaveTransformFlags = $flags;
301  }
302 
308  public function getPreSaveTransformFlags() {
309  return $this->preSaveTransformFlags;
310  }
311 }
const CONTENT_MODEL_WIKITEXT
Definition: Defines.php:209
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
MediaWiki exception.
Definition: MWException.php:33
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:568
A class containing constants representing the names of configuration variables.
Service locator for MediaWiki core services.
This class encapsulates "magic words" such as "#redirect", NOTOC, etc.
Definition: MagicWord.php:65
match( $text)
Returns true if the text contains the word.
Definition: MagicWord.php:254
Represents a title within MediaWiki.
Definition: Title.php:76
getFullText()
Get the prefixed title with spaces, plus any fragment (part beginning with '#')
Definition: Title.php:1909
isValidRedirectTarget()
Check if this Title is a valid redirect target.
Definition: Title.php:3549
static getMain()
Get the RequestContext object associated with the main request.
Content object implementation for representing flat text.
Definition: TextContent.php:41
getText()
Returns the text represented by this Content object, as a string.
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 representing page content.
Definition: Content.php:39
getModel()
Returns the ID of the content model used by this Content object.
$header