Exemple #1
0
$warnings = array();
$messages = array();
if (!isset($_REQUEST["qtiid"])) {
    badrequest("no QTI ID was specified");
}
$item = getitem($_REQUEST["qtiid"]);
if (!$item) {
    badrequest("no item with the given QTI ID exists in the database");
}
// if not cloning...
if (!isset($_REQUEST["clone"])) {
    // only the owner can edit it
    if (!loggedin()) {
        badrequest("you're not logged in so can't edit this item");
    }
    if ($item["user"] != username()) {
        badrequest("you're not the owner of this item and so can't edit it");
    }
    // if the item's already in session memory redirect straight to Eqiat
    if (isset($_SESSION["items"]) && array_key_exists($_REQUEST["qtiid"], $_SESSION["items"])) {
        redirect(SITEROOT_WEB . "eqiat/#item_" . $_REQUEST["qtiid"]);
    }
}
// make a QTIAssessmentItem object from the data we have and put it in session memory
$metadata = array("description" => $item["description"], "keywords" => $item["keywords"]);
$ai = xmltoqtiobject($item["xml"], $errors, $warnings, $messages, $metadata, isset($_REQUEST["clone"]));
if ($ai === false) {
    servererror("Errors:\n" . implode("\n", $errors) . "\n\nWarnings:\n" . implode("\n", $warnings) . "\n\nMessages:\n" . implode("\n", $messages));
}
$ai->sessionStore();
redirect(SITEROOT_WEB . "eqiat/#item_" . $ai->getQTIID());
    public function getContentPackage()
    {
        // build the manifest
        $manifest = new SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?>
			<manifest
				xmlns="http://www.imsglobal.org/xsd/imscp_v1p1"
				xmlns:imsmd="' . NS_IMSMD . '"
				xmlns:imsqti="' . NS_IMSQTI . '"
				xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
				xsi:schemaLocation="http://www.imsglobal.org/xsd/imscp_v1p1 imscp_v1p1.xsd http://www.imsglobal.org/xsd/imsmd_v1p2 imsmd_v1p2p4.xsd http://www.imsglobal.org/xsd/imsqti_v2p1  http://www.imsglobal.org/xsd/imsqti_v2p1.xsd"
			/>
		');
        $manifest->addAttribute("identifier", $this->getMID());
        // organizations element
        $manifest->addChild("organizations");
        // resources element
        $rs = $manifest->addChild("resources");
        $r = $rs->addChild("resource");
        $r->addAttribute("identifier", $this->getQTIID());
        $r->addAttribute("type", "imsqti_item_xmlv2p1");
        $r->addAttribute("href", "{$this->getTitleFS()}.xml");
        $md = $r->addChild("metadata");
        // resource qti metadata
        $qmd = $md->addChild("qtiMetadata", null, NS_IMSQTI);
        $qmd->addChild("timeDependent", "false", NS_IMSQTI);
        foreach ($this->interactionTypes() as $it) {
            $qmd->addChild("interactionType", $it, NS_IMSQTI);
        }
        $qmd->addChild("feedbackType", is_null($this->data("feedback")) ? "none" : "nonadaptive", NS_IMSQTI);
        $qmd->addChild("solutionAvailable", "true", NS_IMSQTI);
        // resource LOM metadata
        $lom = $md->addChild("lom", null, NS_IMSMD);
        $g = $lom->addChild("general", null, NS_IMSMD);
        $g->addChild("title", null, NS_IMSMD)->addChild("langstring", $this->data("data"), NS_IMSMD);
        if (!is_null($this->data("description"))) {
            $g->addChild("description", null, NS_IMSMD)->addChild("langstring", $this->data("description"), NS_IMSMD);
        }
        foreach ($this->getKeywords() as $keyword) {
            $g->addChild("keyword", null, NS_IMSMD)->addChild("langstring", $keyword, NS_IMSMD);
        }
        // file element
        $r->addChild("file")->addAttribute("href", "{$this->getTitleFS()}.xml");
        // make temporary zip archive
        $zip = new ZipArchive();
        $filename = "/tmp/" . uniqid("zip");
        if ($zip->open($filename, ZIPARCHIVE::CREATE) !== true) {
            servererror("couldn't make zip file");
        }
        $zip->addFromString("imsmanifest.xml", simplexml_indented_string($manifest));
        $zip->addFromString("{$this->getTitleFS()}.xml", $this->getQTIIndentedString());
        $zip->close();
        // slurp contents
        $zipcontents = file_get_contents($filename);
        // delete the temporary zip archive
        unlink($filename);
        // return the zip contents as a binary string
        return $zipcontents;
    }
