Last active
March 4, 2019 17:45
-
-
Save ger86/466127d9f1bdad83431df576a4516a76 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Service; | |
final class ShortcodeService { | |
private $shortcodes = []; | |
public function isShortcode($name) { | |
return isset($this->shortcodes[$name]); | |
} | |
/** | |
* Returns all the attrs of a found shortcode as a key / value array. | |
* | |
* @param string $text | |
* @return array | |
*/ | |
private function _shortcodeParseAttrs(string $text): array { | |
$attrs = [] | |
$pattern = '/(\w+)\s*=\s*"([^"]*)"(?:\s|$)|(\w+)\s*=\s*\'([^\']*)\'(?:\s|$)|(\w+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/'; | |
$text = preg_replace("/[\x{00a0}\x{200b}]+/u", " ", $text); | |
$text = html_entity_decode($text); | |
if (preg_match_all($pattern, $text, $match, PREG_SET_ORDER)) { | |
foreach ($match as $m) { | |
if (!empty($m[1])) { | |
$attrs[strtolower($m[1])] = stripcslashes($m[2]); | |
} | |
elseif (!empty($m[3])) { | |
$attrs[strtolower($m[3])] = stripcslashes($m[4]); | |
} | |
elseif (!empty($m[5])) { | |
$attrs[strtolower($m[5])] = stripcslashes($m[6]); | |
} | |
elseif (isset($m[7]) and strlen($m[7])) { | |
$attrs[] = stripcslashes($m[7]); | |
} | |
elseif (isset($m[8])) { | |
$attrs[] = stripcslashes($m[8]); | |
} | |
} | |
} | |
else { | |
$attrs = ltrim($text); | |
} | |
return $attrs; | |
} | |
/** | |
* Process one shortcode | |
* | |
* @param array $m contains the match of the regex | |
* @return string | |
* | |
*/ | |
private function _shortcodeProcessTag(array $m): string { | |
$shortcodes = $this->shortcodes; | |
$tag = $m[2]; | |
if (!empty($shortcodes[$tag])) { | |
$attr = $this->_shortcodeParseAttrs($m[3]); | |
$shortcode = $shortcodes[$tag]; | |
if (!empty($m[4])) { | |
return $m[1] . $shortcode->apply($attr, $m[4]) . $m[5]; | |
} else { | |
return $m[1] . $shortcode->apply($attr, null). $m[5]; | |
} | |
} elseif (empty($m[4])) { | |
return $m[4]; | |
} | |
return ''; | |
} | |
/** | |
* Process a text with shortcodes | |
*/ | |
public function shortcodeProcess(string $text) { | |
$shortcodes = $this->shortcodes; | |
$chunks = preg_split('!(\[{1,2}.*?\]{1,2})!', $text, -1, PREG_SPLIT_DELIM_CAPTURE); | |
$heap = array(); | |
$heapIndex = array(); | |
foreach ($chunks as $c) { | |
if (!$c) { | |
continue; | |
} | |
$escaped = false; | |
if ((substr($c, 0, 2) == '[[') && (substr($c, -2, 2) == ']]')) { | |
$escaped = true; | |
if ((substr($c, 0, 3) != '{') && (substr($c, -3, 1) != '}')) { | |
$c = substr($c, 1, -1); | |
} | |
} | |
if (!$escaped && ($c[0] == '[') && (substr($c, -1, 1) == ']')) { | |
$originalText = $c; | |
$c = substr($c, 1, -1); | |
$c = trim($c); | |
$ts = explode(' ', $c); | |
$tag = array_shift($ts); | |
$tag = trim($tag, '/'); | |
if (!$this->isShortcode($tag)) { | |
array_unshift($heapIndex, '_string_'); | |
array_unshift($heap, $originalText); | |
} elseif (substr($c, -1, 1) == '/') { | |
$m = array( | |
$c, | |
'', | |
$tag, | |
implode(' ', $ts), | |
NULL, | |
'', | |
); | |
array_unshift($heap_index, '_string_'); | |
array_unshift($heap, $this->_shortcodeProcessTag($m)); | |
} elseif ($c[0] == '/') { | |
$closingTag = substr($c, 1); | |
$processHeap = array(); | |
$processHeapIndex = array(); | |
$found = FALSE; | |
do { | |
$tag = array_shift($heapIndex); | |
$heapText = array_shift($heap); | |
if ($closingTag == $tag) { | |
$m = array( | |
$tag . ' ' . $heapText, | |
'', | |
$tag, | |
$heapText, | |
implode('', $processHeap), | |
'', | |
); | |
$str = $this->_shortcodeProcessTag($m); | |
array_unshift($heapIndex, '_string_'); | |
array_unshift($heap, $str); | |
$found = TRUE; | |
} else { | |
array_unshift($processHeap, $heapText); | |
array_unshift($processHeapIndex, $tag); | |
} | |
} while (!$found && $heap); | |
if (!$found) { | |
foreach ($processHeap as $val) { | |
array_unshift($heap, $val); | |
} | |
foreach ($processHeapIndex as $val) { | |
array_unshift($heapIndex, $val); | |
} | |
} | |
} else { | |
array_unshift($heapIndex, $tag); | |
array_unshift($heap, implode(' ', $ts)); | |
} | |
} else { | |
array_unshift($heapIndex, '_string_'); | |
array_unshift($heap, $c); | |
} | |
} | |
return (implode('', array_reverse($heap))); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment