/**
  * Deal with external interwiki links: add exitstitial class to them if needed
  *
  * @param $skin
  * @param $target
  * @param $options
  * @param $text
  * @param $attribs
  * @param $ret
  *
  * @return bool
  */
 public static function onLinkEnd($skin, Title $target, array $options, &$text, array &$attribs, &$ret)
 {
     if ($target->isExternal()) {
         static::handleExternalLink($attribs['href'], $attribs);
     }
     return true;
 }
Example #2
0
 /**
  * Does various sanity checks that the move is
  * valid. Only things based on the two titles
  * should be checked here.
  *
  * @return Status
  */
 public function isValidMove()
 {
     global $wgContentHandlerUseDB;
     $status = new Status();
     if ($this->oldTitle->equals($this->newTitle)) {
         $status->fatal('selfmove');
     }
     if (!$this->oldTitle->isMovable()) {
         $status->fatal('immobile-source-namespace', $this->oldTitle->getNsText());
     }
     if ($this->newTitle->isExternal()) {
         $status->fatal('immobile-target-namespace-iw');
     }
     if (!$this->newTitle->isMovable()) {
         $status->fatal('immobile-target-namespace', $this->newTitle->getNsText());
     }
     $oldid = $this->oldTitle->getArticleID();
     if (strlen($this->newTitle->getDBkey()) < 1) {
         $status->fatal('articleexists');
     }
     if ($this->oldTitle->getDBkey() == '' || !$oldid || $this->newTitle->getDBkey() == '') {
         $status->fatal('badarticleerror');
     }
     # The move is allowed only if (1) the target doesn't exist, or
     # (2) the target is a redirect to the source, and has no history
     # (so we can undo bad moves right after they're done).
     if ($this->newTitle->getArticleID() && !$this->isValidMoveTarget()) {
         $status->fatal('articleexists');
     }
     // Content model checks
     if (!$wgContentHandlerUseDB && $this->oldTitle->getContentModel() !== $this->newTitle->getContentModel()) {
         // can't move a page if that would change the page's content model
         $status->fatal('bad-target-model', ContentHandler::getLocalizedName($this->oldTitle->getContentModel()), ContentHandler::getLocalizedName($this->newTitle->getContentModel()));
     } elseif (!ContentHandler::getForTitle($this->oldTitle)->canBeUsedOn($this->newTitle)) {
         $status->fatal('content-not-allowed-here', ContentHandler::getLocalizedName($this->oldTitle->getContentModel()), $this->newTitle->getPrefixedText());
     }
     // Image-specific checks
     if ($this->oldTitle->inNamespace(NS_FILE)) {
         $status->merge($this->isValidFileMove());
     }
     if ($this->newTitle->inNamespace(NS_FILE) && !$this->oldTitle->inNamespace(NS_FILE)) {
         $status->fatal('nonfile-cannot-move-to-file');
     }
     // Hook for extensions to say a title can't be moved for technical reasons
     Hooks::run('MovePageIsValidMove', [$this->oldTitle, $this->newTitle, $status]);
     return $status;
 }
Example #3
0
 /**
  * @return Title
  */
 private function getRbTitle()
 {
     if ($this->mTitleObj !== null) {
         return $this->mTitleObj;
     }
     $params = $this->extractRequestParams();
     $this->mTitleObj = Title::newFromText($params['title']);
     if (!$this->mTitleObj || $this->mTitleObj->isExternal()) {
         $this->dieUsageMsg(array('invalidtitle', $params['title']));
     }
     if (!$this->mTitleObj->exists()) {
         $this->dieUsageMsg('notanarticle');
     }
     return $this->mTitleObj;
 }
