summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/Maintenance/ConceptCacheRebuilder.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/Maintenance/ConceptCacheRebuilder.php')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/src/Maintenance/ConceptCacheRebuilder.php273
1 files changed, 273 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/Maintenance/ConceptCacheRebuilder.php b/www/wiki/extensions/SemanticMediaWiki/src/Maintenance/ConceptCacheRebuilder.php
new file mode 100644
index 00000000..c8752e0d
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/src/Maintenance/ConceptCacheRebuilder.php
@@ -0,0 +1,273 @@
+<?php
+
+namespace SMW\Maintenance;
+
+use Onoi\MessageReporter\MessageReporter;
+use Onoi\MessageReporter\MessageReporterFactory;
+use SMW\DIConcept;
+use SMW\MediaWiki\TitleLookup;
+use SMW\Settings;
+use SMW\Store;
+use Title;
+
+/**
+ * Is part of the `rebuildConceptCache.php` maintenance script to rebuild
+ * cache entries for selected concepts
+ *
+ * @note This is an internal class and should not be used outside of smw-core
+ *
+ * @license GNU GPL v2+
+ * @since 1.9.2
+ *
+ * @author mwjames
+ */
+class ConceptCacheRebuilder {
+
+ /**
+ * @var Store
+ */
+ private $store;
+
+ /**
+ * @var Settings
+ */
+ private $settings;
+
+ /**
+ * @var MessageReporter
+ */
+ private $reporter;
+
+ private $concept = null;
+ private $action = null;
+ private $options = [];
+ private $startId = 0;
+ private $endId = 0;
+ private $lines = 0;
+ private $verbose = false;
+
+ /**
+ * @since 1.9.2
+ *
+ * @param Store $store
+ * @param Settings $settings
+ */
+ public function __construct( Store $store, Settings $settings ) {
+ $this->store = $store;
+ $this->settings = $settings;
+ $this->reporter = MessageReporterFactory::getInstance()->newNullMessageReporter();
+ }
+
+ /**
+ * @since 2.1
+ *
+ * @param MessageReporter $reporter
+ */
+ public function setMessageReporter( MessageReporter $reporter ) {
+ $this->reporter = $reporter;
+ }
+
+ /**
+ * @since 1.9.2
+ *
+ * @param array $parameters
+ */
+ public function setParameters( array $parameters ) {
+
+ $options = [ 'hard', 'update', 'old', 'quiet', 'status', 'verbose' ];
+
+ foreach ( $options as $option ) {
+ if ( isset( $parameters[$option] ) ) {
+ $this->options[$option] = $parameters[$option];
+ }
+ }
+
+ if ( isset( $parameters['concept'] ) ) {
+ $this->concept = $parameters['concept'];
+ }
+
+ if ( isset( $parameters['s'] ) ) {
+ $this->startId = intval( $parameters['s'] );
+ }
+
+ if ( isset( $parameters['e'] ) ) {
+ $this->endId = intval( $parameters['e'] );
+ }
+
+ $actions = [ 'status', 'create', 'delete' ];
+
+ foreach ( $actions as $action ) {
+ if ( isset( $parameters[$action] ) && $this->action === null ) {
+ $this->action = $action;
+ }
+ }
+
+ $this->verbose = array_key_exists( 'verbose', $parameters );
+ }
+
+ /**
+ * @since 1.9.2
+ *
+ * @return boolean
+ */
+ public function rebuild() {
+
+ switch ( $this->action ) {
+ case 'status':
+ $this->reportMessage( "\nDisplaying concept cache status information. Use CTRL-C to abort.\n\n" );
+ break;
+ case 'create':
+ $this->reportMessage( "\nCreating/updating concept caches. Use CTRL-C to abort.\n\n" );
+ break;
+ case 'delete':
+ $delay = 5;
+ $this->reportMessage( "\nAbort with CTRL-C in the next $delay seconds ... " );
+
+ if ( !$this->hasOption( 'quiet' ) ) {
+ swfCountDown( $delay );
+ }
+
+ $this->reportMessage( "\nDeleting concept caches.\n\n" );
+ break;
+ default:
+ return false;
+ }
+
+ if ( $this->hasOption( 'hard' ) ) {
+
+ $settings = ' smwgQMaxDepth: ' . $this->settings->get( 'smwgQMaxDepth' );
+ $settings .= ' smwgQMaxSize: ' . $this->settings->get( 'smwgQMaxSize' );
+ $settings .= ' smwgQFeatures: ' . $this->settings->get( 'smwgQFeatures' );
+
+ $this->reportMessage( "Option 'hard' is parameterized by{$settings}\n\n" );
+ }
+
+ $concepts = $this->getConcepts();
+
+ foreach ( $concepts as $concept ) {
+ $this->workOnConcept( $concept );
+ }
+
+ if ( $concepts === [] ) {
+ $this->reportMessage( "No concept available.\n" );
+ } else {
+ $this->reportMessage( "\nDone.\n" );
+ }
+
+ return true;
+ }
+
+ private function workOnConcept( Title $title ) {
+
+ $concept = $this->store->getConceptCacheStatus( $title );
+
+ if ( $this->skipConcept( $title, $concept ) ) {
+ return $this->lines += $this->verbose ? 1 : 0;
+ }
+
+ $result = $this->performAction( $title, $concept );
+
+ if ( $result ) {
+ $this->reportMessage( ' ' . implode( $result, "\n " ) . "\n" );
+ }
+
+ return $this->lines += 1;
+ }
+
+ private function skipConcept( $title, $concept = null ) {
+
+ $skip = false;
+
+ if ( $concept === null ) {
+ $skip = 'page not cacheable (no concept description, maybe a redirect)';
+ } elseif ( ( $this->hasOption( 'update' ) ) && ( $concept->getCacheStatus() !== 'full' ) ) {
+ $skip = 'page not cached yet';
+ } elseif ( ( $this->hasOption( 'old' ) ) && ( $concept->getCacheStatus() === 'full' ) &&
+ ( $concept->getCacheDate() > ( strtotime( 'now' ) - intval( $this->options['old'] ) * 60 ) ) ) {
+ $skip = 'cache is not old yet';
+ } elseif ( ( $this->hasOption( 'hard' ) ) && ( $this->settings->get( 'smwgQMaxSize' ) >= $concept->getSize() ) &&
+ ( $this->settings->get( 'smwgQMaxDepth' ) >= $concept->getDepth() &&
+ ( ( ~( ~( $concept->getQueryFeatures() + 0 ) | $this->settings->get( 'smwgQFeatures' ) ) ) == 0 ) ) ) {
+ $skip = 'concept is not "hard" according to wiki settings';
+ }
+
+ if ( $skip ) {
+ $line = $this->lines !== false ? "($this->lines) " : '';
+ $this->reportMessage( $line . 'Skipping concept "' . $title->getPrefixedText() . "\": $skip\n", $this->verbose );
+ }
+
+ return $skip;
+ }
+
+ private function performAction( Title $title, DIConcept $concept ) {
+ $this->reportMessage( "($this->lines) " );
+
+ if ( $this->action === 'create' ) {
+ $this->reportMessage( 'Creating cache for "' . $title->getPrefixedText() . "\" ...\n" );
+ return $this->store->refreshConceptCache( $title );
+ }
+
+ if ( $this->action === 'delete' ) {
+ $this->reportMessage( 'Deleting cache for "' . $title->getPrefixedText() . "\" ...\n" );
+ return $this->store->deleteConceptCache( $title );
+ }
+
+ $this->reportMessage( 'Status for "' . $title->getPrefixedText() . '": ' );
+
+ if ( $concept->getCacheStatus() === 'full' ) {
+ $this->reportMessage( 'Cache created at ' .
+ $this->getCacheDateInfo( $concept->getCacheDate() ) .
+ "{$concept->getCacheCount()} elements in cache\n"
+ );
+ }
+ else {
+ $this->reportMessage( "Not cached.\n" );
+ }
+ }
+
+ private function getConcepts() {
+
+ if ( $this->concept !== null ) {
+ return [ $this->createConcept() ];
+ }
+
+ return $this->createMultipleConcepts();
+ }
+
+ private function createConcept() {
+ return Title::newFromText( $this->concept, SMW_NS_CONCEPT );
+ }
+
+ private function createMultipleConcepts() {
+
+ $titleLookup = new TitleLookup( $this->store->getConnection( 'mw.db' ) );
+ $titleLookup->setNamespace( SMW_NS_CONCEPT );
+
+ if ( $this->endId == 0 && $this->startId == 0 ) {
+ return $titleLookup->selectAll();
+ }
+
+ $endId = $titleLookup->getMaxId();
+
+ if ( $this->endId > 0 ) {
+ $endId = min( $this->endId, $endId );
+ }
+
+ return $titleLookup->selectByIdRange( $this->startId, $endId );
+ }
+
+ private function hasOption( $key ) {
+ return isset( $this->options[$key] );
+ }
+
+ private function reportMessage( $message, $output = true ) {
+ if ( $output ) {
+ $this->reporter->reportMessage( $message );
+ }
+ }
+
+ private function getCacheDateInfo( $date ) {
+ return date( 'Y-m-d H:i:s', $date ) . ' (' . floor( ( strtotime( 'now' ) - $date ) / 60 ) . ' minutes old), ';
+ }
+
+}