$args Arguments. * @return array */ public static function build( array $args ): array { global $wpdb; $components = isset( $args['components'] ) && is_array( $args['components'] ) ? $args['components'] : array( 'database' => true, 'plugins' => true, 'themes' => true, 'uploads' => true, ); $exclusions = isset( $args['exclusions'] ) && is_array( $args['exclusions'] ) ? array_values( $args['exclusions'] ) : array(); $payload_hash = isset( $args['payload_hash'] ) ? (string) $args['payload_hash'] : ''; $created = wp_date( 'c' ); if ( ! is_string( $created ) || '' === $created ) { $created = gmdate( 'c' ); } $manifest = array( 'format' => self::FORMAT, 'created_at' => $created, 'plugin_version' => defined( 'BRVERIFY_VERSION' ) ? BRVERIFY_VERSION : '', 'wp_version' => get_bloginfo( 'version' ), 'php_version' => PHP_VERSION, 'siteurl' => site_url( '/' ), 'home' => home_url( '/' ), 'table_prefix' => $wpdb->prefix, 'source' => self::source_info(), 'blog_charset' => get_bloginfo( 'charset' ), 'locale' => get_locale(), 'components' => array( 'database' => ! empty( $components['database'] ), 'plugins' => ! empty( $components['plugins'] ), 'themes' => ! empty( $components['themes'] ), 'uploads' => ! empty( $components['uploads'] ), ), 'exclusions' => $exclusions, 'encryption' => ( isset( $args['encryption'] ) && is_array( $args['encryption'] ) ) ? $args['encryption'] : null, // Non-secret descriptor only (supplied by an add-on). 'integrity' => array( 'algo' => 'sha256', 'manifest_hash_of_payload_list' => $payload_hash, ), 'parts' => array(), 'generator' => 'brverify', // Free always full; extended edition may attach chain metadata via filter. 'chain' => array( 'mode' => 'full', 'backup_id' => isset( $args['backup_id'] ) ? (string) $args['backup_id'] : '', 'parent_backup_id' => null, 'base_full_id' => isset( $args['backup_id'] ) ? (string) $args['backup_id'] : '', 'sequence' => 0, 'db_policy' => 'full_every_run', ), ); // Phase K: trigger metadata (additive; validators ignore unknown keys). $manifest['trigger'] = isset( $args['trigger'] ) && '' !== (string) $args['trigger'] ? (string) $args['trigger'] : 'manual'; if ( 'pre_update' === $manifest['trigger'] && isset( $args['pre_update'] ) && is_array( $args['pre_update'] ) ) { $manifest['pre_update'] = $args['pre_update']; } /** * Filter brverify-v1 manifest before encode. * * @param array $manifest Manifest. * @param array $args Build args. */ $filtered = apply_filters( 'brverify_manifest', $manifest, $args ); return is_array( $filtered ) ? $filtered : $manifest; } /** * Phase L: facts about the source site (informational, additive; validators ignore it). * * Lets a migration tool know the old URLs, filesystem paths and table prefix without * guessing. Older backups simply lack this block. * * @return array */ public static function source_info(): array { global $wpdb; $upload = function_exists( 'wp_upload_dir' ) ? wp_upload_dir( null, false ) : array(); return array( 'siteurl' => site_url(), 'home' => home_url(), 'abspath' => rtrim( str_replace( '\\', '/', ABSPATH ), '/' ), 'content_dir' => rtrim( str_replace( '\\', '/', dirname( \BRVerify\Support\Working_Dir::plugins_root() ) ), '/' ), 'content_url' => content_url(), 'plugin_dir' => rtrim( str_replace( '\\', '/', \BRVerify\Support\Working_Dir::plugins_root() ), '/' ), 'uploads_basedir' => isset( $upload['basedir'] ) ? rtrim( str_replace( '\\', '/', (string) $upload['basedir'] ), '/' ) : '', 'uploads_baseurl' => isset( $upload['baseurl'] ) ? (string) $upload['baseurl'] : '', 'table_prefix' => $wpdb->prefix, 'multisite' => is_multisite(), ); } /** * Encode pretty JSON. * * @param array $manifest Manifest. */ public static function encode( array $manifest ): string { $json = wp_json_encode( $manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES ); return is_string( $json ) ? $json . "\n" : "{}\n"; } }