From 3007a04188d53a26f67e46db40c50f911477101d Mon Sep 17 00:00:00 2001 From: Frank Stelzer Date: Mon, 13 Feb 2017 12:13:39 +0100 Subject: [PATCH] fixed generation of bbcode for uppercased tags --- JBBCode/CodeDefinition.php | 14 +++ JBBCode/ElementNode.php | 36 ++++++-- JBBCode/UppercasedCodeDefinitionSet.php | 76 ++++++++++++++++ JBBCode/tests/ElementNodeTest.php | 18 ++++ JBBCode/tests/ParsingUpperCaseTest.php | 113 ++++++++++++++++++++++++ JBBCode/tests/bootstrap.php | 3 +- 6 files changed, 251 insertions(+), 9 deletions(-) create mode 100644 JBBCode/UppercasedCodeDefinitionSet.php create mode 100644 JBBCode/tests/ParsingUpperCaseTest.php diff --git a/JBBCode/CodeDefinition.php b/JBBCode/CodeDefinition.php index 2594e42..b2e46c4 100644 --- a/JBBCode/CodeDefinition.php +++ b/JBBCode/CodeDefinition.php @@ -14,6 +14,9 @@ class CodeDefinition /** @var string NOTE: THIS PROPERTY SHOULD ALWAYS BE LOWERCASE; USE setTagName() TO ENSURE THIS */ protected $tagName; + /** @var string The original defined tag name. Needed for uppercased tags */ + protected $originalTagName; + /** @var boolean Whether or not this CodeDefinition uses an option parameter. */ protected $useOption; @@ -188,6 +191,16 @@ public function getTagName() return $this->tagName; } + /** + * Returns the original and not normalized tag name of this code definition + * + * @return string this definition's associated original tag name + */ + public function getOriginalTagName() + { + return $this->originalTagName; + } + /** * Returns the replacement text of this code definition. This usually has little, if any meaning if the * CodeDefinition class was extended. For default, html replacement CodeDefinitions this returns the html @@ -243,6 +256,7 @@ public function getNestLimit() */ public function setTagName($tagName) { + $this->originalTagName = $tagName; $this->tagName = strtolower($tagName); } diff --git a/JBBCode/ElementNode.php b/JBBCode/ElementNode.php index 4eb6b8a..e915861 100644 --- a/JBBCode/ElementNode.php +++ b/JBBCode/ElementNode.php @@ -16,6 +16,13 @@ class ElementNode extends Node /** @var string The tagname of this element, for i.e. "b" in [b]bold[/b] */ protected $tagName; + /** + * The original defined tag name of this element, for i.e. "b" in [b]bold[/b] + * or [B]bold[/B] + * @var string + */ + protected $originalTagName; + /** @var string[] The attributes, if any, of this element node */ protected $attribute; @@ -61,6 +68,7 @@ public function setCodeDefinition(CodeDefinition $codeDef) { $this->codeDefinition = $codeDef; $this->setTagName($codeDef->getTagName()); + $this->originalTagName = $codeDef->getOriginalTagName(); } /** @@ -83,6 +91,16 @@ public function getAttribute() return $this->attribute; } + /** + * Returns if element has any children. + * + * @return bool + */ + public function hasChildren() + { + return (bool) $this->children; + } + /** * Returns all the children of this element. * @@ -123,17 +141,19 @@ public function getAsText() */ public function getAsBBCode() { - $str = "[".$this->tagName; + $str = "[".$this->originalTagName; if (!empty($this->attribute)) { - if(isset($this->attribute[$this->tagName])) { - $str .= "=".$this->attribute[$this->tagName]; + if (isset($this->attribute[$this->originalTagName])) { + // avoid to generate something like [FOO= bar=baz]...[/FOO] + if (!empty($this->attribute[$this->originalTagName]) || !$this->hasChildren()) { + $str .= "=".$this->attribute[$this->originalTagName]; + } } - foreach($this->attribute as $key => $value){ - if($key == $this->tagName){ + foreach ($this->attribute as $key => $value) { + if (strcasecmp($key, $this->originalTagName) === 0) { continue; - } - else{ + } else{ $str .= " ".$key."=" . $value; } } @@ -142,7 +162,7 @@ public function getAsBBCode() foreach ($this->getChildren() as $child) { $str .= $child->getAsBBCode(); } - $str .= "[/".$this->tagName."]"; + $str .= "[/".$this->originalTagName."]"; return $str; } diff --git a/JBBCode/UppercasedCodeDefinitionSet.php b/JBBCode/UppercasedCodeDefinitionSet.php new file mode 100644 index 0000000..3a106c9 --- /dev/null +++ b/JBBCode/UppercasedCodeDefinitionSet.php @@ -0,0 +1,76 @@ +{param}'); + $this->definitions[] = $builder->build(); + + /* [I] italics tag */ + $builder = new CodeDefinitionBuilder('I', '{param}'); + $this->definitions[] = $builder->build(); + + /* [U] underline tag */ + $builder = new CodeDefinitionBuilder('U', '{param}'); + $this->definitions[] = $builder->build(); + + $urlValidator = new \JBBCode\validators\UrlValidator(); + + /* [URL] link tag */ + $builder = new CodeDefinitionBuilder('URL', '{param}'); + $builder->setParseContent(false)->setBodyValidator($urlValidator); + $this->definitions[] = $builder->build(); + + /* [URL=http://example.com] link tag */ + $builder = new CodeDefinitionBuilder('URL', '{param}'); + $builder->setUseOption(true)->setParseContent(true)->setOptionValidator($urlValidator); + $this->definitions[] = $builder->build(); + + /* [IMG] image tag */ + $builder = new CodeDefinitionBuilder('IMG', ''); + $builder->setUseOption(false)->setParseContent(false)->setBodyValidator($urlValidator); + $this->definitions[] = $builder->build(); + + /* [IMG=alt text] image tag */ + $builder = new CodeDefinitionBuilder('IMG', '{option}'); + $builder->setUseOption(true)->setParseContent(false)->setBodyValidator($urlValidator); + $this->definitions[] = $builder->build(); + + /* [COLOR] color tag */ + $builder = new CodeDefinitionBuilder('COLOR', '{param}'); + $builder->setUseOption(true)->setOptionValidator(new \JBBCode\validators\CssColorValidator()); + $this->definitions[] = $builder->build(); + } + + /** + * Returns an array of the default code definitions. + * + * @return CodeDefinition[] + */ + public function getCodeDefinitions() + { + return $this->definitions; + } +} diff --git a/JBBCode/tests/ElementNodeTest.php b/JBBCode/tests/ElementNodeTest.php index 0230cbc..d97617b 100644 --- a/JBBCode/tests/ElementNodeTest.php +++ b/JBBCode/tests/ElementNodeTest.php @@ -76,4 +76,22 @@ public function testGetAsBBCode() )); $this->assertEquals('[foo=bar bar=baz][/foo]', $this->_elementNode->getAsBBCode()); } + + public function testGetAsBBCodeUppercased() + { + $builder = new JBBCode\CodeDefinitionBuilder('FOO', 'bar'); + $codeDefinition = $builder->build(); + $this->_elementNode->setCodeDefinition($codeDefinition); + $this->assertEquals('[FOO][/FOO]', $this->_elementNode->getAsBBCode()); + + $this->_elementNode->setAttribute(array('bar' => 'baz')); + $this->assertEquals('[FOO bar=baz][/FOO]', $this->_elementNode->getAsBBCode()); + + /** @ticket 55 */ + $this->_elementNode->setAttribute(array( + 'bar' => 'baz', + 'FOO' => 'bar' + )); + $this->assertEquals('[FOO=bar bar=baz][/FOO]', $this->_elementNode->getAsBBCode()); + } } diff --git a/JBBCode/tests/ParsingUpperCaseTest.php b/JBBCode/tests/ParsingUpperCaseTest.php new file mode 100644 index 0000000..976a583 --- /dev/null +++ b/JBBCode/tests/ParsingUpperCaseTest.php @@ -0,0 +1,113 @@ +_parser = new JBBCode\Parser(); + $this->_parser->addCodeDefinitionSet(new JBBCode\UppercasedCodeDefinitionSet()); + } + + /** + * @param string $code + * @param string[] $expected + * @dataProvider textCodeProvider + */ + public function testParse($code, $expected) + { + $parser = $this->_parser->parse($code); + $this->assertEquals($expected['text'], $parser->getAsText()); + $this->assertEquals($expected['html'], $parser->getAsHTML()); + $this->assertEquals($expected['bbcode'], $parser->getAsBBCode()); + } + + public function textCodeProvider() + { + return array( + array( + 'foo', + array( + 'text' => 'foo', + 'html' => 'foo', + 'bbcode' => 'foo', + ) + ), + array( + '[B]this is bold[/B]', + array( + 'text' => 'this is bold', + 'html' => 'this is bold', + 'bbcode' => '[B]this is bold[/B]', + ) + ), + array( + '[B]this is bold', + array( + 'text' => 'this is bold', + 'html' => 'this is bold', + 'bbcode' => '[B]this is bold[/B]', + ) + ), + array( + 'buffer text [B]this is bold[/B] buffer text', + array( + 'text' => 'buffer text this is bold buffer text', + 'html' => 'buffer text this is bold buffer text', + 'bbcode' => 'buffer text [B]this is bold[/B] buffer text', + ) + ), + array( + 'this is some text with [B]bold tags[/B] and [I]italics[/I] and things like [U]that[/U].', + array( + 'text' => 'this is some text with bold tags and italics and things like that.', + 'html' => 'this is some text with bold tags and italics and things like that.', + 'bbcode' => 'this is some text with [B]bold tags[/B] and [I]italics[/I] and things like [U]that[/U].', + ) + ), + array( + 'This contains a [URL=http://jbbcode.com]url[/URL] which uses an option.', + array( + 'text' => 'This contains a url which uses an option.', + 'html' => 'This contains a url which uses an option.', + 'bbcode' => 'This contains a [URL=http://jbbcode.com]url[/URL] which uses an option.', + ) + ), + array( + 'This doesn\'t use the url option [URL]http://jbbcode.com[/URL].', + array( + 'text' => 'This doesn\'t use the url option http://jbbcode.com.', + 'html' => 'This doesn\'t use the url option http://jbbcode.com.', + 'bbcode' => 'This doesn\'t use the url option [URL]http://jbbcode.com[/URL].', + ) + ), + ); + } + + /** + * @param string $code + * + * @dataProvider textCodeProviderWithInvalidCode + */ + public function testParseInvalidCode($code) + { + $parser = $this->_parser->parse($code); + $this->assertEquals($code, $parser->getAsText()); + $this->assertEquals($code, $parser->getAsHTML()); + $this->assertEquals($code, $parser->getAsBBCode()); + } + + public function textCodeProviderWithInvalidCode() + { + return array( + array('This is some text with an [URL]I N V A L I D[/URL] URL tag.'), + array('This is some text with an [URL foo=bar]INVALID[/URL] URL tag.'), + array('This is some text with an invalid [URL=INVALID]URL[/URL] tag.') + ); + } +} diff --git a/JBBCode/tests/bootstrap.php b/JBBCode/tests/bootstrap.php index 797237a..542cb0d 100644 --- a/JBBCode/tests/bootstrap.php +++ b/JBBCode/tests/bootstrap.php @@ -1,2 +1,3 @@