Skip to content

Commit

Permalink
Merge pull request #315 from WordPress/enhance/separate-check-reposit…
Browse files Browse the repository at this point in the history
…ory-from-filtering
  • Loading branch information
swissspidy authored Nov 6, 2023
2 parents 74bc890 + b695293 commit 204dadd
Show file tree
Hide file tree
Showing 9 changed files with 431 additions and 61 deletions.
5 changes: 4 additions & 1 deletion includes/Checker/Abstract_Check_Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,10 @@ final public function get_checks_to_run() {
$check_flags = $check_flags | Check_Repository::INCLUDE_EXPERIMENTAL;
}

$checks = $this->check_repository->get_checks( $check_flags, $check_slugs );
$checks = $this->check_repository->get_checks( $check_flags )
->require( $check_slugs ) // Ensures all of the given slugs are valid.
->include( $check_slugs ) // Ensures only the checks with the given slugs are included.
->to_map();

// Filters the checks by specific categories.
$categories = $this->get_categories();
Expand Down
74 changes: 74 additions & 0 deletions includes/Checker/Check_Collection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* Class WordPress\Plugin_Check\Checker\Check_Collection
*
* @package plugin-check
*/

namespace WordPress\Plugin_Check\Checker;

use ArrayAccess;
use Countable;
use Exception;
use IteratorAggregate;

/**
* Check Collection interface.
*
* @since n.e.x.t
*/
interface Check_Collection extends ArrayAccess, Countable, IteratorAggregate {

/**
* Returns the raw indexed array representation of this collection.
*
* @since n.e.x.t
*
* @return array The indexed array of check objects.
*/
public function to_array(): array;

/**
* Returns the raw map of check slugs and their check objects as a representation of this collection.
*
* @since n.e.x.t
*
* @return array Map of `$check_slug => $check_obj` pairs.
*/
public function to_map(): array;

/**
* Returns a new check collection containing the subset of checks based on the given check filter function.
*
* @since n.e.x.t
*
* @param callable $filter_fn Filter function that accepts a single check object and should return a boolean for
* whether to include the check in the new collection.
* @return Check_Collection New check collection, effectively a subset of this one.
*/
public function filter( callable $filter_fn ): Check_Collection;

/**
* Returns a new check collection containing the subset of checks based on the given check slugs.
*
* If the given list is empty, the same collection will be returned without any change.
*
* @since n.e.x.t
*
* @param array $check_slugs List of slugs to limit to only those. If empty, the same collection is returned.
* @return Check_Collection New check collection, effectively a subset of this one.
*/
public function include( array $check_slugs ): Check_Collection;

/**
* Throws an exception if any of the given check slugs are not present, or returns the same collection otherwise.
*
* @since n.e.x.t
*
* @param array $check_slugs List of slugs to limit to only those. If empty, the same collection is returned.
* @return Check_Collection The unchanged check collection.
*
* @throws Exception Thrown when any of the given check slugs is not present in the collection.
*/
public function require( array $check_slugs ): Check_Collection;
}
7 changes: 3 additions & 4 deletions includes/Checker/Check_Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ public function register_check( $slug, Check $check );
*
* @since n.e.x.t
*
* @param int $flags The check type flag.
* @param array $check_slugs An array of check slugs to return.
* @return array An indexed array of check instances.
* @param int $flags The check type flag.
* @return Check_Collection Check collection providing an indexed array of check instances.
*/
public function get_checks( $flags = self::TYPE_ALL, array $check_slugs = array() );
public function get_checks( $flags = self::TYPE_ALL );
}
232 changes: 232 additions & 0 deletions includes/Checker/Default_Check_Collection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
<?php
/**
* Class WordPress\Plugin_Check\Checker\Default_Check_Collection
*
* @package plugin-check
*/

namespace WordPress\Plugin_Check\Checker;

use ArrayIterator;
use Exception;
use Traversable;

