Problem with adding a new external function

Problem with adding a new external function

by Christian Pfisterer -
Number of replies: 23
Hi,

I've created a new external function which should enrol a user into a course.
The problem is that it does not get recognized?!
It is not listed in the list of functions I can add to specific webservice. It is not in the database either.

What am I doing wrong?

here is my code:
added to /lib/db/services.php
[code]
'moodle_enrol_set_manual_enrol' => array(
'classname' => 'moodle_enrol_external',
'methodname' => 'set_manual_enrol',
'classpath' => 'enrol/externallib.php',
'description' => 'Manual enrol users into a course',
'type' => 'write',
'capabilities'=> 'enrol/manual:enrol',
),
[/code]

added to /enrol/externallib.php
[code]
/**
* Returns description of method parameters
* @return external_function_parameters
*/
public static function set_manual_enrol_parameters() {
return new external_function_parameters(
array(
'userid' => new external_value(PARAM_INT, 'ID of user'),
'courseid' => new external_value(PARAM_INT, 'The course id where all users should be enroled to'),
)
);
}

/**
*
* Enrol users into a course
* @param array $userids An array of user ids
* @param int $course_id ID of course
*/
public static function set_manual_enrol($userid, $courseid) {

$params = self::validate_parameters(self::enrol_manual_parameters(), array('userid'=>$userid, 'courseid'=>$courseid));

$instance = $DB->get_record('enrol', array('id'=>1, 'enrol'=>'manual'), '*');
$instance->courseid = $course_id;

if (!$enrol_manual = enrol_get_plugin('manual')) {
throw new coding_exception('Can not instantiate enrol_manual');
}

$timestart = time();
$timeend = 0;

$enrol_manual->enrol_user($instance, $userid, $roleid, $timestart, $timeend);
}

/**
* Returns description of method result value
* @return external_description
*/
public static function set_manual_enrol_returns() {
return null;
}
}
[/code]

I hope somebody can help me. Thanks.
Average of ratings: Useful (1)
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Howard Miller -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers
Did you bump the version number of whatever block/mod/local/whatever you added it to?
In reply to Howard Miller

Re: Problem with adding a new external function

by Christian Pfisterer -
To be honest I don't really understand your question smile
I added the external function to /enrol/externallib.php
Version 1.6!?

In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Jérôme Mouneyrac -
Howard is right. Increase the Moodle version number in moodle/version.php. Increase it adding just some decimal (i.e. YYYYMMDDXX.ZZ), so you don't get impacted during the next update as we don't commit float version number.

Then just go back to moodle/admin, run the Moodle upgrade.
Your functions should appear in the DB (the upgrade system is looking to any changes into services.php files)



Average of ratings: Useful (1)
In reply to Jérôme Mouneyrac

Re: Problem with adding a new external function

by Christian Pfisterer -
Ahhh that's what I was looking for!
Thanks guys! I will try it out!
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Christian Pfisterer -
Well my external function now appears but when I try using it with my test client I get the following error

