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>
207 lines
5.5 KiB
PHP
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';
|
|
}
|
|
}
|