Metadata.php 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. <?php
  2. /**
  3. * Metadata.php -- provides DublinCore and CreativeCommons metadata
  4. * Copyright 2004, Evan Prodromou <evan@wikitravel.org>.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  19. *
  20. * @author Evan Prodromou <evan@wikitravel.org>
  21. */
  22. abstract class RdfMetaData {
  23. const RDF_TYPE_PREFS = 'application/rdf+xml,text/xml;q=0.7,application/xml;q=0.5,text/rdf;q=0.1';
  24. /**
  25. * Constructor
  26. * @param $article Article object
  27. */
  28. public function __construct( Article $article ){
  29. $this->mArticle = $article;
  30. }
  31. public abstract function show();
  32. /**
  33. *
  34. */
  35. protected function setup() {
  36. global $wgOut, $wgRequest;
  37. $httpaccept = isset( $_SERVER['HTTP_ACCEPT'] ) ? $_SERVER['HTTP_ACCEPT'] : null;
  38. $rdftype = wfNegotiateType( wfAcceptToPrefs( $httpaccept ), wfAcceptToPrefs( self::RDF_TYPE_PREFS ) );
  39. if( !$rdftype ){
  40. wfHttpError( 406, 'Not Acceptable', wfMsg( 'notacceptable' ) );
  41. return false;
  42. } else {
  43. $wgOut->disable();
  44. $wgRequest->response()->header( "Content-type: {$rdftype}; charset=utf-8" );
  45. $wgOut->sendCacheControl();
  46. return true;
  47. }
  48. }
  49. /**
  50. *
  51. */
  52. protected function reallyFullUrl() {
  53. return $this->mArticle->getTitle()->getFullURL();
  54. }
  55. protected function basics() {
  56. global $wgContLanguageCode, $wgSitename;
  57. $this->element( 'title', $this->mArticle->mTitle->getText() );
  58. $this->pageOrString( 'publisher', wfMsg( 'aboutpage' ), $wgSitename );
  59. $this->element( 'language', $wgContLanguageCode );
  60. $this->element( 'type', 'Text' );
  61. $this->element( 'format', 'text/html' );
  62. $this->element( 'identifier', $this->reallyFullUrl() );
  63. $this->element( 'date', $this->date( $this->mArticle->getTimestamp() ) );
  64. $lastEditor = User::newFromId( $this->mArticle->getUser() );
  65. $this->person( 'creator', $lastEditor );
  66. foreach( $this->mArticle->getContributors() as $user ){
  67. $this->person( 'contributor', $user );
  68. }
  69. $this->rights();
  70. }
  71. protected function element( $name, $value ) {
  72. $value = htmlspecialchars( $value );
  73. print "\t\t<dc:{$name}>{$value}</dc:{$name}>\n";
  74. }
  75. protected function date($timestamp) {
  76. return substr($timestamp, 0, 4) . '-'
  77. . substr($timestamp, 4, 2) . '-'
  78. . substr($timestamp, 6, 2);
  79. }
  80. protected function pageOrString( $name, $page, $str ){
  81. if( $page instanceof Title )
  82. $nt = $page;
  83. else
  84. $nt = Title::newFromText( $page );
  85. if( !$nt || $nt->getArticleID() == 0 ){
  86. $this->element( $name, $str );
  87. } else {
  88. $this->page( $name, $nt );
  89. }
  90. }
  91. protected function page( $name, $title ){
  92. $this->url( $name, $title->getFullUrl() );
  93. }
  94. protected function url($name, $url) {
  95. $url = htmlspecialchars( $url );
  96. print "\t\t<dc:{$name} rdf:resource=\"{$url}\" />\n";
  97. }
  98. protected function person($name, User $user ){
  99. global $wgContLang;
  100. if( $user->isAnon() ){
  101. $this->element( $name, wfMsgExt( 'anonymous', array( 'parsemag' ), 1 ) );
  102. } else if( $real = $user->getRealName() ) {
  103. $this->element( $name, $real );
  104. } else {
  105. $this->pageOrString( $name, $user->getUserPage(), wfMsg( 'siteuser', $user->getName() ) );
  106. }
  107. }
  108. /**
  109. * Takes an arg, for future enhancement with different rights for
  110. * different pages.
  111. */
  112. protected function rights() {
  113. global $wgRightsPage, $wgRightsUrl, $wgRightsText;
  114. if( $wgRightsPage && ( $nt = Title::newFromText( $wgRightsPage ) )
  115. && ($nt->getArticleID() != 0)) {
  116. $this->page('rights', $nt);
  117. } else if( $wgRightsUrl ){
  118. $this->url('rights', $wgRightsUrl);
  119. } else if( $wgRightsText ){
  120. $this->element( 'rights', $wgRightsText );
  121. }
  122. }
  123. protected function getTerms( $url ){
  124. global $wgLicenseTerms;
  125. if( $wgLicenseTerms ){
  126. return $wgLicenseTerms;
  127. } else {
  128. $known = $this->getKnownLicenses();
  129. if( isset( $known[$url] ) ) {
  130. return $known[$url];
  131. } else {
  132. return array();
  133. }
  134. }
  135. }
  136. protected function getKnownLicenses() {
  137. $ccLicenses = array('by', 'by-nd', 'by-nd-nc', 'by-nc',
  138. 'by-nc-sa', 'by-sa');
  139. $ccVersions = array('1.0', '2.0');
  140. $knownLicenses = array();
  141. foreach ($ccVersions as $version) {
  142. foreach ($ccLicenses as $license) {
  143. if( $version == '2.0' && substr( $license, 0, 2) != 'by' ) {
  144. # 2.0 dropped the non-attribs licenses
  145. continue;
  146. }
  147. $lurl = "http://creativecommons.org/licenses/{$license}/{$version}/";
  148. $knownLicenses[$lurl] = explode('-', $license);
  149. $knownLicenses[$lurl][] = 're';
  150. $knownLicenses[$lurl][] = 'di';
  151. $knownLicenses[$lurl][] = 'no';
  152. if (!in_array('nd', $knownLicenses[$lurl])) {
  153. $knownLicenses[$lurl][] = 'de';
  154. }
  155. }
  156. }
  157. /* Handle the GPL and LGPL, too. */
  158. $knownLicenses['http://creativecommons.org/licenses/GPL/2.0/'] =
  159. array('de', 're', 'di', 'no', 'sa', 'sc');
  160. $knownLicenses['http://creativecommons.org/licenses/LGPL/2.1/'] =
  161. array('de', 're', 'di', 'no', 'sa', 'sc');
  162. $knownLicenses['http://www.gnu.org/copyleft/fdl.html'] =
  163. array('de', 're', 'di', 'no', 'sa', 'sc');
  164. return $knownLicenses;
  165. }
  166. }
  167. class DublinCoreRdf extends RdfMetaData {
  168. public function show(){
  169. if( $this->setup() ){
  170. $this->prologue();
  171. $this->basics();
  172. $this->epilogue();
  173. }
  174. }
  175. /**
  176. * begin of the page
  177. */
  178. protected function prologue() {
  179. global $wgOutputEncoding;
  180. $url = htmlspecialchars( $this->reallyFullUrl() );
  181. print <<<PROLOGUE
  182. <?xml version="1.0" encoding="{$wgOutputEncoding}" ?>
  183. <!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">
  184. <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  185. xmlns:dc="http://purl.org/dc/elements/1.1/">
  186. <rdf:Description rdf:about="{$url}">
  187. PROLOGUE;
  188. }
  189. /**
  190. * end of the page
  191. */
  192. protected function epilogue() {
  193. print <<<EPILOGUE
  194. </rdf:Description>
  195. </rdf:RDF>
  196. EPILOGUE;
  197. }
  198. }
  199. class CreativeCommonsRdf extends RdfMetaData {
  200. public function show(){
  201. if( $this->setup() ){
  202. global $wgRightsUrl;
  203. $url = $this->reallyFullUrl();
  204. $this->prologue();
  205. $this->subPrologue('Work', $url);
  206. $this->basics();
  207. if( $wgRightsUrl ){
  208. $url = htmlspecialchars( $wgRightsUrl );
  209. print "\t\t<cc:license rdf:resource=\"$url\" />\n";
  210. }
  211. $this->subEpilogue('Work');
  212. if( $wgRightsUrl ){
  213. $terms = $this->getTerms( $wgRightsUrl );
  214. if( $terms ){
  215. $this->subPrologue( 'License', $wgRightsUrl );
  216. $this->license( $terms );
  217. $this->subEpilogue( 'License' );
  218. }
  219. }
  220. }
  221. $this->epilogue();
  222. }
  223. protected function prologue() {
  224. global $wgOutputEncoding;
  225. echo <<<PROLOGUE
  226. <?xml version='1.0' encoding="{$wgOutputEncoding}" ?>
  227. <rdf:RDF xmlns:cc="http://web.resource.org/cc/"
  228. xmlns:dc="http://purl.org/dc/elements/1.1/"
  229. xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
  230. PROLOGUE;
  231. }
  232. protected function subPrologue( $type, $url ){
  233. $url = htmlspecialchars( $url );
  234. echo "\t<cc:{$type} rdf:about=\"{$url}\">\n";
  235. }
  236. protected function subEpilogue($type) {
  237. echo "\t</cc:{$type}>\n";
  238. }
  239. protected function license($terms) {
  240. foreach( $terms as $term ){
  241. switch( $term ) {
  242. case 're':
  243. $this->term('permits', 'Reproduction'); break;
  244. case 'di':
  245. $this->term('permits', 'Distribution'); break;
  246. case 'de':
  247. $this->term('permits', 'DerivativeWorks'); break;
  248. case 'nc':
  249. $this->term('prohibits', 'CommercialUse'); break;
  250. case 'no':
  251. $this->term('requires', 'Notice'); break;
  252. case 'by':
  253. $this->term('requires', 'Attribution'); break;
  254. case 'sa':
  255. $this->term('requires', 'ShareAlike'); break;
  256. case 'sc':
  257. $this->term('requires', 'SourceCode'); break;
  258. }
  259. }
  260. }
  261. protected function term( $term, $name ){
  262. print "\t\t<cc:{$term} rdf:resource=\"http://web.resource.org/cc/{$name}\" />\n";
  263. }
  264. protected function epilogue() {
  265. echo "</rdf:RDF>\n";
  266. }
  267. }