Robert Vogel has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/345852 )

Change subject: [WiP] Adding TaskData Schema
......................................................................

[WiP] Adding TaskData Schema

Change-Id: I6d6b7d4d2e5b619728e843853634e3491ad0e3cb
---
M extension.json
M i18n/api/en.json
M i18n/api/qqq.json
M includes/api/BSApiTasksBase.php
M includes/api/BSApiWikiPageTasks.php
A includes/utility/BSTasksApiSpec.php
A tests/utility/BSTasksApiSpecTest.php
7 files changed, 391 insertions(+), 44 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/BlueSpiceFoundation 
refs/changes/52/345852/1

diff --git a/extension.json b/extension.json
index c924686..cc5dd02 100644
--- a/extension.json
+++ b/extension.json
@@ -560,7 +560,8 @@
                "BSApiExtJSStoreTestBase": "tests/BSApiExtJSStoreTestBase.php",
                "BSApiTasksTestBase": "tests/BSApiTasksTestBase.php",
                "BSTemplateHelper": "includes/TemplateHelper.php",
-               "ResourceLoaderBSTemplateModule": 
"includes/resourceloader/ResourceLoaderBSTemplateModule.php"
+               "ResourceLoaderBSTemplateModule": 
"includes/resourceloader/ResourceLoaderBSTemplateModule.php",
+               "BSTasksApiSpec": "includes/utility/BSTasksApiSpec.php"
        },
        "load_composer_autoloader": true,
        "manifest_version": 1,
diff --git a/i18n/api/en.json b/i18n/api/en.json
index e56870d..81b44ba 100644
--- a/i18n/api/en.json
+++ b/i18n/api/en.json
@@ -42,5 +42,6 @@
        "bs-wikipage-tasks-error-page-read-not-allowed": "You are not allowed 
to read page '$1'.",
        "bs-wikipage-tasks-error-nothingtoremove": "There are no categories to 
remove",
        "apihelp-bs-category-treestore-description": "Lists the sub-categories 
of a specific category",
-       "apihelp-bs-category-treestore-param-node": "A path of categories 
separated by slash"
+       "apihelp-bs-category-treestore-param-node": "A path of categories 
separated by slash",
+       "bs-api-task-taskdata-help": "[$1 Schema], [$2 Parameter examples]"
 }
diff --git a/i18n/api/qqq.json b/i18n/api/qqq.json
index 9026adc..e353359 100644
--- a/i18n/api/qqq.json
+++ b/i18n/api/qqq.json
@@ -43,5 +43,6 @@
        "bs-wikipage-tasks-error-page-read-not-allowed": "An error message that 
occurs if a user is not allowed to read page with name '$1'.\n\nParameters:\n* 
$1 - a page title",
        "bs-wikipage-tasks-error-nothingtoremove": "This error message occurs 
if empty array is passed to task_removeCategories method",
        "apihelp-bs-category-treestore-description": 
"{{doc-apihelp-description|bs-category-treestore}}",
-       "apihelp-bs-category-treestore-param-node": 
"{{doc-apihelp-param|bs-category-treestore|node}}"
+       "apihelp-bs-category-treestore-param-node": 
"{{doc-apihelp-param|bs-category-treestore|node}}",
+       "bs-api-task-taskdata-help": "Text for API help 
page.\\n\nParameters:\n* $1 - an url to the API endpoint schema\n* $2 - an url 
to parameter examples"
 }
diff --git a/includes/api/BSApiTasksBase.php b/includes/api/BSApiTasksBase.php
index 539a827..c7b7de8 100644
--- a/includes/api/BSApiTasksBase.php
+++ b/includes/api/BSApiTasksBase.php
@@ -1,6 +1,6 @@
 <?php
 /**
- * Provides the base api for BlueSpice.
+ * Provides the base task api for BlueSpice.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -41,6 +41,22 @@
 
        /**
         * Methods that can be called by task param
+        * e.g.
+        * array(
+        *    'taskname' => array(
+        *       'examples' => [
+        *           [
+        *               'paramname' => 'Some string'
+        *           ]
+        *       ],
+        *       'params' => array(
+        *                      'paramname' => array(
+        *                               'type' => string,
+        *                       'required' => true
+        *                      )
+        *              )
+        *    )
+        * );
         * @var array
         */
        protected $aTasks = array();
