function validateTarget($target)
 {
     if (!$target) {
         return wfMsgExt('lqt_move_nodestination', 'parseinline');
     }
     $title = Title::newFromText($target);
     if (!$title || !LqtDispatch::isLqtPage($title)) {
         return wfMsgExt('lqt_move_thread_bad_destination', 'parseinline');
     }
     if ($title->equals($this->mThread->getTitle())) {
         return wfMsgExt('lqt_move_samedestination', 'parseinline');
     }
     return true;
 }
 /**
  * Creates a flow board.
  * Archives any pre-existing wikitext talk page.
  *
  * @param array $data Form data
  * @return Status Status indicating result
  */
 public function onSubmit(array $data)
 {
     $page = $data['page'];
     $title = Title::newFromText($page);
     if (!$title) {
         return Status::newFatal('flow-special-enableflow-invalid-title', $page);
     }
     // Canonicalize so the error or confirmation message looks nicer (no underscores).
     $page = $title->getPrefixedText();
     if ($this->occupationController->isTalkpageOccupied($title, true)) {
         return Status::newFatal('flow-special-enableflow-board-already-exists', $page);
     }
     $status = Status::newGood();
     if ($title->exists(Title::GAID_FOR_UPDATE)) {
         if (class_exists('LqtDispatch') && \LqtDispatch::isLqtPage($title)) {
             return Status::newFatal('flow-special-enableflow-page-is-liquidthreads', $page);
         }
         $logger = Container::get('default_logger');
         $converter = new Converter(wfGetDB(DB_MASTER), Container::get('importer'), $logger, $this->occupationController->getTalkpageManager(), new EnableFlowWikitextConversionStrategy(Container::get('parser'), new NullImportSourceStore(), $logger, array(), $data['header']));
         try {
             $converter->convert($title);
         } catch (\Exception $e) {
             \MWExceptionHandler::logException($e);
             $status->fatal('flow-error-external', $e->getMessage());
         }
     } else {
         $allowCreationStatus = $this->occupationController->allowCreation($title, $this->getUser(), false);
         if (!$allowCreationStatus->isGood()) {
             return Status::newFatal('flow-special-enableflow-board-creation-not-allowed', $page);
         }
         $loader = $this->loaderFactory->createWorkflowLoader($title);
         $blocks = $loader->getBlocks();
         $action = 'edit-header';
         $params = array('header' => array('content' => $data['header'], 'format' => 'wikitext'));
         $blocksToCommit = $loader->handleSubmit($this->getContext(), $action, $params);
         foreach ($blocks as $block) {
             if ($block->hasErrors()) {
                 $errors = $block->getErrors();
                 foreach ($errors as $errorKey) {
                     $status->fatal($block->getErrorMessage($errorKey));
                 }
             }
         }
         $loader->commit($blocksToCommit);
     }
     $this->page = $data['page'];
     return $status;
 }
