From c1bc3607f85e62b65a3f17fdd02fb670517f2ea5 Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Sat, 4 Jan 2014 00:44:50 -0800 Subject: [PATCH] Add XMLRCFeedFormatter Endpoints like XMPP natively support sending XML, which can be advantageous in some cases. Since most of the logic is the same as the existing JSONRCFeedFormatter, it was moved into an abstract MachineReadableRCFeedFormatter class, which simply creates the array and lets the implementations format it. Change-Id: I44f22777cb55fc1ca6527b79ef40b340e2afbd58 --- includes/AutoLoader.php | 2 + includes/rcfeed/JSONRCFeedFormatter.php | 87 +----------- .../rcfeed/MachineReadableRCFeedFormatter.php | 128 ++++++++++++++++++ includes/rcfeed/XMLRCFeedFormatter.php | 30 ++++ 4 files changed, 162 insertions(+), 85 deletions(-) create mode 100644 includes/rcfeed/MachineReadableRCFeedFormatter.php create mode 100644 includes/rcfeed/XMLRCFeedFormatter.php diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index 6436f3bdca..0e56b7cc23 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -842,6 +842,8 @@ $wgAutoloadLocalClasses = array( 'RCFeedFormatter' => 'includes/rcfeed/RCFeedFormatter.php', 'IRCColourfulRCFeedFormatter' => 'includes/rcfeed/IRCColourfulRCFeedFormatter.php', 'JSONRCFeedFormatter' => 'includes/rcfeed/JSONRCFeedFormatter.php', + 'XMLRCFeedFormatter' => 'includes/rcfeed/XMLRCFeedFormatter.php', + 'MachineReadableRCFeedFormatter' => 'includes/rcfeed/MachineReadableRCFeedFormatter.php', # includes/resourceloader 'ResourceLoader' => 'includes/resourceloader/ResourceLoader.php', diff --git a/includes/rcfeed/JSONRCFeedFormatter.php b/includes/rcfeed/JSONRCFeedFormatter.php index 063cb90b40..98d3f025d5 100644 --- a/includes/rcfeed/JSONRCFeedFormatter.php +++ b/includes/rcfeed/JSONRCFeedFormatter.php @@ -24,92 +24,9 @@ * * @since 1.22 */ +class JSONRCFeedFormatter extends MachineReadableRCFeedFormatter { -class JSONRCFeedFormatter implements RCFeedFormatter { - /** - * Generates a notification that can be easily interpreted by a machine. - * @see RCFeedFormatter::getLine - */ - public function getLine( array $feed, RecentChange $rc, $actionComment ) { - global $wgCanonicalServer, $wgScriptPath, $wgDBname; - $attrib = $rc->getAttributes(); - - $packet = array( - // Usually, RC ID is exposed only for patrolling purposes, - // but there is no real reason not to expose it in other cases, - // and I can see how this may be potentially useful for clients. - 'id' => $attrib['rc_id'], - 'type' => $attrib['rc_type'], - 'namespace' => $rc->getTitle()->getNamespace(), - 'title' => $rc->getTitle()->getPrefixedText(), - 'comment' => $attrib['rc_comment'], - 'timestamp' => (int)wfTimestamp( TS_UNIX, $attrib['rc_timestamp'] ), - 'user' => $attrib['rc_user_text'], - 'bot' => (bool)$attrib['rc_bot'], - ); - - if ( isset( $feed['channel'] ) ) { - $packet['channel'] = $feed['channel']; - } - - $type = $attrib['rc_type']; - if ( $type == RC_EDIT || $type == RC_NEW ) { - global $wgUseRCPatrol, $wgUseNPPatrol; - - $packet['minor'] = $attrib['rc_minor']; - if ( $wgUseRCPatrol || ( $type == RC_NEW && $wgUseNPPatrol ) ) { - $packet['patrolled'] = $attrib['rc_patrolled']; - } - } - - switch ( $type ) { - case RC_EDIT: - $packet['length'] = array( 'old' => $attrib['rc_old_len'], 'new' => $attrib['rc_new_len'] ); - $packet['revision'] = array( 'old' => $attrib['rc_last_oldid'], 'new' => $attrib['rc_this_oldid'] ); - break; - - case RC_NEW: - $packet['length'] = array( 'old' => null, 'new' => $attrib['rc_new_len'] ); - $packet['revision'] = array( 'old' => null, 'new' => $attrib['rc_this_oldid'] ); - break; - - case RC_LOG: - $packet['log_type'] = $attrib['rc_log_type']; - $packet['log_action'] = $attrib['rc_log_action']; - if ( $attrib['rc_params'] ) { - wfSuppressWarnings(); - $params = unserialize( $attrib['rc_params'] ); - wfRestoreWarnings(); - if ( - // If it's an actual serialised false... - $attrib['rc_params'] == serialize( false ) || - // Or if we did not get false back when trying to unserialise - $params !== false - ) { - // From ApiQueryLogEvents::addLogParams - $logParams = array(); - // Keys like "4::paramname" can't be used for output so we change them to "paramname" - foreach ( $params as $key => $value ) { - if ( strpos( $key, ':' ) === false ) { - $logParams[$key] = $value; - continue; - } - $logParam = explode( ':', $key, 3 ); - $logParams[$logParam[2]] = $value; - } - $packet['log_params'] = $logParams; - } else { - $packet['log_params'] = explode( "\n", $attrib['rc_params'] ); - } - } - $packet['log_action_comment'] = $actionComment; - break; - } - - $packet['server_url'] = $wgCanonicalServer; - $packet['server_script_path'] = $wgScriptPath ?: '/'; - $packet['wiki'] = $wgDBname; - + protected function formatArray( array $packet ) { return FormatJson::encode( $packet ); } } diff --git a/includes/rcfeed/MachineReadableRCFeedFormatter.php b/includes/rcfeed/MachineReadableRCFeedFormatter.php new file mode 100644 index 0000000000..565d0eb6d4 --- /dev/null +++ b/includes/rcfeed/MachineReadableRCFeedFormatter.php @@ -0,0 +1,128 @@ +getAttributes(); + + $packet = array( + // Usually, RC ID is exposed only for patrolling purposes, + // but there is no real reason not to expose it in other cases, + // and I can see how this may be potentially useful for clients. + 'id' => $attrib['rc_id'], + 'type' => $attrib['rc_type'], + 'namespace' => $rc->getTitle()->getNamespace(), + 'title' => $rc->getTitle()->getPrefixedText(), + 'comment' => $attrib['rc_comment'], + 'timestamp' => (int)wfTimestamp( TS_UNIX, $attrib['rc_timestamp'] ), + 'user' => $attrib['rc_user_text'], + 'bot' => (bool)$attrib['rc_bot'], + ); + + if ( isset( $feed['channel'] ) ) { + $packet['channel'] = $feed['channel']; + } + + $type = $attrib['rc_type']; + if ( $type == RC_EDIT || $type == RC_NEW ) { + global $wgUseRCPatrol, $wgUseNPPatrol; + + $packet['minor'] = $attrib['rc_minor']; + if ( $wgUseRCPatrol || ( $type == RC_NEW && $wgUseNPPatrol ) ) { + $packet['patrolled'] = $attrib['rc_patrolled']; + } + } + + switch ( $type ) { + case RC_EDIT: + $packet['length'] = array( + 'old' => $attrib['rc_old_len'], + 'new' => $attrib['rc_new_len'] + ); + $packet['revision'] = array( + 'old' => $attrib['rc_last_oldid'], + 'new' => $attrib['rc_this_oldid'] + ); + break; + + case RC_NEW: + $packet['length'] = array( 'old' => null, 'new' => $attrib['rc_new_len'] ); + $packet['revision'] = array( 'old' => null, 'new' => $attrib['rc_this_oldid'] ); + break; + + case RC_LOG: + $packet['log_type'] = $attrib['rc_log_type']; + $packet['log_action'] = $attrib['rc_log_action']; + if ( $attrib['rc_params'] ) { + wfSuppressWarnings(); + $params = unserialize( $attrib['rc_params'] ); + wfRestoreWarnings(); + if ( + // If it's an actual serialised false... + $attrib['rc_params'] == serialize( false ) || + // Or if we did not get false back when trying to unserialise + $params !== false + ) { + // From ApiQueryLogEvents::addLogParams + $logParams = array(); + // Keys like "4::paramname" can't be used for output so we change them to "paramname" + foreach ( $params as $key => $value ) { + if ( strpos( $key, ':' ) === false ) { + $logParams[$key] = $value; + continue; + } + $logParam = explode( ':', $key, 3 ); + $logParams[$logParam[2]] = $value; + } + $packet['log_params'] = $logParams; + } else { + $packet['log_params'] = explode( "\n", $attrib['rc_params'] ); + } + } + $packet['log_action_comment'] = $actionComment; + break; + } + + $packet['server_url'] = $wgCanonicalServer; + $packet['server_script_path'] = $wgScriptPath ?: '/'; + $packet['wiki'] = $wgDBname; + + return $this->formatArray( $packet ); + } +} diff --git a/includes/rcfeed/XMLRCFeedFormatter.php b/includes/rcfeed/XMLRCFeedFormatter.php new file mode 100644 index 0000000000..d5724264ad --- /dev/null +++ b/includes/rcfeed/XMLRCFeedFormatter.php @@ -0,0 +1,30 @@ +