Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
13777b5
Move webp-uploads into modules/images focus folder
adamsilverstein Dec 21, 2021
96b4067
Adjust `perflab_get_modules` paths: add focus part
adamsilverstein Dec 21, 2021
bbd8747
Remove focus from header - implicit in structure
adamsilverstein Dec 21, 2021
448426b
Update docs for writing a module to indlude path, remove focus header
adamsilverstein Dec 21, 2021
9ecb11a
Iterate modules folder using slugs from `perflab_get_focus_areas`
adamsilverstein Dec 21, 2021
ce51914
Remove focus header from demo code
adamsilverstein Dec 21, 2021
3f83c16
Whitespace
adamsilverstein Dec 21, 2021
fa5adc4
Revert "Iterate modules folder using slugs from `perflab_get_focus_ar…
adamsilverstein Dec 21, 2021
57032af
Move test files into focus folders
adamsilverstein Dec 21, 2021
06a5a78
Assign module_dir and use to extract focus
adamsilverstein Dec 21, 2021
1d4984d
Validate module_dir and add slug to $module_data
adamsilverstein Dec 21, 2021
7a2ae01
Update docs to include focus in all paths, phpcs fixes
adamsilverstein Dec 21, 2021
3c4681a
Ensure tests pass
adamsilverstein Dec 21, 2021
a9358f3
move webp-image tests
adamsilverstein Dec 21, 2021
f65b6a3
Merge branch 'trunk' into update/module-naming
Dec 23, 2021
e554158
Update file pattern in translations command to match new module direc…
Dec 23, 2021
1d419bc
Update docs/Writing-a-module.md
adamsilverstein Dec 30, 2021
276d27b
Update docs/Writing-a-module.md
adamsilverstein Dec 30, 2021
f126464
Remove module_dir parameter, extract from $module_file
adamsilverstein Dec 30, 2021
86f7553
Remove focus from default_headers
adamsilverstein Dec 30, 2021
0936560
Adjust test object to match new parsing result
adamsilverstein Dec 30, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 41 additions & 17 deletions admin/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,35 +200,49 @@ function perflab_get_modules( $modules_root = null ) {
$module_files = array();
$modules_dir = @opendir( $modules_root );

// Modules are organized as {focus}/{module-slug} in the modules folder.
if ( $modules_dir ) {
// phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
while ( ( $file = readdir( $modules_dir ) ) !== false ) {
if ( '.' === substr( $file, 0, 1 ) ) {
while ( ( $focus = readdir( $modules_dir ) ) !== false ) {
if ( '.' === substr( $focus, 0, 1 ) ) {
continue;
}

// Unlike plugins, modules must be in a directory.
if ( ! is_dir( $modules_root . '/' . $file ) ) {
// Each focus area must be a directory.
if ( ! is_dir( $modules_root . '/' . $focus ) ) {
continue;
}

$module_dir = @opendir( $modules_root . '/' . $file );
if ( $module_dir ) {
$focus_dir = @opendir( $modules_root . '/' . $focus );
if ( $focus_dir ) {
// phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
while ( ( $subfile = readdir( $module_dir ) ) !== false ) {
if ( '.' === substr( $subfile, 0, 1 ) ) {
while ( ( $file = readdir( $focus_dir ) ) !== false ) {
// Unlike plugins, modules must be in a directory.
if ( ! is_dir( $modules_root . '/' . $focus . '/' . $file ) ) {
continue;
}

// Unlike plugins, module main files must be called `load.php`.
if ( 'load.php' !== $subfile ) {
continue;
}
$module_dir = @opendir( $modules_root . '/' . $focus . '/' . $file );
if ( $module_dir ) {
// phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
while ( ( $subfile = readdir( $module_dir ) ) !== false ) {
if ( '.' === substr( $subfile, 0, 1 ) ) {
continue;
}

// Unlike plugins, module main files must be called `load.php`.
if ( 'load.php' !== $subfile ) {
continue;
}

$module_files[] = "$file/$subfile";
$module_files[] = "$focus/$file/$subfile";
}

closedir( $module_dir );
}
}

closedir( $module_dir );
closedir( $focus_dir );
}
}

Expand All @@ -239,13 +253,13 @@ function perflab_get_modules( $modules_root = null ) {
if ( ! is_readable( "$modules_root/$module_file" ) ) {
continue;
}

$module_dir = dirname( $module_file );
$module_data = perflab_get_module_data( "$modules_root/$module_file" );
if ( ! $module_data ) {
continue;
}

$modules[ dirname( $module_file ) ] = $module_data;
$modules[ $module_dir ] = $module_data;
}

uasort(
Expand All @@ -271,10 +285,13 @@ function( $a, $b ) {
* 'name', 'description', 'focus', and 'experimental'.
*/
function perflab_get_module_data( $module_file ) {
// Extract the module dir in the form {focus}/{module-slug}.
preg_match( '/.*\/(.*\/.*)\/load\.php$/i', $module_file, $matches );
$module_dir = $matches[1];

$default_headers = array(
'name' => 'Module Name',
'description' => 'Description',
'focus' => 'Focus',
'experimental' => 'Experimental',
);

Expand All @@ -292,6 +309,13 @@ function perflab_get_module_data( $module_file ) {
$module_data['experimental'] = false;
}

// Extract the module focus from the module directory.
if ( strpos( $module_dir, '/' ) ) {
list( $focus, $slug ) = explode( '/', $module_dir );
$module_data['focus'] = $focus;
$module_data['slug'] = $slug;
}

// Translate fields using low-level function since they come from PHP comments, including the necessary context for
// `_x()`. This must match how these are translated in the generated `/module-i18n.php` file.
$translatable_fields = array(
Expand Down
2 changes: 1 addition & 1 deletion bin/plugin/commands/translations.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ exports.handler = async ( opt ) => {
* @return {[]WPTranslationEntry} List of translation entries.
*/
async function getTranslations( settings ) {
const moduleFilePattern = path.join( settings.directory, '*/load.php' );
const moduleFilePattern = path.join( settings.directory, '*/*/load.php' );
const moduleFiles = await glob( path.resolve( '.', moduleFilePattern ) );

const moduleTranslations = moduleFiles
Expand Down
12 changes: 5 additions & 7 deletions docs/Writing-a-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,17 @@ Every module surfaces on the admin settings page of the performance plugin, wher

## Module requirements

* The production code for a module must all be located in a directory `/modules/{module-slug}` where `{module-slug}` is the module's slug.
* The entry point file must be called `load.php` and per the above be located at `/modules/{module-slug}/load.php`.
* The production code for a module must all be located in a directory `/modules/{focus}/{module-slug}` where `{module-slug}` is the module's slug and `{focus}` is the focus area: an identifier of a single focus (e.g. `images`). This should correspond to a section on the performance plugin's settings page. [See the `perflab_get_focus_areas()` function for the currently available focus areas.](../admin/load.php#L161)
* The entry point file must be called `load.php` and per the above be located at `/modules/{focus}/{module-slug}/load.php`.
* The `load.php` entry point file must contain a module header with the following fields:
* `Module Name`: Name of the module (comparable to `Plugin Name` for plugins). It will be displayed on the performance plugin's settings page.
* `Description`: Brief description of the module (comparable to `Description` for plugins). It will be displayed next to the module name on the performance plugin's settings page.
* `Focus`: Identifier of a single focus area (e.g. `images`). This should correspond to a section on the performance plugin's settings page. [See the `perflab_get_focus_areas()` function for the currently available focus areas.](../admin/load.php#L161)
* `Experimental`: Either `Yes` or `No`. If `Yes`, the module will be marked as explicitly experimental on the performance plugin's settings page. While all modules are somewhat experimental (similar to feature plugins), for some that may apply more than for others. For example, certain modules we would encourage limited testing in production for, where we've already established a certain level of reliability/quality, in other cases modules shouldn't be used in production at all.
* The module must neither rely on any PHP code from outside its directory nor on any external PHP code. If relying on an external PHP dependency is essential for a module, the approach should be evaluated and discussed with the wider team.
* The module must use the `performance-lab` text domain for all of its localizable strings.
* All global code structures in the module PHP codebase must be prefixed (e.g. with a string based on the module slug) to avoid conflicts with other modules or plugins.
* All test code for a module (e.g. PHPUnit tests) must be located in a directory `/tests/modules/{module-slug}` where `{module-slug}` is the module's slug (i.e. the same folder name used above).
* If tests require some test-specific structures (e.g. dummy data or mock classes), those should be implemented in a directory `/tests/testdata/modules/{module-slug}`.
* All test code for a module (e.g. PHPUnit tests) must be located in a directory `/tests/modules/{focus}/{module-slug}` where `{module-slug}` is the module's slug and `{focus}` is the focus area (i.e. the same folder names used above).
* If tests require some test-specific structures (e.g. dummy data or mock classes), those should be implemented in a directory `/tests/testdata/modules/{focus}/{module-slug}`.
* The module must adhere to the WordPress coding and documentation standards.

## Module recommendations
Expand All @@ -35,14 +34,13 @@ Every module surfaces on the admin settings page of the performance plugin, wher

## Example

The following is a minimum module entry point file `/modules/my-module/load.php` (i.e. the module slug is "my-module"):
The following is a minimum module entry point file `/modules/images/my-module/load.php` (i.e. the module slug is "my-module", and the focus is "images"):

```php
<?php
/**
* Module Name: My Module
* Description: Enhances performance for something.
* Focus: images
* Experimental: No
*
* @package performance-lab
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/**
* Module Name: WebP Uploads
* Description: Uses WebP as the default format for new JPEG image uploads if the server supports it.
* Focus: images
* Experimental: No
*
* @package performance-lab
Expand Down
23 changes: 13 additions & 10 deletions tests/admin/load-tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,26 @@
class Admin_Load_Tests extends WP_UnitTestCase {

private static $demo_modules = array(
'demo-module-1' => array(
'javascript/demo-module-1' => array(
'name' => 'Demo Module 1',
'description' => 'This is the description for demo module 1.',
'focus' => 'javascript',
'experimental' => false,
'focus' => 'javascript',
'slug' => 'demo-module-1',
),
'demo-module-2' => array(
'something/demo-module-2' => array(
'name' => 'Demo Module 2',
'description' => 'This is the description for demo module 2.',
'focus' => 'something',
'experimental' => true,
'focus' => 'something',
'slug' => 'demo-module-2',
),
'demo-module-3' => array(
'images/demo-module-3' => array(
'name' => 'Demo Module 3',
'description' => 'This is the description for demo module 3.',
'focus' => 'images',
'experimental' => false,
'focus' => 'images',
'slug' => 'demo-module-3',
),
);

Expand Down Expand Up @@ -116,15 +119,15 @@ public function test_perflab_load_modules_page() {
array_keys( $wp_settings_fields[ PERFLAB_MODULES_SCREEN ] )
);
$this->assertEqualSets(
array( 'demo-module-3' ),
array( 'images/demo-module-3' ),
array_keys( $wp_settings_fields[ PERFLAB_MODULES_SCREEN ]['images'] )
);
$this->assertEqualSets(
array( 'demo-module-1' ),
array( 'javascript/demo-module-1' ),
array_keys( $wp_settings_fields[ PERFLAB_MODULES_SCREEN ]['javascript'] )
);
$this->assertEqualSets(
array( 'demo-module-2' ),
array( 'something/demo-module-2' ),
array_keys( $wp_settings_fields[ PERFLAB_MODULES_SCREEN ]['other'] )
);
}
Expand All @@ -138,7 +141,7 @@ public function test_perflab_render_modules_page() {
}

public function test_perflab_render_modules_page_field() {
$module_slug = 'demo-module-1';
$module_slug = 'javascript/demo-module-1';
$module_data = self::$demo_modules[ $module_slug ];
$module_settings = array( 'enabled' => false );

Expand Down
2 changes: 1 addition & 1 deletion tests/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
'plugins_loaded',
function() {
require_once TESTS_PLUGIN_DIR . '/admin/load.php';
$module_files = glob( TESTS_PLUGIN_DIR . '/modules/*/load.php' );
$module_files = glob( TESTS_PLUGIN_DIR . '/modules/*/*/load.php' );
if ( $module_files ) {
foreach ( $module_files as $module_file ) {
require_once $module_file;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/**
* Module Name: Demo Module 3
* Description: This is the description for demo module 3.
* Focus: images
* Experimental: No
*
* @package performance-lab
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/**
* Module Name: Demo Module 1
* Description: This is the description for demo module 1.
* Focus: javascript
* Experimental: No
*
* @package performance-lab
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/**
* Module Name: Demo Module 2
* Description: This is the description for demo module 2.
* Focus: something
* Experimental: Yes
*
* @package performance-lab
Expand Down