PHP Brightspace Developer Helper Package v0.1.0b

Introduction

About This Package

This package is currently a preview release. The first official release is expected in January. After the first official release, breaking changes will be avoided whenever possible, with the exception being breaking changes as a result of changes in the Valence API itself. However, as last minute details are worked out, there may be changes to this preview release that may cause code you create with this to be changed. It is being offered for experimental purposes at this time.

This open-source package was built to make it easier to use the API (Valence) and data exports (Data Hub) of D2L Brightspace.

This package is written in PHP. If you do not use PHP, while the packages themselves may not be of direct use to you in your applications, it may inspire you to port them over to the language of your choice.

You'll find that the documentation of this package is sparse, which is intentional. The primary functionality for this package is to use with an IDE, like PhpStorm, which offers completion for using classes, functions, fields, etc.

Want to enroll a user in a course with Valence? Just type $valenceobjectname->enroll and check the autocompletes for the function that contains action you're looking for. The idea is that you will not need to dig through documentation, or memorize all the API routes and fields. You'll use autocomplete to do it for you.

If you do not use an IDE with class-awareness and autocompletion, this package problem won't help you very much. In fact, it will probably increase the amount of time it takes to develop applications with the API as it just adds another layer of documentation you need to read.

Want to access information from the Data Hub? Just type the name of the report you want to retrieve data from (which should autocomplete for you) and access information using the Eloquent ORM.

Features

  • Query the Data Hub using the auto-complete feature, chaining methods to find what you're looking for.
  • Join Data Hub reports using methods.
  • Leverage the Valence API using your IDE's autocomplete features, both to find the appropriate API calls and access the returned object's fields.
  • Work directly in your timezone, letting the Valence class convert the times returned from API calls in GMT to your LMS's or custom time zone, and convert them back to GMT automatically when making a POST or PUT request, all while using a more friendly format.
  • Use virtual PATCH objects, allowing you to specify the object you want to modify and specify only the fields you want to change, without needing to rebuild the entire data object to send with a PUT.
  • Use the Data Hub as a backdrop for retrieving data, allowing you to specify specific reports to utilize or a certain threshold for how long a course must be completed to use the Data Hub, while returning the data in the same format as the API call, no longer requiring you to use two different sets of code depending upon which source you use.

Future Possible Features

  • More API calls added
  • More documentation, both written and inline
  • More helper functions for specific processes
  • More object-specific classes
  • More report relationships
  • Built-in support to process full and differential reports into a local database
  • Helper functions to use additional features of Eloquent
  • Ability to process monthly changes to the Data Hub

Note that there are some areas of the API that will not be included. For example, Wilkes University does not have the Learning Object Repository or ePortfolio addons, so they will not be included. However, if you review the source code and the documentation below, you will find that you can extend this class to add functions of your own to the API calls not included as needed.

Presentations

See the presentation below from the D2L Site Administrator Network Connection Event from May 2021:

Setup

Requirements

This class requires you to use PHP 8.1 or later to fully utilize the type hinting options available. It also requires composer. To utilize functionality of the Data Hub, you must have a database setup with each table named after a report and each field in the table named after the corresponding column of the report.

Install the Package

Install the package from composer using the command:

composer require jason-wagner/brightspace-dev-helper:dev-main

This will install the package, as well as all dependencies, including guzzlehttp/guzzle, nesbot/carbon, vlucas/phpdotenv, illuminate/database, and phpleague/csv.

Generate App and User IDs and Keys

You will need to create an API App ID and key. While this package does support user authentication, you may also need to create a service account, and capture that account's USER ID and key as well. You can find the directions to use generate these through this community post.

Create the .env File

The .env file contains information about your D2L environment and database where the Data Hub reports have been loaded, and is loaded into $_ENV each time you run a script using this helper class.

Use the following to get started with your .env file.

D2L_VALENCE_HOST=
D2L_VALENCE_PORT=
D2L_VALENCE_SCHEME=
D2L_VALENCE_APP_ID=
D2L_VALENCE_APP_KEY=
D2L_VALENCE_USER_ID=
D2L_VALENCE_USER_KEY=

DB_DRIVER=
DB_HOST=
DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
DB_CHARSET=
DB_COLLATION=
DB_PREFIX=

For the configuration, it is recommended that you set the charset to utf and the collation to utf8_unicode_ci. The prefix should be set to be blank, but it is required by the constructor of the database connection class. It may be utilized if additional functionality to support it is added in the future.

Create the init.php File

Finally, create an init.php file which will be included in all files you create that use this package. This will automatically include all composer packages, initialize the environment variables and create a database connection.

<?php

require_once __DIR__.'/vendor/autoload.php';

use Illuminate\Database\Capsule\Manager as Capsule;
use BrightspaceDevHelper\Valence\Object\BrightspaceConfig;

