Index: trunk/extensions/EditSubpages/EditSubpages.php |
— | — | @@ -12,23 +12,25 @@ |
13 | 13 | |
14 | 14 | $wgExtensionCredits['other'][] = array( |
15 | 15 | 'name' => "EditSubpages", |
16 | | -'description' => "Allows sysops to unlock a page and all subpages of that page |
17 | | -for anonymous editing via [[MediaWiki:Unlockedpages]]", |
| 16 | +'description' => "Allows sysops to unlock a page and all subpages of that page for anonymous editing via [[MediaWiki:Unlockedpages]]", |
18 | 17 | 'descriptionmsg' => 'editsubpages-desc', |
19 | 18 | 'author' => "<span class=\"plainlinks\">[http://strategywiki.org/wiki/User:Ryan_Schmidt Ryan Schmidt] and [http://strategywiki.org/wiki/User:Prod Prod]</span>", |
20 | 19 | 'url' => "http://www.mediawiki.org/wiki/Extension:EditSubpages", |
21 | | -'version' => "2.2", |
| 20 | +'version' => "3.0", |
22 | 21 | ); |
23 | 22 | |
24 | 23 | $wgHooks['userCan'][] = 'EditSubpages'; |
25 | 24 | $wgGroupPermissions['*']['edit'] = true; |
| 25 | +$wgGroupPermissions['*']['createpage'] = true; |
| 26 | +$wgGroupPermissions['*']['createtalk'] = true; |
26 | 27 | $dir = dirname(__FILE__) . '/'; |
27 | 28 | $wgExtensionMessagesFiles['EditSubpages'] = $dir .'EditSubpages.i18n.php'; |
| 29 | +$evEditSubpagesCache = array(); |
28 | 30 | |
29 | 31 | function EditSubpages($title, $user, $action, $result) { |
30 | | - if(($action == 'edit' || $action == 'submit') && !$user->isLoggedIn() ){ |
31 | | - $result = false; |
32 | | - $pagename = $title->getText(); //name of page w/ spaces, not underscores |
| 32 | + global $evEditSubpagesCache; |
| 33 | + $pagename = $title->getText(); //name of page w/ spaces, not underscores |
| 34 | + if(!array_key_exists('pagename', $evEditSubpagesCache) || $pagename != $evEditSubpagesCache['pagename']) { |
33 | 35 | $ns = $title->getNsText(); //namespace |
34 | 36 | if( $title->isTalkPage() ) { |
35 | 37 | $ns = $title->getTalkNsText(); |
— | — | @@ -36,9 +38,6 @@ |
37 | 39 | } else { |
38 | 40 | $nstalk = $title->getTalkNsText(); |
39 | 41 | } |
40 | | - //underscores -> spaces |
41 | | - $ns = str_replace('_', ' ', $ns); |
42 | | - $nstalk = str_replace('_', ' ', $nstalk); |
43 | 42 | if($ns == '') { |
44 | 43 | $text = $pagename; |
45 | 44 | } else { |
— | — | @@ -49,26 +48,130 @@ |
50 | 49 | } else { |
51 | 50 | $talktext = $pagename; |
52 | 51 | } |
| 52 | + //underscores -> spaces |
| 53 | + $ns = str_replace('_', ' ', $ns); |
| 54 | + $nstalk = str_replace('_', ' ', $nstalk); |
53 | 55 | $pages = explode ("\n", wfMsg ('unlockedpages')); //grabs MediaWiki:Unlockedpages |
54 | | - foreach($pages as $value) { |
| 56 | + //cache the values so future checks on the same page take less time |
| 57 | + $evEditSubpagesCache = array( |
| 58 | + 'pagename' => $pagename, |
| 59 | + 'ns' => $ns, |
| 60 | + 'nstalk' => $nstalk, |
| 61 | + 'text' => $text, |
| 62 | + 'talktext' => $talktext, |
| 63 | + 'pages' => $pages, |
| 64 | + 'loggedin' => $user->isLoggedIn(), |
| 65 | + ); |
| 66 | + } |
| 67 | + if(($action == 'edit' || $action == 'submit')){ |
| 68 | + foreach($evEditSubpagesCache['pages'] as $value) { |
55 | 69 | if( strpos( $value, '*' ) === false || strpos( $value, '*' ) !== 0 ) |
56 | 70 | continue; // "*" doesn't start the line, so treat it as a comment (aka skip over it) |
| 71 | + $flags = array( 's' => 1, 'c' => 1, 't' => 1, 'e' => 1, 'b' => 0, 'u' => 0, 'i' => 0, 'n' => 0, 'r' => 0, 'w' => 0 ); //default flags |
57 | 72 | $value = trim( trim( trim( trim( $value ), "*[]" ) ), "*[]" ); |
58 | | - if ( $value == $text || strpos( $text, $value . '/' ) === 0 ) { |
59 | | - $result = true; |
60 | | - break; |
| 73 | + /* flags |
| 74 | + * s = unlock subpages |
| 75 | + * c = allow page creation |
| 76 | + * t = unlock talk pages |
| 77 | + * e = allow editing existing pages |
| 78 | + * b = unlock base pages |
| 79 | + * u = apply restrictions to users as well |
| 80 | + * i = case insensitive |
| 81 | + * n = namespace inspecific |
| 82 | + * r = regex fragment |
| 83 | + * w = wildcard matching |
| 84 | + */ |
| 85 | + $pieces = explode('|', $value, 3); |
| 86 | + if( isset($pieces[1]) && strpos($pieces[1], '+') === 0 ) { |
| 87 | + //flag parsing |
| 88 | + $flaglist1 = explode('+', $pieces[1], 2); |
| 89 | + if(isset($flaglist1[1])) { |
| 90 | + $flaglist2 = explode('-', $flaglist1[1], 2); |
| 91 | + } else { |
| 92 | + $flaglist2 = explode('-', $pieces[1], 2); |
| 93 | + } |
| 94 | + $flagpos = str_split($flaglist2[0]); |
| 95 | + if(isset($flaglist2[1])) { |
| 96 | + $flagneg = str_split($flaglist2[1]); |
| 97 | + } else { |
| 98 | + $flagneg = array(''); |
| 99 | + } |
| 100 | + foreach($flagpos as $flag) { |
| 101 | + $flags[$flag] = 1; |
| 102 | + } |
| 103 | + foreach($flagneg as $flag) { |
| 104 | + $flags[$flag] = 0; |
| 105 | + } |
61 | 106 | } |
62 | | - $title = Title::newFromText($value); |
63 | | - if( !$title->isTalkPage() ) { |
64 | | - $talk = $title->getTalkPage(); |
65 | | - $talkpage = $talk->getPrefixedText(); |
66 | | - if($talkpage == $talktext || $talkpage == $text || strpos( $talktext, $talkpage . '/' ) === 0 || strpos( $text, $talkpage . '/' ) === 0 ) { |
67 | | - $result = true; |
68 | | - break; |
| 107 | + $found = checkPage($pieces[0], $evEditSubpagesCache['text'], $flags); |
| 108 | + if(!$found && $flags['n']) |
| 109 | + $found = checkPage($pieces[0], $evEditSubpagesCache['pagename'], $flags); |
| 110 | + if(!$found && $flags['t']) { |
| 111 | + $newtitle = Title::newFromText($pieces[0]); |
| 112 | + //make sure that it's a valid title |
| 113 | + if( $newtitle instanceOf Title && !$newtitle->isTalkPage() ) { |
| 114 | + $talk = $newtitle->getTalkPage(); |
| 115 | + $talkpage = $talk->getPrefixedText(); |
| 116 | + $found = checkPage($talkpage, $evEditSubpagesCache['talktext'], $flags); |
| 117 | + if(!$found) |
| 118 | + $found = checkPage($talkpage, $evEditSubpagesCache['text'], $flags); |
69 | 119 | } |
70 | 120 | } |
| 121 | + if(!$found) |
| 122 | + continue; |
| 123 | + |
| 124 | + if(!$flags['u'] && $evEditSubpagesCache['loggedin']) |
| 125 | + return true; |
| 126 | + //the page matches, now process it and let the software know whether or not to allow the user to do this action |
| 127 | + if(!$flags['c'] && !$newtitle->exists()) { |
| 128 | + $result = false; |
| 129 | + return false; |
| 130 | + } |
| 131 | + if(!$flags['e'] && $newtitle->exists()) { |
| 132 | + $result = false; |
| 133 | + return false; |
| 134 | + } |
| 135 | + $result = true; |
| 136 | + return false; |
71 | 137 | } |
72 | | - return false; //so internal checks cannot override |
| 138 | + if(!$evEditSubpagesCache['loggedin']) { |
| 139 | + $result = false; |
| 140 | + return false; |
| 141 | + } |
73 | 142 | } |
74 | 143 | return true; |
| 144 | +} |
| 145 | + |
| 146 | +function checkPage($page, $check, $flags) { |
| 147 | + if( $flags['w'] && !$flags['r'] ) { |
| 148 | + $flags['r'] = 1; |
| 149 | + $page = preg_quote( $page, '/' ); |
| 150 | + $page = str_replace( '\\\\', '\\', $page ); |
| 151 | + $page = str_replace( '\?', '?', $page ); |
| 152 | + $page = str_replace( '\*', '*', $page ); |
| 153 | + $page = str_replace( '\?', "\x00", $page ); |
| 154 | + $page = str_replace( '?', '.?', $page ); |
| 155 | + $page = str_replace( "\x00", '\?', $page ); |
| 156 | + $page = str_replace( '\*', "\x00", $page ); |
| 157 | + $page = str_replace( '*', '.*', $page ); |
| 158 | + $page = str_replace( "\x00", '\*', $page ); |
| 159 | + } |
| 160 | + if( $flags['r'] ) { |
| 161 | + $i = ''; |
| 162 | + if( $flags['i'] ) |
| 163 | + $i = 'i'; |
| 164 | + $page = preg_replace( '/(\\\\)?\//', '\\/', $page ); |
| 165 | + return preg_match( '/^' . $page . '$/' . $i, $check ); |
| 166 | + } |
| 167 | + if( $flags['i'] ) { |
| 168 | + $page = strtolower($page); |
| 169 | + $check = strtolower($check); |
| 170 | + } |
| 171 | + if( $page == $check ) |
| 172 | + return true; |
| 173 | + if( $flags['s'] && strpos( $check, $page . '/' ) === 0 ) |
| 174 | + return true; |
| 175 | + if( $flags['b'] && strpos( $page, $check . '/' ) === 0 ) |
| 176 | + return true; |
| 177 | + return false; |
75 | 178 | } |
\ No newline at end of file |