Completed
Push — fix/sync-serialize-closures ( 7aebd5...68d535 )
by
unknown
44:55 queued 35:12
created

Jetpack_Keyring_Service_Helper   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 242
Duplicated Lines 19.01 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 0
Metric Value
dl 46
loc 242
rs 10
c 0
b 0
f 0
wmc 27
lcom 2
cbo 3

10 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 7 2
A __construct() 0 5 1
A register_sharing_page() 0 19 3
A get_services() 12 16 4
A api_url() 0 20 3
A connect_url() 12 12 1
A refresh_url() 10 13 1
A disconnect_url() 12 12 1
B admin_page_load() 0 63 9
A disconnect() 0 10 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
class Jetpack_Keyring_Service_Helper {
4
	/**
5
	 * @var Jetpack_Keyring_Service_Helper
6
	 **/
7
	private static $instance = null;
8
9
	/**
10
	 * Whether the `sharing` page is registered.
11
	 *
12
	 * @var bool
13
	 */
14
	private static $is_sharing_page_registered = false;
15
16
	static function init() {
17
		if ( is_null( self::$instance ) ) {
18
			self::$instance = new Jetpack_Keyring_Service_Helper;
19
		}
20
21
		return self::$instance;
22
	}
23
24
	public static $SERVICES = array(
25
		'facebook' => array(
26
			'for' => 'publicize'
27
		),
28
		'twitter' => array(
29
			'for' => 'publicize'
30
		),
31
		'linkedin' => array(
32
			'for' => 'publicize'
33
		),
34
		'tumblr' => array(
35
			'for' => 'publicize'
36
		),
37
		'path' => array(
38
			'for' => 'publicize'
39
		),
40
		'google_plus' => array(
41
			'for' => 'publicize'
42
		),
43
		'google_site_verification' => array(
44
			'for' => 'other'
45
		)
46
	);
47
48
	/**
49
	 * Constructor
50
	 */
51
	private function __construct() {
52
		add_action( 'admin_menu', array( __CLASS__, 'register_sharing_page' ) );
53
54
		add_action( 'load-settings_page_sharing', array( __CLASS__, 'admin_page_load' ), 9 );
55
	}
56
57
	/**
58
	 * We need a `sharing` page to be able to connect and disconnect services.
59
	 */
60
	public static function register_sharing_page() {
61
		if ( self::$is_sharing_page_registered ) {
62
			return;
63
		}
64
65
		self::$is_sharing_page_registered = true;
66
67
		if ( ! current_user_can( 'manage_options' ) ) {
68
			return;
69
		}
70
71
		global $_registered_pages;
72
73
		require_once ABSPATH . 'wp-admin/includes/plugin.php';
74
75
		$hookname = get_plugin_page_hookname( 'sharing', 'options-general.php' );
76
		add_action( $hookname, array( __CLASS__, 'admin_page_load' ) );
77
		$_registered_pages[ $hookname ] = true; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
78
	}
79
80
	function get_services( $filter = 'all' ) {
81
		$services = array();
82
83 View Code Duplication
		if ( 'all' === $filter ) {
84
			return $services;
85
		} else {
86
			$connected_services = array();
87
			foreach ( $services as $service => $empty ) {
88
				$connections = $this->get_connections( $service );
0 ignored issues
show
Bug introduced by
The method get_connections() does not seem to exist on object<Jetpack_Keyring_Service_Helper>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
89
				if ( $connections ) {
90
					$connected_services[ $service ] = $connections;
91
				}
92
			}
93
			return $connected_services;
94
		}
95
	}
96
97
	/**
98
	 * Gets a URL to the public-api actions. Works like WP's admin_url
99
	 *
100
	 * @param string $service Shortname of a specific service.
101
	 *
102
	 * @return URL to specific public-api process
103
	 */
104
	// on WordPress.com this is/calls Keyring::admin_url
105
	static function api_url( $service = false, $params = array() ) {
106
		/**
107
		 * Filters the API URL used to interact with WordPress.com.
108
		 *
109
		 * @since 2.0.0
110
		 *
111
		 * @param string https://public-api.wordpress.com/connect/?jetpack=publicize Default Publicize API URL.
112
		 */
113
		$url = apply_filters( 'publicize_api_url', 'https://public-api.wordpress.com/connect/?jetpack=publicize' );
114
115
		if ( $service ) {
116
			$url = add_query_arg( array( 'service' => $service ), $url );
117
		}
118
119
		if ( count( $params ) ) {
120
			$url = add_query_arg( $params, $url );
121
		}
122
123
		return $url;
124
	}
125
126 View Code Duplication
	static function connect_url( $service_name, $for ) {
127
		return add_query_arg(
128
			array(
129
				'action'   => 'request',
130
				'service'  => $service_name,
131
				'kr_nonce' => wp_create_nonce( 'keyring-request' ),
132
				'nonce'    => wp_create_nonce( "keyring-request-$service_name" ),
133
				'for'      => $for,
134
			),
135
			admin_url( 'options-general.php?page=sharing' )
136
		);
137
	}
138
139 View Code Duplication
	static function refresh_url( $service_name, $for ) {
140
		return add_query_arg(
141
			array(
142
				'action'   => 'request',
143
				'service'  => $service_name,
144
				'kr_nonce' => wp_create_nonce( 'keyring-request' ),
145
				'refresh'  => 1,
146
				'for'      => $for,
147
				'nonce'    => wp_create_nonce( "keyring-request-$service_name" ),
148
			),
149
			admin_url( 'options-general.php?page=sharing' )
150
		);
151
	}
152
153 View Code Duplication
	static function disconnect_url( $service_name, $id ) {
154
		return add_query_arg(
155
			array(
156
				'action'   => 'delete',
157
				'service'  => $service_name,
158
				'id'       => $id,
159
				'kr_nonce' => wp_create_nonce( 'keyring-request' ),
160
				'nonce'    => wp_create_nonce( "keyring-request-$service_name" ),
161
			),
162
			admin_url( 'options-general.php?page=sharing' )
163
		);
164
	}
165
166
	static function admin_page_load() {
167
		if ( isset( $_GET['action'] ) ) {
168
			if ( isset( $_GET['service'] ) ) {
169
				$service_name = $_GET['service'];
170
			}
171
172
			switch ( $_GET['action'] ) {
173
174
				case 'request':
175
					check_admin_referer( 'keyring-request', 'kr_nonce' );
176
					check_admin_referer( "keyring-request-$service_name", 'nonce' );
0 ignored issues
show
Bug introduced by
The variable $service_name 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...
177
178
					$verification = Jetpack::generate_secrets( 'publicize' );
179
					if ( ! $verification ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $verification of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
180
						$url = Jetpack::admin_url( 'jetpack#/settings' );
181
						wp_die( sprintf( __( "Jetpack is not connected. Please connect Jetpack by visiting <a href='%s'>Settings</a>.", 'jetpack' ), $url ) );
182
183
					}
184
					$stats_options = get_option( 'stats_options' );
185
					$wpcom_blog_id = Jetpack_Options::get_option( 'id' );
186
					$wpcom_blog_id = ! empty( $wpcom_blog_id ) ? $wpcom_blog_id : $stats_options['blog_id'];
187
188
					$user     = wp_get_current_user();
189
					$redirect = Jetpack_Keyring_Service_Helper::api_url( $service_name, urlencode_deep( array(
190
						'action'       => 'request',
191
						'redirect_uri' => add_query_arg( array( 'action' => 'done' ), menu_page_url( 'sharing', false ) ),
192
						'for'          => 'publicize',
193
						// required flag that says this connection is intended for publicize
194
						'siteurl'      => site_url(),
195
						'state'        => $user->ID,
196
						'blog_id'      => $wpcom_blog_id,
197
						'secret_1'     => $verification['secret_1'],
198
						'secret_2'     => $verification['secret_2'],
199
						'eol'          => $verification['exp'],
200
					) ) );
201
					wp_redirect( $redirect );
202
					exit;
203
					break;
0 ignored issues
show
Unused Code introduced by
break; 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...
204
205
				case 'completed':
206
					$xml = new Jetpack_IXR_Client();
207
					$xml->query( 'jetpack.fetchPublicizeConnections' );
208
209
					if ( ! $xml->isError() ) {
210
						$response = $xml->getResponse();
211
						Jetpack_Options::update_option( 'publicize_connections', $response );
212
					}
213
214
					break;
215
216
				case 'delete':
217
					$id = $_GET['id'];
218
219
					check_admin_referer( 'keyring-request', 'kr_nonce' );
220
					check_admin_referer( "keyring-request-$service_name", 'nonce' );
221
222
					Jetpack_Keyring_Service_Helper::disconnect( $service_name, $id );
223
224
					do_action( 'connection_disconnected', $service_name );
225
					break;
226
			}
227
		}
228
	}
229
230
	/**
231
	 * Remove a Publicize connection
232
	 */
233
	static function disconnect( $service_name, $connection_id, $_blog_id = false, $_user_id = false, $force_delete = false ) {
234
		$xml = new Jetpack_IXR_Client();
235
		$xml->query( 'jetpack.deletePublicizeConnection', $connection_id );
236
237
		if ( ! $xml->isError() ) {
238
			Jetpack_Options::update_option( 'publicize_connections', $xml->getResponse() );
239
		} else {
240
			return false;
241
		}
242
	}
243
244
}
245