Exemple #3
0
function qtiengine_bodydiv_html(SimpleXMLElement $page, $divid = "qtienginebodydiv")
{
    // php5's support for default namespace is useless so we have to define it
    // manually
    $namespaces = $page->html->getNamespaces();
    $defaultnamespace = $namespaces[""];
    $page->registerXPathNamespace("n", $defaultnamespace);
    $bodydivs = $page->xpath("//n:div[@id='body']");
    if (count($bodydivs) != 1) {
        servererror("didn't get expected HTML output from QTIEngine");
    }
    $bodydiv = $bodydivs[0];
    $bodydiv["id"] = $divid;
    foreach ($page->xpath("//n:input[@type='checkbox']") as $checkbox) {
        if (!preg_match('%\\]$%', (string) $checkbox["name"])) {
            $checkbox["name"] = (string) $checkbox["name"] . "[]";
        }
    }
    return preg_replace(array('%<(/?)h2\\b%', '%<hr\\b.*?>%'), array('<\\1h3', ''), xhtml_to_html(simplexml_indented_string($bodydiv)));
}
Exemple #4
0
/*
 * Eqiat
 * Easy QTI Item Authoring Tool
 */
/*------------------------------------------------------------------------------
(c) 2010 JISC-funded EASiHE project, University of Southampton
Licensed under the Creative Commons 'Attribution non-commercial share alike' 
licence -- see the LICENCE file for more details
------------------------------------------------------------------------------*/
if (isset($_REQUEST["itemtype"])) {
    // item type chosen
    // look for a item type class with this name
    $classname = "QTI" . ucfirst($_REQUEST["itemtype"]);
    if (!@class_exists($classname) || !is_subclass_of($classname, "QTIAssessmentItem")) {
        servererror("Item type doesn't exist or not implemented");
    }
    $ai = new $classname();
    $ai->sessionStore();
    $action = new EditAssessmentItemAction();
    redirect($action->actionURL($ai, false));
}
// choose from a list of item types
$items = item_types();
$GLOBALS["title"] = "New assessment item";
include "htmlheader.php";
?>
<h2><?php 
echo $GLOBALS["title"];
?>
</h2>
Exemple #5
0
        // build request string
        $multipart = new HttpRequestBodyMultipart();
        $multipart->addpart("actionUrl", $actionurl);
        $multipart->addpart("uploadedContent", $item["xml"], "application/xml", "qb_" . $item["identifier"] . ".xml");
        // set up curl handle to upload it
        $curl = curl_init();
        curl_setopt_array($curl, array(CURLOPT_URL => "http://" . QTIENGINE_HOST . ":" . QTIENGINE_PORT . QTIENGINE_PATH . "rest/upload", CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array("Content-Type: multipart/form-data; boundary=" . $multipart->boundary(), "Expect: "), CURLOPT_POSTFIELDS => $multipart->requeststring(), CURLOPT_FOLLOWLOCATION => true, CURLOPT_USERAGENT => PROGRAMNAME . "/" . VERSION));
        // upload it -- curl will follow the location headers and return the
        // final response
        $response = curl_exec($curl);
        // get jsessionid from last URL we were directed to
        $responseinfo = curl_getinfo($curl);
        $_SESSION["qtiengine_session"] = preg_replace('%.*;jsessionid=([0-9A-F]+)\\?.*%', '\\1', $responseinfo["url"]);
    }
    // parse response
    $xml = new SimpleXMLElement($response) or servererror("couldn't parse XML response");
    // inject javascript to header
    ob_start();
    ?>
	<script type="text/javascript">
		$j(document).ready(function() {
			$j("#getcommentslink").click(function(e) {
				e.preventDefault();
				$j.ajax({
					type: "GET",
					cache: false,
					dataType: "json",
					error: function(XMLHttpRequest, textStatus, errorThrown) {
						alert(XMLHttpRequest.responseText);
					},
					success: function(data, textStatus) {
Exemple #6
0
function item_actions()
{
    // look for item action classes
    $dh = opendir(SITEROOT_LOCAL . "classes/itemactions") or servererror("Couldn't open item actions dir");
    $types = array();
    while (($file = readdir($dh)) !== false) {
        if (!preg_match('%^.+Action\\.class\\.php$%', $file)) {
            continue;
        }
        $classname = substr($file, 0, -10);
        // skip classes which aren't ItemActions
        if (!is_subclass_of($classname, "ItemAction")) {
            continue;
        }
        // skip abstract classes
        $rc = new ReflectionClass($classname);
        if ($rc->isAbstract()) {
            continue;
        }
        $types[] = new $classname();
    }
    closedir($dh);
    usort($types, "compare_action_alpha");
    return $types;
}
 public function getLogic()
 {
     $ai = QTIAssessmentItem::fromQTIID($_REQUEST["qtiid"]);
     // upload the QTI to QTIEngine
     // Doing this manually rather than using curl because until PHP 5.2.7
     // (SVN r269951 to be specific) there is a bug
     // (http://bugs.php.net/bug.php?id=46696) which breaks the feature
     // needed to submit the uploaded file's mimetype. PHP 5.2.4 is still
     // common at the time of writing (it's in Ubuntu 8.04 LTS) so we can't
     // use curl here.
     // Could build the multipart/form-data ourselves but that still leaves
     // the issue that we don't want to follow the last redirect.
     // boundary -- see
     // http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
     while (true) {
         $boundary = "----------------------------" . uniqid();
         if (strpos($ai->getQTIIndentedString(), $boundary) === false) {
             break;
         }
     }
     // request
     $request = "--{$boundary}\r\n";
     $request .= "Content-Disposition: form-data; name=\"uploadedContent\"; filename=\"{$ai->getTitleFS()}.xml\"\r\n";
     $request .= "Content-Type: application/xml\r\n";
     $request .= "\r\n";
     $request .= $ai->getQTIIndentedString();
     $request .= "\r\n--{$boundary}--\r\n\r\n";
     // headers
     $reqheader = array("Host" => QTIENGINE_HOST, "Accept" => "*/*", "Content-Length" => strlen($request), "Content-Type" => "multipart/form-data; boundary={$boundary}");
     $url = "/application/upload";
     $reqaction = "POST {$url} HTTP/1.1";
     // make requests until we're redirected to the preview page
     $error = null;
     while (true) {
         // open socket
         $sock = fsockopen(QTIENGINE_HOST, 80, $errno, $errstr, 30);
         if (!$sock) {
             servererror("Couldn't connect to QTIEngine (" . QTIENGINE_HOST . ")");
         }
         // send data
         $reqheaderstrings = array();
         foreach ($reqheader as $key => $value) {
             $reqheaderstrings[] = "{$key}: {$value}";
         }
         fputs($sock, $reqaction . "\r\n" . implode("\r\n", $reqheaderstrings) . "\r\n\r\n" . $request);
         fflush($sock);
         // receive headers
         $header = array();
         $httpcode = null;
         while (!feof($sock) && ($line = fgets($sock)) != "\r\n") {
             if (is_null($httpcode) && preg_match('%^HTTP/[^\\s]*\\s+\\d+%', $line)) {
                 $httpcode = preg_replace('%^HTTP/[^\\s]*\\s+(\\d+).*$%', '\\1', $line);
             } else {
                 $parts = explode(":", $line, 2);
                 $header[trim($parts[0])] = trim($parts[1]);
             }
         }
         // close the socket
         fclose($sock);
         // check HTTP response code is a redirection
         if ($httpcode != 301 && $httpcode != 302 || !array_key_exists("Location", $header)) {
             $error = "Didn't get a redirection to the QTIEngine preview page. Last page was {$url}";
             break;
         }
         // check its URL is valid
         $urlparts = parse_url($header["Location"]);
         if (!isset($urlparts)) {
             $error = "Hit a malformed Location header pointing to '" . $header["Location"] . "'";
             break;
         }
         // stop if we've got to the preview page
         if (preg_match('%^/item/play/0;%', $urlparts["path"])) {
             break;
         }
         // redirect
         $url = $urlparts["path"];
         $reqaction = "GET {$url} HTTP/1.1";
         // delete POST related headers
         if (isset($reqheader["Content-Length"])) {
             unset($reqheader["Content-Length"]);
             unset($reqheader["Content-Type"]);
         }
         // clear the request data
         $request = "";
         // loop...
     }
     if (!is_null($error)) {
         servererror($error);
     }
     redirect($header["Location"]);
 }