MediaWiki  master
PreloadedContentBuilder.php
Go to the documentation of this file.
1 <?php
2 
3 namespace MediaWiki\EditPage;
4 
5 use Content;
18 use MessageCache;
19 use ParserOptions;
20 use Wikimedia\Assert\Assert;
21 
31 
32  use ParametersHelper;
33 
34  private IContentHandlerFactory $contentHandlerFactory;
35  private WikiPageFactory $wikiPageFactory;
36  private RedirectLookup $redirectLookup;
37  private SpecialPageFactory $specialPageFactory;
38  private ContentTransformer $contentTransformer;
39  private HookRunner $hookRunner;
40 
41  public function __construct(
42  IContentHandlerFactory $contentHandlerFactory,
43  WikiPageFactory $wikiPageFactory,
44  RedirectLookup $redirectLookup,
45  SpecialPageFactory $specialPageFactory,
46  ContentTransformer $contentTransformer,
47  HookContainer $hookContainer
48  ) {
49  // Services
50  $this->contentHandlerFactory = $contentHandlerFactory;
51  $this->wikiPageFactory = $wikiPageFactory;
52  $this->redirectLookup = $redirectLookup;
53  $this->specialPageFactory = $specialPageFactory;
54  $this->contentTransformer = $contentTransformer;
55  $this->hookRunner = new HookRunner( $hookContainer );
56  }
57 
69  public function getPreloadedContent(
70  ProperPageIdentity $page,
71  Authority $performer,
72  ?string $preload,
73  array $preloadParams,
74  ?string $section
75  ): Content {
76  Assert::parameterElementType( 'string', $preloadParams, '$preloadParams' );
77 
78  $content = null;
79  if ( $section !== 'new' ) {
80  $content = $this->getDefaultContent( $page );
81  }
82  if ( $content === null ) {
83  if ( ( $preload === null || $preload === '' ) && $section === 'new' ) {
84  // Custom preload text for new sections
85  $preload = 'MediaWiki:addsection-preload';
86  }
87  $content = $this->getPreloadedContentFromParams( $page, $performer, $preload, $preloadParams );
88  }
89  $title = Title::newFromPageIdentity( $page );
90  if ( !$title->getArticleID() ) {
91  $contentModel = $title->getContentModel();
92  $contentHandler = $this->contentHandlerFactory->getContentHandler( $contentModel );
93  $contentFormat = $contentHandler->getDefaultFormat();
94  $text = $contentHandler->serializeContent( $content, $contentFormat );
95  $this->hookRunner->onEditFormPreloadText( $text, $title );
96  $content = $contentHandler->unserializeContent( $text, $contentFormat );
97  }
98  return $content;
99  }
100 
111  public function getDefaultContent( ProperPageIdentity $page ): ?Content {
112  $title = Title::newFromPageIdentity( $page );
113  $contentModel = $title->getContentModel();
114  $contentHandler = $this->contentHandlerFactory->getContentHandler( $contentModel );
115  $contentFormat = $contentHandler->getDefaultFormat();
116  if ( $title->getNamespace() === NS_MEDIAWIKI ) {
117  // If this is a system message, get the default text.
118  $text = $title->getDefaultMessageText();
119  if ( $text !== false ) {
120  return $contentHandler->unserializeContent( $text, $contentFormat );
121  }
122  }
123  return null;
124  }
125 
135  private function getPreloadedContentFromParams(
136  ProperPageIdentity $contextPage,
137  Authority $performer,
138  ?string $preload,
139  array $preloadParams
140  ): Content {
141  $contextTitle = Title::newFromPageIdentity( $contextPage );
142  $contentModel = $contextTitle->getContentModel();
143  $handler = $this->contentHandlerFactory->getContentHandler( $contentModel );
144 
145  // T297725: Don't trick users into making edits to e.g. .js subpages
146  if ( !$handler->supportsPreloadContent() || $preload === null || $preload === '' ) {
147  return $handler->makeEmptyContent();
148  }
149 
150  $title = Title::newFromText( $preload );
151 
152  if ( $title && $title->getNamespace() == NS_MEDIAWIKI ) {
153  // When the preload source is in NS_MEDIAWIKI, get the content via wfMessage, to
154  // enable preloading from i18n messages. The message framework can work with normal
155  // pages in NS_MEDIAWIKI, so this does not restrict preloading only to i18n messages.
156  $msg = wfMessage( MessageCache::normalizeKey( $title->getText() ) );
157 
158  if ( $msg->isDisabled() ) {
159  // Message is disabled and should not be used for preloading
160  return $handler->makeEmptyContent();
161  }
162 
163  return $this->transform(
164  $handler->unserializeContent( $msg
165  ->page( $title )
166  ->params( $preloadParams )
167  ->inContentLanguage()
168  ->plain()
169  ),
170  $title
171  );
172  }
173 
174  // (T299544) Use SpecialMyLanguage redirect so that nonexistent translated pages can
175  // fall back to the corresponding page in a suitable language
176  $title = $this->getTargetTitleIfSpecialMyLanguage( $title );
177 
178  # Check for existence to avoid getting MediaWiki:Noarticletext
179  if ( !$this->isPageExistingAndViewable( $title, $performer ) ) {
180  // TODO: somehow show a warning to the user!
181  return $handler->makeEmptyContent();
182  }
183 
184  $page = $this->wikiPageFactory->newFromTitle( $title );
185  if ( $page->isRedirect() ) {
186  $redirTarget = $this->redirectLookup->getRedirectTarget( $title );
187  $redirTarget = Title::castFromLinkTarget( $redirTarget );
188  # Same as before
189  if ( !$this->isPageExistingAndViewable( $redirTarget, $performer ) ) {
190  // TODO: somehow show a warning to the user!
191  return $handler->makeEmptyContent();
192  }
193  $page = $this->wikiPageFactory->newFromTitle( $redirTarget );
194  }
195 
196  $content = $page->getContent( RevisionRecord::RAW );
197 
198  if ( !$content ) {
199  // TODO: somehow show a warning to the user!
200  return $handler->makeEmptyContent();
201  }
202 
203  if ( $content->getModel() !== $handler->getModelID() ) {
204  $converted = $content->convert( $handler->getModelID() );
205 
206  if ( !$converted ) {
207  // TODO: somehow show a warning to the user!
208  wfDebug( "Attempt to preload incompatible content: " .
209  "can't convert " . $content->getModel() .
210  " to " . $handler->getModelID() );
211 
212  return $handler->makeEmptyContent();
213  }
214 
215  $content = $converted;
216  }
217  return $this->transform( $content, $title, $preloadParams );
218  }
219 
220  private function transform(
222  PageReference $title,
223  array $preloadParams = []
224  ) {
225  return $this->contentTransformer->preloadTransform(
226  $content,
227  $title,
228  // The preload transformations don't depend on the user anyway
230  $preloadParams
231  );
232  }
233 }
const NS_MEDIAWIKI
Definition: Defines.php:72
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Provides the initial content of the edit box displayed in an edit form when creating a new page or a ...
__construct(IContentHandlerFactory $contentHandlerFactory, WikiPageFactory $wikiPageFactory, RedirectLookup $redirectLookup, SpecialPageFactory $specialPageFactory, ContentTransformer $contentTransformer, HookContainer $hookContainer)
getDefaultContent(ProperPageIdentity $page)
Get the content that is displayed when viewing a page that does not exist.
getPreloadedContent(ProperPageIdentity $page, Authority $performer, ?string $preload, array $preloadParams, ?string $section)
Get the initial content of the edit box displayed in an edit form when creating a new page or a new s...
This class provides an implementation of the core hook interfaces, forwarding hook calls to HookConta...
Definition: HookRunner.php:568
Service for creating WikiPage objects.
Page revision base class.
Factory for handling the special page list and generating SpecialPage objects.
Represents a title within MediaWiki.
Definition: Title.php:76
static newFromPageIdentity(PageIdentity $pageIdentity)
Return a Title for a given PageIdentity.
Definition: Title.php:329
getContentModel( $flags=0)
Get the page's content model id, see the CONTENT_MODEL_XXX constants.
Definition: Title.php:1080
Cache messages that are defined by MediaWiki-namespace pages or by hooks.
static normalizeKey( $key)
Normalize message key input.
Set options of the Parser.
static newFromAnon()
Get a ParserOptions object for an anonymous user.
Base interface for representing page content.
Definition: Content.php:39
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.
Interface for a page that is (or could be, or used to be) an editable wiki page.
Service for resolving a wiki page redirect.
This interface represents the authority associated the current execution context, such as a web reque...
Definition: Authority.php:37
$content
Definition: router.php:76