/** * Initialises this item using data from an XML node. * @param DOMElement $node The node to use for initialisation. * @param CqQuestionInterface $context The question or other object that the mapping * can query for things like the current answer, draggables and hotspots. */ public function __construct(DOMElement $node, $context) { module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); if ($node) { $attribs = $node->attributes; if ($attribs) { $item = $attribs->getNamedItem('identifier'); if ($item === NULL) { $item = $attribs->getNamedItem('id'); } if ($item === NULL) { $item = $attribs->getNamedItem('name'); } if ($item !== NULL) { $this->identifier = $item->nodeValue; } $item = $attribs->getNamedItem('src'); if ($item !== NULL) { $this->imgSrc = $item->nodeValue; } $item = $attribs->getNamedItem('class'); if ($item !== NULL) { $this->cssClass = $item->nodeValue; } } $this->text = cq_get_text_content($node, $context); } }
/** * Creates a new CqOption. * * @param DOMElement $node * containing the option definition * @param CqQuestionInterface $context * CqQuestionInterface The question or other object that the mapping can query for * things like the current answer, draggables, hotspots and the parsing of * html. */ public function __construct(DOMElement $node, $context) { foreach ($node->getElementsByTagName('choice') as $choice) { $this->text .= cq_get_text_content($choice, $context); } foreach ($node->getElementsByTagName('description') as $description) { $this->description .= cq_get_text_content($description, $context); } foreach ($node->getElementsByTagName('feedback') as $fb) { $this->feedback[] = CqFeedback::newCqFeedback($fb, $context); } foreach ($node->getElementsByTagName('feedbackunselected') as $fb) { $this->feedbackUnselected[] = CqFeedback::newCqFeedback($fb, $context); } $attribs = $node->attributes; $item = $attribs->getNamedItem('correct'); if ($item !== NULL) { $this->correct = (int) $item->value; } $item = $attribs->getNamedItem('identifier'); if ($item === NULL) { $item = $attribs->getNamedItem('id'); } if ($item === NULL) { $item = $attribs->getNamedItem('name'); } if ($item !== NULL) { $this->identifier = $item->nodeValue; } }
/** * Initialise this Trigger by using values from the given XML node. * * @param $node * DOMElement The node to use for initialisation. * @param $context * CqQuestionInterface The question or other object that the mapping can query for * things like the current answer, draggables, hotspots and the parsing of * html. */ public function initFromNode($node, $context) { module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); $this->context = $context; $this->text .= cq_get_text_content($node, $context, TRUE, TRUE); $attribs = $node->attributes; $itemMin = $attribs->getNamedItem('min'); if ($itemMin !== NULL) { $this->min = (double) $itemMin->value; } $itemMax = $attribs->getNamedItem('max'); if ($itemMax !== NULL) { $this->max = (double) $itemMax->value; } }
/** * Creates a new CqInlineOption * * @param DOMElement $node * The XML node to use to initialise the option. * @param CqQuestionInterface $context * The question or other object that the item can query for things like the * current answer, draggables, hotspots and html processing. */ public function __construct(DOMElement $node, $context) { $this->text .= cq_get_text_content($node, $context); $attribs = $node->attributes; $item = $attribs->getNamedItem('identifier'); if ($item === NULL) { $item = $attribs->getNamedItem('id'); } if ($item === NULL) { $item = $attribs->getNamedItem('name'); } if ($item !== NULL) { $this->identifier = $item->nodeValue; } $item = $attribs->getNamedItem('group'); if ($item !== NULL && !empty($item->nodeValue)) { $this->group = $item->nodeValue; } }
/** * Factory method for creating hotspot classes from XML DOMElements * * @param DOMElement $node * The XML element representing the hotspot. * @param CqQuestionInterface $context * The question or other object that the mapping can query for things like the * current answer, draggables and hotspots. * * @return CqHotspot * The correct hotspot object. */ function cq_Hotspot_from_xml($node, $context) { $type = ''; if ($node) { $type = $node->getAttribute('shape'); $identifier = $node->getAttribute('identifier'); if (empty($identifier)) { $identifier = $node->getAttribute('id'); } $coords = $node->getAttribute('coords'); $description = cq_get_text_content($node, $context); $hotspot = FALSE; switch (drupal_strtoupper($type)) { case 'RECT': $numbers = explode(',', $coords); $x1 = (int) $numbers[0]; $y1 = (int) $numbers[1]; $x2 = (int) $numbers[2]; $y2 = (int) $numbers[3]; $hotspot = new CqHotspotRect($identifier, $x1, $y1, $x2, $y2); $hotspot->setDescription($description); break; case 'CIRCLE': $numbers = explode(',', $coords); $x1 = (int) $numbers[0]; $y1 = (int) $numbers[1]; $radius = (int) $numbers[2]; $hotspot = new CqHotspotCircle($identifier, $x1, $y1, $radius); $hotspot->setDescription($description); break; case 'POLY': $numbers = explode(',', $coords); $hotspot = new CqHotspotPoly($identifier, $numbers); $hotspot->setDescription($description); break; default: drupal_set_message(t('Unknown hotspot type: %type', array('%type' => $type))); break; } } return $hotspot; }
/** * Initialises an existing CqFeedback from an XML node. * * @param DOMElement $node * The node to use for initalisation * @param CqQuestionInterface $context * The question or other object that the item can query for things like the * current answer, draggables, hotspots and html processing. */ public function initFromElement(DOMElement $node, $context, $topParent = NULL) { module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); $this->context =& $context; $this->topParent =& $topParent; $this->text .= cq_get_text_content($node, $context, TRUE, TRUE); $attribs = $node->attributes; $itemMin = $attribs->getNamedItem('mintries'); if ($itemMin !== NULL) { $this->minTries = (int) $itemMin->value; } $itemMax = $attribs->getNamedItem('maxtries'); if ($itemMax !== NULL) { $this->maxTries = (int) $itemMax->value; } $itemBlock = $attribs->getNamedItem('block'); if ($itemBlock !== NULL) { $this->block = $itemBlock->value; } }
/** * Constructor for the Range object. * * @param DOMElement $node * The XML node to use for initalisation * @param <type> $context * CqQuestionInterface The question or other object that the mapping can query for * things like the current answer, draggables, hotspots and the parsing of * html. */ public function __construct(DOMElement $node, $context) { module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); $nodeList = $node->getElementsByTagName('minval'); $item = $nodeList->item(0); if ($item != NULL) { $this->minValue = trim(cq_get_text_content($item, $context)); } $nodeList = $node->getElementsByTagName('maxval'); $item = $nodeList->item(0); if ($item != NULL) { $this->maxValue = trim(cq_get_text_content($item, $context)); } foreach ($node->getElementsByTagName('feedback') as $fb) { $this->feedback[] = CqFeedback::newCqFeedback($fb, $context); } $attribs = $node->attributes; $item = $attribs->getNamedItem('correct'); if ($item !== NULL) { $this->correct = (int) $item->value; } }
/** * Overrides CqQuestionAbstract::loadXml() */ public function loadXml(DOMElement $dom) { parent::loadXml($dom); module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); module_load_include('php', 'closedquestion', 'question/mapping/FactoryHotspot'); $this->hotspots = array(); $this->mappings = array(); $this->hints = array(); $this->draggables = array(); foreach ($dom->childNodes as $node) { $name = drupal_strtolower($node->nodeName); switch ($name) { case 'text': $this->text = cq_get_text_content($node, $this); break; case 'matchimg': $this->matchImgUrl = $node->getAttribute('src'); $this->matchImgHeight = $node->getAttribute('height'); $this->matchImgWidth = $node->getAttribute('width'); $this->maxChoices = $node->getAttribute('maxChoices'); foreach ($node->childNodes as $child) { switch (drupal_strtolower($child->nodeName)) { case 'hotspot': $hotspot = cq_Hotspot_from_xml($child, $this); if (is_object($hotspot)) { if (isset($this->hotspots[$hotspot->getIdentifier()])) { drupal_set_message(t('Hotspot identifier %identifier used more than once!', array('%identifier' => $hotspot->getIdentifier())), 'warning'); } $this->hotspots[$hotspot->getIdentifier()] = $hotspot; } break; } } break; case 'mapping': $map = new CqMapping(); $map->generateFromNode($node, $this); $this->mappings[] = $map; break; case 'hint': $this->hints[] = CqFeedback::newCqFeedback($node, $this); break; default: if (!in_array($name, $this->knownElements)) { drupal_set_message(t('Unknown node: @nodename', array('@nodename' => $node->nodeName))); } break; } } }
/** * Overrides CqQuestionAbstract::loadXml() */ public function loadXml(DOMElement $dom) { parent::loadXml($dom); module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); foreach ($dom->childNodes as $node) { $name = drupal_strtolower($node->nodeName); switch ($name) { case 'text': $this->text = cq_get_text_content($node, $this); break; default: if (!in_array($name, $this->knownElements)) { drupal_set_message(t('Unknown node: @nodename', array('@nodename' => $node->nodeName))); } break; } } }
/** * Overrides CqQuestionAbstract::loadXml() */ public function loadXml(DOMElement $dom) { parent::loadXml($dom); module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); foreach ($dom->childNodes as $node) { if (in_array($node->nodeName, $this->SECTIONS)) { $this->parseSection($node); } else { $name = drupal_strtolower($node->nodeName); switch ($name) { case 'text': $this->text = cq_get_text_content($node, $this); break; case 'hint': $this->hints[] = CqFeedback::newCqFeedback($node, $this); break; case 'correct': $this->correctFeeback['all'] = CqFeedback::newCqFeedback($node, $this); break; default: if (!in_array($name, $this->knownElements)) { drupal_set_message(t('Unknown node: @nodename', array('@nodename' => $node->nodeName))); } break; } } } $attribs = $dom->attributes; $item = $attribs->getNamedItem('inlinefeedback'); if ($item !== NULL) { $this->inlineFeedback = (int) $item->value; } }
/** * Overrides CqQuestionAbstract::loadXml() */ public function loadXml(DOMElement $dom) { parent::loadXml($dom); module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); foreach ($dom->childNodes as $node) { $name = drupal_strtolower($node->nodeName); switch ($name) { case 'option': $this->options[] = new CqOption($node, $this); break; case 'text': $this->text = cq_get_text_content($node, $this); break; case 'prompt': $this->prompt = cq_get_text_content($node, $this); break; case 'hint': $this->hints[] = CqFeedback::newCqFeedback($node, $this); break; case 'correct': $this->correctFeeback = CqFeedback::newCqFeedback($node, $this); break; case 'mapping': // New style mapping, continues at match by default. $map = new CqMapping(); $map->generateFromNode($node, $this); if ($node->nodeName == 'sequence') { $map->setStopIfMatch(TRUE); } $this->mappings[] = $map; break; default: if (!in_array($name, $this->knownElements)) { drupal_set_message(t('Unknown node: @nodename', array('@nodename' => $node->nodeName))); } break; } } $attribs = $dom->attributes; $item = $attribs->getNamedItem('inlinefeedback'); if ($item !== NULL) { $this->inlineFeedback = (int) $item->value; } }
/** * Overrides CqQuestionAbstract::loadXml() */ public function loadXml(DOMElement $dom) { parent::loadXml($dom); module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); foreach ($dom->childNodes as $node) { $name = drupal_strtolower($node->nodeName); switch ($name) { case 'option': case 'item': $option = new CqOption($node, $this); if (is_numeric($option->getIdentifier())) { $this->sections[$option->getIdentifier()] = $option; $this->selectedBySection[$option->getIdentifier()] = array(); } if (isset($this->items[$option->getIdentifier()])) { drupal_set_message(t('Option identifier %identifier used more than once!', array('%identifier' => $option->getIdentifier())), 'warning'); } $this->items[$option->getIdentifier()] = $option; break; case 'sequence': // Old style sequence, would stop at first match. // Old style sequence, would stop at first match. case 'mapping': // New style mapping, continues at match by default. $map = new CqMapping(); $map->generateFromNode($node, $this); if ($node->nodeName == 'sequence') { $map->setStopIfMatch(TRUE); } $this->mappings[] = $map; break; case 'text': $this->text = cq_get_text_content($node, $this); break; case 'hint': $this->hints[] = CqFeedback::newCqFeedback($node, $this); break; case 'default': case 'startstate': $attribs = $node->attributes; $item = $attribs->getNamedItem('value'); if ($item !== NULL) { $this->defaultAnswer = $item->value; } break; default: if (!in_array($name, $this->knownElements)) { drupal_set_message(t('Unknown node: @nodename', array('@nodename' => $node->nodeName))); } break; } } $attribs = $dom->attributes; $item = $attribs->getNamedItem('duplicates'); if ($item !== NULL) { $this->duplicates = (int) $item->value; } $item = $attribs->getNamedItem('alignment'); if ($item !== NULL) { $this->alignment = $item->value; } $item = $attribs->getNamedItem('optionheight'); if ($item !== NULL) { $this->optionHeight = $item->value; } $answer = $this->userAnswer->getAnswer(); if (empty($answer)) { $this->userAnswer->setAnswer($this->defaultAnswer); } if (count($this->selectedBySection) == 0) { // No sections defined, make one. $this->selectedBySection[1] = array(); } }
/** * Overrides CqQuestionAbstract::loadXml() */ public function loadXml(DOMElement $dom) { parent::loadXml($dom); module_load_include('inc.php', 'closedquestion', 'lib/XmlLib'); $textNode = NULL; foreach ($dom->childNodes as $node) { $name = drupal_strtolower($node->nodeName); switch ($name) { case 'inlineoption': $option = new CqInlineOption($node, $this); if (isset($this->inlineOptions[$option->getIdentifier()])) { drupal_set_message(t('Inlineoption identifier %identifier used more than once!', array('%identifier' => $option->getIdentifier())), 'warning'); } $this->inlineOptions[$option->getIdentifier()] = $option; $this->inlineOptionsByGroup[$option->getGroup()][$option->getIdentifier()] = $option; break; case 'mapping': $map = new CqMapping(); $map->generateFromNode($node, $this); $this->mappings[] = $map; break; case 'text': $textNode = $node; break; case 'hint': $this->hints[] = CqFeedback::newCqFeedback($node, $this); break; default: if (!in_array($name, $this->knownElements)) { drupal_set_message(t('Unknown node: @nodename', array('@nodename' => $node->nodeName))); } break; } } if ($textNode != NULL) { $this->text = cq_get_text_content($textNode, $this); } }
/** * Recursively parse the children of an XML node and return the parts that are * valid html. The context CqQuestionInterface object can provide a list of node names * that are not html, but can be turned into html by the context object. * * If fullFilter is set, the final html will be filtered through the Drupal * filter set of the context CqQuestionInterface. * * @param DOMNode $parent * The XML node to parse the children of. * @param CqQuestionInterface $context * The question that can supply extra node names to handle, and drupal * filters. * @param boolean $fullFilter * Filter the result also through the drupal content filters? * @param boolean $delay * If true, some XML nodes are replaced with a [] tag so they can be * processed later. This can be used when not all data needed for full * processing is available yet. * Important: If delay is TRUE then the text is NOT filtered through the * drupal content filters untill after a call to cq_replace_tags(). * * @return string * The html contained in the node. */ function cq_get_text_content($parent, $context, $full_filter = TRUE, $delay = FALSE) { $retval = ''; $nodes = $parent->childNodes; foreach ($nodes as $node) { switch ($node->nodeName) { case '#comment': break; case '#text': case '#cdata-section': $retval .= $node->nodeValue; break; case 'formblock': $retval .= '<formblock/>'; break; case 'img': case 'br': $retval .= '<' . $node->nodeName . ' ' . cq_copy_attributes($node) . '/>'; break; case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': case 'sub': case 'sup': case 'p': case 'pre': case 'b': case 'i': case 'u': case 'strong': case 'em': case 'table': case 'a': case 'tr': case 'td': case 'th': case 'span': case 'div': case 'ul': case 'ol': case 'dl': case 'dt': case 'dd': case 'li': $retval .= '<' . $node->nodeName . ' ' . cq_copy_attributes($node) . '>' . cq_get_text_content($node, $context, FALSE, $delay) . '</' . $node->nodeName . '>'; break; default: $retval .= $node->nodeValue; break; } foreach ($context->getHandledTags() as $tag) { if (drupal_strtolower($node->nodeName) == drupal_strtolower($tag)) { $retval .= $context->handleNode($node, $delay); } } } if ($full_filter && !$delay) { $drupal_node = $context->getNode(); $lang = $drupal_node->language; if (!isset($drupal_node->body[$lang])) { $lang = 'und'; if (!isset($drupal_node->body[$lang])) { $langs = array_keys($drupal_node->body); $lang = $lang[0]; } } $retval = check_markup(trim($retval), $drupal_node->body[$lang][0]['format'], FALSE); } return $retval; }