1
- <?php
2
-
3
- /*
4
- * SemanticDependencyUpdater is a MediaWiki extension that monitors changes in the semantic data of a wiki page.
5
- * The affected page can the Semantic Dependency Updater property to define which pages should also be updated.
6
- * This can be defined through a list of pages or for more advanced use cases, a query string.
7
- *
8
- * This extension requires Semantic MediaWiki >= 2.3 (http://www.semantic-mediawiki.org)
9
- *
10
- * This extension is slightly based on Remco C. de Boers https://www.mediawiki.org/wiki/Extension:SemanticDummyEditor
11
- *
12
- * @author Simon Heimler, gesinn.it GmbH & Co
13
- */
14
-
15
- if ( !defined ( 'MEDIAWIKI ' ) ) {
16
- die ();
17
- }
18
-
19
- if ( !defined ( 'SMW_VERSION ' ) ) {
20
- die ( "ERROR: Semantic MediaWiki must be installed for Semantic Dummy Editor to run! " );
21
- }
22
-
23
- define ( 'SDU_VERSION ' , '1.3.2 ' );
24
-
25
- $ wgExtensionCredits [defined ( 'SEMANTIC_EXTENSION_TYPE ' ) ? 'semantic ' : 'other ' ][] = [
26
- 'name ' => 'SemanticDependencyUpdater ' ,
27
- 'author ' => [
28
- '[https://www.mediawiki.org/wiki/User:Fannon Simon Heimler] ' ,
29
- '[https://www.mediawiki.org/wiki/User:Planetenxin Alexander Gesinn] ' ,
30
- '[https://www.mediawiki.org/wiki/User:Rcdeboer Remco C. de Boer] ' ,
31
- ],
32
- 'url ' => 'http://www.mediawiki.org/wiki/Extension:SemanticDependencyUpdater ' ,
33
- 'description ' => 'Monitors semantic data changes and updates dependend pages ' ,
34
- 'version ' => SDU_VERSION ,
35
- ];
36
-
37
- global $ wgExtensionFunctions ;
38
- $ wgExtensionFunctions [] = 'SemanticDependencyUpdater::setup ' ;
39
- $ wgJobClasses ['DummyEditJob ' ] = 'DummyEditJob ' ;
40
-
41
- $ wgSDUProperty = 'Semantic Dependency ' ;
42
- $ wgSDUUseJobQueue = false ;
43
-
44
- class SemanticDependencyUpdater {
45
-
46
- public static function setup () {
47
- global $ wgHooks ;
48
- $ wgHooks ['SMW::SQLStore::AfterDataUpdateComplete ' ][] = 'SemanticDependencyUpdater::onAfterDataUpdateComplete ' ;
49
- }
50
-
51
- public static function onAfterDataUpdateComplete ( SMWStore $ store , SMWSemanticData $ newData ,
52
- $ compositePropertyTableDiffIterator ) {
53
-
54
- global $ wgSDUProperty ;
55
- global $ wgSDUTraversed ;
56
-
57
- if ( !isset ( $ wgSDUTraversed ) ) {
58
- $ wgSDUTraversed = [];
59
- }
60
-
61
- $ wgSDUProperty = str_replace ( ' ' , '_ ' , $ wgSDUProperty );
62
- $ subject = $ newData ->getSubject ();
63
- $ title = $ subject ->getTitle ();
64
- $ id = $ title ->getPrefixedDBKey ();
65
-
66
- wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] --> " . $ title );
67
-
68
-
69
- // FIRST CHECK: Does the page data contain a $wgSUTPropertyName semantic property ?
70
- $ properties = $ newData ->getProperties ();
71
- $ diffTable = $ compositePropertyTableDiffIterator ->getOrderedDiffByTable ();
72
-
73
- if ( !isset ( $ properties [$ wgSDUProperty ] ) ) {
74
- wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] <-- No SDU property found " );
75
- return true ;
76
- }
77
-
78
-
79
- // SECOND CHECK: Have there been actual changes in the data? (Ignore internal SMW data!)
80
- // TODO: Introduce an explicit list of Semantic Properties to watch ?
81
- unset( $ diffTable ['smw_fpt_mdat ' ] ); // Ignore SMW's internal properties "smw_fpt_mdat"
82
-
83
- if ( count ( $ diffTable ) > 0 ) {
84
- // wfDebugLog('SemanticDependencyUpdater', "[SDU] diffTable: " . print_r($diffTable, true));
85
- wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] -----> Data changes detected " );
86
- } else {
87
- wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] <-- No semantic data changes detected " );
88
- return true ;
89
- }
90
-
91
-
92
- // THIRD CHECK: Has this page been already traversed more than twice?
93
- // This should only be the case when SMW errors occur.
94
- // In that case, the diffTable contains everything and SDU can't know if changes happend
95
- if ( array_key_exists ( $ id , $ wgSDUTraversed ) ) {
96
- $ wgSDUTraversed [$ id ] = $ wgSDUTraversed [$ id ] + 1 ;
97
- } else {
98
- $ wgSDUTraversed [$ id ] = 1 ;
99
- }
100
- if ( $ wgSDUTraversed [$ id ] > 2 ) {
101
- wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] <-- Already traversed " );
102
- return true ;
103
- }
104
-
105
-
106
- // QUERY AND UPDATE DEPENDENCIES
107
-
108
- $ dataItem = $ newData ->getPropertyValues ( $ properties [$ wgSDUProperty ] );
109
-
110
- foreach ( $ dataItem as $ valueItem ) {
111
- SemanticDependencyUpdater::updatePagesMatchingQuery ( $ valueItem ->getString () );
112
- }
113
-
114
- return true ;
115
- }
116
-
117
- /**
118
- * @param string $queryString Query string, excluding [[ and ]] brackets
119
- */
120
- private static function updatePagesMatchingQuery ( $ queryString ) {
121
-
122
- global $ sfgListSeparator ;
123
-
124
- $ queryString = str_replace ( 'AND ' , ']] [[ ' , $ queryString );
125
- $ queryString = str_replace ( 'OR ' , ']] OR [[ ' , $ queryString );
126
-
127
- // If SF is installed, get the separator character and change it into ||
128
- // Otherwise SDU won't work with multi-value properties
129
- if ( isset ( $ sfgListSeparator ) ) {
130
- $ queryString = rtrim ( $ queryString , $ sfgListSeparator );
131
- $ queryString = str_replace ( $ sfgListSeparator , ' || ' , $ queryString );
132
- }
133
-
134
- wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] --------> [[ $ queryString]] " );
135
-
136
- $ store = smwfGetStore ();
137
-
138
- $ params = [
139
- 'limit ' => 10000 ,
140
- ];
141
- $ processedParams = SMWQueryProcessor::getProcessedParams ( $ params );
142
- $ query =
143
- SMWQueryProcessor::createQuery ( "[[ $ queryString]] " , $ processedParams , SMWQueryProcessor::SPECIAL_PAGE );
144
- $ result = $ store ->getQueryResult ( $ query ); // SMWQueryResult
145
- $ wikiPageValues = $ result ->getResults (); // array of SMWWikiPageValues
146
-
147
- // TODO: This can be optimized by collecting a list of all pages first, make them unique
148
- // and do the dummy edit afterwards
149
- // TODO: A threshold when to switch to Queue Jobs might be smarter
150
- foreach ( $ wikiPageValues as $ page ) {
151
- SemanticDependencyUpdater::dummyEdit ( $ page ->getTitle () );
152
- }
153
-
154
- return ;
155
- }
156
-
157
- /**
158
- * Save a null revision in the page's history to propagate the update
159
- *
160
- * @param Title $title
161
- */
162
- public static function dummyEdit ( $ title ) {
163
- global $ wgSDUUseJobQueue ;
164
-
165
- if ( $ wgSDUUseJobQueue ) {
166
- wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] --------> [Edit Job] $ title " );
167
- $ job = new DummyEditJob ( $ title );
168
- $ job ->insert ();
169
- } else {
170
- wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] --------> [Edit] $ title " );
171
- $ page = WikiPage::newFromID ( $ title ->getArticleId () );
172
- if ( $ page ) { // prevent NPE when page not found
173
- $ content = $ page ->getContent ( Revision::RAW );
174
- $ text = ContentHandler::getContentText ( $ content );
175
- $ page ->doEditContent ( ContentHandler::makeContent ( $ text , $ page ->getTitle () ),
176
- "[SemanticDependencyUpdater] Null edit. " ); // since this is a null edit, the edit summary will be ignored.
177
- $ page ->doPurge (); // required since SMW 2.5.1
178
- }
179
- }
180
- }
181
-
182
- }
183
-
184
- class DummyEditJob extends Job {
185
-
186
- function __construct ( $ title , $ params = '' , $ id = 0 ) {
187
- parent ::__construct ( 'DummyEditJob ' , $ title , $ params , $ id );
188
- }
189
-
190
- /**
191
- * Run the job
192
- * @return boolean success
193
- */
194
- function run () {
195
- wfProfileIn ( __METHOD__ );
196
-
197
- if ( is_null ( $ this ->title ) ) {
198
- $ this ->error = "DummyEditJob: Invalid title " ;
199
- wfProfileOut ( __METHOD__ );
200
- return false ;
201
- }
202
-
203
- $ page = WikiPage::newFromID ( $ this ->title ->getArticleId () );
204
- if ( $ page ) { // prevent NPE when page not found
205
- $ content = $ page ->getContent ( Revision::RAW );
206
- $ text = ContentHandler::getContentText ( $ content );
207
- $ page ->doEditContent ( ContentHandler::makeContent ( $ text , $ page ->getTitle () ),
208
- "[SemanticDependencyUpdater] Null edit. " ); // since this is a null edit, the edit summary will be ignored.
209
- $ page ->doPurge (); // required since SMW 2.5.1
210
- }
211
-
212
- wfProfileOut ( __METHOD__ );
213
- return true ;
214
- }
215
- }
1
+ <?php
2
+ /**
3
+ * Created by PhpStorm.
4
+ * User: Sebastian
5
+ * Date: 21.08.2018
6
+ * Time: 08:56
7
+ */
8
+
9
+ namespace SDU ;
10
+
11
+ use SMW ;
12
+ use SMWStore ;
13
+ use SMWSemanticData ;
14
+ use SMWQueryProcessor ;
15
+ use Revision ;
16
+ use WikiPage ;
17
+ use ContentHandler ;
18
+
19
+ class Hooks {
20
+
21
+ public static function setup () {
22
+
23
+ if ( !defined ( 'MEDIAWIKI ' ) ) {
24
+ die ();
25
+ }
26
+
27
+ if ( !defined ( 'SMW_VERSION ' ) ) {
28
+ die ( "ERROR: Semantic MediaWiki must be installed for Semantic Dependency Updater to run! " );
29
+ }
30
+
31
+ global $ wgHooks ;
32
+ // registered Hook this way to make sure SMW is loaded
33
+ $ wgHooks ['SMW::SQLStore::AfterDataUpdateComplete ' ][] = 'SDU\Hooks::onAfterDataUpdateComplete ' ;
34
+ }
35
+
36
+ public static function onAfterDataUpdateComplete ( SMWStore $ store , SMWSemanticData $ newData ,
37
+ $ compositePropertyTableDiffIterator ) {
38
+ global $ wgSDUProperty ;
39
+ global $ wgSDUTraversed ;
40
+
41
+ if ( !isset ( $ wgSDUTraversed ) ) {
42
+ $ wgSDUTraversed = [];
43
+ }
44
+
45
+ $ wgSDUProperty = str_replace ( ' ' , '_ ' , $ wgSDUProperty );
46
+ $ subject = $ newData ->getSubject ();
47
+ $ title = $ subject ->getTitle ();
48
+ $ id = $ title ->getPrefixedDBKey ();
49
+
50
+ wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] --> " . $ title );
51
+
52
+
53
+ // FIRST CHECK: Does the page data contain a $wgSUTPropertyName semantic property ?
54
+ $ properties = $ newData ->getProperties ();
55
+ $ diffTable = $ compositePropertyTableDiffIterator ->getOrderedDiffByTable ();
56
+
57
+ if ( !isset ( $ properties [$ wgSDUProperty ] ) ) {
58
+ wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] <-- No SDU property found " );
59
+ return true ;
60
+ }
61
+
62
+ // SECOND CHECK: Have there been actual changes in the data? (Ignore internal SMW data!)
63
+ // TODO: Introduce an explicit list of Semantic Properties to watch ?
64
+ unset( $ diffTable ['smw_fpt_mdat ' ] ); // Ignore SMW's internal properties "smw_fpt_mdat"
65
+
66
+ if ( count ( $ diffTable ) > 0 ) {
67
+ // wfDebugLog('SemanticDependencyUpdater', "[SDU] diffTable: " . print_r($diffTable, true));
68
+ wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] -----> Data changes detected " );
69
+ } else {
70
+ wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] <-- No semantic data changes detected " );
71
+ return true ;
72
+ }
73
+
74
+
75
+ // THIRD CHECK: Has this page been already traversed more than twice?
76
+ // This should only be the case when SMW errors occur.
77
+ // In that case, the diffTable contains everything and SDU can't know if changes happend
78
+ if ( array_key_exists ( $ id , $ wgSDUTraversed ) ) {
79
+ $ wgSDUTraversed [$ id ] = $ wgSDUTraversed [$ id ] + 1 ;
80
+ } else {
81
+ $ wgSDUTraversed [$ id ] = 1 ;
82
+ }
83
+ if ( $ wgSDUTraversed [$ id ] > 2 ) {
84
+ wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] <-- Already traversed " );
85
+ return true ;
86
+ }
87
+
88
+
89
+ // QUERY AND UPDATE DEPENDENCIES
90
+
91
+ $ dataItem = $ newData ->getPropertyValues ( $ properties [$ wgSDUProperty ] );
92
+
93
+ foreach ( $ dataItem as $ valueItem ) {
94
+ Hooks::updatePagesMatchingQuery ( $ valueItem ->getString () );
95
+ }
96
+
97
+ return true ;
98
+ }
99
+ /**
100
+ * @param string $queryString Query string, excluding [[ and ]] brackets
101
+ */
102
+ private static function updatePagesMatchingQuery ( $ queryString ) {
103
+
104
+ global $ sfgListSeparator ;
105
+
106
+ $ queryString = str_replace ( 'AND ' , ']] [[ ' , $ queryString );
107
+ $ queryString = str_replace ( 'OR ' , ']] OR [[ ' , $ queryString );
108
+
109
+ // If SF is installed, get the separator character and change it into ||
110
+ // Otherwise SDU won't work with multi-value properties
111
+ if ( isset ( $ sfgListSeparator ) ) {
112
+ $ queryString = rtrim ( $ queryString , $ sfgListSeparator );
113
+ $ queryString = str_replace ( $ sfgListSeparator , ' || ' , $ queryString );
114
+ }
115
+
116
+ wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] --------> [[ $ queryString]] " );
117
+
118
+ $ store = smwfGetStore ();
119
+
120
+ $ params = [
121
+ 'limit ' => 10000 ,
122
+ ];
123
+ $ processedParams = SMWQueryProcessor::getProcessedParams ( $ params );
124
+ $ query =
125
+ SMWQueryProcessor::createQuery ( "[[ $ queryString]] " , $ processedParams , SMWQueryProcessor::SPECIAL_PAGE );
126
+ $ result = $ store ->getQueryResult ( $ query ); // SMWQueryResult
127
+ $ wikiPageValues = $ result ->getResults (); // array of SMWWikiPageValues
128
+
129
+ // TODO: This can be optimized by collecting a list of all pages first, make them unique
130
+ // and do the dummy edit afterwards
131
+ // TODO: A threshold when to switch to Queue Jobs might be smarter
132
+ foreach ( $ wikiPageValues as $ page ) {
133
+ Hooks::dummyEdit ( $ page ->getTitle () );
134
+ }
135
+
136
+ return ;
137
+ }
138
+
139
+ /**
140
+ * Save a null revision in the page's history to propagate the update
141
+ *
142
+ * @param Title $title
143
+ */
144
+ public static function dummyEdit ( $ title ) {
145
+ global $ wgSDUUseJobQueue ;
146
+
147
+ if ( $ wgSDUUseJobQueue ) {
148
+ wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] --------> [Edit Job] $ title " );
149
+ $ job = new DummyEditJob ( $ title );
150
+ $ job ->insert ();
151
+ } else {
152
+ wfDebugLog ( 'SemanticDependencyUpdater ' , "[SDU] --------> [Edit] $ title " );
153
+ $ page = WikiPage::newFromID ( $ title ->getArticleId () );
154
+ if ( $ page ) { // prevent NPE when page not found
155
+ $ content = $ page ->getContent ( Revision::RAW );
156
+ $ text = ContentHandler::getContentText ( $ content );
157
+ $ page ->doEditContent ( ContentHandler::makeContent ( $ text , $ page ->getTitle () ),
158
+ "[SemanticDependencyUpdater] Null edit. " ); // since this is a null edit, the edit summary will be ignored.
159
+ $ page ->doPurge (); // required since SMW 2.5.1
160
+ }
161
+ }
162
+ }
163
+
164
+ }
0 commit comments