<?php class WPCF7_Integration { private static $instance; private $services = array(); private $categories = array(); private function __construct() { } public static function get_instance() { if (empty(self::$instance)) { self::$instance = new self(); } return self::$instance; } public function add_service($name, WPCF7_Service $service) { $name = sanitize_key($name); if (empty($name) or isset($this->services[$name])) { return false; } $this->services[$name] = $service; } public function add_category($name, $title) { $name = sanitize_key($name); if (empty($name) or isset($this->categories[$name])) { return false; } $this->categories[$name] = $title; } public function service_exists($name = '') { if ('' == $name) { return (bool) count($this->services); } else { return isset($this->services[$name]); } } public function get_service($name) { if ($this->service_exists($name)) { return $this->services[$name]; } else { return false; } } public function list_services($args = '') { $args = wp_parse_args($args, array('include' => array())); $singular = false; $services = (array) $this->services; if (!empty($args['include'])) { $services = array_intersect_key($services, array_flip((array) $args['include'])); if (1 == count($services)) { $singular = true; } } if (empty($services)) { return; } $action = wpcf7_current_action(); foreach ($services as $name => $service) { $cats = array_intersect_key($this->categories, array_flip($service->get_categories())); ?> <div class="card<?php echo $service->is_active() ? ' active' : ''; ?>" id="<?php echo esc_attr($name); ?>"> <?php $service->icon(); ?> <h2 class="title"><?php echo esc_html($service->get_title()); ?></h2> <div class="infobox"> <?php echo esc_html(implode(', ', $cats)); ?> </div> <br class="clear" /> <div class="inside"> <?php if ($singular) { $service->display($action); } else { $service->display(); } ?> </div> </div> <?php } } } abstract class WPCF7_Service { public abstract function get_title(); public abstract function is_active(); public function get_categories() { return array(); } public function icon() { return ''; } public function link() { return ''; } public function load($action = '') { } public function display($action = '') { } public function admin_notice($message = '') { } } class WPCF7_Service_OAuth2 extends WPCF7_Service { protected $client_id = ''; protected $client_secret = ''; protected $access_token = ''; protected $refresh_token = ''; protected $authorization_endpoint = 'https://example.com/authorization'; protected $token_endpoint = 'https://example.com/token'; public function get_title() { return ''; } public function is_active() { return !empty($this->refresh_token); } protected function save_data() { } protected function reset_data() { } protected function get_redirect_uri() { return admin_url(); } protected function menu_page_url($args = '') { return menu_page_url('wpcf7-integration', false); } public function load($action = '') { if ('auth_redirect' == $action) { $code = isset($_GET['code']) ? $_GET['code'] : ''; if ($code) { $this->request_token($code); } if (!empty($this->access_token)) { $message = 'success'; } else { $message = 'failed'; } wp_safe_redirect($this->menu_page_url(array('action' => 'setup', 'message' => $message))); exit; } } protected function authorize($scope = '') { $endpoint = add_query_arg(array('response_type' => 'code', 'client_id' => $this->client_id, 'redirect_uri' => urlencode($this->get_redirect_uri()), 'scope' => $scope), $this->authorization_endpoint); if (wp_redirect(esc_url_raw($endpoint))) { exit; } } protected function get_http_authorization_header($scheme = 'basic') { $scheme = strtolower(trim($scheme)); switch ($scheme) { case 'bearer': return sprintf('Bearer %s', $this->access_token); case 'basic': default: return sprintf('Basic %s', base64_encode($this->client_id . ':' . $this->client_secret)); } } protected function request_token($authorization_code) { $endpoint = add_query_arg(array('code' => $authorization_code, 'redirect_uri' => urlencode($this->get_redirect_uri()), 'grant_type' => 'authorization_code'), $this->token_endpoint); $request = array('headers' => array('Authorization' => $this->get_http_authorization_header('basic'))); $response = wp_remote_post(esc_url_raw($endpoint), $request); $response_code = (int) wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); $response_body = json_decode($response_body, true); if (WP_DEBUG and 400 <= $response_code) { $this->log($endpoint, $request, $response); } if (401 == $response_code) { $this->access_token = null; $this->refresh_token = null; } else { if (isset($response_body['access_token'])) { $this->access_token = $response_body['access_token']; } else { $this->access_token = null; } if (isset($response_body['refresh_token'])) { $this->refresh_token = $response_body['refresh_token']; } else { $this->refresh_token = null; } } $this->save_data(); return $response; } protected function refresh_token() { $endpoint = add_query_arg(array('refresh_token' => $this->refresh_token, 'grant_type' => 'refresh_token'), $this->token_endpoint); $request = array('headers' => array('Authorization' => $this->get_http_authorization_header('basic'))); $response = wp_remote_post(esc_url_raw($endpoint), $request); $response_code = (int) wp_remote_retrieve_response_code($response); $response_body = wp_remote_retrieve_body($response); $response_body = json_decode($response_body, true); if (WP_DEBUG and 400 <= $response_code) { $this->log($endpoint, $request, $response); } if (401 == $response_code) { $this->access_token = null; $this->refresh_token = null; } else { if (isset($response_body['access_token'])) { $this->access_token = $response_body['access_token']; } else { $this->access_token = null; } if (isset($response_body['refresh_token'])) { $this->refresh_token = $response_body['refresh_token']; } } $this->save_data(); return $response; } protected function remote_request($url, $request = array()) { static $refreshed = false; $request = wp_parse_args($request, array()); $request['headers'] = array_merge($request['headers'], array('Authorization' => $this->get_http_authorization_header('bearer'))); $response = wp_remote_request(esc_url_raw($url), $request); if (401 === wp_remote_retrieve_response_code($response) and !$refreshed) { $this->refresh_token(); $refreshed = true; $response = $this->remote_request($url, $request); } return $response; } protected function log($url, $request, $response) { wpcf7_log_remote_request($url, $request, $response); } }