/**
* Default Check Collection class.
*
* @since n.e.x.t
*/
class Default_Check_Collection implements Check_Collection {

/**
* Map of `$check_slug => $check_obj` pairs.
*
* @since n.e.x.t
* @var array
*/
private $checks;

/**
* List of check slugs, in the same order as `$checks` - effectively the keys of that array.
*
* @since n.e.x.t
* @var array
*/
private $slugs;

/**
* Constructor.
*
* @since n.e.x.t
*
* @param array $checks Map of `$check_slug => $check_obj` pairs for the collection.
*/
public function __construct( array $checks ) {
$this->checks = $checks;
$this->slugs = array_keys( $this->checks );
}

/**
* Returns the raw indexed array representation of this collection.
*
* @since n.e.x.t
*
* @return array The indexed array of check objects.
*/
public function to_array(): array {
return array_values( $this->checks );
}

/**
* Returns the raw map of check slugs and their check objects as a representation of this collection.
*
* @since n.e.x.t
*
* @return array Map of `$check_slug => $check_obj` pairs.
*/
public function to_map(): array {
return $this->checks;
}

/**
* Returns a new check collection containing the subset of checks based on the given check filter function.
*
* @since n.e.x.t
*
* @param callable $filter_fn Filter function that accepts a single check object and should return a boolean for
* whether to include the check in the new collection.
* @return Check_Collection New check collection, effectively a subset of this one.
*/
public function filter( callable $filter_fn ): Check_Collection {
return new self(
array_filter(
$this->checks,
$filter_fn
)
);
}

/**
* Returns a new check collection containing the subset of checks based on the given check slugs.
*
* If the given list is empty, the same collection will be returned without any change.
*
* @since n.e.x.t
*
* @param array $check_slugs List of slugs to limit to only those. If empty, the same collection is returned.
* @return Check_Collection New check collection, effectively a subset of this one.
*/
public function include( array $check_slugs ): Check_Collection {
// Return unmodified collection if no check slugs to limit to are given.
if ( ! $check_slugs ) {
return $this;
}

$check_slugs = array_flip( $check_slugs );

$checks = array();
foreach ( $this->checks as $slug => $check ) {
if ( ! isset( $check_slugs[ $slug ] ) ) {
continue;
}

$checks[ $slug ] = $check;
}

return new self( $checks );
}

/**
* Throws an exception if any of the given check slugs are not present, or returns the same collection otherwise.
*
* @since n.e.x.t
*
* @param array $check_slugs List of slugs to limit to only those. If empty, the same collection is returned.
* @return Check_Collection The unchanged check collection.
*
* @throws Exception Thrown when any of the given check slugs is not present in the collection.
*/
public function require( array $check_slugs ): Check_Collection {
foreach ( $check_slugs as $slug ) {
if ( ! isset( $this->checks[ $slug ] ) ) {
throw new Exception(
sprintf(
/* translators: %s: The Check slug. */
__( 'Check with the slug "%s" does not exist.', 'plugin-check' ),
$slug
)
);
}
}

return $this;
}

/**
* Counts the checks in the collection.
*
* @since n.e.x.t
*
* @return int Number of checks in the collection.
*/
public function count(): int {
return count( $this->checks );
}

/**
* Returns an iterator for the checks in the collection.
*
* @since n.e.x.t
*
* @return Traversable Checks iterator.
*/
public function getIterator(): Traversable {
return new ArrayIterator( $this->checks );
}

/**
* Checks whether a check exists with the given slug or index.
*
* @since n.e.x.t
*
* @param string|int $offset Either a check slug (string) or index (integer).
* @return bool True if a check exists at the given slug or index, false otherwise.
*/
public function offsetExists( $offset ) {
if ( is_string( $offset ) ) {
return isset( $this->checks[ $offset ] );
}

return isset( $this->slugs[ $offset ] );
}

/**
* Retrieves the check with the given slug or index.
*
* @since n.e.x.t
*
* @param string|int $offset Either a check slug (string) or index (integer).
* @return Check|null Check with the given slug or index, or null if it does not exist.
*/
public function offsetGet( $offset ) {
if ( is_string( $offset ) ) {
if ( isset( $this->checks[ $offset ] ) ) {
return $this->checks[ $offset ];
}
return null;
}

if ( isset( $this->slugs[ $offset ] ) ) {
return $this->checks[ $this->slugs[ $offset ] ];
}

return null;
}

/**
* Sets a check in the collection.
*
* This method does nothing as the collection is read-only.
*
* @since n.e.x.t
*
* @param string|int $offset Either a check slug (string) or index (integer).
* @param mixed $value Value to set.
*/
public function offsetSet( $offset, $value ) {
// Not implemented as this is a read-only collection.
}

/**
* Removes a check from the collection.
*
* This method does nothing as the collection is read-only.
*
* @since n.e.x.t
*
* @param string|int $offset Either a check slug (string) or index (integer).
*/
public function offsetUnset( $offset ) {
// Not implemented as this is a read-only collection.
}
}
34 changes: 5 additions & 29 deletions includes/Checker/Default_Check_Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,10 @@ public function register_check( $slug, Check $check ) {
*
* @since n.e.x.t
*
* @param int $flags The check type flag.
* @param array $check_slugs An array of check slugs to return.
* @return array An array of check instances.
*
* @throws Exception Thrown when invalid flag is passed, or Check slug does not exist.
* @param int $flags The check type flag.
* @return Check_Collection Check collection providing an indexed array of check instances.
*/
public function get_checks( $flags = self::TYPE_ALL, array $check_slugs = array() ) {
public function get_checks( $flags = self::TYPE_ALL ) {
$checks = array();

if ( $flags & self::TYPE_STATIC ) {
Expand All @@ -99,34 +96,13 @@ public function get_checks( $flags = self::TYPE_ALL, array $check_slugs = array(
$checks += $this->runtime_checks;
}

// Filter out the specific check slugs requested.
if ( ! empty( $check_slugs ) ) {
$checks = array_map(
function ( $slug ) use ( $checks ) {
if ( ! isset( $checks[ $slug ] ) ) {
throw new Exception(
sprintf(
/* translators: %s: The Check slug. */
__( 'Check with the slug "%s" does not exist.', 'plugin-check' ),
$slug
)
);
}

return $checks[ $slug ];
},
$check_slugs
);
}

// Return all checks, including experimental if requested.
if ( $flags & self::INCLUDE_EXPERIMENTAL ) {
return $checks;
return new Default_Check_Collection( $checks );
}

// Remove experimental checks before returning.
return array_filter(
$checks,
return ( new Default_Check_Collection( $checks ) )->filter(
static function ( $check ) {
return $check->get_stability() !== Check::STABILITY_EXPERIMENTAL;
}
Expand Down
Loading

0 comments on commit 204dadd

Please sign in to comment.