$dotenv = Dotenv\Dotenv::createImmutable(__DIR__)->load();

$valence_config = new BrightspaceConfig($_ENV['D2L_VALENCE_HOST'], $_ENV['D2L_VALENCE_PORT'], $_ENV['D2L_VALENCE_SCHEME'], $_ENV['D2L_VALENCE_APP_ID'], $_ENV['D2L_VALENCE_APP_KEY'], $_ENV['D2L_VALENCE_USER_ID'], $_ENV['D2L_VALENCE_USER_KEY']);

$capsule = new Capsule;

$capsule->addConnection([
    'driver'    => $_ENV['DB_DRIVER'],
    'host'      => $_ENV['DB_HOST'],
    'database'  => $_ENV['DB_DATABASE'],
    'username'  => $_ENV['DB_USERNAME'],
    'password'  => $_ENV['DB_PASSWORD'],
    'charset'   => $_ENV['DB_CHARSET'],
    'collation' => $_ENV['DB_COLLATION'],
    'prefix'    => $_ENV['DB_PREFIX'],
]);

$capsule->setAsGlobal();
$capsule->bootEloquent();

If you will not be using this to connect to a database utilizing the Data Hub, remove the lines related to the Capsule above.

Using the Package

Basic Examples

Making Valence Requests

First, you will need to create a new Valence Client object:

$valenceObject = new Valence($valence_config);

Then, you just need to find the calls you want to use. Suppose you want to enroll John Smith (UserId 12345) into the ENG 101 A (OrgUnitId 67890) as a student (RoleId 246). Then you can use:

$response = $valenceObject->enrollUser(67890, 12345, 246);

The response is an object in which each of the returned items is an attribute. For example, if the returned item has a field that is returned called Identifer, you would access it with $response->Identifier.

There are also "IDer functions" which allow you to easily retrieve the IDs of items that have easily queriable codes, like Users and OrgUnits.

For example, suppose in the exam above, John Smith's username is jsmith12 and the course has an offering code of 13579.202101. We can use the IDer functions to find these IDs.

$userId = $valenceObject->getUserIdFromUsername('jsmith12');
$orgUnitId = $valenceObject->getOrgUnitIdFromOfferingCode('13579.202101');
$response = $valenceObject->enrollUser($orgUnitId, $userId, 246);

If a function does not exist for the API call you want to use, you can use the apirequest($route, $method = 'GET', $data = null) function to make the call. $data is an array with the field names provided as keys.

For example, suppose the whoami function did not exist in this class:

$response = $valenceObject->apirequest("/d2l/api/lp/".Valence::VERSION_LP."/users/whoami");

Note the use of the constant Valence::VERSION_LP to get the current version of the learning platform supported by the class.

Querying the Data Hub

For the Data Hub, this package uses the Eloquent ORM to define relationships to the tables. Once relationships are defined, you can simply call methods on the classes named after what you're attempting to join. Looking for John Doe's assignment submissions?

$user = User::whereUserName('john.doe');

foreach($user->assignmentsubmissions()->get() as $submission)
    echo implode("\t", [$user->FirstName, $user->LastName, $submission->assignmentsummary->orgunit->Name, $submission->assignmentsummary->Name, $submission->LastSubmissionDate, $submission->Score, $submission->assignmentsummary->PossibleScore]) . "\n";

This creates a tab-delimited table with the student's first name, last name, name of the course the assignment is in, name of the assignment, timestamp of the submission, score, and number of points possible.

But what does all of this mean?

First, we find the user with the username John Doe. Normally, we would use User::find($UserId), but since we probably don't know $UserId, a helper function was created to easily find the user by username instead. We can also use other functions of Eloquent to find what we're looking for, such as User::where('Email', 'john.doe@school.edu') or User::where('FirstName', 'John')->where('LastName', 'Doe'). Then, since the Data Hub has a relationship between the Users table and AssignmentSubmissions table (through UserId), a relationship is defined on the User class in a method called assignmentsubmissions. We call that method, then get(), and loop through the results.

Within the results, you can see that there are a few instances where we call assignmentsummary on the $submission object. As we did above, we also defined a relationship on the AssignmentSubmissions and AssignmentSummary tables to join the information. We did this again when we call orgunit to get the name of the course it is in, defining a relationship between AssignmentSummary and OrganizationalUnits.

For other examples. you will first need to come up with a starting point, with a query on one of the objects in the database.

Then, functions were created for the relationships on each object, in both directions.

The syntax of the call for the relationship depends upon the type of relationship.

For example, consider the relationship between an OrganizationalUnit and a QuizObject.

This is a one-to-many relationship: each OrganizationalUnit can have many QuizObjects, but each QuizObject belongs to only one OrganizationalUnit.

