Completed
Push — remove/calypsoify-styles ( f24b27 )
by Kirk
06:44
created

Jetpack_Calypsoify::get_site_suffix()   A

Complexity

Conditions 6
Paths 6

Size

Total Lines 12

Duplication

Lines 12
Ratio 100 %

Importance

Changes 0
Metric Value
cc 6
dl 12
loc 12
rs 9.2222
c 0
b 0
f 0
nc 6
nop 0
1
<?php
2
/**
3
 * This is Calypso skin of the wp-admin interface that is conditionally triggered via the ?calypsoify=1 param.
4
 * Ported from an internal Automattic plugin.
5
 */
6
class Jetpack_Calypsoify {
7
8
	/**
9
	 * Singleton instance of `Jetpack_Calypsoify`.
10
	 *
11
	 * @var object
12
	 */
13
	public static $instance = false;
14
15
	/**
16
	 * Is Calypsoify enabled, based on any value of `calypsoify` user meta.
17
	 *
18
	 * @var bool
19
	 */
20
	public $is_calypsoify_enabled = false;
21
22
	private function __construct() {
23
		add_action( 'wp_loaded', array( $this, 'setup' ) );
24
	}
25
26
	public static function getInstance() {
27
		if ( ! self::$instance ) {
28
			self::$instance = new self();
29
		}
30
31
		return self::$instance;
32
	}
33
34
	public function setup() {
35
		$this->is_calypsoify_enabled = 1 == (int) get_user_meta( get_current_user_id(), 'calypsoify', true );
36
		add_action( 'admin_init', array( $this, 'check_param' ), 4 );
37
38
		if ( $this->is_calypsoify_enabled ) {
39
			add_action( 'admin_init', array( $this, 'setup_admin' ), 6 );
40
		}
41
42
		// Make this always available -- in case calypsoify gets toggled off.
43
		add_action( 'wp_ajax_jetpack_toggle_autoupdate', array( $this, 'jetpack_toggle_autoupdate' ) );
44
		add_filter( 'handle_bulk_actions-plugins', array( $this, 'handle_bulk_actions_plugins' ), 10, 3 );
45
	}
46
47
	public function setup_admin() {
48
		if ( $this->is_page_gutenberg() ) {
49
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_for_gutenberg' ), 100 );
50
			return;
51
		}
52
53
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ), 100 );
54
55
		add_action( 'manage_plugins_columns', array( $this, 'manage_plugins_columns_header' ) );
56
		add_action( 'manage_plugins_custom_column', array( $this, 'manage_plugins_custom_column' ), 10, 2 );
57
		add_filter( 'bulk_actions-plugins', array( $this, 'bulk_actions_plugins' ) );
58
59
		add_action( 'current_screen', array( $this, 'attach_views_filter' ) );
60
61
		if ( 'plugins.php' === basename( $_SERVER['PHP_SELF'] ) ) {
62
			add_action( 'admin_notices', array( $this, 'plugins_admin_notices' ) );
63
		}
64
	}
65
66
	public function manage_plugins_columns_header( $columns ) {
67
		if ( current_user_can( 'jetpack_manage_autoupdates' ) ) {
68
			$columns['autoupdate'] = __( 'Automatic Update', 'jetpack' );
69
		}
70
		return $columns;
71
	}
72
73
	public function manage_plugins_custom_column( $column_name, $slug ) {
74
		static $repo_plugins = array();
75
76
		if ( ! current_user_can( 'jetpack_manage_autoupdates' ) ) {
77
			return;
78
		}
79
80
		if ( empty( $repo_plugins ) ) {
81
			$repo_plugins = self::get_dotorg_repo_plugins();
82
		}
83
84
		$autoupdating_plugins = Jetpack_Options::get_option( 'autoupdate_plugins', array() );
85
		// $autoupdating_plugins_translations = Jetpack_Options::get_option( 'autoupdate_plugins_translations', array() );
86
		if ( 'autoupdate' === $column_name ) {
87
			if ( ! in_array( $slug, $repo_plugins ) ) {
88
				return;
89
			}
90
			// Shamelessly swiped from https://github.com/Automattic/wp-calypso/blob/59bdfeeb97eda4266ad39410cb0a074d2c88dbc8/client/components/forms/form-toggle
91
			?>
92
93
			<span class="form-toggle__wrapper">
94
				<input
95
					id="autoupdate_plugin-toggle-<?php echo esc_attr( $slug ) ?>"
96
					name="autoupdate_plugins[<?php echo esc_attr( $slug ) ?>]"
97
					value="autoupdate"
98
					class="form-toggle autoupdate-toggle"
99
					type="checkbox"
100
					<?php checked( in_array( $slug, $autoupdating_plugins ) ); ?>
101
					readonly
102
					data-slug="<?php echo esc_attr( $slug ); ?>"
103
				/>
104
				<label class="form-toggle__label" for="autoupdate_plugin-toggle-<?php echo esc_attr( $slug ) ?>">
105
					<span class="form-toggle__switch" role="checkbox"></span>
106
					<span class="form-toggle__label-content"><?php /*  */ ?></span>
107
				</label>
108
			</span>
109
110
			<?php
111
		}
112
	}
