PageRenderTime 47ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/themes/nonus/framework/shortcodes/ctShortcodeTester.class.php

https://github.com/alniko009/magic
PHP | 615 lines | 331 code | 116 blank | 168 comment | 47 complexity | c569725576b90e6d7a99bb3f48b9c706 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. <?php
  2. require_once 'ctShortcodeHandler.class.php';
  3. /**
  4. * Generates every possible shortcode
  5. * @author alex
  6. */
  7. class ctShortcodeTester {
  8. /**
  9. * Compile?
  10. * @var bool
  11. */
  12. protected $compile = false;
  13. /**
  14. * Which shortcodes we do not test?
  15. * @var array
  16. */
  17. protected $banned = array(
  18. 'accordion',
  19. 'google_maps',
  20. 'five_sixth_column',
  21. 'full_column',
  22. 'half_column',
  23. 'one_sixth_column',
  24. 'quarter_column',
  25. 'row',
  26. 'third_column',
  27. 'three_quarters_column',
  28. 'two_thirds_column'
  29. );
  30. /**
  31. * Attributes we wont parse. Format: shortcodeName=>
  32. * @var array
  33. */
  34. protected $bannedAttributes;
  35. /**
  36. * Debug?
  37. * @var bool
  38. */
  39. protected $debug = false;
  40. /**
  41. * List of child shortcodes
  42. * @var array
  43. */
  44. protected $childShortcodes = array();
  45. /**
  46. * Creates tester
  47. * @param array $bannedShortcodes
  48. * @param array $bannedAttributes
  49. */
  50. public function __construct($bannedShortcodes = array(), $bannedAttributes = array()) {
  51. $this->bannedAttributes = $bannedAttributes;
  52. $this->banned = array_merge($this->banned, $bannedShortcodes);
  53. }
  54. /**
  55. * Returns shorcodes
  56. */
  57. public function createPages() {
  58. /** @var $codes ctShortcode[] */
  59. $codes = ctShortcodeHandler::getInstance()->getShortcodes();
  60. $childShortcodes = array();
  61. $parentId = $this->reloadSection();
  62. foreach ($codes as $group => $cs) {
  63. foreach ($cs as $code) {
  64. if ($e = $code->getChildShortcodeInfo()) {
  65. if ($child = $e['name']) {
  66. $childShortcodes[$child] = true;
  67. }
  68. }
  69. }
  70. }
  71. $this->childShortcodes = $childShortcodes;
  72. $pageIds = array();
  73. $htmls = '';
  74. foreach ($codes as $cs) {
  75. /** @var $code ctShortcode */
  76. foreach ($cs as $code) {
  77. $n = $code->getShortcodeName();
  78. //we have a child, we parse it when we will parse parent
  79. if (!isset($childShortcodes[$n]) && !$this->isBanned($n)) {
  80. $this->log('Parsing: ' . $code->getShortcodeName());
  81. $result = $this->handleShortcode($code);
  82. $this->compile = true;
  83. $htmls .= $this->wrapShortcode($code, $this->handleShortcode($code, '', true), array('full'));
  84. $this->compile = false;
  85. $result = $this->wrapShortcode($code, $result);
  86. $pageIds[] = $this->createPage($parentId, $code, $result);
  87. }
  88. }
  89. }
  90. $pageIds[] = $this->createPage($parentId, null, $htmls, 'HTML Debug');
  91. $this->updateSection($parentId, $pageIds);
  92. }
  93. /**
  94. * Updates section
  95. * @param $parentId
  96. * @param array $pagesIds
  97. */
  98. protected function updateSection($parentId, $pagesIds) {
  99. $content = '[title_row header="Smokescreen - Shortcodes"]
  100. [row]
  101. Below you will find most popular shortcodes in most common configurations:
  102. [list style="2"]';
  103. foreach ($pagesIds as $pageId) {
  104. $post = get_post($pageId);
  105. $content .= '<li><a href="' . get_permalink($post) . '">' . $post->post_title . '</a></li>';
  106. }
  107. $content .= '[/list][/row]';
  108. wp_update_post(array('ID' => $parentId, 'post_content' => $content));
  109. }
  110. /**
  111. * Do we support it?
  112. * @param $name
  113. * @return bool
  114. */
  115. protected function isBanned($name) {
  116. return array_search($name, $this->banned) !== false;
  117. }
  118. /**
  119. * Removes undeeded attributes
  120. * @param ctShortcode $code
  121. * @param $attributes
  122. * @return array
  123. */
  124. protected function filterAttributes($code, $attributes) {
  125. if (isset($this->bannedAttributes[$code->getShortcodeName()])) {
  126. return array_diff_key($attributes, $this->bannedAttributes[$code->getShortcodeName()]);
  127. }
  128. return $attributes;
  129. }
  130. /**
  131. * Creates debug section
  132. * @throws Exception
  133. */
  134. protected function reloadSection() {
  135. $key = 'ct_debug_post';
  136. if ($id = get_option($key)) {
  137. foreach (get_posts(array('numberposts' => -1, 'post_type' => 'page', 'post_parent' => $id)) as $child) {
  138. wp_delete_post($child->ID, true);
  139. }
  140. if (get_post($id)) {
  141. return $id;
  142. }
  143. }
  144. $post = array(
  145. 'post_name' => "Smokescreen",
  146. 'post_title' => 'Smokescreen',
  147. 'post_type' => "page",
  148. 'post_status' => 'publish'
  149. );
  150. $id = wp_insert_post($post);
  151. if ($id === false) {
  152. throw new Exception("Cannot add debug post");
  153. }
  154. //store it
  155. update_option($key, $id);
  156. return $id;
  157. }
  158. /**
  159. * Creates debug pages
  160. * @param int $parentId
  161. * @param ctShortcode $code
  162. * @param string $result
  163. * @return int|\WP_Error
  164. */
  165. protected function createPage($parentId, $code, $result, $title = '') {
  166. $title = "Shortcode '" . ($code ? $code->getShortcodeName() : $title) . "'";
  167. $post = array(
  168. 'post_content' => $result,
  169. 'post_name' => $title,
  170. 'post_title' => $title,
  171. 'post_type' => "page",
  172. 'post_status' => 'publish',
  173. 'post_parent' => $parentId
  174. );
  175. return wp_insert_post($post);
  176. }
  177. /**
  178. * Logs data
  179. * @param string $content
  180. */
  181. protected function log($content) {
  182. if ($this->debug) {
  183. echo $content . "\n";
  184. }
  185. }
  186. /**
  187. * Parses shortcode - parent or single
  188. * @param ctShortcode $code
  189. * @param string $result
  190. * @return string
  191. */
  192. protected function handleShortcode($code, $result = '', $withHtml = false) {
  193. $child = $code->getChildShortcodeInfo();
  194. if (!$child || !$child['name']) {
  195. $attributes = $code->getAttributes();
  196. //remove builtin queryable data
  197. if ($code instanceof ctShortcodeQueryable) {
  198. $default = $code->getQueryAllAttributes();
  199. $attributes = array_diff_key($attributes, $default);
  200. }
  201. $combs = $this->parseAttributes($code, $attributes);
  202. $data = $this->combinations($this->filterAttributes($code, $combs));
  203. if (!$data) {
  204. $data[] = array('');
  205. }
  206. $content = '';
  207. //content - let's find it
  208. if (isset($attributes['content'])) {
  209. $content = $this->getDefaultFromAttributes($attributes['content'], $this->getTextareaValue());
  210. }
  211. foreach ($data as $e) {
  212. $params = '';
  213. if ($e) {
  214. if (is_array($e)) {
  215. $params = ' ' . implode(' ', $e);
  216. } else {
  217. $params = $e ? ' ' . $e : '';
  218. }
  219. }
  220. if (!isset($this->childShortcodes[$code->getShortcodeName()])) {
  221. $result .= '<pre class="shortcodeTest">&#91;' . $code->getShortcodeName() . $params . '&#93;</pre>';
  222. }
  223. $s = '[' . $code->getShortcodeName() . $params . ']';
  224. if ($content) {
  225. $s .= $content . '[/' . $code->getShortcodeName() . ']';
  226. }
  227. $result .= $s;
  228. // konfiguracja Tidy
  229. $config = array(
  230. 'indent' => true,
  231. 'output-xhtml' => true,
  232. 'wrap' => 200,
  233. 'fix-backslash' => false,
  234. 'fix-bad-comments' => false,
  235. 'fix-uri' => false,
  236. 'join-styles' => false,
  237. 'lower-literals' => false,
  238. 'show-body-only' => true
  239. );
  240. $sCode = do_shortcode($s);
  241. if (class_exists('tidy')) {
  242. // przetwarzanie Tidy
  243. $tidy = new tidy;
  244. $tidy->parseString($sCode, $config, 'utf8');
  245. $tidy->cleanRepair();
  246. $sCode = (string)$tidy;
  247. }
  248. if ($withHtml) {
  249. $result .= '<div class="htmlTest">HTML:<pre class="htmlTest">' . htmlentities($sCode) . '</pre></div>';
  250. $result .= '<hr class="htmlTest" style="margin-bottom:50px">';
  251. }
  252. //$result .= "\n";
  253. }
  254. return $result;
  255. } else {
  256. $result = '[' . $code->getShortcodeName() . ']' . "\n";
  257. $c = $code->getChildShortcode();
  258. for ($x = 0; $x < 3; $x++) {
  259. $result .= $this->handleShortcode($c);
  260. }
  261. $result .= '[/' . $code->getShortcodeName() . ']';
  262. }
  263. return $result;
  264. }
  265. /**
  266. * Patterns cache
  267. * @var null
  268. */
  269. protected static $rowPatterns = null;
  270. /**
  271. * Wraps shortcode
  272. * @param ctShortcode $code
  273. * @param string $html
  274. * @param array $allowTemplates
  275. * @return string
  276. */
  277. protected function wrapShortcode($code, $html, $allowTemplates = array()) {
  278. if (!self::$rowPatterns) {
  279. $row = ctShortcodeHandler::getInstance()->getShortcode('row');
  280. $combs = $this->parseAttributes($row, $row->getAttributes());
  281. $templates = array(
  282. 'full' => '[full_column]%1$s[/full_column]',
  283. 'half' => '[half_column]%1$s[/half_column][half_column]%1$s[/half_column]',
  284. 'third' => '[third_column]%1$s[/third_column][two_thirds_column]%1$s[/two_thirds_column]',
  285. 'no_row' => '%1$s'
  286. );
  287. $data = $this->combinations($combs);
  288. foreach ($data as $key => $profile) {
  289. $params = implode(' ', is_array($profile) ? $profile : array($profile));
  290. foreach ($templates as $name => $template) {
  291. $r = '';
  292. if ($name != 'no_row') {
  293. $r .= '[' . $row->getShortcodeName() . ' ' . $params . ']' . "\n";
  294. }
  295. $r .= $template . "\n";
  296. if ($name != 'no_row') {
  297. $r .= '[/' . $row->getShortcodeName() . ']';
  298. }
  299. self::$rowPatterns[$key][$name] = $r;
  300. }
  301. }
  302. }
  303. $allowTemplates = array_flip($allowTemplates ? $allowTemplates : $this->getShortcodeWrapTemplates($code));
  304. //use only filtered templates
  305. $r = '';
  306. if (isset($allowTemplates['no_row'])) {
  307. foreach (self::$rowPatterns[0] as $pat) {
  308. $r = sprintf($pat, "\n" . $html . "\n") . "\n";
  309. }
  310. } else {
  311. $r = '[title_row header="Shortcode: ' . $code->getShortcodeName() . '"][/title_row]' . "\n";
  312. foreach (self::$rowPatterns as $patterns) {
  313. foreach ($patterns as $type => $pat) {
  314. if (array_key_exists($type, $allowTemplates)) {
  315. $r .= sprintf($pat, "\n" . $html . "\n") . "\n";
  316. }
  317. }
  318. }
  319. }
  320. if ($this->mustCompile($code)) {
  321. $r = do_shortcode($r);
  322. }
  323. return $r . "\n\n";
  324. }
  325. /**
  326. * Should we compile?
  327. * @param ctShortcode $code
  328. * @return bool
  329. */
  330. protected function mustCompile($code) {
  331. return $this->compile;
  332. }
  333. /**
  334. * Is shortcode limited?
  335. * @param ctShortcode $code
  336. * @return array
  337. */
  338. protected function getShortcodeWrapTemplates($code) {
  339. return array('full', 'half', 'third');
  340. }
  341. /**
  342. * Generates combinations
  343. * @param $arrays
  344. * @param int $i
  345. * @return array
  346. */
  347. protected function combinations($arrays, $i = 0) {
  348. if (!isset($arrays[$i])) {
  349. return array();
  350. }
  351. if ($i == count($arrays) - 1) {
  352. return $arrays[$i];
  353. }
  354. // get combinations from subsequent arrays
  355. $tmp = $this->combinations($arrays, $i + 1);
  356. $result = array();
  357. // concat each array from tmp with each element from $arrays[$i]
  358. foreach ($arrays[$i] as $v) {
  359. foreach ($tmp as $t) {
  360. $result[] = is_array($t) ?
  361. array_merge(array($v), $t) :
  362. array($v, $t);
  363. }
  364. }
  365. return $result;
  366. }
  367. /**
  368. * Returns field options
  369. * @param $code
  370. * @param $attributes
  371. * @throws Exception
  372. * @return array
  373. */
  374. protected function parseAttributes($code, $attributes) {
  375. $data = array();
  376. $attributes = $this->filterAttributes($code, $attributes);
  377. foreach ($attributes as $field => $attr) {
  378. $type = isset($attr['type']) && $attr['type'] ? $attr['type'] : 'input';
  379. $method = 'generate' . ucfirst($type);
  380. if (!method_exists($this, $method)) {
  381. throw new Exception("Cannot handle " . $type . ' Attributes: ' . print_r($attr, true));
  382. }
  383. if ($v = $this->$method($field, $attr)) {
  384. $data[$field] = $v;
  385. }
  386. }
  387. $result = array();
  388. foreach ($data as $field => $values) {
  389. $t = array();
  390. foreach ($values as $value) {
  391. $t[] = $field . '="' . $value . '"';
  392. }
  393. $result[] = $t;
  394. }
  395. return $result;
  396. }
  397. /**
  398. * Posts select
  399. * @param string $field
  400. * @param array $attr
  401. * @return array
  402. */
  403. protected function generatePosts_select($field, $attr) {
  404. $args = array('numberposts' => 1, 'orderby' => 'rand');
  405. $posts = get_posts($args);
  406. if (isset($posts[0])) {
  407. return array($posts[0]->ID);
  408. }
  409. return array();
  410. }
  411. /**
  412. * Generates select
  413. * @param $field
  414. * @param $attr
  415. * @return array
  416. */
  417. protected function generateSelect($field, $attr) {
  418. if (!isset($attr['choices'])) {
  419. return array_keys($attr['options']);
  420. }
  421. return array_keys($attr['choices']);
  422. }
  423. /**
  424. * Toggalbe content type
  425. * @param $field
  426. * @param $attr
  427. * @return array
  428. */
  429. protected function generateToggable($field, $attr) {
  430. return array();
  431. }
  432. /**
  433. * Generates checkboxes
  434. * @param $field
  435. * @param $attr
  436. * @return array
  437. */
  438. protected function generateCheckbox($field, $attr) {
  439. return array(0, 1);
  440. }
  441. /**
  442. * Generates combinations
  443. * @param string $field
  444. * @param array $attr
  445. * @return array
  446. */
  447. protected function generateInput($field, $attr) {
  448. $default = $this->getDefaultFromAttributes($attr, 'Example text');
  449. if (!$default && (strpos($field, 'link') !== false || strpos($field, 'url') !== false)) {
  450. return array('http://www.google.com');
  451. }
  452. if (strpos($field, 'img') !== false) {
  453. return $this->generateImage($field, $attr);
  454. }
  455. return array($default);
  456. }
  457. /**
  458. * Generates mockup for textarea
  459. * @param $field
  460. * @param $attr
  461. * @return array
  462. */
  463. protected function generateTextarea($field, $attr) {
  464. //it means its content
  465. return array();
  466. }
  467. /**
  468. * Returns textarea value
  469. * @return string
  470. */
  471. protected function getTextareaValue() {
  472. return "Lorem ipsum";
  473. }
  474. /**
  475. * Generates image combinations
  476. * @param $field
  477. * @param $attr
  478. * @return array
  479. */
  480. protected function generateImage($field, $attr) {
  481. return array('http://lorempixel.com/g/600/400/city/');
  482. }
  483. /**
  484. * Returns default attribute
  485. * @param array $attr
  486. * @param string $default
  487. * @return string
  488. */
  489. protected function getDefaultFromAttributes($attr, $default = '') {
  490. if (isset($attr['example'])) {
  491. $content = $attr['example'];
  492. if (is_array($content)) {
  493. return call_user_func($content); //we support callback for performace reasons
  494. }
  495. return $content;
  496. }
  497. return isset($attr['default']) && $attr['default'] ? $attr['default'] : $default;
  498. }
  499. }