Example #4
0
 /**
  * @param array $params
  *
  * @return Title
  */
 private function getRbTitle(array $params)
 {
     if ($this->mTitleObj !== null) {
         return $this->mTitleObj;
     }
     $this->requireOnlyOneParameter($params, 'title', 'pageid');
     if (isset($params['title'])) {
         $this->mTitleObj = Title::newFromText($params['title']);
         if (!$this->mTitleObj || $this->mTitleObj->isExternal()) {
             $this->dieUsageMsg(array('invalidtitle', $params['title']));
         }
     } elseif (isset($params['pageid'])) {
         $this->mTitleObj = Title::newFromID($params['pageid']);
         if (!$this->mTitleObj) {
             $this->dieUsageMsg(array('nosuchpageid', $params['pageid']));
         }
     }
     if (!$this->mTitleObj->exists()) {
         $this->dieUsageMsg('notanarticle');
     }
     return $this->mTitleObj;
 }
 /**
  * Does various sanity checks that the move is
  * valid. Only things based on the two titles
  * should be checked here.
  *
  * @return Status
  */
 public function isValidMove()
 {
     global $wgContentHandlerUseDB;
     $status = new Status();
     if ($this->oldTitle->equals($this->newTitle)) {
         $status->fatal('selfmove');
     }
     if (!$this->oldTitle->isMovable()) {
         $status->fatal('immobile-source-namespace', $this->oldTitle->getNsText());
     }
     if ($this->newTitle->isExternal()) {
         $status->fatal('immobile-target-namespace-iw');
     }
     if (!$this->newTitle->isMovable()) {
         $status->fatal('immobile-target-namespace', $this->newTitle->getNsText());
     }
     $oldid = $this->oldTitle->getArticleID();
     if (strlen($this->newTitle->getDBkey()) < 1) {
         $status->fatal('articleexists');
     }
     if ($this->oldTitle->getDBkey() == '' || !$oldid || $this->newTitle->getDBkey() == '') {
         $status->fatal('badarticleerror');
     }
     // Content model checks
     if (!$wgContentHandlerUseDB && $this->oldTitle->getContentModel() !== $this->newTitle->getContentModel()) {
         // can't move a page if that would change the page's content model
         $status->fatal('bad-target-model', ContentHandler::getLocalizedName($this->oldTitle->getContentModel()), ContentHandler::getLocalizedName($this->newTitle->getContentModel()));
     }
     // Image-specific checks
     if ($this->oldTitle->inNamespace(NS_FILE)) {
         $status->merge($this->isValidFileMove());
     }
     if ($this->newTitle->inNamespace(NS_FILE) && !$this->oldTitle->inNamespace(NS_FILE)) {
         $status->fatal('nonfile-cannot-move-to-file');
     }
     // Hook for extensions to say a title can't be moved for technical reasons
     Hooks::run('MovePageIsValidMove', array($this->oldTitle, $this->newTitle, $status));
     return $status;
 }
