plans = $plans; $this->service = $service; $this->services = $services; $this->import = $import; $this->settings = $settings; } /** * Registers the standard routes and the import route. * * @since 0.1.0 * * @return void */ public function register_routes() { parent::register_routes(); register_rest_route( $this->namespace, '/' . $this->rest_base . '/import', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'import' ), 'permission_callback' => Permissions::require_capability( $this->capability() ), ) ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P\\d+)/change', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'change_plan' ), 'permission_callback' => Permissions::require_capability( Capabilities::MANAGE_INVOICES ), ) ); } /** * Upgrades or downgrades a hosting record, with an optional prorated adjustment. * * @since 0.1.0 * * @param WP_REST_Request $request Request: `product_id`, `billing_cycle`, `recurring_amount`, `adjustment`. * @return WP_REST_Response|WP_Error */ public function change_plan( $request ) { $result = $this->plans->change( (int) $request['id'], $this->request_body( $request ), Date::today_gmt() ); if ( is_wp_error( $result ) ) { return $result; } return rest_ensure_response( array( 'service' => $this->present( $result['service'] ), 'adjustment' => $result['adjustment'], ) ); } /** * Capability that protects every route. * * @since 0.1.0 * * @return string */ protected function capability(): string { return Capabilities::MANAGE_ORDERS; } /** * Arguments of the list route. * * @since 0.1.0 * * @return array> */ protected function collection_args(): array { return array_merge( $this->list_params( array_keys( ServiceRepository::ORDERBY ), 'id' ), array( 'status' => array( 'type' => 'string', 'default' => '', 'enum' => array_merge( array( '' ), ServiceStatus::all() ), 'validate_callback' => 'rest_validate_request_arg', ), 'customer_id' => array( 'type' => 'integer', 'default' => 0, 'sanitize_callback' => 'absint', ), 'due_within' => array( 'type' => 'integer', 'default' => 0, 'minimum' => 0, 'maximum' => 3650, 'sanitize_callback' => 'absint', ), ) ); } /** * Lists hosting records. `due_within` limits the list to records due in that many days. * * @since 0.1.0 * * @param WP_REST_Request $request Request. * @return array{items: array>, total: int} */ protected function query_items( WP_REST_Request $request ): array { $due_within = (int) $request['due_within']; return $this->services->query( array( 'search' => $request['search'], 'status' => $request['status'], 'customer_id' => $request['customer_id'], 'due_before' => $due_within > 0 ? Date::add_days( Date::today_gmt(), $due_within ) : '', 'orderby' => $request['orderby'], 'order' => $request['order'], 'page' => $request['page'], 'per_page' => $request['per_page'], ) ); } /** * Lists hosting records and reports the number per status in a header. * * @since 0.1.0 * * @param WP_REST_Request $request Request. * @return WP_REST_Response */ public function get_items( $request ) { $response = parent::get_items( $request ); $response->header( 'X-HostKhata-Status-Counts', wp_json_encode( $this->services->status_counts() ) ); return $response; } /** * Finds one hosting record. * * @since 0.1.0 * * @param int $id Item id. * @return array|null */ protected function find_item( int $id ): ?array { return $this->services->find( $id ); } /** * Creates a hosting record. * * @since 0.1.0 * * @param array $body Request body. * @return array|WP_Error */ protected function create_resource( array $body ) { return $this->service->create( $body ); } /** * Updates a hosting record. * * @since 0.1.0 * * @param int $id Item id. * @param array $body Request body. * @return array|WP_Error */ protected function update_resource( int $id, array $body ) { return $this->service->update( $id, $body ); } /** * Deletes a hosting record. * * @since 0.1.0 * * @param int $id Item id. * @return true|WP_Error */ protected function delete_resource( int $id ) { return $this->service->delete( $id ); } /** * Message for a record that does not exist. * * @since 0.1.0 * * @return string */ protected function not_found_message(): string { return __( 'Hosting record not found.', 'hostkhata' ); } /** * Imports hosting records from rows. * * @since 0.1.0 * * @param WP_REST_Request $request Request: `rows` and `dry_run`. * @return WP_REST_Response|WP_Error */ public function import( $request ) { $body = $this->request_body( $request ); $result = $this->import->import_services( isset( $body['rows'] ) && is_array( $body['rows'] ) ? $body['rows'] : array(), ! empty( $body['dry_run'] ) ); return is_wp_error( $result ) ? $result : rest_ensure_response( $result ); } /** * Shapes a hosting record for the response. * * @since 0.1.0 * * @param array $item Item from the repository. * @return array */ protected function present( array $item ): array { return array( 'id' => $item['id'], 'customer_id' => $item['customer_id'], 'customer_name' => $item['customer_name'], 'customer_email' => $item['customer_email'], 'order_id' => $item['order_id'], 'product_id' => $item['product_id'], 'product_name' => $item['product_name'], 'status' => $item['status'], 'domain' => $item['domain'], 'username' => $item['username'], 'server_label' => $item['server_label'], 'server_ip' => $item['server_ip'], 'panel_url' => $item['panel_url'], 'billing_cycle' => $item['billing_cycle'], 'recurring_amount' => $item['recurring_amount'], 'recurring_formatted' => $this->settings->format_money( $item['recurring_amount'] ), 'start_date' => $item['start_date'], 'next_due_date' => $item['next_due_date'], 'end_date' => $item['end_date'], 'notes' => $item['notes'], ); } }