From b010154f3fc541bbc802697f8858977f06f7f663 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Mon, 30 Jan 2023 14:43:37 +1100 Subject: [PATCH 01/14] Track site ID used to create object. --- includes/classes/DistributorPost.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index a5c396ec1..0bd3e1a9d 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -94,6 +94,13 @@ class DistributorPost { */ public $connection_id = 0; + /** + * The site ID of this post. + * + * @var int + */ + public $site_id = 0; + /** * The source site data for internal connections. * @@ -122,7 +129,8 @@ public function __construct( $post ) { return; } - $this->post = $post; + $this->post = $post; + $this->site_id = get_current_blog_id(); /* * The original post ID is listed as excluded post meta and therefore From 1de7cdf5f8f18cd94fc1a0c89a49a8c63d9ff3d8 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:03:52 +1100 Subject: [PATCH 02/14] Add __call magic method to ensure site is correct. --- includes/classes/DistributorPost.php | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index 0bd3e1a9d..32a10a581 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -186,6 +186,36 @@ public function __construct( $post ) { } } + /** + * Magic method for calling methods on the post object. + * + * This is used to ensure the post object is switched to the correct site before + * running any of the internal methods. + * + * @param string $name Method name. + * @param array $arguments Method arguments. + */ + public function __call( $name, $arguments ) { + $switched = false; + if ( ! method_exists( $this, $name ) ) { + // Emulate default behavior of calling non existent method (a fatal error). + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error, WordPress.Security.EscapeOutput -- class and name are safe. + trigger_error( 'Call to undefined method ' . __CLASS__ . '::' . $name . '()', E_USER_ERROR ); + } + + if ( get_current_blog_id() !== $this->site_id ) { + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- throwing a warning is the correct behavior. + trigger_error( 'DistributorPost object is not on the correct site.', E_USER_WARNING ); + switch_to_blog( $this->site_id ); + $switched = true; + } + $result = call_user_func_array( array( $this, $name ), $arguments ); + if ( $switched ) { + restore_current_blog(); + } + return $result; + } + /** * Populate the source site data for internal connections. * From 9ace7086c5c141855cdf6789f9a9b92521c7fb69 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:14:23 +1100 Subject: [PATCH 03/14] Mock `get_current_blog_id()` for all tests. --- tests/php/DistributorPostTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/php/DistributorPostTest.php b/tests/php/DistributorPostTest.php index 5f71546fa..24d4c864c 100644 --- a/tests/php/DistributorPostTest.php +++ b/tests/php/DistributorPostTest.php @@ -34,6 +34,13 @@ public function setup_common() { ] ); + \WP_Mock::userFunction( + 'get_current_blog_id', + [ + 'return' => 1, + ] + ); + // Return voids. \WP_Mock::userFunction( '_prime_post_caches' ); \WP_Mock::userFunction( 'update_object_term_cache' ); From 8085f6f0fd9b2d8828649904392e399925e9f525 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:16:20 +1100 Subject: [PATCH 04/14] Mock `get_current_blog_id()` for all tests. --- tests/php/HooksTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/php/HooksTest.php b/tests/php/HooksTest.php index dced26b91..e7e7c5cee 100644 --- a/tests/php/HooksTest.php +++ b/tests/php/HooksTest.php @@ -17,6 +17,12 @@ class HooksTest extends TestCase { public function setUp(): void { parent::setUp(); + \WP_Mock::userFunction( + 'get_current_blog_id', + [ + 'return' => 1, + ] + ); // Return voids. \WP_Mock::userFunction( '_prime_post_caches' ); From 8e6aa89d594cf99182454aae08855f42474bab39 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:18:13 +1100 Subject: [PATCH 05/14] Group magic methods. --- includes/classes/DistributorPost.php | 72 ++++++++++++++-------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index 32a10a581..3c7bede3a 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -216,6 +216,42 @@ public function __call( $name, $arguments ) { return $result; } + /** + * Magic getter method. + * + * This method is used to get the value of the `source_site` property and + * populate it if needs be. For internal connections the post permalink is + * updated with live data. + * + * @param string $name Property name. + * @return mixed + */ + public function __get( $name ) { + if ( in_array( $name, array( 'source_site', 'original_post_url' ), true ) ) { + $this->populate_source_site(); + } + + return $this->$name; + } + + /** + * Magic isset method. + * + * This method is used to check if the `source_site` property is set and + * populate it if needs be. + * + * @param string $name Property name. + * @return bool + */ + public function __isset( $name ) { + if ( 'source_site' === $name && empty( $this->source_site ) ) { + $this->populate_source_site(); + return ! empty( $this->source_site ); + } + + return isset( $this->$name ); + } + /** * Populate the source site data for internal connections. * @@ -270,42 +306,6 @@ protected function populate_source_site() { } } - /** - * Magic getter method. - * - * This method is used to get the value of the `source_site` property and - * populate it if needs be. For internal connections the post permalink is - * updated with live data. - * - * @param string $name Property name. - * @return mixed - */ - public function __get( $name ) { - if ( in_array( $name, array( 'source_site', 'original_post_url' ), true ) ) { - $this->populate_source_site(); - } - - return $this->$name; - } - - /** - * Magic isset method. - * - * This method is used to check if the `source_site` property is set and - * populate it if needs be. - * - * @param string $name Property name. - * @return bool - */ - public function __isset( $name ) { - if ( 'source_site' === $name && empty( $this->source_site ) ) { - $this->populate_source_site(); - return ! empty( $this->source_site ); - } - - return isset( $this->$name ); - } - /** * Determines whether the post has blocks. * From 1b9bac3727dd171127047afe14925fa48cad6f06 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Mon, 30 Jan 2023 15:33:33 +1100 Subject: [PATCH 06/14] Only throw notice if WP_DEBUG is true. --- includes/classes/DistributorPost.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index 3c7bede3a..dbdb687f2 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -204,8 +204,10 @@ public function __call( $name, $arguments ) { } if ( get_current_blog_id() !== $this->site_id ) { - // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- throwing a warning is the correct behavior. - trigger_error( 'DistributorPost object is not on the correct site.', E_USER_WARNING ); + if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- throwing a warning is the correct behavior. + trigger_error( 'DistributorPost object is not on the correct site.', E_USER_WARNING ); + } switch_to_blog( $this->site_id ); $switched = true; } From 3aaf4f55ed18c67697fb52516ec5dc26de07c3ae Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:06:29 +1100 Subject: [PATCH 07/14] Methods must be inaccessible for magic method to fire. --- includes/classes/DistributorPost.php | 38 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index dbdb687f2..a50b31af7 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -319,7 +319,7 @@ protected function populate_source_site() { * * @return bool Whether the post has blocks. */ - public function has_blocks() { + protected function has_blocks() { return has_blocks( $this->post->post_content ); } @@ -335,7 +335,7 @@ public function has_blocks() { * @param string $block_name Full block type to look for. * @return bool Whether the post content contains the specified block. */ - public function has_block( $block_name ) { + protected function has_block( $block_name ) { return has_block( $block_name, $this->post->post_content ); } @@ -344,7 +344,7 @@ public function has_block( $block_name ) { * * @return int Post ID. */ - public function get_the_id() { + protected function get_the_id() { return $this->post->ID; } @@ -353,7 +353,7 @@ public function get_the_id() { * * @return string Post permalink. */ - public function get_permalink() { + protected function get_permalink() { return get_permalink( $this->post ); } @@ -362,7 +362,7 @@ public function get_permalink() { * * @return string Post type. */ - public function get_post_type() { + protected function get_post_type() { return get_post_type( $this->post ); } @@ -371,7 +371,7 @@ public function get_post_type() { * * @return int|false Post thumbnail ID or false if no thumbnail is set. */ - public function get_post_thumbnail_id() { + protected function get_post_thumbnail_id() { return get_post_thumbnail_id( $this->post ); } @@ -381,7 +381,7 @@ public function get_post_thumbnail_id() { * @param string $size Thumbnail size. Defaults to 'post-thumbnail'. * @return string|false The post's thumbnail URL or false if no thumbnail is set. */ - public function get_post_thumbnail_url( $size = 'post-thumbnail' ) { + protected function get_post_thumbnail_url( $size = 'post-thumbnail' ) { return get_the_post_thumbnail_url( $this->post, $size ); } @@ -392,7 +392,7 @@ public function get_post_thumbnail_url( $size = 'post-thumbnail' ) { * @param array $attr Optional. Attributes for the image markup. Default empty. * @return string|false The post's thumbnail HTML or false if no thumbnail is set. */ - public function get_the_post_thumbnail( $size = 'post-thumbnail', $attr = '' ) { + protected function get_the_post_thumbnail( $size = 'post-thumbnail', $attr = '' ) { return get_the_post_thumbnail( $this->post, $size, $attr ); } @@ -407,7 +407,7 @@ public function get_the_post_thumbnail( $size = 'post-thumbnail', $attr = '' ) { * original source URL. * @return string The post's canonical URL. */ - public function get_canonical_url( $canonical_url = '' ) { + protected function get_canonical_url( $canonical_url = '' ) { if ( $this->is_source || $this->original_deleted @@ -434,7 +434,7 @@ public function get_canonical_url( $canonical_url = '' ) { * author name does not need to be replaced by the original source name. * @return string The post's author name. */ - public function get_author_name( $author_name = '' ) { + protected function get_author_name( $author_name = '' ) { $settings = Utils\get_settings(); if ( @@ -465,7 +465,7 @@ public function get_author_name( $author_name = '' ) { * author link does not need to be replaced by the original source name. * @return string The post's author link. */ - public function get_author_link( $author_link = '' ) { + protected function get_author_link( $author_link = '' ) { $settings = Utils\get_settings(); if ( @@ -491,7 +491,7 @@ public function get_author_link( $author_link = '' ) { * * @return array Array of meta data. */ - public function get_meta() { + protected function get_meta() { return Utils\prepare_meta( $this->post->ID ); } @@ -502,7 +502,7 @@ public function get_meta() { * @type WP_Term[] Post terms keyed by taxonomy. * } */ - public function get_terms() { + protected function get_terms() { return Utils\prepare_taxonomy_terms( $this->post->ID ); } @@ -511,7 +511,7 @@ public function get_terms() { * * @return array */ - public function get_media() { + protected function get_media() { $post_id = $this->post->ID; if ( $this->has_blocks() ) { $raw_media = $this->parse_media_blocks(); @@ -551,7 +551,7 @@ public function get_media() { * * @return WP_Post[] Array of media posts. */ - public function parse_media_blocks() { + protected function parse_media_blocks() { $found = false; // Note: changes to the cache key or group should be reflected in `includes/settings.php` @@ -595,7 +595,7 @@ public function parse_media_blocks() { * @param array $block Block to parse. * @return int[] Array of media attachment IDs. */ - private function parse_blocks_for_attachment_id( $block ) { + protected function parse_blocks_for_attachment_id( $block ) { $media_blocks = array( 'core/image' => 'id', 'core/audio' => 'id', @@ -654,7 +654,7 @@ private function parse_blocks_for_attachment_id( $block ) { * @type array $distributor_meta Post meta. * } */ - public function post_data() { + protected function post_data() { return [ 'title' => html_entity_decode( get_the_title( $this->post->ID ), ENT_QUOTES, get_bloginfo( 'charset' ) ), 'slug' => $this->post->post_name, @@ -687,7 +687,7 @@ public function post_data() { * @type array $distributor_media Media data. * } */ - public function to_insert() { + protected function to_insert() { $insert = []; $post_data = $this->post_data(); $key_mappings = [ @@ -717,7 +717,7 @@ public function to_insert() { * @param int $depth Optional. Maximum depth to walk through $data. Default 512. * @return string JSON encoded post data. */ - public function to_json( $options = 0, $depth = 512 ) { + protected function to_json( $options = 0, $depth = 512 ) { $post_data = $this->post_data(); /* From 91896020b72bdf66ea3692c1c163f6c821acca3b Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:06:49 +1100 Subject: [PATCH 08/14] Set the site ID even earlier. --- includes/classes/DistributorPost.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index a50b31af7..8f56f8678 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -129,8 +129,8 @@ public function __construct( $post ) { return; } - $this->post = $post; $this->site_id = get_current_blog_id(); + $this->post = $post; /* * The original post ID is listed as excluded post meta and therefore From 4e0e09fbb5c6cf02bd51dff54e07f7220c622558 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:19:54 +1100 Subject: [PATCH 09/14] Note for developers. --- includes/classes/DistributorPost.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index 8f56f8678..d3cf662d4 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -17,6 +17,13 @@ * includes the phrase Distributor to make it clear to developers `use`ing * the class that they are not using the `WP_Post` object. * + * Developer note: This class uses the `__call()` magic method to ensure the + * post data is from the correct site on multisite installs. This is to avoid + * repeating code to determine if `switch_to_blog()` is required. + * + * When adding new methods to this class, please ensure that the method is + * protected to ensure the magic method is used. + * * @since x.x.x */ class DistributorPost { From b167b0d5479423f2ee24f1a9247d5e32e6a47586 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:58:35 +1100 Subject: [PATCH 10/14] Test only magic methods are public. --- tests/php/DistributorPostTest.php | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/php/DistributorPostTest.php b/tests/php/DistributorPostTest.php index 24d4c864c..e609ed69f 100644 --- a/tests/php/DistributorPostTest.php +++ b/tests/php/DistributorPostTest.php @@ -114,6 +114,29 @@ public function setup_post_meta_mock( $post_meta ) { ); } + /** + * Test the DistributorPost object for public methods. + * + * Only magic methods are expected to be public as the class uses the + * __call() method to handle all other methods. + * + * @covers ::__construct + * @runInSeparateProcess + */ + public function test_public_methods() { + $actual_methods = get_class_methods( 'Distributor\DistributorPost' ); + $expected_methods = array( + '__construct', + '__call', + '__get', + '__isset', + ); + + sort( $actual_methods ); + sort( $expected_methods ); + $this->assertSame( $expected_methods, $actual_methods, 'Only magic methods are expected to be public.' ); + } + /** * Test the DistributorPost object for internal connections. * From dc19355535579b88437236a5a60b10b096abbe83 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Thu, 2 Feb 2023 10:19:12 +1100 Subject: [PATCH 11/14] Cache results to avoid switching sites too many times. --- includes/classes/DistributorPost.php | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index d3cf662d4..b9857fe4e 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -124,6 +124,16 @@ class DistributorPost { */ private $source_site = []; + /** + * The cache for accessing methods when the site has been switched. + * + * This prevents the need to switch sites multiple times when accessing + * the same method multiple times. + * + * @var array + */ + private $switched_site_cache = []; + /** * Initialize the DistributorPost object. * @@ -203,7 +213,8 @@ public function __construct( $post ) { * @param array $arguments Method arguments. */ public function __call( $name, $arguments ) { - $switched = false; + $switched = false; + $cache_key = md5( "{$name}::" . wp_json_encode( $arguments ) ); if ( ! method_exists( $this, $name ) ) { // Emulate default behavior of calling non existent method (a fatal error). // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error, WordPress.Security.EscapeOutput -- class and name are safe. @@ -215,10 +226,23 @@ public function __call( $name, $arguments ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- throwing a warning is the correct behavior. trigger_error( 'DistributorPost object is not on the correct site.', E_USER_WARNING ); } + // array_key_exists as opposed to isset to avoid false negatives. + if ( array_key_exists( $cache_key, $this->switched_site_cache ) ) { + /* + * Avoid switching sites if the result is already cached. + * + * Due to the use of filters within various functions called by + * the helper methods, this data may not be correct at runtime if + * hooks have been added or removed. However, caching is a performance + * compromise to avoid switching sites on every call. + */ + return $this->switched_site_cache[ $cache_key ]; + } switch_to_blog( $this->site_id ); $switched = true; } - $result = call_user_func_array( array( $this, $name ), $arguments ); + $result = call_user_func_array( array( $this, $name ), $arguments ); + $this->switched_site_cache[ $cache_key ] = $result; if ( $switched ) { restore_current_blog(); } From 1c4c2bf60c4b0e91e56dbfbf49fb1901e23955d0 Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Thu, 2 Feb 2023 14:11:48 +1100 Subject: [PATCH 12/14] Define methods available via the magic method. --- includes/classes/DistributorPost.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index b9857fe4e..74bc4425b 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -25,6 +25,24 @@ * protected to ensure the magic method is used. * * @since x.x.x + * + * @method bool has_blocks() + * @method bool has_block( string $block_name ) + * @method int get_the_ID() + * @method string get_permalink() + * @method string get_post_type() + * @method int|false get_post_thumbnail_id() + * @method string|false get_post_thumbnail_url( string $size = 'post-thumbnail' ) + * @method string|false get_the_post_thumbnail( string $size = 'post-thumbnail', array $attr = '' ) + * @method string get_canonical_url( string $canonical_url = '' ) + * @method string get_author_name( string $author_name = '' ) + * @method string get_author_link( string $author_link = '' ) + * @method array get_meta() + * @method array get_terms() + * @method array get_media() + * @method array post_data() + * @method array to_insert() + * @method string to_json( int $options = 0, int $depth = 512 ) */ class DistributorPost { /** From 1948031f45215a188d7c71aa62c190b0bc8c04da Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Thu, 2 Feb 2023 14:18:04 +1100 Subject: [PATCH 13/14] Note the need to add public methods to docblock. --- includes/classes/DistributorPost.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index 74bc4425b..da0a6f666 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -22,7 +22,9 @@ * repeating code to determine if `switch_to_blog()` is required. * * When adding new methods to this class, please ensure that the method is - * protected to ensure the magic method is used. + * protected to ensure the magic method is used. If the method is intended to + * be public, please add it to the `@method` docblock below to ensure it is + * shown in IDEs. * * @since x.x.x * From 3aa72a12e00fb76cc3c19df5c2ec3232e1c09cdd Mon Sep 17 00:00:00 2001 From: Peter Wilson <519727+peterwilsoncc@users.noreply.github.com> Date: Thu, 2 Feb 2023 14:33:39 +1100 Subject: [PATCH 14/14] Improve error messsages: i18n and phrasing. --- includes/classes/DistributorPost.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/includes/classes/DistributorPost.php b/includes/classes/DistributorPost.php index da0a6f666..3f56d73de 100644 --- a/includes/classes/DistributorPost.php +++ b/includes/classes/DistributorPost.php @@ -237,14 +237,21 @@ public function __call( $name, $arguments ) { $cache_key = md5( "{$name}::" . wp_json_encode( $arguments ) ); if ( ! method_exists( $this, $name ) ) { // Emulate default behavior of calling non existent method (a fatal error). - // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error, WordPress.Security.EscapeOutput -- class and name are safe. - trigger_error( 'Call to undefined method ' . __CLASS__ . '::' . $name . '()', E_USER_ERROR ); + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error + trigger_error( + sprintf( + /* translators: %s: method name */ + esc_html__( 'Call to undefined method %s', 'distributor' ), + esc_html( __CLASS__ . '::' . $name . '()' ) + ), + E_USER_ERROR + ); } if ( get_current_blog_id() !== $this->site_id ) { if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error -- throwing a warning is the correct behavior. - trigger_error( 'DistributorPost object is not on the correct site.', E_USER_WARNING ); + trigger_error( esc_html__( 'DistributorPost object was called from a switched site.', 'distributor' ), E_USER_WARNING ); } // array_key_exists as opposed to isset to avoid false negatives. if ( array_key_exists( $cache_key, $this->switched_site_cache ) ) {