Skip to content

Conversation

@costdev
Copy link
Contributor

@costdev costdev commented Dec 6, 2021

This PR implements a preloader for the upgrade process.

  • This is set to preload the wp-includes/Requests directory.
  • This is set to skip preloading wp-includes/Requests/Autoload.php on WP < 5.9.
  • These are in place as examples but should be part of the overall audit.

Source

  • Allow preloading files.
  • Allow recursively preloading directories.
  • Allow skipping files from preloading.
  • Identify additional functionality that may be needed. Please identify in a review for discussion.
  • Identify additional functionality that may be helpful. Please suggest in a review for discussion.
  • Audit additional files needed by the upgrader.
  • Add the additional paths to the preloader, skipping individual files where necessary.

Tests

  • Add initial tests.
  • If necessary, review the sample files implementation for an alternative.
  • Add more tests.
  • Manual testing.
  • Review documentation.

Trac ticket: https://core.trac.wordpress.org/ticket/54589

@costdev costdev marked this pull request as draft December 6, 2021 17:30
@costdev costdev force-pushed the core_upgrade_preloader branch 13 times, most recently from 6a6fbaa to b9c16aa Compare December 7, 2021 09:31
@costdev costdev force-pushed the core_upgrade_preloader branch from b9c16aa to 6338df4 Compare January 22, 2022 11:12
@costdev costdev force-pushed the core_upgrade_preloader branch from 6338df4 to 8f67690 Compare January 22, 2022 11:13
// Preload files.
$dangerous_paths = array( '', '.', '/' );

foreach ( $preload_paths as $path ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

take a look at validate_file(), I suspect you are doubling up a few things here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice @peterwilsoncc, hadn't thought of that at the time. validate_file() should work nicely here.


// Add errors to the overall list.
if ( is_wp_error( $result ) ) {
$errors->errors = array_merge( $errors->errors, $result->errors );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. This should actually use WP_Error::merge_from().

i.e.

$errors->merge_from( $result );
// This is a directory. Recurse.
if ( $wp_filesystem->is_dir( $fullpath ) ) {
// Get the file or subdirectory names.
$contents = array_keys( $wp_filesystem->dirlist( $fullpath, false, false ) );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll split this out to first check if dirlist() has returned false. If it has, I can add a WP_Error for dirlist_not_returned, then continue.

@BrianHenryIE
Copy link

BrianHenryIE commented Jun 8, 2022

The tests seem inadequate.

If class-foo.php, e.g.

class Foo extends Bar {} 

is require_once'd before class-bar.php has been, then it will fail.

I'm not familiar with the WordPress build process itself, but how I would approach this is:

Use Composer\Autoload\ClassMapGenerator::createMap() to build a classmap from the autoload key in the library.
Use either regex (or maybe Rector related tool php-parser) to read each PHP file and know which rely on none and which ones subclass/implement/use others.
Build a new "ordered" classmap that can safely be used with require_once.
This new classmap can be used in a regular autoloader too.

I worked on a library for prefixing namespaces for WordPress plugins to avoid conflicts: https://github.com/BrianHenryIE/strauss

(my point was to show how I've thought of this in terms of WordPress already. But it's honest to say: The same code could be used to rename namespaces, i.e. the WpOrg WPorg WordPress Wordpress namespace discussion that was earlier.)

Again, I'm not familiar with the WordPress build process and how it could use Composer libraries, but I do see how Strauss's functionality could be split into another library that helps this issue – ultimately listing all classes in a library and ordering them based on what they require (extend/implement/use) before require_once.

@BrianHenryIE
Copy link

I put together a proof of concept here: https://github.com/BrianHenryIE/composer-require-once

It's really just one function in one class, with a test running against Requests.

Requires composer/composer and nikic/php-parser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants