post_type ) { return $actions; } if ( ! current_user_can( 'manage_woocommerce' ) ) { return $actions; } $coupon_code = ( ! empty( $post->post_title ) ) ? $post->post_title : ''; $coupon_id = ( ! empty( $post->ID ) ) ? $post->ID : 0; $shop_page_id = get_option( 'woocommerce_shop_page_id', 0 ); if ( ! empty( $shop_page_id ) ) { $shop_page_id = 'shop'; } else { $home_url = home_url(); $shop_page_id = ( function_exists( 'wpcom_vip_url_to_postid' ) ) ? wpcom_vip_url_to_postid( $home_url ) : url_to_postid( $home_url ); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.url_to_postid_url_to_postid } if ( empty( $shop_page_id ) ) { $shop_page_id = 'cart'; } $coupon_share_url = add_query_arg( array( 'coupon-code' => $coupon_code, 'sc-page' => $shop_page_id, ), home_url( '/' ) ); $actions['copy'] = '' . __( 'Copy', 'woocommerce-smart-coupons' ) . ''; $actions['share-link'] = '' . __( 'Get shareable link', 'woocommerce-smart-coupons' ) . ''; if ( function_exists( 'duplicate_post_plugin_activation' ) ) { return $actions; } else { $actions['duplicate'] = '' . __( 'Duplicate', 'woocommerce-smart-coupons' ) . ''; } return $actions; } /** * Function to insert post meta values for duplicate coupon * * @param int $id ID of parent coupon. * @param int $new_id ID of duplicated coupon. */ public function woocommerce_duplicate_coupon_post_meta( $id, $new_id ) { global $wpdb; $meta_keys = array( 'expiry_date', 'usage_count', '_used_by', 'date_expires' ); $how_many = count( $meta_keys ); $placeholders = array_fill( 0, $how_many, '%s' ); $post_meta_infos = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=%d AND meta_key NOT IN ( " . implode( ',', $placeholders ) . ' )', array_merge( array( $id ), $meta_keys ) ) ); // phpcs:ignore if ( 0 !== count( $post_meta_infos ) ) { $sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) "; foreach ( $post_meta_infos as $meta_info ) { $meta_key = $meta_info->meta_key; $meta_value = $meta_info->meta_value; $sql_query_sel[] = $wpdb->prepare( 'SELECT %d, %s, %s', $new_id, $meta_key, $meta_value ); } $sql_query .= implode( ' UNION ALL ', $sql_query_sel ); $wpdb->query( $sql_query ); // phpcs:ignore } } /** * Function to duplicate post taxonomies for the duplicate coupon * * @param int $id ID of parent coupon. * @param int $new_id ID of duplicated coupon. * @param string $post_type Post type being duplicated. */ public function woocommerce_duplicate_coupon_post_taxonomies( $id, $new_id, $post_type ) { $taxonomies = get_object_taxonomies( $post_type ); foreach ( $taxonomies as $taxonomy ) { $post_terms = wp_get_object_terms( $id, $taxonomy ); $post_terms_count = count( $post_terms ); for ( $i = 0; $i < $post_terms_count; $i++ ) { wp_set_object_terms( $new_id, $post_terms[ $i ]->slug, $taxonomy, true ); } } } /** * Function to create duplicate coupon and copy all properties of the coupon to duplicate coupon * * @param WP_Post $post Post object. * @param int $parent Post parent ID. * @param string $post_status Post status. * @return int $new_post_id */ public function woocommerce_create_duplicate_from_coupon( $post, $parent = 0, $post_status = '' ) { global $wpdb; $new_post_author = wp_get_current_user(); $new_post_date = current_time( 'mysql' ); $new_post_date_gmt = get_gmt_from_date( $new_post_date ); if ( $parent > 0 ) { $post_parent = $parent; $post_status = $post_status ? $post_status : 'publish'; $suffix = ''; } else { $post_parent = $post->post_parent; $post_status = $post_status ? $post_status : 'draft'; $suffix = __( '(Copy)', 'woocommerce-smart-coupons' ); } $new_post_type = $post->post_type; $post_content = str_replace( "'", "''", $post->post_content ); $post_content_filtered = str_replace( "'", "''", $post->post_content_filtered ); $post_excerpt = str_replace( "'", "''", $post->post_excerpt ); $post_title = strtolower( str_replace( "'", "''", $post->post_title ) . $suffix ); $post_name = str_replace( "'", "''", $post->post_name ); $comment_status = str_replace( "'", "''", $post->comment_status ); $ping_status = str_replace( "'", "''", $post->ping_status ); $wpdb->insert( $wpdb->posts, array( 'post_author' => $new_post_author->ID, 'post_date' => $new_post_date, 'post_date_gmt' => $new_post_date_gmt, 'post_content' => $post_content, 'post_content_filtered' => $post_content_filtered, 'post_title' => $post_title, 'post_excerpt' => $post_excerpt, 'post_status' => $post_status, 'post_type' => $new_post_type, 'comment_status' => $comment_status, 'ping_status' => $ping_status, 'post_password' => $post->post_password, 'to_ping' => $post->to_ping, 'pinged' => $post->pinged, 'post_modified' => $new_post_date, 'post_modified_gmt' => $new_post_date_gmt, 'post_parent' => 0, // No need to link it with any other coupon. 'menu_order' => $post->menu_order, 'post_mime_type' => $post->post_mime_type, ) ); // WPCS: db call ok. $new_post_id = $wpdb->insert_id; $this->woocommerce_duplicate_coupon_post_taxonomies( $post->ID, $new_post_id, $post->post_type ); $this->woocommerce_duplicate_coupon_post_meta( $post->ID, $new_post_id ); return $new_post_id; } /** * Function to return post id of the duplicate coupon to be created * * @param int $id ID of the coupon to duplicate. * @return object $post Duplicated post object. */ public function woocommerce_get_coupon_to_duplicate( $id ) { global $wpdb; $post = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID=%d", $id ) ); // WPCS: cache ok, db call ok. if ( isset( $post->post_type ) && 'revision' === $post->post_type ) { $id = $post->post_parent; $post = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID=%d", $id ) ); // WPCS: cache ok, db call ok. } return $post[0]; } /** * Function to validate condition and create duplicate coupon */ public function woocommerce_duplicate_coupon() { if ( empty( $_REQUEST['post'] ) || ( isset( $_REQUEST['action'] ) && 'duplicate_post_save_as_new_page' === $_REQUEST['action'] ) ) { // phpcs:ignore wp_die( esc_html__( 'No coupon to duplicate has been supplied!', 'woocommerce-smart-coupons' ) ); } // Get the original page. $id = absint( $_REQUEST['post'] ); // WPCS: input var ok. check_admin_referer( 'woocommerce-duplicate-coupon_' . $id ); $post = $this->woocommerce_get_coupon_to_duplicate( $id ); if ( isset( $post ) && null !== $post ) { $new_id = $this->woocommerce_create_duplicate_from_coupon( $post ); // If you have written a plugin which uses non-WP database tables to save // information about a page you can hook this action to dupe that data. do_action( 'woocommerce_duplicate_coupon', $new_id, $post ); // Redirect to the edit screen for the new draft page. wp_safe_redirect( admin_url( 'post.php?action=edit&post=' . $new_id ) ); exit; } else { /* translators: %d: Post ID */ wp_die( sprintf( esc_html__( 'Coupon creation failed, could not find original coupon: %d', 'woocommerce-smart-coupons' ), esc_html( $id ) ) ); } } /** * Function to call function to create duplicate coupon */ public function woocommerce_duplicate_coupon_action() { $coupon_id = ( ! empty( $_REQUEST['post'] ) ) ? absint( $_REQUEST['post'] ) : 0; check_admin_referer( 'woocommerce-duplicate-coupon_' . $coupon_id ); $action = ( ! empty( $_REQUEST['action'] ) ) ? wc_clean( wp_unslash( $_REQUEST['action'] ) ) : ''; // phpcs:ignore if ( 'duplicate_coupon' !== $action ) { return; } if ( $this->is_wc_gte_30() ) { $coupon = new WC_Coupon( $coupon_id ); if ( false === $coupon ) { /* translators: %s: coupon id */ wp_die( sprintf( esc_html__( 'Coupon creation failed, could not find original coupon: %s', 'woocommerce-smart-coupons' ), esc_html( $coupon_id ) ) ); } $duplicate = $this->coupon_duplicate( $coupon ); // Hook rename to match other woocommerce_coupon_* hooks, and to move away from depending on a response from the wp_posts table. do_action( 'wc_sc_duplicate_coupon', $duplicate, $coupon ); // Redirect to the edit screen for the new draft page. wp_safe_redirect( admin_url( 'post.php?action=edit&post=' . $duplicate->get_id() ) ); exit; } else { $this->woocommerce_duplicate_coupon(); } } /** * Duplicate coupon * * @param WC_Coupon $coupon The coupon object to duplicate. * @return WC_Coupon $duplicate The duplicated coupon. */ public function coupon_duplicate( $coupon = null ) { /** * Filter to allow us to exclude meta keys from coupon duplication.. * * @param array $exclude_meta The keys to exclude from the duplicate. * @param array $existing_meta_keys The meta keys that the coupon already has. * @since 7.2.0 */ $meta_to_exclude = array_filter( apply_filters( 'wc_sc_duplicate_coupon_exclude_meta', array(), array_map( function ( $meta ) { return $meta->key; }, $coupon->get_meta_data() ) ) ); $duplicate = clone $coupon; $duplicate->set_id( 0 ); /* translators: %s contains the code of the original coupon. */ $duplicate->set_code( sprintf( '%s-copy', $duplicate->get_code() ) ); $duplicate->set_date_created( null ); $duplicate->set_usage_count( 0 ); $duplicate->set_used_by( array() ); $duplicate->set_date_expires( null ); if ( $this->is_wc_greater_than( '6.1.2' ) && $this->is_callable( $duplicate, 'set_status' ) ) { $duplicate->set_status( 'draft' ); } foreach ( $meta_to_exclude as $meta_key ) { $duplicate->delete_meta_data( $meta_key ); } /** * This action can be used to modify the object further before it is created - it will be passed by reference. * * @since 3.0 */ do_action( 'wc_sc_coupon_duplicate_before_save', $duplicate, $coupon ); // Save parent coupon. $duplicate_id = $duplicate->save(); $duplicate = new WC_Coupon( $duplicate ); $this->woocommerce_duplicate_coupon_post_taxonomies( $coupon->get_id(), $duplicate_id, 'shop_coupon' ); if ( $this->is_wc_greater_than( '6.1.2' ) && $this->is_callable( $duplicate, 'get_status' ) ) { $coupon_status = $duplicate->get_status(); } else { $coupon_status = get_post_status( $duplicate_id ); } if ( ! empty( $duplicate_id ) && 'draft' !== $coupon_status ) { $args = array( 'ID' => $duplicate_id, 'post_status' => 'draft', ); wp_update_post( $args ); // Because $coupon->set_status( 'draft' ) not working. } return new WC_Coupon( $duplicate_id ); } /** * Function to copy and share coupon via jQuery. */ public function add_post_row_script() { $screen = get_current_screen(); if ( 'edit-shop_coupon' === $screen->id ) { ?>