1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 * http://www.gnu.org/copyleft/gpl.html
18 *
19 * @file
20 */
21
22/**
23 * Abstract class so there can be multiple formatters outputting the same data
24 *
25 * @since 1.23
26 */
27abstract class MachineReadableRCFeedFormatter implements RCFeedFormatter {
28
29	/**
30	 * Take the packet and return the formatted string
31	 * @param array $packet
32	 * @return string
33	 */
34	abstract protected function formatArray( array $packet );
35
36	/**
37	 * Generates a notification that can be easily interpreted by a machine.
38	 * @see RCFeedFormatter::getLine
39	 * @param array $feed
40	 * @param RecentChange $rc
41	 * @param string|null $actionComment
42	 * @return string|null
43	 */
44	public function getLine( array $feed, RecentChange $rc, $actionComment ) {
45		global $wgCanonicalServer, $wgServerName, $wgScriptPath;
46
47		$packet = [
48			// Usually, RC ID is exposed only for patrolling purposes,
49			// but there is no real reason not to expose it in other cases,
50			// and I can see how this may be potentially useful for clients.
51			'id' => $rc->getAttribute( 'rc_id' ),
52			'type' => RecentChange::parseFromRCType( $rc->getAttribute( 'rc_type' ) ),
53			'namespace' => $rc->getTitle()->getNamespace(),
54			'title' => $rc->getTitle()->getPrefixedText(),
55			'comment' => $rc->getAttribute( 'rc_comment' ),
56			'timestamp' => (int)wfTimestamp( TS_UNIX, $rc->getAttribute( 'rc_timestamp' ) ),
57			'user' => $rc->getAttribute( 'rc_user_text' ),
58			'bot' => (bool)$rc->getAttribute( 'rc_bot' ),
59		];
60
61		if ( isset( $feed['channel'] ) ) {
62			$packet['channel'] = $feed['channel'];
63		}
64
65		$type = $rc->getAttribute( 'rc_type' );
66		if ( $type == RC_EDIT || $type == RC_NEW ) {
67			global $wgUseRCPatrol, $wgUseNPPatrol;
68
69			$packet['minor'] = (bool)$rc->getAttribute( 'rc_minor' );
70			if ( $wgUseRCPatrol || ( $type == RC_NEW && $wgUseNPPatrol ) ) {
71				$packet['patrolled'] = (bool)$rc->getAttribute( 'rc_patrolled' );
72			}
73		}
74
75		switch ( $type ) {
76			case RC_EDIT:
77				$packet['length'] = [
78					'old' => $rc->getAttribute( 'rc_old_len' ),
79					'new' => $rc->getAttribute( 'rc_new_len' )
80				];
81				$packet['revision'] = [
82					'old' => $rc->getAttribute( 'rc_last_oldid' ),
83					'new' => $rc->getAttribute( 'rc_this_oldid' )
84				];
85				break;
86
87			case RC_NEW:
88				$packet['length'] = [ 'old' => null, 'new' => $rc->getAttribute( 'rc_new_len' ) ];
89				$packet['revision'] = [ 'old' => null, 'new' => $rc->getAttribute( 'rc_this_oldid' ) ];
90				break;
91
92			case RC_LOG:
93				$packet['log_id'] = $rc->getAttribute( 'rc_logid' );
94				$packet['log_type'] = $rc->getAttribute( 'rc_log_type' );
95				$packet['log_action'] = $rc->getAttribute( 'rc_log_action' );
96				if ( $rc->getAttribute( 'rc_params' ) ) {
97					$params = $rc->parseParams();
98					if (
99						// If it's an actual serialised false...
100						$rc->getAttribute( 'rc_params' ) == serialize( false ) ||
101						// Or if we did not get false back when trying to unserialise
102						$params !== false
103					) {
104						// From ApiQueryLogEvents::addLogParams
105						$logParams = [];
106						// Keys like "4::paramname" can't be used for output so we change them to "paramname"
107						foreach ( $params as $key => $value ) {
108							if ( strpos( $key, ':' ) === false ) {
109								$logParams[$key] = $value;
110								continue;
111							}
112							$logParam = explode( ':', $key, 3 );
113							$logParams[$logParam[2]] = $value;
114						}
115						$packet['log_params'] = $logParams;
116					} else {
117						$packet['log_params'] = explode( "\n", $rc->getAttribute( 'rc_params' ) );
118					}
119				}
120				$packet['log_action_comment'] = $actionComment;
121				break;
122		}
123
124		$packet['server_url'] = $wgCanonicalServer;
125		$packet['server_name'] = $wgServerName;
126
127		$packet['server_script_path'] = $wgScriptPath ?: '/';
128		$packet['wiki'] = WikiMap::getCurrentWikiId();
129
130		return $this->formatArray( $packet );
131	}
132}
133