r67117 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r67116‎ | r67117 | r67118 >
Date:21:54, 30 May 2010
Author:jeroendedauw
Status:deferred
Tags:
Comment:
Split the OWLExport class to a new file in the export directory
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_Setup.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/export/SMW_OWLExport.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/specials/Export/SMW_SpecialOWLExport.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/specials/Export/SMW_SpecialOWLExport.php
@@ -9,6 +9,7 @@
1010 * @ingroup SpecialPage
1111 *
1212 * @author Markus Krötzsch
 13+ * @author Jeroen De Dauw
1314 */
1415
1516 if ( !defined( 'MEDIAWIKI' ) ) {
@@ -39,17 +40,19 @@
4041 $recursive = 0; // default, no recursion
4142 $backlinks = $smwgExportBacklinks; // default
4243
43 - // check whether we already know what to export //
44 -
45 - if ( $page == '' ) { // try to get GET parameter; simple way of calling the export
 44+ // Check whether we already know what to export.
 45+ if ( $page == '' ) {
 46+ // Try to get GET parameter; simple way of calling the export.
4647 $page = $wgRequest->getVal( 'page' );
4748 } else {
48 - // this is needed since MediaWiki 1.8, but it is wrong for 1.7
 49+ // This is needed since MediaWiki 1.8, but it is wrong for 1.7.
4950 $page = rawurldecode( $page );
5051 }
5152
52 - if ( $page == '' ) { // try to get POST list; some settings are only available via POST
 53+ if ( $page == '' ) {
 54+ // Try to get POST list; some settings are only available via POST.
5355 $pageblob = $wgRequest->getText( 'pages' );
 56+
5457 if ( $pageblob != '' ) {
5558 $pages = explode( "\n", $pageblob );
5659 }
@@ -69,45 +72,61 @@
7073 header( "Content-type: application/xml; charset=UTF-8" );
7174 }
7275
73 - if ( $wgRequest->getText( 'postform' ) == 1 ) {
74 - $postform = true; // effect: assume "no" from missing parameters generated by checkboxes
75 - } else $postform = false;
 76+ // Effect: assume "no" from missing parameters generated by checkboxes.
 77+ $postform = $wgRequest->getText( 'postform' ) == 1;
7678
7779 $rec = $wgRequest->getText( 'recursive' );
 80+
7881 if ( $rec == '' ) $rec = $wgRequest->getVal( 'recursive' );
 82+
7983 if ( ( $rec == '1' ) && ( $smwgAllowRecursiveExport || $wgUser->isAllowed( 'delete' ) ) ) {
8084 $recursive = 1; // users may be allowed to switch it on
8185 }
 86+
8287 $bl = $wgRequest->getText( 'backlinks' );
 88+
8389 if ( $bl == '' ) $bl = $wgRequest->getVal( 'backlinks' );
 90+
8491 if ( ( $bl == '1' ) && ( $wgUser->isAllowed( 'delete' ) ) ) {
8592 $backlinks = true; // admins can always switch on backlinks
8693 } elseif ( ( $bl == '0' ) || ( '' == $bl && $postform ) ) {
8794 $backlinks = false; // everybody can explicitly switch off backlinks
8895 }
 96+
8997 $date = $wgRequest->getText( 'date' );
 98+
9099 if ( $date == '' ) $date = $wgRequest->getVal( 'date' );
91100
92 - $exp = new OWLExport();
 101+ $exp = new SMWOWLExport();
 102+
93103 if ( $date != '' ) $exp->setDate( $date );
 104+
94105 $exp->printPages( $pages, $recursive, $backlinks );
 106+
95107 return;
96108 } else {
97109 $offset = $wgRequest->getVal( 'offset' );
 110+
98111 if ( isset( $offset ) ) {
99112 $wgOut->disable();
 113+
100114 ob_start();
101115 header( "Content-type: application/xml; charset=UTF-8" );
102 - $exp = new OWLExport();
 116+
 117+ $exp = new SMWOWLExport();
103118 $exp->printPageList( $offset );
 119+
104120 return;
105121 } else {
106122 $stats = $wgRequest->getVal( 'stats' );
 123+
107124 if ( isset( $stats ) ) {
108125 $wgOut->disable();
 126+
109127 ob_start();
110128 header( "Content-type: application/xml; charset=UTF-8" );
111 - $exp = new OWLExport();
 129+
 130+ $exp = new SMWOWLExport();
112131 $exp->printWikiInfo();
113132 }
114133 }
@@ -120,722 +139,23 @@
121140 '<p>' . wfMsg( 'smw_exportrdf_docu' ) . "</p>\n" .
122141 '<input type="hidden" name="postform" value="1"/>' . "\n" .
123142 '<textarea name="pages" cols="40" rows="10"></textarea><br />' . "\n";
 143+
124144 if ( $wgUser->isAllowed( 'delete' ) || $smwgAllowRecursiveExport ) {
125145 $html .= '<input type="checkbox" name="recursive" value="1" id="rec">&#160;<label for="rec">' . wfMsg( 'smw_exportrdf_recursive' ) . '</label></input><br />' . "\n";
126146 }
 147+
127148 if ( $wgUser->isAllowed( 'delete' ) || $smwgExportBacklinks ) {
128149 $html .= '<input type="checkbox" name="backlinks" value="1" default="true" id="bl">&#160;<label for="bl">' . wfMsg( 'smw_exportrdf_backlinks' ) . '</label></input><br />' . "\n";
129150 }
 151+
130152 if ( $wgUser->isAllowed( 'delete' ) || $smwgExportAll ) {
131153 $html .= '<br />';
132154 $html .= '<input type="text" name="date" value="' . date( DATE_W3C, mktime( 0, 0, 0, 1, 1, 2000 ) ) . '" id="date">&#160;<label for="ea">' . wfMsg( 'smw_exportrdf_lastdate' ) . '</label></input><br />' . "\n";
133155 }
 156+
134157 $html .= "<br /><input type=\"submit\" value=\"" . wfMsg( 'smw_exportrdf_submit' ) . "\"/>\n</form>";
 158+
135159 $wgOut->addHTML( $html );
136160 }
137161
138 -}
139 -
140 -/**
141 - * Small data object holding the bare essentials of one title.
142 - * Used to store processed and open pages for export.
143 - * @ingroup SMW
144 - */
145 -class SMWSmallTitle {
146 - public $dbkey;
147 - public $namespace; // MW namespace constant
148 - public $modifier = ''; // e.g. a unit string
149 -
150 - public function getHash() {
151 - return $this->dbkey . ' ' . $this->namespace . ' ' . $this->modifier;
152 - }
153 -}
154 -
155 -
156 -/**
157 - * Class for encapsulating the methods for RDF export.
158 - * @ingroup SMW
159 - */
160 -class OWLExport {
161 - /**#@+
162 - * @access private
163 - */
164 -
165 - const MAX_CACHE_SIZE = 5000; // do not let cache arrays get larger than this
166 - const CACHE_BACKJUMP = 500; // kill this many cached entries if limit is reached,
167 - // avoids too much array copying; <= MAX_CACHE_SIZE!
168 -
169 - /**
170 - * An array that keeps track of the elements for which we still need to
171 - * write auxilliary definitions.
172 - */
173 - private $element_queue;
174 -
175 - /**
176 - * An array that keeps track of the elements which have been exported already
177 - */
178 - private $element_done;
179 -
180 - /**
181 - * Date used to filter the export. If a page has not been changed since that
182 - * date it will not be exported
183 - */
184 - private $date;
185 -
186 - /**
187 - * Array of additional namespaces (abbreviation => URI), flushed on
188 - * closing the current namespace tag. Since we export RDF in a streamed
189 - * way, it is not always possible to embed additional namespaces into
190 - * the RDF-tag which might have been sent to the client already. But we
191 - * wait with printing the current Description so that extra namespaces
192 - * from this array can still be printed (note that you never know which
193 - * extra namespaces you encounter during export).
194 - */
195 - private $extra_namespaces;
196 -
197 - /**
198 - * Array of namespaces that have been declared globally already. Contains
199 - * entries of format 'namespace abbreviation' => true, assuming that the
200 - * same abbreviation always refers to the same URI (i.e. you cannot import
201 - * something as rdf:bla if you do not want rdf to be the standard
202 - * namespace that is already given in every RDF export).
203 - */
204 - private $global_namespaces;
205 -
206 - /**
207 - * Unprinted XML is composed from the strings $pre_ns_buffer and $post_ns_buffer.
208 - * The split between the two is such that one can append additional namespace
209 - * declarations to $pre_ns_buffer so that they affect all current elements. The
210 - * buffers are flushed during output in order to achieve "streaming" RDF export
211 - * for larger files.
212 - */
213 - private $pre_ns_buffer;
214 -
215 - /**
216 - * See documentation for OWLExport::pre_ns_buffer.
217 - */
218 - private $post_ns_buffer;
219 -
220 - /**
221 - * Boolean that is true as long as nothing was flushed yet. Indicates that
222 - * extra namespaces can still become global.
223 - */
224 - private $first_flush;
225 -
226 - /**
227 - * Integer that counts down the number of objects we still process before
228 - * doing the first flush. Aggregating some output before flushing is useful
229 - * to get more namespaces global. Flushing will only happen if $delay_flush
230 - * is 0.
231 - */
232 - private $delay_flush;
233 -
234 - /**
235 - * Constructor.
236 - */
237 - public function __construct() {
238 - $this->element_queue = array();
239 - $this->element_done = array();
240 - $this->date = '';
241 - }
242 -
243 - /**
244 - * Sets a date as a filter. Any page that has not been changed since that date
245 - * will not be exported. The date has to be a string in XML Schema format.
246 - */
247 - public function setDate( $date ) {
248 - $timeint = strtotime( $date );
249 - $stamp = date( "YmdHis", $timeint );
250 - $this->date = $stamp;
251 - }
252 -
253 - /**
254 - * This function prints all selected pages. The parameter $recursion determines
255 - * how referenced ressources are treated:
256 - * '0' : add brief declarations for each
257 - * '1' : add full descriptions for each, thus beginning real recursion (and
258 - * probably retrieving the whole wiki ...)
259 - * else: ignore them, though -1 might become a synonym for "export *all*" in the future
260 - * The parameter $backlinks determines whether or not subjects of incoming
261 - * properties are exported as well. Enables "browsable RDF."
262 - */
263 - public function printPages( $pages, $recursion = 1, $backlinks = true ) {
264 - wfProfileIn( "RDF::PrintPages" );
265 -
266 - $linkCache =& LinkCache::singleton();
267 - $this->pre_ns_buffer = '';
268 - $this->post_ns_buffer = '';
269 - $this->first_flush = true;
270 - $this->delay_flush = 10; // flush only after (fully) printing 11 objects
271 - $this->extra_namespaces = array();
272 -
273 - if ( count( $pages ) == 1 ) { // ensure that ontologies that are retrieved as linked data are not confused with their subject!
274 - $ontologyuri = SMWExporter::expandURI( '&export;' ) . '/' . urlencode( end( $pages ) );
275 - } else { // use empty URI, i.e. "location" as URI otherwise
276 - $ontologyuri = '';
277 - }
278 - $this->printHeader( $ontologyuri ); // also inits global namespaces
279 -
280 - wfProfileIn( "RDF::PrintPages::PrepareQueue" );
281 - // transform pages into queued export titles
282 - $cur_queue = array();
283 - foreach ( $pages as $page ) {
284 - $title = Title::newFromText( $page );
285 - if ( null === $title ) continue; // invalid title name given
286 - $st = new SMWSmallTitle();
287 - $st->dbkey = $title->getDBkey();
288 - $st->namespace = $title->getNamespace();
289 - $cur_queue[] = $st;
290 - }
291 - wfProfileOut( "RDF::PrintPages::PrepareQueue" );
292 -
293 - while ( count( $cur_queue ) > 0 ) {
294 - // first, print all selected pages
295 - foreach ( $cur_queue as $st ) {
296 - wfProfileIn( "RDF::PrintPages::PrintOne" );
297 - $this->printObject( $st, true, $backlinks );
298 - wfProfileOut( "RDF::PrintPages::PrintOne" );
299 - if ( $this->delay_flush > 0 ) $this->delay_flush--;
300 - }
301 - // prepare array for next iteration
302 - $cur_queue = array();
303 - if ( 1 == $recursion ) {
304 - $cur_queue = $this->element_queue + $cur_queue; // make sure the array is *dublicated* instead of copying its ref
305 - $this->element_queue = array();
306 - }
307 - $linkCache->clear();
308 - }
309 -
310 - // for pages not processed recursively, print at least basic declarations
311 - wfProfileIn( "RDF::PrintPages::Auxiliary" );
312 - $this->date = ''; // no date restriction for the rest!
313 -
314 - if ( !empty( $this->element_queue ) ) {
315 - if ( $this->pre_ns_buffer != '' ) {
316 - $this->post_ns_buffer .= "\t<!-- auxiliary definitions -->\n";
317 - } else {
318 - print "\t<!-- auxiliary definitions -->\n"; // just print this comment, so that later outputs still find the empty pre_ns_buffer!
319 - }
320 -
321 - while ( !empty( $this->element_queue ) ) {
322 - $st = array_pop( $this->element_queue );
323 - $this->printObject( $st, false, false );
324 - }
325 - }
326 -
327 - wfProfileOut( "RDF::PrintPages::Auxiliary" );
328 - $this->printFooter();
329 - $this->flushBuffers( true );
330 - wfProfileOut( "RDF::PrintPages" );
331 - }
332 -
333 - /**
334 - * This function prints RDF for *all* pages within the wiki, and for all
335 - * elements that are referred to in the exported RDF.
336 - */
337 - public function printAll( $outfile, $ns_restriction = false, $delay, $delayeach ) {
338 - global $smwgNamespacesWithSemanticLinks;
339 - $linkCache =& LinkCache::singleton();
340 -
341 - $db = & wfGetDB( DB_MASTER );
342 - $this->pre_ns_buffer = '';
343 - $this->post_ns_buffer = '';
344 - $this->first_flush = true;
345 - if ( $outfile === false ) {
346 - // $this->delay_flush = 10000; //flush only after (fully) printing 10001 objects,
347 - $this->delay_flush = - 1; // do not flush buffer at all
348 - } else {
349 - $file = fopen( $outfile, 'w' );
350 - if ( !$file ) {
351 - print "\nCannot open \"$outfile\" for writing.\n";
352 - return false;
353 - }
354 - $this->delay_flush = - 1; // never flush, we flush in another way
355 - }
356 - $this->extra_namespaces = array();
357 - $this->printHeader(); // also inits global namespaces
358 -
359 - $start = 1;
360 - $end = $db->selectField( 'page', 'max(page_id)', false, $outfile );
361 -
362 - $a_count = 0; $d_count = 0; // DEBUG
363 -
364 - $delaycount = $delayeach;
365 - for ( $id = $start; $id <= $end; $id++ ) {
366 - $title = Title::newFromID( $id );
367 - if ( ( $title === null ) || !smwfIsSemanticsProcessed( $title->getNamespace() ) ) continue;
368 - if ( !OWLExport::fitsNsRestriction( $ns_restriction, $title->getNamespace() ) ) continue;
369 - $st = new SMWSmallTitle();
370 - $st->dbkey = $title->getDBkey();
371 - $st->namespace = $title->getNamespace();
372 - $cur_queue = array( $st );
373 - $a_count++; // DEBUG
374 - $full_export = true;
375 - while ( count( $cur_queue ) > 0 ) {
376 - foreach ( $cur_queue as $st ) {
377 - wfProfileIn( "RDF::PrintAll::PrintOne" );
378 - $this->printObject( $st, $full_export, false );
379 - wfProfileOut( "RDF::PrintAll::PrintOne" );
380 - }
381 - $full_export = false; // make sure added dependencies do not pull more than needed
382 - // resolve dependencies that will otherwise not be printed
383 - $cur_queue = array();
384 - foreach ( $this->element_queue as $key => $staux ) {
385 - $taux = Title::makeTitle( $staux->namespace, $staux->dbkey );
386 - if ( !smwfIsSemanticsProcessed( $staux->namespace ) || ( $staux->modifier !== '' ) ||
387 - !OWLExport::fitsNsRestriction( $ns_restriction, $staux->namespace ) ||
388 - ( !$taux->exists() ) ) {
389 - // Note: we do not need to check the cache to guess if an element was already
390 - // printed. If so, it would not be included in the queue in the first place.
391 - $cur_queue[] = $staux;
392 -// $this->post_ns_buffer .= "<!-- Adding dependency '" . $staux->getHash() . "' -->"; //DEBUG
393 - $d_count++; // DEBUG
394 - } else {
395 - unset( $this->element_queue[$key] ); // carrying around the values we do not
396 - // want to export now is a potential memory leak
397 - }
398 - }
399 - // sleep each $delaycount for $delay ms to be nice to the server
400 - if ( ( $delaycount-- < 0 ) && ( $delayeach != 0 ) ) {
401 - usleep( $delay );
402 - $delaycount = $delayeach;
403 - }
404 - }
405 - if ( $outfile !== false ) { // flush buffer
406 - fwrite( $file, $this->post_ns_buffer );
407 - $this->post_ns_buffer = '';
408 - }
409 - $linkCache->clear();
410 - }
411 - // DEBUG:
412 - $this->post_ns_buffer .= "<!-- Processed $a_count regular articles. -->\n";
413 - $this->post_ns_buffer .= "<!-- Processed $d_count added dependencies. -->\n";
414 - $this->post_ns_buffer .= "<!-- Final cache size was " . sizeof( $this->element_done ) . ". -->\n";
415 -
416 - $this->printFooter();
417 -
418 - if ( $outfile === false ) {
419 - $this->flushBuffers( true );
420 - } else { // prepend headers to file, there is no really efficient solution (`cat(1)`) for this it seems
421 - // print head:
422 - fclose( $file );
423 - foreach ( $this->extra_namespaces as $nsshort => $nsuri ) {
424 - $this->pre_ns_buffer .= "\n\txmlns:$nsshort=\"$nsuri\"";
425 - }
426 - $full_export = file_get_contents( $outfile );
427 - $full_export = $this->pre_ns_buffer . $full_export . $this->post_ns_buffer;
428 - $file = fopen( $outfile, 'w' );
429 - fwrite( $file, $full_export );
430 - fclose( $file );
431 - }
432 - }
433 -
434 - /**
435 - * Print basic definitions a list of pages ordered by their page id.
436 - * Offset and limit refer to the count of existing pages, not to the
437 - * page id.
438 - */
439 - public function printPageList( $offset = 0, $limit = 30 ) {
440 - wfProfileIn( "RDF::PrintPageList" );
441 -
442 - $db = & wfGetDB( DB_MASTER );
443 - $this->pre_ns_buffer = '';
444 - $this->post_ns_buffer = '';
445 - $this->first_flush = true;
446 - $this->delay_flush = 10; // flush only after (fully) printing 11 objects
447 - $this->extra_namespaces = array();
448 - $this->printHeader(); // also inits global namespaces
449 - $linkCache =& LinkCache::singleton();
450 -
451 - global $smwgNamespacesWithSemanticLinks;
452 - $query = '';
453 - foreach ( $smwgNamespacesWithSemanticLinks as $ns => $enabled ) {
454 - if ( $enabled ) {
455 - if ( $query != '' ) $query .= ' OR ';
456 - $query .= 'page_namespace = ' . $db->addQuotes( $ns );
457 - }
458 - }
459 - $res = $db->select( $db->tableName( 'page' ),
460 - 'page_id,page_title,page_namespace', $query
461 - , 'SMW::RDF::PrintPageList', array( 'ORDER BY' => 'page_id ASC', 'OFFSET' => $offset, 'LIMIT' => $limit ) );
462 - $foundpages = false;
463 - while ( $row = $db->fetchObject( $res ) ) {
464 - $foundpages = true;
465 - // $t = Title::makeTitle($row->page_namespace, $row->page_title);
466 - // if ($t === null) continue;
467 - // $et = new SMWExportTitle($t, $this);
468 - $st = new SMWSmallTitle();
469 - $st->dbkey = $row->page_title;
470 - $st->namespace = $row->page_namespace;
471 - $this->printObject( $st, false, false );
472 - if ( $this->delay_flush > 0 ) $this->delay_flush--;
473 - $linkCache->clear();
474 - }
475 - if ( $foundpages ) { // add link to next result page
476 - if ( strpos( SMWExporter::expandURI( '&wikiurl;' ), '?' ) === false ) { // check whether we have title as a first parameter or in URL
477 - $nexturl = SMWExporter::expandURI( '&export;?offset=' ) . ( $offset + $limit );
478 - } else {
479 - $nexturl = SMWExporter::expandURI( '&export;&amp;offset=' ) . ( $offset + $limit );
480 - }
481 - $this->post_ns_buffer .=
482 - "\t<!-- Link to next set of results -->\n" .
483 - "\t<owl:Thing rdf:about=\"$nexturl\">\n" .
484 - "\t\t<rdfs:isDefinedBy rdf:resource=\"$nexturl\"/>\n" .
485 - "\t</owl:Thing>\n";
486 - }
487 - $this->printFooter();
488 - $this->flushBuffers( true );
489 -
490 - wfProfileOut( "RDF::PrintPageList" );
491 - }
492 -
493 -
494 - /**
495 - * Print basic information about this site.
496 - */
497 - public function printWikiInfo() {
498 - wfProfileIn( "RDF::PrintWikiInfo" );
499 - global $wgSitename, $wgLanguageCode;
500 -
501 - $db = & wfGetDB( DB_MASTER );
502 - $this->pre_ns_buffer = '';
503 - $this->post_ns_buffer = '';
504 - $this->extra_namespaces = array();
505 - $data = new SMWExpData( new SMWExpResource( '&wiki;#wiki' ) );
506 -
507 - $ed = new SMWExpData( SMWExporter::getSpecialElement( 'swivt', 'Wikisite' ) );
508 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ), $ed );
509 - $ed = new SMWExpData( new SMWExpLiteral( $wgSitename ) );
510 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdfs', 'label' ), $ed );
511 - $ed = new SMWExpData( new SMWExpLiteral( $wgSitename, null, 'http://www.w3.org/2001/XMLSchema#string' ) );
512 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'siteName' ), $ed );
513 - $ed = new SMWExpData( new SMWExpLiteral( SMWExporter::expandURI( '&wikiurl;' ), null, 'http://www.w3.org/2001/XMLSchema#string' ) );
514 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'pagePrefix' ), $ed );
515 - $ed = new SMWExpData( new SMWExpLiteral( SMW_VERSION, null, 'http://www.w3.org/2001/XMLSchema#string' ) );
516 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'smwVersion' ), $ed );
517 - $ed = new SMWExpData( new SMWExpLiteral( $wgLanguageCode, null, 'http://www.w3.org/2001/XMLSchema#string' ) );
518 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'langCode' ), $ed );
519 -
520 - // stats
521 - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::pages(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
522 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'pageCount' ), $ed );
523 - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::articles(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
524 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'contentPageCount' ), $ed );
525 - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::images(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
526 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'mediaCount' ), $ed );
527 - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::edits(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
528 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'editCount' ), $ed );
529 - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::views(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
530 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'viewCount' ), $ed );
531 - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::users(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
532 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'userCount' ), $ed );
533 - $ed = new SMWExpData( new SMWExpLiteral( SiteStats::admins(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
534 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'adminCount' ), $ed );
535 -
536 - $mainpage = Title::newMainPage();
537 - if ( $mainpage !== null ) {
538 - $ed = new SMWExpData( new SMWExpResource( $mainpage->getFullURL() ) );
539 - $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'mainPage' ), $ed );
540 - }
541 -
542 -
543 - $this->printHeader(); // also inits global namespaces
544 - $this->printExpData( $data );
545 - if ( strpos( SMWExporter::expandURI( '&wikiurl;' ), '?' ) === false ) { // check whether we have title as a first parameter or in URL
546 - $nexturl = SMWExporter::expandURI( '&export;?offset=0' );
547 - } else {
548 - $nexturl = SMWExporter::expandURI( '&export;&amp;offset=0' );
549 - }
550 - $this->post_ns_buffer .=
551 - "\t<!-- Link to semantic page list -->\n" .
552 - "\t<owl:Thing rdf:about=\"$nexturl\">\n" .
553 - "\t\t<rdfs:isDefinedBy rdf:resource=\"$nexturl\"/>\n" .
554 - "\t</owl:Thing>\n";
555 - $this->printFooter();
556 - $this->flushBuffers( true );
557 -
558 - wfProfileOut( "RDF::PrintWikiInfo" );
559 - }
560 -
561 - /* Functions for exporting RDF */
562 -
563 - protected function printHeader( $ontologyuri = '' ) {
564 - global $wgContLang;
565 -
566 - $this->pre_ns_buffer .=
567 - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
568 - "<!DOCTYPE rdf:RDF[\n" .
569 - "\t<!ENTITY rdf '" . SMWExporter::expandURI( '&rdf;' ) . "'>\n" .
570 - "\t<!ENTITY rdfs '" . SMWExporter::expandURI( '&rdfs;' ) . "'>\n" .
571 - "\t<!ENTITY owl '" . SMWExporter::expandURI( '&owl;' ) . "'>\n" .
572 - "\t<!ENTITY swivt '" . SMWExporter::expandURI( '&swivt;' ) . "'>\n" .
573 - // A note on "wiki": this namespace is crucial as a fallback when it would be illegal to start e.g. with a number. In this case, one can always use wiki:... followed by "_" and possibly some namespace, since _ is legal as a first character.
574 - "\t<!ENTITY wiki '" . SMWExporter::expandURI( '&wiki;' ) . "'>\n" .
575 - "\t<!ENTITY property '" . SMWExporter::expandURI( '&property;' ) . "'>\n" .
576 - "\t<!ENTITY wikiurl '" . SMWExporter::expandURI( '&wikiurl;' ) . "'>\n" .
577 - "]>\n\n" .
578 - "<rdf:RDF\n" .
579 - "\txmlns:rdf=\"&rdf;\"\n" .
580 - "\txmlns:rdfs=\"&rdfs;\"\n" .
581 - "\txmlns:owl =\"&owl;\"\n" .
582 - "\txmlns:swivt=\"&swivt;\"\n" .
583 - "\txmlns:wiki=\"&wiki;\"\n" .
584 - "\txmlns:property=\"&property;\"";
585 - $this->global_namespaces = array( 'rdf' => true, 'rdfs' => true, 'owl' => true, 'swivt' => true, 'wiki' => true, 'property' => true );
586 -
587 - $this->post_ns_buffer .=
588 - ">\n\t<!-- Ontology header -->\n" .
589 - "\t<owl:Ontology rdf:about=\"$ontologyuri\">\n" .
590 - "\t\t<swivt:creationDate rdf:datatype=\"http://www.w3.org/2001/XMLSchema#dateTime\">" . date( DATE_W3C ) . "</swivt:creationDate>\n" .
591 - "\t\t<owl:imports rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0\" />\n" .
592 - "\t</owl:Ontology>\n" .
593 - "\t<!-- exported page data -->\n";
594 - }
595 -
596 - /**
597 - * Prints the footer.
598 - */
599 - protected function printFooter() {
600 - $this->post_ns_buffer .= "\t<!-- Created by Semantic MediaWiki, http://semantic-mediawiki.org/ -->\n";
601 - $this->post_ns_buffer .= '</rdf:RDF>';
602 - }
603 -
604 - /**
605 - * Serialise the given semantic data.
606 - */
607 - protected function printExpData( /*SMWExpData*/ $data, $indent = '' ) {
608 - $type = $data->extractMainType()->getQName();
609 - if ( '' == $this->pre_ns_buffer ) { // start new ns block
610 - $this->pre_ns_buffer .= "\t$indent<$type";
611 - } else {
612 - $this->post_ns_buffer .= "\t$indent<$type";
613 - }
614 - if ( ( $data->getSubject() instanceof SMWExpLiteral ) || ( $data->getSubject() instanceof SMWExpResource ) ) {
615 - $this->post_ns_buffer .= ' rdf:about="' . $data->getSubject()->getName() . '"';
616 - } // else: blank node
617 - if ( count( $data->getProperties() ) == 0 ) {
618 - $this->post_ns_buffer .= " />\n";
619 - } else {
620 - $this->post_ns_buffer .= ">\n";
621 - foreach ( $data->getProperties() as $property ) {
622 - $this->queueElement( $property );
623 - foreach ( $data->getValues( $property ) as $value ) {
624 - $this->post_ns_buffer .= "\t\t$indent<" . $property->getQName();
625 - $this->addExtraNamespace( $property->getNamespaceID(), $property->getNamespace() );
626 - $object = $value->getSubject();
627 - if ( $object instanceof SMWExpLiteral ) {
628 - if ( $object->getDatatype() != '' ) {
629 - $this->post_ns_buffer .= ' rdf:datatype="' . $object->getDatatype() . '"';
630 - }
631 - $this->post_ns_buffer .= '>' .
632 - str_replace( array( '&', '>', '<' ), array( '&amp;', '&gt;', '&lt;' ), $object->getName() ) .
633 - '</' . $property->getQName() . ">\n";
634 - } else { // bnode or resource, may have subdescriptions
635 - $collection = $value->getCollection();
636 - if ( $collection != false ) {
637 - $this->post_ns_buffer .= " rdf:parseType=\"Collection\">\n";
638 - foreach ( $collection as $subvalue ) {
639 - $this->printExpData( $subvalue, $indent . "\t\t" );
640 - }
641 - $this->post_ns_buffer .= "\t\t$indent</" . $property->getQName() . ">\n";
642 - } elseif ( count( $value->getProperties() ) > 0 ) {
643 - $this->post_ns_buffer .= ">\n";
644 - $this->printExpData( $value, $indent . "\t\t" );
645 - $this->post_ns_buffer .= "\t\t$indent</" . $property->getQName() . ">\n";
646 - } else {
647 - if ( $object instanceof SMWExpResource ) {
648 - $this->post_ns_buffer .= ' rdf:resource="' . $object->getName() . '"';
649 - $this->queueElement( $object ); // queue only non-explicated resources
650 - }
651 - $this->post_ns_buffer .= "/>\n";
652 - }
653 - }
654 - }
655 - }
656 - $this->post_ns_buffer .= "\t$indent</" . $type . ">\n";
657 - }
658 - $this->flushBuffers();
659 - }
660 -
661 - /**
662 - * Print the triples associated to a specific page, and references those needed.
663 - * They get printed in the printFooter-function.
664 - *
665 - * @param $st The SMWSmallTitle wrapping the page to be exported
666 - * @param $fullexport Boolean to define whether all the data for the page should
667 - * be exported, or whether just a definition of the given title.
668 - * @param $backlinks Boolean specifying if properties linking to the exported title
669 - * should be included.
670 - */
671 - protected function printObject( /*SMWSmallTitle*/ $st, $fullexport = true, $backlinks = false ) {
672 - global $smwgMW_1_14;
673 - if ( array_key_exists( $st->getHash(), $this->element_done ) ) return; // do not export twice
674 -
675 - $value = SMWWikiPageValue::makePage( $st->dbkey, $st->namespace );
676 - if ( $this->date !== '' ) { // check date restriction if given
677 - $rev = $smwgMW_1_14 ? Revision::getTimeStampFromID( $value->getTitle(), $value->getTitle()->getLatestRevID() ):Revision::getTimeStampFromID( $value->getTitle()->getLatestRevID() );
678 - if ( $rev < $this->date ) return;
679 - }
680 -
681 - $data = SMWExporter::makeExportData( smwfGetStore()->getSemanticData( $value, $fullexport ? false:array( '__spu', '__typ', '__imp' ) ), $st->modifier );
682 - $this->printExpData( $data ); // serialise
683 - // let other extensions add additional RDF data for this page
684 - $additionalDataArray = array();
685 - wfRunHooks( 'smwAddToRDFExport', array( $value->getTitle(), &$additionalDataArray ) );
686 - foreach ( $additionalDataArray as $additionalData ) {
687 - $this->printExpData( $additionalData ); // serialise
688 - }
689 - $this->markAsDone( $st );
690 -
691 - // possibly add backlinks
692 - if ( ( $fullexport ) && ( $backlinks ) ) {
693 - wfProfileIn( "RDF::PrintPages::GetBacklinks" );
694 - $inRels = smwfGetStore()->getInProperties( $value );
695 - foreach ( $inRels as $inRel ) {
696 - $inSubs = smwfGetStore()->getPropertySubjects( $inRel, $value );
697 - foreach ( $inSubs as $inSub ) {
698 - $stb = new SMWSmallTitle();
699 - $stb->dbkey = $inSub->getDBkey();
700 - $stb->namespace = $inSub->getNamespace();
701 - if ( !array_key_exists( $stb->getHash(), $this->element_done ) ) {
702 - $semdata = smwfGetStore()->getSemanticData( $inSub, array( '__spu', '__typ', '__imp' ) );
703 - $semdata->addPropertyObjectValue( $inRel, $value );
704 - $data = SMWExporter::makeExportData( $semdata );
705 - $this->printExpData( $data );
706 - }
707 - }
708 - }
709 - if ( NS_CATEGORY === $value->getNamespace() ) { // also print elements of categories
710 - $options = new SMWRequestOptions();
711 - $options->limit = 100; /// Categories can be large, use limit
712 - $instances = smwfGetStore()->getPropertySubjects( SMWPropertyValue::makeProperty( '_INST' ), $value, $options );
713 - $pinst = SMWPropertyValue::makeProperty( '_INST' );
714 - foreach ( $instances as $instance ) {
715 - $stb = new SMWSmallTitle();
716 - $stb->dbkey = $instance->getDBkey();
717 - $stb->namespace = $instance->getNamespace();
718 - if ( !array_key_exists( $stb->getHash(), $this->element_done ) ) {
719 - $semdata = smwfGetStore()->getSemanticData( $instance, array( '__spu', '__typ', '__imp' ) );
720 - $semdata->addPropertyObjectValue( $pinst, $value );
721 - $data = SMWExporter::makeExportData( $semdata );
722 - $this->printExpData( $data );
723 - }
724 - }
725 - } elseif ( SMW_NS_CONCEPT === $value->getNamespace() ) { // print concept members (slightly different code)
726 - $desc = new SMWConceptDescription( $value->getTitle() );
727 - $desc->addPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, '' ) );
728 - $query = new SMWQuery( $desc );
729 - $query->setLimit( 100 );
730 -
731 - $res = smwfGetStore()->getQueryResult( $query );
732 - $resarray = $res->getNext();
733 - $pinst = SMWPropertyValue::makeProperty( '_INST' );
734 - while ( $resarray !== false ) {
735 - $instance = end( $resarray )->getNextObject();
736 - $stb = new SMWSmallTitle();
737 - $stb->dbkey = $instance->getDBkey();
738 - $stb->namespace = $instance->getNamespace();
739 - if ( !array_key_exists( $stb->getHash(), $this->element_done ) ) {
740 - $semdata = smwfGetStore()->getSemanticData( $instance, array( '__spu', '__typ', '__imp' ) );
741 - $semdata->addPropertyObjectValue( $pinst, $value );
742 - $data = SMWExporter::makeExportData( $semdata );
743 - $this->printExpData( $data );
744 - }
745 - $resarray = $res->getNext();
746 - }
747 - }
748 - wfProfileOut( "RDF::PrintPages::GetBacklinks" );
749 - }
750 - }
751 -
752 - /**
753 - * Flush all buffers and extra namespaces by printing them to stdout and flushing
754 - * the output buffers afterwards.
755 - *
756 - * @param force if true, the flush cannot be delayed any longer
757 - */
758 - protected function flushBuffers( $force = false ) {
759 - if ( $this->post_ns_buffer == '' ) return; // nothing to flush (every non-empty pre_ns_buffer also requires a non-empty post_ns_buffer)
760 - if ( ( 0 != $this->delay_flush ) && !$force ) return; // wait a little longer
761 -
762 - print $this->pre_ns_buffer;
763 - $this->pre_ns_buffer = '';
764 -
765 - foreach ( $this->extra_namespaces as $nsshort => $nsuri ) {
766 - if ( $this->first_flush ) {
767 - $this->global_namespaces[$nsshort] = true;
768 - print "\n\t";
769 - } else print ' ';
770 -
771 - print "xmlns:$nsshort=\"$nsuri\"";
772 - }
773 -
774 - $this->extra_namespaces = array();
775 - print $this->post_ns_buffer;
776 - $this->post_ns_buffer = '';
777 - // Ship data in small chunks (even though browsers often do not display anything
778 - // before the file is complete -- this might be due to syntax highlighting features
779 - // for app/xml). You may want to sleep(1) here for debugging this.
780 - ob_flush();
781 - flush();
782 - $this->first_flush = false;
783 - }
784 -
785 - /**
786 - * Add an extra namespace that was encountered during output. The method
787 - * checks whether the required namespace is available globally and adds
788 - * it to the list of extra_namesapce otherwise.
789 - */
790 - public function addExtraNamespace( $nsshort, $nsuri ) {
791 - if ( !array_key_exists( $nsshort, $this->global_namespaces ) ) {
792 - $this->extra_namespaces[$nsshort] = $nsuri;
793 - }
794 - }
795 -
796 - /**
797 - * Add a given SMWExpResource to the export queue if needed.
798 - */
799 - public function queueElement( $element ) {
800 - if ( !( $element instanceof SMWExpResource ) ) return; // only Resources are queued
801 - $title = $element->getDataValue();
802 - if ( $title instanceof SMWWikiPageValue ) {
803 - $spt = new SMWSmallTitle();
804 - $title = $title->getTitle();
805 - $spt->dbkey = $title->getDBkey();
806 - $spt->namespace = $title->getNamespace();
807 - $spt->modifier = $element->getModifier();
808 - if ( !array_key_exists( $spt->getHash(), $this->element_done ) ) {
809 - $this->element_queue[$spt->getHash()] = $spt;
810 - }
811 - }
812 - }
813 -
814 - /**
815 - * Mark an article as done while making sure that the cache used for this
816 - * stays reasonably small. Input is given as an SMWExportArticle object.
817 - */
818 - protected function markAsDone( $st ) {
819 - if ( count( $this->element_done ) >= OWLExport::MAX_CACHE_SIZE ) {
820 - $this->element_done = array_slice( $this->element_done,
821 - OWLExport::CACHE_BACKJUMP,
822 - OWLExport::MAX_CACHE_SIZE - OWLExport::CACHE_BACKJUMP,
823 - true );
824 - }
825 - $this->element_done[$st->getHash()] = $st; // mark title as done
826 - unset( $this->element_queue[$st->getHash()] ); // make sure it is not in the queue
827 - }
828 -
829 - /**
830 - * This function checks whether some article fits into a given namespace restriction.
831 - * FALSE means "no restriction," non-negative restictions require to check whether
832 - * the given number equals the given namespace. A restriction of -1 requires the
833 - * namespace to be different from Category:, Relation:, Attribute:, and Type:.
834 - */
835 - static public function fitsNsRestriction( $res, $ns ) {
836 - if ( $res === false ) return true;
837 - if ( is_array( $res ) ) return in_array( $ns, $res );
838 - if ( $res >= 0 ) return ( $res == $ns );
839 - return ( ( $res != NS_CATEGORY ) && ( $res != SMW_NS_PROPERTY ) && ( $res != SMW_NS_TYPE ) );
840 - }
841 -
842 -}
 162+}