Esempio n. 3
0
 /**
  * @param $thread Thread
  * @param $levelNum int
  * @param $totalInLevel int
  * @param $options array
  * @throws Exception
  */
 function showThread($thread, $levelNum = 1, $totalInLevel = 1, $options = array())
 {
     // Safeguard
     if ($thread->type() & Threads::TYPE_DELETED || !$thread->root()) {
         return;
     }
     $this->threadNestingLevel++;
     // Figure out which threads *need* to be shown because they're involved in an
     //	operation
     $mustShowOption = array();
     if (isset($options['mustShowThreads'])) {
         $mustShowOption = $options['mustShowThreads'];
     }
     $mustShowThreads = $this->getMustShowThreads($mustShowOption);
     // For cascading.
     $options['mustShowThreads'] = $mustShowThreads;
     // Don't show blank posts unless we have to
     $content = '';
     if ($thread->root()) {
         $content = $thread->root()->getContent();
     }
     if (trim($content) == '' && $thread->type() != Threads::TYPE_MOVED && !self::threadContainsRepliesWithContent($thread) && !array_key_exists($thread->id(), $mustShowThreads)) {
         $this->threadNestingLevel--;
         return;
     }
     // Grab options
     if (isset($options['maxDepth'])) {
         $maxDepth = $options['maxDepth'];
     } else {
         $maxDepth = $this->user->getOption('lqtdisplaydepth');
     }
     if (isset($options['maxCount'])) {
         $maxCount = $options['maxCount'];
     } else {
         $maxCount = $this->user->getOption('lqtdisplaycount');
     }
     if (isset($options['startAt'])) {
         $startAt = $options['startAt'];
     } else {
         $startAt = 0;
     }
     // Figure out if we have replies to show or not.
     $showThreads = $maxDepth == -1 || $this->threadNestingLevel <= $maxDepth;
     $mustShowThreadIds = array_keys($mustShowThreads);
     $subthreadIds = array_keys($thread->replies());
     $mustShowSubthreadIds = array_intersect($mustShowThreadIds, $subthreadIds);
     $hasSubthreads = self::threadContainsRepliesWithContent($thread);
     $hasSubthreads = $hasSubthreads || count($mustShowSubthreadIds);
     // Show subthreads if one of the subthreads is on the must-show list
     $showThreads = $showThreads || count(array_intersect(array_keys($mustShowThreads), array_keys($thread->replies())));
     $replyTo = $this->methodAppliesToThread('reply', $thread);
     $this->output->addModules('ext.liquidThreads');
     $html = '';
     Hooks::run('EditPageBeforeEditToolbar', array(&$html));
     $class = $this->threadDivClass($thread);
     if ($levelNum == 1) {
         $class .= ' lqt-thread-first';
     } elseif ($levelNum == $totalInLevel) {
         $class .= ' lqt-thread-last';
     }
     if ($hasSubthreads && $showThreads) {
         $class .= ' lqt-thread-with-subthreads';
     } else {
         $class .= ' lqt-thread-no-subthreads';
     }
     if (!$thread->title()->quickUserCan('edit') || !LqtDispatch::isLqtPage($thread->getTitle())) {
         $class .= ' lqt-thread-uneditable';
     }
     $class .= ' lqt-thread-wrapper';
     $html .= Xml::openElement('div', array('class' => $class, 'id' => 'lqt_thread_id_' . $thread->id()));
     $html .= Xml::element('a', array('name' => $this->anchorName($thread)), ' ');
     $html .= $this->showThreadHeading($thread);
     // Metadata stuck in the top of the lqt_thread div.
     // Modified time for topmost threads...
     if ($thread->isTopmostThread()) {
         $html .= Html::hidden('lqt-thread-modified-' . $thread->id(), wfTimestamp(TS_MW, $thread->modified()), array('id' => 'lqt-thread-modified-' . $thread->id(), 'class' => 'lqt-thread-modified'));
         $html .= Html::hidden('lqt-thread-sortkey', $thread->sortkey(), array('id' => 'lqt-thread-sortkey-' . $thread->id()));
         $html .= Html::hidden('lqt-thread-talkpage-' . $thread->id(), $thread->article()->getTitle()->getPrefixedText(), array('class' => 'lqt-thread-talkpage-metadata'));
     }
     if (!$thread->title()) {
         throw new Exception("Thread " . $thread->id() . " has null title");
     }
     // Add the thread's title
     $html .= Html::hidden('lqt-thread-title-' . $thread->id(), $thread->title()->getPrefixedText(), array('id' => 'lqt-thread-title-' . $thread->id(), 'class' => 'lqt-thread-title-metadata'));
     // Flush output to display thread
     $this->output->addHTML($html);
     $this->output->addHTML(Xml::openElement('div', array('class' => 'lqt-post-wrapper')));
     $this->showSingleThread($thread);
     $this->output->addHTML(Xml::closeElement('div'));
     $cascadeOptions = $options;
     unset($cascadeOptions['startAt']);
     $replyInterruption = $levelNum < $totalInLevel;
     if ($hasSubthreads && $showThreads) {
         // If the thread has subthreads, and we want to show them, we should do so.
         $this->showThreadReplies($thread, $startAt, $maxCount, $showThreads, $cascadeOptions, $replyInterruption);
     } elseif ($hasSubthreads && !$showThreads) {
         // If the thread has subthreads, but we don't want to show them, then
         //	show the reply form if necessary, and add the "Show X replies" link.
         if ($replyTo) {
             $this->showReplyForm($thread);
         }
         // Add a "show subthreads" link.
         $link = $this->getShowReplies($thread);
         $this->output->addHTML($link);
         if ($levelNum < $totalInLevel) {
             $this->output->addHTML(Xml::tags('div', array('class' => 'lqt-post-sep'), '&#160;'));
         }
     } elseif ($levelNum < $totalInLevel) {
         // If we have no replies, and we're not at the end of this level, add the post separator
         //	and a reply box if necessary.
         $this->output->addHTML(Xml::tags('div', array('class' => 'lqt-post-sep'), '&#160;'));
         if ($replyTo) {
             $class = 'lqt-thread-replies lqt-thread-replies-' . $this->threadNestingLevel;
             $html = Xml::openElement('div', array('class' => $class));
             $this->output->addHTML($html);
             $this->showReplyForm($thread);
             $finishDiv = Xml::tags('div', array('class' => 'lqt-replies-finish'), '&#160;');
             // Layout plus close div.lqt-thread-replies
             $finishHTML = Xml::closeElement('div');
             // lqt-reply-form
             $finishHTML .= $finishDiv;
             // Layout
             $finishHTML .= Xml::closeElement('div');
             // lqt-thread-replies
             $this->output->addHTML($finishHTML);
         }
     } elseif (!$hasSubthreads && $replyTo) {
         // If we have no replies, we're at the end of this level, and we want to reply,
         //	show the reply box.
         $class = 'lqt-thread-replies lqt-thread-replies-' . $this->threadNestingLevel;
         $html = Xml::openElement('div', array('class' => $class));
         $this->output->addHTML($html);
         $this->showReplyForm($thread);
         $html = Xml::tags('div', array('class' => 'lqt-replies-finish'), Xml::tags('div', array('class' => 'lqt-replies-finish-corner'), '&#160;'));
         $html .= Xml::closeElement('div');
         $this->output->addHTML($html);
     }
     // I don't remember why this is here, commenting out.
     //		if ( $this->threadNestingLevel == 1 ) {
     //			if ( !( $hasSubthreads && $showThreads && !$replyTo ) ) {
     //				$this->showReplyBox( $thread );
     //				$finishDiv = '';
     //				$finishDiv .= Xml::tags( 'div', array( 'class' => 'lqt-replies-finish' ),
     //					Xml::tags( 'div', array( 'class' => 'lqt-replies-finish-corner' ), '&#160;' ) );
     //
     //				$this->output->addHTML( $finishDiv );
     //			}
     //		}
     $this->output->addHTML(Xml::closeElement('div'));
     $this->threadNestingLevel--;
 }