Example #6
0
 /**
  * Add a title to the link cache, return the page_id or zero if non-existent
  *
  * @param Title $nt Title object to add
  * @return int Page ID or zero
  */
 public function addLinkObj(Title $nt)
 {
     global $wgContentHandlerUseDB;
     $key = $nt->getPrefixedDBkey();
     if ($this->isBadLink($key) || $nt->isExternal()) {
         return 0;
     }
     $id = $this->getGoodLinkID($key);
     if ($id != 0) {
         return $id;
     }
     if ($key === '') {
         return 0;
     }
     // Some fields heavily used for linking...
     $db = $this->mForUpdate ? wfGetDB(DB_MASTER) : wfGetDB(DB_SLAVE);
     $fields = array('page_id', 'page_len', 'page_is_redirect', 'page_latest');
     if ($wgContentHandlerUseDB) {
         $fields[] = 'page_content_model';
     }
     $row = $db->selectRow('page', $fields, array('page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey()), __METHOD__);
     if ($row !== false) {
         $this->addGoodLinkObjFromRow($nt, $row);
         $id = intval($row->page_id);
     } else {
         $this->addBadLinkObj($nt);
         $id = 0;
     }
     return $id;
 }
 /**
  * Return prefixed text form of title, but using the content language's
  * canonical namespace. This skips any special-casing such as gendered
  * user namespaces -- which while useful, are not yet listed in the
  * XML "<siteinfo>" data so are unsafe in export.
  *
  * @param Title $title
  * @return string
  * @since 1.18
  */
 public static function canonicalTitle(Title $title)
 {
     if ($title->isExternal()) {
         return $title->getPrefixedText();
     }
     global $wgContLang;
     $prefix = str_replace('_', ' ', $wgContLang->getNsText($title->getNamespace()));
     if ($prefix !== '') {
         $prefix .= ':';
     }
     return $prefix . $title->getText();
 }
 /**
  * Validates watchlist entry
  *
  * @param Title $title
  * @param int $namespace
  * @param String $dbKey 
  * @return bool: Whether this item is valid
  */
 private function checkTitle($title, $namespace, $dbKey)
 {
     if ($title && ($title->isExternal() || $title->getNamespace() < 0)) {
         $title = false;
         // unrecoverable
     }
     if (!$title || $title->getNamespace() != $namespace || $title->getDBkey() != $dbKey) {
         $this->badItems[] = array($title, $namespace, $dbKey);
     }
     return (bool) $title;
 }
Example #9
0
 /**
  * Get the Title object or URL to use for a redirect. We use Title
  * objects for same-wiki, non-special redirects and URLs for everything
  * else.
  * @param Title $rt Redirect target
  * @return bool|Title|string False, Title object of local target, or string with URL
  */
 public function getRedirectURL($rt)
 {
     if (!$rt) {
         return false;
     }
     if ($rt->isExternal()) {
         if ($rt->isLocal()) {
             // Offsite wikis need an HTTP redirect.
             // This can be hard to reverse and may produce loops,
             // so they may be disabled in the site configuration.
             $source = $this->mTitle->getFullURL('redirect=no');
             return $rt->getFullURL(['rdfrom' => $source]);
         } else {
             // External pages without "local" bit set are not valid
             // redirect targets
             return false;
         }
     }
     if ($rt->isSpecialPage()) {
         // Gotta handle redirects to special pages differently:
         // Fill the HTTP response "Location" header and ignore the rest of the page we're on.
         // Some pages are not valid targets.
         if ($rt->isValidRedirectTarget()) {
             return $rt->getFullURL();
         } else {
             return false;
         }
     }
     return $rt;
 }
Example #10
0
 /**
  * Record a local or interwiki inline link for saving in future link tables.
  *
  * @param $title Title object
  * @param $id Mixed: optional known page_id so we can skip the lookup
  */
 function addLink(Title $title, $id = null)
 {
     if ($title->isExternal()) {
         // Don't record interwikis in pagelinks
         $this->addInterwikiLink($title);
         return;
     }
     $ns = $title->getNamespace();
     $dbk = $title->getDBkey();
     if ($ns == NS_MEDIA) {
         // Normalize this pseudo-alias if it makes it down here...
         $ns = NS_FILE;
     } elseif ($ns == NS_SPECIAL) {
         // We don't record Special: links currently
         // It might actually be wise to, but we'd need to do some normalization.
         return;
     } elseif ($dbk === '') {
         // Don't record self links -  [[#Foo]]
         return;
     }
     if (!isset($this->mLinks[$ns])) {
         $this->mLinks[$ns] = array();
     }
     if (is_null($id)) {
         $id = $title->getArticleID();
     }
     $this->mLinks[$ns][$dbk] = $id;
 }
Example #11
0
File: Linker.php Project: paladox/2
 /**
  * Generates a link to the given Title
  *
  * @note This is only public for technical reasons. It's not intended for use outside Linker.
  *
  * @param Title $title
  * @param string $text
  * @param string|null $wikiId Id of the wiki to link to (if not the local wiki),
  *  as used by WikiMap.
  * @param string|string[] $options See the $options parameter in Linker::link.
  *
  * @return string HTML link
  */
 public static function makeCommentLink(Title $title, $text, $wikiId = null, $options = array())
 {
     if ($wikiId !== null && !$title->isExternal()) {
         $link = Linker::makeExternalLink(WikiMap::getForeignURL($wikiId, $title->getPrefixedText(), $title->getFragment()), $text, false);
     } else {
         $link = Linker::link($title, $text, array(), array(), $options);
     }
     return $link;
 }
 /**
  * Get the final destination of a redirect
  *
  * @param Title $title
  *
  * @return bool If the specified title is not a redirect, or if it is a circular redirect
  */
 public static function getFinalDestination($title)
 {
     $dbw = wfGetDB(DB_MASTER);
     // Circular redirect check
     $seenTitles = array();
     $dest = false;
     while (true) {
         $titleText = $title->getPrefixedDBkey();
         if (isset($seenTitles[$titleText])) {
             wfDebug(__METHOD__, "Circular redirect detected, aborting\n");
             return false;
         }
         $seenTitles[$titleText] = true;
         if ($title->isExternal()) {
             // If the target is interwiki, we have to break early (bug 40352).
             // Otherwise it will look up a row in the local page table
             // with the namespace/page of the interwiki target which can cause
             // unexpected results (e.g. X -> foo:Bar -> Bar -> .. )
             break;
         }
         $row = $dbw->selectRow(array('redirect', 'page'), array('rd_namespace', 'rd_title', 'rd_interwiki'), array('rd_from=page_id', 'page_namespace' => $title->getNamespace(), 'page_title' => $title->getDBkey()), __METHOD__);
         if (!$row) {
             # No redirect from here, chain terminates
             break;
         } else {
             $dest = $title = Title::makeTitle($row->rd_namespace, $row->rd_title, '', $row->rd_interwiki);
         }
     }
     return $dest;
 }
Example #13
0
 /**
  * @param Title $title Title object, must be an interwiki link
  * @throws MWException If given invalid input
  */
 public function addInterwikiLink($title)
 {
     if (!$title->isExternal()) {
         throw new MWException('Non-interwiki link passed, internal parser error.');
     }
     $prefix = $title->getInterwiki();
     if (!isset($this->mInterwikiLinks[$prefix])) {
         $this->mInterwikiLinks[$prefix] = array();
     }
     $this->mInterwikiLinks[$prefix][$title->getDBkey()] = 1;
 }
 static function linkBegin($skin, Title $target, &$text, array &$attribs, &$query, &$options, &$ret)
 {
     if ($target->isExternal()) {
         $args = '';
         $u = $target->getFullURL();
         $link = $target->getPrefixedURL();
         if ('' == $text) {
             $text = $target->getPrefixedText();
         }
         $style = Linker::getInterwikiLinkAttributes($link, $text, 'extiw');
         if ($text == 'RTENOTITLE') {
             // 2223
             $text = $u = $link;
             $args .= '_fcknotitle="true" ';
         }
         $t = "<a {$args}href=\"{$u}\"{$style}>{$text}</a>";
         wfProfileOut(__METHOD__);
         $ret = $t;
         return false;
     }
     return true;
 }
Example #15
0
 /**
  * Returns the array of attributes used when linking to the Title $target
  *
  * @param Title $target
  * @param array $attribs
  * @param array $options
  *
  * @return array
  */
 private static function linkAttribs($target, $attribs, $options)
 {
     global $wgUser;
     $defaults = array();
     if (!in_array('noclasses', $options)) {
         # Now build the classes.
         $classes = array();
         if (in_array('broken', $options)) {
             $classes[] = 'new';
         }
         if ($target->isExternal()) {
             $classes[] = 'extiw';
         }
         if (!in_array('broken', $options)) {
             # Avoid useless calls to LinkCache (see r50387)
             $colour = self::getLinkColour($target, $wgUser->getStubThreshold());
             if ($colour !== '') {
                 $classes[] = $colour;
                 # mw-redirect or stub
             }
         }
         if ($classes != array()) {
             $defaults['class'] = implode(' ', $classes);
         }
     }
     # Get a default title attribute.
     if ($target->getPrefixedText() == '') {
         # A link like [[#Foo]].  This used to mean an empty title
         # attribute, but that's silly.  Just don't output a title.
     } elseif (in_array('known', $options)) {
         $defaults['title'] = $target->getPrefixedText();
     } else {
         $defaults['title'] = wfMessage('red-link-title', $target->getPrefixedText())->text();
     }
     # Finally, merge the custom attribs with the default ones, and iterate
     # over that, deleting all "false" attributes.
     $ret = array();
     $merged = Sanitizer::mergeAttributes($defaults, $attribs);
     foreach ($merged as $key => $val) {
         # A false value suppresses the attribute, and we don't want the
         # href attribute to be overridden.
         if ($key != 'href' && $val !== false) {
             $ret[$key] = $val;
         }
     }
     return $ret;
 }
Example #16
0
 /**
  * Add a title to the link cache, return the page_id or zero if non-existent
  *
  * @param Title $nt Title object to add
  * @return int
  */
 public function addLinkObj($nt)
 {
     global $wgAntiLockFlags, $wgContentHandlerUseDB;
     wfProfileIn(__METHOD__);
     $key = $nt->getPrefixedDBkey();
     if ($this->isBadLink($key) || $nt->isExternal()) {
         wfProfileOut(__METHOD__);
         return 0;
     }
     $id = $this->getGoodLinkID($key);
     if ($id != 0) {
         wfProfileOut(__METHOD__);
         return $id;
     }
     if ($key === '') {
         wfProfileOut(__METHOD__);
         return 0;
     }
     # Some fields heavily used for linking...
     if ($this->mForUpdate) {
         $db = wfGetDB(DB_MASTER);
         if (!($wgAntiLockFlags & ALF_NO_LINK_LOCK)) {
             $options = array('FOR UPDATE');
         } else {
             $options = array();
         }
     } else {
         $db = wfGetDB(DB_SLAVE);
         $options = array();
     }
     $f = array('page_id', 'page_len', 'page_is_redirect', 'page_latest');
     if ($wgContentHandlerUseDB) {
         $f[] = 'page_content_model';
     }
     $s = $db->selectRow('page', $f, array('page_namespace' => $nt->getNamespace(), 'page_title' => $nt->getDBkey()), __METHOD__, $options);
     # Set fields...
     if ($s !== false) {
         $this->addGoodLinkObjFromRow($nt, $s);
         $id = intval($s->page_id);
     } else {
         $this->addBadLinkObj($nt);
         $id = 0;
     }
     wfProfileOut(__METHOD__);
     return $id;
 }