is_array( $data ) ) { throw new Exception( '$data_callback must return an array.' ); } } catch ( Throwable $e ) { $this->throw_exception( $e ); continue; } $registered_data[ $namespace ] = $data; } return (object) $registered_data; } /** * Returns the registered endpoint schema * * @param string $endpoint A valid identifier. * @param array $passed_args Passed arguments from the Schema class. * @return array Returns an array with registered schema data. * @throws Exception If a registered callback throws an error, or silently logs it. */ public function get_endpoint_schema( $endpoint, array $passed_args = [] ) { $registered_schema = []; if ( ! isset( $this->extend_data[ $endpoint ] ) ) { return (object) $registered_schema; } foreach ( $this->extend_data[ $endpoint ] as $namespace => $callbacks ) { $schema = []; try { $schema = $callbacks['schema_callback']( ...$passed_args ); if ( ! is_array( $schema ) ) { throw new Exception( '$schema_callback must return an array.' ); } } catch ( Throwable $e ) { $this->throw_exception( $e ); continue; } $schema = $this->format_extensions_properties( $namespace, $schema, $callbacks['data_type'] ); $registered_schema[ $namespace ] = $schema; } return (object) $registered_schema; } /** * Registers and validates payment requirements callbacks. * * @param array $args { * Array of registration data. * * @type callable $data_callback Callback executed to add payment requirements data. * } * * @throws Exception On failure to register. * @return boolean True on success. */ public function register_payment_requirements( $args ) { if ( ! is_callable( $args['data_callback'] ) ) { $this->throw_exception( '$data_callback must be a callable function.' ); } $this->payment_requirements[] = $args['data_callback']; return true; } /** * Returns the additional payment requirements. * * @param array $initial_requirements list of requirements that should be added to the collected requirements. * @return array Returns a list of payment requirements. * @throws Exception If a registered callback throws an error, or silently logs it. */ public function get_payment_requirements( array $initial_requirements = [ 'products' ] ) { $requirements = $initial_requirements; if ( empty( $this->payment_requirements ) ) { return $initial_requirements; } foreach ( $this->payment_requirements as $callback ) { $data = []; try { $data = $callback(); if ( ! is_array( $data ) ) { throw new Exception( '$data_callback must return an array.' ); } } catch ( Throwable $e ) { $this->throw_exception( $e ); continue; } $requirements = array_merge( $requirements, $data ); } return array_unique( $requirements ); } /** * Throws error and/or silently logs it. * * @param string|Throwable $exception_or_error Error message or Exception. * @throws Exception An error to throw if we have debug enabled and user is admin. */ private function throw_exception( $exception_or_error ) { if ( is_string( $exception_or_error ) ) { $exception = new Exception( $exception_or_error ); } else { $exception = $exception_or_error; } // Always log an error. wc_caught_exception( $exception ); if ( defined( 'WP_DEBUG' ) && WP_DEBUG && current_user_can( 'manage_woocommerce' ) ) { throw $exception; } } /** * Format schema for an extension. * * @param string $namespace Error message or Exception. * @param array $schema An error to throw if we have debug enabled and user is admin. * @param string $data_type How should data be shaped. * * @return array Formatted schema. */ private function format_extensions_properties( $namespace, $schema, $data_type ) { if ( ARRAY_N === $data_type ) { return [ /* translators: %s: extension namespace */ 'description' => sprintf( __( 'Extension data registered by %s', 'woocommerce' ), $namespace ), 'type' => [ 'array', 'null' ], 'context' => [ 'view', 'edit' ], 'readonly' => true, 'items' => $schema, ]; } return [ /* translators: %s: extension namespace */ 'description' => sprintf( __( 'Extension data registered by %s', 'woocommerce' ), $namespace ), 'type' => [ 'object', 'null' ], 'context' => [ 'view', 'edit' ], 'readonly' => true, 'properties' => $schema, ]; } }