wordpress-develop/tests/phpunit/tests/meta.php
Sergey Biryukov ff96003a0f Coding Standards: Upgrade WPCS to version 3.0.0.
This is an important release which makes significant changes to improve the accuracy, performance, stability and maintainability of all sniffs, as well as making WordPressCS much better at handling modern PHP.

WordPressCS 3.0.0 contains breaking changes, both for people using ignore annotations, people maintaining custom rulesets, as well as for sniff developers who maintain a custom PHPCS standard based on WordPressCS.

If you are an end-user or maintain a custom WordPressCS based ruleset, please start by reading the [https://github.com/WordPress/WordPress-Coding-Standards/wiki/Upgrade-Guide-to-WordPressCS-3.0.0-for-ruleset-maintainers Upgrade Guide to WordPressCS 3.0.0 for ruleset maintainers] which lists the most important changes and contains a step by step guide for upgrading.

If you are a maintainer of an external standard based on WordPressCS and any of your custom sniffs are based on or extend WordPressCS sniffs, please read the [https://github.com/WordPress/WordPress-Coding-Standards/wiki/Upgrade-Guide-to-WordPressCS-3.0.0-for-Developers-of-external-standards Upgrade Guide to WordPressCS 3.0.0 for Developers].

In all cases, please read the complete changelog carefully before you upgrade.

This commit:
* Updates the Composer dependencies to use the new version, including updating the underlying PHP_CodeSniffer dependency to the new minimum supported version for WPCS.[[BR]] Note: the Composer PHPCS installer plugin is no longer explicitly required as it is now a dependency of WPCS, so the dependency is inherited automatically.
* Updates the ruleset for WPCS 3.0.0. This includes:
 * Raising the memory limit to be on the safe side as WPCS 3.0.0 contains a lot more sniffs.
 * Removing explicit inclusions of extra rules, which have now been added to the `WordPress-Core` ruleset..
 * Updating property names for select sniffs.
 * Updating one exclusion — the `WordPress.CodeAnalysis.AssignmentInCondition` sniff has been (partially) replaced by the `Generic.CodeAnalysis.AssignmentInCondition` sniff.
 * Adding one new exclusion.
* Downgrades one new error to a warning.[[BR]] The `Generic.Files.OneObjectStructurePerFile` sniff enforces that there is only one OO structure declaration per file. At this time, this sniff would yield 29 errors. By downgrading the sniff to a ''warning'', the build can pass and the issues can be fixed in due time. For now, the test directory will be excluded until the issues are fixed (as the test directory CS run does not allow for warnings).
* Updates ignore annotations for WPCS 3.0.0.

Reference: [https://github.com/WordPress/WordPress-Coding-Standards/releases/tag/3.0.0 WPCS 3.0.0 release notes].

Follow-up to [43571], [44574], [45600], [47927].

Props jrf, jorbin, desrosj.
See #59161.

git-svn-id: https://develop.svn.wordpress.org/trunk@56695 602fd350-edb4-49c9-b593-d223f7449a82
2023-09-26 00:24:43 +00:00

434 lines
14 KiB
PHP

<?php
/**
* @group meta
*/
class Tests_Meta extends WP_UnitTestCase {
protected $updated_mids = array();
/**
* @var \WP_User
*/
private $author;
private $meta_id;
private $delete_meta_id;
public function set_up() {
parent::set_up();
$this->author = new WP_User( self::factory()->user->create( array( 'role' => 'author' ) ) );
$this->meta_id = add_metadata( 'user', $this->author->ID, 'meta_key', 'meta_value' );
$this->delete_meta_id = add_metadata( 'user', $this->author->ID, 'delete_meta_key', 'delete_meta_value' );
}
public function meta_sanitize_cb( $meta_value, $meta_key, $meta_type ) {
return 'sanitized';
}
public function test_sanitize_meta() {
$meta = sanitize_meta( 'some_meta', 'unsanitized', 'post' );
$this->assertSame( 'unsanitized', $meta );
register_meta( 'post', 'some_meta', array( $this, 'meta_sanitize_cb' ) );
$meta = sanitize_meta( 'some_meta', 'unsanitized', 'post' );
$this->assertSame( 'sanitized', $meta );
}
public function test_delete_metadata_by_mid() {
// Let's try and delete a non-existing ID, non existing meta.
$this->assertFalse( delete_metadata_by_mid( 'user', 0 ) );
$this->assertFalse( delete_metadata_by_mid( 'non_existing_meta', $this->delete_meta_id ) );
// Now let's delete the real meta data.
$this->assertTrue( delete_metadata_by_mid( 'user', $this->delete_meta_id ) );
// And make sure it's been deleted.
$this->assertFalse( get_metadata_by_mid( 'user', $this->delete_meta_id ) );
// Make sure the caches are cleared.
$this->assertFalse( (bool) get_user_meta( $this->author->ID, 'delete_meta_key' ) );
}
public function test_update_metadata_by_mid() {
// Setup.
$meta = get_metadata_by_mid( 'user', $this->meta_id );
// Update the meta value.
$this->assertTrue( update_metadata_by_mid( 'user', $this->meta_id, 'meta_new_value' ) );
$meta = get_metadata_by_mid( 'user', $this->meta_id );
$this->assertSame( 'meta_new_value', $meta->meta_value );
// Update the meta value.
$this->assertTrue( update_metadata_by_mid( 'user', $this->meta_id, 'meta_new_value', 'meta_new_key' ) );
$meta = get_metadata_by_mid( 'user', $this->meta_id );
$this->assertSame( 'meta_new_key', $meta->meta_key );
// Update the key and value.
$this->assertTrue( update_metadata_by_mid( 'user', $this->meta_id, 'meta_value', 'meta_key' ) );
$meta = get_metadata_by_mid( 'user', $this->meta_id );
$this->assertSame( 'meta_key', $meta->meta_key );
$this->assertSame( 'meta_value', $meta->meta_value );
// Update the value that has to be serialized.
$this->assertTrue( update_metadata_by_mid( 'user', $this->meta_id, array( 'first', 'second' ) ) );
$meta = get_metadata_by_mid( 'user', $this->meta_id );
$this->assertSame( array( 'first', 'second' ), $meta->meta_value );
// Let's try some invalid meta data.
$this->assertFalse( update_metadata_by_mid( 'user', 0, 'meta_value' ) );
$this->assertFalse( update_metadata_by_mid( 'user', $this->meta_id, 'meta_value', array( 'invalid', 'key' ) ) );
// Let's see if caches get cleared after updates.
$meta = get_metadata_by_mid( 'user', $this->meta_id );
$first = get_user_meta( $meta->user_id, $meta->meta_key );
$this->assertTrue( update_metadata_by_mid( 'user', $this->meta_id, 'other_meta_value' ) );
$second = get_user_meta( $meta->user_id, $meta->meta_key );
$this->assertFalse( $first === $second );
}
/**
* @ticket 11683
*/
public function test_update_metadata_hooks_for_multiple_updated_rows() {
add_metadata( 'post', 1, 'test_key', 'value_1' );
add_metadata( 'post', 1, 'test_key', 'value_2' );
add_action( 'update_post_meta', array( $this, 'updated_meta' ) );
add_action( 'update_postmeta', array( $this, 'updated_meta' ) );
add_action( 'updated_post_meta', array( $this, 'updated_meta' ) );
add_action( 'updated_postmeta', array( $this, 'updated_meta' ) );
update_metadata( 'post', 1, 'test_key', 'value_3' );
remove_action( 'update_post_meta', array( $this, 'updated_meta' ) );
remove_action( 'update_postmeta', array( $this, 'updated_meta' ) );
remove_action( 'updated_post_meta', array( $this, 'updated_meta' ) );
remove_action( 'updated_postmeta', array( $this, 'updated_meta' ) );
$found = $this->updated_mids;
$this->updated_mids = array();
foreach ( $found as $action => $mids ) {
$this->assertCount( 2, $mids );
}
}
public function test_metadata_exists() {
$this->assertFalse( metadata_exists( 'user', $this->author->ID, 'foobarbaz' ) );
$this->assertTrue( metadata_exists( 'user', $this->author->ID, 'meta_key' ) );
$this->assertFalse( metadata_exists( 'user', 1234567890, 'foobarbaz' ) );
$this->assertFalse( metadata_exists( 'user', 1234567890, 'meta_key' ) );
}
/**
* @ticket 22746
*/
public function test_metadata_exists_with_filter() {
// Let's see if it returns the correct value when adding a filter.
add_filter( 'get_user_metadata', '__return_zero' );
$this->assertFalse( metadata_exists( 'user', $this->author->ID, 'meta_key' ) ); // Existing meta key.
$this->assertFalse( metadata_exists( 'user', 1234567890, 'meta_key' ) );
remove_filter( 'get_user_metadata', '__return_zero' );
}
/**
* @ticket 18158
*/
public function test_user_metadata_not_exists() {
$u = get_users(
array(
'meta_query' => array(
array(
'key' => 'meta_key',
'compare' => 'NOT EXISTS',
),
),
)
);
$this->assertCount( 1, $u );
// User found is not locally defined author (it's the admin).
$this->assertNotEquals( $this->author->user_login, $u[0]->user_login );
// Test EXISTS and NOT EXISTS together, no users should be found.
$this->assertSame(
0,
count(
get_users(
array(
'meta_query' => array(
array(
'key' => 'meta_key',
'compare' => 'NOT EXISTS',
),
array(
'key' => 'delete_meta_key',
'compare' => 'EXISTS',
),
),
)
)
)
);
$this->assertSame(
2,
count(
get_users(
array(
'meta_query' => array(
array(
'key' => 'non_existing_meta',
'compare' => 'NOT EXISTS',
),
),
)
)
)
);
delete_metadata( 'user', $this->author->ID, 'meta_key' );
$this->assertSame(
2,
count(
get_users(
array(
'meta_query' => array(
array(
'key' => 'meta_key',
'compare' => 'NOT EXISTS',
),
),
)
)
)
);
}
public function test_metadata_slashes() {
$key = __FUNCTION__;
$value = 'Test\\singleslash';
$expected = 'Testsingleslash';
$value2 = 'Test\\\\doubleslash';
$expected2 = 'Test\\doubleslash';
$this->assertFalse( metadata_exists( 'user', $this->author->ID, $key ) );
$this->assertFalse( delete_metadata( 'user', $this->author->ID, $key ) );
$this->assertSame( '', get_metadata( 'user', $this->author->ID, $key, true ) );
$this->assertIsInt( add_metadata( 'user', $this->author->ID, $key, $value ) );
$this->assertSame( $expected, get_metadata( 'user', $this->author->ID, $key, true ) );
$this->assertTrue( delete_metadata( 'user', $this->author->ID, $key ) );
$this->assertSame( '', get_metadata( 'user', $this->author->ID, $key, true ) );
$this->assertIsInt( update_metadata( 'user', $this->author->ID, $key, $value ) );
$this->assertSame( $expected, get_metadata( 'user', $this->author->ID, $key, true ) );
$this->assertTrue( update_metadata( 'user', $this->author->ID, $key, 'blah' ) );
$this->assertSame( 'blah', get_metadata( 'user', $this->author->ID, $key, true ) );
$this->assertTrue( delete_metadata( 'user', $this->author->ID, $key ) );
$this->assertSame( '', get_metadata( 'user', $this->author->ID, $key, true ) );
$this->assertFalse( metadata_exists( 'user', $this->author->ID, $key ) );
// Test overslashing.
$this->assertIsInt( add_metadata( 'user', $this->author->ID, $key, $value2 ) );
$this->assertSame( $expected2, get_metadata( 'user', $this->author->ID, $key, true ) );
$this->assertTrue( delete_metadata( 'user', $this->author->ID, $key ) );
$this->assertSame( '', get_metadata( 'user', $this->author->ID, $key, true ) );
$this->assertIsInt( update_metadata( 'user', $this->author->ID, $key, $value2 ) );
$this->assertSame( $expected2, get_metadata( 'user', $this->author->ID, $key, true ) );
}
/**
* @ticket 16814
*/
public function test_meta_type_cast() {
$post_id1 = self::factory()->post->create();
add_post_meta( $post_id1, 'num_as_longtext', 123 );
add_post_meta( $post_id1, 'num_as_longtext_desc', 10 );
$post_id2 = self::factory()->post->create();
add_post_meta( $post_id2, 'num_as_longtext', 99 );
add_post_meta( $post_id2, 'num_as_longtext_desc', 100 );
$posts = new WP_Query(
array(
'fields' => 'ids',
'post_type' => 'any',
'meta_key' => 'num_as_longtext',
'meta_value' => '0',
'meta_compare' => '>',
'meta_type' => 'UNSIGNED',
'orderby' => 'meta_value',
'order' => 'ASC',
)
);
$this->assertSame( array( $post_id2, $post_id1 ), $posts->posts );
$this->assertSame( 2, substr_count( $posts->request, 'CAST(' ) );
// Make sure the newer meta_query syntax behaves in a consistent way.
$posts = new WP_Query(
array(
'fields' => 'ids',
'post_type' => 'any',
'meta_query' => array(
array(
'key' => 'num_as_longtext',
'value' => '0',
'compare' => '>',
'type' => 'UNSIGNED',
),
),
'orderby' => 'meta_value',
'order' => 'ASC',
)
);
$this->assertSame( array( $post_id2, $post_id1 ), $posts->posts );
$this->assertSame( 2, substr_count( $posts->request, 'CAST(' ) );
// The legacy `meta_key` value should take precedence.
$posts = new WP_Query(
array(
'fields' => 'ids',
'post_type' => 'any',
'meta_key' => 'num_as_longtext',
'meta_compare' => '>',
'meta_type' => 'UNSIGNED',
'meta_query' => array(
array(
'key' => 'num_as_longtext_desc',
'value' => '0',
'compare' => '>',
'type' => 'UNSIGNED',
),
),
'orderby' => 'meta_value',
'order' => 'ASC',
)
);
$this->assertSame( array( $post_id2, $post_id1 ), $posts->posts );
$this->assertSame( 2, substr_count( $posts->request, 'CAST(' ) );
}
public function test_meta_cache_order_asc() {
$post_id = self::factory()->post->create();
$colors = array( 'red', 'blue', 'yellow', 'green' );
foreach ( $colors as $color ) {
add_post_meta( $post_id, 'color', $color );
}
foreach ( range( 1, 10 ) as $i ) {
$meta = get_post_meta( $post_id, 'color' );
$this->assertSame( $meta, $colors );
if ( 0 === $i % 2 ) {
wp_cache_delete( $post_id, 'post_meta' );
}
}
}
/**
* @ticket 28315
*/
public function test_non_numeric_object_id() {
$this->assertFalse( add_metadata( 'user', array( 1 ), 'meta_key', 'meta_value' ) );
$this->assertFalse( update_metadata( 'user', array( 1 ), 'meta_key', 'meta_new_value' ) );
$this->assertFalse( delete_metadata( 'user', array( 1 ), 'meta_key' ) );
$this->assertFalse( get_metadata( 'user', array( 1 ) ) );
$this->assertFalse( metadata_exists( 'user', array( 1 ), 'meta_key' ) );
}
/**
* @ticket 28315
*/
public function test_non_numeric_meta_id() {
$this->assertFalse( get_metadata_by_mid( 'user', array( 1 ) ) );
$this->assertFalse( update_metadata_by_mid( 'user', array( 1 ), 'meta_new_value' ) );
$this->assertFalse( delete_metadata_by_mid( 'user', array( 1 ) ) );
}
/**
* @ticket 37746
*/
public function test_negative_meta_id() {
$negative_mid = $this->meta_id * -1;
$this->assertLessThan( 0, $negative_mid );
$this->assertFalse( get_metadata_by_mid( 'user', $negative_mid ) );
$this->assertFalse( update_metadata_by_mid( 'user', $negative_mid, 'meta_new_value' ) );
$this->assertFalse( delete_metadata_by_mid( 'user', $negative_mid ) );
}
/**
* @ticket 37746
*/
public function test_floating_meta_id() {
$floating_mid = $this->meta_id + 0.1337;
$this->assertTrue( floor( $floating_mid ) !== $floating_mid );
$this->assertFalse( get_metadata_by_mid( 'user', $floating_mid ) );
$this->assertFalse( update_metadata_by_mid( 'user', $floating_mid, 'meta_new_value' ) );
$this->assertFalse( delete_metadata_by_mid( 'user', $floating_mid ) );
}
/**
* @ticket 37746
*/
public function test_string_point_zero_meta_id() {
$meta_id = add_metadata( 'user', $this->author->ID, 'meta_key', 'meta_value_2' );
$string_mid = "{$meta_id}.0";
// phpcs:ignore Universal.Operators.StrictComparisons.LooseEqual -- intentional implicit casting check
$this->assertTrue( floor( $string_mid ) == $string_mid );
$this->assertNotFalse( get_metadata_by_mid( 'user', $string_mid ) );
$this->assertNotFalse( update_metadata_by_mid( 'user', $string_mid, 'meta_new_value_2' ) );
$this->assertNotFalse( delete_metadata_by_mid( 'user', $string_mid ) );
}
/**
* @ticket 15030
*/
public function test_get_metadata_with_empty_key_array_value() {
$data = array( 1, 2 );
$value = serialize( $data );
add_metadata( 'user', $this->author->ID, 'foo', $data );
$found = get_metadata( 'user', $this->author->ID );
$this->assertSame( array( $value ), $found['foo'] );
}
/**
* @ticket 15030
*/
public function test_get_metadata_with_empty_key_object_value() {
$data = new stdClass();
$data->foo = 'bar';
$value = serialize( $data );
add_metadata( 'user', $this->author->ID, 'foo', $data );
$found = get_metadata( 'user', $this->author->ID );
$this->assertSame( array( $value ), $found['foo'] );
}
/**
* @ticket 15030
*/
public function test_get_metadata_with_empty_key_nested_array_value() {
$data = array(
array( 1, 2 ),
array( 3, 4 ),
);
$value = serialize( $data );
add_metadata( 'user', $this->author->ID, 'foo', $data );
$found = get_metadata( 'user', $this->author->ID );
$this->assertSame( array( $value ), $found['foo'] );
}
/** Helpers */
public function updated_meta( $meta_id ) {
$this->updated_mids[ current_action() ][] = $meta_id;
}
}