SoapFault Object
(
[message:protected] => Function ("moodle_enrol_set_manual_enrol") is not a valid method for this service
...

When I check the web service documentation everything is correct. Do I need to register the external function for soap????
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Jérôme Mouneyrac -
possible check:
- check if this function is added to the service
- check if the user has access to the service (in the token page, in the service settings page)
In reply to Jérôme Mouneyrac

Re: Problem with adding a new external function

by Christian Pfisterer -
function is added to my service
user has access to the service

It works when I call the function 'moodle_get_users_by_id'
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Christian Pfisterer -
I get the same error message when I try other functions like "moodle_user_create_users"


In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Christian Pfisterer -
Sorry for bothering you so much but now I went back in my test client code to the beginning when at least moodle_user_get_users_by_id did work

Now I am using a token which is not active anymore and was specified for a webservice (TestService) which is no active any more either.

I've deleted this webservice to make sure I did not mess anything up during the setup process.

Can you explain that to me?
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Christian Pfisterer -
After restarting apache everything works. I've read in different forum that zend_soap_server/client caches tokens.

Maybe that was the problem.
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Jérôme Mouneyrac -
From what I read I understand that you deleted your token and your service, or that the "valid until"expired time is expired. But what do you mean by "Can you explain that to me?".

However maybe you don't know, there is an overview to setup web service: Admin > Plugins > Web service > Overview (moodle/admin/settings.php?section=webservicesoverview)

Let me know if anything is unclear, thanks.
In reply to Jérôme Mouneyrac

Re: Problem with adding a new external function

by Christian Pfisterer -
Hi Jerome,

I used this overview to create my first web service and I was able to call 'moodle_user_get_users_by_id' with my soap test client.

Then I added my custom external function and tried calling it with my test client => result: Function (...) is not a valid method for this service

Then I deleted the web service and the token and created a new one, but this time I added both functions from the beginning.

This time I could not even call 'moodle_user_get_users_by_id' with the new token.

I changed my test client code to use the old token again and all the sudden I could at least call 'moodle_user_get_users_by_id' again (even though the token was already deleted in moodle, BUT it was still in the DB)

Anyways I got frustrated and I did shut down my computer. After 2 minutes I turned it on again and of the sudden I could call both functions with the NEW token!?!

What I meant with "Can you explain that to me" is the part that I was able to use a old token even though it was not avlaible in moodle anymore.

Well It is working now. Maybe there was some cache in zend_soap. I don't know.

Again thank you very much for being so patient and kept on helping me. I really appreaciate it! Thanks!
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Jérôme Mouneyrac -
Ah yes, Zend server caches the WSDL. Into /webservice/server.php add this line after the requires:

ini_set("soap.wsdl_cache_enabled", "0");

For the rest, if a deleted token is still working it is a massive security issue and I'll have a look to that, thanks a lot for your report.
In reply to Jérôme Mouneyrac

Re: Problem with adding a new external function

by Jérôme Mouneyrac -
I just tested, if I delete a token, it's well deleted in the DB and any web service call will fail with this token.

I think you probably did something wrong or confusing because if a token is in the DB you will see it in Moodle admin pages. If ever you can reproduce your problem don't hesitate to let me know, thanks.
In reply to Jérôme Mouneyrac

Re: Problem with adding a new external function

by Christian Pfisterer -
I think I was confused or/and did something wrong...too much stuff going on.

Once again thanks for being so patient with confused moodle web service developers wink

In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Jérôme Mouneyrac -
No problem, hopefully Moodle 2.1 will have a wizard to setup the web service in very few clicks, following common use cases. You can vote on this tracker issue MDL-23672
In reply to Jérôme Mouneyrac

Re: Problem with adding a new external function

by Christian Pfisterer -
Hi Jerome,

is there a way to debug the whole process of calling an external function?

My soap test client calls my new external function and no errors appear but it does not enrol a user into a course. I would like to see what is going on on the zend_soap_server side and really see when my external function is called and verify that variables are set properly and so on.

When I try normal debug I can only see the calls of zend_soap_client!

I've tested my code before I implemented it as a external function with a custom script that I run on my dev machine and it works perfect. But when I do the stuff via web service nothing happens?!?
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Christian Pfisterer -
Ok i figured out the problem. It seems like that the wsdl is not setup properly.

When I check my Web Service documentation I can see the parameters but Response is blank.

I've created a new external function which simply takes a parameter and returns it again.

Kind of stupid but I needed to check where/what my errors are.

External function got recognized and I can call it but still my $result is null even though I say return $value at the end?!

/**
* Returns parameter
* @param int $value
* @return int $value
*/
public static function ret_value($value) {
$params = self::validate_parameters(self::ret_value_parameters(), array('value'=>$value));

return $value;
}

/**
* Returns description of method parameters
* @return external_function_parameters
*/
public static function ret_value_returns() {
new external_single_structure(
array(
'value' => new external_value(PARAM_INT, 'Value'),
)
);
}

Is there something wrong with my code?

I just saw that moodle_enrol_get_enrolled_users does not have a response either in the ws documentation even though it returns values?!?
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Christian Pfisterer -
Well...now I am embarassed!!! That happens when you do copy and paste without really checking the code!

a simple RETURN in front of new external_single_structure should make it...cheese I feel like a programmer newby ;)

Now the problem is that my wsdocumentation does not work any longer. I give up for today.

Maybe somebody can help me with this stuff!?Would be nice.

Thanks.
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Jérôme Mouneyrac -
No problem, it was the same error into get_enrolled_users return description. I just fixed it, thanks for noticing. Hopefully you'll find out what's wrong into the ws doc.
In reply to Jérôme Mouneyrac

Re: Problem with adding a new external function

by Christian Pfisterer -
You're welcome...glad I could help fixing a small problem smile
I also fixed my ws doc problem and now my external function does what it is supposed to do!!!!!!
But don't worry...I will come back with other problems big grin. Got a big project I have to realize.
In the end a button will be pressed in a CRM system and the course will be created, new accounts created, users get enroled into the course and activity dates will be adjusted. And everything will be based on web services cool

In reply to Christian Pfisterer

Re: Problem with adding a new external function

by Jérôme Mouneyrac -
Let us know if you have something demo-able, always good to see real web service usage. Good luck.
In reply to Christian Pfisterer

Re: Problem with adding a new external function

by tushar bhatia -

I am Trying to create USER using moodle_user_create_user webservices

but it giving error

faultCode28194976faultStringCalling parameters do not match signature | ERRORCODE:

Please Help

Attaching XML

<?xml version="1.0"?>
<methodCall>
<methodName>moodle_user_create_users</methodName>
<params>
<param>
<value>
<struct>
<member>
<name>username</name>
<value>
<string>abebd089-5555-e311-gh56-00155d01105e</string>
</value>
</member>
<member>
<name>password</name>
<value>
<string>Admine51*</string>
</value>
</member>
<member>
<name>firstname</name>
<value>
<string>Test 1</string>
</value>
</member>
<member>
<name>lastname</name>
<value>
<string>Test 1</string>
</value>
</member>
<member>
<name>email</name>
<value>
<string>testing@mail.com</string>
</value>
</member>
<member>
<name>country</name>
<value>
<string>NZ</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>

 

Please Help

Thanks In Advance