Upgrade PHPStan to 2.x and raise analysis level from 6 to 10
CI / No Debug Code (pull_request) Successful in 3s
CI / Tests (PHP 8.2) (pull_request) Successful in 48s
CI / Tests (PHP 8.3) (pull_request) Successful in 52s
CI / Coding Standards (pull_request) Successful in 57s
CI / Tests (PHP 8.1) (pull_request) Successful in 1m1s
CI / PHPStan (pull_request) Successful in 1m11s
CI / Build Plugin Zip (pull_request) Has been skipped
CI / No Debug Code (pull_request) Successful in 3s
CI / Tests (PHP 8.2) (pull_request) Successful in 48s
CI / Tests (PHP 8.3) (pull_request) Successful in 52s
CI / Coding Standards (pull_request) Successful in 57s
CI / Tests (PHP 8.1) (pull_request) Successful in 1m1s
CI / PHPStan (pull_request) Successful in 1m11s
CI / Build Plugin Zip (pull_request) Has been skipped
- Bump phpstan/phpstan ^2.0 and szepeviktor/phpstan-wordpress ^2.0 - Move the analysis level into phpstan.neon (single source) and raise it to 10 - Add Val, a runtime coercion helper that narrows untyped WordPress boundary values (wpdb rows, REST params, superglobals, options) with explicit checks instead of blind casts, plus unit tests - Type value-object fromRow() params as stdClass (what wpdb returns) and map columns through Val so unexpected shapes degrade safely - Use %i identifier placeholders for table names in all wpdb::prepare() calls so every query string is a literal and identifiers are escaped by WordPress; raises the minimum WordPress version to 6.2 where %i was introduced - Guard wpdb::prepare() null result before wpdb::query() in updateTax() - Fix nullable get_permalink()/strtotime() handling, list types at REST and capability call sites, dead null-coalescing on checked superglobals, and narrow get_users() results before mapping - Register Val method names with the ValidatedSanitizedInput sniff so it validates the real sanitizer around each superglobal read - Update repository unit tests for the %i placeholder arguments Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -8,6 +8,7 @@ use Unsupervised\Schedular\Policy\Policy;
|
||||
use Unsupervised\Schedular\Policy\PolicyAcceptance;
|
||||
use Unsupervised\Schedular\Policy\PolicyRepository;
|
||||
use Unsupervised\Schedular\Policy\PolicyVersionRepository;
|
||||
use Unsupervised\Schedular\Val;
|
||||
|
||||
class RegistrationPage {
|
||||
|
||||
@@ -21,7 +22,7 @@ class RegistrationPage {
|
||||
/**
|
||||
* Renders the student registration shortcode output.
|
||||
*
|
||||
* @param array<string, string> $atts Shortcode attributes (unused — reserved for future options).
|
||||
* @param array<string> $atts Shortcode attributes (unused — reserved for future options).
|
||||
*/
|
||||
public function render( array $atts ): string { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
|
||||
if ( is_user_logged_in() ) {
|
||||
@@ -29,7 +30,7 @@ class RegistrationPage {
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- token identifies the invite; the form submit is nonce-checked below.
|
||||
$token = sanitize_text_field( wp_unslash( $_REQUEST['us_invite'] ?? '' ) );
|
||||
$token = sanitize_text_field( Val::string( wp_unslash( $_REQUEST['us_invite'] ?? '' ) ) );
|
||||
// Only the token's hash is stored, so hash the submitted token for lookup.
|
||||
$invite = '' !== $token ? $this->invites->findByToken( Invite::hashToken( $token ) ) : null;
|
||||
|
||||
@@ -64,12 +65,12 @@ class RegistrationPage {
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only token used only to build the redirect target.
|
||||
$token = sanitize_text_field( wp_unslash( $_GET['us_invite'] ?? '' ) );
|
||||
$token = sanitize_text_field( Val::string( wp_unslash( $_GET['us_invite'] ?? '' ) ) );
|
||||
if ( '' === $token ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pageId = (int) get_option( RegistrationController::OPTION_PAGE, 0 );
|
||||
$pageId = Val::int( get_option( RegistrationController::OPTION_PAGE, 0 ) );
|
||||
if ( $pageId <= 0 || is_page( $pageId ) ) {
|
||||
return;
|
||||
}
|
||||
@@ -90,15 +91,16 @@ class RegistrationPage {
|
||||
// The submit nonce is verified by the caller (render) before this runs.
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Missing
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- passwords must not be sanitized.
|
||||
$password = (string) wp_unslash( $_POST['password'] ?? '' );
|
||||
$displayName = sanitize_text_field( wp_unslash( $_POST['display_name'] ?? '' ) );
|
||||
$password = Val::string( wp_unslash( $_POST['password'] ?? '' ) );
|
||||
$displayName = sanitize_text_field( Val::string( wp_unslash( $_POST['display_name'] ?? '' ) ) );
|
||||
|
||||
if ( strlen( $password ) < 8 ) {
|
||||
return esc_html__( 'Please choose a password of at least 8 characters.', 'unsupervised-schedular' );
|
||||
}
|
||||
|
||||
$policyForms = $this->signupPolicies();
|
||||
$accepted = array_map( 'absint', (array) ( $_POST['accept'] ?? [] ) );
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- each element is coerced to a positive int in the array_map callback; slashes cannot survive integer coercion.
|
||||
$accepted = array_map( static fn( mixed $v ): int => absint( Val::int( $v ) ), (array) ( $_POST['accept'] ?? [] ) );
|
||||
// phpcs:enable WordPress.Security.NonceVerification.Missing
|
||||
|
||||
foreach ( $policyForms as $form ) {
|
||||
@@ -141,7 +143,7 @@ class RegistrationPage {
|
||||
*/
|
||||
private function recordAcceptances( array $policyForms, int $userId ): void {
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- IP is stored verbatim for audit.
|
||||
$ip = sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ?? '' ) );
|
||||
$ip = sanitize_text_field( Val::string( wp_unslash( $_SERVER['REMOTE_ADDR'] ?? '' ) ) );
|
||||
|
||||
foreach ( $policyForms as $form ) {
|
||||
$this->acceptances->insert(
|
||||
|
||||
Reference in New Issue
Block a user