PHPackages                             wikiwijs/php-qti3 - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. wikiwijs/php-qti3

ActiveLibrary[Testing &amp; Quality](/categories/testing)

wikiwijs/php-qti3
=================

PHP library for reading, writing and manipulating QTI 3.0 packages, assessment tests and assessment items

0.1.4(2mo ago)0540[18 issues](https://github.com/kennisnet/php-qti3/issues)[2 PRs](https://github.com/kennisnet/php-qti3/pulls)MITPHPPHP &gt;=8.4CI passing

Since Mar 4Pushed 2mo agoCompare

[ Source](https://github.com/kennisnet/php-qti3)[ Packagist](https://packagist.org/packages/wikiwijs/php-qti3)[ RSS](/packages/wikiwijs-php-qti3/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (5)Dependencies (18)Versions (13)Used By (0)

PHP QTI 3.0 Library
===================

[](#php-qti-30-library)

This library provides functionality for reading, writing and manipulating QTI 3.0 packages, assessment tests and assessment items.

Installation
------------

[](#installation)

You can install the library via Composer:

```
composer require wikiwijs/php-qti3
```

Usage
-----

[](#usage)

The library uses the `QtiClient` as a service container for accessing various services.

### Initializing the QtiClient

[](#initializing-the-qticlient)

To use the library, you first need to initialize the `QtiClient` with the required dependencies. The library provides default implementations using PSR interfaces and Flysystem.

#### Required implementations

[](#required-implementations)

The `QtiClient` expects three implementations:

1. **IFilesystemPackageFactory**: For reading and writing files to a (temporary) file system.
2. **IResourceValidator**: For validating external resources (e.g. URLs).
3. **IResourceDownloader**: For downloading external resources to the local file system.

#### Example with default implementations

[](#example-with-default-implementations)

The implementations below are available in the library but may require additional composer packages (see the `suggest` section in `composer.json`).

```
use League\Flysystem\Local\LocalFilesystemAdapter;
use League\Flysystem\Filesystem;
use Qti3\QtiClient;
use Qti3\Package\Filesystem\FlysystemPackageFactory;
use Qti3\Package\Validator\Resource\PsrHttpClientResourceValidator;
use Qti3\Package\Downloader\Resource\PsrHttpClientResourceDownloader;
use Qti3\Package\Filesystem\FileSystemUtils;

// 1. Setup Flysystem (e.g. local file system)
// Required: composer require league/flysystem
$adapter = new LocalFilesystemAdapter('/tmp/qti-data');
$filesystem = new Filesystem($adapter);
$filesystemPackageFactory = new FlysystemPackageFactory($filesystem);

// 2. Setup PSR-18 HTTP Client and PSR-17 Request Factory
// E.g. Symfony's HTTP Client: composer require symfony/http-client psr/http-client nyholm/psr7
$httpClient = new \Symfony\Component\HttpClient\Psr18Client();
$requestFactory = new \Nyholm\Psr7\Factory\Psr17Factory();

// 3. Initialize the validator and downloader
$resourceValidator = new PsrHttpClientResourceValidator($httpClient, $requestFactory);
$resourceDownloader = new PsrHttpClientResourceDownloader(
    new FileSystemUtils(),
    $httpClient,
    $requestFactory,
    '/tmp/qti-data' // Folder where downloads are stored
);

// 4. Create the QtiClient
$qtiClient = new QtiClient(
    $filesystemPackageFactory,
    $resourceValidator,
    $resourceDownloader,
);
```

### QTI Package Level

[](#qti-package-level)

**UC-P1: Import QTI3 package in ZIP format to package object**

```
$qtiPackageReader = $qtiClient->getQtiPackageReader();
$qtiPackage = $qtiPackageReader->fromZip('/tmp/qti3.zip');
// $qtiPackage is now of type Qti3\Package\Model\QtiPackage
```

**UC-P2: Import QTI3 package from folder to package object**

```
$qtiPackageReader = $qtiClient->getQtiPackageReader();
$qtiPackage = $qtiPackageReader->fromFilesystem('/tmp/folder');
// $qtiPackage is now of type Qti3\Package\Model\QtiPackage
```

**UC-P3: Generate ZIP file from package object**

```
$zipPackageFactory = $qtiClient->getZipPackageFactory();
$writer = $zipPackageFactory->getWriter('/tmp/qti3.zip');
$writer->write($qtiPackage);
```

**UC-P4: Generate folder from package object**

```
$filesystemPackageFactory = $qtiClient->getFilesystemPackageFactory();
$writer = $filesystemPackageFactory->getWriter('/tmp/folder');
$writer->write($qtiPackage);
```

**UC-P5: Validate a QTI package**

```
$validator = $qtiClient->getQtiPackageValidator();
$errors = $validator->validate($qtiPackage);

if ($errors->count() > 0) {
    // $errors is a StringCollection of validation error messages
}
```

By default the library uses an XSD-based syntax validator (`QtiSchemaValidator`). To use the official **IMS Global QTI validator** (Docker image) instead, pass a custom `IQtiSyntaxValidator` implementation as the fourth argument to `QtiClient`. See [docs/ims-global-validator.md](docs/ims-global-validator.md) for setup instructions and a ready-to-use skeleton class.

### Assessment Test Level

[](#assessment-test-level)

**UC-T1: Generate test from package**

```
$testBuilder = $qtiClient->getTestBuilder();
$test = $testBuilder->buildFromPackage($qtiPackage);
// $test is now of type Qti3\AssessmentTest\Model\AssessmentTest
```

**UC-T2: Generate package from test**

```
// $test is of type Qti3\AssessmentTest\Model\AssessmentTest
// $items is an array of Qti3\AssessmentItem\Model\AssessmentItem
$packageBuilder = $qtiClient->getQtiPackageBuilder();
$package = $packageBuilder->buildForTest($test, $items);
// $package is now of type Qti3\Package\Model\QtiPackage
```

### Assessment Item Level

[](#assessment-item-level)

**UC-I1: Parse item XML to model**

```
// $itemXml is of type DomDocument
$assessmentItemParser = $qtiClient->getAssessmentItemParser();
$item = $assessmentItemParser->parse($itemXml);
// $item is now of type Qti3\AssessmentItem\Model\AssessmentItem
```

**UC-I2: Generate XML from item**

```
// $item is of type Qti3\AssessmentItem\Model\AssessmentItem
$xmlBuilder = $qtiClient->getXmlBuilder();
$itemXml = $xmlBuilder->generateXmlFromObject($item);
// $itemXml is now of type DomDocument
```

**UC-I3: Response processing**

```
// $responses is an associative array with response-identifier->value
$responseProcessor = $qtiClient->getResponseProcessor();
$itemState = $responseProcessor->initItemState($itemXml);
$responseProcessor->processResponses($itemState, $responses);
$outcomes = $itemState->outcomeSet->outcomes;
// $outcomes is now an associative array with outcome-identifier->value
```

### Supported interactions

[](#supported-interactions)

The `AssessmentItem` parser supports all current QTI 3.0 interaction types listed below via the `InteractionParser` used by `ItemBodyParser`:

- `qti-choice-interaction`
- `qti-text-entry-interaction`
- `qti-extended-text-interaction`
- `qti-gap-match-interaction`
- `qti-hotspot-interaction`
- `qti-hottext-interaction`
- `qti-match-interaction`
- `qti-order-interaction`
- `qti-select-point-interaction`

Running Tests
-------------

[](#running-tests)

You can run the unit tests with the following Composer command:

```
composer test
```

###  Health Score

44

—

FairBetter than 92% of packages

Maintenance87

Actively maintained with recent releases

Popularity19

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 70.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~2 days

Total

5

Last Release

62d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/3d5ba0d19fd97386ecc8e71a479f33fd1bc47f20b151c52c04c091faf3be186d?d=identicon)[kennisnet](/maintainers/kennisnet)

---

Top Contributors

[![Camacojo](https://avatars.githubusercontent.com/u/26523748?v=4)](https://github.com/Camacojo "Camacojo (53 commits)")[![Julian-91](https://avatars.githubusercontent.com/u/52066808?v=4)](https://github.com/Julian-91 "Julian-91 (11 commits)")[![SanderKN](https://avatars.githubusercontent.com/u/226316403?v=4)](https://github.com/SanderKN "SanderKN (5 commits)")[![gewooneendeveloper](https://avatars.githubusercontent.com/u/302548?v=4)](https://github.com/gewooneendeveloper "gewooneendeveloper (3 commits)")[![defixje](https://avatars.githubusercontent.com/u/1568058?v=4)](https://github.com/defixje "defixje (2 commits)")[![wimmuskee](https://avatars.githubusercontent.com/u/1087783?v=4)](https://github.com/wimmuskee "wimmuskee (1 commits)")

---

Tags

qti3testingeducationQTIIMSAssessmentqti3

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/wikiwijs-php-qti3/health.svg)

```
[![Health](https://phpackages.com/badges/wikiwijs-php-qti3/health.svg)](https://phpackages.com/packages/wikiwijs-php-qti3)
```

###  Alternatives

[phpunit/phpunit

The PHP Unit Testing framework.

20.0k910.7M134.8k](/packages/phpunit-phpunit)[phpunit/php-code-coverage

Library that provides collection, processing, and rendering functionality for PHP code coverage information.

8.9k892.4M1.5k](/packages/phpunit-php-code-coverage)[mockery/mockery

Mockery is a simple yet flexible PHP mock object framework

10.7k497.0M23.6k](/packages/mockery-mockery)[behat/behat

Scenario-oriented BDD framework for PHP

4.0k96.8M2.0k](/packages/behat-behat)[symfony/phpunit-bridge

Provides utilities for PHPUnit, especially user deprecation notices management

2.5k201.2M4.2k](/packages/symfony-phpunit-bridge)[behat/mink

Browser controller/emulator abstraction for PHP

1.6k86.1M606](/packages/behat-mink)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
