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-connector.php

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

237 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 abstract class WP_Stream_Connector {
4
5 /**
6 * Connector slug
7 *
8 * @var string
9 */
10 public static $name = null;
11
12 /**
13 * Actions registered for this connector
14 *
15 * @var array
16 */
17 public static $actions = array();
18
19 /**
20 * Previous Stream entry in same request
21 *
22 * @var int
23 */
24 public static $prev_stream = null;
25
26 /**
27 * Register all context hooks
28 *
29 * @return void
30 */
31 public static function register() {
32 $class = get_called_class();
33
34 foreach ( $class::$actions as $action ) {
35 add_action( $action, array( $class, 'callback' ), null, 5 );
36 }
37
38 add_filter( 'wp_stream_action_links_' . $class::$name, array( $class, 'action_links' ), 10, 2 );
39 }
40
41 /**
42 * Callback for all registered hooks throughout Stream
43 * Looks for a class method with the convention: "callback_{action name}"
44 *
45 * @return void
46 */
47 public static function callback() {
48 $action = current_filter();
49 $class = get_called_class();
50 $callback = array( $class, 'callback_' . preg_replace( '/[^a-z0-9_\-]/', '_', $action ) );
51
52 // For the sake of testing, trigger an action with the name of the callback
53 if ( defined( 'STREAM_TESTS' ) ) {
54 /**
55 * Action fires during testing to test the current callback
56 *
57 * @param array $callback Callback name
58 */
59 do_action( 'wp_stream_test_' . $callback[1] );
60 }
61
62 // Call the real function
63 if ( is_callable( $callback ) ) {
64 return call_user_func_array( $callback, func_get_args() );
65 }
66 }
67
68 /**
69 * Add action links to Stream drop row in admin list screen
70 *
71 * @filter wp_stream_action_links_{connector}
72 * @param array $links Previous links registered
73 * @param object $record Stream record
74 * @return array Action links
75 */
76 public static function action_links( $links, $record ) {
77 return $links;
78 }
79
80 /**
81 * Log handler
82 *
83 * @param string $message sprintf-ready error message string
84 * @param array $args sprintf (and extra) arguments to use
85 * @param int $object_id Target object id
86 * @param string $context Context of the event
87 * @param string $action Action of the event
88 * @param int $user_id User responsible for the event
89 *
90 * @internal param string $action Action performed (stream_action)
91 * @return bool
92 */
93 public static function log( $message, $args, $object_id, $context, $action, $user_id = null ) {
94 $class = get_called_class();
95 $connector = $class::$name;
96
97 $data = apply_filters(
98 'wp_stream_log_data',
99 compact( 'connector', 'message', 'args', 'object_id', 'context', 'action', 'user_id' )
100 );
101
102 if ( ! $data ) {
103 return false;
104 } else {
105 $connector = $data['connector'];
106 $message = $data['message'];
107 $args = $data['args'];
108 $object_id = $data['object_id'];
109 $context = $data['context'];
110 $action = $data['action'];
111 $user_id = $data['user_id'];
112 }
113
114 return call_user_func_array( array( WP_Stream_Log::get_instance(), 'log' ), compact( 'connector', 'message', 'args', 'object_id', 'context', 'action', 'user_id' ) );
115 }
116
117 /**
118 * Save log data till shutdown, so other callbacks would be able to override
119 *
120 * @param string $handle Special slug to be shared with other actions
121 *
122 * @internal param mixed $arg1 Extra arguments to sent to log()
123 * @internal param mixed $arg2 , etc..
124 * @return void
125 */
126 public static function delayed_log( $handle ) {
127 $args = func_get_args();
128
129 array_shift( $args );
130
131 self::$delayed[ $handle ] = $args;
132
133 add_action( 'shutdown', array( __CLASS__, 'delayed_log_commit' ) );
134 }
135
136 /**
137 * Commit delayed logs saved by @delayed_log
138 *
139 * @return void
140 */
141 public static function delayed_log_commit() {
142 foreach ( self::$delayed as $handle => $args ) {
143 call_user_func_array( array( __CLASS__, 'log' ) , $args );
144 }
145 }
146
147 /**
148 * Compare two values and return changed keys if they are arrays
149 *
150 * @param mixed $old_value Value before change
151 * @param mixed $new_value Value after change
152 * @param bool|int $deep Get array children changes keys as well, not just parents
153 *
154 * @return array
155 */
156 public static function get_changed_keys( $old_value, $new_value, $deep = false ) {
157 if ( ! is_array( $old_value ) && ! is_array( $new_value ) ) {
158 return array();
159 }
160
161 if ( ! is_array( $old_value ) ) {
162 return array_keys( $new_value );
163 }
164
165 if ( ! is_array( $new_value ) ) {
166 return array_keys( $old_value );
167 }
168
169 $diff = array_udiff_assoc(
170 $old_value,
171 $new_value,
172 function( $value1, $value2 ) {
173 return maybe_serialize( $value1 ) !== maybe_serialize( $value2 );
174 }
175 );
176
177 $result = array_keys( $diff );
178
179 // find unexisting keys in old or new value
180 $common_keys = array_keys( array_intersect_key( $old_value, $new_value ) );
181 $unique_keys_old = array_values( array_diff( array_keys( $old_value ), $common_keys ) );
182 $unique_keys_new = array_values( array_diff( array_keys( $new_value ), $common_keys ) );
183 $result = array_merge( $result, $unique_keys_old, $unique_keys_new );
184
185 // remove numeric indexes
186 $result = array_filter(
187 $result,
188 function( $value ) {
189 // check if is not valid number (is_int, is_numeric and ctype_digit are not enough)
190 return (string) (int) $value !== (string) $value;
191 }
192 );
193
194 $result = array_values( array_unique( $result ) );
195
196 if ( false === $deep ) {
197 return $result; // Return an numerical based array with changed TOP PARENT keys only
198 }
199
200 $result = array_fill_keys( $result, null );
201
202 foreach ( $result as $key => $val ) {
203 if ( in_array( $key, $unique_keys_old ) ) {
204 $result[ $key ] = false; // Removed
205 }
206 elseif ( in_array( $key, $unique_keys_new ) ) {
207 $result[ $key ] = true; // Added
208 }
209 elseif ( $deep ) { // Changed, find what changed, only if we're allowed to explore a new level
210 if ( is_array( $old_value[ $key ] ) && is_array( $new_value[ $key ] ) ) {
211 $inner = array();
212 $parent = $key;
213 $deep--;
214 $changed = self::get_changed_keys( $old_value[ $key ], $new_value[ $key ], $deep );
215 foreach ( $changed as $child => $change ) {
216 $inner[ $parent . '::' . $child ] = $change;
217 }
218 $result[ $key ] = 0; // Changed parent which has a changed children
219 $result = array_merge( $result, $inner );
220 }
221 }
222 }
223
224 return $result;
225 }
226
227 /**
228 * Allow connectors to determine if their dependencies is satisfied or not
229 *
230 * @return bool
231 */
232 public static function is_dependency_satisfied() {
233 return true;
234 }
235
236 }
237