PHPackages                             learnosity/learnosity-qti - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. learnosity/learnosity-qti

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

learnosity/learnosity-qti
=========================

Learnosity QTI Conversion Library

v2.1.0(3y ago)258.6k↓33.3%23[1 PRs](https://github.com/Learnosity/learnosity-qti/pulls)GPL-2.0PHPPHP &gt;=7.4CI failing

Since Oct 12Pushed 3mo ago52 watchersCompare

[ Source](https://github.com/Learnosity/learnosity-qti)[ Packagist](https://packagist.org/packages/learnosity/learnosity-qti)[ RSS](/packages/learnosity-learnosity-qti/feed)WikiDiscussions develop Synced 1mo ago

READMEChangelog (10)Dependencies (9)Versions (27)Used By (0)

Notice
======

[](#notice)

This library is open source and currently is not actively maintained by Learnosity.

Users should fork this repository to fix any issues found or feature requests required.

The `develop` branch is the mainline you should checkout.

Note: due to containing vendors, this package is licensed under GPL (GPL-2.0).

\--

Learnosity QTI
==============

[](#learnosity-qti)

This package converts between QTI 2.1 Assessment Items and Learnosity JSON.

You can choose between 2 main jobs:

- `convert:to:learnosity` - Converts QTI v2.1 to Learnosity JSON
- `convert:to:qti` - Converts Learnosity JSON to QTI v2.1

Installation via Composer
-------------------------

[](#installation-via-composer)

Using Composer is the recommended way to install Learnosity QTI for PHP. In order to use the package with Composer, you must add "learnosity/learnosity-qti" as a dependency in your project's composer.json file.

```
{
    "require": {
        "learnosity/learnosity-qti": "2.*"
    }
}

```

Then, install your dependencies

```
composer install

```

Or just do:

```
composer global require "learnosity/learnosity-qti"

```

For bleeding edge:

```
{
    "require": {
        "learnosity/learnosity-qti": "dev-develop"
    }
}

```

Make sure to add $HOME/.composer/vendor/bin directory to your $PATH so the `mo` executable can be located by your system. If not, simply replace all `mo` commands below with `./bin/mo` (from the root of the project).

This package has been tested on PHP 8.1+

Usage
-----

[](#usage)

### The `mo` command line runner

[](#the-mo-command-line-runner)

Use the command line tool, `mo` to run conversion jobs. To see all jobs, run `mo list`:

```
$ mo list

Usage:
  mo [command] [options] [--help]

Flags:
  --help                    Print the applications help

Commands:
  convert:to:learnosity     Converts QTI v2.1 to Learnosity JSON
  convert:to:qti            Converts Learnosity JSON to QTI v2.1
  list                      Lists all commands available

```

Converting QTI to Learnosity JSON
---------------------------------

[](#converting-qti-to-learnosity-json)

By default, Learnosity QTI expects a QTI content package, including an imsmanifest.xml.

To convert QTI 2.1 to Learnosity JSON, run the following:

```
mo convert:to:learnosity --organisation_id [integer]

```

`organisation_id` is a mandatory option, where the value is an integer of your Learnosity item bank (organisation).

By default this will look for content packages inside the `./data/input` directory, and output raw results to `./data/output/raw` and final item JSON to `./data/output/final`. A job manifest file will be written to `./data/output/log`, indicating errors or warnings found during the conversion.

Note that only the `data` folder is present in this repository, you can create the `data/input` folder to add content packages there. The `data/output` path will be created automatically if you don't override via input options.

### Conversion options

[](#conversion-options)

If you want to use different input and/or output paths you can use options:

```
mo convert:to:learnosity --input /my/path/to/qti --output /my/path/to/output/folder --organisation_id [integer]

```

All supported input options are as follows:

OptionDefaultDescription‑‑organisation\_id\[Mandatory\] Which Learnosity item bank to use, contact Learnosity for your `organisation_id` value--input`./data/input`File system path to the source content being converted--output`./data/output`File system path to where the converted content will be written‑‑item-reference-source`item`Where to retrieve each items unique identifier from the QTI.
item uses the identifier attribute on the `` elementmetadatauses the `` element from the LOM metadata in the manifest, if available. If no `` is found, then this parameter operates in "item" moderesourceuses the identifier attribute on the `` element in the manifestfilenameuses the basename of the `` XML file--passage-only-items`No`Whether HTML passages should be created as separate, passage-only, items.
NoNo separate items will be createdYes Separate items containing only passages will be created--single-item`No`To convert a single QTI `` instead of a full content package, pass `Yes` and a path to a single XML file to `--input`Assets
------

[](#assets)

The conversion library will update any asset URL inside QTI content to use the following Learnosity CDN address: `https://assets.learnosity.com/organisations/[integer]/[filename]`

The `organisation` value is taken from the `--organisation_id` input parameter passed to the command line.

Supported file types include:

- images
- audio files (mp3)
- video files (mp4)

When importing content using the Data API, you can add files using the [Upload Assets](https://reference.learnosity.com/data-api/endpoints/itembank_endpoints#uploadAssets) endpoint.

Metadata (LOM)
--------------

[](#metadata-lom)

Metadata will be taken from the content package manifest and converted to [Learnosity tags](https://help.learnosity.com/hc/en-us/articles/360000758597-Understanding-Tag-Formats-for-Content-Creation-and-Filtering). The format is assumed to be:

```

                GradeLevel

                    6

```

This will be converted to the following Learnosity JSON (snippet only):

```
{
    "tags": {
        "GradeLevel": [
            "6"
        ]
    }
}

```

Note that `` translates to Learnosity tag types, and `` translates to tag names.

Supported Interactions - QTI to Learnosity
------------------------------------------

[](#supported-interactions---qti-to-learnosity)

The following QTI v2.1 interactions are supported:

QTI InteractionLearnosity Question TypeLearnosity Widget ValueChoiceInteractionMultiple Choice QuestionmcqExtendedTextInteractionEssaylongtextV2GraphicGapMatchInteractionImage AssociationimageclozeassociationV2GapMatchInteractionCloze AssociationclozeassociationHottextInteractionToken HighlighttokenhighlightInlineChoiceInteractionCloze DropdownclozedropdownMatchInteractionChoice MatrixchoicematrixOrderInteractionOrder ListorderlistTextEntryInteractionCloze TextclozetextHotspotInteractionHotspothotspotRubrics
-------

[](#rubrics)

`` elements are commonplace in QTI documents. Learnosity can treat these as:

- passages
- distractor rationale
- rating question types (for scoring)

Passages
--------

[](#passages)

Learnosity has the concept of a [Passage](https://authorguide.learnosity.com/hc/en-us/articles/360000445597-Shared-Passages), which is a separate HTML fragment that can be added to single items, or shared across multiple items. By default, the conversion library looks for the following QTI to be converted into a passage:

```

```

In the example above, the contents of the passage come from an external file in the content package. You can also include the passage contents inline (inside the `` element).

Note that the `use` attribute must be `context`, and the `view` attribute must include `candidate`.

The Learnosity JSON generated would contain 2-columns, the passage(s) in the left and the question(s) in the right.

### Multiple passages

[](#multiple-passages)

If 2 passages are found in a QTI item, a tabbed interface will appear in the converted JSON (in the left-column).

If 3 (or more) passages are found, they will be stacked vertically in the UI (no tabs).

### "Shared" Passages

[](#shared-passages)

In the converted results, the Learnosity reference (unique identifier) to a passage is generated from a hash of the passage body. So, we automatically "share" a passage if an exact match is found based on the contents of the passage.

Distractor rationale
--------------------

[](#distractor-rationale)

### Students

[](#students)

If the `use` attribute of a `` element is `rationale`, and the `view` attribute contains `candidate`, the conversion library will generate [`distractor_rationale_response_level`](https://authorguide.learnosity.com/hc/en-us/articles/360000448738-Understanding-the-Extras-Section-of-the-Question-Editor) inside the question metadata.

The contents of the `` will be broken down by block elements, one for each array element of `distractor_rationale_response_level`. Eg:

```

    Distractor: Enim vestibulum habitant dui ut morbi.
    Distractor: Himenaeos fringilla arcu suspendisse pulvinar.

```

Would generate the following JSON:

```
{
    "metadata": {
        "distractor_rationale_response_level": [
            "Distractor: Natoque velit etiam sem varius consequat.",
            "Distractor: Enim vestibulum habitant dui ut morbi.",
            "Correct: Dapibus scelerisque diam lacus nec lacus.",
            "Distractor: Himenaeos fringilla arcu suspendisse pulvinar."
        ]
    }
}

```

If `` elements are found, they will be converted to `distractor_rationale_response_level`. Eg with the following for a choice interaction:

```

        [Question prompt here]

```

The `feedbackInline` contents will be converted to `distractor_rationale_response_level` array elements.

### Graders

[](#graders)

If the `class` attribute of a `` element is `DistractorRationale`, and the `view` attribute contains `author`, the conversion library will generate `distractor_rationale_scorer` as a custom metadata field inside the question metadata.

The contents of the `` will be used, eg:

```

    Parturient est morbi suspendisse nisi a duis scelerisque integer ut...

```

Would generate the following JSON:

```
{
    "metadata": {
        "distractor_rationale_scorer": "Parturient est morbi suspendisse nisi a duis scelerisque integer ut..."
    }
}

```

It would up to the host page calling the Assessment API to render this content to a grader.

Unsupported
-----------

[](#unsupported)

Learnosity QTI does not support:

- `` with no interactions (passage-only or rubric-only)
- Custom CSS stylesheets. These must be loaded separately at run time for the host page initialising the Assessment API.

Note that only `` are supported, no other QTI elements like ``.

### Help

[](#help)

Remember you can ask for `help`:

```
$ mo convert:to:learnosity --help

Usage:
  convert:to:learnosity [options]

Options:
  -i, --input=INPUT                                    The input path to your QTI content [default: "./data/input"]
  -o, --output=OUTPUT                                  An output path where the Learnosity JSON will be saved [default: "./data/output"]
      --organisation_id=ORGANISATION_ID                The identifier of the item bank you want to import content into [default: ""]
      --item-reference-source[=ITEM-REFERENCE-SOURCE]  The source to use to extract the reference for the item. Valid values are the following:
                                                       item     - uses the identifier attribute on the  element
                                                       metadata - uses the  element from the LOM metadata in the manifest, if available. If
                                                       no  is found, then this parameter operates in "item" mode
                                                       resource - uses the identifier attribute on the  element in the manifest
                                                       filename - uses the basename of the  XML file
                                                       [default: "metadata"]
      --passage-only-items[=PASSAGE-ONLY-ITEMS]        If you pass the value as "Y", the conversion library will convert regular assessment items as well
                                                       as passage-only items, if defined in the manifest [default: "N"]
      --single-item[=SINGLE-ITEM]                      If you pass the value as "Y", the conversion library will convert only single xml file [default: "N"]
  -h, --help                                           Display this help message
  -q, --quiet                                          Do not output any message
  -V, --version                                        Display this application version
      --ansi                                           Force ANSI output
      --no-ansi                                        Disable ANSI output
  -n, --no-interaction                                 Do not ask any interactive question
  -v|vv|vvv, --verbose                                 Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Help:
  Converts QTI v2.1 to Learnosity JSON, expects to run on folder(s) with a imsmanifest.xml file

```

Importing into Learnosity
=========================

[](#importing-into-learnosity)

Once you have Learnosity JSON (the `final` folder), you can use the Data API to import into your Learnosity hosted item bank.

Example of the output format is:

```
{
    "qtiitems": {
        "[item-reference]": {
            "item": {},
            "questions": [],
            "features": [],
            "manifest": [],
            "rubric": null,
            "assumptions": []
        }
    }
}

```

Loop over all item objects inside `qtiitems`. Inside each item object, import the questions (setQuestions) and features (setFeatures) first, then the item (setItems). Setting items will automatically import any tags that were in the manifest.

- [Import questions](https://docs.learnosity.com/analytics/data/endpoints/itembank_endpoints#setQuestions)
- [Import features](https://docs.learnosity.com/analytics/data/endpoints/itembank_endpoints#setFeatures)
- [Import items](https://docs.learnosity.com/analytics/data/endpoints/itembank_endpoints#setItems)

Converting Learnosity JSON to QTI
---------------------------------

[](#converting-learnosity-json-to-qti)

To convert Learnosity JSON to QTI 2.1, run the following:

```
mo convert:to:qti

```

By default this will look for content packages inside the `./data/input` directory, and output raw results to `./data/output/raw`. A manifest file will be written to `./data/output/log`.

Note that only the `data` folder is present in this repository, you can create the `data/input` folder to add content packages there. The `data/output` path will be created automatically if you don't override via input options.

### Conversion options

[](#conversion-options-1)

If you want to use different input and/or output paths you can use options:

```
mo convert:to:qti --input /my/path/to/learnosity-json --output /my/path/to/output/folder

```

All supported input options are as follows:

OptionDefaultDescription--input`./data/input`File system path to the source content being converted‑‑output`./data/output`File system path to where the converted content will be written‑‑format`qti`A flag to choose how to format the QTI output content package, from a list of supported formats. This option supports the following possible values: (canvas, qti). Pass the canvas option to export. QTI content that is compatible with Canvas LMS. The default is qti, which outputs non LMS-specific QTI.--zip`true`A flag determining whether to generate a zip file of the converted package. If you don't require an archive, disable for better performance‑‑logVerbose`false`A flag that can add extra logging not considered essential to the conversion manifest‑‑silencePHPWarnings`false`A flag that can suppress PHP deprecation warnings### Learnosity JSON format

[](#learnosity-json-format)

This conversion tool expects to be given JSON in the format that is returned by the [offline package endpoint of the Data API](https://reference.learnosity.com/data-api/endpoints/itembank_endpoints#getOfflinePackage). The Data API `itembank/offlinepackage` endpoint returns Activities/Items/Questions/Features in a single directory. It also contains any assets, including images, audio or video, that are part of the content.

The directory returned from the itembank/offlinepackage endpoint contains the following files:

```
vendor/learnosity/itembank
	activities/
		hashedfilename.json (optional)
	assets/
		image1.jpg
		image2.jpg
	items/
		hashedfilename.json
		hashedfilename.json
		hashedfilename.json
	manifest.json

```

Each JSON file within the items folder is named from a (lower case) MD5 hash of the item reference. The contents of each item file will be something like:

```
{
    "reference": "",
    "content": "",
    "workflow": null,
    "metadata": {
        "acknowledgements": null,
        "scoring_type": "per-question"
    },
    "tags": {},
    "questions": [],
    "features": []
}

```

### Generated QTI folder structure

[](#generated-qti-folder-structure)

After conversion, expect the `output` location to contain:

```
output/
	final/
	log/
		convert-to-qti.log.json
	raw/
		audio/
		images/
		items/
		passages/
		video/
		imsmanifest.xml

```

Currently, we don't use `final`.

The `log` directory stores a manifest with detail about the conversion.

### Supported Question Types - Learnosity to QTI

[](#supported-question-types---learnosity-to-qti)

The following Learnosity question types are supported:

Learnosity Question TypeLearnosity Widget ValueQTI InteractionChemistry essay with rich textchemistryessayV2ExtendedTextInteractionChoice MatrixchoicematrixMatchInteractionCloze AssociationclozeassociationGapMatchInteractionCloze DropdownclozedropdownInlineChoiceInteractionCloze TextclozetextTextEntryInteractionEssaylongtextExtendedTextInteractionEssay with rich textlongtextV2ExtendedTextInteractionHotspothotspotHotspotInteractionImage Cloze AssociationimageclozeassociationGraphicGapMatchInteractionImage Cloze Association V2imageclozeassociationV2GraphicGapMatchInteractionMath essay with rich textformulaessayV2ExtendedTextInteractionMultiple Choice QuestionmcqChoiceInteractionOrder ListorderlistOrderInteractionPassagesharedpassageN/APlain TextplaintextExtendedTextInteractionShort TextshorttextTextEntryInteractionToken HighlighttokenhighlightHottextInteraction#### Scoring

[](#scoring)

The converter attempts to use one of the following `` templates:

- ``
- ``

In cases where there are multiple interactions on a single item (composite items), or the `score` is greater than `1`, we use custom mappings inside `` coupled with the `map_response` template. Eg:

```

        a
        b

```

#### Known limitations

[](#known-limitations)

##### Item layouts

[](#item-layouts)

2-column items are rendered in the markup like:

```

                Sample question stem
                response 1
                response 2
                response 3
                response 4

```

Recipients of any QTI package should have necessary CSS to render as columns.

##### Tabs

[](#tabs)

Any API column tabs are removed. All contained widgets are vertically stacked in the QTI.

##### Passages

[](#passages-1)

Passages are rendered as ``. Eg,

```

```

##### Cloze Association

[](#cloze-association)

Cannot use the group possible responses option. We flatten all groups into a single `possible_responses` array.

##### Distractor rationale

[](#distractor-rationale-1)

Any `distractor_rationale` is rendered inside `` elements.

##### Media

[](#media)

Video and audio are rendered as `` elements. Eg:

```

```

##### General

[](#general)

Considering the strict nature of QTI (XHTML), we do a *lot* of string processing during the conversion process. This is because invalid content might have been imported into Learnosity via the Data API, or entered by authors.

### Help

[](#help-1)

Remember you can ask for `help`:

```
$ mo convert:to:qti --help

Usage:
  convert:to:qti [options]

Options:
  -i, --input=INPUT     The input path to your Learnosity content [default: "./data/input"]
  -o, --output=OUTPUT   An output path where the QTI will be saved [default: "./data/output"]
  -f, --format=FORMAT   A flag to choose how to format the QTI output content package, from a list of supported formats.
                        This option supports the following possible values: (canvas, qti). Pass the canvas option to export
                        QTI content that is compatible with Canvas LMS. The default is qti, which outputs non LMS-specific QTI.
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Help:
  Converts Learnosity JSON to QTI v2.1

```

###  Health Score

50

—

FairBetter than 96% of packages

Maintenance52

Moderate activity, may be stable

Popularity37

Limited adoption so far

Community29

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor2

2 contributors hold 50%+ of commits

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 ~180 days

Recently: every ~312 days

Total

16

Last Release

1161d ago

Major Versions

v0.9.0 → v1.0.02018-05-23

v1.2.0 → v2.0.0-alpha2019-09-19

v1.2.1 → v2.0.0-beta2019-12-11

PHP version history (4 changes)v0.5.0PHP &gt;=5.5

v1.1.0PHP &gt;=5.6

v2.0.0-betaPHP ^7.1

v2.1.0PHP &gt;=7.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/42ac2bf5d0b7730422a8f5caa80a96f2fee305289a23b4bbf4b51fb79537df85?d=identicon)[learnosity\_oss](/maintainers/learnosity_oss)

![](https://avatars.githubusercontent.com/u/758280?v=4)[Stella Lie](/maintainers/stellalie)[@stellalie](https://github.com/stellalie)

![](https://avatars.githubusercontent.com/u/2345717?v=4)[Trungtin Ton](/maintainers/ttton)[@ttton](https://github.com/ttton)

---

Top Contributors

[![stellalie](https://avatars.githubusercontent.com/u/758280?v=4)](https://github.com/stellalie "stellalie (193 commits)")[![michaelsharman](https://avatars.githubusercontent.com/u/663796?v=4)](https://github.com/michaelsharman "michaelsharman (193 commits)")[![learnosity-frank-an](https://avatars.githubusercontent.com/u/11303294?v=4)](https://github.com/learnosity-frank-an "learnosity-frank-an (69 commits)")[![ttton](https://avatars.githubusercontent.com/u/2345717?v=4)](https://github.com/ttton "ttton (22 commits)")[![rakeshqdsa](https://avatars.githubusercontent.com/u/24287161?v=4)](https://github.com/rakeshqdsa "rakeshqdsa (22 commits)")[![ekcolysp](https://avatars.githubusercontent.com/u/3783872?v=4)](https://github.com/ekcolysp "ekcolysp (19 commits)")[![gsmithpro](https://avatars.githubusercontent.com/u/54034078?v=4)](https://github.com/gsmithpro "gsmithpro (3 commits)")[![pooja31chaudhary](https://avatars.githubusercontent.com/u/49148553?v=4)](https://github.com/pooja31chaudhary "pooja31chaudhary (3 commits)")[![david-johnson-lrn](https://avatars.githubusercontent.com/u/85566442?v=4)](https://github.com/david-johnson-lrn "david-johnson-lrn (1 commits)")[![markkellyeire](https://avatars.githubusercontent.com/u/957999?v=4)](https://github.com/markkellyeire "markkellyeire (1 commits)")

---

Tags

learnosityopensourceqtilearnosityQTItei

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/learnosity-learnosity-qti/health.svg)

```
[![Health](https://phpackages.com/badges/learnosity-learnosity-qti/health.svg)](https://phpackages.com/packages/learnosity-learnosity-qti)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[simplesamlphp/simplesamlphp

A PHP implementation of a SAML 2.0 service provider and identity provider.

1.1k12.4M193](/packages/simplesamlphp-simplesamlphp)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)[contao/core-bundle

Contao Open Source CMS

1231.6M2.4k](/packages/contao-core-bundle)

PHPackages © 2026

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