When something has many, we call it as a function, followed by get(). In this case, to get the QuizObjects of the OrganizationalUnit with OrgUnitId 123456, we would use the following code:

$orgObject = OrganizationalUnit::find(12345);

foreach($orgObject->quizobjects()->get() as $quizobject)
	// loop through each quiz in $quizobject, such as $quizobject's name in $quizobject->Name

However, when something belongs to, we call it as an attribute. In this case, to get the OrganizationalUnit that the QuizObject with a QuizId of 24680, we would use the following code:

$quizObject = QuizObject::find(24680);
$orgObject = $quizObject->orgunit; // record for the org unit is in $orgObject, such as $orgObject's offering code in $orgObject->Code

In a many-to-many relationship (such as the relationship between Users and OrganizationalUnits, which goes through UserEnrollments), you always use functions. In a one-to-one relationship (such as the relationship between OrganizationalUnits and GradebookSettings), you always use attributes.

Options

Logging

The setLogging($mode, $filename) function allows you to automatically log each API call that is requested.

If $mode is 0, nothing is logged; if $mode is 1, only API calls that change data (anything besides a GET) is logged; if $mode is 2, all calls, including GETs, are logged.

If $filename is provided, the logs will be saved to a file in that path. If $filename is not provided, it will automatically be saved in that directory in a file called valence.log in the current directory.

Logging is disabled by default.

Error Handling

The setExitOnError($option) function tells whether the class should exit if there is an HTTP error is encountered, or allow the script to continue.

exitOnError is enabled by default. To disable it:

$valenceObject->setExitOnError(false);

However, if you disable it, be sure to check the HTTP status code after each call to ensure the API calls have been successful.

To re-enable it, set it to true.

Return Object on Create

The setReturnObjectOnCreate($option) function tells whether the class should return a User or Course client object when one of these entities is created with the Valence class using createCourseOffering or createUser. If it is set to false, it will return the default object, which is the default setting. However, to use it:

$valenceObject->setReturnObjectOnCreate(true);
$newCourseObject = $valenceObject->createCourseOffering(...);
print_r($newCourseObject->get()); // displays course information
$userid = $valence->getUserIdFromUsername('jsmith12');
$response = $newCourseObject->enrollInstructor($userid); // enroll John Smith in the course

Alternatively, if it were not enabled:

$valenceObject->setReturnObjectOnCreate(false); // not necessary unless it was previously enabled
$newCourseResponse = $valenceObject->createCourseOffering(...);
print_r($newCourseResponse); // displays course information
$userid = $valence->getUserIdFromUsername('jsmith12');
$newCourseObject = $valence->course($newCourseResponse->Identifier); // to get object, must use OrgUnitId from response on creation
$response = $newCourseObject->enrollInstructor($userid); // enroll John Smith in the course

Set Class Clients

There are functions, setUserClass and setCourseClass, that allow you to set which class should be used to create User and Course clients if you choose to extend them to add more customized functions. See the section below on Extending Clients.

Create Objects

To use create objects, use the constructor to create the object you want to create. When you're created it, you can simply call the create().

$newCourse = $valence->newCreateCourseOfferingObject(/* arguments here */);
$newCourse->create();

This will make the appropriate API call. Alternatively, you can manually call the method for the API call and pass the object as a parameter.

$newCourse = $valence->newCreateCourseOfferingObject(/* arguments here */);
$valence->createCourseOffering($newCourse);

Update Objects

To use update objecrts, they work similarly to create objects except you'll call the update() method when finished.

$updateCourse = $valence->newCourseOfferingInfoObject(/* arguments here */);
$updateCourse->update();

Like above, you can also create an update object and pass it as an argument to the method for teh API call.

$updateCourse = $valence->newCourseOfferingInfoObject(/* arguments here */);
$valence->updateCourseOffering($updateCourse);

Patch Objects

Patch Objects allow you to update an entity while specifying only the fields you want to change and automatically carrying over existing items by at GET request in the background.

For example, suppose you want to activate the course with the OrgId 123456.

$patchObject = $valence->newCourseOfferingInfoPatchObject(123456);
$patchObject->setIsActive(true);
$patchObject->update();

Note that there is a method, setXXXXX($value) method for every property of the block.

Array Block Objects

Array Blocks allow you to iterate through an array of results of a given object.

Support you want to iterate all the topics in ForumId 7890 of OrgUnit 123456:

$topics = $valence->getDiscussionTopics(123456, 7890);

foreach($topics as $topic)
    // use $topic->TopicId, $topic->Name, etc.

For results that are paginated, this will automatically grab the next page of results and continue through the loop. There is no need to manually maek another API call.

Extending Clients

In the event that you need to make custom classes, you can extend any of the clients and include them in your application. This may be to add additional functions that are not supported, or to customize functions for your instance or institution.

