/** * Creates a list. * * @param string $elementType The type of list to create (ul, ol). * @param array $elementAttributes The attributes of the list. * * @return string The object id of the created list. * @throws InvalidArgumentException In case the desired list cannot be created. */ protected function createList($elementType, array $elementAttributes = []) { if (!isset($this->listTypes[$elementType])) { throw new InvalidArgumentException('[HtmlListTag::createList()] Invalid element type found. ' . 'Supported element types: ' . implode(', ', array_keys($this->listTypes))); } $tagClass = $this->listTypes[$elementType]; // generate object id $objectId = XmlParser::generateUniqID(); /* @var $listObject DomNode */ $listObject = new $tagClass(); // add standard and user defined attributes $listObject->setObjectId($objectId); $listObject->setLanguage($this->language); $listObject->setContext($this->context); foreach ($elementAttributes as $key => $value) { $listObject->setAttribute($key, $value); } // add list element to DOM tree and call the onParseTime() method $listObject->setParentObject($this); $listObject->onParseTime(); // add new list element to children list $this->children[$objectId] = $listObject; // call the onAfterAppend() method $this->children[$objectId]->onAfterAppend(); // return object id for further addressing return $objectId; }
/** * Appends a tag instance (option or group) to the current select box. * * @param DomNode $tag The tag instance to add. * * @return DomNode The newly created instance. * * @author Christian Achatz * @version * Version 0.1, 21.10.2015<br /> */ protected function &addEntry(DomNode $tag) { $objectId = XmlParser::generateUniqID(); $this->children[$objectId] = $tag; $this->children[$objectId]->setObjectId($objectId); $this->children[$objectId]->setLanguage($this->language); $this->children[$objectId]->setContext($this->context); $this->children[$objectId]->onParseTime(); // inject parent object (=this) to guarantee native DOM tree environment $this->children[$objectId]->setParentObject($this); $this->children[$objectId]->onAfterAppend(); // add xml marker, necessary for transformation $this->content .= '<' . $objectId . ' />'; return $this->children[$objectId]; }
/** * Adds a list element. * * @param string $content The content of the element. * @param string $cssClass The name of the implementation class. * @param string $elementName The fully qualified class name of the tag implementation. */ protected function addElementInternal($content, $cssClass, $elementName) { $objectId = XmlParser::generateUniqID(); $this->children[$objectId] = new $elementName(); $this->children[$objectId]->setObjectId($objectId); $this->children[$objectId]->setContent($content); $this->children[$objectId]->setLanguage($this->language); $this->children[$objectId]->setContext($this->context); if (!empty($cssClass)) { $this->children[$objectId]->setAttribute('class', $cssClass); } $this->children[$objectId]->onParseTime(); // inject parent object (=this) to guarantee native DOM tree environment $this->children[$objectId]->setParentObject($this); $this->children[$objectId]->onAfterAppend(); // add xml marker, necessary for transformation $this->content .= '<' . $objectId . ' />'; }
/** * Test whether other options are unselected during selection of one * specific option in simple select boxes. */ public function testRemoveSelectedOptions() { $tag = new SelectBoxTag(); $selectedOption = new SelectBoxOptionTag(); $selectedOption->setAttribute('selected', 'selected'); $unselectedOption = new SelectBoxOptionTag(); $firstId = XmlParser::generateUniqID(); $secondId = XmlParser::generateUniqID(); $thirdId = XmlParser::generateUniqID(); // inject child structure as basis for un-selection $property = new ReflectionProperty(SelectBoxTag::class, 'children'); $property->setAccessible(true); $property->setValue($tag, [$firstId => clone $selectedOption->setObjectId($firstId), $secondId => clone $unselectedOption->setObjectId($secondId), $thirdId => clone $selectedOption->setObjectId($thirdId)]); $method = new ReflectionMethod(SelectBoxTag::class, 'removeSelectedOptions'); $method->setAccessible(true); $method->invokeArgs($tag, [$firstId]); /* @var $children DomNode[] */ $children = $property->getValue($tag); $this->assertEquals('selected', $children[$firstId]->getAttribute('selected')); $this->assertNull($children[$secondId]->getAttribute('selected')); $this->assertNull($children[$thirdId]->getAttribute('selected')); }
public function transform() { $t = Singleton::getInstance(BenchmarkTimer::class); /* @var $t BenchmarkTimer */ $t->start('(' . get_class($this) . ') ' . $this->getObjectId() . '::transform()'); // create copy, to preserve it! $content = $this->content; // execute the document controller if applicable if ($this->documentController instanceof DocumentController) { // start benchmark timer $id = '(' . get_class($this->documentController) . ') ' . XmlParser::generateUniqID() . '::transformContent()'; $t->start($id); // execute the document controller by using a standard method $this->documentController->transformContent(); $t->stop($id); } // transform child nodes and replace XML marker to place the output at the right position if (count($this->children) > 0) { foreach ($this->children as &$child) { $content = str_replace('<' . $child->getObjectId() . ' />', $child->transform(), $content); } } $t->stop('(' . get_class($this) . ') ' . $this->getObjectId() . '::transform()'); return $content; }
/** * Implements the onAfterAppend method from the ui_element class. * * @author Christian Achatz, Stephan Spiess * @version * Version 0.1, 20.06.2008<br /> * Version 0.2, 10.11.2008 (Added the "clearonerror" attribute. If set to "true", the field is cleared on error.)<br /> * Version 0.3, 04.01.2010 (Added the text_id attribute)<br /> * Version 0.4, 29.10.2012 (Bug-fix: attribute valmarkerclass is now applied to the inner form field to allow css field validation on error)<br /> */ public function onParseTime() { // create text field $this->textField = new TextFieldTag(); $this->textField->setObjectId(XmlParser::generateUniqID()); // prepare the text field $textClass = $this->getAttribute('text_class'); if ($textClass !== null) { $this->textField->setAttribute('class', $textClass); } $textStyle = $this->getAttribute('text_style'); if ($textStyle !== null) { $this->textField->setAttribute('style', $textStyle); } $textId = $this->getAttribute('text_id'); if ($textId !== null) { $this->textField->setAttribute('id', $textId); } // apply validation marker css class to provide validation markup capabilities $errorClass = $this->getAttribute(AbstractFormValidator::$CUSTOM_MARKER_CLASS_ATTRIBUTE); if ($errorClass !== null) { $this->textField->setAttribute(AbstractFormValidator::$CUSTOM_MARKER_CLASS_ATTRIBUTE, $errorClass); } $this->textFieldName = md5($this->getParentObject()->getAttribute('name') . '_captcha'); $this->textField->setAttribute('name', $this->textFieldName); $this->textField->setAttribute('maxlength', '5'); // apply the onParseTime method to guarantee native APF environment $this->textField->setLanguage($this->language); $this->textField->setContext($this->context); $this->textField->onParseTime(); // apply the onAfterAppend method to guarantee native APF environment $this->textField->setParentObject($this->getParentObject()); $this->textField->onAfterAppend(); // get the captcha string from session $session = $this->getRequest()->getSession(ShowCaptchaImageAction::SESSION_NAMESPACE); $this->captchaString = $session->load($this->textFieldName); $session->save($this->textFieldName, StringAssistant::generateCaptchaString(5)); }
/** * Adds a new form element to the child list. * * @param DomNode $parent The parent document to create the object in. * @param string $elementType Type of the element (e.g. "form:text") * @param array $elementAttributes associative list of form element attributes (e.g. name, to enable the validation and presetting feature) * * @return FormControl The created form element. * @throws FormException In case form element cannot be found. * * @author Christian Achatz, Danil Mihajluk * @version * Version 0.1, 06.09.2008<br /> * Version 0.2, 10.09.2008 (Added the $elementAttributes param)<br /> * Version 0.3, 12.11.2008 (Bug-fix: language and context initialisation were wrong)<br /> * Version 0.4, 23.08.2014 (ID#198: added unlimited form control nesting capability)<br /> * Version 0.5, 03.12.2015 (ID#279: changed code to rely on interface type rather than internal structure by Danil Mihajluk)<br /> */ protected function &createFormElement(DomNode &$parent, $elementType, array $elementAttributes = []) { $class = $this->getTagClass($elementType); if ($class === null) { return null; } // generate object id $objectId = XmlParser::generateUniqID(); // create new form element /* @var FormControl $child */ $child = new $class(); // add standard and user defined attributes $child->setObjectId($objectId); $child->setLanguage($this->getLanguage()); $child->setContext($this->getContext()); $child->setAttributes($elementAttributes); // add form element to DOM tree and call the onParseTime() method $child->setParentObject($parent); $child->onParseTime(); // call the onAfterAppend() method $child->onAfterAppend(); // add child to list $parent->getChildren()[$objectId] = $child; return $child; }
public function testGenerateUniqueId() { // reset counter to avoid influence from other unit tests using this static counter $counter = new ReflectionProperty(XmlParser::class, 'domNodeCounter'); $counter->setAccessible(true); $original = $counter->getValue(); $counter->setValue(1); // test starting point and format $id = XmlParser::generateUniqID(); $this->assertTrue(strlen($id) === 32); $this->assertEquals('node-000000000000000000000000001', $id); // test incrementation by 123 => expect counter at 124 for ($i = 1; $i < 124; $i++) { $id = XmlParser::generateUniqID(); } $this->assertEquals('node-000000000000000000000000124', $id); // reset to state before the test $counter->setValue($original); }
/** * Tests form transformation with a simple and a more sophisticated example. */ public function testTransform() { $form = new HtmlFormTag(); $form->setParentObject(new Document()); $form->setAction('/some-url'); // setup reflection property to be able to inject the DOM structure to test $children = new ReflectionProperty(Document::class, 'children'); $children->setAccessible(true); // set up group $group = new FormGroupTag(); $group->setObjectId(XmlParser::generateUniqID()); $group->setParentObject($form); // set up fields $user = new TextFieldTag(); $user->setObjectId(XmlParser::generateUniqID()); $user->setAttributes(['name' => 'user', 'value' => 'some user']); $user->setParentObject($form); $pass = new TextFieldTag(); $pass->setObjectId(XmlParser::generateUniqID()); $pass->setAttributes(['name' => 'pass', 'value' => 'some pass']); $pass->setParentObject($group); $button = new ButtonTag(); $button->setObjectId(XmlParser::generateUniqID()); $button->setAttributes(['name' => 'submit', 'value' => 'submit']); $button->setParentObject($form); // assemble group $children->setValue($group, array_merge($children->getValue($group), [$pass->getObjectId() => $pass])); $group->setContent('<div class="pass"><' . $pass->getObjectId() . ' /></div>'); // assemble form $children->setValue($form, [$user->getObjectId() => $user, $group->getObjectId() => $group, $button->getObjectId() => $button]); $form->setContent('<p><' . $user->getObjectId() . ' /></p><' . $group->getObjectId() . ' /><' . $button->getObjectId() . ' />'); // build children explicitly up and then check for HTML code... $actual = $form->transformForm(); // general structure $this->assertContains('<form ', $actual); $this->assertContains('</form>', $actual); $this->assertContains('action="/some-url"', $actual); $this->assertContains('<input type="text" name="user" value="some user" />', $actual); $this->assertContains('<input type="text" name="pass" value="some pass" />', $actual); $this->assertContains('<input type="submit" name="submit" value="submit" />', $actual); $this->assertContains('<p>', $actual); $this->assertContains('</p>', $actual); $this->assertContains('<div class="pass">', $actual); $this->assertContains('</div>', $actual); }