@@ -65,6 +81,23 @@
        protected $oExtendedContext = null;
 
        /**
+        *
+        * @var BSTasksApiSpec
+        */
+       protected $oTasksSpec = null;
+
+       /**
+        * @param ApiMain $mainModule
+        * @param string $moduleName Name of this module
+        * @param string $modulePrefix Prefix to use for parameter names
+        */
+       public function __construct( \ApiMain $mainModule, $moduleName, 
$modulePrefix = '' ) {
+               $this->aTasks = array_merge( $this->aTasks,  
$this->aGlobalTasks );
+               $this->oTasksSpec = new BSTasksApiSpec( $this->aTasks );
+               parent::__construct($mainModule, $moduleName, $modulePrefix);
+       }
+
+       /**
         * The execute() method will be invoked directly by ApiMain immediately
         * before the result of the module is output. Aside from the
         * constructor, implementations should assume that no other methods
@@ -74,6 +107,19 @@
         */
        public function execute() {
                $aParams = $this->extractRequestParams();
+
+               /**
+                * As we disable "needToken" of one of the following flags is 
set we
+                * need to make sure that no task is being executed!
+                */
+               if( isset( $aParams['schema'] ) ) {
+                       $this->returnTaskDataSchema( $aParams['task'] );
+                       return;
+               }
+               if( isset( $aParams['examples'] ) ) {
+                       $this->returnTaskDataExamples( $aParams['task'] );
+                       return;
+               }
                $this->initContext();
 
                //Avoid API warning: register the parameter used to bust 
browser cache
@@ -84,7 +130,7 @@
                $oResult = $this->makeStandardReturn();
 
                if( !is_callable( array( $this, $sMethod ) ) ) {
-                       $oResult->errors['task'] = 'Task '.$sTask.' not 
implemented';
+                       $oResult->errors['task'] = "Task '$sTask' not 
implemented!";
                }
                else {
                        $res = $this->checkTaskPermission( $sTask );
@@ -103,7 +149,7 @@
                                $oTaskData = $this->getParameter( 'taskData' );
                                Hooks::run( 'BSApiTasksBaseBeforeExecuteTask', 
array( $this, $sTask, &$oTaskData , &$aParams ) );
 
-                               $oResult = $this->validateTaskData( $oTaskData 
);
+                               $oResult = $this->validateTaskData( $sTask, 
$oTaskData );
                                if( empty( $oResult->errors ) && empty( 
$oResult->message ) ) {
                                        try {
                                                $oResult = $this->$sMethod( 
$oTaskData , $aParams );
@@ -239,34 +285,39 @@
         * @return array
         */
        protected function getAllowedParams() {
-               $this->aTasks = array_merge( $this->aTasks,  
$this->aGlobalTasks );
                return array(
                        'task' => array(
                                ApiBase::PARAM_REQUIRED => true,
-                               ApiBase::PARAM_TYPE => $this->aTasks,
-                               10 /*ApiBase::PARAM_HELP_MSG*/ => 
'apihelp-bs-task-param-task',
+                               ApiBase::PARAM_TYPE => 
$this->oTasksSpec->getTaskNames(),
+                               ApiBase::PARAM_HELP_MSG => 
'apihelp-bs-task-param-task',
+                               ApiBase::PARAM_HELP_MSG_PER_VALUE => 
$this->makeTaskHelpMessages()
                        ),
                        'taskData' => array(
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => false,
                                ApiBase::PARAM_DFLT => '{}',
-                               10 /*ApiBase::PARAM_HELP_MSG*/ => 
'apihelp-bs-task-param-taskdata',
+                               ApiBase::PARAM_HELP_MSG => 
'apihelp-bs-task-param-taskdata',
                        ),
                        'context' => array(
                                ApiBase::PARAM_TYPE => 'string',
                                ApiBase::PARAM_REQUIRED => false,
                                ApiBase::PARAM_DFLT => '{}',
-                               10 /*ApiBase::PARAM_HELP_MSG*/ => 
'apihelp-bs-task-param-context',
+                               ApiBase::PARAM_HELP_MSG => 
'apihelp-bs-task-param-context',
+                       ),
+                       'schema' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => false,
+                               ApiBase::PARAM_HELP_MSG => 
'apihelp-bs-task-param-schema',
+                       ),
+                       'examples' => array(
+                               ApiBase::PARAM_TYPE => 'string',
+                               ApiBase::PARAM_REQUIRED => false,
+                               ApiBase::PARAM_HELP_MSG => 
'apihelp-bs-task-param-examples',
                        ),
                        'format' => array(
                                ApiBase::PARAM_DFLT => 'json',
                                ApiBase::PARAM_TYPE => array( 'json', 'jsonfm' 
),
-                               10 /*ApiBase::PARAM_HELP_MSG*/ => 
'apihelp-bs-task-param-format',
-                       ),
-                       'token' => array(
-                               ApiBase::PARAM_TYPE => 'string',
-                               ApiBase::PARAM_REQUIRED => true,
-                               10 /*ApiBase::PARAM_HELP_MSG*/ => 
'apihelp-bs-task-param-token',
+                               ApiBase::PARAM_HELP_MSG => 
'apihelp-bs-task-param-format',
                        )
                );
        }
@@ -311,8 +362,9 @@
         * @return type
         */
        public function getExamples() {
+               $aTaskNames = $this->oTasksSpec->getTaskNames();
                return array(
-                       
'api.php?action='.$this->getModuleName().'&task='.$this->aTasks[0].'&taskData={someKey:"someValue",isFalse:true}',
+                       
'api.php?action='.$this->getModuleName().'&task='.$aTaskNames[0].'&taskData={someKey:"someValue",isFalse:true}',
                );
        }
 
@@ -379,36 +431,18 @@
 
        /**
         * NOT IMPLEMENTED YET
-        * Return the param definition for each task
-        * array(
-        *    taskname => array(
-        *       paramname => array(
-        *           type => string,
-        *           required => true,
-        *           default => '',
-        *       )
-        *    )
-        * );
-        * @return array - or false to skip validation
-        */
-       public function getTaskDataDefinitions() {
-               return false;
-       }
-
-       /**
-        * NOT IMPLEMENTED YET
         * Use ParamProcessor to validate taskData params
+        * @param string $sTask
         * @param stdClass $oTaskData
         * @return stdClass - Standard return
         */
-       protected function validateTaskData( $oTaskData ) {
-               $aDefinitions = $this->getTaskDataDefinitions();
+       protected function validateTaskData( $sTask, $oTaskData ) {
+               $aDefinitions = $this->oTasksSpec->getTaskDataDefinition( 
$sTask );
                $oReturn = $this->makeStandardReturn();
                if( $aDefinitions === false ) {
                        return $oReturn;
                }
                //TODO: Use ParamProcessor to validate params defined by
-               //$this->getTaskDataDefinitions().
                return $oReturn;
        }
 
@@ -417,6 +451,10 @@
         * @return string
         */
        public function needsToken() {
+               if( $this->isTaskDataSchemaCall() || 
$this->isTaskDataExamplesCall() ) {
+                       return false;
+               }
+
                return 'csrf';
        }
 
@@ -489,4 +527,65 @@
                        'getUserTaskPermissions' => array( 'read' )
                );
        }
+
+       protected function makeTaskHelpMessages() {
+               $aMessages = [];
+               $aUrlParams = [
+                       'path' => wfScript( 'api' )
+               ];
+
+               foreach( $this->oTasksSpec->getTaskNames() as $sTaskName ) {
+                       $aMessages[$sTaskName] = [
+                               'bs-api-task-taskdata-help',
+                               wfExpandUrl( wfAssembleUrl( $aUrlParams + [
+                                       'query' => wfArrayToCgi( [
+                                               'action' => 
$this->getModuleName(),
+                                               'task' => $sTaskName,
+                                               'schema' => ''
+                                       ] )
+                               ] ) ),
+                               wfExpandUrl( wfAssembleUrl( $aUrlParams + [
+                                       'query' => wfArrayToCgi( [
+                                               'action' => 
$this->getModuleName(),
+                                               'task' => $sTaskName,
+                                               'examples' => ''
+                                       ] )
+                               ] ) )
+                       ];
+               }
+
+               return $aMessages;
+       }
+
+       protected function returnTaskDataSchema( $sTaskName ) {
+               $this->getResult()->addValue( 
+                       null,
+                       'taskData',
+                       $this->oTasksSpec->getSchema( $sTaskName )
+               );
+       }
+
+       protected function returnTaskDataExamples( $sTaskName ) {
+               $this->getResult()->addValue( 
+                       null,
+                       'taskData',
+                       $this->oTasksSpec->getExamples( $sTaskName )
+               );
+       }
+
+       public function getCustomPrinter() {
+               if( $this->isTaskDataSchemaCall() || 
$this->isTaskDataExamplesCall() ) {
+                       return new BSApiFormatJson( $this->getMain(), 'jsonfm' 
);
+               }
+
+               return parent::getCustomPrinter();
+       }
+
+       protected function isTaskDataSchemaCall() {
+               return $this->getRequest()->getVal( 'schema', null ) !== null;
+       }
+
+       protected function isTaskDataExamplesCall() {
+               return $this->getRequest()->getVal( 'examples', null ) !== null;
+       }
 }
diff --git a/includes/api/BSApiWikiPageTasks.php 
b/includes/api/BSApiWikiPageTasks.php
index 9aeb7fb..e5d2512 100644
--- a/includes/api/BSApiWikiPageTasks.php
+++ b/includes/api/BSApiWikiPageTasks.php
@@ -32,13 +32,146 @@
  */
 class BSApiWikiPageTasks extends BSApiTasksBase {
        protected $aTasks = array(
-               'setCategories',
-               'getExplicitCategories',
-               'addCategories',
-               'removeCategories',
-               'getDiscussionCount'
+               'setCategories' => [
+                       //'permissions' => [], //TODO migrate 
"getRequiredTaskPermissions"
+                       'examples' => [
+                               [
+                                       'page_id' => 3234,
+                                       'categories' => [ 'Category A', 
'Category_B' ]
+                               ],
+                               [
+                                       'page_title' => 'SomeNamespace:Some 
page title',
+                                       'categories' => []
+                               ]
+                       ],
+                       'params' => [
+                               'page_id' => [
+                                       'type' => 'integer',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_title' ]
+                               ],
+                               'page_title' => [
+                                       'type' => 'string',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_id' ]
+                               ],
+                               'categories' => [
+                                       'type' => 'list',
+                               'required' => false,
+                                   'default' => [],
+                               ]
+                       ]
+               ],
+               'getExplicitCategories' => [
+                       'examples' => [
+                               [
+                                       'page_id' => 3234
+                               ],
+                               [
+                                       'page_title' => 'SomeNamespace:Some 
page title',
+                               ]
+                       ],
+                       'params' => [
+                               'page_id' => [
+                                       'type' => 'integer',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_title' ]
+                               ],
+                               'page_title' => [
+                                       'type' => 'string',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_id' ]
+                               ]
+                       ]
+               ],
+               'addCategories' => [
+                       'examples' => [
+                               [
+                                       'page_id' => 3234,
+                                       'categories' => [ 'Category A', 
'Category_B' ]
+                               ],
+                               [
+                                       'page_title' => 'SomeNamespace:Some 
page title',
+                                       'categories' => [ 'Category A', 
'Category_B' ]
+                               ]
+                       ],
+                       'params' => [
+                               'page_id' => [
+                                       'type' => 'integer',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_title' ]
+                               ],
+                               'page_title' => [
+                                       'type' => 'string',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_id' ]
+                               ],
+                               'categories' => [
+                                       'type' => 'list',
+                               'required' => false,
+                                   'default' => [],
+                               ]
+                       ]
+               ],
+               'removeCategories' => [
+                       'examples' => [
+                               [
+                                       'page_id' => 3234,
+                                       'categories' => [ 'Category A', 
'Category_B' ]
+                               ],
+                               [
+                                       'page_title' => 'SomeNamespace:Some 
page title',
+                                       'categories' => [ 'Category A', 
'Category_B' ]
+                               ]
+                       ],
+                       'params' => [
+                               'page_id' => [
+                                       'descMsg' => 
'bs-api-tadk-taskData-page_id',
+                                       'type' => 'integer',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_title' ]
+                               ],
+                               'page_title' => [
+                                       'type' => 'string',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_id' ]
+                               ],
+                               'categories' => [
+                                       'type' => 'list',
+                               'required' => false,
+                                   'default' => [],
+                               ]
+                       ]
+               ],
+               'examples' => [
+                               [
+                                       'page_id' => 3234
+                               ],
+                               [
+                                       'page_title' => 'SomeNamespace:Some 
page title'
+                               ]
+                       ],
+               'getDiscussionCount' => [
+                       //'readonly' => true, //TODO migrate "$this->aReadTasks"
+                       'params' => [
+                               'page_id' => [
+                                       'type' => 'integer',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_title' ]
+                               ],
+                               'page_title' => [
+                                       'type' => 'string',
+                               'required' => true,
+                                       'alternative_to' => [ 'page_id' ]
+                               ]
+                       ]
+               ]
        );
 
+       protected $aReadTasks = [
+               'getDiscussionCount', 'getExplicitCategories'
+       ];
+
        /**
         * Configures the global permission requirements
         * @return array
diff --git a/includes/utility/BSTasksApiSpec.php 
b/includes/utility/BSTasksApiSpec.php
new file mode 100644
index 0000000..03a2ce4
--- /dev/null
+++ b/includes/utility/BSTasksApiSpec.php
@@ -0,0 +1,65 @@
+<?php
+
+class BSTasksApiSpec {
+       protected $aInitialConfig = [];
+
+       protected $aTaskNames = [];
+
+       public function __construct( $aTasks ) {
+               $this->aInitialConfig = $aTasks;
+               $this->extractTaskNames();
+       }
+
+       /**
+        *
+        * @return string[]
+        */
+       public function getTaskNames() {
+               return $this->aTaskNames;
+       }
+
+       /**
+        *
+        * @param string $sTaskName
+        * @return array the spec
+        */
+       public function getTaskSpec( $sTaskName ) {
+
+       }
+
+       /**
+        *
+        * @param string $sTaskName
+        * @return array
+        */
+       public function getTaskDataDefinition( $sTaskName ) {
+               $aTaskSpec = $this->getTaskSpec( $sTaskName );
+               return isset( $aTaskSpec['params'] ) ? $aTaskSpec['params'] : 
[];
+       }
+
+       protected function extractTaskNames() {
+               foreach( $this->aInitialConfig as $mKey => $mValue ) {
+                       if( is_string( $mKey ) && is_array( $mValue ) ) {
+                               $this->aTaskNames[] = $mKey;
+                       }
+                       elseif( is_int( $mKey ) && is_string( $mValue ) ) {
+                               $this->aTaskNames[] = $mValue;
+                       }
+                       else {
+                               throw new MWException( 'Unsupported TaskAPI 
spec format!' );
+                       }
+               }
+       }
+
+       public function getSchema( $sTaskName ) {
+               return [
+                       'type' => 'object',
+                       'properties' => [ 'Not implemented yet' ]
+               ];
+       }
+
+       public function getExamples( $sTaskName ) {
+               return [ 'Not implemented yet' ];
+       }
+
+}
\ No newline at end of file
diff --git a/tests/utility/BSTasksApiSpecTest.php 
b/tests/utility/BSTasksApiSpecTest.php
new file mode 100644
index 0000000..d4d9823
--- /dev/null
+++ b/tests/utility/BSTasksApiSpecTest.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * @group BlueSpice
+ */
+class BSTasksApiSpecTest extends MediaWikiTestCase {
+
+       public function testGetTaskNames() {
+               $aTasks = [ 'test1', 'test2', 'test3' ];
+               $oSpec = new BSTasksApiSpec( $aTasks );
+               $this->assertArrayEquals( $aTasks, $oSpec->getTaskNames() );
+
+               $aTasks2 = [
+                       'test1' => [],
+                       'test2' => [],
+                       'test3' => [],
+               ];
+               $oSpec2 = new BSTasksApiSpec( $aTasks2 );
+               $this->assertArrayEquals( $aTasks, $oSpec2->getTaskNames() );
+
+               $aTasks3 = [
+                       'test1' => [],
+                       'test2',
+                       'test3' => [],
+               ];
+
+               $oSpec3 = new BSTasksApiSpec( $aTasks3 );
+               $this->assertArrayEquals( $aTasks, $oSpec3->getTaskNames() );
+       }
+
+       /**
+        * @expectedException MWException
+        */
+       public function testUnsupportedTaskSpecException1() {
+               new BSTasksApiSpec( [
+                       'is a string' => 'is not an array'
+               ] );
+       }
+
+       /**
+        * @expectedException MWException
+        */
+       public function testUnsupportedTaskSpecException2() {
+               new BSTasksApiSpec( [
+                       0 => [ 'key is int, but value is not array' ]
+               ] );
+       }
+}
\ No newline at end of file

-- 
To view, visit https://gerrit.wikimedia.org/r/345852
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6d6b7d4d2e5b619728e843853634e3491ad0e3cb
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/BlueSpiceFoundation
Gerrit-Branch: master
Gerrit-Owner: Robert Vogel <vo...@hallowelt.biz>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to