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

/VnKings Theme/VnKing/wp-content/plugins/contact-form-7/includes/shortcodes.php

https://gitlab.com/hop23typhu/list-theme
PHP | 498 lines | 373 code | 121 blank | 4 comment | 78 complexity | 013d2fe770fd039e34baa8889385aa8b MD5 | raw file
  1. <?php
  2. class WPCF7_ShortcodeManager {
  3. private static $instance;
  4. private $shortcode_tags = array();
  5. // Taggs scanned at the last time of do_shortcode()
  6. private $scanned_tags = null;
  7. // Executing shortcodes (true) or just scanning (false)
  8. private $exec = true;
  9. private function __construct() {}
  10. public static function get_instance() {
  11. if ( empty( self::$instance ) ) {
  12. self::$instance = new self;
  13. }
  14. return self::$instance;
  15. }
  16. public function get_scanned_tags() {
  17. return $this->scanned_tags;
  18. }
  19. public function add_shortcode( $tag, $func, $has_name = false ) {
  20. if ( ! is_callable( $func ) )
  21. return;
  22. $tags = array_filter( array_unique( (array) $tag ) );
  23. foreach ( $tags as $tag ) {
  24. $tag = $this->sanitize_tag_type( $tag );
  25. $this->shortcode_tags[$tag] = array(
  26. 'function' => $func,
  27. 'has_name' => (boolean) $has_name );
  28. }
  29. }
  30. private function sanitize_tag_type( $tag ) {
  31. $tag = preg_replace( '/[^a-zA-Z0-9_*]+/', '_', $tag );
  32. $tag = rtrim( $tag, '_' );
  33. $tag = strtolower( $tag );
  34. return $tag;
  35. }
  36. public function remove_shortcode( $tag ) {
  37. unset( $this->shortcode_tags[$tag] );
  38. }
  39. public function normalize_shortcode( $content ) {
  40. if ( empty( $this->shortcode_tags ) || ! is_array( $this->shortcode_tags ) )
  41. return $content;
  42. $pattern = $this->get_shortcode_regex();
  43. return preg_replace_callback( '/' . $pattern . '/s',
  44. array( $this, 'normalize_space_cb' ), $content );
  45. }
  46. private function normalize_space_cb( $m ) {
  47. // allow [[foo]] syntax for escaping a tag
  48. if ( $m[1] == '[' && $m[6] == ']' )
  49. return $m[0];
  50. $tag = $m[2];
  51. $attr = trim( preg_replace( '/[\r\n\t ]+/', ' ', $m[3] ) );
  52. $content = trim( $m[5] );
  53. $content = str_replace( "\n", '<WPPreserveNewline />', $content );
  54. $result = $m[1] . '[' . $tag
  55. . ( $attr ? ' ' . $attr : '' )
  56. . ( $m[4] ? ' ' . $m[4] : '' )
  57. . ']'
  58. . ( $content ? $content . '[/' . $tag . ']' : '' )
  59. . $m[6];
  60. return $result;
  61. }
  62. public function do_shortcode( $content, $exec = true ) {
  63. $this->exec = (bool) $exec;
  64. $this->scanned_tags = array();
  65. if ( empty( $this->shortcode_tags ) || ! is_array( $this->shortcode_tags ) )
  66. return $content;
  67. $pattern = $this->get_shortcode_regex();
  68. return preg_replace_callback( '/' . $pattern . '/s',
  69. array( $this, 'do_shortcode_tag' ), $content );
  70. }
  71. public function scan_shortcode( $content ) {
  72. $this->do_shortcode( $content, false );
  73. return $this->scanned_tags;
  74. }
  75. private function get_shortcode_regex() {
  76. $tagnames = array_keys( $this->shortcode_tags );
  77. $tagregexp = join( '|', array_map( 'preg_quote', $tagnames ) );
  78. return '(\[?)'
  79. . '\[(' . $tagregexp . ')(?:[\r\n\t ](.*?))?(?:[\r\n\t ](\/))?\]'
  80. . '(?:([^[]*?)\[\/\2\])?'
  81. . '(\]?)';
  82. }
  83. private function do_shortcode_tag( $m ) {
  84. // allow [[foo]] syntax for escaping a tag
  85. if ( $m[1] == '[' && $m[6] == ']' ) {
  86. return substr( $m[0], 1, -1 );
  87. }
  88. $tag = $m[2];
  89. $attr = $this->shortcode_parse_atts( $m[3] );
  90. $scanned_tag = array(
  91. 'type' => $tag,
  92. 'basetype' => trim( $tag, '*' ),
  93. 'name' => '',
  94. 'options' => array(),
  95. 'raw_values' => array(),
  96. 'values' => array(),
  97. 'pipes' => null,
  98. 'labels' => array(),
  99. 'attr' => '',
  100. 'content' => '' );
  101. if ( is_array( $attr ) ) {
  102. if ( is_array( $attr['options'] ) ) {
  103. if ( $this->shortcode_tags[$tag]['has_name'] && ! empty( $attr['options'] ) ) {
  104. $scanned_tag['name'] = array_shift( $attr['options'] );
  105. if ( ! wpcf7_is_name( $scanned_tag['name'] ) )
  106. return $m[0]; // Invalid name is used. Ignore this tag.
  107. }
  108. $scanned_tag['options'] = (array) $attr['options'];
  109. }
  110. $scanned_tag['raw_values'] = (array) $attr['values'];
  111. if ( WPCF7_USE_PIPE ) {
  112. $pipes = new WPCF7_Pipes( $scanned_tag['raw_values'] );
  113. $scanned_tag['values'] = $pipes->collect_befores();
  114. $scanned_tag['pipes'] = $pipes;
  115. } else {
  116. $scanned_tag['values'] = $scanned_tag['raw_values'];
  117. }
  118. $scanned_tag['labels'] = $scanned_tag['values'];
  119. } else {
  120. $scanned_tag['attr'] = $attr;
  121. }
  122. $scanned_tag['values'] = array_map( 'trim', $scanned_tag['values'] );
  123. $scanned_tag['labels'] = array_map( 'trim', $scanned_tag['labels'] );
  124. $content = trim( $m[5] );
  125. $content = preg_replace( "/<br[\r\n\t ]*\/?>$/m", '', $content );
  126. $scanned_tag['content'] = $content;
  127. $scanned_tag = apply_filters( 'wpcf7_form_tag', $scanned_tag, $this->exec );
  128. $this->scanned_tags[] = $scanned_tag;
  129. if ( $this->exec ) {
  130. $func = $this->shortcode_tags[$tag]['function'];
  131. return $m[1] . call_user_func( $func, $scanned_tag ) . $m[6];
  132. } else {
  133. return $m[0];
  134. }
  135. }
  136. private function shortcode_parse_atts( $text ) {
  137. $atts = array( 'options' => array(), 'values' => array() );
  138. $text = preg_replace( "/[\x{00a0}\x{200b}]+/u", " ", $text );
  139. $text = stripcslashes( trim( $text ) );
  140. $pattern = '%^([-+*=0-9a-zA-Z:.!?#$&@_/|\%\r\n\t ]*?)((?:[\r\n\t ]*"[^"]*"|[\r\n\t ]*\'[^\']*\')*)$%';
  141. if ( preg_match( $pattern, $text, $match ) ) {
  142. if ( ! empty( $match[1] ) ) {
  143. $atts['options'] = preg_split( '/[\r\n\t ]+/', trim( $match[1] ) );
  144. }
  145. if ( ! empty( $match[2] ) ) {
  146. preg_match_all( '/"[^"]*"|\'[^\']*\'/', $match[2], $matched_values );
  147. $atts['values'] = wpcf7_strip_quote_deep( $matched_values[0] );
  148. }
  149. } else {
  150. $atts = $text;
  151. }
  152. return $atts;
  153. }
  154. }
  155. function wpcf7_add_shortcode( $tag, $func, $has_name = false ) {
  156. $manager = WPCF7_ShortcodeManager::get_instance();
  157. return $manager->add_shortcode( $tag, $func, $has_name );
  158. }
  159. function wpcf7_remove_shortcode( $tag ) {
  160. $manager = WPCF7_ShortcodeManager::get_instance();
  161. return $manager->remove_shortcode( $tag );
  162. }
  163. function wpcf7_do_shortcode( $content ) {
  164. $manager = WPCF7_ShortcodeManager::get_instance();
  165. return $manager->do_shortcode( $content );
  166. }
  167. class WPCF7_Shortcode {
  168. public $type;
  169. public $basetype;
  170. public $name = '';
  171. public $options = array();
  172. public $raw_values = array();
  173. public $values = array();
  174. public $pipes;
  175. public $labels = array();
  176. public $attr = '';
  177. public $content = '';
  178. public function __construct( $tag ) {
  179. foreach ( $tag as $key => $value ) {
  180. if ( property_exists( __CLASS__, $key ) )
  181. $this->{$key} = $value;
  182. }
  183. }
  184. public function is_required() {
  185. return ( '*' == substr( $this->type, -1 ) );
  186. }
  187. public function has_option( $opt ) {
  188. $pattern = sprintf( '/^%s(:.+)?$/i', preg_quote( $opt, '/' ) );
  189. return (bool) preg_grep( $pattern, $this->options );
  190. }
  191. public function get_option( $opt, $pattern = '', $single = false ) {
  192. $preset_patterns = array(
  193. 'date' => '([0-9]{4}-[0-9]{2}-[0-9]{2}|today(.*))',
  194. 'int' => '[0-9]+',
  195. 'signed_int' => '-?[0-9]+',
  196. 'class' => '[-0-9a-zA-Z_]+',
  197. 'id' => '[-0-9a-zA-Z_]+' );
  198. if ( isset( $preset_patterns[$pattern] ) )
  199. $pattern = $preset_patterns[$pattern];
  200. if ( '' == $pattern )
  201. $pattern = '.+';
  202. $pattern = sprintf( '/^%s:%s$/i', preg_quote( $opt, '/' ), $pattern );
  203. if ( $single ) {
  204. $matches = $this->get_first_match_option( $pattern );
  205. if ( ! $matches )
  206. return false;
  207. return substr( $matches[0], strlen( $opt ) + 1 );
  208. } else {
  209. $matches_a = $this->get_all_match_options( $pattern );
  210. if ( ! $matches_a )
  211. return false;
  212. $results = array();
  213. foreach ( $matches_a as $matches )
  214. $results[] = substr( $matches[0], strlen( $opt ) + 1 );
  215. return $results;
  216. }
  217. }
  218. public function get_id_option() {
  219. return $this->get_option( 'id', 'id', true );
  220. }
  221. public function get_class_option( $default = '' ) {
  222. if ( is_string( $default ) )
  223. $default = explode( ' ', $default );
  224. $options = array_merge(
  225. (array) $default,
  226. (array) $this->get_option( 'class', 'class' ) );
  227. $options = array_filter( array_unique( $options ) );
  228. return implode( ' ', $options );
  229. }
  230. public function get_size_option( $default = '' ) {
  231. $matches_a = $this->get_all_match_options( '%^([0-9]*)/[0-9]*$%' );
  232. foreach ( (array) $matches_a as $matches ) {
  233. if ( isset( $matches[1] ) && '' !== $matches[1] )
  234. return $matches[1];
  235. }
  236. return $default;
  237. }
  238. public function get_maxlength_option( $default = '' ) {
  239. $option = $this->get_option( 'maxlength', 'int', true );
  240. if ( $option ) {
  241. return $option;
  242. }
  243. $matches_a = $this->get_all_match_options(
  244. '%^(?:[0-9]*x?[0-9]*)?/([0-9]+)$%' );
  245. foreach ( (array) $matches_a as $matches ) {
  246. if ( isset( $matches[1] ) && '' !== $matches[1] )
  247. return $matches[1];
  248. }
  249. return $default;
  250. }
  251. public function get_minlength_option( $default = '' ) {
  252. $option = $this->get_option( 'minlength', 'int', true );
  253. if ( $option ) {
  254. return $option;
  255. } else {
  256. return $default;
  257. }
  258. }
  259. public function get_cols_option( $default = '' ) {
  260. $matches_a = $this->get_all_match_options(
  261. '%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%' );
  262. foreach ( (array) $matches_a as $matches ) {
  263. if ( isset( $matches[1] ) && '' !== $matches[1] )
  264. return $matches[1];
  265. }
  266. return $default;
  267. }
  268. public function get_rows_option( $default = '' ) {
  269. $matches_a = $this->get_all_match_options(
  270. '%^([0-9]*)x([0-9]*)(?:/[0-9]+)?$%' );
  271. foreach ( (array) $matches_a as $matches ) {
  272. if ( isset( $matches[2] ) && '' !== $matches[2] )
  273. return $matches[2];
  274. }
  275. return $default;
  276. }
  277. public function get_date_option( $opt ) {
  278. $option = $this->get_option( $opt, 'date', true );
  279. if ( preg_match( '/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/', $option ) ) {
  280. return $option;
  281. }
  282. if ( preg_match( '/^today(?:([+-][0-9]+)([a-z]*))?/', $option, $matches ) ) {
  283. $number = isset( $matches[1] ) ? (int) $matches[1] : 0;
  284. $unit = isset( $matches[2] ) ? $matches[2] : '';
  285. if ( ! preg_match( '/^(day|month|year|week)s?$/', $unit ) ) {
  286. $unit = 'days';
  287. }
  288. $date = gmdate( 'Y-m-d',
  289. strtotime( sprintf( 'today %1$s %2$s', $number, $unit ) ) );
  290. return $date;
  291. }
  292. return false;
  293. }
  294. public function get_default_option( $default = '', $args = '' ) {
  295. $args = wp_parse_args( $args, array(
  296. 'multiple' => false ) );
  297. $options = (array) $this->get_option( 'default' );
  298. $values = array();
  299. if ( empty( $options ) ) {
  300. return $args['multiple'] ? $values : $default;
  301. }
  302. foreach ( $options as $opt ) {
  303. $opt = sanitize_key( $opt );
  304. if ( 'user_' == substr( $opt, 0, 5 ) && is_user_logged_in() ) {
  305. $primary_props = array( 'user_login', 'user_email', 'user_url' );
  306. $opt = in_array( $opt, $primary_props ) ? $opt : substr( $opt, 5 );
  307. $user = wp_get_current_user();
  308. $user_prop = $user->get( $opt );
  309. if ( ! empty( $user_prop ) ) {
  310. if ( $args['multiple'] ) {
  311. $values[] = $user_prop;
  312. } else {
  313. return $user_prop;
  314. }
  315. }
  316. } elseif ( 'post_meta' == $opt && in_the_loop() ) {
  317. if ( $args['multiple'] ) {
  318. $values = array_merge( $values,
  319. get_post_meta( get_the_ID(), $this->name ) );
  320. } else {
  321. $val = (string) get_post_meta( get_the_ID(), $this->name, true );
  322. if ( strlen( $val ) ) {
  323. return $val;
  324. }
  325. }
  326. } elseif ( 'get' == $opt && isset( $_GET[$this->name] ) ) {
  327. $vals = (array) $_GET[$this->name];
  328. $vals = array_map( 'wpcf7_sanitize_query_var', $vals );
  329. if ( $args['multiple'] ) {
  330. $values = array_merge( $values, $vals );
  331. } else {
  332. $val = isset( $vals[0] ) ? (string) $vals[0] : '';
  333. if ( strlen( $val ) ) {
  334. return $val;
  335. }
  336. }
  337. } elseif ( 'post' == $opt && isset( $_POST[$this->name] ) ) {
  338. $vals = (array) $_POST[$this->name];
  339. $vals = array_map( 'wpcf7_sanitize_query_var', $vals );
  340. if ( $args['multiple'] ) {
  341. $values = array_merge( $values, $vals );
  342. } else {
  343. $val = isset( $vals[0] ) ? (string) $vals[0] : '';
  344. if ( strlen( $val ) ) {
  345. return $val;
  346. }
  347. }
  348. }
  349. }
  350. if ( $args['multiple'] ) {
  351. $values = array_unique( $values );
  352. return $values;
  353. } else {
  354. return $default;
  355. }
  356. }
  357. public function get_data_option( $args = '' ) {
  358. $options = (array) $this->get_option( 'data' );
  359. return apply_filters( 'wpcf7_form_tag_data_option', null, $options, $args );
  360. }
  361. public function get_first_match_option( $pattern ) {
  362. foreach( (array) $this->options as $option ) {
  363. if ( preg_match( $pattern, $option, $matches ) )
  364. return $matches;
  365. }
  366. return false;
  367. }
  368. public function get_all_match_options( $pattern ) {
  369. $result = array();
  370. foreach( (array) $this->options as $option ) {
  371. if ( preg_match( $pattern, $option, $matches ) )
  372. $result[] = $matches;
  373. }
  374. return $result;
  375. }
  376. }
  377. ?>