(bug 19195) Make user IDs more readily available with the API
[lhc/web/wiklou.git] / includes / parser / StripState.php
1 <?php
2
3 /**
4 * @todo document, briefly.
5 * @ingroup Parser
6 */
7 class StripState {
8 protected $prefix;
9 protected $data;
10 protected $regex;
11
12 protected $tempType, $tempMergePrefix;
13
14 /**
15 * @param $prefix string
16 */
17 function __construct( $prefix ) {
18 $this->prefix = $prefix;
19 $this->data = array(
20 'nowiki' => array(),
21 'general' => array()
22 );
23 $this->regex = "/{$this->prefix}([^\x7f]+)" . Parser::MARKER_SUFFIX . '/';
24 }
25
26 /**
27 * Add a nowiki strip item
28 * @param $marker
29 * @param $value
30 */
31 function addNoWiki( $marker, $value ) {
32 $this->addItem( 'nowiki', $marker, $value );
33 }
34
35 /**
36 * @param $marker
37 * @param $value
38 */
39 function addGeneral( $marker, $value ) {
40 $this->addItem( 'general', $marker, $value );
41 }
42
43 /**
44 * @throws MWException
45 * @param $type
46 * @param $marker
47 * @param $value
48 */
49 protected function addItem( $type, $marker, $value ) {
50 if ( !preg_match( $this->regex, $marker, $m ) ) {
51 throw new MWException( "Invalid marker: $marker" );
52 }
53
54 $this->data[$type][$m[1]] = $value;
55 }
56
57 /**
58 * @param $text
59 * @return mixed
60 */
61 function unstripGeneral( $text ) {
62 return $this->unstripType( 'general', $text );
63 }
64
65 /**
66 * @param $text
67 * @return mixed
68 */
69 function unstripNoWiki( $text ) {
70 return $this->unstripType( 'nowiki', $text );
71 }
72
73 /**
74 * @param $text
75 * @return mixed
76 */
77 function unstripBoth( $text ) {
78 $text = $this->unstripType( 'general', $text );
79 $text = $this->unstripType( 'nowiki', $text );
80 return $text;
81 }
82
83 /**
84 * @param $type
85 * @param $text
86 * @return mixed
87 */
88 protected function unstripType( $type, $text ) {
89 // Shortcut
90 if ( !count( $this->data[$type] ) ) {
91 return $text;
92 }
93
94 wfProfileIn( __METHOD__ );
95 $this->tempType = $type;
96 do {
97 $oldText = $text;
98 $text = preg_replace_callback( $this->regex, array( $this, 'unstripCallback' ), $text );
99 } while ( $text !== $oldText );
100 $this->tempType = null;
101 wfProfileOut( __METHOD__ );
102 return $text;
103 }
104
105 /**
106 * @param $m array
107 * @return array
108 */
109 protected function unstripCallback( $m ) {
110 if ( isset( $this->data[$this->tempType][$m[1]] ) ) {
111 return $this->data[$this->tempType][$m[1]];
112 } else {
113 return $m[0];
114 }
115 }
116
117 /**
118 * Get a StripState object which is sufficient to unstrip the given text.
119 * It will contain the minimum subset of strip items necessary.
120 *
121 * @param $text string
122 *
123 * @return StripState
124 */
125 function getSubState( $text ) {
126 $subState = new StripState( $this->prefix );
127 $pos = 0;
128 while ( true ) {
129 $startPos = strpos( $text, $this->prefix, $pos );
130 $endPos = strpos( $text, Parser::MARKER_SUFFIX, $pos );
131 if ( $startPos === false || $endPos === false ) {
132 break;
133 }
134
135 $endPos += strlen( Parser::MARKER_SUFFIX );
136 $marker = substr( $text, $startPos, $endPos - $startPos );
137 if ( !preg_match( $this->regex, $marker, $m ) ) {
138 continue;
139 }
140
141 $key = $m[1];
142 if ( isset( $this->data['nowiki'][$key] ) ) {
143 $subState->data['nowiki'][$key] = $this->data['nowiki'][$key];
144 } elseif ( isset( $this->data['general'][$key] ) ) {
145 $subState->data['general'][$key] = $this->data['general'][$key];
146 }
147 $pos = $endPos;
148 }
149 return $subState;
150 }
151
152 /**
153 * Merge another StripState object into this one. The strip marker keys
154 * will not be preserved. The strings in the $texts array will have their
155 * strip markers rewritten, the resulting array of strings will be returned.
156 *
157 * @param $otherState StripState
158 * @param $texts Array
159 * @return Array
160 */
161 function merge( $otherState, $texts ) {
162 $mergePrefix = Parser::getRandomString();
163
164 foreach ( $otherState->data as $type => $items ) {
165 foreach ( $items as $key => $value ) {
166 $this->data[$type]["$mergePrefix-$key"] = $value;
167 }
168 }
169
170 $this->tempMergePrefix = $mergePrefix;
171 $texts = preg_replace_callback( $otherState->regex, array( $this, 'mergeCallback' ), $texts );
172 $this->tempMergePrefix = null;
173 return $texts;
174 }
175
176 /**
177 * @param $m
178 * @return string
179 */
180 protected function mergeCallback( $m ) {
181 $key = $m[1];
182 return "{$this->prefix}{$this->tempMergePrefix}-$key" . Parser::MARKER_SUFFIX;
183 }
184
185 /**
186 * Remove any strip markers found in the given text.
187 *
188 * @param $text Input string
189 * @return string
190 */
191 function killMarkers( $text ) {
192 return preg_replace( $this->regex, '', $text );
193 }
194 }
195