discover = $discover; if ( array_key_exists( 'credentials', $selection ) ) { $ids = $selection['credentials']; // Native in the required PHP 8.1; does not depend on WordPress 6.5's polyfill. if ( ! is_array( $ids ) || ! array_is_list( $ids ) || count( $ids ) > self::MAX_CHOICES ) { throw new \RuntimeException( 'Invalid credential selection.' ); } foreach ( $ids as $id ) { if ( ! is_string( $id ) || ! preg_match( '/^[a-f0-9]{64}$/D', $id ) ) { throw new \RuntimeException( 'Invalid credential selection.' ); } } $this->selected = array_fill_keys( $ids, true ); } } public static function context( string $table, string $key, array $row, array $primary ): array { $identity = $primary ? array_intersect_key( $row, array_fill_keys( $primary, true ) ) : $row; $row_id = hash_hmac( 'sha256', serialize( [ $table, $identity ] ), wp_salt( 'auth' ) ); $label = $key ?: 'Row ' . substr( $row_id, 0, 10 ); // Metadata can repeat the same key; identify the exact row without exposing primary-key values. if ( isset( $row['meta_key'] ) ) { $label .= ' ยท ' . substr( $row_id, 0, 10 ); } return [ 'table' => $table, 'row' => $row_id, 'label' => $label, 'key' => $key ]; } public function keep( array $context, string $column, array $path, $value ): bool { // Empty fields carry no credential and need no checkbox or destructive normalization. if ( null === $value || '' === $value || false === $value || [] === $value ) { return true; } $id = hash_hmac( 'sha256', serialize( [ $context['table'], $context['row'], $column, $path, $value ] ), wp_salt( 'auth' ) ); if ( $this->discover && ! isset( $this->found[ $id ] ) ) { if ( count( $this->found ) >= self::MAX_CHOICES ) { throw new \RuntimeException( 'More than 500 credential fields were detected. Narrow the content or user selection before scanning again.' ); } $field = $path ? (string) end( $path ) : ( in_array( $column, [ 'option_value', 'meta_value' ], true ) && $context['key'] ? $context['key'] : $column ); $location = $context['table'] . ' / ' . $context['label'] . ' / ' . $column; if ( $path ) { $location .= ' / ' . implode( ' / ', array_map( 'strval', $path ) ); } $this->found[ $id ] = [ 'id' => $id, 'field' => sanitize_text_field( $field ), 'location' => sanitize_text_field( $location ), 'selected' => false ]; } if ( isset( $this->selected[ $id ] ) ) { $this->matched[ $id ] = true; } return ! $this->discover && isset( $this->selected[ $id ] ); } public function catalog(): array { $items = array_values( $this->found ); usort( $items, static fn( $a, $b ) => strcmp( $a['location'], $b['location'] ) ); return $items; } public function validate(): void { if ( ! $this->discover && array_diff_key( $this->selected, $this->matched ) ) { throw new \RuntimeException( 'A selected credential changed or is outside the selected data. Refresh the credential list and choose it again.' ); } } }