Update composer dependencies

This commit is contained in:
Kijin Sung 2020-04-08 00:10:06 +09:00
parent 255352df62
commit 61d2e8c141
419 changed files with 37794 additions and 5489 deletions

3
vendor/jbbcode/jbbcode/.coveralls.yml vendored Normal file
View file

@ -0,0 +1,3 @@
src_dir: .
coverage_clover: clover.xml
json_path: clover.json

View file

@ -1,2 +1,4 @@
composer.lock
vendor
clover.xml
clover.json

28
vendor/jbbcode/jbbcode/.travis.yml vendored Normal file
View file

@ -0,0 +1,28 @@
language: php
php:
- 5.6
- hhvm
- nightly
matrix:
fast_finish: true
allow_failures:
- php: hhvm
- php: nightly
git:
depth: 10
cache:
directories:
- vendor
- $HOME/.composer/cache
sudo: false
install:
- composer self-update
- composer install --prefer-source --no-interaction
after_success:
- php vendor/bin/coveralls -v

View file

@ -11,28 +11,28 @@ namespace JBBCode;
*/
class CodeDefinition
{
/* NOTE: THIS PROPERTY SHOULD ALWAYS BE LOWERCASE; USE setTagName() TO ENSURE THIS */
/** @var string NOTE: THIS PROPERTY SHOULD ALWAYS BE LOWERCASE; USE setTagName() TO ENSURE THIS */
protected $tagName;
/* Whether or not this CodeDefinition uses an option parameter. */
/** @var boolean Whether or not this CodeDefinition uses an option parameter. */
protected $useOption;
/* The replacement text to be used for simple CodeDefinitions */
/** @var string The replacement text to be used for simple CodeDefinitions */
protected $replacementText;
/* Whether or not to parse elements of this definition's contents */
/** @var boolean Whether or not to parse elements of this definition's contents */
protected $parseContent;
/* How many of this element type may be nested within each other */
/** @var integer How many of this element type may be nested within each other */
protected $nestLimit;
/* How many of this element type have been seen */
/** @var integer How many of this element type have been seen */
protected $elCounter;
/* The input validator to run options through */
/** @var array[string]InputValidator The input validators to run options through */
protected $optionValidator;
/* The input validator to run the body ({param}) through */
/** @var InputValidator The input validator to run the body ({param}) through */
protected $bodyValidator;
/**
@ -42,7 +42,7 @@ class CodeDefinition
$parseContent = true, $nestLimit = -1, $optionValidator = array(),
$bodyValidator = null)
{
$def = new CodeDefinition();
$def = new CodeDefinition();
$def->elCounter = 0;
$def->setTagName($tagName);
$def->setReplacementText($replacementText);
@ -52,10 +52,10 @@ class CodeDefinition
$def->optionValidator = $optionValidator;
$def->bodyValidator = $bodyValidator;
return $def;
}
}
/**
* Constructs a new CodeDefinition.
* Constructs a new CodeDefinition.
*
* This constructor is deprecated. You should use the static construct() method or the
* CodeDefinitionBuilder class to construct a new CodeDefiniton.
@ -78,16 +78,16 @@ class CodeDefinition
* Determines if the arguments to the given element are valid based on
* any validators attached to this CodeDefinition.
*
* @param $el the ElementNode to validate
* @return true if the ElementNode's {option} and {param} are OK, false if they're not
* @param ElementNode $el the ElementNode to validate
* @return boolean true if the ElementNode's {option} and {param} are OK, false if they're not
*/
public function hasValidInputs(ElementNode $el)
{
if ($this->usesOption() && $this->optionValidator) {
$att = $el->getAttribute();
foreach($att as $name => $value){
if(isset($this->optionValidator[$name]) && !$this->optionValidator[$name]->validate($value)){
foreach ($att as $name => $value) {
if (isset($this->optionValidator[$name]) && !$this->optionValidator[$name]->validate($value)) {
return false;
}
}
@ -103,7 +103,7 @@ class CodeDefinition
/* The content of the element is not valid. */
return false;
}
}
}
return true;
}
@ -113,9 +113,9 @@ class CodeDefinition
* markup of the element. This is a commonly overridden class for custom CodeDefinitions
* so that the content can be directly manipulated.
*
* @param $el the element to return an html representation of
* @param ElementNode $el the element to return an html representation of
*
* @return the parsed html of this element (INCLUDING ITS CHILDREN)
* @return string the parsed html of this element (INCLUDING ITS CHILDREN)
*/
public function asHtml(ElementNode $el)
{
@ -127,12 +127,11 @@ class CodeDefinition
if ($this->usesOption()) {
$options = $el->getAttribute();
if(count($options)==1){
if (count($options)==1) {
$vals = array_values($options);
$html = str_ireplace('{option}', reset($vals), $html);
}
else{
foreach($options as $key => $val){
} else {
foreach ($options as $key => $val) {
$html = str_ireplace('{' . $key . '}', $val, $html);
}
}
@ -145,15 +144,18 @@ class CodeDefinition
return $html;
}
protected function getContent(ElementNode $el){
protected function getContent(ElementNode $el)
{
if ($this->parseContent()) {
$content = "";
foreach ($el->getChildren() as $child)
foreach ($el->getChildren() as $child) {
$content .= $child->getAsHTML();
}
} else {
$content = "";
foreach ($el->getChildren() as $child)
foreach ($el->getChildren() as $child) {
$content .= $child->getAsBBCode();
}
}
return $content;
}
@ -162,9 +164,9 @@ class CodeDefinition
* Accepts an ElementNode that is defined by this CodeDefinition and returns the text
* representation of the element. This may be overridden by a custom CodeDefinition.
*
* @param $el the element to return a text representation of
* @param ElementNode $el the element to return a text representation of
*
* @return the text representation of $el
* @return string the text representation of $el
*/
public function asText(ElementNode $el)
{
@ -173,15 +175,16 @@ class CodeDefinition
}
$s = "";
foreach ($el->getChildren() as $child)
foreach ($el->getChildren() as $child) {
$s .= $child->getAsText();
}
return $s;
}
/**
* Returns the tag name of this code definition
*
* @return this definition's associated tag name
* @return string this definition's associated tag name
*/
public function getTagName()
{
@ -193,7 +196,7 @@ class CodeDefinition
* CodeDefinition class was extended. For default, html replacement CodeDefinitions this returns the html
* markup for the definition.
*
* @return the replacement text of this CodeDefinition
* @return string the replacement text of this CodeDefinition
*/
public function getReplacementText()
{
@ -203,7 +206,7 @@ class CodeDefinition
/**
* Returns whether or not this CodeDefinition uses the optional {option}
*
* @return true if this CodeDefinition uses the option, false otherwise
* @return boolean true if this CodeDefinition uses the option, false otherwise
*/
public function usesOption()
{
@ -211,10 +214,10 @@ class CodeDefinition
}
/**
* Returns whether or not this CodeDefnition parses elements contained within it,
* Returns whether or not this CodeDefinition parses elements contained within it,
* or just treats its children as text.
*
* @return true if this CodeDefinition parses elements contained within itself
* @return boolean true if this CodeDefinition parses elements contained within itself
*/
public function parseContent()
{
@ -226,6 +229,8 @@ class CodeDefinition
* nested together. If after parsing elements are nested beyond this limit, the
* subtrees formed by those nodes will be removed from the parse tree. A nest
* limit of -1 signifies no limit.
*
* @return integer
*/
public function getNestLimit()
{
@ -237,7 +242,7 @@ class CodeDefinition
*
* @deprecated
*
* @param the new tag name of this definition
* @param string $tagName the new tag name of this definition
*/
public function setTagName($tagName)
{
@ -249,7 +254,7 @@ class CodeDefinition
*
* @deprecated
*
* @param the new replacement text
* @param string $txt the new replacement text
*/
public function setReplacementText($txt)
{

View file

@ -13,19 +13,26 @@ require_once "CodeDefinition.php";
class CodeDefinitionBuilder
{
/** @var string */
protected $tagName;
/** @var boolean */
protected $useOption = false;
/** @var string */
protected $replacementText;
/** @var boolean */
protected $parseContent = true;
/** @var integer */
protected $nestLimit = -1;
/** @var array[string]InputValidator The input validators to run options through */
protected $optionValidator = array();
/** @var InputValidator */
protected $bodyValidator = null;
/**
* Construct a CodeDefinitionBuilder.
*
* @param $tagName the tag name of the definition to build
* @param $replacementText the replacement text of the definition to build
* @param string $tagName the tag name of the definition to build
* @param string $replacementText the replacement text of the definition to build
*/
public function __construct($tagName, $replacementText)
{
@ -36,7 +43,8 @@ class CodeDefinitionBuilder
/**
* Sets the tag name the CodeDefinition should be built with.
*
* @param $tagName the tag name for the new CodeDefinition
* @param string $tagName the tag name for the new CodeDefinition
* @return self
*/
public function setTagName($tagName)
{
@ -48,7 +56,8 @@ class CodeDefinitionBuilder
* Sets the replacement text that the new CodeDefinition should be
* built with.
*
* @param $replacementText the replacement text for the new CodeDefinition
* @param string $replacementText the replacement text for the new CodeDefinition
* @return self
*/
public function setReplacementText($replacementText)
{
@ -60,7 +69,8 @@ class CodeDefinitionBuilder
* Set whether or not the built CodeDefinition should use the {option} bbcode
* argument.
*
* @param $option ture iff the definition includes an option
* @param boolean $option true iff the definition includes an option
* @return self
*/
public function setUseOption($option)
{
@ -72,7 +82,8 @@ class CodeDefinitionBuilder
* Set whether or not the built CodeDefinition should allow its content
* to be parsed and evaluated as bbcode.
*
* @param $parseContent true iff the content should be parsed
* @param boolean $parseContent true iff the content should be parsed
* @return self
*/
public function setParseContent($parseContent)
{
@ -83,12 +94,13 @@ class CodeDefinitionBuilder
/**
* Sets the nest limit for this code definition.
*
* @param $nestLimit a positive integer, or -1 if there is no limit.
* @param integer $limit a positive integer, or -1 if there is no limit.
* @throws \InvalidArgumentException if the nest limit is invalid
* @return self
*/
public function setNestLimit($limit)
{
if(!is_int($limit) || ($limit <= 0 && -1 != $limit)) {
if (!is_int($limit) || ($limit <= 0 && -1 != $limit)) {
throw new \InvalidArgumentException("A nest limit must be a positive integer " .
"or -1.");
}
@ -99,11 +111,12 @@ class CodeDefinitionBuilder
/**
* Sets the InputValidator that option arguments should be validated with.
*
* @param $validator the InputValidator instance to use
* @param InputValidator $validator the InputValidator instance to use
* @return self
*/
public function setOptionValidator(\JBBCode\InputValidator $validator, $option=null)
{
if(empty($option)){
if (empty($option)) {
$option = $this->tagName;
}
$this->optionValidator[$option] = $validator;
@ -113,7 +126,8 @@ class CodeDefinitionBuilder
/**
* Sets the InputValidator that body ({param}) text should be validated with.
*
* @param $validator the InputValidator instance to use
* @param InputValidator $validator the InputValidator instance to use
* @return self
*/
public function setBodyValidator(\JBBCode\InputValidator $validator)
{
@ -123,6 +137,7 @@ class CodeDefinitionBuilder
/**
* Removes the attached option validator if one is attached.
* @return self
*/
public function removeOptionValidator()
{
@ -132,6 +147,7 @@ class CodeDefinitionBuilder
/**
* Removes the attached body validator if one is attached.
* @return self
*/
public function removeBodyValidator()
{
@ -142,7 +158,7 @@ class CodeDefinitionBuilder
/**
* Builds a CodeDefinition with the current state of the builder.
*
* @return a new CodeDefinition instance
* @return CodeDefinition a new CodeDefinition instance
*/
public function build()
{
@ -155,6 +171,4 @@ class CodeDefinitionBuilder
$this->bodyValidator);
return $definition;
}
}

View file

@ -7,7 +7,7 @@ require_once 'CodeDefinition.php';
use JBBCode\CodeDefinition;
/**
* An interface for sets of code definitons.
* An interface for sets of code definitions.
*
* @author jbowens
*/
@ -16,7 +16,7 @@ interface CodeDefinitionSet
/**
* Retrieves the CodeDefinitions within this set as an array.
* @return CodeDefinition[]
*/
public function getCodeDefinitions();
}

View file

@ -16,7 +16,7 @@ require_once 'validators/UrlValidator.php';
class DefaultCodeDefinitionSet implements CodeDefinitionSet
{
/* The default code definitions in this set. */
/** @var CodeDefinition[] The default code definitions in this set. */
protected $definitions = array();
/**
@ -26,50 +26,51 @@ class DefaultCodeDefinitionSet implements CodeDefinitionSet
{
/* [b] bold tag */
$builder = new CodeDefinitionBuilder('b', '<strong>{param}</strong>');
array_push($this->definitions, $builder->build());
$this->definitions[] = $builder->build();
/* [i] italics tag */
$builder = new CodeDefinitionBuilder('i', '<em>{param}</em>');
array_push($this->definitions, $builder->build());
$this->definitions[] = $builder->build();
/* [u] underline tag */
$builder = new CodeDefinitionBuilder('u', '<u>{param}</u>');
array_push($this->definitions, $builder->build());
$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);
array_push($this->definitions, $builder->build());
$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);
array_push($this->definitions, $builder->build());
$this->definitions[] = $builder->build();
/* [img] image tag */
$builder = new CodeDefinitionBuilder('img', '<img src="{param}" />');
$builder->setUseOption(false)->setParseContent(false)->setBodyValidator($urlValidator);
array_push($this->definitions, $builder->build());
$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);
array_push($this->definitions, $builder->build());
$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());
array_push($this->definitions, $builder->build());
$this->definitions[] = $builder->build();
}
/**
* Returns an array of the default code definitions.
*
* @return CodeDefinition[]
*/
public function getCodeDefinitions()
public function getCodeDefinitions()
{
return $this->definitions;
}
}

View file

@ -5,7 +5,7 @@ namespace JBBCode;
require_once 'ElementNode.php';
/**
* A DocumentElement object represents the root of a document tree. All
* A DocumentElement object represents the root of a document tree. All
* documents represented by this document model should have one as its root.
*
* @author jbowens
@ -19,7 +19,6 @@ class DocumentElement extends ElementNode
{
parent::__construct();
$this->setTagName("Document");
$this->setNodeId(0);
}
/**
@ -28,12 +27,12 @@ class DocumentElement extends ElementNode
*
* Returns the BBCode representation of this document
*
* @return this document's bbcode representation
* @return string this document's bbcode representation
*/
public function getAsBBCode()
{
$s = "";
foreach($this->getChildren() as $child){
foreach ($this->getChildren() as $child) {
$s .= $child->getAsBBCode();
}
@ -48,13 +47,14 @@ class DocumentElement extends ElementNode
* children, so getAsHTML() simply iterates through the document's children,
* returning their html.
*
* @return the HTML representation of this document
* @return string the HTML representation of this document
*/
public function getAsHTML()
{
$s = "";
foreach($this->getChildren() as $child)
foreach ($this->getChildren() as $child) {
$s .= $child->getAsHTML();
}
return $s;
}
@ -63,5 +63,4 @@ class DocumentElement extends ElementNode
{
$visitor->visitDocumentElement($this);
}
}

View file

@ -13,19 +13,19 @@ require_once 'Node.php';
*/
class ElementNode extends Node
{
/* The tagname of this element, for i.e. "b" in [b]bold[/b] */
/** @var string The tagname of this element, for i.e. "b" in [b]bold[/b] */
protected $tagName;
/* The attribute, if any, of this element node */
/** @var string[] The attributes, if any, of this element node */
protected $attribute;
/* The child nodes contained within this element */
/** @var Node[] The child nodes contained within this element */
protected $children;
/* The code definition that defines this element's behavior */
/** @var CodeDefinition The code definition that defines this element's behavior */
protected $codeDefinition;
/* How deeply this node is nested */
/** @var integer How deeply this node is nested */
protected $nestDepth;
/**
@ -37,12 +37,6 @@ class ElementNode extends Node
$this->nestDepth = 0;
}
/**
* Accepts the given NodeVisitor. This is part of an implementation
* of the Visitor pattern.
*
* @param $nodeVisitor the visitor attempting to visit this node
*/
public function accept(NodeVisitor $nodeVisitor)
{
$nodeVisitor->visitElementNode($this);
@ -51,7 +45,7 @@ class ElementNode extends Node
/**
* Gets the CodeDefinition that defines this element.
*
* @return this element's code definition
* @return CodeDefinition this element's code definition
*/
public function getCodeDefinition()
{
@ -61,7 +55,7 @@ class ElementNode extends Node
/**
* Sets the CodeDefinition that defines this element.
*
* @param codeDef the code definition that defines this element node
* @param CodeDefinition $codeDef the code definition that defines this element node
*/
public function setCodeDefinition(CodeDefinition $codeDef)
{
@ -72,7 +66,7 @@ class ElementNode extends Node
/**
* Returns the tag name of this element.
*
* @return the element's tag name
* @return string the element's tag name
*/
public function getTagName()
{
@ -82,7 +76,7 @@ class ElementNode extends Node
/**
* Returns the attribute (used as the option in bbcode definitions) of this element.
*
* @return the attribute of this element
* @return array the attributes of this element
*/
public function getAttribute()
{
@ -92,7 +86,7 @@ class ElementNode extends Node
/**
* Returns all the children of this element.
*
* @return an array of this node's child nodes
* @return Node[] an array of this node's child nodes
*/
public function getChildren()
{
@ -105,7 +99,7 @@ class ElementNode extends Node
*
* Returns the element as text (not including any bbcode markup)
*
* @return the plain text representation of this node
* @return string the plain text representation of this node
*/
public function getAsText()
{
@ -113,8 +107,9 @@ class ElementNode extends Node
return $this->codeDefinition->asText($this);
} else {
$s = "";
foreach ($this->getChildren() as $child)
foreach ($this->getChildren() as $child) {
$s .= $child->getAsText();
}
return $s;
}
}
@ -125,18 +120,20 @@ class ElementNode extends Node
*
* Returns the element as bbcode (with all unclosed tags closed)
*
* @return the bbcode representation of this element
* @return string the bbcode representation of this element
*/
public function getAsBBCode()
{
$str = "[".$this->tagName;
if (!empty($this->attribute)) {
if (isset($this->attribute[$this->tagName])) {
$str .= "=".$this->attribute[$this->tagName];
}
foreach($this->attribute as $key => $value){
if($key == $this->tagName){
$str .= "=".$value;
}
else{
foreach ($this->attribute as $key => $value) {
if ($key == $this->tagName) {
continue;
} else {
$str .= " ".$key."=" . $value;
}
}
@ -156,11 +153,11 @@ class ElementNode extends Node
*
* Returns the element as html with all replacements made
*
* @return the html representation of this node
* @return string the html representation of this node
*/
public function getAsHTML()
{
if($this->codeDefinition) {
if ($this->codeDefinition) {
return $this->codeDefinition->asHtml($this);
} else {
return "";
@ -168,35 +165,36 @@ class ElementNode extends Node
}
/**
* Adds a child to this node's content. A child may be a TextNode, or
* another ElementNode... or anything else that may extend the
* Adds a child to this node's content. A child may be a TextNode, or
* another ElementNode... or anything else that may extend the
* abstract Node class.
*
* @param child the node to add as a child
* @param Node $child the node to add as a child
*/
public function addChild(Node $child)
{
array_push($this->children, $child);
$this->children[] = $child;
$child->setParent($this);
}
/**
* Removes a child from this node's contnet.
* Removes a child from this node's content.
*
* @param child the child node to remove
* @param Node $child the child node to remove
*/
public function removeChild(Node $child)
{
foreach ($this->children as $key => $value) {
if ($value == $child)
if ($value == $child) {
unset($this->children[$key]);
}
}
}
/**
* Sets the tag name of this element node.
*
* @param tagName the element's new tag name
* @param string $tagName the element's new tag name
*/
public function setTagName($tagName)
{
@ -206,7 +204,7 @@ class ElementNode extends Node
/**
* Sets the attribute (option) of this element node.
*
* @param attribute the attribute of this element node
* @param string[] $attribute the attribute(s) of this element node
*/
public function setAttribute($attribute)
{
@ -214,13 +212,13 @@ class ElementNode extends Node
}
/**
* Traverses the parse tree upwards, going from parent to parent, until it finds a
* 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
* if it exists, otherwise returns null.
*
* @param str the tag name to search for
* @param string $str the tag name to search for
*
* @return the closest parent with the given tag name
* @return ElementNode|null the closest parent with the given tag name
*/
public function closestParentOfType($str)
{
@ -237,5 +235,4 @@ class ElementNode extends Node
return $currentEl;
}
}
}

View file

@ -14,7 +14,8 @@ interface InputValidator
/**
* Returns true iff the given input is valid, false otherwise.
* @param string $input
* @return boolean
*/
public function validate($input);
public function validate($input);
}

View file

@ -11,26 +11,13 @@ namespace JBBCode;
*/
abstract class Node
{
/* Pointer to the parent node of this node */
/** @var Node Pointer to the parent node of this node */
protected $parent;
/* The node id of this node */
protected $nodeid;
/**
* Returns the node id of this node. (Not really ever used. Dependent upon the parse tree the node exists within.)
*
* @return this node's id
*/
public function getNodeId()
{
return $this->nodeid;
}
/**
* Returns this node's immediate parent.
*
* @return the node's parent
* @return Node the node's parent
*/
public function getParent()
{
@ -40,7 +27,7 @@ abstract class Node
/**
* Determines if this node has a parent.
*
* @return true if this node has a parent, false otherwise
* @return boolean true if this node has a parent, false otherwise
*/
public function hasParent()
{
@ -51,7 +38,7 @@ abstract class Node
* Returns true if this is a text node. Returns false otherwise.
* (Overridden by TextNode to return true)
*
* @return true if this node is a text node
* @return boolean true if this node is a text node
*/
public function isTextNode()
{
@ -59,51 +46,41 @@ abstract class Node
}
/**
* Accepts a NodeVisitor
* Accepts the given NodeVisitor. This is part of an implementation
* of the Visitor pattern.
*
* @param nodeVisitor the NodeVisitor traversing the graph
* @param NodeVisitor $nodeVisitor the NodeVisitor traversing the graph
*/
abstract public function accept(NodeVisitor $nodeVisitor);
/**
* Returns this node as text (without any bbcode markup)
*
* @return the plain text representation of this node
* @return string the plain text representation of this node
*/
abstract public function getAsText();
/**
* Returns this node as bbcode
*
* @return the bbcode representation of this node
* @return string the bbcode representation of this node
*/
abstract public function getAsBBCode();
/**
* Returns this node as HTML
*
* @return the html representation of this node
* @return string the html representation of this node
*/
abstract public function getAsHTML();
/**
* Sets this node's parent to be the given node.
*
* @param parent the node to set as this node's parent
* @param Node $parent the node to set as this node's parent
*/
public function setParent(Node $parent)
{
$this->parent = $parent;
}
/**
* Sets this node's nodeid
*
* @param nodeid this node's node id
*/
public function setNodeId($nodeid)
{
$this->nodeid = $nodeid;
}
}

View file

@ -10,11 +10,9 @@ namespace JBBCode;
*/
interface NodeVisitor
{
public function visitDocumentElement(DocumentElement $documentElement);
public function visitTextNode(TextNode $textNode);
public function visitElementNode(ElementNode $elementNode);
}

View file

@ -10,7 +10,6 @@ require_once 'CodeDefinition.php';
require_once 'CodeDefinitionBuilder.php';
require_once 'CodeDefinitionSet.php';
require_once 'NodeVisitor.php';
require_once 'ParserException.php';
require_once 'Tokenizer.php';
require_once 'visitors/NestLimitVisitor.php';
require_once 'InputValidator.php';
@ -25,7 +24,6 @@ use JBBCode\CodeDefinition;
*/
class Parser
{
const OPTION_STATE_DEFAULT = 0;
const OPTION_STATE_TAGNAME = 1;
const OPTION_STATE_KEY = 2;
@ -33,22 +31,18 @@ class Parser
const OPTION_STATE_QUOTED_VALUE = 4;
const OPTION_STATE_JAVASCRIPT = 5;
/* The root element of the parse tree */
/** @var DocumentElement The root element of the parse tree */
protected $treeRoot;
/* The list of bbcodes to be used by the parser. */
protected $bbcodes;
/* The next node id to use. This is used while parsing. */
protected $nextNodeid;
/** @var CodeDefinition[] The list of bbcodes to be used by the parser. */
protected $bbcodes = array();
/**
* Constructs an instance of the BBCode parser
*/
public function __construct()
{
$this->reset();
$this->bbcodes = array();
$this->treeRoot = new DocumentElement();
}
/**
@ -61,7 +55,7 @@ class Parser
* @param integer $nestLimit an optional limit of the number of elements of this kind that can be nested within
* each other before the parser stops parsing them.
* @param InputValidator $optionValidator the validator to run {option} through
* @param BodyValidator $bodyValidator the validator to run {param} through (only used if $parseContent == false)
* @param InputValidator $bodyValidator the validator to run {param} through (only used if $parseContent == false)
*
* @return Parser
*/
@ -97,8 +91,7 @@ class Parser
*/
public function addCodeDefinition(CodeDefinition $definition)
{
array_push($this->bbcodes, $definition);
$this->bbcodes[$definition->getTagName()][$definition->usesOption()] = $definition;
return $this;
}
@ -109,7 +102,8 @@ class Parser
*
* @return Parser
*/
public function addCodeDefinitionSet(CodeDefinitionSet $set) {
public function addCodeDefinitionSet(CodeDefinitionSet $set)
{
foreach ($set->getCodeDefinitions() as $def) {
$this->addCodeDefinition($def);
}
@ -152,7 +146,7 @@ class Parser
/**
* Accepts the given NodeVisitor at the root.
*
* @param NodeVisitor a NodeVisitor
* @param NodeVisitor $nodeVisitor a NodeVisitor
*
* @return Parser
*/
@ -214,8 +208,6 @@ class Parser
{
// remove any old tree information
$this->treeRoot = new DocumentElement();
/* The document element is created with nodeid 0. */
$this->nextNodeid = 1;
}
/**
@ -228,13 +220,7 @@ class Parser
*/
public function codeExists($tagName, $usesOption = false)
{
foreach ($this->bbcodes as $code) {
if (strtolower($tagName) == $code->getTagName() && $usesOption == $code->usesOption()) {
return true;
}
}
return false;
return isset($this->bbcodes[strtolower($tagName)][$usesOption]);
}
/**
@ -247,10 +233,8 @@ class Parser
*/
public function getCode($tagName, $usesOption = false)
{
foreach ($this->bbcodes as $code) {
if (strtolower($tagName) == $code->getTagName() && $code->usesOption() == $usesOption) {
return $code;
}
if ($this->codeExists($tagName, $usesOption)) {
return $this->bbcodes[strtolower($tagName)][$usesOption];
}
return null;
@ -273,15 +257,15 @@ class Parser
/**
* Creates a new text node with the given parent and text string.
*
* @param $parent the parent of the text node
* @param $string the text of the text node
* @param ElementNode $parent the parent of the text node
* @param string $string the text of the text node
*
* @return TextNode the newly created TextNode
*/
protected function createTextNode(ElementNode $parent, $string)
{
if (count($parent->getChildren())) {
$children = $parent->getChildren();
$children = $parent->getChildren();
if (!empty($children)) {
$lastElement = end($children);
reset($children);
@ -292,7 +276,6 @@ class Parser
}
$textNode = new TextNode($string);
$textNode->setNodeId(++$this->nextNodeid);
$parent->addChild($textNode);
return $textNode;
}
@ -314,8 +297,7 @@ class Parser
if ('[' == $next) {
return $this->parseTagOpen($parent, $tokenizer);
}
else {
} else {
$this->createTextNode($parent, $next);
/* Drop back into the main parse loop which will call this
* same method again. */
@ -334,7 +316,6 @@ class Parser
*/
protected function parseTagOpen(ElementNode $parent, Tokenizer $tokenizer)
{
if (!$tokenizer->hasNext()) {
/* The [ that sent us to this state was just a trailing [, not the
* opening for a new tag. Treat it as such. */
@ -367,8 +348,7 @@ class Parser
$after_next = $tokenizer->next();
$tokenizer->stepBack();
if ($after_next != ']')
{
if ($after_next != ']') {
$this->createTextNode($parent, '['.$next);
return $parent;
}
@ -397,12 +377,12 @@ class Parser
$done = false;
$idx = 0;
try{
while(!$done){
try {
while (!$done) {
$char = $idx < $len ? $tagContent[$idx]:null;
switch($state){
switch ($state) {
case static::OPTION_STATE_TAGNAME:
switch($char){
switch ($char) {
case '=':
$state = static::OPTION_STATE_VALUE;
$tagName = $buffer;
@ -410,10 +390,15 @@ class Parser
$buffer = "";
break;
case ' ':
$state = static::OPTION_STATE_DEFAULT;
$tagName = $buffer;
$buffer = '';
$keys[] = $tagName;
if ($buffer) {
$state = static::OPTION_STATE_DEFAULT;
$tagName = $buffer;
$buffer = '';
$keys[] = $tagName;
}
break;
case "\n":
case "\r":
break;
case null:
@ -427,7 +412,7 @@ class Parser
break;
case static::OPTION_STATE_DEFAULT:
switch($char){
switch ($char) {
case ' ':
// do nothing
default:
@ -437,18 +422,18 @@ class Parser
break;
case static::OPTION_STATE_VALUE:
switch($char){
switch ($char) {
case '"':
$state = static::OPTION_STATE_QUOTED_VALUE;
break;
case null: // intentional fall-through
case ' ': // key=value<space> delimits to next key
$values[] = $buffer;
$values[] = trim($buffer);
$buffer = "";
$state = static::OPTION_STATE_KEY;
break;
case ":":
if($buffer=="javascript"){
if ($buffer=="javascript") {
$state = static::OPTION_STATE_JAVASCRIPT;
}
$buffer .= $char;
@ -460,7 +445,7 @@ class Parser
break;
case static::OPTION_STATE_JAVASCRIPT:
switch($char){
switch ($char) {
case ";":
$buffer .= $char;
$values[] = $buffer;
@ -474,10 +459,10 @@ class Parser
break;
case static::OPTION_STATE_KEY:
switch($char){
switch ($char) {
case '=':
$state = static::OPTION_STATE_VALUE;
$keys[] = $buffer;
$keys[] = trim($buffer);
$buffer = '';
break;
case ' ': // ignore <space>key=value
@ -489,7 +474,7 @@ class Parser
break;
case static::OPTION_STATE_QUOTED_VALUE:
switch($char){
switch ($char) {
case null:
case '"':
$state = static::OPTION_STATE_KEY;
@ -497,8 +482,8 @@ class Parser
$buffer = '';
// peek ahead. If the next character is not a space or a closing brace, we have a bad tag and need to abort
if(isset($tagContent[$idx+1]) && $tagContent[$idx+1]!=" " && $tagContent[$idx+1]!="]" ){
throw new ParserException("Badly formed attribute: $tagContent");
if (isset($tagContent[$idx+1]) && $tagContent[$idx+1]!=" " && $tagContent[$idx+1]!="]") {
throw new \DomainException("Badly formed attribute: $tagContent");
}
break;
default:
@ -507,26 +492,25 @@ class Parser
}
break;
default:
if(!empty($char)){
if (!empty($char)) {
$state = static::OPTION_STATE_KEY;
}
}
if($idx >= $len){
if ($idx >= $len) {
$done = true;
}
$idx++;
}
if(count($keys) && count($values)){
if(count($keys)==(count($values)+1)){
if (!empty($keys) && !empty($values)) {
if (count($keys)==(count($values)+1)) {
array_unshift($values, "");
}
$options = array_combine($keys, $values);
}
}
catch(ParserException $e){
} catch (\DomainException $e) {
// if we're in this state, then something evidently went wrong. We'll consider everything that came after the tagname to be the attribute for that keyname
$options[$tagName]= substr($tagContent, strpos($tagContent, "=")+1);
}
@ -545,8 +529,6 @@ class Parser
*/
protected function parseTag(ElementNode $parent, Tokenizer $tokenizer, $tagContent)
{
$next;
if (!$tokenizer->hasNext() || ($next = $tokenizer->next()) != ']') {
/* This is a malformed tag. Both the previous [ and the tagContent
* is really just plain text. */
@ -566,12 +548,10 @@ class Parser
// $tagPieces = explode('=', $tagContent);
// $tmpTagName = $tagPieces[0];
$actualTagName;
$actualTagName = $tmpTagName;
if ('' != $tmpTagName && '/' == $tmpTagName[0]) {
/* This is a closing tag name. */
$actualTagName = substr($tmpTagName, 1);
} else {
$actualTagName = $tmpTagName;
}
if ('' != $tmpTagName && '/' == $tmpTagName[0]) {
@ -604,7 +584,6 @@ class Parser
/* If we're here, this is a valid opening tag. Let's make a new node for it. */
$el = new ElementNode();
$el->setNodeId(++$this->nextNodeid);
$code = $this->getCode($actualTagName, !empty($options));
$el->setCodeDefinition($code);
if (!empty($options)) {
@ -658,5 +637,4 @@ class Parser
$curr = $tokenizer->next();
}
}
}

View file

@ -1,7 +0,0 @@
<?php
namespace JBBCode;
use Exception;
class ParserException extends Exception{
}

View file

@ -11,7 +11,7 @@ require_once 'Node.php';
*/
class TextNode extends Node
{
/* The value of this text node */
/** @var string The value of this text node */
protected $value;
/**
@ -33,7 +33,7 @@ class TextNode extends Node
* (non-PHPdoc)
* @see JBBCode.Node::isTextNode()
*
* returns true
* @returns boolean true
*/
public function isTextNode()
{
@ -56,7 +56,7 @@ class TextNode extends Node
*
* Returns the text representation of this node.
*
* @return this node represented as text
* @return string this node represented as text
*/
public function getAsText()
{
@ -69,7 +69,7 @@ class TextNode extends Node
*
* Returns the bbcode representation of this node. (Just its value)
*
* @return this node represented as bbcode
* @return string this node represented as bbcode
*/
public function getAsBBCode()
{
@ -82,7 +82,7 @@ class TextNode extends Node
*
* Returns the html representation of this node. (Just its value)
*
* @return this node represented as HTML
* @return string this node represented as HTML
*/
public function getAsHTML()
{
@ -92,11 +92,10 @@ class TextNode extends Node
/**
* Edits the text value contained within this text node.
*
* @param newValue the new text value of the text node
* @param string $newValue the new text value of the text node
*/
public function setValue($newValue)
{
$this->value = $newValue;
}
}

View file

@ -12,48 +12,48 @@ namespace JBBCode;
class Tokenizer
{
/** @var integer[] the positions of tokens found during parsing */
protected $tokens = array();
/** @var integer the number of the current token */
protected $i = -1;
/**
* Constructs a tokenizer from the given string. The string will be tokenized
* upon construction.
*
* @param $str the string to tokenize
* @param string $str the string to tokenize
*/
public function __construct($str)
{
$strStart = 0;
for ($index = 0; $index < strlen($str); ++$index) {
if (']' == $str[$index] || '[' == $str[$index]) {
/* Are there characters in the buffer from a previous string? */
if ($strStart < $index) {
array_push($this->tokens, substr($str, $strStart, $index - $strStart));
$strStart = $index;
}
$strLen = strlen($str);
$position = 0;
/* Add the [ or ] to the tokens array. */
array_push($this->tokens, $str[$index]);
$strStart = $index+1;
while ($position < $strLen) {
$offset = strcspn($str, '[]', $position);
//Have we hit a single ']' or '['?
if ($offset == 0) {
$this->tokens[] = $str[$position];
$position++;
} else {
$this->tokens[] = substr($str, $position, $offset);
$position += $offset;
}
}
if ($strStart < strlen($str)) {
/* There are still characters in the buffer. Add them to the tokens. */
array_push($this->tokens, substr($str, $strStart, strlen($str) - $strStart));
}
}
/**
* Returns true if there is another token in the token stream.
* @return boolean
*/
public function hasNext()
{
return count($this->tokens) > 1 + $this->i;
return isset($this->tokens[$this->i + 1]);
}
/**
* Advances the token stream to the next token and returns the new token.
* @return null|string
*/
public function next()
{
@ -66,6 +66,7 @@ class Tokenizer
/**
* Retrieves the current token.
* @return null|string
*/
public function current()
{
@ -96,10 +97,10 @@ class Tokenizer
/**
* toString method that returns the entire string from the current index on.
* @return string
*/
public function toString()
{
return implode('', array_slice($this->tokens, $this->i + 1));
}
}

View file

@ -1,85 +0,0 @@
<?php
require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php');
/**
* Test cases testing the functionality of parsing bbcode and
* retrieving a bbcode well-formed bbcode representation.
*
* @author jbowens
*/
class BBCodeToBBCodeTest extends PHPUnit_Framework_TestCase
{
/**
* A utility method for these tests that will evaluate its arguments as bbcode with
* a fresh parser loaded with only the default bbcodes. It returns the
* bbcode output, which in most cases should be in the input itself.
*/
private function defaultBBCodeParse($bbcode)
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse($bbcode);
return $parser->getAsBBCode();
}
/**
* Asserts that the given bbcode matches the given text when
* the bbcode is run through defaultBBCodeParse
*/
private function assertBBCodeOutput($bbcode, $text)
{
$this->assertEquals($this->defaultBBCodeParse($bbcode), $text);
}
public function testEmptyString()
{
$this->assertBBCodeOutput('', '');
}
public function testOneTag()
{
$this->assertBBCodeOutput('[b]this is bold[/b]', '[b]this is bold[/b]');
}
public function testOneTagWithSurroundingText()
{
$this->assertBBCodeOutput('buffer text [b]this is bold[/b] buffer text',
'buffer text [b]this is bold[/b] buffer text');
}
public function testMultipleTags()
{
$bbcode = 'this is some text with [b]bold tags[/b] and [i]italics[/i] and ' .
'things like [u]that[/u].';
$bbcodeOutput = 'this is some text with [b]bold tags[/b] and [i]italics[/i] and ' .
'things like [u]that[/u].';
$this->assertBBCodeOutput($bbcode, $bbcodeOutput);
}
public function testCodeOptions()
{
$code = 'This contains a [url=http://jbbcode.com]url[/url] which uses an option.';
$codeOutput = 'This contains a [url=http://jbbcode.com]url[/url] which uses an option.';
$this->assertBBCodeOutput($code, $codeOutput);
}
/**
* @depends testCodeOptions
*/
public function testOmittedOption()
{
$code = 'This doesn\'t use the url option [url]http://jbbcode.com[/url].';
$codeOutput = 'This doesn\'t use the url option [url]http://jbbcode.com[/url].';
$this->assertBBCodeOutput($code, $codeOutput);
}
public function testUnclosedTags()
{
$code = '[b]bold';
$codeOutput = '[b]bold[/b]';
$this->assertBBCodeOutput($code, $codeOutput);
}
}

View file

@ -1,78 +0,0 @@
<?php
require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php');
/**
* Test cases testing the ability to parse bbcode and retrieve a
* plain text representation without any markup.
*
* @author jbowens
*/
class BBCodeToTextTest extends PHPUnit_Framework_TestCase
{
/**
* A utility method for these tests that will evaluate
* its arguments as bbcode with a fresh parser loaded
* with only the default bbcodes. It returns the
* text output.
*/
private function defaultTextParse($bbcode)
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse($bbcode);
return $parser->getAsText();
}
/**
* Asserts that the given bbcode matches the given text when
* the bbcode is run through defaultTextParse
*/
private function assertTextOutput($bbcode, $text)
{
$this->assertEquals($text, $this->defaultTextParse($bbcode));
}
public function testEmptyString()
{
$this->assertTextOutput('', '');
}
public function testOneTag()
{
$this->assertTextOutput('[b]this is bold[/b]', 'this is bold');
}
public function testOneTagWithSurroundingText()
{
$this->assertTextOutput('buffer text [b]this is bold[/b] buffer text',
'buffer text this is bold buffer text');
}
public function testMultipleTags()
{
$bbcode = 'this is some text with [b]bold tags[/b] and [i]italics[/i] and ' .
'things like [u]that[/u].';
$text = 'this is some text with bold tags and italics and things like that.';
$this->assertTextOutput($bbcode, $text);
}
public function testCodeOptions()
{
$code = 'This contains a [url=http://jbbcode.com]url[/url] which uses an option.';
$text = 'This contains a url which uses an option.';
$this->assertTextOutput($code, $text);
}
/**
* @depends testCodeOptions
*/
public function testOmittedOption()
{
$code = 'This doesn\'t use the url option [url]http://jbbcode.com[/url].';
$text = 'This doesn\'t use the url option http://jbbcode.com.';
$this->assertTextOutput($code, $text);
}
}

View file

@ -0,0 +1,141 @@
<?php
class CodeDefinitionBuilderTest extends PHPUnit_Framework_TestCase
{
/**
* @var CodeDefinitionBuilderStub
*/
private $_builder;
protected function setUp()
{
$this->_builder = new CodeDefinitionBuilderStub('foo', 'bar');
}
public function testConstructor()
{
$codeDefinition = $this->_builder->build();
$this->assertInstanceOf('JBBCode\CodeDefinition', $codeDefinition);
$this->assertEquals('foo', $codeDefinition->getTagName());
$this->assertEquals('bar', $codeDefinition->getReplacementText());
}
public function testSetTagName()
{
$this->assertSame($this->_builder, $this->_builder->setTagName('baz'));
$this->assertEquals('baz', $this->_builder->build()->getTagName());
}
public function testSetReplacementText()
{
$this->assertSame($this->_builder, $this->_builder->setReplacementText('baz'));
$this->assertEquals('baz', $this->_builder->build()->getReplacementText());
}
public function testSetUseOption()
{
$this->assertFalse($this->_builder->build()->usesOption());
$this->assertSame($this->_builder, $this->_builder->setUseOption(true));
$this->assertTrue($this->_builder->build()->usesOption());
}
public function testSetParseContent()
{
$this->assertTrue($this->_builder->build()->parseContent());
$this->assertSame($this->_builder, $this->_builder->setParseContent(false));
$this->assertFalse($this->_builder->build()->parseContent());
}
public function testSetNestLimit()
{
$this->assertEquals(-1, $this->_builder->build()->getNestLimit());
$this->assertSame($this->_builder, $this->_builder->setNestLimit(1));
$this->assertEquals(1, $this->_builder->build()->getNestLimit());
}
/**
* @expectedException InvalidArgumentException
* @dataProvider invalidNestLimitProvider
*/
public function testSetInvalidNestLimit($limit)
{
$this->_builder->setNestLimit($limit);
}
public function testSetOptionValidator()
{
$this->assertEmpty($this->_builder->getOptionValidators());
$urlValidator = new JBBCode\validators\UrlValidator();
$this->assertSame($this->_builder, $this->_builder->setOptionValidator($urlValidator));
$this->assertArrayHasKey('foo', $this->_builder->getOptionValidators());
$this->assertContains($urlValidator, $this->_builder->getOptionValidators());
$otherUrlValidator = new JBBCode\validators\UrlValidator();
$this->assertSame($this->_builder, $this->_builder->setOptionValidator($otherUrlValidator, 'url'));
$this->assertArrayHasKey('url', $this->_builder->getOptionValidators());
$this->assertContains($urlValidator, $this->_builder->getOptionValidators());
$this->assertContains($otherUrlValidator, $this->_builder->getOptionValidators());
}
public function testSetBodyValidator()
{
$this->assertNull($this->_builder->getBodyValidator());
$validator = new JBBCode\validators\UrlValidator();
$this->assertSame($this->_builder, $this->_builder->setBodyValidator($validator));
$this->assertSame($validator, $this->_builder->getBodyValidator());
}
/**
* @depends testSetOptionValidator
*/
public function testRemoveOptionValidator()
{
$this->assertSame($this->_builder, $this->_builder->removeOptionValidator());
$this->assertEmpty($this->_builder->getOptionValidators());
$this->_builder->setOptionValidator(new JBBCode\validators\UrlValidator());
$this->assertSame($this->_builder, $this->_builder->removeOptionValidator());
$this->assertEmpty($this->_builder->getOptionValidators());
}
/**
* @depends testSetBodyValidator
*/
public function testRemoveBodyValidator()
{
$this->assertSame($this->_builder, $this->_builder->removeBodyValidator());
$this->assertNull($this->_builder->getBodyValidator());
$this->_builder->setOptionValidator(new JBBCode\validators\UrlValidator());
$this->assertSame($this->_builder, $this->_builder->removeBodyValidator());
$this->assertNull($this->_builder->getBodyValidator());
}
public function invalidNestLimitProvider()
{
return array(
array(-2),
array(null),
array(false),
);
}
}
class CodeDefinitionBuilderStub extends \JBBCode\CodeDefinitionBuilder
{
/**
* @return \JBBCode\InputValidator
*/
public function getBodyValidator()
{
return $this->bodyValidator;
}
/**
* @return \JBBCode\InputValidator[]
*/
public function getOptionValidators()
{
return $this->optionValidator;
}
}

View file

@ -0,0 +1,37 @@
<?php
/**
* Test cases for the default bbcode set.
*
* @author jbowens
* @since May 2013
*/
class DefaultCodeDefinitionSetTest extends PHPUnit_Framework_TestCase
{
public function testGetCodeDefinitions()
{
$dcds = new JBBCode\DefaultCodeDefinitionSet();
$definitions = $dcds->getCodeDefinitions();
$this->assertInternalType('array', $definitions);
$parser = new JBBCode\Parser();
$this->assertFalse($parser->codeExists('b'));
$this->assertFalse($parser->codeExists('i'));
$this->assertFalse($parser->codeExists('u'));
$this->assertFalse($parser->codeExists('url', true));
$this->assertFalse($parser->codeExists('img'));
$this->assertFalse($parser->codeExists('img', true));
$this->assertFalse($parser->codeExists('color', true));
$parser->addCodeDefinitionSet($dcds);
$this->assertTrue($parser->codeExists('b'));
$this->assertTrue($parser->codeExists('i'));
$this->assertTrue($parser->codeExists('u'));
$this->assertTrue($parser->codeExists('url', true));
$this->assertTrue($parser->codeExists('img'));
$this->assertTrue($parser->codeExists('img', true));
$this->assertTrue($parser->codeExists('color', true));
}
}

View file

@ -1,54 +0,0 @@
<?php
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php';
/**
* Test cases for the default bbcode set.
*
* @author jbowens
* @since May 2013
*/
class DefaultCodesTest extends PHPUnit_Framework_TestCase
{
/**
* Asserts that the given bbcode string produces the given html string
* when parsed with the default bbcodes.
*/
public function assertProduces($bbcode, $html)
{
$parser = new \JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse($bbcode);
$this->assertEquals($html, $parser->getAsHtml());
}
/**
* Tests the [b] bbcode.
*/
public function testBold()
{
$this->assertProduces('[b]this should be bold[/b]', '<strong>this should be bold</strong>');
}
/**
* Tests the [color] bbcode.
*/
public function testColor()
{
$this->assertProduces('[color=red]red[/color]', '<span style="color: red">red</span>');
}
/**
* Tests the example from the documentation.
*/
public function testExample()
{
$text = "The default codes include: [b]bold[/b], [i]italics[/i], [u]underlining[/u], ";
$text .= "[url=http://jbbcode.com]links[/url], [color=red]color![/color] and more.";
$html = 'The default codes include: <strong>bold</strong>, <em>italics</em>, <u>underlining</u>, ';
$html .= '<a href="http://jbbcode.com">links</a>, <span style="color: red">color!</span> and more.';
$this->assertProduces($text, $html);
}
}

View file

@ -0,0 +1,73 @@
<?php
namespace JBBCode;
class DocumentElementTest extends \PHPUnit_Framework_TestCase
{
/**
* @var DocumentElement
*/
private $_documentElement;
protected function setUp()
{
$this->_documentElement = new DocumentElement();
}
public function testGetTagName()
{
$this->assertEquals('Document', $this->_documentElement->getTagName());
}
public function testGetAsText()
{
$this->assertEmpty($this->_documentElement->getAsText());
$mock = $this->getMock('JBBCode\ElementNode', array('getAsText'));
$mock->expects($this->once())
->method('getAsText')
->will($this->returnValue('foo'));
$this->_documentElement->addChild($mock);
$this->assertEquals('foo', $this->_documentElement->getAsText());
}
public function testGetAsHTML()
{
$this->assertEmpty($this->_documentElement->getAsHTML());
$mock = $this->getMock('JBBCode\ElementNode', array('getAsHTML'));
$mock->expects($this->once())
->method('getAsHTML')
->will($this->returnValue('<strong>foo</strong>'));
$this->_documentElement->addChild($mock);
$this->assertEquals('<strong>foo</strong>', $this->_documentElement->getAsHTML());
}
public function testGetAsBBCode()
{
$this->assertEmpty($this->_documentElement->getAsBBCode());
$mock = $this->getMock('JBBCode\ElementNode', array('getAsBBCOde'));
$mock->expects($this->once())
->method('getAsBBCode')
->will($this->returnValue('[b]foo[/b]'));
$this->_documentElement->addChild($mock);
$this->assertEquals('[b]foo[/b]', $this->_documentElement->getAsBBCode());
}
public function testAccept()
{
$mock = $this->getMock('JBBCode\NodeVisitor',
array('visitDocumentElement', 'visitTextNode', 'visitElementNode'));
$mock->expects($this->once())
->method('visitDocumentElement')
->with($this->equalTo($this->_documentElement));
$mock->expects($this->never())
->method('visitTextNode');
$mock->expects($this->never())
->method('visitElementNode');
$this->_documentElement->accept($mock);
}
public function testIsTextNode()
{
$this->assertFalse($this->_documentElement->isTextNode());
}
}

View file

@ -0,0 +1,80 @@
<?php
class ElementNodeTest extends PHPUnit_Framework_TestCase
{
/** @var JBBCode\ElementNode */
private $_elementNode;
protected function setUp()
{
$this->_elementNode = new JBBCode\ElementNode();
}
public function testConstructor()
{
$this->assertNull($this->_elementNode->getCodeDefinition());
$this->assertEmpty($this->_elementNode->getTagName());
$this->assertEmpty($this->_elementNode->getAttribute());
$this->assertEmpty($this->_elementNode->getChildren());
$this->assertEmpty($this->_elementNode->getAsText());
$this->assertEmpty($this->_elementNode->getAsHTML());
}
public function testAccept()
{
$mock = $this->getMock('JBBCode\NodeVisitor',
array('visitDocumentElement', 'visitTextNode', 'visitElementNode'));
$mock->expects($this->never())
->method('visitDocumentElement');
$mock->expects($this->never())
->method('visitTextNode');
$mock->expects($this->once())
->method('visitElementNode')
->with($this->equalTo($this->_elementNode));
$this->_elementNode->accept($mock);
}
public function testSetCodeDefinition()
{
$mock = $this->getMock('JBBCode\CodeDefinition', array('getTagName'));
$mock->expects($this->once())
->method('getTagName')
->will($this->returnValue('foo'));
$this->_elementNode->setCodeDefinition($mock);
$this->assertSame($mock, $this->_elementNode->getCodeDefinition());
$this->assertEquals('foo', $this->_elementNode->getTagName());
}
public function testAddChild()
{
$mock = $this->getMock('JBBCode\ElementNode', array('setParent'));
$mock->expects($this->once())
->method('setParent')
->with($this->equalTo($this->_elementNode));
$this->_elementNode->addChild($mock);
$this->assertContains($mock, $this->_elementNode->getChildren());
}
public function testIsTextNode()
{
$this->assertFalse($this->_elementNode->isTextNode());
}
public function testGetAsBBCode()
{
$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());
}
}

View file

@ -1,7 +1,5 @@
<?php
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php';
/**
* Test cases for the code definition parameter that disallows parsing
* of an element's content.
@ -12,33 +10,37 @@ class ParseContentTest extends PHPUnit_Framework_TestCase
{
/**
* Tests that when a bbcode is created with parseContent = false,
* @var JBBCode\Parser
*/
private $_parser;
protected function setUp()
{
$this->_parser = new JBBCode\Parser();
$this->_parser->addCodeDefinitionSet(new JBBcode\DefaultCodeDefinitionSet());
}
/**
* Tests that when a bbcode is created with parseContent = false,
* its contents actually are not parsed.
*/
public function testSimpleNoParsing()
{
$this->_parser->addBBCode('verbatim', '{param}', false, false);
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->addBBCode('verbatim', '{param}', false, false);
$parser->parse('[verbatim]plain text[/verbatim]');
$this->assertEquals('plain text', $parser->getAsHtml());
$parser->parse('[verbatim][b]bold[/b][/verbatim]');
$this->assertEquals('[b]bold[/b]', $parser->getAsHtml());
$this->_parser->parse('[verbatim]plain text[/verbatim]');
$this->assertEquals('plain text', $this->_parser->getAsHtml());
$this->_parser->parse('[verbatim][b]bold[/b][/verbatim]');
$this->assertEquals('[b]bold[/b]', $this->_parser->getAsHtml());
}
public function testNoParsingWithBufferText()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->addBBCode('verbatim', '{param}', false, false);
$this->_parser->addBBCode('verbatim', '{param}', false, false);
$parser->parse('buffer text[verbatim]buffer text[b]bold[/b]buffer text[/verbatim]buffer text');
$this->assertEquals('buffer textbuffer text[b]bold[/b]buffer textbuffer text', $parser->getAsHtml());
$this->_parser->parse('buffer text[verbatim]buffer text[b]bold[/b]buffer text[/verbatim]buffer text');
$this->assertEquals('buffer textbuffer text[b]bold[/b]buffer textbuffer text', $this->_parser->getAsHtml());
}
/**
@ -48,14 +50,11 @@ class ParseContentTest extends PHPUnit_Framework_TestCase
*/
public function testUnclosedTag()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->addBBCode('verbatim', '{param}', false, false);
$this->_parser->addBBCode('verbatim', '{param}', false, false);
$parser->parse('[verbatim]i wonder [b]what will happen[/verbatim]');
$this->assertEquals('i wonder [b]what will happen', $parser->getAsHtml());
$this->assertEquals('[verbatim]i wonder [b]what will happen[/verbatim]', $parser->getAsBBCode());
$this->_parser->parse('[verbatim]i wonder [b]what will happen[/verbatim]');
$this->assertEquals('i wonder [b]what will happen', $this->_parser->getAsHtml());
$this->assertEquals('[verbatim]i wonder [b]what will happen[/verbatim]', $this->_parser->getAsBBCode());
}
/**
@ -63,12 +62,10 @@ class ParseContentTest extends PHPUnit_Framework_TestCase
*/
public function testUnclosedVerbatimTag()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->addBBCode('verbatim', '{param}', false, false);
$this->_parser->addBBCode('verbatim', '{param}', false, false);
$parser->parse('[verbatim]yo this [b]text should not be bold[/b]');
$this->assertEquals('yo this [b]text should not be bold[/b]', $parser->getAsHtml());
$this->_parser->parse('[verbatim]yo this [b]text should not be bold[/b]');
$this->assertEquals('yo this [b]text should not be bold[/b]', $this->_parser->getAsHtml());
}
/**
@ -76,11 +73,9 @@ class ParseContentTest extends PHPUnit_Framework_TestCase
*/
public function testMalformedVerbatimClosingTag()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->addBBCode('verbatim', '{param}', false, false);
$parser->parse('[verbatim]yo this [b]text should not be bold[/b][/verbatim');
$this->assertEquals('yo this [b]text should not be bold[/b][/verbatim', $parser->getAsHtml());
$this->_parser->addBBCode('verbatim', '{param}', false, false);
$this->_parser->parse('[verbatim]yo this [b]text should not be bold[/b][/verbatim');
$this->assertEquals('yo this [b]text should not be bold[/b][/verbatim', $this->_parser->getAsHtml());
}
/**
@ -93,5 +88,4 @@ class ParseContentTest extends PHPUnit_Framework_TestCase
$parser->parse('[verbatim]');
$this->assertEquals('', $parser->getAsHtml());
}
}

View file

@ -0,0 +1,150 @@
<?php
class ParserTest extends PHPUnit_Framework_TestCase
{
/**
* @var JBBCode\Parser
*/
private $_parser;
protected function setUp()
{
$this->_parser = new JBBCode\Parser();
$this->_parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
}
public function testAddCodeDefinition()
{
$parser = new JBBCode\Parser();
$this->assertFalse($parser->codeExists('foo', true));
$this->assertFalse($parser->codeExists('foo', false));
}
public function testAddBBCode()
{
$parser = new JBBCode\Parser();
$this->assertFalse($parser->codeExists('foo', true));
$this->assertFalse($parser->codeExists('foo', false));
$this->assertSame($parser, $parser->addBBCode('foo', 'bar', true));
$this->assertTrue($parser->codeExists('foo', true));
$this->assertFalse($parser->codeExists('foo', false));
$this->assertSame($parser, $parser->addBBCode('foo', 'bar', true));
$this->assertTrue($parser->codeExists('foo', true));
$this->assertFalse($parser->codeExists('foo', false));
$this->assertSame($parser, $parser->addBBCode('foo', 'bar', false));
$this->assertTrue($parser->codeExists('foo', true));
$this->assertTrue($parser->codeExists('foo', false));
}
/**
* Check for empty strings being the result of empty input
*/
public function testParseEmptyString()
{
$parser = $this->_parser->parse('');
$this->assertEmpty($parser->getAsBBCode());
$this->assertEmpty($parser->getAsText());
$this->assertEmpty($parser->getAsHTML());
}
/**
* Test for artifacts of previous parses
*/
public function testParseContentCleared()
{
$parser = $this->_parser->parse('foo');
$this->assertEquals('foo', $parser->getAsText());
$this->assertEquals('foo', $parser->getAsHTML());
$this->assertEquals('foo', $parser->getAsBBCode());
$parser->parse('bar');
$this->assertEquals('bar', $parser->getAsText());
$this->assertEquals('bar', $parser->getAsHTML());
$this->assertEquals('bar', $parser->getAsBBCode());
}
/**
* @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].',
)
),
);
}
}

View file

@ -1,7 +1,5 @@
<?php
require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php');
/**
* A series of test cases for various potential parsing edge cases. This
* includes a lot of tests using brackets for things besides genuine tag
@ -126,5 +124,4 @@ class ParsingEdgeCaseTest extends PHPUnit_Framework_TestCase
$this->assertProduces('[ ABC ] ',
'[ ABC ] ');
}
}

View file

@ -1,7 +1,5 @@
<?php
require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php');
class SimpleEvaluationTest extends PHPUnit_Framework_TestCase
{
@ -28,36 +26,6 @@ class SimpleEvaluationTest extends PHPUnit_Framework_TestCase
$this->assertEquals($html, $this->defaultParse($bbcode));
}
public function testEmptyString()
{
$this->assertProduces('', '');
}
public function testOneTag()
{
$this->assertProduces('[b]this is bold[/b]', '<strong>this is bold</strong>');
}
public function testOneTagWithSurroundingText()
{
$this->assertProduces('buffer text [b]this is bold[/b] buffer text',
'buffer text <strong>this is bold</strong> buffer text');
}
public function testMultipleTags()
{
$bbcode = <<<EOD
this is some text with [b]bold tags[/b] and [i]italics[/i] and
things like [u]that[/u].
EOD;
$html = <<<EOD
this is some text with <strong>bold tags</strong> and <em>italics</em> and
things like <u>that</u>.
EOD;
$this->assertProduces($bbcode, $html);
}
public function testCodeOptions()
{
$code = 'This contains a [url=http://jbbcode.com/?b=2]url[/url] which uses an option.';
@ -84,23 +52,6 @@ EOD;
$this->assertEquals($expected, $result);
}
/**
* @depends testCodeOptions
*/
public function testOmittedOption()
{
$code = 'This doesn\'t use the url option [url]http://jbbcode.com[/url].';
$html = 'This doesn\'t use the url option <a href="http://jbbcode.com">http://jbbcode.com</a>.';
$this->assertProduces($code, $html);
}
public function testUnclosedTag()
{
$code = 'hello [b]world';
$html = 'hello <strong>world</strong>';
$this->assertProduces($code, $html);
}
public function testNestingTags()
{
$code = '[url=http://jbbcode.com][b]hello [u]world[/u][/b][/url]';
@ -127,5 +78,4 @@ EOD;
{
$this->assertProduces('[b]:-[ [fo[o[bar[/b]', '<strong>:-[ [fo[o[bar</strong>');
}
}

View file

@ -0,0 +1,31 @@
<?php
class TextNodeTest extends PHPUnit_Framework_TestCase
{
/** @var JBBCode\TextNode */
private $_textNode;
protected function setUp()
{
$this->_textNode = new JBBCode\TextNode('');
}
public function accept()
{
$mock = $this->getMock('JBBCode\NodeVisitor',
array('visitDocumentElement', 'visitTextNode', 'visitElementNode'));
$mock->expects($this->never())
->method('visitDocumentElement');
$mock->expects($this->once())
->method('visitTextNode')
->with($this->equalTo($this->_textNode));
$mock->expects($this->never())
->method('visitElementNode');
$this->_textNode->accept($mock);
}
public function testIsTextNode()
{
$this->assertTrue($this->_textNode->isTextNode());
}
}

View file

@ -1,7 +1,5 @@
<?php
require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Tokenizer.php');
/**
* Test cases testing the functionality of the Tokenizer. The tokenizer
* is used by the parser to make parsing simpler.
@ -10,65 +8,109 @@ require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Tokenizer.php')
*/
class TokenizerTest extends PHPUnit_Framework_TestCase
{
public function testEmptyString()
{
$tokenizer = new JBBCode\Tokenizer('');
$this->assertFalse($tokenizer->hasNext());
$this->assertNull($tokenizer->current());
$this->assertNull($tokenizer->next());
$this->assertEmpty($tokenizer->toString());
}
public function testPlainTextOnly()
public function testHasNext()
{
$tokenizer = new JBBCode\Tokenizer('this is some plain text.');
$this->assertEquals('this is some plain text.', $tokenizer->next());
$this->assertEquals('this is some plain text.', $tokenizer->current());
$tokenizer = new JBBCode\Tokenizer('');
$this->assertFalse($tokenizer->hasNext());
$tokenizer = new JBBCode\Tokenizer('[');
$this->assertTrue($tokenizer->hasNext());
$tokenizer->next();
$this->assertFalse($tokenizer->hasNext());
}
public function testStartingBracket()
public function testNext()
{
$tokenizer = new JBBCode\Tokenizer('[this has a starting bracket.');
$tokenizer = new JBBCode\Tokenizer('[');
$this->assertEquals('[', $tokenizer->next());
$this->assertNull($tokenizer->next());
}
public function testCurrent()
{
$tokenizer = new JBBCode\Tokenizer('[');
$this->assertNull($tokenizer->current());
$tokenizer->next();
$this->assertEquals('[', $tokenizer->current());
$this->assertEquals('this has a starting bracket.', $tokenizer->next());
$this->assertEquals('this has a starting bracket.', $tokenizer->current());
$this->assertFalse($tokenizer->hasNext());
$this->assertEquals(null, $tokenizer->next());
}
public function testOneTag()
public function testStepBack()
{
$tokenizer = new JBBCode\Tokenizer('[b]');
$this->assertEquals('[', $tokenizer->next());
$this->assertEquals('b', $tokenizer->next());
$this->assertEquals(']', $tokenizer->next());
$tokenizer = new JBBCode\Tokenizer('');
$tokenizer->stepBack();
$this->assertFalse($tokenizer->hasNext());
$tokenizer = new JBBCode\Tokenizer('[');
$this->assertTrue($tokenizer->hasNext());
$this->assertEquals('[', $tokenizer->next());
$this->assertFalse($tokenizer->hasNext());
$tokenizer->stepBack();
$this->assertTrue($tokenizer->hasNext());
$this->assertEquals('[', $tokenizer->next());
}
public function testMatchingTags()
public function testRestart()
{
$tokenizer = new JBBCode\Tokenizer('[url]http://jbbcode.com[/url]');
$this->assertEquals('[', $tokenizer->next());
$this->assertEquals('url', $tokenizer->next());
$this->assertEquals(']', $tokenizer->next());
$this->assertEquals('http://jbbcode.com', $tokenizer->next());
$this->assertEquals('[', $tokenizer->next());
$this->assertEquals('/url', $tokenizer->next());
$this->assertEquals(']', $tokenizer->next());
$tokenizer = new JBBCode\Tokenizer('');
$tokenizer->restart();
$this->assertFalse($tokenizer->hasNext());
$tokenizer = new JBBCode\Tokenizer('[');
$tokenizer->next();
$tokenizer->restart();
$this->assertTrue($tokenizer->hasNext());
}
public function testLotsOfBrackets()
public function testToString()
{
$tokenizer = new JBBCode\Tokenizer('[[][]][');
$this->assertEquals('[', $tokenizer->next());
$this->assertEquals('[', $tokenizer->next());
$this->assertEquals(']', $tokenizer->next());
$this->assertEquals('[', $tokenizer->next());
$this->assertEquals(']', $tokenizer->next());
$this->assertEquals(']', $tokenizer->next());
$this->assertEquals('[', $tokenizer->next());
$tokenizer = new JBBCode\Tokenizer('[');
$this->assertEquals('[', $tokenizer->toString());
$tokenizer->next();
$this->assertEmpty($tokenizer->toString());
}
/**
* @param string[] $tokens
* @dataProvider tokenProvider()
*/
public function testTokenize($tokens)
{
$string = implode('', $tokens);
$tokenizer = new JBBCode\Tokenizer($string);
$this->assertEquals($string, $tokenizer->toString());
$this->assertTrue($tokenizer->hasNext());
$this->assertNull($tokenizer->current());
foreach ($tokens as $token) {
$this->assertEquals($token, $tokenizer->next());
}
$this->assertNull($tokenizer->next());
$this->assertFalse($tokenizer->hasNext());
}
public function tokenProvider()
{
return array(
array(
array('foo'),
),
array(
array('foo', '[', 'b', ']', 'bar'),
),
array(
array('[', 'foo', ']'),
),
);
}
}

View file

@ -1,151 +0,0 @@
<?php
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php';
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'validators' . DIRECTORY_SEPARATOR . 'UrlValidator.php';
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'validators' . DIRECTORY_SEPARATOR . 'CssColorValidator.php';
/**
* Test cases for InputValidators.
*
* @author jbowens
* @since May 2013
*/
class ValidatorTest extends PHPUnit_Framework_TestCase
{
/**
* Tests an invalid url directly on the UrlValidator.
*/
public function testInvalidUrl()
{
$urlValidator = new \JBBCode\validators\UrlValidator();
$this->assertFalse($urlValidator->validate('#yolo#swag'));
$this->assertFalse($urlValidator->validate('giehtiehwtaw352353%3'));
}
/**
* Tests a valid url directly on the UrlValidator.
*/
public function testValidUrl()
{
$urlValidator = new \JBBCode\validators\UrlValidator();
$this->assertTrue($urlValidator->validate('http://google.com'));
$this->assertTrue($urlValidator->validate('http://jbbcode.com/docs'));
$this->assertTrue($urlValidator->validate('https://www.maps.google.com'));
}
/**
* Tests an invalid url as an option to a url bbcode.
*
* @depends testInvalidUrl
*/
public function testInvalidOptionUrlBBCode()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse('[url=javascript:alert("HACKED!");]click me[/url]');
$this->assertEquals('[url=javascript:alert("HACKED!");]click me[/url]',
$parser->getAsHtml());
}
/**
* Tests an invalid url as the body to a url bbcode.
*
* @depends testInvalidUrl
*/
public function testInvalidBodyUrlBBCode()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse('[url]javascript:alert("HACKED!");[/url]');
$this->assertEquals('[url]javascript:alert("HACKED!");[/url]', $parser->getAsHtml());
}
/**
* Tests a valid url as the body to a url bbcode.
*
* @depends testValidUrl
*/
public function testValidUrlBBCode()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse('[url]http://jbbcode.com[/url]');
$this->assertEquals('<a href="http://jbbcode.com">http://jbbcode.com</a>',
$parser->getAsHtml());
}
/**
* Tests valid english CSS color descriptions on the CssColorValidator.
*/
public function testCssColorEnglish()
{
$colorValidator = new JBBCode\validators\CssColorValidator();
$this->assertTrue($colorValidator->validate('red'));
$this->assertTrue($colorValidator->validate('yellow'));
$this->assertTrue($colorValidator->validate('LightGoldenRodYellow'));
}
/**
* Tests valid hexadecimal CSS color values on the CssColorValidator.
*/
public function testCssColorHex()
{
$colorValidator = new JBBCode\validators\CssColorValidator();
$this->assertTrue($colorValidator->validate('#000'));
$this->assertTrue($colorValidator->validate('#ff0000'));
$this->assertTrue($colorValidator->validate('#aaaaaa'));
}
/**
* Tests valid rgba CSS color values on the CssColorValidator.
*/
public function testCssColorRgba()
{
$colorValidator = new JBBCode\validators\CssColorValidator();
$this->assertTrue($colorValidator->validate('rgba(255, 0, 0, 0.5)'));
$this->assertTrue($colorValidator->validate('rgba(50, 50, 50, 0.0)'));
}
/**
* Tests invalid CSS color values on the CssColorValidator.
*/
public function testInvalidCssColor()
{
$colorValidator = new JBBCode\validators\CssColorValidator();
$this->assertFalse($colorValidator->validate('" onclick="javascript: alert(\"gotcha!\");'));
$this->assertFalse($colorValidator->validate('"><marquee scrollamount="100'));
}
/**
* Tests valid css colors in a color bbcode.
*
* @depends testCssColorEnglish
* @depends testCssColorHex
*/
public function testValidColorBBCode()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse('[color=red]colorful text[/color]');
$this->assertEquals('<span style="color: red">colorful text</span>',
$parser->getAsHtml());
$parser->parse('[color=#00ff00]green[/color]');
$this->assertEquals('<span style="color: #00ff00">green</span>', $parser->getAsHtml());
}
/**
* Tests invalid css colors in a color bbcode.
*
* @depends testInvalidCssColor
*/
public function testInvalidColorBBCode()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse('[color=" onclick="alert(\'hey ya!\');]click me[/color]');
$this->assertEquals('[color=" onclick="alert(\'hey ya!\');]click me[/color]',
$parser->getAsHtml());
}
}

View file

@ -0,0 +1,2 @@
<?php
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'Parser.php';

View file

@ -0,0 +1,37 @@
<?php
class CssColorValidatorTest extends PHPUnit_Framework_TestCase
{
/**
* @var JBBCode\validators\CssColorValidator
*/
private $_validator;
protected function setUp()
{
$this->_validator = new JBBCode\validators\CssColorValidator();
}
/**
* @param string $color
* @dataProvider validColorProvider
*/
public function testValidColors($color)
{
$this->assertTrue($this->_validator->validate($color));
}
public function validColorProvider()
{
return array(
array('red'),
array('yellow'),
array('LightGoldenRodYellow'),
array('#000'),
array('#00ff00'),
array('rgba(255, 0, 0, 0.5)'),
array('rgba(50, 50, 50, 0.0)'),
);
}
}

View file

@ -0,0 +1,50 @@
<?php
class UrlValidatorTest extends PHPUnit_Framework_TestCase
{
/**
* @var JBBCode\validators\UrlValidator
*/
private $_validator;
protected function setUp()
{
$this->_validator = new JBBCode\validators\UrlValidator();
}
/**
* @param string $url
* @dataProvider invalidUrlProvider
*/
public function testInvalidUrl($url)
{
$this->assertFalse($this->_validator->validate($url));
}
/**
* @param string $url
* @dataProvider validUrlProvider
*/
public function testValidUrl($url)
{
$this->assertTrue($this->_validator->validate($url));
}
public function invalidUrlProvider()
{
return array(
array('#yolo#swag'),
array('giehtiehwtaw352353%3'),
);
}
public function validUrlProvider()
{
return array(
array('http://google.com'),
array('http://jbbcode.com/docs'),
array('https://www.maps.google.com'),
);
}
}

View file

@ -0,0 +1,72 @@
<?php
/**
* Test cases for InputValidators.
*
* @author jbowens
* @since May 2013
*/
class ValidatorTest extends PHPUnit_Framework_TestCase
{
/**
* Tests an invalid url as an option to a url bbcode.
*
*/
public function testInvalidOptionUrlBBCode()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse('[url=javascript:alert("HACKED!");]click me[/url]');
$this->assertEquals('[url=javascript:alert("HACKED!");]click me[/url]',
$parser->getAsHtml());
}
/**
* Tests an invalid url as the body to a url bbcode.
*
*/
public function testInvalidBodyUrlBBCode()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse('[url]javascript:alert("HACKED!");[/url]');
$this->assertEquals('[url]javascript:alert("HACKED!");[/url]', $parser->getAsHtml());
}
/**
* Tests a valid url as the body to a url bbcode.
*
*/
public function testValidUrlBBCode()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse('[url]http://jbbcode.com[/url]');
$this->assertEquals('<a href="http://jbbcode.com">http://jbbcode.com</a>',
$parser->getAsHtml());
}
/**
* Tests invalid CSS color values on the CssColorValidator.
*/
public function testInvalidCssColor()
{
$colorValidator = new JBBCode\validators\CssColorValidator();
$this->assertFalse($colorValidator->validate('" onclick="javascript: alert(\"gotcha!\");'));
$this->assertFalse($colorValidator->validate('"><marquee scrollamount="100'));
}
/**
* Tests invalid css colors in a color bbcode.
*
* @depends testInvalidCssColor
*/
public function testInvalidColorBBCode()
{
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse('[color=" onclick="alert(\'hey ya!\');]click me[/color]');
$this->assertEquals('[color=" onclick="alert(\'hey ya!\');]click me[/color]',
$parser->getAsHtml());
}
}

View file

@ -1,13 +1,13 @@
<?php
require_once(dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php');
require_once dirname(dirname(__DIR__)) . '/visitors/HTMLSafeVisitor.php';
/**
* Test cases testing the HTMLSafe visitor, which escapes all html characters in the source text
*
* @author astax-t
*/
class HTMLSafeTest extends PHPUnit_Framework_TestCase
class HTMLSafeVisitorTest extends PHPUnit_Framework_TestCase
{
/**
* Asserts that the given bbcode string produces the given html string
@ -19,12 +19,12 @@ class HTMLSafeTest extends PHPUnit_Framework_TestCase
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$parser->parse($bbcode);
$htmlsafer = new JBBCode\visitors\HTMLSafeVisitor();
$parser->accept($htmlsafer);
$htmlsafer = new JBBCode\visitors\HTMLSafeVisitor();
$parser->accept($htmlsafer);
$this->assertEquals($html, $parser->getAsHtml());
}
/**
* Tests escaping quotes and ampersands in simple text
*/
@ -73,5 +73,4 @@ class HTMLSafeTest extends PHPUnit_Framework_TestCase
{
$this->assertProduces('text [url="http://example.com/?a=b&c=d"]this is a "link"[/url]', 'text <a href="http://example.com/?a=b&amp;c=d">this is a &quot;link&quot;</a>');
}
}

View file

@ -1,7 +1,5 @@
<?php
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php';
/**
* Test cases for CodeDefinition nest limits. If an element is nested beyond
* its CodeDefinition's nest limit, it should be removed from the parse tree.
@ -9,9 +7,46 @@ require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'Parser.php';
* @author jbowens
* @since May 2013
*/
class NestLimitTest extends PHPUnit_Framework_TestCase
class NestLimitVisitorTest extends PHPUnit_Framework_TestCase
{
/** @var \JBBCode\visitors\NestLimitVisitor */
private $_nestLimitVisitor;
protected function setUp()
{
$this->_nestLimitVisitor = new \JBBCode\visitors\NestLimitVisitor();
}
public function testVisitDocumentElement()
{
$childMock = $this->getMock('JBBCode\ElementNode', array('accept'));
$childMock->expects($this->once())
->method('accept')
->with($this->equalTo($this->_nestLimitVisitor));
$mock = $this->getMock('JBBCode\DocumentElement', array('getChildren'));
$mock->expects($this->once())
->method('getChildren')
->will($this->returnValue(array(
$childMock
)));
$this->_nestLimitVisitor->visitDocumentElement($mock);
}
public function testVisitTextNode()
{
$mock = $this->getMockBuilder('JBBCode\TextNode')
->setMethods(array('accept'))
->disableOriginalConstructor()
->getMock();
$mock->expects($this->never())
->method('accept');
$this->_nestLimitVisitor->visitTextNode($mock);
}
/**
* Tests that when elements have no nest limits they may be
* nested indefinitely.
@ -42,5 +77,4 @@ class NestLimitTest extends PHPUnit_Framework_TestCase
$this->assertEquals($expectedBbcode, $parser->getAsBBCode());
$this->assertEquals($expectedHtml, $parser->getAsHtml());
}
}

View file

@ -0,0 +1,91 @@
<?php
require_once dirname(dirname(__DIR__)) . '/visitors/SmileyVisitor.php';
class SmileyVisitorTest extends PHPUnit_Framework_TestCase
{
/** @var \JBBCode\visitors\SmileyVisitor */
private $_smileyVisitor;
protected function setUp()
{
$this->_smileyVisitor = new \JBBCode\visitors\SmileyVisitor();
}
public function testVisitDocumentElement()
{
$childMock = $this->getMock('JBBCode\ElementNode', array('accept'));
$childMock->expects($this->once())
->method('accept')
->with($this->equalTo($this->_smileyVisitor));
$mock = $this->getMock('JBBCode\DocumentElement', array('getChildren'));
$mock->expects($this->once())
->method('getChildren')
->will($this->returnValue(array(
$childMock,
)));
$this->_smileyVisitor->visitDocumentElement($mock);
}
public function testVisitElementNode()
{
$builder = new \JBBCode\CodeDefinitionBuilder('foo', 'bar');
$builder->setParseContent(false);
$mock = $this->getMock('JBBCode\DocumentElement', array('getChildren', 'getCodeDefinition'));
$mock->expects($this->never())
->method('getChildren');
$mock->expects($this->once())
->method('getCodeDefinition')
->will($this->returnValue(
$builder->build()
));
$this->_smileyVisitor->visitElementNode($mock);
$childMock = $this->getMock('JBBCode\ElementNode', array('accept', 'parseContent'));
$childMock->expects($this->once())
->method('accept')
->with($this->equalTo($this->_smileyVisitor));
$mock = $this->getMock('JBBCode\DocumentElement', array('getChildren', 'getCodeDefinition'));
$mock->expects($this->once())
->method('getChildren')
->will($this->returnValue(array(
$childMock,
)));
$mock->expects($this->once())
->method('getCodeDefinition')
->will($this->returnValue($builder->setParseContent(true)->build()));
$this->_smileyVisitor->visitElementNode($mock);
}
public function testVisitTextNodeEmpty()
{
$textNode = new JBBCode\TextNode('');
$textNode->accept($this->_smileyVisitor);
$this->assertEmpty($textNode->getValue());
}
/**
* @param $string
* @dataProvider smileyProvider()
*/
public function testVisitTextNode($string)
{
$textNode = new JBBCode\TextNode($string);
$textNode->accept($this->_smileyVisitor);
$this->assertNotFalse(strpos($textNode->getValue(), '<img src="/smiley.png" alt=":)" />'));
}
public function smileyProvider()
{
return array(
array( ':)'),
array( ':) foo'),
array( 'foo :)'),
array( 'foo :) bar'),
);
}
}

View file

@ -0,0 +1,77 @@
<?php
require_once dirname(dirname(__DIR__)) . '/visitors/TagCountingVisitor.php';
class TagCountingVisitorTest extends \PHPUnit_Framework_TestCase
{
/** @var JBBCode\visitors\TagCountingVisitor */
protected $_tagCountingVisitor;
protected function setUp()
{
$this->_tagCountingVisitor = new JBBCode\visitors\TagCountingVisitor();
}
public function testVisitTextNode()
{
$mock = $this->getMock('JBBCode\TextNode', array('accept'), array(''));
$mock->expects($this->never())
->method('accept');
$this->_tagCountingVisitor->visitTextNode($mock);
}
/**
* @covers JBBCode\visitors\TagCountingVisitor::getFrequency()
* @covers JBBCode\visitors\TagCountingVisitor::visitElementNode()
*/
public function testVisitElementNode()
{
$childMock = $this->getMock('JBBCode\ElementNode', array('accept'));
$childMock->expects($this->once())
->method('accept')
->with($this->equalTo($this->_tagCountingVisitor));
$mock = $this->getMock('JBBCode\ElementNode', array('getChildren', 'getTagName'));
$mock->expects($this->once())
->method('getChildren')
->will($this->returnValue(array(
$childMock,
)));
$mock->expects($this->once())
->method('getTagName')
->will($this->returnValue('foo'));
$this->assertEquals(0, $this->_tagCountingVisitor->getFrequency('foo'));
$this->_tagCountingVisitor->visitElementNode($mock);
$this->assertEquals(1, $this->_tagCountingVisitor->getFrequency('foo'));
$mock = $this->getMock('JBBCode\ElementNode', array('getChildren', 'getTagName'));
$mock->expects($this->once())
->method('getChildren')
->will($this->returnValue(array()));
$mock->expects($this->once())
->method('getTagName')
->will($this->returnValue('foo'));
$this->_tagCountingVisitor->visitElementNode($mock);
$this->assertEquals(2, $this->_tagCountingVisitor->getFrequency('foo'));
}
public function testVisitDocumentElement()
{
$childMock = $this->getMock('JBBCode\ElementNode', array('accept'));
$childMock->expects($this->once())
->method('accept')
->with($this->equalTo($this->_tagCountingVisitor));
$mock = $this->getMock('JBBCode\DocumentElement', array('getChildren'));
$mock->expects($this->once())
->method('getChildren')
->will($this->returnValue(array(
$childMock,
)));
$this->_tagCountingVisitor->visitDocumentElement($mock);
}
}

View file

@ -20,11 +20,11 @@ class CssColorValidator implements \JBBCode\InputValidator
* Returns true if $input uses only valid CSS color value
* characters.
*
* @param $input the string to validate
* @param string $input the string to validate
* @return boolean
*/
public function validate($input)
{
return (bool) preg_match('/^[A-z0-9\-#., ()%]+$/', $input);
}
}

View file

@ -16,12 +16,12 @@ class UrlValidator implements \JBBCode\InputValidator
/**
* Returns true iff $input is a valid url.
*
* @param $input the string to validate
* @param string $input the string to validate
* @return boolean
*/
public function validate($input)
{
$valid = filter_var($input, FILTER_VALIDATE_URL);
return !!$valid;
}
}

View file

@ -9,44 +9,45 @@ namespace JBBCode\visitors;
*/
class HTMLSafeVisitor implements \JBBCode\NodeVisitor
{
public function visitDocumentElement(\JBBCode\DocumentElement $documentElement)
{
foreach ($documentElement->getChildren() as $child) {
$child->accept($this);
}
}
public function visitDocumentElement(\JBBCode\DocumentElement $documentElement)
{
foreach ($documentElement->getChildren() as $child) {
$child->accept($this);
}
}
public function visitTextNode(\JBBCode\TextNode $textNode)
{
$textNode->setValue($this->htmlSafe($textNode->getValue()));
}
public function visitTextNode(\JBBCode\TextNode $textNode)
{
$textNode->setValue($this->htmlSafe($textNode->getValue()));
}
public function visitElementNode(\JBBCode\ElementNode $elementNode)
{
$attrs = $elementNode->getAttribute();
if (is_array($attrs))
{
foreach ($attrs as &$el)
$el = $this->htmlSafe($el);
public function visitElementNode(\JBBCode\ElementNode $elementNode)
{
$attrs = $elementNode->getAttribute();
if (is_array($attrs)) {
foreach ($attrs as &$el) {
$el = $this->htmlSafe($el);
}
$elementNode->setAttribute($attrs);
}
$elementNode->setAttribute($attrs);
}
foreach ($elementNode->getChildren() as $child) {
$child->accept($this);
}
}
foreach ($elementNode->getChildren() as $child) {
$child->accept($this);
}
}
protected function htmlSafe($str, $options = null)
{
if (is_null($options))
{
if (defined('ENT_DISALLOWED'))
$options = ENT_QUOTES | ENT_DISALLOWED | ENT_HTML401; // PHP 5.4+
else
$options = ENT_QUOTES; // PHP 5.3
}
protected function htmlSafe($str, $options = null)
{
if (is_null($options)) {
if (defined('ENT_DISALLOWED')) {
$options = ENT_QUOTES | ENT_DISALLOWED | ENT_HTML401;
} // PHP 5.4+
else {
$options = ENT_QUOTES;
} // PHP 5.3
}
return htmlspecialchars($str, $options, 'UTF-8');
}
return htmlspecialchars($str, $options, 'UTF-8');
}
}

View file

@ -2,11 +2,11 @@
namespace JBBCode\visitors;
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'CodeDefinition.php';
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'DocumentElement.php';
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'ElementNode.php';
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'NodeVisitor.php';
require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'TextNode.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'CodeDefinition.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'DocumentElement.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'ElementNode.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'NodeVisitor.php';
require_once dirname(__DIR__) . DIRECTORY_SEPARATOR . 'TextNode.php';
/**
* This visitor is used by the jBBCode core to enforce nest limits after
@ -19,12 +19,12 @@ require_once dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'TextNode.php';
class NestLimitVisitor implements \JBBCode\NodeVisitor
{
/* A map from tag name to current depth. */
/** @var integer[] A map from tag name to current depth. */
protected $depth = array();
public function visitDocumentElement(\JBBCode\DocumentElement $documentElement)
{
foreach($documentElement->getChildren() as $child) {
foreach ($documentElement->getChildren() as $child) {
$child->accept($this);
}
}
@ -37,7 +37,7 @@ class NestLimitVisitor implements \JBBCode\NodeVisitor
public function visitElementNode(\JBBCode\ElementNode $elementNode)
{
$tagName = strtolower($elementNode->getTagName());
/* Update the current depth for this tag name. */
if (isset($this->depth[$tagName])) {
$this->depth[$tagName]++;
@ -61,5 +61,4 @@ class NestLimitVisitor implements \JBBCode\NodeVisitor
/* Now that we're done visiting this node, decrement the depth. */
$this->depth[$tagName]--;
}
}

View file

@ -11,23 +11,22 @@ namespace JBBCode\visitors;
*/
class SmileyVisitor implements \JBBCode\NodeVisitor
{
function visitDocumentElement(\JBBCode\DocumentElement $documentElement)
public function visitDocumentElement(\JBBCode\DocumentElement $documentElement)
{
foreach($documentElement->getChildren() as $child) {
foreach ($documentElement->getChildren() as $child) {
$child->accept($this);
}
}
function visitTextNode(\JBBCode\TextNode $textNode)
public function visitTextNode(\JBBCode\TextNode $textNode)
{
/* Convert :) into an image tag. */
$textNode->setValue(str_replace(':)',
'<img src="/smiley.png" alt=":)" />',
$textNode->setValue(str_replace(':)',
'<img src="/smiley.png" alt=":)" />',
$textNode->getValue()));
}
function visitElementNode(\JBBCode\ElementNode $elementNode)
public function visitElementNode(\JBBCode\ElementNode $elementNode)
{
/* We only want to visit text nodes within elements if the element's
* code definition allows for its content to be parsed.
@ -38,5 +37,4 @@ class SmileyVisitor implements \JBBCode\NodeVisitor
}
}
}
}

View file

@ -40,13 +40,14 @@ class TagCountingVisitor implements \JBBcode\NodeVisitor
foreach ($elementNode->getChildren() as $child) {
$child->accept($this);
}
}
/**
* Retrieves the frequency of the given tag name.
*
* @param $tagName the tag name to look up
* @param string $tagName the tag name to look up
*
* @return integer
*/
public function getFrequency($tagName)
{
@ -56,5 +57,4 @@ class TagCountingVisitor implements \JBBcode\NodeVisitor
return $this->frequencies[$tagName];
}
}
}

21
vendor/jbbcode/jbbcode/LICENSE.md vendored Normal file
View file

@ -0,0 +1,21 @@
# The MIT License (MIT)
Copyright (c) 2011 Jackson Owens
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in
> all copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> THE SOFTWARE.

View file

@ -1,5 +1,8 @@
jBBCode
=======
[![GitHub release](https://img.shields.io/github/release/jbowens/jBBCode.svg)](https://github.com/jbowens/jBBCode/releases)
[![Software License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE.md)
[![Build Status](https://img.shields.io/travis/jbowens/jBBCode.svg)](https://travis-ci.org/jbowens/jBBCode)
jBBCode is a bbcode parser written in php 5.3. It's relatively lightweight and parses
bbcodes without resorting to expensive regular expressions.
@ -9,70 +12,59 @@ Documentation
For complete documentation and examples visit [jbbcode.com](http://jbbcode.com).
###A basic example
### A basic example
jBBCode includes a few optional, default bbcode definitions that may be loaded through the
`DefaultCodeDefinitionSet` class. Below is a simple example of using these codes to convert
`DefaultCodeDefinitionSet` class. Below is a simple example of using these codes to convert
a bbcode string to html.
```php
<?php
require_once "/path/to/jbbcode/Parser.php";
$parser = new JBBCode\Parser();
$parser->addCodeDefinitionSet(new JBBCode\DefaultCodeDefinitionSet());
$text = "The default codes include: [b]bold[/b], [i]italics[/i], [u]underlining[/u], ";
$text .= "[url=http://jbbcode.com]links[/url], [color=red]color![/color] and more.";
$parser->parse($text);
print $parser->getAsHtml();
```
### Composer
You may load jBBCode via composer. In your composer.json file:
```json
"require": {
"jbbcode/jbbcode": "1.3.*"
}
```
In your php file:
```php
require 'vendor/autoloader.php';
$parser = new JBBCode\Parser();
```
Contribute
----------
I would love help maintaining jBBCode. Look at [open issues](http://github.com/jbowens/jBBCode/issues) for ideas on
what needs to be done. Before submitting a pull request, verify that all unit tests still pass.
what needs to be done. Before submitting a pull request, verify that all unit tests still pass.
#### Running unit tests
#### Running unit tests
To run the unit tests,
ensure that [phpunit](http://github.com/sebastianbergmann/phpunit) is installed, or install it through the composer
dev dependencies. Then run `phpunit ./tests` from the project directory. If you're adding new functionality, writing
dev dependencies. Then run `phpunit` from the project directory. If you're adding new functionality, writing
additional unit tests is a great idea.
Author
------
jBBCode was written by Jackson Owens. You may reach him at [jackson_owens@brown.edu](mailto:jackson_owens@brown.edu).
Other languages
---------------
This library is in the process of being ported to java. For more information, see [jBBCode-java](https://github.com/jbowens/jBBCode-java).
License
-------
The MIT License
Copyright (c) 2011 Jackson Owens
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
The project is under MIT license. Please see the [license file](LICENSE.md) for details.

View file

@ -9,15 +9,14 @@
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "3.7.*"
},
"config": {
"bin-dir": "/usr/local/bin"
"phpunit/phpunit": "4.5.*",
"satooshi/php-coveralls": "0.6.*",
"friendsofphp/php-cs-fixer": "^2.1"
},
"authors": [
{
"name": "Jackson Owens",
"email": "jackson_owens@brown.edu",
"email": "jackson_owens@alumni.brown.edu",
"homepage": "http://jbowens.org/",
"role": "Developer"
}

24
vendor/jbbcode/jbbcode/phpunit.xml.dist vendored Normal file
View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<phpunit bootstrap="JBBCode/tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
stopOnFailure="false"
backupGlobals="false"
backupStaticAttributes="false">
<testsuites>
<testsuite name="jBBCode Test Suite">
<directory>JBBCode/tests</directory>
</testsuite>
</testsuites>
<filter>
<blacklist>
<directory suffix=".php">examples/</directory>
<directory suffix=".php">vendor</directory>
</blacklist>
</filter>
<logging>
<log type="coverage-clover" target="clover.xml"/>
</logging>
</phpunit>