Skip to content

Commit be5f46e

Browse files
committed
🚿
1 parent d36ef9c commit be5f46e

File tree

8 files changed

+56
-183
lines changed

8 files changed

+56
-183
lines changed

README.md

Lines changed: 9 additions & 166 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A recursive regexp [BBCode](http://en.wikipedia.org/wiki/BBCode) parser for PHP 7+ using [preg_replace_callback()](http://php.net/preg_replace_callback),
44
based on an example by [MrNiceGuy](http://www.developers-guide.net/forums/member/69,mrniceguy) on
5-
[developers-guide.net](http://www.developers-guide.net/c/152-bbcode-parser-mit-noparse-tag-selbst-gemacht.html).
5+
[developers-guide.net](http://www.developers-guide.net/c/152-bbcode-parser-mit-noparse-tag-selbst-gemacht.html).
66
Handles nested tags as well as matching brackets and doesn't stumble across invalid tags.
77

88
[![version][packagist-badge]][packagist]
@@ -29,12 +29,9 @@ Handles nested tags as well as matching brackets and doesn't stumble across inva
2929
[donate]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=WLYUNAT9ZTJZ4
3030

3131
# Requirements
32-
- PHP 7+ ([PHP 5.6+ compatible branch](https://github.com/chillerlan/php-bbcode/tree/php5))
32+
- PHP 7.2+
3333

3434
# Documentation
35-
## BBCode docs
36-
A documentation of the included BBCodes is planned and will be available soon™ on [the wiki](https://github.com/chillerlan/php-bbcode/wiki).
37-
3835
## Installation
3936
**requires [composer](https://getcomposer.org)**
4037

@@ -43,186 +40,32 @@ A documentation of the included BBCodes is planned and will be available soon&tr
4340
```json
4441
{
4542
"require": {
46-
"php": ">=7.0.3",
43+
"php": ">=7.2.0",
4744
"chillerlan/php-bbcode": "dev-master"
4845
}
4946
}
5047
```
5148

5249
### Manual installation
53-
Download the desired version of the package from [master](https://github.com/chillerlan/php-bbcode/archive/master.zip) or
50+
Download the desired version of the package from [master](https://github.com/chillerlan/php-bbcode/archive/master.zip) or
5451
[release](https://github.com/chillerlan/php-bbcode/releases) and extract the contents to your project folder. After that:
5552
- run `composer install` to install the required dependencies and generate `/vendor/autoload.php`.
56-
- if you use a custom autoloader, point the namespace `chillerlan\Database` to the folder `src` of the package
53+
- if you use a custom autoloader, point the namespace `chillerlan\BBCode` to the folder `src` of the package
5754

5855
Profit!
5956

6057
## Usage
61-
First of all, you'll need to import the needed classes of course:
62-
```php
63-
namespace MyProject;
64-
65-
use chillerlan\bbcode\Parser;
66-
use chillerlan\bbcode\ParserOptions;
67-
```
68-
69-
### Parser options
70-
In order to create a `Parser` instance, you'll first want to create an instance of `ParserOptions` and alter it if needed.
71-
However, this step is optional (meta, eh?).
72-
```php
73-
$options = new ParserOptions;
74-
$options->languageInterface = MyLanguage::class;
75-
$options->baseModuleInterface = MyAwesomeBaseModule::class;
76-
$options->parserExtensionInterface = MyAwesomeParserExtension::class;
77-
$options->sanitize = true;
78-
$options->nesting_limit = 10;
79-
$options->eol_placeholder = '__MYEOL__';
80-
$options->bbtag_placeholder = '__MYBBTAG__';
81-
$options->allowed_tags = ['mybbcode', 'somebbcode', 'whatever'];
82-
$options->allow_all = false;
83-
```
84-
85-
### Parser
86-
Now we're ready to create the `Parser`:
87-
```php
88-
$bbcode = new Parser($options);
89-
90-
// or...
91-
92-
$bbcode = new Parser;
93-
$bbcode->setOptions($options);
94-
```
95-
96-
Run the parser and output:
97-
```php
98-
echo $bbcode->parse($some_string_containing_bbcode);
99-
```
100-
101-
In case you need some diagnostics, here you go:
102-
```php
103-
$bbcode->getTagmap(); // map of tag -> module FQCN
104-
$bbcode->getAllowed(); // all allowed tags
105-
$bbcode->getNoparse(); // all noparse tags
106-
$bbcode->getSingle(); // all singletags
107-
108-
// get all tags of a module
109-
$module_tags = array_keys($bbcode->getTagmap(), MyAwesomeModule::class);
110-
```
111-
112-
That's all!
113-
114-
## Extend the parser
115-
### Base module
116-
In order to create your own modules, you'll first need an empty base module which contains
117-
all basic settings and methods for each module. To do so, you'll need to extend
118-
`\chillerlan\bbcode\Modules\BaseModuleAbstract` . There's really not much to do, the only and most
119-
important thing is to tell the parser which modules to use. Further, you need to specify
120-
a `sanitize()` method and maybe an EOL token - the rest is up to you and may vary between output types.
121-
```php
122-
namespace Example\MyModules;
123-
124-
use chillerlan\bbcode\Modules\BaseModuleAbstract;
125-
use Example\MyModules\MyAwesomeModule;
126-
127-
class MyAwesomeBaseModule extends BaseModuleAbstract{
128-
129-
protected $modules = [
130-
MyAwesomeModule::class,
131-
];
132-
133-
protected $eol_token = '<br />';
134-
135-
public function sanitize($content){
136-
return htmlspecialchars($content, ENT_NOQUOTES|ENT_HTML5, 'UTF-8', false);
137-
}
138-
139-
}
140-
```
141-
142-
### Encoder module
143-
Now that we have our base module, we're able to create the encoder module, where the actual transform happens.
144-
Each encoder module extends a base module depending on output type (`MyAwesomeBaseModule` here)
145-
and implements `\chillerlan\bbcode\Modules\ModuleInterface`. The property `$tags` and the method `__transform()` are mandatory.
146-
In case your module supports noparse or single tags, you may set the respective properties `$noparse_tags` and `$singletags`.
147-
```php
148-
namespace Example\MyModules;
149-
150-
use chillerlan\bbcode\Modules\ModuleInterface;
151-
use Example\MyModules\MyAwesomeBaseModule;
15258

153-
class MyAwesomeModule extends MyAwesomeBaseModule implements ModuleInterface{
59+
- @todo
15460

155-
protected $tags = ['mybbcode', 'somebbcode', 'whatever'];
61+
For an [implementation example](https://github.com/codemasher/gw1-database/blob/master/public/gwbbcode.php) see the over here: [gw1-database/GWBBCode](https://github.com/codemasher/gw1-database/tree/master/src/GWBBCode).
15662

157-
public function __transform(){
158-
if(empty($this->content)){
159-
return '';
160-
}
161-
162-
return '<'.$this->tag.'>'.$this->content.'</'.$this->tag.'>';
163-
}
164-
165-
}
166-
```
167-
168-
You can also extend one of the existing modules to alter their behaviour, for example if you want the module to support more bbcodes.
169-
In this case, you should be aware that the module already extends a base module, which will be used instead of your own.
170-
However, the module information, EOL token and sanitize method of your base module will be used in the parser then
171-
and should match the extended module's parent.
172-
```php
173-
namespace Example\MyModules;
174-
175-
use chillerlan\bbcode\Modules\ModuleInterface;
176-
use chillerlan\bbcode\Modules\Html5\Simpletext;
177-
178-
class MyAwesomeModule extends Simpletext implements ModuleInterface{
179-
180-
protected $tags = [
181-
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'strong', 'sub', 'sup', 'del', 'small', // default tags
182-
'mybbcode', 'somebbcode', 'whatever', // your own tags
183-
];
184-
185-
}
186-
```
187-
188-
### Parser extension
189-
The parser features an extension which allows you to alter the bbcode during the parsing process,
190-
namely before and after the main parser unit runs. If you want to create your own parser extension,
191-
just implement `\chillerlan\bbcode\ParserExtensionInterface`, set it in the parser options and you're done.
192-
```php
193-
namespace Example;
194-
195-
use chillerlan\bbcode\ParserExtensionInterface;
196-
197-
class MyAwesomeParserExtension implements ParserExtensionInterface{
198-
199-
public function pre($bbcode){
200-
201-
$search = [
202-
"\t", // lets convert all tabs into 4 spaces
203-
'{__BASE_URL__}', // assume we use a special token for our base url
204-
];
205-
206-
$replace = [
207-
' ',
208-
'https://your.base/url/'
209-
];
210-
211-
return str_replace($search, $replace, $bbcode);
212-
}
213-
214-
public function post($bbcode){
215-
return $bbcode;
216-
}
217-
218-
}
219-
```
22063
### Language
22164
- @todo
222-
65+
22366
## Notes
22467
The parser may cause some high CPU load, depending on the input. You should never consider to use it somewhere
225-
in your output subsystem - not even with strong caching. Encode on input - you'll want a preview anyway. ;)
68+
in your output subsystem - encode on input - you'll want a preview anyway. ;)
22669

22770
You may also run into several bugs. In fact, the BBCoder is essentially a tool to squeeze out any PCRE related bug in PHP known to man (and perhaps unknown). Have fun! ;)
22871
[It is highly recommended to use these php.ini settings](https://github.com/chillerlan/php-bbcode/blob/master/travis-php.ini), especially to disable the PCRE JIT in PHP7 which is a troublemaker.

phpunit.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
convertWarningsToExceptions="true"
99
processIsolation="false"
1010
stopOnFailure="false"
11-
syntaxCheck="false"
1211
>
1312
<filter>
1413
<whitelist processUncoveredFilesFromWhitelist="true">

src/BBCache.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
use Psr\SimpleCache\CacheInterface;
1616

17-
class BBCache implements CacheInterface{
17+
final class BBCache implements CacheInterface{
1818

1919
/**
2020
* @var array

src/BBCode.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class BBCode implements LoggerAwareInterface{
2828
protected $options;
2929

3030
/**
31-
* @var \Psr\SimpleCache\CacheInterface
31+
* @var \Psr\SimpleCache\CacheInterface|\chillerlan\BBCode\BBCache
3232
*/
3333
protected $cache;
3434

@@ -62,6 +62,11 @@ class BBCode implements LoggerAwareInterface{
6262
*/
6363
protected $allowed = [];
6464

65+
/**
66+
* @var int
67+
*/
68+
protected $limit;
69+
6570
/**
6671
* BBCode constructor.
6772
*
@@ -143,8 +148,6 @@ public function setOptions(SettingsContainerInterface $options):BBCode{
143148
}
144149
}
145150

146-
147-
148151
if($this->options->preParse || $this->options->postParse){
149152
$this->parserMiddleware = new $this->options->parserMiddlewareInterface($this->options, $this->cache, $this->logger);
150153

@@ -161,6 +164,7 @@ public function setOptions(SettingsContainerInterface $options):BBCode{
161164

162165
$this->tags = $this->outputInterface->getTags();
163166
$this->noparse = $this->outputInterface->getNoparse();
167+
$this->limit = (int)$this->options->nestingLimit;
164168

165169
if(is_array($this->options->allowedTags) && !empty($this->options->allowedTags)){
166170
$this->allowTags($this->options->allowedTags);
@@ -196,6 +200,9 @@ public function parse(string $bbcode):string{
196200

197201
// close singletags: [br] -> [br][/br]
198202
$bbcode = preg_replace('#\[('.implode('|', $singleTags).')((?:\s|=)[^]]*)?]#is', '[$1$2][/$1]', $bbcode);
203+
204+
// @todo: find non-singletags without a closing tag and close them (or convert the brackets to entities)
205+
199206
// protect newlines
200207
$bbcode = str_replace(["\r", "\n"], ['', $this->options->placeholder_eol], $bbcode);
201208
// parse the bbcode
@@ -246,7 +253,7 @@ protected function parseBBCode($bbcode):string{
246253
return '';
247254
}
248255

249-
if($callback_count < (int)$this->options->nestingLimit && !in_array($tag, $this->noparse , true)){
256+
if($callback_count < $this->limit && !in_array($tag, $this->noparse , true)){
250257
$content = preg_replace_callback('#\[(\w+)((?:\s|=)[^]]*)?]((?:[^[]|\[(?!/?\1((?:\s|=)[^]]*)?])|(?R))*)\[/\1]#', __METHOD__, $content);
251258
$e = preg_last_error();
252259

src/BBCodeOptions.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
namespace chillerlan\BBCode;
1414

15-
1615
use chillerlan\Settings\SettingsContainerAbstract;
1716

1817
/**

src/BBCodeOptionsTrait.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212

1313
namespace chillerlan\BBCode;
1414

15-
use chillerlan\BBCode\Output\HTML\{
16-
HTMLOutput, HTMLSanitizer
17-
};
15+
use chillerlan\BBCode\Output\HTML\{HTMLOutput, HTMLSanitizer};
1816

1917
trait BBCodeOptionsTrait{
2018

src/Output/BBCodeModuleAbstract.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,39 @@
1818

1919
abstract class BBCodeModuleAbstract implements BBCodeModuleInterface{
2020

21+
/**
22+
* The current bbcode tag
23+
*
24+
* @var string
25+
*/
2126
protected $tag;
27+
28+
/**
29+
* The attributes of the current bbcode
30+
*
31+
* @var array
32+
*/
2233
protected $attributes;
34+
35+
/**
36+
* The content of the current bbcode
37+
*
38+
* @var string
39+
*/
2340
protected $content;
41+
42+
/**
43+
* The full matched string of the current bbcode
44+
*
45+
* @var
46+
*/
2447
protected $match;
48+
49+
/**
50+
* The callback counter
51+
*
52+
* @var
53+
*/
2554
protected $callback_count;
2655

2756
/**
@@ -249,5 +278,4 @@ protected function tagIn(array $whitelist, $default = false){
249278
: $default;
250279
}
251280

252-
253281
}

src/Output/BBCodeOutputAbstract.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
use Psr\SimpleCache\CacheInterface;
1818

1919
abstract class BBCodeOutputAbstract implements BBCodeOutputInterface{
20-
use ClassLoader;
2120

2221
/**
2322
* @var string[]
@@ -43,6 +42,11 @@ abstract class BBCodeOutputAbstract implements BBCodeOutputInterface{
4342
*/
4443
protected $noparse = [];
4544

45+
/**
46+
* @var string
47+
*/
48+
protected $eol = PHP_EOL;
49+
4650
/**
4751
* @var \chillerlan\BBCode\BBCodeOptions
4852
*/
@@ -63,11 +67,6 @@ abstract class BBCodeOutputAbstract implements BBCodeOutputInterface{
6367
*/
6468
protected $moduleInterfaces = [];
6569

66-
/**
67-
* @var string
68-
*/
69-
protected $eol = PHP_EOL;
70-
7170
/**
7271
* BBCodeOutputInterface constructor.
7372
*

0 commit comments

Comments
 (0)