k bindings source names must contain a namespace prefix. Example: my-plugin/my-custom-source' ), '6.5.0' ); return false; } if ( $this->is_registered( $source_name ) ) { _doing_it_wrong( __METHOD__, /* translators: %s: Block bindings source name. */ sprintf( __( 'Block bindings source "%s" already registered.' ), $source_name ), '6.5.0' ); return false; } // Validates that the source properties contain the label. if ( ! isset( $source_properties['label'] ) ) { _doing_it_wrong( __METHOD__, __( 'The $source_properties must contain a "label".' ), '6.5.0' ); return false; } // Validates that the source properties contain the get_value_callback. if ( ! isset( $source_properties['get_value_callback'] ) ) { _doing_it_wrong( __METHOD__, __( 'The $source_properties must contain a "get_value_callback".' ), '6.5.0' ); return false; } // Validates that the get_value_callback is a valid callback. if ( ! is_callable( $source_properties['get_value_callback'] ) ) { _doing_it_wrong( __METHOD__, __( 'The "get_value_callback" parameter must be a valid callback.' ), '6.5.0' ); return false; } // Validates that the uses_context parameter is an array. if ( isset( $source_properties['uses_context'] ) && ! is_array( $source_properties['uses_context'] ) ) { _doing_it_wrong( __METHOD__, __( 'The "uses_context" parameter must be an array.' ), '6.5.0' ); return false; } if ( ! empty( array_diff( array_keys( $source_properties ), $this->allowed_source_properties ) ) ) { _doing_it_wrong( __METHOD__, __( 'The $source_properties array contains invalid properties.' ), '6.5.0' ); return false; } $source = new WP_Block_Bindings_Source( $source_name, $source_properties ); $this->sources[ $source_name ] = $source; return $source; } /** * Unregisters a block bindings source. * * @since 6.5.0 * * @param string $source_name Block bindings source name including namespace. * @return WP_Block_Bindings_Source|false The unregistered block bindings source on success and `false` otherwise. */ public function unregister( string $source_name ) { if ( ! $this->is_registered( $source_name ) ) { _doing_it_wrong( __METHOD__, /* translators: %s: Block bindings source name. */ sprintf( __( 'Block binding "%s" not found.' ), $source_name ), '6.5.0' ); return false; } $unregistered_source = $this->sources[ $source_name ]; unset( $this->sources[ $source_name ] ); return $unregistered_source; } /** * Retrieves the list of all registered block bindings sources. * * @since 6.5.0 * * @return WP_Block_Bindings_Source[] The array of registered sources. */ public function get_all_registered() { return $this->sources; } /** * Retrieves a registered block bindings source. * * @since 6.5.0 * * @param string $source_name The name of the source. * @return WP_Block_Bindings_Source|null The registered block bindings source, or `null` if it is not registered. */ public function get_registered( string $source_name ) { if ( ! $this->is_registered( $source_name ) ) { return null; } return $this->sources[ $source_name ]; } /** * Checks if a block bindings source is registered. * * @since 6.5.0 * * @param string $source_name The name of the source. * @return bool `true` if the block bindings source is registered, `false` otherwise. */ public function is_registered( $source_name ) { return isset( $this->sources[ $source_name ] ); } /** * Wakeup magic method. * * @since 6.5.0 */ public function __wakeup() { if ( ! $this->sources ) { return; } if ( ! is_array( $this->sources ) ) { throw new UnexpectedValueException(); } foreach ( $this->sources as $value ) { if ( ! $value instanceof WP_Block_Bindings_Source ) { throw new UnexpectedValueException(); } } } /** * Utility method to retrieve the main instance of the class. * * The instance will be created if it does not exist yet. * * @since 6.5.0 * * @return WP_Block_Bindings_Registry The main instance. */ public static function get_instance() { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } } s. If the given URL is a slash only, * it will do nothing. By normalizing the URL there is a basis for matching multiple * variants (Like: url, /url, /url/, url/). * * @param string $url The URL to normalize. * * @return string The modified url. */ protected function normalize_url( $url ) { if ( $url === '/' ) { return $url; } return \trim( $url, '/' ); } /** * Checks if the current URL matches a regex. * * @return void */ protected function handle_regex_redirects() { // Setting the redirects. $this->redirects = $this->get_redirects( WPSEO_Redirect_Option::OPTION_REGEX ); foreach ( $this->redirects as $regex => $redirect ) { // Check if the URL matches the $regex. $this->match_regex_redirect( $regex, $redirect ); } } /** * Check if request URL matches one of the regex redirects. * * @param string $regex The reqular expression to match. * @param array $redirect The URL that might be matched with the regex. * * @return void */ protected function match_regex_redirect( $regex, array $redirect ) { /* * Escape the ` because we use ` to delimit the regex to prevent faulty redirects. * * Explicitly chosen not to use `preg_quote` because we need to be able to parse * user provided regular expression syntax. */ $regex = \str_replace( '`', '\\`', $regex ); // Suppress warning: a faulty redirect will give a warning and not an exception. So we can't catch it. // See issue: https://github.com/Yoast/wordpress-seo-premium/issues/662. // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged if ( @\preg_match( "`{$regex}`", $this->request_url, $this->url_matches ) === 1 ) { // Replace the $regex vars with URL matches. $redirect_url = \preg_replace_callback( '/\$[0-9]+/', [ $this, 'format_regex_redirect_url' ], $redirect['url'] ); $this->do_redirect( $redirect_url, $redirect['type'] ); } // Reset url_matches. $this->url_matches = []; } /** * Gets the redirects from the options. * * @param string $option The option name that wil be fetched. * * @return array Returns the redirects for the given option. */ protected function get_redirects( $option ) { static $redirects; if ( ! isset( $redirects[ $option ] ) ) { $redirects[ $option ] = \get_option( $option, false ); } if ( ! empty( $redirects[ $option ] ) ) { return $redirects[ $option ]; } return []; } /** * Performs the redirect. * * @param string $redirect_url The target URL. * @param string $redirect_type The type of the redirect. * * @return void */ protected function do_redirect( $redirect_url, $redirect_type ) { $redirect_url = $this->parse_target_url( $redirect_url ); // Prevents redirecting to itself. if ( $this->home_url( $this->request_url ) === $redirect_url ) { return; } $redirect_types_without_target = [ 410, 451 ]; if ( \in_array( $redirect_type, $redirect_types_without_target, true ) ) { $this->handle_redirect_without_target( $redirect_type ); return; } $this->redirect( $redirect_url, $redirect_type ); } /** * Checks if a redirect has been executed. * * @return bool Whether a redirect has been executed. */ protected function is_redirected() { return $this->is_redirected === true; } /** * Checks if we should load the PHP redirects. * * If Apache or NginX configuration is selected, don't load PHP redirects. * * @return bool True if PHP redirects should be loaded and used. */ protected function load_php_redirects() { if ( \defined( 'WPSEO_DISABLE_PHP_REDIRECTS' ) && \WPSEO_DISABLE_PHP_REDIRECTS === true ) { return false; } if ( \defined( 'WP_CLI' ) && \WP_CLI === true ) { return false; } $options = \get_option( 'wpseo_redirect', false ); if ( $options === false ) { // If the option is not set, save it, to prevent a query for a non-existing option on every page load. \add_action( 'wp_head', [ $this, 'save_default_redirect_options' ] ); return false; } // If the PHP redirects are disabled intentionally, return false. if ( ! empty( $options['disable_php_redirect'] ) && $options['disable_php_redirect'] === 'on' ) { return false; } // PHP redirects are the enabled method of redirecting. return true; } /** * Saves the default redirects options to the DB. * * @return void */ public function save_default_redirect_options() { $redirect_option = WPSEO_Premium_Redirect_Option::get_instance(); \update_option( 'wpseo_redirect', $redirect_option->get_defaults(), true ); } /** * Gets the request URI. * * @return string */ protected function get_request_uri() { $request_uri = ''; if ( isset( $_SERVER['REQUEST_URI'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- We sanitize after decoding. $request_uri = \sanitize_text_field( \rawurldecode( \wp_unslash( $_SERVER['REQUEST_URI'] ) ) ); } return $this->strip_subdirectory( $request_uri ); } /** * Normalizes the redirects by raw url decoding the origin. * * @param array $redirects The redirects to normalize. * * @return array The normalized redirects. */ protected function normalize_redirects( $redirects ) { $normalized_redirects = []; foreach ( $redirects as $origin => $redirect ) { $normalized_redirects[ \rawurldecode( $origin ) ] = $redirect; } return $normalized_redirects; } /** * Sets the request URL and sanitize the slashes for it. * * @return void */ protected function set_request_url() { $this->request_url = $this->get_request_uri(); } /** * Finds the URL in the redirects. * * @param string $url The needed URL. * * @return bool|string The found url or false if not found. */ protected function find_url( $url ) { $redirect_url = $this->search( $url ); if ( ! empty( $redirect_url ) ) { return $redirect_url; } return $this->find_url_fallback( $url ); } /** * Searches for the given URL in the redirects array. * * @param string $url The URL to search for. * * @return string|bool The found url or false if not found. */ protected function search( $url ) { if ( ! empty( $this->redirects[ $url ] ) ) { return $this->redirects[ $url ]; } return false; } /** * Searches for alternatives with slashes if requested URL isn't found. * * This will add a slash if there isn't a slash or it will remove a trailing slash when there isn't one. * * @todo Discuss: Maybe we should add slashes to all the values we handle instead of using a fallback. * * @param string $url The URL that have to be matched. * * @return bool|string The found url or false if not found. */ protected function find_url_fallback( $url ) { $no_trailing_slash = \rtrim( $url, '/' ); $checks = [ 'no_trailing_slash' => $no_trailing_slash, 'trailing_slash' => $no_trailing_slash . '/', ]; foreach ( $checks as $check ) { $redirect_url = $this->search( $check ); if ( ! empty( $redirect_url ) ) { return $redirect_url; } } return false; } /** * Parses the target URL. * * @param string $target_url The URL to parse. When there isn't found a scheme, just parse it based on the home URL. * * @return string The parsed url. */ protected function parse_target_url( $target_url ) { if ( $this->has_url_scheme( $target_url ) ) { return $target_url; } $target_url = $this->trailingslashit( $target_url ); $target_url = $this->format_for_multisite( $target_url ); return $this->home_url( $target_url ); } /** * Checks if given url has a scheme. * * @param string $url The url to check. * * @return bool True when url has scheme. */ protected function has_url_scheme( $url ) { $scheme = \wp_parse_url( $url, \PHP_URL_SCHEME ); return ! empty( $scheme ); } /** * Determines whether the target URL ends with a slash and adds one if necessary. * * @param string $target_url The url to format. * * @return string The url with trailing slash. */ protected function trailingslashit( $target_url ) { // Adds slash to target URL when permalink structure ends with a slash. if ( $this->requires_trailing_slash( $target_url ) ) { return \trailingslashit( $target_url ); } return $target_url; } /** * Formats the target url for the multisite if needed. * * @param string $target_url The url to format. * * @return string The formatted url. */ protected function format_for_multisite( $target_url ) { if ( ! \is_multisite() ) { return $target_url; } $blog_details = \get_blog_details(); if ( $blog_details && ! empty( $blog_details->path ) ) { $blog_path = \ltrim( $blog_details->path, '/' ); if ( ! empty( $blog_path ) && \strpos( $target_url, $blog_path ) === 0 ) { $target_url = \substr( $target_url, \strlen( $blog_path ) ); } } return $target_url; } /** * Gets the redirect URL by given URL. * * @param string $redirect_url The URL that has to be redirected. * * @return string The redirect url. */ protected function home_url( $redirect_url ) { $redirect_url = $this->strip_subdirectory( $redirect_url ); return \home_url( $redirect_url ); } /** * Strips the subdirectory from the given url. * * @param string $url The url to strip the subdirectory from. * * @return string The url with the stripped subdirectory. */ protected function strip_subdirectory( $url ) { return WPSEO_Redirect_Util::strip_base_url_path_from_url( $this->get_home_url(), $url ); } /** * Returns the URL PATH from the home url. * * @return string|null The url path or null if there isn't one. */ protected function get_home_url() { return \home_url(); } /** * Sets the hook for setting the template include. This is the file that we want to show. * * @param string $template_to_set The template to look for. * * @return bool True when template should be included. */ protected function set_template_include_hook( $template_to_set ) { $this->template_file_path = $this->get_query_template( $template_to_set ); if ( ! empty( $this->template_file_path ) ) { \add_filter( 'template_include', [ $this, 'set_template_include' ] ); return true; } return false; } /** * Wraps the WordPress status_header function. * * @param int $code HTTP status code. * @param string $description Optional. A custom description for the HTTP status. * * @return void */ protected function status_header( $code, $description = '' ) { \status_header( $code, $description ); } /** * Returns instance of WP_Query. * * @return WP_Query Instance of WP_Query. */ protected function get_wp_query() { global $wp_query; if ( \is_object( $wp_query ) ) { return $wp_query; } return new WP_Query(); } /** * Handles the redirects without a target by setting the needed hooks. * * @param string $redirect_type The type of the redirect. * * @return void */ protected function handle_redirect_without_target( $redirect_type ) { if ( $redirect_type === 410 ) { \add_action( 'wp', [ $this, 'do_410' ] ); } if ( $redirect_type === 451 ) { \add_action( 'wp', [ $this, 'do_451' ] ); } } /** * Wrapper method for doing the actual redirect. * * @param string $location The path to redirect to. * @param int $status Status code to use. * * @return void */ protected function redirect( $location, $status = 302 ) { if ( ! \function_exists( 'wp_redirect' ) ) { require_once \ABSPATH . 'wp-includes/pluggable.php'; } \wp_redirect( $location, $status, 'Yoast SEO Premium' ); exit; } /** * Returns whether or not a target URL requires a trailing slash. * * @param string $target_url The target URL to check. * * @return bool True when trailing slash is required. */ protected function requires_trailing_slash( $target_url ) { return WPSEO_Redirect_Util::requires_trailing_slash( $target_url ); } /** * Returns the query template. * * @param string $filename Filename without extension. * * @return string Full path to template file. */ protected function get_query_template( $filename ) { return \get_query_template( $filename ); } /** * Actually handles redirects. * * @return void */ public function handle_redirects() { // Set the requested URL. $this->set_request_url(); // Check the normal redirects. $this->handle_normal_redirects( $this->request_url ); // Check the regex redirects. if ( $this->is_redirected() === false ) { $this->handle_regex_redirects(); } } }
Fatal error: Uncaught Error: Interface "WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Properties\Properties" not found in /htdocs/wp-content/plugins/woocommerce-paypal-payments/lib/packages/Inpsyde/Modularity/Properties/BaseProperties.php:7 Stack trace: #0 /htdocs/wp-content/plugins/better-wp-security/vendor-prod/composer/ClassLoader.php(576): include() #1 /htdocs/wp-content/plugins/better-wp-security/vendor-prod/composer/ClassLoader.php(427): Composer\Autoload\{closure}('/htdocs/wp-cont...') #2 /htdocs/wp-content/plugins/woocommerce-paypal-payments/lib/packages/Inpsyde/Modularity/Properties/PluginProperties.php(14): Composer\Autoload\ClassLoader->loadClass('WooCommerce\\Pay...') #3 /htdocs/wp-content/plugins/better-wp-security/vendor-prod/composer/ClassLoader.php(576): include('/htdocs/wp-cont...') #4 /htdocs/wp-content/plugins/better-wp-security/vendor-prod/composer/ClassLoader.php(427): Composer\Autoload\{closure}('/htdocs/wp-cont...') #5 /htdocs/wp-content/plugins/woocommerce-paypal-payments/bootstrap.php(33): Composer\Autoload\ClassLoader->loadClass('WooCommerce\\Pay...') #6 /htdocs/wp-content/plugins/woocommerce-paypal-payments/woocommerce-paypal-payments.php(77): {closure}('/htdocs/wp-cont...') #7 /htdocs/wp-content/plugins/woocommerce-paypal-payments/woocommerce-paypal-payments.php(92): WooCommerce\PayPalCommerce\init() #8 /htdocs/wp-includes/class-wp-hook.php(324): WooCommerce\PayPalCommerce\{closure}('') #9 /htdocs/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #10 /htdocs/wp-includes/plugin.php(517): WP_Hook->do_action(Array) #11 /htdocs/wp-settings.php(559): do_action('plugins_loaded') #12 /htdocs/wp-config.php(98): require_once('/htdocs/wp-sett...') #13 /htdocs/wp-load.php(50): require_once('/htdocs/wp-conf...') #14 /htdocs/wp-blog-header.php(13): require_once('/htdocs/wp-load...') #15 /htdocs/index.php(17): require('/htdocs/wp-blog...') #16 {main} thrown in /htdocs/wp-content/plugins/woocommerce-paypal-payments/lib/packages/Inpsyde/Modularity/Properties/BaseProperties.php on line 7