sybrew/the-seo-framework

Upgrade to PHP 8.2

Opened this issue · 3 comments

sybrew commented

See #98 and #608.

We expect TSF v5.0 to be released late 2024-- that's when most sites have hopefully upgraded to a secure PHP version–that'd be 8.2. See https://www.php.net/supported-versions.php.

Since the jump from PHP 8.0 to 8.2 is perceived as minor, we expect that most PHP 8.X users will be on 8.2 by the time we upgrade from 7.4.

Features we'd want to utilize

PHP 8.0

  • Named arguments
    • Makes code much more readable.
  • Construction promotion
    • Instantly shows that construction arguments become class properties. This should improve readability and reduce code footprint.
    • However, I have never seen this used before (probably because PHP 8 isn't in widespread use), so I'm not sure if future coders will understand this.
  • Match expression
    • Condenses return-based/value-assigning switch-statements.
  • Nullsafe operator
    • Reduces the need for chaining with isset()/method_exists()/etc., condensing code.
  • str_contains()/str_starts_with()/str_ends_with()
    • Less false/0 !== strpos()/strrpos(), more readable code.

PHP 8.1

  • Named arguments after unpacking
    • Makes code a little more readable.
  • Fibers
    • This is interesting. We can utilize this for generation by suspending coroutines when one value is reached. However, this is quite challenging to make logical, and this feature is probably intended for remote requests.
  • array_is_list()
    • Condenses API functions that rely on lists, or allow both lists (sequential) and associative arrays.
  • Readonly properties
    • This will make me not have to mark everything "@Private".

PHP 8.2

  • Readonly classes
    • Same as readonly properties, but then simpler.
  • Constant in traits
    • Another good reason to start embracing traits and actual OOP.

Conclusion

The tiny list of features in 8.2 does not justify an upgrade unless we can reasonably assume most sites are upgraded.

Proposed version

Ref: https://wordpress.org/about/stats/

We'll upgrade to a version that at least 66% of sites support at our scheduled release. We previously aimed at 85%. However, since WordPress reports data from inactive sites and prevents users from updating plugins with unsupported required PHP versions, I see no issue in upgrading earlier.

TSF v5.0 will have an estimated 6-month development cycle. Hopefully, we can get started somewhere early or even before 2024.
Extension Manager's upgrade will follow soon after that.

chesio commented

I also find enums (added in PHP 8.1) quite useful.

sybrew commented

I simulated the Fiber API here; it's where we could benefit by upgrading, where we need not test for also valid() and next() -- but only resume() (now current()) and isTerminated() (now false):

// Simulate the Fiber API. TODO PHP8.0+ make actual Fiber.
$memo['fiber'] ??= null;
$fiber = &$memo['fiber'];
if ( isset( $fiber ) ) {
// If Fiber's exhausted, go to next generator.
if ( ! $fiber ) continue;
// Iterate to next if still valid from last run.
$fiber->next();
} else {
$fiber = \call_user_func_array( $cb, [ null, $size ] );
}
// phpcs:ignore, WordPress.CodeAnalysis.AssignmentInCondition -- gotta check and end early.
while ( $fiber->valid() || ( $fiber = false ) ) {
$details = \tsf()->s_image_details( static::merge_extra_image_details(
$fiber->current(),
$size,
) );
if ( $details['url'] ) {
yield $memo['values'][] = $details;
if ( $single ) break 2;
}
$fiber->next();
}

We have various functions that could benefit from array_is_list():

// PHP 8.1+, use `!array_is_list()`?
// This is 350x faster than a polyfill for `!array_is_list()`.
if ( [] === $array || array_values( $array ) !== $array ) return $array;

This could be condensed using array unpacking by string (...dimensions,[ etc, ]):

// This returns an array with 'width' and 'height' indexes.
$details += Image\Utils::get_image_dimensions( $details['id'], $size );
// TODO PHP 8.1+ String unpacking in array, so we can directly add the above to it:
$details += [
'alt' => Image\Utils::get_image_alt_tag( $details['id'] ),
'caption' => Image\Utils::get_image_caption( $details['id'] ),
'filesize' => Image\Utils::get_image_filesize( $details['id'], $size ),
];

We're already using str_contains() and str_starts_with() because WordPress provides polyfills.

Some properties could benefit from being readonly -- for now, I marked those as "private" or blocked access altogether by requiring a functional interface. Bypassing the function overhead could speed things up and make the code more readable, especially since the nullsafe operator is also available.

About enums... this requires a new way of thinking about objects -- I'm not sure if it's backportable. I'll look into this one a bit more once we can actually embrace it.

WordPress 6.5+ has a polyfill for array_is_list().