PluginProbe
Stream – Activity Log & Audit Trail / 2.0.2
Stream – Activity Log & Audit Trail v2.0.2
4.4.0 4.3.0 4.2.2 4.2.1 trunk 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.1 3.1.1 3.10.0 3.2.0 3.2.1 3.2.2 3.2.3 All 50 releases
stream / classes / class-wp-stream-log.php

class-wp-stream-log.php in Stream – Activity Log & Audit Trail 2.0.2, at classes/class-wp-stream-log.php

307 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class WP_Stream_Log {
4
5 /**
6 * Log handler
7 *
8 * @var \WP_Stream_Log
9 */
10 public static $instance = null;
11
12 /**
13 * Load log handler class, filterable by extensions
14 *
15 * @return void
16 */
17 public static function load() {
18 /**
19 * Filter allows developers to change log handler class
20 *
21 * @param array Current Class
22 * @return string New Class for log handling
23 */
24 $log_handler = apply_filters( 'wp_stream_log_handler', __CLASS__ );
25
26 self::$instance = new $log_handler;
27 }
28
29 /**
30 * Return active instance of this class
31 *
32 * @return WP_Stream_Log
33 */
34 public static function get_instance() {
35 if ( ! self::$instance ) {
36 $class = __CLASS__;
37 self::$instance = new $class;
38 }
39
40 return self::$instance;
41 }
42
43 /**
44 * Log handler
45 *
46 * @param $connector
47 * @param string $message sprintf-ready error message string
48 * @param array $args sprintf (and extra) arguments to use
49 * @param int $object_id Target object id
50 * @param string $context Context of the event
51 * @param string $action Action of the event
52 * @param int $user_id User responsible for the event
53 *
54 * @return void
55 */
56 public function log( $connector, $message, $args, $object_id, $context, $action, $user_id = null ) {
57 global $wpdb;
58
59 if ( is_null( $user_id ) ) {
60 $user_id = get_current_user_id();
61 }
62
63 if ( is_null( $object_id ) ) {
64 $object_id = 0;
65 }
66
67 $wp_cron_tracking = isset( WP_Stream_Settings::$options['advanced_wp_cron_tracking'] ) ? WP_Stream_Settings::$options['advanced_wp_cron_tracking'] : false;
68 $agent = WP_Stream_Author::get_current_agent();
69
70 // WP cron tracking requires opt-in
71 if ( ! $wp_cron_tracking && 'wp_cron' === $agent ) {
72 return;
73 }
74
75 $user = new WP_User( $user_id );
76 $roles = get_option( $wpdb->get_blog_prefix() . 'user_roles' );
77 $visibility = 'publish';
78
79 if ( self::is_record_excluded( $connector, $context, $action, $user ) ) {
80 $visibility = 'private';
81 }
82
83 if ( defined( 'WP_CLI' ) && empty( $user->display_name ) ) {
84 $display_name = 'WP-CLI';
85 } elseif ( ! empty( $user->display_name ) ) {
86 $display_name = $user->display_name;
87 } else {
88 $display_name = '';
89 }
90
91 $author_meta = array(
92 'user_email' => (string) ! empty( $user->user_email ) ? $user->user_email : '',
93 'display_name' => (string) $display_name,
94 'user_login' => (string) ! empty( $user->user_login ) ? $user->user_login : '',
95 'user_role_label' => (string) ! empty( $user->roles ) ? $roles[ $user->roles[0] ]['name'] : '',
96 'agent' => (string) $agent,
97 );
98
99 if ( ( defined( 'WP_CLI' ) ) && function_exists( 'posix_getuid' ) ) {
100 $uid = posix_getuid();
101 $user_info = posix_getpwuid( $uid );
102
103 $author_meta['system_user_id'] = (int) $uid;
104 $author_meta['system_user_name'] = (string) $user_info['name'];
105 }
106
107 // Prevent any meta with null values from being logged
108 $stream_meta = array_filter(
109 $args,
110 function ( $var ) {
111 return ! is_null( $var );
112 }
113 );
114
115 // All meta must be strings, so we will serialize any array meta values
116 array_walk(
117 $stream_meta,
118 function( &$v ) {
119 $v = (string) maybe_serialize( $v );
120 }
121 );
122
123 // Get the current time in milliseconds
124 $iso_8601_extended_date = wp_stream_get_iso_8601_extended_date();
125
126 $recordarr = array(
127 'object_id' => (int) $object_id,
128 'site_id' => (int) is_multisite() ? get_current_site()->id : 1,
129 'blog_id' => (int) apply_filters( 'wp_stream_blog_id_logged', get_current_blog_id() ),
130 'author' => (int) $user_id,
131 'author_role' => (string) ! empty( $user->roles ) ? $user->roles[0] : '',
132 'author_meta' => (array) $author_meta,
133 'created' => (string) $iso_8601_extended_date,
134 'visibility' => (string) $visibility,
135 'type' => 'stream',
136 'summary' => (string) vsprintf( $message, $args ),
137 'connector' => (string) $connector,
138 'context' => (string) $context,
139 'action' => (string) $action,
140 'stream_meta' => (array) $stream_meta,
141 'ip' => (string) wp_stream_filter_input( INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP ),
142 );
143
144 WP_Stream::$db->store( array( $recordarr ) );
145
146 self::debug_backtrace( $recordarr );
147 }
148
149 /**
150 * This function is use to check whether or not a record should be excluded from the log
151 *
152 * @param $connector string name of the connector being logged
153 * @param $context string name of the context being logged
154 * @param $action string name of the action being logged
155 * @param $user_id int id of the user being logged
156 * @param $ip string ip address being logged
157 * @return bool
158 */
159 public function is_record_excluded( $connector, $context, $action, $user = null, $ip = null ) {
160 if ( is_null( $user ) ) {
161 $user = wp_get_current_user();
162 }
163
164 if ( is_null( $ip ) ) {
165 $ip = wp_stream_filter_input( INPUT_SERVER, 'REMOTE_ADDR', FILTER_VALIDATE_IP );
166 } else {
167 $ip = wp_stream_filter_var( $ip, FILTER_VALIDATE_IP );
168 }
169
170 $user_role = isset( $user->roles[0] ) ? $user->roles[0] : null;
171
172 $record = array(
173 'connector' => $connector,
174 'context' => $context,
175 'action' => $action,
176 'author' => $user->ID,
177 'role' => $user_role,
178 'ip_address' => $ip,
179 );
180
181 $exclude_settings = isset( WP_Stream_Settings::$options['exclude_rules'] ) ? WP_Stream_Settings::$options['exclude_rules'] : array();
182
183 if ( isset( $exclude_settings['exclude_row'] ) && ! empty( $exclude_settings['exclude_row'] ) ) {
184 foreach ( $exclude_settings['exclude_row'] as $key => $value ) {
185 // Prepare values
186 $author_or_role = isset( $exclude_settings['author_or_role'][ $key ] ) ? $exclude_settings['author_or_role'][ $key ] : '';
187 $connector = isset( $exclude_settings['connector'][ $key ] ) ? $exclude_settings['connector'][ $key ] : '';
188 $context = isset( $exclude_settings['context'][ $key ] ) ? $exclude_settings['context'][ $key ] : '';
189 $action = isset( $exclude_settings['action'][ $key ] ) ? $exclude_settings['action'][ $key ] : '';
190 $ip_address = isset( $exclude_settings['ip_address'][ $key ] ) ? $exclude_settings['ip_address'][ $key ] : '';
191
192 $exclude = array(
193 'connector' => ! empty( $connector ) ? $connector : null,
194 'context' => ! empty( $context ) ? $context : null,
195 'action' => ! empty( $action ) ? $action : null,
196 'ip_address' => ! empty( $ip_address ) ? $ip_address : null,
197 'author' => is_numeric( $author_or_role ) ? $author_or_role : null,
198 'role' => ( ! empty( $author_or_role ) && ! is_numeric( $author_or_role ) ) ? $author_or_role : null,
199 );
200
201 $exclude_rules = array_filter( $exclude, 'strlen' );
202
203 if ( ! empty( $exclude_rules ) ) {
204 $excluded = true;
205
206 foreach ( $exclude_rules as $exclude_key => $exclude_value ) {
207 if ( $record[ $exclude_key ] !== $exclude_value ) {
208 $excluded = false;
209 break;
210 }
211 }
212
213 if ( $excluded ) {
214 return true;
215 }
216 }
217 }
218 }
219
220 return false;
221 }
222
223 /**
224 * Send a full backtrace of calls to the PHP error log for debugging
225 *
226 * @param array $recordarr
227 *
228 * @return void
229 */
230 public static function debug_backtrace( $recordarr ) {
231 /**
232 * Enable debug backtrace on records.
233 *
234 * This filter is for developer use only. When enabled, Stream will send
235 * a full debug backtrace of PHP calls for each record. Optionally, you may
236 * use the available $recordarr parameter to specify what types of records to
237 * create backtrace logs for.
238 *
239 * @param array $recordarr
240 *
241 * @return bool Set to FALSE by default (backtrace disabled)
242 */
243 $enabled = apply_filters( 'wp_stream_debug_backtrace', false, $recordarr );
244
245 if ( ! $enabled ) {
246 return;
247 }
248
249 if ( version_compare( PHP_VERSION, '5.3.6', '<' ) ) {
250 error_log( 'WP Stream debug backtrace requires at least PHP 5.3.6' );
251 return;
252 }
253
254 // Record details
255 $summary = isset( $recordarr['summary'] ) ? $recordarr['summary'] : null;
256 $author = isset( $recordarr['author'] ) ? $recordarr['author'] : null;
257 $connector = isset( $recordarr['connector'] ) ? $recordarr['connector'] : null;
258 $context = isset( $recordarr['context'] ) ? $recordarr['context'] : null;
259 $action = isset( $recordarr['action'] ) ? $recordarr['action'] : null;
260
261 // Stream meta
262 $stream_meta = isset( $recordarr['stream_meta'] ) ? $recordarr['stream_meta'] : null;
263
264 if ( $stream_meta ) {
265 array_walk( $stream_meta, function( &$value, $key ) {
266 $value = sprintf( '%s: %s', $key, ( '' === $value ) ? 'null' : $value );
267 });
268
269 $stream_meta = implode( ', ', $stream_meta );
270 }
271
272 // Author meta
273 $author_meta = isset( $recordarr['author_meta'] ) ? $recordarr['author_meta'] : null;
274
275 if ( $author_meta ) {
276 array_walk( $author_meta, function( &$value, $key ) {
277 $value = sprintf( '%s: %s', $key, ( '' === $value ) ? 'null' : $value );
278 });
279
280 $author_meta = implode( ', ', $author_meta );
281 }
282
283 // Debug backtrace
284 ob_start();
285
286 debug_print_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS ); // Option to ignore args requires PHP 5.3.6
287
288 $backtrace = ob_get_clean();
289 $backtrace = array_values( array_filter( explode( "\n", $backtrace ) ) );
290
291 $output = sprintf(
292 "WP Stream Debug Backtrace\n\n Summary | %s\n Author | %s\n Connector | %s\n Context | %s\n Action | %s\nStream Meta | %s\nAuthor Meta | %s\n\n%s\n",
293 $summary,
294 $author,
295 $connector,
296 $context,
297 $action,
298 $stream_meta,
299 $author_meta,
300 implode( "\n", $backtrace )
301 );
302
303 error_log( $output );
304 }
305
306 }
307