Esempio n. 4
0
 function doLazyUpdates()
 {
     if ($this->isHistorical()) {
         return;
     }
     // Don't do lazy updates on stored historical threads.
     // This is an invocation guard to avoid infinite recursion when fixing a
     //  missing ancestor.
     static $doingUpdates = false;
     if ($doingUpdates) {
         return;
     }
     $doingUpdates = true;
     // Fix missing ancestry information.
     // (there was a bug where this was not saved properly)
     if ($this->parentId && !$this->ancestorId) {
         $this->fixMissingAncestor();
     }
     $ancestor = $this->topmostThread();
     $set = array();
     // Fix missing subject information
     // (this information only started to be added later)
     if (!$this->subject && $this->root()) {
         $detectedSubject = $this->root()->getTitle()->getText();
         $parts = self::splitIncrementFromSubject($detectedSubject);
         $this->subject = $detectedSubject = $parts[1];
         // Update in the DB
         $set['thread_subject'] = $detectedSubject;
     }
     // Fix inconsistent subject information
     // (in some intermediate versions this was not updated when the subject was changed)
     if ($this->subject() != $ancestor->subject()) {
         $set['thread_subject'] = $ancestor->subject();
         $this->subject = $ancestor->subject();
     }
     // Fix missing authorship information
     // (this information only started to be added later)
     if (!$this->authorName) {
         $author = $this->loadOriginalAuthorFromRevision();
         $this->authorId = $author->getId();
         $this->authorName = $author->getName();
         $set['thread_author_name'] = $this->authorName;
         $set['thread_author_id'] = $this->authorId;
     }
     // Check for article being in subject, not talk namespace.
     // If the page is non-LiquidThreads and it's in subject-space, we'll assume it's meant
     // to be on the corresponding talk page, but only if the talk-page is a LQT page.
     // (Previous versions stored the subject page, for some totally bizarre reason)
     // Old versions also sometimes store the thread page for trace threads as the
     //  article, not as the root.
     //  Trying not to exacerbate this by moving it to be the 'Thread talk' page.
     $articleTitle = $this->getTitle();
     global $wgLiquidThreadsMigrate;
     if (!LqtDispatch::isLqtPage($articleTitle) && !$articleTitle->isTalkPage() && LqtDispatch::isLqtPage($articleTitle->getTalkPage()) && $articleTitle->getNamespace() != NS_LQT_THREAD && $wgLiquidThreadsMigrate) {
         $newTitle = $articleTitle->getTalkPage();
         $newArticle = new Article($newTitle);
         $set['thread_article_namespace'] = $newTitle->getNamespace();
         $set['thread_article_title'] = $newTitle->getDbKey();
         $this->articleNamespace = $newTitle->getNamespace();
         $this->articleTitle = $newTitle->getDbKey();
         $this->articleId = $newTitle->getArticleId();
         $this->article = $newArticle;
     }
     // Check for article corruption from incomplete thread moves.
     // (thread moves only updated this on immediate replies, not replies to replies etc)
     if (!$ancestor->getTitle()->equals($this->getTitle())) {
         $title = $ancestor->getTitle();
         $set['thread_article_namespace'] = $title->getNamespace();
         $set['thread_article_title'] = $title->getDbKey();
         $this->articleNamespace = $title->getNamespace();
         $this->articleTitle = $title->getDbKey();
         $this->articleId = $title->getArticleId();
         $this->article = $ancestor->article();
     }
     // Check for invalid/missing articleId
     $articleTitle = null;
     $dbTitle = Title::makeTitleSafe($this->articleNamespace, $this->articleTitle);
     if ($this->articleId && isset(self::$titleCacheById[$this->articleId])) {
         // If it corresponds to a title, the article obviously exists.
         $articleTitle = self::$titleCacheById[$this->articleId];
         $this->article = new Article($articleTitle);
     } elseif ($this->articleId) {
         $articleTitle = Title::newFromID($this->articleId);
     }
     // If still unfilled, the article ID referred to is no longer valid. Re-fill it
     //  from the namespace/title pair if an article ID is provided
     if (!$articleTitle && ($this->articleId != 0 || $dbTitle->getArticleId() != 0)) {
         $articleTitle = $dbTitle;
         $this->articleId = $articleTitle->getArticleId();
         $this->article = new Article($dbTitle);
         $set['thread_article_id'] = $this->articleId;
         wfDebug("Unfilled or non-existent thread_article_id, refilling to {$this->articleId}\n");
         // There are probably problems on the rest of the article, trigger a small update
         Threads::synchroniseArticleData($this->article, 100, 'cascade');
     } elseif ($articleTitle && !$articleTitle->equals($dbTitle)) {
         // The page was probably moved and this was probably not updated.
         wfDebug("Article ID/Title discrepancy, resetting NS/Title to article provided by ID\n");
         $this->articleNamespace = $articleTitle->getNamespace();
         $this->articleTitle = $articleTitle->getDBkey();
         $set['thread_article_namespace'] = $articleTitle->getNamespace();
         $set['thread_article_title'] = $articleTitle->getDBkey();
         // There are probably problems on the rest of the article, trigger a small update
         Threads::synchroniseArticleData($this->article, 100, 'cascade');
     }
     // Check for unfilled signature field. This field hasn't existed until
     //  recently.
     if (is_null($this->signature)) {
         // Grab our signature.
         $sig = LqtView::getUserSignature($this->author());
         $set['thread_signature'] = $sig;
         $this->setSignature($sig);
     }
     if (count($set)) {
         $dbw = wfGetDB(DB_MASTER);
         $dbw->update('thread', $set, array('thread_id' => $this->id()), __METHOD__);
     }
     // Done
     $doingUpdates = false;
 }
