3v4l.org

run code in 300+ PHP versions simultaneously
<?php // All of the code needed for this test. function __( $text ) { return $text; } /** * Webfonts Schema Validator. * * Validates the webfont schema. */ class WP_Webfonts_Schema_Validator { /** * Valid font styles. * * @since 5.9.0 * * @var string[] */ const VALID_FONT_STYLE = array( 'normal', 'italic', 'oblique', 'inherit', 'initial', 'revert', 'unset' ); /** * Valid font display values. * * @since 5.9.0 * * @var string[] */ const VALID_FONT_DISPLAY = array( 'auto', 'block', 'fallback', 'swap' ); /** * Valid font weight values. * * @since 5.9.0 * * @var string[] */ const VALID_FONT_WEIGHT = array( 'normal', 'bold', 'bolder', 'lighter', 'inherit' ); /** * An array of valid CSS properties for @font-face. * * @since 5.9.0 * * @var string[] */ protected $font_face_properties = array( 'ascend-override', 'descend-override', 'font-display', 'font-family', 'font-stretch', 'font-style', 'font-weight', 'font-variant', 'font-feature-settings', 'font-variation-settings', 'line-gap-override', 'size-adjust', 'src', 'unicode-range', ); /** * Basic schema structure. * * @since 5.9.0 * * @var array */ protected $basic_schema = array( 'provider' => '', 'font-family' => '', 'font-style' => 'normal', 'font-weight' => '400', 'font-display' => 'fallback', ); /** * Webfont being validated. * * Set as a property for performance. * * @var array */ private $webfont = array(); /** * Checks if the given webfont schema is valid. * * @since 5.9.0 * * @param array $webfont Webfont to validate. * @return bool True when valid. False when invalid. */ public function is_valid_schema( array $webfont ) { $is_valid = ( $this->is_valid_provider( $webfont ) && $this->is_valid_font_family( $webfont ) ); if ( ! $is_valid ) { return false; } if ( 'local' === $webfont['provider'] || array_key_exists( 'src', $webfont ) ) { $is_valid = $this->is_src_valid( $webfont ); } return $is_valid; } /** * Checks if the provider is validate. * * @since 5.9.0 * * @param array $webfont Webfont to validate. * @return bool True if valid. False if invalid. */ private function is_valid_provider( array $webfont ) { // @todo check if provider is registered. if ( empty( $webfont['provider'] ) || ! is_string( $webfont['provider'] ) ) { trigger_error( __( 'Webfont provider must be a non-empty string.' ) ); return false; } return true; } /** * Checks if the font family is validate. * * @since 5.9.0 * * @param array $webfont Webfont to validate. * @return bool True when valid. False when invalid. */ private function is_valid_font_family( array $webfont ) { if ( empty( $webfont['font-family'] ) || ! is_string( $webfont['font-family'] ) ) { trigger_error( __( 'Webfont font family must be a non-empty string.' ) ); return false; } return true; } /** * Checks if the "src" value is valid. * * @since 5.9.0 * * @param array $webfont Webfont to validate. * @return bool True if valid. False if invalid. */ private function is_src_valid( $webfont ) { if ( empty( $webfont['src'] ) || ( ! is_string( $webfont['src'] ) && ! is_array( $webfont['src'] ) ) ) { trigger_error( __( 'Webfont src must be a non-empty string or an array of strings.' ) ); return false; } foreach ( (array) $webfont['src'] as $src ) { if ( ! is_string( $src ) ) { trigger_error( __( 'Each webfont src must be a non-empty string.' ) ); return false; } if ( ! $this->is_src_value_valid( $src ) ) { trigger_error( __( 'Webfont src must be a valid URL or a data URI.' ) ); return false; } } return true; } /** * Checks if the given `src` value is valid. * * @since 5.9.0 * * @param string $src Source to validate. * @return bool True when valid. False when invalid. */ private function is_src_value_valid( $src ) { // Validate data URLs. if ( preg_match( '/^data:.+;base64/', $src ) ) { return true; } // Validate URLs. if ( filter_var( $src, FILTER_VALIDATE_URL ) ) { return true; } // Check if it's a URL starting with "//" (omitted protocol). if ( 0 === strpos( $src, '//' ) ) { return true; } // Check if it's a relative URL. if ( 0 === strpos( $src, 'file:./' ) ) { return true; } return false; } /** * Sets valid properties. * * @since 5.9.0 * * @param array $webfont Webfont definition. * @return array Updated webfont. */ public function set_valid_properties( array $webfont ) { $this->webfont = array_merge( $this->basic_schema, $webfont ); $this->set_valid_font_face_property(); $this->set_valid_font_style(); $this->set_valid_font_weight(); $this->set_valid_font_display(); $webfont = $this->webfont; $this->webfont = array(); // Reset property. return $webfont; } /** * Checks if the CSS property is valid for @font-face. * * @since 5.9.0 */ private function set_valid_font_face_property() { foreach ( array_keys( $this->webfont ) as $property ) { /* * Skip valid configuration parameters (these are configuring the webfont * but are not @font-face properties. */ if ( 'provider' === $property ) { continue; } if ( ! in_array( $property, $this->font_face_properties, true ) ) { unset( $this->webfont[ $property ] ); } } } /** * Checks if the font style is validate. * * @since 5.9.0 */ private function set_valid_font_style() { // If empty or not a string, trigger an error and then set the default value. if ( empty( $this->webfont['font-style'] ) || ! is_string( $this->webfont['font-style'] ) ) { trigger_error( __( 'Webfont font style must be a non-empty string.' ) ); } elseif ( // Bail out if the font-weight is a valid value. in_array( $this->webfont['font-style'], self::VALID_FONT_STYLE, true ) || preg_match( '/^oblique\s+(\d+)%/', $this->webfont['font-style'] ) ) { return; } $this->webfont['font-style'] = 'normal'; } /** * Sets a default font weight if invalid. * * @since 5.9.0 */ private function set_valid_font_weight() { // If empty or not a string, trigger an error and then set the default value. if ( empty( $this->webfont['font-weight'] ) || ! is_string( $this->webfont['font-weight'] ) ) { trigger_error( __( 'Webfont font weight must be a non-empty string.' ) ); } elseif ( // Bail out if the font-weight is a valid value. // Check if value is a single font-weight, formatted as a number. in_array( $this->webfont['font-weight'], self::VALID_FONT_WEIGHT, true ) || // Check if value is a single font-weight, formatted as a number. preg_match( '/^(\d+)$/', $this->webfont['font-weight'], $matches ) || // Check if value is a range of font-weights, formatted as a number range. preg_match( '/^(\d+)\s+(\d+)$/', $this->webfont['font-weight'], $matches ) ) { return; } // Not valid. Set the default value. $this->webfont['font-weight'] = '400'; } /** * Sets a default font display if invalid. * * @since 5.9.0 */ private function set_valid_font_display() { if ( ! empty( $this->webfont['font-display'] ) && in_array( $this->webfont['font-display'], self::VALID_FONT_DISPLAY, true ) ) { return; } $this->webfont['font-display'] = 'fallback'; } } class Profiler { private $validator; private $total_in_microseconds = 0.0; private $cycles = 0; public function __construct( $validator ) { $this->validator = $validator; } public function register( array $webfont ) { $webfont = $this->convert_to_kabeb_case( $webfont ); $this->cycles++; $start_time = microtime( true ); // Validate schema. if ( ! $this->validator->is_valid_schema( $webfont ) ) { // return ''; // Skip for this test. } $webfont = $this->validator->set_valid_properties( $webfont ); // Do the registration. // Get stats. $end_time = microtime( true ); $this->total_in_microseconds += ( $end_time - $start_time ) * 1000000.0; // store in microseconds. } private function convert_to_kabeb_case( array $webfont ) { $kebab_case = preg_replace( '/(?<!^)[A-Z]/', '-$0', array_keys( $webfont ) ); $kebab_case = array_map( 'strtolower', $kebab_case ); return array_combine( $kebab_case, array_values( $webfont ) ); } public function get_avg_microseconds() { return $this->total_in_microseconds / $this->cycles; } } // Let's Go! $profiler = new Profiler( new WP_Webfonts_Schema_Validator() ); $webfont = array( 'fontFamily' => 'Source Serif Pro', 'fontWeight' => '200 900', 'fontStyle' => 'normal', 'fontStretch' => 'normal', 'src' => 'file:./assets/fonts/source-serif-pro/SourceSerif4Variable-Roman.ttf.woff2', 'provider' => 'local', ); /** * Benchmark the average time the Validator takes to validate a single webfont. * The profiler is set to 10,000 cycles to get a fair sampling and distribution. */ $num_time_to_run_validator = 10000; // do work. for ( $i = 1; $i <= $num_time_to_run_validator; $i++ ) { $profiler->register( $webfont ); } printf( "Ran %d in %s microseconds", $num_time_to_run_validator, number_format( $profiler->get_avg_microseconds(), 4 ) );
Output for git.master
Ran 10000 in 2.6662 microseconds
Output for git.master_jit
Ran 10000 in 2.7155 microseconds
Output for rfc.property-hooks
Ran 10000 in 1.6104 microseconds

This tab shows result from various feature-branches currently under review by the php developers. Contact me to have additional branches featured.

Active branches

Archived branches

Once feature-branches are merged or declined, they are no longer available. Their functionality (when merged) can be viewed from the main output page


preferences:
45.4 ms | 401 KiB | 8 Q