Introduction

This page contains information about the D2L PHP API. Before you install these files, I HIGHLY recommend you install the testing package first. This will provide you with the auth services, and a nice testing framework for when you start using the library.

This library provides you with basic token management (explained below), and a thin wrapper around the raw D2L SOAP calls. Essentially, it:

  • gets a token (or you can get it yourself)
  • accepts data to send
  • wraps it in a nice blanket
  • sends it to the server
  • gets the results
  • throws exceptions if there is a problem
  • and returns a SOAP object if it is successful.

You then have to write code, separate from the library files, to interact with these objects, and make further calls. Take a close read of the examples section to see how this is used.

Not all functions have been coded. The ones that are coded should work provided the correct information is passed to them. If you want to add additional functions to the library, I encourage you to. I only ask that you follow a few rules:

  • Follow the same template for your functions as the existing ones. (You can simply copy/paste an existing function. Change the function name (see below), the parameters, and the only line you should need to change in the function is the $request line)
  • Use the same naming scheme for the functions D2L_{WEB SERVICE CALL NAME} but the first letter of the call name is lower case.
  • Share the code back so that it can be incorporated into the whole library.
Author: Thomas Hawkins (thawkins@mun.ca)
Version: 0.5.0
Functions Coded: 23 of 103 = 22%
Released: Dec. 23, 2010
License: http://creativecommons.org/licenses/by-nc-sa/3.0/

License Information

This code is made available by the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported license. You can learn more about it here: http://creativecommons.org/licenses/by-nc-sa/3.0/

In addition to the license restrictions, I would appreciate if any improvements to this script flowed back to me so that they can be distributed to the rest of the community.

Download

Here is a .zip file containing the scripts.

d2l-php-ws-api.zip 9.8kb

Installation

  1. Make sure your environment meets the requirements.
  2. Make sure you meet the framework D2L requirements. Also read this note on Token Management.
  3. Download and copy the files to a web accessible location. If you installed the testing framework, you should already have a working config file. You can just copy these files on top of those files. The auth.php files are the same in the 1.0.0 / 0.5.0 releases.
    • README.txt
    • API/org.php
    • API/grade.php
    • API/auth.php
    • API/user.php
    • API/config.example.php
    • wsdl/
      • This is an empty folder. I highly recommend you download all of your WSDL/xsd files, and place them in this folder. This should greatly increase speed when accessing the system. These files can be found in your D2L installation: {DRIVE}:\Desire2Learn\instances\{INSTANCE NAME}\D2LWS\Schemas
  4. Review the examples.
  5. If you run into trouble, check the troubleshooting section.

Token Management

I designed the API with the assumption that you will use a single account for your web services transactions. This made authentication token management a bit simpler. I would use a stored user name and password, and generate a new token for every call. This capability is built into the API.

If you want to write an application that will allow your users to use to their own D2L credentials and account permissions, you will have to do some token management yourself. You will need to call the authenticate_old/authenticate function yourself to generate the token, and then pass it to the API function call to get the results.1)

Examples

Enroll a User

Example Problem

You want to create a form where someone can enter the username of a user, and then select one of three courses, and enroll them into the course as a student.

Solution

In order to enroll a user into a course using the D2L API you must know both the internal id of the user, and the internal id of the course. Getting the internal id of the course is pretty easy, it is in the URL in D2L. For the example above, we will assume that you know the ids.

UI Setup

You will have the courses available in a select box. The value of the select boxes would be the ou numbers for the course. Also on this page, you will also have a text box that will accept a username and a submit button named submit with the text Enroll User. This form could then either post to a new page, or post to itself, depending on where you like to put your processing code.

Backend Processing

Whether you post to self, or to a new form, you are going to need to harvest the variables from the form. Lets assume that the $_POST variables are course for the OU of the course, username for the username. In order to do the enrollment in D2L, you will need to do something like this:

I didn't actually test this code, so you may encounter an error here and there. Also, you would want to protect pages that can alter your D2L installation. With either user authentication, or IP restrictions on the web server.

