groups = class_exists( 'WC_EDM_Admin_Groups' ) ? new WC_EDM_Admin_Groups() : null; $this->emails = class_exists( 'WC_EDM_Admin_Emails' ) ? new WC_EDM_Admin_Emails() : null; $this->shipping = class_exists( 'WC_EDM_Admin_Shipping' ) ? new WC_EDM_Admin_Shipping() : null; $this->audit = class_exists( 'WC_EDM_Admin_Audit' ) ? new WC_EDM_Admin_Audit() : null; add_action( 'admin_menu', array( $this, 'register_menu' ) ); add_filter( 'wpmgr_dashboard_cards', array( $this, 'dashboard_card' ) ); add_action( 'admin_init', array( $this, 'handle_actions' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); } /** * This plugin's card on the shared Nolimit dashboard. * * The contract says implementations must not measure anything here, * because this filter runs on an admin page load and a slow card makes * somebody else's dashboard slow in a way they cannot attribute. Two * COUNT(*) on small indexed tables is the most this may cost, and even * that is cached: the dashboard is a page people leave open. * * @param array $cards The cards so far. * @return array */ public function dashboard_card( $cards ) { $counts = get_transient( self::CARD_TRANSIENT ); if ( ! is_array( $counts ) ) { $counts = array( 'groups' => WC_EDM_DB::count_groups(), 'emails' => WC_EDM_DB::count_emails( true ), ); set_transient( self::CARD_TRANSIENT, $counts, 5 * MINUTE_IN_SECONDS ); } // "warn", not "fail": a shop that has installed this and not set it up // yet is not broken, it is unfinished. Reserving red for actual // breakage is what keeps red worth reading. $status = $counts['groups'] > 0 && $counts['emails'] > 0 ? 'ok' : 'warn'; $cards[] = array( 'title' => __( 'Discounts', 'wc-email-discount' ), 'status' => $status, 'headline' => sprintf( /* translators: %s: number of email addresses that currently receive a discount. */ _n( '%s address gets a discount', '%s addresses get a discount', $counts['emails'], 'wc-email-discount' ), number_format_i18n( $counts['emails'] ) ), 'lines' => array( __( 'Groups', 'wc-email-discount' ) => number_format_i18n( $counts['groups'] ), __( 'Active addresses', 'wc-email-discount' ) => number_format_i18n( $counts['emails'] ), ), 'url' => admin_url( 'admin.php?page=' . self::PAGE_SLUG ), // The plugin's own colour. Deliberately not WooCommerce's brand // purple; see the note in assets/icon.svg. 'colour' => '#1a7a52', ); return $cards; } /** * Register the page under the shared Nolimit menu. * * wpmgr_ensure_menu() must be called first and is a no-op when another of * the five plugins already registered the parent — whichever booted first * owns it, and none of them may assume it is theirs. * * The page slug is unchanged, so admin.php?page=… still resolves: moving a * page between parents does not move its URL, and an existing bookmark or * a link in an email keeps working. */ public function register_menu() { if ( function_exists( 'wpmgr_ensure_menu' ) ) { wpmgr_ensure_menu(); $parent = WPMGR_MENU_SLUG; } else { // The shared file is missing — a half-copied upgrade. Fall back to // the old home rather than losing the page entirely. $parent = 'woocommerce'; } add_submenu_page( $parent, __( 'Discounts', 'wc-email-discount' ), __( 'Discounts', 'wc-email-discount' ), 'manage_woocommerce', self::PAGE_SLUG, array( $this, 'render_page' ) ); } /** * Enqueue admin CSS/JS on the plugin page only. * * @param string $hook Current admin page hook. */ public function enqueue_assets( $hook ) { if ( false === strpos( $hook, self::PAGE_SLUG ) ) { return; } wp_enqueue_style( 'wc-edm-admin', WC_EDM_PLUGIN_URL . 'assets/css/admin.css', array(), WC_EDM_VERSION ); wp_enqueue_script( 'wc-edm-admin', WC_EDM_PLUGIN_URL . 'assets/js/admin.js', array( 'jquery', 'jquery-ui-sortable' ), WC_EDM_VERSION, true ); wp_localize_script( 'wc-edm-admin', 'wcEdmAdmin', array( 'confirmDelete' => __( 'Are you sure you want to delete this item? This cannot be undone.', 'wc-email-discount' ), ) ); } /** * Get the currently active tab. * * @return string */ public function current_tab() { $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'dashboard'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $tabs = array_keys( $this->get_tabs() ); return in_array( $tab, $tabs, true ) ? $tab : 'dashboard'; } /** * Tab definitions. * * @return array */ private function get_tabs() { $tabs = array( 'dashboard' => __( 'Dashboard', 'wc-email-discount' ) ); // Only offer tabs whose controller actually loaded. if ( $this->groups ) { $tabs['groups'] = __( 'Discount Groups', 'wc-email-discount' ); } if ( $this->emails ) { $tabs['emails'] = __( 'Email Assignments', 'wc-email-discount' ); } if ( $this->shipping ) { $tabs['shipping'] = __( 'Shipping Rules', 'wc-email-discount' ); } if ( $this->audit ) { $tabs['audit'] = __( 'Audit Log', 'wc-email-discount' ); } return $tabs; } /** * Handle POST/GET actions before any output (allows redirects). */ public function handle_actions() { if ( ! isset( $_GET['page'] ) || self::PAGE_SLUG !== $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended return; } if ( ! current_user_can( 'manage_woocommerce' ) ) { return; } switch ( $this->current_tab() ) { case 'groups': $this->groups->handle_actions(); break; case 'emails': $this->emails->handle_actions(); break; case 'shipping': $this->shipping->handle_actions(); break; case 'audit': $this->audit->handle_actions(); break; } } /** * Render the admin page with tab navigation. */ public function render_page() { if ( ! current_user_can( 'manage_woocommerce' ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'wc-email-discount' ) ); } $current = $this->current_tab(); ?>
%2$s
| name ); ?> | discount_percent ) ); ?>% | id ) ) ); ?> | created_at ) ) ); ?> |