selector.func.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. /**
  3. * The selector helpers file of zin of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2023 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
  6. * @author Hao Sun <sunhao@easycorp.ltd>
  7. * @package zin
  8. * @version $Id
  9. * @link https://www.zentao.net
  10. */
  11. namespace zin;
  12. /**
  13. * Parse wg selector.
  14. *
  15. * @param string|object $selector
  16. * @param bool $checkParents
  17. * @return object|null
  18. */
  19. function parseSelector($selector, $checkParents = false)
  20. {
  21. if(is_object($selector)) return $selector;
  22. $selector = trim($selector);
  23. $len = strlen($selector);
  24. if($len < 1) return null;
  25. $result = array(
  26. 'class' => array(),
  27. 'id' => null,
  28. 'tag' => null,
  29. 'inner' => false,
  30. 'name' => null,
  31. 'first' => false,
  32. 'selector' => $selector,
  33. 'options' => array(),
  34. 'parents' => array()
  35. );
  36. if(str_contains($selector, '/'))
  37. {
  38. $parts = explode('/', $selector, 2);
  39. $result['name'] = $parts[0];
  40. $selector = $parts[1];
  41. $len = strlen($selector);
  42. }
  43. $selector = str_replace('> *', '>*', $selector);
  44. if(substr($selector, strlen($selector) - 2) == '>*')
  45. {
  46. $result['inner'] = true;
  47. $selector = substr($selector, 0, strlen($selector) - 2);
  48. $len = strlen($selector);
  49. }
  50. if($checkParents && str_contains($selector, ' '))
  51. {
  52. $parts = explode(' ', $selector);
  53. $selector = array_pop($parts);
  54. $len = strlen($selector);
  55. foreach($parts as $part) $result['parents'][] = parseSelector($part);
  56. }
  57. $type = 'tag';
  58. $current = '';
  59. $updateResult = function(&$result, $current, $type)
  60. {
  61. if(empty($current)) return;
  62. if($type === 'class')
  63. {
  64. $result[$type][] = $current;
  65. }
  66. elseif($type === 'option')
  67. {
  68. $options = array();
  69. parse_str($current, $options);
  70. foreach($options as $key => $value) $result['options'][$key] = empty($value) ? true : $value;
  71. }
  72. else
  73. {
  74. $result[$type] = $current;
  75. }
  76. };
  77. for($i = 0; $i < $len; $i++)
  78. {
  79. $c = $selector[$i];
  80. $t = '';
  81. if($c === '#' & $type !== 'option')
  82. {
  83. $t = 'id';
  84. }
  85. elseif($c === '.' & $type !== 'option')
  86. {
  87. $t = 'class';
  88. }
  89. elseif($c === '(' && $type !== 'option' && str_ends_with($selector, ')'))
  90. {
  91. $command = substr($selector, $i + 1, -1);
  92. if(empty($command)) $command = $current;
  93. $result['command'] = $command;
  94. break;
  95. }
  96. elseif($c === ':')
  97. {
  98. $t = 'option';
  99. }
  100. if(empty($t))
  101. {
  102. $current .= $c;
  103. }
  104. else
  105. {
  106. $updateResult($result, $current, $type);
  107. $current = '';
  108. $type = $t;
  109. }
  110. }
  111. $updateResult($result, $current, $type);
  112. if(empty($result['class'])) $result['class'] = null;
  113. if(empty($result['name']))
  114. {
  115. if(!empty($result['id'])) $result['name'] = $result['id'];
  116. elseif(!empty($result['tag'])) $result['name'] = $result['tag'];
  117. else $result['name'] = $selector;
  118. }
  119. return (object)$result;
  120. }
  121. /**
  122. * Parse wg selectors.
  123. *
  124. * @param object|string|object[]|string[] $selectors
  125. * @param bool $checkParents
  126. * @return object[]
  127. */
  128. function parseSelectors($selectors, $checkParents = false)
  129. {
  130. if(is_object($selectors)) return array($selectors);
  131. if(is_string($selectors)) $selectors = explode(',', trim($selectors));
  132. $results = array();
  133. foreach($selectors as $selector)
  134. {
  135. $selector = parseSelector($selector, $checkParents);
  136. if(is_object($selector)) $results[] = $selector;
  137. }
  138. return $results;
  139. }
  140. /**
  141. * Stringify wg selectors.
  142. * @param object|object[] $selector
  143. * @return string
  144. */
  145. function stringifySelectors($selector)
  146. {
  147. if(empty($selector)) return '';
  148. if(is_array($selector))
  149. {
  150. $result = array();
  151. foreach($selector as $s) $result[] = stringifySelectors($s);
  152. return implode(',', $result);
  153. }
  154. $result = '';
  155. if(!empty($selector->name) && $selector->name !== $selector->selector && $selector->name !== $selector->tag) $result .= $selector->name . '/';
  156. if(!empty($selector->tag)) $result .= $selector->tag;
  157. if(!empty($selector->id)) $result .= '#' . $selector->id;
  158. if(!empty($selector->class)) $result .= '.' . implode('.', $selector->class);
  159. if(!empty($selector->first)) $result .= ':first';
  160. if($selector->inner) $result .= '>*';
  161. if(!empty($selector->options))
  162. {
  163. $options = array();
  164. foreach($selector->options as $key => $value) $options[] = $value === true ? $key : ($key . '=' . $value);
  165. $result .= ':' . implode('&', $options);
  166. }
  167. return $result;
  168. }