1 |h enrolluser.php
<?php
$d2lapi = '{YOUR PATH TO THE API FILES}';
require_once($d2lapi . 'API/auth.php'); //Automatically includes the config file.
require_once($d2lapi . 'API/user.php');
 
/**
 * Here are some functions to interact with the API.
 * You would likely have these in other files and just
 * include those files here.
 */
/**
 * This function enrolls a user into a course in D2L.
 */
function enrollUserInCourse($ou,$user,$role){
	/*
	 * First, get the course ou number.
	 */
	try{	
		$result = D2L_enrollUser($ou,$user,$role,0,0);
	}
	catch(Exception $e){
		//Something bad happened.  You can process that here.
		return false;
	}
	return true;
}
 
/**
 * Get the student details for a student based on that students username.
 * @param $username string - The student to look up.
 * @return Assoc Array of the user details.
 */
function getD2LUserByUsername($username){
	/*
	 * First, get the course ou number.
	 */
	$userinfo = D2L_getUserByUserName($username,0,0);
 
	if(count($userinfo->User) == 0 ){
		throw new userException('Username not Found.'); 
	}
 
	$userinfo = array('d2lid' => $userinfo->User->UserId->Id, 'username' => $userinfo->User->UserName->_,'studentnumber' => $userinfo->User->OrgDefinedId->_,'firstname' => $userinfo->User->FirstName->_,'lastname' => $userinfo->User->LastName->_);
	return $userinfo;
}
 
/**
 * Now lets process the form.
 */
$roleid = 581; //An example Role ID for a student role.
if(isset($_POST['submit']) && $_POST['submit'] == 'Enroll User'){
	//Lets try and get the userid
	try{
		$user = getD2LUserByUsername($_POST['username']);
	}
	catch(userException $e){
		echo "User: $username not found in D2L<br />\n";
		exit();
	}
	catch(SoapFault $e){
		echo "Cannot Connect to D2L<br />\n";
		debugExceptionPrint($e);
		exit();
	}
 
	$userid = $user['d2lid'];
 
	try{
		$user = enrollUserInCourse($_POST['course'],$userid,$roleid);
	}
	catch(userException $e){
		echo "User: Error enrolling user.<br />\n";
		debugExceptionPrint($e);
		exit();
	}
	catch(SoapFault $e){
		echo "Cannot Connect to D2L<br />\n";
		debugExceptionPrint($e);
		exit();
	}
	echo "Operation Complete";
}
?>

Non-Line Numbered Version:

enrolluser.php | h
<?php
$d2lapi = '{YOUR PATH TO THE API FILES}';
require_once($d2lapi . 'API/auth.php'); //Automatically includes the config file.
require_once($d2lapi . 'API/user.php');
 
/**
 * Here are some functions to interact with the API.
 * You would likely have these in other files and just
 * include those files here.
 */
/**
 * This function enrolls a user into a course in D2L.
 */
function enrollUserInCourse($ou,$user,$role){
	/*
	 * First, get the course ou number.
	 */
	try{	
		$result = D2L_enrollUser($ou,$user,$role,0,0);
	}
	catch(Exception $e){
		//Something bad happened.  You can process that here.
		return false;
	}
	return true;
}
 
/**
 * Get the student details for a student based on that students username.
 * @param $username string - The student to look up.
 * @return Assoc Array of the user details.
 */
function getD2LUserByUsername($username){
	/*
	 * First, get the course ou number.
	 */
	$userinfo = D2L_getUserByUserName($username,0,0);
 
	if(count($userinfo->User) == 0 ){
		throw new userException('Username not Found.'); 
	}
 
	$userinfo = array('d2lid' => $userinfo->User->UserId->Id, 'username' => $userinfo->User->UserName->_,'studentnumber' => $userinfo->User->OrgDefinedId->_,'firstname' => $userinfo->User->FirstName->_,'lastname' => $userinfo->User->LastName->_);
	return $userinfo;
}
 
/**
 * Now lets process the form.
 */
