PluginProbe
WP Coder – Insert & Manage Code Snippets / 3.0
WP Coder – Insert & Manage Code Snippets v3.0
4.5.1 1.1 2.3.1 2.3.2 2.4.1 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 3.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.1 3.1.1 3.2 3.2.1 3.3 3.4 3.5 3.5.1 All 39 releases
wp-coder / classes / Optimization / ParseMaster.php

ParseMaster.php in WP Coder – Insert & Manage Code Snippets 3.0, at classes/Optimization/ParseMaster.php

225 lines 5.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPCoder\Optimization;
4
5 defined( 'ABSPATH' ) || exit;
6
7 class ParseMaster {
8 public $ignoreCase = false;
9 public $escapeChar = '';
10
11 // constants
12 const EXPRESSION = 0;
13 const REPLACEMENT = 1;
14 const LENGTH = 2;
15
16 // used to determine nesting levels
17 private $GROUPS = '/\\(/'; //g
18 private $SUB_REPLACE = '/\\$\\d/';
19 private $INDEXED = '/^\\$\\d+$/';
20 private $TRIM = '/([\'"])\\1\\.(.*)\\.\\1\\1$/';
21 private $ESCAPE = '/\\\./'; //g
22 private $QUOTE = '/\'/';
23 private $DELETED = '/\\x01[^\\x01]*\\x01/'; //g
24
25 public function add( $expression, $replacement = '' ) {
26 // count the number of sub-expressions
27 // - add one because each pattern is itself a sub-expression
28 $length = 1 + preg_match_all( $this->GROUPS, $this->_internalEscape( (string) $expression ), $out );
29
30 // treat only strings $replacement
31 if ( is_string( $replacement ) ) {
32 // does the pattern deal with sub-expressions?
33 if ( preg_match( $this->SUB_REPLACE, $replacement ) ) {
34 // a simple lookup? (e.g. "$2")
35 if ( preg_match( $this->INDEXED, $replacement ) ) {
36 // store the index (used for fast retrieval of matched strings)
37 $replacement = (int) ( substr( $replacement, 1 ) ) - 1;
38 } else { // a complicated lookup (e.g. "Hello $2 $1")
39 // build a function to do the lookup
40 $quote = preg_match( $this->QUOTE, $this->_internalEscape( $replacement ) )
41 ? '"' : "'";
42 $replacement = array(
43 'fn' => '_backReferences',
44 'data' => array(
45 'replacement' => $replacement,
46 'length' => $length,
47 'quote' => $quote
48 )
49 );
50 }
51 }
52 }
53 // pass the modified arguments
54 if ( ! empty( $expression ) ) {
55 $this->_add( $expression, $replacement, $length );
56 } else {
57 $this->_add( '/^$/', $replacement, $length );
58 }
59 }
60
61 public function exec( $string ) {
62 // execute the global replacement
63 $this->_escaped = array();
64
65 // simulate the _patterns.toSTring of Dean
66 $regexp = '/';
67 foreach ( $this->_patterns as $reg ) {
68 $regexp .= '(' . substr( $reg[ self::EXPRESSION ], 1, - 1 ) . ')|';
69 }
70 $regexp = substr( $regexp, 0, - 1 ) . '/';
71 $regexp .= ( $this->ignoreCase ) ? 'i' : '';
72
73 $string = $this->_escape( $string, $this->escapeChar );
74 $string = preg_replace_callback(
75 $regexp,
76 array(
77 &$this,
78 '_replacement'
79 ),
80 $string
81 );
82 $string = $this->_unescape( $string, $this->escapeChar );
83
84 return preg_replace( $this->DELETED, '', $string );
85 }
86
87 public function reset() {
88 // clear the patterns collection so that this object may be re-used
89 $this->_patterns = array();
90 }
91
92 // private
93 private $_escaped = array(); // escaped characters
94 private $_patterns = array(); // patterns stored by index
95
96 // create and add a new pattern to the patterns collection
97 private function _add() {
98 $arguments = func_get_args();
99 $this->_patterns[] = $arguments;
100 }
101
102 // this is the global replace function (it's quite complicated)
103 private function _replacement( $arguments ) {
104 if ( empty( $arguments ) ) {
105 return '';
106 }
107
108 $i = 1;
109 $j = 0;
110 // loop through the patterns
111 while ( isset( $this->_patterns[ $j ] ) ) {
112 $pattern = $this->_patterns[ $j ++ ];
113 // do we have a result?
114 if ( isset( $arguments[ $i ] ) && ( $arguments[ $i ] != '' ) ) {
115 $replacement = $pattern[ self::REPLACEMENT ];
116
117 if ( is_array( $replacement ) && isset( $replacement['fn'] ) ) {
118
119 if ( isset( $replacement['data'] ) ) {
120 $this->buffer = $replacement['data'];
121 }
122
123 return call_user_func( array( &$this, $replacement['fn'] ), $arguments, $i );
124
125 } elseif ( is_int( $replacement ) ) {
126 return $arguments[ $replacement + $i ];
127
128 }
129 $delete = ( $this->escapeChar == ''
130 || strpos( $arguments[ $i ], $this->escapeChar ) === false )
131 ? '' : "\x01" . $arguments[ $i ] . "\x01";
132
133 return $delete . $replacement;
134
135 // skip over references to sub-expressions
136 } else {
137 $i += $pattern[ self::LENGTH ];
138 }
139 }
140 }
141
142 private function _backReferences( $match, $offset ) {
143 $replacement = $this->buffer['replacement'];
144 $quote = $this->buffer['quote'];
145 $i = $this->buffer['length'];
146 while ( $i ) {
147 $replacement = str_replace( '$' . $i --, $match[ $offset + $i ], $replacement );
148 }
149
150 return $replacement;
151 }
152
153 private function _replace_name( $match, $offset ) {
154 $length = strlen( $match[ $offset + 2 ] );
155 $start = $length - max( $length - strlen( $match[ $offset + 3 ] ), 0 );
156
157 return substr( $match[ $offset + 1 ], $start, $length ) . $match[ $offset + 4 ];
158 }
159
160 private function _replace_encoded( $match, $offset ) {
161 return $this->buffer[ $match[ $offset ] ];
162 }
163
164
165 // php : we cannot pass additional data to preg_replace_callback,
166 // and we cannot use &$this in create_function, so let's go to lower level
167 private $buffer;
168
169 // encode escaped characters
170 private function _escape( $string, $escapeChar ) {
171 if ( $escapeChar ) {
172 $this->buffer = $escapeChar;
173
174 return preg_replace_callback(
175 '/\\' . $escapeChar . '(.)' . '/',
176 array( &$this, '_escapeBis' ),
177 $string
178 );
179
180 } else {
181 return $string;
182 }
183 }
184
185 private function _escapeBis( $match ) {
186 $this->_escaped[] = $match[1];
187
188 return $this->buffer;
189 }
190
191 // decode escaped characters
192 private function _unescape( $string, $escapeChar ) {
193 if ( $escapeChar ) {
194 $regexp = '/' . '\\' . $escapeChar . '/';
195 $this->buffer = array( 'escapeChar' => $escapeChar, 'i' => 0 );
196
197 return preg_replace_callback
198 (
199 $regexp,
200 array( &$this, '_unescapeBis' ),
201 $string
202 );
203
204 } else {
205 return $string;
206 }
207 }
208
209 private function _unescapeBis() {
210 if ( isset( $this->_escaped[ $this->buffer['i'] ] )
211 && $this->_escaped[ $this->buffer['i'] ] != ''
212 ) {
213 $temp = $this->_escaped[ $this->buffer['i'] ];
214 } else {
215 $temp = '';
216 }
217 $this->buffer['i'] ++;
218
219 return $this->buffer['escapeChar'] . $temp;
220 }
221
222 private function _internalEscape( $string ) {
223 return preg_replace( $this->ESCAPE, '', $string );
224 }
225 }