965 lines
25 KiB
PHP
965 lines
25 KiB
PHP
<?php
|
|
/**
|
|
* PHPUnit and PHPStan bootstrap for isolated plugin tests.
|
|
*
|
|
* @package WPContentSync
|
|
*/
|
|
|
|
// phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- WordPress class and function stubs share this test bootstrap.
|
|
|
|
require_once dirname( __DIR__ ) . '/vendor/autoload.php';
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
define( 'ABSPATH', dirname( __DIR__ ) . '/' );
|
|
}
|
|
|
|
if ( ! defined( 'WPCS_PLUGIN_DIR' ) ) {
|
|
define( 'WPCS_PLUGIN_DIR', dirname( __DIR__ ) . '/' );
|
|
}
|
|
|
|
if ( ! defined( 'WPCS_PLUGIN_URL' ) ) {
|
|
define( 'WPCS_PLUGIN_URL', 'https://example.test/wp-content/plugins/wp-content-sync/' );
|
|
}
|
|
|
|
if ( ! defined( 'WPCS_VERSION' ) ) {
|
|
define( 'WPCS_VERSION', '0.1.0' );
|
|
}
|
|
|
|
if ( ! class_exists( 'WP_Error' ) ) {
|
|
class WP_Error {
|
|
private string $message;
|
|
|
|
public function __construct( string $code, string $message ) {
|
|
$this->message = $message;
|
|
}
|
|
|
|
public function get_error_message(): string {
|
|
return $this->message;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'sanitize_text_field' ) ) {
|
|
/**
|
|
* Minimal WordPress-compatible text sanitizer for unit tests.
|
|
*
|
|
* @param mixed $value Value to sanitize.
|
|
* @return string
|
|
*/
|
|
function sanitize_text_field( $value ) {
|
|
return trim( preg_replace( '/[\r\n\t]+/', ' ', wp_strip_all_tags( (string) $value ) ) );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'sanitize_key' ) ) {
|
|
/**
|
|
* Minimal WordPress-compatible key sanitizer for unit tests.
|
|
*
|
|
* @param mixed $key Key to sanitize.
|
|
* @return string
|
|
*/
|
|
function sanitize_key( $key ) {
|
|
return strtolower( preg_replace( '/[^a-zA-Z0-9_\-]/', '', (string) $key ) );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_strip_all_tags' ) ) {
|
|
/**
|
|
* Minimal tag stripper for unit tests.
|
|
*
|
|
* @param string $value Value to strip.
|
|
* @return string
|
|
*/
|
|
function wp_strip_all_tags( $value ) {
|
|
return preg_replace( '/<[^>]*>/', '', $value );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_unslash' ) ) {
|
|
/**
|
|
* Minimal slashes remover for unit tests.
|
|
*
|
|
* @param mixed $value Value to unslash.
|
|
* @return mixed
|
|
*/
|
|
function wp_unslash( $value ) {
|
|
if ( is_array( $value ) ) {
|
|
return array_map( 'wp_unslash', $value );
|
|
}
|
|
|
|
return is_string( $value ) ? stripslashes( $value ) : $value;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'esc_html' ) ) {
|
|
/**
|
|
* Minimal HTML escaper for unit tests.
|
|
*
|
|
* @param mixed $value Value to escape.
|
|
* @return string
|
|
*/
|
|
function esc_html( $value ) {
|
|
return htmlspecialchars( (string) $value, ENT_QUOTES, 'UTF-8' );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( '__' ) ) {
|
|
/**
|
|
* Minimal translation helper for unit tests.
|
|
*
|
|
* @param string $text Text to translate.
|
|
* @param string $domain Text domain.
|
|
* @return string
|
|
*/
|
|
function __( $text, $domain = 'default' ) {
|
|
$GLOBALS['wpcs_test_text_domain'] = $domain;
|
|
|
|
return $text;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'esc_html__' ) ) {
|
|
/**
|
|
* Minimal translated HTML escaper for unit tests.
|
|
*
|
|
* @param string $text Text to translate and escape.
|
|
* @param string $domain Text domain.
|
|
* @return string
|
|
*/
|
|
function esc_html__( $text, $domain = 'default' ) {
|
|
$GLOBALS['wpcs_test_text_domain'] = $domain;
|
|
|
|
return esc_html( $text );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'esc_attr' ) ) {
|
|
/**
|
|
* Minimal attribute escaper for unit tests.
|
|
*
|
|
* @param mixed $value Value to escape.
|
|
* @return string
|
|
*/
|
|
function esc_attr( $value ) {
|
|
return htmlspecialchars( (string) $value, ENT_QUOTES, 'UTF-8' );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'esc_url' ) ) {
|
|
/**
|
|
* Minimal URL sanitizer for unit tests.
|
|
*
|
|
* @param mixed $value Value to sanitize.
|
|
* @return string
|
|
*/
|
|
function esc_url( $value ) {
|
|
return filter_var( (string) $value, FILTER_SANITIZE_URL );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'esc_url_raw' ) ) {
|
|
/**
|
|
* Minimal raw URL sanitizer for unit tests.
|
|
*
|
|
* @param mixed $value Value to sanitize.
|
|
* @return string
|
|
*/
|
|
function esc_url_raw( $value ) {
|
|
return filter_var( (string) $value, FILTER_SANITIZE_URL );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_parse_url' ) ) {
|
|
/**
|
|
* Minimal URL parser for unit tests.
|
|
*
|
|
* @param string $url URL to parse.
|
|
* @return array<string, mixed>|false
|
|
*/
|
|
function wp_parse_url( $url ) {
|
|
// phpcs:ignore WordPress.WP.AlternativeFunctions.parse_url_parse_url -- Test stub for WordPress' wp_parse_url().
|
|
return parse_url( $url );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_json_encode' ) ) {
|
|
/**
|
|
* Minimal JSON encoder for unit tests.
|
|
*
|
|
* @param mixed $value Value to encode.
|
|
* @param int $flags JSON encoding flags.
|
|
* @return string|false
|
|
*/
|
|
function wp_json_encode( $value, $flags = 0 ) {
|
|
// phpcs:ignore -- Test stub for WordPress' wp_json_encode().
|
|
return json_encode( $value, $flags );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'get_option' ) ) {
|
|
/**
|
|
* Minimal WordPress option reader for unit tests.
|
|
*
|
|
* @param string $name Option name.
|
|
* @param mixed $default_value Default value.
|
|
* @return mixed
|
|
*/
|
|
function get_option( $name, $default_value = false ) {
|
|
return $GLOBALS['wpcs_test_options'][ $name ] ?? $default_value;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'update_option' ) ) {
|
|
/**
|
|
* Minimal WordPress option writer for unit tests.
|
|
*
|
|
* @param string $name Option name.
|
|
* @param mixed $value Option value.
|
|
* @param mixed $autoload Autoload flag.
|
|
* @return bool
|
|
*/
|
|
function update_option( $name, $value, $autoload = null ) {
|
|
$GLOBALS['wpcs_test_options'][ $name ] = $value;
|
|
$GLOBALS['wpcs_test_option_autoloads'][ $name ] = $autoload;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'delete_transient' ) ) {
|
|
/**
|
|
* Minimal WordPress transient deleter for unit tests.
|
|
*
|
|
* @param string $name Transient name.
|
|
* @return bool
|
|
*/
|
|
function delete_transient( $name ) {
|
|
unset( $GLOBALS['wpcs_test_transients'][ $name ] );
|
|
unset( $GLOBALS['wpcs_test_transient_expiration'][ $name ] );
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'get_transient' ) ) {
|
|
/**
|
|
* Minimal WordPress transient reader for unit tests.
|
|
*
|
|
* @param string $name Transient name.
|
|
* @return mixed
|
|
*/
|
|
function get_transient( $name ) {
|
|
return $GLOBALS['wpcs_test_transients'][ $name ] ?? false;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'set_transient' ) ) {
|
|
/**
|
|
* Minimal WordPress transient writer for unit tests.
|
|
*
|
|
* @param string $name Transient name.
|
|
* @param mixed $value Transient value.
|
|
* @param int $expiration Expiration in seconds.
|
|
* @return bool
|
|
*/
|
|
function set_transient( $name, $value, $expiration = 0 ) {
|
|
$GLOBALS['wpcs_test_transients'][ $name ] = $value;
|
|
$GLOBALS['wpcs_test_transient_expiration'][ $name ] = $expiration;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'plugin_dir_path' ) ) {
|
|
/**
|
|
* Minimal plugin path helper for static analysis.
|
|
*
|
|
* @param string $file Plugin file.
|
|
* @return string
|
|
*/
|
|
function plugin_dir_path( $file ) {
|
|
return trailingslashit( dirname( $file ) );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'plugin_dir_url' ) ) {
|
|
/**
|
|
* Minimal plugin URL helper for static analysis.
|
|
*
|
|
* @param string $file Plugin file.
|
|
* @return string
|
|
*/
|
|
function plugin_dir_url( $file ) {
|
|
return 'http://example.org/wp-content/plugins/' . basename( dirname( $file ) ) . '/';
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'trailingslashit' ) ) {
|
|
/**
|
|
* Minimal trailing slash helper for static analysis.
|
|
*
|
|
* @param string $value Value to slash.
|
|
* @return string
|
|
*/
|
|
function trailingslashit( $value ) {
|
|
return rtrim( $value, '/\\' ) . DIRECTORY_SEPARATOR;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'register_activation_hook' ) ) {
|
|
/**
|
|
* Minimal activation hook registrar for static analysis.
|
|
*
|
|
* @param string $file Plugin file.
|
|
* @param callable $callback Activation callback.
|
|
* @return void
|
|
*/
|
|
function register_activation_hook( $file, $callback ) {
|
|
$GLOBALS['wpcs_test_activation_hooks'][ $file ] = $callback;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'register_deactivation_hook' ) ) {
|
|
/**
|
|
* Minimal deactivation hook registrar for static analysis.
|
|
*
|
|
* @param string $file Plugin file.
|
|
* @param callable $callback Deactivation callback.
|
|
* @return void
|
|
*/
|
|
function register_deactivation_hook( $file, $callback ) {
|
|
$GLOBALS['wpcs_test_deactivation_hooks'][ $file ] = $callback;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'add_action' ) ) {
|
|
/**
|
|
* Minimal action registrar for static analysis.
|
|
*
|
|
* @param string $hook_name Hook name.
|
|
* @param callable $callback Hook callback.
|
|
* @return bool
|
|
*/
|
|
function add_action( $hook_name, $callback ) {
|
|
$GLOBALS['wpcs_test_actions'][ $hook_name ][] = $callback;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'add_management_page' ) ) {
|
|
/**
|
|
* Minimal management page registrar for static analysis.
|
|
*
|
|
* @param string $page_title Page title.
|
|
* @param string $menu_title Menu title.
|
|
* @param string $capability Capability required.
|
|
* @param string $menu_slug Menu slug.
|
|
* @param callable $callback Page callback.
|
|
* @return string
|
|
*/
|
|
function add_management_page( $page_title, $menu_title, $capability, $menu_slug, $callback ) {
|
|
$GLOBALS['wpcs_test_admin_pages'][ $menu_slug ] = array(
|
|
'page_title' => $page_title,
|
|
'menu_title' => $menu_title,
|
|
'capability' => $capability,
|
|
'callback' => $callback,
|
|
);
|
|
|
|
return $menu_slug;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'register_setting' ) ) {
|
|
/**
|
|
* Minimal setting registrar for static analysis.
|
|
*
|
|
* @param string $option_group Option group.
|
|
* @param string $option_name Option name.
|
|
* @param array<string, mixed> $args Setting arguments.
|
|
* @return bool
|
|
*/
|
|
function register_setting( $option_group, $option_name, $args = array() ) {
|
|
$GLOBALS['wpcs_test_registered_settings'][ $option_name ] = array(
|
|
'option_group' => $option_group,
|
|
'args' => $args,
|
|
);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'current_user_can' ) ) {
|
|
/**
|
|
* Minimal capability checker for static analysis.
|
|
*
|
|
* @param string $capability Capability to check.
|
|
* @return bool
|
|
*/
|
|
function current_user_can( $capability ) {
|
|
return $GLOBALS['wpcs_current_user_can'][ $capability ] ?? 'manage_options' === $capability;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'check_admin_referer' ) ) {
|
|
/**
|
|
* Minimal nonce checker for unit tests.
|
|
*
|
|
* @param string $action Nonce action.
|
|
* @param string $query_arg Nonce request field.
|
|
* @return bool
|
|
*/
|
|
function check_admin_referer( $action, $query_arg = '_wpnonce' ) {
|
|
return $GLOBALS['wpcs_nonce_valid'][ $action ][ $query_arg ] ?? true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_safe_redirect' ) ) {
|
|
/**
|
|
* Minimal safe redirect helper for unit tests.
|
|
*
|
|
* @param string $location Redirect location.
|
|
* @return bool
|
|
*/
|
|
function wp_safe_redirect( $location ) {
|
|
$GLOBALS['wpcs_redirect_location'] = $location;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_remote_get' ) ) {
|
|
/**
|
|
* Minimal HTTP GET helper for unit tests.
|
|
*
|
|
* @param string $url Request URL.
|
|
* @param array<string, mixed> $args Request arguments.
|
|
* @return array<string, mixed>|\WP_Error
|
|
*/
|
|
function wp_remote_get( $url, array $args = array() ) {
|
|
$GLOBALS['wpcs_last_http_request'] = array(
|
|
'method' => 'GET',
|
|
'url' => $url,
|
|
'args' => $args,
|
|
);
|
|
|
|
return $GLOBALS['wpcs_http_response'] ?? array(
|
|
'response' => array( 'code' => 200 ),
|
|
'body' => '{"ok":true}',
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_remote_post' ) ) {
|
|
/**
|
|
* Minimal HTTP POST helper for unit tests.
|
|
*
|
|
* @param string $url Request URL.
|
|
* @param array<string, mixed> $args Request arguments.
|
|
* @return array<string, mixed>|\WP_Error
|
|
*/
|
|
function wp_remote_post( $url, array $args = array() ) {
|
|
$GLOBALS['wpcs_last_http_request'] = array(
|
|
'method' => 'POST',
|
|
'url' => $url,
|
|
'args' => $args,
|
|
);
|
|
|
|
return $GLOBALS['wpcs_http_response'] ?? array(
|
|
'response' => array( 'code' => 200 ),
|
|
'body' => '{"accepted":true}',
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_remote_retrieve_response_code' ) ) {
|
|
/**
|
|
* Minimal response code helper for unit tests.
|
|
*
|
|
* @param array<string, mixed> $response HTTP response.
|
|
* @return int
|
|
*/
|
|
function wp_remote_retrieve_response_code( array $response ) {
|
|
return (int) ( $response['response']['code'] ?? 0 );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_remote_retrieve_body' ) ) {
|
|
/**
|
|
* Minimal response body helper for unit tests.
|
|
*
|
|
* @param array<string, mixed> $response HTTP response.
|
|
* @return string
|
|
*/
|
|
function wp_remote_retrieve_body( array $response ) {
|
|
return (string) ( $response['body'] ?? '' );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'is_wp_error' ) ) {
|
|
/**
|
|
* Minimal WP_Error checker for unit tests.
|
|
*
|
|
* @param mixed $value Value to check.
|
|
* @return bool
|
|
*/
|
|
function is_wp_error( $value ) {
|
|
return $value instanceof WP_Error;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'register_rest_route' ) ) {
|
|
/**
|
|
* Minimal REST route registrar for unit tests.
|
|
*
|
|
* @param string $rest_namespace REST namespace.
|
|
* @param string $route REST route.
|
|
* @param array<string, mixed> $args Route arguments.
|
|
* @return bool
|
|
*/
|
|
function register_rest_route( $rest_namespace, $route, array $args ) {
|
|
$GLOBALS['wpcs_rest_routes'][ $rest_namespace . $route ] = $args;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'rest_ensure_response' ) ) {
|
|
/**
|
|
* Minimal REST response wrapper for unit tests.
|
|
*
|
|
* @param mixed $response Response value.
|
|
* @return mixed
|
|
*/
|
|
function rest_ensure_response( $response ) {
|
|
return $response;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_insert_post' ) ) {
|
|
/**
|
|
* Minimal post inserter for unit tests.
|
|
*
|
|
* @param array<string, mixed> $postarr Post data.
|
|
* @param bool $wp_error Whether to return WP_Error on failure.
|
|
* @return int|\WP_Error
|
|
*/
|
|
function wp_insert_post( array $postarr, $wp_error = false ) {
|
|
if ( empty( $postarr['post_type'] ) ) {
|
|
return $wp_error ? new WP_Error( 'invalid_post_type', 'Post type is required.' ) : 0;
|
|
}
|
|
|
|
if ( isset( $postarr['ID'] ) && (int) $postarr['ID'] > 0 ) {
|
|
$post_id = (int) $postarr['ID'];
|
|
} else {
|
|
$post_id = (int) ( $GLOBALS['wpcs_test_next_post_id'] ?? 1 );
|
|
$GLOBALS['wpcs_test_next_post_id'] = $post_id + 1;
|
|
}
|
|
|
|
if ( $post_id <= 0 && $wp_error ) {
|
|
return new WP_Error( 'invalid_post_id', 'Post ID is invalid.' );
|
|
}
|
|
|
|
$GLOBALS['wpcs_test_posts'][ $post_id ] = array_merge(
|
|
array(
|
|
'ID' => $post_id,
|
|
'post_title' => '',
|
|
'post_content' => '',
|
|
'post_excerpt' => '',
|
|
'post_status' => 'draft',
|
|
'post_type' => 'post',
|
|
'post_name' => '',
|
|
'post_parent' => 0,
|
|
'menu_order' => 0,
|
|
'post_mime_type' => '',
|
|
),
|
|
$postarr,
|
|
array( 'ID' => $post_id )
|
|
);
|
|
|
|
return $post_id;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_update_post' ) ) {
|
|
/**
|
|
* Minimal post updater for unit tests.
|
|
*
|
|
* @param array<string, mixed> $postarr Post data.
|
|
* @param bool $wp_error Whether to return WP_Error on failure.
|
|
* @return int|\WP_Error
|
|
*/
|
|
function wp_update_post( array $postarr, $wp_error = false ) {
|
|
$post_id = (int) ( $postarr['ID'] ?? 0 );
|
|
|
|
if ( $post_id <= 0 || ! isset( $GLOBALS['wpcs_test_posts'][ $post_id ] ) ) {
|
|
return $wp_error ? new WP_Error( 'invalid_post_id', 'Post does not exist.' ) : 0;
|
|
}
|
|
|
|
$GLOBALS['wpcs_test_posts'][ $post_id ] = array_merge(
|
|
$GLOBALS['wpcs_test_posts'][ $post_id ],
|
|
$postarr,
|
|
array( 'ID' => $post_id )
|
|
);
|
|
|
|
return $post_id;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'get_post' ) ) {
|
|
/**
|
|
* Minimal post reader for unit tests.
|
|
*
|
|
* @param mixed $post Post ID.
|
|
* @param string $output Output format.
|
|
* @param string $filter Filter context.
|
|
* @return array<string, mixed>|object|null
|
|
*/
|
|
function get_post( $post = null, $output = 'ARRAY_A', $filter = 'raw' ) {
|
|
$GLOBALS['wpcs_test_post_filter'] = $filter;
|
|
$post_id = (int) $post;
|
|
$data = $GLOBALS['wpcs_test_posts'][ $post_id ] ?? null;
|
|
|
|
if ( null === $data ) {
|
|
return null;
|
|
}
|
|
|
|
return 'OBJECT' === $output ? (object) $data : $data;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'get_posts' ) ) {
|
|
/**
|
|
* Minimal posts query for unit tests.
|
|
*
|
|
* @param array<string, mixed> $args Query args.
|
|
* @return array<int, object>
|
|
*/
|
|
function get_posts( array $args = array() ) {
|
|
$posts = array_values( $GLOBALS['wpcs_test_posts'] ?? array() );
|
|
|
|
if ( isset( $args['post_type'] ) && 'any' !== $args['post_type'] ) {
|
|
$post_types = is_array( $args['post_type'] ) ? $args['post_type'] : array( $args['post_type'] );
|
|
$posts = array_filter(
|
|
$posts,
|
|
static function ( array $post ) use ( $post_types ): bool {
|
|
return in_array( $post['post_type'] ?? '', $post_types, true );
|
|
}
|
|
);
|
|
}
|
|
|
|
if ( isset( $args['meta_key'], $args['meta_value'] ) ) {
|
|
$posts = array_filter(
|
|
$posts,
|
|
static function ( array $post ) use ( $args ): bool {
|
|
$values = $GLOBALS['wpcs_test_post_meta'][ (int) $post['ID'] ][ (string) $args['meta_key'] ] ?? array();
|
|
|
|
foreach ( $values as $value ) {
|
|
if ( (string) $args['meta_value'] === (string) $value ) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
);
|
|
}
|
|
|
|
return array_values( array_map( static fn( array $post ): object => (object) $post, $posts ) );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_delete_post' ) ) {
|
|
/**
|
|
* Minimal post deleter for unit tests.
|
|
*
|
|
* @param int $post_id Post ID.
|
|
* @param bool $force_delete Force delete flag.
|
|
* @return bool
|
|
*/
|
|
function wp_delete_post( $post_id, $force_delete = false ) {
|
|
$GLOBALS['wpcs_test_force_delete'][ (int) $post_id ] = (bool) $force_delete;
|
|
unset( $GLOBALS['wpcs_test_posts'][ (int) $post_id ] );
|
|
unset( $GLOBALS['wpcs_test_post_meta'][ (int) $post_id ] );
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'update_post_meta' ) ) {
|
|
/**
|
|
* Minimal post meta updater for unit tests.
|
|
*
|
|
* @param int $post_id Post ID.
|
|
* @param string $meta_key Meta key.
|
|
* @param mixed $meta_value Meta value.
|
|
* @return bool
|
|
*/
|
|
function update_post_meta( $post_id, $meta_key, $meta_value ) {
|
|
$GLOBALS['wpcs_test_post_meta'][ (int) $post_id ][ (string) $meta_key ] = array( $meta_value );
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'get_post_meta' ) ) {
|
|
/**
|
|
* Minimal post meta reader for unit tests.
|
|
*
|
|
* @param int $post_id Post ID.
|
|
* @param string $key Meta key.
|
|
* @param bool $single Whether to return single value.
|
|
* @return mixed
|
|
*/
|
|
function get_post_meta( $post_id, $key = '', $single = false ) {
|
|
$meta = $GLOBALS['wpcs_test_post_meta'][ (int) $post_id ] ?? array();
|
|
|
|
if ( '' === $key ) {
|
|
return $meta;
|
|
}
|
|
|
|
$values = $meta[ $key ] ?? array();
|
|
|
|
if ( $single ) {
|
|
return $values[0] ?? '';
|
|
}
|
|
|
|
return $values;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'delete_post_meta' ) ) {
|
|
/**
|
|
* Minimal post meta deleter for unit tests.
|
|
*
|
|
* @param int $post_id Post ID.
|
|
* @param string $meta_key Meta key.
|
|
* @return bool
|
|
*/
|
|
function delete_post_meta( $post_id, $meta_key ) {
|
|
unset( $GLOBALS['wpcs_test_post_meta'][ (int) $post_id ][ (string) $meta_key ] );
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_insert_term' ) ) {
|
|
/**
|
|
* Minimal term inserter for unit tests.
|
|
*
|
|
* @param string $term Term name.
|
|
* @param string $taxonomy Taxonomy.
|
|
* @param array<string, mixed> $args Term args.
|
|
* @return array<string, int>|\WP_Error
|
|
*/
|
|
function wp_insert_term( $term, $taxonomy, array $args = array() ) {
|
|
if ( '' === (string) $term || '' === (string) $taxonomy ) {
|
|
return new WP_Error( 'invalid_term', 'Term name and taxonomy are required.' );
|
|
}
|
|
|
|
$term_id = (int) ( $GLOBALS['wpcs_test_next_term_id'] ?? 1 );
|
|
$GLOBALS['wpcs_test_next_term_id'] = $term_id + 1;
|
|
$slug = (string) ( $args['slug'] ?? sanitize_key( $term ) );
|
|
|
|
$GLOBALS['wpcs_test_terms'][ $term_id ] = array(
|
|
'term_id' => $term_id,
|
|
'term_taxonomy_id' => $term_id,
|
|
'name' => (string) $term,
|
|
'taxonomy' => (string) $taxonomy,
|
|
'slug' => $slug,
|
|
'description' => (string) ( $args['description'] ?? '' ),
|
|
'parent' => (int) ( $args['parent'] ?? 0 ),
|
|
);
|
|
|
|
return array(
|
|
'term_id' => $term_id,
|
|
'term_taxonomy_id' => $term_id,
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_update_term' ) ) {
|
|
/**
|
|
* Minimal term updater for unit tests.
|
|
*
|
|
* @param int $term_id Term ID.
|
|
* @param string $taxonomy Taxonomy.
|
|
* @param array<string, mixed> $args Term args.
|
|
* @return array<string, int>|\WP_Error
|
|
*/
|
|
function wp_update_term( $term_id, $taxonomy, array $args = array() ) {
|
|
$term_id = (int) $term_id;
|
|
|
|
if ( ! isset( $GLOBALS['wpcs_test_terms'][ $term_id ] ) ) {
|
|
return new WP_Error( 'invalid_term_id', 'Term does not exist.' );
|
|
}
|
|
|
|
$GLOBALS['wpcs_test_terms'][ $term_id ] = array_merge(
|
|
$GLOBALS['wpcs_test_terms'][ $term_id ],
|
|
$args,
|
|
array(
|
|
'term_id' => $term_id,
|
|
'term_taxonomy_id' => $term_id,
|
|
'taxonomy' => (string) $taxonomy,
|
|
)
|
|
);
|
|
|
|
return array(
|
|
'term_id' => $term_id,
|
|
'term_taxonomy_id' => $term_id,
|
|
);
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'get_term_by' ) ) {
|
|
/**
|
|
* Minimal term reader for unit tests.
|
|
*
|
|
* @param string $field Field name.
|
|
* @param mixed $value Field value.
|
|
* @param string $taxonomy Taxonomy.
|
|
* @return array<string, mixed>|false
|
|
*/
|
|
function get_term_by( $field, $value, $taxonomy ) {
|
|
foreach ( $GLOBALS['wpcs_test_terms'] ?? array() as $term ) {
|
|
if ( (string) ( $term['taxonomy'] ?? '' ) !== (string) $taxonomy ) {
|
|
continue;
|
|
}
|
|
|
|
if ( isset( $term[ $field ] ) && (string) $value === (string) $term[ $field ] ) {
|
|
return $term;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_set_object_terms' ) ) {
|
|
/**
|
|
* Minimal object term relationship setter for unit tests.
|
|
*
|
|
* @param int $object_id Object ID.
|
|
* @param string|array<mixed> $terms Terms.
|
|
* @param string $taxonomy Taxonomy.
|
|
* @return array<int, mixed>
|
|
*/
|
|
function wp_set_object_terms( $object_id, $terms, $taxonomy ) {
|
|
$term_values = is_array( $terms ) ? array_values( $terms ) : array( $terms );
|
|
$GLOBALS['wpcs_test_object_terms'][ (int) $object_id ][ (string) $taxonomy ] = $term_values;
|
|
|
|
return $term_values;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_insert_attachment' ) ) {
|
|
/**
|
|
* Minimal attachment inserter for unit tests.
|
|
*
|
|
* @param array<string, mixed> $args Attachment args.
|
|
* @param mixed $file File path.
|
|
* @param int $parent_post_id Parent post ID.
|
|
* @param bool $wp_error Whether to return WP_Error on failure.
|
|
* @return int|\WP_Error
|
|
*/
|
|
function wp_insert_attachment( array $args, $file = false, $parent_post_id = 0, $wp_error = false ) {
|
|
$GLOBALS['wpcs_test_attachment_files'][] = $file;
|
|
$args['post_type'] = 'attachment';
|
|
$args['post_parent'] = (int) $parent_post_id;
|
|
|
|
return wp_insert_post( $args, $wp_error );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_update_attachment_metadata' ) ) {
|
|
/**
|
|
* Minimal attachment metadata updater for unit tests.
|
|
*
|
|
* @param int $attachment_id Attachment ID.
|
|
* @param mixed $data Metadata.
|
|
* @return bool
|
|
*/
|
|
function wp_update_attachment_metadata( $attachment_id, $data ) {
|
|
$GLOBALS['wpcs_test_attachment_metadata'][ (int) $attachment_id ] = $data;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_get_attachment_metadata' ) ) {
|
|
/**
|
|
* Minimal attachment metadata reader for unit tests.
|
|
*
|
|
* @param int $attachment_id Attachment ID.
|
|
* @return mixed
|
|
*/
|
|
function wp_get_attachment_metadata( $attachment_id ) {
|
|
return $GLOBALS['wpcs_test_attachment_metadata'][ (int) $attachment_id ] ?? false;
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'admin_url' ) ) {
|
|
/**
|
|
* Minimal admin URL helper for unit tests.
|
|
*
|
|
* @param string $path Admin path.
|
|
* @return string
|
|
*/
|
|
function admin_url( $path = '' ) {
|
|
return 'https://example.test/wp-admin/' . ltrim( $path, '/' );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'add_query_arg' ) ) {
|
|
/**
|
|
* Minimal query arg helper for unit tests.
|
|
*
|
|
* @param array<string, string> $args Query args.
|
|
* @param string $url URL.
|
|
* @return string
|
|
*/
|
|
function add_query_arg( array $args, $url ) {
|
|
return $url . ( false === strpos( $url, '?' ) ? '?' : '&' ) . http_build_query( $args );
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_nonce_field' ) ) {
|
|
/**
|
|
* Minimal nonce field renderer for unit tests.
|
|
*
|
|
* @param string $action Nonce action.
|
|
* @param string $name Field name.
|
|
* @return void
|
|
*/
|
|
function wp_nonce_field( $action, $name ) {
|
|
echo '<input type="hidden" name="' . esc_attr( $name ) . '" value="' . esc_attr( $action ) . '" />';
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'submit_button' ) ) {
|
|
/**
|
|
* Minimal submit button renderer for unit tests.
|
|
*
|
|
* @param string $text Button text.
|
|
* @param string $type Button type.
|
|
* @return void
|
|
*/
|
|
function submit_button( $text, $type = 'primary' ) {
|
|
echo '<button class="button button-' . esc_attr( $type ) . '" type="submit">' . esc_html( $text ) . '</button>';
|
|
}
|
|
}
|
|
|
|
if ( ! function_exists( 'wp_die' ) ) {
|
|
/**
|
|
* Minimal WordPress die handler for unit tests.
|
|
*
|
|
* @param mixed $message Message to die with.
|
|
* @return void
|
|
*
|
|
* @throws \RuntimeException Always throws with the provided message.
|
|
*/
|
|
function wp_die( $message ) {
|
|
throw new \RuntimeException( esc_html( $message ) );
|
|
}
|
|
}
|