For example, at Wilkes University, all course offering codes follow the format crn.termcode from Banner. Thus, I may create a helper function by doing the following:

class MyValance extends Valence {
    public function findIdFromCrn(int $termcode, int $crn) {
        return $this->getOrgUnitIdFromOfferingCode($crn . "." . $termcode):
    }
}

If you override any class besides the main Valence class, you should set the Valence object to utilize that new class.

For example, if you extend the ValenceCourse class:

class MyValanceCourse extends ValenceCourse {
    ...
}

Then, to tell the course object generator in the Valence class to use this when you make a new course object, use the following:

$valenceObject->setCourseClass(MyValenceCourse::class);

Using Eloquent

To do more advanced querying of the database, you should use Laravel's Eloquent ORM. Each of the reports from the Data Hub was created in this package as an Eloquent model. To learn more about what you can do with Eloquent, check out Laravel's documentation.

If you do not use an IDE with class-awareness and autocompletion, this package problem won't help you very much. In fact, it will probably increase the amount of time it takes to develop applications with the API as it just adds another layer of documentation you need to read.

There are some more advanced features of Eloquent that use relationships that you may attempt to use, but may encounter errors if you attempt to use them. This is because many of Eloquent's features rely on default settings with a database created with specific naming conventions that are not utilized by the Data Hub. All the tables in the Data Hub are named exactly as the name of the respective report with spaces removed, while the fields in the table are named exactly as the name of the respective column in the report.

For example, under Laravel's naming conventions, all tables are to be named, in lowercase, of the plural of the object, with a primary key of id, and when used as a foreign key, is to take on the name singularoftablename_id. However, in Data Hub, the tables utilize "uppercase words" casing, and the primary key is TablenameId.

For the majority of Laravel's operations, the default behavior is also to assume there is a single field as a primary key; however, the Data Hub does have several tables which have a composite key.

You can still use many of this additional functionality of Eloquent; however, you may need to dig into the documentation further to find the additional fields that you need to provide to the different functions.

Function Reference

Valence Functions

Valence Client

Options Functions

getDatahubSearch(string $report): int
getTimezone(): string
getTimezoneConvert(): bool
setCopyStatusDelay(int $seconds): void
setCourseClass($courseclass): void
setDatahubDayThreshold(int $days): void
setDatahubSearch(string $report, int $mode): void
setExitOnError(bool $exitonerror): void
setInternalIds(): void
setLogging(int $logMode, ?string $logFile = null): void
setReturnObjectOnCreate(bool $returnobject): void
setRoleNameForInstructor(string $role): void
setRoleNameForStudent(string $role): void
setTimezone(string $timezone): void
setTimezoneConversion(bool $timezoneConversion): void
setUserClass($userclass): void

Client Helper Functions

__construct(BrightspanceConfig $config)
apirequest(string $route, string $method = 'GET', ?array $data = null): ?array
apirequestfile(string $route, string $filepath)
apisendfile(string $route, string $method, string $filepath, string $field, string $name)
checkOrgUnitDatahub(int $orgUnitId): bool
createDateTimeFromIso8601($datetime): DateTime
createDateTimeFromTimestamp($datetime): DateTime
createFromComponents(int $year, int $month, int $day, int $hour, int $minute, int $second): DateTime
isValidResponseCode(): bool
logrequest(string $route, string $method, ?array $data = null): void
responseCode(): ?int
responseError(): ?string

Authentication Functions

getAuthUrl(string $appUrl): string
getUserCredentials(): ?UserIdKeyPair

Object Generator Functions

newCourseObject(int $orgid): ValenceCourse
newUserObject(int $userid): ValenceUser

Create/Patch Object Functions