113
114
	public static function get_dotorg_repo_plugins() {
115
		$plugins = get_site_transient( 'update_plugins' );
116
		return array_merge( array_keys( $plugins->response ), array_keys( $plugins->no_update ) );
117
	}
118
119
	public function bulk_actions_plugins( $bulk_actions ) {
120
		$bulk_actions['jetpack_enable_plugin_autoupdates'] = __( 'Enable Automatic Updates', 'jetpack' );
121
		$bulk_actions['jetpack_disable_plugin_autoupdates'] = __( 'Disable Automatic Updates', 'jetpack' );
122
		return $bulk_actions;
123
	}
124
125
	public function handle_bulk_actions_plugins( $redirect_to, $action, $slugs ) {
126
		$redirect_to = remove_query_arg( array( 'jetpack_enable_plugin_autoupdates', 'jetpack_disable_plugin_autoupdates' ), $redirect_to );
127
		if ( in_array( $action, array( 'jetpack_enable_plugin_autoupdates', 'jetpack_disable_plugin_autoupdates' ) ) ) {
128
			$list = Jetpack_Options::get_option( 'autoupdate_plugins', array() );
129
			$initial_qty = sizeof( $list );
130
131
			if ( 'jetpack_enable_plugin_autoupdates' === $action ) {
132
				$list = array_unique( array_merge( $list, $slugs ) );
133
			} elseif ( 'jetpack_disable_plugin_autoupdates' === $action ) {
134
				$list = array_diff( $list, $slugs );
135
			}
136
137
			Jetpack_Options::update_option( 'autoupdate_plugins', $list );
138
			$redirect_to = add_query_arg( $action, absint( sizeof( $list ) - $initial_qty ), $redirect_to );
139
		}
140
		return $redirect_to;
141
	}
142
143
	public function plugins_admin_notices() {
144
		if ( ! empty( $_GET['jetpack_enable_plugin_autoupdates'] ) ) {
145
			$qty = (int) $_GET['jetpack_enable_plugin_autoupdates'];
146
			printf( '<div id="message" class="updated fade"><p>' . _n( 'Enabled automatic updates on %d plugin.', 'Enabled automatic updates on %d plugins.', $qty, 'jetpack' ) . '</p></div>', $qty );
147
		} elseif ( ! empty( $_GET['jetpack_disable_plugin_autoupdates'] ) ) {
148
			$qty = (int) $_GET['jetpack_disable_plugin_autoupdates'];
149
			printf( '<div id="message" class="updated fade"><p>' . _n( 'Disabled automatic updates on %d plugin.', 'Disabled automatic updates on %d plugins.', $qty, 'jetpack' ) . '</p></div>', $qty );
150
		}
151
	}
152
153
	public function jetpack_toggle_autoupdate() {
154
		if ( ! current_user_can( 'jetpack_manage_autoupdates' ) ) {
155
			wp_send_json_error();
156
			return;
157
		}
158
159
		$type   = $_POST['type'];
160
		$slug   = $_POST['slug'];
161
		$active = 'false' !== $_POST['active'];
162
163
		check_ajax_referer( "jetpack_toggle_autoupdate-{$type}" );
164
165
		if ( ! in_array( $type, array( 'plugins', 'plugins_translations' ) ) ) {
166
			wp_send_json_error();
167
			return;
168
		}
169
170
		$jetpack_option_name = "autoupdate_{$type}";
171
172
		$list = Jetpack_Options::get_option( $jetpack_option_name, array() );
173
174
		if ( $active ) {
175
			$list = array_unique( array_merge( $list, (array) $slug ) );
176
		} else {
177
			$list = array_diff( $list, (array) $slug );
178
		}
179
180
		Jetpack_Options::update_option( $jetpack_option_name, $list );
181
182
		wp_send_json_success( $list );
183
	}
