init_hooks(); } /** * Initialize hooks. */ private function init_hooks() { add_action( 'admin_menu', array( $this, 'add_admin_menu' ) ); add_action( 'admin_post_afridirect_create_request', array( $this, 'handle_create' ) ); add_action( 'admin_post_afridirect_request_action', array( $this, 'handle_action' ) ); } /** * Add admin menu. */ public function add_admin_menu() { $menu_manager = AfriDirect_Payment_Admin_Menu::instance(); add_submenu_page( $menu_manager->get_menu_slug(), __( 'Payment Requests', 'afridirect-payment' ), __( 'Payment Requests', 'afridirect-payment' ), $menu_manager->get_capability(), 'afridirect-payment-requests', array( $this, 'render_page' ) ); } /** * Capability needed to manage requests. * * @return string */ private function capability() { return AfriDirect_Payment_Admin_Menu::instance()->get_capability(); } /** * Currency codes suggested in the form. * * @return string[] */ private function currency_suggestions() { return array( 'USD', 'EUR', 'GBP', 'NGN', 'GHS', 'KES', 'ZAR', 'UGX', 'TZS', 'XOF', 'XAF', 'CAD', 'AUD', 'AED', 'INR' ); } /** * Currency to pre-fill: the one used last, else the store's, else USD. * * @return string */ private function default_currency() { $last = strtoupper( (string) get_option( 'afridirect_last_request_currency', '' ) ); if ( '' !== $last ) { return $last; } $store = function_exists( 'get_woocommerce_currency' ) ? strtoupper( (string) get_woocommerce_currency() ) : ''; return '' !== $store ? $store : 'USD'; } /** * Render the screen: the list, or the "new request" form. */ public function render_page() { if ( ! current_user_can( $this->capability() ) ) { wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'afridirect-payment' ) ); } // Which view to show and one-time notices. Display only; nothing is changed by these arguments. // phpcs:disable WordPress.Security.NonceVerification.Recommended $view = ( isset( $_GET['view'] ) && 'new' === sanitize_key( wp_unslash( $_GET['view'] ) ) ) ? 'new' : 'list'; $notice = isset( $_GET['afd_notice'] ) ? sanitize_key( wp_unslash( $_GET['afd_notice'] ) ) : ''; $created = isset( $_GET['afd_created'] ) ? absint( wp_unslash( $_GET['afd_created'] ) ) : 0; $mail = isset( $_GET['afd_mail'] ) ? sanitize_key( wp_unslash( $_GET['afd_mail'] ) ) : ''; $error = isset( $_GET['afd_error'] ) ? sanitize_key( wp_unslash( $_GET['afd_error'] ) ) : ''; // phpcs:enable WordPress.Security.NonceVerification.Recommended $methods = AfriDirect_Payment_Methods::get_all(); if ( 'new' === $view ) { // Values typed before a validation error, so the form is not lost. $draft_key = 'afridirect_request_draft_' . get_current_user_id(); $draft = get_transient( $draft_key ); $draft = is_array( $draft ) ? $draft : array(); delete_transient( $draft_key ); $values = wp_parse_args( $draft, array( 'customer_name' => '', 'customer_email' => '', 'amount' => '', 'currency' => $this->default_currency(), 'note' => '', 'method_ids' => array_keys( $methods ), 'timer_minutes' => 30, 'valid_days' => 7, 'send_email' => 1, ) ); $currencies = $this->currency_suggestions(); include AFRIDIRECT_PAYMENT_PLUGIN_DIR . 'admin/views/request-new.php'; return; } $requests = AfriDirect_Payment_Requests::get_all( 100 ); $created_request = $created ? AfriDirect_Payment_Requests::get( $created ) : false; $created_link = $created_request ? AfriDirect_Payment_Requests::get_link( $created_request ) : ''; $notice_messages = array( 'cancelled' => __( 'Request cancelled. Its link no longer works.', 'afridirect-payment' ), 'deleted' => __( 'Request deleted.', 'afridirect-payment' ), 'resent' => __( 'Email sent.', 'afridirect-payment' ), 'resend_failed' => __( 'The email could not be sent. Check that the customer has an email address and that your site can send email.', 'afridirect-payment' ), ); include AFRIDIRECT_PAYMENT_PLUGIN_DIR . 'admin/views/requests.php'; } /** * A nonce-protected link to a row action. * * @param string $do Action: cancel, delete or resend. * @param int $request_id Request ID. * @return string */ public function action_url( $do, $request_id ) { return wp_nonce_url( add_query_arg( array( 'action' => 'afridirect_request_action', 'do' => $do, 'request_id' => $request_id, ), admin_url( 'admin-post.php' ) ), 'afridirect_request_' . $do . '_' . $request_id ); } /** * Create a request from the form. */ public function handle_create() { if ( ! current_user_can( $this->capability() ) ) { wp_die( esc_html__( 'You do not have permission to create payment requests.', 'afridirect-payment' ), '', array( 'response' => 403 ) ); } check_admin_referer( 'afridirect_create_request', 'afridirect_request_nonce' ); $data = array( 'customer_name' => isset( $_POST['customer_name'] ) ? sanitize_text_field( wp_unslash( $_POST['customer_name'] ) ) : '', 'customer_email' => isset( $_POST['customer_email'] ) ? sanitize_text_field( wp_unslash( $_POST['customer_email'] ) ) : '', 'amount' => isset( $_POST['amount'] ) ? sanitize_text_field( wp_unslash( $_POST['amount'] ) ) : '', 'currency' => isset( $_POST['currency'] ) ? sanitize_text_field( wp_unslash( $_POST['currency'] ) ) : '', 'note' => isset( $_POST['note'] ) ? sanitize_textarea_field( wp_unslash( $_POST['note'] ) ) : '', 'method_ids' => isset( $_POST['method_ids'] ) && is_array( $_POST['method_ids'] ) ? array_map( 'sanitize_key', wp_unslash( $_POST['method_ids'] ) ) : array(), 'timer_minutes' => isset( $_POST['timer_minutes'] ) ? absint( wp_unslash( $_POST['timer_minutes'] ) ) : 30, 'valid_days' => isset( $_POST['valid_days'] ) ? absint( wp_unslash( $_POST['valid_days'] ) ) : 7, 'send_email' => isset( $_POST['send_email'] ) ? 1 : 0, ); $result = AfriDirect_Payment_Requests::create( $data ); if ( is_wp_error( $result ) ) { set_transient( 'afridirect_request_draft_' . get_current_user_id(), $data, 5 * MINUTE_IN_SECONDS ); wp_safe_redirect( add_query_arg( array( 'view' => 'new', 'afd_error' => $result->get_error_code(), ), AfriDirect_Payment_Admin_UI::page_url( 'afridirect-payment-requests' ) ) ); exit; } update_option( 'afridirect_last_request_currency', strtoupper( preg_replace( '/[^A-Za-z]/', '', $data['currency'] ) ), false ); $mail = 'none'; if ( $data['send_email'] && '' !== $data['customer_email'] ) { $mail = AfriDirect_Payment_Email_Handler::instance()->send_request_email( $result ) ? 'sent' : 'failed'; } wp_safe_redirect( add_query_arg( array( 'afd_created' => $result, 'afd_mail' => $mail, ), AfriDirect_Payment_Admin_UI::page_url( 'afridirect-payment-requests' ) ) ); exit; } /** * Cancel, delete or re-send a request. */ public function handle_action() { if ( ! current_user_can( $this->capability() ) ) { wp_die( esc_html__( 'You do not have permission to manage payment requests.', 'afridirect-payment' ), '', array( 'response' => 403 ) ); } // The nonce is part of the link and is verified below; it is specific to this action and request. // phpcs:disable WordPress.Security.NonceVerification.Recommended $do = isset( $_GET['do'] ) ? sanitize_key( wp_unslash( $_GET['do'] ) ) : ''; $request_id = isset( $_GET['request_id'] ) ? absint( wp_unslash( $_GET['request_id'] ) ) : 0; // phpcs:enable WordPress.Security.NonceVerification.Recommended if ( ! in_array( $do, array( 'cancel', 'delete', 'resend' ), true ) || ! $request_id ) { wp_die( esc_html__( 'That action is not available.', 'afridirect-payment' ), '', array( 'response' => 400 ) ); } check_admin_referer( 'afridirect_request_' . $do . '_' . $request_id ); $notice = ''; if ( 'cancel' === $do ) { AfriDirect_Payment_Requests::cancel( $request_id ); $notice = 'cancelled'; } elseif ( 'delete' === $do ) { AfriDirect_Payment_Requests::delete( $request_id ); $notice = 'deleted'; } else { $notice = AfriDirect_Payment_Email_Handler::instance()->send_request_email( $request_id ) ? 'resent' : 'resend_failed'; } wp_safe_redirect( add_query_arg( 'afd_notice', $notice, AfriDirect_Payment_Admin_UI::page_url( 'afridirect-payment-requests' ) ) ); exit; } }