*/ private static array $depth = array(); /** * Blocking instantiation: this class is a namespaced function group. */ private function __construct() { } /** * Getting the meta key the marker is stored under. * * @return string Meta key. */ public static function meta_key(): string { return MetaKeys::INTERNAL_SAVE; } /** * Adding the marker to post data about to be inserted. * * @param array $post_data Post data being assembled. * * @return array Post data carrying the marker. */ public static function mark( array $post_data ): array { if ( ! isset( $post_data['meta_input'] ) || ! is_array( $post_data['meta_input'] ) ) { $post_data['meta_input'] = array(); } $post_data['meta_input'][ self::meta_key() ] = true; return $post_data; } /** * Opening a guarded operation on an existing post. * * @param int $post_id Post ID. */ public static function begin( int $post_id ): void { if ( $post_id <= 0 ) { return; } self::$depth[ $post_id ] = ( self::$depth[ $post_id ] ?? 0 ) + 1; update_post_meta( $post_id, self::meta_key(), true ); } /** * Closing a guarded operation; the outermost one removes the marker. * * @param int $post_id Post ID. */ public static function end( int $post_id ): void { if ( $post_id <= 0 || ! isset( self::$depth[ $post_id ] ) ) { return; } --self::$depth[ $post_id ]; if ( self::$depth[ $post_id ] > 0 ) { return; } unset( self::$depth[ $post_id ] ); delete_post_meta( $post_id, self::meta_key() ); } /** * Checking whether a save is one of this plugin's own. * * @param int $post_id Post ID. * * @return bool Whether the export direction should stay out of it. */ public static function is_active( int $post_id ): bool { if ( $post_id <= 0 ) { return false; } if ( ( self::$depth[ $post_id ] ?? 0 ) > 0 ) { return true; } if ( self::meta_is_set( $post_id, self::meta_key() ) ) { return true; } return self::meta_is_set( $post_id, MetaKeys::legacy_post_meta()[ MetaKeys::INTERNAL_SAVE ] ); } /** * Running an operation with the guard held, released even if it throws. * * @param int $post_id Post ID. * @param callable $operation Operation to run. * * @return mixed Whatever the operation returned. */ public static function guarded( int $post_id, callable $operation ) { self::begin( $post_id ); try { return $operation(); } finally { self::end( $post_id ); } } /** * Clearing every in-memory marker (for tests). */ public static function reset(): void { self::$depth = array(); } /** * Checking whether a meta key holds a truthy value. * * @param int $post_id Post ID. * @param string $meta_key Meta key. * * @return bool Whether the marker is set. */ private static function meta_is_set( int $post_id, string $meta_key ): bool { $value = get_post_meta( $post_id, $meta_key, true ); return '' !== $value && false !== $value && '0' !== $value && 0 !== $value && null !== $value; } }