/** * @param WebRequest $request * * @return array("<overall message>","<select value>","<text field value>") */ function loadDataFromRequest($request) { if ($request->getCheck($this->mName)) { $list = $request->getText($this->mName); $text = $request->getText($this->mName . '-other'); // Should be built the same as in mediawiki.htmlform.js if ($list == 'other') { $final = $text; } elseif (!in_array($list, $this->mFlatOptions, true)) { # User has spoofed the select form to give an option which wasn't # in the original offer. Sulk... $final = $text; } elseif ($text == '') { $final = $list; } else { $final = $list . $this->msg('colon-separator')->inContentLanguage()->text() . $text; } } else { $final = $this->getDefault(); $list = 'other'; $text = $final; foreach ($this->mFlatOptions as $option) { $match = $option . $this->msg('colon-separator')->inContentLanguage()->text(); if (strpos($text, $match) === 0) { $list = $option; $text = substr($text, strlen($match)); break; } } } return array($final, $list, $text); }
/** * Constructs a page from WebRequest. * This interface is a big klunky. * @param $request WebRequest * @return TranslationEditPage */ public static function newFromRequest(WebRequest $request) { $title = Title::newFromText($request->getText('page')); if (!$title) { return null; } $obj = new self($title); $obj->suggestions = $request->getText('suggestions'); return $obj; }
/** * @param WebRequest $request * * @return string */ function loadDataFromRequest($request) { if ($request->getCheck($this->mName)) { $val = $request->getText($this->mName); if ($val === 'other') { $val = $request->getText($this->mName . '-other'); } return $val; } else { return $this->getDefault(); } }
public function __construct(WebRequest $request) { $this->mType = $request->getText('type'); $this->mOid = preg_replace('/\\?.*$/', '', $request->getText('oid')); parse_str(urldecode($request->getText('params')), $this->mParams); $this->mCb = $request->getInt('cb'); if (!empty($this->mParams['noexternals'])) { $this->mNoExternals = true; } if (!empty($this->mParams['forceprofile'])) { $this->mForceProfile = true; } }
/** * Basic setup and applies the limiting factors from the WebRequest object. * @param WebRequest $request * @private */ function setupQuery($request) { $page = $this->db->tableName('page'); $user = $this->db->tableName('user'); $this->joinClauses = array("LEFT OUTER JOIN {$page} ON log_namespace=page_namespace AND log_title=page_title"); $this->whereClauses = array('user_id=log_user'); $this->limitType($request->getVal('type')); $this->limitUser($request->getText('user')); $this->limitTitle($request->getText('page')); $this->limitTime($request->getVal('from'), '>='); $this->limitTime($request->getVal('until'), '<='); list($this->limit, $this->offset) = $request->getLimitOffset(); }
/** * Constructor * @param WebRequest $request A WebRequest object passed by reference */ function LoginForm(&$request, $par = '') { global $wgLang, $wgAllowRealName, $wgEnableEmail; global $wgAuth; $this->mType = $par == 'signup' ? $par : $request->getText('type'); # Check for [[Special:Userlogin/signup]] $this->mName = $request->getText('wpName'); $this->mPassword = $request->getText('wpPassword'); $this->mRetype = $request->getText('wpRetype'); $this->mRetypeEmail = $request->getText('wpRetypeEmail'); $this->mDomain = $request->getText('wpDomain'); $this->mReturnTo = $request->getVal('returnto'); $this->mAutoRedirect = $request->getVal('autoredirect'); $this->mFromSite = $request->getVal('sitelogin'); $this->mCookieCheck = $request->getVal('wpCookieCheck'); $this->mPosted = $request->wasPosted(); $this->mCreateaccount = $request->getCheck('wpCreateaccount'); $this->mCreateaccountMail = $request->getCheck('wpCreateaccountMail') && $wgEnableEmail; $this->mMailmypassword = $request->getCheck('wpMailmypassword') && $wgEnableEmail; $this->mLoginattempt = $request->getCheck('wpLoginattempt'); $this->mAction = $request->getVal('action'); $this->mRemember = $request->getCheck('wpRemember'); $this->mLanguage = $request->getText('uselang'); if ($wgEnableEmail) { $this->mEmail = $request->getText('wpEmail'); } else { $this->mEmail = ''; } if ($wgAllowRealName && $request->getText('wpUseRealNameAsDisplay') == "on") { $this->mRealName = @strip_tags($request->getText('wpRealName')); } else { $this->mRealName = ''; } if (!$wgAuth->validDomain($this->mDomain)) { $this->mDomain = 'invaliddomain'; } $wgAuth->setDomain($this->mDomain); # When switching accounts, it sucks to get automatically logged out if ($this->mReturnTo == $wgLang->specialPage('Userlogout')) { $this->mReturnTo = ''; } if ($this->mAutoRedirect == $wgLang->specialPage('Userlogout')) { $this->mAutoRedirect = ''; } }
/** * Basic setup and applies the limiting factors from the WebRequest object. * @param WebRequest $request * @private */ function setupQuery($request) { $page = $this->db->tableName('page'); $user = $this->db->tableName('user'); $this->joinClauses = array("LEFT OUTER JOIN {$page} ON log_namespace=page_namespace AND log_title=page_title", "INNER JOIN {$user} ON user_id=log_user"); $this->whereClauses = array(); $this->limitType($request->getVal('type')); $this->limitUser($request->getText('user')); $this->limitTitle($request->getText('page'), $request->getBool('pattern')); $this->limitTime($request->getVal('from'), '>='); $this->limitTime($request->getVal('until'), '<='); list($this->limit, $this->offset) = $request->getLimitOffset(); // XXX This all needs to use Pager, ugly hack for now. global $wgMiserMode; if ($wgMiserMode) { $this->offset = min($this->offset, 10000); } }
/** * @param WebRequest $request */ function initializeFromRequest(&$request) { $upload = $request->getUpload('wpUploadFile'); $desiredDestName = $request->getText('wpDestFile'); if (!$desiredDestName) { $desiredDestName = $upload->getName(); } $this->initialize($desiredDestName, $upload); }
/** * @param WebRequest $request * @return string|MWRestrictions Restrictions object or original string if invalid */ function loadDataFromRequest($request) { if (!$request->getCheck($this->mName)) { return $this->getDefault(); } $value = rtrim($request->getText($this->mName), "\r\n"); $ips = $value === '' ? [] : explode(PHP_EOL, $value); try { return MWRestrictions::newFromArray(['IPAddresses' => $ips]); } catch (InvalidArgumentException $e) { return $value; } }
public static function serve(WebRequest $request) { try { switch ($request->getText('type')) { case 'one': $builder = new AssetsManagerOneBuilder($request); break; case 'group': $builder = new AssetsManagerGroupBuilder($request); break; case 'groups': $builder = new AssetsManagerGroupsBuilder($request); break; case 'sass': $builder = new AssetsManagerSassBuilder($request); break; default: Wikia::log(__METHOD__, false, "Unknown type: {$_SERVER['REQUEST_URI']}", true); Wikia::log(__METHOD__, false, AssetsManager::getRequestDetails(), true); throw new Exception('Unknown type.'); } } catch (Exception $e) { header('HTTP/1.1 404 Not Found'); echo $e->getMessage(); return; } $headers = array(); if ($builder->getContentType()) { $headers['Content-Type'] = $builder->getContentType(); } // BugId:31327 $headers['Vary'] = $builder->getVary(); $cacheDuration = $builder->getCacheDuration(); if ($cacheDuration > 0) { $headers['Expires'] = gmdate('D, d M Y H:i:s \\G\\M\\T', strtotime($cacheDuration . ' seconds')); $headers['X-Pass-Cache-Control'] = $builder->getCacheMode() . ', max-age=' . $cacheDuration; $headers['Cache-Control'] = $builder->getCacheMode() . ', max-age=' . $cacheDuration; } $headers['Last-Modified'] = gmdate('D, d M Y H:i:s \\G\\M\\T'); foreach ($headers as $k => $v) { header($k . ': ' . $v); } echo $builder->getContent(); }
/** * Constructor * @param WebRequest $request A WebRequest object passed by reference */ function LoginForm(&$request) { global $wgLang, $wgAllowRealName, $wgEnableEmail; global $wgAuth; $this->mType = $request->getText('type'); $this->mName = $request->getText('wpName'); $this->mPassword = $request->getText('wpPassword'); $this->mRetype = $request->getText('wpRetype'); $this->mDomain = $request->getText('wpDomain'); $this->mReturnTo = $request->getVal('returnto'); $this->mCookieCheck = $request->getVal('wpCookieCheck'); $this->mPosted = $request->wasPosted(); $this->mCreateaccount = $request->getCheck('wpCreateaccount'); $this->mCreateaccountMail = $request->getCheck('wpCreateaccountMail') && $wgEnableEmail; $this->mMailmypassword = $request->getCheck('wpMailmypassword') && $wgEnableEmail; $this->mLoginattempt = $request->getCheck('wpLoginattempt'); $this->mAction = $request->getVal('action'); $this->mRemember = $request->getCheck('wpRemember'); $this->mLanguage = $request->getText('uselang'); if ($wgEnableEmail) { $this->mEmail = $request->getText('wpEmail'); } else { $this->mEmail = ''; } if ($wgAllowRealName) { $this->mRealName = $request->getText('wpRealName'); } else { $this->mRealName = ''; } if (!$wgAuth->validDomain($this->mDomain)) { $this->mDomain = 'invaliddomain'; } $wgAuth->setDomain($this->mDomain); # When switching accounts, it sucks to get automatically logged out if ($this->mReturnTo == $wgLang->specialPage('Userlogout')) { $this->mReturnTo = ''; } }
/** * Determine the target of the block, and the type of target * TODO: should be in Block.php? * @param $par String subpage parameter passed to setup, or data value from * the HTMLForm * @param $request WebRequest optionally try and get data from a request too * @return array( User|string|null, Block::TYPE_ constant|null ) */ public static function getTargetAndType($par, WebRequest $request = null) { $i = 0; $target = null; while (true) { switch ($i++) { case 0: # The HTMLForm will check wpTarget first and only if it doesn't get # a value use the default, which will be generated from the options # below; so this has to have a higher precedence here than $par, or # we could end up with different values in $this->target and the HTMLForm! if ($request instanceof WebRequest) { $target = $request->getText('wpTarget', null); } break; case 1: $target = $par; break; case 2: if ($request instanceof WebRequest) { $target = $request->getText('ip', null); } break; case 3: # B/C @since 1.18 if ($request instanceof WebRequest) { $target = $request->getText('wpBlockAddress', null); } break; case 4: break 2; } list($target, $type) = Block::parseTarget($target); if ($type !== null) { return array($target, $type); } } return array(null, null); }
/** * Get the value that this input has been set to from a posted form, * or the input's default value if it has not been set. * * @param WebRequest $request * @return string The value */ function loadDataFromRequest($request) { if ($request->getCheck($this->mName)) { return $request->getText($this->mName); } else { return $this->getDefault(); } }
/** * @param WebRequest $request * @param TranslatablePage $page */ protected function handlePriorityLanguages(WebRequest $request, TranslatablePage $page) { // new priority languages $npLangs = rtrim(trim($request->getVal('prioritylangs')), ','); $npForce = $request->getCheck('forcelimit') ? 'on' : 'off'; $npReason = trim($request->getText('priorityreason')); // Normalize $npLangs = array_map('trim', explode(',', $npLangs)); $npLangs = array_unique($npLangs); // Remove invalid language codes. $languages = Language::fetchLanguageNames(); foreach ($npLangs as $index => $language) { if (!array_key_exists($language, $languages)) { unset($npLangs[$index]); } } $npLangs = implode(',', $npLangs); if ($npLangs === '') { $npLangs = false; $npForce = false; $npReason = false; } $groupId = $page->getMessageGroupId(); // old priority languages $opLangs = TranslateMetadata::get($groupId, 'prioritylangs'); $opForce = TranslateMetadata::get($groupId, 'priorityforce'); $opReason = TranslateMetadata::get($groupId, 'priorityreason'); TranslateMetadata::set($groupId, 'prioritylangs', $npLangs); TranslateMetadata::set($groupId, 'priorityforce', $npForce); TranslateMetadata::set($groupId, 'priorityreason', $npReason); if ($opLangs !== $npLangs || $opForce !== $npForce || $opReason !== $npReason) { $params = array('languages' => $npLangs, 'force' => $npForce, 'reason' => $npReason); $entry = new ManualLogEntry('pagetranslation', 'prioritylanguages'); $entry->setPerformer($this->getUser()); $entry->setTarget($page->getTitle()); $entry->setParameters($params); $entry->setComment($npReason); $logid = $entry->insert(); $entry->publish($logid); } }
private function printForm(&$parameters, WebRequest &$request) { global $wgOut, $sfgFormPrinter; // Prepare parameters for SFFormPrinter::formHTML // there is no ONE target page $targetTitle = null; // formDefinition $formName = $request->getText('form'); // if query string did not contain these variables, try the URL if ($formName === '') { $queryparts = explode('/', $parameters); $formName = isset($queryparts[0]) ? $queryparts[0] : null; // if the form name wasn't in the URL either, throw an error if (is_null($formName) || $formName === '') { throw new SPSException(SPSUtils::buildMessage('spserror-noformname')); } } $formTitle = Title::makeTitleSafe(SF_NS_FORM, $formName); if (!$formTitle->exists()) { throw new SPSException(SPSUtils::buildMessage('spserror-formunknown', $formName)); } $formArticle = new Article($formTitle); $formDefinition = StringUtils::delimiterReplace('<noinclude>', '</noinclude>', '', $formArticle->getContent()); // formSubmitted $formSubmitted = false; // pageContents $pageContents = null; // get 'preload' query value, if it exists if ($request->getCheck('preload')) { $pageContents = SFFormUtils::getPreloadedText($request->getVal('preload')); } else { // let other extensions preload the page, if they want wfRunHooks('sfEditFormPreloadText', array(&$pageContents, $targetTitle, $formTitle)); } // pageIsSource $pageIsSource = $pageContents != null; // pageNameFormula // parse the form to see if it has a 'page name' value set $matches; if (preg_match('/{{{info.*page name\\s*=\\s*(.*)}}}/m', $formDefinition, $matches)) { $pageNameElements = SFUtils::getFormTagComponents($matches[1]); $pageNameFormula = $pageNameElements[0]; } else { return 'sf_formedit_badurl'; } // get the iterator parameters $iteratorData = $this->buildIteratorParameters($request); // Call SFFormPrinter::formHTML list($formText, $javascriptText, $dataText, $formPageTitle, $generatedPageName) = $sfgFormPrinter->formHTML($formDefinition, $formSubmitted, $pageIsSource, $formArticle->getID(), $pageContents, '', $pageNameFormula); // Set Special page main header; // override the default title for this page if a title was specified in the form if ($formPageTitle != null) { $wgOut->setPageTitle($formPageTitle); } else { $wgOut->setPageTitle(SPSUtils::buildMessage('sf_formedit_createtitlenotarget', $formTitle->getText())); } $preFormHtml = ''; wfRunHooks('sfHTMLBeforeForm', array(&$targetTitle, &$preFormHtml)); $text = '<form name="createbox" id="sfForm" action="" method="post" class="createbox">' . $preFormHtml . "\n" . SFFormUtils::hiddenFieldHTML('iteratordata', $iteratorData) . $formText; SFUtils::addJavascriptAndCSS(); if (!empty($javascriptText)) { $wgOut->addScript(' <script type="text/javascript">' . "\n{$javascriptText}\n" . '</script>' . "\n"); } $wgOut->addHTML($text); return null; }
public function fetchValuesFromRequest(WebRequest $r, $values = false) { if (!$values) { $values = array_keys($this->options); } foreach ($values as $name) { $default = $this->options[$name]['default']; $type = $this->options[$name]['type']; switch ($type) { case self::BOOL: $value = $r->getBool($name, $default); break; case self::INT: $value = $r->getInt($name, $default); break; case self::STRING: $value = $r->getText($name, $default); break; case self::INTNULL: $value = $r->getIntOrNull($name); break; default: throw new MWException('Unsupported datatype'); } if ($value !== null) { $this->options[$name]['value'] = $value === $default ? null : $value; } } }
/** * Entry point for SpecialUpload * @param WebRequest $request */ public function initializeFromRequest(&$request) { $desiredDestName = $request->getText('wpDestFile'); if (!$desiredDestName) { $desiredDestName = $request->getText('wpUploadFileURL'); } $this->initialize($desiredDestName, trim($request->getVal('wpUploadFileURL')), false); }
/** * @param WebRequest $request */ public function initializeFromRequest(&$request) { // sends wpSessionKey as a default when wpFileKey is missing $fileKey = $request->getText('wpFileKey', $request->getText('wpSessionKey')); // chooses one of wpDestFile, wpUploadFile, filename in that order. $desiredDestName = $request->getText('wpDestFile', $request->getText('wpUploadFile', $request->getText('filename'))); $this->initialize($fileKey, $desiredDestName); }
# Used for some maintenance scripts; user session cookies can screw things up # when the database is in an in-between state. $wgUser = new User(); # Prevent loading User settings from the DB. $wgUser->setLoaded(true); } else { $wgUser = null; wfRunHooks('AutoAuthenticate', array(&$wgUser)); if ($wgUser === null) { $wgUser = User::loadFromSession(); } } wfProfileOut($fname . '-User'); wfProfileIn($fname . '-language2'); // wgLanguageCode now specifically means the UI language $wgLanguageCode = $wgRequest->getText('uselang', ''); if ($wgLanguageCode == '') { $wgLanguageCode = $wgUser->getOption('language'); } # Validate $wgLanguageCode, which will soon be sent to an eval() if (empty($wgLanguageCode) || !preg_match('/^[a-z]+(-[a-z]+)?$/', $wgLanguageCode)) { $wgLanguageCode = $wgContLanguageCode; } $wgLangClass = 'Language' . str_replace('-', '_', ucfirst($wgLanguageCode)); if ($wgLangClass == $wgContLangClass) { $wgLang =& $wgContLang; } else { wfSuppressWarnings(); // Preload base classes to work around APC/PHP5 bug include_once "{$IP}/languages/{$wgLangClass}.deps.php"; include_once "{$IP}/languages/{$wgLangClass}.php";
public static function serve(WebRequest $request) { $type = $request->getText('type'); try { switch ($type) { case 'one': $builder = new AssetsManagerOneBuilder($request); break; case 'group': $builder = new AssetsManagerGroupBuilder($request); break; case 'groups': $builder = new AssetsManagerGroupsBuilder($request); break; case 'sass': $builder = new AssetsManagerSassBuilder($request); break; case 'sasses': $builder = new AssetsManagerSassesBuilder($request); break; default: Wikia::log(__METHOD__, false, "Unknown type: {$_SERVER['REQUEST_URI']}", true); Wikia::log(__METHOD__, false, AssetsManager::getRequestDetails(), true); throw new Exception('Unknown type.'); } } catch (Exception $e) { header('HTTP/1.1 404 Not Found'); echo $e->getMessage(); return; } // do not log illegal request type (one/group/groups/sass supported only) - not to pollute // logs Transaction::setEntryPoint(Transaction::ENTRY_POINT_ASSETS_MANAGER); if (function_exists('newrelic_disable_autorum')) { newrelic_disable_autorum(); } $headers = array(); if ($builder->getContentType()) { $headers['Content-Type'] = $builder->getContentType(); } // BugId:31327 $headers['Vary'] = $builder->getVary(); $cacheDuration = $builder->getCacheDuration(); // render the response try { $content = $builder->getContent(); } catch (Exception $e) { // return HTTP 503 in case of SASS processing error (BAC-592) // Varnish will cache such response for 5 seconds header('HTTP/1.1 503'); // log exception messages \Wikia\Logger\WikiaLogger::instance()->error('AssetsManagerServer::serve failed', ['type' => $type, 'exception' => $e]); // emit full message on devboxes only global $wgDevelEnvironment; $content = !empty($wgDevelEnvironment) ? $msg = $e->getMessage() : '/* SASS processing failed! */'; } if ($cacheDuration > 0) { $headers['Cache-Control'] = 'public, max-age=' . $cacheDuration['server']; $headers['X-Pass-Cache-Control'] = 'public, max-age=' . $cacheDuration['client']; } $headers['Last-Modified'] = gmdate('D, d M Y H:i:s \\G\\M\\T'); // Add X-Served-By and X-Backend-Response-Time response headers to MediaWiki pages // See BAC-550 for details // @macbre global $wgRequestTime; $headers['X-Served-By'] = wfHostname(); $headers['X-Backend-Response-Time'] = round(microtime(true) - $wgRequestTime, 3); foreach ($headers as $k => $v) { header($k . ': ' . $v); } echo $content; }
/** * Get the default viewer type. Is also changeable from the url. Format of get request: <full_url>?viewertype=zv= */ private function getViewerType(WebRequest $request) { if ($request->getText('viewertype') !== '') { if (strpos($request->getText('viewertype'), 'js') !== false) { return 'js'; } else { return 'zv'; } } else { return 'zv'; } }
/** * @param WebRequest $request * @return string */ function formatForSave(WebRequest $request) { $text = ''; // Do not replace spaces by underscores for magic words. See bug T48613 $replaceSpace = $request->getVal('module') !== 'magic'; foreach (array_keys($this->data) as $group) { foreach ($this->getIterator($group) as $key) { $data = $request->getText($this->getKeyForEdit($key)); // Make a nice array out of the submit with trimmed values. $data = array_map('trim', explode(',', $data)); if ($replaceSpace) { // Normalise: Replace spaces with underscores. $data = str_replace(' ', '_', $data); } // Create final format. $data = implode(', ', $data); if ($data !== '') { $text .= "{$key} = {$data}\n"; } } } return $text; }
/** * Try to concat prefix + mainPart, or return the main part if prefix field not available * @param WebRequest $request * @return mixed string, or '' if both prefix and mainPart are not available from request object */ public static function getDestinationFileName($request) { // chooses one of WpDestFileNameMainPart, wpUploadFile, filename in that order. $mainPart = $request->getText('wpDestFileMainPart', $request->getText('wpDestFile', $request->getText('wpUploadFile', $request->getText('filename')))); $prefix = $request->getText('wpDestFilePrefix'); return $prefix ? $prefix . '.' . $mainPart : $mainPart; }
/** * doUpdateTags * * @access private * @author eloy@wikia-inc.com * * @param WebRequest $request WebRequest instance * @param Boolean $tag_id set if removing, tag_id of removing tag * * @return mixed info when change, null when not changed */ private function doUpdateTags(&$request, $tag_id = false) { #global $wgOut; wfProfileIn(__METHOD__); $msg = false; $wfTags = new WikiFactoryTags($this->mWiki->city_id); if ($tag_id) { $tagName = $request->getText("wpTagName"); $newTags = $this->mTags->removeTagsById(array($tag_id)); #$wgOut->addHTML('<pre>' . print_r($newTags,1) . "</pre>" ); $msg = "Tag {$tagName} removed"; } else { $stag = $request->getText("wpTag", false); if ($stag) { $before = $wfTags->getTags(true); // from master $after = $wfTags->addTagsByName($stag); $diff = array_diff($after, $before); #$wgOut->addHTML('<pre>' ); #$wgOut->addHTML( print_r($before,1) ."\n" ); #$wgOut->addHTML( print_r($after,1) ."\n"); #$wgOut->addHTML( print_r($diff,1) ."\n"); #$wgOut->addHTML( "</pre>"); $msg = "Added new tags: " . implode(", ", $diff); } else { $msg = "Nothing to add"; } } wfProfileOut(__METHOD__); return Wikia::successbox($msg); }
/** * Decodes form data sent through form-elements generated by * its complement, getPOFormBox(). UIs may overload both to change form * parameters. * * @param WebRequest $wgRequest * @return array */ protected function processPOFormBox(WebRequest $wgRequest) { $postring = $wgRequest->getText('po'); $poArray = array(); if ($postring !== '') { // parameters from HTML input fields $ps = explode("\n", $postring); // params separated by newlines here (compatible with text-input for printouts) foreach ($ps as $param) { // add initial ? if omitted (all params considered as printouts) $param = trim($param); if ($param !== '' && $param[0] != '?') { $param = '?' . $param; } $poArray[] = $param; } } return $poArray; }
/** * Filter an input field through a Unicode de-armoring process if it * came from an old browser with known broken Unicode editing issues. * * @param WebRequest $request * @param string $field * @return string * @access private */ function safeUnicodeInput($request, $field) { $text = rtrim($request->getText($field)); return $request->getBool('safemode') ? $this->unmakesafe($text) : $text; }
/** * Get a list of suggested titles * * @param WebRequest $request * @return bool|Object|string * * @author Inez Korczyński <*****@*****.**> * @author Robert Elwell <*****@*****.**> */ static function getLinkSuggest(WebRequest $request) { global $wgContLang, $wgContentNamespaces, $wgMemc, $wgLinkSuggestLimit; $measurement = T::start(__FUNCTION__); wfProfileIn(__METHOD__); $isMobile = F::app()->checkSkin('wikiamobile'); // trim passed query and replace spaces by underscores // - this is how MediaWiki store article titles in database $query = urldecode(trim($request->getText('query'))); $query = str_replace(' ', '_', $query); if ($isMobile) { $key = wfMemcKey(__METHOD__, md5($query . '_' . $request->getText('format') . $request->getText('nospecial', '')), 'WikiaMobile'); } else { $key = wfMemcKey(__METHOD__, md5($query . '_' . $request->getText('format') . $request->getText('nospecial', ''))); } if (strlen($query) < 3) { // enforce minimum character limit on server side $out = self::getEmptyResponse($request->getText('format')); } else { if ($cached = $wgMemc->get($key)) { $out = $cached; } } if (isset($out)) { wfProfileOut(__METHOD__); return $out; } // Allow the calling-code to specify a namespace to search in (which at the moment, could be overridden by having prefixed text in the input field). // NOTE: This extension does parse titles to try to find things in other namespaces, but that actually doesn't work in practice because jQuery // Autocomplete will stop making requests after it finds 0 results. So if you start to type "Category" and there is no page beginning // with "Cate", it will not even make the call to LinkSuggest. $namespace = $request->getVal('ns'); // explode passed query by ':' to get namespace and article title $queryParts = explode(':', $query, 2); if (count($queryParts) == 2) { $query = $queryParts[1]; $namespaceName = $queryParts[0]; // try to get the index by canonical name first $namespace = MWNamespace::getCanonicalIndex(strtolower($namespaceName)); if ($namespace == null) { // if we failed, try looking through localized namespace names $namespace = array_search(ucfirst($namespaceName), $wgContLang->getNamespaces()); if (empty($namespace)) { // getting here means our "namespace" is not real and can only be part of the title $query = $namespaceName . ':' . $query; } } if ($namespace !== null && $query === '') { $out = self::getEmptyResponse($request->getText('format')); wfProfileOut(__METHOD__); return $out; } } // which namespaces to search in? if (empty($namespace)) { // search only within content namespaces (BugId:4625) - default behaviour $namespaces = $wgContentNamespaces; } else { // search only within a given namespace $namespaces = array($namespace); } //limit the result only to this namespace $namespaceFilter = $request->getVal('nsfilter'); if (strlen($namespaceFilter) > 0) { $namespaces = array($namespaceFilter); } if (!empty($namespaceFilter) && $namespace != $namespaceFilter) { $out = self::getEmptyResponse($request->getText('format')); wfProfileOut(__METHOD__); return $out; } $query = addslashes($query); $db = wfGetDB(DB_SLAVE, 'search'); $redirects = array(); $results = array(); $exactMatchRow = null; $queryLower = strtolower($query); $sql1Measurement = T::start([__FUNCTION__, "sql-1"]); $res = $db->select(array('querycache', 'page'), array('page_namespace', 'page_title', 'page_is_redirect'), array('qc_title = page_title', 'qc_namespace = page_namespace', 'page_is_redirect = 0', 'qc_type' => 'Mostlinked', "(qc_title LIKE '{$query}%' or LOWER(qc_title) LIKE '{$queryLower}%')", 'qc_namespace' => $namespaces), __METHOD__, array('ORDER BY' => 'qc_value DESC', 'LIMIT' => $wgLinkSuggestLimit)); self::formatResults($db, $res, $query, $redirects, $results, $exactMatchRow); $sql1Measurement->stop(); if (count($namespaces) > 0) { $commaJoinedNamespaces = count($namespaces) > 1 ? array_shift($namespaces) . ', ' . implode(', ', $namespaces) : $namespaces[0]; } $pageNamespaceClause = isset($commaJoinedNamespaces) ? 'page_namespace IN (' . $commaJoinedNamespaces . ') AND ' : ''; if (count($results) < $wgLinkSuggestLimit) { /** * @var string $pageTitlePrefilter this condition is able to use name_title index. It's added only for performance reasons. * It uses fact that page titles can't start with lowercase letter. */ $pageTitlePrefilter = ""; if (strlen($queryLower) >= 2) { $pageTitlePrefilter = "(\n\t\t\t\t\t\t\t( page_title " . $db->buildLike(strtoupper($queryLower[0]) . strtolower($queryLower[1]), $db->anyString()) . " ) OR\n\t\t\t\t\t\t\t( page_title " . $db->buildLike(strtoupper($queryLower[0]) . strtoupper($queryLower[1]), $db->anyString()) . " ) ) AND "; } else { if (strlen($queryLower) >= 1) { $pageTitlePrefilter = "( page_title " . $db->buildLike(strtoupper($queryLower[0]), $db->anyString()) . " ) AND "; } } // TODO: use $db->select helper method $sql = "SELECT page_len, page_id, page_title, rd_title, page_namespace, rd_namespace, page_is_redirect\n\t\t\t\t\t\tFROM page\n\t\t\t\t\t\tLEFT JOIN redirect ON page_is_redirect = 1 AND page_id = rd_from\n\t\t\t\t\t\tLEFT JOIN querycache ON qc_title = page_title AND qc_type = 'BrokenRedirects'\n\t\t\t\t\t\tWHERE {$pageTitlePrefilter} {$pageNamespaceClause} (LOWER(page_title) LIKE '{$queryLower}%')\n\t\t\t\t\t\t\tAND qc_type IS NULL\n\t\t\t\t\t\tLIMIT " . $wgLinkSuggestLimit * 3; // we fetch 3 times more results to leave out redirects to the same page $sql2Measurement = T::start([__FUNCTION__, "sql-2"]); $res = $db->query($sql, __METHOD__); self::formatResults($db, $res, $query, $redirects, $results, $exactMatchRow); $sql2Measurement->stop(); } if ($exactMatchRow !== null) { /* @var StdClass $exactMatchRow */ $row = $exactMatchRow; $titleFormatted = self::formatTitle($row->page_namespace, $row->page_title); if ($row->page_is_redirect == 0) { // remove any instances of original array's value $resultsFlipped = array_flip($results); unset($resultsFlipped[$titleFormatted]); $results = array_flip($resultsFlipped); array_unshift($results, $titleFormatted); $flippedRedirs = array_flip($redirects); if (isset($flippedRedirs[$titleFormatted])) { unset($redirects[$flippedRedirs[$titleFormatted]]); } } else { $redirTitleFormatted = self::formatTitle($row->page_namespace, $row->rd_title); // remove any instances of original array's value $resultsFlipped = array_flip($results); unset($resultsFlipped[$redirTitleFormatted]); $results = array_flip($resultsFlipped); array_unshift($results, $redirTitleFormatted); $redirects[$redirTitleFormatted] = $titleFormatted; } } $db->freeResult($res); if ($request->getText('nospecial', 0) != 1) { // bugid 29988: include special pages // (registered in SpecialPage::$mList, not in the DB like a normal page) if ($namespaces == array('-1') && strlen($query) > 0) { $specialPagesByAlpha = SpecialPageFactory::getList(); $specialPagesByAlpha = get_object_vars($specialPagesByAlpha); ksort($specialPagesByAlpha, SORT_STRING); array_walk($specialPagesByAlpha, function ($val, $key) use(&$results, $query) { if (strtolower(substr($key, 0, strlen($query))) === strtolower($query)) { $results[] = self::formatTitle('-1', $key); } }); } } // Overwrite canonical title with redirect title for all formats self::replaceResultIfRedirected($results, $redirects); $format = $request->getText('format'); if ($format == 'json') { $result_values = array_values($results); if ($isMobile) { $out = json_encode(array(array_splice($result_values, 0, 10), array_splice($redirects, -1, 1))); } else { $out = json_encode(array('query' => $request->getText('query'), 'suggestions' => $result_values, 'redirects' => $redirects)); } } elseif ($format == 'array') { $out = $results; } else { // legacy: LinkSuggest.js uses plain text $out = implode("\n", $results); } // 15 minutes times four (one hour, but easier to slice and dice) $wgMemc->set($key, $out, 4 * 900); wfProfileOut(__METHOD__); return $out; }