ID ) as $c ) { if ( ! isset( $out[ $c['id'] ] ) ) { $out[ $c['id'] ] = $c['name']; } elseif ( false === strpos( $out[ $c['id'] ], $c['name'] ) ) { $out[ $c['id'] ] .= ' / ' . $c['name']; } } } return $out ?: array( 'standard' => __( 'Standard', 'seathive' ), 'vip' => __( 'VIP', 'seathive' ) ); } public function move_above_settings() { global $submenu; if ( empty( $submenu['seatt-main'] ) ) { return; } $submenu['seatt-main'] = self::reorder( $submenu['seatt-main'], array( 'seatt-promos', 'seatt-activity-log', 'seatt-refunds' ) ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride } /** Moves the given slugs (in that order) directly above Settings. */ public static function reorder( array $items, array $slugs ) { $items = array_values( $items ); $moved = array(); foreach ( $slugs as $slug ) { foreach ( $items as $i => $it ) { if ( $slug === ( $it[2] ?? '' ) ) { $moved[] = $it; unset( $items[ $i ] ); } } } $out = array(); $placed = false; foreach ( $items as $it ) { if ( ! $placed && 'seatt-settings' === ( $it[2] ?? '' ) ) { $out = array_merge( $out, $moved ); $placed = true; } $out[] = $it; } return $placed ? $out : array_merge( $out, $moved ); } private function back( $args = array() ) { wp_safe_redirect( add_query_arg( $args, admin_url( 'admin.php?page=seatt-promos' ) ) ); exit; } public function save() { global $wpdb; if ( ! current_user_can( 'manage_options' ) || ! check_admin_referer( 'seatt_promo' ) ) { wp_die( esc_html__( 'Not allowed.', 'seathive' ) ); } $code = SEATT_Pricing::normalize_code( sanitize_text_field( wp_unslash( $_POST['code'] ?? '' ) ) ); if ( strlen( $code ) < 3 ) { $this->back( array( 'seatt_err' => rawurlencode( __( 'Use at least 3 letters/numbers for the code.', 'seathive' ) ) ) ); } $type = 'amount' === sanitize_key( wp_unslash( $_POST['type'] ?? '' ) ) ? 'amount' : 'percent'; $value = max( 0, floatval( $_POST['value'] ?? 0 ) ); if ( 'percent' === $type ) { $value = min( 100, $value ); } $date = function ( $k ) { $v = sanitize_text_field( wp_unslash( $_POST[ $k ] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- nonce checked by the caller (save_post / admin-post handler) return preg_match( '/^\d{4}-\d{2}-\d{2}$/', $v ) ? $v . ( 'ends_at' === $k ? ' 23:59:59' : ' 00:00:00' ) : null; }; $data = array( 'code' => $code, 'type' => $type, 'value' => $value, 'event_id' => max( 0, intval( $_POST['event_id'] ?? 0 ) ), 'category' => sanitize_key( $_POST['category'] ?? '' ), 'max_uses' => max( 0, intval( $_POST['max_uses'] ?? 0 ) ), 'per_email' => max( 0, intval( $_POST['per_email'] ?? 0 ) ), 'min_tickets' => max( 0, intval( $_POST['min_tickets'] ?? 0 ) ), 'starts_at' => $date( 'starts_at' ), 'ends_at' => $date( 'ends_at' ), ); $id = intval( $_POST['id'] ?? 0 ); if ( $id ) { $wpdb->update( $wpdb->seatt_promos, $data, array( 'id' => $id ) ); } else { if ( SEATT_Pricing::get_promo( $code ) ) { $this->back( array( 'seatt_err' => rawurlencode( __( 'That code already exists.', 'seathive' ) ) ) ); } $data['active'] = 1; $data['created_at'] = current_time( 'mysql' ); $wpdb->insert( $wpdb->seatt_promos, $data ); } $this->back( array( 'seatt_ok' => 1 ) ); } public function action() { global $wpdb; if ( ! current_user_can( 'manage_options' ) || ! check_admin_referer( 'seatt_promo_action' ) ) { wp_die( esc_html__( 'Not allowed.', 'seathive' ) ); } $id = intval( $_GET['id'] ?? 0 ); switch ( sanitize_key( $_GET['op'] ?? '' ) ) { case 'pause': $wpdb->update( $wpdb->seatt_promos, array( 'active' => 0 ), array( 'id' => $id ) ); break; case 'resume': $wpdb->update( $wpdb->seatt_promos, array( 'active' => 1 ), array( 'id' => $id ) ); break; case 'delete': $wpdb->delete( $wpdb->seatt_promos, array( 'id' => $id ) ); break; } $this->back( array( 'seatt_ok' => 1 ) ); } public function render() { global $wpdb; $promos = $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM %i ORDER BY id DESC', $wpdb->seatt_promos ) ); $events = get_posts( array( 'post_type' => 'seatt_event', 'numberposts' => 200, 'post_status' => 'any' ) ); $edit = null; if ( ! empty( $_GET['edit'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only: chooses what to display $edit = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM %i WHERE id = %d', $wpdb->seatt_promos, intval( $_GET['edit'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- read-only: chooses what to display } $v = function ( $k, $d = '' ) use ( $edit ) { return $edit ? $edit->$k : $d; }; ?>