require_once ("ApiBase.php");
}
-class ApiPageSet {
+class ApiPageSet extends ApiBase {
private $allPages; // [ns][dbkey] => page_id or 0 when missing
private $db, $resolveRedirs;
- private $goodTitles, $missingTitles, $redirectTitles;
+ private $goodTitles, $missingTitles, $redirectTitles, $normalizedTitles;
- public function __construct($db, $resolveRedirs) {
+ public function __construct($main, $db, $resolveRedirs) {
+ parent :: __construct($main);
$this->db = $db;
$this->resolveRedirs = $resolveRedirs;
$this->allPages = array ();
$this->goodTitles = array ();
$this->missingTitles = array ();
-
- // only when resolving redirects:
- if ($resolveRedirs) {
- $this->redirectTitles = array ();
- }
+ $this->redirectTitles = array ();
+ $this->normalizedTitles = array();
}
/**
return $this->redirectTitles;
}
+ /**
+ * Get a list of title normalizations - maps the title given
+ * with its normalized version.
+ * @return array raw_prefixed_title (string) => prefixed_title (string)
+ */
+ public function GetNormalizedTitles() {
+ return $this->normalizedTitles;
+ }
+
+ /**
+ * Given an array of title strings, convert them into Title objects.
+ * This method validates access rights for the title,
+ * and appends normalization values to the output.
+ *
+ * @return LinkBatch of title objects.
+ */
+ private function ProcessTitlesStrings($titles) {
+
+ $linkBatch = new LinkBatch();
+
+ foreach ($titles as $titleString) {
+ $titleObj = Title :: newFromText($titleString);
+
+ // Validation
+ if (!$titleObj)
+ $this->dieUsage("bad title $titleString", 'invalidtitle');
+ if ($titleObj->getNamespace() < 0)
+ $this->dieUsage("No support for special page $titleString has been implemented", 'unsupportednamespace');
+ if (!$titleObj->userCanRead())
+ $this->dieUsage("No read permission for $titleString", 'titleaccessdenied');
+
+ $linkBatch->addObj($titleObj);
+
+ // Make sure we remember the original title that was given to us
+ // This way the caller can correlate new titles with the originally requested,
+ // i.e. namespace is localized or capitalization is different
+ if ($titleString !== $titleObj->getPrefixedText()) {
+ $this->normalizedTitles[$titleString] = $titleObj->getPrefixedText();
+ }
+ }
+
+ return $linkBatch;
+ }
+
/**
* This method populates internal variables with page information
- * based on the list of page titles given as a LinkBatch object.
+ * based on the given array of title strings.
*
* Steps:
* #1 For each title, get data from `page` table
* #5 Substitute the original LinkBatch object with the new list
* #6 Repeat from step #1
*/
- public function PopulateTitles($linkBatch) {
+ public function PopulateTitles($titles) {
$pageFlds = array (
'page_id',
'page_namespace',
$pageFlds[] = 'page_is_redirect';
}
+ // Get validated and normalized title objects
+ $linkBatch = $this->ProcessTitlesStrings($titles);
+
//
// Repeat until all redirects have been resolved
//
// Hack: Get the ns:titles stored in array(ns => array(titles)) format
$remaining = $linkBatch->data;
- if ($this->resolveRedirs)
- $redirectIds = array ();
+ $redirectIds = array ();
//
// Get data about $linkBatch from `page` table
$this->db->freeResult($res);
}
}
+
+ public function Execute() {
+ $this->DieDebug("Execute() is not supported on this object");
+ }
}
?>
\ No newline at end of file
);\r
\r
private $mQueryPropModules = array (\r
- // 'info' => 'ApiQueryInfo',\r
- // 'categories' => 'ApiQueryCategories',\r
+ 'info' => 'ApiQueryInfo',\r
+ // 'categories' => 'ApiQueryCategories',\r
// 'imageinfo' => 'ApiQueryImageinfo',\r
// 'langlinks' => 'ApiQueryLanglinks',\r
// 'links' => 'ApiQueryLinks',\r
return $this->mSlaveDB;\r
}\r
\r
+ /**\r
+ * Query execution happens in the following steps:\r
+ * #1 Create a PageSet object with any pages requested by the user\r
+ * #2 If using generator, execute it to get a new PageSet object\r
+ * #3 Instantiate all requested modules. \r
+ * This way the PageSet object will know what shared data is required,\r
+ * and minimize DB calls. \r
+ * #4 Output all normalization and redirect resolution information\r
+ * #5 Execute all requested modules\r
+ */\r
public function Execute() {\r
$meta = $prop = $list = $generator = $titles = $pageids = $revids = null;\r
$redirects = null;\r
extract($this->ExtractRequestParams());\r
\r
//\r
- // Only one of the titles/pageids/revids is allowed at the same time\r
+ // Create and initialize PageSet\r
//\r
+ // Only one of the titles/pageids/revids is allowed at the same time\r
$dataSource = null;\r
if (isset ($titles))\r
$dataSource = 'titles';\r
$dataSource = 'revids';\r
}\r
\r
- if (isset($dataSource) && $dataSource !== 'titles')\r
- $this->DieUsage('Currently only titles= parameter is supported.', 'notimplemented');\r
-\r
- // Normalize titles\r
- $linkBatch = $this->ProcessTitles($titles);\r
+ $data = new ApiPageSet($this->GetMain(), $this->GetDB(), $redirects);\r
+\r
+ switch ($dataSource) {\r
+ case 'titles' :\r
+ $data->PopulateTitles($titles);\r
+ break;\r
+ case 'pageids' :\r
+ $data->PopulatePageIDs($pageids);\r
+ break;\r
+ case 'titles' :\r
+ $data->PopulateRevIDs($revids);\r
+ break;\r
+ default :\r
+ // Do nothing - some queries do not need any of the data sources.\r
+ break;\r
+ }\r
\r
- // Get titles info from DB\r
- $data = new ApiPageSet($this->GetDB(), $redirects);\r
- $data->PopulateTitles($linkBatch);\r
+ //\r
+ // If generator is provided, get a new dataset to work on\r
+ //\r
+ if (isset ($generator))\r
+ $data = $this->ExecuteGenerator($generator, $data, $redirects);\r
+\r
+ // Instantiate required modules\r
+ // During instantiation, modules may optimize data requests through the $data object \r
+ // $data will be lazy loaded when modules begin to request data during execution\r
+ $modules = array ();\r
+ if (isset($meta))\r
+ foreach ($meta as $moduleName)\r
+ $modules[] = new $this->mQueryMetaModules[$moduleName] ($this, $moduleName, $data);\r
+ if (isset($prop))\r
+ foreach ($prop as $moduleName)\r
+ $modules[] = new $this->mQueryPropModules[$moduleName] ($this, $moduleName, $data);\r
+ if (isset($list))\r
+ foreach ($list as $moduleName)\r
+ $modules[] = new $this->mQueryListModules[$moduleName] ($this, $moduleName, $data);\r
+\r
+ // Title normalizations\r
+ foreach ($data->GetNormalizedTitles() as $rawTitleStr => $titleStr) {\r
+ $this->GetResult()->AddMessage('query', 'normalized', array (\r
+ 'from' => $rawTitleStr,\r
+ 'to' => $titleStr\r
+ ), 'n');\r
+ }\r
\r
- // Show redirects information\r
+ // Show redirect information\r
if ($redirects) {\r
foreach ($data->GetRedirectTitles() as $titleStrFrom => $titleStrTo) {\r
$this->GetResult()->AddMessage('query', 'redirects', array (\r
), 'r');\r
}\r
}\r
- }\r
-\r
- /**\r
- * Given an array of title strings, convert them into Title objects.\r
- * This method validates access rights for the title, \r
- * and appends normalization values to the output.\r
- * @return LinkBatch of title objects.\r
- */\r
- protected function ProcessTitles($titles) {\r
\r
- $linkBatch = new LinkBatch();\r
-\r
- foreach ($titles as $titleString) {\r
- $titleObj = Title :: newFromText($titleString);\r
-\r
- // Validation\r
- if (!$titleObj)\r
- $this->dieUsage("bad title $titleString", 'invalidtitle');\r
- if ($titleObj->getNamespace() < 0)\r
- $this->dieUsage("No support for special page $titleString has been implemented", 'unsupportednamespace');\r
- if (!$titleObj->userCanRead())\r
- $this->dieUsage("No read permission for $titleString", 'titleaccessdenied');\r
-\r
- $linkBatch->addObj($titleObj);\r
-\r
- // Make sure we remember the original title that was given to us\r
- // This way the caller can correlate new titles with the originally requested, i.e. namespace is localized or capitalization\r
- if ($titleString !== $titleObj->getPrefixedText()) {\r
- $this->GetResult()->AddMessage('query', 'normalized', array (\r
- 'from' => $titleString,\r
- 'to' => $titleObj->getPrefixedText()), 'n');\r
- }\r
- }\r
+ // Execute all requested modules.\r
+ foreach ($modules as $module)\r
+ $module->Execute();\r
+ }\r
\r
- return $linkBatch;\r
+ protected function ExecuteGenerator($generator, $data, $redirects) {\r
+ // TODO: implement\r
+ $this->DieUsage("Generator execution has not been implemented", 'notimplemented');\r
}\r
\r
protected function GetAllowedParams() {\r
GN_ENUM_ISMULTI => true,\r
GN_ENUM_CHOICES => $this->mListModuleNames\r
),\r
- 'generator' => array (\r
- GN_ENUM_CHOICES => $this->mAllowedGenerators\r
- ),\r
+ // 'generator' => array (\r
+ // GN_ENUM_CHOICES => $this->mAllowedGenerators\r
+ // ),\r
'titles' => array (\r
GN_ENUM_ISMULTI => true\r
),\r
- 'pageids' => array (\r
- GN_ENUM_TYPE => 'integer',\r
- GN_ENUM_ISMULTI => true\r
- ),\r
- 'revids' => array (\r
- GN_ENUM_TYPE => 'integer',\r
- GN_ENUM_ISMULTI => true\r
- ),\r
+ // 'pageids' => array (\r
+ // GN_ENUM_TYPE => 'integer',\r
+ // GN_ENUM_ISMULTI => true\r
+ // ),\r
+ // 'revids' => array (\r
+ // GN_ENUM_TYPE => 'integer',\r
+ // GN_ENUM_ISMULTI => true\r
+ // ),\r
'redirects' => false\r
);\r
}\r
'generator' => 'Use the output of a list as the input for other prop/list/meta items',\r
'titles' => 'A list of titles to work on',\r
'pageids' => 'A list of page IDs to work on',\r
- 'revids' => 'A list of revision IDs to work on'\r
+ 'revids' => 'A list of revision IDs to work on',\r
+ 'redirects' => 'Automatically resolve redirects'\r
);\r
}\r
\r
\r
protected function GetExamples() {\r
return array (\r
- 'api.php ? action=query & what=content & titles=ArticleA|ArticleB'\r
+ 'api.php?action=query&what=content&titles=ArticleA|ArticleB'\r
);\r
}\r
}\r