MDL-12886 minor web service code refactoring which includes new base server class...
authorskodak <skodak>
Mon, 12 Oct 2009 21:46:16 +0000 (21:46 +0000)
committerskodak <skodak>
Mon, 12 Oct 2009 21:46:16 +0000 (21:46 +0000)
42 files changed:
admin/external_forms.php [new file with mode: 0644]
admin/external_service.php [new file with mode: 0644]
admin/external_service_functions.php [new file with mode: 0644]
admin/external_service_users.php [new file with mode: 0644]
admin/settings/plugins.php
admin/settings/security.php
admin/webservice_protocols.php [new file with mode: 0644]
admin/webservices.php [deleted file]
admin/wsprotocols.php [deleted file]
lang/en_utf8/admin.php
lang/en_utf8/webservice.php
lang/en_utf8/webservice_amf.php [new file with mode: 0644]
lang/en_utf8/webservice_rest.php [new file with mode: 0644]
lang/en_utf8/webservice_soap.php [new file with mode: 0644]
lang/en_utf8/webservice_xmlrpc.php [new file with mode: 0644]
lib/adminlib.php
lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_get_string.log.php
lib/simpletest/get_string_fixtures/pagelogs/admin_index.php_old_get_string.log.php
webservice/lib.php
webservice/rest/db/access.php [new file with mode: 0644]
webservice/rest/lib.php [deleted file]
webservice/rest/locallib.php
webservice/rest/server.php
webservice/rest/simpleserver.php
webservice/rest/testclient/addgroupmember.php [deleted file]
webservice/rest/testclient/config_rest.php [deleted file]
webservice/rest/testclient/creategroup.php [deleted file]
webservice/rest/testclient/createuser.php [deleted file]
webservice/rest/testclient/deletegroup.php [deleted file]
webservice/rest/testclient/deletegroupmember.php [deleted file]
webservice/rest/testclient/deleteuser.php [deleted file]
webservice/rest/testclient/getgroup.php [deleted file]
webservice/rest/testclient/getusers.php [deleted file]
webservice/rest/testclient/index.php
webservice/rest/testclient/lib.php [deleted file]
webservice/rest/testclient/moodle_group_get_groups_form.php [new file with mode: 0644]
webservice/rest/testclient/return.gif [deleted file]
webservice/rest/testclient/style.css [deleted file]
webservice/rest/testclient/updateuser.php [deleted file]
webservice/rest/version.php [new file with mode: 0644]
webservice/webservice_test_client_form.php [new file with mode: 0644]
webservice/wsdoc.php

diff --git a/admin/external_forms.php b/admin/external_forms.php
new file mode 100644 (file)
index 0000000..3e24b66
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Web services admin UI forms
+ *
+ * @package   webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once $CFG->libdir.'/formslib.php';
+
+class external_service_form extends moodleform {
+    function definition() {
+        global $CFG, $USER;
+
+        $mform = $this->_form;
+        $service = $this->_customdata;
+
+        $mform->addElement('header', 'extservice', get_string('externalservice', 'webservice'));
+
+        $mform->addElement('text', 'name', get_string('name'));
+        $mform->addElement('advcheckbox', 'enabled', get_string('enabled', 'webservice'));
+        $mform->addElement('text', 'requiredcapability', get_string('requiredcapability', 'webservice'));
+        $mform->addElement('advcheckbox', 'restrictedusers', get_string('restrictedusers', 'webservice'));
+
+        $mform->addElement('hidden', 'id');
+        $mform->setType('id', PARAM_INT);
+
+        $this->add_action_buttons(true);
+
+        $this->set_data($service);
+    }
+
+    function definition_after_data() {
+        $mform = $this->_form;
+        $service = $this->_customdata;
+
+        if (!empty($service->component)) {
+            // custom component
+            $mform->hardFreeze('name,requiredcapability,restrictedusers');
+        }
+    }
+}
+
+class external_service_functions_form extends moodleform {
+    function definition() {
+        global $CFG, $USER, $DB;
+
+        $mform = $this->_form;
+        $data = $this->_customdata;
+
+        $mform->addElement('header', 'addfunction', get_string('addfunction', 'webservice'));
+
+        $select = "name NOT IN (SELECT s.functionname
+                                  FROM {external_services_functions} s
+                                 WHERE s.externalserviceid = :sid
+                               )";
+
+        $functions = $DB->get_records_select_menu('external_functions', $select, array('sid'=>$data['id']), 'name', 'id, name');
+
+        $mform->addElement('select', 'fid', get_string('name'), $functions);
+
+        $mform->addElement('hidden', 'id');
+        $mform->setType('id', PARAM_INT);
+
+        $mform->addElement('hidden', 'action');
+        $mform->setType('action', PARAM_ACTION);
+
+        $this->add_action_buttons(true);
+
+        $this->set_data($data);
+    }
+}
diff --git a/admin/external_service.php b/admin/external_service.php
new file mode 100644 (file)
index 0000000..089ef3f
--- /dev/null
@@ -0,0 +1,84 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Web services admin UI
+ *
+ * @package   webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+require_once('external_forms.php');
+
+$id      = required_param('id', PARAM_INT);
+$action  = optional_param('action', '', PARAM_ACTION);
+$confirm = optional_param('confirm', 0, PARAM_BOOL);
+
+$PAGE->set_url('admin/external_service.php', array('id'=>$id));
+
+admin_externalpage_setup('externalservice');
+
+$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=externalservices";
+
+if ($id) {
+    $service = $DB->get_record('external_services', array('id'=>$id), '*', MUST_EXIST);
+} else {
+    $service = null;
+}
+
+if ($action == 'delete' and confirm_sesskey() and $service and empty($service->component)) {
+    if (!$confirm) {
+        admin_externalpage_print_header();
+        $optionsyes = array('id'=>$id, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey());
+        $optionsno  = array('section'=>'externalservices');
+        $formcontinue = html_form::make_button('external_service.php', $optionsyes, get_string('delete'), 'post');
+        $formcancel = html_form::make_button('settings.php', $optionsno, get_string('cancel'), 'get');
+        echo $OUTPUT->confirm(get_string('deleteserviceconfirm', 'webservice', $service->name), $formcontinue, $formcancel);
+        echo $OUTPUT->footer();
+        die;
+    }
+    $DB->delete_records('external_services_users', array('externalserviceid'=>$service->id));
+    $DB->delete_records('external_services_functions', array('externalserviceid'=>$service->id));
+    $DB->delete_records('external_services', array('id'=>$service->id));
+    redirect($returnurl);
+}
+
+$mform = new external_service_form(null, $service);
+
+if ($mform->is_cancelled()) {
+    redirect($returnurl);
+
+} else if ($data = $mform->get_data()) {
+    $data = (object)$data;
+
+    //TODO: add timecreated+modified and maybe logging too
+    if (empty($data->id)) {
+        $DB->insert_record('external_services', $data);
+    } else {
+        $DB->update_record('external_services', $data);
+    }
+
+    redirect($returnurl);
+}
+
+admin_externalpage_print_header();
+$mform->display();
+echo $OUTPUT->footer();
+
diff --git a/admin/external_service_functions.php b/admin/external_service_functions.php
new file mode 100644 (file)
index 0000000..298fb30
--- /dev/null
@@ -0,0 +1,142 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Web services function UI
+ *
+ * @package   webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+require_once('external_forms.php');
+
+$id      = required_param('id', PARAM_INT);
+$fid     = optional_param('fid', 0, PARAM_INT);
+$action  = optional_param('action', '', PARAM_ACTION);
+$confirm = optional_param('confirm', 0, PARAM_BOOL);
+
+$PAGE->set_url('admin/external_service_functions.php', array('id'=>$id));
+
+admin_externalpage_setup('externalservicefunctions');
+
+$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=externalservices";
+$thisurl   = "external_service_functions.php?id=$id";
+
+$service = $DB->get_record('external_services', array('id'=>$id), '*', MUST_EXIST);
+
+if ($action === 'delete' and confirm_sesskey() and $service and empty($service->component)) {
+    $function = $DB->get_record('external_functions', array('id'=>$fid), '*', MUST_EXIST);
+    if (!$confirm) {
+        admin_externalpage_print_header();
+        $optionsyes = array('id'=>$id, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey(), 'fid'=>$function->id);
+        $optionsno  = array('id'=>$id);
+        $formcontinue = html_form::make_button('external_service_functions.php', $optionsyes, get_string('delete'), 'post');
+        $formcancel = html_form::make_button('external_service_functions.php', $optionsno, get_string('cancel'), 'get');
+        echo $OUTPUT->confirm(get_string('removefunctionconfirm', 'webservice', (object)array('service'=>$service->name, 'function'=>$function->name)), $formcontinue, $formcancel);
+        echo $OUTPUT->footer();
+        die;
+    }
+    $DB->delete_records('external_services_functions', array('externalserviceid'=>$service->id, 'functionname'=>$function->name));
+    redirect($thisurl);
+
+} else if ($action === 'add') {
+    $mform = new external_service_functions_form(null, array('action'=>'add', 'id'=>$service->id));
+
+    if ($mform->is_cancelled()) {
+        redirect($thisurl);
+    } else if ($data = $mform->get_data()) {
+        ignore_user_abort(true); // no interruption here!
+        $function = $DB->get_record('external_functions', array('id'=>$data->fid), '*', MUST_EXIST);
+        // make sure the function is not there yet
+        if ($DB->record_exists('external_services_functions', array('externalserviceid'=>$service->id, 'functionname'=>$function->name))) {
+            redirect($thisurl);
+        }
+        $new = new object();
+        $new->externalserviceid = $service->id;
+        $new->functionname      = $function->name;
+        $DB->insert_record('external_services_functions', $new);
+        redirect($thisurl);
+    }
+
+    //ask for function id
+    admin_externalpage_print_header();
+    echo $OUTPUT->heading($service->name);
+    $mform->display();
+    echo $OUTPUT->footer();
+    die;
+}
+
+admin_externalpage_print_header();
+
+echo $OUTPUT->heading($service->name);
+
+$select = "name IN (SELECT s.functionname
+                      FROM {external_services_functions} s
+                     WHERE s.externalserviceid = :sid
+                   )";
+
+$functions = $DB->get_records_select('external_functions', $select, array('sid'=>$service->id), 'name');
+
+$strfunction = get_string('function', 'webservice');
+$strdelete = get_string('removefunction', 'webservice');
+$stredit = get_string('edit');
+
+$table = new html_table();
+$table->head  = array($strfunction);
+$table->align = array('left');
+$table->width = '100%';
+$table->data  = array();
+if (empty($service->component)) {
+    $table->head[] = $stredit;
+    $table->align[] = 'center';
+}
+
+$durl = "$CFG->wwwroot/$CFG->admin/external_service_functions.php?sesskey=".sesskey();
+
+foreach ($functions as $function) {
+    if (empty($service->component)) {
+        $delete = "<a href=\"$durl&amp;action=delete&amp;fid=$function->id&amp;id=$service->id\">$strdelete</a>";
+        $table->data[] = array($function->name, $delete);
+    } else {
+        $table->data[] = array($function->name);
+    }
+}
+
+echo $OUTPUT->table($table);
+
+
+// we can edit only custom functions, the build-in would be overridden after each upgrade
+if (empty($service->component)) {
+    $form = new html_form();
+    $form->url = new moodle_url('external_service_functions.php', array('sesskey'=>sesskey(), 'id'=>$service->id, 'action'=>'add'));
+    $form->button->text = get_string('add');
+    $form->method = 'get';
+    echo $OUTPUT->button($form);
+}
+
+// simple back button
+$form = new html_form();
+$form->url = new moodle_url('settings.php', array('section'=>'externalservices'));
+$form->button->text = get_string('back');
+$form->method = 'get';
+echo $OUTPUT->button($form);
+
+echo $OUTPUT->footer();
+
diff --git a/admin/external_service_users.php b/admin/external_service_users.php
new file mode 100644 (file)
index 0000000..e3b7584
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Web services function UI
+ *
+ * @package   webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+require_once('external_forms.php');
+
+$id = required_param('id', PARAM_INT);
+
+$PAGE->set_url('admin/external_service_users.php', array('id'=>$id));
+
+admin_externalpage_setup('externalserviceusers');
+
+echo('TODO: we need something like the role assign UI');
+
+echo $OUTPUT->footer();
\ No newline at end of file
index 1161a4b..8c98159 100644 (file)
@@ -237,6 +237,33 @@ if ($hassiteconfig || has_capability('moodle/question:config', $systemcontext))
         }
     }
 