newCourseOfferingInfoObject(int $orgUnitId, string $Name, string $Code, bool $IsActive, ?string $StartDate, ?string $EndDate, RichTextInput $Description, bool $CanSelfRegister): CourseOfferingInfo
newCourseOfferingInfoPatchObject(int $orgUnitId): CourseOfferingInfoPatch
newCreateCopyJobRequest(int $SourceOrgUnitId, COPYCOMPONENT|array|null $Components, ?string $CallbackUrl, ?int $DaysToOffsetDates, ?float $HoursToOffsetDates, ?bool $OffsetByStartDate): CreateCopyJobRequest
newCreateCourseOfferingObject(string $Name, string $Code, ?string $Path, int $CourseTemplateId, ?int $SemesterId, DateTime|string|null $StartDate, DateTime|string|null $EndDate, ?int $LocaleId, bool $ForceLocale, bool $ShowAddressBook, RichTextInput $Description, ?bool $CanSelfRegister): CreateCourseOffering
newCreateEnrollmentDataObject(int $OrgUnitId, int $UserId, int $RoleId): CreateEnrollmentData
newGroupCategoryDataCreate(int $orgUnitId, string $Name, RichTextInput $Description, GRPENROLL $EnrollmentStyle, ?int $EnrollmentQuantity, bool $AutoEnroll, bool $RandomizeEnrollments, ?int $NumberOfGroups, ?int $MaxUsersPerGroup, bool $AllocateAfterExpiry, ?string $SelfEnrollmentExpiryDate, ?string $GroupPrefix, ?int $RestrictedByOrgUnitId): ?GroupCategoryDataCreate
newGroupDataCreate(int $orgUnitId, int $groupCategoryId, string $Name, string $Code, RichTextInput $Description): ?GroupDataCreate
newGroupEnrollmentObject(int $orgUnitId, int $groupCategoryId, int $groupId, int $UserId): GroupEnrollment
newNewsItemDataObject(int $orgUnitId, string $Title, RichText $Body, DateTime|string $StartDate, DateTime|string|null $EndDate, bool $IsGlobal, bool $IsPublished, bool $ShowOnlyInCourseOfferings, bool $IsAuthorInfoShown): NewsItemData
newNewsItemDataPatchObject(int $orgUnitId, int $newsItemId): NewsItemDataPatch
newSectionDataCreate(int $orgUnitId, string $Name, string $Code, RichTextInput $Description): ?SectionDataCreate
newSectionEnrollmentObject(int $orgUnitId, int $sectionId, int $UserId): SectionEnrollment
newUserAccommodationsCreateObject(int $OrgUnitId, int $UserId, QuizzingAccommodations $QuizzingAccommodations): UserAccommodationsCreate

ID Retriever Functions

getOrgUnitIdFromCode(string $orgUnitCode, int $orgUnitType): ?int
getOrgUnitIdFromDepartmentCode(string $departmentCode): ?int
getOrgUnitIdFromOfferingCode(string $offeringCode): ?int
getOrgUnitIdFromSemesterCode(string $semesterCode): ?int
getOrgUnitIdFromTemplateCode(string $templateCode): ?int
getUserIdFromOrgDefinedId(string $orgDefinedId): ?int
getUserIdFromUsername(string $username): ?int

API Helper Functions

