* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 */ namespace App\Helpers; class Bbcode { /** * @var array */ public $parsers = [ 'h1' => [ 'pattern' => '/\[h1\](.*?)\[\/h1\]/s', 'replace' => '

$1

', 'content' => '$1', ], 'h2' => [ 'pattern' => '/\[h2\](.*?)\[\/h2\]/s', 'replace' => '

$1

', 'content' => '$1', ], 'h3' => [ 'pattern' => '/\[h3\](.*?)\[\/h3\]/s', 'replace' => '

$1

', 'content' => '$1', ], 'h4' => [ 'pattern' => '/\[h4\](.*?)\[\/h4\]/s', 'replace' => '

$1

', 'content' => '$1', ], 'h5' => [ 'pattern' => '/\[h5\](.*?)\[\/h5\]/s', 'replace' => '
$1
', 'content' => '$1', ], 'h6' => [ 'pattern' => '/\[h6\](.*?)\[\/h6\]/s', 'replace' => '
$1
', 'content' => '$1', ], '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', ], 'size' => [ 'pattern' => '/\[size\=(.*?)\](.*?)\[\/size\]/s', 'replace' => '$2', 'content' => '$2', ], 'font' => [ 'pattern' => '/\[font\=(.*?)\](.*?)\[\/font\]/s', 'replace' => '$2', 'content' => '$2', ], 'color' => [ 'pattern' => '/\[color\=(.*?)\](.*?)\[\/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', ], 'quote' => [ 'pattern' => '/\[quote\](.*?)\[\/quote\]/s', 'replace' => '', 'content' => '$1', ], 'namedquote' => [ 'pattern' => '/\[quote\=(.*?)\](.*)\[\/quote\]/s', 'replace' => '', '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', ], 'sized-image' => [ 'pattern' => '/\[img width\=(.*?)\](.*?)\[\/img\]/s', 'replace' => '', 'content' => '$1', ], 'sized-image2' => [ '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', ], 'alert' => [ 'pattern' => '/\[alert\](.*?)\[\/alert\]/s', 'replace' => '
    $1
    ', 'content' => '$1', ], 'note' => [ 'pattern' => '/\[note\](.*?)\[\/note\]/s', 'replace' => '
    $1
    ', 'content' => '$1', ], 'sub' => [ 'pattern' => '/\[sub\](.*?)\[\/sub\]/s', 'replace' => '$1', 'content' => '$1', ], 'sup' => [ 'pattern' => '/\[sup\](.*?)\[\/sup\]/s', 'replace' => '$1', 'content' => '$1', ], 'small' => [ 'pattern' => '/\[small\](.*?)\[\/small\]/s', 'replace' => '$1', 'content' => '$1', ], 'table' => [ 'pattern' => '/\[table\](.*?)\[\/table\]/s', 'replace' => '$1
    ', 'content' => '$1', ], 'table-row' => [ 'pattern' => '/\[tr\](.*?)\[\/tr\]/s', 'replace' => '$1', 'content' => '$1', ], 'table-data' => [ 'pattern' => '/\[td\](.*?)\[\/td\]/s', 'replace' => '$1', 'content' => '$1', ], 'youtube' => [ 'pattern' => '/\[youtube\](.*?)\[\/youtube\]/s', 'replace' => '', 'content' => '$1', ], 'video' => [ 'pattern' => '/\[video\](.*?)\[\/video\]/s', 'replace' => '', 'content' => '$1', ], 'video-youtube' => [ 'pattern' => '/\[video="youtube"\](.*?)\[\/video\]/s', 'replace' => '', 'content' => '$1', ], 'linebreak' => [ 'pattern' => '/\r\n/', 'replace' => '
    ', 'content' => '', ], 'spoiler' => [ 'pattern' => '/\[spoiler\](.*?)\[\/spoiler\]/s', 'replace' => '
    Spoiler
    $1
    ', 'content' => '$1', ], 'named-spoiler' => [ 'pattern' => '/\[spoiler\=(.*?)\](.*?)\[\/spoiler\]/s', 'replace' => '
    $1
    $2
    ', 'content' => '$1', ], ]; /** * @var array */ protected $enabledParsers = []; public function __construct() { $this->enabledParsers = $this->parsers; } /** * Parses the BBCode string. * * @param $source * @param bool $caseInsensitive * * @return string */ public function parse($source, $caseInsensitive = false) { foreach ($this->enabledParsers as $name => $parser) { $pattern = ($caseInsensitive) ? $parser['pattern'].'i' : $parser['pattern']; $source = $this->searchAndReplace($pattern, $parser['replace'], $source); } return $source; } /** * Remove all BBCode. * * @param string $source * * @return string Parsed text */ public function stripBBCodeTags($source) { foreach ($this->parsers as $name => $parser) { $source = $this->searchAndReplace($parser['pattern'].'i', $parser['content'], $source); } return $source; } /** * Searches after a specified pattern and replaces it with provided structure. * * @param string $pattern Search pattern * @param string $replace Replacement structure * @param string $source Text to search in * * @return string Parsed text */ protected function searchAndReplace($pattern, $replace, $source) { while (preg_match($pattern, $source)) { $source = preg_replace($pattern, $replace, $source); } return $source; } /** * Helper function to parse case sensitive. * * @param string $source String containing the BBCode * * @return string Parsed text */ public function parseCaseSensitive($source) { return $this->parse($source, false); } /** * Helper function to parse case insensitive. * * @param string $source String containing the BBCode * * @return string Parsed text */ public function parseCaseInsensitive($source) { return $this->parse($source, true); } /** * List of chosen parsers. * * @return array array of parsers */ public function getParsers() { return $this->enabledParsers; } /** * Sets the parser pattern and replace. * This can be used for new parsers or overwriting existing ones. * * @param string $name Parser name * @param string $pattern Pattern * @param string $replace Replace pattern * @param string $content Parsed text pattern * * @return void */ public function setParser($name, $pattern, $replace, $content) { $this->parsers[$name] = [ 'pattern' => $pattern, 'replace' => $replace, 'content' => $content, ]; $this->enabledParsers[$name] = [ 'pattern' => $pattern, 'replace' => $replace, 'content' => $content, ]; } }