<?php
/**
 * PHP/JS snippet runtime — packed only in the Pro add-on overlay.
 *
 * Secure design (rafter-secure-design / auth):
 * - Identity: site admin (manage_options) authoring snippets.
 * - AuthZ: This file is physically absent from the wordpress.org Lite zip.
 *   Lite HTML/CSS snippets cannot reach eval/include. Presence of the Pro
 *   overlay + a valid license unlocks JS/PHP. A license filter flip without
 *   these files cannot execute missing PHP.
 * - Untrusted input: user PHP/JS runs only after threat scanning in Module.
 *
 * @package CodeSnippet
 */

namespace CodeSnippet;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Executes licensed PHP/JS snippets. Not loaded in Lite.
 */
final class PremiumPhpJsRuntime {

	public static function isReady(): bool {
		return true;
	}

	/**
	 * Run raw PHP (no opening tag) in the global namespace.
	 */
	public static function run( string $code ): void {
		if ( $code === '' ) {
			return;
		}

		if ( apply_filters( 'wpps_code_snippet_use_eval', false, $code ) ) {
			if ( function_exists( 'wp_powersuite_code_snippet_eval' ) ) {
				\wp_powersuite_code_snippet_eval( $code );
			}
			return;
		}

		$file = self::createTempPhpSnippetFile( $code );
		if ( $file !== '' ) {
			try {
				include $file; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.NotAbsolutePath -- Temp snippet file in get_temp_dir().
			} finally {
				wp_delete_file( $file );
			}
			return;
		}

		if ( function_exists( 'wp_powersuite_code_snippet_eval' ) ) {
			\wp_powersuite_code_snippet_eval( $code );
		}
	}

	/**
	 * Include a path already validated by Module::resolveAllowedPhpSnippetFile().
	 */
	public static function includeResolvedFile( string $resolved ): void {
		include $resolved; // phpcs:ignore WordPressVIPMinimum.Files.IncludingFile.NotAbsolutePath
	}

	public static function wrapJs( string $code ): string {
		$code = Module::stripJsTagsForStorage( $code );
		if ( $code === '' ) {
			return '';
		}

		return '<script>' . "\n" . $code . "\n" . '</script>';
	}

	public static function createTempPhpSnippetFile( string $code ): string {
		$dir = get_temp_dir();
		$dir = is_string( $dir ) ? trailingslashit( wp_normalize_path( $dir ) ) : '';
		if ( $dir === '' ) {
			return '';
		}

		$payload = '<' . '?php' . "\n" . $code . "\n";
		$tmp     = $dir . 'wpps_snip_' . bin2hex( random_bytes( 8 ) ) . '.php';
		if ( file_put_contents( $tmp, $payload ) !== false ) {
			return $tmp;
		}

		$probe = tempnam( $dir, 'wps' );
		if ( ! is_string( $probe ) || $probe === '' ) {
			return '';
		}
		$named = $dir . 'wpps_snip_' . bin2hex( random_bytes( 8 ) ) . '.php';
		if ( ! @rename( $probe, $named ) ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.rename_rename -- tempnam() fallback to a wpps_snip_ name.
			wp_delete_file( $probe );
			return '';
		}
		if ( file_put_contents( $named, $payload ) === false ) {
			wp_delete_file( $named );
			return '';
		}

		return $named;
	}
}
