protected function parseWikitext($title, $newRevId) { $apiParams = array('action' => 'parse', 'page' => $title->getPrefixedDBkey(), 'oldid' => $newRevId, 'prop' => 'text|revid|categorieshtml|displaytitle|modules|jsconfigvars'); $api = new ApiMain(new DerivativeRequest($this->getRequest(), $apiParams, false), true); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $result = $api->getResult()->getResultData(null, array('BC' => array(), 'Types' => array(), 'Strip' => 'all')); } else { $result = $api->getResultData(); } $content = isset($result['parse']['text']['*']) ? $result['parse']['text']['*'] : false; $categorieshtml = isset($result['parse']['categorieshtml']['*']) ? $result['parse']['categorieshtml']['*'] : false; $links = isset($result['parse']['links']) ? $result['parse']['links'] : array(); $revision = Revision::newFromId($result['parse']['revid']); $timestamp = $revision ? $revision->getTimestamp() : wfTimestampNow(); $displaytitle = isset($result['parse']['displaytitle']) ? $result['parse']['displaytitle'] : false; $modules = isset($result['parse']['modules']) ? $result['parse']['modules'] : array(); $jsconfigvars = isset($result['parse']['jsconfigvars']) ? $result['parse']['jsconfigvars'] : array(); if ($content === false || strlen($content) && $revision === null) { return false; } if ($displaytitle !== false) { // Escape entities as in OutputPage::setPageTitle() $displaytitle = Sanitizer::normalizeCharReferences(Sanitizer::removeHTMLtags($displaytitle)); } return array('content' => $content, 'categorieshtml' => $categorieshtml, 'basetimestamp' => $timestamp, 'starttimestamp' => wfTimestampNow(), 'displayTitleHtml' => $displaytitle, 'modules' => $modules, 'jsconfigvars' => $jsconfigvars); }
public function testCrossDomainMangling() { $config = new HashConfig(array('MangleFlashPolicy' => false)); $context = new RequestContext(); $context->setConfig(new MultiConfig(array($config, $context->getConfig()))); $main = new ApiMain($context); $main->getResult()->addValue(null, null, '< Cross-Domain-Policy >'); if (!function_exists('wfOutputHandler')) { function wfOutputHandler($s) { return $s; } } $printer = $main->createPrinterByName('php'); ob_start('wfOutputHandler'); $printer->initPrinter(); $printer->execute(); $printer->closePrinter(); $ret = ob_get_clean(); $this->assertSame('a:1:{i:0;s:23:"< Cross-Domain-Policy >";}', $ret); $config->set('MangleFlashPolicy', true); $printer = $main->createPrinterByName('php'); ob_start('wfOutputHandler'); try { $printer->initPrinter(); $printer->execute(); $printer->closePrinter(); ob_end_clean(); $this->fail('Expected exception not thrown'); } catch (UsageException $ex) { ob_end_clean(); $this->assertSame('This response cannot be represented using format=php. See https://phabricator.wikimedia.org/T68776', $ex->getMessage(), 'Expected exception'); } }
static function saveCat($filename, $category) { global $wgContLang, $wgUser; $mediaString = strtolower($wgContLang->getNsText(NS_FILE)); $title = $mediaString . ':' . $filename; $text = "\n[[" . $category . "]]"; $wgEnableWriteAPI = true; $params = new FauxRequest(array('action' => 'edit', 'section' => 'new', 'title' => $title, 'text' => $text, 'token' => $wgUser->editToken()), true, $_SESSION); $enableWrite = true; // This is set to false by default, in the ApiMain constructor $api = new ApiMain($params, $enableWrite); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $data = $api->getResult()->getResultData(); } else { $data =& $api->getResultData(); } return $mediaString; /* This code does the same and is better, but for some reason it doesn't update the categorylinks table global $wgContLang, $wgUser; $title = Title::newFromText( $filename, NS_FILE ); $page = new WikiPage( $title ); $text = $page->getText(); $text .= "\n\n[[" . $category . "]]"; $summary = wfMessage( 'msu-comment' ); $status = $page->doEditContent( $text, $summary, EDIT_UPDATE, false, $wgUser ); $value = $status->value; $revision = $value['revision']; $page->doEditUpdates( $revision, $wgUser ); return true; */ }
/** * Get the formatter output for the given input data * @param array $params Query parameters * @param array $data Data to encode * @param string $class Printer class to use instead of the normal one * @return string * @throws Exception */ protected function encodeData(array $params, array $data, $class = null) { $context = new RequestContext(); $context->setRequest(new FauxRequest($params, true)); $main = new ApiMain($context); if ($class !== null) { $main->getModuleManager()->addModule($this->printerName, 'format', $class); } $result = $main->getResult(); $result->addArrayType(null, 'default'); foreach ($data as $k => $v) { $result->addValue(null, $k, $v); } $printer = $main->createPrinterByName($this->printerName); $printer->initPrinter(); $printer->execute(); ob_start(); try { $printer->closePrinter(); return ob_get_clean(); } catch (Exception $ex) { ob_end_clean(); throw $ex; } }
/** @dataProvider provideTokenClasses */ public function testTokenRetrieval($id, $class) { // Make sure we have the right to get the token global $wgGroupPermissions; $wgGroupPermissions['*'][$class::getRight()] = true; RequestContext::getMain()->getUser()->clearInstanceCache(); // Reread above global // We should be getting anonymous user token $expected = $class::getToken(); $this->assertNotSame(false, $expected, 'We did not get a valid token'); $actionString = TranslateUtils::getTokenAction($id); $params = wfCgiToArray($actionString); $req = new FauxRequest($params); $api = new ApiMain($req); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $data = $api->getResult()->getResultData(null, array('Strip' => 'all')); } else { $data = $api->getResultData(); } if (isset($data['query'])) { foreach ($data['query']['pages'] as $page) { $this->assertSame($expected, $page[$id . 'token']); } } else { $this->assertArrayHasKey('tokens', $data, 'Result has tokens'); $this->assertSame($expected, $data['tokens'][$id . 'token']); } }
/** * Does the API request and returns the result. * * The returned value is an array containing * - the result data (array) * - the request (WebRequest) * - the session data of the request (array) * - if $appendModule is true, the Api module $module * * @param array $params * @param array|null $session * @param bool $appendModule * @param User|null $user * * @return array */ protected function doApiRequest(array $params, array $session = null, $appendModule = false, User $user = null) { global $wgRequest, $wgUser; if (is_null($session)) { // re-use existing global session by default $session = $wgRequest->getSessionArray(); } // set up global environment if ($user) { $wgUser = $user; } $wgRequest = new FauxRequest($params, true, $session); RequestContext::getMain()->setRequest($wgRequest); RequestContext::getMain()->setUser($wgUser); // set up local environment $context = $this->apiContext->newTestContext($wgRequest, $wgUser); $module = new ApiMain($context, true); // run it! $module->execute(); // construct result $results = array($module->getResult()->getResultData(null, array('Strip' => 'all')), $context->getRequest(), $context->getRequest()->getSessionArray()); if ($appendModule) { $results[] = $module; } return $results; }
public function run() { $scope = RequestContext::importScopedSession($this->params['session']); $context = RequestContext::getMain(); try { $user = $context->getUser(); if (!$user->isLoggedIn()) { $this->setLastError("Could not load the author user from session."); return false; } if (count($_SESSION) === 0) { // Empty session probably indicates that we didn't associate // with the session correctly. Note that being able to load // the user does not necessarily mean the session was loaded. // Most likely cause by suhosin.session.encrypt = On. $this->setLastError("Error associating with user session. " . "Try setting suhosin.session.encrypt = Off"); return false; } UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Poll', 'stage' => 'publish', 'status' => Status::newGood())); $upload = new UploadFromStash($user); // @todo initialize() causes a GET, ideally we could frontload the antivirus // checks and anything else to the stash stage (which includes concatenation and // the local file is thus already there). That way, instead of GET+PUT, there could // just be a COPY operation from the stash to the public zone. $upload->initialize($this->params['filekey'], $this->params['filename']); // Check if the local file checks out (this is generally a no-op) $verification = $upload->verifyUpload(); if ($verification['status'] !== UploadBase::OK) { $status = Status::newFatal('verification-error'); $status->value = array('verification' => $verification); UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Failure', 'stage' => 'publish', 'status' => $status)); $this->setLastError("Could not verify upload."); return false; } // Upload the stashed file to a permanent location $status = $upload->performUpload($this->params['comment'], $this->params['text'], $this->params['watch'], $user); if (!$status->isGood()) { UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Failure', 'stage' => 'publish', 'status' => $status)); $this->setLastError($status->getWikiText()); return false; } // Build the image info array while we have the local reference handy $apiMain = new ApiMain(); // dummy object (XXX) $imageInfo = $upload->getImageInfo($apiMain->getResult()); // Cleanup any temporary local file $upload->cleanupTempFile(); // Cache the info so the user doesn't have to wait forever to get the final info UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Success', 'stage' => 'publish', 'filename' => $upload->getLocalFile()->getName(), 'imageinfo' => $imageInfo, 'status' => Status::newGood())); } catch (MWException $e) { UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Failure', 'stage' => 'publish', 'status' => Status::newFatal('api-error-publishfailed'))); $this->setLastError(get_class($e) . ": " . $e->getText()); // To prevent potential database referential integrity issues. // See bug 32551. MWExceptionHandler::rollbackMasterChangesAndLog($e); return false; } return true; }
/** * Test that the API will accept a FauxRequest and execute. */ public function testApi() { $api = new ApiMain(new FauxRequest(array('action' => 'query', 'meta' => 'siteinfo'))); $api->execute(); $data = $api->getResult()->getResultData(); $this->assertInternalType('array', $data); $this->assertArrayHasKey('query', $data); }
protected function doApiRequest(array $params, array $unused = null, $appendModule = false, User $user = null) { global $wgRequest; $req = new FauxRequest($params, true, $wgRequest->getSession()); $module = new ApiMain($req, true); $module->execute(); return array($module->getResult()->getResultData(null, array('Strip' => 'all')), $req); }
/** * * @param <type> $params the array of keys and values that would have appeared in the URL if this were a normal request. See API documentation * @return <type> */ public function make_fake_request($params) { $request = new FauxRequest($params, true); $api = new ApiMain($request); // Process data & use an output buffer to capture the resutls $api->execute(); $result = $api->getResult(); $data =& $result->getData(); return $data; }
protected function doApiRequest(array $params, array $unused = null, $appendModule = false, User $user = null) { $sessionId = session_id(); session_write_close(); $req = new FauxRequest($params, true, $_SESSION); $module = new ApiMain($req, true); $module->execute(); wfSetupSession($sessionId); return array($module->getResult()->getResultData(null, array('Strip' => 'all')), $req); }
public function run() { $scope = RequestContext::importScopedSession($this->params['session']); $this->addTeardownCallback(function () use(&$scope) { ScopedCallback::consume($scope); // T126450 }); $context = RequestContext::getMain(); $user = $context->getUser(); try { if (!$user->isLoggedIn()) { $this->setLastError("Could not load the author user from session."); return false; } UploadBase::setSessionStatus($user, $this->params['filekey'], ['result' => 'Poll', 'stage' => 'publish', 'status' => Status::newGood()]); $upload = new UploadFromStash($user); // @todo initialize() causes a GET, ideally we could frontload the antivirus // checks and anything else to the stash stage (which includes concatenation and // the local file is thus already there). That way, instead of GET+PUT, there could // just be a COPY operation from the stash to the public zone. $upload->initialize($this->params['filekey'], $this->params['filename']); // Check if the local file checks out (this is generally a no-op) $verification = $upload->verifyUpload(); if ($verification['status'] !== UploadBase::OK) { $status = Status::newFatal('verification-error'); $status->value = ['verification' => $verification]; UploadBase::setSessionStatus($user, $this->params['filekey'], ['result' => 'Failure', 'stage' => 'publish', 'status' => $status]); $this->setLastError("Could not verify upload."); return false; } // Upload the stashed file to a permanent location $status = $upload->performUpload($this->params['comment'], $this->params['text'], $this->params['watch'], $user, isset($this->params['tags']) ? $this->params['tags'] : []); if (!$status->isGood()) { UploadBase::setSessionStatus($user, $this->params['filekey'], ['result' => 'Failure', 'stage' => 'publish', 'status' => $status]); $this->setLastError($status->getWikiText(false, false, 'en')); return false; } // Build the image info array while we have the local reference handy $apiMain = new ApiMain(); // dummy object (XXX) $imageInfo = $upload->getImageInfo($apiMain->getResult()); // Cleanup any temporary local file $upload->cleanupTempFile(); // Cache the info so the user doesn't have to wait forever to get the final info UploadBase::setSessionStatus($user, $this->params['filekey'], ['result' => 'Success', 'stage' => 'publish', 'filename' => $upload->getLocalFile()->getName(), 'imageinfo' => $imageInfo, 'status' => Status::newGood()]); } catch (Exception $e) { UploadBase::setSessionStatus($user, $this->params['filekey'], ['result' => 'Failure', 'stage' => 'publish', 'status' => Status::newFatal('api-error-publishfailed')]); $this->setLastError(get_class($e) . ": " . $e->getMessage()); // To prevent potential database referential integrity issues. // See bug 32551. MWExceptionHandler::rollbackMasterChangesAndLog($e); return false; } return true; }
/** * Gets ApiContributionTracking's response in array format, for the given * $request params. * @global FauxRequest $wgRequest used to shoehorn in our own request vars. * @param <type> $request Request vars we are sending to * ApiContributionTracking. * @return array Values to be returned by ApiContributionTracking */ function getAPIResultData($request) { global $wgRequest; $request['format'] = 'xml'; $request['action'] = 'contributiontracking'; $wgRequest = new FauxRequest($request); $ctapi = new ApiMain($wgRequest, true); $ctapi->execute(); $api_response = $ctapi->getResult()->getData(); return $api_response; }
/** * Returns an array of languages that the page is available in * @return array */ private function getLanguages() { $api = new ApiMain(new DerivativeRequest($this->getRequest(), array('action' => 'query', 'prop' => 'langlinks', 'llprop' => 'url', 'lllimit' => 'max', 'titles' => $this->title->getPrefixedText()))); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $data = (array) $api->getResult()->getResultData(array('query', 'pages'), array('Strip' => 'all')); } else { $data = $api->getResult()->getData(); // Paranoia if (!isset($data['query']['pages'])) { return array(); } $data = $data['query']['pages']; } // Silly strict php $pages = array_values($data); $page = array_shift($pages); if (isset($page['langlinks'])) { // Set the name of each lanugage based on the system list of language names $languageMap = Language::fetchLanguageNames(); $languages = $page['langlinks']; foreach ($page['langlinks'] as $code => $langObject) { if (!isset($languageMap[$langObject['lang']])) { // Bug T93500: DB might still have preantiquated rows with bogus languages unset($languages[$code]); continue; } $langObject['langname'] = $languageMap[$langObject['lang']]; $langObject['url'] = MobileContext::singleton()->getMobileUrl($langObject['url']); $languages[$code] = $langObject; } return $languages; } else { // No langlinks available return array(); } }
public function run() { $scope = RequestContext::importScopedSession($this->params['session']); $context = RequestContext::getMain(); try { $user = $context->getUser(); if (!$user->isLoggedIn()) { $this->setLastError("Could not load the author user from session."); return false; } if (count($_SESSION) === 0) { // Empty session probably indicates that we didn't associate // with the session correctly. Note that being able to load // the user does not necessarily mean the session was loaded. // Most likely cause by suhosin.session.encrypt = On. $this->setLastError("Error associating with user session. " . "Try setting suhosin.session.encrypt = Off"); return false; } UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Poll', 'stage' => 'assembling', 'status' => Status::newGood())); $upload = new UploadFromChunks($user); $upload->continueChunks($this->params['filename'], $this->params['filekey'], $context->getRequest()); // Combine all of the chunks into a local file and upload that to a new stash file $status = $upload->concatenateChunks(); if (!$status->isGood()) { UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Failure', 'stage' => 'assembling', 'status' => $status)); $this->setLastError($status->getWikiText()); return false; } // We have a new filekey for the fully concatenated file $newFileKey = $upload->getLocalFile()->getFileKey(); // Remove the old stash file row and first chunk file $upload->stash->removeFileNoAuth($this->params['filekey']); // Build the image info array while we have the local reference handy $apiMain = new ApiMain(); // dummy object (XXX) $imageInfo = $upload->getImageInfo($apiMain->getResult()); // Cleanup any temporary local file $upload->cleanupTempFile(); // Cache the info so the user doesn't have to wait forever to get the final info UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Success', 'stage' => 'assembling', 'filekey' => $newFileKey, 'imageinfo' => $imageInfo, 'status' => Status::newGood())); } catch (MWException $e) { UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Failure', 'stage' => 'assembling', 'status' => Status::newFatal('api-error-stashfailed'))); $this->setLastError(get_class($e) . ": " . $e->getText()); // To be extra robust. MWExceptionHandler::rollbackMasterChangesAndLog($e); return false; } return true; }
/** * @param Title $title * @param string $submodule * @param array $request * @param bool $requiredBlock * @return array * @throws MWException */ public function flowApi(Title $title, $submodule, array $request, $requiredBlock = false) { $request = new FauxRequest($request + array('action' => 'flow', 'submodule' => $submodule, 'page' => $title->getPrefixedText())); $api = new ApiMain($request); $api->execute(); $flowData = $api->getResult()->getResultData(array('flow', $submodule, 'result')); if ($flowData === null) { throw new MWException("API response has no Flow data"); } $flowData = ApiResult::stripMetadata($flowData); if ($requiredBlock !== false && !isset($flowData[$requiredBlock])) { throw new MWException("No {$requiredBlock} block in API response"); } return $flowData; }
public function run() { $scope = RequestContext::importScopedSession($this->params['session']); $this->addTeardownCallback(function () use(&$scope) { ScopedCallback::consume($scope); // T126450 }); $context = RequestContext::getMain(); $user = $context->getUser(); try { if (!$user->isLoggedIn()) { $this->setLastError("Could not load the author user from session."); return false; } UploadBase::setSessionStatus($user, $this->params['filekey'], ['result' => 'Poll', 'stage' => 'assembling', 'status' => Status::newGood()]); $upload = new UploadFromChunks($user); $upload->continueChunks($this->params['filename'], $this->params['filekey'], new WebRequestUpload($context->getRequest(), 'null')); // Combine all of the chunks into a local file and upload that to a new stash file $status = $upload->concatenateChunks(); if (!$status->isGood()) { UploadBase::setSessionStatus($user, $this->params['filekey'], ['result' => 'Failure', 'stage' => 'assembling', 'status' => $status]); $this->setLastError($status->getWikiText(false, false, 'en')); return false; } // We can only get warnings like 'duplicate' after concatenating the chunks $status = Status::newGood(); $status->value = ['warnings' => $upload->checkWarnings()]; // We have a new filekey for the fully concatenated file $newFileKey = $upload->getStashFile()->getFileKey(); // Remove the old stash file row and first chunk file $upload->stash->removeFileNoAuth($this->params['filekey']); // Build the image info array while we have the local reference handy $apiMain = new ApiMain(); // dummy object (XXX) $imageInfo = $upload->getImageInfo($apiMain->getResult()); // Cleanup any temporary local file $upload->cleanupTempFile(); // Cache the info so the user doesn't have to wait forever to get the final info UploadBase::setSessionStatus($user, $this->params['filekey'], ['result' => 'Success', 'stage' => 'assembling', 'filekey' => $newFileKey, 'imageinfo' => $imageInfo, 'status' => $status]); } catch (Exception $e) { UploadBase::setSessionStatus($user, $this->params['filekey'], ['result' => 'Failure', 'stage' => 'assembling', 'status' => Status::newFatal('api-error-stashfailed')]); $this->setLastError(get_class($e) . ": " . $e->getMessage()); // To be extra robust. MWExceptionHandler::rollbackMasterChangesAndLog($e); return false; } return true; }
private function doTest(array $params, $expected) { $params += array('action' => 'parse'); $req = new FauxRequest($params); $api = new ApiMain($req); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $data = $api->getResult()->getResultData(null, array('BC' => array(), 'Types' => array())); } else { $data = $api->getResultData(); } $this->assertFalse(isset($data['errors'])); $text = preg_replace("/[\r\n]/", '', trim($data['parse']['text']['*'])); $expected = preg_replace("/[\r\n]/", '', trim($expected)); $this->assertEquals($expected, $text); }
public function run() { $scope = RequestContext::importScopedSession($this->params['session']); $context = RequestContext::getMain(); try { $user = $context->getUser(); if (!$user->isLoggedIn()) { $this->setLastError("Could not load the author user from session."); return false; } UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Poll', 'stage' => 'assembling', 'status' => Status::newGood())); $upload = new UploadFromChunks($user); $upload->continueChunks($this->params['filename'], $this->params['filekey'], $context->getRequest()); // Combine all of the chunks into a local file and upload that to a new stash file $status = $upload->concatenateChunks(); if (!$status->isGood()) { UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Failure', 'stage' => 'assembling', 'status' => $status)); $this->setLastError($status->getWikiText()); return false; } // We have a new filekey for the fully concatenated file $newFileKey = $upload->getLocalFile()->getFileKey(); // Remove the old stash file row and first chunk file $upload->stash->removeFileNoAuth($this->params['filekey']); // Build the image info array while we have the local reference handy $apiMain = new ApiMain(); // dummy object (XXX) $imageInfo = $upload->getImageInfo($apiMain->getResult()); // Cleanup any temporary local file $upload->cleanupTempFile(); // Cache the info so the user doesn't have to wait forever to get the final info UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Success', 'stage' => 'assembling', 'filekey' => $newFileKey, 'imageinfo' => $imageInfo, 'status' => Status::newGood())); } catch (MWException $e) { UploadBase::setSessionStatus($this->params['filekey'], array('result' => 'Failure', 'stage' => 'assembling', 'status' => Status::newFatal('api-error-stashfailed'))); $this->setLastError(get_class($e) . ": " . $e->getText()); return false; } return true; }
protected function cacheSourceText($code, $ids) { $cache = wfGetCache(CACHE_DB); $key = wfMemckey(__CLASS__, 'cc', $code); $text = $cache->get($key); if (!is_string($text)) { $snippets = array(); $ids = explode('|', $ids); $len = count($ids); if ($len < 1000) { $this->output("{$code}: {$len} SKIPPED\n"); return ''; } else { $this->output("{$code} PROCESSING\n"); } $time = microtime(true); foreach ($ids as $id) { $params = new FauxRequest(array('pageid' => $id, 'action' => 'parse', 'prop' => 'text', 'disablepp' => 'true')); $api = new ApiMain($params); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $result = $api->getResult()->getResultData(null, array('BC' => array())); } else { $result = $api->getResultData(); } $text = $result['parse']['text']['*']; $text = strip_tags($text); $text = str_replace('!!FUZZY!!', '', $text); $text = preg_replace('/\\$[0-9]/', '', $text); $text = trim($text); $snippets[] = $text; } $text = implode(" ", $snippets); $cache->set($key, $text, 3600 * 24); $delta = microtime(true) - $time; $this->output("{$code} TOOK {$delta}\n"); } else { $this->output("{$code} FROM CACHE\n"); } return $text; }
/** * Return page image and extracts * @param array $pageIds * @return array */ private function getPages($pageIds) { $result = array(); $api = new ApiMain(new DerivativeRequest($this->getRequest(), array('action' => 'query', 'list' => 'allpages', 'pageids' => implode('|', $pageIds), 'prop' => 'extracts|pageimages', 'explaintext' => true, 'exsentences' => self::EXTRACT_SENTENCES, 'exlimit' => count($pageIds), 'exintro' => true, 'piprop' => 'name', 'continue' => ''))); $api->execute(); $data = $api->getResult()->getResultData(null, array('Strip' => 'all')); if (isset($data['query']['pages'])) { $result = $data['query']['pages']; } return $result; }
/** * Makes an internal request to the API to get the needed revision. * * @since 0.3 * * @param Title $title * * @return array or false */ protected function getPageRevision(Title $title) { $revId = PushFunctions::getRevisionToPush($title); $requestData = array('action' => 'query', 'format' => 'json', 'prop' => 'revisions', 'rvprop' => 'timestamp|user|comment|content', 'titles' => $title->getFullText(), 'rvstartid' => $revId, 'rvendid' => $revId); $api = new ApiMain(new FauxRequest($requestData, true), true); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $response = $api->getResult()->getResultData(null, array('BC' => array(), 'Types' => array(), 'Strip' => 'all')); } else { $response = $api->getResultData(); } $revision = false; if ($response !== false && array_key_exists('query', $response) && array_key_exists('pages', $response['query']) && count($response['query']['pages']) > 0) { foreach ($response['query']['pages'] as $key => $value) { $first = $key; break; } if (array_key_exists('revisions', $response['query']['pages'][$first]) && count($response['query']['pages'][$first]['revisions']) > 0) { $revision = $response['query']['pages'][$first]['revisions'][0]; } else { $this->dieUsage(wfMsg('push-special-err-pageget-failed'), 'page-get-failed'); } } else { $this->dieUsage(wfMsg('push-special-err-pageget-failed'), 'page-get-failed'); } return $revision; }
/** * Gets the edit token and timestamps in some ugly array structure. Needs to * be cleaned up. * @throws MWException * @return \array */ protected function getEditInfo() { $params = new FauxRequest(array('action' => 'query', 'prop' => 'info|revisions', 'intoken' => 'edit', 'titles' => $this->getTitle(), 'rvprop' => 'timestamp')); $api = new ApiMain($params); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $data = $api->getResult()->getResultData(); } else { $data = $api->getResultData(); } if (!isset($data['query']['pages'])) { throw new MWException('Api query failed'); } $data = $data['query']['pages']; if (defined('ApiResult::META_CONTENT')) { $data = ApiResult::stripMetadataNonRecursive($data); } $data = array_shift($data); return $data; }
protected function getLangLinks($title) { $apiParams = array('action' => 'query', 'prop' => 'langlinks', 'lllimit' => 500, 'titles' => $title->getPrefixedDBkey(), 'indexpageids' => 1); $api = new ApiMain(new DerivativeRequest($this->getRequest(), $apiParams, false), true); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $result = $api->getResult()->getResultData(null, array('BC' => array(), 'Types' => array(), 'Strip' => 'all')); } else { $result = $api->getResultData(); } if (!isset($result['query']['pages'][$title->getArticleID()]['langlinks'])) { return false; } $langlinks = $result['query']['pages'][$title->getArticleID()]['langlinks']; $langnames = Language::fetchLanguageNames(); foreach ($langlinks as $i => $lang) { $langlinks[$i]['langname'] = $langnames[$langlinks[$i]['lang']]; } return $langlinks; }
/** * Returns the names of the images embedded in a set of pages. * * @param array $pages * * @return array */ protected static function getImagesForPages(array $pages) { $images = array(); $requestData = array('action' => 'query', 'format' => 'json', 'prop' => 'images', 'titles' => implode('|', $pages), 'imlimit' => 500); $api = new ApiMain(new FauxRequest($requestData, true), true); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $response = $api->getResult()->getResultData(null, array('Strip' => 'all')); } else { $response = $api->getResultData(); } if (is_array($response) && array_key_exists('query', $response) && array_key_exists('pages', $response['query'])) { foreach ($response['query']['pages'] as $page) { if (array_key_exists('images', $page)) { foreach ($page['images'] as $image) { $title = Title::newFromText($image['title'], NS_FILE); if (!is_null($title) && $title->getNamespace() == NS_FILE && $title->exists()) { $images[] = $image['title']; } } } } } return array_unique($images); }
function wfParseText($text, $action = 'parse', $format = 'xml') { # Initialise faux request $cliRequest = new FauxRequest(array('action' => &$action, 'text' => &$text, 'format' => &$format)); # Initialise api and execute $processor = new ApiMain($cliRequest); $processor->execute(); # generate result and print the result $printer = $processor->createPrinterByName($format); $result = $processor->getResult(); if ($printer->getNeedsRawData()) { $result->setRawMode(); } $result->cleanUpUTF8(); #$printer->profileIn(); $printer->initPrinter(false); $printer->execute(); $printer->closePrinter(); #$printer->profileOut(); return true; }
protected function saveWikitext($title, $wikitext, $params) { global $wgContentTranslationHighMTCategory; $categories = array(); $sourceLink = '[[:' . $params['from'] . ':Special:Redirect/revision/' . $params['sourcerevision'] . '|' . $params['sourcetitle'] . ']]'; if ($params['categories']) { $categories = explode('|', $params['categories']); } $progress = json_decode($params['progress'], true); if ($progress && $wgContentTranslationHighMTCategory && $this->hasHighMT($progress)) { $categories[] = $wgContentTranslationHighMTCategory; } if (count($categories)) { $categoryText = "\n[[" . implode("]]\n[[", $categories) . ']]'; // If publishing to User namespace, wrap categories in <nowiki> // to avoid blocks by abuse filter. See T88007. if ($title->inNamespace(NS_USER)) { $categoryText = "\n<nowiki>{$categoryText}</nowiki>"; } $wikitext .= $categoryText; } $summary = $this->msg('cx-publish-summary', $sourceLink)->inContentLanguage()->text(); $apiParams = array('action' => 'edit', 'title' => $title->getPrefixedDBkey(), 'text' => $wikitext, 'summary' => $summary); $request = $this->getRequest(); $api = new ApiMain(new DerivativeRequest($request, $apiParams + $request->getValues(), true), true); $api->execute(); return $api->getResult()->getResultData(); }
/** * Collects metadata and additional resources for this page * @param Title $oTitle * @param DOMDocument $oPageDOM * @param array $aParams * @return array array( 'meta' => ..., 'resources' => ...); */ private static function collectData($oTitle, $oPageDOM, $aParams) { $aMeta = array(); $aResources = array('ATTACHMENT' => array(), 'STYLESHEET' => array(), 'IMAGE' => array()); // TODO RBV (01.02.12 13:51): Handle oldid $aCategories = array(); if ($oTitle->exists()) { // TODO RBV (27.06.12 11:47): Throws an exception. Maybe better use try ... catch instead of $oTitle->exists() $aAPIParams = new FauxRequest(array('action' => 'parse', 'page' => $oTitle->getPrefixedText(), 'prop' => 'images|categories|links')); $oAPI = new ApiMain($aAPIParams); $oAPI->execute(); if (defined('ApiResult::META_CONTENT')) { $aResult = $oAPI->getResult()->getResultData(null, array('BC' => array(), 'Types' => array(), 'Strip' => 'all')); } else { $aResult = $oAPI->getResultData(); } foreach ($aResult['parse']['categories'] as $aCat) { $aCategories[] = $aCat['*']; } } /* //For future use... foreach($aResult['parse']['images'] as $sFileName ) { $oImage = RepoGroup::singleton()->getLocalRepo()->newFile( Title::newFromText( $sFileName, NS_FILE ) ); if( $oImage->exists() ) { $sAbsoluteFileSystemPath = $oImage->getFullPath(); } } */ //Dublin Core: $aMeta['DC.title'] = $oTitle->getPrefixedText(); $aMeta['DC.date'] = wfTimestamp(TS_ISO_8601); // TODO RBV (14.12.10 14:01): Check for conformity. Maybe there is a better way to acquire than wfTimestamp()? //Custom global $wgLang; $sCurrentTS = $wgLang->userAdjust(wfTimestampNow()); $aMeta['title'] = $oTitle->getPrefixedText(); $aMeta['exportdate'] = $wgLang->sprintfDate('d.m.Y', $sCurrentTS); $aMeta['exporttime'] = $wgLang->sprintfDate('H:i', $sCurrentTS); $aMeta['exporttimeexact'] = $wgLang->sprintfDate('H:i:s', $sCurrentTS); //Custom - Categories->Keywords $aMeta['keywords'] = implode(', ', $aCategories); $oDOMXPath = new DOMXPath($oPageDOM); $oMetadataElements = $oDOMXPath->query("//div[@class='bs-universalexport-meta']"); foreach ($oMetadataElements as $oMetadataElement) { if ($oMetadataElement->hasAttributes()) { foreach ($oMetadataElement->attributes as $oAttribute) { if ($oAttribute->name !== 'class') { $aMeta[$oAttribute->name] = $oAttribute->value; } } } $oMetadataElement->parentNode->removeChild($oMetadataElement); } //If it's a normal article if (!in_array($oTitle->getNamespace(), array(NS_SPECIAL, NS_IMAGE, NS_CATEGORY))) { $oArticle = new Article($oTitle); $aMeta['author'] = $oArticle->getUserText(); // TODO RBV (14.12.10 12:19): Realname/Username -> DisplayName $aMeta['date'] = $wgLang->sprintfDate('d.m.Y', $oArticle->getTouched()); } wfRunHooks('BSUEModulePDFcollectMetaData', array($oTitle, $oPageDOM, &$aParams, $oDOMXPath, &$aMeta)); $aMetaDataOverrides = json_decode(BsConfig::get('MW::UniversalExport::MetadataOverrides'), true); $aMeta = array_merge($aMeta, $aMetaDataOverrides); return array('meta' => $aMeta, 'resources' => $aResources); }
/** * Make a nested call to the API to request watchlist items in the last $hours. * Wrap the result as an RSS/Atom feed. */ public function execute() { $config = $this->getConfig(); $feedClasses = $config->get('FeedClasses'); try { $params = $this->extractRequestParams(); if (!$config->get('Feed')) { $this->dieUsage('Syndication feeds are not available', 'feed-unavailable'); } if (!isset($feedClasses[$params['feedformat']])) { $this->dieUsage('Invalid subscription feed type', 'feed-invalid'); } // limit to the number of hours going from now back $endTime = wfTimestamp(TS_MW, time() - intval($params['hours'] * 60 * 60)); // Prepare parameters for nested request $fauxReqArr = array('action' => 'query', 'meta' => 'siteinfo', 'siprop' => 'general', 'list' => 'watchlist', 'wlprop' => 'title|user|comment|timestamp|ids', 'wldir' => 'older', 'wlend' => $endTime, 'wllimit' => min(50, $this->getConfig()->get('FeedLimit'))); if ($params['wlowner'] !== null) { $fauxReqArr['wlowner'] = $params['wlowner']; } if ($params['wltoken'] !== null) { $fauxReqArr['wltoken'] = $params['wltoken']; } if ($params['wlexcludeuser'] !== null) { $fauxReqArr['wlexcludeuser'] = $params['wlexcludeuser']; } if ($params['wlshow'] !== null) { $fauxReqArr['wlshow'] = $params['wlshow']; } if ($params['wltype'] !== null) { $fauxReqArr['wltype'] = $params['wltype']; } // Support linking directly to sections when possible // (possible only if section name is present in comment) if ($params['linktosections']) { $this->linkToSections = true; } // Check for 'allrev' parameter, and if found, show all revisions to each page on wl. if ($params['allrev']) { $fauxReqArr['wlallrev'] = ''; } // Create the request $fauxReq = new FauxRequest($fauxReqArr); // Execute $module = new ApiMain($fauxReq); $module->execute(); $data = $module->getResult()->getResultData(array('query', 'watchlist')); $feedItems = array(); foreach ((array) $data as $key => $info) { if (ApiResult::isMetadataKey($key)) { continue; } $feedItem = $this->createFeedItem($info); if ($feedItem) { $feedItems[] = $feedItem; } } $msg = wfMessage('watchlist')->inContentLanguage()->text(); $feedTitle = $this->getConfig()->get('Sitename') . ' - ' . $msg . ' [' . $this->getConfig()->get('LanguageCode') . ']'; $feedUrl = SpecialPage::getTitleFor('Watchlist')->getFullURL(); $feed = new $feedClasses[$params['feedformat']]($feedTitle, htmlspecialchars($msg), $feedUrl); ApiFormatFeedWrapper::setResult($this->getResult(), $feed, $feedItems); } catch (Exception $e) { // Error results should not be cached $this->getMain()->setCacheMaxAge(0); // @todo FIXME: Localise brackets $feedTitle = $this->getConfig()->get('Sitename') . ' - Error - ' . wfMessage('watchlist')->inContentLanguage()->text() . ' [' . $this->getConfig()->get('LanguageCode') . ']'; $feedUrl = SpecialPage::getTitleFor('Watchlist')->getFullURL(); $feedFormat = isset($params['feedformat']) ? $params['feedformat'] : 'rss'; $msg = wfMessage('watchlist')->inContentLanguage()->escaped(); $feed = new $feedClasses[$feedFormat]($feedTitle, $msg, $feedUrl); if ($e instanceof UsageException) { $errorCode = $e->getCodeString(); } else { // Something is seriously wrong $errorCode = 'internal_api_error'; } $errorText = $e->getMessage(); $feedItems[] = new FeedItem("Error ({$errorCode})", $errorText, '', '', ''); ApiFormatFeedWrapper::setResult($this->getResult(), $feed, $feedItems); } }
public function actionReply($threads, $params) { // Validate thread parameter if (count($threads) > 1) { $this->dieUsage('You may only reply to one thread at a time', 'too-many-threads'); } elseif (count($threads) < 1) { $this->dieUsage('You must specify a thread to reply to', 'no-specified-threads'); } $replyTo = array_pop($threads); // Check if we can reply to that thread. $user = $this->getUser(); $perm_result = $replyTo->canUserReply($user); if ($perm_result !== true) { $this->dieUsage("You cannot reply to this thread, because the " . $perm_result . " is protected from replies.", $perm_result . '-protected'); } // Validate text parameter if (empty($params['text'])) { $this->dieUsage('You must include text in your post', 'no-text'); } $text = $params['text']; $bump = isset($params['bump']) ? $params['bump'] : null; // Generate/pull summary $summary = wfMessage('lqt-reply-summary', $replyTo->subject(), $replyTo->title()->getPrefixedText())->inContentLanguage()->text(); if (!empty($params['reason'])) { $summary = $params['reason']; } $signature = null; if (isset($params['signature'])) { $signature = $params['signature']; } // Grab data from parent $talkpage = $replyTo->article(); // Generate a reply title. $title = Threads::newReplyTitle($replyTo, $user); $article = new Article($title, 0); // Inform hooks what we're doing LqtHooks::$editTalkpage = $talkpage; LqtHooks::$editArticle = $article; LqtHooks::$editThread = null; LqtHooks::$editType = 'reply'; LqtHooks::$editAppliesTo = $replyTo; // Pull token in $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::replyMetadataUpdates(array('root' => $article, 'replyTo' => $replyTo, 'signature' => $signature, 'summary' => $summary, 'text' => $text, 'bump' => $bump)); $result = array('action' => 'reply', 'result' => 'Success', 'thread-id' => $thread->id(), 'thread-title' => $title->getPrefixedText(), 'parent-id' => $replyTo->id(), 'parent-title' => $replyTo->title()->getPrefixedText(), 'ancestor-id' => $replyTo->topmostThread()->id(), 'ancestor-title' => $replyTo->topmostThread()->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); }