184
185 View Code Duplication
	public function enqueue() {
186
		wp_enqueue_script( 'calypsoify_wpadminmods_js', plugin_dir_url( __FILE__ ) . 'mods.js', false, JETPACK__VERSION );
187
		wp_localize_script( 'calypsoify_wpadminmods_js', 'CalypsoifyOpts', array(
188
			'nonces' => array(
189
				'autoupdate_plugins' => wp_create_nonce( 'jetpack_toggle_autoupdate-plugins' ),
190
				'autoupdate_plugins_translations' => wp_create_nonce( 'jetpack_toggle_autoupdate-plugins_translations' ),
191
			)
192
		) );
193
	}
194
195
	public function enqueue_for_gutenberg() {
196
		wp_enqueue_script( 'calypsoify_wpadminmods_js', plugin_dir_url( __FILE__ ) . 'mods-gutenberg.js', false, JETPACK__VERSION );
197
		wp_localize_script(
198
			'calypsoify_wpadminmods_js',
199
			'calypsoifyGutenberg',
200
			array(
201
				'closeUrl'   => $this->get_close_gutenberg_url(),
202
				'manageReusableBlocksUrl' => $this->get_calypso_origin() . '/types/wp_block' . $this->get_site_suffix(),
203
			)
204
		);
205
	}
206
207
	/**
208
	 * Returns the Calypso domain that originated the current request.
209
	 *
210
	 * @return string
211
	 */
212
	private function get_calypso_origin() {
213
		$origin    = ! empty( $_GET['origin'] ) ? $_GET['origin'] : 'https://wordpress.com';
214
		$whitelist = array(
215
			'http://calypso.localhost:3000',
216
			'http://127.0.0.1:41050', // Desktop App
217
			'https://wpcalypso.wordpress.com',
218
			'https://horizon.wordpress.com',
219
			'https://wordpress.com',
220
		);
221
		return in_array( $origin, $whitelist ) ? $origin : 'https://wordpress.com';
222
223 View Code Duplication
		function get_site_suffix() {
0 ignored issues
show
Unused Code introduced by
function get_site_suffix... } return ''; } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
224
			if ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'build_raw_urls' ) ) {
225
				$site_suffix = Jetpack::build_raw_urls( home_url() );
226
			} elseif ( class_exists( 'WPCOM_Masterbar' ) && method_exists( 'WPCOM_Masterbar', 'get_calypso_site_slug' ) ) {
227
				$site_suffix = WPCOM_Masterbar::get_calypso_site_slug( get_current_blog_id() );
228
			}
229
230
			if ( $site_suffix ) {
231
				return "/${site_suffix}";
232
			}
233
			return '';
234
		}
235
	}
236
237
	/**
238
	 * Returns the site slug suffix to be used as part of the Calypso URLs. It already
239
	 * includes the slash separator at the beginning.
240
	 *
241
	 * @example "https://wordpress.com/block-editor" . $this->get_site_suffix()
242
	 *
243
	 * @return string
244
	 */
245 View Code Duplication
	private function get_site_suffix() {
246
		if ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'build_raw_urls' ) ) {
247
			$site_suffix = Jetpack::build_raw_urls( home_url() );
248
		} elseif ( class_exists( 'WPCOM_Masterbar' ) && method_exists( 'WPCOM_Masterbar', 'get_calypso_site_slug' ) ) {
249
			$site_suffix = WPCOM_Masterbar::get_calypso_site_slug( get_current_blog_id() );
250
		}
251
252
		if ( $site_suffix ) {
253
			return "/${site_suffix}";
0 ignored issues
show
Bug introduced by
The variable $site_suffix does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
254
		}
255
		return '';
256
	}
257
258
	/**
259
	 * Returns the Calypso URL that displays either the current post type list (if no args
260
	 * are supplied) or the classic editor for the current post (if a post ID is supplied).
261
	 *
262
	 * @param int|null $post_id
263
	 * @return string
264
	 */
