PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/extensions/LocalisationUpdate/QuickArrayReader.php

https://gitlab.com/link233/bootmw
PHP | 215 lines | 157 code | 22 blank | 36 comment | 47 complexity | 31a5fb2c399a5a5587adc31a212d69b0 MD5 | raw file
  1. <?php
  2. /**
  3. * Quickie parser class that can happily read the subset of PHP we need
  4. * for our localization arrays safely.
  5. *
  6. * Still an order of magnitude slower than eval().
  7. */
  8. class QuickArrayReader {
  9. private $vars = array();
  10. /**
  11. * @param $string string
  12. */
  13. function __construct( $string ) {
  14. $scalarTypes = array(
  15. T_LNUMBER => true,
  16. T_DNUMBER => true,
  17. T_STRING => true,
  18. T_CONSTANT_ENCAPSED_STRING => true,
  19. );
  20. $skipTypes = array(
  21. T_WHITESPACE => true,
  22. T_COMMENT => true,
  23. T_DOC_COMMENT => true,
  24. );
  25. $tokens = token_get_all( $string );
  26. $count = count( $tokens );
  27. for ( $i = 0; $i < $count; ) {
  28. while ( isset( $skipTypes[$tokens[$i][0]] ) ) {
  29. $i++;
  30. }
  31. switch ( $tokens[$i][0] ) {
  32. case T_OPEN_TAG:
  33. $i++;
  34. continue;
  35. case T_VARIABLE:
  36. // '$messages' -> 'messages'
  37. $varname = trim( substr( $tokens[$i][1], 1 ) );
  38. $varindex = null;
  39. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  40. }
  41. if ( $tokens[$i] === '[' ) {
  42. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  43. }
  44. if ( isset( $scalarTypes[$tokens[$i][0]] ) ) {
  45. $varindex = $this->parseScalar( $tokens[$i] );
  46. } else {
  47. throw $this->except( $tokens[$i], 'scalar index' );
  48. }
  49. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  50. }
  51. if ( $tokens[$i] !== ']' ) {
  52. throw $this->except( $tokens[$i], ']' );
  53. }
  54. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  55. }
  56. }
  57. if ( $tokens[$i] !== '=' ) {
  58. throw $this->except( $tokens[$i], '=' );
  59. }
  60. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  61. }
  62. if ( isset( $scalarTypes[$tokens[$i][0]] ) ) {
  63. $buildval = $this->parseScalar( $tokens[$i] );
  64. } elseif ( $tokens[$i][0] === T_ARRAY ) {
  65. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  66. }
  67. if ( $tokens[$i] !== '(' ) {
  68. throw $this->except( $tokens[$i], '(' );
  69. }
  70. $buildval = array();
  71. do {
  72. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  73. }
  74. if ( $tokens[$i] === ')' ) {
  75. break;
  76. }
  77. if ( isset( $scalarTypes[$tokens[$i][0]] ) ) {
  78. $key = $this->parseScalar( $tokens[$i] );
  79. }
  80. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  81. }
  82. if ( $tokens[$i][0] !== T_DOUBLE_ARROW ) {
  83. throw $this->except( $tokens[$i], '=>' );
  84. }
  85. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  86. }
  87. if ( isset( $scalarTypes[$tokens[$i][0]] ) ) {
  88. $val = $this->parseScalar( $tokens[$i] );
  89. }
  90. wfSuppressWarnings();
  91. $buildval[$key] = $val;
  92. wfRestoreWarnings();
  93. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  94. }
  95. if ( $tokens[$i] === ',' ) {
  96. continue;
  97. } elseif ( $tokens[$i] === ')' ) {
  98. break;
  99. } else {
  100. throw $this->except( $tokens[$i], ', or )' );
  101. }
  102. } while ( true );
  103. } else {
  104. throw $this->except( $tokens[$i], 'scalar or array' );
  105. }
  106. if ( is_null( $varindex ) ) {
  107. $this->vars[$varname] = $buildval;
  108. } else {
  109. wfSuppressWarnings();
  110. $this->vars[$varname][$varindex] = $buildval;
  111. wfRestoreWarnings();
  112. }
  113. while ( isset( $skipTypes[$tokens[++$i][0]] ) ) {
  114. }
  115. if ( $tokens[$i] !== ';' ) {
  116. throw $this->except( $tokens[$i], ';' );
  117. }
  118. $i++;
  119. break;
  120. default:
  121. throw $this->except( $tokens[$i], 'open tag, whitespace, or variable.' );
  122. }
  123. }
  124. }
  125. /**
  126. * @param $got string
  127. * @param $expected string
  128. * @return Exception
  129. */
  130. private function except( $got, $expected ) {
  131. if ( is_array( $got ) ) {
  132. $got = token_name( $got[0] ) . " ('" . $got[1] . "')";
  133. } else {
  134. $got = "'" . $got . "'";
  135. }
  136. return new Exception( "Expected $expected, got $got" );
  137. }
  138. /**
  139. * Parse a scalar value in PHP
  140. *
  141. * @param $token string
  142. *
  143. * @return mixed Parsed value
  144. */
  145. function parseScalar( $token ) {
  146. if ( is_array( $token ) ) {
  147. $str = $token[1];
  148. } else {
  149. $str = $token;
  150. }
  151. if ( $str !== '' && $str[0] == '\'' ) {
  152. // Single-quoted string
  153. // @fixme trim() call is due to mystery bug where whitespace gets
  154. // appended to the token; without it we ended up reading in the
  155. // extra quote on the end!
  156. return strtr( substr( trim( $str ), 1, -1 ),
  157. array( '\\\'' => '\'', '\\\\' => '\\' ) );
  158. }
  159. wfSuppressWarnings();
  160. if ( $str !== '' && $str[0] == '"' ) {
  161. // Double-quoted string
  162. // @fixme trim() call is due to mystery bug where whitespace gets
  163. // appended to the token; without it we ended up reading in the
  164. // extra quote on the end!
  165. wfRestoreWarnings();
  166. return stripcslashes( substr( trim( $str ), 1, -1 ) );
  167. }
  168. wfRestoreWarnings();
  169. if ( substr( $str, 0, 4 ) === 'true' ) {
  170. return true;
  171. }
  172. if ( substr( $str, 0, 5 ) === 'false' ) {
  173. return false;
  174. }
  175. if ( substr( $str, 0, 4 ) === 'null' ) {
  176. return null;
  177. }
  178. // Must be some kind of numeric value, so let PHP's weak typing
  179. // be useful for a change
  180. return $str;
  181. }
  182. /**
  183. * @param $varname string
  184. * @return null|string
  185. */
  186. function getVar( $varname ) {
  187. if ( isset( $this->vars[$varname] ) ) {
  188. return $this->vars[$varname];
  189. } else {
  190. return null;
  191. }
  192. }
  193. }