diff --git a/includes/class-indieauth-authorize.php b/includes/class-authorize.php
similarity index 77%
rename from includes/class-indieauth-authorize.php
rename to includes/class-authorize.php
index bba4bb5..0f80a47 100644
--- a/includes/class-indieauth-authorize.php
+++ b/includes/class-authorize.php
@@ -5,6 +5,10 @@
* @package IndieAuth
*/
+namespace IndieAuth;
+
+use IndieAuth\Token\User as Token_User;
+
/**
* IndieAuth Authorize class.
*
@@ -12,12 +16,12 @@
*
* @since 1.0.0
*/
-class IndieAuth_Authorize {
+class Authorize {
/**
* Error object.
*
- * @var WP_Error|WP_OAuth_Response|null
+ * @var \WP_Error|OAuth_Response|null
*/
public $error = null;
@@ -58,30 +62,30 @@ public function load() {
// WordPress validates the auth cookie at priority 10 and this cannot be overridden by an earlier priority.
// It validates the logged in cookie at 20 and can be overridden by something with a higher priority.
- add_filter( 'determine_current_user', array( $this, 'determine_current_user' ), 15 );
- add_filter( 'rest_authentication_errors', array( $this, 'rest_authentication_errors' ) );
+ \add_filter( 'determine_current_user', array( $this, 'determine_current_user' ), 15 );
+ \add_filter( 'rest_authentication_errors', array( $this, 'rest_authentication_errors' ) );
- add_filter( 'indieauth_scopes', array( $this, 'get_indieauth_scopes' ), 9 );
- add_filter( 'indieauth_response', array( $this, 'get_indieauth_response' ), 9 );
- add_filter( 'wp_rest_server_class', array( $this, 'wp_rest_server_class' ) );
- add_filter( 'rest_request_after_callbacks', array( $this, 'return_oauth_error' ), 10, 3 );
+ \add_filter( 'indieauth_scopes', array( $this, 'get_indieauth_scopes' ), 9 );
+ \add_filter( 'indieauth_response', array( $this, 'get_indieauth_response' ), 9 );
+ \add_filter( 'wp_rest_server_class', array( $this, 'wp_rest_server_class' ) );
+ \add_filter( 'rest_request_after_callbacks', array( $this, 'return_oauth_error' ), 10, 3 );
}
/**
* Ensures responses to any IndieAuth endpoints are always OAuth Responses rather than WP_Error.
*
- * @param WP_REST_Response|WP_HTTP_Response|WP_Error|mixed $response Result to send to the client.
- * @param array $handler Route handler used for the request.
- * @param WP_REST_Request $request Request used to generate the response.
- * @return WP_REST_Response|WP_OAuth_Response|mixed Modified response.
+ * @param \WP_REST_Response|\WP_HTTP_Response|\WP_Error|mixed $response Result to send to the client.
+ * @param array $handler Route handler used for the request.
+ * @param \WP_REST_Request $request Request used to generate the response.
+ * @return \WP_REST_Response|OAuth_Response|mixed Modified response.
*/
public static function return_oauth_error( $response, $handler, $request ) {
if ( 0 !== strpos( $request->get_route(), '/indieauth/1.0/' ) ) {
return $response;
}
- if ( is_wp_error( $response ) ) {
+ if ( \is_wp_error( $response ) ) {
return wp_error_to_oauth_response( $response );
}
return $response;
@@ -98,7 +102,7 @@ public static function return_oauth_error( $response, $handler, $request ) {
*/
public static function wp_rest_server_class( $class ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.classFound
global $current_user;
- if ( defined( 'REST_REQUEST' ) && REST_REQUEST && $current_user instanceof WP_User && 0 === $current_user->ID ) {
+ if ( defined( 'REST_REQUEST' ) && REST_REQUEST && $current_user instanceof \WP_User && 0 === $current_user->ID ) {
/*
* For our authentication to work, we need to remove the cached lack
* of a current user, so the next time it checks, we can detect that
@@ -137,16 +141,16 @@ public function get_indieauth_response( $response ) {
* Attached to the rest_authentication_errors filter. Passes through existing
* errors registered on the filter.
*
- * @param WP_Error|null|true $error Current error, null or true.
- * @return WP_Error|null|true Error if one is set, unchanged otherwise.
+ * @param \WP_Error|null|true $error Current error, null or true.
+ * @return \WP_Error|null|true Error if one is set, unchanged otherwise.
*/
public function rest_authentication_errors( $error = null ) {
- if ( is_user_logged_in() ) {
+ if ( \is_user_logged_in() ) {
// Another OAuth2 plugin successfully authenticated.
return $error;
}
- if ( is_wp_error( $this->error ) ) {
+ if ( \is_wp_error( $this->error ) ) {
return $this->error;
}
@@ -193,9 +197,9 @@ public function determine_current_user( $user_id ) {
}
}
- $this->error = new WP_OAuth_Response(
+ $this->error = new OAuth_Response(
'unauthorized',
- __( 'User Not Found on this Site', 'indieauth' ),
+ \__( 'User Not Found on this Site', 'indieauth' ),
401,
array(
'response' => $params,
@@ -217,16 +221,16 @@ public function determine_current_user( $user_id ) {
public function get_authorization_header() {
$auth = null;
if ( ! empty( $_SERVER['HTTP_AUTHORIZATION'] ) ) {
- $auth = wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+ $auth = \wp_unslash( $_SERVER['HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
} elseif ( ! empty( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ) {
// When Apache speaks via FastCGI with PHP, then the authorization header is often available as REDIRECT_HTTP_AUTHORIZATION.
- $auth = wp_unslash( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+ $auth = \wp_unslash( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
} else {
$headers = getallheaders();
// Check for the authorization header case-insensitively.
foreach ( $headers as $key => $value ) {
if ( strtolower( $key ) === 'authorization' ) {
- $auth = wp_unslash( $value );
+ $auth = \wp_unslash( $value );
break;
}
}
@@ -278,7 +282,7 @@ public function get_token_from_request() {
if ( empty( $_POST['access_token'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
return null;
}
- $token = sanitize_text_field( wp_unslash( $_POST['access_token'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ $token = \sanitize_text_field( \wp_unslash( $_POST['access_token'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
if ( is_string( $token ) ) {
return $token;
@@ -290,15 +294,15 @@ public function get_token_from_request() {
* Verifies Access Token.
*
* @param string $token The token to verify.
- * @return array|WP_OAuth_Response Return either the token information or an OAuth Error Object.
+ * @return array|OAuth_Response Return either the token information or an OAuth Error Object.
*/
public function verify_access_token( $token ) {
$tokens = new Token_User( '_indieauth_token_' );
$return = $tokens->get( $token );
if ( empty( $return ) ) {
- return new WP_OAuth_Response(
+ return new OAuth_Response(
'invalid_token',
- __( 'Invalid access token', 'indieauth' ),
+ \__( 'Invalid access token', 'indieauth' ),
401
);
}
@@ -306,7 +310,7 @@ public function verify_access_token( $token ) {
return $return;
}
$return['last_accessed'] = time();
- $return['last_ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
+ $return['last_ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? \sanitize_text_field( \wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
$tokens->update( $token, $return );
if ( array_key_exists( 'exp', $return ) ) {
$return['expires_in'] = $return['exp'] - time();
@@ -318,15 +322,15 @@ public function verify_access_token( $token ) {
* Verifies authorization code.
*
* @param string $code Authorization Code.
- * @return array|WP_OAuth_Response Return either the code information or an OAuth Error object.
+ * @return array|OAuth_Response Return either the code information or an OAuth Error object.
*/
public static function verify_authorization_code( $code ) {
$tokens = new Token_User( '_indieauth_code_' );
$return = $tokens->get( $code );
if ( empty( $return ) ) {
- return new WP_OAuth_Response(
+ return new OAuth_Response(
'invalid_code',
- __( 'Invalid authorization code', 'indieauth' ),
+ \__( 'Invalid authorization code', 'indieauth' ),
401
);
}
diff --git a/includes/class-autoloader.php b/includes/class-autoloader.php
new file mode 100644
index 0000000..e184801
--- /dev/null
+++ b/includes/class-autoloader.php
@@ -0,0 +1,106 @@
+prefix = $prefix;
+ $this->prefix_length = \strlen( $prefix );
+ $this->path = \rtrim( $path . '/' );
+ }
+
+ /**
+ * Registers Autoloader's autoload function.
+ *
+ * @throws \Exception When autoload_function cannot be registered.
+ *
+ * @param string $prefix Namespace prefix all classes have in common.
+ * @param string $path Path to the files to be loaded.
+ */
+ public static function register_path( $prefix, $path ) {
+ $loader = new self( $prefix, $path );
+ \spl_autoload_register( array( $loader, 'load' ) );
+ }
+
+ /**
+ * Loads a class if its namespace starts with `$this->prefix`.
+ *
+ * @param string $class_name The class to be loaded.
+ */
+ public function load( $class_name ) {
+ if ( \strpos( $class_name, $this->prefix . self::NS_SEPARATOR ) !== 0 ) {
+ return;
+ }
+
+ // Strip prefix from the start (ala PSR-4).
+ $class_name = \substr( $class_name, $this->prefix_length + 1 );
+ $class_name = \strtolower( $class_name );
+ $dir = '';
+
+ $last_ns_pos = \strripos( $class_name, self::NS_SEPARATOR );
+ if ( false !== $last_ns_pos ) {
+ $namespace = \substr( $class_name, 0, $last_ns_pos );
+ $namespace = \str_replace( '_', '-', $namespace );
+ $class_name = \substr( $class_name, $last_ns_pos + 1 );
+ $dir = \str_replace( self::NS_SEPARATOR, DIRECTORY_SEPARATOR, $namespace ) . DIRECTORY_SEPARATOR;
+ }
+
+ $path = $this->path . $dir . 'class-' . \str_replace( '_', '-', $class_name ) . '.php';
+
+ if ( ! \file_exists( $path ) ) {
+ $path = $this->path . $dir . 'interface-' . \str_replace( '_', '-', $class_name ) . '.php';
+ }
+
+ if ( ! \file_exists( $path ) ) {
+ $path = $this->path . $dir . 'trait-' . \str_replace( '_', '-', $class_name ) . '.php';
+ }
+
+ if ( \file_exists( $path ) ) {
+ require_once $path;
+ }
+ }
+}
diff --git a/includes/class-indieauth-client-discovery.php b/includes/class-client-discovery.php
similarity index 78%
rename from includes/class-indieauth-client-discovery.php
rename to includes/class-client-discovery.php
index 35d02c7..08ecdd1 100644
--- a/includes/class-indieauth-client-discovery.php
+++ b/includes/class-client-discovery.php
@@ -5,10 +5,12 @@
* @package IndieAuth
*/
+namespace IndieAuth;
+
/**
* Discovers information about an IndieAuth client from its client_id URL.
*/
-class IndieAuth_Client_Discovery {
+class Client_Discovery {
/**
* Discovered rel values.
@@ -78,7 +80,7 @@ public function __construct( $client_id ) {
return;
}
// Validate if this is an IP address.
- $ip = filter_var( wp_parse_url( $client_id, PHP_URL_HOST ), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 );
+ $ip = filter_var( \wp_parse_url( $client_id, PHP_URL_HOST ), FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 );
$donotfetch = array(
'127.0.0.1',
'0000:0000:0000:0000:0000:0000:0000:0001',
@@ -90,13 +92,13 @@ public function __construct( $client_id ) {
return;
}
- if ( 'localhost' === wp_parse_url( $client_id, PHP_URL_HOST ) ) {
+ if ( 'localhost' === \wp_parse_url( $client_id, PHP_URL_HOST ) ) {
return;
}
$response = self::parse( $client_id );
- if ( is_wp_error( $response ) ) {
+ if ( \is_wp_error( $response ) ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
- error_log( __( 'Failed to Retrieve IndieAuth Client Details ', 'indieauth' ) . wp_json_encode( $response ) );
+ \error_log( \__( 'Failed to Retrieve IndieAuth Client Details ', 'indieauth' ) . \wp_json_encode( $response ) );
return;
}
}
@@ -123,22 +125,22 @@ public function export() {
* Fetches the client URL content.
*
* @param string $url The URL to fetch.
- * @return array|WP_Error The HTTP response or WP_Error on failure.
+ * @return array|\WP_Error The HTTP response or WP_Error on failure.
*/
private function fetch( $url ) {
- $wp_version = get_bloginfo( 'version' );
- $user_agent = apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' ) );
+ $wp_version = \get_bloginfo( 'version' );
+ $user_agent = \apply_filters( 'http_headers_useragent', 'WordPress/' . $wp_version . '; ' . \get_bloginfo( 'url' ) );
$args = array(
'timeout' => 100,
'limit_response_size' => 1048576,
'redirection' => 3,
'user-agent' => "$user_agent; IndieAuth Client Information Discovery",
);
- $response = wp_safe_remote_get( $url, $args );
- if ( ! is_wp_error( $response ) ) {
- $code = wp_remote_retrieve_response_code( $response );
+ $response = \wp_safe_remote_get( $url, $args );
+ if ( ! \is_wp_error( $response ) ) {
+ $code = \wp_remote_retrieve_response_code( $response );
if ( ( $code / 100 ) !== 2 ) {
- return new WP_Error( 'retrieval_error', __( 'Failed to Retrieve Client Details', 'indieauth' ), $code );
+ return new \WP_Error( 'retrieval_error', \__( 'Failed to Retrieve Client Details', 'indieauth' ), $code );
}
}
@@ -149,18 +151,18 @@ private function fetch( $url ) {
* Parses the client URL to extract client metadata.
*
* @param string $url The client URL to parse.
- * @return void|WP_Error Void on success, WP_Error on failure.
+ * @return void|\WP_Error Void on success, WP_Error on failure.
*/
private function parse( $url ) {
$response = self::fetch( $url );
- if ( is_wp_error( $response ) ) {
+ if ( \is_wp_error( $response ) ) {
return $response;
}
- $content_type = wp_remote_retrieve_header( $response, 'content-type' );
+ $content_type = \wp_remote_retrieve_header( $response, 'content-type' );
if ( 'application/json' === $content_type ) {
- $this->json = json_decode( wp_remote_retrieve_body( $response ), true );
+ $this->json = json_decode( \wp_remote_retrieve_body( $response ), true );
/**
* Expected format is per the IndieAuth standard as revised 2024-06-23 to include a JSON Client Metadata File
*
@@ -175,10 +177,10 @@ private function parse( $url ) {
* }
*/
if ( ! is_array( $this->json ) || empty( $this->json ) ) {
- return new WP_Error( 'empty_json', __( 'Discovery Has Returned an Empty JSON Document', 'indieauth' ) );
+ return new \WP_Error( 'empty_json', \__( 'Discovery Has Returned an Empty JSON Document', 'indieauth' ) );
}
if ( ! array_key_exists( 'client_id', $this->json ) ) {
- return new WP_Error( 'missing_client_id', __( 'No Client ID Found in JSON Client Metadata', 'indieauth' ) );
+ return new \WP_Error( 'missing_client_id', \__( 'No Client ID Found in JSON Client Metadata', 'indieauth' ) );
}
$this->client_id = $this->json['client_id'];
if ( array_key_exists( 'client_name', $this->json ) ) {
@@ -191,7 +193,7 @@ private function parse( $url ) {
$this->client_uri = $this->json['client_uri'];
}
} elseif ( 'text/html' === $content_type ) {
- $content = wp_remote_retrieve_body( $response );
+ $content = \wp_remote_retrieve_body( $response );
$this->get_mf2( $content, $url );
if ( ! empty( $this->mf2 ) ) {
if ( array_key_exists( 'name', $this->mf2 ) ) {
@@ -205,14 +207,14 @@ private function parse( $url ) {
}
}
} else {
- $domdocument = new DOMDocument( wp_remote_retrieve_body( $response ) );
+ $domdocument = new \DOMDocument( \wp_remote_retrieve_body( $response ) );
$this->client_icon = $this->determine_icon( $this->rels );
$this->get_html( $domdocument );
$this->client_name = $this->html['title'];
}
if ( ! empty( $this->client_icon ) ) {
- $this->client_icon = WP_Http::make_absolute_url( $this->client_icon, $url );
+ $this->client_icon = \WP_Http::make_absolute_url( $this->client_icon, $url );
}
}
}
@@ -225,11 +227,11 @@ private function parse( $url ) {
*/
private function get_mf2( $input, $url ) {
if ( ! class_exists( 'Mf2\Parser' ) ) {
- require_once plugin_dir_path( __DIR__ ) . 'lib/mf2/Parser.php';
+ require_once \plugin_dir_path( __DIR__ ) . 'lib/mf2/Parser.php';
}
$mf = Mf2\parse( $input, $url );
if ( array_key_exists( 'rels', $mf ) ) {
- $this->rels = wp_array_slice_assoc( $mf['rels'], array( 'apple-touch-icon', 'icon', 'mask-icon' ) );
+ $this->rels = \wp_array_slice_assoc( $mf['rels'], array( 'apple-touch-icon', 'icon', 'mask-icon' ) );
}
if ( array_key_exists( 'items', $mf ) ) {
foreach ( $mf['items'] as $item ) {
@@ -244,10 +246,10 @@ private function get_mf2( $input, $url ) {
/**
* Extracts HTML metadata from a DOMDocument.
*
- * @param DOMDocument $input The parsed DOM document.
+ * @param \DOMDocument $input The parsed DOM document.
*/
private function get_html( $input ) {
- $xpath = new DOMXPath( $input );
+ $xpath = new \DOMXPath( $input );
if ( ! empty( $xpath ) ) {
$title = $xpath->query( '//title' );
if ( ! empty( $title ) ) {
@@ -319,7 +321,7 @@ private function determine_icon( $input ) {
$icons = $input['icon'];
}
- if ( is_array( $icons ) && ! wp_is_numeric_array( $icons ) && isset( $icons['url'] ) ) {
+ if ( is_array( $icons ) && ! \wp_is_numeric_array( $icons ) && isset( $icons['url'] ) ) {
return $icons['url'];
} elseif ( is_string( $icons[0] ) ) {
return $icons[0];
diff --git a/includes/class-indieauth-client-taxonomy.php b/includes/class-client-taxonomy.php
old mode 100755
new mode 100644
similarity index 68%
rename from includes/class-indieauth-client-taxonomy.php
rename to includes/class-client-taxonomy.php
index ee71335..5c32739
--- a/includes/class-indieauth-client-taxonomy.php
+++ b/includes/class-client-taxonomy.php
@@ -5,7 +5,7 @@
* @package IndieAuth
*/
-add_action( 'init', array( 'IndieAuth_Client_Taxonomy', 'init' ) );
+namespace IndieAuth;
/**
* Class that handles the client taxonomy functions.
@@ -14,7 +14,7 @@
*
* @since 1.0.0
*/
-final class IndieAuth_Client_Taxonomy {
+final class Client_Taxonomy {
/**
* Initialize the taxonomy.
@@ -22,7 +22,7 @@ final class IndieAuth_Client_Taxonomy {
public static function init() {
self::register();
- add_filter( 'terms_clauses', array( __CLASS__, 'terms_clauses' ), 11, 3 );
+ \add_filter( 'terms_clauses', array( __CLASS__, 'terms_clauses' ), 11, 3 );
}
/**
@@ -48,18 +48,18 @@ public static function terms_clauses( $clauses, $taxonomies, $args ) {
*/
public static function register() {
$labels = array(
- 'name' => _x( 'IndieAuth Applications', 'taxonomy general name', 'indieauth' ),
- 'singular_name' => _x( 'IndieAuth Applications', 'taxonomy singular name', 'indieauth' ),
- 'search_items' => _x( 'Search IndieAuth Applications', 'search locations', 'indieauth' ),
- 'popular_items' => _x( 'Popular Applications', 'popular locations', 'indieauth' ),
- 'all_items' => _x( 'All Applications', 'all taxonomy items', 'indieauth' ),
- 'edit_item' => _x( 'Edit Application', 'edit taxonomy item', 'indieauth' ),
- 'view_item' => _x( 'View Application Archive', 'view taxonomy item', 'indieauth' ),
- 'update_item' => _x( 'Update Application', 'update taxonomy item', 'indieauth' ),
- 'add_new_item' => _x( 'Add New Application', 'add taxonomy item', 'indieauth' ),
- 'new_item_name' => _x( 'New Application', 'new taxonomy item', 'indieauth' ),
- 'not found' => _x( 'No applications found', 'no clients found', 'indieauth' ),
- 'no_terms' => _x( 'No applications', 'no locations', 'indieauth' ),
+ 'name' => \_x( 'IndieAuth Applications', 'taxonomy general name', 'indieauth' ),
+ 'singular_name' => \_x( 'IndieAuth Applications', 'taxonomy singular name', 'indieauth' ),
+ 'search_items' => \_x( 'Search IndieAuth Applications', 'search locations', 'indieauth' ),
+ 'popular_items' => \_x( 'Popular Applications', 'popular locations', 'indieauth' ),
+ 'all_items' => \_x( 'All Applications', 'all taxonomy items', 'indieauth' ),
+ 'edit_item' => \_x( 'Edit Application', 'edit taxonomy item', 'indieauth' ),
+ 'view_item' => \_x( 'View Application Archive', 'view taxonomy item', 'indieauth' ),
+ 'update_item' => \_x( 'Update Application', 'update taxonomy item', 'indieauth' ),
+ 'add_new_item' => \_x( 'Add New Application', 'add taxonomy item', 'indieauth' ),
+ 'new_item_name' => \_x( 'New Application', 'new taxonomy item', 'indieauth' ),
+ 'not found' => \_x( 'No applications found', 'no clients found', 'indieauth' ),
+ 'no_terms' => \_x( 'No applications', 'no locations', 'indieauth' ),
);
$args = array(
@@ -74,44 +74,44 @@ public static function register() {
'show_tagcloud' => false,
'show_in_quick_edit' => false,
'show_admin_column' => false,
- 'description' => __( 'Stores information in IndieAuth Client Applications', 'indieauth' ),
+ 'description' => \__( 'Stores information in IndieAuth Client Applications', 'indieauth' ),
);
- $object_types = apply_filters( 'indieauth_client_taxonomy_object_types', array( 'post', 'page', 'attachment' ) );
+ $object_types = \apply_filters( 'indieauth_client_taxonomy_object_types', array( 'post', 'page', 'attachment' ) );
- register_taxonomy( 'indieauth_client', $object_types, $args );
+ \register_taxonomy( 'indieauth_client', $object_types, $args );
- register_meta(
+ \register_meta(
'term',
'icon',
array(
'object_subtype' => 'indieauth_client',
'type' => 'string',
- 'description' => __( 'IndieAuth Client Application Icon', 'indieauth' ),
+ 'description' => \__( 'IndieAuth Client Application Icon', 'indieauth' ),
'single' => true,
'sanitize_callback' => 'esc_url_raw',
'show_in_rest' => true,
)
);
- register_meta(
+ \register_meta(
'term',
'client_uri',
array(
'object_subtype' => 'indieauth_client',
'type' => 'string',
- 'description' => __( 'IndieAuth Client Application URI', 'indieauth' ),
+ 'description' => \__( 'IndieAuth Client Application URI', 'indieauth' ),
'single' => true,
'sanitize_callback' => 'esc_url_raw',
'show_in_rest' => true,
)
);
- register_meta(
+ \register_meta(
'term',
'last_modified',
array(
'object_subtype' => 'indieauth_client',
'type' => 'integer',
- 'description' => __( 'Last Modified Client Timestamp', 'indieauth' ),
+ 'description' => \__( 'Last Modified Client Timestamp', 'indieauth' ),
'single' => true,
'show_in_rest' => true,
)
@@ -130,7 +130,7 @@ public static function update_client_icon_from_discovery( $url ) {
return false;
}
- $client = new IndieAuth_Client_Discovery( $url );
+ $client = new Client_Discovery( $url );
if ( ! $client->get_icon() ) {
return false;
}
@@ -146,12 +146,12 @@ public static function update_client_icon_from_discovery( $url ) {
* @return string Generated slug.
*/
public static function generate_slug( $url ) {
- $host = wp_parse_url( $url, PHP_URL_HOST );
+ $host = \wp_parse_url( $url, PHP_URL_HOST );
// Strip leading www, if any.
$host = preg_replace( '/^www\./', '', $host );
- $path = wp_parse_url( $url, PHP_URL_PATH );
+ $path = \wp_parse_url( $url, PHP_URL_PATH );
$path = str_replace( '/', '_', $path );
- return sanitize_title( $host . $path );
+ return \sanitize_title( $host . $path );
}
/**
@@ -160,20 +160,20 @@ public static function generate_slug( $url ) {
* @param string $url Client URL.
* @param string|null $name Client name.
* @param string|null $icon Client icon URL.
- * @return array|WP_Error Client data or error.
+ * @return array|\WP_Error Client data or error.
*/
public static function add_client( $url, $name = null, $icon = null ) {
$exists = self::get_client( $url );
// Do Not Overwrite if Already Exists.
- if ( ! is_wp_error( $exists ) ) {
+ if ( ! \is_wp_error( $exists ) ) {
return $exists;
}
$client_uri = '';
if ( empty( $name ) ) {
- $client = new IndieAuth_Client_Discovery( $url );
+ $client = new Client_Discovery( $url );
if ( defined( 'INDIEAUTH_UNIT_TESTS' ) ) {
return array(
'client_id' => $url,
@@ -189,25 +189,25 @@ public static function add_client( $url, $name = null, $icon = null ) {
$icon = self::sideload_icon( $icon, $url );
- $term = wp_insert_term(
+ $term = \wp_insert_term(
$name,
'indieauth_client',
array(
'slug' => self::generate_slug( $url ),
- 'description' => esc_url_raw( $url ),
+ 'description' => \esc_url_raw( $url ),
)
);
- if ( is_wp_error( $term ) ) {
+ if ( \is_wp_error( $term ) ) {
return $term;
}
if ( ! empty( $icon ) ) {
- add_term_meta( $term['term_id'], 'icon', $icon );
+ \add_term_meta( $term['term_id'], 'icon', $icon );
}
if ( ! empty( $client_uri ) ) {
- add_term_meta( $term['term_id'], 'client_uri', $client_uri );
+ \add_term_meta( $term['term_id'], 'client_uri', $client_uri );
}
- add_term_meta( $term['term_id'], 'last_modified', time() );
+ \add_term_meta( $term['term_id'], 'last_modified', time() );
return array_filter(
array(
'url' => $url,
@@ -222,12 +222,12 @@ public static function add_client( $url, $name = null, $icon = null ) {
* Get client.
*
* @param string|int|null $url Client URL, term ID, or null for all.
- * @return array|WP_Error Client data or error.
+ * @return array|\WP_Error Client data or error.
*/
public static function get_client( $url = null ) {
// If URL is null retrieve all clients.
if ( is_null( $url ) ) {
- $terms = get_terms(
+ $terms = \get_terms(
array(
'taxonomy' => 'indieauth_client',
'hide_empty' => false,
@@ -239,19 +239,19 @@ public static function get_client( $url = null ) {
'url' => $term->description,
'name' => $term->name,
'id' => $term->term_id,
- 'icon' => get_term_meta( $term->term_id, 'icon', true ),
- 'uri' => get_term_meta( $term->term_id, 'client_uri', true ),
- 'last_modified' => get_term_meta( $term->term_id, 'last_modified', true ),
+ 'icon' => \get_term_meta( $term->term_id, 'icon', true ),
+ 'uri' => \get_term_meta( $term->term_id, 'client_uri', true ),
+ 'last_modified' => \get_term_meta( $term->term_id, 'last_modified', true ),
);
}
return $clients;
}
if ( is_numeric( $url ) ) {
- $terms = array( get_term( $url, 'indieauth_client' ) );
+ $terms = array( \get_term( $url, 'indieauth_client' ) );
return $terms;
} else {
- $terms = get_terms(
+ $terms = \get_terms(
array(
'taxonomy' => 'indieauth_client',
'description' => $url,
@@ -260,11 +260,11 @@ public static function get_client( $url = null ) {
);
}
if ( empty( $terms ) ) {
- return new WP_Error( 'not_found', __( 'No Term Found', 'indieauth' ) );
+ return new \WP_Error( 'not_found', \__( 'No Term Found', 'indieauth' ) );
}
if ( 1 !== count( $terms ) ) {
- return new WP_Error( 'multiples', __( 'Multiple Terms Found', 'indieauth' ), $terms );
+ return new \WP_Error( 'multiples', \__( 'Multiple Terms Found', 'indieauth' ), $terms );
}
$term = $terms[0];
@@ -273,9 +273,9 @@ public static function get_client( $url = null ) {
'url' => $term->description,
'name' => $term->name,
'id' => $term->term_id,
- 'icon' => get_term_meta( $term->term_id, 'icon', true ),
- 'uri' => get_term_meta( $term->term_id, 'client_uri', true ),
- 'last_modified' => get_term_meta( $term->term_id, 'last_modified', true ),
+ 'icon' => \get_term_meta( $term->term_id, 'icon', true ),
+ 'uri' => \get_term_meta( $term->term_id, 'client_uri', true ),
+ 'last_modified' => \get_term_meta( $term->term_id, 'last_modified', true ),
);
}
@@ -283,7 +283,7 @@ public static function get_client( $url = null ) {
* Delete a client.
*
* @param string $url Client URL.
- * @return bool|int|WP_Error Term ID or error.
+ * @return bool|int|\WP_Error Term ID or error.
*/
public static function delete_client( $url ) {
$client = self::get_client( $url );
@@ -293,7 +293,7 @@ public static function delete_client( $url ) {
self::delete_icon_file( $client['icon'] );
- return wp_delete_term(
+ return \wp_delete_term(
$client['id'],
'indieauth_client'
);
@@ -307,10 +307,10 @@ public static function delete_client( $url ) {
* @return string URL or path of upload directory.
*/
public static function upload_directory( $filepath = '', $url = false ) {
- $upload_dir = wp_get_upload_dir();
+ $upload_dir = \wp_get_upload_dir();
$upload_dir = $url ? $upload_dir['baseurl'] : $upload_dir['basedir'];
$upload_dir .= '/indieauth/icons/';
- $upload_dir = apply_filters( 'indieauth_client_icon_directory', $upload_dir, $url );
+ $upload_dir = \apply_filters( 'indieauth_client_icon_directory', $upload_dir, $url );
return $upload_dir . $filepath;
}
@@ -340,7 +340,7 @@ public static function delete_icon_file( $url ) {
return false;
}
if ( file_exists( $filepath ) ) {
- wp_delete_file( $filepath );
+ \wp_delete_file( $filepath );
return true;
}
return false;
@@ -369,7 +369,7 @@ public static function sideload_icon( $url, $client_id ) {
// Allow for common query parameters in image APIs to get a better quality image.
$query = array();
- wp_parse_str( wp_parse_url( $url, PHP_URL_QUERY ), $query );
+ \wp_parse_str( \wp_parse_url( $url, PHP_URL_QUERY ), $query );
if ( array_key_exists( 's', $query ) && is_numeric( $query['s'] ) ) {
$url = str_replace( 's=' . $query['s'], 's=' . INDIEAUTH_ICON_SIZE, $url );
}
@@ -379,12 +379,12 @@ public static function sideload_icon( $url, $client_id ) {
}
// Download profile picture and add as attachment.
- $download = download_url( $url, 300 );
- if ( is_wp_error( $download ) ) {
+ $download = \download_url( $url, 300 );
+ if ( \is_wp_error( $download ) ) {
return false;
}
- $file = wp_get_image_editor( $download );
- if ( is_wp_error( $file ) ) {
+ $file = \wp_get_image_editor( $download );
+ if ( \is_wp_error( $file ) ) {
return false;
}
$file->resize( null, INDIEAUTH_ICON_SIZE, true );
diff --git a/includes/class-indieauth-client.php b/includes/class-client.php
similarity index 66%
rename from includes/class-indieauth-client.php
rename to includes/class-client.php
index 414a171..f49c30c 100644
--- a/includes/class-indieauth-client.php
+++ b/includes/class-client.php
@@ -5,10 +5,12 @@
* @package IndieAuth
*/
+namespace IndieAuth;
+
/**
* IndieAuth Client class.
*/
-class IndieAuth_Client {
+class Client {
/**
* Metadata including endpoints.
@@ -28,17 +30,17 @@ class IndieAuth_Client {
* Constructor.
*/
public function __construct() {
- $this->client_id = trailingslashit( home_url() );
+ $this->client_id = \trailingslashit( \home_url() );
}
/**
* Perform a remote GET request.
*
* @param string $url URL to request.
- * @return array|WP_OAuth_Response Response array or error.
+ * @return array|OAuth_Response Response array or error.
*/
public function remote_get( $url ) {
- $resp = wp_remote_get(
+ $resp = \wp_remote_get(
$url,
array(
'headers' => array(
@@ -46,21 +48,21 @@ public function remote_get( $url ) {
),
)
);
- if ( is_wp_error( $resp ) ) {
+ if ( \is_wp_error( $resp ) ) {
return wp_error_to_oauth_response( $resp );
}
- $code = (int) wp_remote_retrieve_response_code( $resp );
- $body = wp_remote_retrieve_body( $resp );
+ $code = (int) \wp_remote_retrieve_response_code( $resp );
+ $body = \wp_remote_retrieve_body( $resp );
if ( ( $code / 100 ) !== 2 ) {
- return new WP_OAuth_Response( 'unable_retrieve', __( 'Unable to Retrieve', 'indieauth' ), $code, $body );
+ return new OAuth_Response( 'unable_retrieve', \__( 'Unable to Retrieve', 'indieauth' ), $code, $body );
}
$body = json_decode( $body, true );
if ( ! is_array( $body ) ) {
- return new WP_OAuth_Response( 'server_error', __( 'The endpoint did not return a JSON response', 'indieauth' ), 500 );
+ return new OAuth_Response( 'server_error', \__( 'The endpoint did not return a JSON response', 'indieauth' ), 500 );
}
return $body;
@@ -71,10 +73,10 @@ public function remote_get( $url ) {
*
* @param string $url URL to request.
* @param array $post_args POST body arguments.
- * @return array|WP_OAuth_Response Response array or error.
+ * @return array|OAuth_Response Response array or error.
*/
public function remote_post( $url, $post_args ) {
- $resp = wp_remote_post(
+ $resp = \wp_remote_post(
$url,
array(
'headers' => array(
@@ -92,17 +94,17 @@ public function remote_post( $url, $post_args ) {
return $error;
}
- $code = (int) wp_remote_retrieve_response_code( $resp );
- $body = wp_remote_retrieve_body( $resp );
+ $code = (int) \wp_remote_retrieve_response_code( $resp );
+ $body = \wp_remote_retrieve_body( $resp );
if ( ( $code / 100 ) !== 2 ) {
- return new WP_OAuth_Response( 'unable_retrieve', __( 'Unable to Retrieve', 'indieauth' ), $code, $body );
+ return new OAuth_Response( 'unable_retrieve', \__( 'Unable to Retrieve', 'indieauth' ), $code, $body );
}
$body = json_decode( $body, true );
if ( ! is_array( $body ) ) {
- return new WP_OAuth_Response( 'server_error', __( 'The endpoint did not return a JSON response', 'indieauth' ), 500 );
+ return new OAuth_Response( 'server_error', \__( 'The endpoint did not return a JSON response', 'indieauth' ), 500 );
}
return $body;
@@ -112,10 +114,10 @@ public function remote_post( $url, $post_args ) {
* Discover IndieAuth Metadata either from a Metadata Endpoint or Otherwise.
*
* @param string $url URL.
- * @return bool|WP_OAuth_Response True on success, false or error on failure.
+ * @return bool|OAuth_Response True on success, false or error on failure.
*/
public function discover_endpoints( $url ) {
- $endpoints = get_transient( 'indieauth_discovery_' . base64_urlencode( $url ) );
+ $endpoints = \get_transient( 'indieauth_discovery_' . base64_urlencode( $url ) );
if ( $endpoints ) {
$this->meta = $endpoints;
return true;
@@ -135,12 +137,12 @@ public function discover_endpoints( $url ) {
$this->meta = $resp;
// Store endpoint discovery results for this URL for 3 hours.
- set_transient( 'indieauth_discovery_' . base64_urlencode( $url ), $this->meta, 10800 );
+ \set_transient( 'indieauth_discovery_' . base64_urlencode( $url ), $this->meta, 10800 );
return true;
} elseif ( array_key_exists( 'authorization_endpoint', $endpoints ) && array_key_exists( 'token_endpoint', $endpoints ) ) {
$this->meta = $endpoints;
// Store endpoint discovery results for this URL for 3 hours.
- set_transient( 'indieauth_discovery_' . base64_urlencode( $url ), $this->meta, 10800 );
+ \set_transient( 'indieauth_discovery_' . base64_urlencode( $url ), $this->meta, 10800 );
return true;
}
return false;
@@ -156,11 +158,11 @@ public function discover_endpoints( $url ) {
* @type string $code_verifier The code verifier.
* }
* @param boolean $token Redeem For a Token or User Profile.
- * @return WP_OAuth_Response|array Return Error or Response Array.
+ * @return OAuth_Response|array Return Error or Response Array.
*/
public function redeem_authorization_code( $post_args, $token = true ) {
if ( empty( $this->meta ) ) {
- return new WP_OAuth_Response( 'server_error', __( 'Valid Endpoint Not Provided', 'indieauth' ), 500 );
+ return new OAuth_Response( 'server_error', \__( 'Valid Endpoint Not Provided', 'indieauth' ), 500 );
}
$endpoint = $token ? $this->meta['token_endpoint'] : $this->meta['authorization_endpoint'];
@@ -170,10 +172,10 @@ public function redeem_authorization_code( $post_args, $token = true ) {
'grant_type' => 'authorization_code',
);
- $post_args = wp_parse_args( $post_args, $defaults );
+ $post_args = \wp_parse_args( $post_args, $defaults );
if ( ! empty( array_diff( array( 'redirect_uri', 'code', 'code_verifier', 'client_id', 'grant_type' ), array_keys( $post_args ) ) ) ) {
- return new WP_OAuth_Response( 'missing_arguments', __( 'Arguments are missing from redemption flow', 'indieauth' ), 500 );
+ return new OAuth_Response( 'missing_arguments', \__( 'Arguments are missing from redemption flow', 'indieauth' ), 500 );
}
$response = $this->remote_post( $endpoint, $post_args );
@@ -187,13 +189,13 @@ public function redeem_authorization_code( $post_args, $token = true ) {
// If this redemption is at the token endpoint.
if ( $token ) {
if ( ! array_key_exists( 'access_token', $response ) ) {
- return new WP_OAuth_Response( 'unknown_error', __( 'Token Endpoint did Not Return a Token', 'indieauth' ), 500 );
+ return new OAuth_Response( 'unknown_error', \__( 'Token Endpoint did Not Return a Token', 'indieauth' ), 500 );
}
}
return $response;
}
- $error = new WP_OAuth_Response( 'server_error', __( 'There was an error verifying the authorization code, the authorization server returned an expected response', 'indieauth' ), 500 );
+ $error = new OAuth_Response( 'server_error', \__( 'There was an error verifying the authorization code, the authorization server returned an expected response', 'indieauth' ), 500 );
$error->set_debug( array( 'debug' => $response ) );
return $error;
}
diff --git a/includes/class-indieauth-debug.php b/includes/class-debug.php
similarity index 65%
rename from includes/class-indieauth-debug.php
rename to includes/class-debug.php
index f5d34d4..b2a8b8c 100644
--- a/includes/class-indieauth-debug.php
+++ b/includes/class-debug.php
@@ -5,18 +5,20 @@
* @package IndieAuth
*/
+namespace IndieAuth;
+
/**
* Class for debugging IndieAuth requests and responses.
*/
-class IndieAuth_Debug {
+class Debug {
/**
* Constructor. Registers hooks for debugging.
*/
public function __construct() {
- add_filter( 'http_request_args', array( $this, 'indieauth_allow_localhost' ), 10, 2 );
- add_filter( 'rest_post_dispatch', array( $this, 'log_rest_api_errors' ), 10, 3 );
- add_action( 'rest_api_init', array( $this, 'register_routes' ) );
+ \add_filter( 'http_request_args', array( $this, 'indieauth_allow_localhost' ), 10, 2 );
+ \add_filter( 'rest_post_dispatch', array( $this, 'log_rest_api_errors' ), 10, 3 );
+ \add_action( 'rest_api_init', array( $this, 'register_routes' ) );
}
/**
@@ -35,10 +37,10 @@ public function indieauth_allow_localhost( $r, $url ) { // phpcs:ignore Generic.
/**
* Log REST API errors.
*
- * @param WP_REST_Response $result Result that will be sent to the client.
- * @param WP_REST_Server $server The API server instance.
- * @param WP_REST_Request $request The request used to generate the response.
- * @return WP_REST_Response The result.
+ * @param \WP_REST_Response $result Result that will be sent to the client.
+ * @param \WP_REST_Server $server The API server instance.
+ * @param \WP_REST_Request $request The request used to generate the response.
+ * @return \WP_REST_Response The result.
*/
public function log_rest_api_errors( $result, $server, $request ) {
$request_route = $request->get_route();
@@ -65,23 +67,23 @@ public function log_rest_api_errors( $result, $server, $request ) {
$data['access_token'] = 'XXXX';
}
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
- error_log(
+ \error_log(
sprintf(
'REST request: %s: %s(Header %s)',
$request->get_route(),
- wp_json_encode( $params ),
+ \wp_json_encode( $params ),
$token
)
);
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
- error_log(
+ \error_log(
sprintf(
'REST result: %s: %s(%s) - %s(User ID: %s)',
$result->get_matched_route(),
- wp_json_encode( $data ),
+ \wp_json_encode( $data ),
$result->get_status(),
- wp_json_encode( $result->get_headers() ),
- get_current_user_id()
+ \wp_json_encode( $result->get_headers() ),
+ \get_current_user_id()
)
);
}
@@ -92,12 +94,12 @@ public function log_rest_api_errors( $result, $server, $request ) {
* Register test route for authorization.
*/
public function register_routes() {
- register_rest_route(
+ \register_rest_route(
'indieauth/1.0',
'/test',
array(
array(
- 'methods' => WP_REST_Server::READABLE,
+ 'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'test' ),
'permission_callback' => array( $this, 'permissions_test' ),
),
@@ -108,27 +110,27 @@ public function register_routes() {
/**
* Permission callback for the test route.
*
- * @param WP_REST_Request $request The request object.
- * @return true|WP_Error True if authorized, WP_Error otherwise.
+ * @param \WP_REST_Request $request The request object.
+ * @return true|\WP_Error True if authorized, WP_Error otherwise.
*/
public function permissions_test( $request ) {
$access_token = $request->get_param( 'access_token' );
$header = $request->get_header( 'authorization' );
if ( ! $access_token && ! $header ) {
- return new WP_Error( 'forbidden', __( 'Could Not Find Token', 'indieauth' ), array( 'status' => 403 ) );
+ return new \WP_Error( 'forbidden', \__( 'Could Not Find Token', 'indieauth' ), array( 'status' => 403 ) );
}
- if ( 0 === get_current_user_id() ) {
+ if ( 0 === \get_current_user_id() ) {
if ( empty( $this->response ) ) {
- return new WP_Error(
+ return new \WP_Error(
'forbidden',
- __( 'No User is Currently Set', 'indieauth' ),
+ \__( 'No User is Currently Set', 'indieauth' ),
array(
'status' => 403,
'request' => $request,
)
);
} else {
- return new WP_Error( 'forbidden', __( 'A Successful Auth Response was Given yet No User is Currently Set', 'indieauth' ), array( 'status' => 403 ) );
+ return new \WP_Error( 'forbidden', \__( 'A Successful Auth Response was Given yet No User is Currently Set', 'indieauth' ), array( 'status' => 403 ) );
}
}
return true;
@@ -137,12 +139,12 @@ public function permissions_test( $request ) {
/**
* Callback for the test route.
*
- * @param WP_REST_Request $request The request object.
- * @return array|WP_Error The IndieAuth response or error.
+ * @param \WP_REST_Request $request The request object.
+ * @return array|\WP_Error The IndieAuth response or error.
*/
public function test( $request ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
- if ( 0 === get_current_user_id() ) {
- return new WP_Error( 'forbidden', __( 'You have passed a permissions test but somehow the system is still not showing you as logged in', 'indieauth' ) );
+ if ( 0 === \get_current_user_id() ) {
+ return new \WP_Error( 'forbidden', \__( 'You have passed a permissions test but somehow the system is still not showing you as logged in', 'indieauth' ) );
}
return indieauth_get_response();
}
diff --git a/includes/class-indieauth-admin.php b/includes/class-indieauth-admin.php
deleted file mode 100644
index db3c069..0000000
--- a/includes/class-indieauth-admin.php
+++ /dev/null
@@ -1,372 +0,0 @@
- __( 'IndieAuth Test', 'indieauth' ),
- 'test' => array( $this, 'site_health_header_test' ),
- );
- $tests['direct']['indieauth_https'] = array(
- 'label' => __( 'SSL Test', 'indieauth' ),
- 'test' => array( $this, 'site_health_https_test' ),
- );
- return $tests;
- }
-
-
- /**
- * Site health test for HTTPS.
- *
- * @return array Test result.
- */
- public function site_health_https_test() {
- $result = array(
- 'label' => __( 'HTTPS Check Passed', 'indieauth' ),
- 'status' => 'good',
- 'badge' => array(
- 'label' => __( 'IndieAuth', 'indieauth' ),
- 'color' => 'green',
- ),
- 'description' => sprintf(
- '
%s
',
- __( 'You are using HTTPS and IndieAuth will be secure', 'indieauth' )
- ),
- 'actions' => '',
- 'test' => 'indieauth_https',
- );
-
- if ( ! is_ssl() ) {
- $result['status'] = 'critical';
- $result['label'] = __( 'HTTPS Test Failed', 'indieauth' );
- $result['description'] = sprintf(
- '%s
',
- __( 'You are not serving your site via HTTPS. This is a security risk if running IndieAuth.', 'indieauth' )
- );
- $result['actions'] = __( 'We recommend you acquire an SSL Certificate. You can do this for free through Lets Encrypt', 'indieauth' );
- }
-
- return $result;
- }
-
- /**
- * Site health test for authorization headers.
- *
- * @return array Test result.
- */
- public function site_health_header_test() {
- $result = array(
- 'label' => __( 'Authorization Header Passed', 'indieauth' ),
- 'status' => 'good',
- 'badge' => array(
- 'label' => __( 'IndieAuth', 'indieauth' ),
- 'color' => 'green',
- ),
- 'description' => sprintf(
- '%s
',
- __( 'Your hosting provider allows authorization headers to pass so IndieAuth should work', 'indieauth' )
- ),
- 'actions' => '',
- 'test' => 'indieauth_headers',
- );
-
- if ( ! self::test_auth() ) {
- $result['status'] = 'critical';
- $result['label'] = __( 'Authorization Test Failed', 'indieauth' );
- ob_start();
- include plugin_dir_path( __DIR__ ) . 'templates/authdiagfail.php';
- $result['description'] = ob_get_contents();
- ob_end_clean();
- $result['actions'] = sprintf( '%2$s ', 'https://github.com/indieweb/wordpress-indieauth/issues', __( 'If contacting your hosting provider does not work you can open an issue on GitHub and we will try to assist', 'indieauth' ) );
- }
-
- return $result;
- }
-
- /**
- * Handle the auth diagnostic login form.
- */
- public function login_form_authdiag() {
- $return = '';
- if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] ) {
- if ( ! empty( $_SERVER['HTTP_AUTHORIZATION'] ) && 'Bearer SjdWwSPRi9rdNzyKVDiZRkXhm0fxP0lAmksJXNOgwc7SYREqJnDpXky1MCbIW6UNAFqCwXHswKGaps2lSZfwpYEZnIdREikjiKKSE6UJNlJ3NLXyvyFSQdzUiRg531uG' === $_SERVER['HTTP_AUTHORIZATION'] ) {
- $return = '' . esc_html__( 'Authorization Header Found. You should be able to use all clients.', 'indieauth' ) . '
';
- } elseif ( ! empty( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) && 'Bearer SjdWwSPRi9rdNzyKVDiZRkXhm0fxP0lAmksJXNOgwc7SYREqJnDpXky1MCbIW6UNAFqCwXHswKGaps2lSZfwpYEZnIdREikjiKKSE6UJNlJ3NLXyvyFSQdzUiRg531uG' === $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) {
- $return = '' . esc_html__( 'Alternate Header Found. You should be able to use all clients.', 'indieauth' ) . '
';
- }
- if ( empty( $return ) ) {
- ob_start();
- include plugin_dir_path( __DIR__ ) . 'templates/authdiagfail.php';
- $return = ob_get_contents();
- ob_end_clean();
- }
- if ( isset( $_SERVER['HTTP_ACCEPT'] ) && 'application/json' === $_SERVER['HTTP_ACCEPT'] ) {
- header( 'Content-Type: application/json' );
- echo wp_json_encode( array( 'message' => esc_html( $return ) ) );
- exit;
- }
- echo wp_kses(
- $return,
- array(
- 'div' => array(
- 'class' => array(),
- ),
- 'p' => array(),
- )
- );
- exit;
- }
- $args = array(
- 'action' => 'authdiag',
- );
- $url = add_query_params_to_url( $args, wp_login_url() ); // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Used in included template.
- include plugin_dir_path( __DIR__ ) . 'templates/authdiagtest.php';
- exit;
- }
-
- /**
- * Register plugin settings.
- */
- public function settings() {
- register_setting(
- 'indieauth',
- 'indieauth_config',
- array(
- 'type' => 'string',
- 'description' => __( 'Configuration option for IndieAuth Plugin', 'indieauth' ),
- 'show_in_rest' => true,
- 'default' => 'local',
- )
- );
- register_setting(
- 'indieauth',
- 'indieauth_root_user',
- array(
- 'type' => 'int',
- 'description' => __( 'User Who is Represented by the Site URL', 'indieauth' ),
- 'show_in_rest' => true,
- )
- );
- register_setting(
- 'indieauth',
- 'indieauth_expires_in',
- array(
- 'type' => 'number',
- 'description' => __( 'IndieAuth Default Expiry Time', 'indieauth' ),
- 'show_in_rest' => true,
- 'default' => 1209600, // Two Weeks.
- )
- );
- }
-
-
- /**
- * Initialize admin settings fields.
- */
- public function admin_init() {
- add_settings_field( 'indieauth_general_settings', __( 'IndieAuth Settings', 'indieauth' ), array( $this, 'general_settings' ), 'general', 'default' );
-
- add_settings_section(
- 'indieauth',
- 'IndieAuth Endpoint Settings',
- array( $this, 'endpoint_settings' ),
- 'indieauth'
- );
- add_settings_field(
- 'indieauth_expires_in',
- __( 'Default Token Expiration Time', 'indieauth' ),
- array( $this, 'numeric_field' ),
- 'indieauth',
- 'indieauth',
- array(
- 'label_for' => 'indieauth_expires_in',
- 'class' => 'widefat',
- 'description' => __( 'Set the Number of Seconds until a Token expires (Default is Two Weeks). 0 to Disable Expiration.', 'indieauth' ),
- 'default' => '',
- 'min' => 0,
- )
- );
- }
-
- /**
- * Render endpoint settings section description.
- */
- public static function endpoint_settings() {
- esc_html_e( 'These settings control the behavior of the endpoints', 'indieauth' );
- }
-
-
- /**
- * Render a numeric settings field.
- *
- * @param array $args Field arguments.
- */
- public static function numeric_field( $args ) {
- $props = array();
- if ( array_key_exists( 'min', $args ) && is_numeric( $args['min'] ) ) {
- $props[] = 'min=' . $args['min'];
- }
- if ( array_key_exists( 'max', $args ) && is_numeric( $args['max'] ) ) {
- $props[] = 'max=' . $args['max'];
- }
- if ( array_key_exists( 'step', $args ) && is_numeric( $args['step'] ) ) {
- $props[] = 'step=' . $args['step'];
- }
- $props = implode( ' ', $props );
- printf( ' ', esc_attr( $args['label_for'] ), esc_attr( get_option( $args['label_for'], $args['default'] ) ), esc_html( $props ) );
- if ( array_key_exists( 'description', $args ) && ! empty( $args['description'] ) ) {
- printf( '%1$s
', esc_html( $args['description'] ) );
- }
- }
-
- /**
- * Add IndieAuth options to the WordPress general settings page.
- */
- public function general_settings() {
- if ( class_exists( 'IndieWeb_Plugin' ) ) {
- $path = 'admin.php?page=indieauth';
- } else {
- $path = 'options-general.php?page=indieauth';
- }
- printf( __( 'Based on your feedback and to improve the user experience, we decided to move the settings to a separate settings-page .', 'indieauth' ), $path ); // phpcs:ignore
- }
-
- /**
- * Add admin menu entry
- */
- public function admin_menu() {
- $title = __( 'IndieAuth', 'indieauth' );
- // If the IndieWeb Plugin is installed use its menu.
- if ( class_exists( 'IndieWeb_Plugin' ) ) {
- $options_page = add_submenu_page(
- 'indieweb',
- $title,
- $title,
- 'manage_options',
- 'indieauth',
- array( $this, 'settings_page' )
- );
- } else {
- $options_page = add_options_page(
- $title,
- $title,
- 'manage_options',
- 'indieauth',
- array( $this, 'settings_page' )
- );
- }
- add_action( 'load-' . $options_page, array( $this, 'add_help_tab' ) );
- }
-
- /**
- * Test if authorization headers pass through.
- *
- * @return string|false The diagnostic message or false on error.
- */
- public function test_auth() {
- $response = wp_remote_post(
- add_query_params_to_url(
- array(
- 'action' => 'authdiag',
- ),
- wp_login_url()
- ),
- array(
- 'method' => 'POST',
- 'headers' => array(
- 'Authorization' => 'Bearer SjdWwSPRi9rdNzyKVDiZRkXhm0fxP0lAmksJXNOgwc7SYREqJnDpXky1MCbIW6UNAFqCwXHswKGaps2lSZfwpYEZnIdREikjiKKSE6UJNlJ3NLXyvyFSQdzUiRg531uG',
- 'Accept' => 'application/json',
- ),
- )
- );
- if ( ! is_wp_error( $response ) ) {
- $json = json_decode( wp_remote_retrieve_body( $response ) );
- return wp_specialchars_decode( $json->message );
- } else {
- return false;
- }
- }
-
- /**
- * Load settings page
- */
- public function settings_page() {
- $response = self::test_auth();
- if ( ! $response ) {
- ob_start();
- include plugin_dir_path( __DIR__ ) . 'templates/authdiagfail.php';
- $response = ob_get_contents();
- ob_end_clean();
- }
- set_query_var( 'authdiag_message', $response );
- load_template( plugin_dir_path( __DIR__ ) . '/templates/indieauth-settings.php' );
- }
-
- /**
- * Add help tabs to the settings page.
- */
- public function add_help_tab() {
- get_current_screen()->add_help_tab(
- array(
- 'id' => 'overview',
- 'title' => __( 'Overview', 'indieauth' ),
- 'content' =>
- '' . __( 'IndieAuth is a way for doing Web sign-in, where you use your own homepage to sign in to other places.', 'indieauth' ) . '
' .
- '' . __( 'IndieAuth was built on ideas and technology from existing proven technologies like OAuth and OpenID but aims at making it easier for users as well as developers. It also decentralises much of the process so completely separate implementations and services can be used for each part.', 'indieauth' ) . '
',
- )
- );
-
- get_current_screen()->add_help_tab(
- array(
- 'id' => 'indieweb',
- 'title' => __( 'The IndieWeb', 'indieauth' ),
- 'content' =>
- '' . __( 'The IndieWeb is a people-focused alternative to the "corporate web".', 'indieauth' ) . '
' .
- '
- ' . __( 'Your content is yours', 'indieauth' ) . ' ' .
- __( 'When you post something on the web, it should belong to you, not a corporation. Too many companies have gone out of business and lost all of their users’ data. By joining the IndieWeb, your content stays yours and in your control.', 'indieauth' ) .
- '
' .
- '
- ' . __( 'You are better connected', 'indieauth' ) . ' ' .
- __( 'Your articles and status messages can go to all services, not just one, allowing you to engage with everyone. Even replies and likes on other services can come back to your site so they’re all in one place.', 'indieauth' ) .
- '
' .
- '
- ' . __( 'You are in control', 'indieauth' ) . ' ' .
- __( 'You can post anything you want, in any format you want, with no one monitoring you. In addition, you share simple readable links such as example.com/ideas. These links are permanent and will always work.', 'indieauth' ) .
- '
',
- )
- );
-
- get_current_screen()->set_help_sidebar(
- '' . __( 'For more information:', 'indieauth' ) . '
' .
- '' . __( 'IndieWeb Wiki page ', 'indieauth' ) . '
' .
- '' . __( 'Test suite ', 'indieauth' ) . '
' .
- '' . __( 'W3C Spec ', 'indieauth' ) . '
'
- );
- }
-}
diff --git a/includes/class-indieauth-metadata-endpoint.php b/includes/class-indieauth-metadata-endpoint.php
deleted file mode 100644
index 5a8f1dd..0000000
--- a/includes/class-indieauth-metadata-endpoint.php
+++ /dev/null
@@ -1,172 +0,0 @@
-; rel="%s"', $url, $rel ), $replace );
- }
-
- /**
- * Returns a marked up HTML link header.
- *
- * @param string $url URL for the link.
- * @param string $rel Rel property for the link.
- * @return string Marked up HTML link to add to head.
- */
- public static function get_html_header( $url, $rel ) {
- return sprintf( ' ' . PHP_EOL, $rel, $url );
- }
-
- /**
- * Hooks into the REST API output to add a metadata header to the Issuer URL.
- *
- * @param bool $served Whether the request has already been served.
- * @param WP_HTTP_ResponseInterface $result Result to send to the client. Usually a WP_REST_Response.
- * @param WP_REST_Request $request Request used to generate the response.
- * @param WP_REST_Server $server Server instance.
- * @return bool Whether the request has been served.
- */
- public static function serve_request( $served, $result, $request, $server ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
- if ( false === strpos( $request->get_route(), '/indieauth/1.0' ) ) {
- return $served;
- }
- static::set_http_header( static::get_endpoint(), 'indieauth-metadata' );
-
- return $served;
- }
-
- /**
- * Add authentication information into the REST API Index.
- *
- * @param WP_REST_Response $response REST API Response Object.
- * @return WP_REST_Response Response object with endpoint info added.
- */
- public function register_index( WP_REST_Response $response ) {
- $data = $response->get_data();
- $endpoints = array(
- 'metadata' => $this->get_endpoint(),
- );
- $endpoints = array_filter( $endpoints );
- if ( empty( $endpoints ) ) {
- return $response;
- }
- $data['authentication']['indieauth'] = array(
- 'endpoints' => apply_filters( 'rest_index_indieauth_endpoints', $endpoints ),
- );
- $response->set_data( $data );
- return $response;
- }
-
- /**
- * Output HTTP link header on author and front pages.
- */
- public function http_header() {
- if ( is_author() || is_front_page() ) {
- $this->set_http_header( static::get_endpoint(), 'indieauth-metadata' );
- }
- }
-
- /**
- * Output HTML link header on author and front pages.
- */
- public function html_header() {
- $kses = array(
- 'link' => array(
- 'href' => array(),
- 'rel' => array(),
- ),
- );
-
- if ( is_author() || is_front_page() ) {
- echo wp_kses( $this->get_html_header( static::get_endpoint(), 'indieauth-metadata' ), $kses );
- }
- }
-
- /**
- * Register the Route.
- */
- public function register_routes() {
- register_rest_route(
- 'indieauth/1.0',
- '/metadata',
- array(
- array(
- 'methods' => WP_REST_Server::READABLE,
- 'callback' => array( $this, 'metadata' ),
- 'args' => array(),
- 'permission_callback' => '__return_true',
- ),
- )
- );
- }
-
- /**
- * Metadata Endpoint GET request handler.
- *
- * @param WP_REST_Request $request The Request Object.
- * @return WP_REST_Response Response to Return to the REST Server.
- */
- public function metadata( $request ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
- $metadata = array(
- 'issuer' => indieauth_get_issuer(),
- 'scopes_supported' => IndieAuth_Plugin::$scopes->get_names(),
- 'service_documentation' => 'https://indieauth.spec.indieweb.org',
- 'code_challenge_methods_supported' => array( 'S256' ),
- );
-
- $metadata = apply_filters( 'indieauth_metadata', $metadata );
- return new WP_REST_Response(
- $metadata,
- 200,
- array(
- 'Content-Type' => 'application/json',
- )
- );
- }
-}
diff --git a/includes/class-indieauth-token-ui.php b/includes/class-indieauth-token-ui.php
deleted file mode 100644
index 1e4584e..0000000
--- a/includes/class-indieauth-token-ui.php
+++ /dev/null
@@ -1,216 +0,0 @@
-export(), JSON_PRETTY_PRINT );
- exit;
- }
-
- /**
- * Handle new token creation action.
- */
- public function new_token() {
- if ( ! isset( $_POST['indieauth_nonce'] )
- || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['indieauth_nonce'] ) ), 'indieauth_newtoken' )
- ) {
- esc_html_e( 'Invalid Nonce', 'indieauth' );
- exit;
- }
- $GLOBALS['title'] = esc_html__( 'Add IndieAuth Token', 'indieauth' ); // phpcs:ignore
- if ( empty( $_REQUEST['client_name'] ) ) {
- esc_html_e( 'A Name Must be Set for Your Token', 'indieauth' );
- exit;
- }
- require ABSPATH . 'wp-admin/admin-header.php';
- $client_name = sanitize_text_field( wp_unslash( $_REQUEST['client_name'] ) );
- $scopes = isset( $_REQUEST['scopes'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_REQUEST['scopes'] ) ) : array();
- $scopes = trim( implode( ' ', $scopes ) );
- if ( empty( $scopes ) ) {
- $scopes = 'create update';
- }
- $scopes = sanitize_text_field( $scopes );
- $expires = isset( $_REQUEST['expires_in'] ) ? absint( $_REQUEST['expires_in'] ) : 0;
- $token = self::generate_local_token( $client_name, $scopes, $expires );
- ?>
-
-
-
- set_user( $user_id );
- $token = array(
- 'token_type' => 'Bearer',
- 'scope' => $scopes,
- 'me' => get_the_author_meta( 'user_url', $user_id ) ? get_the_author_meta( 'user_url', $user_id ) : get_author_posts_url( $user_id ),
- 'issued_by' => rest_url( 'indieauth/1.0/token' ),
- 'user' => $user_id,
- 'client_id' => admin_url(),
- 'client_name' => wp_strip_all_tags( $name ),
- 'client_icon' => get_avatar_url( $user_id ),
- 'issued_at' => time(),
- );
- if ( $expires_in > 0 ) {
- $token['expires_in'] = $expires_in;
- $token['expiration'] = time() + $expires_in;
- }
- return $tokens->set( $token );
- }
-
-
-
- /**
- * Generate Options Form.
- *
- * @access public
- */
- public function options_form() {
- // As a precaution every time the Token UI page is loaded it will check for any expired auth codes and purge them.
- $codes = new Token_User( '_indieauth_code_', get_current_user_id() );
- $codes->check_expires();
- // Check to see if the cleanup function is scheduled.
- IndieAuth_Plugin::schedule();
-
- $token_table = new Token_List_Table();
- echo '
' . esc_html__( 'Manage IndieAuth Tokens', 'indieauth' ) . ' ';
- echo '';
- ?>
-
-
-
-
- ';
- foreach ( $scopes as $scope => $description ) {
- printf( '%1$s - %2$s ', esc_attr( $scope ), esc_html( $description ) );
- }
- echo '';
- }
-
- /**
- * Is prefix in string.
- *
- * @param string $source The source string.
- * @param string $prefix The prefix you wish to check for in source.
- * @return boolean The result.
- */
- public static function str_prefix( $source, $prefix ) {
- return strncmp( $source, $prefix, strlen( $prefix ) ) === 0;
- }
-}
-
-new IndieAuth_Token_UI();
-
diff --git a/includes/class-indieauth.php b/includes/class-indieauth.php
new file mode 100644
index 0000000..f7a7d31
--- /dev/null
+++ b/includes/class-indieauth.php
@@ -0,0 +1,370 @@
+initialized ) {
+ return;
+ }
+
+ $this->register_hooks();
+ $this->register_rest_routes();
+ $this->register_admin_hooks();
+
+ $this->initialized = true;
+ }
+
+ /**
+ * Register hooks.
+ */
+ private function register_hooks() {
+ \add_action( 'init', array( $this, 'init_plugin' ), 2 );
+ }
+
+ /**
+ * Initialize plugin components on init hook.
+ *
+ * Runs at priority 2 to match original plugin behavior. Components that
+ * use translations or register filters must be created on init, not earlier.
+ */
+ public function init_plugin() {
+ static::$scopes = new Scopes();
+ static::$scopes->init();
+
+ new Authorize();
+ Client_Taxonomy::init();
+ new Web_Signin();
+
+ if ( \WP_DEBUG ) {
+ new Debug();
+ }
+ }
+
+ /**
+ * Register REST API routes and controller hooks.
+ */
+ private function register_rest_routes() {
+ // Instantiate controllers so hooks can reference them.
+ static::$metadata = new Metadata_Controller();
+ $this->authorization = new Authorization_Controller();
+ $this->token = new Token_Controller();
+ $this->revocation = new Revocation_Controller();
+ $this->introspection = new Introspection_Controller();
+ $this->userinfo = new Userinfo_Controller();
+ $this->fedcm = new FedCM_Controller();
+
+ // Metadata Controller hooks.
+ \add_filter( 'rest_pre_serve_request', array( static::$metadata, 'serve_request' ), 11, 4 );
+ \add_filter( 'rest_index', array( static::$metadata, 'register_index' ) );
+ \add_action( 'rest_api_init', array( static::$metadata, 'register_routes' ) );
+
+ // Authorization Controller hooks.
+ \add_action( 'rest_api_init', array( $this->authorization, 'register_routes' ) );
+ \add_action( 'login_form_indieauth', array( $this->authorization, 'login_form_indieauth' ) );
+ \add_filter( 'indieauth_metadata', array( $this->authorization, 'metadata' ) );
+ \add_filter( 'rest_index_indieauth_endpoints', array( $this->authorization, 'rest_index' ) );
+
+ // Token Controller hooks.
+ \add_action( 'rest_api_init', array( $this->token, 'register_routes' ) );
+ \add_filter( 'indieauth_metadata', array( $this->token, 'metadata' ) );
+ \add_filter( 'rest_index_indieauth_endpoints', array( $this->token, 'rest_index' ) );
+
+ // Revocation Controller hooks.
+ \add_action( 'rest_api_init', array( $this->revocation, 'register_routes' ) );
+ \add_filter( 'indieauth_metadata', array( $this->revocation, 'metadata' ) );
+ \add_filter( 'rest_index_indieauth_endpoints', array( $this->revocation, 'rest_index' ) );
+
+ // Introspection Controller hooks.
+ \add_action( 'rest_api_init', array( $this->introspection, 'register_routes' ) );
+ \add_filter( 'indieauth_metadata', array( $this->introspection, 'metadata' ) );
+ \add_filter( 'rest_index_indieauth_endpoints', array( $this->introspection, 'rest_index' ) );
+
+ // Userinfo Controller hooks.
+ \add_action( 'rest_api_init', array( $this->userinfo, 'register_routes' ) );
+ \add_filter( 'indieauth_metadata', array( $this->userinfo, 'metadata' ) );
+ \add_filter( 'rest_index_indieauth_endpoints', array( $this->userinfo, 'rest_index' ) );
+
+ // FedCM Controller hooks.
+ \add_action( 'rest_api_init', array( $this->fedcm, 'register_routes' ) );
+ \add_filter( 'indieauth_metadata', array( $this->fedcm, 'metadata' ) );
+ \add_filter( 'rest_index_indieauth_endpoints', array( $this->fedcm, 'rest_index' ) );
+ \add_action( 'set_logged_in_cookie', array( $this->fedcm, 'set_login_status_logged_in' ) );
+ \add_action( 'clear_auth_cookie', array( $this->fedcm, 'set_login_status_logged_out' ) );
+ \add_action( 'admin_enqueue_scripts', array( $this->fedcm, 'enqueue_scripts' ) );
+
+ // Centralized HTTP and HTML header output.
+ \add_action( 'wp_head', array( $this, 'html_headers' ) );
+ \add_action( 'template_redirect', array( $this, 'http_headers' ) );
+
+ // WebIdentity uses rewrite rules, not REST.
+ WebIdentity::init();
+
+ // Ticket Controller (conditional).
+ if ( INDIEAUTH_TICKET_ENDPOINT ) {
+ $this->ticket = new Ticket_Controller();
+ \add_action( 'rest_api_init', array( $this->ticket, 'register_routes' ) );
+ \add_filter( 'indieauth_metadata', array( $this->ticket, 'metadata' ) );
+ \add_action( 'indieauth_ticket_redeemed', array( $this->ticket, 'notify' ) );
+ }
+ }
+
+ /**
+ * Output HTTP Link headers on author and front pages.
+ */
+ public function http_headers() {
+ if ( ! \is_author() && ! \is_front_page() ) {
+ return;
+ }
+
+ $headers = array(
+ 'indieauth-metadata' => static::$metadata,
+ 'authorization_endpoint' => $this->authorization,
+ 'token_endpoint' => $this->token,
+ );
+
+ if ( INDIEAUTH_TICKET_ENDPOINT && $this->ticket ) {
+ $headers['ticket_endpoint'] = $this->ticket;
+ }
+
+ foreach ( $headers as $rel => $controller ) {
+ header( sprintf( 'Link: <%s>; rel="%s"', $controller->get_endpoint(), $rel ), false );
+ }
+ }
+
+ /**
+ * Output HTML link headers on author and front pages.
+ */
+ public function html_headers() {
+ if ( ! \is_author() && ! \is_front_page() ) {
+ return;
+ }
+
+ $headers = array(
+ 'indieauth-metadata' => static::$metadata,
+ 'authorization_endpoint' => $this->authorization,
+ 'token_endpoint' => $this->token,
+ );
+
+ if ( INDIEAUTH_TICKET_ENDPOINT && $this->ticket ) {
+ $headers['ticket_endpoint'] = $this->ticket;
+ }
+
+ $kses = array(
+ 'link' => array(
+ 'href' => array(),
+ 'rel' => array(),
+ ),
+ );
+
+ foreach ( $headers as $rel => $controller ) {
+ echo \wp_kses( sprintf( ' ' . PHP_EOL, $rel, $controller->get_endpoint() ), $kses );
+ }
+ }
+
+ /**
+ * Register admin hooks.
+ */
+ private function register_admin_hooks() {
+ new Admin();
+ new Token_UI();
+
+ if ( INDIEAUTH_TICKET_ENDPOINT ) {
+ new Ticket\External_Token_Page();
+ }
+ }
+
+ /**
+ * Plugin activation.
+ */
+ public static function activation() {
+ self::schedule();
+
+ // Flush rewrite rules for FedCM well-known endpoint.
+ WebIdentity::flush_rewrite_rules();
+ }
+
+ /**
+ * Plugin deactivation.
+ */
+ public static function deactivation() {
+ self::cancel_schedule();
+ }
+
+ /**
+ * Process to trigger on plugin update.
+ *
+ * @param \WP_Upgrader $upgrade_object Upgrader object.
+ * @param array $options Upgrade options.
+ */
+ public static function upgrader_process_complete( $upgrade_object, $options ) {
+ if ( ( 'update' === $options['action'] ) && ( 'plugin' === $options['type'] ) ) {
+ $current_plugin_path_name = \plugin_basename( INDIEAUTH_PLUGIN_FILE );
+ foreach ( $options['plugins'] as $each_plugin ) {
+ if ( $each_plugin === $current_plugin_path_name ) {
+ self::schedule();
+ }
+ }
+ }
+ }
+
+ /**
+ * Schedule cleanup event.
+ *
+ * @return bool|\WP_Error True on success, WP_Error on failure.
+ */
+ public static function schedule() {
+ if ( ! \wp_next_scheduled( 'indieauth_cleanup', array( false ) ) ) {
+ return \wp_schedule_event( time() + HOUR_IN_SECONDS, 'twicedaily', 'indieauth_cleanup', array( false ) );
+ }
+ return true;
+ }
+
+ /**
+ * Cancel scheduled cleanup event.
+ */
+ public static function cancel_schedule() {
+ $timestamp = \wp_next_scheduled( 'indieauth_cleanup', array( false ) );
+ if ( $timestamp ) {
+ \wp_unschedule_event( $timestamp, 'indieauth_cleanup', array( false ) );
+ }
+ }
+
+ /**
+ * Expires authorization codes in the event any are left in the system.
+ */
+ public static function expires() {
+ $t = new Token_User( '_indieauth_token_' );
+ $t->get_all();
+ $t = new Token_User( '_indieauth_code_' );
+ $t->get_all();
+ $t = new Token_User( '_indieauth_refresh_' );
+ $t->get_all();
+ if ( INDIEAUTH_TICKET_ENDPOINT ) {
+ $t = new External_User_Token();
+ $t->expire_all_tokens();
+ }
+ }
+}
diff --git a/includes/class-oauth-response.php b/includes/class-oauth-response.php
index ec168eb..2ffd659 100644
--- a/includes/class-oauth-response.php
+++ b/includes/class-oauth-response.php
@@ -5,6 +5,8 @@
* @package IndieAuth
*/
+namespace IndieAuth;
+
// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed
/**
@@ -12,7 +14,7 @@
*
* @since 1.0.0
*/
-class WP_OAuth_Response extends WP_REST_Response {
+class OAuth_Response extends \WP_REST_Response {
/**
* Constructor.
@@ -34,7 +36,7 @@ public function __construct( $error, $error_description, $code = 200, $debug = n
$this->set_debug( $debug );
}
if ( WP_DEBUG ) {
- error_log( $this->to_log() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
+ \error_log( $this->to_log() ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
}
}
@@ -51,7 +53,7 @@ public function set_debug( $debug_data ) {
/**
* Convert to WP_Error.
*
- * @return WP_Error The error object.
+ * @return \WP_Error The error object.
*/
public function to_wp_error() {
$data = $this->get_data();
@@ -60,7 +62,7 @@ public function to_wp_error() {
unset( $data['error'] );
unset( $data['error_description'] );
$status = $this->get_status();
- return new WP_Error(
+ return new \WP_Error(
$error,
$error_description,
array(
@@ -78,62 +80,6 @@ public function to_wp_error() {
public function to_log() {
$data = $this->get_data();
$status = $this->get_status();
- return sprintf( 'IndieAuth Error: %1$s %2$s - %3$s %4$s', $status, $data['error'], $data['error_description'], wp_json_encode( $data ) );
- }
-}
-
-/**
- * Get OAuth error from response.
- *
- * @param mixed $obj Response object or array.
- * @return WP_OAuth_Response|false OAuth response or false.
- */
-function get_oauth_error( $obj ) {
- if ( is_array( $obj ) ) {
- // When checking the result of wp_remote_post.
- if ( isset( $obj['body'] ) ) {
- $body = json_decode( $obj['body'], true );
- if ( isset( $body['error'] ) ) {
- return new WP_OAuth_Response(
- $body['error'],
- isset( $body['error_description'] ) ? $body['error_description'] : null,
- $obj['response']['code']
- );
- }
- }
- } elseif ( is_object( $obj ) && 'WP_OAuth_Response' === get_class( $obj ) ) {
- $data = $obj->get_data();
- if ( isset( $data['error'] ) ) {
- return $obj;
- }
- }
- return false;
-}
-
-/**
- * Check if object is an OAuth error.
- *
- * @param mixed $obj Object to check.
- * @return bool True if OAuth error.
- */
-function is_oauth_error( $obj ) {
- return ( $obj instanceof WP_OAuth_Response );
-}
-
-/**
- * Convert WP_Error to OAuth response.
- *
- * @param WP_Error $error The WordPress error.
- * @return WP_OAuth_Response|null OAuth response or null.
- */
-function wp_error_to_oauth_response( $error ) {
- if ( is_wp_error( $error ) ) {
- $data = $error->get_error_data();
- $status = isset( $data['status'] ) ? $data['status'] : 200;
- if ( is_array( $data ) ) {
- unset( $data['status'] );
- }
- return new WP_OAuth_Response( $error->get_error_code(), $error->get_error_message(), $status, $data );
+ return sprintf( 'IndieAuth Error: %1$s %2$s - %3$s %4$s', $status, $data['error'], $data['error_description'], \wp_json_encode( $data ) );
}
- return null;
}
diff --git a/includes/class-indieauth-scopes.php b/includes/class-scopes.php
similarity index 71%
rename from includes/class-indieauth-scopes.php
rename to includes/class-scopes.php
index f77abbf..c43cb2e 100644
--- a/includes/class-indieauth-scopes.php
+++ b/includes/class-scopes.php
@@ -5,12 +5,16 @@
* @package IndieAuth
*/
+namespace IndieAuth;
+
+use IndieAuth\Scope\Scope;
+
/**
* Container class used to hold all of the registered scopes.
*
* @since 1.0.0
*/
-class IndieAuth_Scopes {
+class Scopes {
/**
* Stores all registered scopes.
@@ -24,8 +28,14 @@ class IndieAuth_Scopes {
*/
public function __construct() {
$this->scopes = array();
+ \add_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 20, 4 );
+ }
+
+ /**
+ * Initialize builtin scopes. Called on init to avoid early translation loading.
+ */
+ public function init() {
$this->register_builtin_scopes();
- add_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 20, 4 );
}
/**
@@ -34,7 +44,7 @@ public function __construct() {
* @return array List of capabilities to filter.
*/
public function map_caps() {
- return apply_filters( 'indieauth_meta_caps', array( 'publish_posts', 'delete_users', 'edit_users', 'remove_users', 'promote_users', 'delete_posts', 'delete_pages', 'edit_posts', 'edit_pages', 'read_posts', 'read_pages', 'unfiltered_html' ) );
+ return \apply_filters( 'indieauth_meta_caps', array( 'publish_posts', 'delete_users', 'edit_users', 'remove_users', 'promote_users', 'delete_posts', 'delete_pages', 'edit_posts', 'edit_pages', 'read_posts', 'read_pages', 'unfiltered_html' ) );
}
/**
@@ -59,7 +69,7 @@ public function map_meta_cap( $caps, $cap, $user_id, $args ) { // phpcs:ignore G
if ( ! in_array( $cap, $this->map_caps(), true ) ) {
if ( WP_DEBUG ) {
/* translators: %s: Capability name. */
- error_log( sprintf( __( 'Unknown cap: %s', 'indieauth' ), $cap ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
+ \error_log( sprintf( \__( 'Unknown cap: %s', 'indieauth' ), $cap ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
}
return $caps;
}
@@ -79,9 +89,9 @@ public function map_meta_cap( $caps, $cap, $user_id, $args ) { // phpcs:ignore G
*/
public function register_builtin_scopes() {
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'create',
- __( 'Allows the application to create posts', 'indieauth' ),
+ \__( 'Allows the application to create posts', 'indieauth' ),
array(
'edit_posts',
'edit_published_posts',
@@ -94,9 +104,9 @@ public function register_builtin_scopes() {
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'draft',
- __( 'Allows the application to create draft posts only.', 'indieauth' ),
+ \__( 'Allows the application to create draft posts only.', 'indieauth' ),
array(
'edit_posts',
'unfiltered_html',
@@ -106,9 +116,9 @@ public function register_builtin_scopes() {
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'update',
- __( 'Allows the application to update posts', 'indieauth' ),
+ \__( 'Allows the application to update posts', 'indieauth' ),
array(
'edit_published_posts',
'edit_others_posts',
@@ -119,9 +129,9 @@ public function register_builtin_scopes() {
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'delete',
- __( 'Allows the application to delete or undelete posts', 'indieauth' ),
+ \__( 'Allows the application to delete or undelete posts', 'indieauth' ),
array(
'delete_posts',
'delete_published_posts',
@@ -131,9 +141,9 @@ public function register_builtin_scopes() {
)
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'media',
- __( 'Allows the application to upload to the media endpoint', 'indieauth' ),
+ \__( 'Allows the application to upload to the media endpoint', 'indieauth' ),
array(
'upload_files',
'read',
@@ -142,9 +152,9 @@ public function register_builtin_scopes() {
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'read',
- __( 'Allows the application read access to Microsub channels', 'indieauth' ),
+ \__( 'Allows the application read access to Microsub channels', 'indieauth' ),
array(
'read',
)
@@ -152,9 +162,9 @@ public function register_builtin_scopes() {
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'follow',
- __( 'Allows the application to manage a Microsub following list', 'indieauth' ),
+ \__( 'Allows the application to manage a Microsub following list', 'indieauth' ),
array(
'read',
)
@@ -162,9 +172,9 @@ public function register_builtin_scopes() {
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'mute',
- __( 'Allows the application to mute and unmute users in a Microsub channel', 'indieauth' ),
+ \__( 'Allows the application to mute and unmute users in a Microsub channel', 'indieauth' ),
array(
'read',
)
@@ -172,27 +182,27 @@ public function register_builtin_scopes() {
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'block',
- __( 'Allows the application to block users in a Microsub channel', 'indieauth' ),
+ \__( 'Allows the application to block users in a Microsub channel', 'indieauth' ),
array(
'read',
)
)
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'channels',
- __( 'Allows the application to manage Microsub channels', 'indieauth' ),
+ \__( 'Allows the application to manage Microsub channels', 'indieauth' ),
array(
'read',
)
)
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'save',
- __( 'Allows the application to save content for later retrieval', 'indieauth' ),
+ \__( 'Allows the application to save content for later retrieval', 'indieauth' ),
array(
'read',
)
@@ -200,9 +210,9 @@ public function register_builtin_scopes() {
);
$this->register_scope(
- new IndieAuth_Scope(
+ new Scope(
'profile',
- __( 'Returns a complete profile to the application as part of the IndieAuth response. Without this only a display name, avatar, and url will be returned', 'indieauth' ),
+ \__( 'Returns a complete profile to the application as part of the IndieAuth response. Without this only a display name, avatar, and url will be returned', 'indieauth' ),
array(
'read',
)
@@ -213,11 +223,11 @@ public function register_builtin_scopes() {
/**
* Register a scope.
*
- * @param IndieAuth_Scope $scope Scope object.
+ * @param Scope $scope Scope object.
* @return bool Whether successful or not.
*/
public function register_scope( $scope ) {
- if ( ! $scope instanceof IndieAuth_Scope ) {
+ if ( ! $scope instanceof Scope ) {
return false;
}
$this->scopes[ $scope->name ] = $scope;
@@ -237,7 +247,7 @@ public function deregister_scope( $name ) {
* Retrieve a scope by name.
*
* @param string $name Scope name.
- * @return null|IndieAuth_Scope Scope object or null.
+ * @return null|Scope Scope object or null.
*/
public function get_scope( $name ) {
if ( array_key_exists( $name, $this->scopes ) ) {
diff --git a/includes/class-web-signin.php b/includes/class-web-signin.php
index 5a7a77f..da54eaf 100644
--- a/includes/class-web-signin.php
+++ b/includes/class-web-signin.php
@@ -5,6 +5,10 @@
* @package IndieAuth
*/
+namespace IndieAuth;
+
+use IndieAuth\Token\Transient as Token_Transient;
+
/**
* Web Sign In class.
*
@@ -18,24 +22,24 @@ class Web_Signin {
* Constructor.
*/
public function __construct() {
- add_action( 'init', array( $this, 'settings' ) );
+ \add_action( 'init', array( $this, 'settings' ) );
- add_action( 'login_form', array( $this, 'login_form' ) );
- add_action( 'login_form_websignin', array( $this, 'login_form_websignin' ) );
+ \add_action( 'login_form', array( $this, 'login_form' ) );
+ \add_action( 'login_form_websignin', array( $this, 'login_form_websignin' ) );
- add_action( 'authenticate', array( $this, 'authenticate' ), 20, 2 );
+ \add_action( 'authenticate', array( $this, 'authenticate' ), 20, 2 );
}
/**
* Register settings for web sign-in.
*/
public function settings() {
- register_setting(
+ \register_setting(
'indieauth',
'indieauth_show_login_form',
array(
'type' => 'boolean',
- 'description' => __( 'Offer IndieAuth on Login Form', 'indieauth' ),
+ 'description' => \__( 'Offer IndieAuth on Login Form', 'indieauth' ),
'show_in_rest' => true,
'default' => 0,
)
@@ -47,25 +51,25 @@ public function settings() {
*
* @param string $me URL parameter.
* @param string $redirect_uri Where to redirect.
- * @return WP_Error|void Error on failure, redirects on success.
+ * @return \WP_Error|void Error on failure, redirects on success.
*/
public function websignin_redirect( $me, $redirect_uri ) {
$me = indieauth_validate_user_identifier( $me );
if ( ! $me ) {
- return new WP_Error(
+ return new \WP_Error(
'authentication_failed',
- __( 'ERROR : Invalid URL', 'indieauth' ),
+ \__( 'ERROR : Invalid URL', 'indieauth' ),
array(
'status' => 401,
)
);
}
- $client = new IndieAuth_Client();
+ $client = new Client();
$endpoints = $client->discover_endpoints( $me );
if ( ! $endpoints ) {
- return new WP_Error(
+ return new \WP_Error(
'authentication_failed',
- __( 'ERROR : Could not discover endpoints', 'indieauth' ),
+ \__( 'ERROR : Could not discover endpoints', 'indieauth' ),
array(
'status' => 401,
)
@@ -74,10 +78,10 @@ public function websignin_redirect( $me, $redirect_uri ) {
$state = $client->meta;
$state['me'] = $me;
- $state['code_verifier'] = wp_generate_password( 128, false );
+ $state['code_verifier'] = \wp_generate_password( 128, false );
$token = new Token_Transient( 'indieauth_state' );
- $query = add_query_arg(
+ $query = \add_query_arg(
array(
'response_type' => 'code', // In earlier versions of the specification this was ID.
'client_id' => rawurlencode( $client->client_id ),
@@ -90,71 +94,71 @@ public function websignin_redirect( $me, $redirect_uri ) {
$state['authorization_endpoint']
);
// Redirect to authentication endpoint.
- wp_redirect( $query ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
+ \wp_redirect( $query ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
}
/**
* Authenticate user to WordPress using IndieAuth.
*
- * @param WP_User|WP_Error|null $user Authenticated user object, or WP_Error or null.
- * @param string $url URL parameter (unused but required by filter).
- * @return WP_User|WP_Error|null Authenticated user object, or WP_Error or null.
+ * @param \WP_User|\WP_Error|null $user Authenticated user object, or WP_Error or null.
+ * @param string $url URL parameter (unused but required by filter).
+ * @return \WP_User|\WP_Error|null Authenticated user object, or WP_Error or null.
*/
public function authenticate( $user, $url ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
- if ( $user instanceof WP_User ) {
+ if ( $user instanceof \WP_User ) {
return $user;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
- $redirect_to = array_key_exists( 'redirect_to', $_REQUEST ) ? sanitize_text_field( wp_unslash( $_REQUEST['redirect_to'] ) ) : '';
+ $redirect_to = array_key_exists( 'redirect_to', $_REQUEST ) ? \sanitize_text_field( \wp_unslash( $_REQUEST['redirect_to'] ) ) : '';
$redirect_to = rawurldecode( $redirect_to );
$token = new Token_Transient( 'indieauth_state' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( array_key_exists( 'code', $_REQUEST ) && array_key_exists( 'state', $_REQUEST ) ) {
- $state = $token->verify( sanitize_text_field( wp_unslash( $_REQUEST['state'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ $state = $token->verify( \sanitize_text_field( \wp_unslash( $_REQUEST['state'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! $state ) {
- return new WP_Error( 'indieauth_state_error', __( 'IndieAuth Server did not return the same state parameter', 'indieauth' ) );
+ return new \WP_Error( 'indieauth_state_error', \__( 'IndieAuth Server did not return the same state parameter', 'indieauth' ) );
}
if ( ! isset( $state['authorization_endpoint'] ) ) {
- return new WP_Error( 'indieauth_missing_endpoint', __( 'Cannot Find IndieAuth Endpoint Cookie', 'indieauth' ) );
+ return new \WP_Error( 'indieauth_missing_endpoint', \__( 'Cannot Find IndieAuth Endpoint Cookie', 'indieauth' ) );
}
- if ( is_wp_error( $state ) ) {
+ if ( \is_wp_error( $state ) ) {
return $state;
}
if ( array_key_exists( 'iss', $_REQUEST ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
- $iss = rawurldecode( sanitize_text_field( wp_unslash( $_REQUEST['iss'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ $iss = rawurldecode( \sanitize_text_field( \wp_unslash( $_REQUEST['iss'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! indieauth_validate_issuer_identifier( $iss ) ) {
- return new WP_Error( 'indieauth_iss_error', __( 'Issuer Parameter is Not Valid', 'indieauth' ) );
+ return new \WP_Error( 'indieauth_iss_error', \__( 'Issuer Parameter is Not Valid', 'indieauth' ) );
}
if ( $iss !== $state['issuer'] ) {
- return new WP_Error( 'indieauth_iss_error', __( 'Issuer Parameter does not Match Server Metadata', 'indieauth' ) );
+ return new \WP_Error( 'indieauth_iss_error', \__( 'Issuer Parameter does not Match Server Metadata', 'indieauth' ) );
}
} elseif ( array_key_exists( 'issuer', $state ) ) {
- return new WP_Error( 'indieauth_iss_error', __( 'Issuer Parameter Present in Metadata Endpoint But Not Returned by Authorization Endpoint', 'indieauth' ) );
+ return new \WP_Error( 'indieauth_iss_error', \__( 'Issuer Parameter Present in Metadata Endpoint But Not Returned by Authorization Endpoint', 'indieauth' ) );
}
- $client = new IndieAuth_Client();
+ $client = new Client();
$client->meta = $state;
$response = $client->redeem_authorization_code(
array(
- 'code' => sanitize_text_field( wp_unslash( $_REQUEST['code'] ) ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
- 'redirect_uri' => wp_login_url( $redirect_to ),
+ 'code' => \sanitize_text_field( \wp_unslash( $_REQUEST['code'] ) ), // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ 'redirect_uri' => \wp_login_url( $redirect_to ),
'code_verifier' => $state['code_verifier'],
),
false // Redeem at Authorization Endpoint.
);
- if ( is_wp_error( $response ) ) {
+ if ( \is_wp_error( $response ) ) {
return $response;
}
if ( is_oauth_error( $response ) ) {
return $response->to_wp_error();
}
- if ( trailingslashit( $state['me'] ) !== trailingslashit( $response['me'] ) ) {
- return new WP_Error( 'indieauth_registration_failure', __( 'The domain does not match the domain you used to start the authentication.', 'indieauth' ) );
+ if ( \trailingslashit( $state['me'] ) !== \trailingslashit( $response['me'] ) ) {
+ return new \WP_Error( 'indieauth_registration_failure', \__( 'The domain does not match the domain you used to start the authentication.', 'indieauth' ) );
}
$user = get_user_by_identifier( $response['me'] );
if ( ! $user ) {
- $user = new WP_Error( 'indieauth_registration_failure', __( 'Your have entered a valid Domain, but you have no account on this blog.', 'indieauth' ) );
+ $user = new \WP_Error( 'indieauth_registration_failure', \__( 'Your have entered a valid Domain, but you have no account on this blog.', 'indieauth' ) );
}
}
return $user;
@@ -165,9 +169,9 @@ public function authenticate( $user, $url ) { // phpcs:ignore Generic.CodeAnalys
* Render the login form.
*/
public function login_form() {
- $template = plugin_dir_path( __DIR__ ) . 'templates/websignin-link.php';
- if ( 1 === (int) get_option( 'indieauth_show_login_form' ) ) {
- load_template( $template );
+ $template = \plugin_dir_path( __DIR__ ) . 'templates/websignin-link.php';
+ if ( 1 === (int) \get_option( 'indieauth_show_login_form' ) ) {
+ \load_template( $template );
}
}
@@ -177,18 +181,16 @@ public function login_form() {
public function login_form_websignin() {
if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'POST' === $_SERVER['REQUEST_METHOD'] ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
- $redirect_to = array_key_exists( 'redirect_to', $_REQUEST ) ? sanitize_text_field( wp_unslash( $_REQUEST['redirect_to'] ) ) : '';
+ $redirect_to = array_key_exists( 'redirect_to', $_REQUEST ) ? \sanitize_text_field( \wp_unslash( $_REQUEST['redirect_to'] ) ) : '';
$redirect_to = rawurldecode( $redirect_to );
if ( array_key_exists( 'websignin_identifier', $_POST ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
- $me = esc_url_raw( wp_unslash( $_POST['websignin_identifier'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
- $this->websignin_redirect( $me, wp_login_url( $redirect_to ) );
+ $me = \esc_url_raw( \wp_unslash( $_POST['websignin_identifier'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ $this->websignin_redirect( $me, \wp_login_url( $redirect_to ) );
}
}
- include plugin_dir_path( __DIR__ ) . 'templates/websignin-form.php';
+ include \plugin_dir_path( __DIR__ ) . 'templates/websignin-form.php';
exit;
}
}
-
-new Web_Signin();
diff --git a/includes/class-indieauth-webidentity.php b/includes/class-webidentity.php
similarity index 65%
rename from includes/class-indieauth-webidentity.php
rename to includes/class-webidentity.php
index d9c9d5b..1cd570f 100644
--- a/includes/class-indieauth-webidentity.php
+++ b/includes/class-webidentity.php
@@ -5,27 +5,32 @@
* @package IndieAuth
*/
+namespace IndieAuth;
+
+use IndieAuth\Rest\FedCM_Controller;
+
/**
* Handles the /.well-known/web-identity endpoint for FedCM discovery.
*
* @see https://indieweb.org/FedCM_for_IndieAuth
*/
-class IndieAuth_WebIdentity {
+class WebIdentity {
/**
- * Constructor.
+ * Initialize hooks for the WebIdentity handler.
*/
- public function __construct() {
- add_action( 'init', array( $this, 'add_rewrite_rules' ) );
- add_action( 'template_redirect', array( $this, 'handle_request' ) );
- add_filter( 'query_vars', array( $this, 'add_query_vars' ) );
+ public static function init() {
+ $instance = new self();
+ \add_action( 'init', array( $instance, 'add_rewrite_rules' ) );
+ \add_action( 'template_redirect', array( $instance, 'handle_request' ) );
+ \add_filter( 'query_vars', array( $instance, 'add_query_vars' ) );
}
/**
* Add rewrite rules for well-known endpoint.
*/
public function add_rewrite_rules() {
- add_rewrite_rule(
+ \add_rewrite_rule(
'^\.well-known/web-identity$',
'index.php?well-known=web-identity',
'top'
@@ -47,14 +52,14 @@ public function add_query_vars( $vars ) {
* Handle the well-known request.
*/
public function handle_request() {
- $well_known = get_query_var( 'well-known' );
+ $well_known = \get_query_var( 'well-known' );
if ( 'web-identity' !== $well_known ) {
return;
}
$provider_urls = array(
- IndieAuth_FedCM_Endpoint::get_config_endpoint(),
+ FedCM_Controller::get_config_endpoint(),
);
/**
@@ -62,7 +67,7 @@ public function handle_request() {
*
* @param array $provider_urls The provider URLs.
*/
- $provider_urls = apply_filters( 'indieauth_fedcm_provider_urls', $provider_urls );
+ $provider_urls = \apply_filters( 'indieauth_fedcm_provider_urls', $provider_urls );
$response = array(
'provider_urls' => $provider_urls,
@@ -70,7 +75,7 @@ public function handle_request() {
header( 'Content-Type: application/json' );
header( 'Access-Control-Allow-Origin: *' );
- echo wp_json_encode( $response );
+ echo \wp_json_encode( $response );
exit;
}
@@ -80,6 +85,6 @@ public function handle_request() {
public static function flush_rewrite_rules() {
$instance = new self();
$instance->add_rewrite_rules();
- flush_rewrite_rules();
+ \flush_rewrite_rules();
}
}
diff --git a/includes/functions-api.php b/includes/functions-api.php
new file mode 100644
index 0000000..b79c82e
--- /dev/null
+++ b/includes/functions-api.php
@@ -0,0 +1,331 @@
+ 100,
'limit_response_size' => 1048576,
'redirection' => 3,
'user-agent' => "$user_agent; finding rel properties",
);
- $response = wp_safe_remote_get( $me, $args );
- if ( is_wp_error( $response ) ) {
+ $response = \wp_safe_remote_get( $me, $args );
+ if ( \is_wp_error( $response ) ) {
return $response;
}
$rels = array();
// Check link header.
- $links = wp_remote_retrieve_header( $response, 'link' );
+ $links = \wp_remote_retrieve_header( $response, 'link' );
if ( $links ) {
if ( is_string( $links ) ) {
$links = array( $links );
@@ -83,11 +85,11 @@ function find_rels( $me, $endpoints = null ) {
$rels = parse_link_rels( $links, $me );
}
- $code = (int) wp_remote_retrieve_response_code( $response );
+ $code = (int) \wp_remote_retrieve_response_code( $response );
switch ( $code ) {
case 301:
case 308:
- $rels['me'] = wp_remote_retrieve_header( $response, 'Location' );
+ $rels['me'] = \wp_remote_retrieve_header( $response, 'Location' );
break;
}
if ( isset( $rels['me'] ) ) {
@@ -95,13 +97,13 @@ function find_rels( $me, $endpoints = null ) {
}
// Not an (x)html, sgml, or xml page, no use going further.
- if ( ! preg_match( '#(image|audio|video|model)/#is', wp_remote_retrieve_header( $response, 'content-type' ) ) ) {
- $contents = wp_remote_retrieve_body( $response );
+ if ( ! preg_match( '#(image|audio|video|model)/#is', \wp_remote_retrieve_header( $response, 'content-type' ) ) ) {
+ $contents = \wp_remote_retrieve_body( $response );
$rels = array_merge( $rels, parse_html_rels( $contents, $me ) );
}
if ( is_array( $endpoints ) ) {
$endpoints[] = 'me';
- $rels = wp_array_slice_assoc( $rels, $endpoints );
+ $rels = \wp_array_slice_assoc( $rels, $endpoints );
if ( ! empty( $rels ) ) {
return $rels;
}
@@ -112,7 +114,7 @@ function find_rels( $me, $endpoints = null ) {
}
}
-if ( ! function_exists( 'parse_html_rels' ) ) {
+if ( ! function_exists( 'IndieAuth\parse_html_rels' ) ) {
/**
* Parse HTML for rel links.
*
@@ -124,19 +126,19 @@ function parse_html_rels( $contents, $url ) {
// Unicode to HTML entities.
$contents = mb_convert_encoding( $contents, 'HTML-ENTITIES', mb_detect_encoding( $contents ) );
libxml_use_internal_errors( true );
- $doc = new DOMDocument();
+ $doc = new \DOMDocument();
$doc->loadHTML( $contents );
- $xpath = new DOMXPath( $doc );
+ $xpath = new \DOMXPath( $doc );
$results = array();
// Check and elements.
foreach ( $xpath->query( '//a[@rel and @href] | //link[@rel and @href]' ) as $hyperlink ) {
- $results[ $hyperlink->getAttribute( 'rel' ) ] = WP_Http::make_absolute_url( $hyperlink->getAttribute( 'href' ), $url );
+ $results[ $hyperlink->getAttribute( 'rel' ) ] = \WP_Http::make_absolute_url( $hyperlink->getAttribute( 'href' ), $url );
}
return $results;
}
}
-if ( ! function_exists( 'get_single_author' ) ) {
+if ( ! function_exists( 'IndieAuth\get_single_author' ) ) {
/**
* Uses the code from is_multi_author to determine the identity of the single author.
*
@@ -144,22 +146,22 @@ function parse_html_rels( $contents, $url ) {
*/
function get_single_author() {
global $wpdb;
- $single_author = get_transient( 'single_author' );
+ $single_author = \get_transient( 'single_author' );
if ( false === $single_author ) {
$rows = (array) $wpdb->get_col( "SELECT DISTINCT post_author FROM $wpdb->posts WHERE post_type = 'post' AND post_status = 'publish' LIMIT 2" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$single_author = 1 === count( $rows ) ? (int) $rows[0] : false;
- set_transient( 'single_author', $single_author );
+ \set_transient( 'single_author', $single_author );
}
return $single_author;
}
}
-if ( ! function_exists( 'get_user_by_identifier' ) ) {
+if ( ! function_exists( 'IndieAuth\get_user_by_identifier' ) ) {
/**
* Get the user associated with the specified Identifier-URI.
*
* @param string $identifier Identifier to match.
- * @return WP_User|null Associated user, or null if no associated user.
+ * @return \WP_User|null Associated user, or null if no associated user.
*/
function get_user_by_identifier( $identifier ) {
// Refuse to validate empty or invalid user identifiers.
@@ -168,20 +170,20 @@ function get_user_by_identifier( $identifier ) {
}
$identifier = normalize_url( $identifier );
- if ( ( 'https' === wp_parse_url( home_url(), PHP_URL_SCHEME ) ) && ( wp_parse_url( home_url(), PHP_URL_HOST ) === wp_parse_url( $identifier, PHP_URL_HOST ) ) ) {
- $identifier = set_url_scheme( $identifier, 'https' );
+ if ( ( 'https' === \wp_parse_url( \home_url(), PHP_URL_SCHEME ) ) && ( \wp_parse_url( \home_url(), PHP_URL_HOST ) === \wp_parse_url( $identifier, PHP_URL_HOST ) ) ) {
+ $identifier = \set_url_scheme( $identifier, 'https' );
}
// Try to save the expense of a search query if the URL is the site URL.
- if ( home_url( '/' ) === $identifier ) {
+ if ( \home_url( '/' ) === $identifier ) {
// Use the settings to set the root user.
if ( 0 !== indieauth_get_root_user() ) {
- return get_user_by( 'id', (int) get_option( 'indieauth_root_user' ) );
+ return \get_user_by( 'id', (int) \get_option( 'indieauth_root_user' ) );
}
}
// Check if this is a author post URL.
$user = url_to_author( $identifier );
- if ( $user instanceof WP_User ) {
+ if ( $user instanceof \WP_User ) {
return $user;
}
@@ -190,7 +192,7 @@ function get_user_by_identifier( $identifier ) {
'search_columns' => array( 'user_url' ),
);
- $users = get_users( $args );
+ $users = \get_users( $args );
// Check result.
if ( is_countable( $users ) && 1 === count( $users ) ) {
return $users[0];
@@ -199,7 +201,7 @@ function get_user_by_identifier( $identifier ) {
}
}
-if ( ! function_exists( 'get_url_from_user' ) ) {
+if ( ! function_exists( 'IndieAuth\get_url_from_user' ) ) {
/**
* Tries to make some decisions about what URL to return for a user.
*
@@ -208,33 +210,33 @@ function get_user_by_identifier( $identifier ) {
*/
function get_url_from_user( $user_id ) {
if ( (int) indieauth_get_root_user() === $user_id ) {
- return home_url( '/' );
+ return \home_url( '/' );
}
if ( ! $user_id ) {
return null;
}
- return get_author_posts_url( $user_id );
+ return \get_author_posts_url( $user_id );
}
}
-if ( ! function_exists( 'url_to_author' ) ) {
+if ( ! function_exists( 'IndieAuth\url_to_author' ) ) {
/**
* Examine a url and try to determine the author ID it represents.
*
* @param string $url Permalink to check.
- * @return WP_User|null User or null on failure.
+ * @return \WP_User|null User or null on failure.
*/
function url_to_author( $url ) {
global $wp_rewrite;
// Check if url has the same host.
- if ( wp_parse_url( site_url(), PHP_URL_HOST ) !== wp_parse_url( $url, PHP_URL_HOST ) ) {
+ if ( \wp_parse_url( \site_url(), PHP_URL_HOST ) !== \wp_parse_url( $url, PHP_URL_HOST ) ) {
return null;
}
// First, check to see if there is a 'author=N' to match against.
if ( preg_match( '/[?&]author=(\d+)/i', $url, $values ) ) {
- $id = absint( $values[1] );
+ $id = \absint( $values[1] );
if ( $id ) {
- return get_user_by( 'id', $id );
+ return \get_user_by( 'id', $id );
}
}
// Check to see if we are using rewrite rules.
@@ -248,7 +250,7 @@ function url_to_author( $url ) {
$author_regexp = str_replace( '%author%', '', $author_rewrite );
// Match the rewrite rule with the passed url.
if ( preg_match( '/https?:\/\/(.+)' . preg_quote( $author_regexp, '/' ) . '([^\/]+)/i', $url, $match ) ) {
- $user = get_user_by( 'slug', $match[2] );
+ $user = \get_user_by( 'slug', $match[2] );
if ( $user ) {
return $user;
}
@@ -260,16 +262,16 @@ function url_to_author( $url ) {
/**
* Returns if valid URL for REST validation.
*
- * @param string $url URL to validate.
- * @param WP_REST_Request|null $request REST request object.
- * @param string|null $key Parameter key.
+ * @param string $url URL to validate.
+ * @param \WP_REST_Request|null $request REST request object.
+ * @param string|null $key Parameter key.
* @return bool Whether URL is valid.
*/
function rest_is_valid_url( $url, $request = null, $key = null ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
if ( ! is_string( $url ) || empty( $url ) ) {
return false;
}
- return filter_var( $url, FILTER_VALIDATE_URL );
+ return \filter_var( $url, FILTER_VALIDATE_URL );
}
/**
@@ -283,9 +285,9 @@ function indieauth_rest_url( $path = '' ) {
// This fallback checks and returns the non rewritten version.
global $wp_rewrite;
if ( ! $wp_rewrite ) {
- return home_url( 'index.php?rest_route=' . $path );
+ return \home_url( 'index.php?rest_route=' . $path );
}
- return rest_url( $path );
+ return \rest_url( $path );
}
// @see https://github.com/ralouphie/getallheaders.
@@ -319,12 +321,12 @@ function getallheaders() {
if ( ! isset( $headers['Authorization'] ) ) {
if ( isset( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ) {
- $headers['Authorization'] = wp_unslash( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+ $headers['Authorization'] = \wp_unslash( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
} elseif ( isset( $_SERVER['PHP_AUTH_USER'] ) ) {
- $basic_pass = isset( $_SERVER['PHP_AUTH_PW'] ) ? sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_PW'] ) ) : '';
- $headers['Authorization'] = 'Basic ' . base64_encode( sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_USER'] ) ) . ':' . $basic_pass ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
+ $basic_pass = isset( $_SERVER['PHP_AUTH_PW'] ) ? \sanitize_text_field( \wp_unslash( $_SERVER['PHP_AUTH_PW'] ) ) : '';
+ $headers['Authorization'] = 'Basic ' . base64_encode( \sanitize_text_field( \wp_unslash( $_SERVER['PHP_AUTH_USER'] ) ) . ':' . $basic_pass ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
} elseif ( isset( $_SERVER['PHP_AUTH_DIGEST'] ) ) {
- $headers['Authorization'] = sanitize_text_field( wp_unslash( $_SERVER['PHP_AUTH_DIGEST'] ) );
+ $headers['Authorization'] = \sanitize_text_field( \wp_unslash( $_SERVER['PHP_AUTH_DIGEST'] ) );
}
}
@@ -332,7 +334,7 @@ function getallheaders() {
}
}
-if ( ! function_exists( 'add_query_params_to_url' ) ) {
+if ( ! function_exists( 'IndieAuth\add_query_params_to_url' ) ) {
/**
* Add query strings to an URL.
*
@@ -344,7 +346,7 @@ function getallheaders() {
* @return string URL with query parameters.
*/
function add_query_params_to_url( $args, $url ) {
- $parts = wp_parse_url( $url );
+ $parts = \wp_parse_url( $url );
if ( array_key_exists( 'query', $parts ) && $parts['query'] ) {
parse_str( $parts['query'], $params );
} else {
@@ -359,7 +361,7 @@ function add_query_params_to_url( $args, $url ) {
}
}
-if ( ! function_exists( 'build_url' ) ) {
+if ( ! function_exists( 'IndieAuth\build_url' ) ) {
/**
* Inverse of parse_url.
*
@@ -385,7 +387,7 @@ function build_url( $parsed_url ) {
}
}
-if ( ! function_exists( 'normalize_url' ) ) {
+if ( ! function_exists( 'IndieAuth\normalize_url' ) ) {
/**
* Normalize a URL by adding slash if no path and converting hostname to lowercase.
*
@@ -394,7 +396,7 @@ function build_url( $parsed_url ) {
* @return string|false Normalized URL or false.
*/
function normalize_url( $url, $force_ssl = false ) {
- $parts = wp_parse_url( $url );
+ $parts = \wp_parse_url( $url );
if ( array_key_exists( 'path', $parts ) && '' === $parts['path'] ) {
return false;
}
@@ -425,7 +427,7 @@ function normalize_url( $url, $force_ssl = false ) {
* @return array|null Array of Scopes or Null if Not Added at all.
*/
function indieauth_get_scopes() {
- return apply_filters( 'indieauth_scopes', null );
+ return \apply_filters( 'indieauth_scopes', null );
}
/**
@@ -448,7 +450,7 @@ function indieauth_check_scope( $scope ) {
* @return array|null Array with Response Token from IndieAuth endpoint.
*/
function indieauth_get_response() {
- return apply_filters( 'indieauth_response', null );
+ return \apply_filters( 'indieauth_response', null );
}
/**
@@ -467,14 +469,14 @@ function indieauth_get_client_id() {
/**
* Get Client Data.
*
- * @return array|WP_Error|null Client data or null.
+ * @return array|\WP_Error|null Client data or null.
*/
function indieauth_get_client_data() {
$response = indieauth_get_response();
if ( is_null( $response ) || ! isset( $response['client_id'] ) ) {
return null;
}
- return IndieAuth_Client_Taxonomy::get_client( $response['client_id'] );
+ return Client_Taxonomy::get_client( $response['client_id'] );
}
/**
@@ -528,21 +530,21 @@ function base64_urlencode( $data ) {
/**
* Returns IndieAuth profile user data.
*
- * @param int|WP_User $user User.
- * @param bool $email Whether to return email or not.
+ * @param int|\WP_User $user User.
+ * @param bool $email Whether to return email or not.
* @return array User information or empty if none.
*/
function indieauth_get_user( $user, $email = false ) {
if ( is_numeric( $user ) ) {
- $user = get_user_by( 'ID', $user );
+ $user = \get_user_by( 'ID', $user );
}
- if ( ! $user instanceof WP_User ) {
+ if ( ! $user instanceof \WP_User ) {
return array();
}
$return = array(
'name' => $user->display_name,
- 'url' => empty( $user->user_url ) ? get_author_posts_url( $user->ID ) : $user->user_url,
- 'photo' => get_avatar_url(
+ 'url' => empty( $user->user_url ) ? \get_author_posts_url( $user->ID ) : $user->user_url,
+ 'photo' => \get_avatar_url(
$user->ID,
array(
'size' => 125,
@@ -560,16 +562,16 @@ function indieauth_get_user( $user, $email = false ) {
* @return int User ID or 0.
*/
function indieauth_get_root_user() {
- $default = get_option( 'indieauth_root_user', null );
+ $default = \get_option( 'indieauth_root_user', null );
// Null is only returned if the setting does not exist.
if ( ! is_null( $default ) ) {
return $default;
}
- $default = get_option( 'iw_default_author', null );
+ $default = \get_option( 'iw_default_author', null );
if ( $default ) {
return $default;
}
- $users = get_users(
+ $users = \get_users(
array(
'fields' => 'ID',
)
@@ -577,7 +579,7 @@ function indieauth_get_root_user() {
// If the setting is not set then default it to a single user. This can be overridden if it is set to None in the settings.
if ( 1 === count( $users ) ) {
- update_option( 'indieauth_root_user', $users[0] );
+ \update_option( 'indieauth_root_user', $users[0] );
}
// If there is more than one user, but multiple authors you cannot tell who the prime user is.
$single = get_single_author();
@@ -585,7 +587,7 @@ function indieauth_get_root_user() {
return 0;
}
- update_option( 'indieauth_root_user', $single );
+ \update_option( 'indieauth_root_user', $single );
return $single;
}
@@ -595,7 +597,7 @@ function indieauth_get_root_user() {
* @return string Metadata endpoint URL.
*/
function indieauth_get_metadata_endpoint() {
- return IndieAuth_Plugin::$metadata->get_endpoint();
+ return IndieAuth::$metadata->get_endpoint();
}
/**
@@ -604,7 +606,7 @@ function indieauth_get_metadata_endpoint() {
* @return string Issuer URL.
*/
function indieauth_get_issuer() {
- return IndieAuth_Plugin::$metadata->get_issuer();
+ return IndieAuth::$metadata->get_issuer();
}
/**
@@ -618,13 +620,13 @@ function indieauth_validate_user_identifier( $url ) {
return false;
}
- $url = trailingslashit( $url );
+ $url = \trailingslashit( $url );
if ( ! $url ) {
return false;
}
- $parsed_url = wp_parse_url( $url );
+ $parsed_url = \wp_parse_url( $url );
if ( ! $parsed_url || empty( $parsed_url['host'] ) || ! in_array( $parsed_url['scheme'], array( 'http', 'https' ), true ) ) {
return false;
@@ -641,7 +643,7 @@ function indieauth_validate_user_identifier( $url ) {
}
// If this is an IP address it is not permitted.
- $ip = filter_var( $parsed_url['host'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 );
+ $ip = \filter_var( $parsed_url['host'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 );
if ( $ip ) {
return false;
}
@@ -660,13 +662,13 @@ function indieauth_validate_client_identifier( $url ) {
return false;
}
- $url = trailingslashit( $url );
+ $url = \trailingslashit( $url );
if ( ! $url ) {
return false;
}
- $parsed_url = wp_parse_url( $url );
+ $parsed_url = \wp_parse_url( $url );
if ( ! $parsed_url || empty( $parsed_url['host'] ) ) {
return false;
}
@@ -682,7 +684,7 @@ function indieauth_validate_client_identifier( $url ) {
}
// Validate that if this is an IP address it is one of the approved IPs.
- $ip = filter_var( $parsed_url['host'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 );
+ $ip = \filter_var( $parsed_url['host'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6 );
$allowed = array(
'127.0.0.1',
'0000:0000:0000:0000:0000:0000:0000:0001',
@@ -707,13 +709,13 @@ function indieauth_validate_issuer_identifier( $url ) {
return false;
}
- $url = trailingslashit( $url );
+ $url = \trailingslashit( $url );
if ( ! $url ) {
return false;
}
- $parsed_url = wp_parse_url( $url );
+ $parsed_url = \wp_parse_url( $url );
// Issuer Identifiers MUST be https.
if ( ! isset( $parsed_url['scheme'] ) || 'https' !== $parsed_url['scheme'] ) {
@@ -736,3 +738,63 @@ function indieauth_validate_issuer_identifier( $url ) {
return $url;
}
+
+/**
+ * Get the OAuth error from a response.
+ *
+ * Checks if a response is a WP_Error or contains an OAuth error
+ * in the response body, and returns an OAuth_Response if so.
+ *
+ * @param mixed $obj Response object to check.
+ * @return OAuth_Response|false OAuth_Response on error, false otherwise.
+ */
+function get_oauth_error( $obj ) {
+ if ( $obj instanceof OAuth_Response ) {
+ return $obj;
+ }
+ if ( \is_wp_error( $obj ) ) {
+ return wp_error_to_oauth_response( $obj );
+ }
+ if ( is_array( $obj ) ) {
+ $body = \wp_remote_retrieve_body( $obj );
+ if ( $body ) {
+ $body = json_decode( $body, true );
+ if ( is_array( $body ) && isset( $body['error'] ) ) {
+ $code = (int) \wp_remote_retrieve_response_code( $obj );
+ return new OAuth_Response(
+ $body['error'],
+ isset( $body['error_description'] ) ? $body['error_description'] : '',
+ $code ? $code : 400
+ );
+ }
+ }
+ }
+ return false;
+}
+
+/**
+ * Check if an object is an OAuth error response.
+ *
+ * @param mixed $obj Object to check.
+ * @return bool Whether the object is an OAuth_Response.
+ */
+function is_oauth_error( $obj ) {
+ return $obj instanceof OAuth_Response;
+}
+
+/**
+ * Convert a WP_Error to an OAuth_Response.
+ *
+ * @param \WP_Error $error WP_Error to convert.
+ * @return OAuth_Response OAuth error response.
+ */
+function wp_error_to_oauth_response( $error ) {
+ $data = $error->get_error_data();
+ $status = isset( $data['status'] ) ? $data['status'] : 400;
+
+ return new OAuth_Response(
+ $error->get_error_code(),
+ $error->get_error_message(),
+ $status
+ );
+}
diff --git a/includes/class-indieauth-authorization-endpoint.php b/includes/rest/class-authorization-controller.php
similarity index 62%
rename from includes/class-indieauth-authorization-endpoint.php
rename to includes/rest/class-authorization-controller.php
index e390591..1d9b846 100644
--- a/includes/class-indieauth-authorization-endpoint.php
+++ b/includes/rest/class-authorization-controller.php
@@ -1,64 +1,59 @@
codes = new Token_User( '_indieauth_code_' );
- }
+ protected $rest_base = 'auth';
/**
- * Output HTTP Link header for authorization endpoint.
+ * Authorization codes storage.
+ *
+ * @var Token_User
*/
- public function http_header() {
- if ( is_author() || is_front_page() ) {
- $this->set_http_header( $this->get_endpoint(), 'authorization_endpoint' );
- }
- }
+ private $codes;
/**
- * Output HTML link tag for authorization endpoint.
+ * Constructor.
*/
- public function html_header() {
- $kses = array(
- 'link' => array(
- 'href' => array(),
- 'rel' => array(),
- ),
- );
-
- if ( is_author() || is_front_page() ) {
- echo wp_kses( $this->get_html_header( $this->get_endpoint(), 'authorization_endpoint' ), $kses );
- }
+ public function __construct() {
+ $this->codes = new Token_User( '_indieauth_code_' );
}
/**
@@ -66,8 +61,8 @@ public function html_header() {
*
* @return string The authorization endpoint URL.
*/
- public static function get_endpoint() {
- return rest_url( '/indieauth/1.0/auth' );
+ public function get_endpoint() {
+ return \rest_url( $this->namespace . '/' . $this->rest_base );
}
/**
@@ -76,7 +71,7 @@ public static function get_endpoint() {
* @return array List of supported response types.
*/
public static function get_response_types() {
- return array_unique( apply_filters( 'indieauth_response_types_supported', array( 'code' ) ) );
+ return array_unique( \apply_filters( 'indieauth_response_types_supported', array( 'code' ) ) );
}
/**
@@ -108,12 +103,12 @@ public function metadata( $metadata ) {
* Register the Route.
*/
public function register_routes() {
- register_rest_route(
- 'indieauth/1.0',
- '/auth',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base,
array(
array(
- 'methods' => WP_REST_Server::READABLE,
+ 'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get' ),
'args' => array(
// Code is currently the only type as of IndieAuth 1.1 and a response_type is now required.
@@ -123,13 +118,13 @@ public function register_routes() {
),
// The client URL.
'client_id' => array(
- 'validate_callback' => 'indieauth_validate_client_identifier',
+ 'validate_callback' => 'IndieAuth\indieauth_validate_client_identifier',
'sanitize_callback' => 'esc_url_raw',
'required' => true,
),
// The redirect URL indicating where the user should be redirected to after approving the request.
'redirect_uri' => array(
- 'validate_callback' => 'rest_is_valid_url',
+ 'validate_callback' => 'IndieAuth\rest_is_valid_url',
'sanitize_callback' => 'esc_url_raw',
'required' => true,
),
@@ -151,14 +146,14 @@ public function register_routes() {
'scope' => array(),
// The profile URL the user entered. Optional.
'me' => array(
- 'validate_callback' => 'indieauth_validate_user_identifier',
+ 'validate_callback' => 'IndieAuth\indieauth_validate_user_identifier',
'sanitize_callback' => 'esc_url_raw',
),
),
'permission_callback' => '__return_true',
),
array(
- 'methods' => WP_REST_Server::CREATABLE,
+ 'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'post' ),
'args' => array(
// grant_type=authorization_code is the only POST option supported right now.
@@ -169,12 +164,12 @@ public function register_routes() {
'code' => array(),
// The client's URL, which MUST match the client_id used in the authentication request.
'client_id' => array(
- 'validate_callback' => 'indieauth_validate_client_identifier',
+ 'validate_callback' => 'IndieAuth\indieauth_validate_client_identifier',
'sanitize_callback' => 'esc_url_raw',
),
// The client's redirect URL, which MUST match the initial authentication request.
'redirect_uri' => array(
- 'validate_callback' => 'rest_is_valid_url',
+ 'validate_callback' => 'IndieAuth\rest_is_valid_url',
'sanitize_callback' => 'esc_url_raw',
),
// The original plaintext random string generated before starting the authorization request.
@@ -195,29 +190,29 @@ public function register_routes() {
public static function scopes( $scope = 'all' ) {
$scopes = array(
// Micropub Scopes.
- 'post' => __( 'Legacy Scope (Deprecated)', 'indieauth' ),
- 'draft' => __( 'Allows the applicate to create posts in draft status only', 'indieauth' ),
- 'create' => __( 'Allows the application to create posts and upload to the Media Endpoint', 'indieauth' ),
- 'update' => __( 'Allows the application to update posts', 'indieauth' ),
- 'delete' => __( 'Allows the application to delete posts', 'indieauth' ),
- 'undelete' => __( 'Allows the application to undelete posts', 'indieauth' ),
- 'media' => __( 'Allows the application to upload to the media endpoint', 'indieauth' ),
+ 'post' => \__( 'Legacy Scope (Deprecated)', 'indieauth' ),
+ 'draft' => \__( 'Allows the applicate to create posts in draft status only', 'indieauth' ),
+ 'create' => \__( 'Allows the application to create posts and upload to the Media Endpoint', 'indieauth' ),
+ 'update' => \__( 'Allows the application to update posts', 'indieauth' ),
+ 'delete' => \__( 'Allows the application to delete posts', 'indieauth' ),
+ 'undelete' => \__( 'Allows the application to undelete posts', 'indieauth' ),
+ 'media' => \__( 'Allows the application to upload to the media endpoint', 'indieauth' ),
// Microsub Scopes.
- 'read' => __( 'Allows the application read access to channels', 'indieauth' ),
- 'follow' => __( 'Allows the application to manage a follow list', 'indieauth' ),
- 'mute' => __( 'Allows the application to mute and unmute users', 'indieauth' ),
- 'block' => __( 'Allows the application to block and unlock users', 'indieauth' ),
- 'channels' => __( 'Allows the application to manage channels', 'indieauth' ),
- 'save' => __( 'Allows the application to save content for later retrieval', 'indieauth' ),
+ 'read' => \__( 'Allows the application read access to channels', 'indieauth' ),
+ 'follow' => \__( 'Allows the application to manage a follow list', 'indieauth' ),
+ 'mute' => \__( 'Allows the application to mute and unmute users', 'indieauth' ),
+ 'block' => \__( 'Allows the application to block and unlock users', 'indieauth' ),
+ 'channels' => \__( 'Allows the application to manage channels', 'indieauth' ),
+ 'save' => \__( 'Allows the application to save content for later retrieval', 'indieauth' ),
// Profile.
- 'profile' => __( 'Allows access to the users default profile information which includes name, photo, and url', 'indieauth' ),
- 'email' => __( 'Allows access to the users email address', 'indieauth' ),
+ 'profile' => \__( 'Allows access to the users default profile information which includes name, photo, and url', 'indieauth' ),
+ 'email' => \__( 'Allows access to the users email address', 'indieauth' ),
);
if ( 'all' === $scope ) {
return $scopes;
}
- $description = isset( $scopes[ $scope ] ) ? $scopes[ $scope ] : __( 'No Description Available', 'indieauth' );
- return apply_filters( 'indieauth_scope_description', $description, $scope );
+ $description = isset( $scopes[ $scope ] ) ? $scopes[ $scope ] : \__( 'No Description Available', 'indieauth' );
+ return \apply_filters( 'indieauth_scope_description', $description, $scope );
}
/**
@@ -236,8 +231,8 @@ public static function scope_list( $scopes ) {
}
$scopes = array_values( $scopes );
echo '';
- echo wp_kses(
- sprintf( '
create - %2$s ', esc_attr( 'checked' ), esc_html( self::scopes( 'create' ) ) ),
+ echo \wp_kses(
+ sprintf( 'create - %2$s ', \esc_attr( 'checked' ), \esc_html( self::scopes( 'create' ) ) ),
array(
'li' => array(),
'strong' => array(),
@@ -249,8 +244,8 @@ public static function scope_list( $scopes ) {
),
)
);
- echo wp_kses(
- sprintf( 'draft - %1$s ', esc_html( self::scopes( 'draft' ) ) ),
+ echo \wp_kses(
+ sprintf( 'draft - %1$s ', \esc_html( self::scopes( 'draft' ) ) ),
array(
'li' => array(),
'strong' => array(),
@@ -261,8 +256,8 @@ public static function scope_list( $scopes ) {
),
)
);
- echo wp_kses(
- sprintf( 'none - %1$s ', __( 'Token will have no privileges to create posts', 'indieauth' ) ),
+ echo \wp_kses(
+ sprintf( 'none - %1$s ', \__( 'Token will have no privileges to create posts', 'indieauth' ) ),
array(
'li' => array(),
'strong' => array(),
@@ -276,8 +271,8 @@ public static function scope_list( $scopes ) {
echo '';
}
foreach ( $scopes as $s ) {
- echo wp_kses(
- sprintf( '%1$s - %3$s ', $s, checked( true, true, false ), esc_html( self::scopes( $s ) ) ),
+ echo \wp_kses(
+ sprintf( '%1$s - %3$s ', $s, \checked( true, true, false ), \esc_html( self::scopes( $s ) ) ),
array(
'li' => array(),
'strong' => array(),
@@ -296,8 +291,8 @@ public static function scope_list( $scopes ) {
/**
* Authorization Endpoint GET request handler.
*
- * @param WP_REST_Request $request The Request Object.
- * @return WP_REST_Response|WP_OAuth_Response Response to return to the REST Server.
+ * @param \WP_REST_Request $request The Request Object.
+ * @return \WP_REST_Response|OAuth_Response Response to return to the REST Server.
*/
public function get( $request ) {
$params = $request->get_params();
@@ -308,28 +303,28 @@ public function get( $request ) {
return $this->code( $params );
}
- return new WP_OAuth_Response( 'unsupported_response_type', __( 'Unsupported Response Type', 'indieauth' ), 400 );
+ return new OAuth_Response( 'unsupported_response_type', \__( 'Unsupported Response Type', 'indieauth' ), 400 );
}
/**
* Handler for Response Type Code.
*
* @param array $params The parameters passed to the REST Server.
- * @return WP_REST_Response|WP_OAuth_Response Response to return to the REST Server.
+ * @return \WP_REST_Response|OAuth_Response Response to return to the REST Server.
*/
public function code( $params ) {
$required = array( 'redirect_uri', 'client_id', 'state' );
foreach ( $required as $require ) {
if ( ! isset( $params[ $require ] ) ) {
// translators: Name of missing parameter.
- return new WP_OAuth_Response( 'parameter_absent', sprintf( __( 'Missing Parameter: %1$s', 'indieauth' ), $require ), 400 );
+ return new OAuth_Response( 'parameter_absent', sprintf( \__( 'Missing Parameter: %1$s', 'indieauth' ), $require ), 400 );
}
}
- $url = wp_login_url( $params['redirect_uri'], true );
+ $url = \wp_login_url( $params['redirect_uri'], true );
$args = array_filter(
array(
'action' => 'indieauth',
- '_wpnonce' => wp_create_nonce( 'wp_rest' ),
+ '_wpnonce' => \wp_create_nonce( 'wp_rest' ),
'response_type' => $params['response_type'],
'client_id' => $params['client_id'],
'me' => isset( $params['me'] ) ? $params['me'] : null,
@@ -341,18 +336,18 @@ public function code( $params ) {
$args['scope'] = isset( $params['scope'] ) ? $params['scope'] : '';
if ( ! preg_match( '@^([\x21\x23-\x5B\x5D-\x7E]+( [\x21\x23-\x5B\x5D-\x7E]+)*)?$@', $args['scope'] ) ) {
- return new WP_OAuth_Response( 'invalid_grant', __( 'Invalid scope request', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'Invalid scope request', 'indieauth' ), 400 );
}
$scopes = explode( ' ', $args['scope'] );
if ( in_array( 'email', $scopes, true ) && ! in_array( 'profile', $scopes, true ) ) {
- return new WP_OAuth_Response( 'invalid_grant', __( 'Cannot request email scope without profile scope', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'Cannot request email scope without profile scope', 'indieauth' ), 400 );
}
$url = add_query_params_to_url( $args, $url );
- return new WP_REST_Response( array( 'url' => $url ), 302, array( 'Location' => $url ) );
+ return new \WP_REST_Response( array( 'url' => $url ), 302, array( 'Location' => $url ) );
}
/**
@@ -394,8 +389,8 @@ public function delete_code( $code, $user_id = null ) {
/**
* Authorization Endpoint POST request handler.
*
- * @param WP_REST_Request $request The Request Object.
- * @return WP_REST_Response|WP_OAuth_Response|array Response to return to the REST Server.
+ * @param \WP_REST_Request $request The Request Object.
+ * @return \WP_REST_Response|OAuth_Response|array Response to return to the REST Server.
*/
public function post( $request ) {
$params = $request->get_params();
@@ -404,48 +399,48 @@ public function post( $request ) {
return $this->authorization_code( $params );
}
- return new WP_OAuth_Response( 'unsupported_grant_type', __( 'Endpoint only accepts authorization_code grant_type', 'indieauth' ), 400 );
+ return new OAuth_Response( 'unsupported_grant_type', \__( 'Endpoint only accepts authorization_code grant_type', 'indieauth' ), 400 );
}
/**
* Grant Type Authorization Code Request Handler.
*
* @param array $params Parameters.
- * @return array|WP_OAuth_Response Response to return to the REST Server.
+ * @return array|OAuth_Response Response to return to the REST Server.
*/
public function authorization_code( $params ) {
$required = array( 'redirect_uri', 'client_id', 'code', 'grant_type' );
foreach ( $required as $require ) {
if ( ! isset( $params[ $require ] ) ) {
// translators: Name of missing parameter.
- return new WP_OAuth_Response( 'parameter_absent', sprintf( __( 'Missing Parameter: %1$s', 'indieauth' ), $require ), 400 );
+ return new OAuth_Response( 'parameter_absent', sprintf( \__( 'Missing Parameter: %1$s', 'indieauth' ), $require ), 400 );
}
}
$code = $params['code'];
$code_verifier = isset( $params['code_verifier'] ) ? $params['code_verifier'] : null;
- $params = wp_array_slice_assoc( $params, array( 'client_id', 'redirect_uri' ) );
+ $params = \wp_array_slice_assoc( $params, array( 'client_id', 'redirect_uri' ) );
$token = $this->get_code( $code );
$scopes = isset( $token['scope'] ) ? array_filter( explode( ' ', $token['scope'] ) ) : array();
if ( ! $token ) {
- return new WP_OAuth_Response( 'invalid_grant', __( 'Invalid authorization code', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'Invalid authorization code', 'indieauth' ), 400 );
}
- $user = get_user_by( 'id', $token['user'] );
+ $user = \get_user_by( 'id', $token['user'] );
if ( $token['exp'] <= time() ) {
$this->delete_code( $code, $token['user'] );
- return new WP_OAuth_Response( 'invalid_grant', __( 'The authorization code expired', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'The authorization code expired', 'indieauth' ), 400 );
}
unset( $token['exp'] );
// If there is a code challenge.
if ( isset( $token['code_challenge'] ) ) {
if ( ! $code_verifier ) {
$this->delete_code( $code, $token['user'] );
- return new WP_OAuth_Response( 'invalid_grant', __( 'Failed PKCE Validation', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'Failed PKCE Validation', 'indieauth' ), 400 );
}
if ( ! pkce_verifier( $token['code_challenge'], $code_verifier, $token['code_challenge_method'] ) ) {
$this->delete_code( $code, $token['user'] );
- return new WP_OAuth_Response( 'invalid_grant', __( 'Failed PKCE Validation', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'Failed PKCE Validation', 'indieauth' ), 400 );
}
unset( $token['code_challenge'] );
unset( $token['code_challenge_method'] );
@@ -462,15 +457,15 @@ public function authorization_code( $params ) {
return $return;
}
- return new WP_OAuth_Response( 'invalid_grant', __( 'There was an error verifying the authorization code. Check that the client_id and redirect_uri match the original request.', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'There was an error verifying the authorization code. Check that the client_id and redirect_uri match the original request.', 'indieauth' ), 400 );
}
/**
* Handle IndieAuth login form action.
*/
public function login_form_indieauth() {
- if ( ! is_user_logged_in() ) {
- auth_redirect();
+ if ( ! \is_user_logged_in() ) {
+ \auth_redirect();
}
if ( isset( $_SERVER['REQUEST_METHOD'] ) && 'GET' === $_SERVER['REQUEST_METHOD'] ) {
@@ -486,9 +481,9 @@ public function login_form_indieauth() {
*/
public function authorize() {
// phpcs:disable
- $client_id = esc_url_raw( wp_unslash( $_GET['client_id'] ) );
- $client_term = IndieAuth_Client_Taxonomy::add_client( $client_id );
- if ( ! is_wp_error( $client_term ) ) {
+ $client_id = \esc_url_raw( \wp_unslash( $_GET['client_id'] ) );
+ $client_term = Client_Taxonomy::add_client( $client_id );
+ if ( ! \is_wp_error( $client_term ) ) {
$client_name = $client_term['name'];
$client_icon = $client_term['icon'];
} else {
@@ -501,14 +496,14 @@ public function authorize() {
$client = sprintf( ' %1$s ', $client_id );
}
- $redirect_uri = isset( $_GET['redirect_to'] ) ? wp_unslash( $_GET['redirect_to'] ) : null;
- $scope = isset( $_GET['scope'] ) ? sanitize_text_field( wp_unslash( $_GET['scope'] ) ) : null;
+ $redirect_uri = isset( $_GET['redirect_to'] ) ? \wp_unslash( $_GET['redirect_to'] ) : null;
+ $scope = isset( $_GET['scope'] ) ? \sanitize_text_field( \wp_unslash( $_GET['scope'] ) ) : null;
$scopes = array_filter( explode( ' ', $scope ) );
$state = isset( $_GET['state'] ) ? $_GET['state'] : null;
- $me = isset( $_GET['me'] ) ? esc_url_raw( wp_unslash( $_GET['me'] ) ) : null;
- $response_type = isset( $_GET['response_type'] ) ? sanitize_text_field( wp_unslash( $_GET['response_type'] ) ) : null;
- $code_challenge = isset( $_GET['code_challenge'] ) ? wp_unslash( $_GET['code_challenge'] ) : null;
- $code_challenge_method = isset( $_GET['code_challenge_method'] ) ? wp_unslash( $_GET['code_challenge_method'] ) : null;
+ $me = isset( $_GET['me'] ) ? \esc_url_raw( \wp_unslash( $_GET['me'] ) ) : null;
+ $response_type = isset( $_GET['response_type'] ) ? \sanitize_text_field( \wp_unslash( $_GET['response_type'] ) ) : null;
+ $code_challenge = isset( $_GET['code_challenge'] ) ? \wp_unslash( $_GET['code_challenge'] ) : null;
+ $code_challenge_method = isset( $_GET['code_challenge_method'] ) ? \wp_unslash( $_GET['code_challenge_method'] ) : null;
// phpcs:enable
$action = 'indieauth';
@@ -522,14 +517,14 @@ public function authorize() {
'action'
)
);
- $url = add_query_params_to_url( $args, wp_login_url() ); // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Used in included template.
+ $url = add_query_params_to_url( $args, \wp_login_url() ); // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Used in included template.
if ( empty( $scopes ) || empty( array_diff( $scopes, array( 'profile', 'email' ) ) ) ) {
- include plugin_dir_path( __DIR__ ) . 'templates/indieauth-authenticate-form.php';
+ include INDIEAUTH_PLUGIN_DIR . 'templates/indieauth-authenticate-form.php';
} else {
- include plugin_dir_path( __DIR__ ) . 'templates/indieauth-authorize-form.php';
+ include INDIEAUTH_PLUGIN_DIR . 'templates/indieauth-authorize-form.php';
}
- include plugin_dir_path( __DIR__ ) . 'templates/indieauth-auth-footer.php';
+ include INDIEAUTH_PLUGIN_DIR . 'templates/indieauth-auth-footer.php';
}
/**
@@ -537,19 +532,19 @@ public function authorize() {
*/
public function confirmed() {
// Verify nonce for CSRF protection before processing any user input.
- $nonce = isset( $_POST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ) : '';
- if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'indieauth_authorize' ) ) {
- wp_die( esc_html__( 'Security check failed. Please try again.', 'indieauth' ) );
+ $nonce = isset( $_POST['_wpnonce'] ) ? \sanitize_text_field( \wp_unslash( $_POST['_wpnonce'] ) ) : '';
+ if ( empty( $nonce ) || ! \wp_verify_nonce( $nonce, 'indieauth_authorize' ) ) {
+ \wp_die( \esc_html__( 'Security check failed. Please try again.', 'indieauth' ) );
}
- $current_user = wp_get_current_user();
+ $current_user = \wp_get_current_user();
$user = $current_user->ID;
// phpcs:disable
- $client_id = wp_unslash( $_POST['client_id'] );
- $redirect_uri = isset( $_POST['redirect_uri'] ) ? wp_unslash( $_POST['redirect_uri'] ) : null;
+ $client_id = \wp_unslash( $_POST['client_id'] );
+ $redirect_uri = isset( $_POST['redirect_uri'] ) ? \wp_unslash( $_POST['redirect_uri'] ) : null;
$scope = isset( $_POST['scope'] ) ? $_POST['scope'] : array();
- $code_challenge = isset( $_POST['code_challenge'] ) ? wp_unslash( $_POST['code_challenge'] ) : null;
- $code_challenge_method = isset( $_POST['code_challenge_method'] ) ? wp_unslash( $_POST['code_challenge_method'] ) : null;
+ $code_challenge = isset( $_POST['code_challenge'] ) ? \wp_unslash( $_POST['code_challenge'] ) : null;
+ $code_challenge_method = isset( $_POST['code_challenge_method'] ) ? \wp_unslash( $_POST['code_challenge_method'] ) : null;
// Do not allow the post scope as deprecated.
// For compatibility, instead update the offering to the more limited but functionally identical create/update.
@@ -562,7 +557,7 @@ public function confirmed() {
$scope = implode( ' ', $scope );
$state = isset( $_POST['state'] ) ? $_POST['state'] : null;
-
+
// In IndieAuth 1.1, me parameter is optional.
// Me should actually be derived only from the logged in user not from this parameter.
// In other implementations, there may be multiple identities permitted for a single user, but this is not currently practical on a
@@ -570,16 +565,16 @@ public function confirmed() {
$me = get_url_from_user( $user );
- $response_type = isset( $_POST['response_type'] ) ? wp_unslash( $_POST['response_type'] ) : null;
+ $response_type = isset( $_POST['response_type'] ) ? \wp_unslash( $_POST['response_type'] ) : null;
// Add UUID for reference.
- $uuid = wp_generate_uuid4();
+ $uuid = \wp_generate_uuid4();
/// phpcs:enable
$token = compact( 'response_type', 'client_id', 'redirect_uri', 'scope', 'me', 'code_challenge', 'code_challenge_method', 'user', 'uuid' );
$token = array_filter( $token );
- $code = self::set_code( $current_user->ID, $token );
+ $code = $this->set_code( $current_user->ID, $token );
$url = add_query_params_to_url(
array(
'code' => $code,
@@ -588,6 +583,6 @@ public function confirmed() {
),
$redirect_uri
);
- wp_redirect( $url ); // phpcs:ignore
+ \wp_redirect( $url ); // phpcs:ignore
}
}
diff --git a/includes/class-indieauth-fedcm-endpoint.php b/includes/rest/class-fedcm-controller.php
similarity index 68%
rename from includes/class-indieauth-fedcm-endpoint.php
rename to includes/rest/class-fedcm-controller.php
index b213ae6..fee276e 100644
--- a/includes/class-indieauth-fedcm-endpoint.php
+++ b/includes/rest/class-fedcm-controller.php
@@ -1,17 +1,40 @@
codes = new Token_User( '_indieauth_code_' );
-
- add_action( 'rest_api_init', array( $this, 'register_routes' ) );
- add_filter( 'indieauth_metadata', array( $this, 'metadata' ) );
- add_filter( 'rest_index_indieauth_endpoints', array( $this, 'rest_index' ) );
-
- // Login Status API hooks.
- add_action( 'set_logged_in_cookie', array( $this, 'set_login_status_logged_in' ) );
- add_action( 'clear_auth_cookie', array( $this, 'set_login_status_logged_out' ) );
-
- // FedCM IdP registration script.
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
}
/**
@@ -58,18 +70,18 @@ public function enqueue_scripts( $hook_suffix ) {
return;
}
- $script_path = plugin_dir_path( __DIR__ ) . 'js/fedcm-register.js';
+ $script_path = INDIEAUTH_PLUGIN_DIR . 'js/fedcm-register.js';
$version = file_exists( $script_path ) ? (string) filemtime( $script_path ) : '1.0.0';
- wp_enqueue_script(
+ \wp_enqueue_script(
'indieauth-fedcm-register',
- plugins_url( 'js/fedcm-register.js', __DIR__ ),
+ \plugins_url( 'js/fedcm-register.js', INDIEAUTH_PLUGIN_FILE ),
array(),
$version,
true
);
- wp_localize_script(
+ \wp_localize_script(
'indieauth-fedcm-register',
'indieAuthFedCM',
array(
@@ -110,7 +122,7 @@ public function set_login_status_logged_out() {
* @return string The config endpoint URL.
*/
public static function get_config_endpoint() {
- return rest_url( '/indieauth/1.0/fedcm/config.json' );
+ return \rest_url( '/indieauth/1.0/fedcm/config.json' );
}
/**
@@ -119,7 +131,7 @@ public static function get_config_endpoint() {
* @return string The accounts endpoint URL.
*/
public static function get_accounts_endpoint() {
- return rest_url( '/indieauth/1.0/fedcm/accounts' );
+ return \rest_url( '/indieauth/1.0/fedcm/accounts' );
}
/**
@@ -128,7 +140,7 @@ public static function get_accounts_endpoint() {
* @return string The client metadata endpoint URL.
*/
public static function get_client_metadata_endpoint() {
- return rest_url( '/indieauth/1.0/fedcm/client_metadata' );
+ return \rest_url( '/indieauth/1.0/fedcm/client_metadata' );
}
/**
@@ -137,7 +149,7 @@ public static function get_client_metadata_endpoint() {
* @return string The assertion endpoint URL.
*/
public static function get_assertion_endpoint() {
- return rest_url( '/indieauth/1.0/fedcm/assertion' );
+ return \rest_url( '/indieauth/1.0/fedcm/assertion' );
}
/**
@@ -146,7 +158,7 @@ public static function get_assertion_endpoint() {
* @return string The login URL.
*/
public static function get_login_url() {
- return wp_login_url();
+ return \wp_login_url();
}
/**
@@ -176,12 +188,12 @@ public function metadata( $metadata ) {
*/
public function register_routes() {
// FedCM Config endpoint.
- register_rest_route(
- 'indieauth/1.0',
- '/fedcm/config.json',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/config.json',
array(
array(
- 'methods' => WP_REST_Server::READABLE,
+ 'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'config' ),
'permission_callback' => '__return_true',
),
@@ -189,12 +201,12 @@ public function register_routes() {
);
// Accounts endpoint.
- register_rest_route(
- 'indieauth/1.0',
- '/fedcm/accounts',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/accounts',
array(
array(
- 'methods' => WP_REST_Server::READABLE,
+ 'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'accounts' ),
'permission_callback' => '__return_true',
),
@@ -202,16 +214,16 @@ public function register_routes() {
);
// Client metadata endpoint.
- register_rest_route(
- 'indieauth/1.0',
- '/fedcm/client_metadata',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/client_metadata',
array(
array(
- 'methods' => WP_REST_Server::READABLE,
+ 'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'client_metadata' ),
'args' => array(
'client_id' => array(
- 'validate_callback' => 'indieauth_validate_client_identifier',
+ 'validate_callback' => 'IndieAuth\indieauth_validate_client_identifier',
'sanitize_callback' => 'esc_url_raw',
),
),
@@ -221,22 +233,22 @@ public function register_routes() {
);
// ID assertion endpoint.
- register_rest_route(
- 'indieauth/1.0',
- '/fedcm/assertion',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base . '/assertion',
array(
array(
- 'methods' => WP_REST_Server::CREATABLE,
+ 'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'assertion' ),
'args' => array(
'client_id' => array(
'required' => true,
- 'validate_callback' => 'indieauth_validate_client_identifier',
+ 'validate_callback' => 'IndieAuth\indieauth_validate_client_identifier',
'sanitize_callback' => 'esc_url_raw',
),
'account_id' => array(
'required' => true,
- 'validate_callback' => 'indieauth_validate_user_identifier',
+ 'validate_callback' => 'IndieAuth\indieauth_validate_user_identifier',
'sanitize_callback' => 'esc_url_raw',
),
'nonce' => array(
@@ -257,26 +269,26 @@ public function register_routes() {
* Validate the params argument contains required PKCE fields.
*
* @param mixed $value The params value.
- * @return bool|WP_Error True if valid, WP_Error otherwise.
+ * @return bool|\WP_Error True if valid, WP_Error otherwise.
*/
public function validate_params( $value ) {
if ( is_string( $value ) ) {
$value = json_decode( $value, true );
if ( JSON_ERROR_NONE !== json_last_error() ) {
- return new WP_Error( 'invalid_params', __( 'Invalid JSON in params', 'indieauth' ) );
+ return new \WP_Error( 'invalid_params', \__( 'Invalid JSON in params', 'indieauth' ) );
}
}
if ( ! is_array( $value ) ) {
- return new WP_Error( 'invalid_params', __( 'Invalid params format', 'indieauth' ) );
+ return new \WP_Error( 'invalid_params', \__( 'Invalid params format', 'indieauth' ) );
}
if ( empty( $value['code_challenge'] ) || empty( $value['code_challenge_method'] ) ) {
- return new WP_Error( 'invalid_params', __( 'PKCE parameters required', 'indieauth' ) );
+ return new \WP_Error( 'invalid_params', \__( 'PKCE parameters required', 'indieauth' ) );
}
if ( 'S256' !== $value['code_challenge_method'] ) {
- return new WP_Error( 'invalid_params', __( 'Unsupported code_challenge_method', 'indieauth' ) );
+ return new \WP_Error( 'invalid_params', \__( 'Unsupported code_challenge_method', 'indieauth' ) );
}
return true;
@@ -285,7 +297,7 @@ public function validate_params( $value ) {
/**
* Check if the request has the required FedCM header.
*
- * @param WP_REST_Request $request The request object.
+ * @param \WP_REST_Request $request The request object.
* @return bool True if valid FedCM request.
*/
private function is_valid_fedcm_request( $request ) {
@@ -298,8 +310,8 @@ private function is_valid_fedcm_request( $request ) {
*
* Per FedCM spec, the full origin (scheme + host + port) must match.
*
- * @param WP_REST_Request $request The request object.
- * @param string $client_id The client ID.
+ * @param \WP_REST_Request $request The request object.
+ * @param string $client_id The client ID.
* @return bool True if valid.
*/
private function validate_origin( $request, $client_id ) {
@@ -308,8 +320,8 @@ private function validate_origin( $request, $client_id ) {
return false;
}
- $origin_parts = wp_parse_url( $origin );
- $client_id_parts = wp_parse_url( $client_id );
+ $origin_parts = \wp_parse_url( $origin );
+ $client_id_parts = \wp_parse_url( $client_id );
if ( ! is_array( $origin_parts ) || ! is_array( $client_id_parts ) ) {
return false;
@@ -338,9 +350,9 @@ private function validate_origin( $request, $client_id ) {
/**
* Add CORS headers for FedCM responses.
*
- * @param WP_REST_Response $response The response object.
- * @param WP_REST_Request $request The request object.
- * @return WP_REST_Response Modified response.
+ * @param \WP_REST_Response $response The response object.
+ * @param \WP_REST_Request $request The request object.
+ * @return \WP_REST_Response Modified response.
*/
private function add_cors_headers( $response, $request ) {
$origin = $request->get_header( 'Origin' );
@@ -358,8 +370,8 @@ private function add_cors_headers( $response, $request ) {
*
* Returns the IdP configuration for FedCM.
*
- * @param WP_REST_Request $request The request object.
- * @return WP_REST_Response The config response.
+ * @param \WP_REST_Request $request The request object.
+ * @return \WP_REST_Response The config response.
*/
public function config( $request ) {
$config = array(
@@ -372,12 +384,12 @@ public function config( $request ) {
/**
* Filter the FedCM config response.
*
- * @param array $config The config array.
- * @param WP_REST_Request $request The request object.
+ * @param array $config The config array.
+ * @param \WP_REST_Request $request The request object.
*/
- $config = apply_filters( 'indieauth_fedcm_config', $config, $request );
+ $config = \apply_filters( 'indieauth_fedcm_config', $config, $request );
- $response = new WP_REST_Response( $config, 200 );
+ $response = new \WP_REST_Response( $config, 200 );
// Config endpoint must be accessible cross-origin per FedCM spec.
return $this->add_cors_headers( $response, $request );
@@ -388,27 +400,27 @@ public function config( $request ) {
*
* Returns the list of accounts for the current logged-in user.
*
- * @param WP_REST_Request $request The request object.
- * @return WP_REST_Response|WP_Error The accounts response or error.
+ * @param \WP_REST_Request $request The request object.
+ * @return \WP_REST_Response|\WP_Error The accounts response or error.
*/
public function accounts( $request ) {
// Validate FedCM request header.
if ( ! $this->is_valid_fedcm_request( $request ) ) {
- return new WP_REST_Response(
+ return new \WP_REST_Response(
array( 'error' => 'Missing or invalid Sec-Fetch-Dest header' ),
400
);
}
// Check if user is logged in.
- if ( ! is_user_logged_in() ) {
- return new WP_REST_Response(
+ if ( ! \is_user_logged_in() ) {
+ return new \WP_REST_Response(
array( 'error' => 'Not logged in' ),
401
);
}
- $user = wp_get_current_user();
+ $user = \wp_get_current_user();
$me = get_url_from_user( $user->ID );
// Build the account object.
@@ -420,7 +432,7 @@ public function accounts( $request ) {
);
// Add picture if available.
- $avatar = get_avatar_url(
+ $avatar = \get_avatar_url(
$user->ID,
array(
'size' => 256,
@@ -434,12 +446,12 @@ public function accounts( $request ) {
/**
* Filter the FedCM account data.
*
- * @param array $account The account data.
- * @param WP_User $user The WordPress user.
+ * @param array $account The account data.
+ * @param \WP_User $user The WordPress user.
*/
- $account = apply_filters( 'indieauth_fedcm_account', $account, $user );
+ $account = \apply_filters( 'indieauth_fedcm_account', $account, $user );
- $response = new WP_REST_Response(
+ $response = new \WP_REST_Response(
array( 'accounts' => array( $account ) ),
200,
array()
@@ -453,8 +465,8 @@ public function accounts( $request ) {
*
* Returns metadata about the requesting client.
*
- * @param WP_REST_Request $request The request object.
- * @return WP_REST_Response The client metadata response.
+ * @param \WP_REST_Request $request The request object.
+ * @return \WP_REST_Response The client metadata response.
*/
public function client_metadata( $request ) {
$client_id = $request->get_param( 'client_id' );
@@ -463,8 +475,8 @@ public function client_metadata( $request ) {
// Try to discover client metadata.
if ( $client_id ) {
- $client = IndieAuth_Client_Taxonomy::get_client( $client_id );
- if ( $client && ! is_wp_error( $client ) ) {
+ $client = Client_Taxonomy::get_client( $client_id );
+ if ( $client && ! \is_wp_error( $client ) ) {
if ( ! empty( $client['privacy_policy'] ) ) {
$metadata['privacy_policy_url'] = $client['privacy_policy'];
}
@@ -480,9 +492,9 @@ public function client_metadata( $request ) {
* @param array $metadata The metadata array.
* @param string $client_id The client ID.
*/
- $metadata = apply_filters( 'indieauth_fedcm_client_metadata', $metadata, $client_id );
+ $metadata = \apply_filters( 'indieauth_fedcm_client_metadata', $metadata, $client_id );
- $response = new WP_REST_Response(
+ $response = new \WP_REST_Response(
$metadata,
200,
array()
@@ -496,13 +508,13 @@ public function client_metadata( $request ) {
*
* Issues an authorization code for FedCM authentication.
*
- * @param WP_REST_Request $request The request object.
- * @return WP_REST_Response|WP_Error The assertion response or error.
+ * @param \WP_REST_Request $request The request object.
+ * @return \WP_REST_Response|\WP_Error The assertion response or error.
*/
public function assertion( $request ) {
// Validate FedCM request header.
if ( ! $this->is_valid_fedcm_request( $request ) ) {
- return new WP_REST_Response(
+ return new \WP_REST_Response(
array( 'error' => 'Missing or invalid Sec-Fetch-Dest header' ),
400
);
@@ -515,26 +527,26 @@ public function assertion( $request ) {
// Validate origin.
if ( ! $this->validate_origin( $request, $client_id ) ) {
- return new WP_REST_Response(
+ return new \WP_REST_Response(
array( 'error' => 'Origin mismatch' ),
403
);
}
// Check if user is logged in.
- if ( ! is_user_logged_in() ) {
- return new WP_REST_Response(
+ if ( ! \is_user_logged_in() ) {
+ return new \WP_REST_Response(
array( 'error' => 'Not logged in' ),
401
);
}
- $user = wp_get_current_user();
+ $user = \wp_get_current_user();
$me = get_url_from_user( $user->ID );
// Verify account_id matches the current user.
if ( normalize_url( $account_id ) !== normalize_url( $me ) ) {
- return new WP_REST_Response(
+ return new \WP_REST_Response(
array( 'error' => 'Account mismatch' ),
403
);
@@ -545,26 +557,26 @@ public function assertion( $request ) {
$params = json_decode( $params, true );
}
- $code_challenge = sanitize_text_field( $params['code_challenge'] );
- $code_challenge_method = sanitize_text_field( $params['code_challenge_method'] );
+ $code_challenge = \sanitize_text_field( $params['code_challenge'] );
+ $code_challenge_method = \sanitize_text_field( $params['code_challenge_method'] );
// Generate authorization code.
- $uuid = wp_generate_uuid4();
+ $uuid = \wp_generate_uuid4();
// Determine scope - default to 'profile' for FedCM.
$scope = 'profile';
if ( is_array( $params ) && isset( $params['scope'] ) ) {
- $scope = sanitize_text_field( $params['scope'] );
+ $scope = \sanitize_text_field( $params['scope'] );
}
/**
* Filter the scope used for FedCM-issued authorization codes.
*
- * @param string $scope The scope to be stored with the authorization code.
- * @param WP_REST_Request $request The REST request object.
- * @param WP_User $user The authenticated WordPress user.
+ * @param string $scope The scope to be stored with the authorization code.
+ * @param \WP_REST_Request $request The REST request object.
+ * @param \WP_User $user The authenticated WordPress user.
*/
- $scope = apply_filters( 'indieauth_fedcm_scope', $scope, $request, $user );
+ $scope = \apply_filters( 'indieauth_fedcm_scope', $scope, $request, $user );
$token = array(
'response_type' => 'code',
@@ -580,7 +592,7 @@ public function assertion( $request ) {
);
if ( $nonce ) {
- $token['nonce'] = sanitize_text_field( $nonce );
+ $token['nonce'] = \sanitize_text_field( $nonce );
}
$token = array_filter( $token );
@@ -591,23 +603,23 @@ public function assertion( $request ) {
// Build the token response.
$token_response = array(
'code' => $code,
- 'metadata_endpoint' => IndieAuth_Metadata_Endpoint::get_endpoint(),
+ 'metadata_endpoint' => \rest_url( 'indieauth/1.0/metadata' ),
);
/**
* Filter the FedCM assertion token response.
*
- * @param array $token_response The token response.
- * @param WP_REST_Request $request The request object.
- * @param WP_User $user The WordPress user.
+ * @param array $token_response The token response.
+ * @param \WP_REST_Request $request The request object.
+ * @param \WP_User $user The WordPress user.
*/
- $token_response = apply_filters( 'indieauth_fedcm_assertion_token', $token_response, $request, $user );
+ $token_response = \apply_filters( 'indieauth_fedcm_assertion_token', $token_response, $request, $user );
// Add client to taxonomy for tracking.
- IndieAuth_Client_Taxonomy::add_client( $client_id );
+ Client_Taxonomy::add_client( $client_id );
- $response = new WP_REST_Response(
- array( 'token' => wp_json_encode( $token_response ) ),
+ $response = new \WP_REST_Response(
+ array( 'token' => \wp_json_encode( $token_response ) ),
200,
array()
);
diff --git a/includes/class-indieauth-introspection-endpoint.php b/includes/rest/class-introspection-controller.php
similarity index 66%
rename from includes/class-indieauth-introspection-endpoint.php
rename to includes/rest/class-introspection-controller.php
index 49bcf7e..b1f525e 100644
--- a/includes/class-indieauth-introspection-endpoint.php
+++ b/includes/rest/class-introspection-controller.php
@@ -1,25 +1,40 @@
init_tokens();
}
/**
@@ -27,8 +42,8 @@ public function __construct() {
*
* @return string Endpoint URL.
*/
- public static function get_endpoint() {
- return rest_url( '/indieauth/1.0/introspection' );
+ public function get_endpoint() {
+ return \rest_url( $this->namespace . '/' . $this->rest_base );
}
/**
@@ -37,7 +52,7 @@ public static function get_endpoint() {
* @return array Supported authentication methods.
*/
public function auth_methods_supported() {
- return array_unique( apply_filters( 'indieauth_introspection_auth_methods_supported', array( 'none' ) ) );
+ return array_unique( \apply_filters( 'indieauth_introspection_auth_methods_supported', array( 'none' ) ) );
}
/**
@@ -67,12 +82,12 @@ public function rest_index( $index ) {
* Register the Route.
*/
public function register_routes() {
- register_rest_route(
- 'indieauth/1.0',
- '/introspection',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base,
array(
array(
- 'methods' => WP_REST_Server::CREATABLE,
+ 'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'introspection' ),
'args' => array(
'token' => array(
@@ -91,8 +106,8 @@ public function register_routes() {
/**
* Introspection Endpoint request handler.
*
- * @param WP_REST_Request $request The Request Object.
- * @return WP_REST_Response Response to return to the REST Server.
+ * @param \WP_REST_Request $request The Request Object.
+ * @return \WP_REST_Response Response to return to the REST Server.
*/
public function introspection( $request ) {
$params = $request->get_params();
@@ -103,6 +118,6 @@ public function introspection( $request ) {
$token = array( 'active' => false );
}
- return rest_ensure_response( $token );
+ return \rest_ensure_response( $token );
}
}
diff --git a/includes/rest/class-metadata-controller.php b/includes/rest/class-metadata-controller.php
new file mode 100644
index 0000000..98e5c1c
--- /dev/null
+++ b/includes/rest/class-metadata-controller.php
@@ -0,0 +1,134 @@
+namespace . '/' . $this->rest_base );
+ }
+
+ /**
+ * Returns the issuer URL.
+ *
+ * @return string Issuer URL.
+ */
+ public static function get_issuer() {
+ return \rest_url( '/indieauth/1.0' );
+ }
+
+ /**
+ * Hooks into the REST API output to add a metadata header to the Issuer URL.
+ *
+ * @param bool $served Whether the request has already been served.
+ * @param \WP_HTTP_ResponseInterface $result Result to send to the client. Usually a WP_REST_Response.
+ * @param \WP_REST_Request $request Request used to generate the response.
+ * @param \WP_REST_Server $server Server instance.
+ * @return bool Whether the request has been served.
+ */
+ public function serve_request( $served, $result, $request, $server ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
+ if ( false === strpos( $request->get_route(), '/indieauth/1.0' ) ) {
+ return $served;
+ }
+ header( sprintf( 'Link: <%s>; rel="%s"', $this->get_endpoint(), 'indieauth-metadata' ), false );
+
+ return $served;
+ }
+
+ /**
+ * Add authentication information into the REST API Index.
+ *
+ * @param \WP_REST_Response $response REST API Response Object.
+ * @return \WP_REST_Response Response object with endpoint info added.
+ */
+ public function register_index( \WP_REST_Response $response ) {
+ $data = $response->get_data();
+ $endpoints = array(
+ 'metadata' => $this->get_endpoint(),
+ );
+ $endpoints = array_filter( $endpoints );
+ if ( empty( $endpoints ) ) {
+ return $response;
+ }
+ $data['authentication']['indieauth'] = array(
+ 'endpoints' => \apply_filters( 'rest_index_indieauth_endpoints', $endpoints ),
+ );
+ $response->set_data( $data );
+ return $response;
+ }
+
+ /**
+ * Register the Route.
+ */
+ public function register_routes() {
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base,
+ array(
+ array(
+ 'methods' => \WP_REST_Server::READABLE,
+ 'callback' => array( $this, 'metadata' ),
+ 'args' => array(),
+ 'permission_callback' => '__return_true',
+ ),
+ )
+ );
+ }
+
+ /**
+ * Metadata Endpoint GET request handler.
+ *
+ * @param \WP_REST_Request $request The Request Object.
+ * @return \WP_REST_Response Response to Return to the REST Server.
+ */
+ public function metadata( $request ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
+ $metadata = array(
+ 'issuer' => indieauth_get_issuer(),
+ 'scopes_supported' => IndieAuth::$scopes->get_names(),
+ 'service_documentation' => 'https://indieauth.spec.indieweb.org',
+ 'code_challenge_methods_supported' => array( 'S256' ),
+ );
+
+ $metadata = \apply_filters( 'indieauth_metadata', $metadata );
+ return new \WP_REST_Response(
+ $metadata,
+ 200,
+ array(
+ 'Content-Type' => 'application/json',
+ )
+ );
+ }
+}
diff --git a/includes/class-indieauth-revocation-endpoint.php b/includes/rest/class-revocation-controller.php
similarity index 63%
rename from includes/class-indieauth-revocation-endpoint.php
rename to includes/rest/class-revocation-controller.php
index 4d27574..e4bcf4c 100644
--- a/includes/class-indieauth-revocation-endpoint.php
+++ b/includes/rest/class-revocation-controller.php
@@ -1,25 +1,40 @@
init_tokens();
}
/**
@@ -27,8 +42,8 @@ public function __construct() {
*
* @return string Endpoint URL.
*/
- public static function get_endpoint() {
- return rest_url( '/indieauth/1.0/revocation' );
+ public function get_endpoint() {
+ return \rest_url( $this->namespace . '/' . $this->rest_base );
}
/**
@@ -37,7 +52,7 @@ public static function get_endpoint() {
* @return array Supported authentication methods.
*/
public function auth_methods_supported() {
- return array_unique( apply_filters( 'indieauth_revocation_auth_methods_supported', array( 'none' ) ) );
+ return array_unique( \apply_filters( 'indieauth_revocation_auth_methods_supported', array( 'none' ) ) );
}
/**
@@ -67,12 +82,12 @@ public function rest_index( $index ) {
* Register the Route.
*/
public function register_routes() {
- register_rest_route(
- 'indieauth/1.0',
- '/revocation',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base,
array(
array(
- 'methods' => WP_REST_Server::CREATABLE,
+ 'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'revoke' ),
'args' => array(
'token' => array(
@@ -91,14 +106,14 @@ public function register_routes() {
/**
* Revocation Endpoint request handler.
*
- * @param WP_REST_Request $request The Request Object.
- * @return WP_REST_Response Response to return to the REST Server.
+ * @param \WP_REST_Request $request The Request Object.
+ * @return \WP_REST_Response Response to return to the REST Server.
*/
public function revoke( $request ) {
$params = $request->get_params();
$this->delete_token( $params['token'], $params['token_type_hint'] );
- return new WP_REST_Response(
- __( 'The Token Provided is No Longer Valid', 'indieauth' ),
+ return new \WP_REST_Response(
+ \__( 'The Token Provided is No Longer Valid', 'indieauth' ),
200
);
}
diff --git a/includes/class-indieauth-ticket-endpoint.php b/includes/rest/class-ticket-controller.php
similarity index 54%
rename from includes/class-indieauth-ticket-endpoint.php
rename to includes/rest/class-ticket-controller.php
index cd8809a..9c5a184 100644
--- a/includes/class-indieauth-ticket-endpoint.php
+++ b/includes/rest/class-ticket-controller.php
@@ -1,37 +1,55 @@
namespace . '/' . $this->rest_base );
}
/**
@@ -45,36 +63,16 @@ public function metadata( $metadata ) {
return $metadata;
}
- /**
- * Output HTTP Link header for ticket endpoint.
- */
- public function http_header() {
- $this->set_http_header( static::get_endpoint(), 'ticket_endpoint' );
- }
-
- /**
- * Output HTML link tag for ticket endpoint.
- */
- public function html_header() {
- $kses = array(
- 'link' => array(
- 'href' => array(),
- 'rel' => array(),
- ),
- );
- echo wp_kses( $this->get_html_header( static::get_endpoint(), 'ticket_endpoint' ), $kses );
- }
-
/**
* Register the Route.
*/
public function register_routes() {
- register_rest_route(
- 'indieauth/1.0',
- '/ticket',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base,
array(
array(
- 'methods' => WP_REST_Server::CREATABLE,
+ 'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'post' ),
'args' => array(
// A random string that can be redeemed for an access token.
@@ -83,19 +81,19 @@ public function register_routes() {
),
// The access token will work at this URL.
'resource' => array(
- 'validate_callback' => 'rest_is_valid_url',
+ 'validate_callback' => 'IndieAuth\rest_is_valid_url',
'sanitize_callback' => 'esc_url_raw',
'required' => true,
),
// The access token is used when acting on behalf of this URL.
'subject' => array(
- 'validate_callback' => 'indieauth_validate_user_identifier',
+ 'validate_callback' => 'IndieAuth\indieauth_validate_user_identifier',
'sanitize_callback' => 'esc_url_raw',
'required' => true,
),
// The server issuer identifier.
'iss' => array(
- 'validate_callback' => 'indieauth_validate_issuer_identifier',
+ 'validate_callback' => 'IndieAuth\indieauth_validate_issuer_identifier',
'sanitize_callback' => 'esc_url_raw',
),
),
@@ -109,21 +107,21 @@ public function register_routes() {
/**
* Handle ticket endpoint POST request.
*
- * @param WP_REST_Request $request The request object.
- * @return WP_REST_Response|WP_OAuth_Response Response object.
+ * @param \WP_REST_Request $request The request object.
+ * @return \WP_REST_Response|OAuth_Response Response object.
*/
public function post( $request ) {
$params = $request->get_params();
- $clean_params = wp_array_slice_assoc( $params, array( 'subject', 'resource', 'iss' ) );
+ $clean_params = \wp_array_slice_assoc( $params, array( 'subject', 'resource', 'iss' ) );
// Fires when a ticket is received with the parameters. Excludes ticket code itself.
- do_action( 'indieauth_ticket_received', $clean_params );
- $client = new IndieAuth_Client();
+ \do_action( 'indieauth_ticket_received', $clean_params );
+ $client = new Client();
$endpoints = false;
if ( array_key_exists( 'subject', $params ) ) {
$user = get_user_by_identifier( $params['subject'] );
- if ( ! $user instanceof WP_User ) {
- return new WP_OAuth_Response( 'invalid_request', __( 'Subject is not a user on this site', 'indieauth' ), 400 );
+ if ( ! $user instanceof \WP_User ) {
+ return new OAuth_Response( 'invalid_request', \__( 'Subject is not a user on this site', 'indieauth' ), 400 );
}
}
if ( array_key_exists( 'iss', $params ) ) {
@@ -135,25 +133,25 @@ public function post( $request ) {
$endpoints = $client->discover_endpoints( $params['resource'] );
}
} else {
- return new WP_OAuth_Response( 'invalid_request', __( 'Missing Parameters', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_request', \__( 'Missing Parameters', 'indieauth' ), 400 );
}
if ( ! $endpoints ) {
- return new WP_OAuth_Response( 'invalid_request', __( 'Unable to Find Endpoints', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_request', \__( 'Unable to Find Endpoints', 'indieauth' ), 400 );
}
if ( is_oauth_error( $endpoints ) ) {
return $endpoints;
}
- if ( ! wp_http_validate_url( $client->meta['token_endpoint'] ) ) {
- return new WP_OAuth_Response( 'invalid_request', __( 'Invalid Token Endpoint URL', 'indieauth' ), 400 );
+ if ( ! \wp_http_validate_url( $client->meta['token_endpoint'] ) ) {
+ return new OAuth_Response( 'invalid_request', \__( 'Invalid Token Endpoint URL', 'indieauth' ), 400 );
}
$return = $this->request_token( $client->meta['token_endpoint'], $params );
if ( is_oauth_error( $return ) ) {
- do_action( 'indieauth_ticket_redemption_failed', $clean_params, $return );
+ \do_action( 'indieauth_ticket_redemption_failed', $clean_params, $return );
return $return;
}
@@ -178,37 +176,37 @@ public function post( $request ) {
}
// Fires when ticket is successfully redeemed, omits token info.
- do_action( 'indieauth_ticket_redeemed', wp_array_slice_assoc( $return, array( 'me', 'expires_in', 'iat', 'expiration', 'resource', 'iss', 'token_endpoint', 'uuid' ) ) );
- return new WP_REST_Response(
+ \do_action( 'indieauth_ticket_redeemed', \wp_array_slice_assoc( $return, array( 'me', 'expires_in', 'iat', 'expiration', 'resource', 'iss', 'token_endpoint', 'uuid' ) ) );
+ return new \WP_REST_Response(
array(
- 'success' => __( 'Your Ticket Has Been Redeemed. Thank you for your trust!', 'indieauth' ),
+ 'success' => \__( 'Your Ticket Has Been Redeemed. Thank you for your trust!', 'indieauth' ),
),
200
);
}
// If nothing works, return an error.
- return new WP_OAuth_Response( 'invalid_request', __( 'Invalid Request', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_request', \__( 'Invalid Request', 'indieauth' ), 400 );
}
/**
* Save token from ticket redemption.
*
* @param array $token Token data.
- * @return true|WP_OAuth_Response True on success, error on failure.
+ * @return true|OAuth_Response True on success, error on failure.
*/
public function save_token( $token ) {
if ( ! array_key_exists( 'me', $token ) ) {
- return new WP_OAuth_Response( 'invalid_request', __( 'Me Property Missing From Response', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_request', \__( 'Me Property Missing From Response', 'indieauth' ), 400 );
}
if ( ! indieauth_validate_user_identifier( $token['me'] ) ) {
- return new WP_OAuth_Response( 'invalid_request', __( 'Invalid Me Property', 'indieauth' ), 400, $token['me'] );
+ return new OAuth_Response( 'invalid_request', \__( 'Invalid Me Property', 'indieauth' ), 400, $token['me'] );
}
$user = get_user_by_identifier( $token['me'] );
- if ( ! $user instanceof WP_User ) {
- return new WP_OAuth_Response( 'unknown', __( 'Unable to Identify User Associated with Me Property', 'indieauth' ), 500, $token['me'] );
+ if ( ! $user instanceof \WP_User ) {
+ return new OAuth_Response( 'unknown', \__( 'Unable to Identify User Associated with Me Property', 'indieauth' ), 500, $token['me'] );
}
$tokens = new External_User_Token( $user->ID );
@@ -222,10 +220,10 @@ public function save_token( $token ) {
*
* @param string $url Token endpoint URL.
* @param array $params Request parameters.
- * @return array|WP_OAuth_Response Token data or error.
+ * @return array|OAuth_Response Token data or error.
*/
public function request_token( $url, $params ) {
- $client = new IndieAuth_Client();
+ $client = new Client();
return $client->remote_post(
$url,
array(
@@ -245,11 +243,11 @@ public function notify( $params ) {
if ( ! $user ) {
return;
}
- $body = __( 'A new ticket was received and successfully redeemed', 'indieauth' ) . "\r\n";
+ $body = \__( 'A new ticket was received and successfully redeemed', 'indieauth' ) . "\r\n";
foreach ( $params as $key => $value ) {
switch ( $key ) {
case 'iat':
- $iat = new DateTime( 'now', wp_timezone() );
+ $iat = new \DateTime( 'now', \wp_timezone() );
$iat->setTimeStamp( $value );
$body .= sprintf( 'Issued at: %s', $iat->format( DATE_W3C ) ) . "\r\n";
break;
@@ -259,9 +257,9 @@ public function notify( $params ) {
$body .= sprintf( '%s: %s', $key, $value ) . "\r\n";
}
}
- wp_mail(
+ \wp_mail(
$user->user_email,
- wp_specialchars_decode( __( 'IndieAuth Ticket Redeemed', 'indieauth' ) ),
+ \wp_specialchars_decode( \__( 'IndieAuth Ticket Redeemed', 'indieauth' ) ),
$body,
''
);
diff --git a/includes/class-indieauth-token-endpoint.php b/includes/rest/class-token-controller.php
similarity index 64%
rename from includes/class-indieauth-token-endpoint.php
rename to includes/rest/class-token-controller.php
index bae9e40..2bcbfb9 100644
--- a/includes/class-indieauth-token-endpoint.php
+++ b/includes/rest/class-token-controller.php
@@ -1,64 +1,61 @@
set_http_header( $this->get_endpoint(), 'token_endpoint' );
- }
+ public function __construct() {
+ $this->init_tokens();
}
/**
- * Output HTML link tag for token endpoint.
+ * Get the token endpoint URL.
+ *
+ * @return string The token endpoint URL.
*/
- public function html_header() {
- $kses = array(
- 'link' => array(
- 'href' => array(),
- 'rel' => array(),
- ),
- );
-
- if ( is_author() || is_front_page() ) {
- echo wp_kses( $this->get_html_header( $this->get_endpoint(), 'token_endpoint' ), $kses );
- }
+ public function get_endpoint() {
+ return \rest_url( $this->namespace . '/' . $this->rest_base );
}
/**
@@ -78,7 +75,7 @@ public function rest_index( $index ) {
* @return array List of supported grant types.
*/
public static function get_grant_types() {
- return array_unique( apply_filters( 'indieauth_grant_types_supported', array( 'authorization_code', 'refresh_token' ) ) );
+ return array_unique( \apply_filters( 'indieauth_grant_types_supported', array( 'authorization_code', 'refresh_token' ) ) );
}
/**
@@ -98,12 +95,12 @@ public function metadata( $metadata ) {
* Register the Route.
*/
public function register_routes() {
- register_rest_route(
- 'indieauth/1.0',
- '/token',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base,
array(
array(
- 'methods' => WP_REST_Server::CREATABLE,
+ 'methods' => \WP_REST_Server::CREATABLE,
'callback' => array( $this, 'post' ),
'args' => array(
'grant_type' => array(),
@@ -111,12 +108,12 @@ public function register_routes() {
'code' => array(),
// The client's URL, which MUST match the client_id used in the authentication request.
'client_id' => array(
- 'validate_callback' => 'indieauth_validate_client_identifier',
+ 'validate_callback' => 'IndieAuth\indieauth_validate_client_identifier',
'sanitize_callback' => 'esc_url_raw',
),
// The client's redirect URL, which MUST match the initial authentication request.
'redirect_uri' => array(
- 'validate_callback' => 'rest_is_valid_url',
+ 'validate_callback' => 'IndieAuth\rest_is_valid_url',
'sanitize_callback' => 'esc_url_raw',
),
// The original plaintext random string generated before starting the authorization request.
@@ -130,12 +127,12 @@ public function register_routes() {
),
)
);
- register_rest_route(
- 'indieauth/1.0',
- '/token',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base,
array(
array(
- 'methods' => WP_REST_Server::READABLE,
+ 'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'get' ),
'args' => array(),
'permission_callback' => '__return_true',
@@ -147,19 +144,19 @@ public function register_routes() {
/**
* Token Endpoint GET Handler.
*
- * @param WP_REST_Request $request The Request Object.
- * @return WP_REST_Response|WP_OAuth_Response Response to return to the REST Server.
+ * @param \WP_REST_Request $request The Request Object.
+ * @return \WP_REST_Response|OAuth_Response Response to return to the REST Server.
*/
public function get( $request ) {
$header = $request->get_header( 'Authorization' );
if ( ! $header && ! empty( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ) {
- $header = wp_unslash( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+ $header = \wp_unslash( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
}
$access_token = $this->get_token_from_bearer_header( $header );
if ( ! $access_token ) {
- return new WP_OAuth_Response(
+ return new OAuth_Response(
'parameter_absent',
- __(
+ \__(
'Bearer Token Not Supplied or Server Misconfigured to Not Pass Token. Run diagnostic script in WordPress Admin
IndieAuth Settings Page',
'indieauth'
@@ -169,27 +166,27 @@ public function get( $request ) {
}
$token = $this->get_token( $access_token );
if ( ! $token ) {
- return new WP_OAuth_Response( 'invalid_token', __( 'Invalid access token', 'indieauth' ), 401 );
+ return new OAuth_Response( 'invalid_token', \__( 'Invalid access token', 'indieauth' ), 401 );
}
$token['active'] = 'true';
- return rest_ensure_response( $token );
+ return \rest_ensure_response( $token );
}
/**
* Token Endpoint POST Handler.
*
- * @param WP_REST_Request $request The Request Object.
- * @return WP_REST_Response|WP_OAuth_Response|string Response to return to the REST Server.
+ * @param \WP_REST_Request $request The Request Object.
+ * @return \WP_REST_Response|OAuth_Response|string Response to return to the REST Server.
*/
public function post( $request ) {
$params = $request->get_params();
// You cannot have both an action and a grant_type parameter.
if ( isset( $params['action'] ) && isset( $params['grant_type'] ) ) {
- return WP_OAuth_Response( 'invalid_request', __( 'Please choose either an action or a grant_type', 'indieauth' ) );
+ return new OAuth_Response( 'invalid_request', \__( 'Please choose either an action or a grant_type', 'indieauth' ) );
}
- $resp = new WP_OAuth_Response( 'invalid_request', __( 'Invalid Request', 'indieauth' ), 400 );
+ $resp = new OAuth_Response( 'invalid_request', \__( 'Invalid Request', 'indieauth' ), 400 );
// Action Handler.
if ( isset( $params['action'] ) ) {
@@ -198,16 +195,16 @@ public function post( $request ) {
case 'revoke':
if ( isset( $params['token'] ) ) {
$this->delete_token( $params['token'] );
- return __( 'The Token Provided is No Longer Valid', 'indieauth' );
+ return \__( 'The Token Provided is No Longer Valid', 'indieauth' );
} else {
- return new WP_OAuth_Response( 'invalid_request', __( 'Revoke is Missing Required Parameter token', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_request', \__( 'Revoke is Missing Required Parameter token', 'indieauth' ), 400 );
}
default:
- $resp = new WP_OAuth_Response( 'unsupported_action', __( 'Unsupported Action', 'indieauth' ), 400 );
+ $resp = new OAuth_Response( 'unsupported_action', \__( 'Unsupported Action', 'indieauth' ), 400 );
}
// Allows for adding custom actions.
- $resp = apply_filters( 'indieauth_token_action_handler', $resp, $params );
+ $resp = \apply_filters( 'indieauth_token_action_handler', $resp, $params );
}
// Grant Type Handler.
@@ -219,10 +216,10 @@ public function post( $request ) {
case 'refresh_token':
return $this->refresh_token( $params );
default:
- $resp = new WP_OAuth_Response( 'unsupported_grant_type', __( 'Unsupported grant_type.', 'indieauth' ), 400 );
+ $resp = new OAuth_Response( 'unsupported_grant_type', \__( 'Unsupported grant_type.', 'indieauth' ), 400 );
}
// Allows for adding custom grant type handling.
- $resp = apply_filters( 'indieauth_token_grant_type_handler', $resp, $params );
+ $resp = \apply_filters( 'indieauth_token_grant_type_handler', $resp, $params );
}
// Everything Failed.
@@ -234,17 +231,17 @@ public function post( $request ) {
* Handle refresh token grant type.
*
* @param array $params Request parameters.
- * @return WP_REST_Response|WP_OAuth_Response Token response or error.
+ * @return \WP_REST_Response|OAuth_Response Token response or error.
*/
public function refresh_token( $params ) {
$diff = array_diff( array( 'refresh_token' ), array_keys( $params ) );
if ( ! empty( $diff ) ) {
- return new WP_OAuth_Response( 'invalid_request', __( 'The request is missing one or more required parameters', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_request', \__( 'The request is missing one or more required parameters', 'indieauth' ), 400 );
}
$refresh = $this->refresh_tokens->get( $params['refresh_token'] );
if ( ! $refresh ) {
- return new WP_OAuth_Response( 'invalid_grant', __( 'Invalid Token', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'Invalid Token', 'indieauth' ), 400 );
}
// Destroy the refresh token.
@@ -257,12 +254,12 @@ public function refresh_token( $params ) {
* Handle authorization code grant type.
*
* @param array $params Request parameters.
- * @return WP_REST_Response|WP_OAuth_Response Token response or error.
+ * @return \WP_REST_Response|OAuth_Response Token response or error.
*/
public function authorization_code( $params ) {
$diff = array_diff( array( 'code', 'client_id', 'redirect_uri' ), array_keys( $params ) );
if ( ! empty( $diff ) ) {
- return new WP_OAuth_Response( 'invalid_request', __( 'The request is missing one or more required parameters', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_request', \__( 'The request is missing one or more required parameters', 'indieauth' ), 400 );
}
$args = array_filter(
array(
@@ -286,7 +283,7 @@ public function authorization_code( $params ) {
* Generate token response from authorization data.
*
* @param array $response Authorization response data.
- * @return WP_REST_Response|WP_OAuth_Response Token response or error.
+ * @return \WP_REST_Response|OAuth_Response Token response or error.
*/
public function generate_token_response( $response ) {
$return = array(
@@ -305,8 +302,8 @@ public function generate_token_response( $response ) {
// Issue a token.
if ( ! empty( $scopes ) ) {
- $client = IndieAuth_Client_Taxonomy::add_client( $response['client_id'] );
- if ( is_wp_error( $client ) ) {
+ $client = Client_Taxonomy::add_client( $response['client_id'] );
+ if ( \is_wp_error( $client ) ) {
$client = array( 'id' => $client->get_error_message() );
}
@@ -316,13 +313,13 @@ public function generate_token_response( $response ) {
// Add UUID for reference. In case you'd like to build infrastructure for additional properties and store them in an alternate location.
// As of 4.1.0, the uuid is passed from the authorization code to the access token and refresh token. But if not, it is added here.
// This idea came from the core application password implementation.
- $return['uuid'] = wp_generate_uuid4();
+ $return['uuid'] = \wp_generate_uuid4();
} else {
$return['uuid'] = $response['uuid'];
}
$return['scope'] = $response['scope'];
- $return['issued_by'] = rest_url( 'indieauth/1.0/token' );
+ $return['issued_by'] = \rest_url( 'indieauth/1.0/token' );
$return['client_id'] = $response['client_id'];
if ( array_key_exists( 'id', $client ) ) {
$return['client_uid'] = $client['id'];
@@ -330,7 +327,7 @@ public function generate_token_response( $response ) {
$return['iat'] = time();
- $expires = (int) get_option( 'indieauth_expires_in' );
+ $expires = (int) \get_option( 'indieauth_expires_in' );
$return = array_filter( $return );
@@ -346,8 +343,8 @@ public function generate_token_response( $response ) {
if ( $return ) {
// Return only the standard keys in the response.
- return new WP_REST_Response(
- wp_array_slice_assoc(
+ return new \WP_REST_Response(
+ \wp_array_slice_assoc(
$return,
array(
'access_token',
@@ -366,29 +363,29 @@ public function generate_token_response( $response ) {
)
);
}
- return new WP_OAuth_Response( 'server_error', __( 'There was an error in response.', 'indieauth' ), 500 );
+ return new OAuth_Response( 'server_error', \__( 'There was an error in response.', 'indieauth' ), 500 );
}
/**
* Verify local authorization code.
*
* @param array $args Arguments including code, redirect_uri, client_id, code_verifier.
- * @return array|WP_OAuth_Response Authorization data or error.
+ * @return array|OAuth_Response Authorization data or error.
*/
public function verify_local_authorization_code( $args ) {
$codes = new Token_User( '_indieauth_code_' );
$return = $codes->get( $args['code'] );
if ( ! $return ) {
- return new WP_OAuth_Response( 'invalid_code', __( 'Invalid authorization code', 'indieauth' ), 401 );
+ return new OAuth_Response( 'invalid_code', \__( 'Invalid authorization code', 'indieauth' ), 401 );
}
if ( isset( $return['code_challenge'] ) ) {
if ( ! isset( $args['code_verifier'] ) ) {
$codes->destroy( $args['code'] );
- return new WP_OAuth_Response( 'invalid_grant', __( 'Failed PKCE Validation', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'Failed PKCE Validation', 'indieauth' ), 400 );
}
if ( ! pkce_verifier( $return['code_challenge'], $args['code_verifier'], $return['code_challenge_method'] ) ) {
$codes->destroy( $args['code'] );
- return new WP_OAuth_Response( 'invalid_grant', __( 'Failed PKCE Validation', 'indieauth' ), 400 );
+ return new OAuth_Response( 'invalid_grant', \__( 'Failed PKCE Validation', 'indieauth' ), 400 );
}
unset( $return['code_challenge'] );
unset( $return['code_challenge_method'] );
diff --git a/includes/class-indieauth-userinfo-endpoint.php b/includes/rest/class-userinfo-controller.php
similarity index 61%
rename from includes/class-indieauth-userinfo-endpoint.php
rename to includes/rest/class-userinfo-controller.php
index 6d49ee7..a1f08fe 100644
--- a/includes/class-indieauth-userinfo-endpoint.php
+++ b/includes/rest/class-userinfo-controller.php
@@ -1,25 +1,43 @@
init_tokens();
}
/**
@@ -27,8 +45,8 @@ public function __construct() {
*
* @return string Endpoint URL.
*/
- public static function get_endpoint() {
- return rest_url( '/indieauth/1.0/userinfo' );
+ public function get_endpoint() {
+ return \rest_url( $this->namespace . '/' . $this->rest_base );
}
/**
@@ -57,12 +75,12 @@ public function rest_index( $index ) {
* Register the Route.
*/
public function register_routes() {
- register_rest_route(
- 'indieauth/1.0',
- '/userinfo',
+ \register_rest_route(
+ $this->namespace,
+ '/' . $this->rest_base,
array(
array(
- 'methods' => WP_REST_Server::READABLE,
+ 'methods' => \WP_REST_Server::READABLE,
'callback' => array( $this, 'userinfo' ),
'args' => array(),
'permission_callback' => '__return_true',
@@ -74,19 +92,19 @@ public function register_routes() {
/**
* User Info Endpoint request handler.
*
- * @param WP_REST_Request $request The Request Object.
- * @return WP_REST_Response|WP_OAuth_Response Response to return to the REST Server.
+ * @param \WP_REST_Request $request The Request Object.
+ * @return \WP_REST_Response|OAuth_Response Response to return to the REST Server.
*/
public function userinfo( $request ) {
$header = $request->get_header( 'Authorization' );
if ( ! $header && ! empty( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ) ) {
- $header = wp_unslash( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+ $header = \wp_unslash( $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
}
$access_token = $this->get_token_from_bearer_header( $header );
if ( ! $access_token ) {
- return new WP_OAuth_Response(
+ return new OAuth_Response(
'parameter_absent',
- __(
+ \__(
'Bearer Token Not Supplied or Server Misconfigured to Not Pass Token. Run diagnostic script in WordPress Admin
IndieAuth Settings Page',
'indieauth'
@@ -96,13 +114,13 @@ public function userinfo( $request ) {
}
$token = $this->get_token( $access_token );
if ( ! $token ) {
- return new WP_OAuth_Response( 'invalid_token', __( 'Invalid access token', 'indieauth' ), 401 );
+ return new OAuth_Response( 'invalid_token', \__( 'Invalid access token', 'indieauth' ), 401 );
}
$scopes = explode( ' ', $token['scope'] );
if ( ! in_array( 'profile', $scopes, true ) ) {
- return new WP_OAuth_Response(
+ return new OAuth_Response(
'insufficient_scope',
- __(
+ \__(
'Bearer Token does not have profile scope',
'indieauth'
),
diff --git a/includes/class-indieauth-endpoint.php b/includes/rest/trait-token-management.php
similarity index 80%
rename from includes/class-indieauth-endpoint.php
rename to includes/rest/trait-token-management.php
index d0d6051..a5f958e 100644
--- a/includes/class-indieauth-endpoint.php
+++ b/includes/rest/trait-token-management.php
@@ -1,16 +1,21 @@
tokens = new Token_User( '_indieauth_token_' );
$this->refresh_tokens = new Token_User( '_indieauth_refresh_' );
}
- /**
- * Outputs a marked up Http link header.
- *
- * @param string $url URL for the link.
- * @param string $rel Rel property for the link.
- * @param bool $replace Passes the value of replace through to the header PHP.
- */
- public static function set_http_header( $url, $rel, $replace = false ) {
- header( sprintf( 'Link: <%s>; rel="%s"', $url, $rel ), $replace );
- }
-
- /**
- * Returns a marked up HTML link header.
- *
- * @param string $url URL for the link.
- * @param string $rel Rel property for the link.
- * @return string Marked up HTML link to add to head.
- */
- public static function get_html_header( $url, $rel ) {
- return sprintf( ' ' . PHP_EOL, $rel, $url );
- }
-
/**
* Extracts the token from the given authorization header.
*
@@ -134,7 +117,7 @@ public function set_token( $token, $expiration = null, $user_id = null ) {
}
if ( ! $user_id ) {
$user = get_user_by_identifier( $token['me'] );
- if ( $user instanceof WP_User ) {
+ if ( $user instanceof \WP_User ) {
$user_id = $user->ID;
} else {
return false;
diff --git a/includes/class-indieauth-scope.php b/includes/scope/class-scope.php
similarity index 93%
rename from includes/class-indieauth-scope.php
rename to includes/scope/class-scope.php
index f6216cb..f1b50d4 100644
--- a/includes/class-indieauth-scope.php
+++ b/includes/scope/class-scope.php
@@ -5,12 +5,14 @@
* @package IndieAuth
*/
+namespace IndieAuth\Scope;
+
/**
* Class used to define a scope.
*
* @since 1.0.0
*/
-class IndieAuth_Scope {
+class Scope {
/**
* Name of the Scope.
@@ -83,7 +85,7 @@ public function has_cap( $cap ) {
* @param string $cap Capability name.
* @param string $name Scope name.
*/
- $capabilities = apply_filters( 'scope_has_cap', $this->capabilities, $cap, $this->name );
+ $capabilities = \apply_filters( 'scope_has_cap', $this->capabilities, $cap, $this->name );
return in_array( $cap, $capabilities, true );
}
}
diff --git a/includes/class-external-token-page.php b/includes/ticket/class-external-token-page.php
similarity index 63%
rename from includes/class-external-token-page.php
rename to includes/ticket/class-external-token-page.php
index 9b92738..c1f7d2d 100644
--- a/includes/class-external-token-page.php
+++ b/includes/ticket/class-external-token-page.php
@@ -5,6 +5,11 @@
* @package IndieAuth
*/
+namespace IndieAuth\Ticket;
+
+use IndieAuth\IndieAuth;
+use IndieAuth\WP_Admin\External_Token_List_Table;
+
/**
* Generates page for external token UI.
*
@@ -17,8 +22,8 @@ class External_Token_Page {
* @access public
*/
public function __construct() {
- add_action( 'admin_init', array( $this, 'admin_init' ) );
- add_action( 'admin_menu', array( $this, 'admin_menu' ), 11 );
+ \add_action( 'admin_init', array( $this, 'admin_init' ) );
+ \add_action( 'admin_menu', array( $this, 'admin_menu' ), 11 );
}
/**
@@ -35,7 +40,7 @@ public function admin_init() {
* @access public
*/
public function admin_menu() {
- add_users_page( __( 'Manage External Tokens', 'indieauth' ), __( 'Manage External Tokens', 'indieauth' ), 'read', 'indieauth_external_token', array( $this, 'options_form' ) );
+ \add_users_page( \__( 'Manage External Tokens', 'indieauth' ), \__( 'Manage External Tokens', 'indieauth' ), 'read', 'indieauth_external_token', array( $this, 'options_form' ) );
}
/**
@@ -53,10 +58,10 @@ public function options_callback() {
*/
public function options_form() {
// Check to see if the cleanup function is scheduled.
- IndieAuth_Plugin::schedule();
+ IndieAuth::schedule();
- $token_table = new External_Token_Table();
- echo '' . esc_html__( 'Manage External Tokens', 'indieauth' ) . ' ';
+ $token_table = new External_Token_List_Table();
+ echo '
' . \esc_html__( 'Manage External Tokens', 'indieauth' ) . ' ';
echo '