wp-php-toolkit/polyfill

Polyfill component for WordPress.

Maintainers

Package info

github.com/wp-php-toolkit/polyfill

Homepage

Issues

Documentation

pkg:composer/wp-php-toolkit/polyfill

Statistics

Installs: 51

Dependents: 0

Suggesters: 0

Stars: 0

v0.8.0 2026-05-18 15:07 UTC

README

slug polyfill
title Polyfill
install wp-php-toolkit/polyfill
credit_title WordPress-shaped compatibility
credit_body When WordPress is loaded, every function in this component defers to WordPress. Outside WordPress, the standalone implementations cover the subset toolkit components need from <code>esc_html()</code>, <code>add_filter()</code>, <code>__()</code>, and related helpers.
see_also
html | HTML | Run WordPress-shaped escaping and translation helpers beside HTML processors. blockparser | BlockParser | Keep standalone block tooling familiar outside WordPress.

PHP 8 string functions on PHP 7.2+, WordPress hook stubs, and translation/escaping passthroughs so toolkit code runs without booting WordPress.

Why this exists

A lot of WordPress-adjacent code wants to call esc_html(), __(), or apply_filters() without booting WordPress. The polyfill component provides minimal implementations for the subset used by the toolkit, and stays out of the way when WordPress is loaded (every function uses function_exists() guards).

PHP 8 string functions on PHP 7.2

The polyfills define str_contains, str_starts_with, str_ends_with, and array_key_first only when missing.

<?php
require '/php-toolkit/vendor/autoload.php';

var_dump( str_starts_with( '/var/www/html', '/var' ) );
var_dump( str_ends_with( 'image.png', '.png' ) );
var_dump( str_contains( 'WordPress Toolkit', 'Toolkit' ) );

$first_key = array_key_first( array( 'alpha' => 1, 'beta' => 2 ) );
echo "first key: {$first_key}\n";
bool(true)
bool(true)
bool(true)
first key: alpha

Escaping and translation stubs

Pass-through implementations let you write code that looks WordPressy and runs anywhere.

<?php
require '/php-toolkit/vendor/autoload.php';

echo __( 'Hello, world' ) . "\n";
echo esc_html( '<script>alert("xss")</script>' ) . "\n";
echo esc_attr( 'a "quoted" value' ) . "\n";
echo esc_url( 'https://example.com/?a=1&b=2' ) . "\n";
Hello, world
&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;
a &quot;quoted&quot; value
https://example.com/?a=1&amp;b=2

A simple filter chain

The hook system implements the common filter path: registered callbacks get applied in priority order, and each one transforms the running value.

<?php
require '/php-toolkit/vendor/autoload.php';

add_filter( 'sanitize_title', 'trim' );
add_filter( 'sanitize_title', 'strtolower' );
add_filter( 'sanitize_title', function ( $title ) {
	return preg_replace( '/\s+/', '-', $title );
} );

echo apply_filters( 'sanitize_title', '  My Post Title  ' ) . "\n";
my-post-title

Priority ordering and multi-arg passing

Lower priority numbers run first. The fourth argument to add_filter controls how many context values get passed to the callback.

<?php
require '/php-toolkit/vendor/autoload.php';

add_filter( 'render_price', function ( $html, $price, $currency ) {
	return $html . " ({$currency} markup)";
}, 30, 3 );

add_filter( 'render_price', function ( $html, $price ) {
	return "<strong>{$html}</strong>";
}, 10, 2 );

add_filter( 'render_price', function ( $html, $price, $currency ) {
	if ( 'EUR' === $currency ) return $html . ' EUR';
	return $html . " {$currency}";
}, 20, 3 );

echo apply_filters( 'render_price', '19.99', 19.99, 'EUR' ) . "\n";
<strong>19.99</strong> EUR (EUR markup)

Hook-based extension points in standalone libraries

Use do_action and apply_filters as cheap extension points in your own code, without depending on WordPress.

<?php
require '/php-toolkit/vendor/autoload.php';

class ImportPipeline {
	public function process( array $row ) {
		$row = apply_filters( 'import_pipeline_normalize', $row );
		do_action( 'import_pipeline_row_processed', $row );
		return $row;
	}
}

add_filter( 'import_pipeline_normalize', function ( $row ) {
	$row['email'] = strtolower( trim( $row['email'] ) );
	return $row;
} );

$log = array();
add_action( 'import_pipeline_row_processed', function ( $row ) use ( &$log ) {
	$log[] = $row['email'];
} );

$pipeline = new ImportPipeline();
$pipeline->process( array( 'email' => '  USER@EXAMPLE.COM  ' ) );
$pipeline->process( array( 'email' => 'OTHER@example.com' ) );

echo implode( "\n", $log ) . "\n";
user@example.com
other@example.com