'capability_here' * To add a page to the network admin (wp-admin/network), use: 'network_admin_menu' => 'capability_here' * To add a page to the user (wp-admin/user) admin, use: 'user_admin_menu' => 'capability_here' * * @since 2.0.0 * @var array */ protected $supported_panels = [ 'network_admin_menu' => 'wu_read_broadcasts', ]; /** * Register ajax forms that we use for send broadcasts. * * @since 2.0.0 * @return void */ public function register_forms(): void { /* * Add new broadcast notice. */ wu_register_form( 'add_new_broadcast_message', [ 'render' => [$this, 'render_add_new_broadcast_modal'], 'handler' => [$this, 'handle_add_new_broadcast_modal'], 'capability' => 'wu_add_broadcasts', ] ); /** * Ajax to render the broadcast targets modal. */ add_action('wu_ajax_wu_modal_targets_display', [$this, 'display_targets_modal']); /** * Ajax to render the targets modal with customers from a specific membership. */ add_action('wu_ajax_wu_modal_product_targets_display', [$this, 'display_product_targets_modal']); } /** * Enqueue the necessary scripts. * * @since 2.0.0 * @return void */ public function register_scripts(): void { parent::register_scripts(); wp_enqueue_editor(); } /** * Renders the broadcast targets modal, when requested. * * @since 2.0.0 * @return void */ public function display_targets_modal(): void { $broadcast_id = wu_request('object_id'); $object = \WP_Ultimo\Models\Broadcast::get_by_id($broadcast_id); $target_type = wu_request('target_type'); $targets = wu_get_broadcast_targets($object->get_id(), $target_type); $display_targets = []; if ($targets) { if ('customers' === $target_type) { foreach ($targets as $key => $value) { $customer = wu_get_customer($value); $url_atts = [ 'id' => $customer->get_id(), ]; $link = wu_network_admin_url('wp-ultimo-edit-customer', $url_atts); $avatar = get_avatar( $customer->get_user_id(), 48, 'identicon', '', [ 'force_display' => true, 'class' => 'wu-rounded-full', ] ); $display_targets[ $key ] = [ 'link' => $link, 'avatar' => $avatar, 'display_name' => $customer->get_display_name(), 'id' => $customer->get_id(), 'description' => $customer->get_email_address(), ]; } } if ('products' === $target_type) { foreach ($targets as $key => $value) { $product = wu_get_product($value); $url_atts = [ 'id' => $product->get_id(), ]; $link = wu_network_admin_url('wp-ultimo-edit-product', $url_atts); $avatar = $product->get_featured_image('thumbnail'); if ($avatar) { $avatar = sprintf('', esc_attr($avatar)); } else { $avatar = ''; } $plan_customers = wu_get_membership_customers($product->get_id()); $customer_count = (int) 0; if ($plan_customers) { $customer_count = count($plan_customers); } // translators: %s is the number of customers. $description = sprintf(__('%s customer(s) targeted.', 'wp-ultimo'), $customer_count); $display_targets[ $key ] = [ 'link' => $link, 'avatar' => $avatar, 'display_name' => $product->get_name(), 'id' => $product->get_id(), 'description' => $description, ]; } } } $args = [ 'targets' => $display_targets, 'wrapper_class' => 'wu-bg-gray-100 wu--mt-3 wu--mb-6 wu-max-h-2', 'modal_class' => '', ]; wu_get_template('broadcast/widget-targets', $args); exit; } /** * Renders the broadcast targets modal, when requested. * * @since 2.0.0 * @return void */ public function display_product_targets_modal(): void { $product_id = wu_request('product_id'); $customers = wu_get_membership_customers($product_id); $display_targets = []; if ($customers) { foreach ($customers as $key => $value) { $customer = wu_get_customer($value); $url_atts = [ 'id' => $customer->get_id(), ]; $link = wu_network_admin_url('wp-ultimo-edit-customer', $url_atts); $avatar = get_avatar( $customer->get_user_id(), 48, 'identicon', '', [ 'force_display' => true, 'class' => 'wu-rounded-full', ] ); $display_targets[ $key ] = [ 'link' => $link, 'avatar' => $avatar, 'display_name' => $customer->get_display_name(), 'id' => $customer->get_id(), 'description' => $customer->get_email_address(), ]; } } $args = [ 'targets' => $display_targets, 'wrapper_class' => 'wu-bg-gray-100 wu--mt-3 wu--mb-6 wu-max-h-2', 'modal_class' => '', ]; wu_get_template('broadcast/widget-targets', $args); exit; } /** * Renders the add new broadcast message modal. * * @since 2.0.0 * @return void */ public function render_add_new_broadcast_modal(): void { $fields = [ 'type' => [ 'type' => 'select-icon', 'title' => __('Broadcast Type', 'wp-ultimo'), 'desc' => __('Select the type of message you want to send.', 'wp-ultimo'), 'placeholder' => '', 'tooltip' => '', 'value' => '', 'classes' => 'wu-w-1/2', 'html_attr' => [ 'v-model' => 'type', ], 'wrapper_html_attr' => [ 'v-show' => 'step === 1', ], 'options' => [ 'broadcast_notice' => [ 'title' => __('Message', 'wp-ultimo'), 'tooltip' => __('Display a message on your customers\' dashboard.', 'wp-ultimo'), 'icon' => 'dashicons-before dashicons-excerpt-view', ], 'broadcast_email' => [ 'title' => __('Email', 'wp-ultimo'), 'tooltip' => __('Send an email to your customers.', 'wp-ultimo'), 'icon' => 'dashicons-before dashicons-email', ], ], ], 'step_note' => [ 'type' => 'note', 'desc' => sprintf('%s', __('← Back to Type Selection', 'wp-ultimo')), 'wrapper_html_attr' => [ 'v-show' => 'step === 2', ], ], 'target_customers' => [ 'type' => 'model', 'title' => __('Target Customers', 'wp-ultimo'), 'desc' => __('This broadcast will be sent to the user or users that are selected here. You can select more than one.', 'wp-ultimo'), 'placeholder' => __('Search a customer...', 'wp-ultimo'), 'min' => 1, 'html_attr' => [ 'v-model' => 'target_customers', 'data-model' => 'customer', 'data-value-field' => 'id', 'data-label-field' => 'display_name', 'data-search-field' => 'display_name', 'data-max-items' => 10000, ], 'wrapper_html_attr' => [ 'v-show' => 'step === 2', ], ], 'target_products' => [ 'type' => 'model', 'title' => __('Target Product', 'wp-ultimo'), 'desc' => __('This broadcast will be sent to the users that have this product. You can select more than one.', 'wp-ultimo'), 'placeholder' => __('Search for a product..', 'wp-ultimo'), 'html_attr' => [ 'v-model' => 'target_products', 'data-model' => 'product', 'data-value-field' => 'id', 'data-label-field' => 'name', 'data-search-field' => 'name', 'data-max-items' => 99, ], 'wrapper_html_attr' => [ 'v-show' => 'step === 2', ], ], 'notice_type' => [ 'title' => __('Message Type', 'wp-ultimo'), 'desc' => __('The color of the notice is based on the type.', 'wp-ultimo'), 'type' => 'select', 'default' => 'success', 'options' => [ 'success' => __('Success (green)', 'wp-ultimo'), 'info' => __('Info (blue)', 'wp-ultimo'), 'warning' => __('Warning (orange)', 'wp-ultimo'), 'error' => __('Error (red)', 'wp-ultimo'), ], 'wrapper_html_attr' => [ 'v-show' => "step === 2 && require('type', 'broadcast_notice')", 'v-cloak' => 1, ], ], 'step_note_2' => [ 'type' => 'note', 'desc' => sprintf('%s', __('← Back to Target Selection', 'wp-ultimo')), 'wrapper_html_attr' => [ 'v-show' => 'step === 3', ], ], 'subject' => [ 'type' => 'text', 'title' => __('Message Subject', 'wp-ultimo'), 'desc' => __('The title will appear above the main content in the notice or used as subject of the email.', 'wp-ultimo'), 'placeholder' => __('Enter a title for your broadcast.', 'wp-ultimo'), 'html_attr' => [ 'v-model' => 'subject', ], 'wrapper_html_attr' => [ 'v-show' => 'step === 3', ], ], 'content' => [ 'id' => 'content', 'title' => __('Content', 'wp-ultimo'), 'desc' => __('The main content of your broadcast.', 'wp-ultimo'), 'type' => 'wp-editor', 'settings' => [ 'tinymce' => ['toolbar1' => 'bold,italic,strikethrough,link,unlink,undo,redo,pastetext'], ], 'html_attr' => [ 'v-model' => 'content', ], 'wrapper_html_attr' => [ 'v-show' => 'step === 3', ], ], 'submit_button' => [ 'type' => 'submit', 'title' => __('Next Step →', 'wp-ultimo'), 'value' => 'save', 'classes' => 'button button-primary wu-w-full', 'wrapper_classes' => 'wu-items-end', 'wrapper_html_attr' => [ 'v-show' => 'step === 1', ], 'html_attr' => [ 'v-bind:disabled' => 'type === ""', 'v-on:click.prevent' => 'step = 2', ], ], 'submit_button_2' => [ 'type' => 'submit', 'title' => __('Next Step →', 'wp-ultimo'), 'value' => 'save', 'classes' => 'button button-primary wu-w-full', 'wrapper_classes' => 'wu-items-end', 'wrapper_html_attr' => [ 'v-show' => 'step === 2', ], 'html_attr' => [ 'v-bind:disabled' => 'target_customers === "" && target_products === ""', // phpcs:ignore 'v-on:click.prevent' => 'step = 3', ], ], 'submit_button_3' => [ 'type' => 'submit', 'title' => __('Send →', 'wp-ultimo'), 'value' => 'save', 'classes' => 'button button-primary wu-w-full', 'wrapper_classes' => 'wu-items-end', 'html_attr' => [ 'v-bind:disabled' => 'subject === ""', ], 'wrapper_html_attr' => [ 'v-show' => 'step === 3', ], ], ]; $form = new \WP_Ultimo\UI\Form( 'add_new_broadcast', $fields, [ 'views' => 'admin-pages/fields', 'classes' => 'wu-modal-form wu-widget-list wu-striped wu-m-0 wu-mt-0', 'field_wrapper_classes' => 'wu-w-full wu-box-border wu-items-center wu-flex wu-justify-between wu-p-4 wu-m-0 wu-border-t wu-border-l-0 wu-border-r-0 wu-border-b-0 wu-border-gray-300 wu-border-solid', 'html_attr' => [ 'data-wu-app' => 'add_new_broadcast', 'data-state' => wu_convert_to_state( [ 'type' => 'broadcast_notice', 'content' => '', 'step' => 1, 'confirmed' => false, 'target_customers' => '', 'target_products' => '', 'subject' => '', ] ), ], ] ); $form->render(); } /** * Handles the add new broadcast modal. * * @since 2.0.0 * @return void */ public function handle_add_new_broadcast_modal(): void { $broadcast = Broadcast_Manager::get_instance(); $broadcast->handle_broadcast(); } /** * Allow child classes to register widgets, if they need them. * * @since 1.8.2 * @return void */ public function register_widgets() {} /** * Returns an array with the labels for the edit page. * * @since 1.8.2 * @return array */ public function get_labels() { return [ 'deleted_message' => __('Broadcast removed successfully.', 'wp-ultimo'), 'search_label' => __('Search Broadcast', 'wp-ultimo'), ]; } /** * Returns the title of the page. * * @since 2.0.0 * @return string Title of the page. */ public function get_title() { return __('Broadcast', 'wp-ultimo'); } /** * Returns the title of menu for this page. * * @since 2.0.0 * @return string Menu label of the page. */ public function get_menu_title() { return __('Broadcasts', 'wp-ultimo'); } /** * Allows admins to rename the sub-menu (first item) for a top-level page. * * @since 2.0.0 * @return string False to use the title menu or string with sub-menu title. */ public function get_submenu_title() { return __('Broadcasts', 'wp-ultimo'); } /** * Returns the action links for that page. * * @since 1.8.2 * @return array */ public function action_links() { return [ [ 'label' => __('Add Broadcast', 'wp-ultimo'), 'icon' => 'wu-circle-with-plus', 'classes' => 'wubox', 'url' => wu_get_form_url('add_new_broadcast_message'), ], [ 'url' => wu_network_admin_url('wp-ultimo-emails'), 'label' => __('System Emails'), 'icon' => 'wu-mail', ], ]; } /** * Loads the list table for this particular page. * * @since 2.0.0 * @return \WP_Ultimo\List_Tables\Base_List_Table */ public function table() { return new \WP_Ultimo\List_Tables\Broadcast_List_Table(); } }