From 25234bd1fcf61f31b052831f32937deed6c4f839 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 12 Oct 2006 03:15:42 +0000 Subject: [PATCH] * allpages module fix * added exception handling code --- includes/api/ApiMain.php | 81 ++++++++++++++++++++++++++---- includes/api/ApiQuery.php | 15 ++++++ includes/api/ApiQueryAllpages.php | 35 ++++++------- includes/api/ApiQueryRevisions.php | 24 ++++----- 4 files changed, 112 insertions(+), 43 deletions(-) diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php index f31f3e2bc3..83949913a8 100644 --- a/includes/api/ApiMain.php +++ b/includes/api/ApiMain.php @@ -51,6 +51,9 @@ class ApiMain extends ApiBase { $this->mResult = new ApiResult($this); $this->mShowVersions = false; $this->mEnableWrite = $enableWrite; + + // Initialize Error handler + set_exception_handler( array($this, 'exceptionHandler') ); } public function & getResult() { @@ -107,12 +110,7 @@ class ApiMain extends ApiBase { $this->printResult(false); } catch (UsageException $e) { - - // Printer may not be initialized if the extractRequestParams() fails for the main module - if (!isset ($this->mPrinter)) - $this->mPrinter = new $this->mFormats[API_DEFAULT_FORMAT] ($this, API_DEFAULT_FORMAT); - $this->printResult(true); - + $this->printError(); } $this->profileOut(); } @@ -130,6 +128,13 @@ class ApiMain extends ApiBase { $printer->closePrinter(); $printer->profileOut(); } + + private function printError() { + // Printer may not be initialized if the extractRequestParams() fails for the main module + if (!isset ($this->mPrinter)) + $this->mPrinter = new $this->mFormats[API_DEFAULT_FORMAT] ($this, API_DEFAULT_FORMAT); + $this->printResult(true); + } protected function getDescription() { return array ( @@ -141,22 +146,29 @@ class ApiMain extends ApiBase { } public function mainDieUsage($description, $errorCode, $httpRespCode = 0) { - $this->mResult->Reset(); if ($httpRespCode === 0) header($errorCode, true); else header($errorCode, true, $httpRespCode); + $this->makeErrorMessage($description, $errorCode); + + throw new UsageException($description, $errorCode); + } + + public function makeErrorMessage($description, $errorCode, $customContent = null) { + $this->mResult->Reset(); $data = array ( 'code' => $errorCode, 'info' => $description ); - ApiResult :: setContent($data, $this->makeHelpMsg()); + + ApiResult :: setContent($data, + is_null($customContent) ? $this->makeHelpMsg() : $customContent); + $this->mResult->addValue(null, 'error', $data); - - throw new UsageException($description, $errorCode); } - + /** * Override the parent to generate help messages for all available modules. */ @@ -188,6 +200,53 @@ class ApiMain extends ApiBase { return $msg; } + + /** + * Exception handler which simulates the appropriate catch() handling: + * + * try { + * ... + * } catch ( MWException $e ) { + * dieUsage() + * } catch ( Exception $e ) { + * echo $e->__toString(); + * } + * + * + * + * + * !!!!!!!!!!!!! REVIEW needed !!!!!!!!!!!!!!!!!! + * + * this method needs to be reviewed/cleaned up + * + * + * + */ + public function exceptionHandler( $e ) { + global $wgFullyInitialised; + if ( is_a( $e, 'MWException' ) ) { + try { + $msg = "Exception Caught: {$e->getMessage()}"; + $this->makeErrorMessage($msg, 'internal_error', "\n\n{$e->getTraceAsString()}\n\n"); + $this->printError(); + } catch (Exception $e2) { + echo $e->__toString(); + } + } else { + echo $e->__toString(); + } + + // Final cleanup, similar to wfErrorExit() + if ( $wgFullyInitialised ) { + try { + wfLogProfilingData(); // uses $wgRequest, hence the $wgFullyInitialised condition + } catch ( Exception $e ) {} + } + + // Exit value should be nonzero for the benefit of shell jobs + exit( 1 ); + } + private $mIsBot = null; public function isBot() { diff --git a/includes/api/ApiQuery.php b/includes/api/ApiQuery.php index be57b06dc2..ea6d35918b 100644 --- a/includes/api/ApiQuery.php +++ b/includes/api/ApiQuery.php @@ -33,6 +33,7 @@ class ApiQuery extends ApiBase { private $mPropModuleNames, $mListModuleNames, $mMetaModuleNames; private $mPageSet; + private $mValidNamespaces; private $mQueryPropModules = array ( 'info' => 'ApiQueryInfo', @@ -69,6 +70,7 @@ class ApiQuery extends ApiBase { $this->mPropModuleNames = array_keys($this->mQueryPropModules); $this->mListModuleNames = array_keys($this->mQueryListModules); $this->mMetaModuleNames = array_keys($this->mQueryMetaModules); + $this->mValidNamespaces = null; // Allow the entire list of modules at first, // but during module instantiation check if it can be used as a generator. @@ -85,6 +87,19 @@ class ApiQuery extends ApiBase { return $this->mPageSet; } + public function getValidNamespaces() { + global $wgContLang; + + if (is_null($this->mValidNamespaces)) { + $this->mValidNamespaces = array (); + foreach (array_keys($wgContLang->getNamespaces()) as $ns) { + if ($ns >= 0) + $this->mValidNamespaces[] = $ns; // strval($ns); + } + } + return $this->mValidNamespaces; + } + /** * Query execution happens in the following steps: * #1 Create a PageSet object with any pages requested by the user diff --git a/includes/api/ApiQueryAllpages.php b/includes/api/ApiQueryAllpages.php index 89b22662a3..dc7758b40b 100644 --- a/includes/api/ApiQueryAllpages.php +++ b/includes/api/ApiQueryAllpages.php @@ -42,7 +42,7 @@ class ApiQueryAllpages extends ApiQueryGeneratorBase { public function executeGenerator($resultPageSet) { if ($resultPageSet->isResolvingRedirects()) $this->dieUsage('Use "gapfilterredir=nonredirects" option instead of "redirects" when using allpages as a generator', 'params'); - + $this->run($resultPageSet); } @@ -55,11 +55,11 @@ class ApiQueryAllpages extends ApiQueryGeneratorBase { $where = array ( 'page_namespace' => $namespace ); - + if (isset ($from)) { $where[] = 'page_title>=' . $db->addQuotes(ApiQueryBase :: titleToKey($from)); } - + if ($filterredir === 'redirects') { $where['page_is_redirect'] = 1; } @@ -77,12 +77,14 @@ class ApiQueryAllpages extends ApiQueryGeneratorBase { $fields = $resultPageSet->getPageTableFields(); } - $this->profileDBIn(); - $res = $db->select('page', $fields, $where, __CLASS__ . '::' . __METHOD__, array ( + $options = array ( 'USE INDEX' => 'name_title', 'LIMIT' => $limit +1, 'ORDER BY' => 'page_namespace, page_title' - )); + ); + + $this->profileDBIn(); + $res = $db->select('page', $fields, $where, __METHOD__, $options); $this->profileDBOut(); $data = array (); @@ -103,7 +105,10 @@ class ApiQueryAllpages extends ApiQueryGeneratorBase { if (is_null($resultPageSet)) { $id = intval($row->page_id); - $data[] = $id; // in generator mode, just assemble a list of page IDs. + $data[$id] = array ( + 'id' => $id, + 'ns' => $title->getNamespace(), + 'title' => $title->getPrefixedText()); } else { $resultPageSet->processDbRow($row); } @@ -119,35 +124,25 @@ class ApiQueryAllpages extends ApiQueryGeneratorBase { protected function getAllowedParams() { - global $wgContLang; - $validNamespaces = array (); - foreach (array_keys($wgContLang->getNamespaces()) as $ns) { - if ($ns >= 0) - $validNamespaces[] = $ns; // strval($ns); - } - return array ( 'from' => null, 'namespace' => array ( ApiBase :: PARAM_DFLT => 0, - ApiBase :: PARAM_TYPE => $validNamespaces - ), + ApiBase :: PARAM_TYPE => $this->getQuery()->getValidNamespaces()), 'filterredir' => array ( ApiBase :: PARAM_DFLT => 'all', ApiBase :: PARAM_TYPE => array ( 'all', 'redirects', 'nonredirects' - ) - ), + )), 'limit' => array ( ApiBase :: PARAM_DFLT => 10, ApiBase :: PARAM_TYPE => 'limit', ApiBase :: PARAM_MIN => 1, ApiBase :: PARAM_MAX1 => 500, ApiBase :: PARAM_MAX2 => 5000 - ) - ); + )); } protected function getParamDescription() { diff --git a/includes/api/ApiQueryRevisions.php b/includes/api/ApiQueryRevisions.php index dce0a8db3d..65e25b6efa 100644 --- a/includes/api/ApiQueryRevisions.php +++ b/includes/api/ApiQueryRevisions.php @@ -76,7 +76,7 @@ class ApiQueryRevisions extends ApiQueryBase { 'rev_text_id', 'rev_minor_edit' ); - $conds = array ( + $where = array ( 'rev_deleted' => 0 ); $options = array (); @@ -100,7 +100,7 @@ class ApiQueryRevisions extends ApiQueryBase { break; case 'content' : $tables[] = 'text'; - $conds[] = 'rev_text_id=old_id'; + $where[] = 'rev_text_id=old_id'; $fields[] = 'old_id'; $fields[] = 'old_text'; $fields[] = 'old_flags'; @@ -136,13 +136,13 @@ class ApiQueryRevisions extends ApiQueryBase { $after = ($dirNewer ? '>=' : '<='); if ($startid !== 0) - $conds[] = 'rev_id' . $after . intval($startid); + $where[] = 'rev_id' . $after . intval($startid); if ($endid !== 0) - $conds[] = 'rev_id' . $before . intval($endid); + $where[] = 'rev_id' . $before . intval($endid); if (isset ($start)) - $conds[] = 'rev_timestamp' . $after . $db->addQuotes($start); + $where[] = 'rev_timestamp' . $after . $db->addQuotes($start); if (isset ($end)) - $conds[] = 'rev_timestamp' . $before . $db->addQuotes($end); + $where[] = 'rev_timestamp' . $before . $db->addQuotes($end); // must manually initialize unset limit if (!isset ($limit)) @@ -151,19 +151,19 @@ class ApiQueryRevisions extends ApiQueryBase { $this->validateLimit($this->encodeParamName('limit'), $limit, 1, $userMax, $botMax); // There is only one ID, use it - $conds['rev_page'] = array_pop(array_keys($pageSet->getGoodTitles())); + $where['rev_page'] = array_pop(array_keys($pageSet->getGoodTitles())); } elseif ($pageCount > 0) { // When working in multi-page non-enumeration mode, // limit to the latest revision only $tables[] = 'page'; - $conds[] = 'page_id=rev_page'; - $conds[] = 'page_latest=rev_id'; + $where[] = 'page_id=rev_page'; + $where[] = 'page_latest=rev_id'; $this->validateLimit('page_count', $pageCount, 1, $userMax, $botMax); // Get all page IDs - $conds['page_id'] = array_keys($pageSet->getGoodTitles()); + $where['page_id'] = array_keys($pageSet->getGoodTitles()); $limit = $pageCount; // assumption testing -- we should never get more then $pageCount rows. } @@ -171,7 +171,7 @@ class ApiQueryRevisions extends ApiQueryBase { $this->validateLimit('rev_count', $revCount, 1, $userMax, $botMax); // Get all revision IDs - $conds['rev_id'] = array_keys($pageSet->getRevisionIDs()); + $where['rev_id'] = array_keys($pageSet->getRevisionIDs()); $limit = $revCount; // assumption testing -- we should never get more then $revCount rows. } else @@ -180,7 +180,7 @@ class ApiQueryRevisions extends ApiQueryBase { $options['LIMIT'] = $limit +1; $this->profileDBIn(); - $res = $db->select($tables, $fields, $conds, __METHOD__, $options); + $res = $db->select($tables, $fields, $where, __METHOD__, $options); $this->profileDBOut(); $data = array (); -- 2.20.1