createCourseCopyRequest(int $orgUnitId, CreateCopyJobRequest $input): ?CreateCopyJobResponse
createCourseCopyRequestAndWait(int $orgUnitId, CreateCopyJobRequest $input): bool
createCourseCopyRequestsAndWait(CopyRequestQueue $requests): bool
createCourseGroup(int $orgUnitId, int $groupCategoryId, GroupDataCreate $input): ?GroupData
createCourseGroupCategory(int $orgUnitId, GroupCategoryDataCreate $input): ?GroupCategoryData
createCourseGroupCategoryAndWait(int $orgUnitId, GroupCategoryDataCreate $input): ?GroupCategoryData
createCourseOffering(CreateCourseOffering $input): ValenceCourse|CourseOffering
createCourseSection(int $orgUnitId, SectionDataCreate $input): ?SectionData
deleteCourseAnnouncement(int $orgUnitId, int $newsItemId): void
deleteCourseGroup(int $orgUnitId, int $groupCategoryId, int $groupId): void
deleteCourseGroupCategory(int $orgUnitId, int $groupCategoryId): void
deleteCourseOffering(int $orgUnitId): void
deleteCourseSection(int $orgUnitId, int $sectionId): void
deleteUserPicture(int $userId): void
dismissCourseAnnouncement(int $orgUnitId, int $newsItemId): void
enrollInstructor(int $OrgUnitId, int $UserId): ?EnrollmentData
enrollStudent(int $OrgUnitId, int $UserId): ?EnrollmentData
enrollUser(CreateEnrollmentData $input): ?EnrollmentData
enrollUserInCourseSection(int $orgUnitId, int $sectionId, SectionEnrollment $input): void
enrollUserInGroup(int $orgUnitId, int $groupCategoryId, int $groupId, int $UserId): void
getAccommodations(int $orgUnitId, int $userId): UserAccommodations
getBrightSpaceDataSets(): BrightspaceDataSetReportInfoArray
getContentToc(int $orgUnitId): ?TableOfContents
getContentTopicFile(int $orgUnitId, int $topicId, string $filepath): bool
getCourseAnnouncement(int $orgUnitId, int $newsItemId): ?NewsItem
getCourseAnnouncements(int $orgUnitId): ?NewsItemArray
getCourseAnnouncementsForUser(int $orgUnitId, int $userId): ?NewsItemArray
getCourseCopyJobStatus(int $orgUnitId, string $jobToken): ?GetCopyJobResponse
getCourseGroup(int $orgUnitId, int $groupCategoryId, int $groupId): ?GroupData
getCourseGroupCategories(int $orgUnitId): GroupCategoryDataArray
getCourseGroupCategory(int $orgUnitId, int $groupCategoryId): ?GroupCategoryData
getCourseGroups(int $orgUnitId, int $groupCategoryId): GroupDataArray
getCourseImage(int $orgUnitId, string $filepath): bool
getCourseOffering(int $orgUnitId): ?CourseOffering
getCourseSection(int $orgUnitId, int $sectionId): ?SectionData
getCourseSectionSettings(int $orgUnitId): ?SectionPropertyData
getCourseSections(int $orgUnitId): SectionDataArray
getDeletedCourseAnnouncements(int $orgUnitId): ?NewsItemArray
getDiscussionForum(int $orgUnitId, int $forumId): ?Forum
getDiscussionForums(int $orgUnitId): ForumArray
getDiscussionPost(int $orgUnitId, int $forumId, int $topicId, int $postId): ?Post
getDiscussionPosts(int $orgUnitId, int $forumId, int $topicId): PostArray
getDiscussionTopic(int $orgUnitId, int $forumId, int $topicId): ?Topic
getDiscussionTopics(int $orgUnitId, int $forumId): TopicArray
getEnrollment(int $orgUnitId, int $userId): ?EnrollmentData
getEnrollments(int $orgUnitId): ?OrgUnitUserArray
getOrgUnitType($orgUnitTypeId): ?OrgUnitType
getOrgUnitTypes(): OrgUnitTypeArray
getOrganization(): ?Organization
getRole($roleId): ?Role
getRoles(): RoleArray
getUser(int $userId): ?UserData
getUserNames(int $userId): ?LegalPreferredNames
getUserPicture(int $userId, string $filepath): bool
getUserProfile(int $userId): ?UserProfile
initializeCourseSections(int $orgUnitId, SECTENROLL $EnrollmentStyle, int $EnrollmentQuantity, bool $AuthEnroll, bool $RandomizeEnrollments): ?SectionData
pinCourse(int $orgUnitId, int $userId): void
postCourseAnnouncement(int $orgUnitId, NewsItemData $input): NewsItem
publishCourseAnnouncement(int $orgUnitId, int $newsItemId): void
restoreCourseAnnouncement(int $orgUnitId, int $newsItemId): void
restoreDeletedCourseAnnouncement(int $orgUnitId, int $newsItemId): void
setAccommodations(UserAccommodationsCreate $input): UserAccommodations
unenrollUser(int $userId, int $orgUnitId): void
unenrollUserFromGroup(int $orgUnitId, int $groupCategoryId, int $groupId, int $userId): void
unpinCourse(int $orgUnitId, int $userId): void
updateCourseAnnouncement(int $orgUnitId, int $newsItemId, NewsItemData $input): void
updateCourseGroup(int $orgUnitId, int $groupCategoryId, int $groupId, string $Name, string $Code, string $DescriptionText): ?GroupData
updateCourseGroupCategory(int $orgUnitId, int $groupCategoryId, string $Name, string $DescriptionText, GRPENROLL $EnrollmentStyle, ?int $EnrollmentQuantity, bool $AutoEnroll, bool $RandomizeEnrollments, ?int $NumberOfGroups, ?int $MaxUsersPerGroup, bool $AllocateAfterExpiry, ?string $SelfEnrollmentExpiryDate, ?string $GroupPrefix, ?int $RestrictedByOrgUnitId): ?GroupCategoryData
updateCourseOffering(int $orgUnitId, CourseOfferingInfo $input): void
updateCourseSection(int $orgUnitId, int $sectionId, string $Name, string $Code, string $DescriptionText): ?SectionData
updateCourseSectionSettings(int $orgUnitId, SECTENROLL $EnrollmentStyle, int $EnrollmentQuantity, int $AuthEnroll, int $RandomizeEnrollments): ?SectionPropertyData
updateUserNames(int $userId, string $LegalFirstName, string $LegalLastName, ?string $PreferredFirstName, ?string $PreferredLastName): ?LegalPreferredNames
uploadCourseImage(int $orgUnitId, string $filepath, string $name): bool
uploadUserPicture(int $userId, string $filepath): bool
version(string $productCode): ?ProductVersions
versions(): ProductVersionArray
whoami(): ?WhoAmIUser

Course Client API Helper Functions

