PluginProbe
Stream – Activity Log & Audit Trail / 3.9.2
Stream – Activity Log & Audit Trail v3.9.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 / connectors / class-connector-editor.php

class-connector-editor.php in Stream – Activity Log & Audit Trail 3.9.2, at connectors/class-connector-editor.php

343 lines 7.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Connector for Editor
4 *
5 * @package WP_Stream
6 */
7
8 namespace WP_Stream;
9
10 /**
11 * Class - Connector_Editor
12 */
13 class Connector_Editor extends Connector {
14 /**
15 * Connector slug
16 *
17 * @var string
18 */
19 public $name = 'editor';
20
21 /**
22 * Actions registered for this connector
23 *
24 * @var array
25 */
26 public $actions = array();
27
28 /**
29 * Actions registered for this connector
30 *
31 * @var array
32 */
33 private $edited_file = array();
34
35 /**
36 * Register connector in the WP Frontend
37 *
38 * @var bool
39 */
40 public $register_frontend = false;
41
42 /**
43 * Register all context hooks
44 *
45 * @return void
46 */
47 public function register() {
48 parent::register();
49 add_action( 'load-theme-editor.php', array( $this, 'get_edition_data' ) );
50 add_action( 'load-plugin-editor.php', array( $this, 'get_edition_data' ) );
51 add_filter( 'wp_redirect', array( $this, 'log_changes' ) );
52 }
53
54 /**
55 * Return translated connector label
56 *
57 * @return string Translated connector label
58 */
59 public function get_label() {
60 return esc_html__( 'Editor', 'stream' );
61 }
62
63 /**
64 * Return translated action labels
65 *
66 * @return array Action label translations
67 */
68 public function get_action_labels() {
69 return array(
70 'updated' => esc_html__( 'Updated', 'stream' ),
71 );
72 }
73
74 /**
75 * Return translated context labels
76 *
77 * @return array Context label translations
78 */
79 public function get_context_labels() {
80 /**
81 * Filter available context labels for the Editor connector
82 *
83 * @return array Array of context slugs and their translated labels
84 */
85 return apply_filters(
86 'wp_stream_editor_context_labels',
87 array(
88 'themes' => esc_html__( 'Themes', 'stream' ),
89 'plugins' => esc_html__( 'Plugins', 'stream' ),
90 )
91 );
92 }
93
94 /**
95 * Get the context based on wp_redirect location
96 *
97 * @param string $location The URL of the redirect.
98 *
99 * @return string Context slug
100 */
101 public function get_context( $location ) {
102 $context = null;
103
104 if ( false !== strpos( $location, 'theme-editor.php' ) ) {
105 $context = 'themes';
106 }
107
108 if ( false !== strpos( $location, 'plugin-editor.php' ) ) {
109 $context = 'plugins';
110 }
111
112 /**
113 * Filter available contexts for the Editor connector
114 *
115 * @param string $context Context slug
116 * @param string $location The URL of the redirect
117 * @return string Context slug
118 */
119 return apply_filters( 'wp_stream_editor_context', $context, $location );
120 }
121
122 /**
123 * Get the message format for file updates
124 *
125 * @return string Translated string
126 */
127 public function get_message() {
128 /* translators: %1$s: a file name, %2$s: a theme / plugin name (e.g. "index.php", "Stream") */
129 return _x(
130 '"%1$s" in "%2$s" updated',
131 '1: File name, 2: Theme/plugin name',
132 'stream'
133 );
134 }
135
136 /**
137 * Add action links to Stream drop row in admin list screen
138 *
139 * @filter wp_stream_action_links_{connector}
140 *
141 * @param array $links Previous links registered.
142 * @param object $record Stream record.
143 *
144 * @return array Action links
145 */
146 public function action_links( $links, $record ) {
147 if ( current_user_can( 'edit_theme_options' ) ) {
148 $file_name = $record->get_meta( 'file', true );
149 $file_path = $record->get_meta( 'file_path', true );
150
151 if ( ! empty( $file_name ) && ! empty( $file_path ) ) {
152 $theme_slug = $record->get_meta( 'theme_slug', true );
153 $plugin_slug = $record->get_meta( 'plugin_slug', true );
154 $theme_exists = ( ! empty( $theme_slug ) && file_exists( $file_path ) );
155 $plugin_exists = ( ! empty( $plugin_slug ) && file_exists( $file_path ) );
156
157 if ( $theme_exists ) {
158 $links[ esc_html__( 'Edit File', 'stream' ) ] = add_query_arg(
159 array(
160 'theme' => rawurlencode( $theme_slug ),
161 'file' => rawurlencode( $file_name ),
162 ),
163 self_admin_url( 'theme-editor.php' )
164 );
165
166 $links[ esc_html__( 'Theme Details', 'stream' ) ] = add_query_arg(
167 array(
168 'theme' => rawurlencode( $theme_slug ),
169 ),
170 self_admin_url( 'themes.php' )
171 );
172 }
173
174 if ( $plugin_exists ) {
175 $links[ esc_html__( 'Edit File', 'stream' ) ] = add_query_arg(
176 array(
177 'plugin' => rawurlencode( $plugin_slug ),
178 'file' => rawurlencode( str_ireplace( trailingslashit( WP_PLUGIN_DIR ), '', $file_path ) ),
179 ),
180 self_admin_url( 'plugin-editor.php' )
181 );
182 }
183 }
184 }
185
186 return $links;
187 }
188
189 /**
190 * Retrieves data submitted on the screen, and prepares it for the appropriate context type
191 *
192 * @action load-theme-editor.php
193 * @action load-plugin-editor.php
194 */
195 public function get_edition_data() {
196 if (
197 (
198 isset( $_SERVER['REQUEST_METHOD'] )
199 &&
200 'POST' !== sanitize_text_field( $_SERVER['REQUEST_METHOD'] )
201 )
202 ||
203 'update' !== wp_stream_filter_input( INPUT_POST, 'action' )
204 ) {
205 return;
206 }
207
208 $theme_slug = wp_stream_filter_input( INPUT_POST, 'theme' );
209 if ( $theme_slug ) {
210 $this->edited_file = $this->get_theme_data( $theme_slug );
211 }
212
213 $plugin_slug = wp_stream_filter_input( INPUT_POST, 'plugin' );
214 if ( $plugin_slug ) {
215 $this->edited_file = $this->get_plugin_data( $plugin_slug );
216 }
217 }
218
219 /**
220 * Retrieve theme data needed for the log message
221 *
222 * @param string $slug The theme slug (e.g. twentyfourteen).
223 *
224 * @return mixed $output Compacted variables
225 */
226 public function get_theme_data( $slug ) {
227 $theme = wp_get_theme( $slug );
228
229 if ( ! $theme->exists() || ( $theme->errors() && 'theme_no_stylesheet' === $theme->errors()->get_error_code() ) ) {
230 return false;
231 }
232
233 $allowed_files = $theme->get_files( 'php', 1 );
234 $style_files = $theme->get_files( 'css' );
235 $file = wp_stream_filter_input( INPUT_POST, 'file' );
236
237 $allowed_files['style.css'] = $style_files['style.css'];
238
239 if ( empty( $file ) ) {
240 $file_name = 'style.css';
241 $file_path = $allowed_files['style.css'];
242 } else {
243 $file_name = $file;
244 $file_path = sprintf( '%s/%s', $theme->get_stylesheet_directory(), $file_name );
245 }
246
247 $file_md5 = md5_file( $file_path );
248 $name = $theme->get( 'Name' );
249
250 $output = compact(
251 'file_name',
252 'file_path',
253 'file_md5',
254 'slug',
255 'name'
256 );
257
258 return $output;
259 }
260
261 /**
262 * Retrieve plugin data needed for the log message
263 *
264 * @param string $slug The plugin file base name (e.g. akismet/akismet.php).
265 * @return mixed $output Compacted variables.
266 */
267 public function get_plugin_data( $slug ) {
268 $base = null;
269 $name = null;
270 $slug = current( explode( '/', $slug ) );
271 $file_name = wp_stream_filter_input( INPUT_POST, 'file' );
272 $file_path = WP_PLUGIN_DIR . '/' . $file_name;
273 $file_md5 = md5_file( $file_path );
274 $plugins = get_plugins();
275
276 foreach ( $plugins as $key => $plugin_data ) {
277 if ( 0 === strpos( $key, $slug ) ) {
278 $base = $key;
279 $name = $plugin_data['Name'];
280 break;
281 }
282 }
283
284 $file_name = str_ireplace( trailingslashit( $slug ), '', $file_name );
285 $slug = ! empty( $base ) ? $base : $slug;
286
287 $output = compact(
288 'file_name',
289 'file_path',
290 'file_md5',
291 'slug',
292 'name'
293 );
294
295 return $output;
296 }
297
298 /**
299 * Logs changes
300 *
301 * @filter wp_redirect
302 *
303 * @param string $location Location.
304 */
305 public function log_changes( $location ) {
306 if ( ! empty( $this->edited_file ) ) {
307 // TODO: phpcs fix.
308 if ( md5_file( $this->edited_file['file_path'] ) !== $this->edited_file['file_md5'] ) {
309 $context = $this->get_context( $location );
310
311 switch ( $context ) {
312 case 'themes':
313 $name_key = 'theme_name';
314 $slug_key = 'theme_slug';
315 break;
316 case 'plugins':
317 $name_key = 'plugin_name';
318 $slug_key = 'plugin_slug';
319 break;
320 default:
321 $name_key = 'name';
322 $slug_key = 'slug';
323 }
324
325 $this->log(
326 $this->get_message(),
327 array(
328 'file' => (string) $this->edited_file['file_name'],
329 $name_key => (string) $this->edited_file['name'],
330 $slug_key => (string) $this->edited_file['slug'],
331 'file_path' => (string) $this->edited_file['file_path'],
332 ),
333 null,
334 $context,
335 'updated'
336 );
337 }
338 }
339
340 return $location;
341 }
342 }
343