$roleid = 581; //An example Role ID for a student role.
if(isset($_POST['submit']) && $_POST['submit'] == 'Enroll User'){
	//Lets try and get the userid
	try{
		$user = getD2LUserByUsername($_POST['username']);
	}
	catch(userException $e){
		echo "User: $username not found in D2L<br />\n";
		exit();
	}
	catch(SoapFault $e){
		echo "Cannot Connect to D2L<br />\n";
		debugExceptionPrint($e);
		exit();
	}
 
	$userid = $user['d2lid'];
 
	try{
		$user = enrollUserInCourse($_POST['course'],$userid,$roleid);
	}
	catch(userException $e){
		echo "User: Error enrolling user.<br />\n";
		debugExceptionPrint($e);
		exit();
	}
	catch(SoapFault $e){
		echo "Cannot Connect to D2L<br />\n";
		debugExceptionPrint($e);
		exit();
	}
	echo "Operation Complete";
}
?>

Line by Line Explanation

1 - 4: The EnrollUser and GetUserByUserName functions are available in the User Management Service, so we are required to include that, and the auth.php file at the top (auth.php is required for all calls. It also automatically includes the config.php file with your profiles).

14 - 26: Here is an example function that enrolls a user into a course. This is where you have to do all of the heavy lifting. You need to write code that preforms the logic of the application. In this example, we take in the ou number, userid, and role id, and feed that directly into the API function (D2L_enrolUser) for enrolling a user. We throw that in a try/catch block to catch and exceptions and return false. You would likely want to print or log the exceptions, or something here on a production app.

33 - 45: This is an example function that pulls out the user information by username. You pass in the user name, and then the API function is called (D2L_getUserByUserName). In this case, I'm not checking for exceptions. If an exception were encountered it would halt the processing of the program (which you sometimes want, and sometimes won't want. You would normally not catch exceptions until you know what types of exceptions will be thrown by both the API functions, and the SOAP layer in PHP.

Now, after the function is called, I have a check on line 39 which checks to see if there are any properties in the object. If there are not, then it throws a custom user exception. When I wrote this originally, I found that the GetUserByUserName call in D2L would always return something. Even if the user was not found, or searchable, it would return a blank object. This check ensures that the object is not blank, and if it is, throws a custom exception. There are a few places throughout the API where things like this happen. You would normally check for this in your middle layer between your application and the API.

Finally, on line 43, I grab the properties from the object, and assign them to an associative array, and return this array.

50: This sets a role ID. It is required in the EnrollUser call, and in the UI above, I don't have it selectable as all users will be entered as a student. To get these role ids, you can hover your mouse over the role name in the Roles and Permissions tool in D2L. There is probably also an API call that will grab them if you need to do it programmatically.

51: This makes sure the form was posted from the correct place. You could add additional checks here.

53 - 65: Make the call to our function that calls the API. You could make a call directly to the API here, but some times you will want to do additional processing on the results, and that is better handled in a dedicated function. If the user isn't found in D2L, a message is printed. If you got a general SoapFault exception, then for some reason it cannot connect to the D2L server, and the exception is printed.

66: If you get here, then the user information is available and we assign it to a new variable.

68 - 80: Here we try to enroll the user. This is also encased in a try/catch block. These blocks can protect users from exceptions. It would allow you to take action on an exception (like log it or try again later) or to print a friendly message to users that prevents total failure of the program.

81: Print a message saying that we are done. You could redirect to another page, or provide some navigation options.

Alternative Approach

You could choose to not have individual functions that call the D2L API individually. If you have a specialized use, you could write a function like this to replace lines 14-45:

/**
 * This function enrolls a user into a course in D2L.
 */
function enrollUserInCourse($ou,$username,$role){
	$userinfo = D2L_getUserByUserName($username,0,0);
 
	try{	
		$result = D2L_enrollUser($ou,$userinfo['d2lid'],$role,0,0);
	}
	catch(Exception $e){
		//Something bad happened.  You can process that here.
		return false;
	}
	return true;
}

Troubleshooting

1) Eventually I want to add full token management to optimize the API calls, but it is not ready at this time
d2l/webserviceslibrary.txt · Last modified: 2011/01/05 12:22 by cornmaster
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0