Index: trunk/phase3/includes/Article.php |
— | — | @@ -660,7 +660,7 @@ |
661 | 661 | $user = $this->getUser(); |
662 | 662 | $pageId = $this->getId(); |
663 | 663 | |
664 | | - $sql = "SELECT rev_user, rev_user_text, user_real_name, MAX(rev_timestamp) as timestamp |
| 664 | + $sql = "SELECT {$userTable}.*, MAX(rev_timestamp) as timestamp |
665 | 665 | FROM $revTable LEFT JOIN $userTable ON rev_user = user_id |
666 | 666 | WHERE rev_page = $pageId |
667 | 667 | AND rev_user != $user |
— | — | @@ -672,14 +672,9 @@ |
673 | 673 | |
674 | 674 | $sql .= ' '. $this->getSelectOptions(); |
675 | 675 | |
676 | | - $res = $dbr->query($sql, __METHOD__); |
| 676 | + $res = $dbr->query($sql, __METHOD__ ); |
677 | 677 | |
678 | | - while ( $line = $dbr->fetchObject( $res ) ) { |
679 | | - $contribs[] = array($line->rev_user, $line->rev_user_text, $line->user_real_name); |
680 | | - } |
681 | | - |
682 | | - $dbr->freeResult($res); |
683 | | - return $contribs; |
| 678 | + return new UserArrayFromResult( $res ); |
684 | 679 | } |
685 | 680 | |
686 | 681 | /** |
Index: trunk/phase3/includes/Wiki.php |
— | — | @@ -458,21 +458,20 @@ |
459 | 459 | if( !$this->getVal( 'EnableDublinCoreRdf' ) ) { |
460 | 460 | wfHttpError( 403, 'Forbidden', wfMsg( 'nodublincore' ) ); |
461 | 461 | } else { |
462 | | - require_once( 'includes/Metadata.php' ); |
463 | | - wfDublinCoreRdf( $article ); |
| 462 | + $rdf = new DublinCoreRdf( $article ); |
| 463 | + $rdf->show(); |
464 | 464 | } |
465 | 465 | break; |
466 | 466 | case 'creativecommons': |
467 | 467 | if( !$this->getVal( 'EnableCreativeCommonsRdf' ) ) { |
468 | 468 | wfHttpError( 403, 'Forbidden', wfMsg( 'nocreativecommons' ) ); |
469 | 469 | } else { |
470 | | - require_once( 'includes/Metadata.php' ); |
471 | | - wfCreativeCommonsRdf( $article ); |
| 470 | + $rdf = new CreativeCommonsRdf( $article ); |
| 471 | + $rdf->show(); |
472 | 472 | } |
473 | 473 | break; |
474 | 474 | case 'credits': |
475 | | - require_once( 'includes/Credits.php' ); |
476 | | - showCreditsPage( $article ); |
| 475 | + Credits::showPage( $article ); |
477 | 476 | break; |
478 | 477 | case 'submit': |
479 | 478 | if( session_id() == '' ) { |
Index: trunk/phase3/includes/SkinTemplate.php |
— | — | @@ -370,11 +370,10 @@ |
371 | 371 | |
372 | 372 | $this->credits = false; |
373 | 373 | |
374 | | - if (isset($wgMaxCredits) && $wgMaxCredits != 0) { |
375 | | - require_once("Credits.php"); |
376 | | - $this->credits = getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax); |
| 374 | + if( $wgMaxCredits != 0 ){ |
| 375 | + $this->credits = Credits::getCredits( $wgArticle, $wgMaxCredits, $wgShowCreditsIfMax ); |
377 | 376 | } else { |
378 | | - $tpl->set('lastmod', $this->lastModified()); |
| 377 | + $tpl->set( 'lastmod', $this->lastModified() ); |
379 | 378 | } |
380 | 379 | |
381 | 380 | $tpl->setRef( 'credits', $this->credits ); |
Index: trunk/phase3/includes/Metadata.php |
— | — | @@ -20,347 +20,299 @@ |
21 | 21 | * @author Evan Prodromou <evan@wikitravel.org> |
22 | 22 | */ |
23 | 23 | |
24 | | -/** |
25 | | - * TODO: Perhaps make this file into a Metadata class, with static methods (declared |
26 | | - * as private where indicated), to move these functions out of the global namespace? |
27 | | - */ |
28 | | -define('RDF_TYPE_PREFS', "application/rdf+xml,text/xml;q=0.7,application/xml;q=0.5,text/rdf;q=0.1"); |
| 24 | +abstract class RdfMetaData { |
| 25 | + const RDF_TYPE_PREFS = 'application/rdf+xml,text/xml;q=0.7,application/xml;q=0.5,text/rdf;q=0.1'; |
29 | 26 | |
30 | | -function wfDublinCoreRdf($article) { |
31 | | - |
32 | | - $url = dcReallyFullUrl($article->mTitle); |
33 | | - |
34 | | - if (rdfSetup()) { |
35 | | - dcPrologue($url); |
36 | | - dcBasics($article); |
37 | | - dcEpilogue(); |
| 27 | + /** |
| 28 | + * Constructor |
| 29 | + * @param $article Article object |
| 30 | + */ |
| 31 | + public function __construct( Article $article ){ |
| 32 | + $this->mArticle = $article; |
38 | 33 | } |
39 | | -} |
40 | 34 | |
41 | | -function wfCreativeCommonsRdf($article) { |
| 35 | + public abstract function show(); |
42 | 36 | |
43 | | - if (rdfSetup()) { |
44 | | - global $wgRightsUrl; |
| 37 | + /** |
| 38 | + * |
| 39 | + */ |
| 40 | + protected function setup() { |
| 41 | + global $wgOut, $wgRequest; |
45 | 42 | |
46 | | - $url = dcReallyFullUrl($article->mTitle); |
| 43 | + $httpaccept = isset( $_SERVER['HTTP_ACCEPT'] ) ? $_SERVER['HTTP_ACCEPT'] : null; |
| 44 | + $rdftype = wfNegotiateType( wfAcceptToPrefs( $httpaccept ), wfAcceptToPrefs( self::RDF_TYPE_PREFS ) ); |
47 | 45 | |
48 | | - ccPrologue(); |
49 | | - ccSubPrologue('Work', $url); |
50 | | - dcBasics($article); |
51 | | - if (isset($wgRightsUrl)) { |
52 | | - $url = htmlspecialchars( $wgRightsUrl ); |
53 | | - print " <cc:license rdf:resource=\"$url\" />\n"; |
| 46 | + if( !$rdftype ){ |
| 47 | + wfHttpError( 406, 'Not Acceptable', wfMsg( 'notacceptable' ) ); |
| 48 | + return false; |
| 49 | + } else { |
| 50 | + $wgOut->disable(); |
| 51 | + $wgRequest->response()->header( "Content-type: {$rdftype}; charset=utf-8" ); |
| 52 | + $wgOut->sendCacheControl(); |
| 53 | + return true; |
54 | 54 | } |
| 55 | + } |
55 | 56 | |
56 | | - ccSubEpilogue('Work'); |
57 | | - |
58 | | - if (isset($wgRightsUrl)) { |
59 | | - $terms = ccGetTerms($wgRightsUrl); |
60 | | - if ($terms) { |
61 | | - ccSubPrologue('License', $wgRightsUrl); |
62 | | - ccLicense($terms); |
63 | | - ccSubEpilogue('License'); |
64 | | - } |
65 | | - } |
| 57 | + /** |
| 58 | + * |
| 59 | + */ |
| 60 | + protected function reallyFullUrl() { |
| 61 | + return $this->mArticle->getTitle()->getFullURL(); |
66 | 62 | } |
67 | 63 | |
68 | | - ccEpilogue(); |
69 | | -} |
| 64 | + protected function basics() { |
| 65 | + global $wgContLanguageCode, $wgSitename; |
70 | 66 | |
71 | | -/** |
72 | | - * @private |
73 | | - */ |
74 | | -function rdfSetup() { |
75 | | - global $wgOut, $_SERVER; |
| 67 | + $this->element( 'title', $this->mArticle->mTitle->getText() ); |
| 68 | + $this->pageOrString( 'publisher', wfMsg( 'aboutpage' ), $wgSitename ); |
| 69 | + $this->element( 'language', $wgContLanguageCode ); |
| 70 | + $this->element( 'type', 'Text' ); |
| 71 | + $this->element( 'format', 'text/html' ); |
| 72 | + $this->element( 'identifier', $this->reallyFullUrl() ); |
| 73 | + $this->element( 'date', $this->date( $this->mArticle->getTimestamp() ) ); |
76 | 74 | |
77 | | - $httpaccept = isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : null; |
| 75 | + $lastEditor = User::newFromId( $this->mArticle->getUser() ); |
| 76 | + $this->person( 'creator', $lastEditor ); |
78 | 77 | |
79 | | - $rdftype = wfNegotiateType(wfAcceptToPrefs($httpaccept), wfAcceptToPrefs(RDF_TYPE_PREFS)); |
| 78 | + foreach( $this->mArticle->getContributors() as $user ){ |
| 79 | + $this->person( 'contributor', $user ); |
| 80 | + } |
80 | 81 | |
81 | | - if (!$rdftype) { |
82 | | - wfHttpError(406, "Not Acceptable", wfMsg("notacceptable")); |
83 | | - return false; |
84 | | - } else { |
85 | | - $wgOut->disable(); |
86 | | - header( "Content-type: {$rdftype}; charset=utf-8" ); |
87 | | - $wgOut->sendCacheControl(); |
88 | | - return true; |
| 82 | + $this->rights(); |
89 | 83 | } |
90 | | -} |
91 | 84 | |
92 | | -/** |
93 | | - * @private |
94 | | - */ |
95 | | -function dcPrologue($url) { |
96 | | - global $wgOutputEncoding; |
| 85 | + protected function element( $name, $value ) { |
| 86 | + $value = htmlspecialchars( $value ); |
| 87 | + print "\t\t<dc:{$name}>{$value}</dc:{$name}>\n"; |
| 88 | + } |
97 | 89 | |
98 | | - $url = htmlspecialchars( $url ); |
99 | | - print "<" . "?xml version=\"1.0\" encoding=\"{$wgOutputEncoding}\" ?" . "> |
| 90 | + protected function date($timestamp) { |
| 91 | + return substr($timestamp, 0, 4) . '-' |
| 92 | + . substr($timestamp, 4, 2) . '-' |
| 93 | + . substr($timestamp, 6, 2); |
| 94 | + } |
100 | 95 | |
101 | | - <!DOCTYPE rdf:RDF PUBLIC \"-//DUBLIN CORE//DCMES DTD 2002/07/31//EN\" \"http://dublincore.org/documents/2002/07/31/dcmes-xml/dcmes-xml-dtd.dtd\"> |
| 96 | + protected function pageOrString( $name, $page, $str ){ |
| 97 | + if( $page instanceof Title ) |
| 98 | + $nt = $page; |
| 99 | + else |
| 100 | + $nt = Title::newFromText( $page ); |
102 | 101 | |
103 | | - <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" |
104 | | - xmlns:dc=\"http://purl.org/dc/elements/1.1/\"> |
105 | | - <rdf:Description rdf:about=\"$url\"> |
106 | | - "; |
107 | | -} |
| 102 | + if( !$nt || $nt->getArticleID() == 0 ){ |
| 103 | + $this->element( $name, $str ); |
| 104 | + } else { |
| 105 | + $this->page( $name, $nt ); |
| 106 | + } |
| 107 | + } |
108 | 108 | |
109 | | -/** |
110 | | - * @private |
111 | | - */ |
112 | | -function dcEpilogue() { |
113 | | - print " |
114 | | - </rdf:Description> |
115 | | - </rdf:RDF> |
116 | | - "; |
117 | | -} |
| 109 | + protected function page( $name, $title ){ |
| 110 | + $this->url( $name, $title->getFullUrl() ); |
| 111 | + } |
118 | 112 | |
119 | | -/** |
120 | | - * @private |
121 | | - */ |
122 | | -function dcBasics($article) { |
123 | | - global $wgContLanguageCode, $wgSitename; |
| 113 | + protected function url($name, $url) { |
| 114 | + $url = htmlspecialchars( $url ); |
| 115 | + print "\t\t<dc:{$name} rdf:resource=\"{$url}\" />\n"; |
| 116 | + } |
124 | 117 | |
125 | | - dcElement('title', $article->mTitle->getText()); |
126 | | - dcPageOrString('publisher', wfMsg('aboutpage'), $wgSitename); |
127 | | - dcElement('language', $wgContLanguageCode); |
128 | | - dcElement('type', 'Text'); |
129 | | - dcElement('format', 'text/html'); |
130 | | - dcElement('identifier', dcReallyFullUrl($article->mTitle)); |
131 | | - dcElement('date', dcDate($article->getTimestamp())); |
| 118 | + protected function person($name, User $user ){ |
| 119 | + global $wgContLang; |
132 | 120 | |
133 | | - $last_editor = $article->getUser(); |
| 121 | + if( $user->isAnon() ){ |
| 122 | + $this->element( $name, wfMsg( 'anonymous' ) ); |
| 123 | + } else if( $real = $user->getRealName() ) { |
| 124 | + $this->element( $name, $real ); |
| 125 | + } else { |
| 126 | + $this->pageOrString( $name, $user->getUserPage(), wfMsg( 'siteuser', $user->getName() ) ); |
| 127 | + } |
| 128 | + } |
134 | 129 | |
135 | | - if ($last_editor == 0) { |
136 | | - dcPerson('creator', 0); |
137 | | - } else { |
138 | | - dcPerson('creator', $last_editor, $article->getUserText(), |
139 | | - User::whoIsReal($last_editor)); |
| 130 | + /** |
| 131 | + * Takes an arg, for future enhancement with different rights for |
| 132 | + * different pages. |
| 133 | + */ |
| 134 | + protected function rights() { |
| 135 | + global $wgRightsPage, $wgRightsUrl, $wgRightsText; |
| 136 | + |
| 137 | + if( $wgRightsPage && ( $nt = Title::newFromText( $wgRightsPage ) ) |
| 138 | + && ($nt->getArticleID() != 0)) { |
| 139 | + $this->page('rights', $nt); |
| 140 | + } else if( $wgRightsUrl ){ |
| 141 | + $this->url('rights', $wgRightsUrl); |
| 142 | + } else if( $wgRightsText ){ |
| 143 | + $this->element( 'rights', $wgRightsText ); |
| 144 | + } |
140 | 145 | } |
141 | 146 | |
142 | | - $contributors = $article->getContributors(); |
| 147 | + protected function getTerms( $url ){ |
| 148 | + global $wgLicenseTerms; |
143 | 149 | |
144 | | - foreach ($contributors as $user_parts) { |
145 | | - dcPerson('contributor', $user_parts[0], $user_parts[1], $user_parts[2]); |
| 150 | + if( $wgLicenseTerms ){ |
| 151 | + return $wgLicenseTerms; |
| 152 | + } else { |
| 153 | + $known = $this->getKnownLicenses(); |
| 154 | + if( isset( $known[$url] ) ) { |
| 155 | + return $known[$url]; |
| 156 | + } else { |
| 157 | + return array(); |
| 158 | + } |
| 159 | + } |
146 | 160 | } |
147 | 161 | |
148 | | - dcRights(); |
149 | | -} |
| 162 | + protected function getKnownLicenses() { |
| 163 | + $ccLicenses = array('by', 'by-nd', 'by-nd-nc', 'by-nc', |
| 164 | + 'by-nc-sa', 'by-sa'); |
| 165 | + $ccVersions = array('1.0', '2.0'); |
| 166 | + $knownLicenses = array(); |
150 | 167 | |
151 | | -/** |
152 | | - * @private |
153 | | - */ |
154 | | -function ccPrologue() { |
155 | | - global $wgOutputEncoding; |
| 168 | + foreach ($ccVersions as $version) { |
| 169 | + foreach ($ccLicenses as $license) { |
| 170 | + if( $version == '2.0' && substr( $license, 0, 2) != 'by' ) { |
| 171 | + # 2.0 dropped the non-attribs licenses |
| 172 | + continue; |
| 173 | + } |
| 174 | + $lurl = "http://creativecommons.org/licenses/{$license}/{$version}/"; |
| 175 | + $knownLicenses[$lurl] = explode('-', $license); |
| 176 | + $knownLicenses[$lurl][] = 're'; |
| 177 | + $knownLicenses[$lurl][] = 'di'; |
| 178 | + $knownLicenses[$lurl][] = 'no'; |
| 179 | + if (!in_array('nd', $knownLicenses[$lurl])) { |
| 180 | + $knownLicenses[$lurl][] = 'de'; |
| 181 | + } |
| 182 | + } |
| 183 | + } |
156 | 184 | |
157 | | - echo "<" . "?xml version='1.0' encoding='{$wgOutputEncoding}' ?" . "> |
| 185 | + /* Handle the GPL and LGPL, too. */ |
158 | 186 | |
159 | | - <rdf:RDF xmlns:cc=\"http://web.resource.org/cc/\" |
160 | | - xmlns:dc=\"http://purl.org/dc/elements/1.1/\" |
161 | | - xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"> |
162 | | - "; |
163 | | -} |
| 187 | + $knownLicenses['http://creativecommons.org/licenses/GPL/2.0/'] = |
| 188 | + array('de', 're', 'di', 'no', 'sa', 'sc'); |
| 189 | + $knownLicenses['http://creativecommons.org/licenses/LGPL/2.1/'] = |
| 190 | + array('de', 're', 'di', 'no', 'sa', 'sc'); |
| 191 | + $knownLicenses['http://www.gnu.org/copyleft/fdl.html'] = |
| 192 | + array('de', 're', 'di', 'no', 'sa', 'sc'); |
164 | 193 | |
165 | | -/** |
166 | | - * @private |
167 | | - */ |
168 | | -function ccSubPrologue($type, $url) { |
169 | | - $url = htmlspecialchars( $url ); |
170 | | - echo " <cc:{$type} rdf:about=\"{$url}\">\n"; |
| 194 | + return $knownLicenses; |
| 195 | + } |
171 | 196 | } |
172 | 197 | |
173 | | -/** |
174 | | - * @private |
175 | | - */ |
176 | | -function ccSubEpilogue($type) { |
177 | | - echo " </cc:{$type}>\n"; |
178 | | -} |
| 198 | +class DublinCoreRdf extends RdfMetaData { |
179 | 199 | |
180 | | -/** |
181 | | - * @private |
182 | | - */ |
183 | | -function ccLicense($terms) { |
184 | | - |
185 | | - foreach ($terms as $term) { |
186 | | - switch ($term) { |
187 | | - case 're': |
188 | | - ccTerm('permits', 'Reproduction'); break; |
189 | | - case 'di': |
190 | | - ccTerm('permits', 'Distribution'); break; |
191 | | - case 'de': |
192 | | - ccTerm('permits', 'DerivativeWorks'); break; |
193 | | - case 'nc': |
194 | | - ccTerm('prohibits', 'CommercialUse'); break; |
195 | | - case 'no': |
196 | | - ccTerm('requires', 'Notice'); break; |
197 | | - case 'by': |
198 | | - ccTerm('requires', 'Attribution'); break; |
199 | | - case 'sa': |
200 | | - ccTerm('requires', 'ShareAlike'); break; |
201 | | - case 'sc': |
202 | | - ccTerm('requires', 'SourceCode'); break; |
| 200 | + public function show(){ |
| 201 | + if( $this->setup() ){ |
| 202 | + $this->prologue(); |
| 203 | + $this->basics(); |
| 204 | + $this->epilogue(); |
203 | 205 | } |
204 | 206 | } |
205 | | -} |
206 | 207 | |
207 | | -/** |
208 | | - * @private |
209 | | - */ |
210 | | -function ccTerm($term, $name) { |
211 | | - print " <cc:{$term} rdf:resource=\"http://web.resource.org/cc/{$name}\" />\n"; |
212 | | -} |
| 208 | + /** |
| 209 | + * begin of the page |
| 210 | + */ |
| 211 | + protected function prologue() { |
| 212 | + global $wgOutputEncoding; |
213 | 213 | |
214 | | -/** |
215 | | - * @private |
216 | | - */ |
217 | | -function ccEpilogue() { |
218 | | - echo "</rdf:RDF>\n"; |
219 | | -} |
| 214 | + $url = htmlspecialchars( $this->reallyFullUrl() ); |
| 215 | + print <<<PROLOGUE |
| 216 | +<?xml version="1.0" encoding="{$wgOutputEncoding}" ?> |
| 217 | +<!DOCTYPE rdf:RDF PUBLIC "-//DUBLIN CORE//DCMES DTD 2002/07/31//EN" "http://dublincore.org/documents/2002/07/31/dcmes-xml/dcmes-xml-dtd.dtd"> |
| 218 | +<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
| 219 | + xmlns:dc="http://purl.org/dc/elements/1.1/"> |
| 220 | + <rdf:Description rdf:about="{$url}"> |
220 | 221 | |
221 | | -/** |
222 | | - * @private |
223 | | - */ |
224 | | -function dcElement($name, $value) { |
225 | | - $value = htmlspecialchars( $value ); |
226 | | - print " <dc:{$name}>{$value}</dc:{$name}>\n"; |
227 | | -} |
| 222 | +PROLOGUE; |
| 223 | + } |
228 | 224 | |
229 | | -/** |
230 | | - * @private |
231 | | - */ |
232 | | -function dcDate($timestamp) { |
233 | | - return substr($timestamp, 0, 4) . '-' |
234 | | - . substr($timestamp, 4, 2) . '-' |
235 | | - . substr($timestamp, 6, 2); |
| 225 | + /** |
| 226 | + * end of the page |
| 227 | + */ |
| 228 | + protected function epilogue() { |
| 229 | + print <<<EPILOGUE |
| 230 | + </rdf:Description> |
| 231 | +</rdf:RDF> |
| 232 | +EPILOGUE; |
| 233 | + } |
236 | 234 | } |
237 | 235 | |
238 | | -/** |
239 | | - * @private |
240 | | - */ |
241 | | -function dcReallyFullUrl($title) { |
242 | | - return $title->getFullURL(); |
243 | | -} |
| 236 | +class CreativeCommonsRdf extends RdfMetaData { |
244 | 237 | |
245 | | -/** |
246 | | - * @private |
247 | | - */ |
248 | | -function dcPageOrString($name, $page, $str) { |
249 | | - $nt = Title::newFromText($page); |
| 238 | + public function show(){ |
| 239 | + if( $this->setup() ){ |
| 240 | + global $wgRightsUrl; |
250 | 241 | |
251 | | - if (!$nt || $nt->getArticleID() == 0) { |
252 | | - dcElement($name, $str); |
253 | | - } else { |
254 | | - dcPage($name, $nt); |
255 | | - } |
256 | | -} |
| 242 | + $url = $this->reallyFullUrl(); |
257 | 243 | |
258 | | -/** |
259 | | - * @private |
260 | | - */ |
261 | | -function dcPage($name, $title) { |
262 | | - dcUrl($name, dcReallyFullUrl($title)); |
263 | | -} |
| 244 | + $this->prologue(); |
| 245 | + $this->subPrologue('Work', $url); |
264 | 246 | |
265 | | -/** |
266 | | - * @private |
267 | | - */ |
268 | | -function dcUrl($name, $url) { |
269 | | - $url = htmlspecialchars( $url ); |
270 | | - print " <dc:{$name} rdf:resource=\"{$url}\" />\n"; |
271 | | -} |
| 247 | + $this->basics(); |
| 248 | + if( $wgRightsUrl ){ |
| 249 | + $url = htmlspecialchars( $wgRightsUrl ); |
| 250 | + print "\t\t<cc:license rdf:resource=\"$url\" />\n"; |
| 251 | + } |
272 | 252 | |
273 | | -/** |
274 | | - * @private |
275 | | - */ |
276 | | -function dcPerson($name, $id, $user_name='', $user_real_name='') { |
277 | | - global $wgContLang; |
| 253 | + $this->subEpilogue('Work'); |
278 | 254 | |
279 | | - if ($id == 0) { |
280 | | - dcElement($name, wfMsg('anonymous')); |
281 | | - } else if ( !empty($user_real_name) ) { |
282 | | - dcElement($name, $user_real_name); |
283 | | - } else { |
284 | | - # XXX: This shouldn't happen. |
285 | | - if( empty( $user_name ) ) { |
286 | | - $user_name = User::whoIs($id); |
| 255 | + if( $wgRightsUrl ){ |
| 256 | + $terms = $this->getTerms( $wgRightsUrl ); |
| 257 | + if( $terms ){ |
| 258 | + $this->subPrologue( 'License', $wgRightsUrl ); |
| 259 | + $this->license( $terms ); |
| 260 | + $this->subEpilogue( 'License' ); |
| 261 | + } |
| 262 | + } |
287 | 263 | } |
288 | | - dcPageOrString($name, $wgContLang->getNsText(NS_USER) . ':' . $user_name, wfMsg('siteuser', $user_name)); |
| 264 | + |
| 265 | + $this->epilogue(); |
289 | 266 | } |
290 | | -} |
291 | 267 | |
292 | | -/** |
293 | | - * Takes an arg, for future enhancement with different rights for |
294 | | - * different pages. |
295 | | - * @private |
296 | | - */ |
297 | | -function dcRights() { |
| 268 | + protected function prologue() { |
| 269 | + global $wgOutputEncoding; |
| 270 | + echo <<<PROLOGUE |
| 271 | +<?xml version='1.0' encoding="{$wgOutputEncoding}" ?> |
| 272 | +<rdf:RDF xmlns:cc="http://web.resource.org/cc/" |
| 273 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
| 274 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> |
298 | 275 | |
299 | | - global $wgRightsPage, $wgRightsUrl, $wgRightsText; |
| 276 | +PROLOGUE; |
| 277 | + } |
300 | 278 | |
301 | | - if (isset($wgRightsPage) && |
302 | | - ($nt = Title::newFromText($wgRightsPage)) |
303 | | - && ($nt->getArticleID() != 0)) { |
304 | | - dcPage('rights', $nt); |
305 | | - } else if (isset($wgRightsUrl)) { |
306 | | - dcUrl('rights', $wgRightsUrl); |
307 | | - } else if (isset($wgRightsText)) { |
308 | | - dcElement('rights', $wgRightsText); |
| 279 | + protected function subPrologue( $type, $url ){ |
| 280 | + $url = htmlspecialchars( $url ); |
| 281 | + echo "\t<cc:{$type} rdf:about=\"{$url}\">\n"; |
309 | 282 | } |
310 | | -} |
311 | 283 | |
312 | | -/** |
313 | | - * @private |
314 | | - */ |
315 | | -function ccGetTerms($url) { |
316 | | - global $wgLicenseTerms; |
317 | | - |
318 | | - if (isset($wgLicenseTerms)) { |
319 | | - return $wgLicenseTerms; |
320 | | - } else { |
321 | | - $known = getKnownLicenses(); |
322 | | - if( isset( $known[$url] ) ) { |
323 | | - return $known[$url]; |
324 | | - } else { |
325 | | - return array(); |
326 | | - } |
| 284 | + protected function subEpilogue($type) { |
| 285 | + echo "\t</cc:{$type}>\n"; |
327 | 286 | } |
328 | | -} |
329 | 287 | |
330 | | -/** |
331 | | - * @private |
332 | | - */ |
333 | | -function getKnownLicenses() { |
| 288 | + protected function license($terms) { |
334 | 289 | |
335 | | - $ccLicenses = array('by', 'by-nd', 'by-nd-nc', 'by-nc', |
336 | | - 'by-nc-sa', 'by-sa'); |
337 | | - $ccVersions = array('1.0', '2.0'); |
338 | | - $knownLicenses = array(); |
339 | | - |
340 | | - foreach ($ccVersions as $version) { |
341 | | - foreach ($ccLicenses as $license) { |
342 | | - if( $version == '2.0' && substr( $license, 0, 2) != 'by' ) { |
343 | | - # 2.0 dropped the non-attribs licenses |
344 | | - continue; |
| 290 | + foreach( $terms as $term ){ |
| 291 | + switch( $term ) { |
| 292 | + case 're': |
| 293 | + $this->term('permits', 'Reproduction'); break; |
| 294 | + case 'di': |
| 295 | + $this->term('permits', 'Distribution'); break; |
| 296 | + case 'de': |
| 297 | + $this->term('permits', 'DerivativeWorks'); break; |
| 298 | + case 'nc': |
| 299 | + $this->term('prohibits', 'CommercialUse'); break; |
| 300 | + case 'no': |
| 301 | + $this->term('requires', 'Notice'); break; |
| 302 | + case 'by': |
| 303 | + $this->term('requires', 'Attribution'); break; |
| 304 | + case 'sa': |
| 305 | + $this->term('requires', 'ShareAlike'); break; |
| 306 | + case 'sc': |
| 307 | + $this->term('requires', 'SourceCode'); break; |
345 | 308 | } |
346 | | - $lurl = "http://creativecommons.org/licenses/{$license}/{$version}/"; |
347 | | - $knownLicenses[$lurl] = explode('-', $license); |
348 | | - $knownLicenses[$lurl][] = 're'; |
349 | | - $knownLicenses[$lurl][] = 'di'; |
350 | | - $knownLicenses[$lurl][] = 'no'; |
351 | | - if (!in_array('nd', $knownLicenses[$lurl])) { |
352 | | - $knownLicenses[$lurl][] = 'de'; |
353 | | - } |
354 | 309 | } |
355 | 310 | } |
356 | 311 | |
357 | | - /* Handle the GPL and LGPL, too. */ |
| 312 | + protected function term( $term, $name ){ |
| 313 | + print "\t\t<cc:{$term} rdf:resource=\"http://web.resource.org/cc/{$name}\" />\n"; |
| 314 | + } |
358 | 315 | |
359 | | - $knownLicenses['http://creativecommons.org/licenses/GPL/2.0/'] = |
360 | | - array('de', 're', 'di', 'no', 'sa', 'sc'); |
361 | | - $knownLicenses['http://creativecommons.org/licenses/LGPL/2.1/'] = |
362 | | - array('de', 're', 'di', 'no', 'sa', 'sc'); |
363 | | - $knownLicenses['http://www.gnu.org/copyleft/fdl.html'] = |
364 | | - array('de', 're', 'di', 'no', 'sa', 'sc'); |
365 | | - |
366 | | - return $knownLicenses; |
367 | | -} |
| 316 | + protected function epilogue() { |
| 317 | + echo "</rdf:RDF>\n"; |
| 318 | + } |
| 319 | +} |
\ No newline at end of file |
Index: trunk/phase3/includes/Credits.php |
— | — | @@ -20,167 +20,187 @@ |
21 | 21 | * @author <evan@wikitravel.org> |
22 | 22 | */ |
23 | 23 | |
24 | | -/** |
25 | | - * This is largely cadged from PageHistory::history |
26 | | - */ |
27 | | -function showCreditsPage($article) { |
28 | | - global $wgOut; |
| 24 | +class Credits { |
29 | 25 | |
30 | | - $fname = 'showCreditsPage'; |
31 | | - |
32 | | - wfProfileIn( $fname ); |
33 | | - |
34 | | - $wgOut->setPageTitle( $article->mTitle->getPrefixedText() ); |
35 | | - $wgOut->setSubtitle( wfMsg( 'creditspage' ) ); |
36 | | - $wgOut->setArticleFlag( false ); |
37 | | - $wgOut->setArticleRelated( true ); |
38 | | - $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
39 | | - |
40 | | - if( $article->mTitle->getArticleID() == 0 ) { |
41 | | - $s = wfMsg( 'nocredits' ); |
42 | | - } else { |
43 | | - $s = getCredits($article, -1); |
44 | | - } |
45 | | - |
46 | | - $wgOut->addHTML( $s ); |
47 | | - |
48 | | - wfProfileOut( $fname ); |
49 | | -} |
50 | | - |
51 | | -function getCredits($article, $cnt, $showIfMax=true) { |
52 | | - $fname = 'getCredits'; |
53 | | - wfProfileIn( $fname ); |
54 | | - $s = ''; |
55 | | - |
56 | | - if (isset($cnt) && $cnt != 0) { |
57 | | - $s = getAuthorCredits($article); |
58 | | - if ($cnt > 1 || $cnt < 0) { |
59 | | - $s .= ' ' . getContributorCredits($article, $cnt - 1, $showIfMax); |
| 26 | + /** |
| 27 | + * This is largely cadged from PageHistory::history |
| 28 | + * @param $article Article object |
| 29 | + */ |
| 30 | + public static function showPage( Article $article ) { |
| 31 | + global $wgOut; |
| 32 | + |
| 33 | + wfProfileIn( __METHOD__ ); |
| 34 | + |
| 35 | + $wgOut->setPageTitle( $article->mTitle->getPrefixedText() ); |
| 36 | + $wgOut->setSubtitle( wfMsg( 'creditspage' ) ); |
| 37 | + $wgOut->setArticleFlag( false ); |
| 38 | + $wgOut->setArticleRelated( true ); |
| 39 | + $wgOut->setRobotPolicy( 'noindex,nofollow' ); |
| 40 | + |
| 41 | + if( $article->mTitle->getArticleID() == 0 ) { |
| 42 | + $s = wfMsg( 'nocredits' ); |
| 43 | + } else { |
| 44 | + $s = self::getCredits($article, -1 ); |
60 | 45 | } |
| 46 | + |
| 47 | + $wgOut->addHTML( $s ); |
| 48 | + |
| 49 | + wfProfileOut( __METHOD__ ); |
61 | 50 | } |
62 | 51 | |
63 | | - wfProfileOut( $fname ); |
64 | | - return $s; |
65 | | -} |
| 52 | + /** |
| 53 | + * Get a list of contributors of $article |
| 54 | + * @param $article Article object |
| 55 | + * @param $cnt Int: maximum list of contributors to show |
| 56 | + * @param $showIfMax Bool: whether to contributors if there more than $cnt |
| 57 | + * @return String: html |
| 58 | + */ |
| 59 | + public static function getCredits($article, $cnt, $showIfMax=true) { |
| 60 | + wfProfileIn( __METHOD__ ); |
| 61 | + $s = ''; |
66 | 62 | |
67 | | -/** |
68 | | - * |
69 | | - */ |
70 | | -function getAuthorCredits($article) { |
71 | | - global $wgLang, $wgAllowRealName; |
72 | | - |
73 | | - $last_author = $article->getUser(); |
74 | | - |
75 | | - if ($last_author == 0) { |
76 | | - $author_credit = wfMsg('anonymous'); |
77 | | - } else { |
78 | | - if($wgAllowRealName) { $real_name = User::whoIsReal($last_author); } |
79 | | - $user_name = User::whoIs($last_author); |
80 | | - |
81 | | - if (!empty($real_name)) { |
82 | | - $author_credit = creditLink($user_name, $real_name); |
83 | | - } else { |
84 | | - $author_credit = wfMsg('siteuser', creditLink($user_name)); |
| 63 | + if( isset( $cnt ) && $cnt != 0 ){ |
| 64 | + $s = self::getAuthor( $article ); |
| 65 | + if ($cnt > 1 || $cnt < 0) { |
| 66 | + $s .= ' ' . self::getContributors( $article, $cnt - 1, $showIfMax ); |
| 67 | + } |
85 | 68 | } |
86 | | - } |
87 | 69 | |
88 | | - $timestamp = $article->getTimestamp(); |
89 | | - if ($timestamp) { |
90 | | - $d = $wgLang->date($article->getTimestamp(), true); |
91 | | - $t = $wgLang->time($article->getTimestamp(), true); |
92 | | - } else { |
93 | | - $d = ''; |
94 | | - $t = ''; |
| 70 | + wfProfileOut( __METHOD__ ); |
| 71 | + return $s; |
95 | 72 | } |
96 | | - return wfMsg('lastmodifiedatby', $d, $t, $author_credit); |
97 | | -} |
98 | 73 | |
99 | | -/** |
100 | | - * |
101 | | - */ |
102 | | -function getContributorCredits($article, $cnt, $showIfMax) { |
| 74 | + /** |
| 75 | + * Get the last author with the last modification time |
| 76 | + * @param $article Article object |
| 77 | + */ |
| 78 | + protected static function getAuthor( Article $article ){ |
| 79 | + global $wgLang, $wgAllowRealName; |
103 | 80 | |
104 | | - global $wgLang, $wgAllowRealName; |
| 81 | + $user = User::newFromId( $article->getUser() ); |
105 | 82 | |
106 | | - $contributors = $article->getContributors(); |
107 | | - |
108 | | - $others_link = ''; |
109 | | - |
110 | | - # Hmm... too many to fit! |
111 | | - |
112 | | - if ($cnt > 0 && count($contributors) > $cnt) { |
113 | | - $others_link = creditOthersLink($article); |
114 | | - if (!$showIfMax) { |
115 | | - return wfMsg('othercontribs', $others_link); |
| 83 | + $timestamp = $article->getTimestamp(); |
| 84 | + if( $timestamp ){ |
| 85 | + $d = $wgLang->date( $article->getTimestamp(), true ); |
| 86 | + $t = $wgLang->time( $article->getTimestamp(), true ); |
116 | 87 | } else { |
117 | | - $contributors = array_slice($contributors, 0, $cnt); |
| 88 | + $d = ''; |
| 89 | + $t = ''; |
118 | 90 | } |
| 91 | + return wfMsg( 'lastmodifiedatby', $d, $t, self::userLink( $user ) ); |
119 | 92 | } |
120 | 93 | |
121 | | - $real_names = array(); |
122 | | - $user_names = array(); |
123 | | - |
124 | | - $anon = ''; |
125 | | - |
126 | | - # Sift for real versus user names |
127 | | - |
128 | | - foreach ($contributors as $user_parts) { |
129 | | - if ($user_parts[0] != 0) { |
130 | | - if ($wgAllowRealName && !empty($user_parts[2])) { |
131 | | - $real_names[] = creditLink($user_parts[1], $user_parts[2]); |
| 94 | + /** |
| 95 | + * Get a list of contributors of $article |
| 96 | + * @param $article Article object |
| 97 | + * @param $cnt Int: maximum list of contributors to show |
| 98 | + * @param $showIfMax Bool: whether to contributors if there more than $cnt |
| 99 | + * @return String: html |
| 100 | + */ |
| 101 | + protected static function getContributors( Article $article, $cnt, $showIfMax ) { |
| 102 | + global $wgLang, $wgAllowRealName; |
| 103 | + |
| 104 | + $contributors = $article->getContributors(); |
| 105 | + |
| 106 | + $others_link = ''; |
| 107 | + |
| 108 | + # Hmm... too many to fit! |
| 109 | + if( $cnt > 0 && $contributors->count() > $cnt ){ |
| 110 | + $others_link = self::othersLink( $article ); |
| 111 | + if( !$showIfMax ) |
| 112 | + return wfMsg( 'othercontribs', $others_link ); |
| 113 | + } |
| 114 | + |
| 115 | + $real_names = array(); |
| 116 | + $user_names = array(); |
| 117 | + $anon = 0; |
| 118 | + |
| 119 | + # Sift for real versus user names |
| 120 | + foreach( $contributors as $user ) { |
| 121 | + $cnt--; |
| 122 | + if( $user->isLoggedIn() ){ |
| 123 | + $link = self::link( $user ); |
| 124 | + if( $wgAllowRealName && $user->getRealName() ) |
| 125 | + $real_names[] = $link; |
| 126 | + else |
| 127 | + $user_names[] = $link; |
132 | 128 | } else { |
133 | | - $user_names[] = creditLink($user_parts[1]); |
| 129 | + $anon++; |
134 | 130 | } |
135 | | - } else { |
136 | | - $anon = wfMsg('anonymous'); |
| 131 | + if( $cnt == 0 ) break; |
137 | 132 | } |
138 | | - } |
| 133 | + |
| 134 | + # Two strings: real names, and user names |
| 135 | + $real = $wgLang->listToText( $real_names ); |
| 136 | + $user = $wgLang->listToText( $user_names ); |
| 137 | + if( $anon ) |
| 138 | + $anon = wfMsgExt( 'anonymous', array( 'parseinline' ), $anon ); |
| 139 | + |
| 140 | + # "ThisSite user(s) A, B and C" |
| 141 | + if( !empty( $user ) ){ |
| 142 | + $user = wfMsgExt( 'siteusers', array( 'parsemag' ), $user, count( $user_names ) ); |
| 143 | + } |
| 144 | + |
| 145 | + # This is the big list, all mooshed together. We sift for blank strings |
| 146 | + $fulllist = array(); |
| 147 | + foreach( array( $real, $user, $anon, $others_link ) as $s ){ |
| 148 | + if( !empty( $s ) ){ |
| 149 | + array_push( $fulllist, $s ); |
| 150 | + } |
| 151 | + } |
139 | 152 | |
140 | | - # Two strings: real names, and user names |
| 153 | + # Make the list into text... |
| 154 | + $creds = $wgLang->listToText( $fulllist ); |
141 | 155 | |
142 | | - $real = $wgLang->listToText($real_names); |
143 | | - $user = $wgLang->listToText($user_names); |
| 156 | + # "Based on work by ..." |
| 157 | + return empty( $creds ) ? '' : wfMsg( 'othercontribs', $creds ); |
| 158 | + } |
144 | 159 | |
145 | | - # "ThisSite user(s) A, B and C" |
| 160 | + /** |
| 161 | + * Get a link to $user_name page |
| 162 | + * @param $user User object |
| 163 | + * @return String: html |
| 164 | + */ |
| 165 | + protected static function link( User $user ) { |
| 166 | + global $wgUser, $wgAllowRealName; |
| 167 | + if( $wgAllowRealName ) |
| 168 | + $real = $user->getRealName(); |
| 169 | + else |
| 170 | + $real = false; |
146 | 171 | |
147 | | - if (!empty($user)) { |
148 | | - $user = wfMsgExt('siteusers', array( 'parsemag' ), array( $user, count($contributors) ) ); |
| 172 | + $skin = $wgUser->getSkin(); |
| 173 | + $page = $user->getUserPage(); |
| 174 | + |
| 175 | + return $skin->link( $page, htmlspecialchars( $real ? $real : $user->getName() ) ); |
149 | 176 | } |
150 | 177 | |
151 | | - # This is the big list, all mooshed together. We sift for blank strings |
152 | | - |
153 | | - $fulllist = array(); |
154 | | - |
155 | | - foreach (array($real, $user, $anon, $others_link) as $s) { |
156 | | - if (!empty($s)) { |
157 | | - array_push($fulllist, $s); |
| 178 | + /** |
| 179 | + * Get a link to $user_name page |
| 180 | + * @param $user_name String: user name |
| 181 | + * @param $linkText String: optional display |
| 182 | + * @return String: html |
| 183 | + */ |
| 184 | + protected static function userLink( User $user ) { |
| 185 | + global $wgUser, $wgAllowRealName; |
| 186 | + if( $user->isAnon() ){ |
| 187 | + return wfMsgExt( 'anonymous', array( 'parseinline' ), 1 ); |
| 188 | + } else { |
| 189 | + $link = self::link( $user ); |
| 190 | + if( $wgAllowRealName && $user->getRealName() ) |
| 191 | + return $link; |
| 192 | + else |
| 193 | + return wfMsgExt( 'siteuser', array( 'parseinline', 'replaceafter' ), $link ); |
158 | 194 | } |
159 | 195 | } |
160 | 196 | |
161 | | - # Make the list into text... |
162 | | - |
163 | | - $creds = $wgLang->listToText($fulllist); |
164 | | - |
165 | | - # "Based on work by ..." |
166 | | - |
167 | | - return (empty($creds)) ? '' : wfMsg('othercontribs', $creds); |
168 | | -} |
169 | | - |
170 | | -/** |
171 | | - * |
172 | | - */ |
173 | | -function creditLink($user_name, $link_text = '') { |
174 | | - global $wgUser, $wgContLang; |
175 | | - $skin = $wgUser->getSkin(); |
176 | | - return $skin->makeLink($wgContLang->getNsText(NS_USER) . ':' . $user_name, |
177 | | - htmlspecialchars( (empty($link_text)) ? $user_name : $link_text )); |
178 | | -} |
179 | | - |
180 | | -/** |
181 | | - * |
182 | | - */ |
183 | | -function creditOthersLink($article) { |
184 | | - global $wgUser; |
185 | | - $skin = $wgUser->getSkin(); |
186 | | - return $skin->makeKnownLink($article->mTitle->getPrefixedText(), wfMsg('others'), 'action=credits'); |
187 | | -} |
| 197 | + /** |
| 198 | + * Get a link to action=credits of $article page |
| 199 | + * @param $article Article object |
| 200 | + * @return String: html |
| 201 | + */ |
| 202 | + protected static function othersLink( Article $article ) { |
| 203 | + global $wgUser; |
| 204 | + $skin = $wgUser->getSkin(); |
| 205 | + return $skin->link( $article->getTitle(), wfMsgHtml( 'others' ), array(), array( 'action' => 'credits' ), array( 'known' ) ); |
| 206 | + } |
| 207 | +} |
\ No newline at end of file |
Index: trunk/phase3/includes/Skin.php |
— | — | @@ -1214,14 +1214,13 @@ |
1215 | 1215 | } |
1216 | 1216 | } |
1217 | 1217 | |
1218 | | - if (isset($wgMaxCredits) && $wgMaxCredits != 0) { |
1219 | | - require_once('Credits.php'); |
1220 | | - $s .= ' ' . getCredits($wgArticle, $wgMaxCredits, $wgShowCreditsIfMax); |
| 1218 | + if( $wgMaxCredits != 0 ){ |
| 1219 | + $s .= ' ' . Credits::getCredits( $wgArticle, $wgMaxCredits, $wgShowCreditsIfMax ); |
1221 | 1220 | } else { |
1222 | | - $s .= $this->lastModified(); |
| 1221 | + $s .= $this->lastModified(); |
1223 | 1222 | } |
1224 | 1223 | |
1225 | | - if ($wgPageShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' )) { |
| 1224 | + if( $wgPageShowWatchingUsers && $wgUser->getOption( 'shownumberswatching' ) ) { |
1226 | 1225 | $dbr = wfGetDB( DB_SLAVE ); |
1227 | 1226 | $watchlist = $dbr->tableName( 'watchlist' ); |
1228 | 1227 | $sql = "SELECT COUNT(*) AS n FROM $watchlist |