From 13777b5b432d7978bc893f3f2b9c2c0d474b372e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 10:52:51 -0700 Subject: [PATCH 01/20] Move webp-uploads into modules/images focus folder --- modules/{ => images}/webp-uploads/load.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/{ => images}/webp-uploads/load.php (100%) diff --git a/modules/webp-uploads/load.php b/modules/images/webp-uploads/load.php similarity index 100% rename from modules/webp-uploads/load.php rename to modules/images/webp-uploads/load.php From 96b406740fa54c60b930f44354ff971418c4fa3a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 11:02:31 -0700 Subject: [PATCH 02/20] Adjust `perflab_get_modules` paths: add focus part --- admin/load.php | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/admin/load.php b/admin/load.php index 9863027bc3..f3b53888b7 100644 --- a/admin/load.php +++ b/admin/load.php @@ -200,35 +200,48 @@ 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 ) { - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition - while ( ( $subfile = readdir( $module_dir ) ) !== false ) { - if ( '.' === substr( $subfile, 0, 1 ) ) { + $focus_dir = @opendir( $modules_root . '/' . $focus ); + if ( $focus_dir ) { + 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 ); } } From bbd8747f83f46354338cef4bdb08a4dfa89162c9 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 11:08:07 -0700 Subject: [PATCH 03/20] Remove focus from header - implicit in structure --- modules/images/webp-uploads/load.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/images/webp-uploads/load.php b/modules/images/webp-uploads/load.php index 3dbd44f292..f05e724c5b 100644 --- a/modules/images/webp-uploads/load.php +++ b/modules/images/webp-uploads/load.php @@ -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 From 448426b581e27384aee5522c217ae7ff8b6a73a2 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 11:30:49 -0700 Subject: [PATCH 04/20] Update docs for writing a module to indlude path, remove focus header --- docs/Writing-a-module.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/Writing-a-module.md b/docs/Writing-a-module.md index a09d044118..72f98826c0 100644 --- a/docs/Writing-a-module.md +++ b/docs/Writing-a-module.md @@ -13,12 +13,11 @@ 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 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) +* 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. From 9ecb11a1dd6224c271c90269c35194cbad7dcdb8 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 11:31:12 -0700 Subject: [PATCH 05/20] Iterate modules folder using slugs from `perflab_get_focus_areas` --- admin/load.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/admin/load.php b/admin/load.php index f3b53888b7..020914e204 100644 --- a/admin/load.php +++ b/admin/load.php @@ -202,11 +202,9 @@ function perflab_get_modules( $modules_root = null ) { // Modules are organized as {focus}/{module-slug} in the modules folder. if ( $modules_dir ) { - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition - while ( ( $focus = readdir( $modules_dir ) ) !== false ) { - if ( '.' === substr( $focus, 0, 1 ) ) { - continue; - } + // Load modules from each focus area folder. + $focus_areas = perflab_get_focus_areas(); + foreach ( array_keys( $focus_areas ) as $focus ) { // Each focus area must be a directory. if ( ! is_dir( $modules_root . '/' . $focus ) ) { @@ -215,6 +213,7 @@ function perflab_get_modules( $modules_root = null ) { $focus_dir = @opendir( $modules_root . '/' . $focus ); if ( $focus_dir ) { + // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition while ( ( $file = readdir( $focus_dir ) ) !== false ) { // Unlike plugins, modules must be in a directory. if ( ! is_dir( $modules_root . '/' . $focus . '/' . $file ) ) { @@ -244,8 +243,6 @@ function perflab_get_modules( $modules_root = null ) { closedir( $focus_dir ); } } - - closedir( $modules_dir ); } foreach ( $module_files as $module_file ) { @@ -286,7 +283,6 @@ function perflab_get_module_data( $module_file ) { $default_headers = array( 'name' => 'Module Name', 'description' => 'Description', - 'focus' => 'Focus', 'experimental' => 'Experimental', ); @@ -304,5 +300,11 @@ function perflab_get_module_data( $module_file ) { $module_data['experimental'] = false; } + // Extract the module focus from its filename. + preg_match( '/.*\/modules\/([^\/]*)\/.*/', $module_file, $matches ); + if (isset( $matches[1] ) ) { + $module_data['focus'] = $matches[1]; + } + return $module_data; } From ce51914eea8a576fe03f7ca0fb85278822cc3030 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 11:31:42 -0700 Subject: [PATCH 06/20] Remove focus header from demo code --- docs/Writing-a-module.md | 3 +-- tests/testdata/demo-modules/demo-module-1/load.php | 1 - tests/testdata/demo-modules/demo-module-2/load.php | 1 - tests/testdata/demo-modules/demo-module-3/load.php | 1 - 4 files changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/Writing-a-module.md b/docs/Writing-a-module.md index 72f98826c0..bbc24047e8 100644 --- a/docs/Writing-a-module.md +++ b/docs/Writing-a-module.md @@ -13,7 +13,7 @@ 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/{focus}/{module-slug}` where `{module-slug}` is the module's slug and `{focus}` is the focus area, an 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) +* 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. @@ -41,7 +41,6 @@ The following is a minimum module entry point file `/modules/my-module/load.php` /** * Module Name: My Module * Description: Enhances performance for something. - * Focus: images * Experimental: No * * @package performance-lab diff --git a/tests/testdata/demo-modules/demo-module-1/load.php b/tests/testdata/demo-modules/demo-module-1/load.php index 2ca7a19009..e1cdb99aa4 100644 --- a/tests/testdata/demo-modules/demo-module-1/load.php +++ b/tests/testdata/demo-modules/demo-module-1/load.php @@ -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 diff --git a/tests/testdata/demo-modules/demo-module-2/load.php b/tests/testdata/demo-modules/demo-module-2/load.php index 2f76cb23ad..5e8e698a9a 100644 --- a/tests/testdata/demo-modules/demo-module-2/load.php +++ b/tests/testdata/demo-modules/demo-module-2/load.php @@ -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 diff --git a/tests/testdata/demo-modules/demo-module-3/load.php b/tests/testdata/demo-modules/demo-module-3/load.php index 5acbe73b1d..007ba59552 100644 --- a/tests/testdata/demo-modules/demo-module-3/load.php +++ b/tests/testdata/demo-modules/demo-module-3/load.php @@ -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 From 3f83c16c75131e3d1e679c2972f3c8f373997b71 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 11:43:54 -0700 Subject: [PATCH 07/20] Whitespace --- admin/load.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/load.php b/admin/load.php index 020914e204..eec48fb57b 100644 --- a/admin/load.php +++ b/admin/load.php @@ -302,7 +302,7 @@ function perflab_get_module_data( $module_file ) { // Extract the module focus from its filename. preg_match( '/.*\/modules\/([^\/]*)\/.*/', $module_file, $matches ); - if (isset( $matches[1] ) ) { + if ( isset( $matches[1] ) ) { $module_data['focus'] = $matches[1]; } From fa5adc419c169385355b5841c514a17868637a3a Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 15:28:25 -0700 Subject: [PATCH 08/20] Revert "Iterate modules folder using slugs from `perflab_get_focus_areas`" This reverts commit 9ecb11a1dd6224c271c90269c35194cbad7dcdb8. # Conflicts: # admin/load.php --- admin/load.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/admin/load.php b/admin/load.php index eec48fb57b..cd50bc1439 100644 --- a/admin/load.php +++ b/admin/load.php @@ -202,9 +202,11 @@ function perflab_get_modules( $modules_root = null ) { // Modules are organized as {focus}/{module-slug} in the modules folder. if ( $modules_dir ) { - // Load modules from each focus area folder. - $focus_areas = perflab_get_focus_areas(); - foreach ( array_keys( $focus_areas ) as $focus ) { + // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition + while ( ( $focus = readdir( $modules_dir ) ) !== false ) { + if ( '.' === substr( $focus, 0, 1 ) ) { + continue; + } // Each focus area must be a directory. if ( ! is_dir( $modules_root . '/' . $focus ) ) { @@ -213,7 +215,6 @@ function perflab_get_modules( $modules_root = null ) { $focus_dir = @opendir( $modules_root . '/' . $focus ); if ( $focus_dir ) { - // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition while ( ( $file = readdir( $focus_dir ) ) !== false ) { // Unlike plugins, modules must be in a directory. if ( ! is_dir( $modules_root . '/' . $focus . '/' . $file ) ) { @@ -243,6 +244,8 @@ function perflab_get_modules( $modules_root = null ) { closedir( $focus_dir ); } } + + closedir( $modules_dir ); } foreach ( $module_files as $module_file ) { @@ -283,6 +286,7 @@ function perflab_get_module_data( $module_file ) { $default_headers = array( 'name' => 'Module Name', 'description' => 'Description', + 'focus' => 'Focus', 'experimental' => 'Experimental', ); From 57032af36851a7179c6131cb9f2f44da57deed05 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 15:43:18 -0700 Subject: [PATCH 09/20] Move test files into focus folders --- tests/bootstrap.php | 2 +- tests/testdata/demo-modules/{ => images}/demo-module-3/load.php | 0 .../demo-modules/{ => javascript}/demo-module-1/load.php | 0 .../demo-modules/{ => something}/demo-module-2/load.php | 0 .../webp-uploads/class-wp-image-doesnt-support-webp.php | 0 .../{ => images}/webp-uploads/class-wp-image-supports-webp.php | 0 6 files changed, 1 insertion(+), 1 deletion(-) rename tests/testdata/demo-modules/{ => images}/demo-module-3/load.php (100%) rename tests/testdata/demo-modules/{ => javascript}/demo-module-1/load.php (100%) rename tests/testdata/demo-modules/{ => something}/demo-module-2/load.php (100%) rename tests/testdata/modules/{ => images}/webp-uploads/class-wp-image-doesnt-support-webp.php (100%) rename tests/testdata/modules/{ => images}/webp-uploads/class-wp-image-supports-webp.php (100%) diff --git a/tests/bootstrap.php b/tests/bootstrap.php index ff6bf784ae..b615fc636f 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -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; diff --git a/tests/testdata/demo-modules/demo-module-3/load.php b/tests/testdata/demo-modules/images/demo-module-3/load.php similarity index 100% rename from tests/testdata/demo-modules/demo-module-3/load.php rename to tests/testdata/demo-modules/images/demo-module-3/load.php diff --git a/tests/testdata/demo-modules/demo-module-1/load.php b/tests/testdata/demo-modules/javascript/demo-module-1/load.php similarity index 100% rename from tests/testdata/demo-modules/demo-module-1/load.php rename to tests/testdata/demo-modules/javascript/demo-module-1/load.php diff --git a/tests/testdata/demo-modules/demo-module-2/load.php b/tests/testdata/demo-modules/something/demo-module-2/load.php similarity index 100% rename from tests/testdata/demo-modules/demo-module-2/load.php rename to tests/testdata/demo-modules/something/demo-module-2/load.php diff --git a/tests/testdata/modules/webp-uploads/class-wp-image-doesnt-support-webp.php b/tests/testdata/modules/images/webp-uploads/class-wp-image-doesnt-support-webp.php similarity index 100% rename from tests/testdata/modules/webp-uploads/class-wp-image-doesnt-support-webp.php rename to tests/testdata/modules/images/webp-uploads/class-wp-image-doesnt-support-webp.php diff --git a/tests/testdata/modules/webp-uploads/class-wp-image-supports-webp.php b/tests/testdata/modules/images/webp-uploads/class-wp-image-supports-webp.php similarity index 100% rename from tests/testdata/modules/webp-uploads/class-wp-image-supports-webp.php rename to tests/testdata/modules/images/webp-uploads/class-wp-image-supports-webp.php From 06a5a786bd327afd137655471b301ae0d4ed946d Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 15:44:00 -0700 Subject: [PATCH 10/20] Assign module_dir and use to extract focus --- admin/load.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/admin/load.php b/admin/load.php index cd50bc1439..d7c9f0c6f4 100644 --- a/admin/load.php +++ b/admin/load.php @@ -252,13 +252,13 @@ function perflab_get_modules( $modules_root = null ) { if ( ! is_readable( "$modules_root/$module_file" ) ) { continue; } - - $module_data = perflab_get_module_data( "$modules_root/$module_file" ); + $module_dir = dirname( $module_file ); + $module_data = perflab_get_module_data( "$modules_root/$module_file", $module_dir ); if ( ! $module_data ) { continue; } - $modules[ dirname( $module_file ) ] = $module_data; + $modules[ $module_dir ] = $module_data; } uasort( @@ -279,10 +279,11 @@ function( $a, $b ) { * @since 1.0.0 * * @param string $module_file Absolute path to the main module file. + * @param string $module_dir The module directory ({focus}/{module-slug}). * @return array|bool Associative array of parsed module data, or false on failure. Fields for every module include * 'name', 'description', 'focus', and 'experimental'. */ -function perflab_get_module_data( $module_file ) { +function perflab_get_module_data( $module_file, $module_dir ) { $default_headers = array( 'name' => 'Module Name', 'description' => 'Description', @@ -304,10 +305,10 @@ function perflab_get_module_data( $module_file ) { $module_data['experimental'] = false; } - // Extract the module focus from its filename. - preg_match( '/.*\/modules\/([^\/]*)\/.*/', $module_file, $matches ); - if ( isset( $matches[1] ) ) { - $module_data['focus'] = $matches[1]; + // Extract the module focus from the module directory. + list( $focus, $slug ) = explode( '/', $module_dir ); + if ( $focus ) { + $module_data['focus'] = $focus; } return $module_data; From 1d4984d4a31ca2b8e09512acb29fcf37d07b8bfb Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 15:54:51 -0700 Subject: [PATCH 11/20] Validate module_dir and add slug to $module_data --- admin/load.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/admin/load.php b/admin/load.php index d7c9f0c6f4..1938e6cf42 100644 --- a/admin/load.php +++ b/admin/load.php @@ -306,9 +306,10 @@ function perflab_get_module_data( $module_file, $module_dir ) { } // Extract the module focus from the module directory. - list( $focus, $slug ) = explode( '/', $module_dir ); - if ( $focus ) { + if ( strpos( $module_dir, '/' ) ) { + list( $focus, $slug ) = explode( '/', $module_dir ); $module_data['focus'] = $focus; + $module_data['slug'] = $slug; } return $module_data; From 7a2ae01a404dfac10774f8b08f70fdb3bf7a935d Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 16:00:05 -0700 Subject: [PATCH 12/20] Update docs to include focus in all paths, phpcs fixes --- admin/load.php | 5 +++-- docs/Writing-a-module.md | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/admin/load.php b/admin/load.php index 1938e6cf42..4463aab23e 100644 --- a/admin/load.php +++ b/admin/load.php @@ -215,6 +215,7 @@ function perflab_get_modules( $modules_root = null ) { $focus_dir = @opendir( $modules_root . '/' . $focus ); if ( $focus_dir ) { + // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition while ( ( $file = readdir( $focus_dir ) ) !== false ) { // Unlike plugins, modules must be in a directory. if ( ! is_dir( $modules_root . '/' . $focus . '/' . $file ) ) { @@ -252,7 +253,7 @@ function perflab_get_modules( $modules_root = null ) { if ( ! is_readable( "$modules_root/$module_file" ) ) { continue; } - $module_dir = dirname( $module_file ); + $module_dir = dirname( $module_file ); $module_data = perflab_get_module_data( "$modules_root/$module_file", $module_dir ); if ( ! $module_data ) { continue; @@ -309,7 +310,7 @@ function perflab_get_module_data( $module_file, $module_dir ) { if ( strpos( $module_dir, '/' ) ) { list( $focus, $slug ) = explode( '/', $module_dir ); $module_data['focus'] = $focus; - $module_data['slug'] = $slug; + $module_data['slug'] = $slug; } return $module_data; diff --git a/docs/Writing-a-module.md b/docs/Writing-a-module.md index bbc24047e8..e9f68db905 100644 --- a/docs/Writing-a-module.md +++ b/docs/Writing-a-module.md @@ -22,8 +22,8 @@ Every module surfaces on the admin settings page of the performance plugin, wher * 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 (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/{focus}/{module-slug}`. * The module must adhere to the WordPress coding and documentation standards. ## Module recommendations @@ -34,7 +34,7 @@ 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/focus/my-module/load.php` (i.e. the module slug is "my-module"): ```php Date: Tue, 21 Dec 2021 16:10:02 -0700 Subject: [PATCH 13/20] Ensure tests pass --- tests/admin/load-tests.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/admin/load-tests.php b/tests/admin/load-tests.php index 453d4bd3a3..6d5e9ee971 100644 --- a/tests/admin/load-tests.php +++ b/tests/admin/load-tests.php @@ -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, + '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, + '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, + 'slug' => 'demo-module-3', ), ); @@ -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'] ) ); } @@ -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 ); @@ -183,7 +186,7 @@ public function test_perflab_get_modules() { public function test_perflab_get_module_data() { // Use test data directory with demo modules that match the modules declared on top of this file. foreach ( self::$demo_modules as $module_slug => $expected_module_data ) { - $module_data = perflab_get_module_data( TESTS_PLUGIN_DIR . '/tests/testdata/demo-modules/' . $module_slug . '/load.php' ); + $module_data = perflab_get_module_data( TESTS_PLUGIN_DIR . '/tests/testdata/demo-modules/' . $module_slug . '/load.php', $module_slug ); $this->assertSame( $expected_module_data, $module_data ); } } From a9358f33e59da18c55479686f35db771eb93ed48 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Tue, 21 Dec 2021 16:14:28 -0700 Subject: [PATCH 14/20] move webp-image tests --- tests/modules/{ => images}/webp-uploads/webp-uploads-test.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/modules/{ => images}/webp-uploads/webp-uploads-test.php (100%) diff --git a/tests/modules/webp-uploads/webp-uploads-test.php b/tests/modules/images/webp-uploads/webp-uploads-test.php similarity index 100% rename from tests/modules/webp-uploads/webp-uploads-test.php rename to tests/modules/images/webp-uploads/webp-uploads-test.php From e5541589a2ee0a644e3dabf49a936eaec996efa1 Mon Sep 17 00:00:00 2001 From: Felix Arntz Date: Thu, 23 Dec 2021 04:27:17 -0800 Subject: [PATCH 15/20] Update file pattern in translations command to match new module directory hierarchy. --- bin/plugin/commands/translations.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/plugin/commands/translations.js b/bin/plugin/commands/translations.js index f9afa1bb6d..8fb0283984 100644 --- a/bin/plugin/commands/translations.js +++ b/bin/plugin/commands/translations.js @@ -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 From 1d419bcf6774ddd7f094f61173f34cd87a1d1e67 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 30 Dec 2021 09:21:39 -0700 Subject: [PATCH 16/20] Update docs/Writing-a-module.md Co-authored-by: Felix Arntz --- docs/Writing-a-module.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Writing-a-module.md b/docs/Writing-a-module.md index e9f68db905..c2890488c0 100644 --- a/docs/Writing-a-module.md +++ b/docs/Writing-a-module.md @@ -22,7 +22,7 @@ Every module surfaces on the admin settings page of the performance plugin, wher * 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/{focus}/{module-slug}` where `{module-slug}` is the module's slug (i.e. the same folder name used above). +* 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. From 276d27b9a8fa8dfabd70ab46c40cf50184704d65 Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 30 Dec 2021 09:22:15 -0700 Subject: [PATCH 17/20] Update docs/Writing-a-module.md Co-authored-by: Felix Arntz --- docs/Writing-a-module.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Writing-a-module.md b/docs/Writing-a-module.md index c2890488c0..d4b814004e 100644 --- a/docs/Writing-a-module.md +++ b/docs/Writing-a-module.md @@ -34,7 +34,7 @@ Every module surfaces on the admin settings page of the performance plugin, wher ## Example -The following is a minimum module entry point file `/modules/focus/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 Date: Thu, 30 Dec 2021 09:45:01 -0700 Subject: [PATCH 18/20] Remove module_dir parameter, extract from $module_file --- admin/load.php | 9 ++++++--- tests/admin/load-tests.php | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/admin/load.php b/admin/load.php index fb15e09710..a3a50463b6 100644 --- a/admin/load.php +++ b/admin/load.php @@ -254,7 +254,7 @@ function perflab_get_modules( $modules_root = null ) { continue; } $module_dir = dirname( $module_file ); - $module_data = perflab_get_module_data( "$modules_root/$module_file", $module_dir ); + $module_data = perflab_get_module_data( "$modules_root/$module_file" ); if ( ! $module_data ) { continue; } @@ -281,11 +281,14 @@ function( $a, $b ) { * @since 1.0.0 * * @param string $module_file Absolute path to the main module file. - * @param string $module_dir The module directory ({focus}/{module-slug}). * @return array|bool Associative array of parsed module data, or false on failure. Fields for every module include * 'name', 'description', 'focus', and 'experimental'. */ -function perflab_get_module_data( $module_file, $module_dir ) { +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', diff --git a/tests/admin/load-tests.php b/tests/admin/load-tests.php index 6d5e9ee971..33e19b4511 100644 --- a/tests/admin/load-tests.php +++ b/tests/admin/load-tests.php @@ -186,7 +186,7 @@ public function test_perflab_get_modules() { public function test_perflab_get_module_data() { // Use test data directory with demo modules that match the modules declared on top of this file. foreach ( self::$demo_modules as $module_slug => $expected_module_data ) { - $module_data = perflab_get_module_data( TESTS_PLUGIN_DIR . '/tests/testdata/demo-modules/' . $module_slug . '/load.php', $module_slug ); + $module_data = perflab_get_module_data( TESTS_PLUGIN_DIR . '/tests/testdata/demo-modules/' . $module_slug . '/load.php' ); $this->assertSame( $expected_module_data, $module_data ); } } From 86f755346278b3473f727a836af52a99a354576e Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 30 Dec 2021 09:46:43 -0700 Subject: [PATCH 19/20] Remove focus from default_headers --- admin/load.php | 1 - 1 file changed, 1 deletion(-) diff --git a/admin/load.php b/admin/load.php index a3a50463b6..11b27a98fe 100644 --- a/admin/load.php +++ b/admin/load.php @@ -292,7 +292,6 @@ function perflab_get_module_data( $module_file ) { $default_headers = array( 'name' => 'Module Name', 'description' => 'Description', - 'focus' => 'Focus', 'experimental' => 'Experimental', ); From 0936560ce3140ce637e1ae6c4ae5faddd567dccf Mon Sep 17 00:00:00 2001 From: Adam Silverstein Date: Thu, 30 Dec 2021 11:05:06 -0700 Subject: [PATCH 20/20] Adjust test object to match new parsing result --- tests/admin/load-tests.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/admin/load-tests.php b/tests/admin/load-tests.php index 33e19b4511..2b1acc00b8 100644 --- a/tests/admin/load-tests.php +++ b/tests/admin/load-tests.php @@ -11,22 +11,22 @@ class Admin_Load_Tests extends WP_UnitTestCase { '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', ), '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', ), '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', ), );