breznflow/includes/Admin/ThemesPage.php
Michael fd83e4810b BreznFlow 1.0.0 — WordPress.org submission
Initial public release of BreznFlow, an n8n workflow renderer for WordPress.
Fully PHPCS-compliant (WordPress Coding Standards), security-hardened,
and ready for WordPress.org plugin review.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 11:27:36 +00:00

188 lines
4.2 KiB
PHP

<?php
/**
* Theme management admin page.
*
* @package BreznFlow
* @since 1.0.0
*/
namespace BreznFlow\Admin;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
use BreznFlow\Features\ThemeImporter;
use BreznFlow\Features\ThemeRegistry;
/**
* Handles theme import, deletion, and the themes admin page rendering.
*
* @since 1.0.0
*/
class ThemesPage {
/**
* Registers admin_init hooks for import and delete handling.
*
* @since 1.0.0
* @return void
*/
public function register(): void {
add_action( 'admin_init', array( $this, 'handle_import' ) );
add_action( 'admin_init', array( $this, 'handle_delete' ) );
}
/**
* Processes the theme import form submission.
* Runs early in admin_init so wp_safe_redirect() works before any output.
*/
public function handle_import(): void {
if ( ! isset( $_GET['page'] ) || 'breznflow-themes' !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}
if ( empty( $_POST['_wpnonce'] ) || empty( $_FILES['breznflow_theme_file'] ) ) {
return;
}
check_admin_referer( 'breznflow_theme_import' );
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Insufficient permissions.', 'breznflow' ) );
}
$file = $_FILES['breznflow_theme_file']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
// Verify file extension.
$filename = isset( $file['name'] ) ? sanitize_file_name( $file['name'] ) : '';
if ( ! str_ends_with( $filename, '.breznflow.json' ) && ! str_ends_with( $filename, '.json' ) ) {
wp_safe_redirect(
add_query_arg(
array(
'page' => 'breznflow-themes',
'error' => 'invalid_file',
),
admin_url( 'admin.php' )
)
);
exit;
}
if ( ! isset( $file['tmp_name'] ) || ! is_uploaded_file( $file['tmp_name'] ) ) {
wp_safe_redirect(
add_query_arg(
array(
'page' => 'breznflow-themes',
'error' => 'upload_failed',
),
admin_url( 'admin.php' )
)
);
exit;
}
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
$raw = file_get_contents( $file['tmp_name'] );
if ( false === $raw ) {
wp_safe_redirect(
add_query_arg(
array(
'page' => 'breznflow-themes',
'error' => 'read_failed',
),
admin_url( 'admin.php' )
)
);
exit;
}
$data = json_decode( $raw, true );
if ( ! is_array( $data ) ) {
wp_safe_redirect(
add_query_arg(
array(
'page' => 'breznflow-themes',
'error' => 'invalid_json',
),
admin_url( 'admin.php' )
)
);
exit;
}
$result = ThemeImporter::import( $data );
if ( is_wp_error( $result ) ) {
wp_safe_redirect(
add_query_arg(
array(
'page' => 'breznflow-themes',
'error' => 'validation',
'message' => rawurlencode( $result->get_error_message() ),
),
admin_url( 'admin.php' )
)
);
exit;
}
wp_safe_redirect(
add_query_arg(
array(
'page' => 'breznflow-themes',
'imported' => '1',
),
admin_url( 'admin.php' )
)
);
exit;
}
/**
* Processes a theme delete action.
*/
public function handle_delete(): void {
if ( ! isset( $_GET['page'] ) || 'breznflow-themes' !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}
if ( empty( $_GET['action'] ) || 'delete_theme' !== $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}
$id = isset( $_GET['theme_id'] ) ? sanitize_key( $_GET['theme_id'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( '' === $id ) {
return;
}
check_admin_referer( 'breznflow_theme_delete_' . $id );
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'Insufficient permissions.', 'breznflow' ) );
}
ThemeImporter::delete( $id );
wp_safe_redirect(
add_query_arg(
array(
'page' => 'breznflow-themes',
'deleted' => '1',
),
admin_url( 'admin.php' )
)
);
exit;
}
/**
* Renders the themes management page.
*
* @since 1.0.0
* @return void
*/
public function render(): void {
require BREZNFLOW_DIR . 'includes/Admin/views/themes.php';
}
}