namespace, '/' . $this->rest_base, array( array( 'methods' => \WP_REST_Server::READABLE, 'callback' => array( $this, 'get_items' ), 'permission_callback' => array( $this, 'check_permission' ), ), 'schema' => array( $this, 'get_public_item_schema' ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-z0-9]+(?:-[a-z0-9]+)*)', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array( $this, 'update_item' ), 'permission_callback' => array( $this, 'check_permission' ), 'args' => array( 'id' => array( 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_key', ), 'enabled' => array( 'type' => 'boolean', 'required' => true, ), ), ), ) ); $this->register_option_route(); } /** * Register the route for a module's own options. * * @return void */ private function register_option_route() { register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P[a-z0-9]+(?:-[a-z0-9]+)*)/options', array( array( 'methods' => \WP_REST_Server::EDITABLE, 'callback' => array( $this, 'update_option' ), 'permission_callback' => array( $this, 'check_permission' ), 'args' => array( 'id' => array( 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_key', ), 'key' => array( 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_key', ), 'value' => array( 'type' => 'boolean', 'required' => true, ), ), ), ) ); } /** * Change one of a module's options. * * Only keys the module declares are accepted, so the route cannot be used * to write any other setting the module keeps. * * @param \WP_REST_Request $request Request. * @return \WP_REST_Response|\WP_Error */ public function update_option( $request ) { $module = pagecore()->modules()->get( $request->get_param( 'id' ) ); $key = (string) $request->get_param( 'key' ); if ( ! $module || ! $module->has_option( $key ) ) { return new \WP_Error( 'pagecore_unknown_option', __( 'That module has no such option.', 'pagecore' ), array( 'status' => 404 ) ); } $module->set_setting( $key, (bool) $request->get_param( 'value' ) ); return $this->ok( array( 'module' => $module->to_array() ) ); } /** * List every module and its state. * * @param \WP_REST_Request $request Request. * @return \WP_REST_Response */ public function get_items( $request ) { unset( $request ); return $this->ok( array( 'modules' => pagecore()->modules()->to_array(), ) ); } /** * Switch one module on or off. * * @param \WP_REST_Request $request Request. * @return \WP_REST_Response|\WP_Error */ public function update_item( $request ) { $id = $request->get_param( 'id' ); $enabled = (bool) $request->get_param( 'enabled' ); $result = pagecore()->modules()->set_enabled( $id, $enabled ); if ( is_wp_error( $result ) ) { return $result; } $module = pagecore()->modules()->get( $id ); Logger::info( sprintf( 'Module %1$s switched %2$s.', $id, $enabled ? 'on' : 'off' ) ); return $this->ok( array( 'module' => $module ? $module->to_array() : null, ) ); } /** * Schema for one module. * * @return array */ public function get_item_schema() { if ( $this->schema ) { return $this->add_additional_fields_schema( $this->schema ); } $this->schema = array( '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'pagecore-module', 'type' => 'object', 'properties' => array( 'id' => array( 'type' => 'string', 'description' => __( 'Stable module identifier.', 'pagecore' ), 'readonly' => true, ), 'label' => array( 'type' => 'string', 'description' => __( 'Name shown in the admin.', 'pagecore' ), 'readonly' => true, ), 'description' => array( 'type' => 'string', 'description' => __( 'What the module does.', 'pagecore' ), 'readonly' => true, ), 'enabled' => array( 'type' => 'boolean', 'description' => __( 'Whether the module runs on this site.', 'pagecore' ), ), 'available' => array( 'type' => 'boolean', 'description' => __( 'Whether this environment can run the module.', 'pagecore' ), 'readonly' => true, ), 'unavailableReason' => array( 'type' => 'string', 'description' => __( 'Why the module cannot run here.', 'pagecore' ), 'readonly' => true, ), 'hasScreen' => array( 'type' => 'boolean', 'description' => __( 'Whether the module adds a submenu screen.', 'pagecore' ), 'readonly' => true, ), 'screenUrl' => array( 'type' => 'string', 'format' => 'uri', 'description' => __( 'Address of the module screen.', 'pagecore' ), 'readonly' => true, ), 'options' => array( 'type' => 'array', 'description' => __( 'Site-wide switches the module offers.', 'pagecore' ), 'readonly' => true, ), ), ); return $this->add_additional_fields_schema( $this->schema ); } }