├── README.md ├── Shortcode.php └── composer.json /README.md: -------------------------------------------------------------------------------- 1 | yii2-shortcodes 2 | =============== 3 | 4 | Wordpress style shortcodes support for Yii2 5 | 6 | Most part of the code taken from https://github.com/Easy-Forex/WordPress-Shortcodes 7 | 8 | 9 | Installation 10 | ------------ 11 | ```code 12 | { 13 | "require": { 14 | "tpoxa/shortcodes": "dev-master" 15 | } 16 | } 17 | ``` 18 | Configuration 19 | ------------- 20 | In config file 21 | ```code 22 | /config/main.php 23 | ``` 24 | Add shortcodes component 25 | ```code 26 | 'components' => array( 27 | ... 28 | 'shortcodes' => [ 29 | 'class' => 'tpoxa\shortcodes\Shortcode', 30 | 'callbacks' => [ 31 | 'lastphotos' => ['frontend\widgets\lastPhoto\lastPhoto', 'widget'], 32 | 'anothershortcode'=>function($attrs, $content, $tag){ 33 | /// 34 | }, 35 | 36 | ] 37 | ], 38 | ``` 39 | Usage 40 | ----- 41 | ```php 42 | 43 | echo \Yii::$app->shortcodes->parse(' 44 |
some content [lastphotos limit=8] >
45 | ') 46 | 47 | ``` 48 | 49 | Additional 50 | ---- 51 | callbacks - An array of valid PHP callbacks. Keys should contain names of the shortcodes. 52 | 53 | lastPhoto example class - common Yii2 widget 54 | 55 | ```php 56 | namespace frontend\widgets\lastPhoto; // your App class 57 | 58 | use yii\base\Widget; 59 | class lastPhoto extends Widget { 60 | 61 | public $limit = 5; // this parameter will be overwritten by 8 62 | 63 | public function run() { 64 | // your widget content goes here 65 | } 66 | 67 | } 68 | ``` 69 | -------------------------------------------------------------------------------- /Shortcode.php: -------------------------------------------------------------------------------- 1 | getShortcodeList($content); 30 | foreach ($shortcodes as $shortcode) { 31 | // Only process known/supported shortcodes 32 | if (in_array($shortcode, array_keys($this->callbacks))) { 33 | $regexp = $this->getShortcodeRegexp($shortcode); 34 | $result = preg_replace_callback("/$regexp/s", array($this, 'parseSingle'), $result); 35 | } 36 | } 37 | 38 | return $result; 39 | } 40 | 41 | /** 42 | * Parse single shortcode 43 | * 44 | * Borrowed from WordPress wp/wp-includes/shortcode.php 45 | * 46 | * @param array $m Shortcode matches 47 | * @return string 48 | */ 49 | protected function parseSingle($m) { 50 | 51 | // allow [[foo]] syntax for escaping a tag 52 | if ($m[1] == '[' && $m[6] == ']') { 53 | return substr($m[0], 1, -1); 54 | } 55 | 56 | $tag = $m[2]; 57 | $attr = $this->shortcodeParseAtts($m[3]); 58 | 59 | if ($attr === '') { 60 | $attr = null; 61 | } 62 | 63 | if (isset($m[5])) { 64 | // enclosing tag - extra parameter 65 | return $m[1] . call_user_func($this->callbacks[$tag], $attr, $m[5], $tag) . $m[6]; 66 | } else { 67 | // self-closing tag 68 | return $m[1] . call_user_func($this->callbacks[$tag], $attr, null, $tag) . $m[6]; 69 | } 70 | } 71 | 72 | /** 73 | * Get the list of all shortcodes found in given content 74 | * 75 | * @param string $content Content to process 76 | * @return array 77 | */ 78 | protected function getShortcodeList($content) { 79 | $result = array(); 80 | 81 | preg_match_all("/\[([A-Za-z_]+[^\ \]]+)/", $content, $matches); 82 | if (!empty($matches[1])) { 83 | foreach ($matches[1] as $match) { 84 | $result[$match] = $match; 85 | } 86 | } 87 | return $result; 88 | } 89 | 90 | /** 91 | * Parses attributes from a shortcode 92 | * 93 | * Borrowed from WordPress wp/wp-includes/shortcode.php 94 | * 95 | * @param string $text 96 | * @return array 97 | */ 98 | protected function shortcodeParseAtts($text) { 99 | $atts = array(); 100 | $pattern = '/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/'; 101 | $text = preg_replace("/[\x{00a0}\x{200b}]+/u", " ", $text); 102 | if (preg_match_all($pattern, $text, $match, PREG_SET_ORDER)) { 103 | foreach ($match as $m) { 104 | if (!empty($m[1])) 105 | $atts[strtolower($m[1])] = stripcslashes($m[2]); 106 | elseif (!empty($m[3])) 107 | $atts[strtolower($m[3])] = stripcslashes($m[4]); 108 | elseif (!empty($m[5])) 109 | $atts[strtolower($m[5])] = stripcslashes($m[6]); 110 | elseif (isset($m[7]) and strlen($m[7])) 111 | $atts[] = stripcslashes($m[7]); 112 | elseif (isset($m[8])) 113 | $atts[] = stripcslashes($m[8]); 114 | } 115 | } else { 116 | $atts = ltrim($text); 117 | } 118 | return $atts; 119 | } 120 | 121 | /** 122 | * Returns a regular expression for matching a shortcode tag 123 | * 124 | * Borrowed from WordPress wp/wp-includes/shortcode.php 125 | * 126 | * @return string 127 | */ 128 | protected function getShortcodeRegexp($tagregexp) { 129 | 130 | return 131 | '\\[' // Opening bracket 132 | . '(\\[?)' // 1: Optional second opening bracket for escaping shortcodes: [[tag]] 133 | . "($tagregexp)" // 2: Shortcode name 134 | . '(?![\\w-])' // Not followed by word character or hyphen 135 | . '(' // 3: Unroll the loop: Inside the opening shortcode tag 136 | . '[^\\]\\/]*' // Not a closing bracket or forward slash 137 | . '(?:' 138 | . '\\/(?!\\])' // A forward slash not followed by a closing bracket 139 | . '[^\\]\\/]*' // Not a closing bracket or forward slash 140 | . ')*?' 141 | . ')' 142 | . '(?:' 143 | . '(\\/)' // 4: Self closing tag ... 144 | . '\\]' // ... and closing bracket 145 | . '|' 146 | . '\\]' // Closing bracket 147 | . '(?:' 148 | . '(' // 5: Unroll the loop: Optionally, anything between the opening and closing shortcode tags 149 | . '[^\\[]*+' // Not an opening bracket 150 | . '(?:' 151 | . '\\[(?!\\/\\2\\])' // An opening bracket not followed by the closing shortcode tag 152 | . '[^\\[]*+' // Not an opening bracket 153 | . ')*+' 154 | . ')' 155 | . '\\[\\/\\2\\]' // Closing shortcode tag 156 | . ')?' 157 | . ')' 158 | . '(\\]?)'; // 6: Optional second closing brocket for escaping shortcodes: [[tag]] 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tpoxa/shortcodes", 3 | "description": "Wordpress style shorttags support for Yii2", 4 | "type": "yii2-extension", 5 | "keywords": ["yii2", "shortcode"], 6 | "license": "Apache-2.0", 7 | "authors": [ 8 | { 9 | "name": "Maksym Trofimenko", 10 | "email": "gtpoxa@gmail.com" 11 | } 12 | ], 13 | "require": { 14 | 15 | }, 16 | "autoload": { 17 | "psr-4": { 18 | "tpoxa\\shortcodes\\": "" 19 | } 20 | } 21 | } 22 | --------------------------------------------------------------------------------