__construct(Valence $valence, int $orgUnitId)
createCopyRequest(CreateCopyJobRequest $input): ?CreateCopyJobResponse
createGroup(int $groupCategoryId, string $Name, string $Code, string $DescriptionText): ?GroupData
createGroupCategory(string $Name, string $DescriptionText, GRPENROLL $EnrollmentStyle, ?int $EnrollmentQuantity, bool $AutoEnroll, bool $RandomizeEnrollments, ?int $NumberOfGroups, ?int $MaxUsersPerGroup, bool $AllocateAfterExpiry, ?string $SelfEnrollmentExpiryDate, ?string $GroupPrefix, ?int $RestrictedByOrgUnitId): ?GroupCategoryData
createSection(string $Name, string $Code, RichText $Description): ?SectionData
deleteCourseAnnouncement(int $newsItemId): void
deleteGroup(int $groupCategoryId, int $groupId): void
deleteGroupCategory(int $groupCategoryId): void
deleteSection(int $sectionId): void
dismissCourseAnnouncement(int $newsItemId): void
enrollInstructor(int $UserId): ?EnrollmentData
enrollStudent(int $UserId): ?EnrollmentData
enrollUser(int $UserId, int $RoleId): ?EnrollmentData
enrollUserInGroup(int $groupCategoryId, int $groupId, int $UserId): void
enrollUserInSection(int $sectionId, int $UserId): void
get(): ?CourseOffering
getAccommodations(int $userId): UserAccommodations
getAnnouncement(int $newsItemId): NewsItem
getAnnouncements(): NewsItemArray
getAnnouncementsForUser(int $userId): NewsItemArray
getContentToc(): ?TableOfContents
getContentTopicFile(int $topicId, string $filepath): bool
getCopyJobStatus(string $jobToken): ?GetCopyJobResponse
getDeletedAnnouncements(): NewsItemArray
getDiscussionForum(int $forumId): ?Forum
getDiscussionForums(): ForumArray
getDiscussionPost(int $forumId, int $topicId, int $postId): ?Post
getDiscussionPosts(int $forumId, int $topicId): PostArray
getDiscussionTopic(int $forumId, int $topicId): ?Topic
getDiscussionTopics(int $forumId): TopicArray
getEnrollment(int $userId): ?EnrollmentData
getEnrollments(): ?OrgUnitUserArray
getGroup(int $groupCategoryId, int $groupId): ?GroupData
getGroupCategories(): GroupCategoryDataArray
getGroupCategory(int $groupCategoryId): ?GroupCategoryData
getGroups(int $groupCategoryId): GroupDataArray
getImage(string $filepath): bool
getSection(int $sectionid): ?SectionData
getSectionSettings(): ?SectionPropertyData
getSections(): SectionDataArray
initializeSections(SECTENROLL $EnrollmentStyle, int $EnrollmentQuantity, bool $AuthEnroll, bool $RandomizeEnrollments): ?SectionData
pinForUser(int $userId): void
postCourseAnnouncement(NewsItemData $input): NewsItem
publishCourseAnnouncement(int $newsItemId): void
restoreCourseAnnouncement(int $newsItemId): void
restoreDeletedCourseAnnouncement(int $newsItemId): void
unenrollUser(int $UserId): void
unenrollUserFromGroup(int $groupCategoryId, int $groupId, int $userId): void
unpinForUser(int $userId): void
updateCourseAnnouncement(int $newsItemId, NewsItemData $input): void
updateGroup(int $groupCategoryId, int $groupId, string $Name, string $Code, string $DescriptionText): ?GroupData
updateGroupCategory(int $groupCategoryId, string $Name, string $DescriptionText, GRPENROLL $EnrollmentType, ?int $EnrollmentQuantity, bool $AutoEnrollment, bool $RandomizeEnrollments, ?int $NumberOfGroups, ?int $MaxUsersPerGroup, bool $AllocateAfterExpiry, ?string $SelfEnrollmentExpiryDate, ?string $GroupPrefix, ?int $RestrictedByOrgUnitId): ?GroupCategoryData
updateSection(int $sectionId, string $Name, string $Code, string $DescriptionText): ?SectionData
updateSectionSettings(SECTENROLL $EnrollmentStyle, int $EnrollmentQuantity, bool $AuthEnroll, bool $RandomizeEnrollments): ?SectionPropertyData
uploadCourseImage(string $filepath, string $name): bool

User Client API Helper Functions

__construct(Valence $valence, int $userId)
deletePicture(): void
enrollAsInstructor(int $OrgUnitId): ?EnrollmentData
enrollAsStudent(int $OrgUnitId): ?EnrollmentData
enrollInCourse(int $OrgUnitId, int $RoleId): ?EnrollmentData
enrollInCourseSection(int $orgUnitId, int $sectionId): void
enrollInGroup(int $orgUnitId, int $groupCategoryId, GroupEnrollment $input): void
get(): ?UserData
getAccommodations(int $orgUnitId): UserAccommodations
getEnrollment(int $orgUnitId): ?EnrollmentData
getNames(): LegalPreferredNames
getPicture(string $filepath): bool
getProfile(): ?UserProfile
pinCourse(int $orgUnitId): void
unenroll(int $orgUnitId): void
unenrollFromGroup(int $orgUnitId, int $groupCategoryId, int $groupId): void
unpinCourse(int $orgUnitId): void
updateNames(string $LegalFirstName, string $LegalLastName, ?string $PreferredFirstName, ?string $PreferredLastName): LegalPreferredNames
uploadPicture(string $filepath): bool

