Skip to content

Latest commit

 

History

History
333 lines (271 loc) · 8.93 KB

File metadata and controls

333 lines (271 loc) · 8.93 KB

EduDex API Client - Implementation Summary

Overview

Complete PHP EduDex API client scaffolded from openapi-edudex-spec.json, following SilverStripe 5 coding standards.

Total Files Created: 28 files across 8 directories

Project Structure

app/src/EduDex/
├── Client.php                      # Main API client entry point
├── Endpoints/                      # API endpoint classes
│   ├── BaseEndpoint.php
│   ├── Organizations.php
│   ├── Suppliers.php
│   ├── Accreditors.php
│   ├── Programs.php
│   └── Validations.php
├── Models/                         # Data models from OpenAPI schemas
│   ├── Model.php                   # Base model with hydration
│   ├── Organization.php
│   ├── Supplier.php
│   ├── Accreditor.php
│   ├── Accreditation.php
│   ├── StaticCatalog.php
│   ├── DynamicCatalog.php
│   ├── Webhook.php
│   ├── Program.php
│   └── ValidationResult.php
├── Types/                          # Helper types
│   ├── LocalizedString.php
│   └── ValidationMessage.php
├── Exceptions/                     # Exception hierarchy
│   ├── EduDexException.php
│   ├── AuthenticationException.php
│   ├── ValidationException.php
│   └── ApiException.php
├── Http/                           # HTTP client abstraction
│   ├── ClientInterface.php
│   └── GuzzleClient.php
├── Extensions/                     # SilverStripe extensions
│   └── SiteConfigExtension.php
└── README.md                       # Complete usage documentation

Key Features Implemented

1. Core Infrastructure

  • ✅ Main Client class with endpoint accessors
  • BaseEndpoint with common HTTP methods and model hydration
  • ✅ Abstract Model class with fromArray/toArray serialization
  • ✅ HTTP client abstraction (Guzzle implementation)
  • ✅ Complete exception hierarchy

2. API Endpoints (Full Coverage)

  • Organizations - List, get, catalogs (static/dynamic), webhooks
  • Suppliers - List, get, programs, metadata, discounts
  • Accreditors - List, get, accreditations (CRUD)
  • Programs - Bulk operations
  • Validations - Program, institute, discount validation

3. Models (All Major Entities)

  • ✅ Organization (with roles, accreditations, helper methods)
  • ✅ Supplier, Accreditor (with localized names)
  • ✅ Accreditation (with validity checks, expiry calculations)
  • ✅ StaticCatalog, DynamicCatalog (with helper methods)
  • ✅ Webhook (with status checking)
  • ✅ Program (with title/description extraction)
  • ✅ ValidationResult (with error/warning separation)

4. Type Helpers

  • LocalizedString - Multi-language content with fallback logic
  • ValidationMessage - Structured validation messages

5. SilverStripe Integration

  • ✅ Config API support with YML configuration
  • ✅ Environment variable support (EDUDEX_API_TOKEN)
  • ✅ SiteConfig extension for admin UI
  • ✅ Connection status testing in CMS
  • ✅ Injector/Singleton support

6. Code Quality

  • ✅ PHP 8.1+ with strict type hints
  • ✅ Full PHPDoc blocks on all public methods
  • ✅ SilverStripe coding standards (4 spaces, naming conventions)
  • ✅ PSR-4 autoloading
  • ✅ Comprehensive error handling

Next Steps

1. Configure the Client

Add to .env:

EDUDEX_API_TOKEN="your-jwt-bearer-token"

2. Rebuild Database

ddev exec vendor/bin/sake dev/build flush=1

3. Test the Connection

Via CMS:

  • Go to Settings → EduDex tab
  • Enter bearer token
  • Check connection status

Via Code:

use Restruct\EduDex\Client;

$client = new Client();
$orgs = $client->organizations()->list();
echo "Found " . count($orgs) . " organizations\n";

4. Optional: Add Unit Tests

Create app/tests/EduDex/ with PHPUnit tests for:

  • Model hydration/serialization
  • LocalizedString fallback logic
  • Exception handling
  • Endpoint method signatures

Example test structure:

app/tests/EduDex/
├── ClientTest.php
├── Models/
│   ├── OrganizationTest.php
│   └── LocalizedStringTest.php
└── Endpoints/
    └── OrganizationsTest.php

5. Optional: Add Caching Layer

Extend endpoint classes to cache responses:

use SilverStripe\Core\Cache\CacheFactory;

