Index: trunk/phase3/maintenance/parserTests.inc |
— | — | @@ -269,9 +269,13 @@ |
270 | 270 | $out = $parser->preSaveTransform( $input, $title, $user, $options ); |
271 | 271 | } elseif (preg_match('/\\bmsg\\b/i', $opts)) { |
272 | 272 | $out = $parser->transformMsg( $input, $options ); |
273 | | - } elseif( preg_match( '/\\bsection=(\d+)\b/', $opts, $matches ) ) { |
| 273 | + } elseif( preg_match( '/\\bsection=(\d+)\b/i', $opts, $matches ) ) { |
274 | 274 | $section = intval( $matches[1] ); |
275 | | - $out = Article::getSection( $input, $section ); |
| 275 | + $out = $parser->getSection( $input, $section ); |
| 276 | + } elseif( preg_match( '/\\breplace=(\d+),"(.*?)"/i', $opts, $matches ) ) { |
| 277 | + $section = intval( $matches[1] ); |
| 278 | + $replace = $matches[2]; |
| 279 | + $out = $parser->replaceSection( $input, $section, $replace ); |
276 | 280 | } else { |
277 | 281 | $output = $parser->parse( $input, $title, $options, true, true, 1337 ); |
278 | 282 | $out = $output->getText(); |
Index: trunk/phase3/maintenance/parserTests.txt |
— | — | @@ -4839,7 +4839,438 @@ |
4840 | 4840 | <h3>aa</h3> |
4841 | 4841 | !! end |
4842 | 4842 | |
| 4843 | +!! test |
| 4844 | +Section extraction, HTML headings should be ignored in extensions (bug 3476) |
| 4845 | +!! options |
| 4846 | +section=2 |
| 4847 | +!! input |
| 4848 | +<h2>a</h2> |
| 4849 | +<tag> |
| 4850 | +<h2>not b</h2> |
| 4851 | +</tag> |
| 4852 | +<h2>b</h2> |
| 4853 | +!! result |
| 4854 | +<h2>b</h2> |
| 4855 | +!! end |
4843 | 4856 | |
| 4857 | +!! test |
| 4858 | +Section replacement test (section 0) |
| 4859 | +!! options |
| 4860 | +replace=0,"xxx" |
| 4861 | +!! input |
| 4862 | +start |
| 4863 | +==a== |
| 4864 | +===aa=== |
| 4865 | +====aaa==== |
| 4866 | +==b== |
| 4867 | +===ba=== |
| 4868 | +===bb=== |
| 4869 | +====bba==== |
| 4870 | +===bc=== |
| 4871 | +==c== |
| 4872 | +===ca=== |
| 4873 | +!! result |
| 4874 | +xxx |
| 4875 | + |
| 4876 | +==a== |
| 4877 | +===aa=== |
| 4878 | +====aaa==== |
| 4879 | +==b== |
| 4880 | +===ba=== |
| 4881 | +===bb=== |
| 4882 | +====bba==== |
| 4883 | +===bc=== |
| 4884 | +==c== |
| 4885 | +===ca=== |
| 4886 | +!! end |
| 4887 | + |
| 4888 | +!! test |
| 4889 | +Section replacement test (section 1) |
| 4890 | +!! options |
| 4891 | +replace=1,"xxx" |
| 4892 | +!! input |
| 4893 | +start |
| 4894 | +==a== |
| 4895 | +===aa=== |
| 4896 | +====aaa==== |
| 4897 | +==b== |
| 4898 | +===ba=== |
| 4899 | +===bb=== |
| 4900 | +====bba==== |
| 4901 | +===bc=== |
| 4902 | +==c== |
| 4903 | +===ca=== |
| 4904 | +!! result |
| 4905 | +start |
| 4906 | +xxx |
| 4907 | + |
| 4908 | +==b== |
| 4909 | +===ba=== |
| 4910 | +===bb=== |
| 4911 | +====bba==== |
| 4912 | +===bc=== |
| 4913 | +==c== |
| 4914 | +===ca=== |
| 4915 | +!! end |
| 4916 | + |
| 4917 | +!! test |
| 4918 | +Section replacement test (section 2) |
| 4919 | +!! options |
| 4920 | +replace=2,"xxx" |
| 4921 | +!! input |
| 4922 | +start |
| 4923 | +==a== |
| 4924 | +===aa=== |
| 4925 | +====aaa==== |
| 4926 | +==b== |
| 4927 | +===ba=== |
| 4928 | +===bb=== |
| 4929 | +====bba==== |
| 4930 | +===bc=== |
| 4931 | +==c== |
| 4932 | +===ca=== |
| 4933 | +!! result |
| 4934 | +start |
| 4935 | +==a== |
| 4936 | +xxx |
| 4937 | + |
| 4938 | +==b== |
| 4939 | +===ba=== |
| 4940 | +===bb=== |
| 4941 | +====bba==== |
| 4942 | +===bc=== |
| 4943 | +==c== |
| 4944 | +===ca=== |
| 4945 | +!! end |
| 4946 | + |
| 4947 | +!! test |
| 4948 | +Section replacement test (section 3) |
| 4949 | +!! options |
| 4950 | +replace=3,"xxx" |
| 4951 | +!! input |
| 4952 | +start |
| 4953 | +==a== |
| 4954 | +===aa=== |
| 4955 | +====aaa==== |
| 4956 | +==b== |
| 4957 | +===ba=== |
| 4958 | +===bb=== |
| 4959 | +====bba==== |
| 4960 | +===bc=== |
| 4961 | +==c== |
| 4962 | +===ca=== |
| 4963 | +!! result |
| 4964 | +start |
| 4965 | +==a== |
| 4966 | +===aa=== |
| 4967 | +xxx |
| 4968 | + |
| 4969 | +==b== |
| 4970 | +===ba=== |
| 4971 | +===bb=== |
| 4972 | +====bba==== |
| 4973 | +===bc=== |
| 4974 | +==c== |
| 4975 | +===ca=== |
| 4976 | +!! end |
| 4977 | + |
| 4978 | +!! test |
| 4979 | +Section replacement test (section 4) |
| 4980 | +!! options |
| 4981 | +replace=4,"xxx" |
| 4982 | +!! input |
| 4983 | +start |
| 4984 | +==a== |
| 4985 | +===aa=== |
| 4986 | +====aaa==== |
| 4987 | +==b== |
| 4988 | +===ba=== |
| 4989 | +===bb=== |
| 4990 | +====bba==== |
| 4991 | +===bc=== |
| 4992 | +==c== |
| 4993 | +===ca=== |
| 4994 | +!! result |
| 4995 | +start |
| 4996 | +==a== |
| 4997 | +===aa=== |
| 4998 | +====aaa==== |
| 4999 | +xxx |
| 5000 | + |
| 5001 | +==c== |
| 5002 | +===ca=== |
| 5003 | +!! end |
| 5004 | + |
| 5005 | +!! test |
| 5006 | +Section replacement test (section 5) |
| 5007 | +!! options |
| 5008 | +replace=5,"xxx" |
| 5009 | +!! input |
| 5010 | +start |
| 5011 | +==a== |
| 5012 | +===aa=== |
| 5013 | +====aaa==== |
| 5014 | +==b== |
| 5015 | +===ba=== |
| 5016 | +===bb=== |
| 5017 | +====bba==== |
| 5018 | +===bc=== |
| 5019 | +==c== |
| 5020 | +===ca=== |
| 5021 | +!! result |
| 5022 | +start |
| 5023 | +==a== |
| 5024 | +===aa=== |
| 5025 | +====aaa==== |
| 5026 | +==b== |
| 5027 | +xxx |
| 5028 | + |
| 5029 | +===bb=== |
| 5030 | +====bba==== |
| 5031 | +===bc=== |
| 5032 | +==c== |
| 5033 | +===ca=== |
| 5034 | +!! end |
| 5035 | + |
| 5036 | +!! test |
| 5037 | +Section replacement test (section 6) |
| 5038 | +!! options |
| 5039 | +replace=6,"xxx" |
| 5040 | +!! input |
| 5041 | +start |
| 5042 | +==a== |
| 5043 | +===aa=== |
| 5044 | +====aaa==== |
| 5045 | +==b== |
| 5046 | +===ba=== |
| 5047 | +===bb=== |
| 5048 | +====bba==== |
| 5049 | +===bc=== |
| 5050 | +==c== |
| 5051 | +===ca=== |
| 5052 | +!! result |
| 5053 | +start |
| 5054 | +==a== |
| 5055 | +===aa=== |
| 5056 | +====aaa==== |
| 5057 | +==b== |
| 5058 | +===ba=== |
| 5059 | +xxx |
| 5060 | + |
| 5061 | +===bc=== |
| 5062 | +==c== |
| 5063 | +===ca=== |
| 5064 | +!! end |
| 5065 | + |
| 5066 | +!! test |
| 5067 | +Section replacement test (section 7) |
| 5068 | +!! options |
| 5069 | +replace=7,"xxx" |
| 5070 | +!! input |
| 5071 | +start |
| 5072 | +==a== |
| 5073 | +===aa=== |
| 5074 | +====aaa==== |
| 5075 | +==b== |
| 5076 | +===ba=== |
| 5077 | +===bb=== |
| 5078 | +====bba==== |
| 5079 | +===bc=== |
| 5080 | +==c== |
| 5081 | +===ca=== |
| 5082 | +!! result |
| 5083 | +start |
| 5084 | +==a== |
| 5085 | +===aa=== |
| 5086 | +====aaa==== |
| 5087 | +==b== |
| 5088 | +===ba=== |
| 5089 | +===bb=== |
| 5090 | +xxx |
| 5091 | + |
| 5092 | +===bc=== |
| 5093 | +==c== |
| 5094 | +===ca=== |
| 5095 | +!! end |
| 5096 | + |
| 5097 | +!! test |
| 5098 | +Section replacement test (section 8) |
| 5099 | +!! options |
| 5100 | +replace=8,"xxx" |
| 5101 | +!! input |
| 5102 | +start |
| 5103 | +==a== |
| 5104 | +===aa=== |
| 5105 | +====aaa==== |
| 5106 | +==b== |
| 5107 | +===ba=== |
| 5108 | +===bb=== |
| 5109 | +====bba==== |
| 5110 | +===bc=== |
| 5111 | +==c== |
| 5112 | +===ca=== |
| 5113 | +!! result |
| 5114 | +start |
| 5115 | +==a== |
| 5116 | +===aa=== |
| 5117 | +====aaa==== |
| 5118 | +==b== |
| 5119 | +===ba=== |
| 5120 | +===bb=== |
| 5121 | +====bba==== |
| 5122 | +xxx |
| 5123 | + |
| 5124 | +==c== |
| 5125 | +===ca=== |
| 5126 | +!!end |
| 5127 | + |
| 5128 | +!! test |
| 5129 | +Section replacement test (section 9) |
| 5130 | +!! options |
| 5131 | +replace=9,"xxx" |
| 5132 | +!! input |
| 5133 | +start |
| 5134 | +==a== |
| 5135 | +===aa=== |
| 5136 | +====aaa==== |
| 5137 | +==b== |
| 5138 | +===ba=== |
| 5139 | +===bb=== |
| 5140 | +====bba==== |
| 5141 | +===bc=== |
| 5142 | +==c== |
| 5143 | +===ca=== |
| 5144 | +!! result |
| 5145 | +start |
| 5146 | +==a== |
| 5147 | +===aa=== |
| 5148 | +====aaa==== |
| 5149 | +==b== |
| 5150 | +===ba=== |
| 5151 | +===bb=== |
| 5152 | +====bba==== |
| 5153 | +===bc=== |
| 5154 | +xxx |
| 5155 | +!! end |
| 5156 | + |
| 5157 | +!! test |
| 5158 | +Section replacement test (section 10) |
| 5159 | +!! options |
| 5160 | +replace=10,"xxx" |
| 5161 | +!! input |
| 5162 | +start |
| 5163 | +==a== |
| 5164 | +===aa=== |
| 5165 | +====aaa==== |
| 5166 | +==b== |
| 5167 | +===ba=== |
| 5168 | +===bb=== |
| 5169 | +====bba==== |
| 5170 | +===bc=== |
| 5171 | +==c== |
| 5172 | +===ca=== |
| 5173 | +!! result |
| 5174 | +start |
| 5175 | +==a== |
| 5176 | +===aa=== |
| 5177 | +====aaa==== |
| 5178 | +==b== |
| 5179 | +===ba=== |
| 5180 | +===bb=== |
| 5181 | +====bba==== |
| 5182 | +===bc=== |
| 5183 | +==c== |
| 5184 | +xxx |
| 5185 | +!! end |
| 5186 | + |
| 5187 | + |
| 5188 | +!! test |
| 5189 | +Section extraction, HTML headings not at line boundaries (section 0) |
| 5190 | +!! options |
| 5191 | +section=0 |
| 5192 | +!! input |
| 5193 | +<h2>Evil</h2><i>blah blah blah</i> |
| 5194 | + |
| 5195 | +evil blah |
| 5196 | + |
| 5197 | +<h2>Nice</h2> |
| 5198 | + |
| 5199 | +nice blah |
| 5200 | + |
| 5201 | +<i>extra evil</i><h2>Extra nasty</h2> |
| 5202 | + |
| 5203 | +extra nasty |
| 5204 | +!! result |
| 5205 | +!! end |
| 5206 | + |
| 5207 | +!! test |
| 5208 | +Section extraction, HTML headings not at line boundaries (section 1) |
| 5209 | +!! options |
| 5210 | +section=1 |
| 5211 | +!! input |
| 5212 | +<h2>Evil</h2><i>blah blah blah</i> |
| 5213 | + |
| 5214 | +evil blah |
| 5215 | + |
| 5216 | +<h2>Nice</h2> |
| 5217 | + |
| 5218 | +nice blah |
| 5219 | + |
| 5220 | +<i>extra evil</i><h2>Extra nasty</h2> |
| 5221 | + |
| 5222 | +extra nasty |
| 5223 | +!! result |
| 5224 | +<h2>Evil</h2><i>blah blah blah</i> |
| 5225 | + |
| 5226 | +evil blah |
| 5227 | +!! end |
| 5228 | + |
| 5229 | +!! test |
| 5230 | +Section extraction, HTML headings not at line boundaries (section 2) |
| 5231 | +!! options |
| 5232 | +section=2 |
| 5233 | +!! input |
| 5234 | +<h2>Evil</h2><i>blah blah blah</i> |
| 5235 | + |
| 5236 | +evil blah |
| 5237 | + |
| 5238 | +<h2>Nice</h2> |
| 5239 | + |
| 5240 | +nice blah |
| 5241 | + |
| 5242 | +<i>extra evil</i><h2>Extra nasty</h2> |
| 5243 | + |
| 5244 | +extra nasty |
| 5245 | +!! result |
| 5246 | +<h2>Nice</h2> |
| 5247 | + |
| 5248 | +nice blah |
| 5249 | + |
| 5250 | +<i>extra evil</i> |
| 5251 | +!! end |
| 5252 | + |
| 5253 | +!! test |
| 5254 | +Section extraction, HTML headings not at line boundaries (section 3) |
| 5255 | +!! options |
| 5256 | +section=3 |
| 5257 | +!! input |
| 5258 | +<h2>Evil</h2><i>blah blah blah</i> |
| 5259 | + |
| 5260 | +evil blah |
| 5261 | + |
| 5262 | +<h2>Nice</h2> |
| 5263 | + |
| 5264 | +nice blah |
| 5265 | + |
| 5266 | +<i>extra evil</i><h2>Extra nasty</h2> |
| 5267 | + |
| 5268 | +extra nasty |
| 5269 | +!! result |
| 5270 | +<h2>Extra nasty</h2> |
| 5271 | + |
| 5272 | +extra nasty |
| 5273 | +!! end |
| 5274 | + |
4844 | 5275 | # |
4845 | 5276 | # |
4846 | 5277 | # |
Index: trunk/phase3/includes/Article.php |
— | — | @@ -242,62 +242,8 @@ |
243 | 243 | * @return string text of the requested section |
244 | 244 | */ |
245 | 245 | function getSection($text,$section) { |
246 | | - |
247 | | - # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML |
248 | | - # comments to be stripped as well) |
249 | | - $striparray=array(); |
250 | | - $parser=new Parser(); |
251 | | - $parser->mOutputType=OT_WIKI; |
252 | | - $parser->mOptions = new ParserOptions(); |
253 | | - $striptext=$parser->strip($text, $striparray, true); |
254 | | - |
255 | | - # now that we can be sure that no pseudo-sections are in the source, |
256 | | - # split it up by section |
257 | | - $secs = |
258 | | - preg_split( |
259 | | - '/(^=+.+?=+|^<h[1-6].*?>.*?<\/h[1-6].*?>)(?!\S)/mi', |
260 | | - $striptext, -1, |
261 | | - PREG_SPLIT_DELIM_CAPTURE); |
262 | | - if($section==0) { |
263 | | - $rv=$secs[0]; |
264 | | - } else { |
265 | | - $headline=$secs[$section*2-1]; |
266 | | - preg_match( '/^(=+).+?=+|^<h([1-6]).*?>.*?<\/h[1-6].*?>(?!\S)/mi',$headline,$matches); |
267 | | - $hlevel=$matches[1]; |
268 | | - |
269 | | - # translate wiki heading into level |
270 | | - if(strpos($hlevel,'=')!==false) { |
271 | | - $hlevel=strlen($hlevel); |
272 | | - } |
273 | | - |
274 | | - $rv=$headline. $secs[$section*2]; |
275 | | - $count=$section+1; |
276 | | - |
277 | | - $break=false; |
278 | | - while(!empty($secs[$count*2-1]) && !$break) { |
279 | | - |
280 | | - $subheadline=$secs[$count*2-1]; |
281 | | - preg_match( '/^(=+).+?=+|^<h([1-6]).*?>.*?<\/h[1-6].*?>(?!\S)/mi',$subheadline,$matches); |
282 | | - $subhlevel=$matches[1]; |
283 | | - if(strpos($subhlevel,'=')!==false) { |
284 | | - $subhlevel=strlen($subhlevel); |
285 | | - } |
286 | | - if($subhlevel > $hlevel) { |
287 | | - $rv.=$subheadline.$secs[$count*2]; |
288 | | - } |
289 | | - if($subhlevel <= $hlevel) { |
290 | | - $break=true; |
291 | | - } |
292 | | - $count++; |
293 | | - |
294 | | - } |
295 | | - } |
296 | | - # reinsert stripped tags |
297 | | - $rv=$parser->unstrip($rv,$striparray); |
298 | | - $rv=$parser->unstripNoWiki($rv,$striparray); |
299 | | - $rv=trim($rv); |
300 | | - return $rv; |
301 | | - |
| 246 | + global $wgParser; |
| 247 | + return $wgParser->getSection( $text, $section ); |
302 | 248 | } |
303 | 249 | |
304 | 250 | /** |
— | — | @@ -1288,8 +1234,10 @@ |
1289 | 1235 | function replaceSection($section, $text, $summary = '', $edittime = NULL) { |
1290 | 1236 | $fname = 'Article::replaceSection'; |
1291 | 1237 | wfProfileIn( $fname ); |
1292 | | - |
1293 | | - if ($section != '') { |
| 1238 | + |
| 1239 | + if( $section == '' ) { |
| 1240 | + // Whole-page edit; let the text through unmolested. |
| 1241 | + } else { |
1294 | 1242 | if( is_null( $edittime ) ) { |
1295 | 1243 | $rev = Revision::newFromTitle( $this->mTitle ); |
1296 | 1244 | } else { |
— | — | @@ -1307,71 +1255,11 @@ |
1308 | 1256 | if($summary) $subject="== {$summary} ==\n\n"; |
1309 | 1257 | $text=$oldtext."\n\n".$subject.$text; |
1310 | 1258 | } else { |
1311 | | - |
1312 | | - # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML |
1313 | | - # comments to be stripped as well) |
1314 | | - $striparray=array(); |
1315 | | - $parser=new Parser(); |
1316 | | - $parser->mOutputType=OT_WIKI; |
1317 | | - $parser->mOptions = new ParserOptions(); |
1318 | | - $oldtext=$parser->strip($oldtext, $striparray, true); |
1319 | | - |
1320 | | - # now that we can be sure that no pseudo-sections are in the source, |
1321 | | - # split it up |
1322 | | - # Unfortunately we can't simply do a preg_replace because that might |
1323 | | - # replace the wrong section, so we have to use the section counter instead |
1324 | | - $secs=preg_split('/(^=+.+?=+|^<h[1-6].*?>.*?<\/h[1-6].*?>)(?!\S)/mi', |
1325 | | - $oldtext,-1,PREG_SPLIT_DELIM_CAPTURE); |
1326 | | - $secs[$section*2]=$text."\n\n"; // replace with edited |
1327 | | - |
1328 | | - # section 0 is top (intro) section |
1329 | | - if($section!=0) { |
1330 | | - |
1331 | | - # headline of old section - we need to go through this section |
1332 | | - # to determine if there are any subsections that now need to |
1333 | | - # be erased, as the mother section has been replaced with |
1334 | | - # the text of all subsections. |
1335 | | - $headline=$secs[$section*2-1]; |
1336 | | - preg_match( '/^(=+).+?=+|^<h([1-6]).*?>.*?<\/h[1-6].*?>(?!\S)/mi',$headline,$matches); |
1337 | | - $hlevel=$matches[1]; |
1338 | | - |
1339 | | - # determine headline level for wikimarkup headings |
1340 | | - if(strpos($hlevel,'=')!==false) { |
1341 | | - $hlevel=strlen($hlevel); |
1342 | | - } |
1343 | | - |
1344 | | - $secs[$section*2-1]=''; // erase old headline |
1345 | | - $count=$section+1; |
1346 | | - $break=false; |
1347 | | - while(!empty($secs[$count*2-1]) && !$break) { |
1348 | | - |
1349 | | - $subheadline=$secs[$count*2-1]; |
1350 | | - preg_match( |
1351 | | - '/^(=+).+?=+|^<h([1-6]).*?>.*?<\/h[1-6].*?>(?!\S)/mi',$subheadline,$matches); |
1352 | | - $subhlevel=$matches[1]; |
1353 | | - if(strpos($subhlevel,'=')!==false) { |
1354 | | - $subhlevel=strlen($subhlevel); |
1355 | | - } |
1356 | | - if($subhlevel > $hlevel) { |
1357 | | - // erase old subsections |
1358 | | - $secs[$count*2-1]=''; |
1359 | | - $secs[$count*2]=''; |
1360 | | - } |
1361 | | - if($subhlevel <= $hlevel) { |
1362 | | - $break=true; |
1363 | | - } |
1364 | | - $count++; |
1365 | | - |
1366 | | - } |
1367 | | - |
1368 | | - } |
1369 | | - $text=join('',$secs); |
1370 | | - # reinsert the stuff that we stripped out earlier |
1371 | | - $text=$parser->unstrip($text,$striparray); |
1372 | | - $text=$parser->unstripNoWiki($text,$striparray); |
| 1259 | + global $wgParser; |
| 1260 | + $text = $wgParser->replaceSection( $oldtext, $section, $text ); |
1373 | 1261 | } |
1374 | | - |
1375 | 1262 | } |
| 1263 | + |
1376 | 1264 | wfProfileOut( $fname ); |
1377 | 1265 | return $text; |
1378 | 1266 | } |
Index: trunk/phase3/includes/Parser.php |
— | — | @@ -367,7 +367,7 @@ |
368 | 368 | $inside = $p[4]; |
369 | 369 | } |
370 | 370 | |
371 | | - $marker = "$uniq_prefix-$element-$rand" . sprintf('%08X', $n++); |
| 371 | + $marker = "$uniq_prefix-$element-$rand" . sprintf('%08X', $n++) . '-QINU'; |
372 | 372 | $stripped .= $marker; |
373 | 373 | |
374 | 374 | if ( $close === '/>' ) { |
— | — | @@ -883,7 +883,7 @@ |
884 | 884 | wfProfileIn( $fname ); |
885 | 885 | for ( $i = 6; $i >= 1; --$i ) { |
886 | 886 | $h = str_repeat( '=', $i ); |
887 | | - $text = preg_replace( "/^{$h}(.+){$h}(\\s|$)/m", |
| 887 | + $text = preg_replace( "/^{$h}(.+){$h}\\s*$/m", |
888 | 888 | "<h{$i}>\\1</h{$i}>\\2", $text ); |
889 | 889 | } |
890 | 890 | wfProfileOut( $fname ); |
— | — | @@ -4209,6 +4209,165 @@ |
4210 | 4210 | */ |
4211 | 4211 | function getTags() { return array_keys( $this->mTagHooks ); } |
4212 | 4212 | /**#@-*/ |
| 4213 | + |
| 4214 | + |
| 4215 | + /** |
| 4216 | + * Break wikitext input into sections, and either pull or replace |
| 4217 | + * some particular section's text. |
| 4218 | + * |
| 4219 | + * External callers should use the getSection and replaceSection methods. |
| 4220 | + * |
| 4221 | + * @param $text Page wikitext |
| 4222 | + * @param $section Numbered section. 0 pulls the text before the first |
| 4223 | + * heading; other numbers will pull the given section |
| 4224 | + * along with its lower-level subsections. |
| 4225 | + * @param $mode One of "get" or "replace" |
| 4226 | + * @param $newtext Replacement text for section data. |
| 4227 | + * @return string for "get", the extracted section text. |
| 4228 | + * for "replace", the whole page with the section replaced. |
| 4229 | + */ |
| 4230 | + private function extractSections( $text, $section, $mode, $newtext='' ) { |
| 4231 | + # strip NOWIKI etc. to avoid confusion (true-parameter causes HTML |
| 4232 | + # comments to be stripped as well) |
| 4233 | + $striparray = array(); |
| 4234 | + |
| 4235 | + $oldOutputType = $this->mOutputType; |
| 4236 | + $oldOptions = $this->mOptions; |
| 4237 | + $this->mOptions = new ParserOptions(); |
| 4238 | + $this->mOutputType = OT_WIKI; |
| 4239 | + |
| 4240 | + $striptext = $this->strip( $text, $striparray, true ); |
| 4241 | + |
| 4242 | + $this->mOutputType = $oldOutputType; |
| 4243 | + $this->mOptions = $oldOptions; |
| 4244 | + |
| 4245 | + # now that we can be sure that no pseudo-sections are in the source, |
| 4246 | + # split it up by section |
| 4247 | + $uniq = preg_quote( $this->uniqPrefix(), '/' ); |
| 4248 | + $comment = "(?:$uniq-!--.*?QINU)"; |
| 4249 | + $secs = preg_split( |
| 4250 | + /* |
| 4251 | + "/ |
| 4252 | + ^( |
| 4253 | + (?:$comment|<\/?noinclude>)* # Initial comments will be stripped |
| 4254 | + (?: |
| 4255 | + (=+) # Should this be limited to 6? |
| 4256 | + .+? # Section title... |
| 4257 | + \\2 # Ending = count must match start |
| 4258 | + | |
| 4259 | + ^ |
| 4260 | + <h([1-6])\b.*?> |
| 4261 | + .*? |
| 4262 | + <\/h\\3\s*> |
| 4263 | + ) |
| 4264 | + (?:$comment|<\/?noinclude>|\s+)* # Trailing whitespace ok |
| 4265 | + )$ |
| 4266 | + /mix", |
| 4267 | + */ |
| 4268 | + "/ |
| 4269 | + ( |
| 4270 | + ^ |
| 4271 | + (?:$comment|<\/?noinclude>)* # Initial comments will be stripped |
| 4272 | + (=+) # Should this be limited to 6? |
| 4273 | + .+? # Section title... |
| 4274 | + \\2 # Ending = count must match start |
| 4275 | + (?:$comment|<\/?noinclude>|\s+)* # Trailing whitespace ok |
| 4276 | + $ |
| 4277 | + | |
| 4278 | + <h([1-6])\b.*?> |
| 4279 | + .*? |
| 4280 | + <\/h\\3\s*> |
| 4281 | + ) |
| 4282 | + /mix", |
| 4283 | + $striptext, -1, |
| 4284 | + PREG_SPLIT_DELIM_CAPTURE); |
| 4285 | + |
| 4286 | + if( $mode == "get" ) { |
| 4287 | + if( $section == 0 ) { |
| 4288 | + // "Section 0" returns the content before any other section. |
| 4289 | + $rv = $secs[0]; |
| 4290 | + } else { |
| 4291 | + $rv = ""; |
| 4292 | + } |
| 4293 | + } elseif( $mode == "replace" ) { |
| 4294 | + if( $section == 0 ) { |
| 4295 | + $rv = $newtext . "\n\n"; |
| 4296 | + $remainder = true; |
| 4297 | + } else { |
| 4298 | + $rv = $secs[0]; |
| 4299 | + $remainder = false; |
| 4300 | + } |
| 4301 | + } |
| 4302 | + $count = 0; |
| 4303 | + $sectionLevel = 0; |
| 4304 | + for( $index = 1; $index < count( $secs ); ) { |
| 4305 | + $headerLine = $secs[$index++]; |
| 4306 | + if( $secs[$index] ) { |
| 4307 | + // A wiki header |
| 4308 | + $headerLevel = strlen( $secs[$index++] ); |
| 4309 | + } else { |
| 4310 | + // An HTML header |
| 4311 | + $index++; |
| 4312 | + $headerLevel = intval( $secs[$index++] ); |
| 4313 | + } |
| 4314 | + $content = $secs[$index++]; |
| 4315 | + |
| 4316 | + $count++; |
| 4317 | + if( $mode == "get" ) { |
| 4318 | + if( $count == $section ) { |
| 4319 | + $rv = $headerLine . $content; |
| 4320 | + $sectionLevel = $headerLevel; |
| 4321 | + } elseif( $count > $section ) { |
| 4322 | + if( $sectionLevel && $headerLevel > $sectionLevel ) { |
| 4323 | + $rv .= $headerLine . $content; |
| 4324 | + } else { |
| 4325 | + // Broke out to a higher-level section |
| 4326 | + break; |
| 4327 | + } |
| 4328 | + } |
| 4329 | + } elseif( $mode == "replace" ) { |
| 4330 | + if( $count < $section ) { |
| 4331 | + $rv .= $headerLine . $content; |
| 4332 | + } elseif( $count == $section ) { |
| 4333 | + $rv .= $newtext . "\n\n"; |
| 4334 | + $sectionLevel = $headerLevel; |
| 4335 | + } elseif( $count > $section ) { |
| 4336 | + if( $headerLevel <= $sectionLevel ) { |
| 4337 | + // Passed the section's sub-parts. |
| 4338 | + $remainder = true; |
| 4339 | + } |
| 4340 | + if( $remainder ) { |
| 4341 | + $rv .= $headerLine . $content; |
| 4342 | + } |
| 4343 | + } |
| 4344 | + } |
| 4345 | + } |
| 4346 | + # reinsert stripped tags |
| 4347 | + $rv = $this->unstrip( $rv, $striparray ); |
| 4348 | + $rv = $this->unstripNoWiki( $rv, $striparray ); |
| 4349 | + $rv = trim( $rv ); |
| 4350 | + return $rv; |
| 4351 | + } |
| 4352 | + |
| 4353 | + /** |
| 4354 | + * This function returns the text of a section, specified by a number ($section). |
| 4355 | + * A section is text under a heading like == Heading == or \<h1\>Heading\</h1\>, or |
| 4356 | + * the first section before any such heading (section 0). |
| 4357 | + * |
| 4358 | + * If a section contains subsections, these are also returned. |
| 4359 | + * |
| 4360 | + * @param $text String: text to look in |
| 4361 | + * @param $section Integer: section number |
| 4362 | + * @return string text of the requested section |
| 4363 | + */ |
| 4364 | + function getSection( $text, $section ) { |
| 4365 | + return $this->extractSections( $text, $section, "get" ); |
| 4366 | + } |
| 4367 | + |
| 4368 | + function replaceSection( $oldtext, $section, $text ) { |
| 4369 | + return $this->extractSections( $oldtext, $section, "replace", $text ); |
| 4370 | + } |
| 4371 | + |
4213 | 4372 | } |
4214 | 4373 | |
4215 | 4374 | /** |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -429,7 +429,17 @@ |
430 | 430 | * Add 'SiteNoticeBefore' and 'SiteNoticeAfter' hooks |
431 | 431 | * (bug 6182) Date passed in "sp-newimages-showfrom" not adjusted to user time |
432 | 432 | preferences |
| 433 | +* (bug 2587) Fix for section editing with comment prefix |
| 434 | +* (bug 2607) Fix for section editing with mix of wiki and HTML headings |
| 435 | +* (bug 3342) Fix for section editing with headings wrapped in <noinclude> |
| 436 | +* (bug 3476) Fix for section editing with faux headings in extensions |
| 437 | +* (bug 5272) Fix for section editing with HTML-heading subsections |
| 438 | +* Fix for bogus wiki headings improperly detected with following text |
| 439 | +* Fix for HTML headings improperly not detected with preceding/following text |
| 440 | +* Section extraction and replacement functions merged into one implementation |
| 441 | + on the Parser object, so they can't get out of sync with each other. |
433 | 442 | |
| 443 | + |
434 | 444 | == Compatibility == |
435 | 445 | |
436 | 446 | MediaWiki 1.7 requires PHP 5 (5.1 recommended). PHP 4 is no longer supported. |