diff --git a/app/BBCode/Parser.php b/app/BBCode/Parser.php
new file mode 100644
index 0000000..1dc7f00
--- /dev/null
+++ b/app/BBCode/Parser.php
@@ -0,0 +1,93 @@
+
+ */
+class Parser
+{
+ /**
+ * Holds the bbcode parsers.
+ * @var array
+ */
+ public static $parsers = [
+ // Basic markup
+ Tags\Bold::class,
+ Tags\Italics::class,
+ Tags\Underline::class,
+ Tags\Strike::class,
+ Tags\Header::class,
+ Tags\Image::class,
+ Tags\Spoiler::class,
+
+ // More advanced
+ Tags\Colour::class,
+ Tags\Align::class,
+ Tags\Size::class,
+ Tags\YouTube::class,
+
+ // Links
+ Tags\NamedLink::class,
+ Tags\Link::class,
+
+ // Quotes
+ Tags\NamedQuote::class,
+ Tags\Quote::class,
+
+ // Advanced parsing
+ Tags\Box::class,
+ Tags\Code::class,
+ Tags\ListTag::class,
+ Tags\User::class,
+
+ // Newline must always be last
+ Tags\Newline::class,
+ ];
+
+ /**
+ * Parse the emoticons.
+ * @param string $text
+ * @return string
+ */
+ public static function parseEmoticons($text)
+ {
+ // Get emoticons from the database
+ $emotes = DB::table('emoticons')
+ ->get();
+
+ // Parse all emoticons
+ foreach ($emotes as $emote) {
+ $image = "";
+ $icon = preg_quote($emote->emote_string, '#');
+ $text = preg_replace("#{$icon}#", $image, $text);
+ }
+
+ // Return the parsed text
+ return $text;
+ }
+
+ /**
+ * Convert the parsed text to HTML.
+ * @param string $text
+ * @return string
+ */
+ public static function toHTML($text)
+ {
+ $text = self::parseEmoticons($text);
+
+ foreach (self::$parsers as $parser) {
+ $text = call_user_func([$parser, 'parse'], $text);
+ }
+
+ return $text;
+ }
+}
diff --git a/app/BBCode/TagBase.php b/app/BBCode/TagBase.php
new file mode 100644
index 0000000..a9a6a6f
--- /dev/null
+++ b/app/BBCode/TagBase.php
@@ -0,0 +1,37 @@
+
+ */
+class TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "";
+
+ /**
+ * Parses the bbcode.
+ * @param string $text
+ * @return string
+ */
+ public static function parse($text)
+ {
+ return preg_replace(static::$pattern, static::$replace, $text);
+ }
+}
diff --git a/app/BBCode/Tags/Align.php b/app/BBCode/Tags/Align.php
new file mode 100644
index 0000000..34f8bbb
--- /dev/null
+++ b/app/BBCode/Tags/Align.php
@@ -0,0 +1,37 @@
+
+ */
+class Align extends TagBase
+{
+ /**
+ * Parses the bbcode.
+ * @param string $text
+ * @return string
+ */
+ public static function parse($text)
+ {
+ return preg_replace_callback(
+ '/\[align\=(left|center|centre|right)\](.*?)\[\/align\]/s',
+ function ($matches) {
+ if ($matches[1] === 'centre') {
+ $matches[1] = 'center';
+ }
+
+ return "
{$matches[2]}
";
+ },
+ $text
+ );
+ }
+}
diff --git a/app/BBCode/Tags/Bold.php b/app/BBCode/Tags/Bold.php
new file mode 100644
index 0000000..d6b2400
--- /dev/null
+++ b/app/BBCode/Tags/Bold.php
@@ -0,0 +1,29 @@
+
+ */
+class Bold extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[b\](.*?)\[\/b\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$1";
+}
diff --git a/app/BBCode/Tags/Box.php b/app/BBCode/Tags/Box.php
new file mode 100644
index 0000000..6d62993
--- /dev/null
+++ b/app/BBCode/Tags/Box.php
@@ -0,0 +1,38 @@
+
+ */
+class Box extends TagBase
+{
+ /**
+ * Parses the bbcode.
+ * @param string $text
+ * @return string
+ */
+ public static function parse($text)
+ {
+ return preg_replace_callback(
+ '/\[box(?:\=(.*?))?\](.*?)\[\/box\]/s',
+ function ($matches) {
+ $title = strlen($matches[1]) ? $matches[1] : 'Click to open';
+
+ return ""
+ . "
{$title}
"
+ . "
{$matches[2]}
"
+ . "
";
+ },
+ $text
+ );
+ }
+}
diff --git a/app/BBCode/Tags/Code.php b/app/BBCode/Tags/Code.php
new file mode 100644
index 0000000..2201742
--- /dev/null
+++ b/app/BBCode/Tags/Code.php
@@ -0,0 +1,36 @@
+
+ */
+class Code extends TagBase
+{
+ /**
+ * Parses the bbcode.
+ * @param string $text
+ * @return string
+ */
+ public static function parse($text)
+ {
+ return preg_replace_callback(
+ '/\[code(?:\=([a-z]+))?\](.*?)\[\/code\]/s',
+ function ($matches) {
+ $class = strlen($matches[1]) ? " class='lang-{$matches[1]}'" : '';
+ // htmlencode bbcode characters here as well
+
+ return "{$matches[2]}
";
+ },
+ $text
+ );
+ }
+}
diff --git a/app/BBCode/Tags/Colour.php b/app/BBCode/Tags/Colour.php
new file mode 100644
index 0000000..8ed8457
--- /dev/null
+++ b/app/BBCode/Tags/Colour.php
@@ -0,0 +1,29 @@
+
+ */
+class Colour extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[colou?r\=(#[A-f0-9]{6}|#[A-f0-9]{3})\](.*?)\[\/colou?r\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$2";
+}
diff --git a/app/BBCode/Tags/Header.php b/app/BBCode/Tags/Header.php
new file mode 100644
index 0000000..fac0b9b
--- /dev/null
+++ b/app/BBCode/Tags/Header.php
@@ -0,0 +1,29 @@
+
+ */
+class Header extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[header\](.*?)\[\/header\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$1
";
+}
diff --git a/app/BBCode/Tags/Image.php b/app/BBCode/Tags/Image.php
new file mode 100644
index 0000000..2547385
--- /dev/null
+++ b/app/BBCode/Tags/Image.php
@@ -0,0 +1,29 @@
+
+ */
+class Image extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[img\](.*?)\[\/img\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "";
+}
diff --git a/app/BBCode/Tags/Italics.php b/app/BBCode/Tags/Italics.php
new file mode 100644
index 0000000..cd489fb
--- /dev/null
+++ b/app/BBCode/Tags/Italics.php
@@ -0,0 +1,29 @@
+
+ */
+class Italics extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[i\](.*?)\[\/i\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$1";
+}
diff --git a/app/BBCode/Tags/Link.php b/app/BBCode/Tags/Link.php
new file mode 100644
index 0000000..e9099fb
--- /dev/null
+++ b/app/BBCode/Tags/Link.php
@@ -0,0 +1,29 @@
+
+ */
+class Link extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[url\](.*?)\[\/url\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$1";
+}
diff --git a/app/BBCode/Tags/ListTag.php b/app/BBCode/Tags/ListTag.php
new file mode 100644
index 0000000..0838d5f
--- /dev/null
+++ b/app/BBCode/Tags/ListTag.php
@@ -0,0 +1,39 @@
+
+ */
+class ListTag extends TagBase
+{
+ /**
+ * Parses the bbcode.
+ * @param string $text
+ * @return string
+ */
+ public static function parse($text)
+ {
+ return preg_replace_callback(
+ '/\[list(?:\=(1|A|a|I|i))?\](.*?)\[\/list\]/s',
+ function ($matches) {
+ $content = preg_replace('/\[\*\](.*)/', '$1', $matches[2]);
+
+ if ($matches[1] !== '') {
+ return "{$content}
";
+ }
+
+ return "";
+ },
+ $text
+ );
+ }
+}
diff --git a/app/BBCode/Tags/NamedLink.php b/app/BBCode/Tags/NamedLink.php
new file mode 100644
index 0000000..4947a8d
--- /dev/null
+++ b/app/BBCode/Tags/NamedLink.php
@@ -0,0 +1,29 @@
+
+ */
+class NamedLink extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[url\=(.*?)\](.*?)\[\/url\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$2";
+}
diff --git a/app/BBCode/Tags/NamedQuote.php b/app/BBCode/Tags/NamedQuote.php
new file mode 100644
index 0000000..7082818
--- /dev/null
+++ b/app/BBCode/Tags/NamedQuote.php
@@ -0,0 +1,29 @@
+
+ */
+class NamedQuote extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[quote\=(.*?)\](.*)\[\/quote\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$1$2
";
+}
diff --git a/app/BBCode/Tags/Newline.php b/app/BBCode/Tags/Newline.php
new file mode 100644
index 0000000..3cb00ab
--- /dev/null
+++ b/app/BBCode/Tags/Newline.php
@@ -0,0 +1,29 @@
+
+ */
+class Newline extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\r\n|\r|\n/";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "
";
+}
diff --git a/app/BBCode/Tags/Quote.php b/app/BBCode/Tags/Quote.php
new file mode 100644
index 0000000..14afd00
--- /dev/null
+++ b/app/BBCode/Tags/Quote.php
@@ -0,0 +1,29 @@
+
+ */
+class Quote extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[quote\](.*?)\[\/quote\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$1
";
+}
diff --git a/app/BBCode/Tags/Size.php b/app/BBCode/Tags/Size.php
new file mode 100644
index 0000000..4c574b9
--- /dev/null
+++ b/app/BBCode/Tags/Size.php
@@ -0,0 +1,70 @@
+
+ */
+class Size extends TagBase
+{
+ /**
+ * The maximum size a user can specify.
+ * @var int
+ */
+ private static $maxSize = 200;
+
+ /**
+ * The minimum size a user can specify.
+ * @var int
+ */
+ private static $minSize = 1;
+
+ /**
+ * Text aliases for the various sizes.
+ * @var array
+ */
+ private static $aliases = [
+ 'tiny' => 50,
+ 'small' => 85,
+ 'normal' => 100,
+ 'large' => 150,
+ 'huge' => 200,
+ ];
+
+ /**
+ * Parses the bbcode.
+ * @param string $text
+ * @return string
+ */
+ public static function parse($text)
+ {
+ return preg_replace_callback(
+ '/\[size\=([a-z0-9]+)\](.*?)\[\/size\]/s',
+ function ($matches) {
+ if (is_numeric($matches[1])) {
+ $size = intval($matches[1]);
+
+ if ($size < self::$minSize || $size > self::$maxSize) {
+ return $matches[0];
+ }
+ } elseif (in_array($matches[1], self::$aliases)) {
+ $size = self::$aliases[$matches[1]];
+ } else {
+ return $matches[0];
+ }
+
+ // we'll just use per cent for now, don't let this make it to production though
+ return "{$matches[2]}
";
+ },
+ $text
+ );
+ }
+}
diff --git a/app/BBCode/Tags/Spoiler.php b/app/BBCode/Tags/Spoiler.php
new file mode 100644
index 0000000..dc50b96
--- /dev/null
+++ b/app/BBCode/Tags/Spoiler.php
@@ -0,0 +1,29 @@
+
+ */
+class Spoiler extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[spoiler\](.*?)\[\/spoiler\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$1";
+}
diff --git a/app/BBCode/Tags/Strike.php b/app/BBCode/Tags/Strike.php
new file mode 100644
index 0000000..d4b8371
--- /dev/null
+++ b/app/BBCode/Tags/Strike.php
@@ -0,0 +1,29 @@
+
+ */
+class Strike extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[s\](.*?)\[\/s\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$1";
+}
diff --git a/app/BBCode/Tags/Underline.php b/app/BBCode/Tags/Underline.php
new file mode 100644
index 0000000..f45d7d7
--- /dev/null
+++ b/app/BBCode/Tags/Underline.php
@@ -0,0 +1,29 @@
+
+ */
+class Underline extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[u\](.*?)\[\/u\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "$1";
+}
diff --git a/app/BBCode/Tags/User.php b/app/BBCode/Tags/User.php
new file mode 100644
index 0000000..4306931
--- /dev/null
+++ b/app/BBCode/Tags/User.php
@@ -0,0 +1,38 @@
+
+ */
+class User extends TagBase
+{
+ /**
+ * Parses the bbcode.
+ * @param string $text
+ * @return string
+ */
+ public static function parse($text)
+ {
+ return preg_replace_callback(
+ '/\[user\]([0-9]+)\[\/user\]/s',
+ function ($matches) {
+ $user = UserObject::construct($matches[1]);
+ $route = route('user.profile', $user->id);
+
+ return "{$user->username}";
+ },
+ $text
+ );
+ }
+}
diff --git a/app/BBCode/Tags/YouTube.php b/app/BBCode/Tags/YouTube.php
new file mode 100644
index 0000000..5fbf0e1
--- /dev/null
+++ b/app/BBCode/Tags/YouTube.php
@@ -0,0 +1,30 @@
+
+ */
+class YouTube extends TagBase
+{
+ /**
+ * The pattern to match.
+ * @var string
+ */
+ public static $pattern = "/\[youtube\]([A-Za-z0-9\-\_]+)\[\/youtube\]/s";
+
+ /**
+ * The string to replace it with.
+ * @var string
+ */
+ public static $replace = "";
+}
diff --git a/app/BBcode.php b/app/BBcode.php
deleted file mode 100644
index 86365dd..0000000
--- a/app/BBcode.php
+++ /dev/null
@@ -1,175 +0,0 @@
-
- */
-class BBcode
-{
- /**
- * Holds the bbcode parsers.
- * @var array
- */
- public static $parsers = [
- 'bold' => [
- 'pattern' => '/\[b\](.*?)\[\/b\]/s',
- 'replace' => '$1',
- 'content' => '$1',
- ],
- 'italic' => [
- 'pattern' => '/\[i\](.*?)\[\/i\]/s',
- 'replace' => '$1',
- 'content' => '$1',
- ],
- 'underline' => [
- 'pattern' => '/\[u\](.*?)\[\/u\]/s',
- 'replace' => '$1',
- 'content' => '$1',
- ],
- 'linethrough' => [
- 'pattern' => '/\[s\](.*?)\[\/s\]/s',
- 'replace' => '$1',
- 'content' => '$1',
- ],
- 'header' => [
- 'pattern' => '/\[header\](.*?)\[\/header\]/s',
- 'replace' => '$1
',
- 'content' => '$1',
- ],
- 'size' => [
- 'pattern' => '/\[size\=([1-7])\](.*?)\[\/size\]/s',
- 'replace' => '$2',
- 'content' => '$2',
- ],
- 'color' => [
- 'pattern' => '/\[color\=(#[A-f0-9]{6}|#[A-f0-9]{3})\](.*?)\[\/color\]/s',
- 'replace' => '$2',
- 'content' => '$2',
- ],
- 'center' => [
- 'pattern' => '/\[center\](.*?)\[\/center\]/s',
- 'replace' => '$1
',
- 'content' => '$1',
- ],
- 'left' => [
- 'pattern' => '/\[left\](.*?)\[\/left\]/s',
- 'replace' => '$1
',
- 'content' => '$1',
- ],
- 'right' => [
- 'pattern' => '/\[right\](.*?)\[\/right\]/s',
- 'replace' => '$1
',
- 'content' => '$1',
- ],
- 'align' => [
- 'pattern' => '/\[align\=(left|center|right)\](.*?)\[\/align\]/s',
- 'replace' => '$2
',
- 'content' => '$2',
- ],
- 'quote' => [
- 'pattern' => '/\[quote\](.*?)\[\/quote\]/s',
- 'replace' => '$1
',
- 'content' => '$1',
- ],
- 'namedquote' => [
- 'pattern' => '/\[quote\=(.*?)\](.*)\[\/quote\]/s',
- 'replace' => '$1$2
',
- 'content' => '$2',
- ],
- 'link' => [
- 'pattern' => '/\[url\](.*?)\[\/url\]/s',
- 'replace' => '$1',
- 'content' => '$1',
- ],
- 'namedlink' => [
- 'pattern' => '/\[url\=(.*?)\](.*?)\[\/url\]/s',
- 'replace' => '$2',
- 'content' => '$2',
- ],
- 'image' => [
- 'pattern' => '/\[img\](.*?)\[\/img\]/s',
- 'replace' => '',
- 'content' => '$1',
- ],
- 'orderedlistnumerical' => [
- 'pattern' => '/\[list=1\](.*?)\[\/list\]/s',
- 'replace' => '$1
',
- 'content' => '$1',
- ],
- 'orderedlistalpha' => [
- 'pattern' => '/\[list=a\](.*?)\[\/list\]/s',
- 'replace' => '$1
',
- 'content' => '$1',
- ],
- 'unorderedlist' => [
- 'pattern' => '/\[list\](.*?)\[\/list\]/s',
- 'replace' => '',
- 'content' => '$1',
- ],
- 'listitem' => [
- 'pattern' => '/\[\*\](.*)/',
- 'replace' => '$1',
- 'content' => '$1',
- ],
- 'code' => [
- 'pattern' => '/\[code\](.*?)\[\/code\]/s',
- 'replace' => '$1
',
- 'content' => '$1',
- ],
- 'youtube' => [
- 'pattern' => '/\[youtube\](.*?)\[\/youtube\]/s',
- 'replace' => '',
- 'content' => '$1',
- ],
- 'linebreak' => [
- 'pattern' => '/\r\n|\r|\n/',
- 'replace' => '
',
- 'content' => '',
- ],
- ];
-
- /**
- * Parse the emoticons.
- * @param string $text
- * @return string
- */
- public static function parseEmoticons($text)
- {
- // Get emoticons from the database
- $emotes = DB::table('emoticons')
- ->get();
-
- // Parse all emoticons
- foreach ($emotes as $emote) {
- $image = "";
- $icon = preg_quote($emote->emote_string, '#');
- $text = preg_replace("#{$icon}#", $image, $text);
- }
-
- // Return the parsed text
- return $text;
- }
-
- /**
- * Convert the parsed text to HTML.
- * @param string $text
- * @return string
- */
- public static function toHTML($text)
- {
- $text = self::parseEmoticons($text);
-
- foreach (self::$parsers as $parser) {
- $text = preg_replace($parser['pattern'], $parser['replace'], $text);
- }
-
- return $text;
- }
-}
diff --git a/app/Comment.php b/app/Comment.php
index 2eaf835..beb106d 100644
--- a/app/Comment.php
+++ b/app/Comment.php
@@ -166,7 +166,7 @@ class Comment
public function parsed()
{
if (!$this->parsedCache) {
- $this->parsedCache = BBcode::parseEmoticons(clean_string($this->text));
+ $this->parsedCache = BBCode\Parser::parseEmoticons(clean_string($this->text));
}
return $this->parsedCache;
diff --git a/app/Controllers/HelperController.php b/app/Controllers/HelperController.php
index 7d431e3..fe147ec 100644
--- a/app/Controllers/HelperController.php
+++ b/app/Controllers/HelperController.php
@@ -6,7 +6,7 @@
namespace Sakura\Controllers;
-use Sakura\BBcode;
+use Sakura\BBCode\Parser as BBParser;
/**
* Helper controller.
@@ -21,6 +21,6 @@ class HelperController extends Controller
*/
public function bbcodeParse()
{
- return BBcode::toHTML(htmlentities($_POST['text'] ?? ''));
+ return BBParser::toHTML(htmlentities($_POST['text'] ?? ''));
}
}
diff --git a/app/Forum/Post.php b/app/Forum/Post.php
index 6c31f86..784059d 100644
--- a/app/Forum/Post.php
+++ b/app/Forum/Post.php
@@ -125,7 +125,7 @@ class Post
}
// Parse the markup
- $this->parsed = BBcode::toHTML(htmlentities($this->text));
+ $this->parsed = BBCode\Parser::toHTML(htmlentities($this->text));
}
/**
diff --git a/app/User.php b/app/User.php
index add61bc..8037549 100644
--- a/app/User.php
+++ b/app/User.php
@@ -902,7 +902,7 @@ class User
*/
public function userPage()
{
- return BBcode::toHTML(htmlentities($this->page));
+ return BBCode\Parser::toHTML(htmlentities($this->page));
}
/**
@@ -911,7 +911,7 @@ class User
*/
public function signature()
{
- return BBcode::toHTML(htmlentities($this->signature));
+ return BBCode\Parser::toHTML(htmlentities($this->signature));
}
/**