PageRenderTime 111ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/enlighter/class/ShortcodeFilter.php

https://bitbucket.org/hcdesenvolvimentos/tiagobalabuch_site
PHP | 224 lines | 101 code | 47 blank | 76 comment | 13 complexity | a231b5eab6ff1171b6dfff76917675da MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0
  1. <?php
  2. /**
  3. LowlLevel Shortcode handler to avoid issues with uescaped html or wpautop
  4. Version: 1.0
  5. Author: Andi Dittrich
  6. Author URI: http://andidittrich.de
  7. Plugin URI: http://andidittrich.de/go/enlighterjs
  8. License: MIT X11-License
  9. Copyright (c) 2016, Andi Dittrich
  10. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  11. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
  12. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  13. */
  14. namespace Enlighter;
  15. class ShortcodeFilter{
  16. // stores the plugin config
  17. private $_config;
  18. // store registered shortcodes
  19. private $_languageTags;
  20. // cached code content
  21. // public visibility required for PHP5.3 compatibility (lambda functions)
  22. // @TODO set to private in next major release (requires PHP5.4)
  23. public $_codeFragments = array();
  24. public function __construct($settingsUtil, $languageShortcodes){
  25. // store local plugin config
  26. $this->_config = $settingsUtil->getOptions();
  27. // default shortcodes
  28. $this->_languageTags = 'enlighter';
  29. // enable language shortcodes ?
  30. if ($this->_config['languageShortcode']){
  31. $this->_languageTags .= '|' . implode('|', $languageShortcodes);
  32. }
  33. }
  34. private function getShortcodeRegex($shortcodes){
  35. // opening tag based on enabled shortcodes
  36. return '/\[(' . $shortcodes . ')\s*' .
  37. // shortcode attributes (optional)
  38. '(.*)?' .
  39. // close opening tag
  40. '\s*\]' .
  41. // arbitrary multi-line content
  42. '([\S\s]*)' .
  43. // closing tag using opening tag back reference
  44. '\[\/\1\]' .
  45. // ungreedy, case insensitive
  46. '/Ui';
  47. }
  48. // internal regex function to replace shortcodes with placeholders
  49. // scoped to use it standalone as well as within shortcodes as second stage
  50. public function findShortcodes($content, $group = null){
  51. // PHP 5.3 compatibility
  52. $T = $this;
  53. // process enlighter & language shortcodes
  54. return preg_replace_callback($this->getShortcodeRegex($this->_languageTags), function ($match) use ($T, $group){
  55. // wordpress internal shortcode attribute parsing
  56. $attb = shortcode_parse_atts($match[2]);
  57. // language identifier (tagname)
  58. $lang = $match[1];
  59. // generic shortcode ?
  60. if (strtolower($match[1]) == 'enlighter') {
  61. // set language
  62. if ($attb['lang']) {
  63. $lang = $attb['lang'];
  64. }
  65. }
  66. // generate code fragment
  67. $T->_codeFragments[] = array(
  68. // the language identifier
  69. 'lang' => $lang,
  70. // shortcode attributes
  71. 'attb' => $attb,
  72. // code to highlight
  73. 'code' => $match[3],
  74. // auto codegroup
  75. 'group' => $group
  76. );
  77. // replace it with a placeholder
  78. return '{{EJS0-' . count($T->_codeFragments) . '}}';
  79. }, $content);
  80. }
  81. // strip the content
  82. // internal shortcode processor - replace enlighter shortcodes by placeholder
  83. public function stripCodeFragments($content){
  84. // PHP 5.3 compatibility
  85. $T = $this;
  86. // STAGE 1
  87. // process codegroup shortcodes
  88. $content = preg_replace_callback($this->getShortcodeRegex('codegroup'), function ($match) use ($T){
  89. // create unique group identifier
  90. $group = uniqid('ejsg');
  91. // replace it with inner content an parse the shortcodes
  92. return $T->findShortcodes($match[3], $group);
  93. }, $content);
  94. // STAGE 2
  95. // process non grouped shortcodes
  96. $content = $this->findShortcodes($content);
  97. return $content;
  98. }
  99. // internal handler to insert the content
  100. public function renderFragments($content){
  101. // replace placeholders by html
  102. foreach ($this->_codeFragments as $index => $fragment){
  103. $content = str_replace('{{EJS0-' . ($index + 1) . '}}', $this->renderFragment($fragment), $content);
  104. }
  105. return $content;
  106. }
  107. // restore the content
  108. // process shortcode attributes and generate html
  109. private function renderFragment($fragment){
  110. // default attribute settings
  111. $shortcodeAttributes = shortcode_atts(
  112. array(
  113. 'theme' => null,
  114. 'group' => false,
  115. 'tab' => null,
  116. 'highlight' => null,
  117. 'offset' => null,
  118. 'linenumbers' => null
  119. ), $fragment['attb']);
  120. // html tag standard attributes
  121. $htmlAttributes = array(
  122. 'data-enlighter-language' => InputFilter::filterLanguage($fragment['lang']),
  123. 'class' => 'EnlighterJSRAW'
  124. );
  125. // force theme ?
  126. if ($shortcodeAttributes['theme']){
  127. $htmlAttributes['data-enlighter-theme'] = InputFilter::filterTheme($shortcodeAttributes['theme']);
  128. }
  129. // handle as inline code ?
  130. if ($this->_config['enableInlineHighlighting'] && strpos($fragment['code'], "\n") === false){
  131. // generate html output
  132. return $this->generateCodeblock($htmlAttributes, $fragment['code'], 'code');
  133. // line-breaks found -> block code
  134. }else{
  135. // highlight specific lines of code ?
  136. if ($shortcodeAttributes['highlight']){
  137. $htmlAttributes['data-enlighter-highlight'] = trim($shortcodeAttributes['highlight']);
  138. }
  139. // line offset ?
  140. if ($shortcodeAttributes['offset']){
  141. $htmlAttributes['data-enlighter-lineoffset'] = InputFilter::filterInteger($shortcodeAttributes['offset']);
  142. }
  143. // force linenumber visibility ?
  144. if ($shortcodeAttributes['linenumbers']){
  145. $htmlAttributes['data-enlighter-linenumbers'] = (strtolower($shortcodeAttributes['linenumbers']) === 'true' ? 'true' : 'false');
  146. }
  147. // tab-name available ?
  148. if ($shortcodeAttributes['tab']){
  149. $htmlAttributes['data-enlighter-title'] = trim($shortcodeAttributes['tab']);
  150. }
  151. // auto grouping ?
  152. if ($fragment['group']){
  153. $htmlAttributes['data-enlighter-group'] = trim($fragment['group']);
  154. // manual grouping ?
  155. }else if ($shortcodeAttributes['group']){
  156. $htmlAttributes['data-enlighter-group'] = trim($shortcodeAttributes['group']);
  157. }
  158. // generate html output
  159. return $this->generateCodeblock($htmlAttributes, $fragment['code']);
  160. }
  161. }
  162. /**
  163. * Generate HTML output (code within "pre"/"code"-tag including options)
  164. */
  165. private function generateCodeblock($attributes, $content, $tagname = 'pre'){
  166. // generate "pre" wrapped html output
  167. $html = HtmlUtil::generateTag($tagname, $attributes, false);
  168. // strip specialchars
  169. $content = esc_html($content);
  170. // add closing tag
  171. return $html.$content.'</'.$tagname.'>';
  172. }
  173. }