Objects

Arrays

COPYCOMPONENT

Attributes

ACTIVITYTYPE
AVAILABILITY
CONTENT_COMPLETIONTYPE
COPYJOBSTATUS
GRPENROLL
RATING
SCORING
SECTENROLL
TIMEOP

Blocks

BasicOrgUnit
Birthday
BrightspaceDatasetReportInfo
CourseOffering
CreateCopyJobResponse
EnrollmentData
Forum
GetCopyJobResponse
GroupCategoryData
GroupData
LegalPreferredNames
NewsItem
OrgUnitType
OrgUnitUser
Organization
Permissions
Post
ProductVersions
QuizzingAccommodations
QuizControlAccommodation
QuizTimeLimitAccommodation
RichText
Role
RoleInfo
SectionData
SectionPropertyData
SocialMediaUrl
TableOfContents
TableOfContentsModule
TableOfContentsTopic
Topic
User
UserAccommodations
UserActivationData
UserData
UserProfile
WhoAmIUser

Block Arrays

BrightspaceDataSetReportInfoArray
BrightspaceDataSetReportInfoPreviousArray
ForumArray
GroupCategoryDataArray
GroupDataArray
NewsItemArray
OrgUnitTypeArray
OrgUnitUserArray
PostArray
ProductVersionArray
RoleArray
SectionDataArray
SocialMediaUrls
TableOfContentsModuleArray
TableOfContentsTopicArray
TopicArray

Create Blocks

CreateCopyJobRequest
CreateCourseOffering
CreateEnrollmentData
GroupCategoryDataCreate
GroupDataCreate
GroupEnrollment
NewsItemData
QuizzingAccommodationsCreate
QuizControlAccommodationCreate
QuizTimeLimitAccommodationCreate
RichTextInput
SectionDataCreate
SectionEnrollment
UserAccommodationsCreate

Update Blocks

CourseOfferingInfo

Patch Blocks

CourseOfferingInfoPatch
NewsItemDataPatch

Class Objects

BrightspaceConfig
CopyRequest
CopyRequestQueue
DateTime
NotInDatahub
UserIdKeyPair

Data Hub Related Functions

Relationship Mappings

While this release contains all the objects for the Data Hub, it does not have all the relationships mapped. These are the relationships that are currently included:

  • AssignmentSubmission
    • assignmentsubmissions
    • assignmentsummary
    • orgunit
    • users
  • DiscussionForum
    • discussiontopics
    • orgunit
  • DiscussionPost
    • discussiontopic
    • users
  • DiscussionTopic
    • discussionforum
    • discussionposts
  • OrganizationalUnit
    • assignments
    • department
    • discussionforums
    • parents
    • quizobjects
    • semester
    • template
    • users
  • QuizAttempt
    • quizobject
    • user
  • QuizObject
    • orgunit
    • quizattempts
  • User
    • assignmentsubmissions
    • courses
    • discussionposts
    • quizattempts

Helper Functions

The following helper functions exist to find some of the objects that have a more common identifier you may be familiar with.

  • OrganizationalUnit::whereCode($code)
  • OrganizationalUnit::whereCodeAndType($code, $type)
  • OrganizationalUnit::whereOrgUnitId($orgunitid)
  • OrganizationalUnit::isCurrent($orgUnitId, $thresholdInDays)
  • Users::whereOrgDefinedId($orgdefinedid)
  • Users::whereUserId($userid)
  • Users::whereUserName($username)

Frequently Asked Questions

Why are some variables in the hints in camel case (i.e. variableName) and some with uppercase words (VariableName)?

This is intentionally done to be consistent with the corresponding variables in the API. In general, variables in URLs (such as parameters within the API calls and query strings) are in camel case and fields within the JSON parameters have the uppercase first words.

Why are the variables inconsistent in terms of some being arrays and some being objects? Is there a way to have all functions return arrays instead of objects?

This is to best utilize the functionality of your IDE. In PHP, there is no way to define anything like an "array template." Thus, if we simply utilized an array, you would still need to dig in to the documentation to find the fields that are available. However, by using objects, and using type-hinting to define the return type of a function to be a particular object, your IDE can then autocomplete the attributes of an object returned by a function. Although a later version of PHP introduces the ability to specify that a function may return one of several object types, it would break -- at least partially -- the ability to autocomplete attributes of a class if we were to specify that an array could also be returned.