From 19d5fefa4e85290ad4172fb24e5c11068a42c554 Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Wed, 29 May 2019 18:57:32 +0100 Subject: [PATCH 1/2] Add API framework --- library/Falcon.php | 2 + library/Falcon/API.php | 129 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 library/Falcon/API.php diff --git a/library/Falcon.php b/library/Falcon.php index c2f8476..65a2641 100755 --- a/library/Falcon.php +++ b/library/Falcon.php @@ -9,6 +9,8 @@ public static function bootstrap() { // Kill the defaults remove_action( 'bbp_new_reply', 'bbp_notify_subscribers', 11 ); + add_action( 'rest_api_init', [ 'Falcon_API', 'bootstrap' ] ); + if (is_admin()) { Falcon_Admin::bootstrap(); } diff --git a/library/Falcon/API.php b/library/Falcon/API.php new file mode 100644 index 0000000..e64c8af --- /dev/null +++ b/library/Falcon/API.php @@ -0,0 +1,129 @@ + [ get_called_class(), 'get_pref_field' ], + 'update_callback' => [ get_called_class(), 'update_pref_field' ], + 'schema' => static::get_pref_schema(), + ] ); + } + + /** + * Get the preferences field value. + * + * Calls out to the enabled connectors. + * + * @param array $data Full response data. + * @return array Data for the field. + */ + public static function get_pref_field( $data ) { + $user = get_user_by( 'id', $data['id'] ); + $field_data = []; + foreach ( Falcon::get_connectors() as $type => $connector ) { + /** + * Filter preference field value. + * + * Connect to this in your connector to make the data available + * via the REST API. + * + * @param mixed $connector_data Data for your connector. Null to skip in the API. + * @param WP_User $user User to get data for. + */ + $connector_data = apply_filters( "falcon.api.get_pref_field.$type", null, $user ); + if ( $connector_data === null ) { + continue; + } + + $field_data[ $type ] = $connector_data; + } + return $field_data; + } + + /** + * Update the preferences field value. + * + * Calls out to the enabled connectors. + * + * @param array $value Value passed by the user (validated by the schema). + * @param WP_User $user User being updated. + * @return boolean|WP_Error True if field was updated, error otherwise. + */ + public static function update_pref_field( $value, WP_User $user ) { + if ( empty( $value ) ) { + return true; + } + + $connectors = Falcon::get_connectors(); + foreach ( $value as $type => $type_options ) { + if ( empty( $connectors[ $type ] ) ) { + return new WP_Error( + 'falcon.api.update_pref_field.invalid_type', + __( 'Attempted to set preference for invalid connector', 'falcon' ), + compact( 'type' ) + ); + } + + /** + * Filter the result of updating the field. + * + * Connect to this in your connector to make the data updatable via + * the REST API. + * + * @param mixed $result True if field was updated, WP_Error if cannot update, null if unhandled. + */ + $result = apply_filters( "falcon.api.update_pref_field.$type", null, $type_options, $user ); + if ( $result === null ) { + return new WP_Error( + 'falcon.api.update_pref_field.unhandled_update', + __( 'Connector does not support updating via the API', 'falcon' ), + compact( 'type' ) + ); + } + if ( is_wp_error( $result ) ) { + return $result; + } + } + + return true; + } + + /** + * Get the schema for the preferences field. + * + * Calls out to the enabled connectors. + * + * @return array Schema for the preferences field. + */ + public static function get_pref_schema() { + $schema = [ + 'description' => __( 'Falcon notification preferences', 'falcon' ), + 'type' => 'object', + 'properties' => [], + ]; + + foreach ( Falcon::get_connectors() as $type => $connector ) { + /** + * Filter preference field schema. + * + * Connect to this in your connector to make the data available + * via the REST API. + * + * @param mixed $connector_schema Schema for your connector. Null to skip in the API. + */ + $connector_schema = apply_filters( "falcon.api.get_pref_schema.$type", null ); + if ( $connector_schema === null ) { + continue; + } + + $schema['properties'][ $type ] = $connector_schema; + } + + return $schema; + } +} From 38f93a2cb2b5f5cc5ca0016f3fd4184ab6d11365 Mon Sep 17 00:00:00 2001 From: Ryan McCue Date: Wed, 29 May 2019 18:57:48 +0100 Subject: [PATCH 2/2] Add API support to the default handlers --- library/Falcon/Connector.php | 90 ++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/library/Falcon/Connector.php b/library/Falcon/Connector.php index cc5209c..55c929d 100644 --- a/library/Falcon/Connector.php +++ b/library/Falcon/Connector.php @@ -189,12 +189,102 @@ public function save_profile_settings( $user_id, $args = array(), $sites = null * Call this from __construct if using the built-in settings UI. */ protected function register_settings_hooks() { + $id = $this->get_id(); + add_filter( "falcon.api.get_pref_field.$id", array( $this, 'get_pref_field' ), 10, 2 ); + add_filter( "falcon.api.get_pref_schema.$id", array( $this, 'get_pref_schema' ) ); + add_filter( "falcon.api.update_pref_field.$id", array( $this, 'update_pref_field' ), 10, 3 ); add_action( 'falcon.manager.profile_fields', array( $this, 'output_settings' ) ); add_action( 'falcon.manager.save_profile_fields', array( $this, 'save_profile_settings' ), 10, 2 ); add_action( 'falcon.manager.network_profile_fields', array( $this, 'network_notification_settings' ), 10, 2 ); add_action( 'falcon.manager.save_network_profile_fields', array( $this, 'save_profile_settings' ), 10, 3 ); } + /** + * Get preference field value for the connector. + * + * Makes the data available via the REST API. + * + * @param mixed $value Existing value for the connector + * @param WP_User $user User to get data for. + * @return array Current settings for the user. + */ + public function get_pref_field( $value, WP_User $user ) { + return $this->get_settings_for_user( $user->ID ); + } + + /** + * Get preference field schema for the connector. + * + * @param mixed $connector_schema Existing schema for the connector + * @return array Schema for the conneector. + */ + public function get_pref_schema() { + $schema = [ + 'type' => 'object', + 'properties' => [], + ]; + $fields = $this->get_settings_fields(); + foreach ( $this->get_available_settings() as $key => $values ) { + $field = $fields[ $key ]; + $schema['properties'][ $key ] = [ + 'type' => 'string', + 'description' => $field['label'], + 'default' => $field['default'], + 'enum' => array_keys( $values ), + 'enumLabels' => $values, + ]; + } + return $schema; + } + + public function update_pref_field( $result, $data, WP_User $user ) { + $available = $this->get_available_settings(); + $site = get_current_blog_id(); + + foreach ( $data as $type => $value ) { + if ( empty( $available[ $type ] ) ) { + return new WP_Error( + 'falcon.api.update_pref_field.invalid_type', + __( 'Attempted to update invalid type', 'falcon' ), + compact( 'type' ) + ); + } + + $options = $available[ $type ]; + $key = $this->key_for_setting( 'notifications.' . $type, $site ); + + // Check the value is valid + $options = array_keys( $options ); + if ( ! in_array( $value, $options ) ) { + // This should be handled by the schema validation, but just + // in case... + return new WP_Error( + 'falcon.api.update_pref_field.invalid_value', + __( 'Invalid value for type', 'falcon' ), + compact( 'type', 'value' ) + ); + } + + // Is this the current value? + $current = get_user_meta( $user->ID, wp_slash( $key ), true ); + if ( $current === $value ) { + // Skip attempting to update. + continue; + } + + // Actually set it! + if ( ! update_user_meta( $user->ID, wp_slash( $key ), wp_slash( $value ) ) ) { + return new WP_Error( + 'falcon.api.update_pref_field.could_not_update', + __( 'Could not update preference', 'falcon' ), + compact( 'type', 'value' ) + ); + } + } + + return true; + } + /** * Output the settings fields. *