diff --git a/includes/Emails/Manager.php b/includes/Emails/Manager.php index 36b56d644f..4529c25124 100755 --- a/includes/Emails/Manager.php +++ b/includes/Emails/Manager.php @@ -92,6 +92,7 @@ public function load_dokan_emails( $wc_emails ) { $wc_emails['Dokan_Email_New_Order'] = new VendorNewOrder(); $wc_emails['Dokan_Email_Completed_Order'] = new VendorCompletedOrder(); $wc_emails['Dokan_Email_Reverse_Withdrawal_Invoice'] = new ReverseWithdrawalInvoice(); + $wc_emails['Dokan_Email_Vendor_Product_Review'] = new VendorProductReview(); return apply_filters( 'dokan_email_classes', $wc_emails ); } @@ -153,6 +154,8 @@ public function register_email_actions( $actions ) { 'dokan_withdraw_request_cancelled', 'dokan_pending_product_published_notification', 'dokan_trigger_contact_seller_mail', + 'wp_set_comment_status', + 'comment_post', ) ); diff --git a/includes/Emails/VendorProductReview.php b/includes/Emails/VendorProductReview.php new file mode 100644 index 0000000000..8ae7f380c2 --- /dev/null +++ b/includes/Emails/VendorProductReview.php @@ -0,0 +1,229 @@ +id = 'dokan_contact_seller'; + $this->title = __( 'Dokan Vendor Product Review', 'dokan-lite' ); + $this->description = __( 'After a product has been reviewed, an email is sent to the vendor containing information about the review. The email may include details such as the reviewer’s name, the product’s name and description, the review rating, and the review text. The email may also contain a link to the review page where the vendor can view the review and respond to it if necessary.', 'dokan-lite' ); + $this->template_html = 'emails/vendor-product-review.php'; + $this->template_plain = 'emails/plain/vendor-product-review.php'; + $this->template_base = DOKAN_DIR . '/templates/'; + $this->placeholders = [ + '{store_name}' => '', + '{product_name}' => '', + '{customer_name}' => '', + '{rating}' => '', + '{review_text}' => '', + '{review_link}' => '', + ]; + + // Triggers for this email + add_action( 'wp_set_comment_status', [ $this, 'trigger' ], 35, 1 ); + add_action( 'comment_post', [ $this, 'trigger' ], 35, 1 ); + + // Call parent constructor + parent::__construct(); + + // Other settings + $this->recipient = 'vendor@ofthe.product'; + } + + /** + * Get the email subject. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_default_subject() { + return __( 'New Product Review Alert from {site_title}', 'dokan-lite' ); + } + + /** + * Get email heading. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_default_heading() { + return __( 'New Product Review Alert From Your Store: {store_name} at - {site_title}', 'dokan-lite' ); + } + + /** + * Trigger this email. + * + * @since DOKAN_SINCE + * + * @param int $comment_id + * + * @return void + */ + public function trigger( $comment_id ) { + if ( ! $this->is_enabled() || ! $this->get_recipient() ) { + return; + } + + $comment = get_comment( $comment_id ); + + $product = wc_get_product( $comment->comment_post_ID ); + if ( ! $product ) { + // the review is not for a product + return; + } + + $this->setup_locale(); + + $this->from_email = get_option( 'admin_email' ); + + // get the vendor + $seller = dokan_get_vendor_by_product( $product->get_id() ); + + $this->placeholders['{store_name}'] = $seller->get_shop_name(); + $this->placeholders['{product_name}'] = $product->get_title(); + $this->placeholders['{customer_name}'] = $comment->comment_author; + $this->placeholders['{rating}'] = (int) get_comment_meta( $comment->comment_ID, 'rating', true ); + $this->placeholders['{review_text}'] = wp_specialchars_decode( $comment->comment_content ); + $this->placeholders['{review_link}'] = get_comment_link( $comment ); + $this->send( $seller->get_email(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); + $this->restore_locale(); + } + + /** + * Get the from address for outgoing emails. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_from_address( $from_email = '' ) { + return $this->from_email; + } + + /** + * Get content html. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_content_html() { + return wc_get_template_html( + $this->template_html, + [ + 'email_heading' => $this->get_heading(), + 'additional_content' => $this->get_additional_content(), + 'sent_to_admin' => false, + 'plain_text' => false, + 'email' => $this, + 'data' => $this->placeholders, + ], + 'dokan/', $this->template_base + ); + } + + /** + * Get content plain. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_content_plain() { + return wc_get_template_html( + $this->template_plain, + [ + 'email_heading' => $this->get_heading(), + 'additional_content' => $this->get_additional_content(), + 'sent_to_admin' => false, + 'plain_text' => true, + 'email' => $this, + 'data' => $this->placeholders, + ], + 'dokan/', $this->template_base + ); + } + + /** + * Initialize settings form fields. + * + * @since DOKAN_SINCE + */ + public function init_form_fields() { + /* translators: %s: list of placeholders */ + $placeholder_text = sprintf( __( 'Available placeholders: %s', 'dokan-lite' ), '' . implode( ', ', array_keys( $this->placeholders ) ) . '' ); + $this->form_fields = [ + 'enabled' => [ + 'title' => __( 'Enable/Disable', 'dokan-lite' ), + 'type' => 'checkbox', + 'label' => __( 'Enable this email notification', 'dokan-lite' ), + 'default' => 'yes', + ], + + 'subject' => [ + 'title' => __( 'Subject', 'dokan-lite' ), + 'type' => 'text', + 'desc_tip' => true, + 'description' => $placeholder_text, + 'placeholder' => $this->get_default_subject(), + 'default' => $this->get_default_subject(), + ], + 'heading' => [ + 'title' => __( 'Email heading', 'dokan-lite' ), + 'type' => 'text', + 'desc_tip' => true, + 'description' => $placeholder_text, + 'placeholder' => $this->get_default_heading(), + 'default' => $this->get_default_heading(), + ], + 'additional_content' => [ + 'title' => __( 'Additional content', 'dokan-lite' ), + 'description' => __( 'Text to appear below the main email content.', 'dokan-lite' ) . ' ' . $placeholder_text, + 'css' => 'width:400px; height: 75px;', + 'placeholder' => __( 'N/A', 'dokan-lite' ), + 'type' => 'textarea', + 'default' => $this->get_default_additional_content(), + 'desc_tip' => false, + ], + 'email_type' => [ + 'title' => __( 'Email type', 'dokan-lite' ), + 'type' => 'select', + 'description' => __( 'Choose which format of email to send.', 'dokan-lite' ), + 'default' => 'html', + 'class' => 'email_type wc-enhanced-select', + 'options' => $this->get_email_type_options(), + 'desc_tip' => true, + ], + ]; + } +} diff --git a/includes/Product/Hooks.php b/includes/Product/Hooks.php index 0e67bd006d..477038bfec 100644 --- a/includes/Product/Hooks.php +++ b/includes/Product/Hooks.php @@ -24,24 +24,9 @@ public function __construct() { add_action( 'dokan_bulk_product_status_change', [ $this, 'bulk_product_delete' ], 10, 2 ); add_action( 'dokan_store_profile_frame_after', [ $this, 'store_products_orderby' ], 30, 2 ); add_action( 'wp_ajax_dokan_store_product_search_action', [ $this, 'store_product_search_action' ], 10, 2 ); - add_action( - 'wp_ajax_nopriv_dokan_store_product_search_action', [ - $this, - 'store_product_search_action', - ], 10, 2 - ); - add_action( - 'woocommerce_product_quick_edit_save', [ - $this, - 'update_category_data_for_bulk_and_quick_edit', - ], 10, 1 - ); - add_action( - 'woocommerce_product_bulk_edit_save', [ - $this, - 'update_category_data_for_bulk_and_quick_edit', - ], 10, 1 - ); + add_action( 'wp_ajax_nopriv_dokan_store_product_search_action', [ $this, 'store_product_search_action' ], 10, 2 ); + add_action( 'woocommerce_product_quick_edit_save', [ $this, 'update_category_data_for_bulk_and_quick_edit' ], 10, 1 ); + add_action( 'woocommerce_product_bulk_edit_save', [ $this, 'update_category_data_for_bulk_and_quick_edit' ], 10, 1 ); add_action( 'woocommerce_new_product', [ $this, 'update_category_data_for_new_and_update_product' ], 10, 1 ); add_action( 'woocommerce_update_product', [ $this, 'update_category_data_for_new_and_update_product' ], 10, 1 ); add_filter( 'dokan_post_status', [ $this, 'set_product_status' ], 1, 2 ); @@ -50,6 +35,9 @@ public function __construct() { // Remove product type filter if pro not exists. add_filter( 'dokan_product_listing_filter_args', [ $this, 'remove_product_type_filter' ] ); + // product review action hook + add_action( 'comment_notification_recipients', [ $this, 'product_review_notification_recipients' ], 10, 2 ); + // Init Product Cache Class new VendorStoreInfo(); new ProductCache(); @@ -58,8 +46,8 @@ public function __construct() { /** * Callback for Ajax Action Initialization * - * @return void * @since DOKAN_LITE_SINCE + * @return void */ public function store_product_search_action() { if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_POST['_wpnonce'] ), 'dokan_store_product_search_nonce' ) ) { @@ -179,8 +167,8 @@ public function store_product_search_action() { /** * Output the store product sorting options * - * @return void * @since DOKAN_LITE_SINCE + * @return void */ public function store_products_orderby() { $store_products = dokan_get_option( 'store_products', 'dokan_appearance' ); @@ -196,11 +184,11 @@ public function store_products_orderby() {
+ placeholder="" autocomplete="off" + data-store_id="">
+ value="">