API * Better log events info * Added RAW debugging format
authorYuri Astrakhan <yurik@users.mediawiki.org>
Tue, 17 Oct 2006 02:01:20 +0000 (02:01 +0000)
committerYuri Astrakhan <yurik@users.mediawiki.org>
Tue, 17 Oct 2006 02:01:20 +0000 (02:01 +0000)
includes/api/ApiBase.php
includes/api/ApiFormatJson.php
includes/api/ApiFormatXml.php
includes/api/ApiMain.php
includes/api/ApiQueryAllpages.php
includes/api/ApiQueryLogEvents.php
includes/api/ApiQueryRevisions.php
includes/api/ApiQueryWatchlist.php

index 8e1974b..e0ed028 100644 (file)
@@ -35,6 +35,11 @@ abstract class ApiBase {
        const PARAM_MAX2 = 4;
        const PARAM_MIN = 5;
 
+       const LIMIT_BIG1 = 500; // Fast query, user's limit
+       const LIMIT_BIG2 = 5000; // Fast query, bot's limit
+       const LIMIT_SML1 = 50; // Slow query, user's limit
+       const LIMIT_SML2 = 500; // Slow query, bot's limit
+
        private $mMainModule, $mModuleName, $mParamPrefix;
 
        /**
@@ -42,7 +47,7 @@ abstract class ApiBase {
        */
        public function __construct($mainModule, $moduleName, $paramPrefix = '') {
                $this->mMainModule = $mainModule;
-        $this->mModuleName = $moduleName;
+               $this->mModuleName = $moduleName;
                $this->mParamPrefix = $paramPrefix;
        }
 
@@ -51,22 +56,22 @@ abstract class ApiBase {
         */
        public abstract function execute();
 
-    /**
-     * Get the name of the module being executed by this instance 
-     */
-    public function getModuleName() {
-        return $this->mModuleName;
-    }
-
-    /**
-     * Get the name of the module as shown in the profiler log 
-     */
-    public function getModuleProfileName($db = false) {
-        if ($db)
-            return 'API:' . $this->mModuleName . '-DB';
-        else
-               return 'API:' . $this->mModuleName;
-    }
+       /**
+        * Get the name of the module being executed by this instance 
+        */
+       public function getModuleName() {
+               return $this->mModuleName;
+       }
+
+       /**
+        * Get the name of the module as shown in the profiler log 
+        */
+       public function getModuleProfileName($db = false) {
+               if ($db)
+                       return 'API:' . $this->mModuleName . '-DB';
+               else
+                       return 'API:' . $this->mModuleName;
+       }
 
        /**
         * Get main module
@@ -161,23 +166,21 @@ abstract class ApiBase {
                        $paramsDescription = $this->getParamDescription();
                        $msg = '';
                        $paramPrefix = "\n" . str_repeat(' ', 19);
-                       foreach ($params as $paramName => &$paramSettings) {
+                       foreach ($params as $paramName => & $paramSettings) {
                                $desc = isset ($paramsDescription[$paramName]) ? $paramsDescription[$paramName] : '';
                                if (is_array($desc))
                                        $desc = implode($paramPrefix, $desc);
                                if (isset ($paramSettings[self :: PARAM_TYPE])) {
                                        $type = $paramSettings[self :: PARAM_TYPE];
                                        if (is_array($type)) {
-                                               $desc .= $paramPrefix . 'Allowed values: '. implode(', ', $type);
+                                               $desc .= $paramPrefix . 'Allowed values: ' . implode(', ', $type);
                                        }
                                }
-                               
-                               $default = is_array($paramSettings) 
-                                       ? (isset ($paramSettings[self :: PARAM_DFLT]) ? $paramSettings[self :: PARAM_DFLT] : null)
-                                       : $paramSettings;
+
+                               $default = is_array($paramSettings) ? (isset ($paramSettings[self :: PARAM_DFLT]) ? $paramSettings[self :: PARAM_DFLT] : null) : $paramSettings;
                                if (!is_null($default) && $default !== false)
                                        $desc .= $paramPrefix . "Default: $default";
-                                       
+
                                $msg .= sprintf("  %-14s - %s\n", $this->encodeParamName($paramName), $desc);
                        }
                        return $msg;
@@ -213,7 +216,7 @@ abstract class ApiBase {
        protected function getParamDescription() {
                return false;
        }
-       
+
        /**
         * This method mangles parameter name based on the prefix supplied to the constructor.
         * Override this method to change parameter name during runtime 
@@ -250,7 +253,7 @@ abstract class ApiBase {
         * Using the settings determine the value for the given parameter
         * @param $paramName String: parameter name
         * @param $paramSettings Mixed: default value or an array of settings using PARAM_* constants.
-        */     
+        */
        protected function getParameterFromSettings($paramName, $paramSettings) {
 
                // Some classes may decide to change parameter names
@@ -284,7 +287,7 @@ abstract class ApiBase {
                } else {
                        $value = $this->getMain()->getRequest()->getVal($paramName, $default);
                }
-               
+
                if (isset ($value) && ($multi || is_array($type)))
                        $value = $this->parseMultiValue($paramName, $value, $multi, is_array($type) ? $type : null);
 
@@ -328,7 +331,7 @@ abstract class ApiBase {
                // There should never be any duplicate values in a list
                if (is_array($value))
                        $value = array_unique($value);
-                       
+
                return $value;
        }
 
@@ -418,9 +421,21 @@ abstract class ApiBase {
 
                $this->mModuleTime += microtime(true) - $this->mTimeIn;
                $this->mTimeIn = 0;
-               wfProfileOut($this->getModuleProfileName()); 
+               wfProfileOut($this->getModuleProfileName());
        }
 
+       /**
+        * When modules crash, sometimes it is needed to do a profileOut() regardless
+        * of the profiling state the module was in. This method does such cleanup. 
+        */
+       public function safeProfileOut() {
+               if ($this->mTimeIn !== 0) {
+                       if ($this->mDBTimeIn !== 0)
+                               $this->profileDBOut();
+                       $this->profileOut();
+               }
+       }
+       
        /**
         * Total time the module was executed
         */
@@ -474,7 +489,7 @@ abstract class ApiBase {
        }
 
        public abstract function getVersion();
-       
+
        public static function getBaseVersion() {
                return __CLASS__ . ': $Id$';
        }
index 48de5af..7e72693 100644 (file)
@@ -31,14 +31,21 @@ if (!defined('MEDIAWIKI')) {
 
 class ApiFormatJson extends ApiFormatBase {
 
+       private $mIsRaw;
+       
        public function __construct($main, $format) {
                parent :: __construct($main, $format);
+               $this->mIsRaw = ($format === 'raw' || $format === 'rawfm');
        }
 
        public function getMimeType() {
                return 'application/json';
        }
-
+       
+       public function getNeedsRawData() {
+               return $this->mIsRaw;
+       }
+       
        public function execute() {
                if (!function_exists('json_encode') || $this->getIsHtml()) {
                        $json = new Services_JSON();
index f4bf838..09621f6 100644 (file)
@@ -104,8 +104,6 @@ class ApiFormatXml extends ApiFormatBase {
                                $subElements = array ();
                                foreach ($elemValue as $subElemId => & $subElemValue) {
                                        if (gettype($subElemId) === 'integer') {
-                                               if (!is_array($subElemValue))
-                                                       ApiBase :: dieDebug(__METHOD__, "($elemName, ...) has a scalar indexed value.");
                                                $indElements[] = $subElemValue;
                                                unset ($elemValue[$subElemId]);
                                        } elseif (is_array($subElemValue)) {
@@ -115,7 +113,7 @@ class ApiFormatXml extends ApiFormatBase {
                                }
 
                                if (is_null($subElemIndName) && !empty ($indElements))
-                                       ApiBase :: dieDebug(__METHOD__, "($elemName, ...) has integer keys without _element value");
+                                       ApiBase :: dieDebug(__METHOD__, "($elemName, ...) has integer keys without _element value. Use ApiResult::setIndexedTagName().");
 
                                if (!empty ($subElements) && !empty ($indElements) && !is_null($subElemContent))
                                        ApiBase :: dieDebug(__METHOD__, "($elemName, ...) has content and subelements");
index 53f0cf1..9803e03 100644 (file)
@@ -57,6 +57,8 @@ class ApiMain extends ApiBase {
        private static $Formats = array (
                'json' => 'ApiFormatJson',
                'jsonfm' => 'ApiFormatJson',
+               'raw' => 'ApiFormatJson',
+               'rawfm' => 'ApiFormatJson',
                'xml' => 'ApiFormatXml',
                'xmlfm' => 'ApiFormatXml',
                'yaml' => 'ApiFormatYaml',
@@ -169,6 +171,9 @@ class ApiMain extends ApiBase {
                        ob_clean();
                        $this->mResult->Reset();
                        $this->mResult->addValue(null, 'error', $errMessage);
+
+                       // If the error occured during printing, do a printer->profileOut()
+                       $this->mPrinter->safeProfileOut();
                        $this->printResult(true);
                }
                
index 0966445..5e01222 100644 (file)
@@ -142,8 +142,8 @@ class ApiQueryAllpages extends ApiQueryGeneratorBase {
                                ApiBase :: PARAM_DFLT => 10,
                                ApiBase :: PARAM_TYPE => 'limit',
                                ApiBase :: PARAM_MIN => 1,
-                               ApiBase :: PARAM_MAX1 => 500,
-                               ApiBase :: PARAM_MAX2 => 5000
+                               ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
+                               ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
                ));
        }
 
index 77d87db..7da11b0 100644 (file)
@@ -36,14 +36,14 @@ class ApiQueryLogEvents extends ApiQueryBase {
        }
 
        public function execute() {
-               $limit = $type = $from = $to = $dir = $user = $title = $namespace = null;
+               $limit = $type = $start = $end = $dir = $user = $title = null;
                extract($this->extractRequestParams());
 
                $db = $this->getDB();
 
                extract($db->tableNames('logging', 'page', 'user'), EXTR_PREFIX_ALL, 'tbl');
-
-               $tables = "$tbl_logging LEFT OUTER JOIN $tbl_page ON log_namespace=page_namespace AND log_title=page_title " .
+               $tables = "$tbl_logging LEFT OUTER JOIN $tbl_page ON " .
+               "log_namespace=page_namespace AND log_title=page_title " .
                "INNER JOIN $tbl_user ON user_id=log_user";
 
                $fields = array (
@@ -80,11 +80,19 @@ class ApiQueryLogEvents extends ApiQueryBase {
                        $where['log_title'] = $titleObj->getDBkey();
                }
 
-               //              $where[] = "log_timestamp $direction '$safetime'";
+               $dirNewer = ($dir === 'newer');
+               $before = ($dirNewer ? '<=' : '>=');
+               $after = ($dirNewer ? '>=' : '<=');
+
+               if (!is_null($start))
+                       $where[] = 'log_timestamp' . $after . $db->addQuotes($start);
+               if (!is_null($end))
+                       $where[] = 'log_timestamp' . $before . $db->addQuotes($end);
 
                $options = array (
-                       'LIMIT' => $limit +1
-               );
+                       'LIMIT' => $limit +1,
+                       'ORDER BY' => 'log_timestamp' . ($dirNewer ? '' : ' DESC'
+               ));
 
                $this->profileDBIn();
                $res = $db->select($tables, $fields, $where, __METHOD__, $options);
@@ -95,27 +103,42 @@ class ApiQueryLogEvents extends ApiQueryBase {
                while ($row = $db->fetchObject($res)) {
                        if (++ $count > $limit) {
                                // We've reached the one extra which shows that there are additional pages to be had. Stop here...
-                               $this->setContinueEnumParameter('from', ApiQueryBase :: keyToTitle($row->page_title));
+                               $this->setContinueEnumParameter('start', ApiQueryBase :: keyToTitle($row->log_timestamp));
                                break;
                        }
 
                        $vals = array (
-                               'type' => $row->log_type,
-                               'action' => $row->log_action,
+                               'action' => "$row->log_type/$row->log_action",
                                'timestamp' => $row->log_timestamp,
                                'comment' => $row->log_comment,
-                               'params' => $row->log_params,
-                               'pageid' => intval($row->page_id)
-                       );
-                       
+                               'pageid' => intval($row->page_id
+                       ));
+
                        $title = Title :: makeTitle($row->log_namespace, $row->log_title);
                        $vals['ns'] = $title->getNamespace();
                        $vals['title'] = $title->getPrefixedText();
 
+                       if ($row->log_params !== '') {
+                               $params = explode("\n", $row->log_params);
+                               if ($row->log_type == 'move' && isset ($params[0])) {
+                                       $destTitle = Title :: newFromText($params[0]);
+                                       if ($destTitle) {
+                                               $vals['tons'] = $destTitle->getNamespace();
+                                               $vals['totitle'] = $destTitle->getPrefixedText();
+                                               $params = null;
+                                       }
+                               }
+                               
+                               if(!empty($params)) {
+                                       ApiResult :: setIndexedTagName($params, 'param');
+                                       $vals = array_merge($vals, $params);
+                               }
+                       }
+
                        if (!$row->log_user)
                                $vals['anon'] = '';
                        $vals['user'] = $row->user_name;
-                       
+
                        $data[] = $vals;
                }
                $db->freeResult($res);
@@ -125,21 +148,56 @@ class ApiQueryLogEvents extends ApiQueryBase {
        }
 
        protected function getAllowedParams() {
-
                return array (
                        'limit' => array (
                                ApiBase :: PARAM_DFLT => 10,
                                ApiBase :: PARAM_TYPE => 'limit',
                                ApiBase :: PARAM_MIN => 1,
-                               ApiBase :: PARAM_MAX1 => 500,
-                               ApiBase :: PARAM_MAX2 => 5000
-                       )
+                               ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
+                               ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
+                       ),
+                       'type' => array (
+                               ApiBase :: PARAM_ISMULTI => true,
+                               ApiBase :: PARAM_TYPE => array (
+                                       'block',
+                                       'protect',
+                                       'rights',
+                                       'delete',
+                                       'upload',
+                                       'move',
+                                       'import',
+                                       'renameuser',
+                                       'newusers',
+                                       'makebot'
+                               )
+                       ),
+                       'start' => array (
+                               ApiBase :: PARAM_TYPE => 'timestamp'
+                       ),
+                       'end' => array (
+                               ApiBase :: PARAM_TYPE => 'timestamp'
+                       ),
+                       'dir' => array (
+                               ApiBase :: PARAM_DFLT => 'older',
+                               ApiBase :: PARAM_TYPE => array (
+                                       'newer',
+                                       'older'
+                               )
+                       ),
+                       'user' => null,
+                       'title' => null
                );
        }
 
        protected function getParamDescription() {
                return array (
-                       'limit' => 'How many total items to return.'
+                       'limit' => '',
+                       'type' => '',
+                       'start' => '',
+                       'end' => '',
+                       'dir' => '',
+                       'user' => '',
+                       'title' => ''
                );
        }
 
@@ -154,7 +212,7 @@ class ApiQueryLogEvents extends ApiQueryBase {
        }
 
        public function getVersion() {
-               return __CLASS__ . ': $Id:$';
+               return __CLASS__ . ': $Id$';
        }
 }
 ?>
\ No newline at end of file
index 1fbc357..729b623 100644 (file)
@@ -245,11 +245,10 @@ class ApiQueryRevisions extends ApiQueryBase {
                                )
                        ),
                        'limit' => array (
-                               ApiBase :: PARAM_DFLT => null,
                                ApiBase :: PARAM_TYPE => 'limit',
-                               ApiBase :: PARAM_MIN => 0,
-                               ApiBase :: PARAM_MAX1 => 50,
-                               ApiBase :: PARAM_MAX2 => 500
+                               ApiBase :: PARAM_MIN => 1,
+                               ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_SML1,
+                               ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_SML2
                        ),
                        'startid' => array (
                                ApiBase :: PARAM_TYPE => 'integer'
index 92273a1..a2552f6 100644 (file)
@@ -232,8 +232,8 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                                ApiBase :: PARAM_DFLT => 10,
                                ApiBase :: PARAM_TYPE => 'limit',
                                ApiBase :: PARAM_MIN => 1,
-                               ApiBase :: PARAM_MAX1 => 500,
-                               ApiBase :: PARAM_MAX2 => 5000
+                               ApiBase :: PARAM_MAX1 => ApiBase :: LIMIT_BIG1,
+                               ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
                        ),
                        'prop' => array (
                                APIBase :: PARAM_ISMULTI => true,