summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Hooks/ParserAfterTidy.php
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Hooks/ParserAfterTidy.php')
-rw-r--r--www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Hooks/ParserAfterTidy.php258
1 files changed, 258 insertions, 0 deletions
diff --git a/www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Hooks/ParserAfterTidy.php b/www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Hooks/ParserAfterTidy.php
new file mode 100644
index 00000000..96ee83d1
--- /dev/null
+++ b/www/wiki/extensions/SemanticMediaWiki/src/MediaWiki/Hooks/ParserAfterTidy.php
@@ -0,0 +1,258 @@
+<?php
+
+namespace SMW\MediaWiki\Hooks;
+
+use Parser;
+use SMW\ApplicationFactory;
+use SMW\MediaWiki\MediaWiki;
+use SMW\ParserData;
+use SMW\SemanticData;
+
+/**
+ * Hook: ParserAfterTidy to add some final processing to the
+ * fully-rendered page output
+ *
+ * @see http://www.mediawiki.org/wiki/Manual:Hooks/ParserAfterTidy
+ *
+ * @license GNU GPL v2+
+ * @since 1.9
+ *
+ * @author mwjames
+ */
+class ParserAfterTidy extends HookHandler {
+
+ /**
+ * @var Parser
+ */
+ private $parser;
+
+ /**
+ * @var NamespaceExaminer
+ */
+ private $namespaceExaminer;
+
+ /**
+ * @var boolean
+ */
+ private $isCommandLineMode = false;
+
+ /**
+ * @var boolean
+ */
+ private $isReadOnly = false;
+
+ /**
+ * @since 1.9
+ *
+ * @param Parser $parser
+ */
+ public function __construct( Parser &$parser ) {
+ $this->parser = $parser;
+ $this->namespaceExaminer = ApplicationFactory::getInstance()->getNamespaceExaminer();
+ }
+
+ /**
+ * @see https://www.mediawiki.org/wiki/Manual:$wgCommandLineMode
+ *
+ * @since 2.5
+ *
+ * @param boolean $isCommandLineMode
+ */
+ public function isCommandLineMode( $isCommandLineMode ) {
+ $this->isCommandLineMode = (bool)$isCommandLineMode;
+ }
+
+ /**
+ * @since 3.0
+ *
+ * @param boolean $isReadOnly
+ */
+ public function isReadOnly( $isReadOnly ) {
+ $this->isReadOnly = (bool)$isReadOnly;
+ }
+
+ /**
+ * @since 1.9
+ *
+ * @param string $text
+ *
+ * @return true
+ */
+ public function process( &$text ) {
+
+ if ( $this->canPerformUpdate() ) {
+ $this->performUpdate( $text );
+ }
+
+ return true;
+ }
+
+ private function canPerformUpdate() {
+
+ // #2432 avoid access to the DBLoadBalancer while being in readOnly mode
+ // when for example Title::isProtected is accessed
+ if ( $this->isReadOnly ) {
+ return false;
+ }
+
+ $title = $this->parser->getTitle();
+
+ if ( !$this->namespaceExaminer->isSemanticEnabled( $title->getNamespace() ) ) {
+ return false;
+ }
+
+ // Avoid an update for the SCHEMA NS to ensure errors remain present without
+ // the need the rerun the schema validator again.
+ if ( $title->getNamespace() === SMW_NS_SCHEMA ) {
+ return false;
+ }
+
+ // ParserOptions::getInterfaceMessage is being used to identify whether a
+ // parse was initiated by `Message::parse`
+ if ( $title->isSpecialPage() || $this->parser->getOptions()->getInterfaceMessage() ) {
+ return false;
+ }
+
+ $parserOutput = $this->parser->getOutput();
+
+ if ( $parserOutput->getProperty( 'displaytitle' ) ||
+ $parserOutput->getExtensionData( 'translate-translation-page' ) ||
+ $parserOutput->getCategoryLinks() ) {
+ return true;
+ }
+
+ if ( ParserData::hasSemanticData( $parserOutput ) ||
+ $title->isProtected( 'edit' ) ||
+ $this->parser->getDefaultSort() ) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private function performUpdate( &$text ) {
+
+ $applicationFactory = ApplicationFactory::getInstance();
+
+ $parserData = $applicationFactory->newParserData(
+ $this->parser->getTitle(),
+ $this->parser->getOutput()
+ );
+
+ $semanticData = $parserData->getSemanticData();
+
+ $this->addPropertyAnnotations(
+ $applicationFactory->singleton( 'PropertyAnnotatorFactory' ),
+ $semanticData
+ );
+
+ $parserData->copyToParserOutput();
+ $subject = $semanticData->getSubject();
+
+ // Only carry out a purge where the InTextAnnotationParser have set
+ // an appropriate context reference otherwise it is assumed that the hook
+ // call is part of another non SMW related parse
+ if ( $subject->getContextReference() !== null || $subject->getNamespace() === SMW_NS_SCHEMA ) {
+ $this->checkPurgeRequest( $parserData );
+ }
+ }
+
+ private function addPropertyAnnotations( $propertyAnnotatorFactory, $semanticData ) {
+
+ $parserOutput = $this->parser->getOutput();
+
+ $propertyAnnotator = $propertyAnnotatorFactory->newNullPropertyAnnotator(
+ $semanticData
+ );
+
+ $propertyAnnotator = $propertyAnnotatorFactory->newCategoryPropertyAnnotator(
+ $propertyAnnotator,
+ $parserOutput->getCategoryLinks()
+ );
+
+ $propertyAnnotator = $propertyAnnotatorFactory->newMandatoryTypePropertyAnnotator(
+ $propertyAnnotator
+ );
+
+ $propertyAnnotator = $propertyAnnotatorFactory->newEditProtectedPropertyAnnotator(
+ $propertyAnnotator,
+ $this->parser->getTitle()
+ );
+
+ // Special case! belongs to the EditProtectedPropertyAnnotator instance
+ $propertyAnnotator->addTopIndicatorTo(
+ $parserOutput
+ );
+
+ $propertyAnnotator = $propertyAnnotatorFactory->newDisplayTitlePropertyAnnotator(
+ $propertyAnnotator,
+ $parserOutput->getProperty( 'displaytitle' ),
+ $this->parser->getDefaultSort()
+ );
+
+ $propertyAnnotator = $propertyAnnotatorFactory->newSortKeyPropertyAnnotator(
+ $propertyAnnotator,
+ $this->parser->getDefaultSort()
+ );
+
+ // #2300
+ $propertyAnnotator = $propertyAnnotatorFactory->newTranslationPropertyAnnotator(
+ $propertyAnnotator,
+ $parserOutput->getExtensionData( 'translate-translation-page' )
+ );
+
+ $propertyAnnotator->addAnnotation();
+ }
+
+ /**
+ * @note Article purge: In case an article was manually purged/moved
+ * the store is updated as well; for all other cases LinksUpdateConstructed
+ * will handle the store update
+ *
+ * @note The purge action is isolated from any other request therefore using
+ * a static variable or any other messaging that is not persistent will not
+ * work hence the reliance on the cache as temporary persistence marker
+ */
+ private function checkPurgeRequest( $parserData ) {
+
+ $cache = ApplicationFactory::getInstance()->getCache();
+ $start = microtime( true );
+
+ $key = ApplicationFactory::getInstance()->getCacheFactory()->getPurgeCacheKey(
+ $this->parser->getTitle()->getArticleID()
+ );
+
+ if( $cache->contains( $key ) && $cache->fetch( $key ) ) {
+ $cache->delete( $key );
+
+ // Avoid a Parser::lock for when a PurgeRequest remains intact
+ // during an update process while being executed from the cmdLine
+ if ( $this->isCommandLineMode ) {
+ return true;
+ }
+
+ $parserData->setOrigin( 'ParserAfterTidy' );
+
+ // Set an explicit timestamp to create a new hash for the property
+ // table change row differ and force a data comparison (this doesn't
+ // change the _MDAT annotation)
+ $parserData->getSemanticData()->setOption(
+ SemanticData::OPT_LAST_MODIFIED,
+ wfTimestamp( TS_UNIX )
+ );
+
+ $parserData->setOption(
+ $parserData::OPT_FORCED_UPDATE,
+ true
+ );
+
+ $parserData->updateStore( true );
+
+ $parserData->addLimitReport(
+ 'pagepurge-storeupdatetime',
+ number_format( ( microtime( true ) - $start ), 3 )
+ );
+ }
+ }
+
+}