265
	public function get_calypso_url( $post_id = null ) {
266
		$screen = get_current_screen();
267
		$post_type = $screen->post_type;
268
		if ( is_null( $post_id ) ) {
269
			// E.g. `posts`, `pages`, or `types/some_custom_post_type`
270
			$post_type_suffix = ( 'post' === $post_type || 'page' === $post_type )
271
				? "/${post_type}s"
272
				: "/types/${post_type}";
273
			$post_suffix = '';
274
		} else {
275
			$post_type_suffix = ( 'post' === $post_type || 'page' === $post_type )
276
				? "/${post_type}"
277
				: "/edit/${post_type}";
278
			$post_suffix = "/${post_id}";
279
		}
280
281
		return $this->get_calypso_origin() . $post_type_suffix . $this->get_site_suffix() . $post_suffix;
282
	}
283
284
	/**
285
	 * Returns the URL to be used on the block editor close button for going back to the
286
	 * Calypso post list.
287
	 *
288
	 * @return string
289
	 */
290
	public function get_close_gutenberg_url() {
291
		return $this->get_calypso_url();
292
	}
293
294
	/**
295
	 * Returns the URL for switching the user's editor to the Calypso (WordPress.com Classic) editor.
296
	 *
297
	 * @return string
298
	 */
299
	public function get_switch_to_classic_editor_url() {
300
		return add_query_arg(
301
			'set-editor',
302
			'classic',
303
			$this->is_calypsoify_enabled ? $this->get_calypso_url( get_the_ID() ) : false
304
		);
305
	}
306
307
	public function check_param() {
308
		if ( isset( $_GET['calypsoify'] ) ) {
309
			if ( 1 == (int) $_GET['calypsoify'] ) {
310
				update_user_meta( get_current_user_id(), 'calypsoify', 1 );
311
			} else {
312
				update_user_meta( get_current_user_id(), 'calypsoify', 0 );
313
			}
314
315
			$page = remove_query_arg( 'calypsoify', wp_basename( $_SERVER['REQUEST_URI'] ) );
316
317
			wp_safe_redirect( admin_url( $page ) );
318
		}
319
	}
320
321
	/**
322
	 * Return whether a post type should display the Gutenberg/block editor.
323
	 *
324
	 * @since 6.7.0
325
	 */
326
	public function is_post_type_gutenberg( $post_type ) {
327
		return use_block_editor_for_post_type( $post_type );
328
	}
329
330
	public function is_page_gutenberg() {
331
		$page = wp_basename( esc_url( $_SERVER['REQUEST_URI'] ) );
332
333
		if ( false !== strpos( $page, 'post-new.php' ) && empty ( $_GET['post_type'] ) ) {
334
			return true;
335
		}
336
337
		if ( false !== strpos( $page, 'post-new.php' ) && isset( $_GET['post_type'] ) && $this->is_post_type_gutenberg( $_GET['post_type'] ) ) {
338
			return true;
339
		}
340
341 View Code Duplication
		if ( false !== strpos( $page, 'post.php' ) ) {
342
			$post = get_post( $_GET['post'] );
343
			if ( isset( $post ) && isset( $post->post_type ) && $this->is_post_type_gutenberg( $post->post_type ) ) {
344
				return true;
345
			}
346
		}
347
348 View Code Duplication
		if ( false !== strpos( $page, 'revision.php' ) ) {
349
			$post   = get_post( $_GET['revision'] );
350
			$parent = get_post( $post->post_parent );
351
			if ( isset( $parent ) && isset( $parent->post_type ) && $this->is_post_type_gutenberg( $parent->post_type ) ) {
352
				return true;
353
			}
354
		}
355
356
		return false;
357
	}
358
359
	/**
360
	 * Attach a WP_List_Table views filter to all screens.
361
	 */
362
	public function attach_views_filter( $current_screen ) {
363
		add_filter( "views_{$current_screen->id}", array( $this, 'filter_views' ) );
364
	}
365
366
	/**
367
	 * Remove the parentheses from list table view counts when Calypsofied.
368
	 * 
369
	 * @param array $views Array of views. See: WP_List_Table::get_views().
370
	 * @return array Filtered views.
371
	 */
372
	public function filter_views( $views ) {
373
		foreach ( $views as $id => $view ) {
374
			$views[ $id ] = preg_replace( '/<span class="count">\((\d+)\)<\/span>/', '<span class="count">$1</span>', $view );
375
		}
376
377
		return $views;
378
	}
379
}
380
381
$Jetpack_Calypsoify = Jetpack_Calypsoify::getInstance();
382