From 57116f8b7c14151091417c0fbbe6d9152f366b0f Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 14 Aug 2026 16:44:48 +0400 Subject: [PATCH 1/6] use SMW ExporterFactory --- src/JsonLDSerializer.php | 65 +++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/src/JsonLDSerializer.php b/src/JsonLDSerializer.php index a4e7fc0..9b67420 100644 --- a/src/JsonLDSerializer.php +++ b/src/JsonLDSerializer.php @@ -13,6 +13,7 @@ use MediaWiki\Output\OutputPage; use MediaWiki\SpecialPage\SpecialPage; use MediaWiki\Title\Title; +use SMW\Exporter\ExporterFactory; class JsonLDSerializer { /** @@ -46,37 +47,47 @@ public static function setJsonLD( $title, $outputPage ) { return; } - // @TODO use directly the function makeExportDataForSubject - // SemanticMediawiki/includes/export/SMW_Exporter.php - $export_rdf = SpecialPage::getTitleFor( 'ExportRDF' ); - if ( $export_rdf->isKnown() ) { - $export_url = $export_rdf->getFullURL( [ - 'page' => $title->getFullText(), - 'recursive' => '1', - 'backlinks' => 0 - ], false, PROTO_FALLBACK ); + // @see SMW\Query\ResultPrinters\RdfResultPrinter + $exporterFactory = new ExporterFactory(); + $serializer = $exporterFactory->newRDFXMLSerializer(); + $export_controller = $exporterFactory->newExportController( $serializer ); - try { - $foaf = new \EasyRdf\Graph( $export_url ); - $foaf->load(); + $outputPage->disable(); + ob_start(); - $format = \EasyRdf\Format::getFormat( 'jsonld' ); - $output = $foaf->serialise( $format, [ - 'compact' => true, - ] ); + try { + $recursive = true; + $export_controller->enableBacklinks( false ); + $revisionDate = false; + $pages = [ $title->getFullText() ]; + $export_controller->printPages( $pages, $recursive, $revisionDate ); + + } catch ( Exception $e ) { + ob_end_clean(); + LoggerFactory::getInstance( 'smt' )->error( 'SMW ExporterFactory error: ' . $e->getMessage() ); + return; + } + + $data = ob_get_clean(); - } catch ( Exception $e ) { - LoggerFactory::getInstance( 'smt' )->error( 'EasyRdf error: ' . $export_url ); - return; - } + try { + $foaf = new \EasyRdf\Graph( $title->getFullUrl(), $data ); + $format = \EasyRdf\Format::getFormat( 'jsonld' ); + $output = $foaf->serialise( $format, [ + 'compact' => true, + ] ); + + } catch ( Exception $e ) { + LoggerFactory::getInstance( 'smt' )->error( 'EasyRdf error: ' . $e->getMessage() ); + return; + } - // https://hotexamples.com/examples/-/EasyRdf_Graph/serialise/php-easyrdf_graph-serialise-method-examples.html - if ( is_scalar( $output ) ) { - $outputPage->addHeadItem( 'json-ld', Html::Element( - 'script', [ 'type' => 'application/ld+json' ], $output - ) - ); - } + // https://hotexamples.com/examples/-/EasyRdf_Graph/serialise/php-easyrdf_graph-serialise-method-examples.html + if ( is_scalar( $output ) ) { + $outputPage->addHeadItem( 'json-ld', Html::Element( + 'script', [ 'type' => 'application/ld+json' ], $output + ) + ); } } } From eaba33b3cb7b40ee1aeffb551536956937249495 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Fri, 14 Aug 2026 16:52:45 +0400 Subject: [PATCH 2/6] fix phpcs --- src/JsonLDSerializer.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/JsonLDSerializer.php b/src/JsonLDSerializer.php index 9b67420..5b1bcfb 100644 --- a/src/JsonLDSerializer.php +++ b/src/JsonLDSerializer.php @@ -11,7 +11,6 @@ use MediaWiki\Html\Html; use MediaWiki\Logger\LoggerFactory; use MediaWiki\Output\OutputPage; -use MediaWiki\SpecialPage\SpecialPage; use MediaWiki\Title\Title; use SMW\Exporter\ExporterFactory; @@ -46,22 +45,21 @@ public static function setJsonLD( $title, $outputPage ) { if ( !class_exists( '\EasyRdf\Graph' ) || !class_exists( '\ML\JsonLD\JsonLD' ) ) { return; } - // @see SMW\Query\ResultPrinters\RdfResultPrinter $exporterFactory = new ExporterFactory(); $serializer = $exporterFactory->newRDFXMLSerializer(); $export_controller = $exporterFactory->newExportController( $serializer ); $outputPage->disable(); - ob_start(); + ob_start(); try { - $recursive = true; - $export_controller->enableBacklinks( false ); - $revisionDate = false; - $pages = [ $title->getFullText() ]; - $export_controller->printPages( $pages, $recursive, $revisionDate ); - + $recursive = true; + $export_controller->enableBacklinks( false ); + $revisionDate = false; + $pages = [ $title->getFullText() ]; + $export_controller->printPages( $pages, $recursive, $revisionDate ); + } catch ( Exception $e ) { ob_end_clean(); LoggerFactory::getInstance( 'smt' )->error( 'SMW ExporterFactory error: ' . $e->getMessage() ); From 7fa51db87429646858a94ca55d8eb4ed08345c75 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Wed, 2 Sep 2026 17:37:38 +0400 Subject: [PATCH 3/6] add cache config --- extension.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extension.json b/extension.json index f1d96cb..f3258b5 100644 --- a/extension.json +++ b/extension.json @@ -31,6 +31,12 @@ }, "config_prefix": "smtg", "config": { + "JsonLDDisableCache": { + "value": false + }, + "JsonLDCacheStore": { + "value": "SessionCache" + }, "TagsProperties": { "value": [], "description": "An array of tags that assigns related properties such as `'keywords' => [ 'Has keywords', ... ]`." From 1006dcf819f571d89b5702c80a2f9bf7f54f8d34 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Wed, 2 Sep 2026 17:39:10 +0400 Subject: [PATCH 4/6] add cache --- src/JsonLDSerializer.php | 102 +++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 21 deletions(-) diff --git a/src/JsonLDSerializer.php b/src/JsonLDSerializer.php index 5b1bcfb..0fadbbe 100644 --- a/src/JsonLDSerializer.php +++ b/src/JsonLDSerializer.php @@ -1,7 +1,7 @@ isKnownArticle( $title ) ) { - $this->setJsonLD( $title, $outputPage ); + $this->outputPage = $outputPage; + $this->setJsonLD( $title ); } } /** - * @see https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/PageProperties/+/548d30609c512a79e202dfa7c02a298c66ca34fa/includes/PageProperties.php * @param Title $title * @return bool */ @@ -36,30 +41,46 @@ private function isKnownArticle( $title ) { } /** - * @see https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/PageProperties/+/548d30609c512a79e202dfa7c02a298c66ca34fa/includes/PageProperties.php - * @param Title $title - * @param OutputPage $outputPage - * @return void + * @return mixed|false */ - public static function setJsonLD( $title, $outputPage ) { - if ( !class_exists( '\EasyRdf\Graph' ) || !class_exists( '\ML\JsonLD\JsonLD' ) ) { - return; + private function getCache() { + switch ( $GLOBALS['smtgJsonLDCacheStore'] ) { + case 'LocalServerObjectCache': + return MediaWikiServices::getInstance()->getLocalServerObjectCache(); + + case 'WANObjectCache': + return MediaWikiServices::getInstance()->getMainWANObjectCache(); + + case 'SessionCache': + default: + // @see MediaWiki\Session\SessionManager + $config = MediaWikiServices::getInstance()->getMainConfig(); + $store = \ObjectCache::getInstance( $config->get( + class_exists( 'MainConfigNames' ) ? MainConfigNames::SessionCacheType : 'SessionCacheType' ) ); + return new \CachedBagOStuff( $store ); } + } + + /** + * @param Title $title + * @return string|null + */ + private function getJsonLDOutput( $title ) { // @see SMW\Query\ResultPrinters\RdfResultPrinter $exporterFactory = new ExporterFactory(); $serializer = $exporterFactory->newRDFXMLSerializer(); $export_controller = $exporterFactory->newExportController( $serializer ); - $outputPage->disable(); - ob_start(); + $this->outputPage->disable(); + ob_start(); try { - $recursive = true; - $export_controller->enableBacklinks( false ); - $revisionDate = false; - $pages = [ $title->getFullText() ]; - $export_controller->printPages( $pages, $recursive, $revisionDate ); - + $recursive = true; + $export_controller->enableBacklinks( false ); + $revisionDate = false; + $pages = [ $title->getFullText() ]; + $export_controller->printPages( $pages, $recursive, $revisionDate ); + } catch ( Exception $e ) { ob_end_clean(); LoggerFactory::getInstance( 'smt' )->error( 'SMW ExporterFactory error: ' . $e->getMessage() ); @@ -71,18 +92,57 @@ public static function setJsonLD( $title, $outputPage ) { try { $foaf = new \EasyRdf\Graph( $title->getFullUrl(), $data ); $format = \EasyRdf\Format::getFormat( 'jsonld' ); - $output = $foaf->serialise( $format, [ + return $foaf->serialise( $format, [ 'compact' => true, ] ); } catch ( Exception $e ) { LoggerFactory::getInstance( 'smt' )->error( 'EasyRdf error: ' . $e->getMessage() ); + } + } + + /** + * @param Title $title + * @return void + */ + public function setJsonLD( $title ) { + if ( !class_exists( '\EasyRdf\Graph' ) || !class_exists( '\ML\JsonLD\JsonLD' ) ) { return; } + $cache = null; + if ( empty( $GLOBALS['smtgJsonLDDisableCache'] ) ) { + $revisionId = (int)$title->getLatestRevID(); + $cache = $this->getCache(); + + if ( $cache ) { + $cacheKey = $cache->makeKey( + 'SemanticMetaTags', + 'jsonld', + $title->getNamespace(), + $title->getDBkey(), + $revisionId, + ); + + $thisClass = $this; + $output = $cache->getWithSetCallback( + $cacheKey, + $cache::TTL_INDEFINITE, + static function () use ( &$thisClass, $title ) { + return $thisClass->getJsonLDOutput( $title ); + } + ); + } + + } + + if ( !$cache ) { + $output = $this->getJsonLDOutput( $title ); + } + // https://hotexamples.com/examples/-/EasyRdf_Graph/serialise/php-easyrdf_graph-serialise-method-examples.html - if ( is_scalar( $output ) ) { - $outputPage->addHeadItem( 'json-ld', Html::Element( + if ( is_string( $output ) && !empty( $output ) ) { + $this->outputPage->addHeadItem( 'json-ld', Html::Element( 'script', [ 'type' => 'application/ld+json' ], $output ) ); From c3776c78f5f3375b9874d212420060364c5790d2 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Wed, 2 Sep 2026 17:40:49 +0400 Subject: [PATCH 5/6] add ref --- src/JsonLDSerializer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/JsonLDSerializer.php b/src/JsonLDSerializer.php index 0fadbbe..f92bf99 100644 --- a/src/JsonLDSerializer.php +++ b/src/JsonLDSerializer.php @@ -48,6 +48,7 @@ private function getCache() { case 'LocalServerObjectCache': return MediaWikiServices::getInstance()->getLocalServerObjectCache(); + // @see https://github.com/SemanticMediaWiki/SemanticMetaTags/pull/118 case 'WANObjectCache': return MediaWikiServices::getInstance()->getMainWANObjectCache(); From 5968cc0e95e72958bcdc8bb605332d6903ecf4f0 Mon Sep 17 00:00:00 2001 From: thomas-topway-it Date: Wed, 2 Sep 2026 17:46:44 +0400 Subject: [PATCH 6/6] fix PHPCS --- src/JsonLDSerializer.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/JsonLDSerializer.php b/src/JsonLDSerializer.php index f92bf99..46cce52 100644 --- a/src/JsonLDSerializer.php +++ b/src/JsonLDSerializer.php @@ -12,7 +12,6 @@ use MediaWiki\Logger\LoggerFactory; use MediaWiki\MediaWikiServices; use MediaWiki\Output\OutputPage; -use MediaWiki\SpecialPage\SpecialPage; use MediaWiki\Title\Title; use SMW\Exporter\ExporterFactory; @@ -41,6 +40,8 @@ private function isKnownArticle( $title ) { } /** + * @see https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/SubpageNavigation/+/refs/heads/master/includes/SubpageNavigation.php#278 + * * @return mixed|false */ private function getCache() { @@ -73,15 +74,15 @@ private function getJsonLDOutput( $title ) { $export_controller = $exporterFactory->newExportController( $serializer ); $this->outputPage->disable(); - ob_start(); + ob_start(); try { - $recursive = true; - $export_controller->enableBacklinks( false ); - $revisionDate = false; - $pages = [ $title->getFullText() ]; - $export_controller->printPages( $pages, $recursive, $revisionDate ); - + $recursive = true; + $export_controller->enableBacklinks( false ); + $revisionDate = false; + $pages = [ $title->getFullText() ]; + $export_controller->printPages( $pages, $recursive, $revisionDate ); + } catch ( Exception $e ) { ob_end_clean(); LoggerFactory::getInstance( 'smt' )->error( 'SMW ExporterFactory error: ' . $e->getMessage() ); @@ -134,7 +135,6 @@ static function () use ( &$thisClass, $title ) { } ); } - } if ( !$cache ) {