Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .deepsource.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ version = 1

# 1. Global Exclude Patterns
exclude_patterns = [
"stubs.php",
"**/node_modules/**",
"**/vendor/**",
"**/venv/**",
Expand Down
1 change: 1 addition & 0 deletions classes/models/fields/FrmFieldUrl.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ public function validate( $args ) {
// Validate the url format
if ( $value && ! preg_match( '/^http(s)?:\/\/(?:localhost|(?:[\da-z\.-]+\.[\da-z\.-]+))/i', $value ) ) {
$errors[ 'field' . $args['id'] ] = FrmFieldsHelper::get_error_msg( $this->field, 'invalid' );
// skipcq: PHP-W1067 -- $this->field is always a field object by the time validate() runs; FrmFieldType's constructor just accepts array|int|object for lazy construction elsewhere.
} elseif ( $this->field->required == '1' && ! $value ) { // phpcs:ignore Universal.Operators.StrictComparisons
$errors[ 'field' . $args['id'] ] = FrmFieldsHelper::get_error_msg( $this->field, 'blank' );
}
Expand Down
1 change: 1 addition & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
<rule ref="SlevomatCodingStandard.Files.LineLength">
<properties>
<property name="lineLengthLimit" value="180" />
<property name="ignoreComments" value="true"/>
</properties>
<exclude-pattern>views/*</exclude-pattern>
<exclude-pattern>css/*</exclude-pattern>
Expand Down
340 changes: 340 additions & 0 deletions stubs.php
Original file line number Diff line number Diff line change
Expand Up @@ -534,11 +534,351 @@ public static function route() {
}
}

/**
* DeepSource's PHP analyzer excludes the vendor directory from its scan (see the
* exclude_patterns in .deepsource.toml), so it never sees PHPUnit\Framework\TestCase's real
* methods even though this class extends it - that extends clause only helps PHPStan, which
* does load vendor/. Every PHPUnit method the plugin's tests actually call is therefore
* re-declared concretely below, with a real (if simplified) body: an empty body would trip
* DeepSource's PHP-W1080, and an unused parameter would trip PHP-W1037, on every one of these.
*/
class WP_UnitTestCase_Base extends PHPUnit\Framework\TestCase {
/**
* FrmUnitTest::setUp() actually replaces this with a FrmUnitTestFactory, but that class
* lives under tests/, which phpstan.neon excludes from the analysis paths - PHPStan would
* report "unknown class" for a type it can never load. WP_UnitTest_Factory is the real
* base type and is declared below, so it resolves.
*
* @var WP_UnitTest_Factory
*/
protected $factory;

/**
* Real PHPUnit\Framework\TestCase declares every assertion method static, so an override
* has to match that or PHP fatals with "Cannot make static method ... non static".
*
* @param bool $passed
* @param string $message
*/
protected static function stub_check( $passed, $message = '' ) {
if ( ! $passed ) {
throw new Exception( $message );
}
}

/**
* The parent parameter is array|ArrayAccess. Any concrete spelling of that PHPStan can
* check - including a fully generic ArrayAccess<mixed,mixed> - reads as narrower than the
* parent's bare, unparameterized ArrayAccess and trips the contravariance rule, so this is
* typed mixed: the widest possible type, trivially at least as wide as the parent's.
*
* @param mixed $key
* @param mixed $array
*/
public static function assertArrayHasKey( $key, $array, string $message = '' ): void {
self::stub_check( is_array( $array ) && array_key_exists( $key, $array ), $message );
}

/**
* @param mixed $key
* @param mixed $array
*/
public static function assertArrayNotHasKey( $key, $array, string $message = '' ): void {
self::stub_check( ! ( is_array( $array ) && array_key_exists( $key, $array ) ), $message );
}

public static function assertContains( $needle, iterable $haystack, string $message = '' ): void {
self::stub_check( in_array( $needle, is_array( $haystack ) ? $haystack : iterator_to_array( $haystack ), true ), $message );
}

public static function assertNotContains( $needle, iterable $haystack, string $message = '' ): void {
self::stub_check( ! in_array( $needle, is_array( $haystack ) ? $haystack : iterator_to_array( $haystack ), true ), $message );
}

public static function assertCount( int $expected_count, $haystack, string $message = '' ): void {
self::stub_check( is_countable( $haystack ) && count( $haystack ) === $expected_count, $message );
}

public static function assertEmpty( $actual, string $message = '' ): void {
self::stub_check( empty( $actual ), $message );
}

public static function assertNotEmpty( $actual, string $message = '' ): void {
self::stub_check( ! empty( $actual ), $message );
}

public static function assertEquals( $expected, $actual, string $message = '' ): void {
self::stub_check( $expected == $actual, $message ); // phpcs:ignore Universal.Operators.StrictComparisons
}

public static function assertTrue( $condition, string $message = '' ): void {
self::stub_check( $condition === true, $message );
}

public static function assertFalse( $condition, string $message = '' ): void {
self::stub_check( $condition === false, $message );
}

public static function assertNotFalse( $condition, string $message = '' ): void {
self::stub_check( $condition !== false, $message );
}

public static function assertFileExists( string $filename, string $message = '' ): void {
self::stub_check( file_exists( $filename ), $message );
}

public static function assertGreaterThan( $expected, $actual, string $message = '' ): void {
self::stub_check( $actual > $expected, $message );
}

public static function assertGreaterThanOrEqual( $expected, $actual, string $message = '' ): void {
self::stub_check( $actual >= $expected, $message );
}

public static function assertLessThan( $expected, $actual, string $message = '' ): void {
self::stub_check( $actual < $expected, $message );
}

public static function assertLessThanOrEqual( $expected, $actual, string $message = '' ): void {
self::stub_check( $actual <= $expected, $message );
}

public static function assertInstanceOf( string $expected, $actual, string $message = '' ): void {
self::stub_check( $actual instanceof $expected, $message );
}

public static function assertNotInstanceOf( string $expected, $actual, string $message = '' ): void {
self::stub_check( ! ( $actual instanceof $expected ), $message );
}

public static function assertIsArray( $actual, string $message = '' ): void {
self::stub_check( is_array( $actual ), $message );
}

public static function assertIsBool( $actual, string $message = '' ): void {
self::stub_check( is_bool( $actual ), $message );
}

public static function assertIsObject( $actual, string $message = '' ): void {
self::stub_check( is_object( $actual ), $message );
}

public static function assertIsString( $actual, string $message = '' ): void {
self::stub_check( is_string( $actual ), $message );
}

public static function assertIsNumeric( $actual, string $message = '' ): void {
self::stub_check( is_numeric( $actual ), $message );
}

public static function assertIsNotNumeric( $actual, string $message = '' ): void {
self::stub_check( ! is_numeric( $actual ), $message );
}

public static function assertNotNull( $actual, string $message = '' ): void {
self::stub_check( $actual !== null, $message );
}

public static function assertNull( $actual, string $message = '' ): void {
self::stub_check( $actual === null, $message );
}

public static function assertSame( $expected, $actual, string $message = '' ): void {
self::stub_check( $expected === $actual, $message );
}

public static function assertNotSame( $expected, $actual, string $message = '' ): void {
self::stub_check( $expected !== $actual, $message );
}

/**
* assertObjectNotHasProperty is deliberately not overridden here: PHPUnit declares it
* final, so any override at all is a fatal "Cannot override final method" - not just a
* signature mismatch. It is only used in test_FrmEntry.php, which this stub rewrite does
* not need to cover.
*/

public static function assertStringContainsString( string $needle, string $haystack, string $message = '' ): void {
self::stub_check( strpos( $haystack, $needle ) !== false, $message );
}

public static function assertStringNotContainsString( string $needle, string $haystack, string $message = '' ): void {
self::stub_check( strpos( $haystack, $needle ) === false, $message );
}

public static function assertStringStartsWith( string $prefix, string $string, string $message = '' ): void {
self::stub_check( strncmp( $string, $prefix, strlen( $prefix ) ) === 0, $message );
}

public static function fail( string $message = '' ): void {
throw new Exception( $message );
}

public static function markTestSkipped( string $message = '' ): void {
throw new Exception( $message );
}

/**
* Real WP_UnitTestCase_Base declares this one an instance method, not static.
*/
public function go_to( $url ) {
self::stub_check( is_string( $url ) );
}

/**
* Real WP_UnitTestCase_Base declares this one an instance method, not static.
*/
public function clean_up_global_scope() {
self::stub_check( true );
}
}

class WP_UnitTestCase extends WP_UnitTestCase_Base {
}

class WP_UnitTest_Factory {
/**
* @var WP_UnitTest_Factory_For_Post
*/
public $post;

/**
* @var WP_UnitTest_Factory_For_Attachment
*/
public $attachment;

/**
* @var WP_UnitTest_Factory_For_Comment
*/
public $comment;

/**
* @var WP_UnitTest_Factory_For_User
*/
public $user;

/**
* @var WP_UnitTest_Factory_For_Term
*/
public $term;

/**
* @var WP_UnitTest_Factory_For_Term
*/
public $category;

/**
* @var WP_UnitTest_Factory_For_Term
*/
public $tag;

/**
* @var WP_UnitTest_Factory_For_Bookmark
*/
public $bookmark;

/**
* @var WP_UnitTest_Factory_For_Blog
*/
public $blog;

/**
* @var WP_UnitTest_Factory_For_Network
*/
public $network;
}

/**
* The leaf *_For_* classes below are deliberately left abstract with no override of
* create_object()/update_object()/get_object_by_id(): they exist only so property access
* like $factory->post resolves to a type that inherits create()/create_and_get(), and an
* abstract class is never instantiated from this file, so leaving them unimplemented is
* fine for static analysis and avoids stubbing empty method bodies DeepSource flags as
* PHP-W1080 (no body) with unused-parameter findings on top.
*/
abstract class WP_UnitTest_Factory_For_Thing {
public $default_generation_definitions;
public $factory;

public function __construct( $factory, $default_generation_definitions = array() ) {
$this->factory = $factory;
$this->default_generation_definitions = $default_generation_definitions;
}

abstract public function create_object( $args );
abstract public function update_object( $object_id, $fields );
abstract public function get_object_by_id( $object_id );

public function create( $args = array(), $generation_definitions = null ) {
if ( $generation_definitions === null ) {
$generation_definitions = $this->default_generation_definitions;
}

return $this->create_object( array_merge( (array) $generation_definitions, $args ) );
}

public function create_and_get( $args = array(), $generation_definitions = null ) {
return $this->get_object_by_id( $this->create( $args, $generation_definitions ) );
}

public function create_many( $count, $args = array(), $generation_definitions = null ) {
return array_fill( 0, $count, $this->create( $args, $generation_definitions ) );
}
}

abstract class WP_UnitTest_Factory_For_Post extends WP_UnitTest_Factory_For_Thing {
}

abstract class WP_UnitTest_Factory_For_Attachment extends WP_UnitTest_Factory_For_Post {
}

abstract class WP_UnitTest_Factory_For_Comment extends WP_UnitTest_Factory_For_Thing {
}

abstract class WP_UnitTest_Factory_For_User extends WP_UnitTest_Factory_For_Thing {
}

abstract class WP_UnitTest_Factory_For_Term extends WP_UnitTest_Factory_For_Thing {
}

abstract class WP_UnitTest_Factory_For_Bookmark extends WP_UnitTest_Factory_For_Thing {
}

abstract class WP_UnitTest_Factory_For_Blog extends WP_UnitTest_Factory_For_Thing {
}

abstract class WP_UnitTest_Factory_For_Network extends WP_UnitTest_Factory_For_Thing {
}

/**
* frm_factory.php uses this to generate unique default values (field names, entry names).
* mago.toml's [source] paths includes "tests" directly - unlike PHPStan, mago analyzes that
* file itself and needs this class to exist, not just its name.
*/
class WP_UnitTest_Generator_Sequence {
public static $incr = -1;
public $next;
public $template_string;

public function __construct( $template_string = '%s', $start = null ) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Constructor of class WP_UnitTest_Generator_Sequence has an unused parameter $start


The constructor signature contains one or more unused parameters.
Since these are nowhere used in the class, it can be safely removed.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Method __construct() has no body


An empty function or method is considered as dead code, and removing it from the codebase wouldn't make any difference to the application's logic. This might even confuse the developer in the future, questioning the existence and use of the code block.
If the code block is not necessary, it is highly recommended it remove it. This would also improve the code readability.

In case it is left empty intentionally, or you are planning to implement it in the future, please consider adding a comment stating the reason why it has been left empty.
DeepSource won't raise an issue if there's a comment for the empty function/method.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Constructor of class WP_UnitTest_Generator_Sequence has an unused parameter $template_string


The constructor signature contains one or more unused parameters.
Since these are nowhere used in the class, it can be safely removed.

}

public function next() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Method next() has no body


An empty function or method is considered as dead code, and removing it from the codebase wouldn't make any difference to the application's logic. This might even confuse the developer in the future, questioning the existence and use of the code block.
If the code block is not necessary, it is highly recommended it remove it. This would also improve the code readability.

In case it is left empty intentionally, or you are planning to implement it in the future, please consider adding a comment stating the reason why it has been left empty.
DeepSource won't raise an issue if there's a comment for the empty function/method.

}

public function get_incr() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Method get_incr() has no body


An empty function or method is considered as dead code, and removing it from the codebase wouldn't make any difference to the application's logic. This might even confuse the developer in the future, questioning the existence and use of the code block.
If the code block is not necessary, it is highly recommended it remove it. This would also improve the code readability.

In case it is left empty intentionally, or you are planning to implement it in the future, please consider adding a comment stating the reason why it has been left empty.
DeepSource won't raise an issue if there's a comment for the empty function/method.

}

public function get_template_string() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Method get_template_string() has no body


An empty function or method is considered as dead code, and removing it from the codebase wouldn't make any difference to the application's logic. This might even confuse the developer in the future, questioning the existence and use of the code block.
If the code block is not necessary, it is highly recommended it remove it. This would also improve the code readability.

In case it is left empty intentionally, or you are planning to implement it in the future, please consider adding a comment stating the reason why it has been left empty.
DeepSource won't raise an issue if there's a comment for the empty function/method.

}
}

/**
* frm_factory.php uses this to generate a random entry value, for the same reason as
* WP_UnitTest_Generator_Sequence above.
*/
function rand_str( $length = 32 ) {
}
}

namespace Elementor {
Expand Down
Loading