Index: trunk/extensions/SemanticNotifyMe/specials/SMWNotifyMe/SMW_NMSendMailAsync.php |
— | — | @@ -1,67 +1,64 @@ |
2 | | -<?php
|
3 | | -/*
|
4 | | - * Created on 2009/3/25
|
5 | | - *
|
6 | | - * Author: Dch
|
7 | | - */
|
8 | | -
|
9 | | -
|
10 | | -//get Parameter
|
11 | | -$wgRequestTime = microtime(true);
|
12 | | -
|
13 | | -/** */
|
14 | | -# Abort if called from a web server
|
15 | | -if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) {
|
16 | | - print "This script must be run from the command line\n";
|
17 | | - exit();
|
18 | | -}
|
19 | | -
|
20 | | -
|
21 | | -if( version_compare( PHP_VERSION, '5.0.0' ) < 0 ) {
|
22 | | - print "Sorry! This version of MediaWiki requires PHP 5; you are running " .
|
23 | | - PHP_VERSION . ".\n\n" .
|
24 | | - "If you are sure you already have PHP 5 installed, it may be " .
|
25 | | - "installed\n" .
|
26 | | - "in a different path from PHP 4. Check with your system administrator.\n";
|
27 | | - die( -1 );
|
28 | | -}
|
29 | | -
|
30 | | -// copy from user class
|
31 | | -function getUserNMOption( $str ) {
|
32 | | - $options = array();
|
33 | | - $a = explode( "\n", $str );
|
34 | | - foreach ( $a as $s ) {
|
35 | | - $m = array();
|
36 | | - if ( preg_match( "/^(.[^=]*)=(.*)$/", $s, $m ) ) {
|
37 | | - $options[$m[1]] = $m[2];
|
38 | | - }
|
39 | | - }
|
40 | | - return $options['enotifyme'];
|
41 | | -}
|
42 | | -
|
43 | | -// include commandLine script which provides some basic
|
44 | | -// methodes for maintenance scripts
|
45 | | -$mediaWikiLocation = dirname(__FILE__) . '/../../../..';
|
46 | | -require_once "$mediaWikiLocation/maintenance/commandLine.inc";
|
47 | | -
|
48 | | -$sStore = smwfGetSemanticStore();
|
49 | | -$msgs = $sStore->getUnmailedNMMessages();
|
50 | | -foreach($msgs as $msg) {
|
51 | | - // send notifications by mail
|
52 | | - $user_info = $sStore->getUserInfo($msg['user_id']);
|
53 | | - if(($user_info->user_email != '') && getUserNMOption($user_info->user_options)) {
|
54 | | - $name = (($user_info->user_real_name=='')?$user_info->user_name:$user_info->user_real_name);
|
55 | | - $body = "Dear Mr./Mrs. $name,<br/>".$msg['notify'].
|
56 | | - "<br/><br/>Sincerely yours,<br/>SMW NotifyMe Bot";
|
57 | | -
|
58 | | - UserMailer::send( //userMailer(
|
59 | | - new MailAddress($user_info->user_email, $name),
|
60 | | - new MailAddress($wgEmergencyContact, 'Admin'),
|
61 | | - 'New SMW Notification comes, from '.$wgSitename,
|
62 | | - $body,
|
63 | | - new MailAddress($wgEmergencyContact, 'Admin'),
|
64 | | - true
|
65 | | - );
|
66 | | - }
|
67 | | -}
|
68 | | -?>
|
| 2 | +<?php |
| 3 | +/* |
| 4 | + * Created on 2009/3/25 |
| 5 | + * |
| 6 | + * Author: Dch |
| 7 | + */ |
| 8 | + |
| 9 | +// get Parameter |
| 10 | +$wgRequestTime = microtime( true ); |
| 11 | + |
| 12 | +/** */ |
| 13 | +# Abort if called from a web server |
| 14 | +if ( isset( $_SERVER ) && array_key_exists( 'REQUEST_METHOD', $_SERVER ) ) { |
| 15 | + print "This script must be run from the command line\n"; |
| 16 | + exit(); |
| 17 | +} |
| 18 | + |
| 19 | +if ( version_compare( PHP_VERSION, '5.0.0' ) < 0 ) { |
| 20 | + print "Sorry! This version of MediaWiki requires PHP 5; you are running " . |
| 21 | + PHP_VERSION . ".\n\n" . |
| 22 | + "If you are sure you already have PHP 5 installed, it may be " . |
| 23 | + "installed\n" . |
| 24 | + "in a different path from PHP 4. Check with your system administrator.\n"; |
| 25 | + die( - 1 ); |
| 26 | +} |
| 27 | + |
| 28 | +// copy from user class |
| 29 | +function getUserNMOption( $str ) { |
| 30 | + $options = array(); |
| 31 | + $a = explode( "\n", $str ); |
| 32 | + foreach ( $a as $s ) { |
| 33 | + $m = array(); |
| 34 | + if ( preg_match( "/^(.[^=]*)=(.*)$/", $s, $m ) ) { |
| 35 | + $options[$m[1]] = $m[2]; |
| 36 | + } |
| 37 | + } |
| 38 | + return $options['enotifyme']; |
| 39 | +} |
| 40 | + |
| 41 | +// include commandLine script which provides some basic |
| 42 | +// methodes for maintenance scripts |
| 43 | +$mediaWikiLocation = dirname( __FILE__ ) . '/../../../..'; |
| 44 | +require_once "$mediaWikiLocation/maintenance/commandLine.inc"; |
| 45 | + |
| 46 | +$sStore = smwfGetSemanticStore(); |
| 47 | +$msgs = $sStore->getUnmailedNMMessages(); |
| 48 | +foreach ( $msgs as $msg ) { |
| 49 | + // send notifications by mail |
| 50 | + $user_info = $sStore->getUserInfo( $msg['user_id'] ); |
| 51 | + if ( ( $user_info->user_email != '' ) && getUserNMOption( $user_info->user_options ) ) { |
| 52 | + $name = ( ( $user_info->user_real_name == '' ) ? $user_info->user_name:$user_info->user_real_name ); |
| 53 | + $body = "Dear Mr./Mrs. $name,<br/>" . $msg['notify'] . |
| 54 | + "<br/><br/>Sincerely yours,<br/>SMW NotifyMe Bot"; |
| 55 | + |
| 56 | + UserMailer::send( // userMailer( |
| 57 | + new MailAddress( $user_info->user_email, $name ), |
| 58 | + new MailAddress( $wgEmergencyContact, 'Admin' ), |
| 59 | + 'New SMW Notification comes, from ' . $wgSitename, |
| 60 | + $body, |
| 61 | + new MailAddress( $wgEmergencyContact, 'Admin' ), |
| 62 | + true |
| 63 | + ); |
| 64 | + } |
| 65 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/specials/SMWNotifyMe/SMW_NMSendMailAsync.php |
___________________________________________________________________ |
Name: svn:eol-style |
69 | 66 | + native |
Index: trunk/extensions/SemanticNotifyMe/specials/SMWNotifyMe/SMW_NotAjaxAccess.php |
— | — | @@ -1,111 +1,110 @@ |
2 | | -<?php
|
3 | | -
|
4 | | -global $wgAjaxExportList;
|
5 | | -global $smwgNMIP;
|
6 | | -
|
7 | | -require_once($smwgNMIP . '/includes/SMW_NotifyProcessor.php');
|
8 | | -$wgAjaxExportList[] = 'smwf_nm_NotifyAccess';
|
9 | | -
|
10 | | -
|
11 | | -function smwf_nm_NotifyAccess($method, $params) {
|
12 | | - $p_array = explode(",", $params);
|
13 | | - global $smwgQEnabled;
|
14 | | -
|
15 | | - $result="Query disabled.";
|
16 | | - if($method == "updateMail"){
|
17 | | - global $wgUser;
|
18 | | - $wgUser->setOption( 'enotifyme', $params );
|
19 | | - $wgUser->saveSettings();
|
20 | | - return 'Update NotifyMe mail setting successfully!';
|
21 | | - }
|
22 | | - else if($method == "addNotify"){
|
23 | | - if ($smwgQEnabled) {
|
24 | | - $result = SMWNotifyProcessor::addNotify(str_replace('&', '&', str_replace(',', ',', $p_array[0])),
|
25 | | - str_replace('&', '&', str_replace(',', ',', $p_array[3])),
|
26 | | - $p_array[1], $p_array[2], implode(",", array_slice($p_array, 4)));
|
27 | | - }
|
28 | | - return $result;
|
29 | | - }
|
30 | | - else if($method == "getQueryResult"){
|
31 | | - if ($smwgQEnabled) {
|
32 | | - $params .= '
|
33 | | -| format=table
|
34 | | -| link=all';
|
35 | | -
|
36 | | - // parse params and answer query
|
37 | | - SMWQueryProcessor::processFunctionParams(SMWNotifyProcessor::getQueryRawParams($params),$querystring,$params,$printouts);
|
38 | | -
|
39 | | - $result = SMWQueryProcessor::getResultFromQueryString($querystring,$params,$printouts, SMW_OUTPUT_WIKI);
|
40 | | - switch ($params->format) {
|
41 | | - case 'timeline':
|
42 | | - return $result;
|
43 | | - break;
|
44 | | - case 'eventline':
|
45 | | - return $result;
|
46 | | - break;
|
47 | | - case 'googlepie':
|
48 | | - return $result[0];
|
49 | | - break;
|
50 | | - case 'googlebar':
|
51 | | - return $result[0];
|
52 | | - break;
|
53 | | - case 'exhibit':
|
54 | | - return $result;
|
55 | | - break;
|
56 | | - default:
|
57 | | - }
|
58 | | - global $wgParser;
|
59 | | -
|
60 | | - if ( ($wgParser->getTitle() instanceof Title) && ($wgParser->getOptions() instanceof ParserOptions) ) {
|
61 | | - $result = $wgParser->recursiveTagParse($result);
|
62 | | - } else {
|
63 | | - global $wgTitle;
|
64 | | - $popt = new ParserOptions();
|
65 | | - $popt->setEditSection(false);
|
66 | | - $pout = $wgParser->parse($result . '__NOTOC__', $wgTitle, $popt);
|
67 | | - /// NOTE: as of MW 1.14SVN, there is apparently no better way to hide the TOC
|
68 | | - SMWOutputs::requireFromParserOutput($pout);
|
69 | | - $result = $pout->getText();
|
70 | | - }
|
71 | | -
|
72 | | - // add target="_new" for all links
|
73 | | - $pattern = "|<a|i";
|
74 | | - $result = preg_replace($pattern, '<a target="_new"', $result);
|
75 | | - }
|
76 | | - return $result;
|
77 | | - }
|
78 | | - else if($method == "updateStates"){
|
79 | | - if ($smwgQEnabled) {
|
80 | | - $result = SMWNotifyProcessor::updateStates($p_array);
|
81 | | - }
|
82 | | - return $result;
|
83 | | - }
|
84 | | - else if($method == "updateReportAll"){
|
85 | | - if ($smwgQEnabled) {
|
86 | | - $result = SMWNotifyProcessor::updateReportAll($p_array);
|
87 | | - }
|
88 | | - return $result;
|
89 | | - }
|
90 | | - else if($method == "updateShowAll"){
|
91 | | - if ($smwgQEnabled) {
|
92 | | - $result = SMWNotifyProcessor::updateShowAll($p_array);
|
93 | | - }
|
94 | | - return $result;
|
95 | | - }
|
96 | | - else if($method == "updateDelegates"){
|
97 | | - if ($smwgQEnabled) {
|
98 | | - $result = SMWNotifyProcessor::updateDelegates(explode("|", $params));
|
99 | | - }
|
100 | | - return $result;
|
101 | | - }
|
102 | | - else if($method == "delNotify"){
|
103 | | - if ($smwgQEnabled) {
|
104 | | - $result = SMWNotifyProcessor::delNotify($p_array);
|
105 | | - }
|
106 | | - return $result;
|
107 | | - }
|
108 | | - else {
|
109 | | - return "Operation failed, please retry later.";
|
110 | | - }
|
111 | | -}
|
112 | | -?> |
\ No newline at end of file |
| 2 | +<?php |
| 3 | + |
| 4 | +global $wgAjaxExportList; |
| 5 | +global $smwgNMIP; |
| 6 | + |
| 7 | +require_once( $smwgNMIP . '/includes/SMW_NotifyProcessor.php' ); |
| 8 | +$wgAjaxExportList[] = 'smwf_nm_NotifyAccess'; |
| 9 | + |
| 10 | + |
| 11 | +function smwf_nm_NotifyAccess( $method, $params ) { |
| 12 | + $p_array = explode( ",", $params ); |
| 13 | + global $smwgQEnabled; |
| 14 | + |
| 15 | + $result = "Query disabled."; |
| 16 | + if ( $method == "updateMail" ) { |
| 17 | + global $wgUser; |
| 18 | + $wgUser->setOption( 'enotifyme', $params ); |
| 19 | + $wgUser->saveSettings(); |
| 20 | + return 'Update NotifyMe mail setting successfully!'; |
| 21 | + } |
| 22 | + else if ( $method == "addNotify" ) { |
| 23 | + if ( $smwgQEnabled ) { |
| 24 | + $result = SMWNotifyProcessor::addNotify( str_replace( '&', '&', str_replace( ',', ',', $p_array[0] ) ), |
| 25 | + str_replace( '&', '&', str_replace( ',', ',', $p_array[3] ) ), |
| 26 | + $p_array[1], $p_array[2], implode( ",", array_slice( $p_array, 4 ) ) ); |
| 27 | + } |
| 28 | + return $result; |
| 29 | + } |
| 30 | + else if ( $method == "getQueryResult" ) { |
| 31 | + if ( $smwgQEnabled ) { |
| 32 | + $params .= ' |
| 33 | +| format=table |
| 34 | +| link=all'; |
| 35 | + |
| 36 | + // parse params and answer query |
| 37 | + SMWQueryProcessor::processFunctionParams( SMWNotifyProcessor::getQueryRawParams( $params ), $querystring, $params, $printouts ); |
| 38 | + |
| 39 | + $result = SMWQueryProcessor::getResultFromQueryString( $querystring, $params, $printouts, SMW_OUTPUT_WIKI ); |
| 40 | + switch ( $params->format ) { |
| 41 | + case 'timeline': |
| 42 | + return $result; |
| 43 | + break; |
| 44 | + case 'eventline': |
| 45 | + return $result; |
| 46 | + break; |
| 47 | + case 'googlepie': |
| 48 | + return $result[0]; |
| 49 | + break; |
| 50 | + case 'googlebar': |
| 51 | + return $result[0]; |
| 52 | + break; |
| 53 | + case 'exhibit': |
| 54 | + return $result; |
| 55 | + break; |
| 56 | + default: |
| 57 | + } |
| 58 | + global $wgParser; |
| 59 | + |
| 60 | + if ( ( $wgParser->getTitle() instanceof Title ) && ( $wgParser->getOptions() instanceof ParserOptions ) ) { |
| 61 | + $result = $wgParser->recursiveTagParse( $result ); |
| 62 | + } else { |
| 63 | + global $wgTitle; |
| 64 | + $popt = new ParserOptions(); |
| 65 | + $popt->setEditSection( false ); |
| 66 | + $pout = $wgParser->parse( $result . '__NOTOC__', $wgTitle, $popt ); |
| 67 | + // / NOTE: as of MW 1.14SVN, there is apparently no better way to hide the TOC |
| 68 | + SMWOutputs::requireFromParserOutput( $pout ); |
| 69 | + $result = $pout->getText(); |
| 70 | + } |
| 71 | + |
| 72 | + // add target="_new" for all links |
| 73 | + $pattern = "|<a|i"; |
| 74 | + $result = preg_replace( $pattern, '<a target="_new"', $result ); |
| 75 | + } |
| 76 | + return $result; |
| 77 | + } |
| 78 | + else if ( $method == "updateStates" ) { |
| 79 | + if ( $smwgQEnabled ) { |
| 80 | + $result = SMWNotifyProcessor::updateStates( $p_array ); |
| 81 | + } |
| 82 | + return $result; |
| 83 | + } |
| 84 | + else if ( $method == "updateReportAll" ) { |
| 85 | + if ( $smwgQEnabled ) { |
| 86 | + $result = SMWNotifyProcessor::updateReportAll( $p_array ); |
| 87 | + } |
| 88 | + return $result; |
| 89 | + } |
| 90 | + else if ( $method == "updateShowAll" ) { |
| 91 | + if ( $smwgQEnabled ) { |
| 92 | + $result = SMWNotifyProcessor::updateShowAll( $p_array ); |
| 93 | + } |
| 94 | + return $result; |
| 95 | + } |
| 96 | + else if ( $method == "updateDelegates" ) { |
| 97 | + if ( $smwgQEnabled ) { |
| 98 | + $result = SMWNotifyProcessor::updateDelegates( explode( "|", $params ) ); |
| 99 | + } |
| 100 | + return $result; |
| 101 | + } |
| 102 | + else if ( $method == "delNotify" ) { |
| 103 | + if ( $smwgQEnabled ) { |
| 104 | + $result = SMWNotifyProcessor::delNotify( $p_array ); |
| 105 | + } |
| 106 | + return $result; |
| 107 | + } |
| 108 | + else { |
| 109 | + return "Operation failed, please retry later."; |
| 110 | + } |
| 111 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/specials/SMWNotifyMe/SMW_NotAjaxAccess.php |
___________________________________________________________________ |
Name: svn:eol-style |
113 | 112 | + native |
Index: trunk/extensions/SemanticNotifyMe/specials/SMWNotifyMe/SMWNotifyMe.php |
— | — | @@ -1,406 +1,403 @@ |
2 | | -<?php
|
3 | | -
|
4 | | -if (!defined('MEDIAWIKI')) die();
|
5 | | -
|
6 | | -
|
7 | | -
|
8 | | -global $IP;
|
9 | | -require_once( $IP . "/includes/SpecialPage.php" );
|
10 | | -require_once( "SMW_NotAjaxAccess.php" );
|
11 | | -
|
12 | | -global $smwgNMIP;
|
13 | | -
|
14 | | -require_once($smwgNMIP . '/includes/SMW_NotifyProcessor.php');
|
15 | | -
|
16 | | -/*
|
17 | | - * Standard class that is resopnsible for the creation of the Special Page
|
18 | | - */
|
19 | | -class SMWNotifyMe extends SpecialPage {
|
20 | | - public function __construct() {
|
21 | | - parent::__construct('NotifyMe');
|
22 | | - }
|
23 | | -/*
|
24 | | - * Overloaded function that is responsible for the creation of the Special Page
|
25 | | - */
|
26 | | - public function execute() {
|
27 | | -
|
28 | | - global $wgRequest, $wgOut, $smwgNMScriptPath, $wgUser;
|
29 | | -
|
30 | | - # Get query parameters
|
31 | | - $feedFormat = $wgRequest->getVal( 'feed' );
|
32 | | - if($feedFormat=='rss') {
|
33 | | - # 10 seconds server-side caching max
|
34 | | - $wgOut->setSquidMaxage( 10 );
|
35 | | -
|
36 | | - global $smwgNMMaxFeedItems;
|
37 | | - $limit = ($smwgNMMaxFeedItems > 0) ? $smwgNMMaxFeedItems : 20;
|
38 | | -
|
39 | | - $dbr = wfGetDB( DB_SLAVE );
|
40 | | - $id = $wgRequest->getVal( 'uid' );
|
41 | | - $type = "uid";
|
42 | | - if($id) {
|
43 | | - # Get last modified date, for client caching
|
44 | | - # Don't use this if we are using the patrol feature, patrol changes don't update the timestamp
|
45 | | - $lastmod = $dbr->selectField( 'smw_nm_rss', 'MAX(timestamp)', array('user_id'=>$id), 'NotifyMeRSS' );
|
46 | | - } else {
|
47 | | - $type = "nid";
|
48 | | - $id = $wgRequest->getVal( 'nid' );
|
49 | | - $lastmod = $dbr->selectField( 'smw_nm_rss', 'MAX(timestamp)', array('notify_id'=>$id), 'NotifyMeRSS' );
|
50 | | - }
|
51 | | - if( $lastmod && $wgOut->checkLastModified( $lastmod ) ){
|
52 | | - # Client cache fresh and headers sent, nothing more to do.
|
53 | | - return;
|
54 | | - }
|
55 | | - $this->rcOutputFeed( $feedFormat, $type, $id, $limit, $lastmod, true );
|
56 | | - } else {
|
57 | | - $user_id = $wgUser->getId();
|
58 | | -
|
59 | | - $wgOut->setPageTitle(wfMsg('smw_notifyme'));
|
60 | | -
|
61 | | - if($user_id > 0) {
|
62 | | - $isSysop = in_array('sysop', $wgUser->getEffectiveGroups());
|
63 | | - if($isSysop) {
|
64 | | - SMWNotifyMe::addAutocomplete();
|
65 | | - }
|
66 | | -
|
67 | | - $imagepath = $smwgNMScriptPath . '/skins/images/';
|
68 | | -
|
69 | | - $html = '<div id="nmcontent">
|
70 | | - <div id="shade" style="display:none"></div>
|
71 | | - <div id="fullpreviewbox" style="display:none">
|
72 | | - <div id="fullpreview"></div>
|
73 | | - <span class="nmbutton" onclick="$(\'fullpreviewbox\', \'shade\').invoke(\'toggle\')"><img src="'. $imagepath. 'delete.png"/>Close Preview</span></div>
|
74 | | - <div id="nmlayout">
|
75 | | - <div id="querytitle" onclick="notifyhelper.switchquery()" onmouseover="Tip(\'' . wfMsg('smw_nm_tt_query') . '\')"><a id="querytitle-link" class="minusplus" href="javascript:void(0)"></a>Notify Me Query</div>
|
76 | | - <div id="querycontent">'.$this->getQueryLayout().'</div>
|
77 | | - <div id="layouttitle" onclick="notifyhelper.switchlayout()" onmouseover="Tip(\'' . wfMsg('smw_nm_tt_nmm') . '\')"><a id="layouttitle-link" class="minusplus" href="javascript:void(0)"></a>Notify Me Manager</div>
|
78 | | - <div id="layoutcontent">' . $this->getNotifyTable().'</div>
|
79 | | - </div>
|
80 | | - </div>';
|
81 | | -
|
82 | | - global $wgEmailAuthentication, $wgEnableEmail;
|
83 | | - if ($wgEnableEmail) {
|
84 | | - if ($wgEmailAuthentication && ($wgUser->getEmail() != '') ) {
|
85 | | - if( $wgUser->getEmailAuthenticationTimestamp() ) {
|
86 | | - $disableEmailPrefs = false;
|
87 | | - } else {
|
88 | | - $disableEmailPrefs = true;
|
89 | | - }
|
90 | | - } else {
|
91 | | - $disableEmailPrefs = false;
|
92 | | - }
|
93 | | - $eEmail = $wgUser->getOption( 'enotifyme' );
|
94 | | - $html .= '<div class="nmmenubar">
|
95 | | - <input id="nmemail" type="checkbox" value="1"'.($disableEmailPrefs?' disabled':'').($eEmail?' checked':'').'/> Enable \'Notify Me\' by E-mail ';
|
96 | | - if($disableEmailPrefs) {
|
97 | | - $href = htmlspecialchars( $wgUser->getSkin()->makeSpecialUrl( 'Preferences' ) );
|
98 | | - $text = htmlspecialchars( wfMsg( 'mypreferences' ) );
|
99 | | - $html .= " (Please enable your email account in '<a href=\"$href\">$text</a>'. )";
|
100 | | - }
|
101 | | - $html .= '</div>';
|
102 | | - }
|
103 | | -
|
104 | | - $html .= '<div>
|
105 | | - RSS Feed : <input id="nmrss" size="80" type="text" title="RSS feed url" value="'.$this->getTitle()->getFullURL( 'feed=rss&uid='.$user_id ).'" />
|
106 | | - <button class="btn" onclick="notifyhelper.copyToClipboard(\'nmrss\')" onmouseover="this.className=\'btn btnhov\'; Tip(\'' . wfMsg('smw_nm_tt_clipboard') . '\')" onmouseout="this.className=\'btn\'">' . wfMsg('smw_qi_clipboard') . '</button>
|
107 | | - </div>';
|
108 | | -
|
109 | | - $html .= '<script type="text/javascript" src="' . $smwgNMScriptPath . '/scripts/NotifyMe/nm_tooltip.js"></script>';
|
110 | | - } else {
|
111 | | - $html = '<div id="nmlayout">You have not logged in, please login first. Thanks.</div>';
|
112 | | - }
|
113 | | - $wgOut->addHTML($html);
|
114 | | - }
|
115 | | - }
|
116 | | - private function getQueryLayout() {
|
117 | | - global $wgUser;
|
118 | | - $isSysop = in_array('sysop', $wgUser->getEffectiveGroups());
|
119 | | -
|
120 | | - $html = '<table style="width: 100%;"><tr><td width=40%>
|
121 | | - <table width=100%>
|
122 | | - <tr><th width=40%>Name :</th><td width=60% onmouseover="Tip(\'Name of the notification\')"><input type="text" id="nmqname"></td></tr>
|
123 | | - <tr><th nowrap>Report all :</th><td onmouseover="Tip(\'Report all semantic semantic attribes\\\' change of monitored pages\')"><input type="checkbox" checked id="nmqrall"></td></tr>
|
124 | | - <tr><th nowrap>Show all :</th><td onmouseover="Tip(\'Show all query results with notifications\')"><input type="checkbox" id="nmqsall"></td></tr>';
|
125 | | - if($isSysop) {
|
126 | | - $html .= '<tr><th nowrap>Delegate to :</th><td><input type="text" id="nmd_new" size=35>
|
127 | | - <div class="page_name_auto_complete" id="nmdiv_new"></div></td>';
|
128 | | - }
|
129 | | - $html .= '</table></td><td width=60%><table style="width: 100%;">
|
130 | | - <tr><th onmouseover="Tip(\'' . wfMsg('smw_nm_tt_qtext') . '\')">Query (table format, all link only)</th></tr>
|
131 | | - <tr><td onmouseover="Tip(\'Full query string, with {{#ask syntax\')">
|
132 | | - {{#ask:<br/>
|
133 | | - <textarea id="nmquery" cols="20" rows="6"></textarea><br/>
|
134 | | - | format=table<br/>
|
135 | | - | link=all<br/>
|
136 | | - |}}
|
137 | | - </td></tr>
|
138 | | - </table>
|
139 | | - </td></tr></table>
|
140 | | - <div class="nmmenubar">
|
141 | | - <div style="text-align:left;float:left;">
|
142 | | - <button class="btn" onclick="notifyhelper.previewQuery()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Show full preview of your query results\')" onmouseout="this.className=\'btn\'">Preview Results</button>
|
143 | | - <button class="btn" onclick="notifyhelper.doSaveToNotify('.$isSysop.')" onmouseover="this.className=\'btn btnhov\'; Tip(\'Add this notification to you NotifyMe\')" onmouseout="this.className=\'btn\'">Add to NotifyMe</button>
|
144 | | - </div><div style="text-align:right;">
|
145 | | - <button class="btn" onclick="notifyhelper.resetQuery()"onmouseout="this.className=\'btn\'" onmouseover="this.className=\'btn btnhov\'; Tip(\'Resets the entire query\')">Reset Query</button>
|
146 | | - </div></div>';
|
147 | | -
|
148 | | - return $html;
|
149 | | - }
|
150 | | -
|
151 | | - static function addAutocomplete() {
|
152 | | - global $smwgNMDelegateQuery, $smwgNMDelegateUserGroup;
|
153 | | - if(!$smwgNMDelegateQuery && !$smwgNMDelegateUserGroup) return;
|
154 | | -
|
155 | | - global $wgOut, $smwgNMScriptPath;
|
156 | | - $nmScriptPath = $smwgNMScriptPath . '/specials/SMWNotifyMe';
|
157 | | - $nmYUIBase = "http://yui.yahooapis.com/2.7.0/build/";
|
158 | | -
|
159 | | - $wgOut->addLink( array(
|
160 | | - 'rel' => 'stylesheet',
|
161 | | - 'type' => 'text/css',
|
162 | | - 'media' => "screen, projection",
|
163 | | - 'href' => $nmScriptPath . '/skins/NM_yui_autocompletion.css'
|
164 | | - ));
|
165 | | - $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'yahoo/yahoo-min.js"></script>' . "\n");
|
166 | | - $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'dom/dom-min.js"></script>' . "\n");
|
167 | | - $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'event/event-min.js"></script>' . "\n");
|
168 | | - $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'get/get-min.js"></script>' . "\n");
|
169 | | - $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'connection/connection-min.js"></script>' . "\n");
|
170 | | - $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'json/json-min.js"></script>' . "\n");
|
171 | | - $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'datasource/datasource-min.js"></script>' . "\n");
|
172 | | - $wgOut->addScript('<script type="text/javascript" src="' . $nmYUIBase . 'autocomplete/autocomplete-min.js"></script>' . "\n");
|
173 | | - $wgOut->addScript('<script type="text/javascript" src="' . $nmScriptPath . '/libs/NM_yui_autocompletion.js"></script>' . "\n");
|
174 | | -
|
175 | | - $pages = array();
|
176 | | - if($smwgNMDelegateUserGroup) {
|
177 | | - if($smwgNMDelegateUserGroup != "*" && !is_array($smwgNMDelegateUserGroup)) {
|
178 | | - $groups = split(",", $smwgNMDelegateUserGroup);
|
179 | | - for($i = count($groups)-1; $i>=0; --$i) {
|
180 | | - $groups[$i] = strtolower(trim(str_replace("\'", "\\\'", $groups[$i])));
|
181 | | - }
|
182 | | - }
|
183 | | - $pages = NMStorage::getDatabase()->getGroupedUsers($groups);
|
184 | | - for($i = count($pages)-1; $i>=0; --$i) {
|
185 | | - $pages[$i] = "['".str_replace("\'", "\\\'", $pages[$i])."']";
|
186 | | - }
|
187 | | - }
|
188 | | - if($smwgNMDelegateQuery) {
|
189 | | - global $smwgQDefaultNamespaces, $smwgQFeatures;
|
190 | | - $qp = new SMWQueryParser($smwgQFeatures);
|
191 | | - $qp->setDefaultNamespaces($smwgQDefaultNamespaces);
|
192 | | - $desc = $qp->getQueryDescription($smwgNMDelegateQuery);
|
193 | | -
|
194 | | - $desc->prependPrintRequest(new SMWPrintRequest(SMWPrintRequest::PRINT_THIS, ""));
|
195 | | -
|
196 | | - $query = new SMWQuery($desc, true);
|
197 | | -
|
198 | | - $query_result = smwfGetStore()->getQueryResult($query);
|
199 | | - while ($res = $query_result->getNext()) {
|
200 | | - $pages[] = "['".str_replace("\'", "\\\'", $res[0]->getNextObject()->getWikiValue())."']";
|
201 | | - }
|
202 | | - }
|
203 | | - global $smwgNMMaxAutocompleteValues;
|
204 | | - if($smwgNMMaxAutocompleteValues <= 0) {
|
205 | | - $smwgNMMaxAutocompleteValues = 10;
|
206 | | - }
|
207 | | - $wgOut->addScript('<script type="text/javascript">
|
208 | | - nmautocompletestrings = ['.join(',', $pages).'];
|
209 | | - nmMaxResultsDisplayed = '.$smwgNMMaxAutocompleteValues.';
|
210 | | - </script>');
|
211 | | - }
|
212 | | - private function getNotifyTable() {
|
213 | | - global $wgUser;
|
214 | | - $isSysop = in_array('sysop', $wgUser->getEffectiveGroups());
|
215 | | -
|
216 | | - $cols = 6;
|
217 | | - $html = '<table width="100%" class="smwtable" id="nmtable">
|
218 | | - <tr><th width="5%" onmouseover="Tip(\'Select notifications to be deleted\')">Delete?</th>
|
219 | | - <th width="20%" onmouseover="Tip(\'Name of the notification\')">Name</th>
|
220 | | - <th width="40%" onmouseover="Tip(\'Full query string, with {{#ask syntax\')" nowrap>Query String</th>
|
221 | | - <th width="5%" onmouseover="Tip(\'Report all semantic semantic attribes\\\' change of monitored pages\')" nowrap>Report All</th>
|
222 | | - <th width="5%" onmouseover="Tip(\'Show all query results with notifications\')" nowrap>Show All</th>
|
223 | | - <th width="5%" onmouseover="Tip(\'Current state of notification. Enabled?\')">Enabled?</th>';
|
224 | | - if($isSysop) {
|
225 | | - $cols ++;
|
226 | | - $html .= '<th width="20%" onmouseover="Tip(\'Add delegate users to recieve NotifyMe, separated by comma\')">Delegate</th>';
|
227 | | - }
|
228 | | - $html .= '</tr>';
|
229 | | - $notifications = SMWNotifyProcessor::getNotifications();
|
230 | | - if ($notifications != null) {
|
231 | | - foreach ($notifications as $row) {
|
232 | | - $html .= '<tr>
|
233 | | - <td><input type="checkbox" name="nmdel" value='.$row['notify_id'].'></td>
|
234 | | - <td><a target="_blank" href="'.$this->getTitle()->getFullURL( 'feed=rss&nid='.$row['notify_id'] ).'">'.$row['name'].'</a></td>
|
235 | | - <td>'.str_replace("\n", "<br/>", $row['query']).'</td>
|
236 | | - <td><input type="checkbox" '.($row['rep_all']?'checked':'').' name="nmall" value='.$row['notify_id'].'></td>
|
237 | | - <td><input type="checkbox" '.($row['show_all']?'checked':'').' name="nmsall" value='.$row['notify_id'].'></td>
|
238 | | - <td><input type="checkbox" '.($row['enable']?'checked':'').' name="nmenable" id="nmenable_'.$row['notify_id'].'" value='.$row['notify_id'].'></td>';
|
239 | | - if($isSysop) {
|
240 | | - $html .= '<td><input type="text" name="nmdelegate" id=nmd_'.$row['notify_id'].' value="'.$row['delegate'].'">
|
241 | | - <div class="page_name_auto_complete" id="nmdiv_'.$row['notify_id'].'"></div></td>';
|
242 | | - }
|
243 | | - $html .= '</tr>';
|
244 | | - }
|
245 | | - }
|
246 | | - $html .= '<tr id="nmtoolbar">
|
247 | | - <td><a href="#" onclick="notifyhelper.delall(true)">ALL</a>/<a href="#" onclick="notifyhelper.delall(false)">NONE</a> <button class="btn" onclick="notifyhelper.deleteNotify()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Delete the checked notifications\')" onmouseout="this.className=\'btn\'">Update</button></td>
|
248 | | - <td></td><td></td>
|
249 | | - <td><a href="#" onclick="notifyhelper.reportall(true)">ALL</a>/<a href="#" onclick="notifyhelper.reportall(false)">NONE</a> <button class="btn" onclick="notifyhelper.updateReportAll()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Report all semantic attributes\\\' change on checked notifications\')" onmouseout="this.className=\'btn\'">Update</button></td>
|
250 | | - <td><a href="#" onclick="notifyhelper.showall(true)">ALL</a>/<a href="#" onclick="notifyhelper.showall(false)">NONE</a> <button class="btn" onclick="notifyhelper.updateShowAll()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Show all query results with notifications\')" onmouseout="this.className=\'btn\'">Update</button></td>
|
251 | | - <td><a href="#" onclick="notifyhelper.enableall(true)">ALL</a>/<a href="#" onclick="notifyhelper.enableall(false)">NONE</a> <button class="btn" onclick="notifyhelper.updateStates()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Update the states of your notifications, enable or disable them\')" onmouseout="this.className=\'btn\'">Update</button></td>';
|
252 | | - if($isSysop)
|
253 | | - $html .= '<td><button class="btn" onclick="notifyhelper.updateDelegate()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Update delegate\')" onmouseout="this.className=\'btn\'">Update</button></td>';
|
254 | | - $html .= '</tr></table>';
|
255 | | - return $html;
|
256 | | - }
|
257 | | -
|
258 | | - // rss feed related features
|
259 | | - function rcOutputFeed( $feedFormat, $type, $id, $limit, $lastmod, $queryresult_item = false) {
|
260 | | - global $messageMemc, $wgFeedCacheTimeout;
|
261 | | - global $wgFeedClasses, $wgTitle, $wgSitename, $wgContLanguageCode;
|
262 | | -
|
263 | | - if( !isset( $wgFeedClasses[$feedFormat] ) ) {
|
264 | | - wfHttpError( 500, "Internal Server Error", "Unsupported feed type." );
|
265 | | - return false;
|
266 | | - }
|
267 | | -
|
268 | | - $timekey = wfMemcKey( 'nmfeed', $feedFormat, $type, $id, 'timestamp' );
|
269 | | - $key = wfMemcKey( 'nmfeed', $feedFormat, $type, $id, 'limit', $limit );
|
270 | | -
|
271 | | - //purge cache if requested
|
272 | | - global $wgRequest, $wgUser;
|
273 | | - $purge = $wgRequest->getVal( 'action' ) == 'purge';
|
274 | | - if ( $purge && $wgUser->isAllowed('purge') ) {
|
275 | | - $messageMemc->delete( $timekey );
|
276 | | - $messageMemc->delete( $key );
|
277 | | - }
|
278 | | -
|
279 | | - /**
|
280 | | - * Bumping around loading up diffs can be pretty slow, so where
|
281 | | - * possible we want to cache the feed output so the next visitor
|
282 | | - * gets it quick too.
|
283 | | - */
|
284 | | - $cachedFeed = false;
|
285 | | - if( ( $wgFeedCacheTimeout > 0 ) && ( $feedLastmod = $messageMemc->get( $timekey ) ) ) {
|
286 | | - /**
|
287 | | - * If the cached feed was rendered very recently, we may
|
288 | | - * go ahead and use it even if there have been edits made
|
289 | | - * since it was rendered. This keeps a swarm of requests
|
290 | | - * from being too bad on a super-frequently edited wiki.
|
291 | | - */
|
292 | | - if( time() - wfTimestamp( TS_UNIX, $feedLastmod ) < $wgFeedCacheTimeout ||
|
293 | | - wfTimestamp( TS_UNIX, $feedLastmod ) > wfTimestamp( TS_UNIX, $lastmod ) ) {
|
294 | | - wfDebug( "RC: loading feed from cache ($key; $feedLastmod; $lastmod)...\n" );
|
295 | | - $cachedFeed = $messageMemc->get( $key );
|
296 | | - } else {
|
297 | | - wfDebug( "RC: cached feed timestamp check failed ($feedLastmod; $lastmod)\n" );
|
298 | | - }
|
299 | | - }
|
300 | | -
|
301 | | - $feedTitle = $wgSitename . ' - Recent changes to ';
|
302 | | - if($type = "nid") {
|
303 | | - $dbr = wfGetDB( DB_SLAVE );
|
304 | | - $notify_name = $dbr->selectField( 'smw_nm_query', 'name', array('notify_id'=>$id), 'NotifyMeRSS' );
|
305 | | - $feedTitle .= "\"$notify_name\"";
|
306 | | - } else {
|
307 | | - $feedTitle .= "Notify Me";
|
308 | | - }
|
309 | | - $feedTitle .= ' [' . $wgContLanguageCode . ']';
|
310 | | -
|
311 | | - $feed = new $wgFeedClasses[$feedFormat](
|
312 | | - $feedTitle,
|
313 | | - 'Track the most recent changes to '.($notify_name?"\"$notify_name\"":'Notify Me').' in this feed.',
|
314 | | - $wgTitle->getFullUrl() );
|
315 | | -
|
316 | | - if( is_string( $cachedFeed ) ) {
|
317 | | - wfDebug( "RC: Outputting cached feed\n" );
|
318 | | - $feed->httpHeaders();
|
319 | | - echo $cachedFeed;
|
320 | | - } else {
|
321 | | - wfDebug( "RC: rendering new feed and caching it\n" );
|
322 | | - ob_start();
|
323 | | - $this->rcDoOutputFeed( $feed, $queryresult_item, $type, $id, $limit );
|
324 | | - $cachedFeed = ob_get_contents();
|
325 | | - ob_end_flush();
|
326 | | -
|
327 | | - $expire = 3600 * 24; # One day
|
328 | | - $messageMemc->set( $key, $cachedFeed );
|
329 | | - $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire );
|
330 | | - }
|
331 | | - return true;
|
332 | | - }
|
333 | | -
|
334 | | - function rcDoOutputFeed( &$feed, $queryresult_item, $type, $id, $limit ) {
|
335 | | - wfProfileIn( __METHOD__ );
|
336 | | -
|
337 | | - $feed->outHeader();
|
338 | | -
|
339 | | - if($queryresult_item && $type=="nid") {
|
340 | | - $dbr = wfGetDB( DB_SLAVE );
|
341 | | - $showall = $dbr->selectField( 'smw_nm_query', 'show_all', array('notify_id'=>$id), 'NotifyMeRSS' );
|
342 | | - if($showall) {
|
343 | | - $query = $dbr->selectField( 'smw_nm_query', 'query', array('notify_id'=>$id), 'NotifyMeRSS' );
|
344 | | - SMWQueryProcessor::processFunctionParams(explode("\n", $query), $querystring, $params, $printouts);
|
345 | | - $query = SMWQueryProcessor::createQuery($querystring, $params, SMWQueryProcessor::INLINE_QUERY, 'auto', $printouts);
|
346 | | - $res = smwfGetStore()->getQueryResult($query);
|
347 | | -
|
348 | | - $items = array();
|
349 | | - $labels = array();
|
350 | | - foreach ($res->getPrintRequests() as $pr) {
|
351 | | - $labels[] = $pr->getText(SMW_OUTPUT_WIKI);
|
352 | | - }
|
353 | | - $row = $res->getNext();
|
354 | | - $linker = new Linker();
|
355 | | - while ( $row !== false ) {
|
356 | | - $wikipage = $row[0]->getNextObject(); // get the object
|
357 | | - $a = new Article($wikipage->getTitle());
|
358 | | - $description = "<table style=\"width: 60em; font-size: 90%; border: 1px solid #aaaaaa; background-color: #f9f9f9; color: black; margin-bottom: 0.5em; margin-left: 1em; padding: 0.2em; clear: right; text-align:left;\"><tr><th style=\"text-align: center; background-color:#ccccff;\" colspan=\"2\"><big>".$wikipage->getText()."</big></th></tr>";
|
359 | | - $idx = 0;
|
360 | | - foreach ($row as $field) {
|
361 | | - $description .= "<tr><td>".$labels[$idx]."</td><td>";
|
362 | | - $first_value = true;
|
363 | | - while ( ($object = $field->getNextObject()) !== false ) {
|
364 | | - if ($first_value) $first_value = false; else $description .= ', ';
|
365 | | - $description .= $object->getShortText(SMW_OUTPUT_HTML, $linker);
|
366 | | - }
|
367 | | - $description .= "</td></tr>";
|
368 | | - $idx ++;
|
369 | | - }
|
370 | | - $description .= "</table>";
|
371 | | - $items[] = array ('title'=>$wikipage->getText(),'notify'=>$description,'timestamp'=>$a->getTimestamp());
|
372 | | - $row = $res->getNext();
|
373 | | - }
|
374 | | - } else {
|
375 | | - $items = NMStorage::getDatabase()->getNotifyRSS($type, $id, $limit);
|
376 | | - }
|
377 | | - } else {
|
378 | | - $items = NMStorage::getDatabase()->getNotifyRSS($type, $id, $limit);
|
379 | | - }
|
380 | | - foreach( $items as $i ) {
|
381 | | - if(isset($i['link']) && $i['link']) {
|
382 | | - $item = new FeedItem(
|
383 | | - $i['title'],
|
384 | | - $i['notify'],
|
385 | | - $i['link'],
|
386 | | - $i['timestamp']
|
387 | | - );
|
388 | | - } else {
|
389 | | - $title = Title::makeTitle( NS_MAIN, $i['title'] );
|
390 | | - $talkpage = $title->getTalkPage();
|
391 | | - $item = new FeedItem(
|
392 | | - $title->getPrefixedText(),
|
393 | | - $i['notify'],
|
394 | | - $title->getFullURL(),
|
395 | | - $i['timestamp'],
|
396 | | - "",
|
397 | | - $talkpage->getFullURL()
|
398 | | - );
|
399 | | - }
|
400 | | - $feed->outItem( $item );
|
401 | | - }
|
402 | | -
|
403 | | - $feed->outFooter();
|
404 | | - wfProfileOut( __METHOD__ );
|
405 | | - }
|
406 | | -}
|
407 | | -?> |
\ No newline at end of file |
| 2 | +<?php |
| 3 | + |
| 4 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 5 | + |
| 6 | +global $IP; |
| 7 | +require_once( $IP . "/includes/SpecialPage.php" ); |
| 8 | +require_once( "SMW_NotAjaxAccess.php" ); |
| 9 | + |
| 10 | +global $smwgNMIP; |
| 11 | + |
| 12 | +require_once( $smwgNMIP . '/includes/SMW_NotifyProcessor.php' ); |
| 13 | + |
| 14 | +/* |
| 15 | + * Standard class that is resopnsible for the creation of the Special Page |
| 16 | + */ |
| 17 | +class SMWNotifyMe extends SpecialPage { |
| 18 | + public function __construct() { |
| 19 | + parent::__construct( 'NotifyMe' ); |
| 20 | + } |
| 21 | +/* |
| 22 | + * Overloaded function that is responsible for the creation of the Special Page |
| 23 | + */ |
| 24 | + public function execute() { |
| 25 | + |
| 26 | + global $wgRequest, $wgOut, $smwgNMScriptPath, $wgUser; |
| 27 | + |
| 28 | + # Get query parameters |
| 29 | + $feedFormat = $wgRequest->getVal( 'feed' ); |
| 30 | + if ( $feedFormat == 'rss' ) { |
| 31 | + # 10 seconds server-side caching max |
| 32 | + $wgOut->setSquidMaxage( 10 ); |
| 33 | + |
| 34 | + global $smwgNMMaxFeedItems; |
| 35 | + $limit = ( $smwgNMMaxFeedItems > 0 ) ? $smwgNMMaxFeedItems : 20; |
| 36 | + |
| 37 | + $dbr = wfGetDB( DB_SLAVE ); |
| 38 | + $id = $wgRequest->getVal( 'uid' ); |
| 39 | + $type = "uid"; |
| 40 | + if ( $id ) { |
| 41 | + # Get last modified date, for client caching |
| 42 | + # Don't use this if we are using the patrol feature, patrol changes don't update the timestamp |
| 43 | + $lastmod = $dbr->selectField( 'smw_nm_rss', 'MAX(timestamp)', array( 'user_id' => $id ), 'NotifyMeRSS' ); |
| 44 | + } else { |
| 45 | + $type = "nid"; |
| 46 | + $id = $wgRequest->getVal( 'nid' ); |
| 47 | + $lastmod = $dbr->selectField( 'smw_nm_rss', 'MAX(timestamp)', array( 'notify_id' => $id ), 'NotifyMeRSS' ); |
| 48 | + } |
| 49 | + if ( $lastmod && $wgOut->checkLastModified( $lastmod ) ) { |
| 50 | + # Client cache fresh and headers sent, nothing more to do. |
| 51 | + return; |
| 52 | + } |
| 53 | + $this->rcOutputFeed( $feedFormat, $type, $id, $limit, $lastmod, true ); |
| 54 | + } else { |
| 55 | + $user_id = $wgUser->getId(); |
| 56 | + |
| 57 | + $wgOut->setPageTitle( wfMsg( 'smw_notifyme' ) ); |
| 58 | + |
| 59 | + if ( $user_id > 0 ) { |
| 60 | + $isSysop = in_array( 'sysop', $wgUser->getEffectiveGroups() ); |
| 61 | + if ( $isSysop ) { |
| 62 | + SMWNotifyMe::addAutocomplete(); |
| 63 | + } |
| 64 | + |
| 65 | + $imagepath = $smwgNMScriptPath . '/skins/images/'; |
| 66 | + |
| 67 | + $html = '<div id="nmcontent"> |
| 68 | + <div id="shade" style="display:none"></div> |
| 69 | + <div id="fullpreviewbox" style="display:none"> |
| 70 | + <div id="fullpreview"></div> |
| 71 | + <span class="nmbutton" onclick="$(\'fullpreviewbox\', \'shade\').invoke(\'toggle\')"><img src="' . $imagepath . 'delete.png"/>Close Preview</span></div> |
| 72 | + <div id="nmlayout"> |
| 73 | + <div id="querytitle" onclick="notifyhelper.switchquery()" onmouseover="Tip(\'' . wfMsg( 'smw_nm_tt_query' ) . '\')"><a id="querytitle-link" class="minusplus" href="javascript:void(0)"></a>Notify Me Query</div> |
| 74 | + <div id="querycontent">' . $this->getQueryLayout() . '</div> |
| 75 | + <div id="layouttitle" onclick="notifyhelper.switchlayout()" onmouseover="Tip(\'' . wfMsg( 'smw_nm_tt_nmm' ) . '\')"><a id="layouttitle-link" class="minusplus" href="javascript:void(0)"></a>Notify Me Manager</div> |
| 76 | + <div id="layoutcontent">' . $this->getNotifyTable() . '</div> |
| 77 | + </div> |
| 78 | + </div>'; |
| 79 | + |
| 80 | + global $wgEmailAuthentication, $wgEnableEmail; |
| 81 | + if ( $wgEnableEmail ) { |
| 82 | + if ( $wgEmailAuthentication && ( $wgUser->getEmail() != '' ) ) { |
| 83 | + if ( $wgUser->getEmailAuthenticationTimestamp() ) { |
| 84 | + $disableEmailPrefs = false; |
| 85 | + } else { |
| 86 | + $disableEmailPrefs = true; |
| 87 | + } |
| 88 | + } else { |
| 89 | + $disableEmailPrefs = false; |
| 90 | + } |
| 91 | + $eEmail = $wgUser->getOption( 'enotifyme' ); |
| 92 | + $html .= '<div class="nmmenubar"> |
| 93 | + <input id="nmemail" type="checkbox" value="1"' . ( $disableEmailPrefs ? ' disabled':'' ) . ( $eEmail ? ' checked':'' ) . '/> Enable \'Notify Me\' by E-mail '; |
| 94 | + if ( $disableEmailPrefs ) { |
| 95 | + $href = htmlspecialchars( $wgUser->getSkin()->makeSpecialUrl( 'Preferences' ) ); |
| 96 | + $text = htmlspecialchars( wfMsg( 'mypreferences' ) ); |
| 97 | + $html .= " (Please enable your email account in '<a href=\"$href\">$text</a>'. )"; |
| 98 | + } |
| 99 | + $html .= '</div>'; |
| 100 | + } |
| 101 | + |
| 102 | + $html .= '<div> |
| 103 | + RSS Feed : <input id="nmrss" size="80" type="text" title="RSS feed url" value="' . $this->getTitle()->getFullURL( 'feed=rss&uid=' . $user_id ) . '" /> |
| 104 | + <button class="btn" onclick="notifyhelper.copyToClipboard(\'nmrss\')" onmouseover="this.className=\'btn btnhov\'; Tip(\'' . wfMsg( 'smw_nm_tt_clipboard' ) . '\')" onmouseout="this.className=\'btn\'">' . wfMsg( 'smw_qi_clipboard' ) . '</button> |
| 105 | + </div>'; |
| 106 | + |
| 107 | + $html .= '<script type="text/javascript" src="' . $smwgNMScriptPath . '/scripts/NotifyMe/nm_tooltip.js"></script>'; |
| 108 | + } else { |
| 109 | + $html = '<div id="nmlayout">You have not logged in, please login first. Thanks.</div>'; |
| 110 | + } |
| 111 | + $wgOut->addHTML( $html ); |
| 112 | + } |
| 113 | + } |
| 114 | + private function getQueryLayout() { |
| 115 | + global $wgUser; |
| 116 | + $isSysop = in_array( 'sysop', $wgUser->getEffectiveGroups() ); |
| 117 | + |
| 118 | + $html = '<table style="width: 100%;"><tr><td width=40%> |
| 119 | + <table width=100%> |
| 120 | + <tr><th width=40%>Name :</th><td width=60% onmouseover="Tip(\'Name of the notification\')"><input type="text" id="nmqname"></td></tr> |
| 121 | + <tr><th nowrap>Report all :</th><td onmouseover="Tip(\'Report all semantic semantic attribes\\\' change of monitored pages\')"><input type="checkbox" checked id="nmqrall"></td></tr> |
| 122 | + <tr><th nowrap>Show all :</th><td onmouseover="Tip(\'Show all query results with notifications\')"><input type="checkbox" id="nmqsall"></td></tr>'; |
| 123 | + if ( $isSysop ) { |
| 124 | + $html .= '<tr><th nowrap>Delegate to :</th><td><input type="text" id="nmd_new" size=35> |
| 125 | + <div class="page_name_auto_complete" id="nmdiv_new"></div></td>'; |
| 126 | + } |
| 127 | + $html .= '</table></td><td width=60%><table style="width: 100%;"> |
| 128 | + <tr><th onmouseover="Tip(\'' . wfMsg( 'smw_nm_tt_qtext' ) . '\')">Query (table format, all link only)</th></tr> |
| 129 | + <tr><td onmouseover="Tip(\'Full query string, with {{#ask syntax\')"> |
| 130 | + {{#ask:<br/> |
| 131 | + <textarea id="nmquery" cols="20" rows="6"></textarea><br/> |
| 132 | + | format=table<br/> |
| 133 | + | link=all<br/> |
| 134 | + |}} |
| 135 | + </td></tr> |
| 136 | + </table> |
| 137 | + </td></tr></table> |
| 138 | + <div class="nmmenubar"> |
| 139 | + <div style="text-align:left;float:left;"> |
| 140 | + <button class="btn" onclick="notifyhelper.previewQuery()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Show full preview of your query results\')" onmouseout="this.className=\'btn\'">Preview Results</button> |
| 141 | + <button class="btn" onclick="notifyhelper.doSaveToNotify(' . $isSysop . ')" onmouseover="this.className=\'btn btnhov\'; Tip(\'Add this notification to you NotifyMe\')" onmouseout="this.className=\'btn\'">Add to NotifyMe</button> |
| 142 | + </div><div style="text-align:right;"> |
| 143 | + <button class="btn" onclick="notifyhelper.resetQuery()"onmouseout="this.className=\'btn\'" onmouseover="this.className=\'btn btnhov\'; Tip(\'Resets the entire query\')">Reset Query</button> |
| 144 | + </div></div>'; |
| 145 | + |
| 146 | + return $html; |
| 147 | + } |
| 148 | + |
| 149 | + static function addAutocomplete() { |
| 150 | + global $smwgNMDelegateQuery, $smwgNMDelegateUserGroup; |
| 151 | + if ( !$smwgNMDelegateQuery && !$smwgNMDelegateUserGroup ) return; |
| 152 | + |
| 153 | + global $wgOut, $smwgNMScriptPath; |
| 154 | + $nmScriptPath = $smwgNMScriptPath . '/specials/SMWNotifyMe'; |
| 155 | + $nmYUIBase = "http://yui.yahooapis.com/2.7.0/build/"; |
| 156 | + |
| 157 | + $wgOut->addLink( array( |
| 158 | + 'rel' => 'stylesheet', |
| 159 | + 'type' => 'text/css', |
| 160 | + 'media' => "screen, projection", |
| 161 | + 'href' => $nmScriptPath . '/skins/NM_yui_autocompletion.css' |
| 162 | + ) ); |
| 163 | + $wgOut->addScript( '<script type="text/javascript" src="' . $nmYUIBase . 'yahoo/yahoo-min.js"></script>' . "\n" ); |
| 164 | + $wgOut->addScript( '<script type="text/javascript" src="' . $nmYUIBase . 'dom/dom-min.js"></script>' . "\n" ); |
| 165 | + $wgOut->addScript( '<script type="text/javascript" src="' . $nmYUIBase . 'event/event-min.js"></script>' . "\n" ); |
| 166 | + $wgOut->addScript( '<script type="text/javascript" src="' . $nmYUIBase . 'get/get-min.js"></script>' . "\n" ); |
| 167 | + $wgOut->addScript( '<script type="text/javascript" src="' . $nmYUIBase . 'connection/connection-min.js"></script>' . "\n" ); |
| 168 | + $wgOut->addScript( '<script type="text/javascript" src="' . $nmYUIBase . 'json/json-min.js"></script>' . "\n" ); |
| 169 | + $wgOut->addScript( '<script type="text/javascript" src="' . $nmYUIBase . 'datasource/datasource-min.js"></script>' . "\n" ); |
| 170 | + $wgOut->addScript( '<script type="text/javascript" src="' . $nmYUIBase . 'autocomplete/autocomplete-min.js"></script>' . "\n" ); |
| 171 | + $wgOut->addScript( '<script type="text/javascript" src="' . $nmScriptPath . '/libs/NM_yui_autocompletion.js"></script>' . "\n" ); |
| 172 | + |
| 173 | + $pages = array(); |
| 174 | + if ( $smwgNMDelegateUserGroup ) { |
| 175 | + if ( $smwgNMDelegateUserGroup != "*" && !is_array( $smwgNMDelegateUserGroup ) ) { |
| 176 | + $groups = split( ",", $smwgNMDelegateUserGroup ); |
| 177 | + for ( $i = count( $groups ) - 1; $i >= 0; --$i ) { |
| 178 | + $groups[$i] = strtolower( trim( str_replace( "\'", "\\\'", $groups[$i] ) ) ); |
| 179 | + } |
| 180 | + } |
| 181 | + $pages = NMStorage::getDatabase()->getGroupedUsers( $groups ); |
| 182 | + for ( $i = count( $pages ) - 1; $i >= 0; --$i ) { |
| 183 | + $pages[$i] = "['" . str_replace( "\'", "\\\'", $pages[$i] ) . "']"; |
| 184 | + } |
| 185 | + } |
| 186 | + if ( $smwgNMDelegateQuery ) { |
| 187 | + global $smwgQDefaultNamespaces, $smwgQFeatures; |
| 188 | + $qp = new SMWQueryParser( $smwgQFeatures ); |
| 189 | + $qp->setDefaultNamespaces( $smwgQDefaultNamespaces ); |
| 190 | + $desc = $qp->getQueryDescription( $smwgNMDelegateQuery ); |
| 191 | + |
| 192 | + $desc->prependPrintRequest( new SMWPrintRequest( SMWPrintRequest::PRINT_THIS, "" ) ); |
| 193 | + |
| 194 | + $query = new SMWQuery( $desc, true ); |
| 195 | + |
| 196 | + $query_result = smwfGetStore()->getQueryResult( $query ); |
| 197 | + while ( $res = $query_result->getNext() ) { |
| 198 | + $pages[] = "['" . str_replace( "\'", "\\\'", $res[0]->getNextObject()->getWikiValue() ) . "']"; |
| 199 | + } |
| 200 | + } |
| 201 | + global $smwgNMMaxAutocompleteValues; |
| 202 | + if ( $smwgNMMaxAutocompleteValues <= 0 ) { |
| 203 | + $smwgNMMaxAutocompleteValues = 10; |
| 204 | + } |
| 205 | + $wgOut->addScript( '<script type="text/javascript"> |
| 206 | + nmautocompletestrings = [' . join( ',', $pages ) . ']; |
| 207 | + nmMaxResultsDisplayed = ' . $smwgNMMaxAutocompleteValues . '; |
| 208 | + </script>' ); |
| 209 | + } |
| 210 | + private function getNotifyTable() { |
| 211 | + global $wgUser; |
| 212 | + $isSysop = in_array( 'sysop', $wgUser->getEffectiveGroups() ); |
| 213 | + |
| 214 | + $cols = 6; |
| 215 | + $html = '<table width="100%" class="smwtable" id="nmtable"> |
| 216 | + <tr><th width="5%" onmouseover="Tip(\'Select notifications to be deleted\')">Delete?</th> |
| 217 | + <th width="20%" onmouseover="Tip(\'Name of the notification\')">Name</th> |
| 218 | + <th width="40%" onmouseover="Tip(\'Full query string, with {{#ask syntax\')" nowrap>Query String</th> |
| 219 | + <th width="5%" onmouseover="Tip(\'Report all semantic semantic attribes\\\' change of monitored pages\')" nowrap>Report All</th> |
| 220 | + <th width="5%" onmouseover="Tip(\'Show all query results with notifications\')" nowrap>Show All</th> |
| 221 | + <th width="5%" onmouseover="Tip(\'Current state of notification. Enabled?\')">Enabled?</th>'; |
| 222 | + if ( $isSysop ) { |
| 223 | + $cols ++; |
| 224 | + $html .= '<th width="20%" onmouseover="Tip(\'Add delegate users to recieve NotifyMe, separated by comma\')">Delegate</th>'; |
| 225 | + } |
| 226 | + $html .= '</tr>'; |
| 227 | + $notifications = SMWNotifyProcessor::getNotifications(); |
| 228 | + if ( $notifications != null ) { |
| 229 | + foreach ( $notifications as $row ) { |
| 230 | + $html .= '<tr> |
| 231 | + <td><input type="checkbox" name="nmdel" value=' . $row['notify_id'] . '></td> |
| 232 | + <td><a target="_blank" href="' . $this->getTitle()->getFullURL( 'feed=rss&nid=' . $row['notify_id'] ) . '">' . $row['name'] . '</a></td> |
| 233 | + <td>' . str_replace( "\n", "<br/>", $row['query'] ) . '</td> |
| 234 | + <td><input type="checkbox" ' . ( $row['rep_all'] ? 'checked':'' ) . ' name="nmall" value=' . $row['notify_id'] . '></td> |
| 235 | + <td><input type="checkbox" ' . ( $row['show_all'] ? 'checked':'' ) . ' name="nmsall" value=' . $row['notify_id'] . '></td> |
| 236 | + <td><input type="checkbox" ' . ( $row['enable'] ? 'checked':'' ) . ' name="nmenable" id="nmenable_' . $row['notify_id'] . '" value=' . $row['notify_id'] . '></td>'; |
| 237 | + if ( $isSysop ) { |
| 238 | + $html .= '<td><input type="text" name="nmdelegate" id=nmd_' . $row['notify_id'] . ' value="' . $row['delegate'] . '"> |
| 239 | + <div class="page_name_auto_complete" id="nmdiv_' . $row['notify_id'] . '"></div></td>'; |
| 240 | + } |
| 241 | + $html .= '</tr>'; |
| 242 | + } |
| 243 | + } |
| 244 | + $html .= '<tr id="nmtoolbar"> |
| 245 | + <td><a href="#" onclick="notifyhelper.delall(true)">ALL</a>/<a href="#" onclick="notifyhelper.delall(false)">NONE</a> <button class="btn" onclick="notifyhelper.deleteNotify()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Delete the checked notifications\')" onmouseout="this.className=\'btn\'">Update</button></td> |
| 246 | + <td></td><td></td> |
| 247 | + <td><a href="#" onclick="notifyhelper.reportall(true)">ALL</a>/<a href="#" onclick="notifyhelper.reportall(false)">NONE</a> <button class="btn" onclick="notifyhelper.updateReportAll()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Report all semantic attributes\\\' change on checked notifications\')" onmouseout="this.className=\'btn\'">Update</button></td> |
| 248 | + <td><a href="#" onclick="notifyhelper.showall(true)">ALL</a>/<a href="#" onclick="notifyhelper.showall(false)">NONE</a> <button class="btn" onclick="notifyhelper.updateShowAll()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Show all query results with notifications\')" onmouseout="this.className=\'btn\'">Update</button></td> |
| 249 | + <td><a href="#" onclick="notifyhelper.enableall(true)">ALL</a>/<a href="#" onclick="notifyhelper.enableall(false)">NONE</a> <button class="btn" onclick="notifyhelper.updateStates()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Update the states of your notifications, enable or disable them\')" onmouseout="this.className=\'btn\'">Update</button></td>'; |
| 250 | + if ( $isSysop ) |
| 251 | + $html .= '<td><button class="btn" onclick="notifyhelper.updateDelegate()" onmouseover="this.className=\'btn btnhov\'; Tip(\'Update delegate\')" onmouseout="this.className=\'btn\'">Update</button></td>'; |
| 252 | + $html .= '</tr></table>'; |
| 253 | + return $html; |
| 254 | + } |
| 255 | + |
| 256 | + // rss feed related features |
| 257 | + function rcOutputFeed( $feedFormat, $type, $id, $limit, $lastmod, $queryresult_item = false ) { |
| 258 | + global $messageMemc, $wgFeedCacheTimeout; |
| 259 | + global $wgFeedClasses, $wgTitle, $wgSitename, $wgContLanguageCode; |
| 260 | + |
| 261 | + if ( !isset( $wgFeedClasses[$feedFormat] ) ) { |
| 262 | + wfHttpError( 500, "Internal Server Error", "Unsupported feed type." ); |
| 263 | + return false; |
| 264 | + } |
| 265 | + |
| 266 | + $timekey = wfMemcKey( 'nmfeed', $feedFormat, $type, $id, 'timestamp' ); |
| 267 | + $key = wfMemcKey( 'nmfeed', $feedFormat, $type, $id, 'limit', $limit ); |
| 268 | + |
| 269 | + // purge cache if requested |
| 270 | + global $wgRequest, $wgUser; |
| 271 | + $purge = $wgRequest->getVal( 'action' ) == 'purge'; |
| 272 | + if ( $purge && $wgUser->isAllowed( 'purge' ) ) { |
| 273 | + $messageMemc->delete( $timekey ); |
| 274 | + $messageMemc->delete( $key ); |
| 275 | + } |
| 276 | + |
| 277 | + /** |
| 278 | + * Bumping around loading up diffs can be pretty slow, so where |
| 279 | + * possible we want to cache the feed output so the next visitor |
| 280 | + * gets it quick too. |
| 281 | + */ |
| 282 | + $cachedFeed = false; |
| 283 | + if ( ( $wgFeedCacheTimeout > 0 ) && ( $feedLastmod = $messageMemc->get( $timekey ) ) ) { |
| 284 | + /** |
| 285 | + * If the cached feed was rendered very recently, we may |
| 286 | + * go ahead and use it even if there have been edits made |
| 287 | + * since it was rendered. This keeps a swarm of requests |
| 288 | + * from being too bad on a super-frequently edited wiki. |
| 289 | + */ |
| 290 | + if ( time() - wfTimestamp( TS_UNIX, $feedLastmod ) < $wgFeedCacheTimeout || |
| 291 | + wfTimestamp( TS_UNIX, $feedLastmod ) > wfTimestamp( TS_UNIX, $lastmod ) ) { |
| 292 | + wfDebug( "RC: loading feed from cache ($key; $feedLastmod; $lastmod)...\n" ); |
| 293 | + $cachedFeed = $messageMemc->get( $key ); |
| 294 | + } else { |
| 295 | + wfDebug( "RC: cached feed timestamp check failed ($feedLastmod; $lastmod)\n" ); |
| 296 | + } |
| 297 | + } |
| 298 | + |
| 299 | + $feedTitle = $wgSitename . ' - Recent changes to '; |
| 300 | + if ( $type = "nid" ) { |
| 301 | + $dbr = wfGetDB( DB_SLAVE ); |
| 302 | + $notify_name = $dbr->selectField( 'smw_nm_query', 'name', array( 'notify_id' => $id ), 'NotifyMeRSS' ); |
| 303 | + $feedTitle .= "\"$notify_name\""; |
| 304 | + } else { |
| 305 | + $feedTitle .= "Notify Me"; |
| 306 | + } |
| 307 | + $feedTitle .= ' [' . $wgContLanguageCode . ']'; |
| 308 | + |
| 309 | + $feed = new $wgFeedClasses[$feedFormat]( |
| 310 | + $feedTitle, |
| 311 | + 'Track the most recent changes to ' . ( $notify_name ? "\"$notify_name\"":'Notify Me' ) . ' in this feed.', |
| 312 | + $wgTitle->getFullUrl() ); |
| 313 | + |
| 314 | + if ( is_string( $cachedFeed ) ) { |
| 315 | + wfDebug( "RC: Outputting cached feed\n" ); |
| 316 | + $feed->httpHeaders(); |
| 317 | + echo $cachedFeed; |
| 318 | + } else { |
| 319 | + wfDebug( "RC: rendering new feed and caching it\n" ); |
| 320 | + ob_start(); |
| 321 | + $this->rcDoOutputFeed( $feed, $queryresult_item, $type, $id, $limit ); |
| 322 | + $cachedFeed = ob_get_contents(); |
| 323 | + ob_end_flush(); |
| 324 | + |
| 325 | + $expire = 3600 * 24; # One day |
| 326 | + $messageMemc->set( $key, $cachedFeed ); |
| 327 | + $messageMemc->set( $timekey, wfTimestamp( TS_MW ), $expire ); |
| 328 | + } |
| 329 | + return true; |
| 330 | + } |
| 331 | + |
| 332 | + function rcDoOutputFeed( &$feed, $queryresult_item, $type, $id, $limit ) { |
| 333 | + wfProfileIn( __METHOD__ ); |
| 334 | + |
| 335 | + $feed->outHeader(); |
| 336 | + |
| 337 | + if ( $queryresult_item && $type == "nid" ) { |
| 338 | + $dbr = wfGetDB( DB_SLAVE ); |
| 339 | + $showall = $dbr->selectField( 'smw_nm_query', 'show_all', array( 'notify_id' => $id ), 'NotifyMeRSS' ); |
| 340 | + if ( $showall ) { |
| 341 | + $query = $dbr->selectField( 'smw_nm_query', 'query', array( 'notify_id' => $id ), 'NotifyMeRSS' ); |
| 342 | + SMWQueryProcessor::processFunctionParams( explode( "\n", $query ), $querystring, $params, $printouts ); |
| 343 | + $query = SMWQueryProcessor::createQuery( $querystring, $params, SMWQueryProcessor::INLINE_QUERY, 'auto', $printouts ); |
| 344 | + $res = smwfGetStore()->getQueryResult( $query ); |
| 345 | + |
| 346 | + $items = array(); |
| 347 | + $labels = array(); |
| 348 | + foreach ( $res->getPrintRequests() as $pr ) { |
| 349 | + $labels[] = $pr->getText( SMW_OUTPUT_WIKI ); |
| 350 | + } |
| 351 | + $row = $res->getNext(); |
| 352 | + $linker = new Linker(); |
| 353 | + while ( $row !== false ) { |
| 354 | + $wikipage = $row[0]->getNextObject(); // get the object |
| 355 | + $a = new Article( $wikipage->getTitle() ); |
| 356 | + $description = "<table style=\"width: 60em; font-size: 90%; border: 1px solid #aaaaaa; background-color: #f9f9f9; color: black; margin-bottom: 0.5em; margin-left: 1em; padding: 0.2em; clear: right; text-align:left;\"><tr><th style=\"text-align: center; background-color:#ccccff;\" colspan=\"2\"><big>" . $wikipage->getText() . "</big></th></tr>"; |
| 357 | + $idx = 0; |
| 358 | + foreach ( $row as $field ) { |
| 359 | + $description .= "<tr><td>" . $labels[$idx] . "</td><td>"; |
| 360 | + $first_value = true; |
| 361 | + while ( ( $object = $field->getNextObject() ) !== false ) { |
| 362 | + if ( $first_value ) $first_value = false; else $description .= ', '; |
| 363 | + $description .= $object->getShortText( SMW_OUTPUT_HTML, $linker ); |
| 364 | + } |
| 365 | + $description .= "</td></tr>"; |
| 366 | + $idx ++; |
| 367 | + } |
| 368 | + $description .= "</table>"; |
| 369 | + $items[] = array ( 'title' => $wikipage->getText(), 'notify' => $description, 'timestamp' => $a->getTimestamp() ); |
| 370 | + $row = $res->getNext(); |
| 371 | + } |
| 372 | + } else { |
| 373 | + $items = NMStorage::getDatabase()->getNotifyRSS( $type, $id, $limit ); |
| 374 | + } |
| 375 | + } else { |
| 376 | + $items = NMStorage::getDatabase()->getNotifyRSS( $type, $id, $limit ); |
| 377 | + } |
| 378 | + foreach ( $items as $i ) { |
| 379 | + if ( isset( $i['link'] ) && $i['link'] ) { |
| 380 | + $item = new FeedItem( |
| 381 | + $i['title'], |
| 382 | + $i['notify'], |
| 383 | + $i['link'], |
| 384 | + $i['timestamp'] |
| 385 | + ); |
| 386 | + } else { |
| 387 | + $title = Title::makeTitle( NS_MAIN, $i['title'] ); |
| 388 | + $talkpage = $title->getTalkPage(); |
| 389 | + $item = new FeedItem( |
| 390 | + $title->getPrefixedText(), |
| 391 | + $i['notify'], |
| 392 | + $title->getFullURL(), |
| 393 | + $i['timestamp'], |
| 394 | + "", |
| 395 | + $talkpage->getFullURL() |
| 396 | + ); |
| 397 | + } |
| 398 | + $feed->outItem( $item ); |
| 399 | + } |
| 400 | + |
| 401 | + $feed->outFooter(); |
| 402 | + wfProfileOut( __METHOD__ ); |
| 403 | + } |
| 404 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/specials/SMWNotifyMe/SMWNotifyMe.php |
___________________________________________________________________ |
Name: svn:eol-style |
408 | 405 | + native |
Index: trunk/extensions/SemanticNotifyMe/INSTALL |
— | — | @@ -1,18 +1,18 @@ |
2 | | -== Requirements ==
|
3 | | -
|
4 | | -* MediaWiki 1.13.5
|
5 | | -* Semantic MediaWiki 1.4.2
|
6 | | -* PHP 5.x or greater installed and working
|
7 | | -* MySQL >= 4.0.14 (version required by MediaWiki)
|
8 | | -* Halo extension 1.4.4 (optional)
|
9 | | -
|
10 | | -== Installation ==
|
11 | | -
|
12 | | -Edit $IP/LocalSettings.php and add:
|
13 | | -
|
14 | | - include_once('extensions/SemanticNotifyMe/includes/SNM_Initialize.php');
|
15 | | -
|
16 | | -Apply this patch, $IP/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php
|
17 | | -line 1268, add the following
|
18 | | - $title = Title::makeTitle(NS_SPECIAL, 'SMWNotifyMe');
|
19 | | - $updatejobs[] = new SMWNMRefreshJob($title);
|
| 2 | +== Requirements == |
| 3 | + |
| 4 | +* MediaWiki 1.13.5 |
| 5 | +* Semantic MediaWiki 1.4.2 |
| 6 | +* PHP 5.x or greater installed and working |
| 7 | +* MySQL >= 4.0.14 (version required by MediaWiki) |
| 8 | +* Halo extension 1.4.4 (optional) |
| 9 | + |
| 10 | +== Installation == |
| 11 | + |
| 12 | +Edit $IP/LocalSettings.php and add: |
| 13 | + |
| 14 | + include_once('extensions/SemanticNotifyMe/includes/SNM_Initialize.php'); |
| 15 | + |
| 16 | +Apply this patch, $IP/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php |
| 17 | +line 1268, add the following |
| 18 | + $title = Title::makeTitle(NS_SPECIAL, 'SMWNotifyMe'); |
| 19 | + $updatejobs[] = new SMWNMRefreshJob($title); |
Property changes on: trunk/extensions/SemanticNotifyMe/INSTALL |
___________________________________________________________________ |
Name: svn:eol-style |
20 | 20 | + native |
Index: trunk/extensions/SemanticNotifyMe/RELEASE-NOTES |
— | — | @@ -1,9 +1,9 @@ |
2 | | -For a documentation of all features, see http://www.mediawiki.org/wiki/Extension:Semantic_NotifyMe
|
3 | | -
|
4 | | -== Semantic NotifyMe 0.5 ==
|
5 | | -
|
6 | | -This is a pre-alpha version of the Semantic NotifyMe extensions.
|
7 | | -It includes:
|
8 | | -
|
9 | | -* support for realtime notification on Semantic property/value changing
|
10 | | -* Special:NotifyMe, manage all NotifyMe notifications, delegation enabled
|
| 2 | +For a documentation of all features, see http://www.mediawiki.org/wiki/Extension:Semantic_NotifyMe |
| 3 | + |
| 4 | +== Semantic NotifyMe 0.5 == |
| 5 | + |
| 6 | +This is a pre-alpha version of the Semantic NotifyMe extensions. |
| 7 | +It includes: |
| 8 | + |
| 9 | +* support for realtime notification on Semantic property/value changing |
| 10 | +* Special:NotifyMe, manage all NotifyMe notifications, delegation enabled |
Property changes on: trunk/extensions/SemanticNotifyMe/RELEASE-NOTES |
___________________________________________________________________ |
Name: svn:eol-style |
11 | 11 | + native |
Index: trunk/extensions/SemanticNotifyMe/includes/SMW_NotifyProcessor.php |
— | — | @@ -1,1655 +1,1655 @@ |
2 | | -<?php
|
3 | | -/**
|
4 | | - * This file contains a static class for accessing functions to generate and execute
|
5 | | - * notify me semantic queries and to serialise their results.
|
6 | | - *
|
7 | | - * @author dch
|
8 | | - */
|
9 | | -
|
10 | | -global $smwgIP, $smwgNMIP ;
|
11 | | -require_once($smwgIP . '/includes/storage/SMW_Store.php');
|
12 | | -require_once( $smwgNMIP . '/includes/SMW_NMStorage.php' );
|
13 | | -
|
14 | | -/**
|
15 | | - * Static class for accessing functions to generate and execute semantic queries
|
16 | | - * and to serialise their results.
|
17 | | - */
|
18 | | -class SMWNotifyProcessor {
|
19 | | -
|
20 | | - static public function getNotifications() {
|
21 | | - $sStore = NMStorage::getDatabase();
|
22 | | - global $wgUser;
|
23 | | - $user_id = $wgUser->getId();
|
24 | | -
|
25 | | - $notifications = $sStore->getNotifications($user_id);
|
26 | | -
|
27 | | - return $notifications;
|
28 | | - }
|
29 | | -
|
30 | | - /**
|
31 | | - * Enable a NotifyMe with specified id and querystring
|
32 | | - *
|
33 | | - * used for inline query only
|
34 | | - */
|
35 | | - static public function enableNotify($notify_id, $querystring, &$msg = NULL) {
|
36 | | - wfProfileIn('SMWNotifyProcessor::enableNotify (SMW)');
|
37 | | -
|
38 | | - $sStore = NMStorage::getDatabase();
|
39 | | - global $smwgQDefaultNamespaces;
|
40 | | -
|
41 | | - SMWQueryProcessor::processFunctionParams(SMWNotifyProcessor::getQueryRawParams($querystring),$querystring,$params,$printouts);
|
42 | | - $relatedArticles = array();
|
43 | | - foreach($printouts as $po) {
|
44 | | - if($po == $params['sort']) $sorted = true;
|
45 | | - $printoutArticles[] = array(
|
46 | | - 'namespace' => SMW_NS_PROPERTY,
|
47 | | - 'title' => Title::makeTitle( SMW_NS_PROPERTY, $po->getText() )->getDBkey());
|
48 | | - }
|
49 | | - if(!$sorted && isset($params['sort'])) {
|
50 | | - $printoutArticles[] = array(
|
51 | | - 'namespace' => SMW_NS_PROPERTY,
|
52 | | - 'title' => Title::makeTitle( SMW_NS_PROPERTY, $params['sort'] )->getDBkey());
|
53 | | - }
|
54 | | -
|
55 | | - $qp = new SMWNotifyParser($notify_id, $printoutArticles);
|
56 | | - $qp->setDefaultNamespaces($smwgQDefaultNamespaces);
|
57 | | - $desc = $qp->getQueryDescription($querystring);
|
58 | | -
|
59 | | - if(!$qp->m_result) {
|
60 | | - $qp->m_errors[] = "The category / instance / property page in query may not exists.";
|
61 | | - }
|
62 | | -
|
63 | | - if(isset($msg) && $qp->hasSubquery()) {
|
64 | | - $msg .= "\nThe query contains subquery, which may affect the precision of notifications.";
|
65 | | - }
|
66 | | -
|
67 | | - $query = new SMWQuery($desc, true, false);
|
68 | | - $query->setQueryString($querystring);
|
69 | | - $query->addErrors($qp->getErrors()); // keep parsing errors for later output
|
70 | | -
|
71 | | - $res = $sStore->getNMQueryResult($query);
|
72 | | -
|
73 | | - if(count($query->getErrors())>0) {
|
74 | | - if(isset($msg)) {
|
75 | | - $msg .= "\n\n" . implode('\n', $query->getErrors()) . "\n\nYou can enable the query in NotifyMe manager later.";
|
76 | | - }
|
77 | | - $sStore->disableNotifyState($notify_id);
|
78 | | - wfProfileOut('SMWNotifyProcessor::enableNotify (SMW)');
|
79 | | - return false;
|
80 | | - }
|
81 | | -
|
82 | | - $sStore->updateNMSql($notify_id, $res['sql'], $res['tmp_hierarchy']);
|
83 | | - if (count($res['page_ids']) > 0) {
|
84 | | - $add_monitor = array();
|
85 | | - foreach($res['page_ids'] as $page_id) {
|
86 | | - $add_monitor[] = array('notify_id'=>$notify_id, 'page_id'=>$page_id);
|
87 | | - }
|
88 | | - $sStore->addNotifyMonitor($add_monitor);
|
89 | | - }
|
90 | | - $sStore->updateNotifyState($notify_id, 1);
|
91 | | - wfProfileOut('SMWNotifyProcessor::enableNotify (SMW)');
|
92 | | -
|
93 | | - return true;
|
94 | | - }
|
95 | | -
|
96 | | - static public function getQueryRawParams($querystring){
|
97 | | - // read query with printouts and (possibly) other parameters like sort, order, limit, etc...
|
98 | | - $pos = strpos($querystring, "|?");
|
99 | | - if ($pos > 0) {
|
100 | | - $rawparams[] = trim(substr($querystring, 0, $pos));
|
101 | | - $ps = explode("|?", trim(substr($querystring, $pos+2)));
|
102 | | - foreach ($ps as $param) {
|
103 | | - $rawparams[] = "?" . trim($param);
|
104 | | - }
|
105 | | - } else {
|
106 | | - $ps = preg_split('/[^\|]{1}\|{1}(?!\|)/s', $querystring);
|
107 | | - if (count($ps) > 1) {
|
108 | | - // last char of query condition is missing (matched with [^\|]{1}) therefore copy from original
|
109 | | - $rawparams[] = trim(substr($querystring, 0, strlen($ps[0]) + 1));
|
110 | | - array_shift($ps); // remove the query condition
|
111 | | - // add other params for formating etc.
|
112 | | - foreach ($ps as $param)
|
113 | | - $rawparams[] = trim($param);
|
114 | | - } // no single pipe found, no params specified in query
|
115 | | - else $rawparams[] = trim($querystring);
|
116 | | - }
|
117 | | - $rawparams[] = "format=table";
|
118 | | - $rawparams[] = "link=all";
|
119 | | - return $rawparams;
|
120 | | - }
|
121 | | -
|
122 | | - static public function addNotify($rawquery, $name, $rep_all, $show_all, $delegate) {
|
123 | | - global $wgTitle;
|
124 | | - // Take care at least of some templates -- for better template support use #ask
|
125 | | - $parser = new Parser();
|
126 | | - $parserOptions = new ParserOptions();
|
127 | | - $parser->startExternalParse( $wgTitle, $parserOptions, OT_HTML );
|
128 | | - $rawquery = $parser->transformMsg( $rawquery, $parserOptions );
|
129 | | -
|
130 | | - wfProfileIn('SMWNotifyProcessor::createNotify (SMW)');
|
131 | | - $sStore = NMStorage::getDatabase();
|
132 | | - global $wgUser;
|
133 | | - $user_id = $wgUser->getId();
|
134 | | - if($user_id == 0) {
|
135 | | - wfProfileOut('SMWNotifyProcessor::createNotify (SMW)');
|
136 | | - return "You have not logged in yet, please log in and retry again. Thanks.";
|
137 | | - }
|
138 | | -
|
139 | | - // check notify query first, use QueryParser from SMW
|
140 | | - SMWQueryProcessor::processFunctionParams(SMWNotifyProcessor::getQueryRawParams($rawquery),$querystring,$params,$printouts);
|
141 | | -
|
142 | | - $qp = new SMWQueryParser();
|
143 | | - $qp->setDefaultNamespaces($smwgQDefaultNamespaces);
|
144 | | - $desc = $qp->getQueryDescription($querystring);
|
145 | | -
|
146 | | - if(count($qp->getErrors())>0) {
|
147 | | - wfProfileOut('SMWNotifyProcessor::createNotify (SMW)');
|
148 | | - return "Notify create failed!\n\n" . implode('\n', $qp->getErrors()) . "\n\nPlease check the query and retry again";
|
149 | | - }
|
150 | | -
|
151 | | - $notify_id = $sStore->addNotifyQuery($user_id, $rawquery, $name, $rep_all, $show_all, $delegate);
|
152 | | - if($notify_id == 0) {
|
153 | | - wfProfileOut('SMWNotifyProcessor::createNotify (SMW)');
|
154 | | - return "Fail to save query. Please retry later...";
|
155 | | - }
|
156 | | - wfProfileOut('SMWNotifyProcessor::createNotify (SMW)');
|
157 | | -
|
158 | | - wfProfileIn('SMWNotifyProcessor::enableNotify (SMW)');
|
159 | | - $msg = '';
|
160 | | - $result = SMWNotifyProcessor::enableNotify($notify_id, $rawquery, $msg);
|
161 | | - wfProfileOut('SMWNotifyProcessor::enableNotify (SMW)');
|
162 | | - return "1".($result?"1":"0")."$notify_id,$msg";
|
163 | | - }
|
164 | | -
|
165 | | - static public function updateStates($notify_ids) {
|
166 | | - wfProfileIn('SMWNotifyProcessor::updateStates (SMW)');
|
167 | | -
|
168 | | - $notifications = SMWNotifyProcessor::getNotifications();
|
169 | | - if ($notifications == null || !is_array($notifications)) {
|
170 | | - return "No notifications available.";
|
171 | | - }
|
172 | | - $result = true;
|
173 | | - $idx = 0;
|
174 | | - $count = count($notify_ids) - 1;
|
175 | | - $msg = '';
|
176 | | - $errs = '';
|
177 | | - $sStore = NMStorage::getDatabase();
|
178 | | - foreach ($notifications as $row) {
|
179 | | - if(($idx<$count) && ($notify_ids[$idx]==$row['notify_id'])) {
|
180 | | - if($row['enable']==0) {
|
181 | | - $m = '';
|
182 | | - $r = SMWNotifyProcessor::enableNotify($row['notify_id'], $row['query'], $m);
|
183 | | - if(!$r) {
|
184 | | - $msg .= "NotifyMe : '" . $row['name'] . "'$m\n\n";
|
185 | | - $errs .= $row['notify_id'] . ",";
|
186 | | - $result = false;
|
187 | | - }
|
188 | | - }
|
189 | | - $idx ++;
|
190 | | - } else {
|
191 | | - if($row['enable']==1) {
|
192 | | - $result = $sStore->disableNotifyState($row['notify_id']);
|
193 | | - }
|
194 | | - }
|
195 | | - }
|
196 | | -
|
197 | | - wfProfileOut('SMWNotifyProcessor::updateStates (SMW)');
|
198 | | - return $result ? "States updated successfully!" : "0$errs|\n\n$msg";
|
199 | | - }
|
200 | | -
|
201 | | - static public function updateDelegates($delegates) {
|
202 | | - wfProfileIn('SMWNotifyProcessor::updateDelegates (SMW)');
|
203 | | -
|
204 | | - $notifications = SMWNotifyProcessor::getNotifications();
|
205 | | - if ($notifications == null || !is_array($notifications)) {
|
206 | | - return "No notifications available.";
|
207 | | - }
|
208 | | - $result = true;
|
209 | | - $idx = 0;
|
210 | | - $s = explode(':', $delegates[$idx], 2);
|
211 | | - $count = count($delegates) - 1;
|
212 | | - $sStore = NMStorage::getDatabase();
|
213 | | - foreach ($notifications as $row) {
|
214 | | - if(($idx<$count) && ($s[0]==$row['notify_id'])) {
|
215 | | - $result = $sStore->updateDelegate($row['notify_id'], $s[1]);
|
216 | | - $idx ++;
|
217 | | - $s = explode(':', $delegates[$idx], 2);
|
218 | | - } else {
|
219 | | - $result = $sStore->updateDelegate($row['notify_id'], '');
|
220 | | - }
|
221 | | - if(!$result) break;
|
222 | | - }
|
223 | | -
|
224 | | - wfProfileOut('SMWNotifyProcessor::updateDelegates (SMW)');
|
225 | | - return $result ? "Delegates updated successfully!" : "Delegates updated error!";
|
226 | | - }
|
227 | | -
|
228 | | - static public function refreshNotifyMe() {
|
229 | | - wfProfileIn('SMWNotifyProcessor::refreshNotifyMe (SMW)');
|
230 | | - $notifications = NMStorage::getDatabase()->getAllNotifications();
|
231 | | - foreach ($notifications as $row) {
|
232 | | - if($row['enable']) {
|
233 | | - $result = SMWNotifyProcessor::enableNotify($row['notify_id'], $row['query']);
|
234 | | - }
|
235 | | - }
|
236 | | - wfProfileOut('SMWNotifyProcessor::refreshNotifyMe (SMW)');
|
237 | | - }
|
238 | | -
|
239 | | - static public function updateReportAll($notify_ids) {
|
240 | | - wfProfileIn('SMWNotifyProcessor::updateStates (SMW)');
|
241 | | -
|
242 | | - $notifications = SMWNotifyProcessor::getNotifications();
|
243 | | - if ($notifications == null || !is_array($notifications)) {
|
244 | | - return "No notifications available.";
|
245 | | - }
|
246 | | - $result = true;
|
247 | | - $idx = 0;
|
248 | | - $count = count($notify_ids) - 1;
|
249 | | - $sStore = NMStorage::getDatabase();
|
250 | | - foreach ($notifications as $row) {
|
251 | | - if(($idx<$count) && ($notify_ids[$idx]==$row['notify_id'])) {
|
252 | | - if($row['rep_all']==0) {
|
253 | | - $result = $sStore->updateNotifyReportAll($row['notify_id'], 1);
|
254 | | - }
|
255 | | - $idx ++;
|
256 | | - } else {
|
257 | | - if($row['rep_all']==1) {
|
258 | | - $result = $sStore->updateNotifyReportAll($row['notify_id'], 0);
|
259 | | - }
|
260 | | - }
|
261 | | - if(!$result) break;
|
262 | | - }
|
263 | | -
|
264 | | - wfProfileOut('SMWNotifyProcessor::updateStates (SMW)');
|
265 | | - return $result ? "States updated successfully!" : "States updated error!";
|
266 | | - }
|
267 | | -
|
268 | | - static public function updateShowAll($notify_ids) {
|
269 | | - wfProfileIn('SMWNotifyProcessor::updateStates (SMW)');
|
270 | | -
|
271 | | - $notifications = SMWNotifyProcessor::getNotifications();
|
272 | | - if ($notifications == null || !is_array($notifications)) {
|
273 | | - return "No notifications available.";
|
274 | | - }
|
275 | | - $result = true;
|
276 | | - $idx = 0;
|
277 | | - $count = count($notify_ids) - 1;
|
278 | | - $sStore = NMStorage::getDatabase();
|
279 | | - foreach ($notifications as $row) {
|
280 | | - if(($idx<$count) && ($notify_ids[$idx]==$row['notify_id'])) {
|
281 | | - if($row['show_all']==0) {
|
282 | | - $result = $sStore->updateNotifyShowAll($row['notify_id'], 1);
|
283 | | - }
|
284 | | - $idx ++;
|
285 | | - } else {
|
286 | | - if($row['show_all']==1) {
|
287 | | - $result = $sStore->updateNotifyShowAll($row['notify_id'], 0);
|
288 | | - }
|
289 | | - }
|
290 | | - if(!$result) break;
|
291 | | - }
|
292 | | -
|
293 | | - wfProfileOut('SMWNotifyProcessor::updateStates (SMW)');
|
294 | | - return $result ? "States updated successfully!" : "States updated error!";
|
295 | | - }
|
296 | | -
|
297 | | - static public function delNotify($notify_ids) {
|
298 | | - wfProfileIn('SMWNotifyProcessor::delNotify (SMW)');
|
299 | | - $sStore = NMStorage::getDatabase();
|
300 | | - $result = $sStore->removeNotifyQuery($notify_ids);
|
301 | | - wfProfileOut('SMWNotifyProcessor::delNotify (SMW)');
|
302 | | - return $result ? "Notification(s) deleted successfully!" : "Notification(s) deleted error!";
|
303 | | - }
|
304 | | -
|
305 | | - static protected $notifyJobs = array();
|
306 | | - static public function prepareArticleSave($title) {
|
307 | | - $page_id = $title->getArticleID();
|
308 | | - if($page_id == 0) {
|
309 | | - return;
|
310 | | - }
|
311 | | - $updates = SMWNotifyProcessor::$notifyJobs[$page_id];
|
312 | | - if(empty($updates)) {
|
313 | | - SMWNotifyProcessor::$notifyJobs[$page_id] = new SMWNotifyUpdate($title);
|
314 | | - }
|
315 | | - }
|
316 | | - static public function articleSavedComplete($title) {
|
317 | | - $page_id = $title->getArticleID();
|
318 | | - if($page_id == 0) {
|
319 | | - return;
|
320 | | - }
|
321 | | - $updates = SMWNotifyProcessor::$notifyJobs[$page_id];
|
322 | | - if(empty($updates)) {
|
323 | | - SMWNotifyProcessor::$notifyJobs[$page_id] = new SMWNotifyUpdate($title);
|
324 | | - $updates = SMWNotifyProcessor::$notifyJobs[$page_id];
|
325 | | - } else {
|
326 | | - $updates->executeNotifyUpdate();
|
327 | | - }
|
328 | | - $updates->updateNotifyMonitor();
|
329 | | - $updates->notifyUsers();
|
330 | | - unset(SMWNotifyProcessor::$notifyJobs[$page_id]);
|
331 | | - }
|
332 | | - static public function articleDelete($title, $reason) {
|
333 | | - $page_id = $title->getArticleID();
|
334 | | - if($page_id == 0) {
|
335 | | - return;
|
336 | | - }
|
337 | | - $updates = new SMWNotifyUpdate($title);
|
338 | | - $updates->executeNotifyDelete($reason);
|
339 | | - }
|
340 | | - static public function toInfoId($type, $subquery, $attr_id) {
|
341 | | - return base_convert(strval(($subquery << 8)|$type), 10, 9).'9'.$attr_id;
|
342 | | - }
|
343 | | - static public function getInfoFromId($id) {
|
344 | | - $idx = strpos($id, '9');
|
345 | | - $t = intval(base_convert(substr($id, 0, $idx), 9, 10));
|
346 | | - return array(
|
347 | | - 'type'=>$t&0xFF,
|
348 | | - 'subquery'=>$t>>8,
|
349 | | - 'attr_id'=>intval(substr($id, $idx+1))
|
350 | | - );
|
351 | | - }
|
352 | | -
|
353 | | -}
|
354 | | -
|
355 | | -// based on SMW_QueryProcessor.php (v 1.4.2)
|
356 | | -/**
|
357 | | - * Objects of this class are in charge of parsing a query string in order
|
358 | | - * to create an SMWDescription. The class and methods are not static in order
|
359 | | - * to more cleanly store the intermediate state and progress of the parser.
|
360 | | - */
|
361 | | -class SMWNotifyParser {
|
362 | | -
|
363 | | - protected $m_sepstack; // list of open blocks ("parentheses") that need closing at current step
|
364 | | - protected $m_curstring; // remaining string to be parsed (parsing eats query string from the front)
|
365 | | - var $m_errors; // empty array if all went right, array of strings otherwise
|
366 | | - protected $m_label; //label of the main query result
|
367 | | - protected $m_defaultns; //description of the default namespace restriction, or NULL if not used
|
368 | | -
|
369 | | - protected $m_categoryprefix; // cache label of category namespace . ':'
|
370 | | - protected $m_conceptprefix; // cache label of concept namespace . ':'
|
371 | | - protected $m_queryfeatures; // query features to be supported, format similar to $smwgQFeatures
|
372 | | -
|
373 | | - // added by dch
|
374 | | - protected $m_notify_id;
|
375 | | - protected $m_subquery;
|
376 | | - protected $m_printoutArticles;
|
377 | | - public $m_result;
|
378 | | -
|
379 | | - // modified by dch
|
380 | | - public function SMWNotifyParser($notify_id, $printoutArticles, $queryfeatures = false) {
|
381 | | - $this->m_notify_id = $notify_id;
|
382 | | - $this->m_printoutArticles = $printoutArticles;
|
383 | | - $this->m_result = true;
|
384 | | -
|
385 | | - global $wgContLang, $smwgQFeatures;
|
386 | | - $this->m_categoryprefix = $wgContLang->getNsText(NS_CATEGORY) . ':';
|
387 | | - $this->m_conceptprefix = $wgContLang->getNsText(SMW_NS_CONCEPT) . ':';
|
388 | | - $this->m_defaultns = NULL;
|
389 | | - $this->m_queryfeatures = $queryfeatures===false?$smwgQFeatures:$queryfeatures;
|
390 | | - }
|
391 | | -
|
392 | | - // added by dch
|
393 | | - public function hasSubquery() {
|
394 | | - return $this->m_subquery > 1;
|
395 | | - }
|
396 | | -
|
397 | | - /**
|
398 | | - * Provide an array of namespace constants that are used as default restrictions.
|
399 | | - * If NULL is given, no such default restrictions will be added (faster).
|
400 | | - */
|
401 | | - public function setDefaultNamespaces($nsarray) {
|
402 | | - $this->m_defaultns = NULL;
|
403 | | - if ($nsarray !== NULL) {
|
404 | | - foreach ($nsarray as $ns) {
|
405 | | - $this->m_defaultns = $this->addDescription($this->m_defaultns, new SMWNamespaceDescription($ns), false);
|
406 | | - }
|
407 | | - }
|
408 | | - }
|
409 | | -
|
410 | | - /**
|
411 | | - * Compute an SMWDescription from a query string. Returns whatever descriptions could be
|
412 | | - * wrestled from the given string (the most general result being SMWThingDescription if
|
413 | | - * no meaningful condition was extracted).
|
414 | | - */
|
415 | | - public function getQueryDescription($querystring) {
|
416 | | - wfProfileIn('SMWNotifyParser::getQueryDescription (SMW)');
|
417 | | - $this->m_errors = array();
|
418 | | - $this->m_label = '';
|
419 | | - $this->m_curstring = $querystring;
|
420 | | - $this->m_sepstack = array();
|
421 | | - $setNS = false;
|
422 | | -
|
423 | | - // added by dch
|
424 | | - $this->m_subquery = 0;
|
425 | | -
|
426 | | - $result = $this->getSubqueryDescription($setNS, $this->m_label);
|
427 | | - if (!$setNS) { // add default namespaces if applicable
|
428 | | - $result = $this->addDescription($this->m_defaultns, $result);
|
429 | | - }
|
430 | | - if ($result === NULL) { // parsing went wrong, no default namespaces
|
431 | | - $result = new SMWThingDescription();
|
432 | | - }
|
433 | | - wfProfileOut('SMWNotifyParser::getQueryDescription (SMW)');
|
434 | | - return $result;
|
435 | | - }
|
436 | | -
|
437 | | - /**
|
438 | | - * Return array of error messages (possibly empty).
|
439 | | - */
|
440 | | - public function getErrors() {
|
441 | | - return $this->m_errors;
|
442 | | - }
|
443 | | -
|
444 | | - /**
|
445 | | - * Return error message or empty string if no error occurred.
|
446 | | - */
|
447 | | - public function getErrorString() {
|
448 | | - return smwfEncodeMessages($this->m_errors);
|
449 | | - }
|
450 | | -
|
451 | | - /**
|
452 | | - * Return label for the results of this query (which
|
453 | | - * might be empty if no such information was passed).
|
454 | | - */
|
455 | | - public function getLabel() {
|
456 | | - return $this->m_label;
|
457 | | - }
|
458 | | -
|
459 | | -
|
460 | | - /**
|
461 | | - * Compute an SMWDescription for current part of a query, which should
|
462 | | - * be a standalone query (the main query or a subquery enclosed within
|
463 | | - * "\<q\>...\</q\>". Recursively calls similar methods and returns NULL upon error.
|
464 | | - *
|
465 | | - * The call-by-ref parameter $setNS is a boolean. Its input specifies whether
|
466 | | - * the query should set the current default namespace if no namespace restrictions
|
467 | | - * were given. If false, the calling super-query is happy to set the required
|
468 | | - * NS-restrictions by itself if needed. Otherwise the subquery has to impose the defaults.
|
469 | | - * This is so, since outermost queries and subqueries of disjunctions will have to set
|
470 | | - * their own default restrictions.
|
471 | | - *
|
472 | | - * The return value of $setNS specifies whether or not the subquery has a namespace
|
473 | | - * specification in place. This might happen automatically if the query string imposes
|
474 | | - * such restrictions. The return value is important for those callers that otherwise
|
475 | | - * set up their own restrictions.
|
476 | | - *
|
477 | | - * Note that $setNS is no means to switch on or off default namespaces in general,
|
478 | | - * but just controls query generation. For general effect, the default namespaces
|
479 | | - * should be set to NULL.
|
480 | | - *
|
481 | | - * The call-by-ref parameter $label is used to append any label strings found.
|
482 | | - */
|
483 | | - protected function getSubqueryDescription(&$setNS, &$label) {
|
484 | | - global $smwgQPrintoutLimit;
|
485 | | - wfLoadExtensionMessages('SemanticMediaWiki');
|
486 | | - $conjunction = NULL; // used for the current inner conjunction
|
487 | | - $disjuncts = array(); // (disjunctive) array of subquery conjunctions
|
488 | | - $printrequests = array(); // the printrequests found for this query level
|
489 | | - $hasNamespaces = false; // does the current $conjnuction have its own namespace restrictions?
|
490 | | - $mustSetNS = $setNS; // must ns restrictions be set? (may become true even if $setNS is false)
|
491 | | -
|
492 | | - // added by dch
|
493 | | - $subquery = $this->m_subquery;
|
494 | | - if($subquery == 0) {
|
495 | | - $relatedArticles = $this->m_printoutArticles;
|
496 | | - } else {
|
497 | | - $relatedArticles = array();
|
498 | | - }
|
499 | | - $this->m_subquery ++;
|
500 | | -
|
501 | | - $continue = ($chunk = $this->readChunk()) != ''; // skip empty subquery completely, thorwing an error
|
502 | | - while ($continue) {
|
503 | | - $setsubNS = false;
|
504 | | - switch ($chunk) {
|
505 | | - case '[[': // start new link block
|
506 | | - // modified by dch
|
507 | | - $ld = $this->getLinkDescription($setsubNS, $label, $relatedArticles);
|
508 | | -
|
509 | | - if ($ld instanceof SMWPrintRequest) {
|
510 | | - $printrequests[] = $ld;
|
511 | | - } elseif ($ld instanceof SMWDescription) {
|
512 | | - $conjunction = $this->addDescription($conjunction,$ld);
|
513 | | - }
|
514 | | - break;
|
515 | | - case '<q>': // enter new subquery, currently irrelevant but possible
|
516 | | - $this->pushDelimiter('</q>');
|
517 | | - $conjunction = $this->addDescription($conjunction, $this->getSubqueryDescription($setsubNS, $label));
|
518 | | - /// TODO: print requests from subqueries currently are ignored, should be moved down
|
519 | | - break;
|
520 | | - case 'OR': case '||': case '': case '</q>': // finish disjunction and maybe subquery
|
521 | | - if ($this->m_defaultns !== NULL) { // possibly add namespace restrictions
|
522 | | - if ( $hasNamespaces && !$mustSetNS) {
|
523 | | - // add ns restrictions to all earlier conjunctions (all of which did not have them yet)
|
524 | | - $mustSetNS = true; // enforce NS restrictions from now on
|
525 | | - $newdisjuncts = array();
|
526 | | - foreach ($disjuncts as $conj) {
|
527 | | - $newdisjuncts[] = $this->addDescription($conj, $this->m_defaultns);
|
528 | | - }
|
529 | | - $disjuncts = $newdisjuncts;
|
530 | | - } elseif ( !$hasNamespaces && $mustSetNS) {
|
531 | | - // add ns restriction to current result
|
532 | | - $conjunction = $this->addDescription($conjunction, $this->m_defaultns);
|
533 | | - }
|
534 | | - }
|
535 | | - $disjuncts[] = $conjunction;
|
536 | | - // start anew
|
537 | | - $conjunction = NULL;
|
538 | | - $hasNamespaces = false;
|
539 | | - // finish subquery?
|
540 | | - if ($chunk == '</q>') {
|
541 | | - if ($this->popDelimiter('</q>')) {
|
542 | | - $continue = false; // leave the loop
|
543 | | - } else {
|
544 | | - $this->m_errors[] = wfMsgForContent('smw_toomanyclosing', $chunk);
|
545 | | - return NULL;
|
546 | | - }
|
547 | | - } elseif ($chunk == '') {
|
548 | | - $continue = false;
|
549 | | - }
|
550 | | - break;
|
551 | | - case '+': // "... AND true" (ignore)
|
552 | | - break;
|
553 | | - default: // error: unexpected $chunk
|
554 | | - $this->m_errors[] = wfMsgForContent('smw_unexpectedpart', $chunk);
|
555 | | - //return NULL; // Try to go on, it can only get better ...
|
556 | | - }
|
557 | | - if ($setsubNS) { // namespace restrictions encountered in current conjunct
|
558 | | - $hasNamespaces = true;
|
559 | | - }
|
560 | | - if ($continue) { // read on only if $continue remained true
|
561 | | - $chunk = $this->readChunk();
|
562 | | - }
|
563 | | - }
|
564 | | -
|
565 | | - if (count($disjuncts) > 0) { // make disjunctive result
|
566 | | - $result = NULL;
|
567 | | - foreach ($disjuncts as $d) {
|
568 | | - if ($d === NULL) {
|
569 | | - $this->m_errors[] = wfMsgForContent('smw_emptysubquery');
|
570 | | - $setNS = false;
|
571 | | - return NULL;
|
572 | | - } else {
|
573 | | - $result = $this->addDescription($result, $d, false);
|
574 | | - }
|
575 | | - }
|
576 | | - } else {
|
577 | | - $this->m_errors[] = wfMsgForContent('smw_emptysubquery');
|
578 | | - $setNS = false;
|
579 | | - return NULL;
|
580 | | - }
|
581 | | - $setNS = $mustSetNS; // NOTE: also false if namespaces were given but no default NS descs are available
|
582 | | -
|
583 | | - $prcount = 0;
|
584 | | - foreach ($printrequests as $pr) { // add printrequests
|
585 | | - if ($prcount < $smwgQPrintoutLimit) {
|
586 | | - $result->addPrintRequest($pr);
|
587 | | - $prcount++;
|
588 | | - } else {
|
589 | | - $this->m_errors[] = wfMsgForContent('smw_overprintoutlimit');
|
590 | | - break;
|
591 | | - }
|
592 | | - }
|
593 | | -
|
594 | | - // added by dch
|
595 | | - if($this->m_result) {
|
596 | | - $sStore = NMStorage::getDatabase();
|
597 | | - $this->m_result = $sStore->addNotifyRelations($this->m_notify_id, $relatedArticles, $subquery);
|
598 | | - }
|
599 | | -
|
600 | | - return $result;
|
601 | | - }
|
602 | | -
|
603 | | - /**
|
604 | | - * Compute an SMWDescription for current part of a query, which should
|
605 | | - * be the content of "[[ ... ]]". Alternatively, if the current syntax
|
606 | | - * specifies a print request, return the print request object.
|
607 | | - * Returns NULL upon error.
|
608 | | - *
|
609 | | - * Parameters $setNS and $label have the same use as in getSubqueryDescription().
|
610 | | - */
|
611 | | - // modified by dch, add $relatedArticles
|
612 | | - protected function getLinkDescription(&$setNS, &$label, &$relatedArticles) {
|
613 | | - // This method is called when we encountered an opening '[['. The following
|
614 | | - // block could be a Category-statement, fixed object, property statements,
|
615 | | - // or according print statements.
|
616 | | - $chunk = $this->readChunk('',true,false); // NOTE: untrimmed, initial " " escapes prop. chains
|
617 | | - if ( (smwfNormalTitleText($chunk) == $this->m_categoryprefix) || // category statement or
|
618 | | - (smwfNormalTitleText($chunk) == $this->m_conceptprefix) ) { // concept statement
|
619 | | - return $this->getClassDescription($setNS, $label, $relatedArticles,
|
620 | | - (smwfNormalTitleText($chunk) == $this->m_categoryprefix));
|
621 | | - } else { // fixed subject, namespace restriction, property query, or subquery
|
622 | | - $sep = $this->readChunk('',false); //do not consume hit, "look ahead"
|
623 | | - if ( ($sep == '::') || ($sep == ':=') ) {
|
624 | | - if ($chunk{0} !=':') { // property statement
|
625 | | - return $this->getPropertyDescription($chunk, $setNS, $label, $relatedArticles);
|
626 | | - } else { // escaped article description, read part after :: to get full contents
|
627 | | - $chunk .= $this->readChunk('\[\[|\]\]|\|\||\|');
|
628 | | - return $this->getArticleDescription(trim($chunk), $setNS, $label, $relatedArticles);
|
629 | | - }
|
630 | | - } else { // Fixed article/namespace restriction. $sep should be ]] or ||
|
631 | | - return $this->getArticleDescription(trim($chunk), $setNS, $label, $relatedArticles);
|
632 | | - }
|
633 | | - }
|
634 | | - }
|
635 | | -
|
636 | | - /**
|
637 | | - * Parse a category description (the part of an inline query that
|
638 | | - * is in between "[[Category:" and the closing "]]" and create a
|
639 | | - * suitable description.
|
640 | | - */
|
641 | | - // modified by dch ,add $relatedArticles
|
642 | | - protected function getClassDescription(&$setNS, &$label, &$relatedArticles, $category=true) {
|
643 | | - global $smwgSMWBetaCompatible; // * printouts only for this old version
|
644 | | - // note: no subqueries allowed here, inline disjunction allowed, wildcards allowed
|
645 | | - $result = NULL;
|
646 | | - $continue = true;
|
647 | | - while ($continue) {
|
648 | | - $chunk = $this->readChunk();
|
649 | | - if ($chunk == '+') {
|
650 | | - //wildcard, ignore for categories (semantically meaningless, everything is in some class)
|
651 | | - } elseif ( ($chunk == '+') && $category && $smwgSMWBetaCompatible) { // print statement
|
652 | | - $chunk = $this->readChunk('\]\]|\|');
|
653 | | - if ($chunk == '|') {
|
654 | | - $printlabel = $this->readChunk('\]\]');
|
655 | | - if ($printlabel != ']]') {
|
656 | | - $chunk = $this->readChunk('\]\]');
|
657 | | - } else {
|
658 | | - $printlabel = '';
|
659 | | - $chunk = ']]';
|
660 | | - }
|
661 | | - } else {
|
662 | | - global $wgContLang;
|
663 | | - $printlabel = $wgContLang->getNSText(NS_CATEGORY);
|
664 | | - }
|
665 | | - if ($chunk == ']]') {
|
666 | | - return new SMWPrintRequest(SMWPrintRequest::PRINT_CATS, $printlabel);
|
667 | | - } else {
|
668 | | - $this->m_errors[] = wfMsgForContent('smw_badprintout');
|
669 | | - return NULL;
|
670 | | - }
|
671 | | - } else { //assume category/concept title
|
672 | | - /// NOTE: use m_c...prefix to prevent problems with, e.g., [[Category:Template:Test]]
|
673 | | - $class = Title::newFromText(($category?$this->m_categoryprefix:$this->m_conceptprefix) . $chunk);
|
674 | | - if ($class !== NULL) {
|
675 | | - $desc = $category?new SMWClassDescription($class):new SMWConceptDescription($class);
|
676 | | - $result = $this->addDescription($result, $desc, false);
|
677 | | - }
|
678 | | -
|
679 | | - // added by dch
|
680 | | - if($category) {
|
681 | | - $relatedArticles[] = array(
|
682 | | - 'namespace' => NS_CATEGORY,
|
683 | | - 'title' => $class->getDBkey());
|
684 | | - }
|
685 | | -
|
686 | | - }
|
687 | | - $chunk = $this->readChunk();
|
688 | | - $continue = ($chunk == '||') && $category; // disjunctions only for cateories
|
689 | | - }
|
690 | | -
|
691 | | - return $this->finishLinkDescription($chunk, false, $result, $setNS, $label);
|
692 | | - }
|
693 | | -
|
694 | | - /**
|
695 | | - * Parse a property description (the part of an inline query that
|
696 | | - * is in between "[[Some property::" and the closing "]]" and create a
|
697 | | - * suitable description. The "::" is the first chunk on the current
|
698 | | - * string.
|
699 | | - */
|
700 | | - // modified by dch ,add $relatedArticles
|
701 | | - protected function getPropertyDescription($propertyname, &$setNS, &$label, &$relatedArticles) {
|
702 | | - global $smwgSMWBetaCompatible; // support for old * printouts of beta
|
703 | | - wfLoadExtensionMessages('SemanticMediaWiki');
|
704 | | - $this->readChunk(); // consume separator ":=" or "::"
|
705 | | - // first process property chain syntax (e.g. "property1.property2::value"):
|
706 | | - if ($propertyname{0} == ' ') { // escape
|
707 | | - $propertynames = array($propertyname);
|
708 | | - } else {
|
709 | | - $propertynames = explode('.', $propertyname);
|
710 | | - }
|
711 | | - $properties = array();
|
712 | | - $typeid = '_wpg';
|
713 | | - foreach ($propertynames as $name) {
|
714 | | - if ($typeid != '_wpg') { // non-final property in chain was no wikipage: not allowed
|
715 | | - $this->m_errors[] = wfMsgForContent('smw_valuesubquery', $prevname);
|
716 | | - return NULL; ///TODO: read some more chunks and try to finish [[ ]]
|
717 | | - }
|
718 | | - $property = SMWPropertyValue::makeUserProperty($name);
|
719 | | - if (!$property->isValid()) { // illegal property identifier
|
720 | | - $this->m_errors = array_merge($this->m_errors, $property->getErrors());
|
721 | | - return NULL; ///TODO: read some more chunks and try to finish [[ ]]
|
722 | | - }
|
723 | | - $typeid = $property->getTypeID();
|
724 | | - $prevname = $name;
|
725 | | - $properties[] = $property;
|
726 | | -
|
727 | | - // added by dch
|
728 | | - $relatedArticles[] = array(
|
729 | | - 'namespace' => SMW_NS_PROPERTY,
|
730 | | - 'title' => $property->getDBkey());
|
731 | | -
|
732 | | - } ///NOTE: after iteration, $property and $typeid correspond to last value
|
733 | | -
|
734 | | - $innerdesc = NULL;
|
735 | | - $continue = true;
|
736 | | - while ($continue) {
|
737 | | - $chunk = $this->readChunk();
|
738 | | - switch ($chunk) {
|
739 | | - case '+': // wildcard, add namespaces for page-type properties
|
740 | | - if ( ($this->m_defaultns !== NULL) && ($typeid == '_wpg') ) {
|
741 | | - $innerdesc = $this->addDescription($innerdesc, $this->m_defaultns, false);
|
742 | | - } else {
|
743 | | - $innerdesc = $this->addDescription($innerdesc, new SMWThingDescription(), false);
|
744 | | - }
|
745 | | - $chunk = $this->readChunk();
|
746 | | - break;
|
747 | | - case '<q>': // subquery, set default namespaces
|
748 | | - if ($typeid == '_wpg') {
|
749 | | - $this->pushDelimiter('</q>');
|
750 | | - $setsubNS = true;
|
751 | | - $sublabel = '';
|
752 | | - $innerdesc = $this->addDescription($innerdesc, $this->getSubqueryDescription($setsubNS, $sublabel), false);
|
753 | | - } else { // no subqueries allowed for non-pages
|
754 | | - $this->m_errors[] = wfMsgForContent('smw_valuesubquery', end($propertynames));
|
755 | | - $innerdesc = $this->addDescription($innerdesc, new SMWThingDescription(), false);
|
756 | | - }
|
757 | | - $chunk = $this->readChunk();
|
758 | | - break;
|
759 | | - default: //normal object value or print statement
|
760 | | - // read value(s), possibly with inner [[...]]
|
761 | | - $open = 1;
|
762 | | - $value = $chunk;
|
763 | | - $continue2 = true;
|
764 | | - // read value with inner [[, ]], ||
|
765 | | - while ( ($open > 0) && ($continue2) ) {
|
766 | | - $chunk = $this->readChunk('\[\[|\]\]|\|\||\|');
|
767 | | - switch ($chunk) {
|
768 | | - case '[[': // open new [[ ]]
|
769 | | - $open++;
|
770 | | - break;
|
771 | | - case ']]': // close [[ ]]
|
772 | | - $open--;
|
773 | | - break;
|
774 | | - case '|': case '||': // terminates only outermost [[ ]]
|
775 | | - if ($open == 1) {
|
776 | | - $open = 0;
|
777 | | - }
|
778 | | - break;
|
779 | | - case '': ///TODO: report error; this is not good right now
|
780 | | - $continue2 = false;
|
781 | | - break;
|
782 | | - }
|
783 | | - if ($open != 0) {
|
784 | | - $value .= $chunk;
|
785 | | - }
|
786 | | - } ///NOTE: at this point, we normally already read one more chunk behind the value
|
787 | | -
|
788 | | - if ($typeid == '__nry') { // nary value
|
789 | | - $dv = SMWDataValueFactory::newPropertyObjectValue($property);
|
790 | | - $dv->acceptQuerySyntax();
|
791 | | - $dv->setUserValue($value);
|
792 | | - $vl = $dv->getValueList();
|
793 | | - $pm = $dv->getPrintModifier();
|
794 | | - if ($vl !== NULL) { // prefer conditions over print statements (only one possible right now)
|
795 | | - $innerdesc = $this->addDescription($innerdesc, $vl, false);
|
796 | | - } elseif ($pm !== false) {
|
797 | | - if ($chunk == '|') {
|
798 | | - $printlabel = $this->readChunk('\]\]');
|
799 | | - if ($printlabel != ']]') {
|
800 | | - $chunk = $this->readChunk('\]\]');
|
801 | | - } else {
|
802 | | - $printlabel = '';
|
803 | | - $chunk = ']]';
|
804 | | - }
|
805 | | - } else {
|
806 | | - $printlabel = $property->getWikiValue();
|
807 | | - }
|
808 | | - if ($chunk == ']]') {
|
809 | | - return new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, $printlabel, $property, $pm);
|
810 | | - } else {
|
811 | | - $this->m_errors[] = wfMsgForContent('smw_badprintout');
|
812 | | - return NULL;
|
813 | | - }
|
814 | | - }
|
815 | | - } else { // unary value
|
816 | | - $comparator = SMW_CMP_EQ;
|
817 | | - $printmodifier = '';
|
818 | | - SMWNotifyParser::prepareValue($value, $comparator, $printmodifier);
|
819 | | - if ( ($value == '*') && $smwgSMWBetaCompatible ) {
|
820 | | - if ($chunk == '|') {
|
821 | | - $printlabel = $this->readChunk('\]\]');
|
822 | | - if ($printlabel != ']]') {
|
823 | | - $chunk = $this->readChunk('\]\]');
|
824 | | - } else {
|
825 | | - $printlabel = '';
|
826 | | - $chunk = ']]';
|
827 | | - }
|
828 | | - } else {
|
829 | | - $printlabel = $property->getWikiValue();
|
830 | | - }
|
831 | | - if ($chunk == ']]') {
|
832 | | - return new SMWPrintRequest(SMWPrintRequest::PRINT_PROP, $printlabel, $property, $printmodifier);
|
833 | | - } else {
|
834 | | - $this->m_errors[] = wfMsgForContent('smw_badprintout');
|
835 | | - return NULL;
|
836 | | - }
|
837 | | - } else {
|
838 | | - $dv = SMWDataValueFactory::newPropertyObjectValue($property, $value);
|
839 | | - if (!$dv->isValid()) {
|
840 | | - $this->m_errors = $this->m_errors + $dv->getErrors();
|
841 | | - $vd = new SMWThingDescription();
|
842 | | - } else {
|
843 | | - $vd = new SMWValueDescription($dv, $comparator);
|
844 | | - }
|
845 | | - $innerdesc = $this->addDescription($innerdesc, $vd, false);
|
846 | | - }
|
847 | | - }
|
848 | | - }
|
849 | | - $continue = ($chunk == '||');
|
850 | | - }
|
851 | | -
|
852 | | - if ($innerdesc === NULL) { // make a wildcard search
|
853 | | - if ( ($this->m_defaultns !== NULL) && ($typeid == '_wpg') ) {
|
854 | | - $innerdesc = $this->addDescription($innerdesc, $this->m_defaultns, false);
|
855 | | - } else {
|
856 | | - $innerdesc = $this->addDescription($innerdesc, new SMWThingDescription(), false);
|
857 | | - }
|
858 | | - $this->m_errors[] = wfMsgForContent('smw_propvalueproblem', $property->getWikiValue());
|
859 | | - }
|
860 | | - $properties = array_reverse($properties);
|
861 | | - foreach ($properties as $property) {
|
862 | | - $innerdesc = new SMWSomeProperty($property,$innerdesc);
|
863 | | - }
|
864 | | - $result = $innerdesc;
|
865 | | - return $this->finishLinkDescription($chunk, false, $result, $setNS, $label);
|
866 | | - }
|
867 | | -
|
868 | | -
|
869 | | - /**
|
870 | | - * Prepare a single value string, possibly extracting comparators and
|
871 | | - * printmodifier. $value is changed to consist only of the remaining
|
872 | | - * effective value string, or of "*" for print statements.
|
873 | | - */
|
874 | | - static public function prepareValue(&$value, &$comparator, &$printmodifier) {
|
875 | | - global $smwgQComparators, $smwgSMWBetaCompatible; // support for old * printouts of beta
|
876 | | - // get print modifier behind *
|
877 | | - if ($smwgSMWBetaCompatible) {
|
878 | | - $list = preg_split('/^\*/',$value,2);
|
879 | | - if (count($list) == 2) { //hit
|
880 | | - $value = '*';
|
881 | | - $printmodifier = $list[1];
|
882 | | - } else {
|
883 | | - $printmodifier = '';
|
884 | | - }
|
885 | | - if ($value == '*') { // printout statement
|
886 | | - return;
|
887 | | - }
|
888 | | - }
|
889 | | - $list = preg_split('/^(' . $smwgQComparators . ')/u',$value, 2, PREG_SPLIT_DELIM_CAPTURE);
|
890 | | - $comparator = SMW_CMP_EQ;
|
891 | | - if (count($list) == 3) { // initial comparator found ($list[1] should be empty)
|
892 | | - switch ($list[1]) {
|
893 | | - case '<':
|
894 | | - $comparator = SMW_CMP_LEQ;
|
895 | | - $value = $list[2];
|
896 | | - break;
|
897 | | - case '>':
|
898 | | - $comparator = SMW_CMP_GEQ;
|
899 | | - $value = $list[2];
|
900 | | - break;
|
901 | | - case '!':
|
902 | | - $comparator = SMW_CMP_NEQ;
|
903 | | - $value = $list[2];
|
904 | | - break;
|
905 | | - case '~':
|
906 | | - $comparator = SMW_CMP_LIKE;
|
907 | | - $value = $list[2];
|
908 | | - break;
|
909 | | - //default: not possible
|
910 | | - }
|
911 | | - }
|
912 | | - }
|
913 | | -
|
914 | | - /**
|
915 | | - * Parse an article description (the part of an inline query that
|
916 | | - * is in between "[[" and the closing "]]" assuming it is not specifying
|
917 | | - * a category or property) and create a suitable description.
|
918 | | - * The first chunk behind the "[[" has already been read and is
|
919 | | - * passed as a parameter.
|
920 | | - */
|
921 | | - // modified by dch ,add $relatedArticles
|
922 | | - protected function getArticleDescription($firstchunk, &$setNS, &$label, &$relatedArticles) {
|
923 | | - wfLoadExtensionMessages('SemanticMediaWiki');
|
924 | | - $chunk = $firstchunk;
|
925 | | - $result = NULL;
|
926 | | - $continue = true;
|
927 | | - //$innerdesc = NULL;
|
928 | | - while ($continue) {
|
929 | | - if ($chunk == '<q>') { // no subqueries of the form [[<q>...</q>]] (not needed)
|
930 | | - $this->m_errors[] = wfMsgForContent('smw_misplacedsubquery');
|
931 | | - return NULL;
|
932 | | - }
|
933 | | - $list = preg_split('/:/', $chunk, 3); // ":Category:Foo" "User:bar" ":baz" ":+"
|
934 | | - if ( ($list[0] == '') && (count($list)==3) ) {
|
935 | | - $list = array_slice($list, 1);
|
936 | | - }
|
937 | | - if ( (count($list) == 2) && ($list[1] == '+') ) { // try namespace restriction
|
938 | | - global $wgContLang;
|
939 | | - $idx = $wgContLang->getNsIndex($list[0]);
|
940 | | - if ($idx !== false) {
|
941 | | - $result = $this->addDescription($result, new SMWNamespaceDescription($idx), false);
|
942 | | - }
|
943 | | - } else {
|
944 | | - $value = SMWDataValueFactory::newTypeIDValue('_wpg', $chunk);
|
945 | | - if ($value->isValid()) {
|
946 | | - $result = $this->addDescription($result, new SMWValueDescription($value), false);
|
947 | | - // added by dch
|
948 | | - $relatedArticles[] = array(
|
949 | | - 'namespace' => NS_MAIN,
|
950 | | - 'title' => Title::makeTitle( NS_MAIN, $chunk )->getDBkey());
|
951 | | - }
|
952 | | - }
|
953 | | -
|
954 | | - $chunk = $this->readChunk('\[\[|\]\]|\|\||\|');
|
955 | | - if ($chunk == '||') {
|
956 | | - $chunk = $this->readChunk('\[\[|\]\]|\|\||\|');
|
957 | | - $continue = true;
|
958 | | - } else {
|
959 | | - $continue = false;
|
960 | | - }
|
961 | | - }
|
962 | | -
|
963 | | - return $this->finishLinkDescription($chunk, true, $result, $setNS, $label);
|
964 | | - }
|
965 | | -
|
966 | | - protected function finishLinkDescription($chunk, $hasNamespaces, $result, &$setNS, &$label) {
|
967 | | - wfLoadExtensionMessages('SemanticMediaWiki');
|
968 | | - if ($result === NULL) { // no useful information or concrete error found
|
969 | | - $this->m_errors[] = wfMsgForContent('smw_badqueryatom');
|
970 | | - } elseif (!$hasNamespaces && $setNS && ($this->m_defaultns !== NULL) ) {
|
971 | | - $result = $this->addDescription($result, $this->m_defaultns);
|
972 | | - $hasNamespaces = true;
|
973 | | - }
|
974 | | - $setNS = $hasNamespaces;
|
975 | | -
|
976 | | - // terminate link (assuming that next chunk was read already)
|
977 | | - if ($chunk == '|') {
|
978 | | - $chunk = $this->readChunk('\]\]');
|
979 | | - if ($chunk != ']]') {
|
980 | | - $label .= $chunk;
|
981 | | - $chunk = $this->readChunk('\]\]');
|
982 | | - } else { // empty label does not add to overall label
|
983 | | - $chunk = ']]';
|
984 | | - }
|
985 | | - }
|
986 | | - if ($chunk != ']]') {
|
987 | | - // What happended? We found some chunk that could not be processed as
|
988 | | - // link content (as in [[Category:Test<q>]]) and there was no label to
|
989 | | - // eat it. Or the closing ]] are just missing entirely.
|
990 | | - if ($chunk != '') {
|
991 | | - $this->m_errors[] = wfMsgForContent('smw_misplacedsymbol', htmlspecialchars($chunk));
|
992 | | - // try to find a later closing ]] to finish this misshaped subpart
|
993 | | - $chunk = $this->readChunk('\]\]');
|
994 | | - if ($chunk != ']]') {
|
995 | | - $chunk = $this->readChunk('\]\]');
|
996 | | - }
|
997 | | - }
|
998 | | - if ($chunk == '') {
|
999 | | - $this->m_errors[] = wfMsgForContent('smw_noclosingbrackets');
|
1000 | | - }
|
1001 | | - }
|
1002 | | - return $result;
|
1003 | | - }
|
1004 | | -
|
1005 | | - /**
|
1006 | | - * Get the next unstructured string chunk from the query string.
|
1007 | | - * Chunks are delimited by any of the special strings used in inline queries
|
1008 | | - * (such as [[, ]], <q>, ...). If the string starts with such a delimiter,
|
1009 | | - * this delimiter is returned. Otherwise the first string in front of such a
|
1010 | | - * delimiter is returned.
|
1011 | | - * Trailing and initial spaces are ignored if $trim is true, and chunks
|
1012 | | - * consisting only of spaces are not returned.
|
1013 | | - * If there is no more qurey string left to process, the empty string is
|
1014 | | - * returned (and in no other case).
|
1015 | | - *
|
1016 | | - * The stoppattern can be used to customise the matching, especially in order to
|
1017 | | - * overread certain special symbols.
|
1018 | | - *
|
1019 | | - * $consume specifies whether the returned chunk should be removed from the
|
1020 | | - * query string.
|
1021 | | - */
|
1022 | | - protected function readChunk($stoppattern = '', $consume=true, $trim=true) {
|
1023 | | - if ($stoppattern == '') {
|
1024 | | - $stoppattern = '\[\[|\]\]|::|:=|<q>|<\/q>|^' . $this->m_categoryprefix .
|
1025 | | - '|^' . $this->m_conceptprefix . '|\|\||\|';
|
1026 | | - }
|
1027 | | - $chunks = preg_split('/[\s]*(' . $stoppattern . ')/u', $this->m_curstring, 2, PREG_SPLIT_DELIM_CAPTURE);
|
1028 | | - if (count($chunks) == 1) { // no matches anymore, strip spaces and finish
|
1029 | | - if ($consume) {
|
1030 | | - $this->m_curstring = '';
|
1031 | | - }
|
1032 | | - return $trim?trim($chunks[0]):$chunks[0];
|
1033 | | - } elseif (count($chunks) == 3) { // this should generally happen if count is not 1
|
1034 | | - if ($chunks[0] == '') { // string started with delimiter
|
1035 | | - if ($consume) {
|
1036 | | - $this->m_curstring = $chunks[2];
|
1037 | | - }
|
1038 | | - return $trim?trim($chunks[1]):$chunks[1];
|
1039 | | - } else {
|
1040 | | - if ($consume) {
|
1041 | | - $this->m_curstring = $chunks[1] . $chunks[2];
|
1042 | | - }
|
1043 | | - return $trim?trim($chunks[0]):$chunks[0];
|
1044 | | - }
|
1045 | | - } else { return false; } //should never happen
|
1046 | | - }
|
1047 | | -
|
1048 | | - /**
|
1049 | | - * Enter a new subblock in the query, which must at some time be terminated by the
|
1050 | | - * given $endstring delimiter calling popDelimiter();
|
1051 | | - */
|
1052 | | - protected function pushDelimiter($endstring) {
|
1053 | | - array_push($this->m_sepstack, $endstring);
|
1054 | | - }
|
1055 | | -
|
1056 | | - /**
|
1057 | | - * Exit a subblock in the query ending with the given delimiter.
|
1058 | | - * If the delimiter does not match the top-most open block, false
|
1059 | | - * will be returned. Otherwise return true.
|
1060 | | - */
|
1061 | | - protected function popDelimiter($endstring) {
|
1062 | | - $topdelim = array_pop($this->m_sepstack);
|
1063 | | - return ($topdelim == $endstring);
|
1064 | | - }
|
1065 | | -
|
1066 | | - /**
|
1067 | | - * Extend a given description by a new one, either by adding the new description
|
1068 | | - * (if the old one is a container description) or by creating a new container.
|
1069 | | - * The parameter $conjunction determines whether the combination of both descriptions
|
1070 | | - * should be a disjunction or conjunction.
|
1071 | | - *
|
1072 | | - * In the special case that the current description is NULL, the new one will just
|
1073 | | - * replace the current one.
|
1074 | | - *
|
1075 | | - * The return value is the expected combined description. The object $curdesc will
|
1076 | | - * also be changed (if it was non-NULL).
|
1077 | | - */
|
1078 | | - protected function addDescription($curdesc, $newdesc, $conjunction = true) {
|
1079 | | - wfLoadExtensionMessages('SemanticMediaWiki');
|
1080 | | - $notallowedmessage = 'smw_noqueryfeature';
|
1081 | | - if ($newdesc instanceof SMWSomeProperty) {
|
1082 | | - $allowed = $this->m_queryfeatures & SMW_PROPERTY_QUERY;
|
1083 | | - } elseif ($newdesc instanceof SMWClassDescription) {
|
1084 | | - $allowed = $this->m_queryfeatures & SMW_CATEGORY_QUERY;
|
1085 | | - } elseif ($newdesc instanceof SMWConceptDescription) {
|
1086 | | - $allowed = $this->m_queryfeatures & SMW_CONCEPT_QUERY;
|
1087 | | - } elseif ($newdesc instanceof SMWConjunction) {
|
1088 | | - $allowed = $this->m_queryfeatures & SMW_CONJUNCTION_QUERY;
|
1089 | | - $notallowedmessage = 'smw_noconjunctions';
|
1090 | | - } elseif ($newdesc instanceof SMWDisjunction) {
|
1091 | | - $allowed = $this->m_queryfeatures & SMW_DISJUNCTION_QUERY;
|
1092 | | - $notallowedmessage = 'smw_nodisjunctions';
|
1093 | | - } else {
|
1094 | | - $allowed = true;
|
1095 | | - }
|
1096 | | - if (!$allowed) {
|
1097 | | - $this->m_errors[] = wfMsgForContent($notallowedmessage, str_replace('[', '[', $newdesc->getQueryString()));
|
1098 | | - return $curdesc;
|
1099 | | - }
|
1100 | | - if ($newdesc === NULL) {
|
1101 | | - return $curdesc;
|
1102 | | - } elseif ($curdesc === NULL) {
|
1103 | | - return $newdesc;
|
1104 | | - } else { // we already found descriptions
|
1105 | | - if ( (($conjunction) && ($curdesc instanceof SMWConjunction)) ||
|
1106 | | - ((!$conjunction) && ($curdesc instanceof SMWDisjunction)) ) { // use existing container
|
1107 | | - $curdesc->addDescription($newdesc);
|
1108 | | - return $curdesc;
|
1109 | | - } elseif ($conjunction) { // make new conjunction
|
1110 | | - if ($this->m_queryfeatures & SMW_CONJUNCTION_QUERY) {
|
1111 | | - return new SMWConjunction(array($curdesc,$newdesc));
|
1112 | | - } else {
|
1113 | | - $this->m_errors[] = wfMsgForContent('smw_noconjunctions', str_replace('[', '[', $newdesc->getQueryString()));
|
1114 | | - return $curdesc;
|
1115 | | - }
|
1116 | | - } else { // make new disjunction
|
1117 | | - if ($this->m_queryfeatures & SMW_DISJUNCTION_QUERY) {
|
1118 | | - return new SMWDisjunction(array($curdesc,$newdesc));
|
1119 | | - } else {
|
1120 | | - $this->m_errors[] = wfMsgForContent('smw_nodisjunctions', str_replace('[', '[', $newdesc->getQueryString()));
|
1121 | | - return $curdesc;
|
1122 | | - }
|
1123 | | - }
|
1124 | | - }
|
1125 | | - }
|
1126 | | -}
|
1127 | | -
|
1128 | | -class SMWNotifyUpdate {
|
1129 | | - protected $m_info;
|
1130 | | - protected $m_title;
|
1131 | | - protected $m_userMsgs;
|
1132 | | - protected $m_userHtmlPropMsgs;
|
1133 | | - protected $m_userHtmlNMMsgs;
|
1134 | | - protected $m_userNMs;
|
1135 | | - protected $m_notifyHtmlPropMsgs;
|
1136 | | - protected $m_notifyHtmlMsgs;
|
1137 | | - protected $m_newMonitor;
|
1138 | | - protected $m_removeMonitored;
|
1139 | | - protected $m_subQueryNotify;
|
1140 | | -
|
1141 | | - protected $m_linker;
|
1142 | | -
|
1143 | | - protected function getSemanticInfo($title) {
|
1144 | | - $result = array();
|
1145 | | - $sStore = NMStorage::getDatabase();
|
1146 | | - $semdata = smwfGetStore()->getSemanticData($title);
|
1147 | | - foreach($semdata->getProperties() as $property) {
|
1148 | | - if (!$property->isShown() && $property->getWikiValue()!='') { // showing this is not desired, hide
|
1149 | | - continue;
|
1150 | | - } elseif ($property->isUserDefined()) { // user defined property
|
1151 | | - $property->setCaption(preg_replace('/[ ]/u',' ',$property->getWikiValue(),2));
|
1152 | | - }
|
1153 | | -
|
1154 | | - $propvalues = $semdata->getPropertyValues($property);
|
1155 | | - if($property->getWikiValue()!='') {
|
1156 | | - foreach ($propvalues as $propvalue) {
|
1157 | | - if($propvalue->getXSDValue() != '') {
|
1158 | | - $result[SMWNotifyProcessor::toInfoId(2,0,$sStore->lookupSmwId(SMW_NS_PROPERTY, $property->getXSDValue()))][] = array('name'=>$property, 'value'=>$propvalue);
|
1159 | | - }
|
1160 | | - }
|
1161 | | - } else {
|
1162 | | - foreach ($propvalues as $propvalue) {
|
1163 | | - if(($propvalue instanceof SMWWikiPageValue)&&($propvalue->getNamespace() == NS_CATEGORY)) {
|
1164 | | - $result[SMWNotifyProcessor::toInfoId(0,0,$sStore->lookupSmwId(NS_CATEGORY, $propvalue->getXSDValue()))][] = array('name'=>$propvalue, 'value'=>null);
|
1165 | | - }
|
1166 | | - }
|
1167 | | - }
|
1168 | | - }
|
1169 | | - return $result;
|
1170 | | - }
|
1171 | | -
|
1172 | | - public function SMWNotifyUpdate($title) {
|
1173 | | - $this->m_title = $title;
|
1174 | | - $this->m_userMsgs = array();
|
1175 | | - $this->m_userHtmlPropMsgs = array();
|
1176 | | - $this->m_userHtmlNMMsgs = array();
|
1177 | | - $this->m_userNMs = array();
|
1178 | | - $this->m_notifyHtmlPropMsgs = array();
|
1179 | | - $this->m_notifyHtmlMsgs = array();
|
1180 | | - $this->m_newMonitor = array();
|
1181 | | - $this->m_removeMonitored = array();
|
1182 | | - $this->m_subQueryNotify = array();
|
1183 | | - $this->m_linker = new Linker();
|
1184 | | -
|
1185 | | - $page_id = $title->getArticleID();
|
1186 | | - if(($page_id == 0) || ($this->m_title->getNamespace() != NS_MAIN)) {
|
1187 | | - return;
|
1188 | | - }
|
1189 | | - $this->m_info = $this->getSemanticInfo($this->m_title);
|
1190 | | - }
|
1191 | | - public function executeNotifyDelete($reason) {
|
1192 | | - $page_id = $this->m_title->getArticleID();
|
1193 | | - if(($page_id == 0) || ($this->m_title->getNamespace() != NS_MAIN)) {
|
1194 | | - return;
|
1195 | | - }
|
1196 | | - $page_name = $this->m_title->getText().' ('.$this->m_title->getFullUrl().')';
|
1197 | | - $page_html_name = '<a href="'.$this->m_title->getFullUrl().'">'.htmlspecialchars($this->m_title->getText()).'</a>';
|
1198 | | -
|
1199 | | - $msg .= "\r\nPage $page_name has been deleted.\r\nReason : $reason";
|
1200 | | - $sStore = NMStorage::getDatabase();
|
1201 | | - $notifications = $sStore->getMonitoredNotifications($page_id);
|
1202 | | -
|
1203 | | - foreach($notifications as $user_id=>$notifies) {
|
1204 | | - $this->m_userMsgs[$user_id] .= $msg.'\r\n( NM: ';
|
1205 | | - $hint = "<P>Page $page_html_name has been deleted.<br/>Reason : <font color='red'>".htmlspecialchars($reason)."</font></P>";
|
1206 | | - $this->m_userHtmlNMMsgs[$user_id] .= "$hint<P>Notify Me: ";
|
1207 | | - $idx = 0;
|
1208 | | - foreach($notifies as $notify_id=>$notify_detail) {
|
1209 | | - if($idx>0) {
|
1210 | | - $this->m_userMsgs[$user_id] .= ', ';
|
1211 | | - $this->m_userHtmlNMMsgs[$user_id] .= ', ';
|
1212 | | - }
|
1213 | | - $this->m_notifyHtmlMsgs[$notify_id] .= $hint;
|
1214 | | -
|
1215 | | - $this->m_userMsgs[$user_id] .= $notify_detail['name'];
|
1216 | | - $this->m_userHtmlNMMsgs[$user_id] .= '<b>'.htmlspecialchars($notify_detail['name']).'</b>';
|
1217 | | - $idx++;
|
1218 | | - $this->m_removeMonitored[] = array('notify_id'=>$notify_id, 'page_id'=>$page_id);
|
1219 | | -
|
1220 | | - $this->m_userNMs[$user_id][] = $notify_id;
|
1221 | | - }
|
1222 | | -
|
1223 | | - $this->m_userMsgs[$user_id] .= " ).";
|
1224 | | - $this->m_userHtmlNMMsgs[$user_id] .= " does not match this page now.</P>";
|
1225 | | - }
|
1226 | | -
|
1227 | | - $this->notifyUsers();
|
1228 | | - $sStore->removeNotifyMonitor($this->m_removeMonitored);
|
1229 | | - }
|
1230 | | - function isEqual($v1, $v2) {
|
1231 | | - return (strval($v1[value]->getXSDValue()) == strval($v2[value]->getXSDValue()));
|
1232 | | - }
|
1233 | | - function getNotifyPlain($info, $key){
|
1234 | | - $i = SMWNotifyProcessor::getInfoFromId($key);
|
1235 | | - if($i[type]==0) {
|
1236 | | - return "\r\n'".$info[name]->getWikiValue()."' has been ".($info[sem_act]==0?"deleted":"added").".";
|
1237 | | - } else {
|
1238 | | - $tmp = "\r\nProperty '".$info[name]->getWikiValue()."' has been ".($info[sem_act]==0?"deleted.":($info[sem_act]==1?"modified":"added")).".";
|
1239 | | - $first = true;
|
1240 | | - foreach($info[del_vals] as $val) {
|
1241 | | - if($first) {
|
1242 | | - $tmp .= "\r\nValue '";
|
1243 | | - $first = false;
|
1244 | | - } else {
|
1245 | | - $tmp .= "', '";
|
1246 | | - }
|
1247 | | - $tmp .= $val[plain];
|
1248 | | - }
|
1249 | | - if(!$first) {
|
1250 | | - $tmp .= "' deleted.";
|
1251 | | - }
|
1252 | | - $first = true;
|
1253 | | - foreach($info[new_vals] as $val) {
|
1254 | | - if($first) {
|
1255 | | - $tmp .= "\r\nValue '";
|
1256 | | - $first = false;
|
1257 | | - } else {
|
1258 | | - $tmp .= "', '";
|
1259 | | - }
|
1260 | | - $tmp .= $val[plain];
|
1261 | | - }
|
1262 | | - if(!$first) {
|
1263 | | - $tmp .= "' added.";
|
1264 | | - }
|
1265 | | - return $tmp."\r\n";
|
1266 | | - }
|
1267 | | - }
|
1268 | | - function getNotifyHtml($info, $key){
|
1269 | | - $i = SMWNotifyProcessor::getInfoFromId($key);
|
1270 | | - if($i[type]==0) {
|
1271 | | - return "<td>Category</td>
|
1272 | | - <td>".$info[name]->getShortHTMLText($this->m_linker)."</td>
|
1273 | | - <td>".($info[sem_act]==0?"<font color='green'>remove</font>":"<font color='red'>cite</font>")."</td>
|
1274 | | - <td colspan='2'>N/A</td>";
|
1275 | | - } else {
|
1276 | | - $rows = max(count($info[del_vals]), count($info[new_vals]));
|
1277 | | - $tmp = "<tr><td rowspan='$rows'>Property</td>
|
1278 | | - <td rowspan='$rows'>".$info[name]->getShortHTMLText($this->m_linker)."</td>
|
1279 | | - <td rowspan='$rows'>".($info[sem_act]==0?"<font color='green'>remove</font>":($info[sem_act]==1?"<font color='blue'>modify</font>":"<font color='red'>cite</font>"))."</td>";
|
1280 | | - for($idx=0;$idx<$rows;++$idx) {
|
1281 | | - if($idx>0){
|
1282 | | - $tmp .= "<tr>";
|
1283 | | - }
|
1284 | | - $tmp .= "<td>".(isset($info[del_vals][$idx])?$info[del_vals][$idx][html]:" ")."</td>
|
1285 | | - <td>".(isset($info[new_vals][$idx])?$info[new_vals][$idx][html]:" ")."</td>
|
1286 | | - </tr>";
|
1287 | | - }
|
1288 | | - return $tmp;
|
1289 | | - }
|
1290 | | - }
|
1291 | | - public function executeNotifyUpdate() {
|
1292 | | - $page_id = $this->m_title->getArticleID();
|
1293 | | - if(($page_id == 0) || ($this->m_title->getNamespace() != NS_MAIN)) {
|
1294 | | - return;
|
1295 | | - }
|
1296 | | - $sStore = NMStorage::getDatabase();
|
1297 | | -
|
1298 | | - $info = $this->getSemanticInfo($this->m_title);
|
1299 | | - // get different
|
1300 | | - $tmp_info = array(); // type : category 0, property 2; name; sem action : del 0, modify 1, add 2; val action : del 0, add 1
|
1301 | | - foreach($this->m_info as $key=>$value) {
|
1302 | | - $i = SMWNotifyProcessor::getInfoFromId($key);
|
1303 | | - $updated = false;
|
1304 | | - if(!isset($info[$key])) {
|
1305 | | - if($i[type]==0) {
|
1306 | | - $tmp_info[$key] = array('sem_act' => 0, 'name'=>$value[0][name]);
|
1307 | | - }else {
|
1308 | | - $tmp_info[$key] = array('sem_act'=>0, 'name'=>$value[0][name], 'del_vals'=>array(), 'new_vals'=>array());
|
1309 | | - foreach($value as $v) {
|
1310 | | - $tmp_info[$key][del_vals][] = array( 'plain' => $v[value]->getWikiValue(), 'html' => $v[value]->getShortHTMLText($this->m_linker));
|
1311 | | - }
|
1312 | | - }
|
1313 | | - } else if($i[type] == 2) {
|
1314 | | - $mvalue = $info[$key];
|
1315 | | - foreach($value as $v1) {
|
1316 | | - $found = false;
|
1317 | | - foreach($mvalue as $v2) {
|
1318 | | - if($this->isEqual($v1, $v2)) {
|
1319 | | - $found = true;
|
1320 | | - break;
|
1321 | | - }
|
1322 | | - }
|
1323 | | - if(!$found) {
|
1324 | | - if(!$updated){
|
1325 | | - $updated = true;
|
1326 | | - $tmp_info[$key] = array('sem_act'=>1, 'name'=>$value[0][name], 'del_vals'=>array(), 'new_vals'=>array());
|
1327 | | - }
|
1328 | | - $tmp_info[$key][del_vals][] = array( 'plain' => $v1[value]->getWikiValue(), 'html' => $v1[value]->getShortHTMLText($this->m_linker));
|
1329 | | - }
|
1330 | | - }
|
1331 | | - foreach($mvalue as $v1) {
|
1332 | | - $found = false;
|
1333 | | - foreach($value as $v2) {
|
1334 | | - if($this->isEqual($v1, $v2)) {
|
1335 | | - $found = true;
|
1336 | | - break;
|
1337 | | - }
|
1338 | | - }
|
1339 | | - if(!$found) {
|
1340 | | - if(!$updated){
|
1341 | | - $updated = true;
|
1342 | | - $tmp_info[$key] = array('sem_act'=>1, 'name'=>$value[0][name], 'del_vals'=>array(), 'new_vals'=>array());
|
1343 | | - }
|
1344 | | - $tmp_info[$key][new_vals][] = array( 'plain' => $v1[value]->getWikiValue(), 'html' => $v1[value]->getShortHTMLText($this->m_linker));
|
1345 | | - }
|
1346 | | - }
|
1347 | | - }
|
1348 | | - }
|
1349 | | - foreach($info as $key=>$value) {
|
1350 | | - $i = SMWNotifyProcessor::getInfoFromId($key);
|
1351 | | - if(!isset($this->m_info[$key])) {
|
1352 | | - if($i[type]==0) {
|
1353 | | - $tmp_info[$key] = array('sem_act' => 2, 'name'=>$value[0][name]);
|
1354 | | - }else {
|
1355 | | - $tmp_info[$key] = array('sem_act'=>2, 'name'=>$value[0][name], 'del_vals'=>array(), 'new_vals'=>array());
|
1356 | | - foreach($value as $v) {
|
1357 | | - $tmp_info[$key][new_vals][] = array( 'plain' => $v[value]->getWikiValue(), 'html' => $v[value]->getShortHTMLText($this->m_linker));
|
1358 | | - }
|
1359 | | - }
|
1360 | | - }
|
1361 | | - }
|
1362 | | -
|
1363 | | - $notifications = $sStore->getMonitoredNotificationsDetail($page_id);
|
1364 | | - // add semantic info to report all NM
|
1365 | | - foreach($notifications as $user_id=>$notifies) {
|
1366 | | - foreach($notifies['rep_all'] as $notify_id=>$notify_name) {
|
1367 | | - foreach(array_keys($tmp_info) as $key) {
|
1368 | | - $notifications[$user_id]['semantic'][$key][$notify_id]=$notify_name;
|
1369 | | - }
|
1370 | | - }
|
1371 | | - }
|
1372 | | - $page_name = $this->m_title->getText().' ('.$this->m_title->getFullUrl().')';
|
1373 | | -
|
1374 | | - foreach($notifications as $user_id=>$notifies) {
|
1375 | | - foreach($notifies['semantic'] as $key=>$notify) {
|
1376 | | - if(isset($tmp_info[$key])) {
|
1377 | | - $hint = "";
|
1378 | | - if(!isset($this->m_userMsgs[$user_id])) {
|
1379 | | - $this->m_userMsgs[$user_id] = "\r\nSemantic attributes are changed in page $page_name.";
|
1380 | | - $hint = "Semantic attributes are changed in page <a href='".$this->m_title->getFullUrl()."'>".htmlspecialchars($this->m_title->getText())."</a>.<br/>";
|
1381 | | - $this->m_userHtmlNMMsgs[$user_id] .= $hint;
|
1382 | | - }
|
1383 | | -
|
1384 | | - $this->m_userMsgs[$user_id] .= $this->getNotifyPlain($tmp_info[$key],$key).' ( NM: ';
|
1385 | | - $propHint = $this->getNotifyHtml($tmp_info[$key],$key);
|
1386 | | - $this->m_userHtmlPropMsgs[$user_id] .= $propHint . "<tr><td colspan='5'>Notify Me: ";
|
1387 | | - $idx = 0;
|
1388 | | - foreach($notify as $notify_id=>$notify_name) {
|
1389 | | - if($idx>0) {
|
1390 | | - $this->m_userMsgs[$user_id] .= ', ';
|
1391 | | - $this->m_userHtmlPropMsgs[$user_id] .= ', ';
|
1392 | | - }
|
1393 | | - $this->m_userMsgs[$user_id] .= $notify_name;
|
1394 | | - $this->m_userHtmlPropMsgs[$user_id] .= '<b>'.htmlspecialchars($notify_name).'</b>';
|
1395 | | - $this->m_notifyHtmlMsgs[$notify_id] .= $hint;
|
1396 | | - $this->m_notifyHtmlPropMsgs[$notify_id] .= $propHint;
|
1397 | | - $idx++;
|
1398 | | -
|
1399 | | - $this->m_userNMs[$user_id][] = $notify_id;
|
1400 | | - }
|
1401 | | - $this->m_userMsgs[$user_id] .= ' ).';
|
1402 | | - $this->m_userHtmlPropMsgs[$user_id] .= "</td></tr>";
|
1403 | | - }
|
1404 | | - }
|
1405 | | - }
|
1406 | | - // get possible subquery
|
1407 | | - $this->m_subQueryNotify = array();
|
1408 | | - $queries = $sStore->getPossibleQuery($this->m_info);
|
1409 | | - if(is_array($queries)) {
|
1410 | | - foreach($queries[1] as $notify_id=>$notify) {
|
1411 | | - $this->m_subQueryNotify[$notify_id] = $notify;
|
1412 | | - }
|
1413 | | - }
|
1414 | | -
|
1415 | | - $this->m_info = $info;
|
1416 | | - }
|
1417 | | -
|
1418 | | - // this will cost time, think we can update monitor in a single thread, like Job
|
1419 | | - public function updateNotifyMonitor() {
|
1420 | | - $page_id = $this->m_title->getArticleID();
|
1421 | | - if(($page_id == 0) || ($this->m_title->getNamespace() != NS_MAIN)) {
|
1422 | | - return;
|
1423 | | - }
|
1424 | | - $sStore = NMStorage::getDatabase();
|
1425 | | - $queries = $sStore->getPossibleQuery($this->m_info);
|
1426 | | - if(!is_array($queries)) {
|
1427 | | - return;
|
1428 | | - }
|
1429 | | - // get monitored query
|
1430 | | - $main_queries = $sStore->getMonitoredQuery($page_id);
|
1431 | | - foreach($queries[0] as $notify_id=>$notify) {
|
1432 | | - $main_queries[$notify_id] = $notify;
|
1433 | | - }
|
1434 | | -
|
1435 | | - // begin notify query on main query
|
1436 | | - $page_name = $this->m_title->getText().' ('.$this->m_title->getFullUrl().')';
|
1437 | | - $page_html_name = '<a href="'.$this->m_title->getFullUrl().'">'.htmlspecialchars($this->m_title->getText()).'</a>';
|
1438 | | -
|
1439 | | - foreach($main_queries as $notify_id=>$notify) {
|
1440 | | - $sStore->getNotifyInMainQuery($page_id, $notify_id, $notify['sql'], $notify['hierarchy'], $match, $monitoring);
|
1441 | | - if((!$monitoring) && $match) {
|
1442 | | - $this->m_userMsgs[$notify['user_id']] .= "\r\nPage $page_name matches NotifyMe '$notify[name]' now.";
|
1443 | | - $hint = "Page $page_html_name matches \"<b>".htmlspecialchars($notify[name])."</b>\" now.<br/>";
|
1444 | | - $this->m_userHtmlNMMsgs[$notify['user_id']] .= $hint;
|
1445 | | - $this->m_notifyHtmlMsgs[$notify_id] .= $hint;
|
1446 | | - $this->m_newMonitor[] = array('notify_id'=>$notify_id, 'page_id'=>$page_id);
|
1447 | | - } else if((!$match) && $monitoring) {
|
1448 | | - $this->m_userMsgs[$notify['user_id']] .= "\r\nPage $page_name does not match NotifyMe '$notify[name]' now.";
|
1449 | | - $hint = "Page $page_html_name does not match \"<b>".htmlspecialchars($notify[name])."</b>\" now.<br/>";
|
1450 | | - $this->m_userHtmlNMMsgs[$notify['user_id']] .= $hint;
|
1451 | | - $this->m_notifyHtmlMsgs[$notify_id] .= $hint;
|
1452 | | - $this->m_removeMonitored[] = array('notify_id'=>$notify_id, 'page_id'=>$page_id);
|
1453 | | - }
|
1454 | | - $this->m_userNMs[$notify['user_id']][] = $notify_id;
|
1455 | | - }
|
1456 | | - // begin notify query on sub query, should go through all pages
|
1457 | | - foreach($queries[1] as $notify_id=>$notify) {
|
1458 | | - $this->m_subQueryNotify[$notify_id] = $notify;
|
1459 | | - }
|
1460 | | - foreach($this->m_subQueryNotify as $notify_id=>$notify) {
|
1461 | | - $res = $sStore->getNotifyInSubquery($notify_id, $notify['sql'], $notify['hierarchy']);
|
1462 | | -
|
1463 | | - $no_matches = array_diff($res['monitoring'], $res['match']);
|
1464 | | - $matches = array_diff($res['match'], $res['monitoring']);
|
1465 | | - foreach($matches as $pid) {
|
1466 | | - $pt = $sStore->getPageTitle($pid);
|
1467 | | - if(!$pt) {
|
1468 | | - continue;
|
1469 | | - }
|
1470 | | - $t = Title::makeTitle( NS_MAIN, $pt->page_title );
|
1471 | | - $p_name = $t->getText().' ('.$t->getFullUrl().')';
|
1472 | | - $p_html_name = '<a href="'.$t->getFullUrl().'">'.htmlspecialchars($t->getText()).'</a>';
|
1473 | | -
|
1474 | | - $this->m_userMsgs[$notify['user_id']] .= "\r\nSub page $page_name changed, $p_name matches NotifyMe '$notify[name]' now.";
|
1475 | | - $hint = "Sub page $page_html_name changed, $p_html_name matches \"<b>".htmlspecialchars($notify[name])."</b>\" now.<br/>";
|
1476 | | - $this->m_userHtmlNMMsgs[$notify['user_id']] .= $hint;
|
1477 | | - $this->m_notifyHtmlMsgs[$notify_id] .= $hint;
|
1478 | | - $this->m_newMonitor[] = array('notify_id'=>$notify_id, 'page_id'=>$pid);
|
1479 | | -
|
1480 | | - $this->m_userNMs[$notify['user_id']][] = $notify_id;
|
1481 | | - }
|
1482 | | - foreach($no_matches as $pid) {
|
1483 | | - $pt = $sStore->getPageTitle($pid);
|
1484 | | - if(!$pt) {
|
1485 | | - continue;
|
1486 | | - }
|
1487 | | - $t = Title::makeTitle( NS_MAIN, $pt->page_title );
|
1488 | | - $p_name = $t->getText().' ('.$t->getFullUrl().')';
|
1489 | | - $p_html_name = '<a href="'.$t->getFullUrl().'">'.htmlspecialchars($t->getText()).'</a>';
|
1490 | | -
|
1491 | | - $this->m_userMsgs[$notify['user_id']] .= "\r\nSub page $page_name changed, page $p_name does not match NotifyMe '$notify[name]' now.";
|
1492 | | - $hint = "Sub page $page_html_name changed, $p_html_name does not match \"<b>".htmlspecialchars($notify[name])."</b>\" now.<br/>";
|
1493 | | - $this->m_userHtmlNMMsgs[$notify['user_id']] .= $hint;
|
1494 | | - $this->m_notifyHtmlMsgs[$notify_id] .= $hint;
|
1495 | | - $this->m_removeMonitored[] = array('notify_id'=>$notify_id, 'page_id'=>$pid);
|
1496 | | -
|
1497 | | - $this->m_userNMs[$notify['user_id']][] = $notify_id;
|
1498 | | - }
|
1499 | | - }
|
1500 | | -
|
1501 | | - $sStore->removeNotifyMonitor($this->m_removeMonitored);
|
1502 | | - $sStore->addNotifyMonitor($this->m_newMonitor);
|
1503 | | - }
|
1504 | | - private function applyStyle($html) {
|
1505 | | - $html = str_replace("class=\"smwtable\"", "style=\"background-color: #EEEEFF;\"", $html);
|
1506 | | - $html = str_replace("<th", "<th style=\"background-color: #EEEEFF;text-align: left;\"", $html);
|
1507 | | - $html = str_replace("<td", "<td style=\"background-color: #FFFFFF;padding: 1px;padding-left: 5px;padding-right: 5px;text-align: left;vertical-align: top;\"", $html);
|
1508 | | - return $html;
|
1509 | | - }
|
1510 | | - public function notifyUsers() {
|
1511 | | - global $wgSitename, $wgSMTP, $wgEmergencyContact, $wgEnotifyMeJob;
|
1512 | | - $sStore = NMStorage::getDatabase();
|
1513 | | -
|
1514 | | - $nm_send_jobs = array();
|
1515 | | - $id = 0;
|
1516 | | -
|
1517 | | - if(count($this->m_notifyHtmlMsgs) > 0) {
|
1518 | | - $notifications = $sStore->getNotifyMe(array_keys($this->m_notifyHtmlMsgs));
|
1519 | | - }
|
1520 | | - $html_style = '';
|
1521 | | -//<style>
|
1522 | | -//table.smwtable{background-color: #EEEEFF;}
|
1523 | | -//table.smwtable th{background-color: #EEEEFF;text-align: left;}
|
1524 | | -//table.smwtable td{background-color: #FFFFFF;padding: 1px;padding-left: 5px;padding-right: 5px;text-align: left;vertical-align: top;}
|
1525 | | -//table.smwtable tr.smwfooter td{font-size: 90%;line-height: 1;background-color: #EEEEFF;padding: 0px;padding-left: 5px;padding-right: 5px;text-align: right;vertical-align: top;}
|
1526 | | -//</style>';
|
1527 | | - $html_showall = array();
|
1528 | | - foreach($this->m_notifyHtmlMsgs as $notify_id=>$msg) {
|
1529 | | - $html_msg = $html_style;
|
1530 | | - $showing_all = false;
|
1531 | | - if(isset($notifications[$notify_id]) && $notifications[$notify_id]['show_all']) {
|
1532 | | - SMWQueryProcessor::processFunctionParams(explode("\n", $notifications[$notify_id]['query']), $querystring, $params, $printouts);
|
1533 | | -
|
1534 | | - $format = 'auto';
|
1535 | | - if (array_key_exists('format', $params)) {
|
1536 | | - $format = strtolower(trim($params['format']));
|
1537 | | - global $smwgResultFormats;
|
1538 | | - if ( !array_key_exists($format, $smwgResultFormats) ) {
|
1539 | | - $format = 'auto';
|
1540 | | - }
|
1541 | | - }
|
1542 | | - $query = SMWQueryProcessor::createQuery($querystring, $params, SMWQueryProcessor::INLINE_QUERY, $format, $printouts);
|
1543 | | - $res = smwfGetStore()->getQueryResult($query);
|
1544 | | - $printer = SMWQueryProcessor::getResultPrinter($format, SMWQueryProcessor::INLINE_QUERY, $res);
|
1545 | | - $result = $printer->getResult($res, $params, SMW_OUTPUT_HTML);
|
1546 | | - $html_msg .= $result . '<br/>';
|
1547 | | - $html_showall[$notify_id] = array ('name'=>$notifications[$notify_id]['name'], 'html'=>$result);
|
1548 | | -
|
1549 | | - $showing_all = true;
|
1550 | | - $link = $res->getQueryLink()->getURL();
|
1551 | | - }
|
1552 | | - global $smwgNMHideDiffWhenShowAll;
|
1553 | | - if(!($smwgNMHideDiffWhenShowAll && $showing_all)) {
|
1554 | | - $html_msg .= '<p><b>Semantic changes from last revision:</b><br/><span style="font-size: 8pt;">'.$this->m_notifyHtmlMsgs[$notify_id].'</span></P>';
|
1555 | | - if(isset($this->m_notifyHtmlPropMsgs[$notify_id])) {
|
1556 | | - $html_msg .= "<P><table class=\"smwtable\"><tr><th>Semantic type</th><th>Name</th><th>Action</th><th>Deleted</th><th>Added</th></tr>";
|
1557 | | - $html_msg .= $this->m_notifyHtmlPropMsgs[$notify_id];
|
1558 | | - $html_msg .= "</table></P>";
|
1559 | | - }
|
1560 | | - }
|
1561 | | - if($showing_all) {
|
1562 | | - $id = $sStore->addNotifyRSS('nid', $notify_id, "All current items, ".date('Y-m-d H:i:s', time()), $this->applyStyle($html_msg), $link);
|
1563 | | - } else {
|
1564 | | - $id = $sStore->addNotifyRSS('nid', $notify_id, $this->m_title->getText(), $this->applyStyle($html_msg));
|
1565 | | - }
|
1566 | | - }
|
1567 | | - foreach($this->m_userMsgs as $user_id=>$msg) {
|
1568 | | - // generate RSS items
|
1569 | | - $html_msg = $html_style;
|
1570 | | - foreach(array_unique($this->m_userNMs[$user_id]) as $showall_nid) {
|
1571 | | - if(isset($html_showall[$showall_nid])) {
|
1572 | | - $html_msg .= "<br/>All current items for \"<b>".$html_showall[$showall_nid]['name']."</b>\":<br/>";
|
1573 | | - $html_msg .= $html_showall[$showall_nid]['html'] . '<br/>';
|
1574 | | - }
|
1575 | | - }
|
1576 | | -
|
1577 | | - $html_msg .= '<p><b>Semantic changes from last revision:</b><br/><span style="font-size: 8pt;">'.$this->m_userHtmlNMMsgs[$user_id].'</span></P>';
|
1578 | | - if(isset($this->m_userHtmlPropMsgs[$user_id])) {
|
1579 | | - $html_msg .= "<P><table class=\"smwtable\"><tr><th>Semantic type</th><th>Name</th><th>Action</th><th>Deleted</th><th>Added</th></tr>";
|
1580 | | - $html_msg .= $this->m_userHtmlPropMsgs[$user_id];
|
1581 | | - $html_msg .= "</table></P>";
|
1582 | | - }
|
1583 | | -
|
1584 | | - $id = $sStore->addNotifyRSS('uid', $user_id, $this->m_title->getText(), $this->applyStyle($html_msg));
|
1585 | | -
|
1586 | | - if($wgEnotifyMeJob) {
|
1587 | | - // send notifications by mail
|
1588 | | - $user_info = $sStore->getUserInfo($user_id);
|
1589 | | - if(($user_info->user_email != '') && $this->getUserNMOption($user_info->user_options)) {
|
1590 | | - $name = (($user_info->user_real_name=='')?$user_info->user_name:$user_info->user_real_name);
|
1591 | | - $body = "Dear Mr./Mrs. $name,\r\n$msg".
|
1592 | | - "\r\n\r\nSincerely yours,\r\nSMW NotifyMe Bot";
|
1593 | | -
|
1594 | | - $params = array('to' => new MailAddress($user_info->user_email, $name),
|
1595 | | - 'from' => new MailAddress($wgEmergencyContact, 'Admin'),
|
1596 | | - 'subj' => 'New SMW Notification comes, from '.$wgSitename,
|
1597 | | - 'body' => $body,
|
1598 | | - 'replyto' => new MailAddress($wgEmergencyContact, 'Admin'));
|
1599 | | -
|
1600 | | - $nm_send_jobs[] = new SMW_NMSendMailJob($this->m_title, $params);
|
1601 | | - }
|
1602 | | - }
|
1603 | | - }
|
1604 | | -
|
1605 | | - if( $wgEnotifyMeJob ) {
|
1606 | | - if( count( $nm_send_jobs ) ) {
|
1607 | | - Job :: batchInsert($nm_send_jobs);
|
1608 | | - }
|
1609 | | - } else {
|
1610 | | - global $phpInterpreter;
|
1611 | | - if (!isset($phpInterpreter)) {
|
1612 | | - // if $phpInterpreter is not set, assume it is in search path
|
1613 | | - // if not, starting of bot will FAIL!
|
1614 | | - $phpInterpreter = "php";
|
1615 | | - }
|
1616 | | - // copy from SMW_GardeningBot.php
|
1617 | | - ob_start();
|
1618 | | - phpinfo();
|
1619 | | - $info = ob_get_contents();
|
1620 | | - ob_end_clean();
|
1621 | | - //Get Systemstring
|
1622 | | - preg_match('!\nSystem(.*?)\n!is',strip_tags($info),$ma);
|
1623 | | - //Check if it consists 'windows' as string
|
1624 | | - preg_match('/[Ww]indows/',$ma[1],$os);
|
1625 | | - global $smwgNMIP ;
|
1626 | | - if($os[0]=='' && $os[0]==null ) {
|
1627 | | -
|
1628 | | - //FIXME: $runCommand must allow whitespaces in paths too
|
1629 | | - $runCommand = "$phpInterpreter -q $smwgNMIP/specials/SMWNotifyMe/SMW_NMSendMailAsync.php";
|
1630 | | - //TODO: test async code for linux.
|
1631 | | - //low prio
|
1632 | | - $nullResult = `$runCommand > /dev/null &`;
|
1633 | | - }
|
1634 | | - else //windowze
|
1635 | | - {
|
1636 | | - $runCommand = "\"\"$phpInterpreter\" -q \"$smwgNMIP/specials/SMWNotifyMe/SMW_NMSendMailAsync.php\"\"";
|
1637 | | - $wshShell = new COM("WScript.Shell");
|
1638 | | - $runCommand = "cmd /C ".$runCommand;
|
1639 | | -
|
1640 | | - $oExec = $wshShell->Run($runCommand, 7, false);
|
1641 | | - }
|
1642 | | - }
|
1643 | | - }
|
1644 | | - // copy from user class
|
1645 | | - function getUserNMOption( $str ) {
|
1646 | | - $options = array();
|
1647 | | - $a = explode( "\n", $str );
|
1648 | | - foreach ( $a as $s ) {
|
1649 | | - $m = array();
|
1650 | | - if ( preg_match( "/^(.[^=]*)=(.*)$/", $s, $m ) ) {
|
1651 | | - $options[$m[1]] = $m[2];
|
1652 | | - }
|
1653 | | - }
|
1654 | | - return $options['enotifyme'];
|
1655 | | - }
|
1656 | | -}
|
| 2 | +<?php |
| 3 | +/** |
| 4 | + * This file contains a static class for accessing functions to generate and execute |
| 5 | + * notify me semantic queries and to serialise their results. |
| 6 | + * |
| 7 | + * @author dch |
| 8 | + */ |
| 9 | + |
| 10 | +global $smwgIP, $smwgNMIP ; |
| 11 | +require_once( $smwgIP . '/includes/storage/SMW_Store.php' ); |
| 12 | +require_once( $smwgNMIP . '/includes/SMW_NMStorage.php' ); |
| 13 | + |
| 14 | +/** |
| 15 | + * Static class for accessing functions to generate and execute semantic queries |
| 16 | + * and to serialise their results. |
| 17 | + */ |
| 18 | +class SMWNotifyProcessor { |
| 19 | + |
| 20 | + static public function getNotifications() { |
| 21 | + $sStore = NMStorage::getDatabase(); |
| 22 | + global $wgUser; |
| 23 | + $user_id = $wgUser->getId(); |
| 24 | + |
| 25 | + $notifications = $sStore->getNotifications( $user_id ); |
| 26 | + |
| 27 | + return $notifications; |
| 28 | + } |
| 29 | + |
| 30 | + /** |
| 31 | + * Enable a NotifyMe with specified id and querystring |
| 32 | + * |
| 33 | + * used for inline query only |
| 34 | + */ |
| 35 | + static public function enableNotify( $notify_id, $querystring, &$msg = NULL ) { |
| 36 | + wfProfileIn( 'SMWNotifyProcessor::enableNotify (SMW)' ); |
| 37 | + |
| 38 | + $sStore = NMStorage::getDatabase(); |
| 39 | + global $smwgQDefaultNamespaces; |
| 40 | + |
| 41 | + SMWQueryProcessor::processFunctionParams( SMWNotifyProcessor::getQueryRawParams( $querystring ), $querystring, $params, $printouts ); |
| 42 | + $relatedArticles = array(); |
| 43 | + foreach ( $printouts as $po ) { |
| 44 | + if ( $po == $params['sort'] ) $sorted = true; |
| 45 | + $printoutArticles[] = array( |
| 46 | + 'namespace' => SMW_NS_PROPERTY, |
| 47 | + 'title' => Title::makeTitle( SMW_NS_PROPERTY, $po->getText() )->getDBkey() ); |
| 48 | + } |
| 49 | + if ( !$sorted && isset( $params['sort'] ) ) { |
| 50 | + $printoutArticles[] = array( |
| 51 | + 'namespace' => SMW_NS_PROPERTY, |
| 52 | + 'title' => Title::makeTitle( SMW_NS_PROPERTY, $params['sort'] )->getDBkey() ); |
| 53 | + } |
| 54 | + |
| 55 | + $qp = new SMWNotifyParser( $notify_id, $printoutArticles ); |
| 56 | + $qp->setDefaultNamespaces( $smwgQDefaultNamespaces ); |
| 57 | + $desc = $qp->getQueryDescription( $querystring ); |
| 58 | + |
| 59 | + if ( !$qp->m_result ) { |
| 60 | + $qp->m_errors[] = "The category / instance / property page in query may not exists."; |
| 61 | + } |
| 62 | + |
| 63 | + if ( isset( $msg ) && $qp->hasSubquery() ) { |
| 64 | + $msg .= "\nThe query contains subquery, which may affect the precision of notifications."; |
| 65 | + } |
| 66 | + |
| 67 | + $query = new SMWQuery( $desc, true, false ); |
| 68 | + $query->setQueryString( $querystring ); |
| 69 | + $query->addErrors( $qp->getErrors() ); // keep parsing errors for later output |
| 70 | + |
| 71 | + $res = $sStore->getNMQueryResult( $query ); |
| 72 | + |
| 73 | + if ( count( $query->getErrors() ) > 0 ) { |
| 74 | + if ( isset( $msg ) ) { |
| 75 | + $msg .= "\n\n" . implode( '\n', $query->getErrors() ) . "\n\nYou can enable the query in NotifyMe manager later."; |
| 76 | + } |
| 77 | + $sStore->disableNotifyState( $notify_id ); |
| 78 | + wfProfileOut( 'SMWNotifyProcessor::enableNotify (SMW)' ); |
| 79 | + return false; |
| 80 | + } |
| 81 | + |
| 82 | + $sStore->updateNMSql( $notify_id, $res['sql'], $res['tmp_hierarchy'] ); |
| 83 | + if ( count( $res['page_ids'] ) > 0 ) { |
| 84 | + $add_monitor = array(); |
| 85 | + foreach ( $res['page_ids'] as $page_id ) { |
| 86 | + $add_monitor[] = array( 'notify_id' => $notify_id, 'page_id' => $page_id ); |
| 87 | + } |
| 88 | + $sStore->addNotifyMonitor( $add_monitor ); |
| 89 | + } |
| 90 | + $sStore->updateNotifyState( $notify_id, 1 ); |
| 91 | + wfProfileOut( 'SMWNotifyProcessor::enableNotify (SMW)' ); |
| 92 | + |
| 93 | + return true; |
| 94 | + } |
| 95 | + |
| 96 | + static public function getQueryRawParams( $querystring ) { |
| 97 | + // read query with printouts and (possibly) other parameters like sort, order, limit, etc... |
| 98 | + $pos = strpos( $querystring, "|?" ); |
| 99 | + if ( $pos > 0 ) { |
| 100 | + $rawparams[] = trim( substr( $querystring, 0, $pos ) ); |
| 101 | + $ps = explode( "|?", trim( substr( $querystring, $pos + 2 ) ) ); |
| 102 | + foreach ( $ps as $param ) { |
| 103 | + $rawparams[] = "?" . trim( $param ); |
| 104 | + } |
| 105 | + } else { |
| 106 | + $ps = preg_split( '/[^\|]{1}\|{1}(?!\|)/s', $querystring ); |
| 107 | + if ( count( $ps ) > 1 ) { |
| 108 | + // last char of query condition is missing (matched with [^\|]{1}) therefore copy from original |
| 109 | + $rawparams[] = trim( substr( $querystring, 0, strlen( $ps[0] ) + 1 ) ); |
| 110 | + array_shift( $ps ); // remove the query condition |
| 111 | + // add other params for formating etc. |
| 112 | + foreach ( $ps as $param ) |
| 113 | + $rawparams[] = trim( $param ); |
| 114 | + } // no single pipe found, no params specified in query |
| 115 | + else $rawparams[] = trim( $querystring ); |
| 116 | + } |
| 117 | + $rawparams[] = "format=table"; |
| 118 | + $rawparams[] = "link=all"; |
| 119 | + return $rawparams; |
| 120 | + } |
| 121 | + |
| 122 | + static public function addNotify( $rawquery, $name, $rep_all, $show_all, $delegate ) { |
| 123 | + global $wgTitle; |
| 124 | + // Take care at least of some templates -- for better template support use #ask |
| 125 | + $parser = new Parser(); |
| 126 | + $parserOptions = new ParserOptions(); |
| 127 | + $parser->startExternalParse( $wgTitle, $parserOptions, OT_HTML ); |
| 128 | + $rawquery = $parser->transformMsg( $rawquery, $parserOptions ); |
| 129 | + |
| 130 | + wfProfileIn( 'SMWNotifyProcessor::createNotify (SMW)' ); |
| 131 | + $sStore = NMStorage::getDatabase(); |
| 132 | + global $wgUser; |
| 133 | + $user_id = $wgUser->getId(); |
| 134 | + if ( $user_id == 0 ) { |
| 135 | + wfProfileOut( 'SMWNotifyProcessor::createNotify (SMW)' ); |
| 136 | + return "You have not logged in yet, please log in and retry again. Thanks."; |
| 137 | + } |
| 138 | + |
| 139 | + // check notify query first, use QueryParser from SMW |
| 140 | + SMWQueryProcessor::processFunctionParams( SMWNotifyProcessor::getQueryRawParams( $rawquery ), $querystring, $params, $printouts ); |
| 141 | + |
| 142 | + $qp = new SMWQueryParser(); |
| 143 | + $qp->setDefaultNamespaces( $smwgQDefaultNamespaces ); |
| 144 | + $desc = $qp->getQueryDescription( $querystring ); |
| 145 | + |
| 146 | + if ( count( $qp->getErrors() ) > 0 ) { |
| 147 | + wfProfileOut( 'SMWNotifyProcessor::createNotify (SMW)' ); |
| 148 | + return "Notify create failed!\n\n" . implode( '\n', $qp->getErrors() ) . "\n\nPlease check the query and retry again"; |
| 149 | + } |
| 150 | + |
| 151 | + $notify_id = $sStore->addNotifyQuery( $user_id, $rawquery, $name, $rep_all, $show_all, $delegate ); |
| 152 | + if ( $notify_id == 0 ) { |
| 153 | + wfProfileOut( 'SMWNotifyProcessor::createNotify (SMW)' ); |
| 154 | + return "Fail to save query. Please retry later..."; |
| 155 | + } |
| 156 | + wfProfileOut( 'SMWNotifyProcessor::createNotify (SMW)' ); |
| 157 | + |
| 158 | + wfProfileIn( 'SMWNotifyProcessor::enableNotify (SMW)' ); |
| 159 | + $msg = ''; |
| 160 | + $result = SMWNotifyProcessor::enableNotify( $notify_id, $rawquery, $msg ); |
| 161 | + wfProfileOut( 'SMWNotifyProcessor::enableNotify (SMW)' ); |
| 162 | + return "1" . ( $result ? "1":"0" ) . "$notify_id,$msg"; |
| 163 | + } |
| 164 | + |
| 165 | + static public function updateStates( $notify_ids ) { |
| 166 | + wfProfileIn( 'SMWNotifyProcessor::updateStates (SMW)' ); |
| 167 | + |
| 168 | + $notifications = SMWNotifyProcessor::getNotifications(); |
| 169 | + if ( $notifications == null || !is_array( $notifications ) ) { |
| 170 | + return "No notifications available."; |
| 171 | + } |
| 172 | + $result = true; |
| 173 | + $idx = 0; |
| 174 | + $count = count( $notify_ids ) - 1; |
| 175 | + $msg = ''; |
| 176 | + $errs = ''; |
| 177 | + $sStore = NMStorage::getDatabase(); |
| 178 | + foreach ( $notifications as $row ) { |
| 179 | + if ( ( $idx < $count ) && ( $notify_ids[$idx] == $row['notify_id'] ) ) { |
| 180 | + if ( $row['enable'] == 0 ) { |
| 181 | + $m = ''; |
| 182 | + $r = SMWNotifyProcessor::enableNotify( $row['notify_id'], $row['query'], $m ); |
| 183 | + if ( !$r ) { |
| 184 | + $msg .= "NotifyMe : '" . $row['name'] . "'$m\n\n"; |
| 185 | + $errs .= $row['notify_id'] . ","; |
| 186 | + $result = false; |
| 187 | + } |
| 188 | + } |
| 189 | + $idx ++; |
| 190 | + } else { |
| 191 | + if ( $row['enable'] == 1 ) { |
| 192 | + $result = $sStore->disableNotifyState( $row['notify_id'] ); |
| 193 | + } |
| 194 | + } |
| 195 | + } |
| 196 | + |
| 197 | + wfProfileOut( 'SMWNotifyProcessor::updateStates (SMW)' ); |
| 198 | + return $result ? "States updated successfully!" : "0$errs|\n\n$msg"; |
| 199 | + } |
| 200 | + |
| 201 | + static public function updateDelegates( $delegates ) { |
| 202 | + wfProfileIn( 'SMWNotifyProcessor::updateDelegates (SMW)' ); |
| 203 | + |
| 204 | + $notifications = SMWNotifyProcessor::getNotifications(); |
| 205 | + if ( $notifications == null || !is_array( $notifications ) ) { |
| 206 | + return "No notifications available."; |
| 207 | + } |
| 208 | + $result = true; |
| 209 | + $idx = 0; |
| 210 | + $s = explode( ':', $delegates[$idx], 2 ); |
| 211 | + $count = count( $delegates ) - 1; |
| 212 | + $sStore = NMStorage::getDatabase(); |
| 213 | + foreach ( $notifications as $row ) { |
| 214 | + if ( ( $idx < $count ) && ( $s[0] == $row['notify_id'] ) ) { |
| 215 | + $result = $sStore->updateDelegate( $row['notify_id'], $s[1] ); |
| 216 | + $idx ++; |
| 217 | + $s = explode( ':', $delegates[$idx], 2 ); |
| 218 | + } else { |
| 219 | + $result = $sStore->updateDelegate( $row['notify_id'], '' ); |
| 220 | + } |
| 221 | + if ( !$result ) break; |
| 222 | + } |
| 223 | + |
| 224 | + wfProfileOut( 'SMWNotifyProcessor::updateDelegates (SMW)' ); |
| 225 | + return $result ? "Delegates updated successfully!" : "Delegates updated error!"; |
| 226 | + } |
| 227 | + |
| 228 | + static public function refreshNotifyMe() { |
| 229 | + wfProfileIn( 'SMWNotifyProcessor::refreshNotifyMe (SMW)' ); |
| 230 | + $notifications = NMStorage::getDatabase()->getAllNotifications(); |
| 231 | + foreach ( $notifications as $row ) { |
| 232 | + if ( $row['enable'] ) { |
| 233 | + $result = SMWNotifyProcessor::enableNotify( $row['notify_id'], $row['query'] ); |
| 234 | + } |
| 235 | + } |
| 236 | + wfProfileOut( 'SMWNotifyProcessor::refreshNotifyMe (SMW)' ); |
| 237 | + } |
| 238 | + |
| 239 | + static public function updateReportAll( $notify_ids ) { |
| 240 | + wfProfileIn( 'SMWNotifyProcessor::updateStates (SMW)' ); |
| 241 | + |
| 242 | + $notifications = SMWNotifyProcessor::getNotifications(); |
| 243 | + if ( $notifications == null || !is_array( $notifications ) ) { |
| 244 | + return "No notifications available."; |
| 245 | + } |
| 246 | + $result = true; |
| 247 | + $idx = 0; |
| 248 | + $count = count( $notify_ids ) - 1; |
| 249 | + $sStore = NMStorage::getDatabase(); |
| 250 | + foreach ( $notifications as $row ) { |
| 251 | + if ( ( $idx < $count ) && ( $notify_ids[$idx] == $row['notify_id'] ) ) { |
| 252 | + if ( $row['rep_all'] == 0 ) { |
| 253 | + $result = $sStore->updateNotifyReportAll( $row['notify_id'], 1 ); |
| 254 | + } |
| 255 | + $idx ++; |
| 256 | + } else { |
| 257 | + if ( $row['rep_all'] == 1 ) { |
| 258 | + $result = $sStore->updateNotifyReportAll( $row['notify_id'], 0 ); |
| 259 | + } |
| 260 | + } |
| 261 | + if ( !$result ) break; |
| 262 | + } |
| 263 | + |
| 264 | + wfProfileOut( 'SMWNotifyProcessor::updateStates (SMW)' ); |
| 265 | + return $result ? "States updated successfully!" : "States updated error!"; |
| 266 | + } |
| 267 | + |
| 268 | + static public function updateShowAll( $notify_ids ) { |
| 269 | + wfProfileIn( 'SMWNotifyProcessor::updateStates (SMW)' ); |
| 270 | + |
| 271 | + $notifications = SMWNotifyProcessor::getNotifications(); |
| 272 | + if ( $notifications == null || !is_array( $notifications ) ) { |
| 273 | + return "No notifications available."; |
| 274 | + } |
| 275 | + $result = true; |
| 276 | + $idx = 0; |
| 277 | + $count = count( $notify_ids ) - 1; |
| 278 | + $sStore = NMStorage::getDatabase(); |
| 279 | + foreach ( $notifications as $row ) { |
| 280 | + if ( ( $idx < $count ) && ( $notify_ids[$idx] == $row['notify_id'] ) ) { |
| 281 | + if ( $row['show_all'] == 0 ) { |
| 282 | + $result = $sStore->updateNotifyShowAll( $row['notify_id'], 1 ); |
| 283 | + } |
| 284 | + $idx ++; |
| 285 | + } else { |
| 286 | + if ( $row['show_all'] == 1 ) { |
| 287 | + $result = $sStore->updateNotifyShowAll( $row['notify_id'], 0 ); |
| 288 | + } |
| 289 | + } |
| 290 | + if ( !$result ) break; |
| 291 | + } |
| 292 | + |
| 293 | + wfProfileOut( 'SMWNotifyProcessor::updateStates (SMW)' ); |
| 294 | + return $result ? "States updated successfully!" : "States updated error!"; |
| 295 | + } |
| 296 | + |
| 297 | + static public function delNotify( $notify_ids ) { |
| 298 | + wfProfileIn( 'SMWNotifyProcessor::delNotify (SMW)' ); |
| 299 | + $sStore = NMStorage::getDatabase(); |
| 300 | + $result = $sStore->removeNotifyQuery( $notify_ids ); |
| 301 | + wfProfileOut( 'SMWNotifyProcessor::delNotify (SMW)' ); |
| 302 | + return $result ? "Notification(s) deleted successfully!" : "Notification(s) deleted error!"; |
| 303 | + } |
| 304 | + |
| 305 | + static protected $notifyJobs = array(); |
| 306 | + static public function prepareArticleSave( $title ) { |
| 307 | + $page_id = $title->getArticleID(); |
| 308 | + if ( $page_id == 0 ) { |
| 309 | + return; |
| 310 | + } |
| 311 | + $updates = SMWNotifyProcessor::$notifyJobs[$page_id]; |
| 312 | + if ( empty( $updates ) ) { |
| 313 | + SMWNotifyProcessor::$notifyJobs[$page_id] = new SMWNotifyUpdate( $title ); |
| 314 | + } |
| 315 | + } |
| 316 | + static public function articleSavedComplete( $title ) { |
| 317 | + $page_id = $title->getArticleID(); |
| 318 | + if ( $page_id == 0 ) { |
| 319 | + return; |
| 320 | + } |
| 321 | + $updates = SMWNotifyProcessor::$notifyJobs[$page_id]; |
| 322 | + if ( empty( $updates ) ) { |
| 323 | + SMWNotifyProcessor::$notifyJobs[$page_id] = new SMWNotifyUpdate( $title ); |
| 324 | + $updates = SMWNotifyProcessor::$notifyJobs[$page_id]; |
| 325 | + } else { |
| 326 | + $updates->executeNotifyUpdate(); |
| 327 | + } |
| 328 | + $updates->updateNotifyMonitor(); |
| 329 | + $updates->notifyUsers(); |
| 330 | + unset( SMWNotifyProcessor::$notifyJobs[$page_id] ); |
| 331 | + } |
| 332 | + static public function articleDelete( $title, $reason ) { |
| 333 | + $page_id = $title->getArticleID(); |
| 334 | + if ( $page_id == 0 ) { |
| 335 | + return; |
| 336 | + } |
| 337 | + $updates = new SMWNotifyUpdate( $title ); |
| 338 | + $updates->executeNotifyDelete( $reason ); |
| 339 | + } |
| 340 | + static public function toInfoId( $type, $subquery, $attr_id ) { |
| 341 | + return base_convert( strval( ( $subquery << 8 ) | $type ), 10, 9 ) . '9' . $attr_id; |
| 342 | + } |
| 343 | + static public function getInfoFromId( $id ) { |
| 344 | + $idx = strpos( $id, '9' ); |
| 345 | + $t = intval( base_convert( substr( $id, 0, $idx ), 9, 10 ) ); |
| 346 | + return array( |
| 347 | + 'type' => $t&0xFF, |
| 348 | + 'subquery' => $t >> 8, |
| 349 | + 'attr_id' => intval( substr( $id, $idx + 1 ) ) |
| 350 | + ); |
| 351 | + } |
| 352 | + |
| 353 | +} |
| 354 | + |
| 355 | +// based on SMW_QueryProcessor.php (v 1.4.2) |
| 356 | +/** |
| 357 | + * Objects of this class are in charge of parsing a query string in order |
| 358 | + * to create an SMWDescription. The class and methods are not static in order |
| 359 | + * to more cleanly store the intermediate state and progress of the parser. |
| 360 | + */ |
| 361 | +class SMWNotifyParser { |
| 362 | + |
| 363 | + protected $m_sepstack; // list of open blocks ("parentheses") that need closing at current step |
| 364 | + protected $m_curstring; // remaining string to be parsed (parsing eats query string from the front) |
| 365 | + var $m_errors; // empty array if all went right, array of strings otherwise |
| 366 | + protected $m_label; // label of the main query result |
| 367 | + protected $m_defaultns; // description of the default namespace restriction, or NULL if not used |
| 368 | + |
| 369 | + protected $m_categoryprefix; // cache label of category namespace . ':' |
| 370 | + protected $m_conceptprefix; // cache label of concept namespace . ':' |
| 371 | + protected $m_queryfeatures; // query features to be supported, format similar to $smwgQFeatures |
| 372 | + |
| 373 | + // added by dch |
| 374 | + protected $m_notify_id; |
| 375 | + protected $m_subquery; |
| 376 | + protected $m_printoutArticles; |
| 377 | + public $m_result; |
| 378 | + |
| 379 | + // modified by dch |
| 380 | + public function SMWNotifyParser( $notify_id, $printoutArticles, $queryfeatures = false ) { |
| 381 | + $this->m_notify_id = $notify_id; |
| 382 | + $this->m_printoutArticles = $printoutArticles; |
| 383 | + $this->m_result = true; |
| 384 | + |
| 385 | + global $wgContLang, $smwgQFeatures; |
| 386 | + $this->m_categoryprefix = $wgContLang->getNsText( NS_CATEGORY ) . ':'; |
| 387 | + $this->m_conceptprefix = $wgContLang->getNsText( SMW_NS_CONCEPT ) . ':'; |
| 388 | + $this->m_defaultns = NULL; |
| 389 | + $this->m_queryfeatures = $queryfeatures === false ? $smwgQFeatures:$queryfeatures; |
| 390 | + } |
| 391 | + |
| 392 | + // added by dch |
| 393 | + public function hasSubquery() { |
| 394 | + return $this->m_subquery > 1; |
| 395 | + } |
| 396 | + |
| 397 | + /** |
| 398 | + * Provide an array of namespace constants that are used as default restrictions. |
| 399 | + * If NULL is given, no such default restrictions will be added (faster). |
| 400 | + */ |
| 401 | + public function setDefaultNamespaces( $nsarray ) { |
| 402 | + $this->m_defaultns = NULL; |
| 403 | + if ( $nsarray !== NULL ) { |
| 404 | + foreach ( $nsarray as $ns ) { |
| 405 | + $this->m_defaultns = $this->addDescription( $this->m_defaultns, new SMWNamespaceDescription( $ns ), false ); |
| 406 | + } |
| 407 | + } |
| 408 | + } |
| 409 | + |
| 410 | + /** |
| 411 | + * Compute an SMWDescription from a query string. Returns whatever descriptions could be |
| 412 | + * wrestled from the given string (the most general result being SMWThingDescription if |
| 413 | + * no meaningful condition was extracted). |
| 414 | + */ |
| 415 | + public function getQueryDescription( $querystring ) { |
| 416 | + wfProfileIn( 'SMWNotifyParser::getQueryDescription (SMW)' ); |
| 417 | + $this->m_errors = array(); |
| 418 | + $this->m_label = ''; |
| 419 | + $this->m_curstring = $querystring; |
| 420 | + $this->m_sepstack = array(); |
| 421 | + $setNS = false; |
| 422 | + |
| 423 | + // added by dch |
| 424 | + $this->m_subquery = 0; |
| 425 | + |
| 426 | + $result = $this->getSubqueryDescription( $setNS, $this->m_label ); |
| 427 | + if ( !$setNS ) { // add default namespaces if applicable |
| 428 | + $result = $this->addDescription( $this->m_defaultns, $result ); |
| 429 | + } |
| 430 | + if ( $result === NULL ) { // parsing went wrong, no default namespaces |
| 431 | + $result = new SMWThingDescription(); |
| 432 | + } |
| 433 | + wfProfileOut( 'SMWNotifyParser::getQueryDescription (SMW)' ); |
| 434 | + return $result; |
| 435 | + } |
| 436 | + |
| 437 | + /** |
| 438 | + * Return array of error messages (possibly empty). |
| 439 | + */ |
| 440 | + public function getErrors() { |
| 441 | + return $this->m_errors; |
| 442 | + } |
| 443 | + |
| 444 | + /** |
| 445 | + * Return error message or empty string if no error occurred. |
| 446 | + */ |
| 447 | + public function getErrorString() { |
| 448 | + return smwfEncodeMessages( $this->m_errors ); |
| 449 | + } |
| 450 | + |
| 451 | + /** |
| 452 | + * Return label for the results of this query (which |
| 453 | + * might be empty if no such information was passed). |
| 454 | + */ |
| 455 | + public function getLabel() { |
| 456 | + return $this->m_label; |
| 457 | + } |
| 458 | + |
| 459 | + |
| 460 | + /** |
| 461 | + * Compute an SMWDescription for current part of a query, which should |
| 462 | + * be a standalone query (the main query or a subquery enclosed within |
| 463 | + * "\<q\>...\</q\>". Recursively calls similar methods and returns NULL upon error. |
| 464 | + * |
| 465 | + * The call-by-ref parameter $setNS is a boolean. Its input specifies whether |
| 466 | + * the query should set the current default namespace if no namespace restrictions |
| 467 | + * were given. If false, the calling super-query is happy to set the required |
| 468 | + * NS-restrictions by itself if needed. Otherwise the subquery has to impose the defaults. |
| 469 | + * This is so, since outermost queries and subqueries of disjunctions will have to set |
| 470 | + * their own default restrictions. |
| 471 | + * |
| 472 | + * The return value of $setNS specifies whether or not the subquery has a namespace |
| 473 | + * specification in place. This might happen automatically if the query string imposes |
| 474 | + * such restrictions. The return value is important for those callers that otherwise |
| 475 | + * set up their own restrictions. |
| 476 | + * |
| 477 | + * Note that $setNS is no means to switch on or off default namespaces in general, |
| 478 | + * but just controls query generation. For general effect, the default namespaces |
| 479 | + * should be set to NULL. |
| 480 | + * |
| 481 | + * The call-by-ref parameter $label is used to append any label strings found. |
| 482 | + */ |
| 483 | + protected function getSubqueryDescription( &$setNS, &$label ) { |
| 484 | + global $smwgQPrintoutLimit; |
| 485 | + wfLoadExtensionMessages( 'SemanticMediaWiki' ); |
| 486 | + $conjunction = NULL; // used for the current inner conjunction |
| 487 | + $disjuncts = array(); // (disjunctive) array of subquery conjunctions |
| 488 | + $printrequests = array(); // the printrequests found for this query level |
| 489 | + $hasNamespaces = false; // does the current $conjnuction have its own namespace restrictions? |
| 490 | + $mustSetNS = $setNS; // must ns restrictions be set? (may become true even if $setNS is false) |
| 491 | + |
| 492 | + // added by dch |
| 493 | + $subquery = $this->m_subquery; |
| 494 | + if ( $subquery == 0 ) { |
| 495 | + $relatedArticles = $this->m_printoutArticles; |
| 496 | + } else { |
| 497 | + $relatedArticles = array(); |
| 498 | + } |
| 499 | + $this->m_subquery ++; |
| 500 | + |
| 501 | + $continue = ( $chunk = $this->readChunk() ) != ''; // skip empty subquery completely, thorwing an error |
| 502 | + while ( $continue ) { |
| 503 | + $setsubNS = false; |
| 504 | + switch ( $chunk ) { |
| 505 | + case '[[': // start new link block |
| 506 | + // modified by dch |
| 507 | + $ld = $this->getLinkDescription( $setsubNS, $label, $relatedArticles ); |
| 508 | + |
| 509 | + if ( $ld instanceof SMWPrintRequest ) { |
| 510 | + $printrequests[] = $ld; |
| 511 | + } elseif ( $ld instanceof SMWDescription ) { |
| 512 | + $conjunction = $this->addDescription( $conjunction, $ld ); |
| 513 | + } |
| 514 | + break; |
| 515 | + case '<q>': // enter new subquery, currently irrelevant but possible |
| 516 | + $this->pushDelimiter( '</q>' ); |
| 517 | + $conjunction = $this->addDescription( $conjunction, $this->getSubqueryDescription( $setsubNS, $label ) ); |
| 518 | + // / TODO: print requests from subqueries currently are ignored, should be moved down |
| 519 | + break; |
| 520 | + case 'OR': case '||': case '': case '</q>': // finish disjunction and maybe subquery |
| 521 | + if ( $this->m_defaultns !== NULL ) { // possibly add namespace restrictions |
| 522 | + if ( $hasNamespaces && !$mustSetNS ) { |
| 523 | + // add ns restrictions to all earlier conjunctions (all of which did not have them yet) |
| 524 | + $mustSetNS = true; // enforce NS restrictions from now on |
| 525 | + $newdisjuncts = array(); |
| 526 | + foreach ( $disjuncts as $conj ) { |
| 527 | + $newdisjuncts[] = $this->addDescription( $conj, $this->m_defaultns ); |
| 528 | + } |
| 529 | + $disjuncts = $newdisjuncts; |
| 530 | + } elseif ( !$hasNamespaces && $mustSetNS ) { |
| 531 | + // add ns restriction to current result |
| 532 | + $conjunction = $this->addDescription( $conjunction, $this->m_defaultns ); |
| 533 | + } |
| 534 | + } |
| 535 | + $disjuncts[] = $conjunction; |
| 536 | + // start anew |
| 537 | + $conjunction = NULL; |
| 538 | + $hasNamespaces = false; |
| 539 | + // finish subquery? |
| 540 | + if ( $chunk == '</q>' ) { |
| 541 | + if ( $this->popDelimiter( '</q>' ) ) { |
| 542 | + $continue = false; // leave the loop |
| 543 | + } else { |
| 544 | + $this->m_errors[] = wfMsgForContent( 'smw_toomanyclosing', $chunk ); |
| 545 | + return NULL; |
| 546 | + } |
| 547 | + } elseif ( $chunk == '' ) { |
| 548 | + $continue = false; |
| 549 | + } |
| 550 | + break; |
| 551 | + case '+': // "... AND true" (ignore) |
| 552 | + break; |
| 553 | + default: // error: unexpected $chunk |
| 554 | + $this->m_errors[] = wfMsgForContent( 'smw_unexpectedpart', $chunk ); |
| 555 | + // return NULL; // Try to go on, it can only get better ... |
| 556 | + } |
| 557 | + if ( $setsubNS ) { // namespace restrictions encountered in current conjunct |
| 558 | + $hasNamespaces = true; |
| 559 | + } |
| 560 | + if ( $continue ) { // read on only if $continue remained true |
| 561 | + $chunk = $this->readChunk(); |
| 562 | + } |
| 563 | + } |
| 564 | + |
| 565 | + if ( count( $disjuncts ) > 0 ) { // make disjunctive result |
| 566 | + $result = NULL; |
| 567 | + foreach ( $disjuncts as $d ) { |
| 568 | + if ( $d === NULL ) { |
| 569 | + $this->m_errors[] = wfMsgForContent( 'smw_emptysubquery' ); |
| 570 | + $setNS = false; |
| 571 | + return NULL; |
| 572 | + } else { |
| 573 | + $result = $this->addDescription( $result, $d, false ); |
| 574 | + } |
| 575 | + } |
| 576 | + } else { |
| 577 | + $this->m_errors[] = wfMsgForContent( 'smw_emptysubquery' ); |
| 578 | + $setNS = false; |
| 579 | + return NULL; |
| 580 | + } |
| 581 | + $setNS = $mustSetNS; // NOTE: also false if namespaces were given but no default NS descs are available |
| 582 | + |
| 583 | + $prcount = 0; |
| 584 | + foreach ( $printrequests as $pr ) { // add printrequests |
| 585 | + if ( $prcount < $smwgQPrintoutLimit ) { |
| 586 | + $result->addPrintRequest( $pr ); |
| 587 | + $prcount++; |
| 588 | + } else { |
| 589 | + $this->m_errors[] = wfMsgForContent( 'smw_overprintoutlimit' ); |
| 590 | + break; |
| 591 | + } |
| 592 | + } |
| 593 | + |
| 594 | + // added by dch |
| 595 | + if ( $this->m_result ) { |
| 596 | + $sStore = NMStorage::getDatabase(); |
| 597 | + $this->m_result = $sStore->addNotifyRelations( $this->m_notify_id, $relatedArticles, $subquery ); |
| 598 | + } |
| 599 | + |
| 600 | + return $result; |
| 601 | + } |
| 602 | + |
| 603 | + /** |
| 604 | + * Compute an SMWDescription for current part of a query, which should |
| 605 | + * be the content of "[[ ... ]]". Alternatively, if the current syntax |
| 606 | + * specifies a print request, return the print request object. |
| 607 | + * Returns NULL upon error. |
| 608 | + * |
| 609 | + * Parameters $setNS and $label have the same use as in getSubqueryDescription(). |
| 610 | + */ |
| 611 | + // modified by dch, add $relatedArticles |
| 612 | + protected function getLinkDescription( &$setNS, &$label, &$relatedArticles ) { |
| 613 | + // This method is called when we encountered an opening '[['. The following |
| 614 | + // block could be a Category-statement, fixed object, property statements, |
| 615 | + // or according print statements. |
| 616 | + $chunk = $this->readChunk( '', true, false ); // NOTE: untrimmed, initial " " escapes prop. chains |
| 617 | + if ( ( smwfNormalTitleText( $chunk ) == $this->m_categoryprefix ) || // category statement or |
| 618 | + ( smwfNormalTitleText( $chunk ) == $this->m_conceptprefix ) ) { // concept statement |
| 619 | + return $this->getClassDescription( $setNS, $label, $relatedArticles, |
| 620 | + ( smwfNormalTitleText( $chunk ) == $this->m_categoryprefix ) ); |
| 621 | + } else { // fixed subject, namespace restriction, property query, or subquery |
| 622 | + $sep = $this->readChunk( '', false ); // do not consume hit, "look ahead" |
| 623 | + if ( ( $sep == '::' ) || ( $sep == ':=' ) ) { |
| 624 | + if ( $chunk { 0 } != ':' ) { // property statement |
| 625 | + return $this->getPropertyDescription( $chunk, $setNS, $label, $relatedArticles ); |
| 626 | + } else { // escaped article description, read part after :: to get full contents |
| 627 | + $chunk .= $this->readChunk( '\[\[|\]\]|\|\||\|' ); |
| 628 | + return $this->getArticleDescription( trim( $chunk ), $setNS, $label, $relatedArticles ); |
| 629 | + } |
| 630 | + } else { // Fixed article/namespace restriction. $sep should be ]] or || |
| 631 | + return $this->getArticleDescription( trim( $chunk ), $setNS, $label, $relatedArticles ); |
| 632 | + } |
| 633 | + } |
| 634 | + } |
| 635 | + |
| 636 | + /** |
| 637 | + * Parse a category description (the part of an inline query that |
| 638 | + * is in between "[[Category:" and the closing "]]" and create a |
| 639 | + * suitable description. |
| 640 | + */ |
| 641 | + // modified by dch ,add $relatedArticles |
| 642 | + protected function getClassDescription( &$setNS, &$label, &$relatedArticles, $category = true ) { |
| 643 | + global $smwgSMWBetaCompatible; // * printouts only for this old version |
| 644 | + // note: no subqueries allowed here, inline disjunction allowed, wildcards allowed |
| 645 | + $result = NULL; |
| 646 | + $continue = true; |
| 647 | + while ( $continue ) { |
| 648 | + $chunk = $this->readChunk(); |
| 649 | + if ( $chunk == '+' ) { |
| 650 | + // wildcard, ignore for categories (semantically meaningless, everything is in some class) |
| 651 | + } elseif ( ( $chunk == '+' ) && $category && $smwgSMWBetaCompatible ) { // print statement |
| 652 | + $chunk = $this->readChunk( '\]\]|\|' ); |
| 653 | + if ( $chunk == '|' ) { |
| 654 | + $printlabel = $this->readChunk( '\]\]' ); |
| 655 | + if ( $printlabel != ']]' ) { |
| 656 | + $chunk = $this->readChunk( '\]\]' ); |
| 657 | + } else { |
| 658 | + $printlabel = ''; |
| 659 | + $chunk = ']]'; |
| 660 | + } |
| 661 | + } else { |
| 662 | + global $wgContLang; |
| 663 | + $printlabel = $wgContLang->getNSText( NS_CATEGORY ); |
| 664 | + } |
| 665 | + if ( $chunk == ']]' ) { |
| 666 | + return new SMWPrintRequest( SMWPrintRequest::PRINT_CATS, $printlabel ); |
| 667 | + } else { |
| 668 | + $this->m_errors[] = wfMsgForContent( 'smw_badprintout' ); |
| 669 | + return NULL; |
| 670 | + } |
| 671 | + } else { // assume category/concept title |
| 672 | + // / NOTE: use m_c...prefix to prevent problems with, e.g., [[Category:Template:Test]] |
| 673 | + $class = Title::newFromText( ( $category ? $this->m_categoryprefix:$this->m_conceptprefix ) . $chunk ); |
| 674 | + if ( $class !== NULL ) { |
| 675 | + $desc = $category ? new SMWClassDescription( $class ):new SMWConceptDescription( $class ); |
| 676 | + $result = $this->addDescription( $result, $desc, false ); |
| 677 | + } |
| 678 | + |
| 679 | + // added by dch |
| 680 | + if ( $category ) { |
| 681 | + $relatedArticles[] = array( |
| 682 | + 'namespace' => NS_CATEGORY, |
| 683 | + 'title' => $class->getDBkey() ); |
| 684 | + } |
| 685 | + |
| 686 | + } |
| 687 | + $chunk = $this->readChunk(); |
| 688 | + $continue = ( $chunk == '||' ) && $category; // disjunctions only for cateories |
| 689 | + } |
| 690 | + |
| 691 | + return $this->finishLinkDescription( $chunk, false, $result, $setNS, $label ); |
| 692 | + } |
| 693 | + |
| 694 | + /** |
| 695 | + * Parse a property description (the part of an inline query that |
| 696 | + * is in between "[[Some property::" and the closing "]]" and create a |
| 697 | + * suitable description. The "::" is the first chunk on the current |
| 698 | + * string. |
| 699 | + */ |
| 700 | + // modified by dch ,add $relatedArticles |
| 701 | + protected function getPropertyDescription( $propertyname, &$setNS, &$label, &$relatedArticles ) { |
| 702 | + global $smwgSMWBetaCompatible; // support for old * printouts of beta |
| 703 | + wfLoadExtensionMessages( 'SemanticMediaWiki' ); |
| 704 | + $this->readChunk(); // consume separator ":=" or "::" |
| 705 | + // first process property chain syntax (e.g. "property1.property2::value"): |
| 706 | + if ( $propertyname { 0 } == ' ' ) { // escape |
| 707 | + $propertynames = array( $propertyname ); |
| 708 | + } else { |
| 709 | + $propertynames = explode( '.', $propertyname ); |
| 710 | + } |
| 711 | + $properties = array(); |
| 712 | + $typeid = '_wpg'; |
| 713 | + foreach ( $propertynames as $name ) { |
| 714 | + if ( $typeid != '_wpg' ) { // non-final property in chain was no wikipage: not allowed |
| 715 | + $this->m_errors[] = wfMsgForContent( 'smw_valuesubquery', $prevname ); |
| 716 | + return NULL; // /TODO: read some more chunks and try to finish [[ ]] |
| 717 | + } |
| 718 | + $property = SMWPropertyValue::makeUserProperty( $name ); |
| 719 | + if ( !$property->isValid() ) { // illegal property identifier |
| 720 | + $this->m_errors = array_merge( $this->m_errors, $property->getErrors() ); |
| 721 | + return NULL; // /TODO: read some more chunks and try to finish [[ ]] |
| 722 | + } |
| 723 | + $typeid = $property->getTypeID(); |
| 724 | + $prevname = $name; |
| 725 | + $properties[] = $property; |
| 726 | + |
| 727 | + // added by dch |
| 728 | + $relatedArticles[] = array( |
| 729 | + 'namespace' => SMW_NS_PROPERTY, |
| 730 | + 'title' => $property->getDBkey() ); |
| 731 | + |
| 732 | + } // /NOTE: after iteration, $property and $typeid correspond to last value |
| 733 | + |
| 734 | + $innerdesc = NULL; |
| 735 | + $continue = true; |
| 736 | + while ( $continue ) { |
| 737 | + $chunk = $this->readChunk(); |
| 738 | + switch ( $chunk ) { |
| 739 | + case '+': // wildcard, add namespaces for page-type properties |
| 740 | + if ( ( $this->m_defaultns !== NULL ) && ( $typeid == '_wpg' ) ) { |
| 741 | + $innerdesc = $this->addDescription( $innerdesc, $this->m_defaultns, false ); |
| 742 | + } else { |
| 743 | + $innerdesc = $this->addDescription( $innerdesc, new SMWThingDescription(), false ); |
| 744 | + } |
| 745 | + $chunk = $this->readChunk(); |
| 746 | + break; |
| 747 | + case '<q>': // subquery, set default namespaces |
| 748 | + if ( $typeid == '_wpg' ) { |
| 749 | + $this->pushDelimiter( '</q>' ); |
| 750 | + $setsubNS = true; |
| 751 | + $sublabel = ''; |
| 752 | + $innerdesc = $this->addDescription( $innerdesc, $this->getSubqueryDescription( $setsubNS, $sublabel ), false ); |
| 753 | + } else { // no subqueries allowed for non-pages |
| 754 | + $this->m_errors[] = wfMsgForContent( 'smw_valuesubquery', end( $propertynames ) ); |
| 755 | + $innerdesc = $this->addDescription( $innerdesc, new SMWThingDescription(), false ); |
| 756 | + } |
| 757 | + $chunk = $this->readChunk(); |
| 758 | + break; |
| 759 | + default: // normal object value or print statement |
| 760 | + // read value(s), possibly with inner [[...]] |
| 761 | + $open = 1; |
| 762 | + $value = $chunk; |
| 763 | + $continue2 = true; |
| 764 | + // read value with inner [[, ]], || |
| 765 | + while ( ( $open > 0 ) && ( $continue2 ) ) { |
| 766 | + $chunk = $this->readChunk( '\[\[|\]\]|\|\||\|' ); |
| 767 | + switch ( $chunk ) { |
| 768 | + case '[[': // open new [[ ]] |
| 769 | + $open++; |
| 770 | + break; |
| 771 | + case ']]': // close [[ ]] |
| 772 | + $open--; |
| 773 | + break; |
| 774 | + case '|': case '||': // terminates only outermost [[ ]] |
| 775 | + if ( $open == 1 ) { |
| 776 | + $open = 0; |
| 777 | + } |
| 778 | + break; |
| 779 | + case '': // /TODO: report error; this is not good right now |
| 780 | + $continue2 = false; |
| 781 | + break; |
| 782 | + } |
| 783 | + if ( $open != 0 ) { |
| 784 | + $value .= $chunk; |
| 785 | + } |
| 786 | + } // /NOTE: at this point, we normally already read one more chunk behind the value |
| 787 | + |
| 788 | + if ( $typeid == '__nry' ) { // nary value |
| 789 | + $dv = SMWDataValueFactory::newPropertyObjectValue( $property ); |
| 790 | + $dv->acceptQuerySyntax(); |
| 791 | + $dv->setUserValue( $value ); |
| 792 | + $vl = $dv->getValueList(); |
| 793 | + $pm = $dv->getPrintModifier(); |
| 794 | + if ( $vl !== NULL ) { // prefer conditions over print statements (only one possible right now) |
| 795 | + $innerdesc = $this->addDescription( $innerdesc, $vl, false ); |
| 796 | + } elseif ( $pm !== false ) { |
| 797 | + if ( $chunk == '|' ) { |
| 798 | + $printlabel = $this->readChunk( '\]\]' ); |
| 799 | + if ( $printlabel != ']]' ) { |
| 800 | + $chunk = $this->readChunk( '\]\]' ); |
| 801 | + } else { |
| 802 | + $printlabel = ''; |
| 803 | + $chunk = ']]'; |
| 804 | + } |
| 805 | + } else { |
| 806 | + $printlabel = $property->getWikiValue(); |
| 807 | + } |
| 808 | + if ( $chunk == ']]' ) { |
| 809 | + return new SMWPrintRequest( SMWPrintRequest::PRINT_PROP, $printlabel, $property, $pm ); |
| 810 | + } else { |
| 811 | + $this->m_errors[] = wfMsgForContent( 'smw_badprintout' ); |
| 812 | + return NULL; |
| 813 | + } |
| 814 | + } |
| 815 | + } else { // unary value |
| 816 | + $comparator = SMW_CMP_EQ; |
| 817 | + $printmodifier = ''; |
| 818 | + SMWNotifyParser::prepareValue( $value, $comparator, $printmodifier ); |
| 819 | + if ( ( $value == '*' ) && $smwgSMWBetaCompatible ) { |
| 820 | + if ( $chunk == '|' ) { |
| 821 | + $printlabel = $this->readChunk( '\]\]' ); |
| 822 | + if ( $printlabel != ']]' ) { |
| 823 | + $chunk = $this->readChunk( '\]\]' ); |
| 824 | + } else { |
| 825 | + $printlabel = ''; |
| 826 | + $chunk = ']]'; |
| 827 | + } |
| 828 | + } else { |
| 829 | + $printlabel = $property->getWikiValue(); |
| 830 | + } |
| 831 | + if ( $chunk == ']]' ) { |
| 832 | + return new SMWPrintRequest( SMWPrintRequest::PRINT_PROP, $printlabel, $property, $printmodifier ); |
| 833 | + } else { |
| 834 | + $this->m_errors[] = wfMsgForContent( 'smw_badprintout' ); |
| 835 | + return NULL; |
| 836 | + } |
| 837 | + } else { |
| 838 | + $dv = SMWDataValueFactory::newPropertyObjectValue( $property, $value ); |
| 839 | + if ( !$dv->isValid() ) { |
| 840 | + $this->m_errors = $this->m_errors + $dv->getErrors(); |
| 841 | + $vd = new SMWThingDescription(); |
| 842 | + } else { |
| 843 | + $vd = new SMWValueDescription( $dv, $comparator ); |
| 844 | + } |
| 845 | + $innerdesc = $this->addDescription( $innerdesc, $vd, false ); |
| 846 | + } |
| 847 | + } |
| 848 | + } |
| 849 | + $continue = ( $chunk == '||' ); |
| 850 | + } |
| 851 | + |
| 852 | + if ( $innerdesc === NULL ) { // make a wildcard search |
| 853 | + if ( ( $this->m_defaultns !== NULL ) && ( $typeid == '_wpg' ) ) { |
| 854 | + $innerdesc = $this->addDescription( $innerdesc, $this->m_defaultns, false ); |
| 855 | + } else { |
| 856 | + $innerdesc = $this->addDescription( $innerdesc, new SMWThingDescription(), false ); |
| 857 | + } |
| 858 | + $this->m_errors[] = wfMsgForContent( 'smw_propvalueproblem', $property->getWikiValue() ); |
| 859 | + } |
| 860 | + $properties = array_reverse( $properties ); |
| 861 | + foreach ( $properties as $property ) { |
| 862 | + $innerdesc = new SMWSomeProperty( $property, $innerdesc ); |
| 863 | + } |
| 864 | + $result = $innerdesc; |
| 865 | + return $this->finishLinkDescription( $chunk, false, $result, $setNS, $label ); |
| 866 | + } |
| 867 | + |
| 868 | + |
| 869 | + /** |
| 870 | + * Prepare a single value string, possibly extracting comparators and |
| 871 | + * printmodifier. $value is changed to consist only of the remaining |
| 872 | + * effective value string, or of "*" for print statements. |
| 873 | + */ |
| 874 | + static public function prepareValue( &$value, &$comparator, &$printmodifier ) { |
| 875 | + global $smwgQComparators, $smwgSMWBetaCompatible; // support for old * printouts of beta |
| 876 | + // get print modifier behind * |
| 877 | + if ( $smwgSMWBetaCompatible ) { |
| 878 | + $list = preg_split( '/^\*/', $value, 2 ); |
| 879 | + if ( count( $list ) == 2 ) { // hit |
| 880 | + $value = '*'; |
| 881 | + $printmodifier = $list[1]; |
| 882 | + } else { |
| 883 | + $printmodifier = ''; |
| 884 | + } |
| 885 | + if ( $value == '*' ) { // printout statement |
| 886 | + return; |
| 887 | + } |
| 888 | + } |
| 889 | + $list = preg_split( '/^(' . $smwgQComparators . ')/u', $value, 2, PREG_SPLIT_DELIM_CAPTURE ); |
| 890 | + $comparator = SMW_CMP_EQ; |
| 891 | + if ( count( $list ) == 3 ) { // initial comparator found ($list[1] should be empty) |
| 892 | + switch ( $list[1] ) { |
| 893 | + case '<': |
| 894 | + $comparator = SMW_CMP_LEQ; |
| 895 | + $value = $list[2]; |
| 896 | + break; |
| 897 | + case '>': |
| 898 | + $comparator = SMW_CMP_GEQ; |
| 899 | + $value = $list[2]; |
| 900 | + break; |
| 901 | + case '!': |
| 902 | + $comparator = SMW_CMP_NEQ; |
| 903 | + $value = $list[2]; |
| 904 | + break; |
| 905 | + case '~': |
| 906 | + $comparator = SMW_CMP_LIKE; |
| 907 | + $value = $list[2]; |
| 908 | + break; |
| 909 | + // default: not possible |
| 910 | + } |
| 911 | + } |
| 912 | + } |
| 913 | + |
| 914 | + /** |
| 915 | + * Parse an article description (the part of an inline query that |
| 916 | + * is in between "[[" and the closing "]]" assuming it is not specifying |
| 917 | + * a category or property) and create a suitable description. |
| 918 | + * The first chunk behind the "[[" has already been read and is |
| 919 | + * passed as a parameter. |
| 920 | + */ |
| 921 | + // modified by dch ,add $relatedArticles |
| 922 | + protected function getArticleDescription( $firstchunk, &$setNS, &$label, &$relatedArticles ) { |
| 923 | + wfLoadExtensionMessages( 'SemanticMediaWiki' ); |
| 924 | + $chunk = $firstchunk; |
| 925 | + $result = NULL; |
| 926 | + $continue = true; |
| 927 | + // $innerdesc = NULL; |
| 928 | + while ( $continue ) { |
| 929 | + if ( $chunk == '<q>' ) { // no subqueries of the form [[<q>...</q>]] (not needed) |
| 930 | + $this->m_errors[] = wfMsgForContent( 'smw_misplacedsubquery' ); |
| 931 | + return NULL; |
| 932 | + } |
| 933 | + $list = preg_split( '/:/', $chunk, 3 ); // ":Category:Foo" "User:bar" ":baz" ":+" |
| 934 | + if ( ( $list[0] == '' ) && ( count( $list ) == 3 ) ) { |
| 935 | + $list = array_slice( $list, 1 ); |
| 936 | + } |
| 937 | + if ( ( count( $list ) == 2 ) && ( $list[1] == '+' ) ) { // try namespace restriction |
| 938 | + global $wgContLang; |
| 939 | + $idx = $wgContLang->getNsIndex( $list[0] ); |
| 940 | + if ( $idx !== false ) { |
| 941 | + $result = $this->addDescription( $result, new SMWNamespaceDescription( $idx ), false ); |
| 942 | + } |
| 943 | + } else { |
| 944 | + $value = SMWDataValueFactory::newTypeIDValue( '_wpg', $chunk ); |
| 945 | + if ( $value->isValid() ) { |
| 946 | + $result = $this->addDescription( $result, new SMWValueDescription( $value ), false ); |
| 947 | + // added by dch |
| 948 | + $relatedArticles[] = array( |
| 949 | + 'namespace' => NS_MAIN, |
| 950 | + 'title' => Title::makeTitle( NS_MAIN, $chunk )->getDBkey() ); |
| 951 | + } |
| 952 | + } |
| 953 | + |
| 954 | + $chunk = $this->readChunk( '\[\[|\]\]|\|\||\|' ); |
| 955 | + if ( $chunk == '||' ) { |
| 956 | + $chunk = $this->readChunk( '\[\[|\]\]|\|\||\|' ); |
| 957 | + $continue = true; |
| 958 | + } else { |
| 959 | + $continue = false; |
| 960 | + } |
| 961 | + } |
| 962 | + |
| 963 | + return $this->finishLinkDescription( $chunk, true, $result, $setNS, $label ); |
| 964 | + } |
| 965 | + |
| 966 | + protected function finishLinkDescription( $chunk, $hasNamespaces, $result, &$setNS, &$label ) { |
| 967 | + wfLoadExtensionMessages( 'SemanticMediaWiki' ); |
| 968 | + if ( $result === NULL ) { // no useful information or concrete error found |
| 969 | + $this->m_errors[] = wfMsgForContent( 'smw_badqueryatom' ); |
| 970 | + } elseif ( !$hasNamespaces && $setNS && ( $this->m_defaultns !== NULL ) ) { |
| 971 | + $result = $this->addDescription( $result, $this->m_defaultns ); |
| 972 | + $hasNamespaces = true; |
| 973 | + } |
| 974 | + $setNS = $hasNamespaces; |
| 975 | + |
| 976 | + // terminate link (assuming that next chunk was read already) |
| 977 | + if ( $chunk == '|' ) { |
| 978 | + $chunk = $this->readChunk( '\]\]' ); |
| 979 | + if ( $chunk != ']]' ) { |
| 980 | + $label .= $chunk; |
| 981 | + $chunk = $this->readChunk( '\]\]' ); |
| 982 | + } else { // empty label does not add to overall label |
| 983 | + $chunk = ']]'; |
| 984 | + } |
| 985 | + } |
| 986 | + if ( $chunk != ']]' ) { |
| 987 | + // What happended? We found some chunk that could not be processed as |
| 988 | + // link content (as in [[Category:Test<q>]]) and there was no label to |
| 989 | + // eat it. Or the closing ]] are just missing entirely. |
| 990 | + if ( $chunk != '' ) { |
| 991 | + $this->m_errors[] = wfMsgForContent( 'smw_misplacedsymbol', htmlspecialchars( $chunk ) ); |
| 992 | + // try to find a later closing ]] to finish this misshaped subpart |
| 993 | + $chunk = $this->readChunk( '\]\]' ); |
| 994 | + if ( $chunk != ']]' ) { |
| 995 | + $chunk = $this->readChunk( '\]\]' ); |
| 996 | + } |
| 997 | + } |
| 998 | + if ( $chunk == '' ) { |
| 999 | + $this->m_errors[] = wfMsgForContent( 'smw_noclosingbrackets' ); |
| 1000 | + } |
| 1001 | + } |
| 1002 | + return $result; |
| 1003 | + } |
| 1004 | + |
| 1005 | + /** |
| 1006 | + * Get the next unstructured string chunk from the query string. |
| 1007 | + * Chunks are delimited by any of the special strings used in inline queries |
| 1008 | + * (such as [[, ]], <q>, ...). If the string starts with such a delimiter, |
| 1009 | + * this delimiter is returned. Otherwise the first string in front of such a |
| 1010 | + * delimiter is returned. |
| 1011 | + * Trailing and initial spaces are ignored if $trim is true, and chunks |
| 1012 | + * consisting only of spaces are not returned. |
| 1013 | + * If there is no more qurey string left to process, the empty string is |
| 1014 | + * returned (and in no other case). |
| 1015 | + * |
| 1016 | + * The stoppattern can be used to customise the matching, especially in order to |
| 1017 | + * overread certain special symbols. |
| 1018 | + * |
| 1019 | + * $consume specifies whether the returned chunk should be removed from the |
| 1020 | + * query string. |
| 1021 | + */ |
| 1022 | + protected function readChunk( $stoppattern = '', $consume = true, $trim = true ) { |
| 1023 | + if ( $stoppattern == '' ) { |
| 1024 | + $stoppattern = '\[\[|\]\]|::|:=|<q>|<\/q>|^' . $this->m_categoryprefix . |
| 1025 | + '|^' . $this->m_conceptprefix . '|\|\||\|'; |
| 1026 | + } |
| 1027 | + $chunks = preg_split( '/[\s]*(' . $stoppattern . ')/u', $this->m_curstring, 2, PREG_SPLIT_DELIM_CAPTURE ); |
| 1028 | + if ( count( $chunks ) == 1 ) { // no matches anymore, strip spaces and finish |
| 1029 | + if ( $consume ) { |
| 1030 | + $this->m_curstring = ''; |
| 1031 | + } |
| 1032 | + return $trim ? trim( $chunks[0] ):$chunks[0]; |
| 1033 | + } elseif ( count( $chunks ) == 3 ) { // this should generally happen if count is not 1 |
| 1034 | + if ( $chunks[0] == '' ) { // string started with delimiter |
| 1035 | + if ( $consume ) { |
| 1036 | + $this->m_curstring = $chunks[2]; |
| 1037 | + } |
| 1038 | + return $trim ? trim( $chunks[1] ):$chunks[1]; |
| 1039 | + } else { |
| 1040 | + if ( $consume ) { |
| 1041 | + $this->m_curstring = $chunks[1] . $chunks[2]; |
| 1042 | + } |
| 1043 | + return $trim ? trim( $chunks[0] ):$chunks[0]; |
| 1044 | + } |
| 1045 | + } else { return false; } // should never happen |
| 1046 | + } |
| 1047 | + |
| 1048 | + /** |
| 1049 | + * Enter a new subblock in the query, which must at some time be terminated by the |
| 1050 | + * given $endstring delimiter calling popDelimiter(); |
| 1051 | + */ |
| 1052 | + protected function pushDelimiter( $endstring ) { |
| 1053 | + array_push( $this->m_sepstack, $endstring ); |
| 1054 | + } |
| 1055 | + |
| 1056 | + /** |
| 1057 | + * Exit a subblock in the query ending with the given delimiter. |
| 1058 | + * If the delimiter does not match the top-most open block, false |
| 1059 | + * will be returned. Otherwise return true. |
| 1060 | + */ |
| 1061 | + protected function popDelimiter( $endstring ) { |
| 1062 | + $topdelim = array_pop( $this->m_sepstack ); |
| 1063 | + return ( $topdelim == $endstring ); |
| 1064 | + } |
| 1065 | + |
| 1066 | + /** |
| 1067 | + * Extend a given description by a new one, either by adding the new description |
| 1068 | + * (if the old one is a container description) or by creating a new container. |
| 1069 | + * The parameter $conjunction determines whether the combination of both descriptions |
| 1070 | + * should be a disjunction or conjunction. |
| 1071 | + * |
| 1072 | + * In the special case that the current description is NULL, the new one will just |
| 1073 | + * replace the current one. |
| 1074 | + * |
| 1075 | + * The return value is the expected combined description. The object $curdesc will |
| 1076 | + * also be changed (if it was non-NULL). |
| 1077 | + */ |
| 1078 | + protected function addDescription( $curdesc, $newdesc, $conjunction = true ) { |
| 1079 | + wfLoadExtensionMessages( 'SemanticMediaWiki' ); |
| 1080 | + $notallowedmessage = 'smw_noqueryfeature'; |
| 1081 | + if ( $newdesc instanceof SMWSomeProperty ) { |
| 1082 | + $allowed = $this->m_queryfeatures & SMW_PROPERTY_QUERY; |
| 1083 | + } elseif ( $newdesc instanceof SMWClassDescription ) { |
| 1084 | + $allowed = $this->m_queryfeatures & SMW_CATEGORY_QUERY; |
| 1085 | + } elseif ( $newdesc instanceof SMWConceptDescription ) { |
| 1086 | + $allowed = $this->m_queryfeatures & SMW_CONCEPT_QUERY; |
| 1087 | + } elseif ( $newdesc instanceof SMWConjunction ) { |
| 1088 | + $allowed = $this->m_queryfeatures & SMW_CONJUNCTION_QUERY; |
| 1089 | + $notallowedmessage = 'smw_noconjunctions'; |
| 1090 | + } elseif ( $newdesc instanceof SMWDisjunction ) { |
| 1091 | + $allowed = $this->m_queryfeatures & SMW_DISJUNCTION_QUERY; |
| 1092 | + $notallowedmessage = 'smw_nodisjunctions'; |
| 1093 | + } else { |
| 1094 | + $allowed = true; |
| 1095 | + } |
| 1096 | + if ( !$allowed ) { |
| 1097 | + $this->m_errors[] = wfMsgForContent( $notallowedmessage, str_replace( '[', '[', $newdesc->getQueryString() ) ); |
| 1098 | + return $curdesc; |
| 1099 | + } |
| 1100 | + if ( $newdesc === NULL ) { |
| 1101 | + return $curdesc; |
| 1102 | + } elseif ( $curdesc === NULL ) { |
| 1103 | + return $newdesc; |
| 1104 | + } else { // we already found descriptions |
| 1105 | + if ( ( ( $conjunction ) && ( $curdesc instanceof SMWConjunction ) ) || |
| 1106 | + ( ( !$conjunction ) && ( $curdesc instanceof SMWDisjunction ) ) ) { // use existing container |
| 1107 | + $curdesc->addDescription( $newdesc ); |
| 1108 | + return $curdesc; |
| 1109 | + } elseif ( $conjunction ) { // make new conjunction |
| 1110 | + if ( $this->m_queryfeatures & SMW_CONJUNCTION_QUERY ) { |
| 1111 | + return new SMWConjunction( array( $curdesc, $newdesc ) ); |
| 1112 | + } else { |
| 1113 | + $this->m_errors[] = wfMsgForContent( 'smw_noconjunctions', str_replace( '[', '[', $newdesc->getQueryString() ) ); |
| 1114 | + return $curdesc; |
| 1115 | + } |
| 1116 | + } else { // make new disjunction |
| 1117 | + if ( $this->m_queryfeatures & SMW_DISJUNCTION_QUERY ) { |
| 1118 | + return new SMWDisjunction( array( $curdesc, $newdesc ) ); |
| 1119 | + } else { |
| 1120 | + $this->m_errors[] = wfMsgForContent( 'smw_nodisjunctions', str_replace( '[', '[', $newdesc->getQueryString() ) ); |
| 1121 | + return $curdesc; |
| 1122 | + } |
| 1123 | + } |
| 1124 | + } |
| 1125 | + } |
| 1126 | +} |
| 1127 | + |
| 1128 | +class SMWNotifyUpdate { |
| 1129 | + protected $m_info; |
| 1130 | + protected $m_title; |
| 1131 | + protected $m_userMsgs; |
| 1132 | + protected $m_userHtmlPropMsgs; |
| 1133 | + protected $m_userHtmlNMMsgs; |
| 1134 | + protected $m_userNMs; |
| 1135 | + protected $m_notifyHtmlPropMsgs; |
| 1136 | + protected $m_notifyHtmlMsgs; |
| 1137 | + protected $m_newMonitor; |
| 1138 | + protected $m_removeMonitored; |
| 1139 | + protected $m_subQueryNotify; |
| 1140 | + |
| 1141 | + protected $m_linker; |
| 1142 | + |
| 1143 | + protected function getSemanticInfo( $title ) { |
| 1144 | + $result = array(); |
| 1145 | + $sStore = NMStorage::getDatabase(); |
| 1146 | + $semdata = smwfGetStore()->getSemanticData( $title ); |
| 1147 | + foreach ( $semdata->getProperties() as $property ) { |
| 1148 | + if ( !$property->isShown() && $property->getWikiValue() != '' ) { // showing this is not desired, hide |
| 1149 | + continue; |
| 1150 | + } elseif ( $property->isUserDefined() ) { // user defined property |
| 1151 | + $property->setCaption( preg_replace( '/[ ]/u', ' ', $property->getWikiValue(), 2 ) ); |
| 1152 | + } |
| 1153 | + |
| 1154 | + $propvalues = $semdata->getPropertyValues( $property ); |
| 1155 | + if ( $property->getWikiValue() != '' ) { |
| 1156 | + foreach ( $propvalues as $propvalue ) { |
| 1157 | + if ( $propvalue->getXSDValue() != '' ) { |
| 1158 | + $result[SMWNotifyProcessor::toInfoId( 2, 0, $sStore->lookupSmwId( SMW_NS_PROPERTY, $property->getXSDValue() ) )][] = array( 'name' => $property, 'value' => $propvalue ); |
| 1159 | + } |
| 1160 | + } |
| 1161 | + } else { |
| 1162 | + foreach ( $propvalues as $propvalue ) { |
| 1163 | + if ( ( $propvalue instanceof SMWWikiPageValue ) && ( $propvalue->getNamespace() == NS_CATEGORY ) ) { |
| 1164 | + $result[SMWNotifyProcessor::toInfoId( 0, 0, $sStore->lookupSmwId( NS_CATEGORY, $propvalue->getXSDValue() ) )][] = array( 'name' => $propvalue, 'value' => null ); |
| 1165 | + } |
| 1166 | + } |
| 1167 | + } |
| 1168 | + } |
| 1169 | + return $result; |
| 1170 | + } |
| 1171 | + |
| 1172 | + public function SMWNotifyUpdate( $title ) { |
| 1173 | + $this->m_title = $title; |
| 1174 | + $this->m_userMsgs = array(); |
| 1175 | + $this->m_userHtmlPropMsgs = array(); |
| 1176 | + $this->m_userHtmlNMMsgs = array(); |
| 1177 | + $this->m_userNMs = array(); |
| 1178 | + $this->m_notifyHtmlPropMsgs = array(); |
| 1179 | + $this->m_notifyHtmlMsgs = array(); |
| 1180 | + $this->m_newMonitor = array(); |
| 1181 | + $this->m_removeMonitored = array(); |
| 1182 | + $this->m_subQueryNotify = array(); |
| 1183 | + $this->m_linker = new Linker(); |
| 1184 | + |
| 1185 | + $page_id = $title->getArticleID(); |
| 1186 | + if ( ( $page_id == 0 ) || ( $this->m_title->getNamespace() != NS_MAIN ) ) { |
| 1187 | + return; |
| 1188 | + } |
| 1189 | + $this->m_info = $this->getSemanticInfo( $this->m_title ); |
| 1190 | + } |
| 1191 | + public function executeNotifyDelete( $reason ) { |
| 1192 | + $page_id = $this->m_title->getArticleID(); |
| 1193 | + if ( ( $page_id == 0 ) || ( $this->m_title->getNamespace() != NS_MAIN ) ) { |
| 1194 | + return; |
| 1195 | + } |
| 1196 | + $page_name = $this->m_title->getText() . ' (' . $this->m_title->getFullUrl() . ')'; |
| 1197 | + $page_html_name = '<a href="' . $this->m_title->getFullUrl() . '">' . htmlspecialchars( $this->m_title->getText() ) . '</a>'; |
| 1198 | + |
| 1199 | + $msg .= "\r\nPage $page_name has been deleted.\r\nReason : $reason"; |
| 1200 | + $sStore = NMStorage::getDatabase(); |
| 1201 | + $notifications = $sStore->getMonitoredNotifications( $page_id ); |
| 1202 | + |
| 1203 | + foreach ( $notifications as $user_id => $notifies ) { |
| 1204 | + $this->m_userMsgs[$user_id] .= $msg . '\r\n( NM: '; |
| 1205 | + $hint = "<P>Page $page_html_name has been deleted.<br/>Reason : <font color='red'>" . htmlspecialchars( $reason ) . "</font></P>"; |
| 1206 | + $this->m_userHtmlNMMsgs[$user_id] .= "$hint<P>Notify Me: "; |
| 1207 | + $idx = 0; |
| 1208 | + foreach ( $notifies as $notify_id => $notify_detail ) { |
| 1209 | + if ( $idx > 0 ) { |
| 1210 | + $this->m_userMsgs[$user_id] .= ', '; |
| 1211 | + $this->m_userHtmlNMMsgs[$user_id] .= ', '; |
| 1212 | + } |
| 1213 | + $this->m_notifyHtmlMsgs[$notify_id] .= $hint; |
| 1214 | + |
| 1215 | + $this->m_userMsgs[$user_id] .= $notify_detail['name']; |
| 1216 | + $this->m_userHtmlNMMsgs[$user_id] .= '<b>' . htmlspecialchars( $notify_detail['name'] ) . '</b>'; |
| 1217 | + $idx++; |
| 1218 | + $this->m_removeMonitored[] = array( 'notify_id' => $notify_id, 'page_id' => $page_id ); |
| 1219 | + |
| 1220 | + $this->m_userNMs[$user_id][] = $notify_id; |
| 1221 | + } |
| 1222 | + |
| 1223 | + $this->m_userMsgs[$user_id] .= " )."; |
| 1224 | + $this->m_userHtmlNMMsgs[$user_id] .= " does not match this page now.</P>"; |
| 1225 | + } |
| 1226 | + |
| 1227 | + $this->notifyUsers(); |
| 1228 | + $sStore->removeNotifyMonitor( $this->m_removeMonitored ); |
| 1229 | + } |
| 1230 | + function isEqual( $v1, $v2 ) { |
| 1231 | + return ( strval( $v1[value]->getXSDValue() ) == strval( $v2[value]->getXSDValue() ) ); |
| 1232 | + } |
| 1233 | + function getNotifyPlain( $info, $key ) { |
| 1234 | + $i = SMWNotifyProcessor::getInfoFromId( $key ); |
| 1235 | + if ( $i[type] == 0 ) { |
| 1236 | + return "\r\n'" . $info[name]->getWikiValue() . "' has been " . ( $info[sem_act] == 0 ? "deleted":"added" ) . "."; |
| 1237 | + } else { |
| 1238 | + $tmp = "\r\nProperty '" . $info[name]->getWikiValue() . "' has been " . ( $info[sem_act] == 0 ? "deleted.":( $info[sem_act] == 1 ? "modified":"added" ) ) . "."; |
| 1239 | + $first = true; |
| 1240 | + foreach ( $info[del_vals] as $val ) { |
| 1241 | + if ( $first ) { |
| 1242 | + $tmp .= "\r\nValue '"; |
| 1243 | + $first = false; |
| 1244 | + } else { |
| 1245 | + $tmp .= "', '"; |
| 1246 | + } |
| 1247 | + $tmp .= $val[plain]; |
| 1248 | + } |
| 1249 | + if ( !$first ) { |
| 1250 | + $tmp .= "' deleted."; |
| 1251 | + } |
| 1252 | + $first = true; |
| 1253 | + foreach ( $info[new_vals] as $val ) { |
| 1254 | + if ( $first ) { |
| 1255 | + $tmp .= "\r\nValue '"; |
| 1256 | + $first = false; |
| 1257 | + } else { |
| 1258 | + $tmp .= "', '"; |
| 1259 | + } |
| 1260 | + $tmp .= $val[plain]; |
| 1261 | + } |
| 1262 | + if ( !$first ) { |
| 1263 | + $tmp .= "' added."; |
| 1264 | + } |
| 1265 | + return $tmp . "\r\n"; |
| 1266 | + } |
| 1267 | + } |
| 1268 | + function getNotifyHtml( $info, $key ) { |
| 1269 | + $i = SMWNotifyProcessor::getInfoFromId( $key ); |
| 1270 | + if ( $i[type] == 0 ) { |
| 1271 | + return "<td>Category</td> |
| 1272 | + <td>" . $info[name]->getShortHTMLText( $this->m_linker ) . "</td> |
| 1273 | + <td>" . ( $info[sem_act] == 0 ? "<font color='green'>remove</font>":"<font color='red'>cite</font>" ) . "</td> |
| 1274 | + <td colspan='2'>N/A</td>"; |
| 1275 | + } else { |
| 1276 | + $rows = max( count( $info[del_vals] ), count( $info[new_vals] ) ); |
| 1277 | + $tmp = "<tr><td rowspan='$rows'>Property</td> |
| 1278 | + <td rowspan='$rows'>" . $info[name]->getShortHTMLText( $this->m_linker ) . "</td> |
| 1279 | + <td rowspan='$rows'>" . ( $info[sem_act] == 0 ? "<font color='green'>remove</font>":( $info[sem_act] == 1 ? "<font color='blue'>modify</font>":"<font color='red'>cite</font>" ) ) . "</td>"; |
| 1280 | + for ( $idx = 0; $idx < $rows; ++$idx ) { |
| 1281 | + if ( $idx > 0 ) { |
| 1282 | + $tmp .= "<tr>"; |
| 1283 | + } |
| 1284 | + $tmp .= "<td>" . ( isset( $info[del_vals][$idx] ) ? $info[del_vals][$idx][html]:" " ) . "</td> |
| 1285 | + <td>" . ( isset( $info[new_vals][$idx] ) ? $info[new_vals][$idx][html]:" " ) . "</td> |
| 1286 | + </tr>"; |
| 1287 | + } |
| 1288 | + return $tmp; |
| 1289 | + } |
| 1290 | + } |
| 1291 | + public function executeNotifyUpdate() { |
| 1292 | + $page_id = $this->m_title->getArticleID(); |
| 1293 | + if ( ( $page_id == 0 ) || ( $this->m_title->getNamespace() != NS_MAIN ) ) { |
| 1294 | + return; |
| 1295 | + } |
| 1296 | + $sStore = NMStorage::getDatabase(); |
| 1297 | + |
| 1298 | + $info = $this->getSemanticInfo( $this->m_title ); |
| 1299 | + // get different |
| 1300 | + $tmp_info = array(); // type : category 0, property 2; name; sem action : del 0, modify 1, add 2; val action : del 0, add 1 |
| 1301 | + foreach ( $this->m_info as $key => $value ) { |
| 1302 | + $i = SMWNotifyProcessor::getInfoFromId( $key ); |
| 1303 | + $updated = false; |
| 1304 | + if ( !isset( $info[$key] ) ) { |
| 1305 | + if ( $i[type] == 0 ) { |
| 1306 | + $tmp_info[$key] = array( 'sem_act' => 0, 'name' => $value[0][name] ); |
| 1307 | + } else { |
| 1308 | + $tmp_info[$key] = array( 'sem_act' => 0, 'name' => $value[0][name], 'del_vals' => array(), 'new_vals' => array() ); |
| 1309 | + foreach ( $value as $v ) { |
| 1310 | + $tmp_info[$key][del_vals][] = array( 'plain' => $v[value]->getWikiValue(), 'html' => $v[value]->getShortHTMLText( $this->m_linker ) ); |
| 1311 | + } |
| 1312 | + } |
| 1313 | + } else if ( $i[type] == 2 ) { |
| 1314 | + $mvalue = $info[$key]; |
| 1315 | + foreach ( $value as $v1 ) { |
| 1316 | + $found = false; |
| 1317 | + foreach ( $mvalue as $v2 ) { |
| 1318 | + if ( $this->isEqual( $v1, $v2 ) ) { |
| 1319 | + $found = true; |
| 1320 | + break; |
| 1321 | + } |
| 1322 | + } |
| 1323 | + if ( !$found ) { |
| 1324 | + if ( !$updated ) { |
| 1325 | + $updated = true; |
| 1326 | + $tmp_info[$key] = array( 'sem_act' => 1, 'name' => $value[0][name], 'del_vals' => array(), 'new_vals' => array() ); |
| 1327 | + } |
| 1328 | + $tmp_info[$key][del_vals][] = array( 'plain' => $v1[value]->getWikiValue(), 'html' => $v1[value]->getShortHTMLText( $this->m_linker ) ); |
| 1329 | + } |
| 1330 | + } |
| 1331 | + foreach ( $mvalue as $v1 ) { |
| 1332 | + $found = false; |
| 1333 | + foreach ( $value as $v2 ) { |
| 1334 | + if ( $this->isEqual( $v1, $v2 ) ) { |
| 1335 | + $found = true; |
| 1336 | + break; |
| 1337 | + } |
| 1338 | + } |
| 1339 | + if ( !$found ) { |
| 1340 | + if ( !$updated ) { |
| 1341 | + $updated = true; |
| 1342 | + $tmp_info[$key] = array( 'sem_act' => 1, 'name' => $value[0][name], 'del_vals' => array(), 'new_vals' => array() ); |
| 1343 | + } |
| 1344 | + $tmp_info[$key][new_vals][] = array( 'plain' => $v1[value]->getWikiValue(), 'html' => $v1[value]->getShortHTMLText( $this->m_linker ) ); |
| 1345 | + } |
| 1346 | + } |
| 1347 | + } |
| 1348 | + } |
| 1349 | + foreach ( $info as $key => $value ) { |
| 1350 | + $i = SMWNotifyProcessor::getInfoFromId( $key ); |
| 1351 | + if ( !isset( $this->m_info[$key] ) ) { |
| 1352 | + if ( $i[type] == 0 ) { |
| 1353 | + $tmp_info[$key] = array( 'sem_act' => 2, 'name' => $value[0][name] ); |
| 1354 | + } else { |
| 1355 | + $tmp_info[$key] = array( 'sem_act' => 2, 'name' => $value[0][name], 'del_vals' => array(), 'new_vals' => array() ); |
| 1356 | + foreach ( $value as $v ) { |
| 1357 | + $tmp_info[$key][new_vals][] = array( 'plain' => $v[value]->getWikiValue(), 'html' => $v[value]->getShortHTMLText( $this->m_linker ) ); |
| 1358 | + } |
| 1359 | + } |
| 1360 | + } |
| 1361 | + } |
| 1362 | + |
| 1363 | + $notifications = $sStore->getMonitoredNotificationsDetail( $page_id ); |
| 1364 | + // add semantic info to report all NM |
| 1365 | + foreach ( $notifications as $user_id => $notifies ) { |
| 1366 | + foreach ( $notifies['rep_all'] as $notify_id => $notify_name ) { |
| 1367 | + foreach ( array_keys( $tmp_info ) as $key ) { |
| 1368 | + $notifications[$user_id]['semantic'][$key][$notify_id] = $notify_name; |
| 1369 | + } |
| 1370 | + } |
| 1371 | + } |
| 1372 | + $page_name = $this->m_title->getText() . ' (' . $this->m_title->getFullUrl() . ')'; |
| 1373 | + |
| 1374 | + foreach ( $notifications as $user_id => $notifies ) { |
| 1375 | + foreach ( $notifies['semantic'] as $key => $notify ) { |
| 1376 | + if ( isset( $tmp_info[$key] ) ) { |
| 1377 | + $hint = ""; |
| 1378 | + if ( !isset( $this->m_userMsgs[$user_id] ) ) { |
| 1379 | + $this->m_userMsgs[$user_id] = "\r\nSemantic attributes are changed in page $page_name."; |
| 1380 | + $hint = "Semantic attributes are changed in page <a href='" . $this->m_title->getFullUrl() . "'>" . htmlspecialchars( $this->m_title->getText() ) . "</a>.<br/>"; |
| 1381 | + $this->m_userHtmlNMMsgs[$user_id] .= $hint; |
| 1382 | + } |
| 1383 | + |
| 1384 | + $this->m_userMsgs[$user_id] .= $this->getNotifyPlain( $tmp_info[$key], $key ) . ' ( NM: '; |
| 1385 | + $propHint = $this->getNotifyHtml( $tmp_info[$key], $key ); |
| 1386 | + $this->m_userHtmlPropMsgs[$user_id] .= $propHint . "<tr><td colspan='5'>Notify Me: "; |
| 1387 | + $idx = 0; |
| 1388 | + foreach ( $notify as $notify_id => $notify_name ) { |
| 1389 | + if ( $idx > 0 ) { |
| 1390 | + $this->m_userMsgs[$user_id] .= ', '; |
| 1391 | + $this->m_userHtmlPropMsgs[$user_id] .= ', '; |
| 1392 | + } |
| 1393 | + $this->m_userMsgs[$user_id] .= $notify_name; |
| 1394 | + $this->m_userHtmlPropMsgs[$user_id] .= '<b>' . htmlspecialchars( $notify_name ) . '</b>'; |
| 1395 | + $this->m_notifyHtmlMsgs[$notify_id] .= $hint; |
| 1396 | + $this->m_notifyHtmlPropMsgs[$notify_id] .= $propHint; |
| 1397 | + $idx++; |
| 1398 | + |
| 1399 | + $this->m_userNMs[$user_id][] = $notify_id; |
| 1400 | + } |
| 1401 | + $this->m_userMsgs[$user_id] .= ' ).'; |
| 1402 | + $this->m_userHtmlPropMsgs[$user_id] .= "</td></tr>"; |
| 1403 | + } |
| 1404 | + } |
| 1405 | + } |
| 1406 | + // get possible subquery |
| 1407 | + $this->m_subQueryNotify = array(); |
| 1408 | + $queries = $sStore->getPossibleQuery( $this->m_info ); |
| 1409 | + if ( is_array( $queries ) ) { |
| 1410 | + foreach ( $queries[1] as $notify_id => $notify ) { |
| 1411 | + $this->m_subQueryNotify[$notify_id] = $notify; |
| 1412 | + } |
| 1413 | + } |
| 1414 | + |
| 1415 | + $this->m_info = $info; |
| 1416 | + } |
| 1417 | + |
| 1418 | + // this will cost time, think we can update monitor in a single thread, like Job |
| 1419 | + public function updateNotifyMonitor() { |
| 1420 | + $page_id = $this->m_title->getArticleID(); |
| 1421 | + if ( ( $page_id == 0 ) || ( $this->m_title->getNamespace() != NS_MAIN ) ) { |
| 1422 | + return; |
| 1423 | + } |
| 1424 | + $sStore = NMStorage::getDatabase(); |
| 1425 | + $queries = $sStore->getPossibleQuery( $this->m_info ); |
| 1426 | + if ( !is_array( $queries ) ) { |
| 1427 | + return; |
| 1428 | + } |
| 1429 | + // get monitored query |
| 1430 | + $main_queries = $sStore->getMonitoredQuery( $page_id ); |
| 1431 | + foreach ( $queries[0] as $notify_id => $notify ) { |
| 1432 | + $main_queries[$notify_id] = $notify; |
| 1433 | + } |
| 1434 | + |
| 1435 | + // begin notify query on main query |
| 1436 | + $page_name = $this->m_title->getText() . ' (' . $this->m_title->getFullUrl() . ')'; |
| 1437 | + $page_html_name = '<a href="' . $this->m_title->getFullUrl() . '">' . htmlspecialchars( $this->m_title->getText() ) . '</a>'; |
| 1438 | + |
| 1439 | + foreach ( $main_queries as $notify_id => $notify ) { |
| 1440 | + $sStore->getNotifyInMainQuery( $page_id, $notify_id, $notify['sql'], $notify['hierarchy'], $match, $monitoring ); |
| 1441 | + if ( ( !$monitoring ) && $match ) { |
| 1442 | + $this->m_userMsgs[$notify['user_id']] .= "\r\nPage $page_name matches NotifyMe '$notify[name]' now."; |
| 1443 | + $hint = "Page $page_html_name matches \"<b>" . htmlspecialchars( $notify[name] ) . "</b>\" now.<br/>"; |
| 1444 | + $this->m_userHtmlNMMsgs[$notify['user_id']] .= $hint; |
| 1445 | + $this->m_notifyHtmlMsgs[$notify_id] .= $hint; |
| 1446 | + $this->m_newMonitor[] = array( 'notify_id' => $notify_id, 'page_id' => $page_id ); |
| 1447 | + } else if ( ( !$match ) && $monitoring ) { |
| 1448 | + $this->m_userMsgs[$notify['user_id']] .= "\r\nPage $page_name does not match NotifyMe '$notify[name]' now."; |
| 1449 | + $hint = "Page $page_html_name does not match \"<b>" . htmlspecialchars( $notify[name] ) . "</b>\" now.<br/>"; |
| 1450 | + $this->m_userHtmlNMMsgs[$notify['user_id']] .= $hint; |
| 1451 | + $this->m_notifyHtmlMsgs[$notify_id] .= $hint; |
| 1452 | + $this->m_removeMonitored[] = array( 'notify_id' => $notify_id, 'page_id' => $page_id ); |
| 1453 | + } |
| 1454 | + $this->m_userNMs[$notify['user_id']][] = $notify_id; |
| 1455 | + } |
| 1456 | + // begin notify query on sub query, should go through all pages |
| 1457 | + foreach ( $queries[1] as $notify_id => $notify ) { |
| 1458 | + $this->m_subQueryNotify[$notify_id] = $notify; |
| 1459 | + } |
| 1460 | + foreach ( $this->m_subQueryNotify as $notify_id => $notify ) { |
| 1461 | + $res = $sStore->getNotifyInSubquery( $notify_id, $notify['sql'], $notify['hierarchy'] ); |
| 1462 | + |
| 1463 | + $no_matches = array_diff( $res['monitoring'], $res['match'] ); |
| 1464 | + $matches = array_diff( $res['match'], $res['monitoring'] ); |
| 1465 | + foreach ( $matches as $pid ) { |
| 1466 | + $pt = $sStore->getPageTitle( $pid ); |
| 1467 | + if ( !$pt ) { |
| 1468 | + continue; |
| 1469 | + } |
| 1470 | + $t = Title::makeTitle( NS_MAIN, $pt->page_title ); |
| 1471 | + $p_name = $t->getText() . ' (' . $t->getFullUrl() . ')'; |
| 1472 | + $p_html_name = '<a href="' . $t->getFullUrl() . '">' . htmlspecialchars( $t->getText() ) . '</a>'; |
| 1473 | + |
| 1474 | + $this->m_userMsgs[$notify['user_id']] .= "\r\nSub page $page_name changed, $p_name matches NotifyMe '$notify[name]' now."; |
| 1475 | + $hint = "Sub page $page_html_name changed, $p_html_name matches \"<b>" . htmlspecialchars( $notify[name] ) . "</b>\" now.<br/>"; |
| 1476 | + $this->m_userHtmlNMMsgs[$notify['user_id']] .= $hint; |
| 1477 | + $this->m_notifyHtmlMsgs[$notify_id] .= $hint; |
| 1478 | + $this->m_newMonitor[] = array( 'notify_id' => $notify_id, 'page_id' => $pid ); |
| 1479 | + |
| 1480 | + $this->m_userNMs[$notify['user_id']][] = $notify_id; |
| 1481 | + } |
| 1482 | + foreach ( $no_matches as $pid ) { |
| 1483 | + $pt = $sStore->getPageTitle( $pid ); |
| 1484 | + if ( !$pt ) { |
| 1485 | + continue; |
| 1486 | + } |
| 1487 | + $t = Title::makeTitle( NS_MAIN, $pt->page_title ); |
| 1488 | + $p_name = $t->getText() . ' (' . $t->getFullUrl() . ')'; |
| 1489 | + $p_html_name = '<a href="' . $t->getFullUrl() . '">' . htmlspecialchars( $t->getText() ) . '</a>'; |
| 1490 | + |
| 1491 | + $this->m_userMsgs[$notify['user_id']] .= "\r\nSub page $page_name changed, page $p_name does not match NotifyMe '$notify[name]' now."; |
| 1492 | + $hint = "Sub page $page_html_name changed, $p_html_name does not match \"<b>" . htmlspecialchars( $notify[name] ) . "</b>\" now.<br/>"; |
| 1493 | + $this->m_userHtmlNMMsgs[$notify['user_id']] .= $hint; |
| 1494 | + $this->m_notifyHtmlMsgs[$notify_id] .= $hint; |
| 1495 | + $this->m_removeMonitored[] = array( 'notify_id' => $notify_id, 'page_id' => $pid ); |
| 1496 | + |
| 1497 | + $this->m_userNMs[$notify['user_id']][] = $notify_id; |
| 1498 | + } |
| 1499 | + } |
| 1500 | + |
| 1501 | + $sStore->removeNotifyMonitor( $this->m_removeMonitored ); |
| 1502 | + $sStore->addNotifyMonitor( $this->m_newMonitor ); |
| 1503 | + } |
| 1504 | + private function applyStyle( $html ) { |
| 1505 | + $html = str_replace( "class=\"smwtable\"", "style=\"background-color: #EEEEFF;\"", $html ); |
| 1506 | + $html = str_replace( "<th", "<th style=\"background-color: #EEEEFF;text-align: left;\"", $html ); |
| 1507 | + $html = str_replace( "<td", "<td style=\"background-color: #FFFFFF;padding: 1px;padding-left: 5px;padding-right: 5px;text-align: left;vertical-align: top;\"", $html ); |
| 1508 | + return $html; |
| 1509 | + } |
| 1510 | + public function notifyUsers() { |
| 1511 | + global $wgSitename, $wgSMTP, $wgEmergencyContact, $wgEnotifyMeJob; |
| 1512 | + $sStore = NMStorage::getDatabase(); |
| 1513 | + |
| 1514 | + $nm_send_jobs = array(); |
| 1515 | + $id = 0; |
| 1516 | + |
| 1517 | + if ( count( $this->m_notifyHtmlMsgs ) > 0 ) { |
| 1518 | + $notifications = $sStore->getNotifyMe( array_keys( $this->m_notifyHtmlMsgs ) ); |
| 1519 | + } |
| 1520 | + $html_style = ''; |
| 1521 | +// <style> |
| 1522 | +// table.smwtable{background-color: #EEEEFF;} |
| 1523 | +// table.smwtable th{background-color: #EEEEFF;text-align: left;} |
| 1524 | +// table.smwtable td{background-color: #FFFFFF;padding: 1px;padding-left: 5px;padding-right: 5px;text-align: left;vertical-align: top;} |
| 1525 | +// table.smwtable tr.smwfooter td{font-size: 90%;line-height: 1;background-color: #EEEEFF;padding: 0px;padding-left: 5px;padding-right: 5px;text-align: right;vertical-align: top;} |
| 1526 | +// </style>'; |
| 1527 | + $html_showall = array(); |
| 1528 | + foreach ( $this->m_notifyHtmlMsgs as $notify_id => $msg ) { |
| 1529 | + $html_msg = $html_style; |
| 1530 | + $showing_all = false; |
| 1531 | + if ( isset( $notifications[$notify_id] ) && $notifications[$notify_id]['show_all'] ) { |
| 1532 | + SMWQueryProcessor::processFunctionParams( explode( "\n", $notifications[$notify_id]['query'] ), $querystring, $params, $printouts ); |
| 1533 | + |
| 1534 | + $format = 'auto'; |
| 1535 | + if ( array_key_exists( 'format', $params ) ) { |
| 1536 | + $format = strtolower( trim( $params['format'] ) ); |
| 1537 | + global $smwgResultFormats; |
| 1538 | + if ( !array_key_exists( $format, $smwgResultFormats ) ) { |
| 1539 | + $format = 'auto'; |
| 1540 | + } |
| 1541 | + } |
| 1542 | + $query = SMWQueryProcessor::createQuery( $querystring, $params, SMWQueryProcessor::INLINE_QUERY, $format, $printouts ); |
| 1543 | + $res = smwfGetStore()->getQueryResult( $query ); |
| 1544 | + $printer = SMWQueryProcessor::getResultPrinter( $format, SMWQueryProcessor::INLINE_QUERY, $res ); |
| 1545 | + $result = $printer->getResult( $res, $params, SMW_OUTPUT_HTML ); |
| 1546 | + $html_msg .= $result . '<br/>'; |
| 1547 | + $html_showall[$notify_id] = array ( 'name' => $notifications[$notify_id]['name'], 'html' => $result ); |
| 1548 | + |
| 1549 | + $showing_all = true; |
| 1550 | + $link = $res->getQueryLink()->getURL(); |
| 1551 | + } |
| 1552 | + global $smwgNMHideDiffWhenShowAll; |
| 1553 | + if ( !( $smwgNMHideDiffWhenShowAll && $showing_all ) ) { |
| 1554 | + $html_msg .= '<p><b>Semantic changes from last revision:</b><br/><span style="font-size: 8pt;">' . $this->m_notifyHtmlMsgs[$notify_id] . '</span></P>'; |
| 1555 | + if ( isset( $this->m_notifyHtmlPropMsgs[$notify_id] ) ) { |
| 1556 | + $html_msg .= "<P><table class=\"smwtable\"><tr><th>Semantic type</th><th>Name</th><th>Action</th><th>Deleted</th><th>Added</th></tr>"; |
| 1557 | + $html_msg .= $this->m_notifyHtmlPropMsgs[$notify_id]; |
| 1558 | + $html_msg .= "</table></P>"; |
| 1559 | + } |
| 1560 | + } |
| 1561 | + if ( $showing_all ) { |
| 1562 | + $id = $sStore->addNotifyRSS( 'nid', $notify_id, "All current items, " . date( 'Y-m-d H:i:s', time() ), $this->applyStyle( $html_msg ), $link ); |
| 1563 | + } else { |
| 1564 | + $id = $sStore->addNotifyRSS( 'nid', $notify_id, $this->m_title->getText(), $this->applyStyle( $html_msg ) ); |
| 1565 | + } |
| 1566 | + } |
| 1567 | + foreach ( $this->m_userMsgs as $user_id => $msg ) { |
| 1568 | + // generate RSS items |
| 1569 | + $html_msg = $html_style; |
| 1570 | + foreach ( array_unique( $this->m_userNMs[$user_id] ) as $showall_nid ) { |
| 1571 | + if ( isset( $html_showall[$showall_nid] ) ) { |
| 1572 | + $html_msg .= "<br/>All current items for \"<b>" . $html_showall[$showall_nid]['name'] . "</b>\":<br/>"; |
| 1573 | + $html_msg .= $html_showall[$showall_nid]['html'] . '<br/>'; |
| 1574 | + } |
| 1575 | + } |
| 1576 | + |
| 1577 | + $html_msg .= '<p><b>Semantic changes from last revision:</b><br/><span style="font-size: 8pt;">' . $this->m_userHtmlNMMsgs[$user_id] . '</span></P>'; |
| 1578 | + if ( isset( $this->m_userHtmlPropMsgs[$user_id] ) ) { |
| 1579 | + $html_msg .= "<P><table class=\"smwtable\"><tr><th>Semantic type</th><th>Name</th><th>Action</th><th>Deleted</th><th>Added</th></tr>"; |
| 1580 | + $html_msg .= $this->m_userHtmlPropMsgs[$user_id]; |
| 1581 | + $html_msg .= "</table></P>"; |
| 1582 | + } |
| 1583 | + |
| 1584 | + $id = $sStore->addNotifyRSS( 'uid', $user_id, $this->m_title->getText(), $this->applyStyle( $html_msg ) ); |
| 1585 | + |
| 1586 | + if ( $wgEnotifyMeJob ) { |
| 1587 | + // send notifications by mail |
| 1588 | + $user_info = $sStore->getUserInfo( $user_id ); |
| 1589 | + if ( ( $user_info->user_email != '' ) && $this->getUserNMOption( $user_info->user_options ) ) { |
| 1590 | + $name = ( ( $user_info->user_real_name == '' ) ? $user_info->user_name:$user_info->user_real_name ); |
| 1591 | + $body = "Dear Mr./Mrs. $name,\r\n$msg" . |
| 1592 | + "\r\n\r\nSincerely yours,\r\nSMW NotifyMe Bot"; |
| 1593 | + |
| 1594 | + $params = array( 'to' => new MailAddress( $user_info->user_email, $name ), |
| 1595 | + 'from' => new MailAddress( $wgEmergencyContact, 'Admin' ), |
| 1596 | + 'subj' => 'New SMW Notification comes, from ' . $wgSitename, |
| 1597 | + 'body' => $body, |
| 1598 | + 'replyto' => new MailAddress( $wgEmergencyContact, 'Admin' ) ); |
| 1599 | + |
| 1600 | + $nm_send_jobs[] = new SMW_NMSendMailJob( $this->m_title, $params ); |
| 1601 | + } |
| 1602 | + } |
| 1603 | + } |
| 1604 | + |
| 1605 | + if ( $wgEnotifyMeJob ) { |
| 1606 | + if ( count( $nm_send_jobs ) ) { |
| 1607 | + Job :: batchInsert( $nm_send_jobs ); |
| 1608 | + } |
| 1609 | + } else { |
| 1610 | + global $phpInterpreter; |
| 1611 | + if ( !isset( $phpInterpreter ) ) { |
| 1612 | + // if $phpInterpreter is not set, assume it is in search path |
| 1613 | + // if not, starting of bot will FAIL! |
| 1614 | + $phpInterpreter = "php"; |
| 1615 | + } |
| 1616 | + // copy from SMW_GardeningBot.php |
| 1617 | + ob_start(); |
| 1618 | + phpinfo(); |
| 1619 | + $info = ob_get_contents(); |
| 1620 | + ob_end_clean(); |
| 1621 | + // Get Systemstring |
| 1622 | + preg_match( '!\nSystem(.*?)\n!is', strip_tags( $info ), $ma ); |
| 1623 | + // Check if it consists 'windows' as string |
| 1624 | + preg_match( '/[Ww]indows/', $ma[1], $os ); |
| 1625 | + global $smwgNMIP ; |
| 1626 | + if ( $os[0] == '' && $os[0] == null ) { |
| 1627 | + |
| 1628 | + // FIXME: $runCommand must allow whitespaces in paths too |
| 1629 | + $runCommand = "$phpInterpreter -q $smwgNMIP/specials/SMWNotifyMe/SMW_NMSendMailAsync.php"; |
| 1630 | + // TODO: test async code for linux. |
| 1631 | + // low prio |
| 1632 | + $nullResult = `$runCommand > /dev/null &`; |
| 1633 | + } |
| 1634 | + else // windowze |
| 1635 | + { |
| 1636 | + $runCommand = "\"\"$phpInterpreter\" -q \"$smwgNMIP/specials/SMWNotifyMe/SMW_NMSendMailAsync.php\"\""; |
| 1637 | + $wshShell = new COM( "WScript.Shell" ); |
| 1638 | + $runCommand = "cmd /C " . $runCommand; |
| 1639 | + |
| 1640 | + $oExec = $wshShell->Run( $runCommand, 7, false ); |
| 1641 | + } |
| 1642 | + } |
| 1643 | + } |
| 1644 | + // copy from user class |
| 1645 | + function getUserNMOption( $str ) { |
| 1646 | + $options = array(); |
| 1647 | + $a = explode( "\n", $str ); |
| 1648 | + foreach ( $a as $s ) { |
| 1649 | + $m = array(); |
| 1650 | + if ( preg_match( "/^(.[^=]*)=(.*)$/", $s, $m ) ) { |
| 1651 | + $options[$m[1]] = $m[2]; |
| 1652 | + } |
| 1653 | + } |
| 1654 | + return $options['enotifyme']; |
| 1655 | + } |
| 1656 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/includes/SMW_NotifyProcessor.php |
___________________________________________________________________ |
Name: svn:eol-style |
1657 | 1657 | + native |
Index: trunk/extensions/SemanticNotifyMe/includes/SNM_Initialize.php |
— | — | @@ -1,294 +1,293 @@ |
2 | | -<?php
|
3 | | -/*
|
4 | | - * Created on 24.6.2009
|
5 | | - *
|
6 | | - * Author: dch
|
7 | | - */
|
8 | | -if ( !defined( 'MEDIAWIKI' ) ) die;
|
9 | | -
|
10 | | -define('SMW_NM_VERSION', '0.5');
|
11 | | -
|
12 | | -$smwgNMIP = $IP . '/extensions/SemanticNotifyMe';
|
13 | | -$smwgNMScriptPath = $wgScriptPath . '/extensions/SemanticNotifyMe';
|
14 | | -
|
15 | | -global $wgExtensionFunctions;
|
16 | | -$wgExtensionFunctions[] = 'smwgNMSetupExtension';
|
17 | | -
|
18 | | -global $wgDefaultUserOptions;
|
19 | | -$wgDefaultUserOptions['enotifyme'] = 1;
|
20 | | -
|
21 | | -function smwfNMInitMessages() {
|
22 | | - global $smwgNMMessagesInitialized;
|
23 | | - if (isset($smwgNMMessagesInitialized)) return; // prevent double init
|
24 | | -
|
25 | | - smwfNMInitUserMessages(); // lazy init for ajax calls
|
26 | | -
|
27 | | - $smwgNMMessagesInitialized = true;
|
28 | | -}
|
29 | | -function smwfNMInitUserMessages() {
|
30 | | - global $wgMessageCache, $smwgNMContLang, $wgLanguageCode;
|
31 | | - smwfNMInitContentLanguage($wgLanguageCode);
|
32 | | -
|
33 | | - global $smwgNMIP, $smwgNMLang;
|
34 | | - if (!empty($smwgNMLang)) { return; }
|
35 | | - global $wgMessageCache, $wgLang;
|
36 | | - $smwLangClass = 'SMW_NMLanguage' . str_replace( '-', '_', ucfirst( $wgLang->getCode() ) );
|
37 | | -
|
38 | | - if (file_exists($smwgNMIP . '/languages/'. $smwLangClass . '.php')) {
|
39 | | - include_once( $smwgNMIP . '/languages/'. $smwLangClass . '.php' );
|
40 | | - }
|
41 | | - // fallback if language not supported
|
42 | | - if ( !class_exists($smwLangClass)) {
|
43 | | - global $smwgNMContLang;
|
44 | | - $smwgNMLang = $smwgNMContLang;
|
45 | | - } else {
|
46 | | - $smwgNMLang = new $smwLangClass();
|
47 | | - }
|
48 | | -
|
49 | | - $wgMessageCache->addMessages($smwgNMLang->getUserMsgArray(), $wgLang->getCode());
|
50 | | -}
|
51 | | -function smwfNMInitContentLanguage($langcode) {
|
52 | | - global $smwgNMIP, $smwgNMContLang;
|
53 | | - if (!empty($smwgNMContLang)) { return; }
|
54 | | -
|
55 | | - $smwContLangClass = 'SMW_NMLanguage' . str_replace( '-', '_', ucfirst( $langcode ) );
|
56 | | -
|
57 | | - if (file_exists($smwgNMIP . '/languages/'. $smwContLangClass . '.php')) {
|
58 | | - include_once( $smwgNMIP . '/languages/'. $smwContLangClass . '.php' );
|
59 | | - }
|
60 | | -
|
61 | | - // fallback if language not supported
|
62 | | - if ( !class_exists($smwContLangClass)) {
|
63 | | - include_once($smwgNMIP . '/languages/SMW_NMLanguageEn.php');
|
64 | | - $smwContLangClass = 'SMW_NMLanguageEn';
|
65 | | - }
|
66 | | - $smwgNMContLang = new $smwContLangClass();
|
67 | | -}
|
68 | | -
|
69 | | -function smwfNMInitializeTables() {
|
70 | | - global $smwgNMIP;
|
71 | | - require_once( $smwgNMIP . '/includes/SMW_NMStorage.php' );
|
72 | | - NMStorage::getDatabase()->setup(true);
|
73 | | -
|
74 | | - return true;
|
75 | | -}
|
76 | | -
|
77 | | -function smwfNMGetAjaxMethodPrefix() {
|
78 | | - $func_name = isset( $_POST["rs"] ) ? $_POST["rs"] : (isset( $_GET["rs"] ) ? $_GET["rs"] : NULL);
|
79 | | - if ($func_name == NULL) return NULL;
|
80 | | - return substr($func_name, 4, 4); // return _xx_ of smwf_xx_methodname, may return FALSE
|
81 | | -}
|
82 | | -
|
83 | | -/**
|
84 | | - * Intializes Semantic NotifyMe Extension.
|
85 | | - * Called from SNM during initialization.
|
86 | | - */
|
87 | | -function smwgNMSetupExtension() {
|
88 | | - global $smwgNMIP, $wgHooks, $wgJobClasses, $wgExtensionCredits;
|
89 | | - global $wgAutoloadClasses, $wgSpecialPages, $wgSpecialPageGroups;
|
90 | | -
|
91 | | - smwfNMInitMessages();
|
92 | | -
|
93 | | -
|
94 | | - // register SMW hooks
|
95 | | - $wgHooks['smwInitializeTables'][] = 'smwfNMInitializeTables';
|
96 | | -
|
97 | | - $wgHooks['ArticleSaveComplete'][] = 'smwfNMSaveHook';
|
98 | | - $wgHooks['ArticleUndelete'][] = 'smwfNMUndeleteHook';
|
99 | | - $wgHooks['ArticleSave'][] = 'smwfNMPreSaveHook';
|
100 | | - $wgHooks['ArticleDelete'][] = 'smwfNMPreDeleteHook';
|
101 | | -
|
102 | | - // queryinterface hook
|
103 | | - $wgHooks['QI_AddButtons'][] = 'smwfNMAddQIButton';
|
104 | | -
|
105 | | - global $wgRequest, $wgContLang;
|
106 | | -
|
107 | | - $spns_text = $wgContLang->getNsText(NS_SPECIAL);
|
108 | | -
|
109 | | - // register AddHTMLHeader functions for special pages
|
110 | | - // to include javascript and css files (only on special page requests).
|
111 | | - if (stripos($wgRequest->getRequestURL(), $spns_text.":") !== false
|
112 | | - || stripos($wgRequest->getRequestURL(), $spns_text."%3A") !== false) {
|
113 | | -
|
114 | | - if ( defined( 'SMW_HALO_VERSION' ) ){
|
115 | | - // insert NM header hook before add halo header
|
116 | | - foreach($wgHooks['BeforePageDisplay'] as $k=>$hookVal) {
|
117 | | - if($hookVal=='smwfHaloAddHTMLHeader') {
|
118 | | - $wgHooks['BeforePageDisplay'][$k] = 'smwNMAddHTMLHeader';
|
119 | | - break;
|
120 | | - }
|
121 | | - }
|
122 | | - $wgHooks['BeforePageDisplay'][]='smwfHaloAddHTMLHeader';
|
123 | | - } else {
|
124 | | - $wgHooks['BeforePageDisplay'][]='smwNMAddHTMLHeader';
|
125 | | - }
|
126 | | -
|
127 | | - }
|
128 | | -
|
129 | | - $wgJobClasses['SMW_NMSendMailJob'] = 'SMW_NMSendMailJob';
|
130 | | - require_once($smwgNMIP . '/includes/jobs/SMW_NMSendMailJob.php');
|
131 | | - $wgJobClasses['SMWNMRefreshJob'] = 'SMWNMRefreshJob';
|
132 | | - require_once($smwgNMIP . '/includes/jobs/SMW_NMRefreshJob.php');
|
133 | | -
|
134 | | - $wgAutoloadClasses['SMWNotifyProcessor'] = $smwgNMIP . '/includes/SMW_NotifyProcessor.php';
|
135 | | -
|
136 | | - $action = $wgRequest->getVal('action');
|
137 | | - // add some AJAX calls
|
138 | | - if ($action == 'ajax') {
|
139 | | - $method_prefix = smwfNMGetAjaxMethodPrefix();
|
140 | | -
|
141 | | - // decide according to ajax method prefix which script(s) to import
|
142 | | - switch($method_prefix) {
|
143 | | - case '_nm_' :
|
144 | | - require_once($smwgNMIP . '/specials/SMWNotifyMe/SMW_NotAjaxAccess.php');
|
145 | | - break;
|
146 | | - }
|
147 | | - } else { // otherwise register special pages
|
148 | | - $wgAutoloadClasses['SMWNotifyMe'] = $smwgNMIP . '/specials/SMWNotifyMe/SMWNotifyMe.php';
|
149 | | - $wgSpecialPages['NotifyMe'] = array('SMWNotifyMe');
|
150 | | - $wgSpecialPageGroups['NotifyMe'] = 'smwplus_group';
|
151 | | - }
|
152 | | -
|
153 | | - // Register Credits
|
154 | | - $wgExtensionCredits['parserhook'][]= array(
|
155 | | - 'name'=>'Semantic NotifyMe Extension', 'version'=>SMW_NM_VERSION,
|
156 | | - 'author'=>"Ning Hu, Justin Zhang, [http://smwforum.ontoprise.com/smwforum/index.php/Jesse_Wang Jesse Wang], sponsored by [http://projecthalo.com Project Halo], [http://www.vulcan.com Vulcan Inc.]",
|
157 | | - 'url'=>'http://wiking.vulcan.com/dev',
|
158 | | - 'description' => 'Notify wiki user with specified queries.');
|
159 | | -
|
160 | | - return true;
|
161 | | -}
|
162 | | -
|
163 | | -function smwfNMGetJSLanguageScripts(&$pathlng, &$userpathlng) {
|
164 | | - global $smwgNMIP, $wgLanguageCode, $smwgNMScriptPath, $wgUser;
|
165 | | -
|
166 | | - // content language file
|
167 | | - $lng = '/scripts/Language/SMW_NMLanguage';
|
168 | | - if (!empty($wgLanguageCode)) {
|
169 | | - $lng .= ucfirst($wgLanguageCode).'.js';
|
170 | | - if (file_exists($smwgNMIP . $lng)) {
|
171 | | - $pathlng = $smwgNMScriptPath . $lng;
|
172 | | - } else {
|
173 | | - $pathlng = $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguageEn.js';
|
174 | | - }
|
175 | | - } else {
|
176 | | - $pathlng = $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguageEn.js';
|
177 | | - }
|
178 | | -
|
179 | | - // user language file
|
180 | | - $lng = '/scripts/Language/SMW_NMLanguage';
|
181 | | - if (isset($wgUser)) {
|
182 | | - $lng .= "User".ucfirst($wgUser->getOption('language')).'.js';
|
183 | | - if (file_exists($smwgNMIP . $lng)) {
|
184 | | - $userpathlng = $smwgNMScriptPath . $lng;
|
185 | | - } else {
|
186 | | - $userpathlng = $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguageUserEn.js';
|
187 | | - }
|
188 | | - } else {
|
189 | | - $userpathlng = $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguageUserEn.js';
|
190 | | - }
|
191 | | -}
|
192 | | -
|
193 | | -// NotifyMe scripts callback
|
194 | | -// includes necessary script and css files.
|
195 | | -function smwNMAddHTMLHeader(&$out){
|
196 | | - global $wgTitle;
|
197 | | - if ($wgTitle->getNamespace() != NS_SPECIAL) return true;
|
198 | | -
|
199 | | - global $smwgNMScriptPath, $smwgScriptPath;
|
200 | | - smwfNMGetJSLanguageScripts($pathlng, $userpathlng);
|
201 | | -
|
202 | | - if ( defined( 'SMW_HALO_VERSION' ) ){
|
203 | | - global $smwgHaloScriptPath, $smwgDeployVersion;
|
204 | | -
|
205 | | - $jsm = SMWResourceManager::SINGLETON();
|
206 | | -
|
207 | | - $jsm->addScriptIf($smwgHaloScriptPath . '/scripts/prototype.js', "all", -1, NS_SPECIAL.":NotifyMe");
|
208 | | - $jsm->addScriptIf($smwgHaloScriptPath . '/scripts/Logger/smw_logger.js', "all", -1, NS_SPECIAL.":NotifyMe");
|
209 | | - $jsm->addScriptIf($smwgScriptPath . '/skins/SMW_tooltip.js', "all", -1, NS_SPECIAL.":NotifyMe");
|
210 | | -
|
211 | | - $jsm->addScriptIf($smwgNMScriptPath . '/scripts/Language/SMW_NMLanguage.js', "all", -1, NS_SPECIAL.":NotifyMe");
|
212 | | - $jsm->addScriptIf($pathlng, "all", -1, NS_SPECIAL.":NotifyMe");
|
213 | | - $jsm->addScriptIf($userpathlng, "all", -1, NS_SPECIAL.":NotifyMe");
|
214 | | - $jsm->addScriptIf($smwgNMScriptPath . '/scripts/NotifyMe/NotifyHelper.js', "all", -1, NS_SPECIAL.":NotifyMe");
|
215 | | -
|
216 | | - $jsm->addScriptIf($smwgNMScriptPath . '/scripts/Language/SMW_NMLanguage.js', "all", -1, NS_SPECIAL.":QueryInterface");
|
217 | | - $jsm->addScriptIf($pathlng, "all", -1, NS_SPECIAL.":QueryInterface");
|
218 | | - $jsm->addScriptIf($userpathlng, "all", -1, NS_SPECIAL.":QueryInterface");
|
219 | | - $jsm->addScriptIf($smwgNMScriptPath . '/scripts/NotifyMe/NotifyHelper.js', "all", -1, NS_SPECIAL.":QueryInterface");
|
220 | | -
|
221 | | - $jsm->addCSSIf($smwgScriptPath . '/skins/SMW_custom.css', "all", -1, NS_SPECIAL.":NotifyMe");
|
222 | | - $jsm->addCSSIf($smwgNMScriptPath . '/skins/nm.css', "all", -1, NS_SPECIAL.":NotifyMe");
|
223 | | - } else {
|
224 | | - global $wgRequest;
|
225 | | - $scripts = array();
|
226 | | - $$css = array();
|
227 | | -
|
228 | | - // read state
|
229 | | - if ($wgRequest != NULL && $wgTitle != NULL) {
|
230 | | - $action = $wgRequest->getVal("action");
|
231 | | - // $action of NULL or '' means view mode
|
232 | | - $action = $action == NULL || $action == '' ? "view" : $action;
|
233 | | - $namespace = $wgTitle->getNamespace();
|
234 | | - $page = $wgTitle->getNamespace().":".$wgTitle->getText();
|
235 | | -
|
236 | | - } else { // if no state could be read, set default -> load all!
|
237 | | - $action = "all";
|
238 | | - $namespace = -1;
|
239 | | - $page = array();
|
240 | | - }
|
241 | | - if(($namespace == NS_SPECIAL || $namespace == -1) && ($page == NS_SPECIAL.":NotifyMe")) {
|
242 | | - $out->addScript('<script type="text/javascript" src="'. $smwgNMScriptPath . '/scripts/prototype.js"></script>');
|
243 | | - $out->addScript('<script type="text/javascript" src="'. $smwgScriptPath . '/skins/SMW_tooltip.js"></script>');
|
244 | | - $out->addScript('<script type="text/javascript" src="'. $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguage.js"></script>');
|
245 | | - $out->addScript('<script type="text/javascript" src="'. $pathlng .'"></script>');
|
246 | | - $out->addScript('<script type="text/javascript" src="'. $userpathlng .'"></script>');
|
247 | | - $out->addScript('<script type="text/javascript" src="'. $smwgNMScriptPath . '/scripts/NotifyMe/NotifyHelper.js"></script>');
|
248 | | -
|
249 | | - $out->addLink(array(
|
250 | | - 'rel' => 'stylesheet',
|
251 | | - 'type' => 'text/css',
|
252 | | - 'media' => 'screen, projection',
|
253 | | - 'href' => $smwgScriptPath . '/skins/SMW_custom.css'
|
254 | | - ));
|
255 | | - $out->addLink(array(
|
256 | | - 'rel' => 'stylesheet',
|
257 | | - 'type' => 'text/css',
|
258 | | - 'media' => 'screen, projection',
|
259 | | - 'href' => $smwgNMScriptPath . '/skins/nm.css'
|
260 | | - ));
|
261 | | - }
|
262 | | - }
|
263 | | - return true; // do not load other scripts or CSS
|
264 | | -}
|
265 | | -
|
266 | | -
|
267 | | -function smwfNMPreSaveHook(&$article, &$user, &$text, &$summary, $minor, $watch, $sectionanchor, &$flags) {
|
268 | | - SMWNotifyProcessor::prepareArticleSave($article->getTitle());
|
269 | | -
|
270 | | - return true;
|
271 | | -}
|
272 | | -function smwfNMPreDeleteHook(&$article, &$user, &$reason) {
|
273 | | - SMWNotifyProcessor::articleDelete($article->getTitle(), $reason);
|
274 | | -
|
275 | | - return true;
|
276 | | -}
|
277 | | -function smwfNMSaveHook(&$article, &$user, &$text) {
|
278 | | - SMWNotifyProcessor::articleSavedComplete($article->getTitle());
|
279 | | -
|
280 | | - return true; // always return true, in order not to stop MW's hook processing!
|
281 | | -}
|
282 | | -function smwfNMUndeleteHook(&$title, $create) {
|
283 | | - SMWNotifyProcessor::articleSavedComplete($title);
|
284 | | - return true; // always return true, in order not to stop MW's hook processing!
|
285 | | -}
|
286 | | -function smwfNMAddQIButton(&$buttons) {
|
287 | | - global $wgUser;
|
288 | | - $user_id = $wgUser->getId();
|
289 | | - $buttons = '';
|
290 | | - if($user_id != 0) {
|
291 | | - $buttons = '<button class="btn" onclick="notifyhelper.saveQueryToNotify()" onmouseover="this.className=\'btn btnhov\'; Tip(\'' . wfMsg('smw_qi_tt_addNotify') . '\')" onmouseout="this.className=\'btn\'">' . wfMsg('smw_qi_addNotify') . '</button>';
|
292 | | - }
|
293 | | - return true;
|
294 | | -}
|
295 | | -?> |
\ No newline at end of file |
| 2 | +<?php |
| 3 | +/* |
| 4 | + * Created on 24.6.2009 |
| 5 | + * |
| 6 | + * Author: dch |
| 7 | + */ |
| 8 | +if ( !defined( 'MEDIAWIKI' ) ) die; |
| 9 | + |
| 10 | +define( 'SMW_NM_VERSION', '0.5' ); |
| 11 | + |
| 12 | +$smwgNMIP = $IP . '/extensions/SemanticNotifyMe'; |
| 13 | +$smwgNMScriptPath = $wgScriptPath . '/extensions/SemanticNotifyMe'; |
| 14 | + |
| 15 | +global $wgExtensionFunctions; |
| 16 | +$wgExtensionFunctions[] = 'smwgNMSetupExtension'; |
| 17 | + |
| 18 | +global $wgDefaultUserOptions; |
| 19 | +$wgDefaultUserOptions['enotifyme'] = 1; |
| 20 | + |
| 21 | +function smwfNMInitMessages() { |
| 22 | + global $smwgNMMessagesInitialized; |
| 23 | + if ( isset( $smwgNMMessagesInitialized ) ) return; // prevent double init |
| 24 | + |
| 25 | + smwfNMInitUserMessages(); // lazy init for ajax calls |
| 26 | + |
| 27 | + $smwgNMMessagesInitialized = true; |
| 28 | +} |
| 29 | +function smwfNMInitUserMessages() { |
| 30 | + global $wgMessageCache, $smwgNMContLang, $wgLanguageCode; |
| 31 | + smwfNMInitContentLanguage( $wgLanguageCode ); |
| 32 | + |
| 33 | + global $smwgNMIP, $smwgNMLang; |
| 34 | + if ( !empty( $smwgNMLang ) ) { return; } |
| 35 | + global $wgMessageCache, $wgLang; |
| 36 | + $smwLangClass = 'SMW_NMLanguage' . str_replace( '-', '_', ucfirst( $wgLang->getCode() ) ); |
| 37 | + |
| 38 | + if ( file_exists( $smwgNMIP . '/languages/' . $smwLangClass . '.php' ) ) { |
| 39 | + include_once( $smwgNMIP . '/languages/' . $smwLangClass . '.php' ); |
| 40 | + } |
| 41 | + // fallback if language not supported |
| 42 | + if ( !class_exists( $smwLangClass ) ) { |
| 43 | + global $smwgNMContLang; |
| 44 | + $smwgNMLang = $smwgNMContLang; |
| 45 | + } else { |
| 46 | + $smwgNMLang = new $smwLangClass(); |
| 47 | + } |
| 48 | + |
| 49 | + $wgMessageCache->addMessages( $smwgNMLang->getUserMsgArray(), $wgLang->getCode() ); |
| 50 | +} |
| 51 | +function smwfNMInitContentLanguage( $langcode ) { |
| 52 | + global $smwgNMIP, $smwgNMContLang; |
| 53 | + if ( !empty( $smwgNMContLang ) ) { return; } |
| 54 | + |
| 55 | + $smwContLangClass = 'SMW_NMLanguage' . str_replace( '-', '_', ucfirst( $langcode ) ); |
| 56 | + |
| 57 | + if ( file_exists( $smwgNMIP . '/languages/' . $smwContLangClass . '.php' ) ) { |
| 58 | + include_once( $smwgNMIP . '/languages/' . $smwContLangClass . '.php' ); |
| 59 | + } |
| 60 | + |
| 61 | + // fallback if language not supported |
| 62 | + if ( !class_exists( $smwContLangClass ) ) { |
| 63 | + include_once( $smwgNMIP . '/languages/SMW_NMLanguageEn.php' ); |
| 64 | + $smwContLangClass = 'SMW_NMLanguageEn'; |
| 65 | + } |
| 66 | + $smwgNMContLang = new $smwContLangClass(); |
| 67 | +} |
| 68 | + |
| 69 | +function smwfNMInitializeTables() { |
| 70 | + global $smwgNMIP; |
| 71 | + require_once( $smwgNMIP . '/includes/SMW_NMStorage.php' ); |
| 72 | + NMStorage::getDatabase()->setup( true ); |
| 73 | + |
| 74 | + return true; |
| 75 | +} |
| 76 | + |
| 77 | +function smwfNMGetAjaxMethodPrefix() { |
| 78 | + $func_name = isset( $_POST["rs"] ) ? $_POST["rs"] : ( isset( $_GET["rs"] ) ? $_GET["rs"] : NULL ); |
| 79 | + if ( $func_name == NULL ) return NULL; |
| 80 | + return substr( $func_name, 4, 4 ); // return _xx_ of smwf_xx_methodname, may return FALSE |
| 81 | +} |
| 82 | + |
| 83 | +/** |
| 84 | + * Intializes Semantic NotifyMe Extension. |
| 85 | + * Called from SNM during initialization. |
| 86 | + */ |
| 87 | +function smwgNMSetupExtension() { |
| 88 | + global $smwgNMIP, $wgHooks, $wgJobClasses, $wgExtensionCredits; |
| 89 | + global $wgAutoloadClasses, $wgSpecialPages, $wgSpecialPageGroups; |
| 90 | + |
| 91 | + smwfNMInitMessages(); |
| 92 | + |
| 93 | + |
| 94 | + // register SMW hooks |
| 95 | + $wgHooks['smwInitializeTables'][] = 'smwfNMInitializeTables'; |
| 96 | + |
| 97 | + $wgHooks['ArticleSaveComplete'][] = 'smwfNMSaveHook'; |
| 98 | + $wgHooks['ArticleUndelete'][] = 'smwfNMUndeleteHook'; |
| 99 | + $wgHooks['ArticleSave'][] = 'smwfNMPreSaveHook'; |
| 100 | + $wgHooks['ArticleDelete'][] = 'smwfNMPreDeleteHook'; |
| 101 | + |
| 102 | + // queryinterface hook |
| 103 | + $wgHooks['QI_AddButtons'][] = 'smwfNMAddQIButton'; |
| 104 | + |
| 105 | + global $wgRequest, $wgContLang; |
| 106 | + |
| 107 | + $spns_text = $wgContLang->getNsText( NS_SPECIAL ); |
| 108 | + |
| 109 | + // register AddHTMLHeader functions for special pages |
| 110 | + // to include javascript and css files (only on special page requests). |
| 111 | + if ( stripos( $wgRequest->getRequestURL(), $spns_text . ":" ) !== false |
| 112 | + || stripos( $wgRequest->getRequestURL(), $spns_text . "%3A" ) !== false ) { |
| 113 | + |
| 114 | + if ( defined( 'SMW_HALO_VERSION' ) ) { |
| 115 | + // insert NM header hook before add halo header |
| 116 | + foreach ( $wgHooks['BeforePageDisplay'] as $k => $hookVal ) { |
| 117 | + if ( $hookVal == 'smwfHaloAddHTMLHeader' ) { |
| 118 | + $wgHooks['BeforePageDisplay'][$k] = 'smwNMAddHTMLHeader'; |
| 119 | + break; |
| 120 | + } |
| 121 | + } |
| 122 | + $wgHooks['BeforePageDisplay'][] = 'smwfHaloAddHTMLHeader'; |
| 123 | + } else { |
| 124 | + $wgHooks['BeforePageDisplay'][] = 'smwNMAddHTMLHeader'; |
| 125 | + } |
| 126 | + |
| 127 | + } |
| 128 | + |
| 129 | + $wgJobClasses['SMW_NMSendMailJob'] = 'SMW_NMSendMailJob'; |
| 130 | + require_once( $smwgNMIP . '/includes/jobs/SMW_NMSendMailJob.php' ); |
| 131 | + $wgJobClasses['SMWNMRefreshJob'] = 'SMWNMRefreshJob'; |
| 132 | + require_once( $smwgNMIP . '/includes/jobs/SMW_NMRefreshJob.php' ); |
| 133 | + |
| 134 | + $wgAutoloadClasses['SMWNotifyProcessor'] = $smwgNMIP . '/includes/SMW_NotifyProcessor.php'; |
| 135 | + |
| 136 | + $action = $wgRequest->getVal( 'action' ); |
| 137 | + // add some AJAX calls |
| 138 | + if ( $action == 'ajax' ) { |
| 139 | + $method_prefix = smwfNMGetAjaxMethodPrefix(); |
| 140 | + |
| 141 | + // decide according to ajax method prefix which script(s) to import |
| 142 | + switch( $method_prefix ) { |
| 143 | + case '_nm_' : |
| 144 | + require_once( $smwgNMIP . '/specials/SMWNotifyMe/SMW_NotAjaxAccess.php' ); |
| 145 | + break; |
| 146 | + } |
| 147 | + } else { // otherwise register special pages |
| 148 | + $wgAutoloadClasses['SMWNotifyMe'] = $smwgNMIP . '/specials/SMWNotifyMe/SMWNotifyMe.php'; |
| 149 | + $wgSpecialPages['NotifyMe'] = array( 'SMWNotifyMe' ); |
| 150 | + $wgSpecialPageGroups['NotifyMe'] = 'smwplus_group'; |
| 151 | + } |
| 152 | + |
| 153 | + // Register Credits |
| 154 | + $wgExtensionCredits['parserhook'][] = array( |
| 155 | + 'name' => 'Semantic NotifyMe Extension', 'version' => SMW_NM_VERSION, |
| 156 | + 'author' => "Ning Hu, Justin Zhang, [http://smwforum.ontoprise.com/smwforum/index.php/Jesse_Wang Jesse Wang], sponsored by [http://projecthalo.com Project Halo], [http://www.vulcan.com Vulcan Inc.]", |
| 157 | + 'url' => 'http://wiking.vulcan.com/dev', |
| 158 | + 'description' => 'Notify wiki user with specified queries.' ); |
| 159 | + |
| 160 | + return true; |
| 161 | +} |
| 162 | + |
| 163 | +function smwfNMGetJSLanguageScripts( &$pathlng, &$userpathlng ) { |
| 164 | + global $smwgNMIP, $wgLanguageCode, $smwgNMScriptPath, $wgUser; |
| 165 | + |
| 166 | + // content language file |
| 167 | + $lng = '/scripts/Language/SMW_NMLanguage'; |
| 168 | + if ( !empty( $wgLanguageCode ) ) { |
| 169 | + $lng .= ucfirst( $wgLanguageCode ) . '.js'; |
| 170 | + if ( file_exists( $smwgNMIP . $lng ) ) { |
| 171 | + $pathlng = $smwgNMScriptPath . $lng; |
| 172 | + } else { |
| 173 | + $pathlng = $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguageEn.js'; |
| 174 | + } |
| 175 | + } else { |
| 176 | + $pathlng = $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguageEn.js'; |
| 177 | + } |
| 178 | + |
| 179 | + // user language file |
| 180 | + $lng = '/scripts/Language/SMW_NMLanguage'; |
| 181 | + if ( isset( $wgUser ) ) { |
| 182 | + $lng .= "User" . ucfirst( $wgUser->getOption( 'language' ) ) . '.js'; |
| 183 | + if ( file_exists( $smwgNMIP . $lng ) ) { |
| 184 | + $userpathlng = $smwgNMScriptPath . $lng; |
| 185 | + } else { |
| 186 | + $userpathlng = $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguageUserEn.js'; |
| 187 | + } |
| 188 | + } else { |
| 189 | + $userpathlng = $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguageUserEn.js'; |
| 190 | + } |
| 191 | +} |
| 192 | + |
| 193 | +// NotifyMe scripts callback |
| 194 | +// includes necessary script and css files. |
| 195 | +function smwNMAddHTMLHeader( &$out ) { |
| 196 | + global $wgTitle; |
| 197 | + if ( $wgTitle->getNamespace() != NS_SPECIAL ) return true; |
| 198 | + |
| 199 | + global $smwgNMScriptPath, $smwgScriptPath; |
| 200 | + smwfNMGetJSLanguageScripts( $pathlng, $userpathlng ); |
| 201 | + |
| 202 | + if ( defined( 'SMW_HALO_VERSION' ) ) { |
| 203 | + global $smwgHaloScriptPath, $smwgDeployVersion; |
| 204 | + |
| 205 | + $jsm = SMWResourceManager::SINGLETON(); |
| 206 | + |
| 207 | + $jsm->addScriptIf( $smwgHaloScriptPath . '/scripts/prototype.js', "all", - 1, NS_SPECIAL . ":NotifyMe" ); |
| 208 | + $jsm->addScriptIf( $smwgHaloScriptPath . '/scripts/Logger/smw_logger.js', "all", - 1, NS_SPECIAL . ":NotifyMe" ); |
| 209 | + $jsm->addScriptIf( $smwgScriptPath . '/skins/SMW_tooltip.js', "all", - 1, NS_SPECIAL . ":NotifyMe" ); |
| 210 | + |
| 211 | + $jsm->addScriptIf( $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguage.js', "all", - 1, NS_SPECIAL . ":NotifyMe" ); |
| 212 | + $jsm->addScriptIf( $pathlng, "all", - 1, NS_SPECIAL . ":NotifyMe" ); |
| 213 | + $jsm->addScriptIf( $userpathlng, "all", - 1, NS_SPECIAL . ":NotifyMe" ); |
| 214 | + $jsm->addScriptIf( $smwgNMScriptPath . '/scripts/NotifyMe/NotifyHelper.js', "all", - 1, NS_SPECIAL . ":NotifyMe" ); |
| 215 | + |
| 216 | + $jsm->addScriptIf( $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguage.js', "all", - 1, NS_SPECIAL . ":QueryInterface" ); |
| 217 | + $jsm->addScriptIf( $pathlng, "all", - 1, NS_SPECIAL . ":QueryInterface" ); |
| 218 | + $jsm->addScriptIf( $userpathlng, "all", - 1, NS_SPECIAL . ":QueryInterface" ); |
| 219 | + $jsm->addScriptIf( $smwgNMScriptPath . '/scripts/NotifyMe/NotifyHelper.js', "all", - 1, NS_SPECIAL . ":QueryInterface" ); |
| 220 | + |
| 221 | + $jsm->addCSSIf( $smwgScriptPath . '/skins/SMW_custom.css', "all", - 1, NS_SPECIAL . ":NotifyMe" ); |
| 222 | + $jsm->addCSSIf( $smwgNMScriptPath . '/skins/nm.css', "all", - 1, NS_SPECIAL . ":NotifyMe" ); |
| 223 | + } else { |
| 224 | + global $wgRequest; |
| 225 | + $scripts = array(); |
| 226 | + $$css = array(); |
| 227 | + |
| 228 | + // read state |
| 229 | + if ( $wgRequest != NULL && $wgTitle != NULL ) { |
| 230 | + $action = $wgRequest->getVal( "action" ); |
| 231 | + // $action of NULL or '' means view mode |
| 232 | + $action = $action == NULL || $action == '' ? "view" : $action; |
| 233 | + $namespace = $wgTitle->getNamespace(); |
| 234 | + $page = $wgTitle->getNamespace() . ":" . $wgTitle->getText(); |
| 235 | + |
| 236 | + } else { // if no state could be read, set default -> load all! |
| 237 | + $action = "all"; |
| 238 | + $namespace = - 1; |
| 239 | + $page = array(); |
| 240 | + } |
| 241 | + if ( ( $namespace == NS_SPECIAL || $namespace == - 1 ) && ( $page == NS_SPECIAL . ":NotifyMe" ) ) { |
| 242 | + $out->addScript( '<script type="text/javascript" src="' . $smwgNMScriptPath . '/scripts/prototype.js"></script>' ); |
| 243 | + $out->addScript( '<script type="text/javascript" src="' . $smwgScriptPath . '/skins/SMW_tooltip.js"></script>' ); |
| 244 | + $out->addScript( '<script type="text/javascript" src="' . $smwgNMScriptPath . '/scripts/Language/SMW_NMLanguage.js"></script>' ); |
| 245 | + $out->addScript( '<script type="text/javascript" src="' . $pathlng . '"></script>' ); |
| 246 | + $out->addScript( '<script type="text/javascript" src="' . $userpathlng . '"></script>' ); |
| 247 | + $out->addScript( '<script type="text/javascript" src="' . $smwgNMScriptPath . '/scripts/NotifyMe/NotifyHelper.js"></script>' ); |
| 248 | + |
| 249 | + $out->addLink( array( |
| 250 | + 'rel' => 'stylesheet', |
| 251 | + 'type' => 'text/css', |
| 252 | + 'media' => 'screen, projection', |
| 253 | + 'href' => $smwgScriptPath . '/skins/SMW_custom.css' |
| 254 | + ) ); |
| 255 | + $out->addLink( array( |
| 256 | + 'rel' => 'stylesheet', |
| 257 | + 'type' => 'text/css', |
| 258 | + 'media' => 'screen, projection', |
| 259 | + 'href' => $smwgNMScriptPath . '/skins/nm.css' |
| 260 | + ) ); |
| 261 | + } |
| 262 | + } |
| 263 | + return true; // do not load other scripts or CSS |
| 264 | +} |
| 265 | + |
| 266 | + |
| 267 | +function smwfNMPreSaveHook( &$article, &$user, &$text, &$summary, $minor, $watch, $sectionanchor, &$flags ) { |
| 268 | + SMWNotifyProcessor::prepareArticleSave( $article->getTitle() ); |
| 269 | + |
| 270 | + return true; |
| 271 | +} |
| 272 | +function smwfNMPreDeleteHook( &$article, &$user, &$reason ) { |
| 273 | + SMWNotifyProcessor::articleDelete( $article->getTitle(), $reason ); |
| 274 | + |
| 275 | + return true; |
| 276 | +} |
| 277 | +function smwfNMSaveHook( &$article, &$user, &$text ) { |
| 278 | + SMWNotifyProcessor::articleSavedComplete( $article->getTitle() ); |
| 279 | + |
| 280 | + return true; // always return true, in order not to stop MW's hook processing! |
| 281 | +} |
| 282 | +function smwfNMUndeleteHook( &$title, $create ) { |
| 283 | + SMWNotifyProcessor::articleSavedComplete( $title ); |
| 284 | + return true; // always return true, in order not to stop MW's hook processing! |
| 285 | +} |
| 286 | +function smwfNMAddQIButton( &$buttons ) { |
| 287 | + global $wgUser; |
| 288 | + $user_id = $wgUser->getId(); |
| 289 | + $buttons = ''; |
| 290 | + if ( $user_id != 0 ) { |
| 291 | + $buttons = '<button class="btn" onclick="notifyhelper.saveQueryToNotify()" onmouseover="this.className=\'btn btnhov\'; Tip(\'' . wfMsg( 'smw_qi_tt_addNotify' ) . '\')" onmouseout="this.className=\'btn\'">' . wfMsg( 'smw_qi_addNotify' ) . '</button>'; |
| 292 | + } |
| 293 | + return true; |
| 294 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/includes/SNM_Initialize.php |
___________________________________________________________________ |
Name: svn:eol-style |
296 | 295 | + native |
Index: trunk/extensions/SemanticNotifyMe/includes/storage/SMW_SQLStore2_QueriesNM.php |
— | — | @@ -1,30 +1,30 @@ |
2 | 2 | <?php |
3 | 3 | /** |
4 | 4 | * Query answering functions for SMWSQLStore2. Separated frmo main code for readability and |
5 | | - * for avoiding twice the amount of code being required on every use of a simple storage function.
|
6 | | - *
|
| 5 | + * for avoiding twice the amount of code being required on every use of a simple storage function. |
| 6 | + * |
7 | 7 | * based on SMW, SMW_SQLStore2_Queries.php, apply query parser to NotifyMe |
8 | 8 | * |
9 | 9 | * @author dch |
10 | 10 | */ |
11 | | -
|
12 | | -global $smwgIP;
|
13 | | -include_once("$smwgIP/includes/storage/SMW_SQLStore2_Queries.php");
|
14 | 11 | |
| 12 | +global $smwgIP; |
| 13 | +include_once( "$smwgIP/includes/storage/SMW_SQLStore2_Queries.php" ); |
| 14 | + |
15 | 15 | /** |
16 | 16 | * Class that implements query answering for SMWSQLStore2. |
17 | 17 | */ |
18 | 18 | class SMWSQLStore2QueryEngineNM { |
19 | 19 | |
20 | | - /// Database slave to be used |
21 | | - protected $m_dbs; /// TODO: should temporary tables be created on the master DB? |
22 | | - /// Parent SMWSQLStore2 |
| 20 | + // / Database slave to be used |
| 21 | + protected $m_dbs; // / TODO: should temporary tables be created on the master DB? |
| 22 | + // / Parent SMWSQLStore2 |
23 | 23 | protected $m_store; |
24 | | - /// Query mode copied from given query, some submethods act differently when in SMWQuery::MODE_DEBUG |
| 24 | + // / Query mode copied from given query, some submethods act differently when in SMWQuery::MODE_DEBUG |
25 | 25 | protected $m_qmode; |
26 | | - /// Array of generated query descriptions |
| 26 | + // / Array of generated query descriptions |
27 | 27 | protected $m_queries = array(); |
28 | | - /// Array of arrays of executed queries, indexed by the temporary table names results were fed into |
| 28 | + // / Array of arrays of executed queries, indexed by the temporary table names results were fed into |
29 | 29 | protected $m_querylog = array(); |
30 | 30 | /** |
31 | 31 | * Array of sorting requests ("Property_name" => "ASC"/"DESC". Used during query |
— | — | @@ -32,12 +32,12 @@ |
33 | 33 | * conditions). |
34 | 34 | */ |
35 | 35 | protected $m_sortkeys; |
36 | | - /// Cache of computed hierarchy queries for reuse, cat/prop-value string => tablename |
| 36 | + // / Cache of computed hierarchy queries for reuse, cat/prop-value string => tablename |
37 | 37 | protected $m_hierarchies = array(); |
38 | | - /// Local collection of error strings, passed on to callers if possible. |
| 38 | + // / Local collection of error strings, passed on to callers if possible. |
39 | 39 | protected $m_errors = array(); |
40 | 40 | |
41 | | - public function __construct(&$parentstore, &$dbslave) { |
| 41 | + public function __construct( &$parentstore, &$dbslave ) { |
42 | 42 | $this->m_store = $parentstore; |
43 | 43 | $this->m_dbs = $dbslave; |
44 | 44 | } |
— | — | @@ -47,18 +47,18 @@ |
48 | 48 | * |
49 | 49 | * @param $concept Title |
50 | 50 | */ |
51 | | - public function refreshConceptCache($concept) { |
| 51 | + public function refreshConceptCache( $concept ) { |
52 | 52 | global $smwgQMaxLimit, $smwgQConceptFeatures; |
53 | | - $cid = $this->m_store->getSMWPageID($concept->getDBKey(), SMW_NS_CONCEPT, ''); |
54 | | - $cid_c = $this->m_store->getSMWPageID($concept->getDBKey(), SMW_NS_CONCEPT, '', false); |
55 | | - if ($cid != $cid_c) { |
| 53 | + $cid = $this->m_store->getSMWPageID( $concept->getDBKey(), SMW_NS_CONCEPT, '' ); |
| 54 | + $cid_c = $this->m_store->getSMWPageID( $concept->getDBKey(), SMW_NS_CONCEPT, '', false ); |
| 55 | + if ( $cid != $cid_c ) { |
56 | 56 | $this->m_errors[] = "Skipping redirect concept."; |
57 | 57 | return $this->m_errors; |
58 | 58 | } |
59 | | - $dv = end($this->m_store->getPropertyValues($concept, SMWPropertyValue::makeProperty('_CONC'))); |
60 | | - $desctxt = ($dv!==false)?$dv->getWikiValue():false; |
| 59 | + $dv = end( $this->m_store->getPropertyValues( $concept, SMWPropertyValue::makeProperty( '_CONC' ) ) ); |
| 60 | + $desctxt = ( $dv !== false ) ? $dv->getWikiValue():false; |
61 | 61 | $this->m_errors = array(); |
62 | | - if ($desctxt) { // concept found |
| 62 | + if ( $desctxt ) { // concept found |
63 | 63 | $this->m_qmode = SMWQuery::MODE_INSTANCES; |
64 | 64 | $this->m_queries = array(); |
65 | 65 | $this->m_hierarchies = array(); |
— | — | @@ -67,25 +67,25 @@ |
68 | 68 | SMWSQLStore2Query::$qnum = 0; |
69 | 69 | |
70 | 70 | // Pre-process query: |
71 | | - $qp = new SMWQueryParser($smwgQConceptFeatures); |
72 | | - $desc = $qp->getQueryDescription($desctxt); |
73 | | - $qid = $this->compileQueries($desc); |
74 | | - $this->executeQueries($this->m_queries[$qid]); // execute query tree, resolve all dependencies |
| 71 | + $qp = new SMWQueryParser( $smwgQConceptFeatures ); |
| 72 | + $desc = $qp->getQueryDescription( $desctxt ); |
| 73 | + $qid = $this->compileQueries( $desc ); |
| 74 | + $this->executeQueries( $this->m_queries[$qid] ); // execute query tree, resolve all dependencies |
75 | 75 | $qobj = $this->m_queries[$qid]; |
76 | | - if ($qobj->joinfield === '') { |
| 76 | + if ( $qobj->joinfield === '' ) { |
77 | 77 | return; |
78 | 78 | } |
79 | 79 | // Update database: |
80 | | - $this->m_dbs->delete('smw_conccache', array('o_id' => $cid), 'SMW::refreshConceptCache'); |
81 | | - $this->m_dbs->query("INSERT IGNORE INTO " . $this->m_dbs->tableName('smw_conccache') . |
| 80 | + $this->m_dbs->delete( 'smw_conccache', array( 'o_id' => $cid ), 'SMW::refreshConceptCache' ); |
| 81 | + $this->m_dbs->query( "INSERT IGNORE INTO " . $this->m_dbs->tableName( 'smw_conccache' ) . |
82 | 82 | " SELECT DISTINCT $qobj->joinfield AS s_id, $cid AS o_id FROM " . |
83 | | - $this->m_dbs->tableName($qobj->jointable) . " AS $qobj->alias" . $qobj->from . |
84 | | - ($qobj->where?" WHERE ":'') . $qobj->where . " LIMIT $smwgQMaxLimit", |
85 | | - 'SMW::refreshConceptCache'); |
86 | | - $this->m_dbs->update('smw_conc2', array('cache_date' => strtotime("now"), 'cache_count' => $this->m_dbs->affectedRows()), array('s_id' => $cid), 'SMW::refreshConceptCache'); |
| 83 | + $this->m_dbs->tableName( $qobj->jointable ) . " AS $qobj->alias" . $qobj->from . |
| 84 | + ( $qobj->where ? " WHERE ":'' ) . $qobj->where . " LIMIT $smwgQMaxLimit", |
| 85 | + 'SMW::refreshConceptCache' ); |
| 86 | + $this->m_dbs->update( 'smw_conc2', array( 'cache_date' => strtotime( "now" ), 'cache_count' => $this->m_dbs->affectedRows() ), array( 's_id' => $cid ), 'SMW::refreshConceptCache' ); |
87 | 87 | } else { // just delete old data if there is any |
88 | | - $this->m_dbs->delete('smw_conccache', array('o_id' => $cid), 'SMW::refreshConceptCache'); |
89 | | - $this->m_dbs->update('smw_conc2', array('cache_date' => NULL, 'cache_count' => NULL), array('s_id' => $cid), 'SMW::refreshConceptCache'); |
| 88 | + $this->m_dbs->delete( 'smw_conccache', array( 'o_id' => $cid ), 'SMW::refreshConceptCache' ); |
| 89 | + $this->m_dbs->update( 'smw_conc2', array( 'cache_date' => NULL, 'cache_count' => NULL ), array( 's_id' => $cid ), 'SMW::refreshConceptCache' ); |
90 | 90 | $this->m_errors[] = "No concept description found."; |
91 | 91 | } |
92 | 92 | $this->cleanUp(); |
— | — | @@ -97,18 +97,18 @@ |
98 | 98 | * |
99 | 99 | * @param $concept Title |
100 | 100 | */ |
101 | | - public function deleteConceptCache($concept) { |
102 | | - $cid = $this->m_store->getSMWPageID($concept->getDBKey(), SMW_NS_CONCEPT, '', false); |
103 | | - $this->m_dbs->delete('smw_conccache', array('o_id' => $cid), 'SMW::refreshConceptCache'); |
104 | | - $this->m_dbs->update('smw_conc2', array('cache_date' => NULL, 'cache_count' => NULL), array('s_id' => $cid), 'SMW::refreshConceptCache'); |
| 101 | + public function deleteConceptCache( $concept ) { |
| 102 | + $cid = $this->m_store->getSMWPageID( $concept->getDBKey(), SMW_NS_CONCEPT, '', false ); |
| 103 | + $this->m_dbs->delete( 'smw_conccache', array( 'o_id' => $cid ), 'SMW::refreshConceptCache' ); |
| 104 | + $this->m_dbs->update( 'smw_conc2', array( 'cache_date' => NULL, 'cache_count' => NULL ), array( 's_id' => $cid ), 'SMW::refreshConceptCache' ); |
105 | 105 | } |
106 | 106 | |
107 | 107 | /** |
108 | 108 | * The new SQL store's implementation of query answering. |
109 | 109 | */ |
110 | | - public function getQueryResult(SMWQuery $query) { |
111 | | - if ($query->querymode == SMWQuery::MODE_NONE) { // don't query, but return something to printer |
112 | | - $result = new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, true); |
| 110 | + public function getQueryResult( SMWQuery $query ) { |
| 111 | + if ( $query->querymode == SMWQuery::MODE_NONE ) { // don't query, but return something to printer |
| 112 | + $result = new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, true ); |
113 | 113 | return $result; |
114 | 114 | } |
115 | 115 | $this->m_qmode = $query->querymode; |
— | — | @@ -124,102 +124,102 @@ |
125 | 125 | $qobj->jointable = 'smw_ids'; |
126 | 126 | $qobj->joinfield = "$qobj->alias.smw_id"; |
127 | 127 | // build query dependency tree: |
128 | | - wfProfileIn('SMWSQLStore2Queries::compileMainQuery (SMW)'); |
129 | | - $qid = $this->compileQueries($query->getDescription()); // compile query, build query "plan" |
130 | | - wfProfileOut('SMWSQLStore2Queries::compileMainQuery (SMW)'); |
131 | | - if ($qid < 0) { // no valid/supported condition; ensure that at least only proper pages are delivered |
| 128 | + wfProfileIn( 'SMWSQLStore2Queries::compileMainQuery (SMW)' ); |
| 129 | + $qid = $this->compileQueries( $query->getDescription() ); // compile query, build query "plan" |
| 130 | + wfProfileOut( 'SMWSQLStore2Queries::compileMainQuery (SMW)' ); |
| 131 | + if ( $qid < 0 ) { // no valid/supported condition; ensure that at least only proper pages are delivered |
132 | 132 | $qid = SMWSQLStore2Query::$qnum; |
133 | 133 | $q = new SMWSQLStore2Query(); |
134 | 134 | $q->jointable = 'smw_ids'; |
135 | 135 | $q->joinfield = "$q->alias.smw_id"; |
136 | | - $q->where = "$q->alias.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWIW) . " AND $q->alias.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWREDIIW) . " AND $q->alias.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWBORDERIW) . " AND $q->alias.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWINTDEFIW); |
| 136 | + $q->where = "$q->alias.smw_iw!=" . $this->m_dbs->addQuotes( SMW_SQL2_SMWIW ) . " AND $q->alias.smw_iw!=" . $this->m_dbs->addQuotes( SMW_SQL2_SMWREDIIW ) . " AND $q->alias.smw_iw!=" . $this->m_dbs->addQuotes( SMW_SQL2_SMWBORDERIW ) . " AND $q->alias.smw_iw!=" . $this->m_dbs->addQuotes( SMW_SQL2_SMWINTDEFIW ); |
137 | 137 | $this->m_queries[$qid] = $q; |
138 | 138 | } |
139 | 139 | // append query to root: |
140 | | - $qobj->components = array($qid => "$qobj->alias.smw_id"); |
| 140 | + $qobj->components = array( $qid => "$qobj->alias.smw_id" ); |
141 | 141 | $qobj->sortfields = $this->m_queries[$qid]->sortfields; |
142 | 142 | $this->m_queries[$rootid] = $qobj; |
143 | 143 | |
144 | | - $this->applyOrderConditions($query,$rootid); // may extend query if needed for sorting |
145 | | - wfProfileIn('SMWSQLStore2Queries::executeMainQuery (SMW)'); |
146 | | - $this->executeQueries($this->m_queries[$rootid]); // execute query tree, resolve all dependencies |
147 | | - wfProfileOut('SMWSQLStore2Queries::executeMainQuery (SMW)'); |
148 | | - $result = $this->getNMQueryResult($query,$rootid);
|
149 | | -
|
| 144 | + $this->applyOrderConditions( $query, $rootid ); // may extend query if needed for sorting |
| 145 | + wfProfileIn( 'SMWSQLStore2Queries::executeMainQuery (SMW)' ); |
| 146 | + $this->executeQueries( $this->m_queries[$rootid] ); // execute query tree, resolve all dependencies |
| 147 | + wfProfileOut( 'SMWSQLStore2Queries::executeMainQuery (SMW)' ); |
| 148 | + $result = $this->getNMQueryResult( $query, $rootid ); |
| 149 | + |
150 | 150 | $this->cleanUp(); |
151 | | - $query->addErrors($this->m_errors); |
| 151 | + $query->addErrors( $this->m_errors ); |
152 | 152 | return $result; |
153 | 153 | } |
154 | | -
|
155 | | - // added by dch
|
156 | | - protected function getNMQueryResult($query,$rootid) {
|
157 | | - wfProfileIn('SMWSQLStore2Queries::getNMQueryResult (SMW)');
|
158 | | - $qobj = $this->m_queries[$rootid];
|
159 | | - if ($qobj->joinfield !== '') {
|
160 | | - $sql = "SELECT DISTINCT $qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns FROM " .
|
161 | | - $this->m_dbs->tableName($qobj->jointable) . " AS $qobj->alias" . $qobj->from .
|
162 | | - (($qobj->where=='')?'':' WHERE ') . $qobj->where;
|
163 | | - } else { // empty result, no query needed
|
164 | | - wfProfileOut('SMWSQLStore2Queries::getNMQueryResult (SMW)');
|
165 | | - return false;
|
166 | | - }
|
167 | | - $tmp = '';
|
168 | | - foreach ($this->m_querylog as $table => $log) {
|
169 | | - foreach ($log as $l => $v) {
|
170 | | - $tmp .= ($tmp!=''?';':'')."$table:$l";
|
171 | | - }
|
172 | | - }
|
173 | | - $result = array('sql'=>$sql, 'tmp_hierarchy'=>$tmp, 'page_ids'=>array());
|
174 | | -
|
175 | | - $res = $this->m_dbs->select($this->m_dbs->tableName($qobj->jointable) . " AS $qobj->alias" . $qobj->from, "DISTINCT $qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns", $qobj->where, 'SMW::getQueryResult');
|
176 | | - while ( $row = $this->m_dbs->fetchObject($res) ) {
|
177 | | - if($row->ns != NS_MAIN) continue;
|
178 | | -
|
179 | | - $title = Title::makeTitle($row->ns, $row->t);
|
180 | | - $result['page_ids'][] = $title->getArticleID();
|
181 | | - }
|
182 | | - $this->m_dbs->freeResult($res);
|
183 | | -
|
184 | | - wfProfileOut('SMWSQLStore2Queries::getNMQueryResult (SMW)');
|
185 | | - return $result;
|
186 | | - }
|
187 | 154 | |
| 155 | + // added by dch |
| 156 | + protected function getNMQueryResult( $query, $rootid ) { |
| 157 | + wfProfileIn( 'SMWSQLStore2Queries::getNMQueryResult (SMW)' ); |
| 158 | + $qobj = $this->m_queries[$rootid]; |
| 159 | + if ( $qobj->joinfield !== '' ) { |
| 160 | + $sql = "SELECT DISTINCT $qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns FROM " . |
| 161 | + $this->m_dbs->tableName( $qobj->jointable ) . " AS $qobj->alias" . $qobj->from . |
| 162 | + ( ( $qobj->where == '' ) ? '':' WHERE ' ) . $qobj->where; |
| 163 | + } else { // empty result, no query needed |
| 164 | + wfProfileOut( 'SMWSQLStore2Queries::getNMQueryResult (SMW)' ); |
| 165 | + return false; |
| 166 | + } |
| 167 | + $tmp = ''; |
| 168 | + foreach ( $this->m_querylog as $table => $log ) { |
| 169 | + foreach ( $log as $l => $v ) { |
| 170 | + $tmp .= ( $tmp != '' ? ';':'' ) . "$table:$l"; |
| 171 | + } |
| 172 | + } |
| 173 | + $result = array( 'sql' => $sql, 'tmp_hierarchy' => $tmp, 'page_ids' => array() ); |
| 174 | + |
| 175 | + $res = $this->m_dbs->select( $this->m_dbs->tableName( $qobj->jointable ) . " AS $qobj->alias" . $qobj->from, "DISTINCT $qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns", $qobj->where, 'SMW::getQueryResult' ); |
| 176 | + while ( $row = $this->m_dbs->fetchObject( $res ) ) { |
| 177 | + if ( $row->ns != NS_MAIN ) continue; |
| 178 | + |
| 179 | + $title = Title::makeTitle( $row->ns, $row->t ); |
| 180 | + $result['page_ids'][] = $title->getArticleID(); |
| 181 | + } |
| 182 | + $this->m_dbs->freeResult( $res ); |
| 183 | + |
| 184 | + wfProfileOut( 'SMWSQLStore2Queries::getNMQueryResult (SMW)' ); |
| 185 | + return $result; |
| 186 | + } |
| 187 | + |
188 | 188 | /** |
189 | 189 | * Create a new SMWSQLStore2Query object that can be used to obtain results for |
190 | 190 | * the given description. The result is stored in $this->m_queries using a numeric |
191 | 191 | * key that is returned as a result of the function. Returns -1 if no query was |
192 | 192 | * created. |
193 | 193 | */ |
194 | | - protected function compileQueries(SMWDescription $description) { |
| 194 | + protected function compileQueries( SMWDescription $description ) { |
195 | 195 | $qid = SMWSQLStore2Query::$qnum; |
196 | 196 | $query = new SMWSQLStore2Query(); |
197 | | - if ($description instanceof SMWSomeProperty) { |
198 | | - $this->compilePropertyCondition($query, $description->getProperty(), $description->getDescription()); |
199 | | - if ($query->type == SMW_SQL2_NOQUERY) $qid = -1; // drop that right away |
200 | | - } elseif ($description instanceof SMWNamespaceDescription) { /// TODO: One instance of smw_ids on s_id always suffices (swm_id is KEY)! Doable in execution ... (PERFORMANCE) |
| 197 | + if ( $description instanceof SMWSomeProperty ) { |
| 198 | + $this->compilePropertyCondition( $query, $description->getProperty(), $description->getDescription() ); |
| 199 | + if ( $query->type == SMW_SQL2_NOQUERY ) $qid = - 1; // drop that right away |
| 200 | + } elseif ( $description instanceof SMWNamespaceDescription ) { // / TODO: One instance of smw_ids on s_id always suffices (swm_id is KEY)! Doable in execution ... (PERFORMANCE) |
201 | 201 | $query->jointable = 'smw_ids'; |
202 | 202 | $query->joinfield = "$query->alias.smw_id"; |
203 | | - $query->where = "$query->alias.smw_namespace=" . $this->m_dbs->addQuotes($description->getNamespace()); |
204 | | - } elseif ( ($description instanceof SMWConjunction) || ($description instanceof SMWDisjunction) ) { |
205 | | - $query->type = ($description instanceof SMWConjunction)?SMW_SQL2_CONJUNCTION:SMW_SQL2_DISJUNCTION; |
206 | | - foreach ($description->getDescriptions() as $subdesc) { |
207 | | - $sub = $this->compileQueries($subdesc); |
208 | | - if ($sub >= 0) { |
| 203 | + $query->where = "$query->alias.smw_namespace=" . $this->m_dbs->addQuotes( $description->getNamespace() ); |
| 204 | + } elseif ( ( $description instanceof SMWConjunction ) || ( $description instanceof SMWDisjunction ) ) { |
| 205 | + $query->type = ( $description instanceof SMWConjunction ) ? SMW_SQL2_CONJUNCTION:SMW_SQL2_DISJUNCTION; |
| 206 | + foreach ( $description->getDescriptions() as $subdesc ) { |
| 207 | + $sub = $this->compileQueries( $subdesc ); |
| 208 | + if ( $sub >= 0 ) { |
209 | 209 | $query->components[$sub] = true; |
210 | 210 | } |
211 | 211 | } |
212 | | - } elseif ($description instanceof SMWClassDescription) { |
| 212 | + } elseif ( $description instanceof SMWClassDescription ) { |
213 | 213 | $cqid = SMWSQLStore2Query::$qnum; |
214 | 214 | $cquery = new SMWSQLStore2Query(); |
215 | 215 | $cquery->type = SMW_SQL2_CLASS_HIERARCHY; |
216 | 216 | $cquery->joinfield = array(); |
217 | | - foreach ($description->getCategories() as $cat) { |
218 | | - $cid = $this->m_store->getSMWPageID($cat->getDBkey(), NS_CATEGORY, $cat->getInterwiki()); |
219 | | - if ($cid != 0) { |
| 217 | + foreach ( $description->getCategories() as $cat ) { |
| 218 | + $cid = $this->m_store->getSMWPageID( $cat->getDBkey(), NS_CATEGORY, $cat->getInterwiki() ); |
| 219 | + if ( $cid != 0 ) { |
220 | 220 | $cquery->joinfield[] = $cid; |
221 | 221 | } |
222 | 222 | } |
223 | | - if (count($cquery->joinfield) == 0) { // empty result |
| 223 | + if ( count( $cquery->joinfield ) == 0 ) { // empty result |
224 | 224 | $query->type = SMW_SQL2_VALUE; |
225 | 225 | $query->jointable = ''; |
226 | 226 | $query->joinfield = ''; |
— | — | @@ -229,70 +229,70 @@ |
230 | 230 | $query->components[$cqid] = "$query->alias.o_id"; |
231 | 231 | $this->m_queries[$cqid] = $cquery; |
232 | 232 | } |
233 | | - } elseif ($description instanceof SMWValueDescription) { // only type '_wpg' objects can appear on query level (essentially as nominal classes) |
234 | | - if ($description->getDatavalue()->getTypeID() == '_wpg') { |
235 | | - if ($description->getComparator() == SMW_CMP_EQ) { |
| 233 | + } elseif ( $description instanceof SMWValueDescription ) { // only type '_wpg' objects can appear on query level (essentially as nominal classes) |
| 234 | + if ( $description->getDatavalue()->getTypeID() == '_wpg' ) { |
| 235 | + if ( $description->getComparator() == SMW_CMP_EQ ) { |
236 | 236 | $query->type = SMW_SQL2_VALUE; |
237 | | - $oid = $this->m_store->getSMWPageID($description->getDatavalue()->getDBkey(), $description->getDatavalue()->getNamespace(),$description->getDatavalue()->getInterwiki()); |
238 | | - $query->joinfield = array($oid); |
| 237 | + $oid = $this->m_store->getSMWPageID( $description->getDatavalue()->getDBkey(), $description->getDatavalue()->getNamespace(), $description->getDatavalue()->getInterwiki() ); |
| 238 | + $query->joinfield = array( $oid ); |
239 | 239 | } else { // join with smw_ids needed for other comparators (apply to title string) |
240 | 240 | $query->jointable = 'smw_ids'; |
241 | 241 | $query->joinfield = "$query->alias.smw_id"; |
242 | 242 | $value = $description->getDatavalue()->getSortkey(); |
243 | | - switch ($description->getComparator()) { |
| 243 | + switch ( $description->getComparator() ) { |
244 | 244 | case SMW_CMP_LEQ: $comp = '<='; break; |
245 | 245 | case SMW_CMP_GEQ: $comp = '>='; break; |
246 | 246 | case SMW_CMP_NEQ: $comp = '!='; break; |
247 | 247 | case SMW_CMP_LIKE: |
248 | 248 | $comp = ' LIKE '; |
249 | | - $value = str_replace(array('%', '_', '*', '?'), array('\%', '\_', '%', '_'), $value); |
| 249 | + $value = str_replace( array( '%', '_', '*', '?' ), array( '\%', '\_', '%', '_' ), $value ); |
250 | 250 | break; |
251 | 251 | } |
252 | | - $query->where = "$query->alias.smw_sortkey$comp" . $this->m_dbs->addQuotes($value); |
| 252 | + $query->where = "$query->alias.smw_sortkey$comp" . $this->m_dbs->addQuotes( $value ); |
253 | 253 | } |
254 | 254 | } |
255 | | - } elseif ($description instanceof SMWConceptDescription) { // fetch concept definition and insert it here |
256 | | - $cid = $this->m_store->getSMWPageID($description->getConcept()->getDBKey(), SMW_NS_CONCEPT, ''); |
257 | | - $row = $this->m_dbs->selectRow('smw_conc2', |
258 | | - array('concept_txt','concept_features','concept_size','concept_depth','cache_date'), |
259 | | - array('s_id'=>$cid), 'SMWSQLStore2Queries::compileQueries'); |
| 255 | + } elseif ( $description instanceof SMWConceptDescription ) { // fetch concept definition and insert it here |
| 256 | + $cid = $this->m_store->getSMWPageID( $description->getConcept()->getDBKey(), SMW_NS_CONCEPT, '' ); |
| 257 | + $row = $this->m_dbs->selectRow( 'smw_conc2', |
| 258 | + array( 'concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date' ), |
| 259 | + array( 's_id' => $cid ), 'SMWSQLStore2Queries::compileQueries' ); |
260 | 260 | if ( $row === false ) { // no description found, concept does not exist |
261 | 261 | // keep the above query object, it yields an empty result |
262 | | - ///TODO: announce an error here? (maybe not, since the query processor can check for |
263 | | - ///non-existing concept pages which is probably the main reason for finding nothing here |
| 262 | + // /TODO: announce an error here? (maybe not, since the query processor can check for |
| 263 | + // /non-existing concept pages which is probably the main reason for finding nothing here |
264 | 264 | } else { |
265 | 265 | global $smwgQConceptCaching, $smwgQMaxSize, $smwgQMaxDepth, $smwgQFeatures, $smwgQConceptCacheLifetime; |
266 | | - $may_be_computed = ($smwgQConceptCaching == CONCEPT_CACHE_NONE) || |
267 | | - ( ($smwgQConceptCaching == CONCEPT_CACHE_HARD) && ( (~(~($row->concept_features+0) | $smwgQFeatures)) == 0) && |
268 | | - ($smwgQMaxSize >= $row->concept_size) && ($smwgQMaxDepth >= $row->concept_depth)); |
269 | | - if ($row->cache_date && |
270 | | - ($row->cache_date > (strtotime("now") - $smwgQConceptCacheLifetime*60) || |
271 | | - !$may_be_computed)) { // cached concept, use cache unless it is dead and can be revived |
| 266 | + $may_be_computed = ( $smwgQConceptCaching == CONCEPT_CACHE_NONE ) || |
| 267 | + ( ( $smwgQConceptCaching == CONCEPT_CACHE_HARD ) && ( ( ~( ~( $row->concept_features + 0 ) | $smwgQFeatures ) ) == 0 ) && |
| 268 | + ( $smwgQMaxSize >= $row->concept_size ) && ( $smwgQMaxDepth >= $row->concept_depth ) ); |
| 269 | + if ( $row->cache_date && |
| 270 | + ( $row->cache_date > ( strtotime( "now" ) - $smwgQConceptCacheLifetime * 60 ) || |
| 271 | + !$may_be_computed ) ) { // cached concept, use cache unless it is dead and can be revived |
272 | 272 | $query->jointable = 'smw_conccache'; |
273 | 273 | $query->joinfield = "$query->alias.s_id"; |
274 | | - $query->where = "$query->alias.o_id=" . $this->m_dbs->addQuotes($cid); |
275 | | - } elseif ($row->concept_txt) { // parse description and process it recursively |
276 | | - if ($may_be_computed) { |
| 274 | + $query->where = "$query->alias.o_id=" . $this->m_dbs->addQuotes( $cid ); |
| 275 | + } elseif ( $row->concept_txt ) { // parse description and process it recursively |
| 276 | + if ( $may_be_computed ) { |
277 | 277 | $qp = new SMWQueryParser(); |
278 | 278 | // no defaultnamespaces here; if any, these are already in the concept |
279 | | - $desc = $qp->getQueryDescription($row->concept_txt); |
280 | | - $qid = $this->compileQueries($desc); |
| 279 | + $desc = $qp->getQueryDescription( $row->concept_txt ); |
| 280 | + $qid = $this->compileQueries( $desc ); |
281 | 281 | $query = $this->m_queries[$qid]; |
282 | 282 | } else { |
283 | | - wfLoadExtensionMessages('SemanticMediaWiki'); |
284 | | - $this->m_errors[] = wfMsg('smw_concept_cache_miss',$description->getConcept()->getText()); |
| 283 | + wfLoadExtensionMessages( 'SemanticMediaWiki' ); |
| 284 | + $this->m_errors[] = wfMsg( 'smw_concept_cache_miss', $description->getConcept()->getText() ); |
285 | 285 | } |
286 | 286 | } // else: no cache, no description (this may happen); treat like empty concept |
287 | 287 | } |
288 | 288 | } else { // (e.g. SMWThingDescription, SMWValueList is also treated elswhere) |
289 | | - $qid = -1; // no condition |
| 289 | + $qid = - 1; // no condition |
290 | 290 | } |
291 | | - if ($qid >= 0) { |
| 291 | + if ( $qid >= 0 ) { |
292 | 292 | $this->m_queries[$qid] = $query; |
293 | 293 | } |
294 | | - if ($query->type != SMW_SQL2_DISJUNCTION) { // sortkeys are killed by disjunctions (not all parts may have them), preprocessing might try to push disjunctions downwards to safe sortkey |
295 | | - foreach ($query->components as $cid => $field) { |
296 | | - $query->sortfields = array_merge($this->m_queries[$cid]->sortfields,$query->sortfields); |
| 294 | + if ( $query->type != SMW_SQL2_DISJUNCTION ) { // sortkeys are killed by disjunctions (not all parts may have them), preprocessing might try to push disjunctions downwards to safe sortkey |
| 295 | + foreach ( $query->components as $cid => $field ) { |
| 296 | + $query->sortfields = array_merge( $this->m_queries[$cid]->sortfields, $query->sortfields ); |
297 | 297 | } |
298 | 298 | } |
299 | 299 | return $qid; |
— | — | @@ -306,68 +306,68 @@ |
307 | 307 | * Some properties cannot be queried for; in this case, the query type is changed to SMW_SQL2_NOQUERY. |
308 | 308 | * Callers need to check for this. |
309 | 309 | */ |
310 | | - protected function compilePropertyCondition(&$query, $property, SMWDescription $valuedesc, $typeid=false) { |
| 310 | + protected function compilePropertyCondition( &$query, $property, SMWDescription $valuedesc, $typeid = false ) { |
311 | 311 | $query->joinfield = "$query->alias.s_id"; |
312 | | - if ($property instanceof SMWPropertyValue) { |
| 312 | + if ( $property instanceof SMWPropertyValue ) { |
313 | 313 | $typeid = $property->getTypeID(); |
314 | | - $mode = SMWSQLStore2::getStorageMode($typeid); |
315 | | - $pid = $this->m_store->getSMWPropertyID($property); |
| 314 | + $mode = SMWSQLStore2::getStorageMode( $typeid ); |
| 315 | + $pid = $this->m_store->getSMWPropertyID( $property ); |
316 | 316 | $sortkey = $property->getXSDValue(); |
317 | | - if ($mode != SMW_SQL2_SUBS2) { // also make property hierarchy (though not for all properties) |
| 317 | + if ( $mode != SMW_SQL2_SUBS2 ) { // also make property hierarchy (though not for all properties) |
318 | 318 | $pqid = SMWSQLStore2Query::$qnum; |
319 | 319 | $pquery = new SMWSQLStore2Query(); |
320 | 320 | $pquery->type = SMW_SQL2_PROP_HIERARCHY; |
321 | | - $pquery->joinfield = array($pid); |
| 321 | + $pquery->joinfield = array( $pid ); |
322 | 322 | $query->components[$pqid] = "$query->alias.p_id"; |
323 | 323 | $this->m_queries[$pqid] = $pquery; |
324 | 324 | } |
325 | 325 | } else { |
326 | 326 | $pid = $property; |
327 | 327 | $sortkey = false; |
328 | | - $mode = SMWSQLStore2::getStorageMode($typeid); |
329 | | - if ($mode != SMW_SQL2_SUBS2) { // no property hierarchy, but normal query (not for all properties) |
330 | | - $query->where = "$query->alias.p_id=" . $this->m_dbs->addQuotes($pid); |
| 328 | + $mode = SMWSQLStore2::getStorageMode( $typeid ); |
| 329 | + if ( $mode != SMW_SQL2_SUBS2 ) { // no property hierarchy, but normal query (not for all properties) |
| 330 | + $query->where = "$query->alias.p_id=" . $this->m_dbs->addQuotes( $pid ); |
331 | 331 | } |
332 | 332 | } |
333 | | - $mode = SMWSQLStore2::getStorageMode($typeid); |
| 333 | + $mode = SMWSQLStore2::getStorageMode( $typeid ); |
334 | 334 | $sortfield = ''; // used if we should sort by this property |
335 | | - switch ($mode) { |
| 335 | + switch ( $mode ) { |
336 | 336 | case SMW_SQL2_RELS2: case SMW_SQL2_SUBS2: // subconditions as subqueries (compiled) |
337 | | - $query->jointable = ($mode==SMW_SQL2_RELS2)?'smw_rels2':'smw_subs2'; |
338 | | - $sub = $this->compileQueries($valuedesc); |
339 | | - if ($sub >= 0) { |
| 337 | + $query->jointable = ( $mode == SMW_SQL2_RELS2 ) ? 'smw_rels2':'smw_subs2'; |
| 338 | + $sub = $this->compileQueries( $valuedesc ); |
| 339 | + if ( $sub >= 0 ) { |
340 | 340 | $query->components[$sub] = "$query->alias.o_id"; |
341 | 341 | } |
342 | | - if ( $sortkey && array_key_exists($sortkey, $this->m_sortkeys) ) { |
343 | | - $query->from = ' INNER JOIN ' . $this->m_dbs->tableName('smw_ids') . " AS ids$query->alias ON ids$query->alias.smw_id=$query->alias.o_id"; |
344 | | - $sortfield = "ids$query->alias.smw_title"; /// TODO: as below, smw_ids here is possibly duplicated! Can we prevent that? (PERFORMANCE) |
| 342 | + if ( $sortkey && array_key_exists( $sortkey, $this->m_sortkeys ) ) { |
| 343 | + $query->from = ' INNER JOIN ' . $this->m_dbs->tableName( 'smw_ids' ) . " AS ids$query->alias ON ids$query->alias.smw_id=$query->alias.o_id"; |
| 344 | + $sortfield = "ids$query->alias.smw_title"; // / TODO: as below, smw_ids here is possibly duplicated! Can we prevent that? (PERFORMANCE) |
345 | 345 | } |
346 | 346 | break; |
347 | 347 | case SMW_SQL2_NARY2: |
348 | 348 | $query->jointable = 'smw_rels2'; |
349 | | - if ($valuedesc instanceof SMWValueList) { // anything else is ignored! |
| 349 | + if ( $valuedesc instanceof SMWValueList ) { // anything else is ignored! |
350 | 350 | $typevalue = $property->getTypesValue(); |
351 | 351 | $typelabels = $typevalue->getTypeLabels(); |
352 | | - reset($typelabels); |
| 352 | + reset( $typelabels ); |
353 | 353 | $subqid = SMWSQLStore2Query::$qnum; |
354 | 354 | $subquery = new SMWSQLStore2Query(); |
355 | 355 | $subquery->type = SMW_SQL2_CONJUNCTION; |
356 | 356 | $query->components[$subqid] = "$query->alias.o_id"; |
357 | 357 | $this->m_queries[$subqid] = $subquery; |
358 | | - for ($i=0; $i<$valuedesc->getCount(); $i++) { |
359 | | - $desc = $valuedesc->getDescription($i); |
360 | | - if ($desc !== NULL) { |
361 | | - $stypeid = SMWDataValueFactory::findTypeID(current($typelabels)); |
362 | | - $valpid = $this->m_store->getSMWPageID(strval($i),SMW_NS_PROPERTY,SMW_SQL2_SMWIW); |
| 358 | + for ( $i = 0; $i < $valuedesc->getCount(); $i++ ) { |
| 359 | + $desc = $valuedesc->getDescription( $i ); |
| 360 | + if ( $desc !== NULL ) { |
| 361 | + $stypeid = SMWDataValueFactory::findTypeID( current( $typelabels ) ); |
| 362 | + $valpid = $this->m_store->getSMWPageID( strval( $i ), SMW_NS_PROPERTY, SMW_SQL2_SMWIW ); |
363 | 363 | $valqid = SMWSQLStore2Query::$qnum; |
364 | 364 | $valquery = new SMWSQLStore2Query(); |
365 | | - $this->compilePropertyCondition($valquery, $valpid, $desc, $stypeid); |
366 | | - if ($valquery->type != SMW_SQL2_NOQUERY) { |
| 365 | + $this->compilePropertyCondition( $valquery, $valpid, $desc, $stypeid ); |
| 366 | + if ( $valquery->type != SMW_SQL2_NOQUERY ) { |
367 | 367 | $subquery->components[$valqid] = true; |
368 | 368 | $this->m_queries[$valqid] = $valquery; |
369 | 369 | } |
370 | 370 | } |
371 | | - next($typelabels); |
| 371 | + next( $typelabels ); |
372 | 372 | } |
373 | 373 | } |
374 | 374 | break; |
— | — | @@ -375,14 +375,14 @@ |
376 | 376 | $query->jointable = 'smw_text2'; |
377 | 377 | break; |
378 | 378 | case SMW_SQL2_ATTS2: case SMW_SQL2_SPEC2: // subquery only conj/disj of values, compile to single "where" |
379 | | - $query->jointable = ($mode==SMW_SQL2_ATTS2)?'smw_atts2':'smw_spec2'; |
380 | | - $aw = $this->compileAttributeWhere($valuedesc,"$query->alias"); |
381 | | - if ($aw != '') { |
382 | | - $query->where .= ($query->where?' AND ':'') . $aw; |
| 379 | + $query->jointable = ( $mode == SMW_SQL2_ATTS2 ) ? 'smw_atts2':'smw_spec2'; |
| 380 | + $aw = $this->compileAttributeWhere( $valuedesc, "$query->alias" ); |
| 381 | + if ( $aw != '' ) { |
| 382 | + $query->where .= ( $query->where ? ' AND ':'' ) . $aw; |
383 | 383 | } |
384 | | - if ( $sortkey && array_key_exists($sortkey, $this->m_sortkeys) ) { |
385 | | - if ($mode==SMW_SQL2_ATTS2) { |
386 | | - $sortfield = "$query->alias." . (SMWDataValueFactory::newTypeIDValue($typeid)->isNumeric()?'value_num':'value_xsd'); |
| 384 | + if ( $sortkey && array_key_exists( $sortkey, $this->m_sortkeys ) ) { |
| 385 | + if ( $mode == SMW_SQL2_ATTS2 ) { |
| 386 | + $sortfield = "$query->alias." . ( SMWDataValueFactory::newTypeIDValue( $typeid )->isNumeric() ? 'value_num':'value_xsd' ); |
387 | 387 | } else { |
388 | 388 | $sortfield = "$query->alias.value_string"; |
389 | 389 | } |
— | — | @@ -392,7 +392,7 @@ |
393 | 393 | $query->type = SMW_SQL2_NOQUERY; |
394 | 394 | $sortfield = false; |
395 | 395 | } |
396 | | - if ($sortfield) { |
| 396 | + if ( $sortfield ) { |
397 | 397 | $query->sortfields[$sortkey] = $sortfield; |
398 | 398 | } |
399 | 399 | } |
— | — | @@ -401,36 +401,36 @@ |
402 | 402 | * Given an SMWDescription that is just a conjunction or disjunction of |
403 | 403 | * SMWValueDescription objects, create a plain WHERE condition string for it. |
404 | 404 | */ |
405 | | - protected function compileAttributeWhere(SMWDescription $description, $jointable) { |
406 | | - if ($description instanceof SMWValueDescription) { |
| 405 | + protected function compileAttributeWhere( SMWDescription $description, $jointable ) { |
| 406 | + if ( $description instanceof SMWValueDescription ) { |
407 | 407 | $dv = $description->getDatavalue(); |
408 | | - if (SMWSQLStore2::getStorageMode($dv->getTypeID()) == SMW_SQL2_SPEC2) { |
| 408 | + if ( SMWSQLStore2::getStorageMode( $dv->getTypeID() ) == SMW_SQL2_SPEC2 ) { |
409 | 409 | $value = $dv->getXSDValue(); |
410 | 410 | $field = "$jointable.value_string"; |
411 | | - } else { //should be SMW_SQL2_ATTS2 |
| 411 | + } else { // should be SMW_SQL2_ATTS2 |
412 | 412 | $value = $dv->isNumeric() ? $dv->getNumericValue() : $dv->getXSDValue(); |
413 | 413 | $field = $dv->isNumeric() ? "$jointable.value_num" : "$jointable.value_xsd"; |
414 | 414 | } |
415 | | - switch ($description->getComparator()) { |
| 415 | + switch ( $description->getComparator() ) { |
416 | 416 | case SMW_CMP_LEQ: $comp = '<='; break; |
417 | 417 | case SMW_CMP_GEQ: $comp = '>='; break; |
418 | 418 | case SMW_CMP_NEQ: $comp = '!='; break; |
419 | 419 | case SMW_CMP_LIKE: |
420 | | - if ($dv->getTypeID() == '_str') { |
| 420 | + if ( $dv->getTypeID() == '_str' ) { |
421 | 421 | $comp = ' LIKE '; |
422 | | - $value = str_replace(array('%', '_', '*', '?'), array('\%', '\_', '%', '_'), $value); |
| 422 | + $value = str_replace( array( '%', '_', '*', '?' ), array( '\%', '\_', '%', '_' ), $value ); |
423 | 423 | } else { // LIKE only supported for strings |
424 | 424 | $comp = '='; |
425 | 425 | } |
426 | 426 | break; |
427 | 427 | case SMW_CMP_EQ: default: $comp = '='; break; |
428 | 428 | } |
429 | | - $result = "$field$comp" . $this->m_dbs->addQuotes($value); |
430 | | - } elseif ( ($description instanceof SMWConjunction) || ($description instanceof SMWDisjunction) ) { |
431 | | - $op = ($description instanceof SMWConjunction) ? ' AND ' : ' OR '; |
| 429 | + $result = "$field$comp" . $this->m_dbs->addQuotes( $value ); |
| 430 | + } elseif ( ( $description instanceof SMWConjunction ) || ( $description instanceof SMWDisjunction ) ) { |
| 431 | + $op = ( $description instanceof SMWConjunction ) ? ' AND ' : ' OR '; |
432 | 432 | $result = ''; |
433 | | - foreach ($description->getDescriptions() as $subdesc) { |
434 | | - $result= $result . ( $result!=''?$op:'' ) . $this->compileAttributeWhere($subdesc,$jointable); |
| 433 | + foreach ( $description->getDescriptions() as $subdesc ) { |
| 434 | + $result = $result . ( $result != '' ? $op:'' ) . $this->compileAttributeWhere( $subdesc, $jointable ); |
435 | 435 | } |
436 | 436 | $result = "($result)"; |
437 | 437 | } else { |
— | — | @@ -444,23 +444,23 @@ |
445 | 445 | * so that it contains non-recursive description of a select to execute for getting |
446 | 446 | * the actual result. |
447 | 447 | */ |
448 | | - protected function executeQueries(SMWSQLStore2Query &$query) { |
449 | | - switch ($query->type) { |
| 448 | + protected function executeQueries( SMWSQLStore2Query &$query ) { |
| 449 | + switch ( $query->type ) { |
450 | 450 | case SMW_SQL2_TABLE: // normal query with conjunctive subcondition |
451 | | - foreach ($query->components as $qid => $joinfield) { |
| 451 | + foreach ( $query->components as $qid => $joinfield ) { |
452 | 452 | $subquery = $this->m_queries[$qid]; |
453 | | - $this->executeQueries($subquery); |
454 | | - if ($subquery->jointable != '') { // join with jointable.joinfield |
455 | | - $query->from .= ' INNER JOIN ' . $this->m_dbs->tableName($subquery->jointable) . " AS $subquery->alias ON $joinfield=" . $subquery->joinfield; |
456 | | - } elseif ($subquery->joinfield !== '') { // require joinfield as "value" via WHERE |
| 453 | + $this->executeQueries( $subquery ); |
| 454 | + if ( $subquery->jointable != '' ) { // join with jointable.joinfield |
| 455 | + $query->from .= ' INNER JOIN ' . $this->m_dbs->tableName( $subquery->jointable ) . " AS $subquery->alias ON $joinfield=" . $subquery->joinfield; |
| 456 | + } elseif ( $subquery->joinfield !== '' ) { // require joinfield as "value" via WHERE |
457 | 457 | $condition = ''; |
458 | | - foreach ($subquery->joinfield as $value) { |
459 | | - $condition .= ($condition?' OR ':'') . "$joinfield=" . $this->m_dbs->addQuotes($value); |
| 458 | + foreach ( $subquery->joinfield as $value ) { |
| 459 | + $condition .= ( $condition ? ' OR ':'' ) . "$joinfield=" . $this->m_dbs->addQuotes( $value ); |
460 | 460 | } |
461 | | - if (count($subquery->joinfield) > 1) { |
| 461 | + if ( count( $subquery->joinfield ) > 1 ) { |
462 | 462 | $condition = "($condition)"; |
463 | 463 | } |
464 | | - $query->where .= (($query->where == '')?'':' AND ') . $condition; |
| 464 | + $query->where .= ( ( $query->where == '' ) ? '':' AND ' ) . $condition; |
465 | 465 | } else { // interpret empty joinfields as impossible condition (empty result) |
466 | 466 | $query->joinfield = ''; // make whole query false |
467 | 467 | $query->jointable = ''; |
— | — | @@ -468,8 +468,8 @@ |
469 | 469 | $query->from = ''; |
470 | 470 | break; |
471 | 471 | } |
472 | | - if ($subquery->where != '') { |
473 | | - $query->where .= (($query->where == '')?'':' AND ') . $subquery->where; |
| 472 | + if ( $subquery->where != '' ) { |
| 473 | + $query->where .= ( ( $query->where == '' ) ? '':' AND ' ) . $subquery->where; |
474 | 474 | } |
475 | 475 | $query->from .= $subquery->from; |
476 | 476 | } |
— | — | @@ -477,29 +477,29 @@ |
478 | 478 | break; |
479 | 479 | case SMW_SQL2_CONJUNCTION: |
480 | 480 | // pick one subquery with jointable as anchor point ... |
481 | | - reset($query->components); |
| 481 | + reset( $query->components ); |
482 | 482 | $key = false; |
483 | | - foreach ($query->components as $qkey => $qid) { |
484 | | - if ($this->m_queries[$qkey]->jointable != '') { |
| 483 | + foreach ( $query->components as $qkey => $qid ) { |
| 484 | + if ( $this->m_queries[$qkey]->jointable != '' ) { |
485 | 485 | $key = $qkey; |
486 | 486 | break; |
487 | 487 | } |
488 | 488 | } |
489 | | - if ($key !== false) { |
| 489 | + if ( $key !== false ) { |
490 | 490 | $result = $this->m_queries[$key]; |
491 | | - unset($query->components[$key]); |
492 | | - $this->executeQueries($result); // execute it first (may change jointable and joinfield, e.g. when making temporary tables) |
| 491 | + unset( $query->components[$key] ); |
| 492 | + $this->executeQueries( $result ); // execute it first (may change jointable and joinfield, e.g. when making temporary tables) |
493 | 493 | // ... and append to this query the remaining queries |
494 | | - foreach ($query->components as $qid => $joinfield) { |
| 494 | + foreach ( $query->components as $qid => $joinfield ) { |
495 | 495 | $result->components[$qid] = $result->joinfield; |
496 | 496 | } |
497 | | - $this->executeQueries($result); // second execute, now incorporating remaining conditions |
| 497 | + $this->executeQueries( $result ); // second execute, now incorporating remaining conditions |
498 | 498 | } else { // only fixed values in conjunction, make a new value without joining |
499 | 499 | $key = $qkey; |
500 | 500 | $result = $this->m_queries[$key]; |
501 | | - unset($query->components[$key]); |
502 | | - foreach ($query->components as $qid => $joinfield) { |
503 | | - if ($result->joinfield != $this->m_queries[$qid]->joinfield) { |
| 501 | + unset( $query->components[$key] ); |
| 502 | + foreach ( $query->components as $qid => $joinfield ) { |
| 503 | + if ( $result->joinfield != $this->m_queries[$qid]->joinfield ) { |
504 | 504 | $result->joinfield = ''; // all other values should already be '' |
505 | 505 | break; |
506 | 506 | } |
— | — | @@ -507,31 +507,31 @@ |
508 | 508 | } |
509 | 509 | $query = $result; |
510 | 510 | break; |
511 | | - case SMW_SQL2_DISJUNCTION:
|
512 | | - // modified by dch, disable TEMPORARY tables
|
| 511 | + case SMW_SQL2_DISJUNCTION: |
| 512 | + // modified by dch, disable TEMPORARY tables |
513 | 513 | // if ($this->m_qmode !== SMWQuery::MODE_DEBUG) { |
514 | 514 | // $this->m_dbs->query( "CREATE TEMPORARY TABLE " . $this->m_dbs->tableName($query->alias) . |
515 | 515 | // ' ( id INT UNSIGNED KEY ) TYPE=MEMORY', 'SMW::executeQueries' ); |
516 | 516 | // } |
517 | 517 | // $this->m_querylog[$query->alias] = array(); |
518 | | - foreach ($query->components as $qid => $joinfield) { |
| 518 | + foreach ( $query->components as $qid => $joinfield ) { |
519 | 519 | $subquery = $this->m_queries[$qid]; |
520 | | - $this->executeQueries($subquery); |
| 520 | + $this->executeQueries( $subquery ); |
521 | 521 | $sql = ''; |
522 | | - if ($subquery->jointable != '') { |
| 522 | + if ( $subquery->jointable != '' ) { |
523 | 523 | // $sql = "INSERT IGNORE INTO " . $this->m_dbs->tableName($query->alias) . " SELECT $subquery->joinfield FROM " . |
524 | 524 | // $this->m_dbs->tableName($subquery->jointable) . " AS $subquery->alias $subquery->from" . ($subquery->where?" WHERE $subquery->where":''); |
525 | | - $sql = ($sql != ''?'UNION':''). "SELECT $subquery->joinfield AS id FROM " .
|
526 | | - $this->m_dbs->tableName($subquery->jointable) . " AS $subquery->alias $subquery->from" . ($subquery->where?" WHERE $subquery->where":'');
|
527 | | - } elseif ($subquery->joinfield !== '') { |
528 | | - /// NOTE: this works only for single "unconditional" values without further |
529 | | - /// WHERE or FROM. The execution must take care of not creating any others. |
| 525 | + $sql = ( $sql != '' ? 'UNION':'' ) . "SELECT $subquery->joinfield AS id FROM " . |
| 526 | + $this->m_dbs->tableName( $subquery->jointable ) . " AS $subquery->alias $subquery->from" . ( $subquery->where ? " WHERE $subquery->where":'' ); |
| 527 | + } elseif ( $subquery->joinfield !== '' ) { |
| 528 | + // / NOTE: this works only for single "unconditional" values without further |
| 529 | + // / WHERE or FROM. The execution must take care of not creating any others. |
530 | 530 | $values = ''; |
531 | | - foreach ($subquery->joinfield as $value) { |
532 | | - $values .= ($values?',':'') . '(' . $this->m_dbs->addQuotes($value) . ')'; |
| 531 | + foreach ( $subquery->joinfield as $value ) { |
| 532 | + $values .= ( $values ? ',':'' ) . '(' . $this->m_dbs->addQuotes( $value ) . ')'; |
533 | 533 | } |
534 | 534 | // $sql = "INSERT IGNORE INTO " . $this->m_dbs->tableName($query->alias) . " (id) VALUES $values"; |
535 | | - $sql = ($sql != ''?'UNION':''). "SELECT smw_id AS id FROM ".$this->m_dbs->tableName('smw_ids')." WHERE smw_id IN ($values)";
|
| 535 | + $sql = ( $sql != '' ? 'UNION':'' ) . "SELECT smw_id AS id FROM " . $this->m_dbs->tableName( 'smw_ids' ) . " WHERE smw_id IN ($values)"; |
536 | 536 | } // else: // interpret empty joinfields as impossible condition (empty result), ignore |
537 | 537 | // if ($sql) { |
538 | 538 | // $this->m_querylog[$query->alias][] = $sql; |
— | — | @@ -541,74 +541,74 @@ |
542 | 542 | // } |
543 | 543 | } |
544 | 544 | // $query->jointable = $query->alias; |
545 | | - $query->jointable = "($sql)";
|
| 545 | + $query->jointable = "($sql)"; |
546 | 546 | $query->joinfield = "$query->alias.id"; |
547 | 547 | $query->sortfields = array(); // make sure we got no sortfields |
548 | | - /// TODO: currently this eliminates sortkeys, possibly keep them (needs different temp table format though, maybe not such a good thing to do) |
| 548 | + // / TODO: currently this eliminates sortkeys, possibly keep them (needs different temp table format though, maybe not such a good thing to do) |
549 | 549 | break; |
550 | 550 | case SMW_SQL2_PROP_HIERARCHY: case SMW_SQL2_CLASS_HIERARCHY: // make a saturated hierarchy |
551 | | - $this->executeHierarchyQuery($query); |
| 551 | + $this->executeHierarchyQuery( $query ); |
552 | 552 | break; |
553 | 553 | case SMW_SQL2_VALUE: break; // nothing to do |
554 | 554 | } |
555 | 555 | } |
556 | | - |
| 556 | + |
557 | 557 | /** |
558 | 558 | * Find subproperties or subcategories. This may require iterative computation, |
559 | 559 | * and temporary tables are used in many cases. |
560 | 560 | */ |
561 | | - protected function executeHierarchyQuery(&$query) { |
| 561 | + protected function executeHierarchyQuery( &$query ) { |
562 | 562 | $fname = "SMWSQLStore2Queries::executeQueries-hierarchy-$query->type (SMW)"; |
563 | | - wfProfileIn($fname); |
| 563 | + wfProfileIn( $fname ); |
564 | 564 | global $smwgQSubpropertyDepth, $smwgQSubcategoryDepth; |
565 | | - $depth = ($query->type == SMW_SQL2_PROP_HIERARCHY)?$smwgQSubpropertyDepth:$smwgQSubcategoryDepth; |
566 | | - if ($depth <= 0) { // treat as value, no recursion |
| 565 | + $depth = ( $query->type == SMW_SQL2_PROP_HIERARCHY ) ? $smwgQSubpropertyDepth:$smwgQSubcategoryDepth; |
| 566 | + if ( $depth <= 0 ) { // treat as value, no recursion |
567 | 567 | $query->type = SMW_SQL2_VALUE; |
568 | | - wfProfileOut($fname); |
| 568 | + wfProfileOut( $fname ); |
569 | 569 | return; |
570 | 570 | } |
571 | 571 | $values = ''; |
572 | 572 | $valuecond = ''; |
573 | | - foreach ($query->joinfield as $value) { |
574 | | - $values .= ($values?',':'') . '(' . $this->m_dbs->addQuotes($value) . ')'; |
575 | | - $valuecond .= ($valuecond?' OR ':'') . 'o_id=' . $this->m_dbs->addQuotes($value); |
| 573 | + foreach ( $query->joinfield as $value ) { |
| 574 | + $values .= ( $values ? ',':'' ) . '(' . $this->m_dbs->addQuotes( $value ) . ')'; |
| 575 | + $valuecond .= ( $valuecond ? ' OR ':'' ) . 'o_id=' . $this->m_dbs->addQuotes( $value ); |
576 | 576 | } |
577 | | - $smw_subs2 = $this->m_dbs->tableName('smw_subs2'); |
| 577 | + $smw_subs2 = $this->m_dbs->tableName( 'smw_subs2' ); |
578 | 578 | // try to safe time (SELECT is cheaper than creating/dropping 3 temp tables): |
579 | | - $res = $this->m_dbs->select($smw_subs2,'s_id',$valuecond, array('LIMIT'=>1)); |
580 | | - if (!$this->m_dbs->fetchObject($res)) { // no subobjects, we are done! |
581 | | - $this->m_dbs->freeResult($res); |
| 579 | + $res = $this->m_dbs->select( $smw_subs2, 's_id', $valuecond, array( 'LIMIT' => 1 ) ); |
| 580 | + if ( !$this->m_dbs->fetchObject( $res ) ) { // no subobjects, we are done! |
| 581 | + $this->m_dbs->freeResult( $res ); |
582 | 582 | $query->type = SMW_SQL2_VALUE; |
583 | | - wfProfileOut($fname); |
| 583 | + wfProfileOut( $fname ); |
584 | 584 | return; |
585 | 585 | } |
586 | | - $this->m_dbs->freeResult($res); |
587 | | - $tablename = $this->m_dbs->tableName($query->alias);
|
588 | | - // modified by dch
|
589 | | -// $this->m_querylog[$query->alias] = array("Recursively computed hierarchy for element(s) $values.");
|
590 | | - $this->m_querylog[$query->alias]["$depth:$values"] = "Recursively computed hierarchy for element(s) $values.";
|
591 | | -
|
592 | | - $query->jointable = $query->alias;
|
| 586 | + $this->m_dbs->freeResult( $res ); |
| 587 | + $tablename = $this->m_dbs->tableName( $query->alias ); |
| 588 | + // modified by dch |
| 589 | +// $this->m_querylog[$query->alias] = array("Recursively computed hierarchy for element(s) $values."); |
| 590 | + $this->m_querylog[$query->alias]["$depth:$values"] = "Recursively computed hierarchy for element(s) $values."; |
| 591 | + |
| 592 | + $query->jointable = $query->alias; |
593 | 593 | $query->joinfield = "$query->alias.id"; |
594 | | - if ($this->m_qmode == SMWQuery::MODE_DEBUG) { |
595 | | - wfProfileOut($fname); |
| 594 | + if ( $this->m_qmode == SMWQuery::MODE_DEBUG ) { |
| 595 | + wfProfileOut( $fname ); |
596 | 596 | return; // no real queries in debug mode |
597 | | - }
|
598 | | - |
| 597 | + } |
| 598 | + |
599 | 599 | $this->m_dbs->query( "CREATE TEMPORARY TABLE $tablename " . |
600 | 600 | '( id INT UNSIGNED NOT NULL KEY) TYPE=MEMORY', 'SMW::executeQueries' ); |
601 | | - if (array_key_exists($values, $this->m_hierarchies)) { // just copy known result
|
602 | | - $this->m_dbs->query("INSERT INTO $tablename (id) SELECT id" .
|
603 | | - ' FROM ' . $this->m_hierarchies[$values],
|
604 | | - 'SMW::executeQueries');
|
605 | | - wfProfileOut($fname); |
| 601 | + if ( array_key_exists( $values, $this->m_hierarchies ) ) { // just copy known result |
| 602 | + $this->m_dbs->query( "INSERT INTO $tablename (id) SELECT id" . |
| 603 | + ' FROM ' . $this->m_hierarchies[$values], |
| 604 | + 'SMW::executeQueries' ); |
| 605 | + wfProfileOut( $fname ); |
606 | 606 | return; |
607 | 607 | } |
608 | 608 | |
609 | | - /// NOTE: we use two helper tables. One holds the results of each new iteration, one holds the |
610 | | - /// results of the previous iteration. One could of course do with only the above result table, |
611 | | - /// but then every iteration would use all elements of this table, while only the new ones |
612 | | - /// obtained in the previous step are relevant. So this is a performance measure. |
| 609 | + // / NOTE: we use two helper tables. One holds the results of each new iteration, one holds the |
| 610 | + // / results of the previous iteration. One could of course do with only the above result table, |
| 611 | + // / but then every iteration would use all elements of this table, while only the new ones |
| 612 | + // / obtained in the previous step are relevant. So this is a performance measure. |
613 | 613 | $tmpnew = 'smw_new'; |
614 | 614 | $tmpres = 'smw_res'; |
615 | 615 | $this->m_dbs->query( "CREATE TEMPORARY TABLE $tmpnew " . |
— | — | @@ -616,39 +616,39 @@ |
617 | 617 | $this->m_dbs->query( "CREATE TEMPORARY TABLE $tmpres " . |
618 | 618 | '( id INT UNSIGNED ) TYPE=MEMORY', 'SMW::executeQueries' ); |
619 | 619 | |
620 | | - $this->m_dbs->query("INSERT IGNORE INTO $tablename (id) VALUES $values", 'SMW::executeQueries'); |
621 | | - $this->m_dbs->query("INSERT IGNORE INTO $tmpnew (id) VALUES $values", 'SMW::executeQueries'); |
| 620 | + $this->m_dbs->query( "INSERT IGNORE INTO $tablename (id) VALUES $values", 'SMW::executeQueries' ); |
| 621 | + $this->m_dbs->query( "INSERT IGNORE INTO $tmpnew (id) VALUES $values", 'SMW::executeQueries' ); |
622 | 622 | |
623 | | - for ($i=0; $i<$depth; $i++) { |
624 | | - $this->m_dbs->query("INSERT INTO $tmpres (id) SELECT s_id FROM $smw_subs2, $tmpnew WHERE o_id=id", |
625 | | - 'SMW::executeQueries'); |
626 | | - if ($this->m_dbs->affectedRows() == 0) { // no change, exit loop |
| 623 | + for ( $i = 0; $i < $depth; $i++ ) { |
| 624 | + $this->m_dbs->query( "INSERT INTO $tmpres (id) SELECT s_id FROM $smw_subs2, $tmpnew WHERE o_id=id", |
| 625 | + 'SMW::executeQueries' ); |
| 626 | + if ( $this->m_dbs->affectedRows() == 0 ) { // no change, exit loop |
627 | 627 | break; |
628 | 628 | } |
629 | | - $this->m_dbs->query("INSERT IGNORE INTO $tablename (id) SELECT $tmpres.id FROM $tmpres", |
630 | | - 'SMW::executeQueries'); |
631 | | - if ($this->m_dbs->affectedRows() == 0) { // no change, exit loop |
| 629 | + $this->m_dbs->query( "INSERT IGNORE INTO $tablename (id) SELECT $tmpres.id FROM $tmpres", |
| 630 | + 'SMW::executeQueries' ); |
| 631 | + if ( $this->m_dbs->affectedRows() == 0 ) { // no change, exit loop |
632 | 632 | break; |
633 | | - }
|
634 | | -
|
635 | | - $this->m_dbs->query('TRUNCATE TABLE ' . $tmpnew, 'SMW::executeQueries'); // empty "new" table |
| 633 | + } |
| 634 | + |
| 635 | + $this->m_dbs->query( 'TRUNCATE TABLE ' . $tmpnew, 'SMW::executeQueries' ); // empty "new" table |
636 | 636 | $tmpname = $tmpnew; |
637 | 637 | $tmpnew = $tmpres; |
638 | 638 | $tmpres = $tmpname; |
639 | | - }
|
640 | | - |
| 639 | + } |
| 640 | + |
641 | 641 | $this->m_hierarchies[$values] = $tablename; |
642 | | - $this->m_dbs->query('DROP TEMPORARY TABLE smw_new', 'SMW::executeQueries'); |
643 | | - $this->m_dbs->query('DROP TEMPORARY TABLE smw_res', 'SMW::executeQueries'); |
644 | | - wfProfileOut($fname); |
| 642 | + $this->m_dbs->query( 'DROP TEMPORARY TABLE smw_new', 'SMW::executeQueries' ); |
| 643 | + $this->m_dbs->query( 'DROP TEMPORARY TABLE smw_res', 'SMW::executeQueries' ); |
| 644 | + wfProfileOut( $fname ); |
645 | 645 | } |
646 | 646 | |
647 | 647 | /** |
648 | | - * This function modifies the given query object at $qid to account for all ordering conditions |
649 | | - * in the SMWQuery $query. It is always required that $qid is the id of a query that joins with |
| 648 | + * This function modifies the given query object at $qid to account for all ordering conditions |
| 649 | + * in the SMWQuery $query. It is always required that $qid is the id of a query that joins with |
650 | 650 | * smw_ids so that the field alias.smw_title is $available for default sorting. |
651 | 651 | */ |
652 | | - protected function applyOrderConditions($query, $qid) { |
| 652 | + protected function applyOrderConditions( $query, $qid ) { |
653 | 653 | global $smwgQSortingSupport; |
654 | 654 | if ( !$smwgQSortingSupport ) { |
655 | 655 | return; |
— | — | @@ -656,27 +656,27 @@ |
657 | 657 | $qobj = $this->m_queries[$qid]; |
658 | 658 | // (1) collect required extra property descriptions: |
659 | 659 | $extraproperties = array(); |
660 | | - foreach ($this->m_sortkeys as $propkey => $order) { |
661 | | - if (!array_key_exists($propkey,$qobj->sortfields)) { // find missing property to sort by |
662 | | - if ($propkey == '') { // sort by first result column (page titles) |
| 660 | + foreach ( $this->m_sortkeys as $propkey => $order ) { |
| 661 | + if ( !array_key_exists( $propkey, $qobj->sortfields ) ) { // find missing property to sort by |
| 662 | + if ( $propkey == '' ) { // sort by first result column (page titles) |
663 | 663 | $qobj->sortfields[$propkey] = "$qobj->alias.smw_sortkey"; |
664 | 664 | } else { // try to extend query |
665 | 665 | $extrawhere = ''; |
666 | | - $sortprop = SMWPropertyValue::makeUserProperty($propkey); |
667 | | - if ($sortprop->isValid()) { |
668 | | - $extraproperties[] = new SMWSomeProperty($sortprop, new SMWThingDescription()); |
| 666 | + $sortprop = SMWPropertyValue::makeUserProperty( $propkey ); |
| 667 | + if ( $sortprop->isValid() ) { |
| 668 | + $extraproperties[] = new SMWSomeProperty( $sortprop, new SMWThingDescription() ); |
669 | 669 | } |
670 | 670 | } |
671 | 671 | } |
672 | 672 | } |
673 | 673 | // (2) compile according conditions and hack them into $qobj: |
674 | | - if (count($extraproperties) > 0) { |
675 | | - $desc = new SMWConjunction($extraproperties); |
676 | | - $newqid = $this->compileQueries($desc); |
| 674 | + if ( count( $extraproperties ) > 0 ) { |
| 675 | + $desc = new SMWConjunction( $extraproperties ); |
| 676 | + $newqid = $this->compileQueries( $desc ); |
677 | 677 | $newqobj = $this->m_queries[$newqid]; // this is always an SMW_SQL2_CONJUNCTION ... |
678 | | - foreach ($newqobj->components as $cid => $field) { // ... so just re-wire its dependencies |
| 678 | + foreach ( $newqobj->components as $cid => $field ) { // ... so just re-wire its dependencies |
679 | 679 | $qobj->components[$cid] = $qobj->joinfield; |
680 | | - $qobj->sortfields = array_merge($qobj->sortfields, $this->m_queries[$cid]->sortfields); |
| 680 | + $qobj->sortfields = array_merge( $qobj->sortfields, $this->m_queries[$cid]->sortfields ); |
681 | 681 | } |
682 | 682 | $this->m_queries[$qid] = $qobj; |
683 | 683 | } |
— | — | @@ -685,20 +685,20 @@ |
686 | 686 | /** |
687 | 687 | * Get a SQL option array for the given query and preprocessed query object at given id. |
688 | 688 | */ |
689 | | - protected function getSQLOptions($query,$rootid) { |
| 689 | + protected function getSQLOptions( $query, $rootid ) { |
690 | 690 | global $smwgQSortingSupport, $smwgQRandSortingSupport; |
691 | 691 | $result = array( 'LIMIT' => $query->getLimit() + 1, 'OFFSET' => $query->getOffset() ); |
692 | 692 | // build ORDER BY options using discovered sorting fields: |
693 | | - if ($smwgQSortingSupport) { |
| 693 | + if ( $smwgQSortingSupport ) { |
694 | 694 | $qobj = $this->m_queries[$rootid]; |
695 | | - foreach ($this->m_sortkeys as $propkey => $order) { |
696 | | - if (array_key_exists($propkey,$qobj->sortfields)) { // field successfully added |
697 | | - if (!array_key_exists('ORDER BY', $result)) { |
| 695 | + foreach ( $this->m_sortkeys as $propkey => $order ) { |
| 696 | + if ( array_key_exists( $propkey, $qobj->sortfields ) ) { // field successfully added |
| 697 | + if ( !array_key_exists( 'ORDER BY', $result ) ) { |
698 | 698 | $result['ORDER BY'] = ''; |
699 | 699 | } else { |
700 | 700 | $result['ORDER BY'] .= ', '; |
701 | 701 | } |
702 | | - if ('RAND()' == $order){ |
| 702 | + if ( 'RAND()' == $order ) { |
703 | 703 | $result['ORDER BY'] .= " $order "; |
704 | 704 | } else { |
705 | 705 | $result['ORDER BY'] .= $qobj->sortfields[$propkey] . " $order "; |
— | — | @@ -713,12 +713,11 @@ |
714 | 714 | /** |
715 | 715 | * After querying, make sure no temporary database tables are left. |
716 | 716 | */ |
717 | | - protected function cleanUp() {
|
718 | | - if ($this->m_qmode !== SMWQuery::MODE_DEBUG) { |
719 | | - foreach ($this->m_querylog as $table => $log) { |
720 | | - $this->m_dbs->query("DROP TEMPORARY TABLE " . $this->m_dbs->tableName($table), 'SMW::getQueryResult'); |
| 717 | + protected function cleanUp() { |
| 718 | + if ( $this->m_qmode !== SMWQuery::MODE_DEBUG ) { |
| 719 | + foreach ( $this->m_querylog as $table => $log ) { |
| 720 | + $this->m_dbs->query( "DROP TEMPORARY TABLE " . $this->m_dbs->tableName( $table ), 'SMW::getQueryResult' ); |
721 | 721 | } |
722 | 722 | } |
723 | 723 | } |
724 | | - |
725 | 724 | } |
Property changes on: trunk/extensions/SemanticNotifyMe/includes/storage/SMW_SQLStore2_QueriesNM.php |
___________________________________________________________________ |
Name: svn:eol-style |
726 | 725 | + native |
Index: trunk/extensions/SemanticNotifyMe/includes/storage/SMW_NMStorageSQL.php |
— | — | @@ -1,700 +1,697 @@ |
2 | | -<?php
|
3 | | -/**
|
4 | | - * This file provides the access to the MediaWiki SQL database tables that are
|
5 | | - * used by the NotifyMe extension.
|
6 | | - *
|
7 | | - * @author dch
|
8 | | - *
|
9 | | - */
|
10 | | -if ( !defined( 'MEDIAWIKI' ) ) die;
|
11 | | -global $smwgNMIP;
|
12 | | -require_once $smwgNMIP . '/includes/SMW_NMDBHelper.php';
|
13 | | -
|
14 | | -/**
|
15 | | - * This class encapsulates all methods that care about the database tables of
|
16 | | - * the NotifyMe extension.
|
17 | | - *
|
18 | | - */
|
19 | | -class NMStorageSQL {
|
20 | | -
|
21 | | - public function setup($verbose) {
|
22 | | -
|
23 | | - $db =& wfGetDB( DB_MASTER );
|
24 | | -
|
25 | | - SNMDBHelper::reportProgress("Setting up NotifyMe database ...\n",$verbose);
|
26 | | -
|
27 | | - extract( $db->tableNames('smw_nm_monitor', 'smw_nm_query', 'smw_nm_relations', 'smw_nm_rss') );
|
28 | | -
|
29 | | - // page_id, monitored page id
|
30 | | - SNMDBHelper::setupTable($smw_nm_monitor,
|
31 | | - array('notify_id' => 'INT(8) UNSIGNED NOT NULL',
|
32 | | - 'page_id' => 'INT(8) UNSIGNED NOT NULL'), $db, $verbose);
|
33 | | - SNMDBHelper::setupIndex($smw_nm_monitor, array('page_id'), $db);
|
34 | | - SNMDBHelper::setupTable($smw_nm_query,
|
35 | | - array('notify_id' => 'INT(8) UNSIGNED NOT NULL KEY AUTO_INCREMENT',
|
36 | | - 'user_id' => 'INT(8) UNSIGNED NOT NULL',
|
37 | | - 'delegate' => 'BLOB',
|
38 | | - 'name' => 'VARCHAR(255) binary NOT NULL',
|
39 | | - 'rep_all' => 'TINYINT(1) NOT NULL default \'1\'',
|
40 | | - 'show_all' => 'TINYINT(1) NOT NULL default \'0\'',
|
41 | | - 'query' => 'BLOB NOT NULL',
|
42 | | - 'nm_sql' => 'BLOB',
|
43 | | - 'nm_hierarchy' => 'BLOB',
|
44 | | - 'enable' => 'TINYINT(1) NOT NULL default \'0\''), $db, $verbose);
|
45 | | - SNMDBHelper::setupIndex($smw_nm_query, array('user_id'), $db);
|
46 | | - // page_id, related page / property id in notify query
|
47 | | - SNMDBHelper::setupTable($smw_nm_relations,
|
48 | | - array('notify_id' => 'INT(8) UNSIGNED NOT NULL',
|
49 | | - 'smw_id' => 'INT(8) UNSIGNED NOT NULL',
|
50 | | - // 0 category, 1 instance, 2 property
|
51 | | - 'type' => 'INT(8) UNSIGNED NOT NULL',
|
52 | | - 'subquery' => 'INT(8) UNSIGNED NOT NULL default \'0\''), $db, $verbose);
|
53 | | - SNMDBHelper::setupIndex($smw_nm_relations, array('smw_id', 'notify_id'), $db);
|
54 | | - SNMDBHelper::setupTable($smw_nm_rss,
|
55 | | - array('msg_id' => 'INT(8) UNSIGNED NOT NULL KEY AUTO_INCREMENT',
|
56 | | - 'mailed' => 'TINYINT(1) NOT NULL default \'0\'',
|
57 | | - 'user_id' => 'INT(8) UNSIGNED',
|
58 | | - 'notify_id' => 'INT(8) UNSIGNED',
|
59 | | - 'title' => 'VARCHAR(255) binary NOT NULL',
|
60 | | - 'link' => 'BLOB',
|
61 | | - 'notify' => 'BLOB NOT NULL',
|
62 | | - 'timestamp' => 'VARCHAR(14) binary NOT NULL'), $db, $verbose);
|
63 | | - SNMDBHelper::setupIndex($smw_nm_rss, array('user_id'), $db);
|
64 | | -
|
65 | | - SNMDBHelper::reportProgress("... done!\n",$verbose);
|
66 | | -
|
67 | | - }
|
68 | | -
|
69 | | - public function addNotifyQuery($user_id, $querystring, $name, $rep_all, $show_all, $delegate) {
|
70 | | - $fname = 'NotifyMe::addNotifyQuery';
|
71 | | - wfProfileIn( $fname );
|
72 | | -
|
73 | | - $dbw =& wfGetDB( DB_MASTER );
|
74 | | - $notify_id = $dbw->nextSequenceValue('nmquery_notify_id_seq');
|
75 | | - if($dbw->insert( 'smw_nm_query', array(
|
76 | | - 'notify_id' => $notify_id,
|
77 | | - 'user_id' => $user_id,
|
78 | | - 'query' => $querystring,
|
79 | | - 'name' => $name,
|
80 | | - 'rep_all' => $rep_all,
|
81 | | - 'show_all' => $show_all,
|
82 | | - 'delegate' => $delegate), $fname))
|
83 | | - {
|
84 | | - $notify_id = $dbw->insertId();
|
85 | | - } else {
|
86 | | - $notify_id = 0;
|
87 | | - }
|
88 | | - wfProfileOut( $fname );
|
89 | | - return $notify_id;
|
90 | | - }
|
91 | | - public function removeNotifyQuery($notify_ids){
|
92 | | - $fname = 'NotifyMe::delNotify';
|
93 | | - wfProfileIn( $fname );
|
94 | | - $db =& wfGetDB( DB_MASTER );
|
95 | | - $db->delete( $db->tableName('smw_nm_monitor'), array('notify_id'=>$notify_ids), $fname);
|
96 | | - $db->delete( $db->tableName('smw_nm_relations'), array('notify_id'=>$notify_ids), $fname);
|
97 | | - $db->delete( $db->tableName('smw_nm_query'), array('notify_id'=>$notify_ids), $fname);
|
98 | | - wfProfileOut( $fname );
|
99 | | - return true;
|
100 | | - }
|
101 | | - public function addNotifyMonitor($add_monitor){
|
102 | | - $fname = 'NotifyMe::addNotifyMonitor';
|
103 | | - wfProfileIn( $fname );
|
104 | | -
|
105 | | - $db =& wfGetDB( DB_MASTER );
|
106 | | - $res = $db->insert( 'smw_nm_monitor', $add_monitor, $fname);
|
107 | | - wfProfileOut( $fname );
|
108 | | - return $res;
|
109 | | - }
|
110 | | - public function removeNotifyMonitor($remove_monitored){
|
111 | | - $fname = 'NotifyMe::addNotifyMonitor';
|
112 | | - wfProfileIn( $fname );
|
113 | | -
|
114 | | - $db =& wfGetDB( DB_MASTER );
|
115 | | - foreach($remove_monitored as $monitor) {
|
116 | | - $db->delete( $db->tableName('smw_nm_monitor'), array('notify_id'=>$monitor['notify_id'], 'page_id'=>$monitor['page_id']), $fname);
|
117 | | - }
|
118 | | - wfProfileOut( $fname );
|
119 | | - return $res;
|
120 | | - }
|
121 | | - public function addNotifyRelations($notify_id, $rels, $subquery=0){
|
122 | | - $fname = 'NotifyMe::addNotifyRelations';
|
123 | | - wfProfileIn( $fname );
|
124 | | -
|
125 | | - foreach($rels as $i=>$vi) {
|
126 | | - foreach($rels as $j=>$vj) {
|
127 | | - if($i != $j && $vi['namespace']==$vj['namespace'] && $vi['title']==$vj['title']) {
|
128 | | - unset($rels[$i]);
|
129 | | - break;
|
130 | | - }
|
131 | | - }
|
132 | | - }
|
133 | | -
|
134 | | - $dbw =& wfGetDB( DB_MASTER );
|
135 | | - $relations = array();
|
136 | | - $new_rel = false;
|
137 | | - foreach($rels as $smw){
|
138 | | - $res = $dbw->select( $dbw->tableName('smw_ids'),
|
139 | | - 'smw_id',
|
140 | | - // array( 'smw_namespace' => $smw['namespace'], 'smw_title' => $smw['title']),
|
141 | | - 'smw_namespace='.$smw['namespace'].' AND smw_title='.$dbw->addQuotes($smw['title']),
|
142 | | - 'NotifyMe::getRelatedSmwId');
|
143 | | - $rel_smw_id = 0;
|
144 | | - if($dbw->numRows( $res ) > 0) {
|
145 | | - $rel_smw_id = $dbw->fetchObject($res)->smw_id;
|
146 | | - $dbw->freeResult($res);
|
147 | | - } else {
|
148 | | - $dbw->freeResult($res);
|
149 | | - return false;
|
150 | | - }
|
151 | | -
|
152 | | - if($rel_smw_id > 0) {
|
153 | | - $new_rel = true;
|
154 | | - $relations[] = array(
|
155 | | - 'notify_id' => $notify_id,
|
156 | | - 'smw_id' => $rel_smw_id,
|
157 | | - // $type: 0 category, 1 instance, 2 property
|
158 | | - 'type' => (($smw['namespace']==NS_CATEGORY)?0:(($smw['namespace']==SMW_NS_PROPERTY)?2:1)),
|
159 | | - 'subquery' => $subquery);
|
160 | | - }
|
161 | | - }
|
162 | | - if($new_rel) {
|
163 | | - $dbw->insert( 'smw_nm_relations', $relations, $fname);
|
164 | | - }
|
165 | | - wfProfileOut( $fname );
|
166 | | - return true;
|
167 | | - }
|
168 | | - public function getNotifications($user_id){
|
169 | | - $fname = 'NotifyMe::getNotifications';
|
170 | | - wfProfileIn( $fname );
|
171 | | -
|
172 | | - $result = array();
|
173 | | -
|
174 | | - $db = wfGetDB( DB_SLAVE );
|
175 | | - $res = $db->select( $db->tableName('smw_nm_query'),
|
176 | | - array('notify_id', 'delegate', 'name', 'query', 'enable', 'rep_all', 'show_all'),
|
177 | | - array('user_id'=>$user_id), $fname, array('ORDER BY' => 'notify_id'));
|
178 | | - if($db->numRows( $res ) > 0) {
|
179 | | - while($row = $db->fetchObject($res)) {
|
180 | | - $result[] = array('notify_id'=>$row->notify_id,
|
181 | | - 'delegate'=>$row->delegate,
|
182 | | - 'name'=>$row->name,
|
183 | | - 'query'=>$row->query,
|
184 | | - 'enable'=>$row->enable,
|
185 | | - 'rep_all'=>$row->rep_all,
|
186 | | - 'show_all'=>$row->show_all);
|
187 | | - }
|
188 | | - }
|
189 | | - $db->freeResult($res);
|
190 | | - wfProfileOut( $fname );
|
191 | | - return $result;
|
192 | | - }
|
193 | | - public function getNotifyMe($notify_ids){
|
194 | | - $fname = 'NotifyMe::getNotifyMe';
|
195 | | - wfProfileIn( $fname );
|
196 | | -
|
197 | | - $result = array();
|
198 | | -
|
199 | | - $db = wfGetDB( DB_SLAVE );
|
200 | | - $res = $db->select( $db->tableName('smw_nm_query'),
|
201 | | - array('notify_id', 'name', 'query', 'show_all'),
|
202 | | - array('notify_id'=>$notify_ids), $fname);
|
203 | | - if($db->numRows( $res ) > 0) {
|
204 | | - while($row = $db->fetchObject($res)) {
|
205 | | - $result[$row->notify_id] = array('query'=>$row->query,
|
206 | | - 'name'=>$row->name,
|
207 | | - 'show_all'=>$row->show_all);
|
208 | | - }
|
209 | | - }
|
210 | | - $db->freeResult($res);
|
211 | | - wfProfileOut( $fname );
|
212 | | - return $result;
|
213 | | - }
|
214 | | - public function getAllNotifications(){
|
215 | | - $fname = 'NotifyMe::getAllNotifications';
|
216 | | - wfProfileIn( $fname );
|
217 | | -
|
218 | | - $result = array();
|
219 | | -
|
220 | | - $db = wfGetDB( DB_SLAVE );
|
221 | | - $res = $db->select( $db->tableName('smw_nm_query'),
|
222 | | - array('notify_id', 'delegate', 'name', 'query', 'enable', 'rep_all', 'show_all'), '',
|
223 | | - $fname, array('ORDER BY' => 'notify_id'));
|
224 | | - if($db->numRows( $res ) > 0) {
|
225 | | - while($row = $db->fetchObject($res)) {
|
226 | | - $result[] = array('notify_id'=>$row->notify_id,
|
227 | | - 'delegate'=>$row->delegate,
|
228 | | - 'name'=>$row->name,
|
229 | | - 'query'=>$row->query,
|
230 | | - 'enable'=>$row->enable,
|
231 | | - 'rep_all'=>$row->rep_all,
|
232 | | - 'show_all'=>$row->show_all);
|
233 | | - }
|
234 | | - }
|
235 | | - $db->freeResult($res);
|
236 | | - wfProfileOut( $fname );
|
237 | | - return $result;
|
238 | | - }
|
239 | | - public function disableNotifyState($notify_id){
|
240 | | - $fname = 'NotifyMe::disableState';
|
241 | | - wfProfileIn( $fname );
|
242 | | - $db =& wfGetDB( DB_MASTER );
|
243 | | - $db->delete( $db->tableName('smw_nm_monitor'), array('notify_id'=>$notify_id), $fname);
|
244 | | - $db->delete( $db->tableName('smw_nm_relations'), array('notify_id'=>$notify_id), $fname);
|
245 | | -
|
246 | | - $this->updateNotifyState($notify_id, 0);
|
247 | | - wfProfileOut( $fname );
|
248 | | - return true;
|
249 | | - }
|
250 | | - public function updateNotifyState($notify_id, $state) {
|
251 | | - $fname = 'NotifyMe::updateNotifyState';
|
252 | | - wfProfileIn( $fname );
|
253 | | -
|
254 | | - $dbw =& wfGetDB( DB_MASTER );
|
255 | | - $dbw->update( 'smw_nm_query', array('enable' => $state), array('notify_id'=>$notify_id), $fname);
|
256 | | - wfProfileOut( $fname );
|
257 | | - return true;
|
258 | | - }
|
259 | | - public function updateDelegate($notify_id, $delegate){
|
260 | | - $fname = 'NotifyMe::updateDelegate';
|
261 | | - wfProfileIn( $fname );
|
262 | | - $dbw =& wfGetDB( DB_MASTER );
|
263 | | - $dbw->update( 'smw_nm_query', array('delegate' => $delegate), array('notify_id'=>$notify_id), $fname);
|
264 | | - wfProfileOut( $fname );
|
265 | | - return true;
|
266 | | - }
|
267 | | - public function updateNotifyReportAll($notify_id, $rep_all) {
|
268 | | - $fname = 'NotifyMe::updateNotifyReportAll';
|
269 | | - wfProfileIn( $fname );
|
270 | | -
|
271 | | - $dbw =& wfGetDB( DB_MASTER );
|
272 | | - $dbw->update( 'smw_nm_query', array('rep_all' => $rep_all), array('notify_id'=>$notify_id), $fname);
|
273 | | - wfProfileOut( $fname );
|
274 | | - return true;
|
275 | | - }
|
276 | | - public function updateNotifyShowAll($notify_id, $show_all) {
|
277 | | - $fname = 'NotifyMe::updateNotifyShowAll';
|
278 | | - wfProfileIn( $fname );
|
279 | | -
|
280 | | - $dbw =& wfGetDB( DB_MASTER );
|
281 | | - $dbw->update( 'smw_nm_query', array('show_all' => $show_all), array('notify_id'=>$notify_id), $fname);
|
282 | | - wfProfileOut( $fname );
|
283 | | - return true;
|
284 | | - }
|
285 | | -
|
286 | | - public function lookupSmwId($namespace, $title) {
|
287 | | - $fname = 'NotifyMe::lookupSmwId';
|
288 | | - wfProfileIn( $fname );
|
289 | | -
|
290 | | - $result = 0;
|
291 | | - $db = wfGetDB( DB_SLAVE );
|
292 | | - $res = $db->selectRow( 'smw_ids', 'smw_id', array( 'smw_namespace' => $namespace, 'smw_title' => $title ), $fname );
|
293 | | -
|
294 | | - if($res) $result = $res->smw_id;
|
295 | | - wfProfileOut( $fname );
|
296 | | - return $result;
|
297 | | - }
|
298 | | - public function getMonitoredNotifications($page_id) {
|
299 | | - $fname = 'NotifyMe::getMonitoredNotifications';
|
300 | | - wfProfileIn( $fname );
|
301 | | -
|
302 | | - $result = array();
|
303 | | -
|
304 | | - $db = wfGetDB( DB_SLAVE );
|
305 | | -
|
306 | | - $res = $db->select( array($db->tableName('smw_nm_query').' q', $db->tableName('smw_nm_monitor').' m'),
|
307 | | - array('q.user_id', 'q.notify_id', 'q.delegate', 'q.name', 'q.rep_all'),
|
308 | | - 'm.page_id='.$page_id.' and m.notify_id=q.notify_id', $fname);
|
309 | | - if($db->numRows( $res ) > 0) {
|
310 | | - while($row = $db->fetchObject($res)) {
|
311 | | - $ds = explode(',', $row->delegate);
|
312 | | - $delegated = false;
|
313 | | - foreach($ds as $delegate) {
|
314 | | - $u = User::newFromName(trim($delegate));
|
315 | | - if($u==null) continue;
|
316 | | - $id = $u->getId();
|
317 | | - if($id > 0) {
|
318 | | - $result[$id][$row->notify_id] = array('name'=>$row->name, 'rep_all'=>$row->rep_all);
|
319 | | - $delegated = true;
|
320 | | - }
|
321 | | - }
|
322 | | - if(!$delegated) {
|
323 | | - $result[$row->user_id][$row->notify_id] = array('name'=>$row->name, 'rep_all'=>$row->rep_all);
|
324 | | - }
|
325 | | - }
|
326 | | - }
|
327 | | - $db->freeResult($res);
|
328 | | -
|
329 | | - wfProfileOut( $fname );
|
330 | | - return $result;
|
331 | | - }
|
332 | | - public function getMonitoredNotificationsDetail($page_id) {
|
333 | | - $fname = 'NotifyMe::getMonitoredNotificationsDetail';
|
334 | | - wfProfileIn( $fname );
|
335 | | -
|
336 | | - $result = array();
|
337 | | -
|
338 | | - $notifies = $this->getMonitoredNotifications($page_id);
|
339 | | -
|
340 | | - $db = wfGetDB( DB_SLAVE );
|
341 | | -
|
342 | | - foreach ($notifies as $user_id=>$notify) {
|
343 | | - foreach($notify as $notify_id=>$notify_detail) {
|
344 | | - if($notify_detail['rep_all']==1) {
|
345 | | - $result[$user_id]['rep_all'][$notify_id] = $notify_detail['name'];
|
346 | | - } else {
|
347 | | - $res = $db->select( $db->tableName('smw_nm_relations'), array('smw_id', 'type'), "notify_id=$notify_id AND subquery=0", $fname);
|
348 | | - if($db->numRows( $res ) > 0) {
|
349 | | - while($row = $db->fetchObject($res)) {
|
350 | | - $result[$user_id]['semantic'][SMWNotifyProcessor::toInfoId($row->type,0,$row->smw_id)][$notify_id] = $notify_detail['name'];
|
351 | | - }
|
352 | | - }
|
353 | | - $db->freeResult($res);
|
354 | | - }
|
355 | | - }
|
356 | | - }
|
357 | | -
|
358 | | - wfProfileOut( $fname );
|
359 | | - return $result;
|
360 | | - }
|
361 | | - public function getPossibleQuery($info) {
|
362 | | - $cnt = count($info);
|
363 | | - if($cnt == 0) {
|
364 | | - return null;
|
365 | | - }
|
366 | | - $fname = 'NotifyMe::getPossibleQuery';
|
367 | | - wfProfileIn( $fname );
|
368 | | -
|
369 | | - $first = true;
|
370 | | - foreach($info as $key=>$value) {
|
371 | | - if($first) {
|
372 | | - $first = false;
|
373 | | - } else {
|
374 | | - $cond .= "OR ";
|
375 | | - }
|
376 | | - $i = SMWNotifyProcessor::getInfoFromId($key);
|
377 | | - $cond .= "(smw_id=$i[attr_id] AND type=$i[type]) ";
|
378 | | - }
|
379 | | -
|
380 | | - $db =& wfGetDB( DB_SLAVE );
|
381 | | - $result = array(0=>array(), 1=>array());
|
382 | | - extract( $db->tableNames('smw_nm_query', 'smw_nm_relations') );
|
383 | | - $res = $db->query("SELECT q.notify_id, q.name, q.user_id, q.delegate, q.nm_sql, q.nm_hierarchy, c1.subquery FROM (".
|
384 | | - "SELECT count(*) cnt, notify_id, subquery FROM $smw_nm_relations ".
|
385 | | - "WHERE $cond GROUP BY notify_id, subquery".
|
386 | | - ") c1 INNER JOIN (".
|
387 | | - "SELECT count(*) cnt, notify_id, subquery FROM $smw_nm_relations ".
|
388 | | - "WHERE type<>1 GROUP BY notify_id, subquery".
|
389 | | - ") c2 ON c1.notify_id=c2.notify_id AND c1.subquery=c2.subquery AND c1.cnt=c2.cnt ".
|
390 | | - "LEFT JOIN $smw_nm_query q ON q.notify_id = c1.notify_id WHERE c1.cnt<=$cnt", $fname);
|
391 | | - if($db->numRows( $res ) > 0) {
|
392 | | - while($row = $db->fetchObject($res)) {
|
393 | | - $ds = explode(',', $row->delegate);
|
394 | | - $delegated = false;
|
395 | | - foreach($ds as $delegate) {
|
396 | | - $u = User::newFromName(trim($delegate));
|
397 | | - if($u==null) continue;
|
398 | | - $id = $u->getId();
|
399 | | - if($id > 0) {
|
400 | | - $result[$row->subquery>0?1:0][$row->notify_id] = array('user_id'=>$id, 'name'=>$row->name, 'sql'=>$row->nm_sql, 'hierarchy'=>$row->nm_hierarchy);
|
401 | | - $delegated = true;
|
402 | | - }
|
403 | | - }
|
404 | | - if(!$delegated) {
|
405 | | - $result[$row->subquery>0?1:0][$row->notify_id] = array('user_id'=>$row->user_id, 'name'=>$row->name, 'sql'=>$row->nm_sql, 'hierarchy'=>$row->nm_hierarchy);
|
406 | | - }
|
407 | | - }
|
408 | | - }
|
409 | | - $db->freeResult($res);
|
410 | | - wfProfileOut( $fname );
|
411 | | - return $result;
|
412 | | - }
|
413 | | - public function getMonitoredQuery($page_id) {
|
414 | | - $fname = 'NotifyMe::getMonitoredQuery';
|
415 | | - wfProfileIn( $fname );
|
416 | | -
|
417 | | - $db =& wfGetDB( DB_SLAVE );
|
418 | | - $res = $db->select( array($db->tableName('smw_nm_monitor').' m', $db->tableName('smw_nm_query').' q'),
|
419 | | - array('q.notify_id, q.delegate, q.name, q.user_id, q.nm_sql, q.nm_hierarchy'),
|
420 | | - "m.notify_id=q.notify_id AND m.page_id=$page_id", $fname);
|
421 | | - if($db->numRows( $res ) > 0) {
|
422 | | - while($row = $db->fetchObject($res)) {
|
423 | | - $ds = explode(',', $row->delegate);
|
424 | | - $delegated = false;
|
425 | | - foreach($ds as $delegate) {
|
426 | | - $u = User::newFromName(trim($delegate));
|
427 | | - if($u==null) continue;
|
428 | | - $id = $u->getId();
|
429 | | - if($id > 0) {
|
430 | | - $result[$row->notify_id] = array('user_id'=>$id, 'name'=>$row->name, 'sql'=>$row->nm_sql, 'hierarchy'=>$row->nm_hierarchy);
|
431 | | - $delegated = true;
|
432 | | - }
|
433 | | - }
|
434 | | - if(!$delegated) {
|
435 | | - $result[$row->notify_id] = array('user_id'=>$row->user_id, 'name'=>$row->name, 'sql'=>$row->nm_sql, 'hierarchy'=>$row->nm_hierarchy);
|
436 | | - }
|
437 | | - }
|
438 | | - }
|
439 | | - $db->freeResult($res);
|
440 | | - wfProfileOut( $fname );
|
441 | | - return $result;
|
442 | | - }
|
443 | | - public function updateNMSql($notify_id, $sql, $tmp_hierarchy) {
|
444 | | - $fname = 'NotifyMe::updateNMSql';
|
445 | | - wfProfileIn( $fname );
|
446 | | -
|
447 | | - $dbw =& wfGetDB( DB_MASTER );
|
448 | | - $dbw->update( 'smw_nm_query', array('nm_sql' => $sql, 'nm_hierarchy' => $tmp_hierarchy), array('notify_id'=>$notify_id), $fname);
|
449 | | - wfProfileOut( $fname );
|
450 | | - return true;
|
451 | | - }
|
452 | | - public function getNotifyInMainQuery($page_id, $notify_id, $sql, $hierarchy, &$match, &$monitoring) {
|
453 | | - $fname = 'NotifyMe::getNotifyInMainQuery';
|
454 | | - wfProfileIn( $fname );
|
455 | | -
|
456 | | - $db =& wfGetDB( DB_SLAVE );
|
457 | | -
|
458 | | - $tmp_tables = array();
|
459 | | - if($hierarchy != '') {
|
460 | | - $_hierarchies = array();
|
461 | | - foreach(explode(";",$hierarchy) as $attrs) {
|
462 | | - $part = explode(":",$attrs,3);
|
463 | | - $tablename = $db->tableName($part[0]);
|
464 | | - $depth = intval($part[1]);
|
465 | | - $values = $part[2];
|
466 | | -
|
467 | | - $tmp_tables[] = $tablename;
|
468 | | -
|
469 | | - $db->query( "CREATE TEMPORARY TABLE $tablename ( id INT UNSIGNED NOT NULL KEY) TYPE=MEMORY", 'SMW::executeQueries' );
|
470 | | - if (array_key_exists($values, $_hierarchies)) { // just copy known result
|
471 | | - $db->query("INSERT INTO $tablename (id) SELECT id FROM " . $_hierarchies[$values], 'SMW::executeQueries');
|
472 | | - } else {
|
473 | | - $tmpnew = 'smw_new';
|
474 | | - $tmpres = 'smw_res';
|
475 | | - $db->query( "CREATE TEMPORARY TABLE $tmpnew ( id INT UNSIGNED ) TYPE=MEMORY", 'SMW::executeQueries' );
|
476 | | - $db->query( "CREATE TEMPORARY TABLE $tmpres ( id INT UNSIGNED ) TYPE=MEMORY", 'SMW::executeQueries' );
|
477 | | - $db->query("INSERT IGNORE INTO $tablename (id) VALUES $values", 'SMW::executeQueries');
|
478 | | - $db->query("INSERT IGNORE INTO $tmpnew (id) VALUES $values", 'SMW::executeQueries');
|
479 | | - $smw_subs2 = $db->tableName('smw_subs2');
|
480 | | - for ($i=0; $i<$depth; $i++) {
|
481 | | - $db->query("INSERT INTO $tmpres (id) SELECT s_id FROM $smw_subs2, $tmpnew WHERE o_id=id", 'SMW::executeQueries');
|
482 | | - if ($db->affectedRows() == 0) { // no change, exit loop
|
483 | | - break;
|
484 | | - }
|
485 | | - $db->query("INSERT IGNORE INTO $tablename (id) SELECT $tmpres.id FROM $tmpres", 'SMW::executeQueries');
|
486 | | - if ($db->affectedRows() == 0) { // no change, exit loop
|
487 | | - break;
|
488 | | - }
|
489 | | - $db->query('TRUNCATE TABLE ' . $tmpnew, 'SMW::executeQueries'); // empty "new" table
|
490 | | - $tmpname = $tmpnew;
|
491 | | - $tmpnew = $tmpres;
|
492 | | - $tmpres = $tmpname;
|
493 | | - }
|
494 | | - $_hierarchies[$values] = $tablename;
|
495 | | - $db->query('DROP TEMPORARY TABLE smw_new', 'SMW::executeQueries');
|
496 | | - $db->query('DROP TEMPORARY TABLE smw_res', 'SMW::executeQueries');
|
497 | | - }
|
498 | | - }
|
499 | | - }
|
500 | | -
|
501 | | - $sql = "SELECT p.page_id FROM " . $db->tableName('page') . " AS p INNER JOIN ($sql) AS s ON s.t=p.page_title AND s.ns=p.page_namespace WHERE p.page_id=$page_id";
|
502 | | - $res = $db->query($sql, $fname);
|
503 | | - $match = ($db->numRows( $res ) > 0);
|
504 | | - $db->freeResult($res);
|
505 | | -
|
506 | | - foreach ($tmp_tables as $tablename) {
|
507 | | - $db->query("DROP TEMPORARY TABLE $tablename", 'SMW::getQueryResult');
|
508 | | - }
|
509 | | -
|
510 | | - $monitoring = ($db->selectRow( 'smw_nm_monitor', array( 'page_id' ),
|
511 | | - array( 'page_id' => $page_id, 'notify_id' => $notify_id ), $fname ) != false);
|
512 | | -
|
513 | | - wfProfileOut( $fname );
|
514 | | - return true;
|
515 | | - }
|
516 | | - public function getNotifyInSubquery($notify_id, $sql, $hierarchy) {
|
517 | | - $fname = 'NotifyMe::getNotifyInSubquery';
|
518 | | - wfProfileIn( $fname );
|
519 | | -
|
520 | | - $result = array('monitoring'=>array(), 'match'=>array());
|
521 | | -
|
522 | | - $db =& wfGetDB( DB_SLAVE );
|
523 | | -
|
524 | | - $tmp_tables = array();
|
525 | | - if($hierarchy != '') {
|
526 | | - $_hierarchies = array();
|
527 | | - foreach(explode(";",$hierarchy) as $attrs) {
|
528 | | - $part = explode(":",$attrs,3);
|
529 | | - $tablename = $db->tableName($part[0]);
|
530 | | - $depth = intval($part[1]);
|
531 | | - $values = $part[2];
|
532 | | -
|
533 | | - $tmp_tables[] = $tablename;
|
534 | | -
|
535 | | - $db->query( "CREATE TEMPORARY TABLE $tablename ( id INT UNSIGNED NOT NULL KEY) TYPE=MEMORY", 'SMW::executeQueries' );
|
536 | | - if (array_key_exists($values, $_hierarchies)) { // just copy known result
|
537 | | - $db->query("INSERT INTO $tablename (id) SELECT id FROM " . $_hierarchies[$values], 'SMW::executeQueries');
|
538 | | - } else {
|
539 | | - $tmpnew = 'smw_new';
|
540 | | - $tmpres = 'smw_res';
|
541 | | - $db->query( "CREATE TEMPORARY TABLE $tmpnew ( id INT UNSIGNED ) TYPE=MEMORY", 'SMW::executeQueries' );
|
542 | | - $db->query( "CREATE TEMPORARY TABLE $tmpres ( id INT UNSIGNED ) TYPE=MEMORY", 'SMW::executeQueries' );
|
543 | | - $db->query("INSERT IGNORE INTO $tablename (id) VALUES $values", 'SMW::executeQueries');
|
544 | | - $db->query("INSERT IGNORE INTO $tmpnew (id) VALUES $values", 'SMW::executeQueries');
|
545 | | - $smw_subs2 = $db->tableName('smw_subs2');
|
546 | | - for ($i=0; $i<$depth; $i++) {
|
547 | | - $db->query("INSERT INTO $tmpres (id) SELECT s_id FROM $smw_subs2, $tmpnew WHERE o_id=id", 'SMW::executeQueries');
|
548 | | - if ($db->affectedRows() == 0) { // no change, exit loop
|
549 | | - break;
|
550 | | - }
|
551 | | - $db->query("INSERT IGNORE INTO $tablename (id) SELECT $tmpres.id FROM $tmpres", 'SMW::executeQueries');
|
552 | | - if ($db->affectedRows() == 0) { // no change, exit loop
|
553 | | - break;
|
554 | | - }
|
555 | | - $db->query('TRUNCATE TABLE ' . $tmpnew, 'SMW::executeQueries'); // empty "new" table
|
556 | | - $tmpname = $tmpnew;
|
557 | | - $tmpnew = $tmpres;
|
558 | | - $tmpres = $tmpname;
|
559 | | - }
|
560 | | - $_hierarchies[$values] = $tablename;
|
561 | | - $db->query('DROP TEMPORARY TABLE smw_new', 'SMW::executeQueries');
|
562 | | - $db->query('DROP TEMPORARY TABLE smw_res', 'SMW::executeQueries');
|
563 | | - }
|
564 | | - }
|
565 | | - }
|
566 | | -
|
567 | | - $res = $db->query("SELECT p.page_id FROM " . $db->tableName('page') . " AS p INNER JOIN ($sql) AS s ON s.t=p.page_title AND s.ns=p.page_namespace", $fname);
|
568 | | - if($db->numRows( $res ) > 0) {
|
569 | | - while($row = $db->fetchObject($res)) {
|
570 | | - $result['match'][] = $row->page_id;
|
571 | | - }
|
572 | | - }
|
573 | | - $db->freeResult($res);
|
574 | | -
|
575 | | - foreach ($tmp_tables as $tablename) {
|
576 | | - $db->query("DROP TEMPORARY TABLE $tablename", 'SMW::getQueryResult');
|
577 | | - }
|
578 | | -
|
579 | | - $res = $db->select( $db->tableName('smw_nm_monitor'), array( 'page_id' ), array( 'notify_id' => $notify_id ), $fname );
|
580 | | - if($db->numRows( $res ) > 0) {
|
581 | | - while($row = $db->fetchObject($res)) {
|
582 | | - $result['monitoring'][] = $row->page_id;
|
583 | | - }
|
584 | | - }
|
585 | | - $db->freeResult($res);
|
586 | | -
|
587 | | - wfProfileOut( $fname );
|
588 | | - return $result;
|
589 | | - }
|
590 | | - public function getUserInfo($user_id) {
|
591 | | - $fname = 'NotifyMe::getUserInfo';
|
592 | | - wfProfileIn( $fname );
|
593 | | -
|
594 | | - $db = wfGetDB( DB_SLAVE );
|
595 | | - $result = $db->selectRow( 'user', array( 'user_name', 'user_real_name', 'user_email', 'user_options' ), array( 'user_id' => $user_id ), $fname );
|
596 | | -
|
597 | | - wfProfileOut( $fname );
|
598 | | - return $result;
|
599 | | - }
|
600 | | - public function getPageTitle($page_id) {
|
601 | | - $db =& wfGetDB( DB_SLAVE );
|
602 | | - return $db->selectRow('page', 'page_title', array('page_id' => $page_id));
|
603 | | - }
|
604 | | - public function addNotifyRSS($type, $id, $title, $msg, $link = NULL) {
|
605 | | - $fname = 'NotifyMe::addNotifyRSS';
|
606 | | - wfProfileIn( $fname );
|
607 | | - $db =& wfGetDB( DB_MASTER );
|
608 | | -
|
609 | | - $rid = $db->nextSequenceValue('nmrss_msg_id_seq');
|
610 | | - $values = array('msg_id' => $rid,
|
611 | | - 'title' => $title,
|
612 | | - 'notify' => $msg,
|
613 | | - 'timestamp' => $db->timestamp());
|
614 | | - if($type == "uid") {
|
615 | | - $values['user_id'] = $id;
|
616 | | - } else {
|
617 | | - $values['notify_id'] = $id;
|
618 | | - }
|
619 | | - if($link !== NULL) {
|
620 | | - $values['link'] = $link;
|
621 | | - }
|
622 | | -
|
623 | | - $db->insert( 'smw_nm_rss', $values, $fname);
|
624 | | - $id = $db->insertId();
|
625 | | -
|
626 | | - wfProfileOut( $fname );
|
627 | | - return $id;
|
628 | | - }
|
629 | | - public function getNotifyRSS($type, $id, $limit) {
|
630 | | - $fname = 'NotifyMe::getNotifyRSS';
|
631 | | - wfProfileIn( $fname );
|
632 | | - $db =& wfGetDB( DB_SLAVE );
|
633 | | - $result = array();
|
634 | | - if($type == "uid") {
|
635 | | - $ids = array('user_id'=>$id);
|
636 | | - } else {
|
637 | | - $ids = array('notify_id'=>$id);
|
638 | | - }
|
639 | | - $res = $db->select( $db->tableName('smw_nm_rss'), array('title', 'link', 'notify', 'timestamp'), $ids, $fname, array('ORDER BY' => 'timestamp DESC', 'LIMIT'=>$limit));
|
640 | | - if($db->numRows( $res ) > 0) {
|
641 | | - while($row = $db->fetchObject($res)) {
|
642 | | - $result[] = array('title' => $row->title, 'link'=>$row->link, 'notify'=>$row->notify, 'timestamp'=>$row->timestamp);
|
643 | | - }
|
644 | | - }
|
645 | | - $db->freeResult($res);
|
646 | | - wfProfileOut( $fname );
|
647 | | - return $result;
|
648 | | - }
|
649 | | - public function getUnmailedNMMessages() {
|
650 | | - $fname = 'NotifyMe::getUnmailedNMMessages';
|
651 | | - wfProfileIn( $fname );
|
652 | | - $db =& wfGetDB( DB_MASTER );
|
653 | | - $smw_nm_rss = $db->tableName('smw_nm_rss');
|
654 | | - $result = array();
|
655 | | - $res = $db->select( $smw_nm_rss,
|
656 | | - array('user_id', 'title', 'notify', 'timestamp'),
|
657 | | - array('mailed'=>'0'), $fname);
|
658 | | - if($db->numRows( $res ) > 0) {
|
659 | | - while($row = $db->fetchObject($res)) {
|
660 | | - $result[] = array('user_id' => $row->user_id, 'title' => $row->title, 'notify'=>$row->notify, 'timestamp'=>$row->timestamp);
|
661 | | - }
|
662 | | - }
|
663 | | - $db->freeResult($res);
|
664 | | - $db->update($smw_nm_rss, array('mailed' => '1'), array('mailed' => '0'), $fname);
|
665 | | - wfProfileOut( $fname );
|
666 | | - return $result;
|
667 | | - }
|
668 | | -
|
669 | | - public function getGroupedUsers($groups) {
|
670 | | - $fname = 'NotifyMe::getGroupedUsers';
|
671 | | - wfProfileIn( $fname );
|
672 | | - $db =& wfGetDB( DB_SLAVE );
|
673 | | - extract( $db->tableNames('user_groups', 'user') );
|
674 | | - $result = array();
|
675 | | - $res = $db->query( "SELECT u.user_name FROM $user u".
|
676 | | - ($groups ? " LEFT JOIN $user_groups g ON u.user_id = g.ug_user
|
677 | | - WHERE g.ug_group IN ('".join("','", $groups)."')
|
678 | | - GROUP BY user_name":""), $fname);
|
679 | | - if($db->numRows( $res ) > 0) {
|
680 | | - while($row = $db->fetchObject($res)) {
|
681 | | - $result[] = $row->user_name;
|
682 | | - }
|
683 | | - }
|
684 | | - $db->freeResult($res);
|
685 | | - wfProfileOut( $fname );
|
686 | | - return $result;
|
687 | | - }
|
688 | | -
|
689 | | - function getNMQueryResult(SMWQuery $query) {
|
690 | | - wfProfileIn('SMWSQLStore2::getNMQueryResult (SMW)');
|
691 | | - global $smwgNMIP;
|
692 | | - include_once("$smwgNMIP/includes/storage/SMW_SQLStore2_QueriesNM.php");
|
693 | | - $qe = new SMWSQLStore2QueryEngineNM(smwfGetStore(), wfGetDB( DB_SLAVE ));
|
694 | | - $result = $qe->getQueryResult($query);
|
695 | | - wfProfileOut('SMWSQLStore2::getNMQueryResult (SMW)');
|
696 | | - return $result;
|
697 | | - }
|
698 | | -
|
699 | | -}
|
700 | | -
|
701 | | -?> |
\ No newline at end of file |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * This file provides the access to the MediaWiki SQL database tables that are |
| 5 | + * used by the NotifyMe extension. |
| 6 | + * |
| 7 | + * @author dch |
| 8 | + * |
| 9 | + */ |
| 10 | +if ( !defined( 'MEDIAWIKI' ) ) die; |
| 11 | +global $smwgNMIP; |
| 12 | +require_once $smwgNMIP . '/includes/SMW_NMDBHelper.php'; |
| 13 | + |
| 14 | +/** |
| 15 | + * This class encapsulates all methods that care about the database tables of |
| 16 | + * the NotifyMe extension. |
| 17 | + * |
| 18 | + */ |
| 19 | +class NMStorageSQL { |
| 20 | + |
| 21 | + public function setup( $verbose ) { |
| 22 | + |
| 23 | + $db =& wfGetDB( DB_MASTER ); |
| 24 | + |
| 25 | + SNMDBHelper::reportProgress( "Setting up NotifyMe database ...\n", $verbose ); |
| 26 | + |
| 27 | + extract( $db->tableNames( 'smw_nm_monitor', 'smw_nm_query', 'smw_nm_relations', 'smw_nm_rss' ) ); |
| 28 | + |
| 29 | + // page_id, monitored page id |
| 30 | + SNMDBHelper::setupTable( $smw_nm_monitor, |
| 31 | + array( 'notify_id' => 'INT(8) UNSIGNED NOT NULL', |
| 32 | + 'page_id' => 'INT(8) UNSIGNED NOT NULL' ), $db, $verbose ); |
| 33 | + SNMDBHelper::setupIndex( $smw_nm_monitor, array( 'page_id' ), $db ); |
| 34 | + SNMDBHelper::setupTable( $smw_nm_query, |
| 35 | + array( 'notify_id' => 'INT(8) UNSIGNED NOT NULL KEY AUTO_INCREMENT', |
| 36 | + 'user_id' => 'INT(8) UNSIGNED NOT NULL', |
| 37 | + 'delegate' => 'BLOB', |
| 38 | + 'name' => 'VARCHAR(255) binary NOT NULL', |
| 39 | + 'rep_all' => 'TINYINT(1) NOT NULL default \'1\'', |
| 40 | + 'show_all' => 'TINYINT(1) NOT NULL default \'0\'', |
| 41 | + 'query' => 'BLOB NOT NULL', |
| 42 | + 'nm_sql' => 'BLOB', |
| 43 | + 'nm_hierarchy' => 'BLOB', |
| 44 | + 'enable' => 'TINYINT(1) NOT NULL default \'0\'' ), $db, $verbose ); |
| 45 | + SNMDBHelper::setupIndex( $smw_nm_query, array( 'user_id' ), $db ); |
| 46 | + // page_id, related page / property id in notify query |
| 47 | + SNMDBHelper::setupTable( $smw_nm_relations, |
| 48 | + array( 'notify_id' => 'INT(8) UNSIGNED NOT NULL', |
| 49 | + 'smw_id' => 'INT(8) UNSIGNED NOT NULL', |
| 50 | + // 0 category, 1 instance, 2 property |
| 51 | + 'type' => 'INT(8) UNSIGNED NOT NULL', |
| 52 | + 'subquery' => 'INT(8) UNSIGNED NOT NULL default \'0\'' ), $db, $verbose ); |
| 53 | + SNMDBHelper::setupIndex( $smw_nm_relations, array( 'smw_id', 'notify_id' ), $db ); |
| 54 | + SNMDBHelper::setupTable( $smw_nm_rss, |
| 55 | + array( 'msg_id' => 'INT(8) UNSIGNED NOT NULL KEY AUTO_INCREMENT', |
| 56 | + 'mailed' => 'TINYINT(1) NOT NULL default \'0\'', |
| 57 | + 'user_id' => 'INT(8) UNSIGNED', |
| 58 | + 'notify_id' => 'INT(8) UNSIGNED', |
| 59 | + 'title' => 'VARCHAR(255) binary NOT NULL', |
| 60 | + 'link' => 'BLOB', |
| 61 | + 'notify' => 'BLOB NOT NULL', |
| 62 | + 'timestamp' => 'VARCHAR(14) binary NOT NULL' ), $db, $verbose ); |
| 63 | + SNMDBHelper::setupIndex( $smw_nm_rss, array( 'user_id' ), $db ); |
| 64 | + |
| 65 | + SNMDBHelper::reportProgress( "... done!\n", $verbose ); |
| 66 | + |
| 67 | + } |
| 68 | + |
| 69 | + public function addNotifyQuery( $user_id, $querystring, $name, $rep_all, $show_all, $delegate ) { |
| 70 | + $fname = 'NotifyMe::addNotifyQuery'; |
| 71 | + wfProfileIn( $fname ); |
| 72 | + |
| 73 | + $dbw =& wfGetDB( DB_MASTER ); |
| 74 | + $notify_id = $dbw->nextSequenceValue( 'nmquery_notify_id_seq' ); |
| 75 | + if ( $dbw->insert( 'smw_nm_query', array( |
| 76 | + 'notify_id' => $notify_id, |
| 77 | + 'user_id' => $user_id, |
| 78 | + 'query' => $querystring, |
| 79 | + 'name' => $name, |
| 80 | + 'rep_all' => $rep_all, |
| 81 | + 'show_all' => $show_all, |
| 82 | + 'delegate' => $delegate ), $fname ) ) |
| 83 | + { |
| 84 | + $notify_id = $dbw->insertId(); |
| 85 | + } else { |
| 86 | + $notify_id = 0; |
| 87 | + } |
| 88 | + wfProfileOut( $fname ); |
| 89 | + return $notify_id; |
| 90 | + } |
| 91 | + public function removeNotifyQuery( $notify_ids ) { |
| 92 | + $fname = 'NotifyMe::delNotify'; |
| 93 | + wfProfileIn( $fname ); |
| 94 | + $db =& wfGetDB( DB_MASTER ); |
| 95 | + $db->delete( $db->tableName( 'smw_nm_monitor' ), array( 'notify_id' => $notify_ids ), $fname ); |
| 96 | + $db->delete( $db->tableName( 'smw_nm_relations' ), array( 'notify_id' => $notify_ids ), $fname ); |
| 97 | + $db->delete( $db->tableName( 'smw_nm_query' ), array( 'notify_id' => $notify_ids ), $fname ); |
| 98 | + wfProfileOut( $fname ); |
| 99 | + return true; |
| 100 | + } |
| 101 | + public function addNotifyMonitor( $add_monitor ) { |
| 102 | + $fname = 'NotifyMe::addNotifyMonitor'; |
| 103 | + wfProfileIn( $fname ); |
| 104 | + |
| 105 | + $db =& wfGetDB( DB_MASTER ); |
| 106 | + $res = $db->insert( 'smw_nm_monitor', $add_monitor, $fname ); |
| 107 | + wfProfileOut( $fname ); |
| 108 | + return $res; |
| 109 | + } |
| 110 | + public function removeNotifyMonitor( $remove_monitored ) { |
| 111 | + $fname = 'NotifyMe::addNotifyMonitor'; |
| 112 | + wfProfileIn( $fname ); |
| 113 | + |
| 114 | + $db =& wfGetDB( DB_MASTER ); |
| 115 | + foreach ( $remove_monitored as $monitor ) { |
| 116 | + $db->delete( $db->tableName( 'smw_nm_monitor' ), array( 'notify_id' => $monitor['notify_id'], 'page_id' => $monitor['page_id'] ), $fname ); |
| 117 | + } |
| 118 | + wfProfileOut( $fname ); |
| 119 | + return $res; |
| 120 | + } |
| 121 | + public function addNotifyRelations( $notify_id, $rels, $subquery = 0 ) { |
| 122 | + $fname = 'NotifyMe::addNotifyRelations'; |
| 123 | + wfProfileIn( $fname ); |
| 124 | + |
| 125 | + foreach ( $rels as $i => $vi ) { |
| 126 | + foreach ( $rels as $j => $vj ) { |
| 127 | + if ( $i != $j && $vi['namespace'] == $vj['namespace'] && $vi['title'] == $vj['title'] ) { |
| 128 | + unset( $rels[$i] ); |
| 129 | + break; |
| 130 | + } |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + $dbw =& wfGetDB( DB_MASTER ); |
| 135 | + $relations = array(); |
| 136 | + $new_rel = false; |
| 137 | + foreach ( $rels as $smw ) { |
| 138 | + $res = $dbw->select( $dbw->tableName( 'smw_ids' ), |
| 139 | + 'smw_id', |
| 140 | + // array( 'smw_namespace' => $smw['namespace'], 'smw_title' => $smw['title']), |
| 141 | + 'smw_namespace=' . $smw['namespace'] . ' AND smw_title=' . $dbw->addQuotes( $smw['title'] ), |
| 142 | + 'NotifyMe::getRelatedSmwId' ); |
| 143 | + $rel_smw_id = 0; |
| 144 | + if ( $dbw->numRows( $res ) > 0 ) { |
| 145 | + $rel_smw_id = $dbw->fetchObject( $res )->smw_id; |
| 146 | + $dbw->freeResult( $res ); |
| 147 | + } else { |
| 148 | + $dbw->freeResult( $res ); |
| 149 | + return false; |
| 150 | + } |
| 151 | + |
| 152 | + if ( $rel_smw_id > 0 ) { |
| 153 | + $new_rel = true; |
| 154 | + $relations[] = array( |
| 155 | + 'notify_id' => $notify_id, |
| 156 | + 'smw_id' => $rel_smw_id, |
| 157 | + // $type: 0 category, 1 instance, 2 property |
| 158 | + 'type' => ( ( $smw['namespace'] == NS_CATEGORY ) ? 0:( ( $smw['namespace'] == SMW_NS_PROPERTY ) ? 2:1 ) ), |
| 159 | + 'subquery' => $subquery ); |
| 160 | + } |
| 161 | + } |
| 162 | + if ( $new_rel ) { |
| 163 | + $dbw->insert( 'smw_nm_relations', $relations, $fname ); |
| 164 | + } |
| 165 | + wfProfileOut( $fname ); |
| 166 | + return true; |
| 167 | + } |
| 168 | + public function getNotifications( $user_id ) { |
| 169 | + $fname = 'NotifyMe::getNotifications'; |
| 170 | + wfProfileIn( $fname ); |
| 171 | + |
| 172 | + $result = array(); |
| 173 | + |
| 174 | + $db = wfGetDB( DB_SLAVE ); |
| 175 | + $res = $db->select( $db->tableName( 'smw_nm_query' ), |
| 176 | + array( 'notify_id', 'delegate', 'name', 'query', 'enable', 'rep_all', 'show_all' ), |
| 177 | + array( 'user_id' => $user_id ), $fname, array( 'ORDER BY' => 'notify_id' ) ); |
| 178 | + if ( $db->numRows( $res ) > 0 ) { |
| 179 | + while ( $row = $db->fetchObject( $res ) ) { |
| 180 | + $result[] = array( 'notify_id' => $row->notify_id, |
| 181 | + 'delegate' => $row->delegate, |
| 182 | + 'name' => $row->name, |
| 183 | + 'query' => $row->query, |
| 184 | + 'enable' => $row->enable, |
| 185 | + 'rep_all' => $row->rep_all, |
| 186 | + 'show_all' => $row->show_all ); |
| 187 | + } |
| 188 | + } |
| 189 | + $db->freeResult( $res ); |
| 190 | + wfProfileOut( $fname ); |
| 191 | + return $result; |
| 192 | + } |
| 193 | + public function getNotifyMe( $notify_ids ) { |
| 194 | + $fname = 'NotifyMe::getNotifyMe'; |
| 195 | + wfProfileIn( $fname ); |
| 196 | + |
| 197 | + $result = array(); |
| 198 | + |
| 199 | + $db = wfGetDB( DB_SLAVE ); |
| 200 | + $res = $db->select( $db->tableName( 'smw_nm_query' ), |
| 201 | + array( 'notify_id', 'name', 'query', 'show_all' ), |
| 202 | + array( 'notify_id' => $notify_ids ), $fname ); |
| 203 | + if ( $db->numRows( $res ) > 0 ) { |
| 204 | + while ( $row = $db->fetchObject( $res ) ) { |
| 205 | + $result[$row->notify_id] = array( 'query' => $row->query, |
| 206 | + 'name' => $row->name, |
| 207 | + 'show_all' => $row->show_all ); |
| 208 | + } |
| 209 | + } |
| 210 | + $db->freeResult( $res ); |
| 211 | + wfProfileOut( $fname ); |
| 212 | + return $result; |
| 213 | + } |
| 214 | + public function getAllNotifications() { |
| 215 | + $fname = 'NotifyMe::getAllNotifications'; |
| 216 | + wfProfileIn( $fname ); |
| 217 | + |
| 218 | + $result = array(); |
| 219 | + |
| 220 | + $db = wfGetDB( DB_SLAVE ); |
| 221 | + $res = $db->select( $db->tableName( 'smw_nm_query' ), |
| 222 | + array( 'notify_id', 'delegate', 'name', 'query', 'enable', 'rep_all', 'show_all' ), '', |
| 223 | + $fname, array( 'ORDER BY' => 'notify_id' ) ); |
| 224 | + if ( $db->numRows( $res ) > 0 ) { |
| 225 | + while ( $row = $db->fetchObject( $res ) ) { |
| 226 | + $result[] = array( 'notify_id' => $row->notify_id, |
| 227 | + 'delegate' => $row->delegate, |
| 228 | + 'name' => $row->name, |
| 229 | + 'query' => $row->query, |
| 230 | + 'enable' => $row->enable, |
| 231 | + 'rep_all' => $row->rep_all, |
| 232 | + 'show_all' => $row->show_all ); |
| 233 | + } |
| 234 | + } |
| 235 | + $db->freeResult( $res ); |
| 236 | + wfProfileOut( $fname ); |
| 237 | + return $result; |
| 238 | + } |
| 239 | + public function disableNotifyState( $notify_id ) { |
| 240 | + $fname = 'NotifyMe::disableState'; |
| 241 | + wfProfileIn( $fname ); |
| 242 | + $db =& wfGetDB( DB_MASTER ); |
| 243 | + $db->delete( $db->tableName( 'smw_nm_monitor' ), array( 'notify_id' => $notify_id ), $fname ); |
| 244 | + $db->delete( $db->tableName( 'smw_nm_relations' ), array( 'notify_id' => $notify_id ), $fname ); |
| 245 | + |
| 246 | + $this->updateNotifyState( $notify_id, 0 ); |
| 247 | + wfProfileOut( $fname ); |
| 248 | + return true; |
| 249 | + } |
| 250 | + public function updateNotifyState( $notify_id, $state ) { |
| 251 | + $fname = 'NotifyMe::updateNotifyState'; |
| 252 | + wfProfileIn( $fname ); |
| 253 | + |
| 254 | + $dbw =& wfGetDB( DB_MASTER ); |
| 255 | + $dbw->update( 'smw_nm_query', array( 'enable' => $state ), array( 'notify_id' => $notify_id ), $fname ); |
| 256 | + wfProfileOut( $fname ); |
| 257 | + return true; |
| 258 | + } |
| 259 | + public function updateDelegate( $notify_id, $delegate ) { |
| 260 | + $fname = 'NotifyMe::updateDelegate'; |
| 261 | + wfProfileIn( $fname ); |
| 262 | + $dbw =& wfGetDB( DB_MASTER ); |
| 263 | + $dbw->update( 'smw_nm_query', array( 'delegate' => $delegate ), array( 'notify_id' => $notify_id ), $fname ); |
| 264 | + wfProfileOut( $fname ); |
| 265 | + return true; |
| 266 | + } |
| 267 | + public function updateNotifyReportAll( $notify_id, $rep_all ) { |
| 268 | + $fname = 'NotifyMe::updateNotifyReportAll'; |
| 269 | + wfProfileIn( $fname ); |
| 270 | + |
| 271 | + $dbw =& wfGetDB( DB_MASTER ); |
| 272 | + $dbw->update( 'smw_nm_query', array( 'rep_all' => $rep_all ), array( 'notify_id' => $notify_id ), $fname ); |
| 273 | + wfProfileOut( $fname ); |
| 274 | + return true; |
| 275 | + } |
| 276 | + public function updateNotifyShowAll( $notify_id, $show_all ) { |
| 277 | + $fname = 'NotifyMe::updateNotifyShowAll'; |
| 278 | + wfProfileIn( $fname ); |
| 279 | + |
| 280 | + $dbw =& wfGetDB( DB_MASTER ); |
| 281 | + $dbw->update( 'smw_nm_query', array( 'show_all' => $show_all ), array( 'notify_id' => $notify_id ), $fname ); |
| 282 | + wfProfileOut( $fname ); |
| 283 | + return true; |
| 284 | + } |
| 285 | + |
| 286 | + public function lookupSmwId( $namespace, $title ) { |
| 287 | + $fname = 'NotifyMe::lookupSmwId'; |
| 288 | + wfProfileIn( $fname ); |
| 289 | + |
| 290 | + $result = 0; |
| 291 | + $db = wfGetDB( DB_SLAVE ); |
| 292 | + $res = $db->selectRow( 'smw_ids', 'smw_id', array( 'smw_namespace' => $namespace, 'smw_title' => $title ), $fname ); |
| 293 | + |
| 294 | + if ( $res ) $result = $res->smw_id; |
| 295 | + wfProfileOut( $fname ); |
| 296 | + return $result; |
| 297 | + } |
| 298 | + public function getMonitoredNotifications( $page_id ) { |
| 299 | + $fname = 'NotifyMe::getMonitoredNotifications'; |
| 300 | + wfProfileIn( $fname ); |
| 301 | + |
| 302 | + $result = array(); |
| 303 | + |
| 304 | + $db = wfGetDB( DB_SLAVE ); |
| 305 | + |
| 306 | + $res = $db->select( array( $db->tableName( 'smw_nm_query' ) . ' q', $db->tableName( 'smw_nm_monitor' ) . ' m' ), |
| 307 | + array( 'q.user_id', 'q.notify_id', 'q.delegate', 'q.name', 'q.rep_all' ), |
| 308 | + 'm.page_id=' . $page_id . ' and m.notify_id=q.notify_id', $fname ); |
| 309 | + if ( $db->numRows( $res ) > 0 ) { |
| 310 | + while ( $row = $db->fetchObject( $res ) ) { |
| 311 | + $ds = explode( ',', $row->delegate ); |
| 312 | + $delegated = false; |
| 313 | + foreach ( $ds as $delegate ) { |
| 314 | + $u = User::newFromName( trim( $delegate ) ); |
| 315 | + if ( $u == null ) continue; |
| 316 | + $id = $u->getId(); |
| 317 | + if ( $id > 0 ) { |
| 318 | + $result[$id][$row->notify_id] = array( 'name' => $row->name, 'rep_all' => $row->rep_all ); |
| 319 | + $delegated = true; |
| 320 | + } |
| 321 | + } |
| 322 | + if ( !$delegated ) { |
| 323 | + $result[$row->user_id][$row->notify_id] = array( 'name' => $row->name, 'rep_all' => $row->rep_all ); |
| 324 | + } |
| 325 | + } |
| 326 | + } |
| 327 | + $db->freeResult( $res ); |
| 328 | + |
| 329 | + wfProfileOut( $fname ); |
| 330 | + return $result; |
| 331 | + } |
| 332 | + public function getMonitoredNotificationsDetail( $page_id ) { |
| 333 | + $fname = 'NotifyMe::getMonitoredNotificationsDetail'; |
| 334 | + wfProfileIn( $fname ); |
| 335 | + |
| 336 | + $result = array(); |
| 337 | + |
| 338 | + $notifies = $this->getMonitoredNotifications( $page_id ); |
| 339 | + |
| 340 | + $db = wfGetDB( DB_SLAVE ); |
| 341 | + |
| 342 | + foreach ( $notifies as $user_id => $notify ) { |
| 343 | + foreach ( $notify as $notify_id => $notify_detail ) { |
| 344 | + if ( $notify_detail['rep_all'] == 1 ) { |
| 345 | + $result[$user_id]['rep_all'][$notify_id] = $notify_detail['name']; |
| 346 | + } else { |
| 347 | + $res = $db->select( $db->tableName( 'smw_nm_relations' ), array( 'smw_id', 'type' ), "notify_id=$notify_id AND subquery=0", $fname ); |
| 348 | + if ( $db->numRows( $res ) > 0 ) { |
| 349 | + while ( $row = $db->fetchObject( $res ) ) { |
| 350 | + $result[$user_id]['semantic'][SMWNotifyProcessor::toInfoId( $row->type, 0, $row->smw_id )][$notify_id] = $notify_detail['name']; |
| 351 | + } |
| 352 | + } |
| 353 | + $db->freeResult( $res ); |
| 354 | + } |
| 355 | + } |
| 356 | + } |
| 357 | + |
| 358 | + wfProfileOut( $fname ); |
| 359 | + return $result; |
| 360 | + } |
| 361 | + public function getPossibleQuery( $info ) { |
| 362 | + $cnt = count( $info ); |
| 363 | + if ( $cnt == 0 ) { |
| 364 | + return null; |
| 365 | + } |
| 366 | + $fname = 'NotifyMe::getPossibleQuery'; |
| 367 | + wfProfileIn( $fname ); |
| 368 | + |
| 369 | + $first = true; |
| 370 | + foreach ( $info as $key => $value ) { |
| 371 | + if ( $first ) { |
| 372 | + $first = false; |
| 373 | + } else { |
| 374 | + $cond .= "OR "; |
| 375 | + } |
| 376 | + $i = SMWNotifyProcessor::getInfoFromId( $key ); |
| 377 | + $cond .= "(smw_id=$i[attr_id] AND type=$i[type]) "; |
| 378 | + } |
| 379 | + |
| 380 | + $db =& wfGetDB( DB_SLAVE ); |
| 381 | + $result = array( 0 => array(), 1 => array() ); |
| 382 | + extract( $db->tableNames( 'smw_nm_query', 'smw_nm_relations' ) ); |
| 383 | + $res = $db->query( "SELECT q.notify_id, q.name, q.user_id, q.delegate, q.nm_sql, q.nm_hierarchy, c1.subquery FROM (" . |
| 384 | + "SELECT count(*) cnt, notify_id, subquery FROM $smw_nm_relations " . |
| 385 | + "WHERE $cond GROUP BY notify_id, subquery" . |
| 386 | + ") c1 INNER JOIN (" . |
| 387 | + "SELECT count(*) cnt, notify_id, subquery FROM $smw_nm_relations " . |
| 388 | + "WHERE type<>1 GROUP BY notify_id, subquery" . |
| 389 | + ") c2 ON c1.notify_id=c2.notify_id AND c1.subquery=c2.subquery AND c1.cnt=c2.cnt " . |
| 390 | + "LEFT JOIN $smw_nm_query q ON q.notify_id = c1.notify_id WHERE c1.cnt<=$cnt", $fname ); |
| 391 | + if ( $db->numRows( $res ) > 0 ) { |
| 392 | + while ( $row = $db->fetchObject( $res ) ) { |
| 393 | + $ds = explode( ',', $row->delegate ); |
| 394 | + $delegated = false; |
| 395 | + foreach ( $ds as $delegate ) { |
| 396 | + $u = User::newFromName( trim( $delegate ) ); |
| 397 | + if ( $u == null ) continue; |
| 398 | + $id = $u->getId(); |
| 399 | + if ( $id > 0 ) { |
| 400 | + $result[$row->subquery > 0 ? 1:0][$row->notify_id] = array( 'user_id' => $id, 'name' => $row->name, 'sql' => $row->nm_sql, 'hierarchy' => $row->nm_hierarchy ); |
| 401 | + $delegated = true; |
| 402 | + } |
| 403 | + } |
| 404 | + if ( !$delegated ) { |
| 405 | + $result[$row->subquery > 0 ? 1:0][$row->notify_id] = array( 'user_id' => $row->user_id, 'name' => $row->name, 'sql' => $row->nm_sql, 'hierarchy' => $row->nm_hierarchy ); |
| 406 | + } |
| 407 | + } |
| 408 | + } |
| 409 | + $db->freeResult( $res ); |
| 410 | + wfProfileOut( $fname ); |
| 411 | + return $result; |
| 412 | + } |
| 413 | + public function getMonitoredQuery( $page_id ) { |
| 414 | + $fname = 'NotifyMe::getMonitoredQuery'; |
| 415 | + wfProfileIn( $fname ); |
| 416 | + |
| 417 | + $db =& wfGetDB( DB_SLAVE ); |
| 418 | + $res = $db->select( array( $db->tableName( 'smw_nm_monitor' ) . ' m', $db->tableName( 'smw_nm_query' ) . ' q' ), |
| 419 | + array( 'q.notify_id, q.delegate, q.name, q.user_id, q.nm_sql, q.nm_hierarchy' ), |
| 420 | + "m.notify_id=q.notify_id AND m.page_id=$page_id", $fname ); |
| 421 | + if ( $db->numRows( $res ) > 0 ) { |
| 422 | + while ( $row = $db->fetchObject( $res ) ) { |
| 423 | + $ds = explode( ',', $row->delegate ); |
| 424 | + $delegated = false; |
| 425 | + foreach ( $ds as $delegate ) { |
| 426 | + $u = User::newFromName( trim( $delegate ) ); |
| 427 | + if ( $u == null ) continue; |
| 428 | + $id = $u->getId(); |
| 429 | + if ( $id > 0 ) { |
| 430 | + $result[$row->notify_id] = array( 'user_id' => $id, 'name' => $row->name, 'sql' => $row->nm_sql, 'hierarchy' => $row->nm_hierarchy ); |
| 431 | + $delegated = true; |
| 432 | + } |
| 433 | + } |
| 434 | + if ( !$delegated ) { |
| 435 | + $result[$row->notify_id] = array( 'user_id' => $row->user_id, 'name' => $row->name, 'sql' => $row->nm_sql, 'hierarchy' => $row->nm_hierarchy ); |
| 436 | + } |
| 437 | + } |
| 438 | + } |
| 439 | + $db->freeResult( $res ); |
| 440 | + wfProfileOut( $fname ); |
| 441 | + return $result; |
| 442 | + } |
| 443 | + public function updateNMSql( $notify_id, $sql, $tmp_hierarchy ) { |
| 444 | + $fname = 'NotifyMe::updateNMSql'; |
| 445 | + wfProfileIn( $fname ); |
| 446 | + |
| 447 | + $dbw =& wfGetDB( DB_MASTER ); |
| 448 | + $dbw->update( 'smw_nm_query', array( 'nm_sql' => $sql, 'nm_hierarchy' => $tmp_hierarchy ), array( 'notify_id' => $notify_id ), $fname ); |
| 449 | + wfProfileOut( $fname ); |
| 450 | + return true; |
| 451 | + } |
| 452 | + public function getNotifyInMainQuery( $page_id, $notify_id, $sql, $hierarchy, &$match, &$monitoring ) { |
| 453 | + $fname = 'NotifyMe::getNotifyInMainQuery'; |
| 454 | + wfProfileIn( $fname ); |
| 455 | + |
| 456 | + $db =& wfGetDB( DB_SLAVE ); |
| 457 | + |
| 458 | + $tmp_tables = array(); |
| 459 | + if ( $hierarchy != '' ) { |
| 460 | + $_hierarchies = array(); |
| 461 | + foreach ( explode( ";", $hierarchy ) as $attrs ) { |
| 462 | + $part = explode( ":", $attrs, 3 ); |
| 463 | + $tablename = $db->tableName( $part[0] ); |
| 464 | + $depth = intval( $part[1] ); |
| 465 | + $values = $part[2]; |
| 466 | + |
| 467 | + $tmp_tables[] = $tablename; |
| 468 | + |
| 469 | + $db->query( "CREATE TEMPORARY TABLE $tablename ( id INT UNSIGNED NOT NULL KEY) TYPE=MEMORY", 'SMW::executeQueries' ); |
| 470 | + if ( array_key_exists( $values, $_hierarchies ) ) { // just copy known result |
| 471 | + $db->query( "INSERT INTO $tablename (id) SELECT id FROM " . $_hierarchies[$values], 'SMW::executeQueries' ); |
| 472 | + } else { |
| 473 | + $tmpnew = 'smw_new'; |
| 474 | + $tmpres = 'smw_res'; |
| 475 | + $db->query( "CREATE TEMPORARY TABLE $tmpnew ( id INT UNSIGNED ) TYPE=MEMORY", 'SMW::executeQueries' ); |
| 476 | + $db->query( "CREATE TEMPORARY TABLE $tmpres ( id INT UNSIGNED ) TYPE=MEMORY", 'SMW::executeQueries' ); |
| 477 | + $db->query( "INSERT IGNORE INTO $tablename (id) VALUES $values", 'SMW::executeQueries' ); |
| 478 | + $db->query( "INSERT IGNORE INTO $tmpnew (id) VALUES $values", 'SMW::executeQueries' ); |
| 479 | + $smw_subs2 = $db->tableName( 'smw_subs2' ); |
| 480 | + for ( $i = 0; $i < $depth; $i++ ) { |
| 481 | + $db->query( "INSERT INTO $tmpres (id) SELECT s_id FROM $smw_subs2, $tmpnew WHERE o_id=id", 'SMW::executeQueries' ); |
| 482 | + if ( $db->affectedRows() == 0 ) { // no change, exit loop |
| 483 | + break; |
| 484 | + } |
| 485 | + $db->query( "INSERT IGNORE INTO $tablename (id) SELECT $tmpres.id FROM $tmpres", 'SMW::executeQueries' ); |
| 486 | + if ( $db->affectedRows() == 0 ) { // no change, exit loop |
| 487 | + break; |
| 488 | + } |
| 489 | + $db->query( 'TRUNCATE TABLE ' . $tmpnew, 'SMW::executeQueries' ); // empty "new" table |
| 490 | + $tmpname = $tmpnew; |
| 491 | + $tmpnew = $tmpres; |
| 492 | + $tmpres = $tmpname; |
| 493 | + } |
| 494 | + $_hierarchies[$values] = $tablename; |
| 495 | + $db->query( 'DROP TEMPORARY TABLE smw_new', 'SMW::executeQueries' ); |
| 496 | + $db->query( 'DROP TEMPORARY TABLE smw_res', 'SMW::executeQueries' ); |
| 497 | + } |
| 498 | + } |
| 499 | + } |
| 500 | + |
| 501 | + $sql = "SELECT p.page_id FROM " . $db->tableName( 'page' ) . " AS p INNER JOIN ($sql) AS s ON s.t=p.page_title AND s.ns=p.page_namespace WHERE p.page_id=$page_id"; |
| 502 | + $res = $db->query( $sql, $fname ); |
| 503 | + $match = ( $db->numRows( $res ) > 0 ); |
| 504 | + $db->freeResult( $res ); |
| 505 | + |
| 506 | + foreach ( $tmp_tables as $tablename ) { |
| 507 | + $db->query( "DROP TEMPORARY TABLE $tablename", 'SMW::getQueryResult' ); |
| 508 | + } |
| 509 | + |
| 510 | + $monitoring = ( $db->selectRow( 'smw_nm_monitor', array( 'page_id' ), |
| 511 | + array( 'page_id' => $page_id, 'notify_id' => $notify_id ), $fname ) != false ); |
| 512 | + |
| 513 | + wfProfileOut( $fname ); |
| 514 | + return true; |
| 515 | + } |
| 516 | + public function getNotifyInSubquery( $notify_id, $sql, $hierarchy ) { |
| 517 | + $fname = 'NotifyMe::getNotifyInSubquery'; |
| 518 | + wfProfileIn( $fname ); |
| 519 | + |
| 520 | + $result = array( 'monitoring' => array(), 'match' => array() ); |
| 521 | + |
| 522 | + $db =& wfGetDB( DB_SLAVE ); |
| 523 | + |
| 524 | + $tmp_tables = array(); |
| 525 | + if ( $hierarchy != '' ) { |
| 526 | + $_hierarchies = array(); |
| 527 | + foreach ( explode( ";", $hierarchy ) as $attrs ) { |
| 528 | + $part = explode( ":", $attrs, 3 ); |
| 529 | + $tablename = $db->tableName( $part[0] ); |
| 530 | + $depth = intval( $part[1] ); |
| 531 | + $values = $part[2]; |
| 532 | + |
| 533 | + $tmp_tables[] = $tablename; |
| 534 | + |
| 535 | + $db->query( "CREATE TEMPORARY TABLE $tablename ( id INT UNSIGNED NOT NULL KEY) TYPE=MEMORY", 'SMW::executeQueries' ); |
| 536 | + if ( array_key_exists( $values, $_hierarchies ) ) { // just copy known result |
| 537 | + $db->query( "INSERT INTO $tablename (id) SELECT id FROM " . $_hierarchies[$values], 'SMW::executeQueries' ); |
| 538 | + } else { |
| 539 | + $tmpnew = 'smw_new'; |
| 540 | + $tmpres = 'smw_res'; |
| 541 | + $db->query( "CREATE TEMPORARY TABLE $tmpnew ( id INT UNSIGNED ) TYPE=MEMORY", 'SMW::executeQueries' ); |
| 542 | + $db->query( "CREATE TEMPORARY TABLE $tmpres ( id INT UNSIGNED ) TYPE=MEMORY", 'SMW::executeQueries' ); |
| 543 | + $db->query( "INSERT IGNORE INTO $tablename (id) VALUES $values", 'SMW::executeQueries' ); |
| 544 | + $db->query( "INSERT IGNORE INTO $tmpnew (id) VALUES $values", 'SMW::executeQueries' ); |
| 545 | + $smw_subs2 = $db->tableName( 'smw_subs2' ); |
| 546 | + for ( $i = 0; $i < $depth; $i++ ) { |
| 547 | + $db->query( "INSERT INTO $tmpres (id) SELECT s_id FROM $smw_subs2, $tmpnew WHERE o_id=id", 'SMW::executeQueries' ); |
| 548 | + if ( $db->affectedRows() == 0 ) { // no change, exit loop |
| 549 | + break; |
| 550 | + } |
| 551 | + $db->query( "INSERT IGNORE INTO $tablename (id) SELECT $tmpres.id FROM $tmpres", 'SMW::executeQueries' ); |
| 552 | + if ( $db->affectedRows() == 0 ) { // no change, exit loop |
| 553 | + break; |
| 554 | + } |
| 555 | + $db->query( 'TRUNCATE TABLE ' . $tmpnew, 'SMW::executeQueries' ); // empty "new" table |
| 556 | + $tmpname = $tmpnew; |
| 557 | + $tmpnew = $tmpres; |
| 558 | + $tmpres = $tmpname; |
| 559 | + } |
| 560 | + $_hierarchies[$values] = $tablename; |
| 561 | + $db->query( 'DROP TEMPORARY TABLE smw_new', 'SMW::executeQueries' ); |
| 562 | + $db->query( 'DROP TEMPORARY TABLE smw_res', 'SMW::executeQueries' ); |
| 563 | + } |
| 564 | + } |
| 565 | + } |
| 566 | + |
| 567 | + $res = $db->query( "SELECT p.page_id FROM " . $db->tableName( 'page' ) . " AS p INNER JOIN ($sql) AS s ON s.t=p.page_title AND s.ns=p.page_namespace", $fname ); |
| 568 | + if ( $db->numRows( $res ) > 0 ) { |
| 569 | + while ( $row = $db->fetchObject( $res ) ) { |
| 570 | + $result['match'][] = $row->page_id; |
| 571 | + } |
| 572 | + } |
| 573 | + $db->freeResult( $res ); |
| 574 | + |
| 575 | + foreach ( $tmp_tables as $tablename ) { |
| 576 | + $db->query( "DROP TEMPORARY TABLE $tablename", 'SMW::getQueryResult' ); |
| 577 | + } |
| 578 | + |
| 579 | + $res = $db->select( $db->tableName( 'smw_nm_monitor' ), array( 'page_id' ), array( 'notify_id' => $notify_id ), $fname ); |
| 580 | + if ( $db->numRows( $res ) > 0 ) { |
| 581 | + while ( $row = $db->fetchObject( $res ) ) { |
| 582 | + $result['monitoring'][] = $row->page_id; |
| 583 | + } |
| 584 | + } |
| 585 | + $db->freeResult( $res ); |
| 586 | + |
| 587 | + wfProfileOut( $fname ); |
| 588 | + return $result; |
| 589 | + } |
| 590 | + public function getUserInfo( $user_id ) { |
| 591 | + $fname = 'NotifyMe::getUserInfo'; |
| 592 | + wfProfileIn( $fname ); |
| 593 | + |
| 594 | + $db = wfGetDB( DB_SLAVE ); |
| 595 | + $result = $db->selectRow( 'user', array( 'user_name', 'user_real_name', 'user_email', 'user_options' ), array( 'user_id' => $user_id ), $fname ); |
| 596 | + |
| 597 | + wfProfileOut( $fname ); |
| 598 | + return $result; |
| 599 | + } |
| 600 | + public function getPageTitle( $page_id ) { |
| 601 | + $db =& wfGetDB( DB_SLAVE ); |
| 602 | + return $db->selectRow( 'page', 'page_title', array( 'page_id' => $page_id ) ); |
| 603 | + } |
| 604 | + public function addNotifyRSS( $type, $id, $title, $msg, $link = NULL ) { |
| 605 | + $fname = 'NotifyMe::addNotifyRSS'; |
| 606 | + wfProfileIn( $fname ); |
| 607 | + $db =& wfGetDB( DB_MASTER ); |
| 608 | + |
| 609 | + $rid = $db->nextSequenceValue( 'nmrss_msg_id_seq' ); |
| 610 | + $values = array( 'msg_id' => $rid, |
| 611 | + 'title' => $title, |
| 612 | + 'notify' => $msg, |
| 613 | + 'timestamp' => $db->timestamp() ); |
| 614 | + if ( $type == "uid" ) { |
| 615 | + $values['user_id'] = $id; |
| 616 | + } else { |
| 617 | + $values['notify_id'] = $id; |
| 618 | + } |
| 619 | + if ( $link !== NULL ) { |
| 620 | + $values['link'] = $link; |
| 621 | + } |
| 622 | + |
| 623 | + $db->insert( 'smw_nm_rss', $values, $fname ); |
| 624 | + $id = $db->insertId(); |
| 625 | + |
| 626 | + wfProfileOut( $fname ); |
| 627 | + return $id; |
| 628 | + } |
| 629 | + public function getNotifyRSS( $type, $id, $limit ) { |
| 630 | + $fname = 'NotifyMe::getNotifyRSS'; |
| 631 | + wfProfileIn( $fname ); |
| 632 | + $db =& wfGetDB( DB_SLAVE ); |
| 633 | + $result = array(); |
| 634 | + if ( $type == "uid" ) { |
| 635 | + $ids = array( 'user_id' => $id ); |
| 636 | + } else { |
| 637 | + $ids = array( 'notify_id' => $id ); |
| 638 | + } |
| 639 | + $res = $db->select( $db->tableName( 'smw_nm_rss' ), array( 'title', 'link', 'notify', 'timestamp' ), $ids, $fname, array( 'ORDER BY' => 'timestamp DESC', 'LIMIT' => $limit ) ); |
| 640 | + if ( $db->numRows( $res ) > 0 ) { |
| 641 | + while ( $row = $db->fetchObject( $res ) ) { |
| 642 | + $result[] = array( 'title' => $row->title, 'link' => $row->link, 'notify' => $row->notify, 'timestamp' => $row->timestamp ); |
| 643 | + } |
| 644 | + } |
| 645 | + $db->freeResult( $res ); |
| 646 | + wfProfileOut( $fname ); |
| 647 | + return $result; |
| 648 | + } |
| 649 | + public function getUnmailedNMMessages() { |
| 650 | + $fname = 'NotifyMe::getUnmailedNMMessages'; |
| 651 | + wfProfileIn( $fname ); |
| 652 | + $db =& wfGetDB( DB_MASTER ); |
| 653 | + $smw_nm_rss = $db->tableName( 'smw_nm_rss' ); |
| 654 | + $result = array(); |
| 655 | + $res = $db->select( $smw_nm_rss, |
| 656 | + array( 'user_id', 'title', 'notify', 'timestamp' ), |
| 657 | + array( 'mailed' => '0' ), $fname ); |
| 658 | + if ( $db->numRows( $res ) > 0 ) { |
| 659 | + while ( $row = $db->fetchObject( $res ) ) { |
| 660 | + $result[] = array( 'user_id' => $row->user_id, 'title' => $row->title, 'notify' => $row->notify, 'timestamp' => $row->timestamp ); |
| 661 | + } |
| 662 | + } |
| 663 | + $db->freeResult( $res ); |
| 664 | + $db->update( $smw_nm_rss, array( 'mailed' => '1' ), array( 'mailed' => '0' ), $fname ); |
| 665 | + wfProfileOut( $fname ); |
| 666 | + return $result; |
| 667 | + } |
| 668 | + |
| 669 | + public function getGroupedUsers( $groups ) { |
| 670 | + $fname = 'NotifyMe::getGroupedUsers'; |
| 671 | + wfProfileIn( $fname ); |
| 672 | + $db =& wfGetDB( DB_SLAVE ); |
| 673 | + extract( $db->tableNames( 'user_groups', 'user' ) ); |
| 674 | + $result = array(); |
| 675 | + $res = $db->query( "SELECT u.user_name FROM $user u" . |
| 676 | + ( $groups ? " LEFT JOIN $user_groups g ON u.user_id = g.ug_user |
| 677 | + WHERE g.ug_group IN ('" . join( "','", $groups ) . "') |
| 678 | + GROUP BY user_name":"" ), $fname ); |
| 679 | + if ( $db->numRows( $res ) > 0 ) { |
| 680 | + while ( $row = $db->fetchObject( $res ) ) { |
| 681 | + $result[] = $row->user_name; |
| 682 | + } |
| 683 | + } |
| 684 | + $db->freeResult( $res ); |
| 685 | + wfProfileOut( $fname ); |
| 686 | + return $result; |
| 687 | + } |
| 688 | + |
| 689 | + function getNMQueryResult( SMWQuery $query ) { |
| 690 | + wfProfileIn( 'SMWSQLStore2::getNMQueryResult (SMW)' ); |
| 691 | + global $smwgNMIP; |
| 692 | + include_once( "$smwgNMIP/includes/storage/SMW_SQLStore2_QueriesNM.php" ); |
| 693 | + $qe = new SMWSQLStore2QueryEngineNM( smwfGetStore(), wfGetDB( DB_SLAVE ) ); |
| 694 | + $result = $qe->getQueryResult( $query ); |
| 695 | + wfProfileOut( 'SMWSQLStore2::getNMQueryResult (SMW)' ); |
| 696 | + return $result; |
| 697 | + } |
| 698 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/includes/storage/SMW_NMStorageSQL.php |
___________________________________________________________________ |
Name: svn:eol-style |
702 | 699 | + native |
Index: trunk/extensions/SemanticNotifyMe/includes/SMW_NMStorage.php |
— | — | @@ -1,84 +1,82 @@ |
2 | | -<?php
|
3 | | -
|
4 | | -/**
|
5 | | - * This file provides the access to the database tables that are
|
6 | | - * used by the NotifyMe extension.
|
7 | | - *
|
8 | | - * @author dch
|
9 | | - *
|
10 | | - */
|
11 | | -if ( !defined( 'MEDIAWIKI' ) ) die;
|
12 | | -global $smwgNMIP;
|
13 | | -require_once $smwgNMIP . '/includes/SMW_NMDBHelper.php';
|
14 | | -
|
15 | | -
|
16 | | -
|
17 | | -/**
|
18 | | - * This class encapsulates all methods that care about the database tables of
|
19 | | - * the NotifyMe extension. It is a singleton that contains an instance
|
20 | | - * of the actual database access object e.g. the Mediawiki SQL database.
|
21 | | - *
|
22 | | - */
|
23 | | -class NMStorage {
|
24 | | -
|
25 | | - //--- Private fields---
|
26 | | -
|
27 | | - private static $mInstance; // NMStorage: the only instance of this singleton
|
28 | | - private static $mDatabase; // The actual database object
|
29 | | -
|
30 | | - //--- Constructor ---
|
31 | | -
|
32 | | - /**
|
33 | | - * Constructor.
|
34 | | - * Creates the object that handles the concrete database access.
|
35 | | - *
|
36 | | - */
|
37 | | - private function __construct() {
|
38 | | - if (self::$mDatabase == NULL) {
|
39 | | - global $smwgBaseStore;
|
40 | | - switch ($smwgBaseStore) {
|
41 | | - case (SMW_STORE_TESTING):
|
42 | | - trigger_error('Testing store not implemented for NotifyMe extension.');
|
43 | | - break;
|
44 | | - case (SMW_STORE_MWDB):
|
45 | | - default:
|
46 | | - global $smwgNMIP;
|
47 | | - require_once($smwgNMIP . '/includes/storage/SMW_NMStorageSQL.php');
|
48 | | - self::$mDatabase = new NMStorageSQL();
|
49 | | - break;
|
50 | | - }
|
51 | | - }
|
52 | | -
|
53 | | - }
|
54 | | -
|
55 | | - //--- Public methods ---
|
56 | | -
|
57 | | - /**
|
58 | | - * Returns the single instance of this class.
|
59 | | - *
|
60 | | - * @return NMStorage
|
61 | | - * The single instance of this class.
|
62 | | - */
|
63 | | - public static function getInstance() {
|
64 | | - if (!isset(self::$mInstance)) {
|
65 | | - $c = __CLASS__;
|
66 | | - self::$mInstance = new $c;
|
67 | | - }
|
68 | | -
|
69 | | - return self::$mInstance;
|
70 | | - }
|
71 | | -
|
72 | | - /**
|
73 | | - * Returns the actual database.
|
74 | | - *
|
75 | | - * @return object
|
76 | | - * The object to access the database.
|
77 | | - */
|
78 | | - public static function getDatabase() {
|
79 | | - self::getInstance(); // Make sure, singleton is initialized
|
80 | | - return self::$mDatabase;
|
81 | | - }
|
82 | | -
|
83 | | -}
|
84 | | -
|
85 | | -?> |
\ No newline at end of file |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * This file provides the access to the database tables that are |
| 6 | + * used by the NotifyMe extension. |
| 7 | + * |
| 8 | + * @author dch |
| 9 | + * |
| 10 | + */ |
| 11 | +if ( !defined( 'MEDIAWIKI' ) ) die; |
| 12 | +global $smwgNMIP; |
| 13 | +require_once $smwgNMIP . '/includes/SMW_NMDBHelper.php'; |
| 14 | + |
| 15 | + |
| 16 | + |
| 17 | +/** |
| 18 | + * This class encapsulates all methods that care about the database tables of |
| 19 | + * the NotifyMe extension. It is a singleton that contains an instance |
| 20 | + * of the actual database access object e.g. the Mediawiki SQL database. |
| 21 | + * |
| 22 | + */ |
| 23 | +class NMStorage { |
| 24 | + |
| 25 | + // --- Private fields--- |
| 26 | + |
| 27 | + private static $mInstance; // NMStorage: the only instance of this singleton |
| 28 | + private static $mDatabase; // The actual database object |
| 29 | + |
| 30 | + // --- Constructor --- |
| 31 | + |
| 32 | + /** |
| 33 | + * Constructor. |
| 34 | + * Creates the object that handles the concrete database access. |
| 35 | + * |
| 36 | + */ |
| 37 | + private function __construct() { |
| 38 | + if ( self::$mDatabase == NULL ) { |
| 39 | + global $smwgBaseStore; |
| 40 | + switch ( $smwgBaseStore ) { |
| 41 | + case ( SMW_STORE_TESTING ): |
| 42 | + trigger_error( 'Testing store not implemented for NotifyMe extension.' ); |
| 43 | + break; |
| 44 | + case ( SMW_STORE_MWDB ): |
| 45 | + default: |
| 46 | + global $smwgNMIP; |
| 47 | + require_once( $smwgNMIP . '/includes/storage/SMW_NMStorageSQL.php' ); |
| 48 | + self::$mDatabase = new NMStorageSQL(); |
| 49 | + break; |
| 50 | + } |
| 51 | + } |
| 52 | + |
| 53 | + } |
| 54 | + |
| 55 | + // --- Public methods --- |
| 56 | + |
| 57 | + /** |
| 58 | + * Returns the single instance of this class. |
| 59 | + * |
| 60 | + * @return NMStorage |
| 61 | + * The single instance of this class. |
| 62 | + */ |
| 63 | + public static function getInstance() { |
| 64 | + if ( !isset( self::$mInstance ) ) { |
| 65 | + $c = __CLASS__; |
| 66 | + self::$mInstance = new $c; |
| 67 | + } |
| 68 | + |
| 69 | + return self::$mInstance; |
| 70 | + } |
| 71 | + |
| 72 | + /** |
| 73 | + * Returns the actual database. |
| 74 | + * |
| 75 | + * @return object |
| 76 | + * The object to access the database. |
| 77 | + */ |
| 78 | + public static function getDatabase() { |
| 79 | + self::getInstance(); // Make sure, singleton is initialized |
| 80 | + return self::$mDatabase; |
| 81 | + } |
| 82 | + |
| 83 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/includes/SMW_NMStorage.php |
___________________________________________________________________ |
Name: svn:eol-style |
86 | 84 | + native |
Index: trunk/extensions/SemanticNotifyMe/includes/SMW_NMDBHelper.php |
— | — | @@ -1,304 +1,299 @@ |
2 | | -<?php
|
3 | | -/*
|
4 | | - * Created on 19.10.2008
|
5 | | - *
|
6 | | - * Author: dch
|
7 | | - */
|
8 | | -
|
9 | | -
|
10 | | -
|
11 | | -class SNMDBHelper {
|
12 | | -
|
13 | | -
|
14 | | - /**
|
15 | | - * Make sure the table of the given name has the given fields, provided
|
16 | | - * as an array with entries fieldname => typeparams. typeparams should be
|
17 | | - * in a normalised form and order to match to existing values.
|
18 | | - *
|
19 | | - * The function returns an array that includes all columns that have been
|
20 | | - * changed. For each such column, the array contains an entry
|
21 | | - * columnname => action, where action is one of 'up', 'new', or 'del'
|
22 | | - * If the table was already fine or was created completely anew, an empty
|
23 | | - * array is returned (assuming that both cases require no action).
|
24 | | - *
|
25 | | - * NOTE: the function partly ignores the order in which fields are set up.
|
26 | | - * Only if the type of some field changes will its order be adjusted explicitly.
|
27 | | - *
|
28 | | - * @param string $primaryKeys
|
29 | | - * This optional string specifies the primary keys if there is more
|
30 | | - * than one. This is a comma separated list of column names. The primary
|
31 | | - * keys are not altered, if the table already exists.
|
32 | | - */
|
33 | | - public static function setupTable($table, $fields, $db, $verbose, $primaryKeys = "") {
|
34 | | - global $wgDBname;
|
35 | | - SNMDBHelper::reportProgress("Setting up table $table ...\n",$verbose);
|
36 | | - if ($db->tableExists($table) === false) { // create new table
|
37 | | - $sql = 'CREATE TABLE ' . $wgDBname . '.' . $table . ' (';
|
38 | | - $first = true;
|
39 | | - foreach ($fields as $name => $type) {
|
40 | | - if ($first) {
|
41 | | - $first = false;
|
42 | | - } else {
|
43 | | - $sql .= ',';
|
44 | | - }
|
45 | | - $sql .= $name . ' ' . $type;
|
46 | | - }
|
47 | | - if (!empty($primaryKeys)) {
|
48 | | - $sql .= ", PRIMARY KEY(".$primaryKeys.")";
|
49 | | - }
|
50 | | - $sql .= ') TYPE=myisam';
|
51 | | - $db->query( $sql, 'SNMDBHelper::setupTable' );
|
52 | | - SNMDBHelper::reportProgress(" ... new table created\n",$verbose);
|
53 | | - return array();
|
54 | | - } else { // check table signature
|
55 | | - SNMDBHelper::reportProgress(" ... table exists already, checking structure ...\n",$verbose);
|
56 | | - $res = $db->query( 'DESCRIBE ' . $table, 'SNMDBHelper::setupTable' );
|
57 | | - $curfields = array();
|
58 | | - $result = array();
|
59 | | - while ($row = $db->fetchObject($res)) {
|
60 | | - $type = strtoupper($row->Type);
|
61 | | - if (substr($type,0,8) == 'VARCHAR(') {
|
62 | | - $type .= ' binary'; // just assume this to be the case for VARCHAR, avoid collation checks
|
63 | | - }
|
64 | | - if ($row->Null != 'YES') {
|
65 | | - $type .= ' NOT NULL';
|
66 | | - }
|
67 | | - if ($row->Key == 'PRI') { /// FIXME: updating "KEY" is not possible, the below query will fail in this case.
|
68 | | - $type .= ' KEY';
|
69 | | - }
|
70 | | - if ($row->Extra == 'auto_increment') {
|
71 | | - $type .= ' AUTO_INCREMENT';
|
72 | | - }
|
73 | | - if ($row->Default != '') {
|
74 | | - $type .= ' default \''.$row->Default.'\'';
|
75 | | - }
|
76 | | -
|
77 | | - $curfields[$row->Field] = $type;
|
78 | | - }
|
79 | | - $position = 'FIRST';
|
80 | | - foreach ($fields as $name => $type) {
|
81 | | - if ( !array_key_exists($name,$curfields) ) {
|
82 | | - SNMDBHelper::reportProgress(" ... creating column $name ... ",$verbose);
|
83 | | - $db->query("ALTER TABLE $table ADD `$name` $type $position", 'SNMDBHelper::setupTable');
|
84 | | - $result[$name] = 'new';
|
85 | | - SNMDBHelper::reportProgress("done \n",$verbose);
|
86 | | - } elseif ($curfields[$name] != $type) {// && stripos("auto_increment", $type) == -1) {
|
87 | | - SNMDBHelper::reportProgress(" ... changing type of column $name from '$curfields[$name]' to '$type' ... ",$verbose);
|
88 | | - $db->query("ALTER TABLE $table CHANGE `$name` `$name` $type $position", 'SNMDBHelper::setupTable');
|
89 | | - $result[$name] = 'up';
|
90 | | - $curfields[$name] = false;
|
91 | | - SNMDBHelper::reportProgress("done.\n",$verbose);
|
92 | | - } else {
|
93 | | - SNMDBHelper::reportProgress(" ... column $name is fine\n",$verbose);
|
94 | | - $curfields[$name] = false;
|
95 | | - }
|
96 | | - $position = "AFTER $name";
|
97 | | - }
|
98 | | - foreach ($curfields as $name => $value) {
|
99 | | - if ($value !== false) { // not encountered yet --> delete
|
100 | | - SNMDBHelper::reportProgress(" ... deleting obsolete column $name ... ",$verbose);
|
101 | | - $db->query("ALTER TABLE $table DROP COLUMN `$name`", 'SNMDBHelper::setupTable');
|
102 | | - $result[$name] = 'del';
|
103 | | - SNMDBHelper::reportProgress("done.\n",$verbose);
|
104 | | - }
|
105 | | - }
|
106 | | - SNMDBHelper::reportProgress(" ... table $table set up successfully.\n",$verbose);
|
107 | | - return $result;
|
108 | | - }
|
109 | | - }
|
110 | | -
|
111 | | - /**
|
112 | | - * Make sure that each of the column descriptions in the given array is indexed by *one* index
|
113 | | - * in the given DB table.
|
114 | | - */
|
115 | | - public static function setupIndex($table, $columns, $db) {
|
116 | | - $table = $db->tableName($table);
|
117 | | - $res = $db->query( 'SHOW INDEX FROM ' . $table , 'SMW::SetupIndex');
|
118 | | - if ( !$res ) {
|
119 | | - return false;
|
120 | | - }
|
121 | | - $indexes = array();
|
122 | | - while ( $row = $db->fetchObject( $res ) ) {
|
123 | | - if (!array_key_exists($row->Key_name, $indexes)) {
|
124 | | - $indexes[$row->Key_name] = array();
|
125 | | - }
|
126 | | - $indexes[$row->Key_name][$row->Seq_in_index] = $row->Column_name;
|
127 | | - }
|
128 | | - foreach ($indexes as $key => $index) { // clean up existing indexes
|
129 | | - $id = array_search(implode(',', $index), $columns );
|
130 | | - if ( $id !== false ) {
|
131 | | - $columns[$id] = false;
|
132 | | - } else { // duplicate or unrequired index
|
133 | | - if($key != 'PRIMARY') {
|
134 | | - $db->query( 'DROP INDEX ' . $key . ' ON ' . $table, 'SMW::SetupIndex');
|
135 | | - }
|
136 | | - }
|
137 | | - }
|
138 | | -
|
139 | | - foreach ($columns as $column) { // add remaining indexes
|
140 | | - if ($column != false) {
|
141 | | - $db->query( "ALTER TABLE $table ADD INDEX ( $column )", 'SMW::SetupIndex');
|
142 | | - }
|
143 | | - }
|
144 | | - return true;
|
145 | | - }
|
146 | | -
|
147 | | - /**
|
148 | | - * Print some output to indicate progress. The output message is given by
|
149 | | - * $msg, while $verbose indicates whether or not output is desired at all.
|
150 | | - */
|
151 | | - public static function reportProgress($msg, $verbose) {
|
152 | | - if (!$verbose) {
|
153 | | - return;
|
154 | | - }
|
155 | | - if (ob_get_level() == 0) { // be sure to have some buffer, otherwise some PHPs complain
|
156 | | - ob_start();
|
157 | | - }
|
158 | | - print $msg;
|
159 | | - ob_flush();
|
160 | | - flush();
|
161 | | - }
|
162 | | -
|
163 | | - /**
|
164 | | - * Transform input parameters into a suitable array of SQL options.
|
165 | | - * The parameter $valuecol defines the string name of the column to which
|
166 | | - * sorting requests etc. are to be applied.
|
167 | | - */
|
168 | | - public static function getSQLOptions($requestoptions, $valuecol = NULL) {
|
169 | | - $sql_options = array();
|
170 | | - if ($requestoptions !== NULL) {
|
171 | | - if (is_numeric($requestoptions->limit) && $requestoptions->limit >= 0) {
|
172 | | - $sql_options['LIMIT'] = $requestoptions->limit;
|
173 | | - }
|
174 | | - if (is_numeric($requestoptions->offset) && $requestoptions->offset > 0) {
|
175 | | - $sql_options['OFFSET'] = $requestoptions->offset;
|
176 | | - }
|
177 | | - if ( ($valuecol !== NULL) && ($requestoptions->sort) ) {
|
178 | | - if (is_array($valuecol)) {
|
179 | | - $sql_options['ORDER BY'] = $requestoptions->ascending ? mysql_real_escape_string(implode(",",$valuecol)) : mysql_real_escape_string(implode(",",$valuecol)) . ' DESC';
|
180 | | - } else {
|
181 | | - $sql_options['ORDER BY'] = $requestoptions->ascending ? mysql_real_escape_string($valuecol) : mysql_real_escape_string($valuecol) . ' DESC';
|
182 | | - }
|
183 | | - }
|
184 | | - }
|
185 | | - return $sql_options;
|
186 | | - }
|
187 | | -
|
188 | | - public static function getSQLOptionsAsString($requestoptions, $valuecol = NULL) {
|
189 | | - $options = SNMDBHelper::getSQLOptions($requestoptions,$valuecol);
|
190 | | - $limit = array_key_exists('LIMIT', $options) && is_numeric($options['LIMIT'])? 'LIMIT '.$options['LIMIT'] : '';
|
191 | | - $offset = array_key_exists('OFFSET', $options) && is_numeric($options['OFFSET']) ? 'OFFSET '.$options['OFFSET'] : '';
|
192 | | - $orderby = array_key_exists('ORDER BY', $options) ? 'ORDER BY '.$options['ORDER BY'] : '';
|
193 | | - return $orderby.' '.$limit.' '.$offset;
|
194 | | - }
|
195 | | -
|
196 | | - /**
|
197 | | - * Transform input parameters into a suitable string of additional SQL conditions.
|
198 | | - * The parameter $valuecol defines the string name of the column to which
|
199 | | - * value restrictions etc. are to be applied.
|
200 | | - * @param $requestoptions object with options
|
201 | | - * @param $valuecol name of SQL column to which conditions apply
|
202 | | - * @param $labelcol name of SQL column to which string conditions apply, if any
|
203 | | - */
|
204 | | - public static function getSQLConditions($requestoptions, $valuecol, $labelcol = NULL) {
|
205 | | - $sql_conds = '';
|
206 | | - if ($requestoptions !== NULL) {
|
207 | | - $db =& wfGetDB( DB_SLAVE ); // TODO: use slave?
|
208 | | - if ($requestoptions->boundary !== NULL) { // apply value boundary
|
209 | | - if ($requestoptions->ascending) {
|
210 | | - if ($requestoptions->include_boundary) {
|
211 | | - $op = ' >= ';
|
212 | | - } else {
|
213 | | - $op = ' > ';
|
214 | | - }
|
215 | | - } else {
|
216 | | - if ($requestoptions->include_boundary) {
|
217 | | - $op = ' <= ';
|
218 | | - } else {
|
219 | | - $op = ' < ';
|
220 | | - }
|
221 | | - }
|
222 | | - $sql_conds .= ' AND ' . mysql_real_escape_string($valuecol) . $op . $db->addQuotes($requestoptions->boundary);
|
223 | | - }
|
224 | | - $operator = isset($requestoptions->disjunctiveStrings) && $requestoptions->disjunctiveStrings === true ? ' OR ' : ' AND ';
|
225 | | - $neutral = isset($requestoptions->disjunctiveStrings) && $requestoptions->disjunctiveStrings === true ? ' FALSE ' : ' TRUE ';
|
226 | | - if ($labelcol !== NULL) { // apply string conditions
|
227 | | -
|
228 | | - $sql_conds .= ' AND ( ';
|
229 | | -
|
230 | | - foreach ($requestoptions->getStringConditions() as $strcond) {
|
231 | | - $string = str_replace(array('_', ' '), array('\_', '\_'), $strcond->string);
|
232 | | - switch ($strcond->condition) {
|
233 | | - case SMWStringCondition::STRCOND_PRE:
|
234 | | - $string .= '%';
|
235 | | - break;
|
236 | | - case SMWStringCondition::STRCOND_POST:
|
237 | | - $string = '%' . $string;
|
238 | | - break;
|
239 | | - case SMWStringCondition::STRCOND_MID:
|
240 | | - $string = '%' . $string . '%';
|
241 | | - break;
|
242 | | - }
|
243 | | - if ($requestoptions->isCaseSensitive) {
|
244 | | - $sql_conds .= mysql_real_escape_string($labelcol) . ' LIKE ' . $db->addQuotes($string). $operator;
|
245 | | - } else {
|
246 | | - $sql_conds .= ' UPPER(' . mysql_real_escape_string($labelcol) . ') LIKE UPPER(' . $db->addQuotes($string).') '.$operator;
|
247 | | - }
|
248 | | - }
|
249 | | - $sql_conds .= ' '.$neutral.' ) ';
|
250 | | - }
|
251 | | - }
|
252 | | - return $sql_conds;
|
253 | | - }
|
254 | | -
|
255 | | - /**
|
256 | | - * Returns sql conditions of $requestoptions in an Array.
|
257 | | - * Warning! Does not support SMWAdvRequestOptions
|
258 | | - *
|
259 | | - * @param SMWRequestOptions $requestoptions
|
260 | | - * @param string $valuecol
|
261 | | - * @param string $labelcol
|
262 | | - * @return array
|
263 | | - */
|
264 | | - public static function getSQLConditionsAsArray($requestoptions, $valuecol, $labelcol = NULL) {
|
265 | | - $sql_conds = array();
|
266 | | - if ($requestoptions !== NULL) {
|
267 | | - $db =& wfGetDB( DB_SLAVE );
|
268 | | - if ($requestoptions->boundary !== NULL) { // apply value boundary
|
269 | | - if ($requestoptions->ascending) {
|
270 | | - if ($requestoptions->include_boundary) {
|
271 | | - $op = ' >= ';
|
272 | | - } else {
|
273 | | - $op = ' > ';
|
274 | | - }
|
275 | | - } else {
|
276 | | - if ($requestoptions->include_boundary) {
|
277 | | - $op = ' <= ';
|
278 | | - } else {
|
279 | | - $op = ' < ';
|
280 | | - }
|
281 | | - }
|
282 | | - $sql_conds[] = mysql_real_escape_string($valuecol) . $op . $db->addQuotes($requestoptions->boundary);
|
283 | | - }
|
284 | | - if ($labelcol !== NULL) { // apply string conditions
|
285 | | - foreach ($requestoptions->getStringConditions() as $strcond) {
|
286 | | - $string = str_replace(array('_', ' '), array('\_', '\_'), $strcond->string);
|
287 | | - switch ($strcond->condition) {
|
288 | | - case SMWStringCondition::STRCOND_PRE:
|
289 | | - $string .= '%';
|
290 | | - break;
|
291 | | - case SMWStringCondition::STRCOND_POST:
|
292 | | - $string = '%' . $string;
|
293 | | - break;
|
294 | | - case SMWStringCondition::STRCOND_MID:
|
295 | | - $string = '%' . $string . '%';
|
296 | | - break;
|
297 | | - }
|
298 | | - $sql_conds[] = 'UPPER('.mysql_real_escape_string($labelcol) . ') LIKE UPPER(' . $db->addQuotes($string).')';
|
299 | | - }
|
300 | | - }
|
301 | | - }
|
302 | | - return $sql_conds;
|
303 | | - }
|
304 | | -}
|
305 | | -?>
|
| 2 | +<?php |
| 3 | +/* |
| 4 | + * Created on 19.10.2008 |
| 5 | + * |
| 6 | + * Author: dch |
| 7 | + */ |
| 8 | + |
| 9 | +class SNMDBHelper { |
| 10 | + /** |
| 11 | + * Make sure the table of the given name has the given fields, provided |
| 12 | + * as an array with entries fieldname => typeparams. typeparams should be |
| 13 | + * in a normalised form and order to match to existing values. |
| 14 | + * |
| 15 | + * The function returns an array that includes all columns that have been |
| 16 | + * changed. For each such column, the array contains an entry |
| 17 | + * columnname => action, where action is one of 'up', 'new', or 'del' |
| 18 | + * If the table was already fine or was created completely anew, an empty |
| 19 | + * array is returned (assuming that both cases require no action). |
| 20 | + * |
| 21 | + * NOTE: the function partly ignores the order in which fields are set up. |
| 22 | + * Only if the type of some field changes will its order be adjusted explicitly. |
| 23 | + * |
| 24 | + * @param string $primaryKeys |
| 25 | + * This optional string specifies the primary keys if there is more |
| 26 | + * than one. This is a comma separated list of column names. The primary |
| 27 | + * keys are not altered, if the table already exists. |
| 28 | + */ |
| 29 | + public static function setupTable( $table, $fields, $db, $verbose, $primaryKeys = "" ) { |
| 30 | + global $wgDBname; |
| 31 | + SNMDBHelper::reportProgress( "Setting up table $table ...\n", $verbose ); |
| 32 | + if ( $db->tableExists( $table ) === false ) { // create new table |
| 33 | + $sql = 'CREATE TABLE ' . $wgDBname . '.' . $table . ' ('; |
| 34 | + $first = true; |
| 35 | + foreach ( $fields as $name => $type ) { |
| 36 | + if ( $first ) { |
| 37 | + $first = false; |
| 38 | + } else { |
| 39 | + $sql .= ','; |
| 40 | + } |
| 41 | + $sql .= $name . ' ' . $type; |
| 42 | + } |
| 43 | + if ( !empty( $primaryKeys ) ) { |
| 44 | + $sql .= ", PRIMARY KEY(" . $primaryKeys . ")"; |
| 45 | + } |
| 46 | + $sql .= ') TYPE=myisam'; |
| 47 | + $db->query( $sql, 'SNMDBHelper::setupTable' ); |
| 48 | + SNMDBHelper::reportProgress( " ... new table created\n", $verbose ); |
| 49 | + return array(); |
| 50 | + } else { // check table signature |
| 51 | + SNMDBHelper::reportProgress( " ... table exists already, checking structure ...\n", $verbose ); |
| 52 | + $res = $db->query( 'DESCRIBE ' . $table, 'SNMDBHelper::setupTable' ); |
| 53 | + $curfields = array(); |
| 54 | + $result = array(); |
| 55 | + while ( $row = $db->fetchObject( $res ) ) { |
| 56 | + $type = strtoupper( $row->Type ); |
| 57 | + if ( substr( $type, 0, 8 ) == 'VARCHAR(' ) { |
| 58 | + $type .= ' binary'; // just assume this to be the case for VARCHAR, avoid collation checks |
| 59 | + } |
| 60 | + if ( $row->Null != 'YES' ) { |
| 61 | + $type .= ' NOT NULL'; |
| 62 | + } |
| 63 | + if ( $row->Key == 'PRI' ) { // / FIXME: updating "KEY" is not possible, the below query will fail in this case. |
| 64 | + $type .= ' KEY'; |
| 65 | + } |
| 66 | + if ( $row->Extra == 'auto_increment' ) { |
| 67 | + $type .= ' AUTO_INCREMENT'; |
| 68 | + } |
| 69 | + if ( $row->Default != '' ) { |
| 70 | + $type .= ' default \'' . $row->Default . '\''; |
| 71 | + } |
| 72 | + |
| 73 | + $curfields[$row->Field] = $type; |
| 74 | + } |
| 75 | + $position = 'FIRST'; |
| 76 | + foreach ( $fields as $name => $type ) { |
| 77 | + if ( !array_key_exists( $name, $curfields ) ) { |
| 78 | + SNMDBHelper::reportProgress( " ... creating column $name ... ", $verbose ); |
| 79 | + $db->query( "ALTER TABLE $table ADD `$name` $type $position", 'SNMDBHelper::setupTable' ); |
| 80 | + $result[$name] = 'new'; |
| 81 | + SNMDBHelper::reportProgress( "done \n", $verbose ); |
| 82 | + } elseif ( $curfields[$name] != $type ) {// && stripos("auto_increment", $type) == -1) { |
| 83 | + SNMDBHelper::reportProgress( " ... changing type of column $name from '$curfields[$name]' to '$type' ... ", $verbose ); |
| 84 | + $db->query( "ALTER TABLE $table CHANGE `$name` `$name` $type $position", 'SNMDBHelper::setupTable' ); |
| 85 | + $result[$name] = 'up'; |
| 86 | + $curfields[$name] = false; |
| 87 | + SNMDBHelper::reportProgress( "done.\n", $verbose ); |
| 88 | + } else { |
| 89 | + SNMDBHelper::reportProgress( " ... column $name is fine\n", $verbose ); |
| 90 | + $curfields[$name] = false; |
| 91 | + } |
| 92 | + $position = "AFTER $name"; |
| 93 | + } |
| 94 | + foreach ( $curfields as $name => $value ) { |
| 95 | + if ( $value !== false ) { // not encountered yet --> delete |
| 96 | + SNMDBHelper::reportProgress( " ... deleting obsolete column $name ... ", $verbose ); |
| 97 | + $db->query( "ALTER TABLE $table DROP COLUMN `$name`", 'SNMDBHelper::setupTable' ); |
| 98 | + $result[$name] = 'del'; |
| 99 | + SNMDBHelper::reportProgress( "done.\n", $verbose ); |
| 100 | + } |
| 101 | + } |
| 102 | + SNMDBHelper::reportProgress( " ... table $table set up successfully.\n", $verbose ); |
| 103 | + return $result; |
| 104 | + } |
| 105 | + } |
| 106 | + |
| 107 | + /** |
| 108 | + * Make sure that each of the column descriptions in the given array is indexed by *one* index |
| 109 | + * in the given DB table. |
| 110 | + */ |
| 111 | + public static function setupIndex( $table, $columns, $db ) { |
| 112 | + $table = $db->tableName( $table ); |
| 113 | + $res = $db->query( 'SHOW INDEX FROM ' . $table , 'SMW::SetupIndex' ); |
| 114 | + if ( !$res ) { |
| 115 | + return false; |
| 116 | + } |
| 117 | + $indexes = array(); |
| 118 | + while ( $row = $db->fetchObject( $res ) ) { |
| 119 | + if ( !array_key_exists( $row->Key_name, $indexes ) ) { |
| 120 | + $indexes[$row->Key_name] = array(); |
| 121 | + } |
| 122 | + $indexes[$row->Key_name][$row->Seq_in_index] = $row->Column_name; |
| 123 | + } |
| 124 | + foreach ( $indexes as $key => $index ) { // clean up existing indexes |
| 125 | + $id = array_search( implode( ',', $index ), $columns ); |
| 126 | + if ( $id !== false ) { |
| 127 | + $columns[$id] = false; |
| 128 | + } else { // duplicate or unrequired index |
| 129 | + if ( $key != 'PRIMARY' ) { |
| 130 | + $db->query( 'DROP INDEX ' . $key . ' ON ' . $table, 'SMW::SetupIndex' ); |
| 131 | + } |
| 132 | + } |
| 133 | + } |
| 134 | + |
| 135 | + foreach ( $columns as $column ) { // add remaining indexes |
| 136 | + if ( $column != false ) { |
| 137 | + $db->query( "ALTER TABLE $table ADD INDEX ( $column )", 'SMW::SetupIndex' ); |
| 138 | + } |
| 139 | + } |
| 140 | + return true; |
| 141 | + } |
| 142 | + |
| 143 | + /** |
| 144 | + * Print some output to indicate progress. The output message is given by |
| 145 | + * $msg, while $verbose indicates whether or not output is desired at all. |
| 146 | + */ |
| 147 | + public static function reportProgress( $msg, $verbose ) { |
| 148 | + if ( !$verbose ) { |
| 149 | + return; |
| 150 | + } |
| 151 | + if ( ob_get_level() == 0 ) { // be sure to have some buffer, otherwise some PHPs complain |
| 152 | + ob_start(); |
| 153 | + } |
| 154 | + print $msg; |
| 155 | + ob_flush(); |
| 156 | + flush(); |
| 157 | + } |
| 158 | + |
| 159 | + /** |
| 160 | + * Transform input parameters into a suitable array of SQL options. |
| 161 | + * The parameter $valuecol defines the string name of the column to which |
| 162 | + * sorting requests etc. are to be applied. |
| 163 | + */ |
| 164 | + public static function getSQLOptions( $requestoptions, $valuecol = NULL ) { |
| 165 | + $sql_options = array(); |
| 166 | + if ( $requestoptions !== NULL ) { |
| 167 | + if ( is_numeric( $requestoptions->limit ) && $requestoptions->limit >= 0 ) { |
| 168 | + $sql_options['LIMIT'] = $requestoptions->limit; |
| 169 | + } |
| 170 | + if ( is_numeric( $requestoptions->offset ) && $requestoptions->offset > 0 ) { |
| 171 | + $sql_options['OFFSET'] = $requestoptions->offset; |
| 172 | + } |
| 173 | + if ( ( $valuecol !== NULL ) && ( $requestoptions->sort ) ) { |
| 174 | + if ( is_array( $valuecol ) ) { |
| 175 | + $sql_options['ORDER BY'] = $requestoptions->ascending ? mysql_real_escape_string( implode( ",", $valuecol ) ) : mysql_real_escape_string( implode( ",", $valuecol ) ) . ' DESC'; |
| 176 | + } else { |
| 177 | + $sql_options['ORDER BY'] = $requestoptions->ascending ? mysql_real_escape_string( $valuecol ) : mysql_real_escape_string( $valuecol ) . ' DESC'; |
| 178 | + } |
| 179 | + } |
| 180 | + } |
| 181 | + return $sql_options; |
| 182 | + } |
| 183 | + |
| 184 | + public static function getSQLOptionsAsString( $requestoptions, $valuecol = NULL ) { |
| 185 | + $options = SNMDBHelper::getSQLOptions( $requestoptions, $valuecol ); |
| 186 | + $limit = array_key_exists( 'LIMIT', $options ) && is_numeric( $options['LIMIT'] ) ? 'LIMIT ' . $options['LIMIT'] : ''; |
| 187 | + $offset = array_key_exists( 'OFFSET', $options ) && is_numeric( $options['OFFSET'] ) ? 'OFFSET ' . $options['OFFSET'] : ''; |
| 188 | + $orderby = array_key_exists( 'ORDER BY', $options ) ? 'ORDER BY ' . $options['ORDER BY'] : ''; |
| 189 | + return $orderby . ' ' . $limit . ' ' . $offset; |
| 190 | + } |
| 191 | + |
| 192 | + /** |
| 193 | + * Transform input parameters into a suitable string of additional SQL conditions. |
| 194 | + * The parameter $valuecol defines the string name of the column to which |
| 195 | + * value restrictions etc. are to be applied. |
| 196 | + * @param $requestoptions object with options |
| 197 | + * @param $valuecol name of SQL column to which conditions apply |
| 198 | + * @param $labelcol name of SQL column to which string conditions apply, if any |
| 199 | + */ |
| 200 | + public static function getSQLConditions( $requestoptions, $valuecol, $labelcol = NULL ) { |
| 201 | + $sql_conds = ''; |
| 202 | + if ( $requestoptions !== NULL ) { |
| 203 | + $db =& wfGetDB( DB_SLAVE ); // TODO: use slave? |
| 204 | + if ( $requestoptions->boundary !== NULL ) { // apply value boundary |
| 205 | + if ( $requestoptions->ascending ) { |
| 206 | + if ( $requestoptions->include_boundary ) { |
| 207 | + $op = ' >= '; |
| 208 | + } else { |
| 209 | + $op = ' > '; |
| 210 | + } |
| 211 | + } else { |
| 212 | + if ( $requestoptions->include_boundary ) { |
| 213 | + $op = ' <= '; |
| 214 | + } else { |
| 215 | + $op = ' < '; |
| 216 | + } |
| 217 | + } |
| 218 | + $sql_conds .= ' AND ' . mysql_real_escape_string( $valuecol ) . $op . $db->addQuotes( $requestoptions->boundary ); |
| 219 | + } |
| 220 | + $operator = isset( $requestoptions->disjunctiveStrings ) && $requestoptions->disjunctiveStrings === true ? ' OR ' : ' AND '; |
| 221 | + $neutral = isset( $requestoptions->disjunctiveStrings ) && $requestoptions->disjunctiveStrings === true ? ' FALSE ' : ' TRUE '; |
| 222 | + if ( $labelcol !== NULL ) { // apply string conditions |
| 223 | + |
| 224 | + $sql_conds .= ' AND ( '; |
| 225 | + |
| 226 | + foreach ( $requestoptions->getStringConditions() as $strcond ) { |
| 227 | + $string = str_replace( array( '_', ' ' ), array( '\_', '\_' ), $strcond->string ); |
| 228 | + switch ( $strcond->condition ) { |
| 229 | + case SMWStringCondition::STRCOND_PRE: |
| 230 | + $string .= '%'; |
| 231 | + break; |
| 232 | + case SMWStringCondition::STRCOND_POST: |
| 233 | + $string = '%' . $string; |
| 234 | + break; |
| 235 | + case SMWStringCondition::STRCOND_MID: |
| 236 | + $string = '%' . $string . '%'; |
| 237 | + break; |
| 238 | + } |
| 239 | + if ( $requestoptions->isCaseSensitive ) { |
| 240 | + $sql_conds .= mysql_real_escape_string( $labelcol ) . ' LIKE ' . $db->addQuotes( $string ) . $operator; |
| 241 | + } else { |
| 242 | + $sql_conds .= ' UPPER(' . mysql_real_escape_string( $labelcol ) . ') LIKE UPPER(' . $db->addQuotes( $string ) . ') ' . $operator; |
| 243 | + } |
| 244 | + } |
| 245 | + $sql_conds .= ' ' . $neutral . ' ) '; |
| 246 | + } |
| 247 | + } |
| 248 | + return $sql_conds; |
| 249 | + } |
| 250 | + |
| 251 | + /** |
| 252 | + * Returns sql conditions of $requestoptions in an Array. |
| 253 | + * Warning! Does not support SMWAdvRequestOptions |
| 254 | + * |
| 255 | + * @param SMWRequestOptions $requestoptions |
| 256 | + * @param string $valuecol |
| 257 | + * @param string $labelcol |
| 258 | + * @return array |
| 259 | + */ |
| 260 | + public static function getSQLConditionsAsArray( $requestoptions, $valuecol, $labelcol = NULL ) { |
| 261 | + $sql_conds = array(); |
| 262 | + if ( $requestoptions !== NULL ) { |
| 263 | + $db =& wfGetDB( DB_SLAVE ); |
| 264 | + if ( $requestoptions->boundary !== NULL ) { // apply value boundary |
| 265 | + if ( $requestoptions->ascending ) { |
| 266 | + if ( $requestoptions->include_boundary ) { |
| 267 | + $op = ' >= '; |
| 268 | + } else { |
| 269 | + $op = ' > '; |
| 270 | + } |
| 271 | + } else { |
| 272 | + if ( $requestoptions->include_boundary ) { |
| 273 | + $op = ' <= '; |
| 274 | + } else { |
| 275 | + $op = ' < '; |
| 276 | + } |
| 277 | + } |
| 278 | + $sql_conds[] = mysql_real_escape_string( $valuecol ) . $op . $db->addQuotes( $requestoptions->boundary ); |
| 279 | + } |
| 280 | + if ( $labelcol !== NULL ) { // apply string conditions |
| 281 | + foreach ( $requestoptions->getStringConditions() as $strcond ) { |
| 282 | + $string = str_replace( array( '_', ' ' ), array( '\_', '\_' ), $strcond->string ); |
| 283 | + switch ( $strcond->condition ) { |
| 284 | + case SMWStringCondition::STRCOND_PRE: |
| 285 | + $string .= '%'; |
| 286 | + break; |
| 287 | + case SMWStringCondition::STRCOND_POST: |
| 288 | + $string = '%' . $string; |
| 289 | + break; |
| 290 | + case SMWStringCondition::STRCOND_MID: |
| 291 | + $string = '%' . $string . '%'; |
| 292 | + break; |
| 293 | + } |
| 294 | + $sql_conds[] = 'UPPER(' . mysql_real_escape_string( $labelcol ) . ') LIKE UPPER(' . $db->addQuotes( $string ) . ')'; |
| 295 | + } |
| 296 | + } |
| 297 | + } |
| 298 | + return $sql_conds; |
| 299 | + } |
| 300 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/includes/SMW_NMDBHelper.php |
___________________________________________________________________ |
Name: svn:eol-style |
306 | 301 | + native |
Index: trunk/extensions/SemanticNotifyMe/includes/jobs/SMW_NMRefreshJob.php |
— | — | @@ -1,18 +1,18 @@ |
2 | 2 | <?php |
3 | 3 | /** |
4 | | - * @author dch
|
| 4 | + * @author dch |
5 | 5 | */ |
6 | 6 | |
7 | | -if ( !defined( 'MEDIAWIKI' ) ) {
|
8 | | - die( "This file is part of the Semantic NotifyMe Extension. It is not a valid entry point.\n" );
|
9 | | -}
|
10 | | -global $IP;
|
11 | | -require_once( "$IP/includes/JobQueue.php" );
|
12 | | -
|
| 7 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 8 | + die( "This file is part of the Semantic NotifyMe Extension. It is not a valid entry point.\n" ); |
| 9 | +} |
| 10 | +global $IP; |
| 11 | +require_once( "$IP/includes/JobQueue.php" ); |
| 12 | + |
13 | 13 | class SMWNMRefreshJob extends Job { |
14 | 14 | |
15 | | - function __construct(Title $title) { |
16 | | - parent::__construct( 'SMWNMRefreshJob', $title); |
| 15 | + function __construct( Title $title ) { |
| 16 | + parent::__construct( 'SMWNMRefreshJob', $title ); |
17 | 17 | } |
18 | 18 | |
19 | 19 | /** |
— | — | @@ -20,9 +20,9 @@ |
21 | 21 | * @return boolean success |
22 | 22 | */ |
23 | 23 | function run() { |
24 | | - wfProfileIn('SMWNMRefreshJob::run (SMW)');
|
25 | | - SMWNotifyProcessor::refreshNotifyMe();
|
26 | | - wfProfileOut('SMWNMRefreshJob::run (SMW)'); |
| 24 | + wfProfileIn( 'SMWNMRefreshJob::run (SMW)' ); |
| 25 | + SMWNotifyProcessor::refreshNotifyMe(); |
| 26 | + wfProfileOut( 'SMWNMRefreshJob::run (SMW)' ); |
27 | 27 | return true; |
28 | 28 | } |
29 | 29 | |
— | — | @@ -34,7 +34,7 @@ |
35 | 35 | */ |
36 | 36 | function insert() { |
37 | 37 | global $smwgEnableUpdateJobs; |
38 | | - if ($smwgEnableUpdateJobs) { |
| 38 | + if ( $smwgEnableUpdateJobs ) { |
39 | 39 | parent::insert(); |
40 | 40 | } |
41 | 41 | } |
Property changes on: trunk/extensions/SemanticNotifyMe/includes/jobs/SMW_NMRefreshJob.php |
___________________________________________________________________ |
Name: svn:eol-style |
42 | 42 | + native |
Index: trunk/extensions/SemanticNotifyMe/includes/jobs/SMW_NMSendMailJob.php |
— | — | @@ -1,52 +1,50 @@ |
2 | | -<?php
|
3 | | -/*
|
4 | | - * SMW_NMSendMailJob.php
|
5 | | - *
|
6 | | - * This job is triggered whenever a notify-me page was saved or removed.
|
7 | | - *
|
8 | | - * @author dch
|
9 | | - *
|
10 | | - */
|
11 | | -if ( !defined( 'MEDIAWIKI' ) ) {
|
12 | | - die( "This file is part of the Semantic NotifyMe Extension. It is not a valid entry point.\n" );
|
13 | | -}
|
14 | | -global $IP;
|
15 | | -require_once( "$IP/includes/JobQueue.php" );
|
16 | | -
|
17 | | -
|
18 | | -class SMW_NMSendMailJob extends Job {
|
19 | | -
|
20 | | - /**
|
21 | | - * Creates a NMSendMailJob
|
22 | | - *
|
23 | | - * @param Title $title
|
24 | | - */
|
25 | | - function __construct($title, $params) {
|
26 | | - wfDebug(__METHOD__." ".get_class($this)." \r\n");
|
27 | | - wfProfileIn( __METHOD__ );
|
28 | | - parent::__construct( get_class($this), Title::newMainPage(), $params);
|
29 | | -
|
30 | | - wfProfileOut( __METHOD__ );
|
31 | | - }
|
32 | | -
|
33 | | - /**
|
34 | | - * Run a SMW_NMSendMailJob job
|
35 | | - * @return boolean success
|
36 | | - */
|
37 | | - function run() {
|
38 | | - wfDebug(__METHOD__);
|
39 | | - wfProfileIn( __METHOD__ );
|
40 | | -
|
41 | | - UserMailer::send( //userMailer(
|
42 | | - $this->params['to'],
|
43 | | - $this->params['from'],
|
44 | | - $this->params['subj'],
|
45 | | - $this->params['body'],
|
46 | | - $this->params['replyto']
|
47 | | - );
|
48 | | -
|
49 | | - wfProfileOut( __METHOD__ );
|
50 | | - return true;
|
51 | | - }
|
52 | | -}
|
53 | | -?>
|
| 2 | +<?php |
| 3 | +/* |
| 4 | + * SMW_NMSendMailJob.php |
| 5 | + * |
| 6 | + * This job is triggered whenever a notify-me page was saved or removed. |
| 7 | + * |
| 8 | + * @author dch |
| 9 | + * |
| 10 | + */ |
| 11 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 12 | + die( "This file is part of the Semantic NotifyMe Extension. It is not a valid entry point.\n" ); |
| 13 | +} |
| 14 | +global $IP; |
| 15 | +require_once( "$IP/includes/JobQueue.php" ); |
| 16 | + |
| 17 | +class SMW_NMSendMailJob extends Job { |
| 18 | + |
| 19 | + /** |
| 20 | + * Creates a NMSendMailJob |
| 21 | + * |
| 22 | + * @param Title $title |
| 23 | + */ |
| 24 | + function __construct( $title, $params ) { |
| 25 | + wfDebug( __METHOD__ . " " . get_class( $this ) . " \r\n" ); |
| 26 | + wfProfileIn( __METHOD__ ); |
| 27 | + parent::__construct( get_class( $this ), Title::newMainPage(), $params ); |
| 28 | + |
| 29 | + wfProfileOut( __METHOD__ ); |
| 30 | + } |
| 31 | + |
| 32 | + /** |
| 33 | + * Run a SMW_NMSendMailJob job |
| 34 | + * @return boolean success |
| 35 | + */ |
| 36 | + function run() { |
| 37 | + wfDebug( __METHOD__ ); |
| 38 | + wfProfileIn( __METHOD__ ); |
| 39 | + |
| 40 | + UserMailer::send( // userMailer( |
| 41 | + $this->params['to'], |
| 42 | + $this->params['from'], |
| 43 | + $this->params['subj'], |
| 44 | + $this->params['body'], |
| 45 | + $this->params['replyto'] |
| 46 | + ); |
| 47 | + |
| 48 | + wfProfileOut( __METHOD__ ); |
| 49 | + return true; |
| 50 | + } |
| 51 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/includes/jobs/SMW_NMSendMailJob.php |
___________________________________________________________________ |
Name: svn:eol-style |
54 | 52 | + native |
Index: trunk/extensions/SemanticNotifyMe/languages/SMW_NMLanguage.php |
— | — | @@ -1,138 +1,133 @@ |
2 | | -<?php
|
3 | | -/**
|
4 | | - * @author dch
|
5 | | - */
|
6 | | -
|
7 | | -/**
|
8 | | - * Base class for all language classes.
|
9 | | - */
|
10 | | -abstract class SMW_NMLanguage {
|
11 | | -
|
12 | | - // the message arrays ...
|
13 | | - protected $smwContentMessages;
|
14 | | - protected $smwUserMessages;
|
15 | | - protected $smwDatatypeLabels;
|
16 | | - protected $smwSpecialProperties;
|
17 | | - protected $smwSpecialSchemaProperties;
|
18 | | - protected $smwNMDatatypes;
|
19 | | - protected $smwNMNamespaces;
|
20 | | - protected $smwNMNamespaceAliases;
|
21 | | -
|
22 | | - /**
|
23 | | - * Function that returns an array of namespace identifiers. This function
|
24 | | - * is obsolete
|
25 | | - */
|
26 | | - abstract function getNamespaceArray();
|
27 | | -
|
28 | | -
|
29 | | - /**
|
30 | | - * Find the internal message id of some localised message string
|
31 | | - * for a datatype. If no type of the given name exists (maybe a
|
32 | | - * custom of compound type) then FALSE is returned.
|
33 | | - */
|
34 | | - function findDatatypeMsgID($label) {
|
35 | | - return array_search($label, $this->smwDatatypeLabels);
|
36 | | - }
|
37 | | -
|
38 | | - /**
|
39 | | - * Registers all special properties of this extension in Semantic Media Wiki.
|
40 | | - *
|
41 | | - * The language files of the NM extension contain a mapping from special
|
42 | | - * property constants to their string representation. These mappings are
|
43 | | - * added to the mapping defined by Semantic Media Wiki.
|
44 | | - */
|
45 | | - function registerSpecialProperties() {
|
46 | | - global $smwgContLang;
|
47 | | - foreach ($this->smwSpecialProperties as $key => $prop) {
|
48 | | - list($typeid, $label) = $prop;
|
49 | | - SMWPropertyValue::registerProperty($key, $typeid, $label, true);
|
50 | | -
|
51 | | - }
|
52 | | - }
|
53 | | -
|
54 | | - /**
|
55 | | - * Returns the label of the special property with the ID $propID.
|
56 | | - * @param int propID
|
57 | | - * ID of the special property
|
58 | | - * @return String Label of the special property
|
59 | | - */
|
60 | | - function getSpecialPropertyLabel($propID) {
|
61 | | - return $this->smwSpecialProperties[$propID];
|
62 | | - }
|
63 | | -
|
64 | | - /**
|
65 | | - * Returns all labels of the special properties.
|
66 | | - * @return array<String> Labels of the special properties
|
67 | | - */
|
68 | | - function getSpecialPropertyLabels() {
|
69 | | - return $this->smwSpecialProperties;
|
70 | | - }
|
71 | | -
|
72 | | - function getSpecialSchemaPropertyArray() {
|
73 | | - return $this->smwSpecialSchemaProperties;
|
74 | | - }
|
75 | | -
|
76 | | - function getSpecialCategoryArray() {
|
77 | | - return $this->smwSpecialCategories;
|
78 | | - }
|
79 | | -
|
80 | | - function getNMDatatype($datatypeID) {
|
81 | | - return $this->smwNMDatatypes[$datatypeID];
|
82 | | - }
|
83 | | -
|
84 | | - /**
|
85 | | - * Function that returns all content messages (those that are stored
|
86 | | - * in some article, and can thus not be translated to individual users).
|
87 | | - */
|
88 | | - function getContentMsgArray() {
|
89 | | - return $this->smwContentMessages;
|
90 | | - }
|
91 | | -
|
92 | | - /**
|
93 | | - * Function that returns all user messages (those that are given only to
|
94 | | - * the current user, and can thus be given in the individual user language).
|
95 | | - */
|
96 | | - function getUserMsgArray() {
|
97 | | - return $this->smwUserMessages;
|
98 | | - }
|
99 | | -
|
100 | | - /**
|
101 | | - * Returns the name of the namespace with the ID <$namespaceID>.
|
102 | | - *
|
103 | | - * @param int $namespaceID
|
104 | | - * ID of the namespace whose name is requested
|
105 | | - * @return string
|
106 | | - * Name of the namespace or <null>.
|
107 | | - *
|
108 | | - */
|
109 | | - public function getNamespace($namespaceID) {
|
110 | | - return $this->smwNMNamespaces[$namespaceID];
|
111 | | - }
|
112 | | -
|
113 | | - /**
|
114 | | - * Returns the array with all namespaces of the NM extension.
|
115 | | - *
|
116 | | - * @return string
|
117 | | - * Array of additional namespaces.
|
118 | | - *
|
119 | | - */
|
120 | | - public function getNamespaces() {
|
121 | | - return $this->smwNMNamespaces;
|
122 | | - }
|
123 | | -
|
124 | | - /**
|
125 | | - * Returns the array with all namespace aliases of the NM extension.
|
126 | | - *
|
127 | | - * @return string
|
128 | | - * Array of additional namespace aliases.
|
129 | | - *
|
130 | | - */
|
131 | | - public function getNamespaceAliases() {
|
132 | | - return $this->smwNMNamespaceAliases;
|
133 | | - }
|
134 | | -
|
135 | | -
|
136 | | -
|
137 | | -}
|
138 | | -
|
139 | | -
|
| 2 | +<?php |
| 3 | +/** |
| 4 | + * @author dch |
| 5 | + */ |
| 6 | + |
| 7 | +/** |
| 8 | + * Base class for all language classes. |
| 9 | + */ |
| 10 | +abstract class SMW_NMLanguage { |
| 11 | + |
| 12 | + // the message arrays ... |
| 13 | + protected $smwContentMessages; |
| 14 | + protected $smwUserMessages; |
| 15 | + protected $smwDatatypeLabels; |
| 16 | + protected $smwSpecialProperties; |
| 17 | + protected $smwSpecialSchemaProperties; |
| 18 | + protected $smwNMDatatypes; |
| 19 | + protected $smwNMNamespaces; |
| 20 | + protected $smwNMNamespaceAliases; |
| 21 | + |
| 22 | + /** |
| 23 | + * Function that returns an array of namespace identifiers. This function |
| 24 | + * is obsolete |
| 25 | + */ |
| 26 | + abstract function getNamespaceArray(); |
| 27 | + |
| 28 | + |
| 29 | + /** |
| 30 | + * Find the internal message id of some localised message string |
| 31 | + * for a datatype. If no type of the given name exists (maybe a |
| 32 | + * custom of compound type) then FALSE is returned. |
| 33 | + */ |
| 34 | + function findDatatypeMsgID( $label ) { |
| 35 | + return array_search( $label, $this->smwDatatypeLabels ); |
| 36 | + } |
| 37 | + |
| 38 | + /** |
| 39 | + * Registers all special properties of this extension in Semantic Media Wiki. |
| 40 | + * |
| 41 | + * The language files of the NM extension contain a mapping from special |
| 42 | + * property constants to their string representation. These mappings are |
| 43 | + * added to the mapping defined by Semantic Media Wiki. |
| 44 | + */ |
| 45 | + function registerSpecialProperties() { |
| 46 | + global $smwgContLang; |
| 47 | + foreach ( $this->smwSpecialProperties as $key => $prop ) { |
| 48 | + list( $typeid, $label ) = $prop; |
| 49 | + SMWPropertyValue::registerProperty( $key, $typeid, $label, true ); |
| 50 | + |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | + /** |
| 55 | + * Returns the label of the special property with the ID $propID. |
| 56 | + * @param int propID |
| 57 | + * ID of the special property |
| 58 | + * @return String Label of the special property |
| 59 | + */ |
| 60 | + function getSpecialPropertyLabel( $propID ) { |
| 61 | + return $this->smwSpecialProperties[$propID]; |
| 62 | + } |
| 63 | + |
| 64 | + /** |
| 65 | + * Returns all labels of the special properties. |
| 66 | + * @return array<String> Labels of the special properties |
| 67 | + */ |
| 68 | + function getSpecialPropertyLabels() { |
| 69 | + return $this->smwSpecialProperties; |
| 70 | + } |
| 71 | + |
| 72 | + function getSpecialSchemaPropertyArray() { |
| 73 | + return $this->smwSpecialSchemaProperties; |
| 74 | + } |
| 75 | + |
| 76 | + function getSpecialCategoryArray() { |
| 77 | + return $this->smwSpecialCategories; |
| 78 | + } |
| 79 | + |
| 80 | + function getNMDatatype( $datatypeID ) { |
| 81 | + return $this->smwNMDatatypes[$datatypeID]; |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * Function that returns all content messages (those that are stored |
| 86 | + * in some article, and can thus not be translated to individual users). |
| 87 | + */ |
| 88 | + function getContentMsgArray() { |
| 89 | + return $this->smwContentMessages; |
| 90 | + } |
| 91 | + |
| 92 | + /** |
| 93 | + * Function that returns all user messages (those that are given only to |
| 94 | + * the current user, and can thus be given in the individual user language). |
| 95 | + */ |
| 96 | + function getUserMsgArray() { |
| 97 | + return $this->smwUserMessages; |
| 98 | + } |
| 99 | + |
| 100 | + /** |
| 101 | + * Returns the name of the namespace with the ID <$namespaceID>. |
| 102 | + * |
| 103 | + * @param int $namespaceID |
| 104 | + * ID of the namespace whose name is requested |
| 105 | + * @return string |
| 106 | + * Name of the namespace or <null>. |
| 107 | + * |
| 108 | + */ |
| 109 | + public function getNamespace( $namespaceID ) { |
| 110 | + return $this->smwNMNamespaces[$namespaceID]; |
| 111 | + } |
| 112 | + |
| 113 | + /** |
| 114 | + * Returns the array with all namespaces of the NM extension. |
| 115 | + * |
| 116 | + * @return string |
| 117 | + * Array of additional namespaces. |
| 118 | + * |
| 119 | + */ |
| 120 | + public function getNamespaces() { |
| 121 | + return $this->smwNMNamespaces; |
| 122 | + } |
| 123 | + |
| 124 | + /** |
| 125 | + * Returns the array with all namespace aliases of the NM extension. |
| 126 | + * |
| 127 | + * @return string |
| 128 | + * Array of additional namespace aliases. |
| 129 | + * |
| 130 | + */ |
| 131 | + public function getNamespaceAliases() { |
| 132 | + return $this->smwNMNamespaceAliases; |
| 133 | + } |
| 134 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/languages/SMW_NMLanguage.php |
___________________________________________________________________ |
Name: svn:eol-style |
140 | 135 | + native |
Index: trunk/extensions/SemanticNotifyMe/languages/SMW_NMLanguageEn.php |
— | — | @@ -1,59 +1,53 @@ |
2 | | -<?php
|
3 | | -/**
|
4 | | - * @author dch
|
5 | | - */
|
6 | | -
|
7 | | -global $smwgNMIP;
|
8 | | -include_once($smwgNMIP . '/languages/SMW_NMLanguage.php');
|
9 | | -
|
10 | | -class SMW_NMLanguageEn extends SMW_NMLanguage {
|
11 | | -
|
12 | | - protected $smwContentMessages = array(
|
13 | | -
|
14 | | - );
|
15 | | -
|
16 | | -
|
17 | | - protected $smwUserMessages = array(
|
18 | | - /*Messages for Notify Me*/
|
19 | | - 'notifyme' => 'Notify Me',
|
20 | | - 'smw_notifyme' => 'Notify Me',
|
21 | | -
|
22 | | - 'smw_qi_addNotify' => 'Notify me',
|
23 | | - 'smw_qi_tt_addNotify' => 'Notify me when article-updates meet query condition',
|
24 | | - 'smw_nm_tt_query' => 'Add #ask query to Notify Me',
|
25 | | - 'smw_nm_tt_qtext' => 'Support query in {{#ask syntax',
|
26 | | - 'smw_nm_tt_nmm' => 'Notify Me Manager enable you to control your notifications',
|
27 | | - 'smw_nm_tt_clipboard' => 'Copies your RSS Feed URL to the clipboard so it can easily be inserted into any RSS reader',
|
28 | | - );
|
29 | | -
|
30 | | -
|
31 | | - protected $smwSpecialProperties = array(
|
32 | | - );
|
33 | | -
|
34 | | -
|
35 | | - var $smwSpecialSchemaProperties = array (
|
36 | | - );
|
37 | | -
|
38 | | - var $smwSpecialCategories = array (
|
39 | | - );
|
40 | | -
|
41 | | - var $smwNMDatatypes = array(
|
42 | | - );
|
43 | | -
|
44 | | - protected $smwNMNamespaces = array(
|
45 | | - );
|
46 | | -
|
47 | | - protected $smwNMNamespaceAliases = array(
|
48 | | - );
|
49 | | -
|
50 | | - /**
|
51 | | - * Function that returns the namespace identifiers. This is probably obsolete!
|
52 | | - */
|
53 | | - public function getNamespaceArray() {
|
54 | | - return array();
|
55 | | - }
|
56 | | -
|
57 | | -
|
58 | | -}
|
59 | | -
|
60 | | -
|
| 2 | +<?php |
| 3 | +/** |
| 4 | + * @author dch |
| 5 | + */ |
| 6 | + |
| 7 | +global $smwgNMIP; |
| 8 | +include_once( $smwgNMIP . '/languages/SMW_NMLanguage.php' ); |
| 9 | + |
| 10 | +class SMW_NMLanguageEn extends SMW_NMLanguage { |
| 11 | + protected $smwContentMessages = array( |
| 12 | + |
| 13 | + ); |
| 14 | + |
| 15 | + protected $smwUserMessages = array( |
| 16 | + /*Messages for Notify Me*/ |
| 17 | + 'notifyme' => 'Notify Me', |
| 18 | + 'smw_notifyme' => 'Notify Me', |
| 19 | + |
| 20 | + 'smw_qi_addNotify' => 'Notify me', |
| 21 | + 'smw_qi_tt_addNotify' => 'Notify me when article-updates meet query condition', |
| 22 | + 'smw_nm_tt_query' => 'Add #ask query to Notify Me', |
| 23 | + 'smw_nm_tt_qtext' => 'Support query in {{#ask syntax', |
| 24 | + 'smw_nm_tt_nmm' => 'Notify Me Manager enable you to control your notifications', |
| 25 | + 'smw_nm_tt_clipboard' => 'Copies your RSS Feed URL to the clipboard so it can easily be inserted into any RSS reader', |
| 26 | + ); |
| 27 | + |
| 28 | + |
| 29 | + protected $smwSpecialProperties = array( |
| 30 | + ); |
| 31 | + |
| 32 | + |
| 33 | + var $smwSpecialSchemaProperties = array ( |
| 34 | + ); |
| 35 | + |
| 36 | + var $smwSpecialCategories = array ( |
| 37 | + ); |
| 38 | + |
| 39 | + var $smwNMDatatypes = array( |
| 40 | + ); |
| 41 | + |
| 42 | + protected $smwNMNamespaces = array( |
| 43 | + ); |
| 44 | + |
| 45 | + protected $smwNMNamespaceAliases = array( |
| 46 | + ); |
| 47 | + |
| 48 | + /** |
| 49 | + * Function that returns the namespace identifiers. This is probably obsolete! |
| 50 | + */ |
| 51 | + public function getNamespaceArray() { |
| 52 | + return array(); |
| 53 | + } |
| 54 | +} |
Property changes on: trunk/extensions/SemanticNotifyMe/languages/SMW_NMLanguageEn.php |
___________________________________________________________________ |
Name: svn:eol-style |
61 | 55 | + native |
Index: trunk/extensions/SemanticNotifyMe/COPYING |
— | — | @@ -1,348 +1,348 @@ |
2 | | -The license text below "----" applies to all files within this distribution, other
|
3 | | -than those that are in a directory which contains files named "LICENSE" or
|
4 | | -"COPYING", or a subdirectory thereof. For those files, the license text contained in
|
5 | | -said file overrides any license information contained in directories of smaller depth.
|
6 | | -Alternative licenses are typically used for software that is provided by external
|
7 | | -parties, and merely packaged with the Semantic MediaWiki release for convenience.
|
8 | | -
|
9 | | - GNU GENERAL PUBLIC LICENSE
|
10 | | - Version 2, June 1991
|
11 | | -
|
12 | | - Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
13 | | - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
14 | | - Everyone is permitted to copy and distribute verbatim copies
|
15 | | - of this license document, but changing it is not allowed.
|
16 | | -
|
17 | | - Preamble
|
18 | | -
|
19 | | - The licenses for most software are designed to take away your
|
20 | | -freedom to share and change it. By contrast, the GNU General Public
|
21 | | -License is intended to guarantee your freedom to share and change free
|
22 | | -software--to make sure the software is free for all its users. This
|
23 | | -General Public License applies to most of the Free Software
|
24 | | -Foundation's software and to any other program whose authors commit to
|
25 | | -using it. (Some other Free Software Foundation software is covered by
|
26 | | -the GNU Library General Public License instead.) You can apply it to
|
27 | | -your programs, too.
|
28 | | -
|
29 | | - When we speak of free software, we are referring to freedom, not
|
30 | | -price. Our General Public Licenses are designed to make sure that you
|
31 | | -have the freedom to distribute copies of free software (and charge for
|
32 | | -this service if you wish), that you receive source code or can get it
|
33 | | -if you want it, that you can change the software or use pieces of it
|
34 | | -in new free programs; and that you know you can do these things.
|
35 | | -
|
36 | | - To protect your rights, we need to make restrictions that forbid
|
37 | | -anyone to deny you these rights or to ask you to surrender the rights.
|
38 | | -These restrictions translate to certain responsibilities for you if you
|
39 | | -distribute copies of the software, or if you modify it.
|
40 | | -
|
41 | | - For example, if you distribute copies of such a program, whether
|
42 | | -gratis or for a fee, you must give the recipients all the rights that
|
43 | | -you have. You must make sure that they, too, receive or can get the
|
44 | | -source code. And you must show them these terms so they know their
|
45 | | -rights.
|
46 | | -
|
47 | | - We protect your rights with two steps: (1) copyright the software, and
|
48 | | -(2) offer you this license which gives you legal permission to copy,
|
49 | | -distribute and/or modify the software.
|
50 | | -
|
51 | | - Also, for each author's protection and ours, we want to make certain
|
52 | | -that everyone understands that there is no warranty for this free
|
53 | | -software. If the software is modified by someone else and passed on, we
|
54 | | -want its recipients to know that what they have is not the original, so
|
55 | | -that any problems introduced by others will not reflect on the original
|
56 | | -authors' reputations.
|
57 | | -
|
58 | | - Finally, any free program is threatened constantly by software
|
59 | | -patents. We wish to avoid the danger that redistributors of a free
|
60 | | -program will individually obtain patent licenses, in effect making the
|
61 | | -program proprietary. To prevent this, we have made it clear that any
|
62 | | -patent must be licensed for everyone's free use or not licensed at all.
|
63 | | -
|
64 | | - The precise terms and conditions for copying, distribution and
|
65 | | -modification follow.
|
66 | | -
|
67 | | - GNU GENERAL PUBLIC LICENSE
|
68 | | - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
69 | | -
|
70 | | - 0. This License applies to any program or other work which contains
|
71 | | -a notice placed by the copyright holder saying it may be distributed
|
72 | | -under the terms of this General Public License. The "Program", below,
|
73 | | -refers to any such program or work, and a "work based on the Program"
|
74 | | -means either the Program or any derivative work under copyright law:
|
75 | | -that is to say, a work containing the Program or a portion of it,
|
76 | | -either verbatim or with modifications and/or translated into another
|
77 | | -language. (Hereinafter, translation is included without limitation in
|
78 | | -the term "modification".) Each licensee is addressed as "you".
|
79 | | -
|
80 | | -Activities other than copying, distribution and modification are not
|
81 | | -covered by this License; they are outside its scope. The act of
|
82 | | -running the Program is not restricted, and the output from the Program
|
83 | | -is covered only if its contents constitute a work based on the
|
84 | | -Program (independent of having been made by running the Program).
|
85 | | -Whether that is true depends on what the Program does.
|
86 | | -
|
87 | | - 1. You may copy and distribute verbatim copies of the Program's
|
88 | | -source code as you receive it, in any medium, provided that you
|
89 | | -conspicuously and appropriately publish on each copy an appropriate
|
90 | | -copyright notice and disclaimer of warranty; keep intact all the
|
91 | | -notices that refer to this License and to the absence of any warranty;
|
92 | | -and give any other recipients of the Program a copy of this License
|
93 | | -along with the Program.
|
94 | | -
|
95 | | -You may charge a fee for the physical act of transferring a copy, and
|
96 | | -you may at your option offer warranty protection in exchange for a fee.
|
97 | | -
|
98 | | - 2. You may modify your copy or copies of the Program or any portion
|
99 | | -of it, thus forming a work based on the Program, and copy and
|
100 | | -distribute such modifications or work under the terms of Section 1
|
101 | | -above, provided that you also meet all of these conditions:
|
102 | | -
|
103 | | - a) You must cause the modified files to carry prominent notices
|
104 | | - stating that you changed the files and the date of any change.
|
105 | | -
|
106 | | - b) You must cause any work that you distribute or publish, that in
|
107 | | - whole or in part contains or is derived from the Program or any
|
108 | | - part thereof, to be licensed as a whole at no charge to all third
|
109 | | - parties under the terms of this License.
|
110 | | -
|
111 | | - c) If the modified program normally reads commands interactively
|
112 | | - when run, you must cause it, when started running for such
|
113 | | - interactive use in the most ordinary way, to print or display an
|
114 | | - announcement including an appropriate copyright notice and a
|
115 | | - notice that there is no warranty (or else, saying that you provide
|
116 | | - a warranty) and that users may redistribute the program under
|
117 | | - these conditions, and telling the user how to view a copy of this
|
118 | | - License. (Exception: if the Program itself is interactive but
|
119 | | - does not normally print such an announcement, your work based on
|
120 | | - the Program is not required to print an announcement.)
|
121 | | -
|
122 | | -These requirements apply to the modified work as a whole. If
|
123 | | -identifiable sections of that work are not derived from the Program,
|
124 | | -and can be reasonably considered independent and separate works in
|
125 | | -themselves, then this License, and its terms, do not apply to those
|
126 | | -sections when you distribute them as separate works. But when you
|
127 | | -distribute the same sections as part of a whole which is a work based
|
128 | | -on the Program, the distribution of the whole must be on the terms of
|
129 | | -this License, whose permissions for other licensees extend to the
|
130 | | -entire whole, and thus to each and every part regardless of who wrote it.
|
131 | | -
|
132 | | -Thus, it is not the intent of this section to claim rights or contest
|
133 | | -your rights to work written entirely by you; rather, the intent is to
|
134 | | -exercise the right to control the distribution of derivative or
|
135 | | -collective works based on the Program.
|
136 | | -
|
137 | | -In addition, mere aggregation of another work not based on the Program
|
138 | | -with the Program (or with a work based on the Program) on a volume of
|
139 | | -a storage or distribution medium does not bring the other work under
|
140 | | -the scope of this License.
|
141 | | -
|
142 | | - 3. You may copy and distribute the Program (or a work based on it,
|
143 | | -under Section 2) in object code or executable form under the terms of
|
144 | | -Sections 1 and 2 above provided that you also do one of the following:
|
145 | | -
|
146 | | - a) Accompany it with the complete corresponding machine-readable
|
147 | | - source code, which must be distributed under the terms of Sections
|
148 | | - 1 and 2 above on a medium customarily used for software interchange; or,
|
149 | | -
|
150 | | - b) Accompany it with a written offer, valid for at least three
|
151 | | - years, to give any third party, for a charge no more than your
|
152 | | - cost of physically performing source distribution, a complete
|
153 | | - machine-readable copy of the corresponding source code, to be
|
154 | | - distributed under the terms of Sections 1 and 2 above on a medium
|
155 | | - customarily used for software interchange; or,
|
156 | | -
|
157 | | - c) Accompany it with the information you received as to the offer
|
158 | | - to distribute corresponding source code. (This alternative is
|
159 | | - allowed only for noncommercial distribution and only if you
|
160 | | - received the program in object code or executable form with such
|
161 | | - an offer, in accord with Subsection b above.)
|
162 | | -
|
163 | | -The source code for a work means the preferred form of the work for
|
164 | | -making modifications to it. For an executable work, complete source
|
165 | | -code means all the source code for all modules it contains, plus any
|
166 | | -associated interface definition files, plus the scripts used to
|
167 | | -control compilation and installation of the executable. However, as a
|
168 | | -special exception, the source code distributed need not include
|
169 | | -anything that is normally distributed (in either source or binary
|
170 | | -form) with the major components (compiler, kernel, and so on) of the
|
171 | | -operating system on which the executable runs, unless that component
|
172 | | -itself accompanies the executable.
|
173 | | -
|
174 | | -If distribution of executable or object code is made by offering
|
175 | | -access to copy from a designated place, then offering equivalent
|
176 | | -access to copy the source code from the same place counts as
|
177 | | -distribution of the source code, even though third parties are not
|
178 | | -compelled to copy the source along with the object code.
|
179 | | -
|
180 | | - 4. You may not copy, modify, sublicense, or distribute the Program
|
181 | | -except as expressly provided under this License. Any attempt
|
182 | | -otherwise to copy, modify, sublicense or distribute the Program is
|
183 | | -void, and will automatically terminate your rights under this License.
|
184 | | -However, parties who have received copies, or rights, from you under
|
185 | | -this License will not have their licenses terminated so long as such
|
186 | | -parties remain in full compliance.
|
187 | | -
|
188 | | - 5. You are not required to accept this License, since you have not
|
189 | | -signed it. However, nothing else grants you permission to modify or
|
190 | | -distribute the Program or its derivative works. These actions are
|
191 | | -prohibited by law if you do not accept this License. Therefore, by
|
192 | | -modifying or distributing the Program (or any work based on the
|
193 | | -Program), you indicate your acceptance of this License to do so, and
|
194 | | -all its terms and conditions for copying, distributing or modifying
|
195 | | -the Program or works based on it.
|
196 | | -
|
197 | | - 6. Each time you redistribute the Program (or any work based on the
|
198 | | -Program), the recipient automatically receives a license from the
|
199 | | -original licensor to copy, distribute or modify the Program subject to
|
200 | | -these terms and conditions. You may not impose any further
|
201 | | -restrictions on the recipients' exercise of the rights granted herein.
|
202 | | -You are not responsible for enforcing compliance by third parties to
|
203 | | -this License.
|
204 | | -
|
205 | | - 7. If, as a consequence of a court judgment or allegation of patent
|
206 | | -infringement or for any other reason (not limited to patent issues),
|
207 | | -conditions are imposed on you (whether by court order, agreement or
|
208 | | -otherwise) that contradict the conditions of this License, they do not
|
209 | | -excuse you from the conditions of this License. If you cannot
|
210 | | -distribute so as to satisfy simultaneously your obligations under this
|
211 | | -License and any other pertinent obligations, then as a consequence you
|
212 | | -may not distribute the Program at all. For example, if a patent
|
213 | | -license would not permit royalty-free redistribution of the Program by
|
214 | | -all those who receive copies directly or indirectly through you, then
|
215 | | -the only way you could satisfy both it and this License would be to
|
216 | | -refrain entirely from distribution of the Program.
|
217 | | -
|
218 | | -If any portion of this section is held invalid or unenforceable under
|
219 | | -any particular circumstance, the balance of the section is intended to
|
220 | | -apply and the section as a whole is intended to apply in other
|
221 | | -circumstances.
|
222 | | -
|
223 | | -It is not the purpose of this section to induce you to infringe any
|
224 | | -patents or other property right claims or to contest validity of any
|
225 | | -such claims; this section has the sole purpose of protecting the
|
226 | | -integrity of the free software distribution system, which is
|
227 | | -implemented by public license practices. Many people have made
|
228 | | -generous contributions to the wide range of software distributed
|
229 | | -through that system in reliance on consistent application of that
|
230 | | -system; it is up to the author/donor to decide if he or she is willing
|
231 | | -to distribute software through any other system and a licensee cannot
|
232 | | -impose that choice.
|
233 | | -
|
234 | | -This section is intended to make thoroughly clear what is believed to
|
235 | | -be a consequence of the rest of this License.
|
236 | | -
|
237 | | - 8. If the distribution and/or use of the Program is restricted in
|
238 | | -certain countries either by patents or by copyrighted interfaces, the
|
239 | | -original copyright holder who places the Program under this License
|
240 | | -may add an explicit geographical distribution limitation excluding
|
241 | | -those countries, so that distribution is permitted only in or among
|
242 | | -countries not thus excluded. In such case, this License incorporates
|
243 | | -the limitation as if written in the body of this License.
|
244 | | -
|
245 | | - 9. The Free Software Foundation may publish revised and/or new versions
|
246 | | -of the General Public License from time to time. Such new versions will
|
247 | | -be similar in spirit to the present version, but may differ in detail to
|
248 | | -address new problems or concerns.
|
249 | | -
|
250 | | -Each version is given a distinguishing version number. If the Program
|
251 | | -specifies a version number of this License which applies to it and "any
|
252 | | -later version", you have the option of following the terms and conditions
|
253 | | -either of that version or of any later version published by the Free
|
254 | | -Software Foundation. If the Program does not specify a version number of
|
255 | | -this License, you may choose any version ever published by the Free Software
|
256 | | -Foundation.
|
257 | | -
|
258 | | - 10. If you wish to incorporate parts of the Program into other free
|
259 | | -programs whose distribution conditions are different, write to the author
|
260 | | -to ask for permission. For software which is copyrighted by the Free
|
261 | | -Software Foundation, write to the Free Software Foundation; we sometimes
|
262 | | -make exceptions for this. Our decision will be guided by the two goals
|
263 | | -of preserving the free status of all derivatives of our free software and
|
264 | | -of promoting the sharing and reuse of software generally.
|
265 | | -
|
266 | | - NO WARRANTY
|
267 | | -
|
268 | | - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
269 | | -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
270 | | -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
271 | | -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
272 | | -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
273 | | -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
274 | | -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
275 | | -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
276 | | -REPAIR OR CORRECTION.
|
277 | | -
|
278 | | - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
279 | | -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
280 | | -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
281 | | -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
282 | | -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
283 | | -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
284 | | -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
285 | | -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
286 | | -POSSIBILITY OF SUCH DAMAGES.
|
287 | | -
|
288 | | - END OF TERMS AND CONDITIONS
|
289 | | -
|
290 | | - How to Apply These Terms to Your New Programs
|
291 | | -
|
292 | | - If you develop a new program, and you want it to be of the greatest
|
293 | | -possible use to the public, the best way to achieve this is to make it
|
294 | | -free software which everyone can redistribute and change under these terms.
|
295 | | -
|
296 | | - To do so, attach the following notices to the program. It is safest
|
297 | | -to attach them to the start of each source file to most effectively
|
298 | | -convey the exclusion of warranty; and each file should have at least
|
299 | | -the "copyright" line and a pointer to where the full notice is found.
|
300 | | -
|
301 | | - <one line to give the program's name and a brief idea of what it does.>
|
302 | | - Copyright (C) <year> <name of author>
|
303 | | -
|
304 | | - This program is free software; you can redistribute it and/or modify
|
305 | | - it under the terms of the GNU General Public License as published by
|
306 | | - the Free Software Foundation; either version 2 of the License, or
|
307 | | - (at your option) any later version.
|
308 | | -
|
309 | | - This program is distributed in the hope that it will be useful,
|
310 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of
|
311 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
312 | | - GNU General Public License for more details.
|
313 | | -
|
314 | | - You should have received a copy of the GNU General Public License
|
315 | | - along with this program; if not, write to the Free Software
|
316 | | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
317 | | -
|
318 | | -
|
319 | | -Also add information on how to contact you by electronic and paper mail.
|
320 | | -
|
321 | | -If the program is interactive, make it output a short notice like this
|
322 | | -when it starts in an interactive mode:
|
323 | | -
|
324 | | - Gnomovision version 69, Copyright (C) year name of author
|
325 | | - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
326 | | - This is free software, and you are welcome to redistribute it
|
327 | | - under certain conditions; type `show c' for details.
|
328 | | -
|
329 | | -The hypothetical commands `show w' and `show c' should show the appropriate
|
330 | | -parts of the General Public License. Of course, the commands you use may
|
331 | | -be called something other than `show w' and `show c'; they could even be
|
332 | | -mouse-clicks or menu items--whatever suits your program.
|
333 | | -
|
334 | | -You should also get your employer (if you work as a programmer) or your
|
335 | | -school, if any, to sign a "copyright disclaimer" for the program, if
|
336 | | -necessary. Here is a sample; alter the names:
|
337 | | -
|
338 | | - Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
339 | | - `Gnomovision' (which makes passes at compilers) written by James Hacker.
|
340 | | -
|
341 | | - <signature of Ty Coon>, 1 April 1989
|
342 | | - Ty Coon, President of Vice
|
343 | | -
|
344 | | -This General Public License does not permit incorporating your program into
|
345 | | -proprietary programs. If your program is a subroutine library, you may
|
346 | | -consider it more useful to permit linking proprietary applications with the
|
347 | | -library. If this is what you want to do, use the GNU Library General
|
348 | | -Public License instead of this License.
|
| 2 | +The license text below "----" applies to all files within this distribution, other |
| 3 | +than those that are in a directory which contains files named "LICENSE" or |
| 4 | +"COPYING", or a subdirectory thereof. For those files, the license text contained in |
| 5 | +said file overrides any license information contained in directories of smaller depth. |
| 6 | +Alternative licenses are typically used for software that is provided by external |
| 7 | +parties, and merely packaged with the Semantic MediaWiki release for convenience. |
| 8 | +---- |
| 9 | + |
| 10 | + GNU GENERAL PUBLIC LICENSE |
| 11 | + Version 2, June 1991 |
| 12 | + |
| 13 | + Copyright (C) 1989, 1991 Free Software Foundation, Inc. |
| 14 | + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 15 | + Everyone is permitted to copy and distribute verbatim copies |
| 16 | + of this license document, but changing it is not allowed. |
| 17 | + |
| 18 | + Preamble |
| 19 | + |
| 20 | + The licenses for most software are designed to take away your |
| 21 | +freedom to share and change it. By contrast, the GNU General Public |
| 22 | +License is intended to guarantee your freedom to share and change free |
| 23 | +software--to make sure the software is free for all its users. This |
| 24 | +General Public License applies to most of the Free Software |
| 25 | +Foundation's software and to any other program whose authors commit to |
| 26 | +using it. (Some other Free Software Foundation software is covered by |
| 27 | +the GNU Library General Public License instead.) You can apply it to |
| 28 | +your programs, too. |
| 29 | + |
| 30 | + When we speak of free software, we are referring to freedom, not |
| 31 | +price. Our General Public Licenses are designed to make sure that you |
| 32 | +have the freedom to distribute copies of free software (and charge for |
| 33 | +this service if you wish), that you receive source code or can get it |
| 34 | +if you want it, that you can change the software or use pieces of it |
| 35 | +in new free programs; and that you know you can do these things. |
| 36 | + |
| 37 | + To protect your rights, we need to make restrictions that forbid |
| 38 | +anyone to deny you these rights or to ask you to surrender the rights. |
| 39 | +These restrictions translate to certain responsibilities for you if you |
| 40 | +distribute copies of the software, or if you modify it. |
| 41 | + |
| 42 | + For example, if you distribute copies of such a program, whether |
| 43 | +gratis or for a fee, you must give the recipients all the rights that |
| 44 | +you have. You must make sure that they, too, receive or can get the |
| 45 | +source code. And you must show them these terms so they know their |
| 46 | +rights. |
| 47 | + |
| 48 | + We protect your rights with two steps: (1) copyright the software, and |
| 49 | +(2) offer you this license which gives you legal permission to copy, |
| 50 | +distribute and/or modify the software. |
| 51 | + |
| 52 | + Also, for each author's protection and ours, we want to make certain |
| 53 | +that everyone understands that there is no warranty for this free |
| 54 | +software. If the software is modified by someone else and passed on, we |
| 55 | +want its recipients to know that what they have is not the original, so |
| 56 | +that any problems introduced by others will not reflect on the original |
| 57 | +authors' reputations. |
| 58 | + |
| 59 | + Finally, any free program is threatened constantly by software |
| 60 | +patents. We wish to avoid the danger that redistributors of a free |
| 61 | +program will individually obtain patent licenses, in effect making the |
| 62 | +program proprietary. To prevent this, we have made it clear that any |
| 63 | +patent must be licensed for everyone's free use or not licensed at all. |
| 64 | + |
| 65 | + The precise terms and conditions for copying, distribution and |
| 66 | +modification follow. |
| 67 | + |
| 68 | + GNU GENERAL PUBLIC LICENSE |
| 69 | + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
| 70 | + |
| 71 | + 0. This License applies to any program or other work which contains |
| 72 | +a notice placed by the copyright holder saying it may be distributed |
| 73 | +under the terms of this General Public License. The "Program", below, |
| 74 | +refers to any such program or work, and a "work based on the Program" |
| 75 | +means either the Program or any derivative work under copyright law: |
| 76 | +that is to say, a work containing the Program or a portion of it, |
| 77 | +either verbatim or with modifications and/or translated into another |
| 78 | +language. (Hereinafter, translation is included without limitation in |
| 79 | +the term "modification".) Each licensee is addressed as "you". |
| 80 | + |
| 81 | +Activities other than copying, distribution and modification are not |
| 82 | +covered by this License; they are outside its scope. The act of |
| 83 | +running the Program is not restricted, and the output from the Program |
| 84 | +is covered only if its contents constitute a work based on the |
| 85 | +Program (independent of having been made by running the Program). |
| 86 | +Whether that is true depends on what the Program does. |
| 87 | + |
| 88 | + 1. You may copy and distribute verbatim copies of the Program's |
| 89 | +source code as you receive it, in any medium, provided that you |
| 90 | +conspicuously and appropriately publish on each copy an appropriate |
| 91 | +copyright notice and disclaimer of warranty; keep intact all the |
| 92 | +notices that refer to this License and to the absence of any warranty; |
| 93 | +and give any other recipients of the Program a copy of this License |
| 94 | +along with the Program. |
| 95 | + |
| 96 | +You may charge a fee for the physical act of transferring a copy, and |
| 97 | +you may at your option offer warranty protection in exchange for a fee. |
| 98 | + |
| 99 | + 2. You may modify your copy or copies of the Program or any portion |
| 100 | +of it, thus forming a work based on the Program, and copy and |
| 101 | +distribute such modifications or work under the terms of Section 1 |
| 102 | +above, provided that you also meet all of these conditions: |
| 103 | + |
| 104 | + a) You must cause the modified files to carry prominent notices |
| 105 | + stating that you changed the files and the date of any change. |
| 106 | + |
| 107 | + b) You must cause any work that you distribute or publish, that in |
| 108 | + whole or in part contains or is derived from the Program or any |
| 109 | + part thereof, to be licensed as a whole at no charge to all third |
| 110 | + parties under the terms of this License. |
| 111 | + |
| 112 | + c) If the modified program normally reads commands interactively |
| 113 | + when run, you must cause it, when started running for such |
| 114 | + interactive use in the most ordinary way, to print or display an |
| 115 | + announcement including an appropriate copyright notice and a |
| 116 | + notice that there is no warranty (or else, saying that you provide |
| 117 | + a warranty) and that users may redistribute the program under |
| 118 | + these conditions, and telling the user how to view a copy of this |
| 119 | + License. (Exception: if the Program itself is interactive but |
| 120 | + does not normally print such an announcement, your work based on |
| 121 | + the Program is not required to print an announcement.) |
| 122 | + |
| 123 | +These requirements apply to the modified work as a whole. If |
| 124 | +identifiable sections of that work are not derived from the Program, |
| 125 | +and can be reasonably considered independent and separate works in |
| 126 | +themselves, then this License, and its terms, do not apply to those |
| 127 | +sections when you distribute them as separate works. But when you |
| 128 | +distribute the same sections as part of a whole which is a work based |
| 129 | +on the Program, the distribution of the whole must be on the terms of |
| 130 | +this License, whose permissions for other licensees extend to the |
| 131 | +entire whole, and thus to each and every part regardless of who wrote it. |
| 132 | + |
| 133 | +Thus, it is not the intent of this section to claim rights or contest |
| 134 | +your rights to work written entirely by you; rather, the intent is to |
| 135 | +exercise the right to control the distribution of derivative or |
| 136 | +collective works based on the Program. |
| 137 | + |
| 138 | +In addition, mere aggregation of another work not based on the Program |
| 139 | +with the Program (or with a work based on the Program) on a volume of |
| 140 | +a storage or distribution medium does not bring the other work under |
| 141 | +the scope of this License. |
| 142 | + |
| 143 | + 3. You may copy and distribute the Program (or a work based on it, |
| 144 | +under Section 2) in object code or executable form under the terms of |
| 145 | +Sections 1 and 2 above provided that you also do one of the following: |
| 146 | + |
| 147 | + a) Accompany it with the complete corresponding machine-readable |
| 148 | + source code, which must be distributed under the terms of Sections |
| 149 | + 1 and 2 above on a medium customarily used for software interchange; or, |
| 150 | + |
| 151 | + b) Accompany it with a written offer, valid for at least three |
| 152 | + years, to give any third party, for a charge no more than your |
| 153 | + cost of physically performing source distribution, a complete |
| 154 | + machine-readable copy of the corresponding source code, to be |
| 155 | + distributed under the terms of Sections 1 and 2 above on a medium |
| 156 | + customarily used for software interchange; or, |
| 157 | + |
| 158 | + c) Accompany it with the information you received as to the offer |
| 159 | + to distribute corresponding source code. (This alternative is |
| 160 | + allowed only for noncommercial distribution and only if you |
| 161 | + received the program in object code or executable form with such |
| 162 | + an offer, in accord with Subsection b above.) |
| 163 | + |
| 164 | +The source code for a work means the preferred form of the work for |
| 165 | +making modifications to it. For an executable work, complete source |
| 166 | +code means all the source code for all modules it contains, plus any |
| 167 | +associated interface definition files, plus the scripts used to |
| 168 | +control compilation and installation of the executable. However, as a |
| 169 | +special exception, the source code distributed need not include |
| 170 | +anything that is normally distributed (in either source or binary |
| 171 | +form) with the major components (compiler, kernel, and so on) of the |
| 172 | +operating system on which the executable runs, unless that component |
| 173 | +itself accompanies the executable. |
| 174 | + |
| 175 | +If distribution of executable or object code is made by offering |
| 176 | +access to copy from a designated place, then offering equivalent |
| 177 | +access to copy the source code from the same place counts as |
| 178 | +distribution of the source code, even though third parties are not |
| 179 | +compelled to copy the source along with the object code. |
| 180 | + |
| 181 | + 4. You may not copy, modify, sublicense, or distribute the Program |
| 182 | +except as expressly provided under this License. Any attempt |
| 183 | +otherwise to copy, modify, sublicense or distribute the Program is |
| 184 | +void, and will automatically terminate your rights under this License. |
| 185 | +However, parties who have received copies, or rights, from you under |
| 186 | +this License will not have their licenses terminated so long as such |
| 187 | +parties remain in full compliance. |
| 188 | + |
| 189 | + 5. You are not required to accept this License, since you have not |
| 190 | +signed it. However, nothing else grants you permission to modify or |
| 191 | +distribute the Program or its derivative works. These actions are |
| 192 | +prohibited by law if you do not accept this License. Therefore, by |
| 193 | +modifying or distributing the Program (or any work based on the |
| 194 | +Program), you indicate your acceptance of this License to do so, and |
| 195 | +all its terms and conditions for copying, distributing or modifying |
| 196 | +the Program or works based on it. |
| 197 | + |
| 198 | + 6. Each time you redistribute the Program (or any work based on the |
| 199 | +Program), the recipient automatically receives a license from the |
| 200 | +original licensor to copy, distribute or modify the Program subject to |
| 201 | +these terms and conditions. You may not impose any further |
| 202 | +restrictions on the recipients' exercise of the rights granted herein. |
| 203 | +You are not responsible for enforcing compliance by third parties to |
| 204 | +this License. |
| 205 | + |
| 206 | + 7. If, as a consequence of a court judgment or allegation of patent |
| 207 | +infringement or for any other reason (not limited to patent issues), |
| 208 | +conditions are imposed on you (whether by court order, agreement or |
| 209 | +otherwise) that contradict the conditions of this License, they do not |
| 210 | +excuse you from the conditions of this License. If you cannot |
| 211 | +distribute so as to satisfy simultaneously your obligations under this |
| 212 | +License and any other pertinent obligations, then as a consequence you |
| 213 | +may not distribute the Program at all. For example, if a patent |
| 214 | +license would not permit royalty-free redistribution of the Program by |
| 215 | +all those who receive copies directly or indirectly through you, then |
| 216 | +the only way you could satisfy both it and this License would be to |
| 217 | +refrain entirely from distribution of the Program. |
| 218 | + |
| 219 | +If any portion of this section is held invalid or unenforceable under |
| 220 | +any particular circumstance, the balance of the section is intended to |
| 221 | +apply and the section as a whole is intended to apply in other |
| 222 | +circumstances. |
| 223 | + |
| 224 | +It is not the purpose of this section to induce you to infringe any |
| 225 | +patents or other property right claims or to contest validity of any |
| 226 | +such claims; this section has the sole purpose of protecting the |
| 227 | +integrity of the free software distribution system, which is |
| 228 | +implemented by public license practices. Many people have made |
| 229 | +generous contributions to the wide range of software distributed |
| 230 | +through that system in reliance on consistent application of that |
| 231 | +system; it is up to the author/donor to decide if he or she is willing |
| 232 | +to distribute software through any other system and a licensee cannot |
| 233 | +impose that choice. |
| 234 | + |
| 235 | +This section is intended to make thoroughly clear what is believed to |
| 236 | +be a consequence of the rest of this License. |
| 237 | + |
| 238 | + 8. If the distribution and/or use of the Program is restricted in |
| 239 | +certain countries either by patents or by copyrighted interfaces, the |
| 240 | +original copyright holder who places the Program under this License |
| 241 | +may add an explicit geographical distribution limitation excluding |
| 242 | +those countries, so that distribution is permitted only in or among |
| 243 | +countries not thus excluded. In such case, this License incorporates |
| 244 | +the limitation as if written in the body of this License. |
| 245 | + |
| 246 | + 9. The Free Software Foundation may publish revised and/or new versions |
| 247 | +of the General Public License from time to time. Such new versions will |
| 248 | +be similar in spirit to the present version, but may differ in detail to |
| 249 | +address new problems or concerns. |
| 250 | + |
| 251 | +Each version is given a distinguishing version number. If the Program |
| 252 | +specifies a version number of this License which applies to it and "any |
| 253 | +later version", you have the option of following the terms and conditions |
| 254 | +either of that version or of any later version published by the Free |
| 255 | +Software Foundation. If the Program does not specify a version number of |
| 256 | +this License, you may choose any version ever published by the Free Software |
| 257 | +Foundation. |
| 258 | + |
| 259 | + 10. If you wish to incorporate parts of the Program into other free |
| 260 | +programs whose distribution conditions are different, write to the author |
| 261 | +to ask for permission. For software which is copyrighted by the Free |
| 262 | +Software Foundation, write to the Free Software Foundation; we sometimes |
| 263 | +make exceptions for this. Our decision will be guided by the two goals |
| 264 | +of preserving the free status of all derivatives of our free software and |
| 265 | +of promoting the sharing and reuse of software generally. |
| 266 | + |
| 267 | + NO WARRANTY |
| 268 | + |
| 269 | + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY |
| 270 | +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN |
| 271 | +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES |
| 272 | +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED |
| 273 | +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| 274 | +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS |
| 275 | +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE |
| 276 | +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, |
| 277 | +REPAIR OR CORRECTION. |
| 278 | + |
| 279 | + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING |
| 280 | +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR |
| 281 | +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, |
| 282 | +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING |
| 283 | +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED |
| 284 | +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY |
| 285 | +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER |
| 286 | +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE |
| 287 | +POSSIBILITY OF SUCH DAMAGES. |
| 288 | + |
| 289 | + END OF TERMS AND CONDITIONS |
| 290 | + |
| 291 | + How to Apply These Terms to Your New Programs |
| 292 | + |
| 293 | + If you develop a new program, and you want it to be of the greatest |
| 294 | +possible use to the public, the best way to achieve this is to make it |
| 295 | +free software which everyone can redistribute and change under these terms. |
| 296 | + |
| 297 | + To do so, attach the following notices to the program. It is safest |
| 298 | +to attach them to the start of each source file to most effectively |
| 299 | +convey the exclusion of warranty; and each file should have at least |
| 300 | +the "copyright" line and a pointer to where the full notice is found. |
| 301 | + |
| 302 | + <one line to give the program's name and a brief idea of what it does.> |
| 303 | + Copyright (C) <year> <name of author> |
| 304 | + |
| 305 | + This program is free software; you can redistribute it and/or modify |
| 306 | + it under the terms of the GNU General Public License as published by |
| 307 | + the Free Software Foundation; either version 2 of the License, or |
| 308 | + (at your option) any later version. |
| 309 | + |
| 310 | + This program is distributed in the hope that it will be useful, |
| 311 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 312 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 313 | + GNU General Public License for more details. |
| 314 | + |
| 315 | + You should have received a copy of the GNU General Public License |
| 316 | + along with this program; if not, write to the Free Software |
| 317 | + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 318 | + |
| 319 | + |
| 320 | +Also add information on how to contact you by electronic and paper mail. |
| 321 | + |
| 322 | +If the program is interactive, make it output a short notice like this |
| 323 | +when it starts in an interactive mode: |
| 324 | + |
| 325 | + Gnomovision version 69, Copyright (C) year name of author |
| 326 | + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. |
| 327 | + This is free software, and you are welcome to redistribute it |
| 328 | + under certain conditions; type `show c' for details. |
| 329 | + |
| 330 | +The hypothetical commands `show w' and `show c' should show the appropriate |
| 331 | +parts of the General Public License. Of course, the commands you use may |
| 332 | +be called something other than `show w' and `show c'; they could even be |
| 333 | +mouse-clicks or menu items--whatever suits your program. |
| 334 | + |
| 335 | +You should also get your employer (if you work as a programmer) or your |
| 336 | +school, if any, to sign a "copyright disclaimer" for the program, if |
| 337 | +necessary. Here is a sample; alter the names: |
| 338 | + |
| 339 | + Yoyodyne, Inc., hereby disclaims all copyright interest in the program |
| 340 | + `Gnomovision' (which makes passes at compilers) written by James Hacker. |
| 341 | + |
| 342 | + <signature of Ty Coon>, 1 April 1989 |
| 343 | + Ty Coon, President of Vice |
| 344 | + |
| 345 | +This General Public License does not permit incorporating your program into |
| 346 | +proprietary programs. If your program is a subroutine library, you may |
| 347 | +consider it more useful to permit linking proprietary applications with the |
| 348 | +library. If this is what you want to do, use the GNU Library General |
| 349 | +Public License instead of this License. |
Property changes on: trunk/extensions/SemanticNotifyMe/COPYING |
___________________________________________________________________ |
Name: svn:eol-style |
349 | 350 | + native |
Index: trunk/extensions/SemanticNotifyMe/README |
— | — | @@ -1,29 +1,29 @@ |
2 | | -== About ==
|
3 | | -
|
4 | | -Semantic NotifyMe is a project for extending Semantic MediaWiki extension with
|
5 | | -"realtime notification" functions that allows users to get realtime notifications
|
6 | | -on semantic property-value changes. For details and further links, see
|
7 | | -http://www.mediawiki.org/wiki/Extension:Semantic_NotifyMe.
|
8 | | -
|
9 | | -Notes on installing Semantic NotifyMe are found in the file INSTALL.
|
10 | | -
|
11 | | -== Contact ==
|
12 | | -
|
13 | | -If you have remarks, questions, or suggestions, please send them to
|
14 | | -ning@teammersion.com.
|
15 | | -
|
16 | | -Bugs should be filed at MediaZilla, http://bugzilla.wikimedia.org/.
|
17 | | -
|
18 | | -== Developers ==
|
19 | | -
|
20 | | -Development is coordinated by Ning Hu and Justin Zhang.
|
21 | | -
|
22 | | -Semantic NotifyMe development is funded by Vulcan Inc.
|
23 | | -Semantic NotifyMe has also been supported in the Halo
|
24 | | -project funded by Vulcan Inc., where development is coordinated
|
25 | | -by ontoprise GmbH, Karlsruhe, Germany.
|
26 | | -
|
27 | | -== Contributors ==
|
28 | | -
|
29 | | -N/A
|
30 | | -
|
| 2 | +== About == |
| 3 | + |
| 4 | +Semantic NotifyMe is a project for extending Semantic MediaWiki extension with |
| 5 | +"realtime notification" functions that allows users to get realtime notifications |
| 6 | +on semantic property-value changes. For details and further links, see |
| 7 | +http://www.mediawiki.org/wiki/Extension:Semantic_NotifyMe. |
| 8 | + |
| 9 | +Notes on installing Semantic NotifyMe are found in the file INSTALL. |
| 10 | + |
| 11 | +== Contact == |
| 12 | + |
| 13 | +If you have remarks, questions, or suggestions, please send them to |
| 14 | +ning@teammersion.com. |
| 15 | + |
| 16 | +Bugs should be filed at MediaZilla, http://bugzilla.wikimedia.org/. |
| 17 | + |
| 18 | +== Developers == |
| 19 | + |
| 20 | +Development is coordinated by Ning Hu and Justin Zhang. |
| 21 | + |
| 22 | +Semantic NotifyMe development is funded by Vulcan Inc. |
| 23 | +Semantic NotifyMe has also been supported in the Halo |
| 24 | +project funded by Vulcan Inc., where development is coordinated |
| 25 | +by ontoprise GmbH, Karlsruhe, Germany. |
| 26 | + |
| 27 | +== Contributors == |
| 28 | + |
| 29 | +N/A |
| 30 | + |
Property changes on: trunk/extensions/SemanticNotifyMe/README |
___________________________________________________________________ |
Name: svn:eol-style |
31 | 31 | + native |