3 class SpecialCiteThisPage extends FormSpecialPage {
8 private $citationParser;
13 protected $title = false;
15 public function __construct() {
16 parent::__construct( 'CiteThisPage' );
22 public function execute( $par ) {
24 parent::execute( $par );
25 if ( $this->title instanceof Title ) {
26 $id = $this->getRequest()->getInt( 'id' );
27 $this->showCitations( $this->title, $id );
31 protected function alterForm( HTMLForm $form ) {
32 $form->setMethod( 'get' );
35 protected function getFormFields() {
36 if ( isset( $this->par ) ) {
37 $default = $this->par;
45 'default' => $default,
46 'label-message' => 'citethispage-change-target'
51 public function onSubmit( array $data ) {
52 // GET forms are "submitted" on every view, so check
53 // that some data was put in for page, as empty string
54 // will pass validation
55 if ( strlen( $data['page'] ) ) {
56 $this->title = Title::newFromText( $data['page'] );
61 * Return an array of subpages beginning with $search that this special page will accept.
63 * @param string $search Prefix to search for
64 * @param int $limit Maximum number of results to return (usually 10)
65 * @param int $offset Number of results to skip (usually 0)
66 * @return string[] Matching subpages
68 public function prefixSearchSubpages( $search, $limit, $offset ) {
69 $title = Title::newFromText( $search );
70 if ( !$title || !$title->canExist() ) {
71 // No prefix suggestion in special and media namespace
74 // Autocomplete subpage the same as a normal search
75 $prefixSearcher = new StringPrefixSearch;
76 $result = $prefixSearcher->search( $search, $limit, [], $offset );
80 protected function getGroupName() {
84 private function showCitations( Title $title, $revId ) {
86 $revId = $title->getLatestRevID();
89 $out = $this->getOutput();
91 $revision = Revision::newFromTitle( $title, $revId );
93 $out->wrapWikiMsg( '<div class="errorbox">$1</div>',
94 [ 'citethispage-badrevision', $title->getPrefixedText(), $revId ] );
98 $parserOptions = $this->getParserOptions();
99 // Set the overall timestamp to the revision's timestamp
100 $parserOptions->setTimestamp( $revision->getTimestamp() );
102 $parser = $this->getParser();
103 // Register our <citation> tag which just parses using a different
105 $parser->setHook( 'citation', [ $this, 'citationTag' ] );
106 // Also hold on to a separate Parser instance for <citation> tag parsing
107 // since we can't parse in a parse using the same Parser
108 $this->citationParser = $this->getParser();
110 $ret = $parser->parse(
111 $this->getContentText(),
114 /* $linestart = */ false,
115 /* $clearstate = */ true,
119 $this->getOutput()->addModuleStyles( 'ext.citeThisPage' );
120 $this->getOutput()->addParserOutputContent( $ret );
126 private function getParser() {
127 $parserConf = $this->getConfig()->get( 'ParserConf' );
128 return new $parserConf['class']( $parserConf );
132 * Get the content to parse
136 private function getContentText() {
137 $msg = $this->msg( 'citethispage-content' )->inContentLanguage()->plain();
139 # With MediaWiki 1.20 the plain text files were deleted
140 # and the text moved into SpecialCite.i18n.php
141 # This code is kept for b/c in case an installation has its own file "citethispage-content-xx"
142 # for a previously not supported language.
143 global $wgContLang, $wgContLanguageCode;
144 $dir = __DIR__ . DIRECTORY_SEPARATOR;
145 $code = $wgContLang->lc( $wgContLanguageCode );
146 if ( file_exists( "${dir}citethispage-content-$code" ) ) {
147 $msg = file_get_contents( "${dir}citethispage-content-$code" );
148 } elseif ( file_exists( "${dir}citethispage-content" ) ) {
149 $msg = file_get_contents( "${dir}citethispage-content" );
157 * Get the common ParserOptions for both parses
159 * @return ParserOptions
161 private function getParserOptions() {
162 $parserOptions = ParserOptions::newFromUser( $this->getUser() );
163 $parserOptions->setDateFormat( 'default' );
164 $parserOptions->setEditSection( false );
166 // Having tidy on causes whitespace and <pre> tags to
167 // be generated around the output of the CiteThisPageOutput
169 $parserOptions->setTidy( false );
171 return $parserOptions;
175 * Implements the <citation> tag.
177 * This is a hack to allow content that is typically parsed
178 * using the page's timestamp/pagetitle to use the current
179 * request's time and title
181 * @param string $text
182 * @param array $params
183 * @param Parser $parser
186 public function citationTag( $text, $params, Parser $parser ) {
187 $ret = $this->citationParser->parse(
189 $this->getPageTitle(),
190 $this->getParserOptions(),
191 /* $linestart = */ false
194 return $ret->getText();
197 protected function getDisplayFormat() {
201 public function requiresUnblock() {
205 public function requiresWrite() {