Skip to content

Commit 7538cca

Browse files
committed
Initial release
1 parent daf5c93 commit 7538cca

File tree

2 files changed

+301
-1
lines changed

2 files changed

+301
-1
lines changed

README.md

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,97 @@
11
# LC-quick-shortcodes
2-
The quickest way to implement WordPress-like shortcodes on your project!
2+
WordPress shortcodes don't need any presentation: they simply are the most used and effective way to turn short texts into complex structures.
3+
Using this tiny PHP class you'll be able to use the same engine also on your project!
4+
5+
As little extra, the class already executes few common __[BBcodes](https://en.wikipedia.org/wiki/BBCode)__ (continue reading to know which ones)
6+
7+
It is just 5KB big and __doesn't have any dependency__.<br/>
8+
Supports any server running __PHP 5.4__ and later.<br/>
9+
Shortcodes can be __nested__ and you can use __HTML__ within.
10+
11+
12+
How to use
13+
---
14+
15+
Include the class in the project and initialize it with its namespace:
16+
17+
``` php
18+
include_once('lc_quick_shortcodes.php');
19+
$lcqs = new lcweb\quick_sc\lc_quick_shortcodes;
20+
```
21+
<br/>
22+
23+
#### Shortcodes registration
24+
Here are two examples: the first says Hello!, while the second prints a code block.
25+
26+
``` php
27+
/**
28+
* Register a new shortcode
29+
*
30+
* @param (string) $name = shortcode's name
31+
* @param (array) $defaults = shortcode parameters and their defaults
32+
* @param (bool) $has_contents = whether shortcode will have contents or not
33+
* @param (func|string) $callback = callback function name or anonymous function
34+
*/
35+
36+
$lcqs->register('hello', array(), false, function($atts, $contents) {
37+
return '<h1>Hello!</h1>';
38+
});
39+
40+
$lcqs->register('title', array('lang'=>'html'), true, function($atts, $contents) {
41+
return '<pre class="language-'. $atts['lang'] .'"><code>'. $contents .'</code></pre>';
42+
});
43+
```
44+
45+
Analyzing function parameters:
46+
47+
1. sets shortcode's name. Must not have spaces in it.<br/><br/>
48+
2. defines shortcode parameters and their defaults. In this example we expect a parameter called _lang_ and it has a default value of _html_.<br/><br/>Then using _[code][/code]_ the resulting code will still use _html_, while using _[code lang="php"][/code]_ you will override the default value.<br/><br/>
49+
3. FALSE if there are no contents (first example), TRUE if contents will be used within (second example)<br/><br/>
50+
4. May be a function name triggering a callback or an [anonymous function](http://php.net/manual/en/functions.anonymous.php) (as used in the example).<br/>The function will have two parameters: and contents.<br/><br/>
51+
1. __*shortcode attributes*__ - an associative array containing every attribute found in the shortcode implementation. It contains also custom ones not declared in shortcode registration (eg. _[hello param1="hey!"]_ )
52+
2. __*contents*__ - this is empty if $has_contents is set to false
53+
54+
55+
<br/>
56+
57+
#### Shortcodes execution
58+
Once everything is properly registered, just let the class execute your string
59+
60+
``` php
61+
/**
62+
* Execute shortcodes in a text string
63+
*
64+
* @param (string) $txt = text
65+
* @param (bool) $bbcodes = whether to execute found BBcodes first (see https://www.bbcode.org/reference.php )
66+
*
67+
* @return (string) executed text
68+
*/
69+
70+
$string = 'Lorem ipsum [code]dolor sit amet[/code]';
71+
echo $lcqs->process($string, $bbcodes = true);
72+
73+
/* Resulting string:
74+
* Lorem ipsum <pre class="language-html"><code>dolor sit amet</code></pre>
75+
*/
76+
```
77+
78+
First parameter is your string, while second ones sets whether to execute also BBcodes or not.
79+
80+
Here's the list of supported BBcodes:
81+
82+
| Example | Description |
83+
| ------------- |:-------------:|
84+
| [b] _test_ [/b] | bold text |
85+
| [i] _test_ [/i] | italic text |
86+
| [u] _test_ [/u] | underlined text |
87+
| [code] _test_ [/code] | PRE code block |
88+
| [size=20] _test_ [/size] | sets font size (in pixels) |
89+
| [color=#ff0000] _test_ [/color] | sets text color (hex vlue) |
90+
| [url] _http://mypage.com_ [/url] | creates a link |
91+
| [ul]<br/>[\*] test 1 <br/>[\*] test 2 <br/>[/ul] | unordered list |
92+
| [ol]<br/>[\*] test 1 <br/>[\*] test 2 <br/>[/ol] | ordered list |
93+
94+
<br/><br/>
95+
* * *
96+
97+
Copyright &copy; Luca Montanari (aka LCweb)

lc_quick_shortcodes.php

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
<?php
2+
/**
3+
* LC Quick Shortcodes v1.0
4+
* Tiny PHP class emulating WordPress shortcodes engine and supporting few BBcodes
5+
*
6+
*
7+
* @author Luca Montanari aka LCweb
8+
* @copyright 2018 Luca Montanari - https://lcweb.it
9+
*
10+
* https://github.com/LCweb-ita/LC-quick-shortcodes
11+
* Licensed under the MIT license
12+
*/
13+
14+
15+
namespace lcweb\quick_sc;
16+
17+
18+
class lc_quick_shortcodes {
19+
20+
/* (array) shortcodes database containing sc key, defaults and callback function
21+
22+
array(
23+
'key' => array(
24+
'defaults' => (array), // expected parameters and default values
25+
'has_contents' => (bool)
26+
'callback' => anonymous function or function name - parameters array is passed
27+
)
28+
)
29+
*/
30+
private $sc_db = array();
31+
32+
33+
34+
35+
36+
37+
/**
38+
* Register a new shortcode
39+
*
40+
* @param (string) $name = shortcode's name
41+
* @param (array) $defaults = shortcode parameters and their defaults
42+
* @param (bool) $has_contents = whether shortcode will have contents or not
43+
* @param (func|string) $callback = callback function name or anonymous function
44+
*/
45+
46+
public function register($name, $defaults = array(), $has_contents = false, $callback) {
47+
48+
$this->sc_db[ $name ] = array(
49+
'defaults' => $defaults,
50+
'has_contents' => $has_contents,
51+
'callback' => $callback
52+
);
53+
}
54+
55+
56+
57+
58+
59+
/**
60+
* Execute shortcodes in a text string
61+
*
62+
* @param (string) $txt = text
63+
* @param (bool) $bbcodes = whether to execute found BBcodes first (see https://www.bbcode.org/reference.php )
64+
*
65+
* @return (string) executed text
66+
*/
67+
68+
public function process($txt, $bbcodes = true) {
69+
70+
if($bbcodes) {
71+
$txt = $this->bbcodes($txt);
72+
}
73+
74+
75+
// cycle shortcodes
76+
foreach($this->sc_db as $sc_name => $sc) {
77+
78+
// find occurrences
79+
$regexp = ($sc['has_contents']) ? '~\['. $sc_name .'(.*?)\](.*?)\[/'. $sc_name .'\]~s' : '~\['. $sc_name .'(.*?)\]~s';
80+
preg_match_all($regexp, $txt, $matches);
81+
82+
// nothing found - skip
83+
if(empty($matches[0])) {
84+
continue;
85+
}
86+
87+
// elaborate results and execute for each occurrence
88+
$managed = $this->manag_matches($matches, $sc['has_contents']);
89+
90+
foreach($managed as $target => $match_data) {
91+
$replace_with = call_user_func(
92+
$sc['callback'],
93+
$this->parse_atts($match_data['atts'], $sc['defaults']),
94+
$match_data['contents']
95+
);
96+
97+
$txt = str_replace($target, $replace_with, $txt);
98+
}
99+
}
100+
101+
return $txt;
102+
}
103+
104+
105+
106+
107+
108+
/**
109+
* Wrap up matches cleaning repeated ones and returning a more useful array
110+
*
111+
* @param (array) $matches = preg_match_all results
112+
* @param (bool) $has_contents = whether we are elaborating a shortcode with contents
113+
*
114+
* @return (array) array('to_be_replaced' => array('atts' => raw_atts_string, 'contents' => ''))
115+
*/
116+
117+
private function manag_matches($matches, $has_contents = false) {
118+
$result = array();
119+
120+
$matched_count = count($matches[0]);
121+
for($a=0; $a < $matched_count; $a++) {
122+
123+
$result[ $matches[0][$a] ] = array(
124+
'atts' => $matches[1][$a],
125+
'contents' => ($has_contents) ? $matches[2][$a] : ''
126+
);
127+
}
128+
129+
return $result;
130+
}
131+
132+
133+
134+
135+
136+
/**
137+
* Set up shortcode parameters overriding defaults with found ones
138+
*
139+
* @param (string) $raw = raw string containing shortcode parameters
140+
* @param (array) $defaults = shortcode defaults
141+
*/
142+
143+
private function parse_atts($raw, $defaults) {
144+
if(empty($raw)) {
145+
return $defaults;
146+
}
147+
148+
$atts = array();
149+
$raw_arr = explode(' ', substr($raw, 1));
150+
151+
foreach($raw_arr as $raw_att) {
152+
$arr = explode('="', substr($raw_att, 0, -1));
153+
154+
if(count($arr) == 2) {
155+
$atts[ $arr[0] ] = $arr[1];
156+
}
157+
}
158+
159+
return array_merge($defaults, $atts);
160+
}
161+
162+
163+
164+
165+
166+
167+
/**
168+
* Turns BBcodes into HTML - actually supporting only few of them
169+
(thanks to Afsal Rahim @ http://digitcodes.com/create-simple-php-bbcode-parser-function/ )
170+
171+
* @param (string) $txt = text to elaborate
172+
*/
173+
174+
public function bbcodes($txt) {
175+
$find = array(
176+
'~\[b\](.*?)\[/b\]~s',
177+
'~\[i\](.*?)\[/i\]~s',
178+
'~\[u\](.*?)\[/u\]~s',
179+
'~\[code\](.*?)\[/code\]~s',
180+
'~\[size=(.*?)\](.*?)\[/size\]~s',
181+
'~\[color=(.*?)\](.*?)\[/color\]~s',
182+
'~\[url\]((?:ftp|https?)://.*?)\[/url\]~s',
183+
'~\[img\](https?://.*?\.(?:jpg|jpeg|gif|png|bmp))\[/img\]~s',
184+
'~\[ul\](.*?)\[/ul\]~s',
185+
'~\[ol\](.*?)\[/ol\]~s',
186+
'~\[\*\]~s',
187+
);
188+
189+
$replace = array(
190+
'<b>$1</b>',
191+
'<i>$1</i>',
192+
'<span style="text-decoration:underline;">$1</span>',
193+
'<pre>$1</pre>',
194+
'<span style="font-size:$1px;">$2</span>',
195+
'<span style="color:$1;">$2</span>',
196+
'<a href="$1">$1</a>',
197+
'<img src="$1" alt="" />',
198+
'<ul>$1</li></ul>',
199+
'<ol>$1</li></ol>',
200+
'<li>'
201+
);
202+
203+
return preg_replace($find, $replace, $txt);
204+
}
205+
}

0 commit comments

Comments
 (0)