+    // Web services
+    $ADMIN->add('modules', new admin_category('webservicesettings', get_string('webservices', 'webservice')));
+    $temp = new admin_settingpage('externalservices', get_string('externalservices', 'webservice'));
+    $temp->add(new admin_setting_manageexternalservices());
+    $ADMIN->add('webservicesettings', $temp);
+    $ADMIN->add('webservicesettings', new admin_externalpage('externalservice', get_string('externalservice', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service.php"), 'moodle/site:config', true);
+    $ADMIN->add('webservicesettings', new admin_externalpage('externalservicefunctions', get_string('externalservicefunctions', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service_functions.php"), 'moodle/site:config', true);
+    $ADMIN->add('webservicesettings', new admin_externalpage('externalserviceusers', get_string('externalserviceusers', 'webservice'), "$CFG->wwwroot/$CFG->admin/external_service_users.php"), 'moodle/site:config', true);
+    $temp = new admin_settingpage('webserviceprotocols', get_string('manageprotocols', 'webservice'));
+    $temp->add(new admin_setting_managewebserviceprotokols());
+    if (empty($CFG->enablewebservices)) {
+        $temp->add(new admin_setting_heading('webservicesaredisabled', '', get_string('disabledwarning', 'webservice')));
+    }
+    $ADMIN->add('webservicesettings', $temp);
+    $webservices_available = get_plugin_list('webservice');
+    $active_webservices = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
+    foreach ($webservices_available as $webservice => $location) {
+        if (file_exists("$location/settings.php")) {
+            $name = get_string('pluginname', 'webservice_'.$webservice);
+            $settings = new admin_settingpage('webservicesetting'.$webservice, $name, 'moodle/site:config', !in_array($webservice, $active_webservices) or empty($CFG->enablewebservices));
+            if ($ADMIN->fulltree) {
+                include("$location/settings.php");
+            }
+            $ADMIN->add('webservicesettings', $settings);
+        }
+    }
+
     // Question type settings.
     $ADMIN->add('modules', new admin_category('qtypesettings', get_string('questiontypes', 'admin')));
     $ADMIN->add('qtypesettings', new admin_page_manageqtypes());
index e5601f8..71145d2 100644 (file)
@@ -11,26 +11,6 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
                                                 '', ''));
     $ADMIN->add('security', $temp);
 
-    // "web service" settingpage
-    $temp = new admin_settingpage('webservices', get_string('webservices', 'admin'));
-    $temp->add(new admin_setting_heading('webserviceprotocols', get_string('protocols', 'webservice'), ''));
-    $temp->add(new admin_setting_managewsprotocols());
-    $url = $CFG->wwwroot.'/'.$CFG->admin.'/wsprotocols.php';
-    $ADMIN->add('security', new admin_externalpage('managews',
-        get_string('managews', 'admin'), $url, 'moodle/site:config', true),
-        '', $url);
-    $temp->add(new admin_setting_heading('webservicesystemsettings', get_string('systemsettings', 'webservice'), ''));
-    $temp->add(new admin_setting_configiplist('ipwhitelist', get_string('ipwhitelist', 'admin'),'', ''));
-    $temp->add(new admin_setting_heading('webserviceusersettings', get_string('usersettings', 'webservice'), ''));
-    $temp->add(new admin_setting_managewsusersettings());
-    $temp->add(new admin_setting_heading('webserviceservicelist', get_string('servicelist', 'webservice'), ''));
-    $temp->add(new admin_setting_managewsservicelist());
-    $url = $CFG->wwwroot.'/'.$CFG->admin.'/webservices.php';
-     $ADMIN->add('security', new admin_externalpage('webservicessettings',
-        get_string('webservicessettings', 'admin'), $url, 'moodle/site:config', true),
-        '', $url);
-    $ADMIN->add('security', $temp);
-
     // "sitepolicies" settingpage
     $temp = new admin_settingpage('sitepolicies', get_string('sitepolicies', 'admin'));
     $temp->add(new admin_setting_configcheckbox('protectusernames', get_string('protectusernames', 'admin'), get_string('configprotectusernames', 'admin'), 1));
@@ -137,4 +117,4 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
 
 } // end of speedup
 
-?>
+
diff --git a/admin/webservice_protocols.php b/admin/webservice_protocols.php
new file mode 100644 (file)
index 0000000..e1b7aba
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Web services protocols admin UI
+ *
+ * @package   webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+require_once($CFG->libdir.'/tablelib.php');
+
+$PAGE->set_url('admin/webservice_protocols.php', array());
+//TODO: disable the blocks here or better make the page layout default to no blocks!
+
+require_login();
+require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
+
+$returnurl = "$CFG->wwwroot/$CFG->admin/settings.php?section=webserviceprotocols";
+
+$action     = optional_param('action', '', PARAM_ACTION);
+$webservice = optional_param('webservice', '', PARAM_SAFEDIR);
+$confirm    = optional_param('confirm', 0, PARAM_BOOL);
+
+// get currently installed and enabled auth plugins
+$available_webservices = get_plugin_list('webservice');
+if (!empty($webservice) and empty($available_webservices[$webservice])) {
+    redirect($returnurl);
+}
+
+$active_webservices = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
+foreach ($active_webservices as $key=>$active) {
+    if (empty($available_webservices[$active])) {
+        unset($active_webservices[$key]);
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// process actions
+
+if (!confirm_sesskey()) {
+    redirect($returnurl);
+}
+
+switch ($action) {
+    case 'uninstall':
+        die('TODO: not implemented yet');
+        break;
+
+    case 'disable':
+        // remove from enabled list
+        $key = array_search($webservice, $active_webservices);
+        unset($active_webservices[$key]);
+        break;
+
+    case 'enable':
+        // add to enabled list
+        if (!in_array($webservice, $active_webservices)) {
+            $active_webservices[] = $webservice;
+            $active_webservices = array_unique($active_webservices);
+        }
+        break;
+
+    default:
+        break;
+}
+
+set_config('webserviceprotocols', implode(',', $active_webservices));
+
+redirect($returnurl);
diff --git a/admin/webservices.php b/admin/webservices.php
deleted file mode 100644 (file)
index 8628a53..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-<?php
-
-// This file is part of Moodle - http://moodle.org/
-//
-// Moodle is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Moodle is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
-
-require_once(dirname(dirname(__FILE__)) . '/config.php');
-require_once($CFG->libdir . '/adminlib.php');
-require_once($CFG->dirroot . '/webservice/lib.php');
-
-
-$serviceid      = optional_param('serviceid', '', PARAM_FORMAT);
-$remove         = optional_param('remove', '', PARAM_FORMAT);
-
-$pagename = 'webservicessettings';
-
-
-admin_externalpage_setup($pagename);
-require_login(SITEID, false);
-require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
-
-$sesskeyurl = "$CFG->wwwroot/$CFG->admin/webservices.php?sesskey=" . sesskey();
-$baseurl    = "$CFG->wwwroot/$CFG->admin/settings.php?section=webservices";
-
-if (!confirm_sesskey()) {
-    print_error('confirmsesskeybad', '', $baseurl);
-}
-
-if (!empty($remove)) {
-    $functionserviceid         = optional_param('functionserviceid', '', PARAM_FORMAT);
-    if (!empty($functionserviceid)) {
-        $DB->delete_records('external_services_functions',array('id' => $functionserviceid));
-    } 
-}
-
-if (!empty($serviceid)) {
-    admin_externalpage_print_header();
-
-    //cannot use moodle form in order to display complex list of functions
-    $form = new html_form();
-    $service = $DB->get_record('external_services',array('id' => $serviceid));
-    $formhtml = get_string('servicename', 'webservice').': '.get_string($service->name, 'webservice') ;
-    $formhtml .= "<br/><br/>";
-    //display function selector
-    if (empty($serviceid)) {
-
-    }
-
-    //display service functions
-    $servicesfunctions = $DB->get_records_sql("SELECT fs.id as id, f.component as component, s.name as servicename, s.id as serviceid, f.name as functionname, f.id as functionid
-                                    FROM {external_services} s, {external_functions} f, {external_services_functions} fs
-                                   WHERE fs.externalserviceid = s.id AND fs.functionname = f.name AND s.id = ?", array($serviceid));
-
-    //save the administrator changes
-    $saved      = optional_param('saved', 0, PARAM_NUMBER);
-
-    if ($saved) {
-        foreach($servicesfunctions as &$servicefunction) { //need to be a refence cause we're going to update the form value too
-            $enabled = optional_param($servicefunction->functionname, '', PARAM_ALPHANUMEXT);
-            if ($enabled) {
-                $servicefunction->enabled =  1; //update the form "enabled" value
-            } else {
-                $servicefunction->enabled = 0; //update the form "enabled" value
-            }
-            $wsservicefunction = new object();
-            $wsservicefunction->id = $servicefunction->id;
-            $wsservicefunction->enabled = $servicefunction->enabled;
-            $DB->update_record('external_services_functions',$wsservicefunction);
-        }
-    }
-
-
-    $data = array();
-    reset($servicesfunctions);
-    foreach($servicesfunctions as $servicefunction) {
-        $checkbox = html_select_option::make_checkbox($servicefunction->functionid, $servicefunction->enabled, 'functionenabled');
-        $checkbox->label->add_class('accesshide');
-        $checkbox->disabled;
-        $checkboxhtml = $OUTPUT->checkbox($checkbox, $servicefunction->functionname);
-        $data[] = array($servicefunction->functionname, $servicefunction->component, "<a href=?sesskey=".sesskey()."&amp;serviceid=".$serviceid."&amp;remove=1&amp;functionserviceid=".$servicefunction->id.">".get_string("removefunctionfromservice","webservice")."</a>");
-    }
-    $table = new html_table();
-    $table->head  = array(get_string('functionname', 'webservice'), get_string('component', 'webservice'), get_string('actions', 'webservice'));
-    $table->size  = array('40%', '40%', '20%');
-    $table->align = array('left', 'left', 'left');
-    //$table->width = '30%';
-    $table->data  = $data;
-    $table->tablealign  = 'center';
-    $formhtml .= $OUTPUT->table($table);
-
-    $form->button->text = get_string('save', 'webservice');
-    $form->button->title = get_string('save', 'webservice');
-    $form->button->id = 'save';
-    $form->url = new moodle_url('webservices.php', array('serviceid' => $serviceid, 'saved' => 1));
-    //$form->add_class($class);
-    $formhtml .= "<br/><br/>";
-
-    echo $OUTPUT->box_start('generalbox boxaligncenter centerpara');
-    echo $OUTPUT->form($form, $formhtml);
-    echo $OUTPUT->box_end();
-
-    echo $OUTPUT->footer();
-
-}
-
-?>
diff --git a/admin/wsprotocols.php b/admin/wsprotocols.php
deleted file mode 100644 (file)
index ad0bf59..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-// $Id$
-require_once(dirname(dirname(__FILE__)) . '/config.php');
-require_once($CFG->dirroot . '/webservice/lib.php');
-require_once($CFG->libdir . '/adminlib.php');
-
-$hide    = optional_param('hide', '', PARAM_ALPHANUM);
-$username    = optional_param('username', '', PARAM_ALPHANUM);
-$settings    = optional_param('settings', '', PARAM_ALPHANUM);
-
-$pagename = 'managews';
-
-admin_externalpage_setup($pagename);
-require_login(SITEID, false);
-require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM));
-
-$baseurl    = "$CFG->wwwroot/$CFG->admin/settings.php?section=webservices";
-
-if (!confirm_sesskey()) {
-        print_error('confirmsesskeybad', '', $baseurl);
-    }
-
-if (!empty($hide)) {
-    
-    set_config("enable", !get_config($hide, "enable"), $hide);   
-    $return = true;
-} else if (!empty($username)) {
-    admin_externalpage_print_header();
-    $mform = new wsuser_form('', array('username' => $username));
-    if ($mform->is_cancelled()){
-        redirect($baseurl);
-        exit;
-    }
-    $fromform = $mform->get_data();
-
-
-
-    if (!empty($fromform)) {
-        $wsuser = $DB->get_record("user", array("username" => $fromform->username));
-        set_user_preference("ipwhitelist", $fromform->ipwhitelist, $wsuser->id);
-        redirect($baseurl,get_string("changessaved"));
-    }
-
-    echo $OUTPUT->box_start();
-    $mform->display();
-    echo $OUTPUT->box_end();
-
-} else if (!empty($settings)) {
-/// Server settings page
-    admin_externalpage_print_header();
-
-    $mform = new wssettings_form('', array('settings' => $settings)); // load the server settings form
-    
-    if ($mform->is_cancelled()){
-    /// user pressed cancel button and return to the security web service page
-        redirect($baseurl);
-        exit;
-    }
-
-    $fromform = $mform->get_data();
-
-    if (!empty($fromform)) {
-    /// save the new setting 
-        require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php');
-        $settingnames = call_user_func(array($settings.'_server', 'get_setting_names'));
-        foreach($settingnames as $settingname) {
-            if (empty($fromform->$settingname)) {
-                set_config($settingname, null, $settings);
-            } else {
-                set_config($settingname, $fromform->$settingname, $settings);
-            }
-        }
-
-        redirect($baseurl,get_string("changessaved")); // return to the security web service page
-    }
-/// display the server settings form
-    echo $OUTPUT->box_start();
-    $mform->display();
-    echo $OUTPUT->box_end();
-} else {
-    $return = true;
-}
-
-if (!empty($return)) {
-    redirect($baseurl);
-}
-
-echo $OUTPUT->footer();
index 09c1fef..dbc4c5c 100644 (file)
@@ -527,8 +527,6 @@ It is recommended to install local copy of free GeoLite City database from MaxMi
 IP address location is displayed on simple map or using Google Maps. Please note that you need to have a Google account and apply for free Google Maps API key to enable interactive maps.';
 $string['iplookupmaxmindnote'] = 'This product includes GeoLite data created by MaxMind, available from <a href=\"http://www.maxmind.com/\">http://www.maxmind.com/</a>.';
 $string['iplookupnetgeonote'] = 'The NetGeo server is currently being used to look up geographical information. For more accurate results we recommend installing a local copy of the MaxMind GeoLite database.';
-$string['ipwhitelist'] = 'IP whitelist';
-$string['ipwhitelistdesc'] = 'When not empty, only IP set here are allowed to use web service with the username: <strong>$a->username</strong>';
 $string['keeptagnamecase'] = 'Keep tag name casing';
 $string['lang'] = 'Default language';
 $string['lang16notify'] = 'Moodle 1.6 and above allows you to install and update language packs directly from download.moodle.org by following the link below';
@@ -571,7 +569,6 @@ $string['maintfileopenerror'] = 'Error opening maintenance files!';
 $string['maintinprogress'] = 'Maintenance is in progress...';
 $string['managelang'] = 'Manage';
 $string['manageqtypes'] = 'Manage question types';
-$string['managews'] = 'Manage web services';
 $string['maintenancemode'] = 'In Maintenance Mode';
 $string['maxbytes'] = 'Maximum uploaded file size';
 $string['maxeditingtime'] = 'Maximum time to edit posts';
@@ -670,6 +667,7 @@ $string['php50restricted'] = 'PHP 5.0.x has a number of known problems, please u
 $string['phpfloatproblem'] = 'Detected unexpected problem in handling of PHP float numbers - $a';
 $string['pleaseregister'] = 'Please register your site to remove this button';
 $string['pleaserefreshregistration'] = 'Your site has been registered with moodle.org, please consider updating the registration if significant changes happened since your last update, on $a';
+$string['plugin'] = 'Plugin';
 $string['plugins'] = 'Plugins';
 $string['profilecategory'] = 'Category';
 $string['profilecategoryname'] = 'Category name (must be unique)';
@@ -832,6 +830,8 @@ $string['supportname'] = 'Support name';
 $string['supportpage'] = 'Support page';
 $string['switchlang'] = 'Switch lang directory';
 $string['systempaths'] = 'System Paths';
+$string['tablenosave'] = 'Changes in table above are saved automatically.';
+$string['tablesnosave'] = 'Changes in tables above are saved automatically.';
 $string['tabselectedtofront'] = 'On tables with tabs, should the row with the currently selected tab be placed at the front';
 $string['tabselectedtofronttext'] = 'Bring selected tab row to front';
 $string['themelist'] = 'Theme list';
@@ -849,6 +849,7 @@ $string['unicodeupgradenotice'] = 'In Moodle 1.6 we have migrated all languages
 $string['unicoderecommended'] = 'Storing all your data in Unicode (UTF-8) is recommended. New installations should be performed into databases that have their default character set as Unicode.  If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).';
 $string['unicoderequired'] = 'It is required that you store all your data in Unicode format (UTF-8). New installations must be performed into databases that have their default character set as Unicode.  If you are upgrading, you should perform the UTF-8 migration process (see the Admin page).';
 $string['uninstall'] = 'Uninstall selected language pack';
+$string['uninstallplugin'] = 'Uninstall';
 $string['uninstallconfirm'] = 'You are about to completely uninstall language pack $a, are you sure?';
 $string['uninstallqtype'] = 'Uninstall this question type.';
 $string['unsupported'] = 'Unsupported';
@@ -931,7 +932,6 @@ $string['verifychangedemail'] = 'Restrict domains when changing email';
 $string['warningcurrentsetting'] = 'Invalid current value: $a';
 $string['webproxy'] = 'Web proxy';
 $string['webproxyinfo'] = 'Fill in following options if your Moodle server can not access internet directly. Internet access is required for download of environment data, language packs, RSS feeds, timezones, etc.<br /><em>PHP cURL extension is highly recommended.</em>';
-$string['webservices'] = 'Web services';
 $string['xmlrpcrecommended'] = 'Installing the optional xmlrpc extension is useful for Moodle Networking functionality.';
 $string['xmlstrictheaders'] = 'XML strict headers';
 $string['useblogassociations'] = 'Enable associations';
index 0847061..a3114fa 100644 (file)
@@ -1,61 +1,25 @@
-<?php // $Id$
-$string['activated'] = 'Activated';
-$string['activatedfunctions'] = 'Activated functions';
-$string['amfdebug'] = 'AMF server debug mode';
-$string['clicktoactivate'] = 'Click to activate';
-$string['clicktodeactivate'] = 'Click to deactivate';
-$string['component'] = 'Component';
-$string['createservicelabel'] = 'Create a custom service';
-$string['custom'] = 'Custom';
-$string['debugdisplayon'] = '\"Display debug messages\" is set On. The XMLRPC server will not work. The other web service servers could also return some problems. <br/>Alert the Moodle administrator to set it Off.';
-$string['enabled'] = 'Enabled';
-$string['fail'] = 'FAIL';
-$string['functionlist'] = 'list of web service functions';
-$string['functionname'] = 'Function name';
-$string['moodlepath'] = 'Moodle path';
-$string['ok'] = 'OK';
-$string['protocolenable'] = '$a[0] protocol enable';
-$string['protocols'] = 'Protocols';
-$string['save'] = 'Save';
-$string['servicelist'] = 'Services';
-$string['servicename'] = 'Service name';
-$string['soapdocumentation'] = '<H2>SOAP Manual</H2>
-        <b>1.</b> Call the method <b>get_token</b> on \"<i>http://remotemoodle/webservice/soap/server.php?wsdl</i>\"<br>
-        The function parameter is an array: in PHP it would be array(\"username\" => \"wsuser\", \"password\" => \"wspassword\")<br>
-        Return value is a token (integer)<br>
-        <br>
-        <b>2.</b> Then call a moodle web service method on \"<i>http://remotemoodle/webservice/soap/server.php?token=the_received_token&classpath=the_moodle_path&wsdl</i>\"<br>
-        Every method has only one parameter which is an array.<br>
-        <br>
-        For example in PHP for this specific function:<br>
-        Moodle path: <b>user</b><br>
-        <b>tmp_delete_user</b>( string username , integer mnethostid )<br>
-        You will call something like:<br>
-        your_client->tmp_delete_user(array(\"username\" => \"username_to_delete\",\"mnethostid\" => 1))<br><br>
-';
-$string['systemsettings'] = 'Common settings';
-$string['usersettings'] = 'Users with web service permissions';
-$string['webservicesenable'] = 'Web services enable';
-$string['wsdeletefunction'] = '<b>$a->functionname</b> function has been deleted from the <b>$a->servicename</b> service.';
-$string['wsinsertfunction'] = '<b>$a->functionname</b> function has been inserted into the <b>$a->servicename</b> service.';
-$string['wspagetitle'] = 'Web services documentation';
-$string['wsuserreminder'] = 'Reminder: the Moodle administrator of this site needs to give you moodle/site:usewebservices capability.';
-$string['xmlrpcdocumentation'] = '<H2>XMLRPC Manual</H2>
-        <b>1.</b> Call the method <b>authentication.get_token</b> on \"<i>http://remotemoodle/webservice/xmlrpc/server.php</i>\"<br>
-        The function parameter is an array: in PHP it would be array(\"username\" => \"wsuser\", \"password\" => \"wspassword\")<br>
-        Return value is a token (integer)<br>
-        <br>
-        <b>2.</b> Then call a moodle web service method on \"<i>http://remotemoodle/webservice/xmlrpc/server.php?classpath=the_moodle_path&token=the_received_token</i>\"<br>
-        Every method has only one parameter which is an array.<br>
-        <br>
-        For example in PHP for this specific function:<br>
-        Moodle path: <b>user</b><br>
-        <b>tmp_delete_user</b>( string username , integer mnethostid )<br>
-        You will call something like:<br>
-        your_client->call(\"user.tmp_delete_user\", array(array(\"username\" => \"username_to_delete\",\"mnethostid\" => 1)))<br>
-
-';
-
-//service names
-$string['user'] = "User";
+<?php
 
+$string['addfunction'] = 'Add function';
+$string['actwebserviceshhdr'] = 'Active web service protocols';
+$string['configwebserviceplugins'] = 'For security reasons enable only protocols that are used.';
+$string['deleteserviceconfirm'] = 'Do you really want to delete external service \"$a\"?';
+$string['disabledwarning'] = 'All webs service protocols are disabled, the \Enable web services\" setting can be found in the \"Advanced features\" section.';
+$string['enabled'] = 'Enabled';
+$string['externalservices'] = 'External services';
+$string['externalservice'] = 'External service';
+$string['externalservicefunctions'] = 'External service functions';
+$string['externalserviceusers'] = 'External service users';
+$string['function'] = 'Function';
+$string['functions'] = 'Functions';
+$string['manageprotocols'] = 'Manage protocols';
+$string['protocol'] = 'Protocol';
+$string['removefunction'] = 'Remove';
+$string['removefunctionconfirm'] = 'Do you really want to remove function \"$a->function\" from service \"$a->service\"?';
+$string['requiredcapability'] = 'Required capability';
+$string['restrictedusers'] = 'Restricted users';
+$string['servicesbuiltin'] = 'Built-in services';
+$string['servicescustom'] = 'Custom services';
+$string['test'] = 'Test';
+$string['testclient'] = 'Test client';
+$string['webservices'] = 'Web services';
diff --git a/lang/en_utf8/webservice_amf.php b/lang/en_utf8/webservice_amf.php
new file mode 100644 (file)
index 0000000..f51fe76
--- /dev/null
@@ -0,0 +1,4 @@
+<?php
+
+$string['amfdebug'] = 'AMF server debug mode';
+$string['pluginname'] = 'AMF protocok';
diff --git a/lang/en_utf8/webservice_rest.php b/lang/en_utf8/webservice_rest.php
new file mode 100644 (file)
index 0000000..3459184
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+
+$string['pluginname'] = 'REST protocol';
diff --git a/lang/en_utf8/webservice_soap.php b/lang/en_utf8/webservice_soap.php
new file mode 100644 (file)
index 0000000..a7d426e
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+
+$string['pluginname'] = 'SOAP protocol';
diff --git a/lang/en_utf8/webservice_xmlrpc.php b/lang/en_utf8/webservice_xmlrpc.php
new file mode 100644 (file)
index 0000000..48d1636
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+
+$string['pluginname'] = 'XMLRPC protocol';
index 8785e84..5bd4503 100644 (file)
@@ -4964,7 +4964,7 @@ class admin_setting_manageeditors extends admin_setting {
             $table->data[] =array($displayname, $hideshow, $updown, $settings);
         }
         $return .= $OUTPUT->table($table);
-        $return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'filters');
+        $return .= get_string('configeditorplugins', 'editor').'<br />'.get_string('tablenosave', 'admin');
         $return .= $OUTPUT->box_end();
         return highlight($query, $return);
     }
@@ -6077,26 +6077,23 @@ class admin_setting_managerepository extends admin_setting {
     }
 }
 
+
 /**
+ * Special class for management of external services
  *
- *
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @author Petr Skoda (skodak)
  */
-class admin_setting_managewsprotocols extends admin_setting {
-/** @var string */
-    private $baseurl;
-
+class admin_setting_manageexternalservices extends admin_setting {
     /**
      * Calls parent::__construct with specific arguments
      */
     public function __construct() {
-        global $CFG;
-        parent::__construct('managewsprotocols', get_string('managewsprotocols', 'admin'), '', '');
-        $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/wsprotocols.php?sesskey=' . sesskey();
+        parent::__construct('webservicesui', get_string('externalservices', 'webservice'), '', '');
     }
 
     /**
      * Always returns true, does nothing
+     *
      * @return true
      */
     public function get_setting() {
@@ -6104,157 +6101,175 @@ class admin_setting_managewsprotocols extends admin_setting {
     }
 
     /**
-     * Doesnt nothing, always returns ''
+     * Always returns true, does nothing
+     *
+     * @return true
+     */
+    public function get_defaultsetting() {
+        return true;
+    }
+
+    /**
+     * Always returns '', does not write anything
      *
      * @return string Always returns ''
      */
     public function write_setting($data) {
-        $url = $this->baseurl . '&amp;new=' . $data;
+    // do not write any setting
         return '';
     }
 
     /**
-     * Builds XHTML to display the control
+     * Checks if $query is one of the available external services
      *
-     * @param string $data
+     * @param string $query The string to search for
+     * @return bool Returns true if found, false if not
+     */
+    public function is_related($query) {
+        global $DB;
+
+        if (parent::is_related($query)) {
+            return true;
+        }
+
+        $textlib = textlib_get_instance();
+        $services = $DB->get_records('external_services', array(), 'id, name');
+        foreach ($services as $service) {
+            if (strpos($textlib->strtolower($service->name), $query) !== false) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Builds the XHTML to display the control
+     *
+     * @param string $data Unused
      * @param string $query
-     * @return string XHTML
+     * @return string
      */
     public function output_html($data, $query='') {
-        global $CFG, $OUTPUT;
+        global $CFG, $OUTPUT, $DB;
+
+        // display strings
+        $stradministration = get_string('administration');
+        $stredit = get_string('edit');
+        $strservice = get_string('externalservice', 'webservice');
+        $strdelete = get_string('delete');
+        $strplugin = get_string('plugin', 'admin');
+        $stradd = get_string('add');
+        $strfunctions = get_string('functions', 'webservice');
+        $strusers = get_string('restrictedusers', 'webservice');
+
+        $esurl = "$CFG->wwwroot/$CFG->admin/external_service.php";
+        $efurl = "$CFG->wwwroot/$CFG->admin/external_service_functions.php";
+        $euurl = "$CFG->wwwroot/$CFG->admin/external_service_users.php";
+
+        // built in services
+        $return = $OUTPUT->heading(get_string('servicesbuiltin', 'webservice'), 3, 'main', true);
+
+        $services = $DB->get_records_select('external_services', 'component IS NOT NULL', null, 'name');
 
-        $namestr = get_string('name');
-        $settingsstr = get_string('settings');
-        $hiddenstr = get_string('activated', 'webservice');
-        require_once("../webservice/lib.php");
-        $protocols = webservice_lib::get_list_protocols();
         $table = new html_table();
-        $table->head = array($namestr, $hiddenstr, $settingsstr);
-        $table->align = array('left', 'center', 'center');
-        $table->data = array();
-        $table->tablealign  = 'center';
+        $table->head  = array($strservice, $strplugin, $strfunctions, $strusers, $stredit);
+        $table->align = array('left', 'left', 'center', 'center', 'center');
+        $table->size = array('30%', '20%', '20%', '20%', '10%');
+        $table->width = '100%';
+        $table->data  = array();
 
-        foreach ($protocols as $i) {
-            $hidetitle = $i->get_protocolid() ? get_string('clicktodeactivate', 'webservice') : get_string('clicktoactivate', 'webservice');
-            $hiddenshow = ' <a href="' . $this->baseurl . '&amp;hide=' . $i->get_protocolid() . '">'
-                .'<img src="' . $OUTPUT->old_icon_url('i/' . ($i->get_enable() ? 'hide' : 'show')) . '"'
-                .' alt="' . $hidetitle . '" '
-                .' title="' . $hidetitle . '" />'
-                .'</a>' . "\n";
+        // iterate through auth plugins and add to the display table
+        foreach ($services as $service) {
+            $name = $service->name;
 
-            $settingnames = $i->get_setting_names();
-            if (!empty($settingnames)) {
-                $settingsshow = ' <a href="' . $this->baseurl . '&amp;settings=' . $i->get_protocolid() . '">'
-                    .$settingsstr
-                    .'</a>' . "\n";
+            // hide/show link
+            if ($service->enabled) {
+                $displayname = "<span>$name</span>";
             } else {
-                $settingsshow = "";
+                $displayname = "<span class=\"dimmed_text\">$name</span>";
             }
-            $table->data[] = array($i->get_protocolname(), $hiddenshow, $settingsshow);
 
-            //display a grey row if the type is defined as not visible
-            if (!$i->get_enable()) {
-                $table->rowclasses[] = 'dimmed_text';
+            $plugin = $service->component;
+
+            $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
+
+            if ($service->restrictedusers) {
+                $users = "<a href=\"$euurl?id=$service->id\">$strusers</a>";
             } else {
-                $table->rowclasses[] = '';
+                $users = '-';
             }
-        }
-        $output = $OUTPUT->table($table);
-        $output .= "<br/><br/>";
-        return highlight($query, $output);
-    }
-}
 
-/**
- *
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-class admin_setting_managewsusersettings extends admin_setting {
-/** @var string */
-    private $baseurl;
+            $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
 
-    /**
-     * Calls parent::__construct with specific arguments
-     */
-    public function __construct() {
-        global $CFG;
-        parent::__construct('managewsusersettings', get_string('managewsusersettings', 'admin'), '', '');
-        $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/wsprotocols.php?sesskey=' . sesskey();
-    }
+            // add a row to the table
+            $table->data[] = array($displayname, $plugin, $functions, $users, $edit);
+        }
+        $return .= $OUTPUT->table($table);
 
-    /**
-     * Always returns true does nothing
-     *
-     * @return true
-     */
-    public function get_setting() {
-        return true;
-    }
+        // Custom services
+        $return .= $OUTPUT->heading(get_string('servicescustom', 'webservice'), 3, 'main', true);
+        $services = $DB->get_records_select('external_services', 'component IS NULL', null, 'name');
 
-    /**
-     * Does nothing always returns ''
-     *
-     * @return string Always returns ''
-     */
-    public function write_setting($data) {
-        $url = $this->baseurl . '&amp;new=' . $data;
-        return '';
-    }
+        $table = new html_table();
+        $table->head  = array($strservice, $strdelete, $strfunctions, $strusers, $stredit);
+        $table->align = array('left', 'center', 'center', 'center', 'center');
+        $table->size = array('30%', '20%', '20%', '20%', '10%');
+        $table->width = '100%';
+        $table->data  = array();
 
-    /**
-     * Build XHTML to display the control
-     *
-     * @param string $data Unused
-     * @param string $query
-     * @return string XHTML
-     */
-    public function output_html($data, $query='') {
-        global $CFG, $OUTPUT;
-        $output = "";
+        // iterate through auth plugins and add to the display table
+        foreach ($services as $service) {
+            $name = $service->name;
+
+            // hide/show link
+            if ($service->enabled) {
+                $displayname = "<span>$name</span>";
+            } else {
+                $displayname = "<span class=\"dimmed_text\">$name</span>";
+            }
 
-        //search all web service users
-        $users = get_users(true, '', false, null, 'firstname ASC','', '', '', 1000);
+            // delete link
+            $delete = "<a href=\"$esurl?action=delete&amp;sesskey=".sesskey()."&amp;id=$service->id\">$strdelete</a>";
 
-        $table = new html_table();
-        $table->head = array('username', 'whitelist');
-        $table->align = array('left', 'center');
-        $table->data = array();
-        $table->tablealign  = 'center';
+            $functions = "<a href=\"$efurl?id=$service->id\">$strfunctions</a>";
 
-        foreach ($users as $user) {
-            if (has_capability("moodle/site:usewebservices",get_system_context(), $user->id)) { //test if the users has has_capability('use_webservice')
-                $wsusersetting = ' <a href="' . $this->baseurl . '&amp;username=' . $user->username . '">'
-                    . get_string("settings")
-                    .'</a>' . "\n";
-                $table->data[] = array($user->username, $wsusersetting);
+            if ($service->restrictedusers) {
+                $users = "<a href=\"$euurl?id=$service->id\">$strusers</a>";
+            } else {
+                $users = '-';
             }
+
+            $edit = "<a href=\"$esurl?id=$service->id\">$stredit</a>";
+
+            // add a row to the table
+            $table->data[] = array($displayname, $delete, $functions, $users, $edit);
         }
+        // add new custom service option
+        $table->data[] = array('', '', '', '', "<a href=\"$esurl?id=0\">$stradd</a>");
+        $return .= $OUTPUT->table($table);
 
-        $output .= $OUTPUT->table($table);
-        $output .= "<br/><br/>";
-        return highlight($query, $output);
+        $return .= '<br />'.get_string('tablesnosave', 'admin');
+
+        return highlight($query, $return);
     }
 }
 
 /**
+ * Special class for web service protocol administration.
  *
- * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ * @author Petr Skoda (skodak)
  */
-class admin_setting_managewsservicelist extends admin_setting {
-/** @var string */
-    private $baseurl;
+class admin_setting_managewebserviceprotokols extends admin_setting {
 
     /**
      * Calls parent::__construct with specific arguments
      */
     public function __construct() {
-        global $CFG;
-        parent::__construct('managewsservicelist', get_string('managewsservicelist', 'admin'), '', '');
-        $this->baseurl = $CFG->wwwroot . '/' . $CFG->admin . '/webservices.php?sesskey=' . sesskey();
+        parent::__construct('webservicesui', get_string('manageprotocols', 'webservice'), '', '');
     }
 
     /**
-     * Always returns true does nothing
+     * Always returns true, does nothing
      *
      * @return true
      */
@@ -6263,74 +6278,127 @@ class admin_setting_managewsservicelist extends admin_setting {
     }
 
     /**
-     * Does nothing always returns ''
+     * Always returns true, does nothing
+     *
+     * @return true
+     */
+    public function get_defaultsetting() {
+        return true;
+    }
+
+    /**
+     * Always returns '', does not write anything
      *
      * @return string Always returns ''
      */
     public function write_setting($data) {
-        $url = $this->baseurl . '&amp;new=' . $data;
+    // do not write any setting
         return '';
     }
 
     /**
-     * Build XHTML to display the control
+     * Checks if $query is one of the available webservices
+     *
+     * @param string $query The string to search for
+     * @return bool Returns true if found, false if not
+     */
+    public function is_related($query) {
+        if (parent::is_related($query)) {
+            return true;
+        }
+
+        $textlib = textlib_get_instance();
+        $protocols = get_plugin_list('webservice');
+        foreach ($protocols as $protocol=>$location) {
+            if (strpos($protocol, $query) !== false) {
+                return true;
+            }
+            $protocolstr = get_string('pluginname', 'webservice_'.$protocol);
+            if (strpos($textlib->strtolower($protocolstr), $query) !== false) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Builds the XHTML to display the control
      *
      * @param string $data Unused
      * @param string $query
-     * @return string XHTML
+     * @return string
      */
     public function output_html($data, $query='') {
-        global $CFG, $OUTPUT, $DB;
-        $output = "<div style=\"text-align:center;\">";
+        global $CFG, $OUTPUT;
 
-        $output .= $OUTPUT->link('/admin/webservices.php?sesskey='.sesskey().'&create=true',get_string('createservicelabel', 'webservice'));
-        $output .= "</div>";
-        $table = new html_table();
-        $table->head = array(get_string('servicename','webservice'), get_string('custom','webservice'), get_string('activated','webservice'),get_string('activatedfunctions','webservice'),get_string('settings'));
-        $table->align = array('left', 'center', 'center','center','center');
-        $table->data = array();
-        $table->tablealign  = 'center';
+        // display strings
+        $stradministration = get_string('administration');
+        $strsettings = get_string('settings');
+        $stredit = get_string('edit');
+        $strprotocol = get_string('protocol', 'webservice');
+        $strenable = get_string('enable');
+        $strdisable = get_string('disable');
+        $strversion = get_string('version');
+        $struninstall = get_string('uninstallplugin', 'admin');
 
-        //retrieve all services
-        // $services = $DB->get_records('external_services',null,'custom DESC');
-        $servicesfunctions = $DB->get_records_sql("SELECT  fs.id as id, s.id as serviceid, s.component as component, s.name as servicename, s.enabled as serviceenabled, f.name as functionname
-                                    FROM {external_services} s, {external_functions} f, {external_services_functions} fs
-                                   WHERE fs.externalserviceid = s.id AND fs.functionname = f.name ORDER BY s.name ASC");
+        $protocols_available = get_plugin_list('webservice');
+        $active_protocols = empty($CFG->webserviceprotocols) ? array() : explode(',', $CFG->webserviceprotocols);
+        ksort($protocols_available);
 
-        //create a services array
-        $services = array();
-        foreach($servicesfunctions as $servicefunction) {
-            if (!array_key_exists($servicefunction->servicename, $services)) {
-                $services[$servicefunction->servicename] = new object();
-                $services[$servicefunction->servicename]->name = $servicefunction->servicename;
-                $services[$servicefunction->servicename]->id = $servicefunction->serviceid;
-                $services[$servicefunction->servicename]->enabled = $servicefunction->serviceenabled;
-                $services[$servicefunction->servicename]->custom = $servicefunction->custom;
-                $services[$servicefunction->servicename]->funcnb = 0;
-                $services[$servicefunction->servicename]->enabledfuncnb = 0;
+        foreach ($active_protocols as $key=>$protocol) {
+            if (empty($protocols_available[$protocol])) {
+                unset($active_protocols[$key]);
             }
-            $services[$servicefunction->servicename]->funcnb = $services[$servicefunction->servicename]->funcnb +1;
-            if ($servicefunction->functionenabled) {
-                $services[$servicefunction->servicename]->enabledfuncnb = $services[$servicefunction->servicename]->enabledfuncnb +1;
+        }
+
+        $return = $OUTPUT->heading(get_string('actwebserviceshhdr', 'webservice'), 3, 'main', true);
+        $return .= $OUTPUT->box_start('generalbox webservicesui');
+
+        $table = new html_table();
+        $table->head  = array($strprotocol, $strversion, $strenable, $struninstall, $strsettings);
+        $table->align = array('left', 'center', 'center', 'center', 'center');
+        $table->width = '100%';
+        $table->data  = array();
+
+        // iterate through auth plugins and add to the display table
+        $url = "$CFG->wwwroot/$CFG->admin/webservice_protocols.php?sesskey=" . sesskey();
+        foreach ($protocols_available as $protocol => $location) {
+            $name = get_string('pluginname', 'webservice_'.$protocol);
+
+            $plugin = new object();
+            if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/version.php')) {
+                include($CFG->dirroot.'/webservice/'.$protocol.'/version.php');
             }
+            $version = isset($plugin->version) ? $plugin->version : '';
 
-        }
+            // hide/show link
+            if (in_array($protocol, $active_protocols)) {
+                $hideshow = "<a href=\"$url&amp;action=disable&amp;webservice=$protocol\">";
+                $hideshow .= "<img src=\"" . $OUTPUT->old_icon_url('i/hide') . "\" class=\"icon\" alt=\"$strdisable\" /></a>";
+                $displayname = "<span>$name</span>";
+            } else {
+                $hideshow = "<a href=\"$url&amp;action=enable&amp;webservice=$protocol\">";
+                $hideshow .= "<img src=\"" . $OUTPUT->old_icon_url('i/show') . "\" class=\"icon\" alt=\"$strenable\" /></a>";
+                $displayname = "<span class=\"dimmed_text\">$name</span>";
+            }
 
-        foreach($services as $service) {
-        //$numberoffunc = $DB->count_records('external_services_functions',array('externalserviceid' => $service->id));
-            $activated = ' <!--a href="' . $this->baseurl . '&amp;deactivate=' . $service->id . '"-->'
-                .'<img src="' . $OUTPUT->old_icon_url('i/' . ($service->enabled ? 'deactivate' : 'activate')) . '"'
-                .' alt="' . ($service->enabled ? 'activated' : 'not activated') . '" '
-                .' title="' . ($service->enabled ? 'activated' : 'not activated') . '" />'.'<!--/a-->' ;
-            $custom = ($service->custom ? get_string('yes') : '');
-            $settings = $OUTPUT->link('/admin/webservices.php?serviceid='.$service->id.'&sesskey='.sesskey().'&settings=true',get_string('settings'));
-            $table->data[] = array(get_string($service->name,'webservice'), $custom, $activated, $service->enabledfuncnb."/".$service->funcnb, $settings);
-        }
+            // delete link
+            $uninstall = "<a href=\"$url&amp;action=uninstall&amp;webservice=$protocol\">$struninstall</a>";
 
-        $output .= $OUTPUT->table($table);
+            // settings link
+            if (file_exists($CFG->dirroot.'/webservice/'.$protocol.'/settings.php')) {
+                $settings = "<a href=\"settings.php?section=webservicesetting$protocol\">$strsettings</a>";
+            } else {
+                $settings = '';
+            }
 
-        $output .= '<br/>';
+            // add a row to the table
+            $table->data[] = array($displayname, $version, $hideshow, $uninstall, $settings);
+        }
+        $return .= $OUTPUT->table($table);
+        $return .= get_string('configwebserviceplugins', 'webservice').'<br />'.get_string('tablenosave', 'admin');
+        $return .= $OUTPUT->box_end();
 
-        return highlight($query, $output);
+        return highlight($query, $return);
     }
 }
index ba91a2c..d338169 100644 (file)
@@ -941,14 +941,6 @@ get_string('allowbeforeblock', 'admin', NULL);
 get_string('allowbeforeblockdesc', 'admin', NULL);
 get_string('allowediplist', 'admin', NULL);
 get_string('blockediplist', 'admin', NULL);
-get_string('webservices', 'admin', NULL);
-get_string('webserviceprotocols', 'admin', NULL);
-get_string('managewsprotocols', 'admin', NULL);
-get_string('managews', 'admin', NULL);
-get_string('webservicesystemsettings', 'admin', NULL);
-get_string('ipwhitelist', 'admin', NULL);
-get_string('webserviceusersettings', 'admin', NULL);
-get_string('managewsusersettings', 'admin', NULL);
 get_string('sitepolicies', 'admin', NULL);
 get_string('protectusernames', 'admin', NULL);
 get_string('configprotectusernames', 'admin', NULL);
index 76261bd..543029f 100644 (file)
@@ -941,14 +941,6 @@ old_get_string('allowbeforeblock', 'admin', NULL);
 old_get_string('allowbeforeblockdesc', 'admin', NULL);
 old_get_string('allowediplist', 'admin', NULL);
 old_get_string('blockediplist', 'admin', NULL);
-old_get_string('webservices', 'admin', NULL);
-old_get_string('webserviceprotocols', 'admin', NULL);
-old_get_string('managewsprotocols', 'admin', NULL);
-old_get_string('managews', 'admin', NULL);
-old_get_string('webservicesystemsettings', 'admin', NULL);
-old_get_string('ipwhitelist', 'admin', NULL);
-old_get_string('webserviceusersettings', 'admin', NULL);
-old_get_string('managewsusersettings', 'admin', NULL);
 old_get_string('sitepolicies', 'admin', NULL);
 old_get_string('protectusernames', 'admin', NULL);
 old_get_string('configprotectusernames', 'admin', NULL);
index 4e1c223..b37a48c 100644 (file)
 <?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
 /**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- *         http://moodle.com
- *
- * LICENSE
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details:
+ * Web services utility functions and classes
  *
- *         http://www.gnu.org/copyleft/gpl.html
- *
- * @category  Moodle
  * @package   webservice
  * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
- * @license   http://www.gnu.org/copyleft/gpl.html     GNU GPL License
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-require_once(dirname(dirname(__FILE__)) . '/lib/formslib.php');
-
-/**
- * Returns detailed information about external function
- * @param string $functionname name of external function
- * @return aray
- */
-function ws_get_function_info($functionname) {
-    global $CFG, $DB;
+require_once($CFG->libdir.'/externallib.php');
 
-    $function = $DB->get_record('external_functions', array('name'=>$functionname), '*', MUST_EXIST);
+function webservice_protocol_is_enabled($protocol) {
+    global $CFG;
 
-    $defpath = get_component_directory($function->component);
-    if (!file_exists("$defpath/db/services.php")) {
-        //TODO: maybe better throw invalid parameter exception
-        return null;
+    if (empty($CFG->enablewebservices)) {
+        return false;
     }
 
-    $functions = array();
-    include("$defpath/db/services.php");
+    $active = explode(',', $CFG->webserviceprotocols);
 
-    if (empty($functions[$functionname])) {
-        return null;
-    }
-
-    $desc = $functions[$functionname];
-    if (empty($desc['classpath'])) {
-        $desc['classpath'] = "$defpath/externallib.php";
-    } else {
-        $desc['classpath'] = "$CFG->dirroot/".$desc['classpath'];
-    }
-    $desc['component'] = $function->component;
+    return(in_array($protocol, $active));
+}
 
-    return $desc;
+/**
+ * Mandatory web service server interface
+ * @author Petr Skoda (skodak)
+ */
+interface webservice_server {
+    /**
+     * Process request from client.
+     * @param bool $simple use simple authentication
+     * @return void
+     */
+    public function run($simple);
 }
 
 /**
- * web service library
+ * Special abstraction of our srvices that allows
+ * interaction with stock Zend ws servers.
+ * @author skodak
  */
-final class webservice_lib {
+abstract class webservice_zend_server implements webservice_server {
+    //TODO: implement base class for all ws servers in zend framework
+    //      the idea is to create one huge class on the fly, this class contains all
+    //      methods user is allowed to access and contains all needed PHPDoc metadata.
+}
+
 
 /**
- * Return list of all web service protocol into the webservice folder
- * @global <type> $CFG
- * @return <type>
+ * Web Service server base class, this class handles both
+ * simple and token authentication.
+ * @author Petr Skoda (skodak)
  */
-    public static function get_list_protocols() {
-        global $CFG;
-        $protocols = array();
-        $directorypath = $CFG->dirroot . "/webservice";
-        if( $dh = opendir($directorypath)) {
-            while( false !== ($file = readdir($dh))) {
-                if( $file == '.' || $file == '..' || $file == 'CVS') {   // Skip '.' and '..'
-                    continue;
-                }
-                $path = $directorypath . '/' . $file;
-                ///browse the subfolder
-                if( is_dir($path) ) {
-                    if ($file != 'db') { //we don't want to browse the 'db' subfolder of webservice folder
-                        require_once($path."/lib.php");
-                        $classname = $file."_server";
-                        $protocols[] = new $classname;
-                    }
-                }
-                ///retrieve api.php file
-                else {
-                    continue;
-                }
-            }
-            closedir($dh);
-        }
-        return $protocols;
-    }
+abstract class webservice_base_server implements webservice_server {
+
+    /** @property string $wsname name of the web server plugin */
+    protected $wsname = null;
+
+    /** @property bool $simple true if simple auth used */
+    protected $simple;
+
+    /** @property string $username name of local user */
+    protected $username = null;
+
+    /** @property string $password password of the local user */
+    protected $password = null;
+
+    /** @property string $token authentication token*/
+    protected $token = null;
+
+    /** @property array $parameters the function parameters - the real values submitted in the request */
+    protected $parameters = null;
+
+    /** @property string $functionname the name of the function that is executed */
+    protected $functionname = null;
+
+    /** @property object $function full function description */
+    protected $function = null;
+
+    /** @property mixed $returns function return value */
+    protected $returns = null;
 
     /**
-     * Temporary Authentication method to be modified/removed
-     * @global <type> $DB
-     * @param <type> $token
-     * @return <type>
+     * Contructor
      */
-    public static function mock_check_token($token) {
-    //fake test
-        if ($token == 456) {
-        ///retrieve the user
-            global $DB;
-            $user = $DB->get_record('user', array('username'=>'wsuser', 'mnethostid'=>1));
-
-            if (empty($user)) {
-                return false;
-            }
-
-            return $user;
-        } else {
-            return false;
-        }
+    public function __construct() {
     }
 
     /**
-     * Retrieve all external.php from Moodle (except the one of the exception list)
-     * @param <type> $
-     * @param <type> $directorypath
-     * @return boolean true if n
+     * This method parses the request input, it needs to get:
+     *  1/ user authentication - username+password or token
+     *  2/ function name
+     *  3/ function parameters
+     *
+     * @return void
      */
-    public static function setListApiFiles( &$files, $directorypath ) {
-        global $CFG;
-
-        if(is_dir($directorypath)) { //check that we are browsing a folder not a file
-
-            if( $dh = opendir($directorypath)) {
-                while( false !== ($file = readdir($dh))) {
-
-                    if( $file == '.' || $file == '..') {   // Skip '.' and '..'
-                        continue;
-                    }
-                    $path = $directorypath . '/' . $file;
-                    ///browse the subfolder
-                    if( is_dir($path) ) {
-                        webservice_lib::setListApiFiles($files, $path);
-                    }
-                    ///retrieve api.php file
-                    else if ($file == "external.php") {
-                            $files[] = $path;
-                        }
-                }
-                closedir($dh);
+    abstract protected function parse_request();
 
-            }
-        }
-
-    }
+    /**
+     * Send the result of function call to the WS client.
+     * @return void
+     */
+    abstract protected function send_response();
 
     /**
-     * Check if the Moodle site has the web service protocol enable
-     * @global object $CFG
-     * @param string $protocol
+     * Send the error information to the WS client.
+     * @param exception $ex
+     * @return void
      */
-    function display_webservices_availability($protocol) {
-        global $CFG;
+    abstract protected function send_error($ex=null);
 
-        $available = true;
 
-        echo get_string('webservicesenable','webservice').": ";
-        if (empty($CFG->enablewebservices)) {
-            echo "<strong style=\"color:red\">".get_string('fail','webservice')."</strong>";
-            $available = false;
-        } else {
-            echo "<strong style=\"color:green\">".get_string('ok','webservice')."</strong>";
-        }
-        echo "<br/>";
-
-        foreach(webservice_lib::get_list_protocols() as $wsprotocol) {
-            if (strtolower($wsprotocol->get_protocolid()) == strtolower($protocol)) {
-                echo get_string('protocolenable','webservice',array($wsprotocol->get_protocolid())).": ";
-                if ( get_config($wsprotocol-> get_protocolid(), "enable")) {
-                    echo "<strong style=\"color:green\">".get_string('ok','webservice')."</strong>";
-                } else {
-                    echo "<strong style=\"color:red\">".get_string('fail','webservice')."</strong>";
-                    $available = false;
-                }
-                echo "<br/>";
-                continue;
-            }
-        }
+    /**
+     * Process request from client.
+     * @param bool $simple use simple authentication
+     * @return void
+     */
+    public function run($simple) {
+        $this->simple = $simple;
 
-        //check debugging
-        if ($CFG->debugdisplay) {
-            echo "<strong style=\"color:red\">".get_string('debugdisplayon','webservice')."</strong>";
-            $available = false;
-        }
+        // we will probably need a lot of memory in some functions
+        @raise_memory_limit('128M');
 
-        return $available;
-    }
+        // set some longer timeout, this script is not sending any output,
+        // this means we need to manually extend the timeout operations
+        // that need longer time to finish
+        external_api::set_timeout();
 
-}
+        // set up exception handler first, we want to sent them back in correct format that
+        // the other system understands
+        // we do not need to call the original default handler because this ws handler does everything
+        set_exception_handler(array($this, 'exception_handler'));
 
-/**
- * Web Service server base class
- */
-abstract class webservice_server {
+        // init all properties from the request data
+        $this->parse_request();
 
-/**
- * Web Service Protocol name (eg. SOAP, REST, XML-RPC,...)
- * @var String
- */
-    private $protocolname;
+        // authenticate user, this has to be done after the request parsing
+        // this also sets up $USER and $SESSION
+        $this->authenticate_user();
 
-    /**
-     * Web Service Protocol id (eg. soap, rest, xmlrpc...)
-     * @var String
-     */
-    private $protocolid;
+        // find all needed function info and make sure user may actually execute the function
+        $this->load_function_info();
 
-    public function __construct() {
-    }
+        // finally, execute the function - any errors are catched by the default exception handler
+        $this->execute();
 
-    abstract public function run();
+        // send the results back in correct format
+        $this->send_response();
 
-    public function get_protocolname() {
-        return $this->protocolname;
-    }
+        // session cleanup
+        $this->session_cleanup();
 
-    public function get_protocolid() {
-        return $this->protocolid;
+        die;
     }
 
-    public function set_protocolname($protocolname) {
-        $this->protocolname = $protocolname;
-    }
+    /**
+     * Specialised exception handler, we can not use the standard one because
+     * it can not just print html to output.
+     *
+     * @param exception $ex
+     * @return void does not return
+     */
+    public function exception_handler($ex) {
+        global $CFG, $DB, $SCRIPT;
+
+        // detect active db transactions, rollback and log as error
+        if ($DB->is_transaction_started()) {
+            error_log('Database transaction aborted by exception in ' . $CFG->dirroot . $SCRIPT);
+            try {
+                // note: transaction blocks should never change current $_SESSION
+                $DB->rollback_sql();
+            } catch (Exception $ignored) {
+            }
+        }
 
-    public function set_protocolid($protocolid) {
-        $this->protocolid = $protocolid;
-    }
+        // now let the plugin send the exception to client
+        $this->send_error($ex);
 
-    public function get_enable() {
-        return get_config($this->get_protocolid(), "enable");
-    }
+        // some hacks might need a cleanup hook
+        $this->session_cleanup($ex);
 
-    public function set_enable($enable) {
-        set_config("enable", $enable, $this->get_protocolid());
+        // not much else we can do now, add some logging later
+        exit(1);
     }
 
     /**
-     * Names of the server settings
-     * @return array
+     * Future hook needed for emulated sessions.
+     * @param exception $exception null means normal termination, $exception received when WS call failed
+     * @return void
      */
-    public static function get_setting_names() {
-        return array();
+    protected function session_cleanup($exception=null) {
+        if ($this->simple) {
+            // nothing needs to be done, there is no persistent session
+        } else {
+            // close emulated session if used
+        }
     }
 
-    public function settings_form(&$mform) {
-    }
+    /**
+     * Authenticate user using username+password or token.
+     * This function sets up $USER global.
+     * It is safe to use has_capability() after this.
+     * This method also verifies user is allowed to use this
+     * server.
+     * @return void
+     */
+    protected function authenticate_user() {
+        global $CFG, $DB;
 
-}
+        if (!NO_MOODLE_COOKIES) {
+            throw new coding_exception('Cookies must be disabled in WS servers!');
+        }
+
+        if ($this->simple) {
+            if (!is_enabled_auth('webservice')) {
+                die('WS auth not enabled');
+            }
+
+            if (!$auth = get_auth_plugin('webservice')) {
+                die('WS auth missing');
+            }
+
+            if (!$this->username) {
+                throw new invalid_parameter_exception('Missing username');
+            }
+
+            if (!$this->password) {
+                throw new invalid_parameter_exception('Missing password');
+            }
+
+            if (!$auth->user_login_webservice($this->username, $this->password)) {
+                throw new invalid_parameter_exception('Wrong username or password');
+            }
+
+            $user = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST);
+
+            // now fake user login, the session is completely empty too
+            session_set_user($user);
+
+            if (!has_capability("webservice/$this->wsname:use", get_context_instance(CONTEXT_SYSTEM))) {
+                throw new invalid_parameter_exception('Access to web service not allowed');
+            }
 
-/**
- * Temporary authentication class to be removed/modified
- */
-class ws_authentication {
-/**
- *
- * @param object|struct $params
- * @return integer
- */
-    function get_token($params) {
-        $params->username = clean_param($params->username, PARAM_ALPHANUM);
-        $params->password = clean_param($params->password, PARAM_ALPHANUM);
-        if ($params->username == 'wsuser' && $params->password == 'wspassword') {
-            return '456';
         } else {
-            throw new moodle_exception('wrongusernamepassword');
+            //TODO: not implemented yet
+            die('token login not implemented yet');
+
+            // note we had to wait until here because we did not know the security context earlier
+            if (!has_capability("webservice/$this->wsname:use", $context)) {
+                throw new invalid_parameter_exception('Access to web service not allowed');
+            }
         }
     }
-}
-
-/**
- * Form for web service user settings (administration)
- */
-final class wsuser_form extends moodleform {
-    protected $username;
 
     /**
-     * Definition of the moodleform
+     * Fetches the function description from database,
+     * verifies user is allowed to use this function and
+     * loads all paremeters and return descriptions.
+     * @return void
      */
-    public function definition() {
-        global $DB;
-        $this->username = $this->_customdata['username'];
-        $mform =& $this->_form;
+    protected function load_function_info() {
+        global $DB, $USER, $CFG;
 
-        $mform->addElement('hidden', 'username', $this->username);
-        $mform->setType('username', PARAM_RAW);
-        $param = new stdClass();
-        $param->username = $this->username;
-        $wsuser = $DB->get_record("user", array("username" => $this->username));
+        if (empty($this->functionname)) {
+            throw new invalid_parameter_exception('Missing function name');
+        }
 
-        $mform->addElement('text', 'ipwhitelist', get_string('ipwhitelist', 'admin'), array('value'=>get_user_preferences("ipwhitelist", "", $wsuser->id),'size' => '40'));
-        $mform->addElement('static', null, '',  get_string('ipwhitelistdesc','admin', $param));
+        // function must exist
+        $function = $DB->get_record('external_functions', array('name'=>$this->functionname), '*', MUST_EXIST);
+
+
+        // now let's verify access control
+        if ($this->simple) {
+            // now make sure the function is listed in at least one service user is allowed to use
+            // allow access only if:
+            //  1/ entry in the external_services_users table if required
+            //  2/ validuntil not reached
+            //  3/ has capability if specified in service desc
+            //  4/ iprestriction
+
+            $sql = "SELECT s.*, NULL AS iprestriction
+                      FROM {external_services} s
+                      JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0 AND sf.functionname = :name1)
+                     WHERE s.enabled = 1
+
+                     UNION
+
+                    SELECT s.*, su.iprestriction
+                      FROM {external_services} s
+                      JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1 AND sf.functionname = :name2)
+                      JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)
+                     WHERE s.enabled = 1 AND su.validuntil IS NULL OR su.validuntil < :now";
+
+            $rs = $DB->get_recordset_sql($sql, array('userid'=>$USER->id, 'name1'=>$function->name, 'name2'=>$function->name, 'now'=>time()));
+            // now make sure user may access at least one service
+            $syscontext = get_context_instance(CONTEXT_SYSTEM);
+            $remoteaddr = getremoteaddr();
+            $allowed = false;
+            foreach ($rs as $service) {
+                if ($service->requiredcapability and !has_capability($service->requiredcapability, $syscontext)) {
+                    continue; // cap required, sorry
+                }
+                if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) {
+                    continue; // wrong request source ip, sorry
+                }
+                $allowed = true;
+                break; // one service is enough, no need to continue
+            }
+            $rs->close();
+            if (!$allowed) {
+                throw new invalid_parameter_exception('Access to external function not allowed');
+            }
+            // now we finally know the user may execute this function,
+            // the last step is to set context restriction - in this simple case
+            // we use system context because each external system has different user account
+            // and we can manage everything through normal permissions.
+            external_api::set_context_restriction($syscontext);
 
-        $this->add_action_buttons(true, get_string('savechanges','admin'));
-    }
-}
+        } else {
+            //TODO: implement token security checks
+            die('not implemented yet');
+        }
 
-/**
- * Form for web service server settings (administration)
- */
-final class wssettings_form extends moodleform {
-    protected $settings;
+        // get the params and return descriptions of the function
+        unset($function->id); // we want to prevent any accidental db updates ;-)
 
-    /**
-     * Definition of the moodleform
-     */
-    public function definition() {
-        global $DB,$CFG;
-        $settings = $this->_customdata['settings'];
-        $mform =& $this->_form;
-
-        $mform->addElement('hidden', 'settings', $settings);
-        $mform->setType('settings', PARAM_RAW);
-        $param = new stdClass();
-
-        require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php');
-        $servername = $settings.'_server';
-        $server = new $servername();
-        $server->settings_form($mform);
-
-        // set the data if we have some.
-        $data = array();
-        $option_names = $server->get_setting_names();
-        foreach ($option_names as $config) {
-            $data[$config] = get_config($settings, $config);
+        $function->classpath = empty($function->classpath) ? get_component_directory($function->component).'/externallib.php' : $CFG->dirroot.'/'.$function->classpath;
+        if (!file_exists($function->classpath)) {
+            throw new coding_exception('Can not find file with external function implementation');
         }
-        $this->set_data($data);
+        require_once($function->classpath);
 
+        $function->parameters_method = $function->methodname.'_parameters';
+        $function->returns_method    = $function->methodname.'_returns';
 
-        $this->add_action_buttons(true, get_string('savechanges','admin'));
-    }
-}
-
-/**
- * Form for web service server settings (administration)
- */
-final class wsservicesettings_form extends moodleform {
-    protected $settings;
+        // make sure the implementaion class is ok
+        if (!method_exists($function->classname, $function->methodname)) {
+            throw new coding_exception('Missing implementation method');
+        }
+        if (!method_exists($function->classname, $function->parameters_method)) {
+            throw new coding_exception('Missing parameters description');
+        }
+        if (!method_exists($function->classname, $function->returns_method)) {
+            throw new coding_exception('Missing returned values description');
+        }
 
-    /**
-     * Definition of the moodleform
-     */
-    public function definition() {
-        global $DB,$CFG;
-        $serviceid = $this->_customdata['serviceid'];
-        $mform =& $this->_form;
-
-        $mform->addElement('hidden', 'serviceid', $serviceid);
-        $mform->setType('serviceid', PARAM_INT);
-        $param = new stdClass();
-
-     //   require_once($CFG->dirroot . '/webservice/'. $settings . '/lib.php');
-      //  $servername = $settings.'_server';
-      //  $server = new $servername();
-      //  $server->settings_form($mform);
-
-        // set the data if we have some.
-    //    $data = array();
-     //   $option_names = $server->get_setting_names();
-    //    foreach ($option_names as $config) {
-    //        $data[$config] = get_config($settings, $config);
-    //    }
-    //    $this->set_data($data);
-        $service = $DB->get_record('external_services',array('id' => $serviceid));
-
-        $mform->addElement('text', 'servicename', get_string('servicename', 'webservice'));
-        $mform->setDefault('servicename',get_string($service->name, 'webservice'));
-        if (!empty($serviceid)) {
-            $mform->disabledIf('servicename', 'serviceid', 'eq', $serviceid);
+        // fetch the parameters description
+        $function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method));
+        if (!($function->parameters_desc instanceof external_function_parameters)) {
+            throw new coding_exception('Invalid parameters description');
         }
 
-        if (empty($serviceid)) {
-            //display list of functions to select
+        // fetch the return values description
+        $function->returns_desc = call_user_func(array($function->classname, $function->returns_method));
+        // null means void result or result is ignored
+        if (!is_null($function->returns_desc) and !($function->returns_desc instanceof external_description)) {
+            throw new coding_exception('Invalid return description');
         }
 
-        //display list of functions associated to the service
-        
-        
+        // we have all we need now
+        $this->function = $function;
+    }
+
+    /**
+     * Execute previously loaded function using parameters parsed from the request data.
+     * @return void
+     */
+    protected function execute() {
+        // validate params, this also sorts the params properly, we need the correct order in the next part
+        $params = call_user_func(array($this->function->classname, 'validate_parameters'), $this->function->parameters_desc, $this->parameters);
 
-        $this->add_action_buttons(true,  get_string('savechanges','admin'));
+        // execute - yay!
+        $this->returns = call_user_func_array(array($this->function->classname, $this->function->methodname), array_values($params));
     }
 }
 
 
-?>
diff --git a/webservice/rest/db/access.php b/webservice/rest/db/access.php
new file mode 100644 (file)
index 0000000..e5de884
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+
+$webservice_rest_capabilities = array(
+
+    'webservice/rest:use' => array(
+        'captype' => 'read', // in fact this may be considered read and write at the same time
+        'contextlevel' => CONTEXT_COURSE, // the context level should be probably CONTEXT_MODULE
+        'legacy' => array(
+        ),
+    ),
+
+);
diff --git a/webservice/rest/lib.php b/webservice/rest/lib.php
deleted file mode 100644 (file)
index 324ce2f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-<?php
-/**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- *         http://moodle.com
- *
- * LICENSE
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details:
- *
- *         http://www.gnu.org/copyleft/gpl.html
- *
- * @category  Moodle
- * @package   webservice
- * @copyright Copyright (c) 1999 onwards Martin Dougiamas     http://dougiamas.com
- * @license   http://www.gnu.org/copyleft/gpl.html     GNU GPL License
- */
-
-require_once($CFG->dirroot.'/webservice/lib.php');
-
-/*
- * Rest server class
- */
-final class rest_server extends webservice_server {
-
-    public function __construct() {
-
-        $this->set_protocolname("Rest");
-        $this->set_protocolid("rest");
-    }
-
-    /**
-     * Run REST server
-     */
-    public function run() {
-        $enable = $this->get_enable();
-        if (empty($enable)) {
-            die;
-        }
-
-        require_once('locallib.php');
-        //retrieve path and function name from the URL
-        $rest_arguments = get_file_argument('server.php');
-        header ("Content-type: text/xml");
-        echo call_moodle_function($rest_arguments);
-    }  
-
-}
-
-
-
-?>
index 1ed14f7..b1af6b7 100644 (file)
 <?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
 /**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- *         http://moodle.com
- *
- * LICENSE
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details:
- *
- *         http://www.gnu.org/copyleft/gpl.html
+ * REST web service implementation classes and methods.
  *
- * @category  Moodle
  * @package   webservice
- * @copyright Copyright (c) 1999 onwards Martin Dougiamas     http://dougiamas.com
- * @license   http://www.gnu.org/copyleft/gpl.html     GNU GPL License
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+require_once("$CFG->dirroot/webservice/lib.php");
 
 /**
- * Rest library
- * @author Jerome Mouneyrac, Ferran Recio, David Castro Garcia
+ * REST service server implementation.
+ * @author Petr Skoda (skodak)
  */
-
-/**
- *
- * @author Jerome Mouneyrac
- * @global object $CFG
- * @param string $rest_arguments example: /mod/forum/get_discussion
- * @return string xml object
- */
-function call_moodle_function ($rest_arguments) {
-    global $CFG, $USER;
-
-    ///REST params conversion
-    $functionname = substr($rest_arguments,strrpos($rest_arguments,"/")+1); //retrieve the function name (it's located after the last '/') in $rest_arguments
-    //$rest_argument
-    $apipath = substr($rest_arguments,0, strlen($rest_arguments) - strlen($functionname)); //api path is the other part of $rest_arguments
-
-    $classname = str_replace('/', '_', $apipath); // convert '/' into '_' (e.g. /mod/forum/ => _mod_forum_)
-    $classname = substr($classname,1, strlen($classname) - 1); //remove first _ (e.g. _mod_forum => mod_forum)
-    $classname .= 'external';
-
-    /// Authentication process
-    /// TODO: this use a fake token => need to implement token generation
-    $token = optional_param('token',null,PARAM_ALPHANUM);
-    if (empty($token)) {
-        if ($functionname != 'get_token') {
-            throw new moodle_exception('identifyfirst');
-        } else {
-            /// TODO: authentication + token generation need to be implemented
-            if (optional_param('username',null,PARAM_ALPHANUM) == 'wsuser' && optional_param('password',null,PARAM_ALPHANUM) == 'wspassword') {
-                return '456';
-            } else {
-                throw new moodle_exception('wrongusernamepassword');
-            }
-        }
-    } else {
-        /// TODO: following function will need to be modified
-        $user = mock_check_token($token);
-        if (empty($user)) {
-            throw new moodle_exception('wrongidentification');
-        }
-        else {
-            /// TODO: probably change this
-            $USER = $user;
-        }
-    }
-
-    /// load the external class
-    $file = $CFG->dirroot.$apipath.'external.php';
-    $description = webservice_lib::generate_webservice_description($file, $classname);
-
-    /// This following line is only REST protocol
-    $params = retrieve_params ($description[$functionname]); //retrieve the REST params
-
-    /// Generic part to any protocols
-    if ($params === false) {
-        //return an error message, the REST params doesn't match with the web service description
+class webservice_rest_server extends webservice_base_server {
+    /**
+     * Contructor
+     */
+    public function __construct() {
+        parent::__construct();
+        $this->wsname = 'rest';
     }
 
-    try {
-        $res = call_user_func_array  ( $classname.'::'.$functionname, array($params));
-    } catch (moodle_exception $e) {
-        return "<Result>".$e->getMessage()."</Result>";
-    }
+    /**
+     * This method parses the $_REQUEST superglobal and looks for
+     * the following information:
+     *  1/ user authentication - username+password or token (wsusername, wspassword and wstoken parameters)
+     *  2/ function name (wsfunction parameter)
+     *  3/ function parameters (all other parameters except those above)
+     *
+     * @return void
+     */
+    protected function parse_request() {
+        if ($this->simple) {
+            $this->username = isset($_REQUEST['wsusername']) ? $_REQUEST['wsusername'] : null;
+            unset($_REQUEST['wsusername']);
 
-    ///Transform result into xml in order to send the REST response
-    $key = key($description[$functionname]['return']);
+            $this->password = isset($_REQUEST['wspassword']) ? $_REQUEST['wspassword'] : null;
+            unset($_REQUEST['wspassword']);
 
-    if (strpos($key,":")!==false) {
-        $key = substr($key, strpos($key,":")+1);
-    } else {
-        $key = 'return';
-    }
-    $return =  mdl_conn_rest_object_to_xml ($res,$key);
+            $this->functionname = isset($_REQUEST['wsfunction']) ? $_REQUEST['wsfunction'] : null;
+            unset($_REQUEST['wsfunction']);
 
-    return "<Result>$return</Result>";
-}
+            $this->parameters = $_REQUEST;
 
-/**
- * TODO: remove/rewrite this function
- * Mock function waiting for token system implementation
- * @param int $token
- * @return object|boolean
- */
-function mock_check_token($token) {
-    //fake test
-    if ($token == 456) {
-        ///retrieve the user
-        global $DB;
-        $user = $DB->get_record('user', array('username'=>'wsuser', 'mnethostid'=>1));
-
-        if (empty($user)) {
-            return false;
+        } else {
+            //TODO
+            die('not implemented yet');
         }
-
-        return $user;
-    } else {
-        return false;
     }
-}
 
-  /**
-     * Convert into a Moodle type
-     * @param integer $param
-     * @return string
+    /**
+     * Send the result of function call to the WS client
+     * formatted as XML document.
+     * @return void
      */
-function convert_paramtype($param) {
-    switch ($param) {
-        case "integer":
-            return PARAM_NUMBER;
-            break;
-        case "integer":
-            return PARAM_INT;
-            break;
-        case "boolean":
-            return PARAM_BOOL;
-            break;
-        case "string":
-            return PARAM_ALPHANUM;
-            break;
-        case "object":
-            return PARAM_RAW;
-            break;
-        default:
-            return PARAM_RAW;
-            break;
+    protected function send_response() {
+        $this->send_headers();
+        $xml = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
+        $xml .= '<RESPONSE>'."\n";
+        $xml .= self::xmlize_result($this->returns, $this->function->returns_desc);
+        $xml .= '</RESPONSE>'."\n";
+        echo $xml;
     }
-}
 
-/**
- *
- * @author Jerome Mouneyrac
- * @param array $description
- * @return array
- */
-function retrieve_params ($description) {
-    $params = array();
-    //retrieve REST param matching the description (warning: PHP assign the first instanciation as the first position in the table)
-    foreach ($description['params'] as $paramname => $paramtype) {
-        $paramtype = convert_paramtype($paramtype);
-        $value = optional_param($paramname,null,$paramtype);
-        if (!empty($value)) {
-            $params[$paramname] = $value;
-        }
-    }
-    //retrieve REST optional params
-    if (!empty($description['optional'])) {
-        foreach ($description['optional'] as $paramname => $paramtype) {
-            $paramtype = convert_paramtype($paramtype);
-            $value = optional_param($paramname,null,$paramtype);
-            if (!empty($value)) {
-                $params[$paramname] = $value;
-            }
+    /**
+     * Send the error information to the WS client
+     * formatted as XML document.
+     * @param exception $ex
+     * @return void
+     */
+    protected function send_error($ex=null) {
+        $this->send_headers();
+        $xml = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
+        $xml .= '<EXCEPTION class="'.get_class($ex).'">'."\n";
+        $xml .= '<MESSAGE>'.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').'</MESSAGE>'."\n";
+        if (debugging() and isset($ex->debuginfo)) {
+            $xml .= '<DEBUGINFO>'.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').'</DEBUGINFO>'."\n";
         }
+        $xml .= '</EXCEPTION>'."\n";
+        echo $xml;
     }
-    return $params;
-}
 
-/**
- * auxiliar function for simplexml_object_to_xml
- * @author Ferran Recio, David Castro Garcia
- * @param $obj
- * @param $tag
- * @param $atts assoc array (key => value)
- * @return string
- */
-function mdl_conn_rest_object_to_xml ($obj, $tag,$atts=false) {
-    $res = '';
-    $tag_atts = '';
-    if ($atts) {
-        $main_atts = array();
-        foreach ($atts as $att=>$val) {
-            $main_atts[] = "$att=\"".urlencode($val)."\"";
-        }
-        if (count($main_atts)) $tag_atts = ' '.implode(' ',$main_atts);
+    /**
+     * Internal implementation - sending of page headers.
+     * @return void
+     */
+    protected function send_headers() {
+        header('Content-Type: application/xml');
+        header('Content-Disposition: inline; filename="response.xml"');
+        header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
+        header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
+        header('Pragma: no-cache');
+        header('Accept-Ranges: none');
     }
 
-    //if is an object
-    if (is_object($obj)) {
-        $parts = get_object_vars($obj);
-        foreach ($parts as $tag2 => $val) {
-            $res.= mdl_conn_rest_object_to_xml ($val, $tag2);
-        }
-        return "<$tag$tag_atts>\n$res</$tag>\n";
-    }
-    //if it's an array all elements will be inside te same tag but with a new atribute key
-    if (is_array($obj)){
-        if (!$atts) $atts = array();
-        //we came from another array
-        if (isset($atts['keys'])) $atts = array();
-        foreach ($obj as $key=>$val) {
-            $array_atts = $atts;
-            $array_atts['key'] = $key;
-            $res.= mdl_conn_rest_object_to_xml ($val, $tag,$array_atts);
+    /**
+     * Internal implementation - recursive function producing XML markup.
+     * @param mixed $returns
+     * @param $desc
+     * @return unknown_type
+     */
+    protected static function xmlize_result($returns, $desc) {
+        if ($desc === null) {
+            return '';
+
+        } else if ($desc instanceof external_value) {
+            //TODO: there should be some way to indicate the real NULL value
+            return '<VALUE>'.htmlentities($returns, ENT_COMPAT, 'UTF-8').'</VALUE>'."\n";
+
+        } else if ($desc instanceof external_multiple_structure) {
+            $mult = '<MULTIPLE>'."\n";
+            foreach ($returns as $val) {
+                $mult .= self::xmlize_result($val, $desc->content);
+            }
+            $mult .= '</MULTIPLE>'."\n";
+            return $mult;
+
+        } else if ($desc instanceof external_single_structure) {
+            $single = '<SINGLE>'."\n";
+            foreach ($desc->keys as $key=>$subdesc) {
+                if (!array_key_exists($key, $returns)) {
+                    if ($subdesc->rewquired) {
+                        $single .= '<ERROR>Missing required key</ERROR>';
+                        continue;
+                    } else {
+                        //optional field
+                        continue;
+                    }
+                }
+                $single .= '<KEY name="'.$key.'">'.self::xmlize_result($returns[$key], $subdesc).'</KEY>'."\n";
+            }
+            $single .= '</SINGLE>'."\n";
+            return $single;
         }
-        return $res;
     }
-    //any other type, just encapsule it
-    $obj = htmlentities($obj);
-    return  "<$tag$tag_atts>$obj</$tag>\n";
-
 }
 
-?>
\ No newline at end of file
index 5851596..0e9def1 100644 (file)
@@ -1,47 +1,38 @@
 <?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
 /**
- * Moodle - Modular Object-Oriented Dynamic Learning Environment
- *         http://moodle.com
- *
- * LICENSE
- *
- * 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
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details:
+ * REST web service entry point. The authentication is done via tokens.
  *
- *         http://www.gnu.org/copyleft/gpl.html
- *
- * @category  Moodle
  * @package   webservice
- * @copyright Copyright (c) 1999 onwards Martin Dougiamas     http://dougiamas.com
- * @license   http://www.gnu.org/copyleft/gpl.html     GNU GPL License
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-/**
- * REST Moodle server.
- *
- * NOTE: for this first implementation, REST requires implicit url encoded params.
- * It uses function get_file_argument to get them.
- *
- * @author Jerome Mouneyrac
- * @author Ferran Recio
- * @author David Castro Garcia
- */
+define('NO_MOODLE_COOKIES', true);
 
-require_once(dirname(dirname(dirname(__FILE__))) . '/config.php');
-require_once('lib.php');
+require('../../config.php');
+require_once("$CFG->dirroot/webservice/rest/locallib.php");
 
-if (empty($CFG->enablewebservices)) {
+if (!webservice_protocol_is_enabled('rest')) {
     die;
 }
 
-$server = new rest_server();
-$server->run();
+$server = new webservice_rest_server();
+$server->run(false);
+die;
 
-?>
\ No newline at end of file
index cb43523..73a5e08 100644 (file)
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 /**
- * Sample simple REST web service server.
+ * REST web service entry point. The authentication is done via tokens.
  *
- * This WS entry point accepts only users from the 'auth/webservice'
- * plugin. Enabling of webservice for each user is explicitly allowed
- * via records in the external_services_users table.
- *
- * @package    moodlecore
- * @subpackage file
- * @copyright  2009 Petr Skoda (http://skodak.org)
- * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
- */
-
-
-/*
- * NOTE: this is a proposal for a new WS server OOP framework
- *
- * I did not understand much how the WS protocols are supposed
- * to work, I just tried to create some clean abstraction that
- * should allow easy implementation of any protocol server.
- * The REST was chosen only because it seems to be the easiest
- * one with no real standardisation ;-)
- *
- * == How to test this ==
- * 1/ create new service that includes function 'moodle_group_get_groups' by adding new local plugin,
- *    this adds new record into external_services table
- * 2/ create new user and select 'webservice' as auth plugin and enable webservice auth plugin
- * 3/ add $CFG->enablesimplewebservices=true; to your config.php
- * 4/ manually enable the rest service: set_config('enable', 1, 'rest');
- * 5/ manually insert record into external_services_users - your new service + your new user
- * 6/ create course with some groups
- * 7/ execute the REST query: http://nahore.skodak.local/moodle20/webservice/rest/simpleserver.php?wsusername=a&wspassword=p&wsfunction=moodle_group_get_groups&groupids[0]=1&groupids[1]=3
- * 8/ sit tight and watch in awe the super hyper mega cool xml response of fully working REST WS server :-)
- *
- * skodak
+ * @package   webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-
 define('NO_MOODLE_COOKIES', true);
 
 require('../../config.php');
-require_once("$CFG->libdir/externallib.php");
-//require_once("$CFG->dirroot/webservice/rest/lib.php"); TODO: uncomment when rewrite finished
-//require_once("$CFG->dirroot/webservice/rest/locallib.php"); TODO: uncomment when rewrite finished
-
-
-
-//======== NOTE: this should be defined in /webservice/rest/locallib.php =============================
-
-/**
- * REST service server class.
- *
- * @author Petr Skoda (skodak)
- */
-class webservice_rest_server extends webservice_base_server {
-    /**
-     * Contructor
-     * @param bool $simple use simple authentication
-     */
-    public function __construct($simple) {
-        parent::__construct($simple);
-        $this->wsname = 'rest';
-    }
-
-    /**
-     * This method parses the $_REQUEST superglobal and looks for
-     * the following information:
-     *  1/ user authentication - username+password or token (wsusername, wspassword and wstoken parameters)
-     *  2/ function name (wsfunction parameter)
-     *  3/ function parameters (all other parameters except those above)
-     *
-     * @return void
-     */
-    protected function parse_request() {
-        if ($this->simple) {
-            $this->username = isset($_REQUEST['wsusername']) ? $_REQUEST['wsusername'] : null;
-            unset($_REQUEST['wsusername']);
-
-            $this->password = isset($_REQUEST['wspassword']) ? $_REQUEST['wspassword'] : null;
-            unset($_REQUEST['wspassword']);
-
-            $this->functionname = isset($_REQUEST['wsfunction']) ? $_REQUEST['wsfunction'] : null;
-            unset($_REQUEST['wsfunction']);
-
-            $this->parameters = $_REQUEST;
-
-        } else {
-            //TODO
-            die('not implemented yet');
-        }
-    }
-
-    /**
-     * Send the result of function call to the WS client
-     * formatted as XML document.
-     * @return void
-     */
-    protected function send_response() {
-        $this->send_headers();
-        $xml = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
-        $xml .= '<RESPONSE>'."\n";
-        $xml .= self::xmlize_result($this->returns, $this->function->returns_desc);
-        $xml .= '</RESPONSE>'."\n";
-        echo $xml;
-    }
-
-    /**
-     * Send the error information to the WS client
-     * formatted as XML document.
-     * @param exception $ex
-     * @return void
-     */
-    protected function send_error($ex=null) {
-        $this->send_headers();
-        $xml = '<?xml version="1.0" encoding="UTF-8" ?>'."\n";
-        $xml .= '<EXCEPTION class="'.get_class($ex).'">'."\n";
-        $xml .= '<MESSAGE>'.htmlentities($ex->getMessage(), ENT_COMPAT, 'UTF-8').'</MESSAGE>'."\n";
-        if (debugging() and isset($ex->debuginfo)) {
-            $xml .= '<DEBUGINFO>'.htmlentities($ex->debuginfo, ENT_COMPAT, 'UTF-8').'</DEBUGINFO>'."\n";
-        }
-        $xml .= '</EXCEPTION>'."\n";
-        echo $xml;
-    }
-
-    /**
-     * Internal implementation - sending of page headers.
-     * @return void
-     */
-    protected function send_headers() {
-        header('Content-Type: application/xml');
-        header('Content-Disposition: inline; filename="response.xml"');
-        header('Cache-Control: private, must-revalidate, pre-check=0, post-check=0, max-age=0');
-        header('Expires: '. gmdate('D, d M Y H:i:s', 0) .' GMT');
-        header('Pragma: no-cache');
-        header('Accept-Ranges: none');
-    }
-
-    /**
-     * Internal implementation - recursive function producing XML markup.
-     * @param mixed $returns
-     * @param $desc
-     * @return unknown_type
-     */
-    protected static function xmlize_result($returns, $desc) {
-        if ($desc === null) {
-            return '';
-
-        } else if ($desc instanceof external_value) {
-            //TODO: there should be some way to indicate the real NULL value
-            return '<VALUE>'.htmlentities($returns, ENT_COMPAT, 'UTF-8').'</VALUE>'."\n";
-
-        } else if ($desc instanceof external_multiple_structure) {
-            $mult = '<MULTIPLE>'."\n";
-            foreach ($returns as $val) {
-                $mult .= self::xmlize_result($val, $desc->content);
-            }
-            $mult .= '</MULTIPLE>'."\n";
-            return $mult;
-
-        } else if ($desc instanceof external_single_structure) {
-            $single = '<SINGLE>'."\n";
-            foreach ($desc->keys as $key=>$subdesc) {
-                if (!array_key_exists($key, $returns)) {
-                    if ($subdesc->rewquired) {
-                        $single .= '<ERROR>Missing key</ERROR>';
-                        continue;
-                    } else {
-                        //optional field
-                        continue;
-                    }
-                }
-                $single .= '<KEY name="'.$key.'">'.self::xmlize_result($returns[$key], $subdesc).'</KEY>'."\n";
-            }
-            $single .= '</SINGLE>'."\n";
-            return $single;
-        }
-    }
-}
-
-
-
-
-//======== NOTE: this should be defined in /webservice/lib.php =============================
-
-/**
- * Web Service server base class, this class handles both
- * simple and token authentication.
- */
-abstract class webservice_base_server {
-
-    /** @property string $wsname name of the web server plugin */
-    protected $wsname = null;
-
-    /** @property bool $simple true if simple auth used */
-    protected $simple;
-
-    /** @property string $username name of local user */
-    protected $username = null;
-
-    /** @property string $password password of the local user */
-    protected $password = null;
-
-    /** @property string $token authentication token*/
-    protected $token = null;
-
-    /** @property array $parameters the function parameters - the real values submitted in the request */
-    protected $parameters = null;
-
-    /** @property string $functionname the name of the function that is executed */
-    protected $functionname = null;
-
-    /** @property object $function full function description */
-    protected $function = null;
-
-    /** @property mixed $returns function return value */
-    protected $returns = null;
-
-    /**
-     * Contructor
-     * @param bool $simple use simple authentication
-     */
-    public function __construct($simple) {
-        $this->simple = $simple;
-    }
-
-    /**
-     * This method parses the request input, it needs to get:
-     *  1/ user authentication - username+password or token
-     *  2/ function name
-     *  3/ function parameters
-     *
-     * @return void
-     */
-    abstract protected function parse_request();
-
-    /**
-     * Send the result of function call to the WS client.
-     * @return void
-     */
-    abstract protected function send_response();
-
-    /**
-     * Send the error information to the WS client.
-     * @param exception $ex
-     * @return void
-     */
-    abstract protected function send_error($ex=null);
-
-
-    public function run() {
-        // first make sure this service is enabled
-        if (!$this->is_enabled()) {
-            die();
-        }
-
-        // we will probably need a lot of memory in some functions
-        @raise_memory_limit('128M');
-
-        // set some longer timeout, this script is not sending any output,
-        // this means we need to manually extend the timeout operations
-        // that need longer time to finish
-        external_api::set_timeout();
-
-        // set up exception handler first, we want to sent them back in correct format that
-        // the other system understands
-        // we do not need to call the original default handler because this ws handler does everything
-        set_exception_handler(array($this, 'exception_handler'));
-
-        // init all properties from the request data
-        $this->parse_request();
-
-        // authenticate user, this has to be done after the request parsing
-        // this also sets up $USER and $SESSION
-        $this->authenticate_user();
-
-        // find all needed function info and make sure user may actually execute the function
-        $this->load_function_info();
-
-        // finally, execute the function - any errors are catched by the default exception handler
-        $this->execute();
-
-        // send the results back in correct format
-        $this->send_response();
-
-        // session cleanup
-        $this->session_cleanup();
-
-        die;
-    }
-
-    /**
-     * Specialised exception handler, we can not use the standard one because
-     * it can not just print html to output.
-     *
-     * @param exception $ex
-     * @return void does not return
-     */
-    public function exception_handler($ex) {
-        global $CFG, $DB, $SCRIPT;
-
-        // detect active db transactions, rollback and log as error
-        if ($DB->is_transaction_started()) {
-            error_log('Database transaction aborted by exception in ' . $CFG->dirroot . $SCRIPT);
-            try {
-                // note: transaction blocks should never change current $_SESSION
-                $DB->rollback_sql();
-            } catch (Exception $ignored) {
-            }
-        }
-
-        // now let the plugin send the exception to client
-        $this->send_error($ex);
-
-        // some hacks might need a cleanup hook
-        $this->session_cleanup($ex);
-
-        // not much else we can do now, add some logging later
-        exit(1);
-    }
-
-    /**
-     * Future hook needed for emulated sessions.
-     * @param exception $exception null means normal termination, $exception received when WS call failed
-     * @return void
-     */
-    protected function session_cleanup($exception=null) {
-        if ($this->simple) {
-            // nothing needs to be done, there is no persistent session
-        } else {
-            // close emulated session if used
-        }
-    }
-
-    /**
-     * Authenticate user using username+password or token.
-     * This function sets up $USER global.
-     * It is safe to use has_capability() after this.
-     * This method also verifies user is allowed to use this
-     * server.
-     * @return void
-     */
-    protected function authenticate_user() {
-        global $CFG, $DB;
-
-        if (!NO_MOODLE_COOKIES) {
-            throw new coding_exception('Cookies must be disabled in WS servers!');
-        }
-
-        if ($this->simple) {
-            if (!is_enabled_auth('webservice')) {
-                die('WS auth not enabled');
-            }
-
-            if (!$auth = get_auth_plugin('webservice')) {
-                die('WS auth missing');
-            }
-
-            if (!$this->username) {
-                throw new invalid_parameter_exception('Missing username');
-            }
-
-            if (!$this->password) {
-                throw new invalid_parameter_exception('Missing password');
-            }
-
-            if (!$auth->user_login_webservice($this->username, $this->password)) {
-                throw new invalid_parameter_exception('Wrong username or password');
-            }
-
-            $user = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST);
-
-            // now fake user login, the session is completely empty too
-            session_set_user($user);
-
-            /* //TODO: add web service usage capabilities
-            if (!has_capability("webservice/$this->wsname:usesimple", get_context_instance(CONTEXT_SYSTEM))) {
-                throw new invalid_parameter_exception('Access to web service not allowed');
-            }
-            */
-
-        } else {
-            //TODO: not implemented yet
-            die('token login not implemented yet');
-
-            /* //TODO: add web service usage capabilities
-            // note we had to wait until here because we did not know the security context earlier
-            if (!has_capability("webservice/$this->wsname:use", $context)) {
-                throw new invalid_parameter_exception('Access to web service not allowed');
-            }
-            */
-        }
-    }
-
-    /**
-     * Fetches the function description from database,
-     * verifies user is allowed to use this function and
-     * loads all paremeters and return descriptions.
-     * @return void
-     */
-    protected function load_function_info() {
-        global $DB, $USER, $CFG;
-
-        if (empty($this->functionname)) {
-            throw new invalid_parameter_exception('Missing function name');
-        }
-
-        // function must exist
-        $function = $DB->get_record('external_functions', array('name'=>$this->functionname), '*', MUST_EXIST);
-
-
-        // now let's verify access control
-        if ($this->simple) {
-            // now make sure the function is listed in at least one service user is allowed to use
-            // allow access only if:
-            //  1/ entry in the external_services_users table - the restricted users flag is ignored in service desc
-            //  2/ validuntil not reached
-            //  3/ has capability if specified in service desc
-            //  4/ iprestriction
-
-            $sql = "SELECT s.*, su.iprestriction
-                      FROM {external_services} s
-                      JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND sf.functionname = :name)
-                      JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)
-                     WHERE su.validuntil IS NULL OR su.validuntil < :now";
-            $rs = $DB->get_recordset_sql($sql, array('userid'=>$USER->id, 'name'=>$function->name, 'now'=>time()));
-            // now make sure user may access at least one service
-            $syscontext = get_context_instance(CONTEXT_SYSTEM);
-            $remoteaddr = getremoteaddr();
-            $allowed = false;
-            foreach ($rs as $service) {
-                if ($service->requiredcapability and !has_capability($service->requiredcapability, $syscontext)) {
-                    continue; // cap required, sorry
-                }
-                if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) {
-                    continue; // wrong request source ip, sorry
-                }
-                $allowed = true;
-                break; // one service is enough, no need to continue
-            }
-            $rs->close();
-            if (!$allowed) {
-                throw new invalid_parameter_exception('Access to external function not allowed');
-            }
-            // now we finally know the user may execute this function,
-            // the last step is to set context restriction - in this simple case
-            // we use system context because each external system has different user account
-            // and we can manage everything through normal permissions.
-            external_api::set_context_restriction($syscontext);
-
-        } else {
-            //TODO: implement token security checks
-            die('not implemented yet');
-        }
-
-        // get the params and return descriptions of the function
-        unset($function->id); // we want to prevent any accidental db updates ;-)
-
-        $function->classpath = empty($function->classpath) ? get_component_directory($function->component).'/externallib.php' : $CFG->dirroot.'/'.$function->classpath;
-        if (!file_exists($function->classpath)) {
-            throw new coding_exception('Can not find file with external function implementation');
-        }
-        require_once($function->classpath);
-
-        $function->parameters_method = $function->methodname.'_parameters';
-        $function->returns_method    = $function->methodname.'_returns';
-
-        // make sure the implementaion class is ok
-        if (!method_exists($function->classname, $function->methodname)) {
-            throw new coding_exception('Missing implementation method');
-        }
-        if (!method_exists($function->classname, $function->parameters_method)) {
-            throw new coding_exception('Missing parameters description');
-        }
-        if (!method_exists($function->classname, $function->returns_method)) {
-            throw new coding_exception('Missing returned values description');
-        }
-
-        // fetch the parameters description
-        $function->parameters_desc = call_user_func(array($function->classname, $function->parameters_method));
-        if (!($function->parameters_desc instanceof external_function_parameters)) {
-            throw new coding_exception('Invalid parameters description');
-        }
-
-        // fetch the return values description
-        $function->returns_desc = call_user_func(array($function->classname, $function->returns_method));
-        // null means void result or result is ignored
-        if (!is_null($function->returns_desc) and !($function->returns_desc instanceof external_description)) {
-            throw new coding_exception('Invalid return description');
-        }
-
-        // we have all we need now
-        $this->function = $function;
-    }
-
-    /**
-     * Execute previously loaded function using parameters parsed from the request data.
-     * @return void
-     */
-    protected function execute() {
-        // validate params, this also sorts the params properly, we need the correct order in the next part
-        $params = call_user_func(array($this->function->classname, 'validate_parameters'), $this->function->parameters_desc, $this->parameters);
-
-        // execute - yay!
-        $this->returns = call_user_func_array(array($this->function->classname, $this->function->methodname), array_values($params));
-    }
-
-    /**
-     * Returns human readable protocol name.
-     * @return string
-     */
-    public function get_protocolname() {
-        return get_string('protocolname', 'webservice_'.$this->wsname); //TODO: add to lang pack
-    }
-
-    /**
-     * Returns WS plugin name (not localized)
-     * @return string
-     */
-    public function get_name() {
-        return $this->wsname;
-    }
-
-    /**
-     * Is this WS server plugin enabled?
-     * @return bool
-     */
-    public function is_enabled() {
-        return get_config($this->wsname, 'enable');
-    }
-
-    /**
-     * Change enabled flag
-     * @param bool $enable
-     * @return void
-     */
-    public function set_enable($enable) {
-        set_config('enable', $enable, $this->wsname);
-    }
-
-    /**
-     * Returns the settings form,
-     * the current data and defaults are already loaded.
-     * @return moodleform or null if settings not used
-     */
-    public function settings_form() {
-        //NOTE: store the form definition in separate file, not directly in lib.php!!
-        return null;
-    }
-
-    /**
-     * Saves settings form data to db.
-     * @param array $data
-     * @return void
-     */
-    public function settings_save($data) {
-        return;
-    }
-}
-
-
-
-//======== NOTE: this is finally the code that would be in this file =============================
-
+require_once("$CFG->dirroot/webservice/rest/locallib.php");
 
-if (empty($CFG->enablesimplewebservices)) {
+if (!webservice_protocol_is_enabled('rest')) {
     die;
 }
 
-$server = new webservice_rest_server(true);
-$server->run();
+$server = new webservice_rest_server();
+$server->run(true);
 die;
 
 
diff --git a/webservice/rest/testclient/addgroupmember.php b/webservice/rest/testclient/addgroupmember.php
deleted file mode 100644 (file)
index 61a7b9e..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php
-/**
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupid', 'userid');
-
-foreach ($params as $param) {
-       $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Add group member to group");
-?>
-
-<form action="addgroupmember.php" method="post">
-<table border="0">
-    <tr><td>Group id: </td><td><input type="text" name="groupid" value="<?php echo $groupid; ?>"/></td></tr>
-    <tr><td>User id: </td><td><input type="text" name="userid" value="<?php echo $userid; ?>"/></td></tr>
-    <tr><td></td><td><input type="submit" value="Add member"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupid && $userid) {
-
-    var_dump($CFG->serverurl.'/group/add_groupmember');
-
-
-    //we are asking for a token
-    $connectiondata['username'] = 'wsuser';
-    $connectiondata['password'] = 'wspassword';
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
-    $token = curl_exec($ch);
-
-    $data['token'] = $token;
-       $data['groupid'] = $groupid;
-       $data['userid'] = $userid;
-
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/group/add_groupmember');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
-    $out = curl_exec($ch);
-
-    $res = basicxml_xml_to_object($out);
-
-    show_object($res->result);
-
-    show_xml ($out);
-} else {
-    echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
diff --git a/webservice/rest/testclient/config_rest.php b/webservice/rest/testclient/config_rest.php
deleted file mode 100644 (file)
index 8f9e944..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client configuration file
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- *
- */
-
-require_once("../../../config.php");
-require_once ('lib.php');
-
-if (empty($CFG->enablewebservices)) {
-    die;
-}
-
-$CFG->serverurl = $CFG->wwwroot.'/webservice/rest/server.php';
-if (!function_exists('curl_init')) die ('CURL library was not found!');
-
-?>
\ No newline at end of file
diff --git a/webservice/rest/testclient/creategroup.php b/webservice/rest/testclient/creategroup.php
deleted file mode 100644 (file)
index c7b78fa..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupname', 'courseid');
-
-foreach ($params as $param) {
-       $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Create Group");
-?>
-
-<form action="creategroup.php" method="post">
-<table border="0">
-    <tr><td>Group name: </td><td><input type="text" name="groupname" value="<?php echo $groupname; ?>"/></td></tr>
-    <tr><td>Course id: </td><td><input type="text" name="courseid" value="<?php echo $groupid; ?>"/></td></tr>
-    <tr><td></td><td><input type="submit" value="Create Group"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupname && $courseid) {
-
-    var_dump($CFG->serverurl.'/group/create_group');
-
-
-    //we are asking for a token
-    $connectiondata['username'] = 'wsuser';
-    $connectiondata['password'] = 'wspassword';
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
-    $token = curl_exec($ch);
-
-    $data['token'] = $token;
-       $data['groupname'] = $groupname;
-       $data['courseid'] = $courseid;
-
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/group/create_group');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
-    $out = curl_exec($ch);
-
-    $res = basicxml_xml_to_object($out);
-
-    show_object($res->groupid);
-
-    show_xml ($out);
-} else {
-    echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
diff --git a/webservice/rest/testclient/createuser.php b/webservice/rest/testclient/createuser.php
deleted file mode 100644 (file)
index 6a8b983..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- */
-
-require_once ('config_rest.php');
-start_interface("Create A User");
-
-$ch = curl_init();
-
-$data['username'] = "mockuser5";
-$data['firstname'] = "mockuser5";
-$data['lastname'] = "mockuser5";
-$data['email'] = "mockuser5@lastname.com";
-
-var_dump($data);
-
-//we are asking for a token
-$connectiondata['username'] = 'wsuser';
-$connectiondata['password'] = 'wspassword';
-$ch = curl_init();
-curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
-curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-curl_setopt($ch, CURLOPT_POST, 1);
-curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
-$token = curl_exec($ch);
-$data['token'] = $token;
-
-curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/create_user');
-curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-curl_setopt($ch, CURLOPT_POST, 1);
-curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
-
-$out = curl_exec($ch);
-
-$res = basicxml_xml_to_object($out);
-
-show_object($res->userid);
-
-show_xml ($out);
-
-end_interface();
-?>
\ No newline at end of file
diff --git a/webservice/rest/testclient/deletegroup.php b/webservice/rest/testclient/deletegroup.php
deleted file mode 100644 (file)
index 889aee6..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupid');
-
-foreach ($params as $param) {
-       $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Delete group");
-?>
-
-<form action="deletegroup.php" method="post">
-<table border="0">
-    <tr><td>Group id: </td><td><input type="text" name="groupid" value="<?php echo $groupid; ?>"/></td></tr>
-    <tr><td></td><td><input type="submit" value="Delete Group"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupid) {
-
-     //we are asking for a token
-    $connectiondata['username'] = 'wsuser';
-    $connectiondata['password'] = 'wspassword';
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
-    $token = curl_exec($ch);
-    $data['token'] = $token;
-
-    $data['groupid'] = $groupid;
-
-    $ch = curl_init();
-
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/group/delete_group');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
-    $out = curl_exec($ch);
-
-    $res = basicxml_xml_to_object($out);
-
-       show_object($res);
-
-    show_xml ($out);
-} else {
-    echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
diff --git a/webservice/rest/testclient/deletegroupmember.php b/webservice/rest/testclient/deletegroupmember.php
deleted file mode 100644 (file)
index 5d493aa..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-<?php
-/**
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupid', 'userid');
-
-foreach ($params as $param) {
-       $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Delete group member from a group");
-?>
-
-<form action="deletegroupmember.php" method="post">
-<table border="0">
-    <tr><td>Group id: </td><td><input type="text" name="groupid" value="<?php echo $groupid; ?>"/></td></tr>
-    <tr><td>User id: </td><td><input type="text" name="userid" value="<?php echo $userid; ?>"/></td></tr>
-    <tr><td></td><td><input type="submit" value="Delete"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupid && $userid) {
-
-    var_dump($CFG->serverurl.'/group/delete_groupmember');
-
-
-    //we are asking for a token
-    $connectiondata['username'] = 'wsuser';
-    $connectiondata['password'] = 'wspassword';
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
-    $token = curl_exec($ch);
-
-    $data['token'] = $token;
-       $data['groupid'] = $groupid;
-       $data['userid'] = $userid;
-
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/group/delete_groupmember');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
-    $out = curl_exec($ch);
-
-    $res = basicxml_xml_to_object($out);
-
-    show_object($res->result);
-
-    show_xml ($out);
-} else {
-    echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
diff --git a/webservice/rest/testclient/deleteuser.php b/webservice/rest/testclient/deleteuser.php
deleted file mode 100644 (file)
index 5aa15ab..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/**
- * Created on 10/17/2008
- * 
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- */
-
-require_once ('config_rest.php');
-
-$params = array('username','mnethostid');
-
-foreach ($params as $param) {
-       $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Delete a user");
-?>
-
-<form action="deleteuser.php" method="post">
-<table border="0">
-    <tr><td>Search: </td><td><input type="text" name="username" value="<?php echo $username; ?>"/></td></tr>
-    <tr><td></td><td><input type="hidden" name="mnethostid" value="1"><input type="submit" value="Find Users"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($username) {
-  
-     //we are asking for a token
-    $connectiondata['username'] = 'wsuser';
-    $connectiondata['password'] = 'wspassword';
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
-    $token = curl_exec($ch);
-    $data['token'] = $token;
-
-    $data['username'] = $username;
-    $data['mnethostid'] = $mnethostid;
-
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/delete_user');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
-    $out = curl_exec($ch);
-
-    $res = basicxml_xml_to_object($out);
-
-    //show_object($res->user,2,'auth');
-    var_dump($res);
-    show_xml ($out);
-} else {
-    echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
diff --git a/webservice/rest/testclient/getgroup.php b/webservice/rest/testclient/getgroup.php
deleted file mode 100644 (file)
index cdc8d90..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jordi Piguillem
- */
-
-require_once ('config_rest.php');
-
-$params = array('groupid');
-
-foreach ($params as $param) {
-       $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Get Group");
-?>
-
-<form action="getgroup.php" method="post">
-<table border="0">
-    <tr><td>Group id: </td><td><input type="text" name="groupid" value="<?php echo $groupid; ?>"/></td></tr>
-    <tr><td></td><td><input type="submit" value="Find Group"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($groupid) {
-
-     //we are asking for a token
-    $connectiondata['username'] = 'wsuser';
-    $connectiondata['password'] = 'wspassword';
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
-    $token = curl_exec($ch);
-    $data['token'] = $token;
-
-    $data['groupid'] = $groupid;
-
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/group/get_group');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
-    $out = curl_exec($ch);
-
-    $res = basicxml_xml_to_object($out);
-
-       show_object($res->return);
-
-    show_xml ($out);
-} else {
-    echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
diff --git a/webservice/rest/testclient/getusers.php b/webservice/rest/testclient/getusers.php
deleted file mode 100644 (file)
index f8117f6..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- */
-
-require_once ('config_rest.php');
-
-$params = array('search');
-
-foreach ($params as $param) {
-    $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("List of Users");
-?>
-
-<form action="getusers.php" method="post">
-    <table border="0">
-        <tr><td>Search: </td><td><input type="text" name="search" value="<?php echo $search; ?>"/></td></tr>
-        <tr><td></td><td><input type="submit" value="Find Users"></td></tr>
-    </table>
-</form>
-
-<?php
-
-if ($search) {
-    $data['search'] = $search;
-
-    //we are asking for a token
-    $connectiondata['username'] = 'wsuser';
-    $connectiondata['password'] = 'wspassword';
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
-    $token = curl_exec($ch);
-    $data['token'] = $token;
-
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_users');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
-    $out = curl_exec($ch);
-
-    $res = basicxml_xml_to_object($out);
-    show_object($res->user,2,'auth');
-
-    show_xml ($out);
-} else {
-    echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
index be0dca4..944a32e 100644 (file)
@@ -1,38 +1,93 @@
 <?php
+
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
 /**
- * Created on 10/17/2008
+ * REST web service test client.
  *
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- * @author Jordi Piguillem
+ * @package   webservice
+ * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
-require_once ('config_rest.php');
-
-start_interface (false);
-
-$links = array( array('USERS'),
-                               array('getusers.php','get_users()'),
-                array('createuser.php','create_user()'),
-                array('deleteuser.php','delete_user()'),
-                array('updateuser.php','update_user()'),
-                array('GROUPS'),
-                array('creategroup.php','create_group()'),
-                array('addgroupmember.php', 'add_groupmember()'),
-                array('getgroup.php', 'get_group()'));
-
-echo '<ul>';
-foreach ($links as $link) {
-       if (sizeof($link)==2){
-       echo '<li><a href="'.$link[0].'">'.$link[1].'</a></li>';
-       } else {
-               echo '</ul><h2>'.$link[0].'</h2><ul>';
-       }
+require('../../../config.php');
+require_once("$CFG->dirroot/webservice/webservice_test_client_form.php");
+require_once("$CFG->dirroot/webservice/rest/locallib.php");
+
+$function = optional_param('function', '', PARAM_SAFEDIR);
+
+$PAGE->set_url('webservice/rest/testclient/index.php');
+
+require_login();
+require_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM)); // TODO: do we need some new capability?
+
+$functions = array('moodle_group_get_groups');
+$functions = array_combine($functions, $functions);
+
+if (!isset($functions[$function])) {
+    $function = '';
 }
-echo '</ul>';
 
-end_interface(false);
-?>
\ No newline at end of file
+if (!$function) {
+    $mform = new webservice_test_client_form(null, $functions);
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('pluginname', 'webservice_rest'));
+    $mform->display();
+    echo $OUTPUT->footer();
+    die;
+}
+
+$class = $function.'_form';
+require_once("$CFG->dirroot/webservice/rest/testclient/$class.php");
+
+$mform = new $class();
+
+if ($mform->is_cancelled()) {
+    redirect('index.php');
+
+} else if ($data = $mform->get_data()) {
+    $serverurl = "$CFG->wwwroot/webservice/rest/simpleserver.php";
+    $serverurl .= '?wsusername='.urlencode($data->wsusername);
+    $serverurl .= '&wspassword='.urlencode($data->wspassword);
+    $serverurl .= '&wsfunction='.urlencode($data->function);
+    for ($i=0; $i<10; $i++) {
+        if (empty($data->groupids[$i])) {
+            continue;
+        }
+        $serverurl .= "&groupids[$i]=".urlencode($data->groupids[$i]);
+    }
+
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('pluginname', 'webservice_rest').': '.$function);
+
+    echo 'URL: '.s($serverurl);
+    echo $OUTPUT->box_start();
+    echo '<code>';
+    $response = download_file_content($serverurl);
+    echo str_replace("\n", '<br />', s($response));
+    echo '</code>';
+    echo $OUTPUT->box_end();
+    $mform->display();
+    echo $OUTPUT->footer();
+    die;
+
+} else {
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('pluginname', 'webservice_rest').': '.$function);
+    $mform->display();
+    echo $OUTPUT->footer();
+    die;
+}
\ No newline at end of file
diff --git a/webservice/rest/testclient/lib.php b/webservice/rest/testclient/lib.php
deleted file mode 100644 (file)
index ebac6cd..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-<?php
-/**
- * Created on 10/17/2008
- *
- * Rest Test Client Suport Library
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- */
-
-//--- interface helpers ---
-
-/**
- * starts the interface
- */
-function start_interface ($title="&nbsp;") {
-    $title2 = ($title)?$title:"&nbsp;";
-    echo '<html><head>';
-    echo "<title>Moodle Webservice Rest Test Client</title>";
-    echo '<link rel="stylesheet" href="style.css" type="text/css">';
-    echo '</head><body>';
-    echo '<div class="head"><h1>Moodle Webservice Rest Test Client</h1>';
-    echo "<h3>$title2</h3>";
-    echo '</div>';
-    echo '<div class="content">';
-    if ($title) echo '<p class="return"><a href="index.php"><img src="return.gif" border="0"/></a></p>';
-}
-
-/**
- * end interface
- *
- * @param bool $ret=true: show return button
- */
-function end_interface ($ret = true) {
-    if ($ret) echo '<p class="return"><a href="index.php"><img src="return.gif" border="0"/></a></p>';
-    echo '</div>';
-    echo '<div class="footer">Created by David Castro i Ferran Recio for Moodle Webservices</div>';
-    echo '</body></html>';
-}
-
-/**
- * print XML div area
- *
- * @param string $xml
- *
- */
-function show_xml ($xml) {
-    echo '<div class="xmlshow">';
-    echo '<a onClick="document.getElementById(\'toggleme\').style.display = ' .
-            '(document.getElementById(\'toggleme\').style.display!=\'none\')?\'none\':\'\';">Hide/Show XML</a>';
-    echo "<div style=\"display:none;\" id=\"toggleme\">";
-    echo '<pre>';echo htmlentities($xml);echo '</pre>';
-    echo "</div>";
-    echo "</div>";
-}
-
-/**
- * format post data
- */
-function format_postdata ($data) {
-    $o="";
-    foreach ($data as $k=>$v) {
-        $o.= "$k=".rawurlencode($v)."&";
-    }
-    $post_data=substr($o,0,-1);
-    return $post_data;
-}
-
-/**
- * shows an object in list format
- *
- * @param mixed $obj
- * @param integer $cols: number of colums
- * @ string string $check=false: if this attribute is not present, the $obj is ans error
- *
- */
-function show_object ($obj,$cols=1,$check=false) {
-    if (!is_array($obj)) $obj = array($obj);
-    echo '<ul class="results">';
-    foreach ($obj as $r) {
-
-        if ($check && (!isset($r->$check) || $r->$check==-1)) {
-            echo '<li class="error">';
-            echo "EMPTY ROW!";
-        } else {
-            if (is_object($r)) {
-                echo '<li class="element">';
-                $text = array();
-                $parts = get_object_vars($r);
-                $num = 1;
-                $currline = '';
-                foreach ($parts as $key => $val) {
-                    $currline.= "<span class=\"resultval\"><b>$key:</b> <i>$val</i></span>, ";
-                    if ($num >= $cols) {
-                        $currline=substr($currline,0,-2);
-                        $text[] = $currline;
-                        $currline = '';
-                        $num = 0;
-                    }
-                    $num++;
-                }
-                echo implode('<br/>',$text);
-            } else {
-                if ($r==-1 || !$r) {
-                    echo '<li class="error">';
-                    echo "EMPTY ROW!";
-                } else {
-                    echo '<li class="element">';
-                    echo "<span class=\"resultval\"><b>Returned Value:</b> <i>$r</i></span>";
-                }
-            }
-        }
-        echo '</li>';
-    }
-    echo '</ul>';
-}
-
-
-//---- XML simple parser ----
-//this code was donated by Ferran Recio
-
-/**
- * convert a simple xml into php object
- *
- * @author ferran recio
- *
- * @param String $xml
- *
- * @return mixed
- */
-function basicxml_xml_to_object ($xml) {
-    $xml=utf8_encode($xml);
-
-    //create the parser
-    $parser = xml_parser_create ();
-    xml_set_default_handler ($parser,'basicxml_xml_to_object_aux');
-
-    $values = array();
-    $index = array();
-    xml_parse_into_struct($parser,$xml,$values,$index);
-
-    //print_object($values);
-    //print_object($index);
-
-    //just simplexml tag (disabled)
-    //if (strtolower($values[0]['tag']) != 'basicxml') return false;
-    //if (strtolower($values[count($values)-1]['tag']) != 'basicxml') return false;
-
-    $res = basicxml_xml_to_object_aux ($values);
-    //omit the first tag
-    $parts = array_keys(get_object_vars($res));
-    $key = $parts[0];
-    return $res->$key;
-}
-
-/**
- * auxiliar function to basicxml_xml_to_object
- *
- * @author ferran recio
- *
- * @param mixed $values
- *
- * @return mixed
- */
-function basicxml_xml_to_object_aux ($values) {
-
-    if (!is_array($values)) return false;
-    //print_object ($values);
-    $currset = array();
-    $search = false;
-
-    foreach ($values as $value) {
-        $tag = strtolower($value['tag']);
-        //if we are acomulating, just acomulate it
-        if ($search) {
-            //if it closes a tag, we just stop searching
-            if ($tag == $search && $value['type']=='close') {
-                //recursivity
-                $obj2 = basicxml_xml_to_object_aux ($currset);
-                //search cleaning
-                $search = false;
-                //add to result
-                if (isset($res->{$tag})){
-                    if (is_array($res->{$tag})){
-                        $res->{$tag}[] = $obj2;
-                    } else {
-                        $res->{$tag} = array($res->{$tag},$obj2);
-                    }
-                } else {
-                    $res->{$tag} = $obj2;
-                }
-            } else {
-                //we are searching. If it's cdada, pass it throw
-                if ($value['type']=='cdata') continue;
-                //if isn't cdata, put it in the set and continue searching
-                //(because isn't the close we're searching)
-                $currset[] = $value;
-            }
-        } else {
-            //walking the xml
-            if ($value['type']=='open'){
-                //on open, let's search on it
-                $currset = array();
-                $search = $tag;
-            } else {
-                //if it's complete just save it
-                if ($value['type']=='complete') {
-                    if (!empty($value['value']  )) {
-                        $val = html_entity_decode($value['value']);
-                        if (isset($res->{$tag})){
-                            if (is_array($res->{$tag})){
-                                $res->{$tag}[] = $val;
-                            } else {
-                                $res->{$tag} = array($res->{$tag},$val);
-                            }
-                        } else {
-                            $res->{$tag} = $val;
-                        }
-                    }
-                }
-            }
-        }
-    }
-    return $res;
-}
-?>
diff --git a/webservice/rest/testclient/moodle_group_get_groups_form.php b/webservice/rest/testclient/moodle_group_get_groups_form.php
new file mode 100644 (file)
index 0000000..682758e
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+
+require_once($CFG->dirroot.'/lib/formslib.php');
+
+
+class moodle_group_get_groups_form extends moodleform {
+    public function definition() {
+        global $CFG;
+
+        $mform = $this->_form;
+
+        $mform->addElement('header', 'wstestclienthdr', get_string('testclient', 'webservice'));
+
+        //note: these values are intentionally PARAM_RAW - we want users to test any rubbish as parameters
+        $mform->addElement('text', 'wsusername', 'wsusername');
+        $mform->addElement('text', 'wspassword', 'wspassword');
+        $mform->addElement('text', 'groupids[0]', 'groupids[0]');
+        $mform->addElement('text', 'groupids[1]', 'groupids[1]');
+        $mform->addElement('text', 'groupids[2]', 'groupids[2]');
+        $mform->addElement('text', 'groupids[3]', 'groupids[3]');
+
+        $mform->addElement('hidden', 'function');
+        $mform->setType('function', PARAM_SAFEDIR);
+        $mform->setDefault('function', 'moodle_group_get_groups');
+
+        $this->add_action_buttons(true, get_string('test', 'webservice'));
+    }
+}
\ No newline at end of file
diff --git a/webservice/rest/testclient/return.gif b/webservice/rest/testclient/return.gif
deleted file mode 100644 (file)
index 96a5251..0000000
Binary files a/webservice/rest/testclient/return.gif and /dev/null differ
diff --git a/webservice/rest/testclient/style.css b/webservice/rest/testclient/style.css
deleted file mode 100644 (file)
index ddd466b..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-body {
-       background-color: #FAFFFF;;
-}
-
-.xmlshow {
-       background-color: #DDDDFF;
-       padding:20px;
-}
-
-.xmlshow div {
-       height: 200px;
-       overflow: auto;
-       padding: 20px;
-       background-color: #EEEEFF;
-}
-
-.head, .footer {
-       background-color: #AAAAFF;
-       text-align: center;
-}
-
-.footer {
-       font-size: small;
-       padding: 10px;
-}
-
-.content {
-       padding-left: 20px;
-       padding-right: 20px;
-}
-
-.results li{
-       margin-bottom:20px;
-       padding: 10px;
-       list-style-type: square;
-}
-
-.element {
-       background-color: #CCCCFF;
-}
-
-.element span:hover{
-       background-color:#DDDDFF;
-}
-
-.error {
-       background-color: #FFCCCC;
-}
-
-.return a, .return a:hover, .return a:visited{
-       color:#0000DD;
-}
-
-h1, h2 {
-       margin:0px;
-       padding:5px;
-}
\ No newline at end of file
diff --git a/webservice/rest/testclient/updateuser.php b/webservice/rest/testclient/updateuser.php
deleted file mode 100644 (file)
index 8ecbfcd..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-/**
- * Created on 10/17/2008
- * 
- * Rest Test Client
- *
- * @author David Castro Garcia
- * @author Ferran Recio Calderó
- * @author Jerome Mouneyrac
- */
-
-require_once ('config_rest.php');
-
-$params = array('username','mnethostid','newusername','firstname');
-
-foreach ($params as $param) {
-       $$param = (isset($_POST[$param]))?$_POST[$param]:'';
-}
-
-start_interface("Update a user");
-?>
-
-<form action="updateuser.php" method="post">
-<table border="0">
- <tr><td>Old username: </td><td><input type="text" name="username" value="<?php echo $username; ?>"/></td></tr>
- <tr><td>New username: </td><td><input type="text" name="newusername" value="<?php echo $newusername; ?>"/></td></tr>
- <tr><td>New firstname: </td><td><input type="text" name="firstname" value="<?php echo $firstname; ?>"/></td></tr>
- <tr><td></td><td><input type="hidden" name="mnethostid" value="1"><input type="submit" value="Find Users"></td></tr>
-</table>
-</form>
-
-<?php
-
-if ($username) {
-
-    //we are asking for a token
-    $connectiondata['username'] = 'wsuser';
-    $connectiondata['password'] = 'wspassword';
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/get_token');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($connectiondata));
-    $token = curl_exec($ch);
-    $data['token'] = $token;
-
-    $data['username'] = $username;
-    $data['mnethostid'] = $mnethostid;
-    $data['newusername'] = $newusername;
-    $data['firstname'] = $firstname;
-
-    $ch = curl_init();
-    curl_setopt($ch, CURLOPT_URL, $CFG->serverurl.'/user/update_user');
-    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
-    curl_setopt($ch, CURLOPT_POST, 1);
-    curl_setopt($ch, CURLOPT_POSTFIELDS, format_postdata($data));
-    $out = curl_exec($ch);
-
-    $res = basicxml_xml_to_object($out);
-
-    //show_object($res->user,2,'auth');
-    var_dump($res);
-    show_xml ($out);
-} else {
-    echo "<p>Fill the form first</p>";
-}
-
-end_interface();
-
-?>
diff --git a/webservice/rest/version.php b/webservice/rest/version.php
new file mode 100644 (file)
index 0000000..aabe26d
--- /dev/null
@@ -0,0 +1,3 @@
+<?php
+
+$plugin->version = 2009100800;
diff --git a/webservice/webservice_test_client_form.php b/webservice/webservice_test_client_form.php
new file mode 100644 (file)
index 0000000..5993516
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+
+require_once($CFG->dirroot.'/lib/formslib.php');
+
+
+class webservice_test_client_form extends moodleform {
+    public function definition() {
+        global $CFG;
+
+        $mform = $this->_form;
+        $functions = $this->_customdata;
+
+        $mform->addElement('header', 'wstestclienthdr', get_string('testclient', 'webservice'));
+
+        $mform->addElement('select', 'function', get_string('function', 'webservice'), $functions);
+
+        $this->add_action_buttons(false, get_string('select'));
+    }
+}
\ No newline at end of file
index 49b7c89..e74ebd9 100644 (file)
 //                                                                       //
 ///////////////////////////////////////////////////////////////////////////
 
+// TODO: this needs to be rewritten to use the new description format
+//       the problem here is that the list of functions is different for each use or even token
+//       I guess this should ne moved to server itself and it should require user auth
+die('TODO');
+
 /**
  * This file generate a web service documentation in HTML
  * This documentation describe how to call a Moodle Web Service