/** * Write a scalar value into the current stream. * * If the given value is a string, it will be output surrounded by double quotes (") characters. * * @param mixed $scalar A PHP scalar value or null. * @throws InvalidArgumentException If $scalar is not a PHP scalar value nor null. * @throws StreamAccessException If an error occurs while writing the scalar value. */ public function writeScalar($scalar) { if (Utils::isScalar($scalar) === false) { $msg = "A '" . gettype($scalar) . "' value is not a PHP scalar value nor null."; throw new InvalidArgumentException($msg); } try { if (is_int($scalar) === true) { $this->getStream()->write($scalar); } else { if (is_double($scalar) === true) { if (strpos('' . $scalar, '.') === false) { $scalar = $scalar . '.0'; } $this->getStream()->write($scalar); } else { if (is_string($scalar) === true) { $this->getStream()->write(PhpUtils::doubleQuotedPhpString($scalar)); } else { if (is_bool($scalar) === true) { $this->getStream()->write($scalar === true ? 'true' : 'false'); } else { if (is_null($scalar) === true) { $this->getStream()->write('null'); } } } } } } catch (StreamException $e) { $msg = "An error occured while writing the scalar value '{$scalar}'."; throw new StreamAccessException($msg, $this, 0, $e); } }
/** * Marshall an array into PHP source code. * * @throws PhpMarshallingException If something wrong happens during marshalling. */ public function marshall() { $ctx = $this->getContext(); $access = $ctx->getStreamAccess(); $array = $this->getToMarshall(); $args = new PhpArgumentCollection(); foreach ($array as $a) { if (PhpUtils::isScalar($a) === false) { $msg = "The PhpArrayMarshaller class only deals with PHP scalar values, object or resource given."; throw new PhpMarshallingException($msg); } $args[] = new PhpArgument($a); } $arrayVarName = $ctx->generateVariableName($array); $access->writeVariable($arrayVarName); $access->writeEquals($ctx->mustFormatOutput()); $access->writeFunctionCall('array', $args); $access->writeSemicolon($ctx->mustFormatOutput()); $ctx->pushOnVariableStack($arrayVarName); }
protected function includeChoiceComponent(QtiComponent $component, DOMDocumentFragment $rendering) { $choiceIndex = $this->choiceCounter; $choiceIdentifier = PhpUtils::doubleQuotedPhpString($component->getIdentifier()); $interactionIndex = $this->interactionCounter; $stateName = $this->getStateName(); $includeStmtCmt = $rendering->ownerDocument->createComment(' qtism-include($' . "{$stateName}, {$interactionIndex}, {$choiceIdentifier}, {$choiceIndex}): "); $endIncludeStmtCmt = $rendering->ownerDocument->createComment(' qtism-endinclude '); $rendering->insertBefore($includeStmtCmt, $rendering->firstChild); $rendering->appendChild($endIncludeStmtCmt); }
/** * Save the PhpDocument to a specific location. * * @param string $url A URL (Uniform Resource Locator) describing where to save the document. * @throws PhpStorageException If an error occurs while saving. */ public function save($url) { $stack = new SplStack(); $stack->push($this->getDocumentComponent()); // 1st/2nd pass marker. $marker = array(); try { // marshalling context. $stream = new MemoryStream(); $stream->open(); $streamAccess = new PhpStreamAccess($stream); $streamAccess->writeOpeningTag(); $ctx = new PhpMarshallingContext($streamAccess); $ctx->setFormatOutput(true); while (count($stack) > 0) { $component = $stack->pop(); $isMarked = in_array($component, $marker, true); if ($isMarked === false && $component instanceof QtiComponent) { // -- QtiComponent node, 1st pass. // Mark as explored. array_push($marker, $component); // Ask for a 2nd pass. $stack->push($component); // Let's look at the Bean properties and ask for a future exploration. $bean = new Bean($component, false, self::getBaseImplementation($component)); $ctorGetters = $bean->getConstructorGetters(); $bodyGetters = $bean->getGetters(true); $getters = array_reverse(array_merge($bodyGetters->getArrayCopy(), $ctorGetters->getArrayCopy())); foreach ($getters as $getter) { $stack->push(call_user_func(array($component, $getter->getName()))); } } else { if ($isMarked === false && ($component instanceof AbstractCollection && !$component instanceof Coords)) { // AbstractCollection node, 1st pass. // Mark as explored. array_push($marker, $component); // Ask for a 2nd pass. $stack->push($component); // Explore all values of the collection please! $values = array_reverse($component->getArrayCopy()); foreach ($values as $val) { $stack->push($val); } } else { if ($isMarked === true && $component instanceof QtiComponent) { // QtiComponent, 2nd pass. $marshaller = new PhpQtiComponentMarshaller($ctx, $component); $marshaller->setAsInstanceOf(self::getBaseImplementation($component)); if ($component === $this->getDocumentComponent()) { $marshaller->setVariableName('rootcomponent'); } $marshaller->marshall(); } else { if ($component instanceof QtiDatatype) { // Leaf node QtiDataType. $marshaller = new PhpQtiDatatypeMarshaller($ctx, $component); $marshaller->marshall(); } else { if ($isMarked === true && $component instanceof AbstractCollection) { // AbstractCollection, 2nd pass. $marshaller = new PhpCollectionMarshaller($ctx, $component); $marshaller->marshall(); } else { if (PhpUtils::isScalar($component) === true) { // Leaf node (QtiDatatype or PHP scalar (including the null value)). $marshaller = new PhpScalarMarshaller($ctx, $component); $marshaller->marshall(); } else { if (is_array($component) === true) { // Leaf node array. $marshaller = new PhpArrayMarshaller($ctx, $component); $marshaller->marshall(); } else { $msg = "Datatype '" . gettype($component) . "' cannot be handled by the PhpDocument::save() method."; throw new PhpStorageException($msg); } } } } } } } } file_put_contents($url, $stream->getBinary()); } catch (StreamAccessException $e) { $msg = "An error occured while writing the PHP source code stream."; throw new PhpStorageException($msg, 0, $e); } }
/** * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren() */ protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '') { $renderingEngine = $this->getRenderingEngine(); if ($renderingEngine !== null) { switch ($renderingEngine->getPrintedVariablePolicy()) { case AbstractMarkupRenderingEngine::CONTEXT_AWARE: $value = Utils::printVariable($this->getRenderingEngine()->getState(), $component->getIdentifier(), $component->getFormat(), $component->mustPowerForm(), $component->getBase(), $component->getIndex(), $component->getDelimiter(), $component->getField(), $component->getMappingIndicator()); $fragment->firstChild->appendChild($fragment->ownerDocument->createTextNode($value)); break; case AbstractMarkupRenderingEngine::TEMPLATE_ORIENTED: $base = $component->getBase(); $index = $component->getIndex(); $params = array('$' . $renderingEngine->getStateName(), PhpUtils::doubleQuotedPhpString($component->getIdentifier()), PhpUtils::doubleQuotedPhpString($component->getFormat()), $component->mustPowerForm() === true ? 'true' : 'false', is_int($base) === true ? $base : PhpUtils::doubleQuotedPhpString($base), is_int($index) === true ? $index : PhpUtils::doubleQuotedPhpString($index), PhpUtils::doubleQuotedPhpString($component->getDelimiter()), PhpUtils::doubleQuotedPhpString($component->getField()), PhpUtils::doubleQuotedPhpString($component->getMappingIndicator())); $value = " qtism-printVariable(" . implode(', ', $params) . ") "; $fragment->firstChild->appendChild($fragment->ownerDocument->createComment($value)); break; } } }
/** * Whether the represented argument is a PHP scalar value. * * @return boolean */ public function isScalar() { return Utils::isScalar($this->getValue()); }
/** * @dataProvider doubleQuotedPhpStringDataProvider */ public function testDoubleQuotedPhpString($input, $expected) { $this->assertEquals($expected, PhpUtils::doubleQuotedPhpString($input)); }
/** * Checks whether or not the given value is marshallable by this implementation. * * @return boolean */ protected function isMarshallable($toMarshall) { return PhpUtils::isScalar($toMarshall); }