protected function getCached(string $key, callable $callback, int $ttl = 3600)
{
    $cache = CacheFactory::inst()->create('EduDex');

    if ($data = $cache->get($key)) {
        return $data;
    }

    $data = $callback();
    $cache->set($key, $data, $ttl);
    return $data;
}

6. Optional: Add Background Jobs

For syncing large datasets:

use Symbiote\QueuedJobs\Services\AbstractQueuedJob;

class SyncEduDexJob extends AbstractQueuedJob
{
    public function process()
    {
        $client = Client::singleton();
        // Sync logic here
    }
}

Usage Examples

Basic Example

use Restruct\EduDex\Client;

$client = new Client();

// Get organizations
$orgs = $client->organizations()->list();

// Validate program before submission
$result = $client->validations()->validateProgram($programData);
if ($result->isValid()) {
    $client->suppliers()->upsertProgram($supplierId, $programId, $clientId, $programData);
}

In a Controller

class CourseController extends ContentController
{
    public function index()
    {
        $client = Client::singleton();

        try {
            $suppliers = $client->suppliers()->list();
            return $this->customise([
                'Suppliers' => $suppliers
            ]);
        } catch (EduDexException $e) {
            return $this->httpError(500, 'Failed to load suppliers');
        }
    }
}

In a Task

class ImportCoursesTask extends BuildTask
{
    public function run($request)
    {
        $client = Client::singleton();
        $suppliers = $client->suppliers()->list();

        foreach ($suppliers as $supplier) {
            $programs = $client->suppliers()->listPrograms($supplier->id);
            // Process programs...
        }
    }
}

Configuration Reference

app/_config/edudex.yml

# Note: Bearer token must be set via EDUDEX_API_TOKEN environment variable
Restruct\EduDex\Integration\SilverStripe\SilverStripeClient:
  api_base_url: 'https://api.edudex.nl/data/v1/'
  timeout: 30
  debug: false
  cache_ttl: 3600

# Map base Client to SilverStripeClient via Injector
SilverStripe\Core\Injector\Injector:
  Restruct\EduDex\Client:
    class: Restruct\EduDex\Integration\SilverStripe\SilverStripeClient

Environment Variables

  • EDUDEX_API_TOKEN - JWT bearer token (required, cannot be set via Config)

API Coverage

Organizations Endpoint ✅

  • List organizations
  • Get organization
  • List/Get/Create/Update/Delete static catalogs
  • Bulk add/remove programs to/from static catalogs
  • List/Get/Create/Update/Delete dynamic catalogs
  • Add/Remove suppliers from dynamic catalogs
  • List/Get/Create/Update/Delete/Test webhooks

Suppliers Endpoint ✅

  • List suppliers
  • Get supplier
  • Get/Update metadata
  • List/Get/Upsert/Delete programs
  • List/Get/Upsert/Delete discounts

Accreditors Endpoint ✅

  • List accreditors
  • Get accreditor
  • List/Get/Create/Update/Delete accreditations

Programs Endpoint ✅

  • Bulk retrieve programs

Validations Endpoint ✅

  • Validate programs
  • Validate institute metadata
  • Validate discounts

Documentation

  • README.md - Complete usage guide with examples
  • IMPLEMENTATION.md - This file (implementation details)
  • openapi-edudex-spec.json - Original OpenAPI specification

Technical Notes

Type Casting

Models automatically cast properties:

  • DateTime strings → DateTime objects
  • Localized arrays → LocalizedString objects
  • Validation messages → ValidationMessage objects
  • Booleans, integers, floats properly typed

Localization

LocalizedString supports:

  • Multiple languages (nl, en, de, fr, etc.)
  • Automatic fallback (nl → en → first available)
  • Easy modification and serialization

Error Handling

Four exception types with specific use cases:

  • EduDexException - Base for all errors
  • AuthenticationException - 401/403 errors
  • ValidationException - 400 with validation messages
  • ApiException - Other HTTP errors (404, 500, etc.)

Extensibility

All classes follow SOLID principles:

  • HTTP client is abstracted (easy to swap)
  • Models use protected methods for custom casting
  • Endpoints extend BaseEndpoint
  • SilverStripe Injector support

Maintenance

To update when API changes:

  1. Update openapi-edudex-spec.json
  2. Review new/changed schemas
  3. Update corresponding Model classes
  4. Update Endpoint methods
  5. Update README examples
  6. Run tests

Support

For issues or questions: