I am new to Moodle. I have done creating user by using web service api and that is running successfully. Now I want to create a course same way. I am using 'core_course_create_courses' function to do this. The post body of my request is
$courses=array("courses" =>
array(
0=>array(
"fullname" => $fullname,
"shortname" => $shortname,
"categoryid" => $categoryid,
"idnumber" =>$idnumber,
"summary"=>$summary,
"summaryformat"=>$summaryformat
)
)
);
Whenever I am running this it is giving me response "{\"exception\":\"moodle_exception\",\"errorcode\":\"errorcatcontextnotvalid\",\"message\":\"You cannot execute functions in the category context (category id:101). The context error message was: Invalid parameter value detected\"}".
But the course category 'programming' with id 101 exists in my moodle site. Please help me. Thanks in advance.
I was wrong ,the categoryid is not the id of the category,it is the sequence id of the category.Now if I give 2 ,it works fine.
$token = $this->config->item('id_token');
$domainname = $this->config->item('domainname');
$functionname = 'core_course_create_courses';
$restformat = 'json';
//crear objeto de acuerdo a la estructura para crear Categoría en Moodle
$curso = new stdClass();
$curso->fullname = $data['patron']['nombre'];
$curso->shortname = $data['patron']['nombre']; // Is unique
**$curso->idnumber = $id; // consecutive
$curso->visible = 1;
$curso->categoryid = 6;
$modulos = array($curso);
$params = array('courses' => $modulos);
header('Content-Type: text/plain');
$serverurl = $domainname . '/webservice/rest/server.php' . '?wstoken=' . $token . '&wsfunction=' . $functionname;
require_once(APPPATH . 'libraries/curl.php');
$curl = new curl;
$restformat = ($restformat == 'json') ? '&moodlewsrestformat=' . $restformat : '';
$resp = $curl->post($serverurl . $restformat, $params);
return $resp;
Related
I want to communicate with an installation of Moodle 2.9.
The following sample client is a slight modification of:
https://github.com/moodlehq/sample-ws-clients/blob/master/PHP-REST/client.php
to use Unirest instead of Curl and JSON instead of XML:
$token = 'd1c74d6466daaaaad59b5d99906bfc84';
$domainname = 'http://moodle.example.com';
$functionname = 'core_user_create_users';
// REST RETURNED VALUES FORMAT
$restformat = 'json';
$user1 = new \stdClass();
$user1->username = 'testusername1';
$user1->password = 'testpassword1';
$user1->firstname = 'testfirstname1';
$user1->lastname = 'testlastname1';
$user1->email = 'testemail1#moodle.com';
$user1->auth = 'manual';
$user1->idnumber = 'testidnumber1';
$user1->lang = 'en';
$user1->theme = 'standard';
$user1->timezone = '-12.5';
$user1->mailformat = 0;
$user1->description = 'Hello World!';
$user1->city = 'testcity1';
$user1->country = 'au';
$preferencename1 = 'preference1';
$preferencename2 = 'preference2';
$user1->preferences = array(
array('type' => $preferencename1, 'value' => 'preferencevalue1'),
array('type' => $preferencename2, 'value' => 'preferencevalue2'));
$user2 = new \stdClass();
$user2->username = 'testusername2';
$user2->password = 'testpassword2';
$user2->firstname = 'testfirstname2';
$user2->lastname = 'testlastname2';
$user2->email = 'testemail2#moodle.com';
$user2->timezone = 'Pacific/Port_Moresby';
$users = array($user1, $user2);
$params = array('users' => $users);
/// REST CALL
$serverurl = $domainname . '/webservice/rest/server.php' . '?wstoken=' . $token . '&wsfunction=' . $functionname;
//if rest format == 'xml', then we do not add the param for backward compatibility with Moodle < 2.2
$restformat = ($restformat == 'json') ? '&moodlewsrestformat=' . $restformat : '';
$headers = array('Accept' => 'application/json');
$response = UnirestRequest::post($serverurl . $restformat, $headers, json_encode($params));
On execution I got an error:
"Notice: Array to string conversion"
, allegedly because of the parameters going in the body. So, I figured I had to serialize the body before sending it, but when I tried:
$response = UnirestRequest::post($serverurl . $restformat, $headers, json_encode($params));
I got back from Moodle:
{"exception":"invalid_parameter_exception","errorcode":"invalidparameter","message":"Detectado
valor de par\u00e1metro no v\u00e1lido","debuginfo":"Missing required
key in single structure: users"} ◀"
There must be something I'm not understanding about how exactly the POST request must look like. Any suggestion?
Moodle expects the body of the post to be URL encoded, so your body must be built
using http_build_query($params) (or any other method to encode your data) such as:
$convertedpostdata = implode('&', $params);//where $params is an array
As far as why, I dont really recall, I remember struggling with an implementation a while ago, you can view
[your_moodle_installation.com]/admin/webservice/documentation.php for more documentation, additionally you here's an example of what I did:
https://gist.github.com/Scott972/5d9e9495c1397a2ad728b66288ce1d42
I'm trying to add new users to moodle 3.2 using a REST web service, and i want to customize thees fields (phone1, department, institution) in the student profile.
I used this code
$token = 'a38805c00f33023f7854d5adc720c7a7';
$domainname = 'http://localhost/moodle';
$functionname = 'core_user_create_users';
$restformat = 'json';
$user2 = new stdClass();
$user2->username = strtolower( $rsnew['Serial']);
$user2->password = $rsnew['pass'];
$user2->firstname = $rsnew['Fname'];
$user2->lastname = $rsnew['Lname'];
$user2->email = $rsnew['Email'];
$user2->lang = 'en';
$user2->auth = 'manual';
$user2->country = $rsnew['Country'];
$user2->timezone = '99';
$user2->phone1 = $rsnew['phone'];
$user2->department = $rsnew['dept'];
$user2->institution = $rsnew['branch'];
$user2->idnumber = $rsnew['grade'];
$users = array($user2);
$params = array('users' => $users);
$serverurl = $domainname . '/webservice/rest/server.php'. '?wstoken=' . $token . '&wsfunction='.$functionname;
require_once('./curl.php');
$curl = new curl;
$restformat = ($restformat == 'json')?'&moodlewsrestformat=' . $restformat:'';
$resp = $curl->post($serverurl . $restformat, $params);
But i get this error :
{
"exception": "invalid_parameter_exception",
"errorcode": "invalidparameter",
"message": "Invalid parameter value detected",
"debuginfo": "users => Invalid parameter value detected: Unexpected keys (phone1, department, institution) detected in parameter array."
}
What should I do to fix that?
Just as the error suggests, that web service does not support the fields you are giving it. You can refer to the function itself to find out what fields are supported and what data they must contain.
core_user_get_users
I am not aware of a workaround for your problem using existing web services. However, you can create your own which includes those additional fields.
Note that this sounds to me like this is a desirable feature and should be raised on the issue tracker.
I'm implementing a moodle web service on localhost.
I followed all the steps to register the service, and I have the token to make the corresponding calls.
I have used the template for REST PHP by Jerome Mouneyrac (https://github.com/moodlehq/sample-ws-clients/blob/master/PHP-REST/client.php).
My code:
$token = '60d4aef82f787b7a0c8499a648a6a919';
$domainname = 'http://localhost/moodle';
$functionname = 'core_user_create_users';
$restformat = 'json';
$user1 = new stdClass();
$user1->username = 'testo';
$user1->password = 'Password_2015';
$user1->createpassword = 0;
$user1->firstname = 'testfirstname1';
$user1->lastname = 'testlastname1';
$user1->email = 'muletssss#gmail.com';
$user1->auth = 'manual';
$user1->idnumber = '';//'testidnumber1';
$user1->lang = 'es';
$user1->theme = "standard";
$user1->timezone = '-12.5';
$user1->mailformat = 0;
$user1->description = 'Hello World!';
$user1->city = 'testcity1';
$user1->country = 'au';
$users = array($user1);//, $user2);
$params = array('users' => $users);
$serverurl = $domainname . '/webservice/rest/server.php'. '?wstoken=' . $token . '&wsfunction='.$functionname;
require_once('./curl.php');
$curl = new curl;
$restformat = ($restformat == 'json')?'&moodlewsrestformat=' . $restformat:'';
$resp = $curl->post($serverurl . $restformat, $params);
print_r($resp);
If I execute it returns this response
{"exception":"invalid_parameter_exception","errorcode":"invalidparameter","message":"Detectado valor de par\u00e1metro no v\u00e1lido","debuginfo":"users => Detectado valor de par\u00e1metro no v\u00e1lido: theme => Detectado valor de par\u00e1metro no v\u00e1lido: Invalid external api parameter: the value is \"standard\", the server was expecting \"theme\" type"}
The API documentation says that the value is string and standard default, so I comment this line because it is optional. And returns
{"exception":"moodle_exception","errorcode":"forcepasswordchangenotice","message":"error\/forcepasswordchangenotice"}
Does anyone know what I can do to work correctly, any solution?
I was facing a similar issue, I have solved it. The issue was that the user that I was using for the web services had force password reset checked while creation. I had not logged in once the user was created and was only using it for the Webservice. Hence I was this error was showing up. I unchecked force password reset from my admin account and it was solved.
I'm trying to create a embedded envelope based on a template. The problem I am having is that in the created envelope the tabs I have created are missing.
I searched around and found the role assignment and used that and still no luck. When I look at the XML the role is the same as the template as well as the routing order and ID.
I tried setting the template so that I can't delete any recipients and I get the error:
Uncaught SoapFault exception: [soap:Client] Required recipient in the template has not been provided. Recipient not satisfied for role, Signer, in template Test Form
Here is my PHP to create and send the envelope, a lot of this is code used from the documentation:
// Get the recipient from a post
$rcp1 = new Recipient(); // First recipient to put in recipient array
$rcp1->UserName = $_POST['Name'];
$rcp1->Email = $_POST['Email'];
$rcp1->Type = RecipientTypeCode::Signer;
$rcp1->ID = "1";
$rcp1->RoutingOrder = 1;
$rcp1->CaptiveInfo = new RecipientCaptiveInfo();
$rcp1->CaptiveInfo->ClientUserId = 1;
$rcp1->RoleName = "Signer";
$rcp1->RequireIDLookup = FALSE;
// Create Role Assignments
$assign = new TemplateReferenceRoleAssignment();
$assign->RecipientID = $rcp1->ID;
$assign->RoleName = $rcp1->RoleName;
// Use a server-side template
$templateRef = new TemplateReference();
$templateRef->TemplateLocation = TemplateLocationCode::Server;
$templateRef->RoleAssignments = $assign;
$templateRef->Template = "****";
// Construct the envelope info
$envInfo = new EnvelopeInformation();
$envInfo->AccountId = $AccountID;
$envInfo->Subject = "This is the Subject";
$envInfo->EmailBlurb = "I have no Idea What a blurb is";
// Send creates draft with all the template info
$createEnvelopeFromTemplatesparams = new CreateEnvelopeFromTemplates();
$createEnvelopeFromTemplatesparams->TemplateReferences = array($templateRef);
$createEnvelopeFromTemplatesparams->Recipients = array($rcp1);
$createEnvelopeFromTemplatesparams->EnvelopeInformation = $envInfo;
$createEnvelopeFromTemplatesparams->ActivateEnvelope = true;
$env = $api->CreateEnvelopeFromTemplates($createEnvelopeFromTemplatesparams);
$envStatus = $env->CreateEnvelopeFromTemplatesResult;
// Construct the recipient token authentication assertion and specify
// ID, start time, method, and domain
$assertion = new RequestRecipientTokenAuthenticationAssertion();
$assertion->AssertionID = guid();
$assertion->AuthenticationInstant = nowXsdDate();
$assertion->AuthenticationMethod = RequestRecipientTokenAuthenticationAssertionAuthenticationMethod::Password;
$assertion->SecurityDomain = "Request Recipient Token Test";
// Construct the URLs based on UserName
$recip = $envStatus->RecipientStatuses->RecipientStatus[0];
$urls = new RequestRecipientTokenClientURLs();
$urlbase = getCallbackURL('pop.php');
$urls->OnSigningComplete = $urlbase . "?event=SignComplete&uname=" . $recip->UserName;
$urls->OnViewingComplete = $urlbase . "?event=ViewComplete&uname=" . $recip->UserName;
$urls->OnCancel = $urlbase . "?event=Cancel&uname=" . $recip->UserName;
$urls->OnDecline = $urlbase . "?event=Decline&uname=" . $recip->UserName;
$urls->OnSessionTimeout = $urlbase . "?event=Timeout&uname=" . $recip->UserName;
$urls->OnTTLExpired = $urlbase . "?event=TTLExpired&uname=" . $recip->UserName;
$urls->OnIdCheckFailed = $urlbase . "?event=IDCheck&uname=" . $recip->UserName;
$urls->OnAccessCodeFailed = $urlbase . "?event=AccesssCode&uname=" . $recip->UserName;
$urls->OnException = $urlbase . "?event=Exception&uname=" . $recip->UserName;
// Send
$requestRecipientTokenparams = new RequestRecipientToken();
$requestRecipientTokenparams->EnvelopeID = $envStatus->EnvelopeID;
$requestRecipientTokenparams->ClientUserID = $recip->ClientUserId;
$requestRecipientTokenparams->Username = $recip->UserName;
$requestRecipientTokenparams->Email = $recip->Email;
$requestRecipientTokenparams->AuthenticationAssertion = $assertion;
$requestRecipientTokenparams->ClientURLs = $urls;
$response = $api->RequestRecipientToken($requestRecipientTokenparams);
$tokenUrl = $response->RequestRecipientTokenResult;
echo '<iframe src="' . $tokenUrl . '" width="100%" height="720px"></iframe>';
This is the recipient info that is returned when I RequestTemplate():
[0] => Recipient Object
(
[ID] => 1
[UserName] =>
[SignerName] =>
[Email] =>
[Type] => Signer
[AccessCode] =>
[AddAccessCodeToEmail] =>
[RequireIDLookup] =>
[IDCheckConfigurationName] =>
[PhoneAuthentication] =>
[SignatureInfo] =>
[CaptiveInfo] =>
[CustomFields] =>
[RoutingOrder] => 1
[IDCheckInformationInput] =>
[AutoNavigation] =>
[RecipientAttachment] =>
[Note] =>
[RoleName] => Signer
[TemplateLocked] =>
[TemplateRequired] => 1
[TemplateAccessCodeRequired] =>
[DefaultRecipient] =>
[SignInEachLocation] =>
)
This might be due to you instatiating the templateRoleAssignments as an object and not an array. Since you're using the SOAP api and not REST have you seen the DocuSign SOAP SDK up on Github? That has sample code and projects for 5 different environments including PHP (PHP, Java, C#, Ruby, and Salesforce):
https://github.com/docusign/DocuSign-eSignature-SDK
Looking at a function defined in the PHP project I see the following:
function createFinalRoleAssignments($recipients) {
$roleAssignments[] = new TemplateReferenceRoleAssignment();
foreach ($recipients as $r) {
$assign = new TemplateReferenceRoleAssignment();
$assign->RecipientID = $r->ID;
$assign->RoleName = $r->RoleName;
array_push($roleAssignments, $assign);
}
// eliminate 0th element
array_shift($roleAssignments);
return $roleAssignments;
}
Notice how $roleAssignments is declared as an array using square brackets [], I have a strong feeling that is causing your error. Try defining your roleAssignments the same way and that will probably work.
I spent my last 5 hours in this issue and finally I came here for the solution.
I am doing log-in using twitter functionality in my site (Zend Framework + PHP) and everything is working fine. But I am facing the following issue in it:
If the user has no tweets (0 tweets) in his account then the
$tweets = json_decode($response->getBody());
echo "<pre>";
print_r($tweets);
exit;
Its showing me blank array. i.e. : Array(); :-(
And if I am adding some tweets there in twitter account then its showing me the complete array along with user information like display name, image, etc...like this:
Array
(
//other data
[0] => stdClass Object
(
[user] => stdClass Object
....
....
so on..
)
)
Following is my code :
public function twitterregisterAction() {
$path = realpath(APPLICATION_PATH . '/../library/');
set_include_path($path);
session_start();
require $path . "/Zend/Oauth/Consumer.php";
$config = array(
"callbackUrl" => "http://" . $_SERVER['HTTP_HOST'] . "/register/twittercallback",
"siteUrl" => "http://twitter.com/oauth",
"consumerKey" => "xxxxxxxxxxxxx",
"consumerSecret" => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
);
$consumer = new Zend_Oauth_Consumer($config);
// fetch a request token
$token = $consumer->getRequestToken();
// persist the token to storage
$_SESSION["TWITTER_REQUEST_TOKEN"] = serialize($token);
// redirect the user
$consumer->redirect();
}
/*
* Ticket id #16
* twittercallbackAction method
*/
public function twittercallbackAction() {
$config = array(
"callbackUrl" => "http://" . $_SERVER['HTTP_HOST'] . "/register/twittercallback",
"siteUrl" => "http://twitter.com/oauth",
"consumerKey" => "xxxxxxxxxxxxxxxxxx",
"consumerSecret" => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
);
$consumer = new Zend_Oauth_Consumer($config);
if (!$this->_getParam("denied")) {
if (!empty($_GET) && isset($_SESSION['TWITTER_REQUEST_TOKEN'])) {
$token = $consumer->getAccessToken($_GET, unserialize($_SESSION['TWITTER_REQUEST_TOKEN']));
} else {
// Mistaken request? Some malfeasant trying something?
exit('Invalid callback request. Oops. Sorry.');
}
// save token to file
// file_put_contents('token.txt', serialize($token));
$client = $token->getHttpClient($config);
$client->setUri('https://api.twitter.com/1/statuses/user_timeline.json?');
$client->setMethod(Zend_Http_Client::GET);
$client->setParameterGet('name');
$client->setParameterGet('profile_image_url');
$response = $client->request();
$tweets = json_decode($response->getBody());
$session = new Zend_Session_Namespace("userIdentity");
Zend_Session::rememberMe(63072000); //2years
$session->tw_id = $tweets[0]->user->id;
$session->tw_name = $tweets[0]->user->name;
$session->tw_image = $tweets[0]->user->profile_image_url;
if ($session->tw_id != "") {
$tw_id = $session->tw_id;
//Calling the function twitterAuthAction for email authentication
$twAuthArr = $this->twitterAuthAction($tw_id);
if ($twAuthArr['socialId'] == $tw_id) {
$session->userId = $twAuthArr['id'];
$session->email = $twAuthArr['emailId'];
$this->_redirect('/profile/showprofile');
} else {
$user = new UserRegistration();
$firstname = "";
$lastname = "";
$password = "";
$socialtype = "twitter";
$email = "";
$socialid = $session->tw_id;
$result = $user->registerUser($firstname, $lastname, $socialid, $socialtype, $email, $password);
$session->userId = $result;
$this->_redirect('/register');
}
}
$this->_redirect("/register");
} else {
$this->_redirect("/register");
}
}
My Questions are :
1) Why its not providing user array if there is no any tweet in my twitter account (or newly created twitter account)
2) I want user profile details from twitter account. How can I get it?
Need Help. Thanks
I think as per david's answer you need to use users/show url there instead of using statuses/user_timeline. You can use curl for requesting url so you'll get the response which contains the users information.
Try with following code:
$user_id = $client->getToken()->getParam('user_id');
$trends_url = "http://api.twitter.com/1/users/show.json?user_id=".$user_id;
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $trends_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$curlout = curl_exec($ch);
curl_close($ch);
$response = json_decode($curlout, true);
$session = new Zend_Session_Namespace("userIdentity");
Zend_Session::rememberMe(63072000); //2years
$session->tw_id = $response['id'];
$session->tw_name = $response['name'];
$session->tw_image = $response['profile_image_url'];
Try this. Hope it will help you.
I think you are misreading the Twitter API docs for the statuses/user_timeline endpoint.
The field user that you identify is one of the fields within a returned tweet. If the user id to which you point has no tweets, then there will be no entries in the returned array, hence no user field.
If you need the user information even in the absence of any tweets, then you probably need to hit the users/show endpoint.