\ No newline at end of file
Index: trunk/extensions/SemanticMediaWiki/includes/export/SMW_OWLExport.php
@@ -0,0 +1,813 @@
 2+<?php
 3+
 4+/**
 5+ * File holding the OWLExport class for OWL export, used by SMWSpecialOWLExport (Special:ExportRDF page).
 6+ *
 7+ * @file SMW_OWLExport.php
 8+ * @ingroup SMW
 9+ *
 10+ * @author Markus Krötzsch
 11+ */
 12+
 13+/**
 14+ * Small data object holding the bare essentials of one title.
 15+ * Used to store processed and open pages for export.
 16+ *
 17+ * @ingroup SMW
 18+ */
 19+class SMWSmallTitle {
 20+ public $dbkey;
 21+ public $namespace; // MW namespace constant
 22+ public $modifier = ''; // e.g. a unit string
 23+
 24+ public function getHash() {
 25+ return $this->dbkey . ' ' . $this->namespace . ' ' . $this->modifier;
 26+ }
 27+}
 28+
 29+
 30+/**
 31+ * Class for encapsulating the methods for RDF export.
 32+ *
 33+ * @ingroup SMW
 34+ */
 35+class SMWOWLExport {
 36+ /**#@+
 37+ * @access private
 38+ */
 39+
 40+ const MAX_CACHE_SIZE = 5000; // do not let cache arrays get larger than this
 41+ const CACHE_BACKJUMP = 500; // kill this many cached entries if limit is reached,
 42+ // avoids too much array copying; <= MAX_CACHE_SIZE!
 43+
 44+ /**
 45+ * An array that keeps track of the elements for which we still need to
 46+ * write auxilliary definitions.
 47+ */
 48+ private $element_queue;
 49+
 50+ /**
 51+ * An array that keeps track of the elements which have been exported already
 52+ */
 53+ private $element_done;
 54+
 55+ /**
 56+ * Date used to filter the export. If a page has not been changed since that
 57+ * date it will not be exported
 58+ */
 59+ private $date;
 60+
 61+ /**
 62+ * Array of additional namespaces (abbreviation => URI), flushed on
 63+ * closing the current namespace tag. Since we export RDF in a streamed
 64+ * way, it is not always possible to embed additional namespaces into
 65+ * the RDF-tag which might have been sent to the client already. But we
 66+ * wait with printing the current Description so that extra namespaces
 67+ * from this array can still be printed (note that you never know which
 68+ * extra namespaces you encounter during export).
 69+ */
 70+ private $extra_namespaces;
 71+
 72+ /**
 73+ * Array of namespaces that have been declared globally already. Contains
 74+ * entries of format 'namespace abbreviation' => true, assuming that the
 75+ * same abbreviation always refers to the same URI (i.e. you cannot import
 76+ * something as rdf:bla if you do not want rdf to be the standard
 77+ * namespace that is already given in every RDF export).
 78+ */
 79+ private $global_namespaces;
 80+
 81+ /**
 82+ * Unprinted XML is composed from the strings $pre_ns_buffer and $post_ns_buffer.
 83+ * The split between the two is such that one can append additional namespace
 84+ * declarations to $pre_ns_buffer so that they affect all current elements. The
 85+ * buffers are flushed during output in order to achieve "streaming" RDF export
 86+ * for larger files.
 87+ */
 88+ private $pre_ns_buffer;
 89+
 90+ /**
 91+ * See documentation for SMWOWLExport::pre_ns_buffer.
 92+ */
 93+ private $post_ns_buffer;
 94+
 95+ /**
 96+ * Boolean that is true as long as nothing was flushed yet. Indicates that
 97+ * extra namespaces can still become global.
 98+ */
 99+ private $first_flush;
 100+
 101+ /**
 102+ * Integer that counts down the number of objects we still process before
 103+ * doing the first flush. Aggregating some output before flushing is useful
 104+ * to get more namespaces global. Flushing will only happen if $delay_flush
 105+ * is 0.
 106+ */
 107+ private $delay_flush;
 108+
 109+ /**
 110+ * Constructor.
 111+ */
 112+ public function __construct() {
 113+ $this->element_queue = array();
 114+ $this->element_done = array();
 115+ $this->date = '';
 116+ }
 117+
 118+ /**
 119+ * Sets a date as a filter. Any page that has not been changed since that date
 120+ * will not be exported. The date has to be a string in XML Schema format.
 121+ */
 122+ public function setDate( $date ) {
 123+ $timeint = strtotime( $date );
 124+ $stamp = date( "YmdHis", $timeint );
 125+ $this->date = $stamp;
 126+ }
 127+
 128+ /**
 129+ * This function prints all selected pages. The parameter $recursion determines
 130+ * how referenced ressources are treated:
 131+ * '0' : add brief declarations for each
 132+ * '1' : add full descriptions for each, thus beginning real recursion (and
 133+ * probably retrieving the whole wiki ...)
 134+ * else: ignore them, though -1 might become a synonym for "export *all*" in the future
 135+ * The parameter $backlinks determines whether or not subjects of incoming
 136+ * properties are exported as well. Enables "browsable RDF."
 137+ */
 138+ public function printPages( $pages, $recursion = 1, $backlinks = true ) {
 139+ wfProfileIn( "RDF::PrintPages" );
 140+
 141+ $linkCache =& LinkCache::singleton();
 142+ $this->pre_ns_buffer = '';
 143+ $this->post_ns_buffer = '';
 144+ $this->first_flush = true;
 145+ $this->delay_flush = 10; // flush only after (fully) printing 11 objects
 146+ $this->extra_namespaces = array();
 147+
 148+ if ( count( $pages ) == 1 ) { // ensure that ontologies that are retrieved as linked data are not confused with their subject!
 149+ $ontologyuri = SMWExporter::expandURI( '&export;' ) . '/' . urlencode( end( $pages ) );
 150+ } else { // use empty URI, i.e. "location" as URI otherwise
 151+ $ontologyuri = '';
 152+ }
 153+
 154+ $this->printHeader( $ontologyuri ); // also inits global namespaces
 155+
 156+ wfProfileIn( "RDF::PrintPages::PrepareQueue" );
 157+
 158+ // transform pages into queued export titles
 159+ $cur_queue = array();
 160+
 161+ foreach ( $pages as $page ) {
 162+ $title = Title::newFromText( $page );
 163+
 164+ if ( null === $title ) continue; // invalid title name given
 165+
 166+ $st = new SMWSmallTitle();
 167+ $st->dbkey = $title->getDBkey();
 168+ $st->namespace = $title->getNamespace();
 169+
 170+ $cur_queue[] = $st;
 171+ }
 172+
 173+ wfProfileOut( "RDF::PrintPages::PrepareQueue" );
 174+
 175+ while ( count( $cur_queue ) > 0 ) {
 176+ // first, print all selected pages
 177+ foreach ( $cur_queue as $st ) {
 178+ wfProfileIn( "RDF::PrintPages::PrintOne" );
 179+
 180+ $this->printObject( $st, true, $backlinks );
 181+
 182+ wfProfileOut( "RDF::PrintPages::PrintOne" );
 183+
 184+ if ( $this->delay_flush > 0 ) $this->delay_flush--;
 185+ }
 186+
 187+ // prepare array for next iteration
 188+ $cur_queue = array();
 189+
 190+ if ( 1 == $recursion ) {
 191+ $cur_queue = $this->element_queue + $cur_queue; // make sure the array is *dublicated* instead of copying its ref
 192+ $this->element_queue = array();
 193+ }
 194+
 195+ $linkCache->clear();
 196+ }
 197+
 198+ // for pages not processed recursively, print at least basic declarations
 199+ wfProfileIn( "RDF::PrintPages::Auxiliary" );
 200+ $this->date = ''; // no date restriction for the rest!
 201+
 202+ if ( !empty( $this->element_queue ) ) {
 203+ if ( $this->pre_ns_buffer != '' ) {
 204+ $this->post_ns_buffer .= "\t<!-- auxiliary definitions -->\n";
 205+ } else {
 206+ print "\t<!-- auxiliary definitions -->\n"; // just print this comment, so that later outputs still find the empty pre_ns_buffer!
 207+ }
 208+
 209+ while ( !empty( $this->element_queue ) ) {
 210+ $st = array_pop( $this->element_queue );
 211+ $this->printObject( $st, false, false );
 212+ }
 213+ }
 214+
 215+ wfProfileOut( "RDF::PrintPages::Auxiliary" );
 216+
 217+ $this->printFooter();
 218+ $this->flushBuffers( true );
 219+
 220+ wfProfileOut( "RDF::PrintPages" );
 221+ }
 222+
 223+ /**
 224+ * This function prints RDF for *all* pages within the wiki, and for all
 225+ * elements that are referred to in the exported RDF.
 226+ */
 227+ public function printAll( $outfile, $ns_restriction = false, $delay, $delayeach ) {
 228+ global $smwgNamespacesWithSemanticLinks;
 229+
 230+ $linkCache =& LinkCache::singleton();
 231+
 232+ $db = & wfGetDB( DB_MASTER );
 233+ $this->pre_ns_buffer = '';
 234+ $this->post_ns_buffer = '';
 235+ $this->first_flush = true;
 236+
 237+ if ( $outfile === false ) {
 238+ // $this->delay_flush = 10000; //flush only after (fully) printing 10001 objects,
 239+ $this->delay_flush = - 1; // do not flush buffer at all
 240+ } else {
 241+ $file = fopen( $outfile, 'w' );
 242+
 243+ if ( !$file ) {
 244+ print "\nCannot open \"$outfile\" for writing.\n";
 245+ return false;
 246+ }
 247+
 248+ $this->delay_flush = - 1; // never flush, we flush in another way
 249+ }
 250+
 251+ $this->extra_namespaces = array();
 252+ $this->printHeader(); // also inits global namespaces
 253+
 254+ $start = 1;
 255+ $end = $db->selectField( 'page', 'max(page_id)', false, $outfile );
 256+
 257+ $a_count = 0; $d_count = 0; // DEBUG
 258+
 259+ $delaycount = $delayeach;
 260+
 261+ for ( $id = $start; $id <= $end; $id++ ) {
 262+ $title = Title::newFromID( $id );
 263+
 264+ if ( ( $title === null ) || !smwfIsSemanticsProcessed( $title->getNamespace() ) ) continue;
 265+ if ( !OWLExport::fitsNsRestriction( $ns_restriction, $title->getNamespace() ) ) continue;
 266+
 267+ $st = new SMWSmallTitle();
 268+ $st->dbkey = $title->getDBkey();
 269+ $st->namespace = $title->getNamespace();
 270+
 271+ $cur_queue = array( $st );
 272+ $a_count++; // DEBUG
 273+ $full_export = true;
 274+
 275+ while ( count( $cur_queue ) > 0 ) {
 276+ foreach ( $cur_queue as $st ) {
 277+ wfProfileIn( "RDF::PrintAll::PrintOne" );
 278+ $this->printObject( $st, $full_export, false );
 279+ wfProfileOut( "RDF::PrintAll::PrintOne" );
 280+ }
 281+
 282+ $full_export = false; // make sure added dependencies do not pull more than needed
 283+ // resolve dependencies that will otherwise not be printed
 284+ $cur_queue = array();
 285+
 286+ foreach ( $this->element_queue as $key => $staux ) {
 287+ $taux = Title::makeTitle( $staux->namespace, $staux->dbkey );
 288+
 289+ if ( !smwfIsSemanticsProcessed( $staux->namespace ) || ( $staux->modifier !== '' ) ||
 290+ !OWLExport::fitsNsRestriction( $ns_restriction, $staux->namespace ) ||
 291+ ( !$taux->exists() ) ) {
 292+ // Note: we do not need to check the cache to guess if an element was already
 293+ // printed. If so, it would not be included in the queue in the first place.
 294+ $cur_queue[] = $staux;
 295+ // $this->post_ns_buffer .= "<!-- Adding dependency '" . $staux->getHash() . "' -->"; //DEBUG
 296+ $d_count++; // DEBUG
 297+ } else {
 298+ unset( $this->element_queue[$key] ); // carrying around the values we do not
 299+ // want to export now is a potential memory leak
 300+ }
 301+ }
 302+
 303+ // sleep each $delaycount for $delay ms to be nice to the server
 304+ if ( ( $delaycount-- < 0 ) && ( $delayeach != 0 ) ) {
 305+ usleep( $delay );
 306+ $delaycount = $delayeach;
 307+ }
 308+ }
 309+
 310+ if ( $outfile !== false ) { // flush buffer
 311+ fwrite( $file, $this->post_ns_buffer );
 312+ $this->post_ns_buffer = '';
 313+ }
 314+
 315+ $linkCache->clear();
 316+ }
 317+
 318+ // DEBUG:
 319+ $this->post_ns_buffer .= "<!-- Processed $a_count regular articles. -->\n";
 320+ $this->post_ns_buffer .= "<!-- Processed $d_count added dependencies. -->\n";
 321+ $this->post_ns_buffer .= "<!-- Final cache size was " . sizeof( $this->element_done ) . ". -->\n";
 322+
 323+ $this->printFooter();
 324+
 325+ if ( $outfile === false ) {
 326+ $this->flushBuffers( true );
 327+ } else { // prepend headers to file, there is no really efficient solution (`cat(1)`) for this it seems
 328+ // print head:
 329+ fclose( $file );
 330+
 331+ foreach ( $this->extra_namespaces as $nsshort => $nsuri ) {
 332+ $this->pre_ns_buffer .= "\n\txmlns:$nsshort=\"$nsuri\"";
 333+ }
 334+
 335+ $full_export = file_get_contents( $outfile );
 336+ $full_export = $this->pre_ns_buffer . $full_export . $this->post_ns_buffer;
 337+
 338+ $file = fopen( $outfile, 'w' );
 339+ fwrite( $file, $full_export );
 340+ fclose( $file );
 341+ }
 342+ }
 343+
 344+ /**
 345+ * Print basic definitions a list of pages ordered by their page id.
 346+ * Offset and limit refer to the count of existing pages, not to the
 347+ * page id.
 348+ */
 349+ public function printPageList( $offset = 0, $limit = 30 ) {
 350+ wfProfileIn( "RDF::PrintPageList" );
 351+
 352+ $db = & wfGetDB( DB_MASTER );
 353+ $this->pre_ns_buffer = '';
 354+ $this->post_ns_buffer = '';
 355+ $this->first_flush = true;
 356+ $this->delay_flush = 10; // flush only after (fully) printing 11 objects
 357+ $this->extra_namespaces = array();
 358+ $this->printHeader(); // also inits global namespaces
 359+ $linkCache =& LinkCache::singleton();
 360+
 361+ global $smwgNamespacesWithSemanticLinks;
 362+ $query = '';
 363+
 364+ foreach ( $smwgNamespacesWithSemanticLinks as $ns => $enabled ) {
 365+ if ( $enabled ) {
 366+ if ( $query != '' ) $query .= ' OR ';
 367+ $query .= 'page_namespace = ' . $db->addQuotes( $ns );
 368+ }
 369+ }
 370+
 371+ $res = $db->select( $db->tableName( 'page' ),
 372+ 'page_id,page_title,page_namespace', $query
 373+ , 'SMW::RDF::PrintPageList', array( 'ORDER BY' => 'page_id ASC', 'OFFSET' => $offset, 'LIMIT' => $limit ) );
 374+ $foundpages = false;
 375+
 376+ while ( $row = $db->fetchObject( $res ) ) {
 377+ $foundpages = true;
 378+ // $t = Title::makeTitle($row->page_namespace, $row->page_title);
 379+ // if ($t === null) continue;
 380+ // $et = new SMWExportTitle($t, $this);
 381+ $st = new SMWSmallTitle();
 382+
 383+ $st->dbkey = $row->page_title;
 384+ $st->namespace = $row->page_namespace;
 385+
 386+ $this->printObject( $st, false, false );
 387+
 388+ if ( $this->delay_flush > 0 ) $this->delay_flush--;
 389+
 390+ $linkCache->clear();
 391+ }
 392+ if ( $foundpages ) { // add link to next result page
 393+ if ( strpos( SMWExporter::expandURI( '&wikiurl;' ), '?' ) === false ) { // check whether we have title as a first parameter or in URL
 394+ $nexturl = SMWExporter::expandURI( '&export;?offset=' ) . ( $offset + $limit );
 395+ } else {
 396+ $nexturl = SMWExporter::expandURI( '&export;&amp;offset=' ) . ( $offset + $limit );
 397+ }
 398+
 399+ $this->post_ns_buffer .=
 400+ "\t<!-- Link to next set of results -->\n" .
 401+ "\t<owl:Thing rdf:about=\"$nexturl\">\n" .
 402+ "\t\t<rdfs:isDefinedBy rdf:resource=\"$nexturl\"/>\n" .
 403+ "\t</owl:Thing>\n";
 404+ }
 405+
 406+ $this->printFooter();
 407+ $this->flushBuffers( true );
 408+
 409+ wfProfileOut( "RDF::PrintPageList" );
 410+ }
 411+
 412+
 413+ /**
 414+ * Print basic information about this site.
 415+ */
 416+ public function printWikiInfo() {
 417+ wfProfileIn( "RDF::PrintWikiInfo" );
 418+
 419+ global $wgSitename, $wgLanguageCode;
 420+
 421+ $db = & wfGetDB( DB_MASTER );
 422+ $this->pre_ns_buffer = '';
 423+ $this->post_ns_buffer = '';
 424+ $this->extra_namespaces = array();
 425+ $data = new SMWExpData( new SMWExpResource( '&wiki;#wiki' ) );
 426+
 427+ $ed = new SMWExpData( SMWExporter::getSpecialElement( 'swivt', 'Wikisite' ) );
 428+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ), $ed );
 429+
 430+ $ed = new SMWExpData( new SMWExpLiteral( $wgSitename ) );
 431+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdfs', 'label' ), $ed );
 432+
 433+ $ed = new SMWExpData( new SMWExpLiteral( $wgSitename, null, 'http://www.w3.org/2001/XMLSchema#string' ) );
 434+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'siteName' ), $ed );
 435+
 436+ $ed = new SMWExpData( new SMWExpLiteral( SMWExporter::expandURI( '&wikiurl;' ), null, 'http://www.w3.org/2001/XMLSchema#string' ) );
 437+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'pagePrefix' ), $ed );
 438+
 439+ $ed = new SMWExpData( new SMWExpLiteral( SMW_VERSION, null, 'http://www.w3.org/2001/XMLSchema#string' ) );
 440+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'smwVersion' ), $ed );
 441+
 442+ $ed = new SMWExpData( new SMWExpLiteral( $wgLanguageCode, null, 'http://www.w3.org/2001/XMLSchema#string' ) );
 443+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'langCode' ), $ed );
 444+
 445+ // stats
 446+ $ed = new SMWExpData( new SMWExpLiteral( SiteStats::pages(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
 447+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'pageCount' ), $ed );
 448+
 449+ $ed = new SMWExpData( new SMWExpLiteral( SiteStats::articles(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
 450+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'contentPageCount' ), $ed );
 451+
 452+ $ed = new SMWExpData( new SMWExpLiteral( SiteStats::images(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
 453+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'mediaCount' ), $ed );
 454+
 455+ $ed = new SMWExpData( new SMWExpLiteral( SiteStats::edits(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
 456+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'editCount' ), $ed );
 457+
 458+ $ed = new SMWExpData( new SMWExpLiteral( SiteStats::views(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
 459+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'viewCount' ), $ed );
 460+
 461+ $ed = new SMWExpData( new SMWExpLiteral( SiteStats::users(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
 462+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'userCount' ), $ed );
 463+
 464+ $ed = new SMWExpData( new SMWExpLiteral( SiteStats::admins(), null, 'http://www.w3.org/2001/XMLSchema#int' ) );
 465+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'adminCount' ), $ed );
 466+
 467+ $mainpage = Title::newMainPage();
 468+
 469+ if ( $mainpage !== null ) {
 470+ $ed = new SMWExpData( new SMWExpResource( $mainpage->getFullURL() ) );
 471+ $data->addPropertyObjectValue( SMWExporter::getSpecialElement( 'swivt', 'mainPage' ), $ed );
 472+ }
 473+
 474+ $this->printHeader(); // also inits global namespaces
 475+ $this->printExpData( $data );
 476+
 477+ if ( strpos( SMWExporter::expandURI( '&wikiurl;' ), '?' ) === false ) { // check whether we have title as a first parameter or in URL
 478+ $nexturl = SMWExporter::expandURI( '&export;?offset=0' );
 479+ } else {
 480+ $nexturl = SMWExporter::expandURI( '&export;&amp;offset=0' );
 481+ }
 482+
 483+ $this->post_ns_buffer .=
 484+ "\t<!-- Link to semantic page list -->\n" .
 485+ "\t<owl:Thing rdf:about=\"$nexturl\">\n" .
 486+ "\t\t<rdfs:isDefinedBy rdf:resource=\"$nexturl\"/>\n" .
 487+ "\t</owl:Thing>\n";
 488+
 489+ $this->printFooter();
 490+ $this->flushBuffers( true );
 491+
 492+ wfProfileOut( "RDF::PrintWikiInfo" );
 493+ }
 494+
 495+ /* Functions for exporting RDF */
 496+
 497+ protected function printHeader( $ontologyuri = '' ) {
 498+ global $wgContLang;
 499+
 500+ $this->pre_ns_buffer .=
 501+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" .
 502+ "<!DOCTYPE rdf:RDF[\n" .
 503+ "\t<!ENTITY rdf '" . SMWExporter::expandURI( '&rdf;' ) . "'>\n" .
 504+ "\t<!ENTITY rdfs '" . SMWExporter::expandURI( '&rdfs;' ) . "'>\n" .
 505+ "\t<!ENTITY owl '" . SMWExporter::expandURI( '&owl;' ) . "'>\n" .
 506+ "\t<!ENTITY swivt '" . SMWExporter::expandURI( '&swivt;' ) . "'>\n" .
 507+ // A note on "wiki": this namespace is crucial as a fallback when it would be illegal to start e.g. with a number. In this case, one can always use wiki:... followed by "_" and possibly some namespace, since _ is legal as a first character.
 508+ "\t<!ENTITY wiki '" . SMWExporter::expandURI( '&wiki;' ) . "'>\n" .
 509+ "\t<!ENTITY property '" . SMWExporter::expandURI( '&property;' ) . "'>\n" .
 510+ "\t<!ENTITY wikiurl '" . SMWExporter::expandURI( '&wikiurl;' ) . "'>\n" .
 511+ "]>\n\n" .
 512+ "<rdf:RDF\n" .
 513+ "\txmlns:rdf=\"&rdf;\"\n" .
 514+ "\txmlns:rdfs=\"&rdfs;\"\n" .
 515+ "\txmlns:owl =\"&owl;\"\n" .
 516+ "\txmlns:swivt=\"&swivt;\"\n" .
 517+ "\txmlns:wiki=\"&wiki;\"\n" .
 518+ "\txmlns:property=\"&property;\"";
 519+ $this->global_namespaces = array( 'rdf' => true, 'rdfs' => true, 'owl' => true, 'swivt' => true, 'wiki' => true, 'property' => true );
 520+
 521+ $this->post_ns_buffer .=
 522+ ">\n\t<!-- Ontology header -->\n" .
 523+ "\t<owl:Ontology rdf:about=\"$ontologyuri\">\n" .
 524+ "\t\t<swivt:creationDate rdf:datatype=\"http://www.w3.org/2001/XMLSchema#dateTime\">" . date( DATE_W3C ) . "</swivt:creationDate>\n" .
 525+ "\t\t<owl:imports rdf:resource=\"http://semantic-mediawiki.org/swivt/1.0\" />\n" .
 526+ "\t</owl:Ontology>\n" .
 527+ "\t<!-- exported page data -->\n";
 528+ }
 529+
 530+ /**
 531+ * Prints the footer.
 532+ */
 533+ protected function printFooter() {
 534+ $this->post_ns_buffer .= "\t<!-- Created by Semantic MediaWiki, http://semantic-mediawiki.org/ -->\n";
 535+ $this->post_ns_buffer .= '</rdf:RDF>';
 536+ }
 537+
 538+ /**
 539+ * Serialise the given semantic data.
 540+ */
 541+ protected function printExpData( /*SMWExpData*/ $data, $indent = '' ) {
 542+ $type = $data->extractMainType()->getQName();
 543+
 544+ if ( '' == $this->pre_ns_buffer ) { // start new ns block
 545+ $this->pre_ns_buffer .= "\t$indent<$type";
 546+ } else {
 547+ $this->post_ns_buffer .= "\t$indent<$type";
 548+ }
 549+
 550+ if ( ( $data->getSubject() instanceof SMWExpLiteral ) || ( $data->getSubject() instanceof SMWExpResource ) ) {
 551+ $this->post_ns_buffer .= ' rdf:about="' . $data->getSubject()->getName() . '"';
 552+ } // else: blank node
 553+
 554+ if ( count( $data->getProperties() ) == 0 ) {
 555+ $this->post_ns_buffer .= " />\n";
 556+ } else {
 557+ $this->post_ns_buffer .= ">\n";
 558+
 559+ foreach ( $data->getProperties() as $property ) {
 560+ $this->queueElement( $property );
 561+
 562+ foreach ( $data->getValues( $property ) as $value ) {
 563+ $this->post_ns_buffer .= "\t\t$indent<" . $property->getQName();
 564+ $this->addExtraNamespace( $property->getNamespaceID(), $property->getNamespace() );
 565+ $object = $value->getSubject();
 566+
 567+ if ( $object instanceof SMWExpLiteral ) {
 568+ if ( $object->getDatatype() != '' ) {
 569+ $this->post_ns_buffer .= ' rdf:datatype="' . $object->getDatatype() . '"';
 570+ }
 571+
 572+ $this->post_ns_buffer .= '>' .
 573+ str_replace( array( '&', '>', '<' ), array( '&amp;', '&gt;', '&lt;' ), $object->getName() ) .
 574+ '</' . $property->getQName() . ">\n";
 575+ } else { // bnode or resource, may have subdescriptions
 576+ $collection = $value->getCollection();
 577+
 578+ if ( $collection != false ) {
 579+ $this->post_ns_buffer .= " rdf:parseType=\"Collection\">\n";
 580+
 581+ foreach ( $collection as $subvalue ) {
 582+ $this->printExpData( $subvalue, $indent . "\t\t" );
 583+ }
 584+
 585+ $this->post_ns_buffer .= "\t\t$indent</" . $property->getQName() . ">\n";
 586+ } elseif ( count( $value->getProperties() ) > 0 ) {
 587+ $this->post_ns_buffer .= ">\n";
 588+ $this->printExpData( $value, $indent . "\t\t" );
 589+ $this->post_ns_buffer .= "\t\t$indent</" . $property->getQName() . ">\n";
 590+ } else {
 591+ if ( $object instanceof SMWExpResource ) {
 592+ $this->post_ns_buffer .= ' rdf:resource="' . $object->getName() . '"';
 593+ $this->queueElement( $object ); // queue only non-explicated resources
 594+ }
 595+
 596+ $this->post_ns_buffer .= "/>\n";
 597+ }
 598+ }
 599+ }
 600+ }
 601+
 602+ $this->post_ns_buffer .= "\t$indent</" . $type . ">\n";
 603+ }
 604+
 605+ $this->flushBuffers();
 606+ }
 607+
 608+ /**
 609+ * Print the triples associated to a specific page, and references those needed.
 610+ * They get printed in the printFooter-function.
 611+ *
 612+ * @param $st The SMWSmallTitle wrapping the page to be exported
 613+ * @param $fullexport Boolean to define whether all the data for the page should
 614+ * be exported, or whether just a definition of the given title.
 615+ * @param $backlinks Boolean specifying if properties linking to the exported title
 616+ * should be included.
 617+ */
 618+ protected function printObject( /*SMWSmallTitle*/ $st, $fullexport = true, $backlinks = false ) {
 619+ global $smwgMW_1_14;
 620+
 621+ if ( array_key_exists( $st->getHash(), $this->element_done ) ) return; // do not export twice
 622+
 623+ $value = SMWWikiPageValue::makePage( $st->dbkey, $st->namespace );
 624+
 625+ if ( $this->date !== '' ) { // check date restriction if given
 626+ $rev = $smwgMW_1_14 ? Revision::getTimeStampFromID( $value->getTitle(), $value->getTitle()->getLatestRevID() ):Revision::getTimeStampFromID( $value->getTitle()->getLatestRevID() );
 627+ if ( $rev < $this->date ) return;
 628+ }
 629+
 630+ $data = SMWExporter::makeExportData( smwfGetStore()->getSemanticData( $value, $fullexport ? false:array( '__spu', '__typ', '__imp' ) ), $st->modifier );
 631+ $this->printExpData( $data ); // serialise
 632+
 633+ // let other extensions add additional RDF data for this page
 634+ $additionalDataArray = array();
 635+
 636+ wfRunHooks( 'smwAddToRDFExport', array( $value->getTitle(), &$additionalDataArray ) );
 637+
 638+ foreach ( $additionalDataArray as $additionalData ) {
 639+ $this->printExpData( $additionalData ); // serialise
 640+ }
 641+
 642+ $this->markAsDone( $st );
 643+
 644+ // possibly add backlinks
 645+ if ( ( $fullexport ) && ( $backlinks ) ) {
 646+ wfProfileIn( "RDF::PrintPages::GetBacklinks" );
 647+ $inRels = smwfGetStore()->getInProperties( $value );
 648+
 649+ foreach ( $inRels as $inRel ) {
 650+ $inSubs = smwfGetStore()->getPropertySubjects( $inRel, $value );
 651+
 652+ foreach ( $inSubs as $inSub ) {
 653+ $stb = new SMWSmallTitle();
 654+ $stb->dbkey = $inSub->getDBkey();
 655+ $stb->namespace = $inSub->getNamespace();
 656+
 657+ if ( !array_key_exists( $stb->getHash(), $this->element_done ) ) {
 658+ $semdata = smwfGetStore()->getSemanticData( $inSub, array( '__spu', '__typ', '__imp' ) );
 659+ $semdata->addPropertyObjectValue( $inRel, $value );
 660+ $data = SMWExporter::makeExportData( $semdata );
 661+ $this->printExpData( $data );
 662+ }
 663+ }
 664+ }
 665+
 666+ if ( NS_CATEGORY === $value->getNamespace() ) { // also print elements of categories
 667+ $options = new SMWRequestOptions();
 668+
 669+ $options->limit = 100; /// Categories can be large, use limit
 670+
 671+ $instances = smwfGetStore()->getPropertySubjects( SMWPropertyValue::makeProperty( '_INST' ), $value, $options );
 672+
 673+ $pinst = SMWPropertyValue::makeProperty( '_INST' );
 674+
 675+ foreach ( $instances as $instance ) {
 676+ $stb = new SMWSmallTitle();
 677+ $stb->dbkey = $instance->getDBkey();
 678+ $stb->namespace = $instance->getNamespace();
 679+
 680+ if ( !array_key_exists( $stb->getHash(), $this->element_done ) ) {
 681+ $semdata = smwfGetStore()->getSemanticData( $instance, array( '__spu', '__typ', '__imp' ) );
 682+ $semdata->addPropertyObjectValue( $pinst, $value );
 683+ $data = SMWExporter::makeExportData( $semdata );
 684+ $this->printExpData( $data );
 685+ }
 686+ }
 687+ } elseif ( SMW_NS_CONCEPT === $value->getNamespace() ) { // print concept members (slightly different code)
 688+ $desc = new SMWConceptDescription( $value->getTitle() );
 689+ $desc->addPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, '' ) );
 690+ $query = new SMWQuery( $desc );
 691+ $query->setLimit( 100 );
 692+
 693+ $res = smwfGetStore()->getQueryResult( $query );
 694+ $resarray = $res->getNext();
 695+ $pinst = SMWPropertyValue::makeProperty( '_INST' );
 696+
 697+ while ( $resarray !== false ) {
 698+ $instance = end( $resarray )->getNextObject();
 699+
 700+ $stb = new SMWSmallTitle();
 701+
 702+ $stb->dbkey = $instance->getDBkey();
 703+ $stb->namespace = $instance->getNamespace();
 704+
 705+ if ( !array_key_exists( $stb->getHash(), $this->element_done ) ) {
 706+ $semdata = smwfGetStore()->getSemanticData( $instance, array( '__spu', '__typ', '__imp' ) );
 707+ $semdata->addPropertyObjectValue( $pinst, $value );
 708+ $data = SMWExporter::makeExportData( $semdata );
 709+ $this->printExpData( $data );
 710+ }
 711+
 712+ $resarray = $res->getNext();
 713+ }
 714+ }
 715+
 716+ wfProfileOut( "RDF::PrintPages::GetBacklinks" );
 717+ }
 718+ }
 719+
 720+ /**
 721+ * Flush all buffers and extra namespaces by printing them to stdout and flushing
 722+ * the output buffers afterwards.
 723+ *
 724+ * @param force if true, the flush cannot be delayed any longer
 725+ */
 726+ protected function flushBuffers( $force = false ) {
 727+ if ( $this->post_ns_buffer == '' ) return; // nothing to flush (every non-empty pre_ns_buffer also requires a non-empty post_ns_buffer)
 728+ if ( ( 0 != $this->delay_flush ) && !$force ) return; // wait a little longer
 729+
 730+ print $this->pre_ns_buffer;
 731+ $this->pre_ns_buffer = '';
 732+
 733+ foreach ( $this->extra_namespaces as $nsshort => $nsuri ) {
 734+ if ( $this->first_flush ) {
 735+ $this->global_namespaces[$nsshort] = true;
 736+ print "\n\t";
 737+ } else print ' ';
 738+
 739+ print "xmlns:$nsshort=\"$nsuri\"";
 740+ }
 741+
 742+ $this->extra_namespaces = array();
 743+ print $this->post_ns_buffer;
 744+ $this->post_ns_buffer = '';
 745+
 746+ // Ship data in small chunks (even though browsers often do not display anything
 747+ // before the file is complete -- this might be due to syntax highlighting features
 748+ // for app/xml). You may want to sleep(1) here for debugging this.
 749+ ob_flush();
 750+ flush();
 751+
 752+ $this->first_flush = false;
 753+ }
 754+
 755+ /**
 756+ * Add an extra namespace that was encountered during output. The method
 757+ * checks whether the required namespace is available globally and adds
 758+ * it to the list of extra_namesapce otherwise.
 759+ */
 760+ public function addExtraNamespace( $nsshort, $nsuri ) {
 761+ if ( !array_key_exists( $nsshort, $this->global_namespaces ) ) {
 762+ $this->extra_namespaces[$nsshort] = $nsuri;
 763+ }
 764+ }
 765+
 766+ /**
 767+ * Add a given SMWExpResource to the export queue if needed.
 768+ */
 769+ public function queueElement( $element ) {
 770+ if ( !( $element instanceof SMWExpResource ) ) return; // only Resources are queued
 771+ $title = $element->getDataValue();
 772+
 773+ if ( $title instanceof SMWWikiPageValue ) {
 774+ $spt = new SMWSmallTitle();
 775+ $title = $title->getTitle();
 776+ $spt->dbkey = $title->getDBkey();
 777+ $spt->namespace = $title->getNamespace();
 778+ $spt->modifier = $element->getModifier();
 779+
 780+ if ( !array_key_exists( $spt->getHash(), $this->element_done ) ) {
 781+ $this->element_queue[$spt->getHash()] = $spt;
 782+ }
 783+ }
 784+ }
 785+
 786+ /**
 787+ * Mark an article as done while making sure that the cache used for this
 788+ * stays reasonably small. Input is given as an SMWExportArticle object.
 789+ */
 790+ protected function markAsDone( $st ) {
 791+ if ( count( $this->element_done ) >= self::MAX_CACHE_SIZE ) {
 792+ $this->element_done = array_slice( $this->element_done,
 793+ self::CACHE_BACKJUMP,
 794+ self::MAX_CACHE_SIZE - self::CACHE_BACKJUMP,
 795+ true );
 796+ }
 797+ $this->element_done[$st->getHash()] = $st; // mark title as done
 798+ unset( $this->element_queue[$st->getHash()] ); // make sure it is not in the queue
 799+ }
 800+
 801+ /**
 802+ * This function checks whether some article fits into a given namespace restriction.
 803+ * FALSE means "no restriction," non-negative restictions require to check whether
 804+ * the given number equals the given namespace. A restriction of -1 requires the
 805+ * namespace to be different from Category:, Relation:, Attribute:, and Type:.
 806+ */
 807+ static public function fitsNsRestriction( $res, $ns ) {
 808+ if ( $res === false ) return true;
 809+ if ( is_array( $res ) ) return in_array( $ns, $res );
 810+ if ( $res >= 0 ) return ( $res == $ns );
 811+ return ( ( $res != NS_CATEGORY ) && ( $res != SMW_NS_PROPERTY ) && ( $res != SMW_NS_TYPE ) );
 812+ }
 813+
 814+}
\ No newline at end of file
Property changes on: trunk/extensions/SemanticMediaWiki/includes/export/SMW_OWLExport.php
___________________________________________________________________
Name: svn:eol-style
1815 + native
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_Setup.php
@@ -148,6 +148,7 @@
149149 $wgSpecialPages['SemanticStatistics'] = array( 'SMWSpecialSemanticStatistics' );
150150 $wgSpecialPageGroups['SemanticStatistics'] = 'wiki'; // Similar to Special:Statistics
151151
 152+ $wgAutoloadClasses['SMWOWLExport'] = $smwgIP . 'includes/export/SMW_OWLExport.php';
152153 $wgAutoloadClasses['SMWSpecialOWLExport'] = $smwgIP . 'specials/Export/SMW_SpecialOWLExport.php';
153154 $wgSpecialPages['ExportRDF'] = array( 'SMWSpecialOWLExport' );
154155 $wgSpecialPageGroups['ExportRDF'] = 'smw_group';

Status & tagging log