summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/Maintenance/DistinctEntityDataRebuilder.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/Maintenance/DistinctEntityDataRebuilder.php')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/src/Maintenance/DistinctEntityDataRebuilder.php294
1 files changed, 294 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/Maintenance/DistinctEntityDataRebuilder.php b/www/wiki/extensions/SemanticMediaWiki/src/Maintenance/DistinctEntityDataRebuilder.php
new file mode 100644
index 00000000..a7c64c84
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/src/Maintenance/DistinctEntityDataRebuilder.php
@@ -0,0 +1,294 @@
+<?php
+
+namespace SMW\Maintenance;
+
+use Exception;
+use Onoi\MessageReporter\MessageReporter;
+use Onoi\MessageReporter\MessageReporterFactory;
+use SMW\DIWikiPage;
+use SMW\MediaWiki\Jobs\UpdateJob;
+use SMW\MediaWiki\TitleFactory;
+use SMW\MediaWiki\TitleLookup;
+use SMW\ApplicationFactory;
+use SMW\Options;
+use SMW\Store;
+use SMWQueryProcessor;
+use Title;
+
+/**
+ * @license GNU GPL v2+
+ * @since 2.4
+ *
+ * @author mwjames
+ */
+class DistinctEntityDataRebuilder {
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @var TitleFactory
+ */
+ private $titleFactory;
+
+ /**
+ * @var Options
+ */
+ private $options;
+
+ /**
+ * @var MessageReporter
+ */
+ private $reporter;
+
+ /**
+ * @var ExceptionFileLogger
+ */
+ private $exceptionFileLogger;
+
+ /**
+ * @var array
+ */
+ private $filters = [];
+
+ /**
+ * @var integer
+ */
+ private $rebuildCount = 0;
+
+ /**
+ * @since 2.4
+ *
+ * @param Store $store
+ * @param TitleFactory $titleFactory
+ */
+ public function __construct( Store $store, TitleFactory $titleFactory ) {
+ $this->store = $store;
+ $this->titleFactory = $titleFactory;
+ $this->reporter = MessageReporterFactory::getInstance()->newNullMessageReporter();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param MessageReporter $reporter
+ */
+ public function setOptions( Options $options ) {
+ $this->options = $options;
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param MessageReporter $reporter
+ */
+ public function setMessageReporter( MessageReporter $reporter ) {
+ $this->reporter = $reporter;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param ExceptionFileLogger $exceptionFileLogger
+ */
+ public function setExceptionFileLogger( ExceptionFileLogger $exceptionFileLogger ) {
+ $this->exceptionFileLogger = $exceptionFileLogger;
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @return int
+ */
+ public function getRebuildCount() {
+ return $this->rebuildCount;
+ }
+
+ /**
+ * @since 2.4
+ *
+ * @return boolean
+ */
+ public function doRebuild() {
+
+ $type = ( $this->options->has( 'redirects' ) ? 'redirect' : '' ) .
+ ( $this->options->has( 'categories' ) ? 'category' : '' ) .
+ ( $this->options->has( 'query' ) ? 'query (' . $this->options->get( 'query' ) .')' : '' ) .
+ ( $this->options->has( 'p' ) ? 'property' : '' );
+
+ $pages = [];
+ $this->findFilters();
+
+ if ( $this->options->has( 'page' ) ) {
+ $pages = explode( '|', $this->options->get( 'page' ) );
+ }
+
+ $pages = $this->normalize(
+ [
+ $this->getPagesFromQuery(),
+ $pages,
+ $this->getPagesFromFilters(),
+ $this->getRedirectPages()
+ ]
+ );
+
+ $total = count( $pages );
+ $this->reportMessage( "Rebuilding $type pages ...\n" );
+ $this->reportMessage( " ... selecting $total pages ...\n" );
+
+ $jobFactory = ApplicationFactory::getInstance()->newJobFactory();
+
+ foreach ( $pages as $key => $page ) {
+
+ $this->rebuildCount++;
+ $progress = round( ( $this->rebuildCount / $total ) * 100 );
+
+ if ( !$this->options->has( 'v' ) ) {
+ $this->reportMessage(
+ "\r". sprintf( "%-50s%s", " ... updating document no.", sprintf( "%s (%1.0f%%)", $this->rebuildCount, $progress ) )
+ );
+ } else {
+ $this->reportMessage(
+ sprintf( "%-16s%s\n", " ... ($this->rebuildCount/$total $progress)", "Page " . $key ),
+ $this->options->has( 'v' )
+ );
+ }
+
+ $this->doUpdate( $jobFactory, $page );
+ }
+
+ $this->reportMessage( ( $this->options->has( 'v' ) ? "" : "\n" ) . " ... done.\n" );
+
+ return true;
+ }
+
+ private function doUpdate( $jobFactory, $page ) {
+
+ $updatejob = $jobFactory->newUpdateJob(
+ $page,
+ [
+ UpdateJob::FORCED_UPDATE => true,
+ 'shallowUpdate' => $this->options->has( 'shallow-update' )
+ ]
+ );
+
+ if ( !$this->options->has( 'ignore-exceptions' ) ) {
+ return $updatejob->run();
+ }
+
+ try {
+ $updatejob->run();
+ } catch ( Exception $e ) {
+ $this->exceptionFileLogger->recordException( $page->getPrefixedDBkey(), $e );
+ }
+ }
+
+ private function findFilters() {
+ $this->filters = [];
+
+ if ( $this->options->has( 'categories' ) ) {
+ $this->filters[] = NS_CATEGORY;
+ }
+
+ if ( $this->options->has( 'p' ) ) {
+ $this->filters[] = SMW_NS_PROPERTY;
+ }
+ }
+
+ private function hasFilters() {
+ return $this->filters !== [];
+ }
+
+ private function getPagesFromQuery() {
+
+ if ( !$this->options->has( 'query' ) ) {
+ return [];
+ }
+
+ $queryString = $this->options->get( 'query' );
+
+ // get number of pages and fix query limit
+ $query = SMWQueryProcessor::createQuery(
+ $queryString,
+ SMWQueryProcessor::getProcessedParams( [ 'format' => 'count' ] )
+ );
+
+ $result = $this->store->getQueryResult( $query );
+
+ // get pages and add them to the pages explicitly listed in the 'page' parameter
+ $query = SMWQueryProcessor::createQuery(
+ $queryString,
+ SMWQueryProcessor::getProcessedParams( [] )
+ );
+
+ $query->setUnboundLimit( $result instanceof \SMWQueryResult ? $result->getCountValue() : $result );
+
+ return $this->store->getQueryResult( $query )->getResults();
+ }
+
+ private function getPagesFromFilters() {
+
+ $pages = [];
+
+ if ( !$this->hasFilters() ) {
+ return $pages;
+ }
+
+ $titleLookup = new TitleLookup( $this->store->getConnection( 'mw.db' ) );
+
+ foreach ( $this->filters as $namespace ) {
+ $pages = array_merge( $pages, $titleLookup->setNamespace( $namespace )->selectAll() );
+ }
+
+ return $pages;
+ }
+
+ private function getRedirectPages() {
+
+ if ( !$this->options->has( 'redirects' ) ) {
+ return [];
+ }
+
+ $titleLookup = new TitleLookup(
+ $this->store->getConnection( 'mw.db' )
+ );
+
+ return $titleLookup->getRedirectPages();
+ }
+
+ private function normalize( $list ) {
+
+ $titleCache = [];
+ $p = [];
+
+ foreach ( $list as $pages ) {
+ foreach ( $pages as $key => $page ) {
+
+ if ( $page instanceof DIWikiPage ) {
+ $page = $page->getTitle();
+ }
+
+ if ( !$page instanceof Title ) {
+ $page = $this->titleFactory->newFromText( $page );
+ }
+
+ $id = $page->getPrefixedDBkey();
+
+ if ( !isset( $p[$id] ) ) {
+ $p[$id] = $page;
+ }
+ }
+ }
+
+ return $p;
+ }
+
+ private function reportMessage( $message, $output = true ) {
+ if ( $output ) {
+ $this->reporter->reportMessage( $message );
+ }
+ }
+
+}