restruct / edudex-api-client
PHP client library for the EDU-DEX Data API. Framework-agnostic with optional SilverStripe integration.
Fund package maintenance!
Requires
- php: ^8.1
- guzzlehttp/guzzle: ^7.0
- psr/log: ^1.0|^2.0|^3.0
Requires (Dev)
- phpstan/phpstan: ^1.10
- phpunit/phpunit: ^10.0|^11.0
- squizlabs/php_codesniffer: ^3.7
Suggests
- monolog/monolog: For enhanced logging support
- silverstripe/framework: For SilverStripe integration (^5.0)
Provides
None
Conflicts
None
Replaces
None
README
Maintained by Restruct. If this module saves you time, you can support ongoing maintenance.
PHP client library for the EDU-DEX Data API. Framework-agnostic with optional SilverStripe integration.
Features
- 🎯 Complete API Coverage - All endpoints from the EDU-DEX OpenAPI specification
- 🔌 Framework Agnostic - Works with any PHP 8.1+ project
- 🔧 Optional SilverStripe Integration - Full Config API, Extensions, and Injector support
- 🎨 Clean Architecture - PSR-4 autoloading, typed models, endpoint classes
- 🛡️ Type Safe - PHP 8.1+ with strict type hints and return types
- 📦 Smart Models - Automatic hydration, serialization, and type casting
- 🌍 Localization - Built-in
LocalizedStringhelper for multi-language content - ✅ Validation - Pre-submission validation for programs, metadata, and discounts
- 🔐 Secure - Bearer token authentication with environment variable support
- 📝 Well Documented - Comprehensive PHPDoc blocks and usage examples
Installation
Install via Composer:
composer require restruct/edudex-api-client
Quick Start
Basic Usage (Any PHP Project)
<?php require 'vendor/autoload.php'; use Restruct\EduDex\Client; // Initialize with bearer token $client = new Client('your-jwt-bearer-token'); // Or use environment variable EDUDEX_API_TOKEN $client = new Client(); // Fetch organizations $organizations = $client->organizations()->list(); foreach ($organizations as $org) { echo $org->getLocalizedName('nl') . "\n"; }
Configuration
use Restruct\EduDex\Client; // From array $config = [ 'bearer_token' => 'your-token', 'api_base_url' => 'https://api.edudex.nl/data/v1/', 'timeout' => 30, ]; $client = Client::fromConfig($config); // From environment variable // Set EDUDEX_API_TOKEN in your .env file $client = new Client();
Usage Examples
Working with Organizations
use Restruct\EduDex\Client; $client = new Client(); // List all organizations $organizations = $client->organizations()->list(); // Get specific organization $org = $client->organizations()->get('organization-id'); echo "Name: " . $org->getLocalizedName('nl') . "\n"; echo "Roles: " . implode(', ', $org->roles) . "\n"; echo "Supplier: " . ($org->isSupplier() ? 'Yes' : 'No') . "\n"; // Working with catalogs $catalogs = $client->organizations()->listStaticCatalogs('org-id'); foreach ($catalogs as $catalog) { echo "{$catalog->title}: {$catalog->countActive}/{$catalog->countTotal} programs\n"; }
Managing Programs
// List programs for a supplier $programs = $client->suppliers()->listPrograms('supplier-id'); // Get specific program $program = $client->suppliers()->getProgram('supplier-id', 'program-id', 'client-id'); echo "Title: " . $program->getTitle('nl') . "\n"; echo "Description: " . $program->getDescription('en') . "\n"; // Create or update program $programData = [ 'editor' => 'Admin User', 'format' => 'application/vnd.edudex.program+json', 'generator' => 'My CMS v1.0', 'lastEdited' => date('c'), 'programDescriptions' => [ 'title' => ['nl' => 'Cursus Titel', 'en' => 'Course Title'], ], // ... additional program data ]; $client->suppliers()->upsertProgram('supplier-id', 'program-id', 'client-id', $programData);
Validating Data
// Validate program before submission $result = $client->validations()->validateProgram($programData); if ($result->isValid()) { echo "✓ Validation passed!\n"; // Submit the program $client->suppliers()->upsertProgram(...); } else { echo "✗ Validation failed:\n"; foreach ($result->getErrors() as $error) { echo " • {$error->message}"; if ($error->contextPath) { echo " (at {$error->contextPath})"; } echo "\n"; } }
Bulk Operations
// Fetch multiple programs at once $programsToFetch = [ ['orgUnitId' => 'supplier-1', 'programId' => 'prog-1', 'clientId' => 'public'], ['orgUnitId' => 'supplier-2', 'programId' => 'prog-2', 'clientId' => 'client-1'], ]; $response = $client->programs()->bulk($programsToFetch); // Process results $successful = $client->programs()->getSuccessful($response); $failed = $client->programs()->getFailed($response); echo "Retrieved " . count($successful) . " programs\n"; echo "Failed: " . count($failed) . " programs\n";
Error Handling
use Restruct\EduDex\Exceptions\AuthenticationException; use Restruct\EduDex\Exceptions\ValidationException; use Restruct\EduDex\Exceptions\ApiException; use Restruct\EduDex\Exceptions\EduDexException; try { $org = $client->organizations()->get('org-id'); } catch (AuthenticationException $e) { // Handle 401/403 errors echo "Authentication error: {$e->getMessage()}\n"; } catch (ValidationException $e) { // Handle validation errors with detailed messages foreach ($e->getErrors() as $error) { echo "Error: {$error['message']}\n"; } } catch (ApiException $e) { // Handle other API errors echo "API error: {$e->getMessage()}\n"; } catch (EduDexException $e) { // Catch-all echo "Error: {$e->getMessage()}\n"; }
SilverStripe Integration
For SilverStripe projects, use the optional integration layer:
composer require restruct/edudex-api-client composer require silverstripe/framework:^5.0
Configuration
The package ships its own _config/edudex.yml, so in a Silverstripe project two things are applied
automatically, without any project config:
SiteConfigExtensionis added toSiteConfig(an "EduDex" tab under Settings in the CMS; rundev/buildafter installing).- The Injector maps
Restruct\EduDex\ClienttoSilverStripeClient.
Client settings are optional; override them in your own config, e.g. app/_config/edudex.yml:
--- Name: app-edudex-client --- Restruct\EduDex\Integration\SilverStripe\SilverStripeClient: api_base_url: 'https://api.edudex.nl/data/v1/' timeout: 30
To switch the CMS integration off, remove the extension in your project's app/_config.php. The
package adds it as an unnamed list entry, which YAML config cannot unset, so this has to be PHP:
use Restruct\EduDex\Integration\SilverStripe\Extensions\SiteConfigExtension; use SilverStripe\SiteConfig\SiteConfig; SiteConfig::remove_extension(SiteConfigExtension::class);
Usage in SilverStripe
use Restruct\EduDex\Integration\SilverStripe\SilverStripeClient; // Using singleton $client = SilverStripeClient::singleton(); // Or via Injector $client = Injector::inst()->get(SilverStripeClient::class); // Same API as standalone $organizations = $client->organizations()->list();
See docs/SILVERSTRIPE_INTEGRATION.md for complete documentation.
API Reference
Endpoints
- Organizations - Manage organizations, catalogs, and webhooks
- Suppliers - Supplier management, programs, discounts, metadata
- Accreditors - Accreditor management and accreditations
- Programs - Bulk program operations
- Validations - Validate programs, metadata, and discounts
Models
Organization- Organization with roles and accreditationsSupplier- Training providerAccreditor- Accreditation organizationAccreditation- Supplier accreditation with validityStaticCatalog- Manual program catalogDynamicCatalog- Automatic catalog with filtersWebhook- Event notification endpointProgram- Training program/courseValidationResult- Validation response
Type Helpers
LocalizedString- Multi-language content handlerValidationMessage- Validation message with severity
Exceptions
EduDexException- Base exceptionAuthenticationException- 401/403 errorsValidationException- 400 validation errorsApiException- Other HTTP errors
Documentation
- Standalone Usage Guide - Complete guide for non-SilverStripe projects
- SilverStripe Integration - SilverStripe-specific setup and usage
- Implementation Details - Technical implementation overview
- Working Examples - Ready-to-run code examples
Requirements
- PHP 8.1 or higher (PHP 7.4 version in backport branch)
- GuzzleHTTP ^7.0
- PSR-3 Logger interface
Optional:
- SilverStripe Framework ^5.0 (for SilverStripe integration;
SiteConfigExtensionextendsDataExtension, which Silverstripe 6 removed, so the integration layer is Silverstripe 5 only)
Testing
There is no test suite yet: phpunit.xml.dist points at a tests/ directory that does not exist, so
composer test has nothing to run. The static analysis and code style scripts:
# Install dev dependencies composer install # Run static analysis composer phpstan # Check code style composer cs-check # Fix code style composer cs-fix
Support
- Issues: https://github.com/restruct/edudex-api-client/issues
- EDU-DEX Data API Documentation: https://api.edudex.nl/data/v1/
- EDU-DEX Data API in Swagger: https://api.edudex.nl/data/v1/openapi/swagger-ui
- EDUDOX: https://www.edudex.nl/edudox/
- API Getting started: https://mijn.edudex.nl/api-getting-started/
License
This library is open-sourced software licensed under the MIT license.
The MIT license covers this library's own code. The bundled openapi-edudex-spec.json is the EDU-DEX Data API specification, published by EDU-DEX; it is included for reference and code generation only, is not covered by the MIT license, and no separate license for it is stated by EDU-DEX. EDU-DEX is an open data standard for exchanging and publishing training course information; see https://www.edudex.nl for its terms of use.
Credits
- Michael van Schaik (Restruct.nl) - development
- Bart van Irsel (Webium) - AI consultant/guru
- EDU-DEX API by WebHare BV