Esempio n. 5
0
 /**
  * If the page we recieve is a LiquidThreads page of any kind, process it
  * as needed and return True. If it's a normal, non-liquid page, return false.
  * @param $output OutputPage
  * @param $article Article
  * @param $title Title
  * @param $user User
  * @param $request WebRequest
  * @return bool
  */
 static function tryPage($output, $article, $title, $user, $request)
 {
     if (LqtDispatch::isLqtPage($title)) {
         // LiquidThreads pages, Talk:X etc
         return self::talkpageMain($output, $article, $title, $user, $request);
     } elseif ($title->getNamespace() == NS_LQT_THREAD) {
         // Thread permalink pages, Thread:X
         return self::threadPermalinkMain($output, $article, $title, $user, $request);
     } elseif ($title->getNamespace() == NS_LQT_SUMMARY) {
         // Summary pages, Summary:X
         return self::threadSummaryMain($output, $article, $title, $user, $request);
     }
     return true;
 }
Esempio n. 6
0
 public function actionNewThread($threads, $params)
 {
     // Validate talkpage parameters
     if (!count($params['talkpage'])) {
         $this->dieUsageMsg(array('missingparam', 'talkpage'));
     }
     $talkpageTitle = Title::newFromText($params['talkpage']);
     if (!$talkpageTitle || !LqtDispatch::isLqtPage($talkpageTitle)) {
         $this->dieUsage('The talkpage you specified is invalid, or does not ' . 'have discussion threading enabled.', 'invalid-talkpage');
     }
     $talkpage = new Article($talkpageTitle, 0);
     // Check if we can post.
     $user = $this->getUser();
     if (Thread::canUserPost($user, $talkpage) !== true) {
         $this->dieUsage('You cannot post to the specified talkpage, ' . 'because it is protected from new posts', 'talkpage-protected');
     }
     // Validate subject, generate a title
     if (empty($params['subject'])) {
         $this->dieUsageMsg(array('missingparam', 'subject'));
     }
     $subject = $params['subject'];
     $title = null;
     $subjectOk = Thread::validateSubject($subject, $title, null, $talkpage);
     if (!$subjectOk) {
         $this->dieUsage('The subject you specified is not valid', 'invalid-subject');
     }
     $article = new Article($title, 0);
     // Check for text
     if (empty($params['text'])) {
         $this->dieUsage('You must include text in your post', 'no-text');
     }
     $text = $params['text'];
     // Generate or pull summary
     $summary = wfMessage('lqt-newpost-summary', $subject)->inContentLanguage()->text();
     if (!empty($params['reason'])) {
         $summary = $params['reason'];
     }
     $signature = null;
     if (isset($params['signature'])) {
         $signature = $params['signature'];
     }
     // Inform hooks what we're doing
     LqtHooks::$editTalkpage = $talkpage;
     LqtHooks::$editArticle = $article;
     LqtHooks::$editThread = null;
     LqtHooks::$editType = 'new';
     LqtHooks::$editAppliesTo = null;
     $token = $params['token'];
     // All seems in order. Construct an API edit request
     $requestData = array('action' => 'edit', 'title' => $title->getPrefixedText(), 'text' => $text, 'summary' => $summary, 'token' => $token, 'basetimestamp' => wfTimestampNow(), 'minor' => 0, 'format' => 'json');
     if ($user->isAllowed('bot')) {
         $requestData['bot'] = true;
     }
     $editReq = new DerivativeRequest($this->getRequest(), $requestData, true);
     $internalApi = new ApiMain($editReq, true);
     $internalApi->execute();
     if (defined('ApiResult::META_CONTENT')) {
         $editResult = $internalApi->getResult()->getResultData();
     } else {
         $editResult = $internalApi->getResultData();
     }
     if ($editResult['edit']['result'] != 'Success') {
         $result = array('result' => 'EditFailure', 'details' => $editResult);
         $this->getResult()->addValue(null, $this->getModuleName(), $result);
         return;
     }
     $articleId = $editResult['edit']['pageid'];
     $article->getTitle()->resetArticleID($articleId);
     $title->resetArticleID($articleId);
     $thread = LqtView::newPostMetadataUpdates(array('root' => $article, 'talkpage' => $talkpage, 'subject' => $subject, 'signature' => $signature, 'summary' => $summary, 'text' => $text));
     $result = array('result' => 'Success', 'thread-id' => $thread->id(), 'thread-title' => $title->getPrefixedText(), 'modified' => $thread->modified());
     if (!empty($params['render'])) {
         $result['html'] = $this->renderThreadPostAction($thread);
     }
     $result = array('thread' => $result);
     $this->getResult()->addValue(null, $this->getModuleName(), $result);
 }
