Skip to content

Commit

Permalink
Merge pull request #195 from IanDelMar/import-extensions
Browse files Browse the repository at this point in the history
Add conditional return types for several functions
  • Loading branch information
szepeviktor authored Sep 8, 2024
2 parents fc274f7 + 53aac37 commit d2a203c
Show file tree
Hide file tree
Showing 13 changed files with 409 additions and 13 deletions.
11 changes: 10 additions & 1 deletion functionMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

$httpReturnType = 'array{headers: \WpOrg\Requests\Utility\CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_Http_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error';
$httpReturnType = 'array{headers: \WpOrg\Requests\Utility\CaseInsensitiveDictionary, body: string, response: array{code: int, message: string}, cookies: array<int, \WP_Http_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error';

if (file_exists(sprintf('%s/source/wordpress/wp-includes/Requests/Cookie/Jar.php', __DIR__))) {
$httpReturnType = 'array{headers: \Requests_Utility_CaseInsensitiveDictionary, body: string, response: array{code: int,message: string}, cookies: array<int, \WP_Http_Cookie>, filename: string|null, http_response: \WP_HTTP_Requests_Response}|\WP_Error';
Expand Down Expand Up @@ -177,6 +177,15 @@
'WP_Widget::form' => [null, 'instance' => 'T'],
'WP_Widget::update' => [null, 'new_instance' => 'T', 'old_instance' => 'T'],
'WP_Widget::widget' => [null, 'instance' => 'T', 'args' => 'array{name:string,id:string,description:string,class:string,before_widget:string,after_widget:string,before_title:string,after_title:string,before_sidebar:string,after_sidebar:string,show_in_rest:boolean,widget_id:string,widget_name:string}'],
'get_approved_comments' => ["(\$args is array{count: true} ? int : (\$args is array{fields: 'ids'} ? array<int, int> : array<int, \WP_Comment>))"],
'get_posts' => ["(\$args is array{fields: 'id=>parent'|'ids'} ? array<int, int> : array<int, \WP_Post>)"],
'get_sites' => ["(\$args is array{count: true} ? int : (\$args is array{fields: 'ids'} ? array<int, int> : array<int, \WP_Site>))"],
'get_tags' => ["(\$args is array{fields: 'count'} ? numeric-string : (\$args is array{fields: 'names'|'slugs'} ? list<string> : (\$args is array{fields: 'id=>name'|'id=>slug'} ? array<int, string> : (\$args is array{fields: 'id=>parent'} ? array<int, int> : (\$args is array{fields: 'ids'|'tt_ids'} ? list<int> : array<int, \WP_Term>)))))|\WP_Error"],
'get_terms' => ["(\$args is array{fields: 'count'} ? numeric-string : (\$args is array{fields: 'names'|'slugs'} ? list<string> : (\$args is array{fields: 'id=>name'|'id=>slug'} ? array<int, string> : (\$args is array{fields: 'id=>parent'} ? array<int, int> : (\$args is array{fields: 'ids'|'tt_ids'} ? list<int> : array<int, \WP_Term>)))))|\WP_Error"],
'wp_get_post_categories' => ["(\$post_id is 0 ? array{} : ((\$args is array{fields: 'names'|'slugs'} ? list<string> : (\$args is array{fields: 'id=>name'|'id=>slug'} ? array<int, string> : (\$args is array{fields: 'id=>parent'} ? array<int, int> : (\$args is array{fields: 'all'|'all_with_object_id'} ? array<int, \WP_Term> : (\$args is array{fields: 'count'} ? numeric-string : list<int>)))))|\WP_Error))"],
'wp_get_post_tags' => ["(\$post_id is 0 ? array{} : ((\$args is array{fields: 'names'|'slugs'} ? list<string> : (\$args is array{fields: 'id=>name'|'id=>slug'} ? array<int, string> : (\$args is array{fields: 'id=>parent'} ? array<int, int> : (\$args is array{fields: 'ids'|'tt_ids'} ? list<int> : (\$args is array{fields: 'count'} ? numeric-string : array<int, \WP_Term>)))))|\WP_Error))"],
'wp_get_post_terms' => ["(\$post_id is 0 ? array{} : (\$taxonomy is empty ? array{} : ((\$args is array{fields: 'names'|'slugs'} ? list<string> : (\$args is array{fields: 'id=>name'|'id=>slug'} ? array<int, string> : (\$args is array{fields: 'id=>parent'} ? array<int, int> : (\$args is array{fields: 'ids'|'tt_ids'} ? list<int> : (\$args is array{fields: 'count'} ? numeric-string : array<int, \WP_Term>)))))|\WP_Error)))"],
'wp_get_object_terms' => ["(\$object_ids is empty ? array{} : (\$taxonomies is empty ? array{} : ((\$args is array{fields: 'names'|'slugs'} ? list<string> : (\$args is array{fields: 'id=>name'|'id=>slug'} ? array<int, string> : (\$args is array{fields: 'id=>parent'} ? array<int, int> : (\$args is array{fields: 'ids'|'tt_ids'} ? list<int> : (\$args is array{fields: 'count'} ? numeric-string : array<int, \WP_Term>)))))|\WP_Error)))"],
'wp_parse_list' => ['($input_list is array ? array<scalar> : list<string>)'],
'wp_parse_str' => [null, '@phpstan-param-out' => 'array<int|string, array|string> $result'],
'size_format' => ["(\$bytes is not numeric ? false : (\$bytes is negative-int|'0' ? false : string))"],
Expand Down
3 changes: 3 additions & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
<rule ref="WordPress.WP.GlobalVariablesOverride">
<exclude-pattern>tests/</exclude-pattern>
</rule>
<rule ref="NeutronStandard.Functions.LongFunction.LongFunction">
<exclude-pattern>tests/TypeInferenceTest.php</exclude-pattern>
</rule>
<rule ref="NeutronStandard.Functions.TypeHint.UnusedReturnType">
<exclude-pattern>tests/TypeInferenceTest.php</exclude-pattern>
</rule>
Expand Down
9 changes: 9 additions & 0 deletions tests/TypeInferenceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/_get_list_table.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/current_time.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/echo_parameter.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_approved_comments.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_attachment_taxonomies.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_bookmark.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_categories.php');
Expand All @@ -22,9 +23,13 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_post.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_post_stati.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_post_types.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_posts.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_page_by_path.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_permalink.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_sites.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_tags.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_term_by.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_terms.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_taxonomies.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_term.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/get_taxonomies_for_attachments.php');
Expand All @@ -40,6 +45,10 @@ public function dataFileAsserts(): iterable
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_error_parameter.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_generate_tag_cloud.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_get_archives.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_get_post_categories.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_get_post_tags.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_get_post_terms.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_get_object_terms.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_is_numeric_array.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_list_bookmarks.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/wp_list_categories.php');
Expand Down
20 changes: 20 additions & 0 deletions tests/data/get_approved_comments.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

declare(strict_types=1);

namespace PhpStubs\WordPress\Core\Tests;

use function get_approved_comments;
use function PHPStan\Testing\assertType;

assertType('array<int, WP_Comment>', get_approved_comments(1));

assertType('int', get_approved_comments(1, ['count' => true]));

assertType('int', get_approved_comments(1, ['count' => true,'fields' => 'ids']));

assertType('array<int, WP_Comment>', get_approved_comments(1, ['count' => false]));

assertType('array<int, int>', get_approved_comments(1, ['fields' => 'ids']));

assertType('array<int, int>', get_approved_comments(1, ['count' => false, 'fields' => 'ids']));
67 changes: 67 additions & 0 deletions tests/data/get_posts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace PhpStubs\WordPress\Core\Tests;

use function get_posts;
use function PHPStan\Testing\assertType;

assertType('array<int, WP_Post>', get_posts());
assertType('array<int, WP_Post>', get_posts(['key' => 'value']));
assertType('array<int, WP_Post>', get_posts(['fields' => '']));
assertType('array<int, int>', get_posts(['fields' => 'ids']));
assertType('array<int, int>', get_posts(['fields' => 'id=>parent']));
assertType('array<int, WP_Post>', get_posts(['fields' => 'Hello']));

// Nonconstant array
assertType('array<int, int|WP_Post>', get_posts((array)$_GET['array']));

// Unions
$union = $_GET['foo'] ? ['key' => 'value'] : ['some' => 'thing'];
assertType('array<int, WP_Post>', get_posts($union));

$union = $_GET['foo'] ? ['key' => 'value'] : ['fields' => 'ids'];
assertType('array<int, int|WP_Post>', get_posts($union));

$union = $_GET['foo'] ? ['key' => 'value'] : ['fields' => ''];
assertType('array<int, WP_Post>', get_posts($union));

$union = $_GET['foo'] ? ['key' => 'value'] : ['fields' => 'id=>parent'];
assertType('array<int, int|WP_Post>', get_posts($union));

$union = $_GET['foo'] ? ['fields' => ''] : ['fields' => 'ids'];
assertType('array<int, int|WP_Post>', get_posts($union));

$union = $_GET['foo'] ? ['fields' => ''] : ['fields' => 'id=>parent'];
assertType('array<int, int|WP_Post>', get_posts($union));

$union = $_GET['foo'] ? ['fields' => 'ids'] : ['fields' => 'id=>parent'];
assertType('array<int, int>', get_posts($union));

$union = $_GET['foo'] ? (array)$_GET['array'] : ['fields' => ''];
assertType('array<int, int|WP_Post>', get_posts($union));

$union = $_GET['foo'] ? (array)$_GET['array'] : ['fields' => 'ids'];
assertType('array<int, int|WP_Post>', get_posts($union));

$union = $_GET['foo'] ? (array)$_GET['array'] : ['fields' => 'id=>parent'];
assertType('array<int, int|WP_Post>', get_posts($union));

$union = $_GET['foo'] ? (string)$_GET['string'] : '';
assertType('array<int, int|WP_Post>', get_posts(['fields' => $union]));

$union = $_GET['foo'] ? (string)$_GET['string'] : 'ids';
assertType('array<int, int|WP_Post>', get_posts(['fields' => $union]));

$union = $_GET['foo'] ? (string)$_GET['string'] : 'id=>parent';
assertType('array<int, int|WP_Post>', get_posts(['fields' => $union]));

$union = $_GET['foo'] ? (string)$_GET['string'] : 'fields';
assertType('array<int, WP_Post>', get_posts([$union => '']));

$union = $_GET['foo'] ? (string)$_GET['string'] : 'fields';
assertType('array<int, int|WP_Post>', get_posts([$union => 'ids']));

$union = $_GET['foo'] ? (string)$_GET['string'] : 'fields';
assertType('array<int, int|WP_Post>', get_posts([$union => 'id=>parent']));
34 changes: 34 additions & 0 deletions tests/data/get_sites.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace PhpStubs\WordPress\Core\Tests;

use function get_sites;
use function PHPStan\Testing\assertType;

// Default parameter
assertType('array<int, WP_Site>', get_sites());
assertType('array<int, WP_Site>', get_sites([]));

// Non constant array parameter
/** @var array<int|string,mixed> $value */
$value = $_GET['foo'];
assertType('array<int, int|WP_Site>|int', get_sites($value));

// Array parameter with explicit fields value and default count value.
assertType('array<int, int>', get_sites(['fields' => 'ids']));
assertType('array<int, WP_Site>', get_sites(['fields' => '']));
assertType('array<int, WP_Site>', get_sites(['fields' => 'nonEmptyString']));

// Array parameter with count set to true.
assertType('int', get_sites(['count' => true]));
assertType('int', get_sites(['fields' => '', 'count' => true]));
assertType('int', get_sites(['fields' => 'ids', 'count' => true]));
assertType('int', get_sites(['fields' => 'nonEmptyString', 'count' => true]));

// Array parameter with count set to false.
assertType('array<int, WP_Site>', get_sites(['count' => false]));
assertType('array<int, WP_Site>', get_sites(['fields' => '', 'count' => false]));
assertType('array<int, int>', get_sites(['fields' => 'ids', 'count' => false]));
assertType('array<int, WP_Site>', get_sites(['fields' => 'nonEmptyString', 'count' => false]));
37 changes: 37 additions & 0 deletions tests/data/get_tags.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace PhpStubs\WordPress\Core\Tests;

use function get_tags;
use function PHPStan\Testing\assertType;

// Default argument values (fields => all)
assertType('array<int, WP_Term>|WP_Error', get_tags());
assertType('array<int, WP_Term>|WP_Error', get_tags([]));

// Requesting a count
assertType('numeric-string|WP_Error', get_tags(['fields' => 'count']));
assertType('numeric-string|WP_Error', get_tags(['foo' => 'bar','fields' => 'count']));

// Requesting names or slugs
assertType('list<string>|WP_Error', get_tags(['fields' => 'names']));
assertType('list<string>|WP_Error', get_tags(['fields' => 'slugs']));
assertType('array<int, string>|WP_Error', get_tags(['fields' => 'id=>name']));
assertType('array<int, string>|WP_Error', get_tags(['fields' => 'id=>slug']));

// Requesting IDs
assertType('list<int>|WP_Error', get_tags(['fields' => 'ids']));
assertType('list<int>|WP_Error', get_tags(['fields' => 'tt_ids']));

// Requesting parent IDs
assertType('array<int, int>|WP_Error', get_tags(['fields' => 'id=>parent']));

// Requesting objects
assertType('array<int, WP_Term>|WP_Error', get_tags(['fields' => 'all']));
assertType('array<int, WP_Term>|WP_Error', get_tags(['fields' => 'all_with_object_id']));
assertType('array<int, WP_Term>|WP_Error', get_tags(['fields' => 'foo']));

// Unknown fields value
assertType('array<int, int|string|WP_Term>|numeric-string|WP_Error', get_tags(['fields' => (string)$_GET['fields']]));
37 changes: 37 additions & 0 deletions tests/data/get_terms.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace PhpStubs\WordPress\Core\Tests;

use function get_terms;
use function PHPStan\Testing\assertType;

// Default argument values (fields => all)
assertType('array<int, WP_Term>|WP_Error', get_terms());
assertType('array<int, WP_Term>|WP_Error', get_terms([]));

// Requesting a count
assertType('numeric-string|WP_Error', get_terms(['fields' => 'count']));
assertType('numeric-string|WP_Error', get_terms(['foo' => 'bar','fields' => 'count']));

// Requesting names or slugs
assertType('list<string>|WP_Error', get_terms(['fields' => 'names']));
assertType('list<string>|WP_Error', get_terms(['fields' => 'slugs']));
assertType('array<int, string>|WP_Error', get_terms(['fields' => 'id=>name']));
assertType('array<int, string>|WP_Error', get_terms(['fields' => 'id=>slug']));

// Requesting IDs
assertType('list<int>|WP_Error', get_terms(['fields' => 'ids']));
assertType('list<int>|WP_Error', get_terms(['fields' => 'tt_ids']));

// Requesting parent IDs
assertType('array<int, int>|WP_Error', get_terms(['fields' => 'id=>parent']));

// Requesting objects
assertType('array<int, WP_Term>|WP_Error', get_terms(['fields' => 'all']));
assertType('array<int, WP_Term>|WP_Error', get_terms(['fields' => 'all_with_object_id']));
assertType('array<int, WP_Term>|WP_Error', get_terms(['fields' => 'foo']));

// Unknown fields value
assertType('array<int, int|string|WP_Term>|numeric-string|WP_Error', get_terms(['fields' => (string)$_GET['fields']]));
45 changes: 45 additions & 0 deletions tests/data/wp_get_object_terms.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace PhpStubs\WordPress\Core\Tests;

use function wp_get_object_terms;
use function PHPStan\Testing\assertType;

$objectIDs = 123;
$taxonomies = 'category';

// Default argument values (fields => all)
assertType('array<int, WP_Term>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies));
assertType('array<int, WP_Term>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, []));

// Empty $object_ids or $taxonomies
assertType('array{}', wp_get_object_terms(0, $taxonomies, ['fields' => 'count']));
assertType('array{}', wp_get_object_terms([], $taxonomies));
assertType('array{}', wp_get_object_terms($objectIDs, ''));
assertType('array{}', wp_get_object_terms($objectIDs, []));

// Requesting names or slugs
assertType('list<string>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'names']));
assertType('list<string>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'slugs']));
assertType('array<int, string>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'id=>name']));
assertType('array<int, string>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'id=>slug']));

// Requesting IDs
assertType('list<int>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'ids']));
assertType('list<int>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'tt_ids']));

// Requesting parent IDs
assertType('array<int, int>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'id=>parent']));

// Requesting objects
assertType('array<int, WP_Term>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'all']));
assertType('array<int, WP_Term>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'all_with_object_id']));
assertType('array<int, WP_Term>|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'foo']));

// Requesting a count
assertType('numeric-string|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => 'count']));

// Unknown fields value
assertType('array<int, int|string|WP_Term>|numeric-string|WP_Error', wp_get_object_terms($objectIDs, $taxonomies, ['fields' => (string)$_GET['fields']]));
41 changes: 41 additions & 0 deletions tests/data/wp_get_post_categories.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace PhpStubs\WordPress\Core\Tests;

use function wp_get_post_categories;
use function PHPStan\Testing\assertType;

$postID = 123;

// Default argument values (fields => ids)
assertType('list<int>|WP_Error', wp_get_post_categories($postID));
assertType('list<int>|WP_Error', wp_get_post_categories($postID, []));

// Empty $post_id
assertType('array{}', wp_get_post_categories(0));

// Requesting names or slugs
assertType('list<string>|WP_Error', wp_get_post_categories($postID, ['fields' => 'names']));
assertType('list<string>|WP_Error', wp_get_post_categories($postID, ['fields' => 'slugs']));
assertType('array<int, string>|WP_Error', wp_get_post_categories($postID, ['fields' => 'id=>name']));
assertType('array<int, string>|WP_Error', wp_get_post_categories($postID, ['fields' => 'id=>slug']));

// Requesting IDs
assertType('list<int>|WP_Error', wp_get_post_categories($postID, ['fields' => 'ids']));
assertType('list<int>|WP_Error', wp_get_post_categories($postID, ['fields' => 'tt_ids']));

// Requesting parent IDs
assertType('array<int, int>|WP_Error', wp_get_post_categories($postID, ['fields' => 'id=>parent']));

// Requesting objects
assertType('array<int, WP_Term>|WP_Error', wp_get_post_categories($postID, ['fields' => 'all']));
assertType('array<int, WP_Term>|WP_Error', wp_get_post_categories($postID, ['fields' => 'all_with_object_id']));
assertType('list<int>|WP_Error', wp_get_post_categories($postID, ['fields' => 'foo']));

// Requesting a count
assertType('numeric-string|WP_Error', wp_get_post_categories($postID, ['fields' => 'count']));

// Unknown fields value
assertType('array<int, int|string|WP_Term>|numeric-string|WP_Error', wp_get_post_categories($postID, ['fields' => (string)$_GET['fields']]));
Loading

0 comments on commit d2a203c

Please sign in to comment.