/** * If requested title doesn't exist, redirect to duplicate title (same name but different case) if exists. * NOTE: As of MediaWiki 1.18.0, $article is NULL * @param Title $title * @param type $article * @param type $output * @param type $user * @param type $request * @param type $mediaWiki * @return boolean */ public static function redirectDuplicate(&$title, $article, &$output, &$user, $request, $mediaWiki) { if ($title->getNamespace() != NS_SPECIAL && !$title->isKnown() && ($duplicate = TitleKey::exactMatchTitle($title))) { wfDebugLog('preventduplicate', "{$title->getPrefixedDBkey()} asked, doesn't exist, suggest to use {$duplicate->getPrefixedDBkey()} instead"); $title = $duplicate; } return true; }
private function getTargetURL(Title $title) { global $wgCreatePageEditExisting, $wgCreatePageUseVisualEditor; $isKnown = $title->isKnown(); $query = array(); if (!$isKnown || $wgCreatePageEditExisting) { # Preload is not yet supported by VisualEditor, but probably will be eventually. # See https://phabricator.wikimedia.org/T51622 $query['preload'] = $this->getRequest()->getText('preload', ''); if (!$isKnown) { $query['redlink'] = '1'; } if ($wgCreatePageUseVisualEditor) { $query['veaction'] = 'edit'; } else { $query['action'] = 'edit'; } } return $title->getLocalUrl($query); }
/** * Check if this page is something we're going to be showing * some sort of sensible content for. If we return false, page * views (plain action=view) will return an HTTP 404 response, * so spiders and robots can know they're following a bad link. * * @return bool */ public function hasViewableContent() { return $this->mTitle->isKnown(); }
/** * Builds an array with tab definition * * @param Title $title Page Where the tab links to * @param string|array $message Message key or an array of message keys (will fall back) * @param bool $selected Display the tab as selected * @param string $query Query string attached to tab URL * @param bool $checkEdit Check if $title exists and mark with .new if one doesn't * * @return array */ function tabAction($title, $message, $selected, $query = '', $checkEdit = false) { $classes = array(); if ($selected) { $classes[] = 'selected'; } if ($checkEdit && !$title->isKnown()) { $classes[] = 'new'; if ($query !== '') { $query = 'action=edit&redlink=1&' . $query; } else { $query = 'action=edit&redlink=1'; } } // wfMessageFallback will nicely accept $message as an array of fallbacks // or just a single key $msg = wfMessageFallback($message)->setContext($this->getContext()); if (is_array($message)) { // for hook compatibility just keep the last message name $message = end($message); } if ($msg->exists()) { $text = $msg->text(); } else { global $wgContLang; $text = $wgContLang->getConverter()->convertNamespace(MWNamespace::getSubject($title->getNamespace())); } $result = array(); if (!Hooks::run('SkinTemplateTabAction', array(&$this, $title, $message, $selected, $checkEdit, &$classes, &$query, &$text, &$result))) { return $result; } return array('class' => implode(' ', $classes), 'text' => $text, 'href' => $title->getLocalURL($query), 'primary' => true); }
/** * Does the Title currently exists * * This method allows a subclass to override this check * (For example, wantedfiles, would want to check if the file exists * not just that a page in the file namespace exists). * * This will only control if the link is crossed out. Whether or not the link * is blue vs red is controlled by if the title exists. * * @note This will only be run if the page is cached (ie $wgMiserMode = true) * unless forceExistenceCheck() is true. * @since 1.24 * @return bool */ protected function existenceCheck(Title $title) { return $title->isKnown(); }
/** * Hook handler for LinkBegin * @param Linker $oLinker * @param Title $oTarget * @param string $sHtml * @param array $aCustomAttribs * @param array $aQuery * @param array $aOptions * @param string $sRet * @return boolean Always true to keep hook running */ public function onLinkBegin($oLinker, $oTarget, &$sHtml, &$aCustomAttribs, &$aQuery, &$aOptions, &$sRet) { if (in_array('known', $aOptions)) { return true; } if (!in_array('broken', $aOptions)) { //It's not marked as "known" and not as "broken" so we have to check if ($oTarget->isKnown()) { return true; } } $aExNs = BsConfig::get('MW::PageTemplates::ExcludeNs'); if (in_array($oTarget->getNamespace(), $aExNs)) { return true; } if (!isset($aQuery['preload'])) { $aQuery['action'] = 'view'; } return true; }
/** * * @param Title $title */ public static function isTitleValidForBackground($title) { return $title instanceof Title && $title->isKnown() && $title->isLocal() && $title->getNamespace() == NS_FILE && ($file = wfLocalFile($title)) != null && $file->exists() && self::isExtensionValidForBackground($file->getExtension()); }
/** * If the page is in a Wikiplace namespace, search the owner and answer. * If the page is in a Wikiplace namespace but cannot be found, state only * * admins users are owner * @todo should not be a hook. Should be... * WpWikiPlaces->hasOwner($user) * and called by getUserPermissionError() * * @param Title $title * @param User $user * @param boolean */ public static function isOwner($title, $user, &$result) { $namespace = $title->getNamespace(); $db_key = $title->getDBkey(); if (WpPage::isPublic($namespace, $db_key) || !WpPage::isInWikiplaceNamespaces($namespace) || !$title->isKnown() || WpPage::isAdmin($namespace, $db_key)) { return true; // skip } $article_id = $title->getArticleID(); $user_id = $user->getId(); $result = WpPage::isOwner($article_id, $user); wfDebugLog('wikiplaces-debug', "{$user->getName()}({$user_id}) is" . ($result ? '' : ' not') . " owner of {$title->getPrefixedDBkey()}({$article_id})"); return false; // stop hook processing, because we have the answer }
/** * Grant rights as needed later by $title->checkPagesRestriction(). Hook userCan is always called * in function $title->checkPermissionHooks(), before calling checkPagesRestriction(). So, it ensures * that correct rights are available when checkPagesRestriction() will be executed. * @global array $wgProtectOwnCacheUserCan * @param Title $title * @param User $user * @param string $action * @param boolean $result * @return boolean */ function poUserCan($title, &$user, $action, &$result) { if ($title->getNamespace() == NS_SPECIAL || !$title->isKnown()) { return true; // skip } // userCan is called before title->checkPageRestrictions $act = $action; //just in case, but shouldn't occur if ($action == '' || $action == 'view') { $act = 'read'; } // update user right about the current title, especially the owner and member rights // (not pretty, but needed because this is the way MW core checks protection...) poGrantProtectionRights($title, $user); // fetch restriction and user groups from MediaWiki core $title_restrictions = $title->getRestrictions($act); // if no restrictions, return "the $user can do $action on $title" if ($title_restrictions === array()) { wfDebugLog('ProtectOwn', 'UserCan: action not restricted, resume other hooks' . ' title="' . $title->getPrefixedDBkey() . '"[' . $title->getArticleId() . ']' . ' isKnown()=' . ($title->isKnown() ? 'YES' : 'NO') . ' user="******"[' . $user->getID() . ']' . ' action="' . $action . '"'); return true; // continue userCan hooks processing (another hook can still disallow user) } //check if cached global $wgProtectOwnCacheUserCan; if (isset($wgProtectOwnCacheUserCan[$user->getID()][$title->getArticleId()][$act])) { $result = $wgProtectOwnCacheUserCan[$user->getID()][$title->getArticleId()][$act]; /* wfDebugLog( 'ProtectOwn', 'UserCan: '.($result?'YES':'NO').', CACHE HIT ' .' title="'.$title->getPrefixedDBkey().'"['.$title->getArticleId().']' .' isKnown()='.($title->isKnown()?'YES':'NO') .' user="******"['.$user->getID().']' .' action="'.$action.'"' ); */ return false; //stop processing } // there should only be one restriction level per page/action // (in MediaWiki core, if multiple levels, user has to be in every restricted level... not very logic, but it's like that) // if not... well, we handle this the same way as in MediaWiki core, but that's bad! if (count($title_restrictions) != 1) { wfDebugLog('ProtectOwn', 'UserCan: /!\\ few restricted level for only a page/action ' . '("' . $act . '" restricted to "' . implode(',', $title_restrictions) . '")'); wfDebug('Restrictions.extension>>UserCan(): /!\\ few restricted level for only a page/action ' . '("' . $act . '" restricted to "' . implode(',', $title_restrictions) . '")'); } // please kick this foreach or change Title.php>checkPageRestrictions() code... we should not test intersection !!! $result = true; foreach ($title_restrictions as $title_restriction) { // intersection test = if we know that user is not allowed for one, do not test other restrictions if (!$result) { break; } // exit foreach if ($title_restriction == 'owner') { // check if the current user is the owner $result = poIsOwner($title, $user); } elseif ($title_restriction == 'member') { // check if the current user is a member $result = poIsMember($title, $user) || poIsOwner($title, $user); } else { // allow if $user is member of the group $result = poIsUserInGroup($user, $title_restriction); } } // if the user has a bypass, she is allowed if ($user->isAllowed(PROTECTOWN_BYPASS)) { wfDebugLog('ProtectOwn', 'UserCan: YES, user has "' . PROTECTOWN_BYPASS . '" right'); $result = true; // allowed } // store to cache $wgProtectOwnCacheUserCan[$user->getID()][$title->getArticleId()][$act] = $result; wfDebugLog('ProtectOwn', 'UserCan: ' . ($result ? 'YES' : 'NO') . ', CACHE MISS ' . ' title="' . $title->getPrefixedDBkey() . '"[' . $title->getArticleId() . ']' . ' isKnown()=' . ($title->isKnown() ? 'YES' : 'NO') . ' user="******"[' . $user->getID() . ']' . ' action="' . $action . '"' . ' restrictions="' . implode(',', $title_restrictions) . '"'); // stop processing return false; }