Esempio n. 7
0
 /**
  * Checks whether the current page should be Reflected. First, only LQT pages
  * can be Reflected. Second, either Reflect must be enabled for all pages, or 
  * the current page must belong to a subset of pages Reflect is enabled on. 
  * 
  * @param $title Title of current page. 
  * 
  * @return Returns whether the current page should have Reflect added.
  */
 private static function isReflectPage($title)
 {
     global $wgReflectPages, $wgReflectTalkPages;
     $isReflectPage = LqtDispatch::isLqtPage($title) && ($wgReflectTalkPages || in_array($title->getPrefixedText(), $wgReflectPages));
     return $isReflectPage;
 }
 /**
  * Execute the requested Api actions.
  * @todo: Write some unit tests for API results
  */
 public function execute()
 {
     // Logged-in users' parser options depend on preferences
     $this->getMain()->setCacheMode('anon-public-user-private');
     // Enough '*' keys in JSON!!!
     $isXml = $this->getMain()->isInternalMode() || $this->getMain()->getPrinter()->getFormat() == 'XML';
     $textElement = $isXml ? '*' : 'text';
     $params = $this->extractRequestParams();
     $prop = array_flip($params['prop']);
     $sectionProp = array_flip($params['sectionprop']);
     $this->variant = $params['variant'];
     $this->followRedirects = $params['redirect'] == 'yes';
     $this->noHeadings = $params['noheadings'];
     $this->noTransform = $params['notransform'];
     $onlyRequestedSections = $params['onlyrequestedsections'];
     $this->offset = $params['offset'];
     $this->maxlen = $params['maxlen'];
     if ($this->offset === 0 && $this->maxlen === 0) {
         $this->offset = -1;
         // Disable text splitting
     } elseif ($this->maxlen === 0) {
         $this->maxlen = PHP_INT_MAX;
     }
     $title = $this->makeTitle($params['page']);
     // See whether the actual page (or if enabled, the redirect target) is the main page
     $this->mainPage = $this->isMainPage($title);
     if ($this->mainPage && $this->noHeadings) {
         $this->noHeadings = false;
         $this->setWarning("``noheadings'' makes no sense on the main page, ignoring");
     }
     if (isset($prop['normalizedtitle']) && $title->getPrefixedText() != $params['page']) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('normalizedtitle' => $title->getPageLanguage()->convert($title->getPrefixedText())));
     }
     $data = $this->getData($title, $params['noimages']);
     // Bug 73109: #getData will return an empty array if the title redirects to
     // a page in a virtual namespace (NS_SPECIAL, NS_MEDIA), so make sure that
     // the requested data exists too.
     if (isset($prop['lastmodified']) && isset($data['lastmodified'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('lastmodified' => $data['lastmodified']));
     }
     if (isset($prop['lastmodifiedby']) && isset($data['lastmodifiedby'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('lastmodifiedby' => $data['lastmodifiedby']));
     }
     if (isset($prop['revision']) && isset($data['revision'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('revision' => $data['revision']));
     }
     if (isset($prop['id']) && isset($data['id'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('id' => $data['id']));
     }
     if (isset($prop['languagecount']) && isset($data['languagecount'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('languagecount' => $data['languagecount']));
     }
     if (isset($prop['hasvariants']) && isset($data['hasvariants'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('hasvariants' => $data['hasvariants']));
     }
     if (isset($prop['displaytitle']) && isset($data['displaytitle'])) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('displaytitle' => $data['displaytitle']));
     }
     if (isset($prop['pageprops'])) {
         $propNames = $params['pageprops'];
         if ($propNames == '*' && isset($data['pageprops'])) {
             $pageProps = $data['pageprops'];
         } else {
             $propNames = explode('|', $propNames);
             $pageProps = array_intersect_key($data['pageprops'], array_flip($propNames));
         }
         $this->getResult()->addValue(null, $this->getModuleName(), array('pageprops' => $pageProps));
     }
     if (isset($prop['description']) && isset($data['pageprops']['wikibase_item'])) {
         $desc = ExtMobileFrontend::getWikibaseDescription($data['pageprops']['wikibase_item']);
         if ($desc) {
             $this->getResult()->addValue(null, $this->getModuleName(), array('description' => $desc));
         }
     }
     if ($this->usePageImages) {
         $this->addPageImage($data, $params, $prop);
     }
     $result = array();
     $missingSections = array();
     if ($this->mainPage) {
         if ($onlyRequestedSections) {
             $requestedSections = self::parseSections($params['sections'], $data, $missingSections);
         } else {
             $requestedSections = array(0);
         }
         $this->getResult()->addValue(null, $this->getModuleName(), array('mainpage' => ''));
     } elseif (isset($params['sections'])) {
         $requestedSections = self::parseSections($params['sections'], $data, $missingSections);
     } else {
         $requestedSections = array();
     }
     if (isset($data['sections'])) {
         if (isset($prop['sections'])) {
             $sectionCount = count($data['sections']);
             for ($i = 0; $i <= $sectionCount; $i++) {
                 if (!isset($requestedSections[$i]) && $onlyRequestedSections) {
                     continue;
                 }
                 $section = array();
                 if ($i > 0) {
                     $section = array_intersect_key($data['sections'][$i - 1], $sectionProp);
                 }
                 $section['id'] = $i;
                 if (isset($prop['text']) && isset($requestedSections[$i]) && isset($data['text'][$i])) {
                     $section[$textElement] = $this->stringSplitter($this->prepareSection($data['text'][$i]));
                     unset($requestedSections[$i]);
                 }
                 if (isset($data['refsections'][$i])) {
                     $section['references'] = '';
                 }
                 $result[] = $section;
             }
             $missingSections = array_keys($requestedSections);
         } else {
             foreach (array_keys($requestedSections) as $index) {
                 $section = array('id' => $index);
                 if (isset($data['text'][$index])) {
                     $section[$textElement] = $this->stringSplitter($this->prepareSection($data['text'][$index]));
                 } else {
                     $missingSections[] = $index;
                 }
                 $result[] = $section;
             }
         }
         $this->getResult()->setIndexedTagName($result, 'section');
         $this->getResult()->addValue(null, $this->getModuleName(), array('sections' => $result));
     }
     if (isset($prop['protection'])) {
         $this->addProtection($title);
     }
     if (isset($prop['editable'])) {
         $user = $this->getUser();
         if ($user->isAnon()) {
             // HACK: Anons receive cached information, so don't check blocked status for them
             // to avoid them receiving false positives. Currently there is no way to check
             // all permissions except blocked status from the Title class.
             $req = new FauxRequest();
             $req->setIP('127.0.0.1');
             $user = User::newFromSession($req);
         }
         $editable = $title->quickUserCan('edit', $user);
         if ($isXml) {
             $editable = intval($editable);
         }
         $this->getResult()->addValue(null, $this->getModuleName(), array('editable' => $editable));
     }
     // https://bugzilla.wikimedia.org/show_bug.cgi?id=51586
     // Inform ppl if the page is infested with LiquidThreads but that's the
     // only thing we support about it.
     if (class_exists('LqtDispatch') && LqtDispatch::isLqtPage($title)) {
         $this->getResult()->addValue(null, $this->getModuleName(), array('liquidthreads' => ''));
     }
     if (count($missingSections) && isset($prop['text'])) {
         $this->setWarning('Section(s) ' . implode(', ', $missingSections) . ' not found');
     }
     if ($this->maxlen < 0) {
         // There is more data available
         $this->getResult()->addValue(null, $this->getModuleName(), array('continue-offset' => $params['offset'] + $params['maxlen']));
     }
 }
Esempio n. 9
0
 public static function onInfoAction($context, $pageInfo)
 {
     if (LqtDispatch::isLqtPage($context->getTitle())) {
         $pageInfo['header-basic'][] = array(wfMessage('pageinfo-usinglqt'), wfMessage('pageinfo-usinglqt-yes'));
     }
     return true;
 }
Esempio n. 10
0
 function show()
 {
     $this->output->addModules('ext.liquidThreads');
     $article = $this->talkpage;
     if (!LqtDispatch::isLqtPage($article->getTitle())) {
         $this->output->addWikiMsg('lqt-not-discussion-page');
         return false;
     }
     $this->output->setPageTitle($this->title->getPrefixedText());
     // Expose feed links.
     global $wgFeedClasses;
     $apiParams = array('action' => 'feedthreads', 'type' => 'replies|newthreads', 'talkpage' => $this->title->getPrefixedText());
     $urlPrefix = wfScript('api') . '?';
     foreach ($wgFeedClasses as $format => $class) {
         $theseParams = $apiParams + array('feedformat' => $format);
         $url = $urlPrefix . wfArrayToCgi($theseParams);
         $this->output->addFeedLink($format, $url);
     }
     if ($this->request->getBool('lqt_inline')) {
         $this->doInlineEditForm();
         return false;
     }
     $this->output->addHTML(Xml::openElement('div', array('class' => 'lqt-talkpage')));
     // Search!
     if ($this->request->getCheck('lqt_search')) {
         $q = $this->request->getText('lqt_search');
         $q .= ' ondiscussionpage:' . $article->getTitle()->getPrefixedText();
         $params = array('search' => $q, 'fulltext' => 1, 'ns' . NS_LQT_THREAD => 1, 'srbackend' => 'LuceneSearch');
         $t = SpecialPage::getTitleFor('Search');
         $url = $t->getLocalURL(wfArrayToCgi($params));
         $this->output->redirect($url);
         return true;
     }
     if ($this->shouldShow('header')) {
         $this->showHeader();
     }
     global $wgLang;
     // This closes the div of mw-content-ltr/rtl containing lang and dir attributes
     $this->output->addHTML(Html::closeElement('div') . Html::openElement('div', array('class' => 'lqt-talkpage', 'lang' => $wgLang->getCode(), 'dir' => $wgLang->getDir())));
     $html = '';
     // Set up a per-page header for new threads, search box, and sorting stuff.
     $talkpageHeader = '';
     if (Thread::canUserPost($this->user, $this->talkpage)) {
         $newThreadText = wfMessage('lqt_new_thread')->parse();
         $newThreadLink = Linker::link($this->title, $newThreadText, array('lqt_talkpage' => $this->talkpage->getTitle()->getPrefixedText()), array('lqt_method' => 'talkpage_new_thread'), array('known'));
         $newThreadLink = Xml::tags('strong', array('class' => 'lqt_start_discussion'), $newThreadLink);
         $talkpageHeader .= $newThreadLink;
     }
     global $wgSearchTypeAlternatives, $wgSearchType;
     if ($wgSearchType == "LuceneSearch" || in_array("LuceneSearch", $wgSearchTypeAlternatives ?: array())) {
         $talkpageHeader .= $this->getSearchBox();
     }
     $talkpageHeader .= $this->showTalkpageViewOptions($article);
     $talkpageHeader = Xml::tags('div', array('class' => 'lqt-talkpage-header'), $talkpageHeader);
     if ($this->shouldShow('options')) {
         $this->output->addHTML($talkpageHeader);
     } elseif ($this->shouldShow('simplenew')) {
         $this->output->addHTML($newThreadLink);
     }
     if ($this->methodApplies('talkpage_new_thread')) {
         $this->showNewThreadForm($this->talkpage);
     } else {
         $this->output->addHTML(Xml::tags('div', array('class' => 'lqt-new-thread lqt-edit-form'), ''));
     }
     $pager = $this->getPager();
     $threads = $this->getPageThreads($pager);
     if (count($threads) > 0 && $this->shouldShow('toc')) {
         $html .= $this->getTOC($threads);
     } elseif (count($threads) == 0) {
         $html .= Xml::tags('div', array('class' => 'lqt-no-threads'), wfMessage('lqt-no-threads')->parse());
     }
     $html .= $pager->getNavigationBar();
     $html .= Xml::openElement('div', array('class' => 'lqt-threads lqt-talkpage-threads'));
     $this->output->addHTML($html);
     foreach ($threads as $t) {
         $this->showThread($t);
     }
     $this->output->addHTML(Xml::closeElement('div') . $pager->getNavigationBar() . Xml::closeElement('div'));
     return false;
 }
 /**
  * {@inheritDoc}
  */
 public function shouldConvert(Title $sourceTitle)
 {
     // If we have LiquidThreads filter out any pages with that enabled.  They should
     // be converted separately.
     if (class_exists('LqtDispatch')) {
         if (\LqtDispatch::isLqtPage($sourceTitle)) {
             $this->logger->info("Skipping LQT enabled page, conversion must be done with convertLqtPagesWithProp.php or convertLqtPageOnLocalWiki.php: {$sourceTitle}");
             return false;
         }
     }
     if (!$this->meetsSubpageRequirements($sourceTitle) || $this->hasNoConvertTemplate($sourceTitle)) {
         return false;
     }
     return true;
 }
Esempio n. 12
0
 /**
  * Send a message to a user
  * Modified from the TranslationNotification extension
  *
  * @return bool
  */
 function sendMessage()
 {
     $title = $this->normalizeTitle($this->title);
     if ($title === null) {
         return true;
         // Skip it
     }
     $this->title = $title;
     if (self::isOptedOut($this->title)) {
         $this->logLocalSkip('skipoptout');
         return true;
         // Oh well.
     }
     // If we're sending to a User:/User talk: page, make sure the user exists.
     // Redirects are automatically followed in getLocalTargets
     if ($title->getNamespace() == NS_USER || $title->getNamespace() == NS_USER_TALK) {
         $user = User::newFromName($title->getBaseText());
         if (!$user->getId()) {
             // Does not exist
             $this->logLocalSkip('skipnouser');
             return true;
         }
     }
     // See if we should use LiquidThreads
     if (class_exists('LqtDispatch') && LqtDispatch::isLqtPage($title)) {
         // This is the same check that LQT uses internally
         $this->addLQTThread();
     } else {
         $this->editPage();
     }
     return true;
 }
Esempio n. 13
0
 /**
  * @param $title Title
  * @param $types
  * @return bool
  */
 static function getProtectionTypes($title, &$types)
 {
     $isLqtPage = LqtDispatch::isLqtPage($title);
     $isThread = $title->getNamespace() == NS_LQT_THREAD;
     if (!$isLqtPage && !$isThread) {
         return true;
     }
     if ($isLqtPage) {
         $types[] = 'newthread';
         $types[] = 'reply';
     }
     if ($isThread) {
         $types[] = 'reply';
     }
     return true;
 }
 function show()
 {
     $this->output->addModules('ext.liquidThreads');
     $article = $this->talkpage;
     if (!LqtDispatch::isLqtPage($article->getTitle())) {
         $this->output->addWikiMsg('lqt-not-discussion-page');
         return false;
     }
     $this->output->setPageTitle($this->title->getPrefixedText());
     // Expose feed links.
     global $wgFeedClasses;
     $apiParams = array('action' => 'feedthreads', 'type' => 'replies|newthreads', 'talkpage' => $this->title->getPrefixedText());
     $urlPrefix = wfScript('api') . '?';
     foreach ($wgFeedClasses as $format => $class) {
         $theseParams = $apiParams + array('feedformat' => $format);
         $url = $urlPrefix . wfArrayToCGI($theseParams);
         $this->output->addFeedLink($format, $url);
     }
     $linker = class_exists('DummyLinker') ? new DummyLinker() : new Linker();
     if ($this->request->getBool('lqt_inline')) {
         $this->doInlineEditForm();
         return false;
     }
     $this->output->addHTML(Xml::openElement('div', array('class' => 'lqt-talkpage')));
     // Search!
     if ($this->request->getCheck('lqt_search')) {
         $q = $this->request->getText('lqt_search');
         $q .= ' ondiscussionpage:' . $article->getTitle()->getPrefixedText();
         $params = array('search' => $q, 'fulltext' => 1, 'ns' . NS_LQT_THREAD => 1);
         $t = SpecialPage::getTitleFor('Search');
         $url = $t->getLocalURL(wfArrayToCGI($params));
         $this->output->redirect($url);
         return true;
     }
     if ($this->shouldShow('header')) {
         $this->showHeader();
     }
     global $wgLang, $wgBetterDirectionality;
     if ($wgBetterDirectionality) {
         // This closes the div of mw-content-ltr/rtl containing lang and dir attributes
         $this->output->addHTML(Html::closeElement('div') . Html::openElement('div', array('class' => 'lqt-talkpage', 'lang' => $wgLang->getCode(), 'dir' => wfUILang()->getDir())));
     }
     $html = '';
     // Set up a per-page header for new threads, search box, and sorting stuff.
     $talkpageHeader = '';
     if (Thread::canUserPost($this->user, $this->talkpage)) {
         $newThreadText = wfMsgExt('lqt_new_thread', 'parseinline');
         $newThreadLink = $linker->link($this->title, $newThreadText, array('lqt_talkpage' => $this->talkpage->getTitle()->getPrefixedText()), array('lqt_method' => 'talkpage_new_thread'), array('known'));
         $newThreadLink = Xml::tags('strong', array('class' => 'lqt_start_discussion'), $newThreadLink);
         $talkpageHeader .= $newThreadLink;
     }
     $talkpageHeader .= $this->getSearchBox();
     $talkpageHeader .= $this->showTalkpageViewOptions($article);
     $talkpageHeader = Xml::tags('div', array('class' => 'lqt-talkpage-header'), $talkpageHeader);
     if ($this->shouldShow('options')) {
         $this->output->addHTML($talkpageHeader);
     } elseif ($this->shouldShow('simplenew')) {
         $this->output->addHTML($newThreadLink);
     }
     if ($this->methodApplies('talkpage_new_thread')) {
         $params = array('class' => 'lqt-new-thread lqt-edit-form');
         $this->output->addHTML(Xml::openElement('div', $params));
         $this->showNewThreadForm($this->talkpage);
         $this->output->addHTML(Xml::closeElement('div'));
     } else {
         $this->output->addHTML(Xml::tags('div', array('class' => 'lqt-new-thread lqt-edit-form'), ''));
     }
     $pager = $this->getPager();
     $threads = $this->getPageThreads($pager);
     if (count($threads) > 0 && $this->shouldShow('toc')) {
         $html .= $this->getTOC($threads);
     } elseif (count($threads) == 0) {
         $html .= Xml::tags('div', array('class' => 'lqt-no-threads'), wfMsgExt('lqt-no-threads', 'parseinline'));
     }
     $html .= $pager->getNavigationBar();
     $html .= Xml::openElement('div', array('class' => 'lqt-threads lqt-talkpage-threads'));
     $this->output->addHTML($html);
     foreach ($threads as $t) {
         $this->showThread($t);
     }
     $this->output->addHTML(Xml::closeElement('div') . $pager->getNavigationBar() . Xml::closeElement('div'));
     // Workaround for bug 25077
     global $wgOut, $wgUser;
     # Skin::setTitle was removed in 1.18, it already shares the same source of title with $wgOut.
     if (method_exists('Skin', 'setTitle')) {
         $sk = $wgUser->getSkin();
         $sk->setTitle($wgOut->getTitle());
     }
     return false;
 }