Skip to content

Commit d3c596e

Browse files
authored
Release version 3.4.2 (#1037)
1 parent fac6064 commit d3c596e

File tree

7 files changed

+225
-90
lines changed

7 files changed

+225
-90
lines changed

classes/class-log.php

Lines changed: 85 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ function ( $var ) {
163163
* @return bool
164164
*/
165165
public function is_record_excluded( $connector, $context, $action, $user = null, $ip = null ) {
166+
$exclude_record = false;
167+
166168
if ( is_null( $user ) ) {
167169
$user = wp_get_current_user();
168170
}
@@ -191,64 +193,25 @@ public function is_record_excluded( $connector, $context, $action, $user = null,
191193
$exclude_settings = isset( $this->plugin->settings->options['exclude_rules'] ) ? $this->plugin->settings->options['exclude_rules'] : array();
192194

193195
if ( is_multisite() && $this->plugin->is_network_activated() && ! is_network_admin() ) {
194-
$multisite_options = (array) get_site_option( 'wp_stream_network', array() );
195-
$multisite_exclude_settings = isset( $multisite_options['exclude_rules'] ) ? $multisite_options['exclude_rules'] : array();
196-
197-
if ( ! empty( $multisite_exclude_settings ) ) {
198-
foreach ( $multisite_exclude_settings['exclude_row'] as $key => $rule ) {
199-
$exclude_settings['exclude_row'][] = $multisite_exclude_settings['exclude_row'][ $key ];
200-
$exclude_settings['author_or_role'][] = $multisite_exclude_settings['author_or_role'][ $key ];
201-
$exclude_settings['connector'][] = $multisite_exclude_settings['connector'][ $key ];
202-
$exclude_settings['context'][] = $multisite_exclude_settings['context'][ $key ];
203-
$exclude_settings['action'][] = $multisite_exclude_settings['action'][ $key ];
204-
$exclude_settings['ip_address'][] = $multisite_exclude_settings['ip_address'][ $key ];
205-
}
206-
}
196+
$multisite_options = (array) get_site_option( 'wp_stream_network', array() );
197+
$exclude_settings = isset( $multisite_options['exclude_rules'] ) ? $multisite_options['exclude_rules'] : array();
207198
}
208199

209-
$exclude_record = false;
200+
foreach ( $this->exclude_rules_by_rows( $exclude_settings ) as $exclude_rule ) {
201+
$exclude = array(
202+
'connector' => ! empty( $exclude_rule['connector'] ) ? $exclude_rule['connector'] : null,
203+
'context' => ! empty( $exclude_rule['context'] ) ? $exclude_rule['context'] : null,
204+
'action' => ! empty( $exclude_rule['action'] ) ? $exclude_rule['action'] : null,
205+
'ip_address' => ! empty( $exclude_rule['ip_address'] ) ? $exclude_rule['ip_address'] : null,
206+
'author' => is_numeric( $exclude_rule['author_or_role'] ) ? absint( $exclude_rule['author_or_role'] ) : null,
207+
'role' => ( ! empty( $exclude_rule['author_or_role'] ) && ! is_numeric( $exclude_rule['author_or_role'] ) ) ? $exclude_rule['author_or_role'] : null,
208+
);
210209

211-
if ( isset( $exclude_settings['exclude_row'] ) && ! empty( $exclude_settings['exclude_row'] ) ) {
212-
foreach ( $exclude_settings['exclude_row'] as $key => $value ) {
213-
// Prepare values.
214-
$author_or_role = isset( $exclude_settings['author_or_role'][ $key ] ) ? $exclude_settings['author_or_role'][ $key ] : '';
215-
$connector = isset( $exclude_settings['connector'][ $key ] ) ? $exclude_settings['connector'][ $key ] : '';
216-
$context = isset( $exclude_settings['context'][ $key ] ) ? $exclude_settings['context'][ $key ] : '';
217-
$action = isset( $exclude_settings['action'][ $key ] ) ? $exclude_settings['action'][ $key ] : '';
218-
$ip_address = isset( $exclude_settings['ip_address'][ $key ] ) ? $exclude_settings['ip_address'][ $key ] : '';
219-
220-
$exclude = array(
221-
'connector' => ! empty( $connector ) ? $connector : null,
222-
'context' => ! empty( $context ) ? $context : null,
223-
'action' => ! empty( $action ) ? $action : null,
224-
'ip_address' => ! empty( $ip_address ) ? $ip_address : null,
225-
'author' => is_numeric( $author_or_role ) ? absint( $author_or_role ) : null,
226-
'role' => ( ! empty( $author_or_role ) && ! is_numeric( $author_or_role ) ) ? $author_or_role : null,
227-
);
228-
229-
$exclude_rules = array_filter( $exclude, 'strlen' );
230-
231-
if ( ! empty( $exclude_rules ) ) {
232-
$matches_exclusion_rule = true;
233-
234-
foreach ( $exclude_rules as $exclude_key => $exclude_value ) {
235-
if ( 'ip_address' === $exclude_key ) {
236-
$ip_addresses = explode( ',', $exclude_value );
237-
if ( ! in_array( $record['ip_address'], $ip_addresses, true ) ) {
238-
$matches_exclusion_rule = false;
239-
break;
240-
}
241-
} elseif ( $record[ $exclude_key ] !== $exclude_value ) {
242-
$matches_exclusion_rule = false;
243-
break;
244-
}
245-
}
246-
247-
if ( $matches_exclusion_rule ) {
248-
$exclude_record = true;
249-
break;
250-
}
251-
}
210+
$exclude_rules = array_filter( $exclude, 'strlen' );
211+
212+
if ( $this->record_matches_rules( $record, $exclude_rules ) ) {
213+
$exclude_record = true;
214+
break;
252215
}
253216
}
254217

@@ -265,6 +228,73 @@ public function is_record_excluded( $connector, $context, $action, $user = null,
265228
return apply_filters( 'wp_stream_is_record_excluded', $exclude_record, $record );
266229
}
267230

231+
/**
232+
* Check if a record to stored matches certain rules.
233+
*
234+
* @param array $record List of record parameters.
235+
* @param array $exclude_rules List of record exclude rules.
236+
*
237+
* @return boolean
238+
*/
239+
public function record_matches_rules( $record, $exclude_rules ) {
240+
foreach ( $exclude_rules as $exclude_key => $exclude_value ) {
241+
if ( ! isset( $record[ $exclude_key ] ) ) {
242+
continue;
243+
}
244+
245+
if ( 'ip_address' === $exclude_key ) {
246+
$ip_addresses = explode( ',', $exclude_value );
247+
248+
if ( in_array( $record['ip_address'], $ip_addresses, true ) ) {
249+
return true;
250+
}
251+
} elseif ( $record[ $exclude_key ] === $exclude_value ) {
252+
return true;
253+
}
254+
}
255+
256+
return false;
257+
}
258+
259+
/**
260+
* Get all exclude rules by row because we store them by rule instead.
261+
*
262+
* @param array $rules List of rules indexed by rule ID.
263+
*
264+
* @return array
265+
*/
266+
public function exclude_rules_by_rows( $rules ) {
267+
$excludes = array();
268+
269+
// TODO: Move these to where the settings are generated to ensure they're in sync.
270+
$rule_keys = array(
271+
'exclude_row',
272+
'author_or_role',
273+
'connector',
274+
'context',
275+
'action',
276+
'ip_address',
277+
);
278+
279+
if ( empty( $rules['exclude_row'] ) ) {
280+
return array();
281+
}
282+
283+
foreach ( array_keys( $rules['exclude_row'] ) as $row_id ) {
284+
$excludes[ $row_id ] = array();
285+
286+
foreach ( $rule_keys as $rule_key ) {
287+
if ( isset( $rules[ $rule_key ][ $row_id ] ) ) {
288+
$excludes[ $row_id ][ $rule_key ] = $rules[ $rule_key ][ $row_id ];
289+
} else {
290+
$excludes[ $row_id ][ $rule_key ] = null;
291+
}
292+
}
293+
}
294+
295+
return $excludes;
296+
}
297+
268298
/**
269299
* Helper function to send a full backtrace of calls to the PHP error log for debugging
270300
*

classes/class-plugin.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Plugin {
99
*
1010
* @const string
1111
*/
12-
const VERSION = '3.4.1';
12+
const VERSION = '3.4.2';
1313

1414
/**
1515
* WP-CLI command

classes/class-settings.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -551,12 +551,12 @@ public function sanitize_settings( $input ) {
551551
// Support all values in multidimentional arrays too.
552552
array_walk_recursive(
553553
$output[ $name ],
554-
function ( &$v, $k ) {
555-
$v = trim( $v );
554+
function ( &$v ) {
555+
$v = sanitize_text_field( trim( $v ) );
556556
}
557557
);
558558
} else {
559-
$output[ $name ] = trim( $input[ $name ] );
559+
$output[ $name ] = sanitize_text_field( trim( $input[ $name ] ) );
560560
}
561561
}
562562
}
@@ -842,8 +842,13 @@ public function render_field( $field ) {
842842

843843
$exclude_rows = array();
844844

845+
// Account for when no rules have been added yet.
846+
if ( ! is_array( $current_value ) ) {
847+
$current_value = array();
848+
}
849+
845850
// Prepend an empty row.
846-
$current_value['exclude_row'] = array( 'helper' => '' ) + ( isset( $current_value['exclude_row'] ) ? $current_value['exclude_row'] : array() );
851+
$current_value['exclude_row'] = ( isset( $current_value['exclude_row'] ) ? $current_value['exclude_row'] : array() ) + array( 'helper' => '' );
847852

848853
foreach ( $current_value['exclude_row'] as $key => $value ) {
849854
// Prepare values.

readme.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
=== Stream ===
2-
Contributors: lukecarbis, fjarrett, stream, xwp
2+
Contributors: lukecarbis, fjarrett, stream, xwp, kasparsd
33
Tags: wp stream, stream, activity, logs, track
44
Requires at least: 4.5
55
Tested up to: 5.2
6-
Stable tag: 3.4.1
6+
Stable tag: 3.4.2
77
License: GPLv2 or later
88
License URI: https://www.gnu.org/licenses/gpl-2.0.html
99

@@ -87,6 +87,11 @@ Thank you for wanting to make Stream better for everyone!
8787

8888
== Changelog ==
8989

90+
= 3.4.2 - September 26, 2019 =
91+
92+
* Fix: Visiting the plugin settings page no longer produces PHP warnings for undefined variables [#1031](https://github.com/xwp/stream/issues/1031).
93+
* Fix: The IP address based exclude rules now stay with the same ruleset when saving [#1035](https://github.com/xwp/stream/issues/1035). Previously IP addresses would jump to the previous rule which didn't have an IP address based conditional.
94+
9095
= 3.4.1 - July 25, 2019 =
9196

9297
* Fix: Allow tracking cron events even when the default WordPress front-end cron runner is disabled via `DISABLE_WP_CRON`. See [#959], props [@khromov](https://github.com/khromov) and [@tareiking](https://github.com/tareiking).

stream.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Plugin Name: Stream
44
* Plugin URI: https://wp-stream.com/
55
* Description: Stream tracks logged-in user activity so you can monitor every change made on your WordPress site in beautifully organized detail. All activity is organized by context, action and IP address for easy filtering. Developers can extend Stream with custom connectors to log any kind of action.
6-
* Version: 3.4.1
6+
* Version: 3.4.2
77
* Author: XWP
88
* Author URI: https://xwp.co/
99
* License: GPLv2+

tests/tests/test-class-log.php

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,103 @@ public function test_field_lengths() {
6363
// Test action length
6464

6565
// Test IP length
66-
66+
67+
}
68+
69+
public function test_can_map_exclude_rules_settings_to_rows() {
70+
$rules_settings = array(
71+
'exclude_row' => array(
72+
null,
73+
null,
74+
),
75+
'action' => array(
76+
'one',
77+
null,
78+
'three'
79+
)
80+
);
81+
82+
$this->assertEquals(
83+
array(
84+
array(
85+
'exclude_row' => null,
86+
'action' => 'one',
87+
'author_or_role' => null,
88+
'connector' => null,
89+
'context' => null,
90+
'ip_address' => null,
91+
),
92+
array(
93+
'exclude_row' => null,
94+
'action' => null,
95+
'author_or_role' => null,
96+
'connector' => null,
97+
'context' => null,
98+
'ip_address' => null,
99+
)
100+
),
101+
$this->plugin->log->exclude_rules_by_rows( $rules_settings )
102+
);
103+
}
104+
105+
public function test_can_match_record_exclude() {
106+
$rules = array(
107+
'action' => 'mega_action',
108+
);
109+
110+
$this->assertTrue(
111+
$this->plugin->log->record_matches_rules(
112+
array(
113+
'action' => 'mega_action',
114+
'ip_address' => '1.1.1.1',
115+
),
116+
$rules
117+
),
118+
'Record action is the same'
119+
);
120+
121+
$this->assertFalse(
122+
$this->plugin->log->record_matches_rules(
123+
array(
124+
'action' => 'different_action',
125+
),
126+
$rules
127+
),
128+
'Record action is different'
129+
);
130+
}
131+
132+
public function test_can_match_record_id_address() {
133+
$this->assertFalse(
134+
$this->plugin->log->record_matches_rules(
135+
array(
136+
'ip_address' => '1.1.1.1',
137+
),
138+
array(
139+
'ip_address' => '8.8.8.8',
140+
)
141+
),
142+
'Record IP address is different'
143+
);
144+
145+
$this->assertTrue( $this->plugin->log->record_matches_rules(
146+
array(
147+
'ip_address' => '1.1.1.1',
148+
),
149+
array(
150+
'ip_address' => '1.1.1.1',
151+
),
152+
'Record and rule IP addresses match'
153+
) );
154+
155+
$this->assertTrue( $this->plugin->log->record_matches_rules(
156+
array(
157+
'ip_address' => '1.1.1.1',
158+
),
159+
array(
160+
'ip_address' => '8.8.8.8,1.1.1.1',
161+
),
162+
'Record IP address is one of the IP addresses in the rule'
163+
) );
67164
}
68165
}

0 commit comments

Comments
 (0)