Skip to content

Commit

Permalink
fixed generation of bbcode for uppercased tags
Browse files Browse the repository at this point in the history
  • Loading branch information
frastel committed Feb 13, 2017
1 parent ca659ac commit dc30728
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 6 deletions.
14 changes: 14 additions & 0 deletions JBBCode/CodeDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -243,6 +256,7 @@ public function getNestLimit()
*/
public function setTagName($tagName)
{
$this->originalTagName = $tagName;
$this->tagName = strtolower($tagName);
}

Expand Down
45 changes: 39 additions & 6 deletions JBBCode/ElementNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -61,6 +68,7 @@ public function setCodeDefinition(CodeDefinition $codeDef)
{
$this->codeDefinition = $codeDef;
$this->setTagName($codeDef->getTagName());
$this->originalTagName = $codeDef->getOriginalTagName();
}

/**
Expand All @@ -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.
*
Expand Down Expand Up @@ -123,14 +141,17 @@ 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 ($this->normalize($key) == $this->normalize($this->originalTagName)) {
continue;
}
else{
Expand All @@ -142,7 +163,7 @@ public function getAsBBCode()
foreach ($this->getChildren() as $child) {
$str .= $child->getAsBBCode();
}
$str .= "[/".$this->tagName."]";
$str .= "[/".$this->originalTagName."]";

return $str;
}
Expand Down Expand Up @@ -210,6 +231,18 @@ public function setAttribute($attribute)
$this->attribute = $attribute;
}

/**
* Normalizes incoming string for better comparison possibilities.
*
* @param string $str
*
* @return string
*/
private function normalize($str)
{
return strtolower($str);
}

/**
* Traverses the parse tree upwards, going from parent to parent, until it finds a
* parent who has the given tag name. Returns the parent with the matching tag name
Expand Down
76 changes: 76 additions & 0 deletions JBBCode/UppercasedCodeDefinitionSet.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace JBBCode;

require_once 'CodeDefinition.php';
require_once 'CodeDefinitionBuilder.php';
require_once 'CodeDefinitionSet.php';
require_once 'validators/CssColorValidator.php';
require_once 'validators/UrlValidator.php';

/**
* Provides a uppercased default set of common bbcode definitions.
*
* @author jbowens|frastel
*/
class UppercasedCodeDefinitionSet implements CodeDefinitionSet
{

/** @var CodeDefinition[] The default code definitions in this set. */
protected $definitions = array();

/**
* Constructs the default code definitions.
*/
public function __construct()
{
/* [B] bold tag */
$builder = new CodeDefinitionBuilder('B', '<strong>{param}</strong>');
$this->definitions[] = $builder->build();

/* [I] italics tag */
$builder = new CodeDefinitionBuilder('I', '<em>{param}</em>');
$this->definitions[] = $builder->build();

/* [U] underline tag */
$builder = new CodeDefinitionBuilder('U', '<u>{param}</u>');
$this->definitions[] = $builder->build();

$urlValidator = new \JBBCode\validators\UrlValidator();

/* [URL] link tag */
$builder = new CodeDefinitionBuilder('URL', '<a href="{param}">{param}</a>');
$builder->setParseContent(false)->setBodyValidator($urlValidator);
$this->definitions[] = $builder->build();

/* [URL=http://example.com] link tag */
$builder = new CodeDefinitionBuilder('URL', '<a href="{option}">{param}</a>');
$builder->setUseOption(true)->setParseContent(true)->setOptionValidator($urlValidator);
$this->definitions[] = $builder->build();

/* [IMG] image tag */
$builder = new CodeDefinitionBuilder('IMG', '<img src="{param}" />');
$builder->setUseOption(false)->setParseContent(false)->setBodyValidator($urlValidator);
$this->definitions[] = $builder->build();

/* [IMG=alt text] image tag */
$builder = new CodeDefinitionBuilder('IMG', '<img src="{param}" alt="{option}" />');
$builder->setUseOption(true)->setParseContent(false)->setBodyValidator($urlValidator);
$this->definitions[] = $builder->build();

/* [COLOR] color tag */
$builder = new CodeDefinitionBuilder('COLOR', '<span style="color: {option}">{param}</span>');
$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;
}
}
18 changes: 18 additions & 0 deletions JBBCode/tests/ElementNodeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
113 changes: 113 additions & 0 deletions JBBCode/tests/ParsingUpperCaseTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php


class ParsingUpperCaseTest extends PHPUnit_Framework_TestCase
{
/**
* @var JBBCode\Parser
*/
private $_parser;

protected function setUp()
{
$this->_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' => '<strong>this is bold</strong>',
'bbcode' => '[B]this is bold[/B]',
)
),
array(
'[B]this is bold',
array(
'text' => 'this is bold',
'html' => '<strong>this is bold</strong>',
'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 <strong>this is bold</strong> 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 <strong>bold tags</strong> and <em>italics</em> and things like <u>that</u>.',
'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 <a href="http://jbbcode.com">url</a> 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 <a href="http://jbbcode.com">http://jbbcode.com</a>.',
'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.')
);
}
}

0 comments on commit dc30728

Please sign in to comment.