breznflow/includes/Admin/AdminMenu.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

207 lines
5.5 KiB
PHP

<?php
/**
* Admin menu registration and dashboard rendering.
*
* @package BreznFlow
* @since 1.0.0
*/
namespace BreznFlow\Admin;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Registers the BreznFlow admin menu pages and handles delete actions.
*
* @since 1.0.0
*/
class AdminMenu {
/**
* Registers admin menu hooks and loads the themes sub-page.
*
* @since 1.0.0
* @return void
*/
public function register(): void {
add_action( 'admin_menu', array( $this, 'add_menus' ) );
add_action( 'admin_init', array( $this, 'handle_delete_action' ) );
require_once BREZNFLOW_DIR . 'includes/Admin/ThemesPage.php';
( new ThemesPage() )->register();
}
/**
* Adds the top-level menu and submenu pages to wp-admin.
*
* @since 1.0.0
* @return void
*/
public function add_menus(): void {
add_menu_page(
__( 'BreznFlow', 'breznflow' ),
__( 'BreznFlow', 'breznflow' ),
'edit_posts',
'breznflow',
array( $this, 'render_dashboard' ),
'dashicons-networking',
30
);
add_submenu_page(
'breznflow',
__( 'All Workflows', 'breznflow' ),
__( 'All Workflows', 'breznflow' ),
'edit_posts',
'breznflow',
array( $this, 'render_dashboard' )
);
add_submenu_page(
'breznflow',
__( 'Add Workflow', 'breznflow' ),
__( 'Add Workflow', 'breznflow' ),
'edit_posts',
'breznflow-add',
array( $this, 'render_wizard' )
);
add_submenu_page(
'breznflow',
__( 'Themes', 'breznflow' ),
__( 'Themes', 'breznflow' ),
'manage_options',
'breznflow-themes',
array( $this, 'render_themes' )
);
add_submenu_page(
'breznflow',
__( 'Settings', 'breznflow' ),
__( 'Settings', 'breznflow' ),
'manage_options',
'breznflow-settings',
array( $this, 'render_settings' )
);
}
/**
* Handles single and bulk delete actions early (admin_init),
* before any output is sent — so wp_safe_redirect() works correctly.
*/
public function handle_delete_action(): void {
// Only act on our page.
if ( ! isset( $_GET['page'] ) || 'breznflow' !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return;
}
$action = isset( $_GET['action'] ) ? sanitize_key( $_GET['action'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
// ── Single-row delete ─────────────────────────────────────────────────
if ( 'delete' === $action && isset( $_GET['post'] ) && ! isset( $_GET['workflow'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$post_id = (int) sanitize_text_field( wp_unslash( $_GET['post'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if (
$post_id > 0
&& check_admin_referer( 'breznflow_delete_' . $post_id )
&& current_user_can( 'delete_post', $post_id )
) {
wp_trash_post( $post_id );
wp_safe_redirect(
add_query_arg(
array(
'page' => 'breznflow',
'deleted' => '1',
),
admin_url( 'admin.php' )
)
);
exit;
}
}
// ── Bulk delete ───────────────────────────────────────────────────────
// WP_List_Table sends action2 when the bottom select is used.
$bulk = $action;
if ( 'delete' !== $bulk && isset( $_GET['action2'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$bulk = sanitize_key( $_GET['action2'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
if ( 'delete' === $bulk && isset( $_GET['workflow'] ) && is_array( $_GET['workflow'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
check_admin_referer( 'bulk-workflows' );
$count = 0;
$raw_workflows = array_map( 'absint', wp_unslash( $_GET['workflow'] ) );
foreach ( $raw_workflows as $pid ) {
if ( $pid > 0 && current_user_can( 'delete_post', $pid ) ) {
wp_trash_post( $pid );
++$count;
}
}
wp_safe_redirect(
add_query_arg(
array(
'page' => 'breznflow',
'deleted' => $count,
),
admin_url( 'admin.php' )
)
);
exit;
}
}
/**
* Renders the workflow list dashboard page.
*
* @since 1.0.0
* @return void
*/
public function render_dashboard(): void {
require_once BREZNFLOW_DIR . 'includes/Admin/WorkflowListTable.php';
$table = new WorkflowListTable();
$table->prepare_items();
require BREZNFLOW_DIR . 'includes/Admin/views/list.php';
}
/**
* Renders the add-workflow wizard page for the current step.
*
* @since 1.0.0
* @return void
*/
public function render_wizard(): void {
$step = isset( $_GET['step'] ) ? (int) $_GET['step'] : 1; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
switch ( $step ) {
case 2:
require BREZNFLOW_DIR . 'includes/Admin/views/wizard-step-2.php';
break;
case 3:
require BREZNFLOW_DIR . 'includes/Admin/views/wizard-step-3.php';
break;
default:
require BREZNFLOW_DIR . 'includes/Admin/views/wizard-step-1.php';
break;
}
}
/**
* Renders the themes management page.
*
* @since 1.0.0
* @return void
*/
public function render_themes(): void {
require_once BREZNFLOW_DIR . 'includes/Admin/ThemesPage.php';
( new ThemesPage() )->render();
}
/**
* Renders the plugin settings page.
*
* @since 1.0.0
* @return void
*/
public function render_settings(): void {
require BREZNFLOW_DIR . 'includes/Admin/views/settings.php';
}
}