Open-source software is central to Alley’s mission and essential to our work. In the last few months, we’ve published several new open-source packages for PHP, JavaScript, and WordPress developers, each of which is rooted in our day-to-day experiences meeting the needs of our clients.
We’re delighted to highlight some of these new packages and invite you to take them for a spin in your own projects. We release new software regularly, so, as always, you can follow our GitHub, Packagist, and NPM profiles to see what we’re up to.
PHP packages
traverse/reshape
traverse()
and reshape()
are companion functions for safely deconstructing and reconstructing arrays and objects. traverse()
deconstructs the given data and offers conveniences such as the ability to select multiple values in one call and shortcut syntax for accessing nested values. reshape()
reconstructs and offers additional features like automatically determining the properties in the new shape and the ability to return a mix of arrays and objects.
$arr = [
'apples' => [
'red' => [
'gala',
'mcintosh',
],
'green' => [
'granny_smith',
],
],
];
$green = \Alley\traverse($arr, 'apples.green');
// ['granny_smith']
$red = \Alley\traverse($arr, 'apples.red');
// ['gala', 'mcintosh']
[$red, $green] = \Alley\traverse($arr, ['apples.red', 'apples.green']);
// ['gala', 'mcintosh'], ['granny_smith']
$sweet = \Alley\traverse($arr, 'apples.green.sweet');
// NULL
Browse on GitHub or install from Packagist.
Laminas Validator Extensions
This package provides additional validation classes for the Laminas Validator framework, including “fast fail” and “any” validator chains, decorators for negating validators and providing custom messages, and a custom base validation class that simplifies writing custom validators.
$valid = new \Alley\Validator\ValidatorByOperator('REGEX', '/^foo/');
$valid->isValid('foobar'); // true
$valid = new \Alley\Validator\ValidatorByOperator('NOT IN', ['bar', 'baz']);
$valid->isValid('bar'); // false
$valid = new \Alley\Validator\ValidatorByOperator('!==', 42);
$valid->isValid(43); // true
Browse on GitHub or install from Packagist.
WordPress packages
Match Blocks
match_blocks()
is a function for finding blocks in post content or raw block HTML using parameters such as the block name, inner HTML, attributes, or index. It has a wide range of uses, like finding blocks in content for removal or promotion, or in WP-CLI scripts that audit blocks in post content.
// Find all paragraph blocks in a post:
$grafs = \Alley\WP\match_blocks( $post, [ 'name' => 'core/paragraph' ] );
// Include paragraphs in inner blocks:
$grafs = \Alley\WP\match_blocks(
$post,
[
'flatten' => true,
'name' => 'core/paragraph',
]
);
// Get all paragraphs and headings:
$blocks = \Alley\WP\match_blocks(
'<!-- wp:paragraph -->…',
[
'name' => [ 'core/heading', 'core/paragraph' ],
]
);
// Get all images credited to the Associated Press:
$images = \Alley\WP\match_blocks(
$post,
[
'attrs' => [
[
'key' => 'credit',
'value' => '/(The )?Associated Press/i',
'operator' => 'REGEX',
],
[
'key' => 'credit',
'value' => 'AP',
],
'relation' => 'OR',
],
'name' => 'core/image',
]
);
Browse on GitHub or install from Packagist.
Caper
Caper provides a fluent interface for distributing post type, taxonomy, or generic primitive capabilities to roles. Its fluid syntax makes it easy to create granular permission schemes across multiple post types, taxonomies, and roles while remaining readable and maintainable.
Alley\WP\Caper::grant_to( 'editor' )->primitives( 'edit_theme_options' );
Alley\WP\Caper::deny_to( 'administrator' )->primitives( 'manage_options' );
Alley\WP\Caper::grant_to( 'author' )->caps_for( 'page' );
Alley\WP\Caper::deny_to( 'editor' )->caps_for( 'category' );
Alley\WP\Caper::grant_to( 'editor' )->caps_for( 'category' )->only( 'delete_terms' );
Alley\WP\Caper::deny( 'author' )->caps_for( 'page' )->except( 'delete_posts' );
Browse on GitHub or install from Packagist.
WP Bulk Task
This package provides a library to make it easier to run bulk tasks against a WordPress database in a performant way. It includes functionality to search through a WordPress database for posts using WP_Query
arguments and keeps a cursor of its location within the database in case it is interrupted and needs to start again.
( new \Alley\WP_Bulk_Task\Bulk_Task( 'bananaify' ) )->run(
[
'post_status' => 'publish',
],
function ( $post ) {
if ( str_contains( $post->post_content, 'apple' ) ) {
$new_value = str_replace( 'apple', 'banana', $post->post_content );
if ( ! empty( $assoc_args['dry-run'] ) ) {
\WP_CLI::log( 'Old post_content: ' . $post->post_content );
\WP_CLI::log( 'New post_content: ' . $new_value );
} else {
$post->post_content = $new_value;
wp_update_post( $post );
}
}
}
);
Browse on GitHub or install from Packagist.
Find One
The find_one()
family of functions are wrappers for common WordPress retrieval functions like get_posts()
or get_terms()
that reduce the return value of those retrieval functions into a single result.
$person = Alley\WP\find_one_post(
[
'meta_key' => 'twitter',
'meta_value' => '@potatomaster',
'post_type' => 'person',
]
); // ?WP_Post
$category = Alley\WP\find_one_term(
[
'slug' => 'potatomaster',
'taxonomy' => 'category',
]
); // ?WP_Term
Browse on GitHub or install from Packagist.
Filter Side Effects
Filter side effects allow you to hook into a WordPress filter and use it like an action when a call to apply_filters()
signals that some behavior needs to occur, but no convenient action exists to run it.
Browse on GitHub or install from Packagist.
WordPress plugins
Elasticsearch Extensions
This WordPress plugin makes complex and repetitive operations with Elasticsearch easier by simplifying common tasks like adding aggregations and filtering indexable post types, taxonomies, and post meta in an implementation-agnostic way.
add_action(
'elasticsearch_extensions_config',
function ( $es_config ) {
$es_config
->restrict_post_types( [ 'post', 'page' ] )
->enable_empty_search()
->enable_post_type_aggregation()
->enable_taxonomy_aggregation( 'category' )
->enable_taxonomy_aggregation( 'post_tag' );
}
);
Create WordPress Plugin
This is a skeleton WordPress plugin that can scaffold a WordPress plugin. This template includes a base plugin file, autoloaded PHP files, unit tests powered by Mantle, frontend assets compiled via Webpack, and continuous integration via GitHub Actions. Actions are configured to test the plugin and also build it for release.
NPM packages
@alleyinteractive/block-editor-tools
This package contains a set of modules to aid in building features for the WordPress block editor.
Browse on GitHub or install from npm.
@alleyinteractive/stylelint-config
This set of stylelint configuration rules extends the stylelint-config-sass-guidelines
intended for use with SCSS syntax.
Browse on GitHub or install from npm
Other packages
@alleyinteractive/hubot-code-review
hubot-code-review
is a Hubot script for GitHub code review on Slack. Simply drop a GitHub pull request URL into a room, and Hubot adds the pull request to the room’s queue. Each room has its own queue.