delete_before = ! empty( $delete_timestamp ) ? intval( $delete_timestamp ) : time(); $paths_to_cleanup = apply_filters( 'wpo_wcpdf_cleanup_tmp_paths', array( $this->get_tmp_path( 'attachments' ), $this->get_tmp_path( 'dompdf' ), ) ); $excluded_files = apply_filters( 'wpo_wcpdf_cleanup_excluded_files', array( 'index.php', '.htaccess', 'log.htm', ) ); $folders_level = apply_filters( 'wpo_wcpdf_cleanup_folders_level', 3 ); $files = array(); $success = 0; $error = 0; $output = array(); foreach ( $paths_to_cleanup as $path ) { if ( ! function_exists( 'list_files' ) ) { include_once( ABSPATH.'wp-admin/includes/file.php' ); } if ( $listed_files = list_files( $path, $folders_level ) ) { $files = array_merge( $files, $listed_files ); } } if ( ! empty( $files ) ) { foreach ( $files as $file ) { $basename = wp_basename( $file ); if ( ! in_array( $basename, $excluded_files ) && file_exists( $file ) && ! is_dir( $file ) ) { $file_timestamp = filemtime( $file ); // delete file if ( $file_timestamp < $delete_before ) { if ( unlink( $file ) ) { $success++; } else { $error++; } } } } if ( $error > 0 ) { /* translators: 1,2. file count */ $message = sprintf( esc_html__( 'Unable to delete %1$d files! (deleted %2$d)', 'woocommerce-pdf-invoices-packing-slips' ), $error, $success ); $output['error'] = $message; } else { /* translators: file count */ $message = sprintf( esc_html__( 'Successfully deleted %d files!', 'woocommerce-pdf-invoices-packing-slips' ), $success ); $output['success'] = $message; } } else { $output['success'] = esc_html__( 'Nothing to delete!', 'woocommerce-pdf-invoices-packing-slips' ); } return $output; } /** * Remove all invoice data when requested */ public function remove_order_personal_data_meta( $meta_to_remove ) { $wcpdf_private_meta = array( '_wcpdf_invoice_number' => 'numeric_id', '_wcpdf_invoice_number_data' => 'array', '_wcpdf_invoice_date' => 'timestamp', '_wcpdf_invoice_date_formatted' => 'date', ); return $meta_to_remove + $wcpdf_private_meta; } /** * Remove references to order in number store tables when removing WC data */ public function remove_order_personal_data( $order ) { global $wpdb; // remove order ID from number stores $number_stores = apply_filters( "wpo_wcpdf_privacy_number_stores", array( 'invoice_number' ) ); foreach ( $number_stores as $store_name ) { $order_id = $order->get_id(); $table_name = apply_filters( "wpo_wcpdf_number_store_table_name", "{$wpdb->prefix}wcpdf_{$store_name}", $store_name, 'auto_increment' ); // i.e. wp_wcpdf_invoice_number $wpdb->query( $wpdb->prepare( "UPDATE $table_name SET order_id = 0 WHERE order_id = %s", $order_id ) ); } } /** * Export all invoice data when requested */ public function export_order_personal_data_meta( $meta_to_export ) { $private_address_meta = array( // _wcpdf_invoice_number_data & _wcpdf_invoice_date are duplicates of the below and therefor not included '_wcpdf_invoice_number' => esc_html__( 'Invoice Number', 'woocommerce-pdf-invoices-packing-slips' ), '_wcpdf_invoice_date_formatted' => esc_html__( 'Invoice Date', 'woocommerce-pdf-invoices-packing-slips' ), ); return $meta_to_export + $private_address_meta; } /** * Set the default PHPMailer validator to 'php' ( which uses filter_var($address, FILTER_VALIDATE_EMAIL) ) * This avoids issues with the presence of attachments affecting email address validation in some distros of PHP 7.3 * See: https://wordpress.org/support/topic/invalid-address-setfrom/#post-11583815 * Fixed in WP5.5 due to upgrade to newer PHPMailer */ public function set_phpmailer_validator( $mailArray ) { if ( version_compare( PHP_VERSION, '7.3', '>=' ) && version_compare( get_bloginfo( 'version' ), '5.5-dev', '<' ) ) { global $phpmailer; if ( ! ( $phpmailer instanceof \PHPMailer ) ) { require_once ABSPATH . WPINC . '/class-phpmailer.php'; require_once ABSPATH . WPINC . '/class-smtp.php'; $phpmailer = new \PHPMailer( true ); } $phpmailer::$validator = 'php'; } return $mailArray; } /** * Log document creation to order notes * * @param object $document * @param string $trigger * @return void */ public function log_document_creation_to_order_notes( $document, $trigger ) { $triggers = $this->get_document_triggers(); if ( ! empty( $document ) && isset( WPO_WCPDF()->settings->debug_settings['log_to_order_notes'] ) && ! empty( $trigger ) && array_key_exists( $trigger, $triggers ) ) { /* translators: 1. document title, 2. creation trigger */ $message = __( 'PDF %1$s created via %2$s.', 'woocommerce-pdf-invoices-packing-slips' ); $note = sprintf( $message, $document->get_title(), $triggers[$trigger] ); $this->log_to_order_notes( $note, $document ); } } /** * Log document printed to order notes * * @param object $document * @param string $trigger * @return void */ public function log_document_printed_to_order_notes( $document, $trigger ) { $triggers = array_merge( [ 'manually' => __( 'manually', 'woocommerce-pdf-invoices-packing-slips' ) ], $this->get_document_triggers() ); if ( ! empty( $document ) && isset( WPO_WCPDF()->settings->debug_settings['log_to_order_notes'] ) && ! empty( $trigger ) && array_key_exists( $trigger, $triggers ) ) { /* translators: 1. document title, 2. creation trigger */ $message = __( '%1$s document marked as printed via %2$s.', 'woocommerce-pdf-invoices-packing-slips' ); $note = sprintf( $message, $document->get_title(), $triggers[$trigger] ); $this->log_to_order_notes( $note, $document ); } } /** * Log document unmark printed to order notes * * @param object $document * @param string $trigger * @return void */ public function log_unmark_document_printed_to_order_notes( $document ) { if ( ! empty( $document ) && isset( WPO_WCPDF()->settings->debug_settings['log_to_order_notes'] ) ) { /* translators: 1. document title, 2. creation trigger */ $message = __( '%1$s document unmark printed.', 'woocommerce-pdf-invoices-packing-slips' ); $note = sprintf( $message, $document->get_title() ); $this->log_to_order_notes( $note, $document ); } } /** * Logs to the order notes * * @param string $note * @param object $document * @return void */ public function log_to_order_notes( $note, $document ) { if ( property_exists( $document, 'order_ids' ) && ! empty( $document->order_ids ) ) { // bulk document $order_ids = $document->order_ids; } else { $order_ids = [ $document->order->get_id() ]; } foreach ( $order_ids as $order_id ) { $order = wc_get_order( $order_id ); if ( empty( $order ) ) { continue; } if ( is_callable( array( $order, 'add_order_note' ) ) ) { // order $order->add_order_note( strip_tags( $note ) ); } elseif ( $document->is_refund( $order ) ) { // refund order $parent_order = $document->get_refund_parent( $order ); if ( ! empty( $parent_order ) && is_callable( array( $parent_order, 'add_order_note' ) ) ) { $parent_order->add_order_note( strip_tags( $note ) ); } } } } /** * Logs to the order meta * * @param object $document * @param string $trigger * @param boolean $force * @return void */ public function log_document_creation_trigger_to_order_meta( $document, $trigger, $force = false ) { if ( $trigger == 'bulk' && property_exists( $document, 'order_ids' ) && ! empty( $document->order_ids ) ) { // bulk document $order_ids = $document->order_ids; } elseif ( ! is_null( $document->order ) && is_callable( [ $document->order, 'get_id' ] ) ) { $order_ids = [ $document->order->get_id() ]; } elseif ( isset( $_REQUEST['order_id'] ) ) { $order_ids = [ absint( $_REQUEST['order_id'] ) ]; } else { $order_ids = []; } if ( ! empty( $order_ids ) ) { foreach ( $order_ids as $order_id ) { $order = wc_get_order( $order_id ); if ( ! empty( $order ) ) { if ( is_callable( [ $document, 'get_type' ] ) && $document->get_type() == 'credit-note' && is_callable( [ $order, 'get_parent_id' ] ) ) { $order = wc_get_order( $order->get_parent_id() ); } if ( empty( $order ) ) { continue; } $status = $order->get_meta( "_wcpdf_{$document->slug}_creation_trigger" ); if ( true == $force || empty( $status ) ) { $order->update_meta_data( "_wcpdf_{$document->slug}_creation_trigger", $trigger ); $order->save_meta_data(); } } } } } /** * Get the document triggers * * @return array */ public function get_document_triggers() { return apply_filters( 'wpo_wcpdf_document_triggers', [ 'single' => __( 'single order action', 'woocommerce-pdf-invoices-packing-slips' ), 'bulk' => __( 'bulk order action', 'woocommerce-pdf-invoices-packing-slips' ), 'my_account' => __( 'my account', 'woocommerce-pdf-invoices-packing-slips' ), 'email_attachment' => __( 'email attachment', 'woocommerce-pdf-invoices-packing-slips' ), 'document_data' => __( 'order document data (number and/or date set manually)', 'woocommerce-pdf-invoices-packing-slips' ), ] ); } /** * Mark document printed * * @return void */ public function mark_document_printed( $document, $trigger ) { $triggers = isset( $document->latest_settings['mark_printed'] ) && is_array( $document->latest_settings['mark_printed'] ) ? $document->latest_settings['mark_printed'] : []; if ( ! empty( $document ) && ! $this->is_document_printed( $document ) ) { if ( ! empty( $order = $document->order ) && ! empty( $trigger ) && in_array( $trigger, $triggers ) && apply_filters( 'wpo_wcpdf_allow_mark_document_printed', true, $document, $trigger ) ) { if ( 'shop_order' === $order->get_type() ) { $data = [ 'date' => time(), 'trigger' => $trigger, ]; $order->update_meta_data( "_wcpdf_{$document->slug}_printed", $data ); $order->save_meta_data(); $this->log_document_printed_to_order_notes( $document, $trigger ); } } } } /** * Unmark document printed * * @return void */ public function unmark_document_printed( $document ) { if ( ! empty( $document ) && $this->is_document_printed( $document ) ) { if ( ! empty( $order = $document->order ) && apply_filters( 'wpo_wcpdf_allow_unmark_document_printed', true, $document ) ) { $meta_key = "_wcpdf_{$document->slug}_printed"; if ( 'shop_order' === $order->get_type() && ! empty( $order->get_meta( $meta_key ) ) ) { $order->delete_meta_data( $meta_key ); $order->save_meta_data(); $this->log_unmark_document_printed_to_order_notes( $document ); } } } } /** * AJAX request for mark/unmark document printed * * @return void */ public function document_printed_ajax() { check_ajax_referer( 'printed_wpo_wcpdf', 'security' ); $data = stripslashes_deep( $_REQUEST ); $error = 0; if ( ! empty( $data['action'] ) && $data['action'] == "printed_wpo_wcpdf" && ! empty( $data['event'] ) && ! empty( $data['document_type'] ) && ! empty( $data['order_id'] ) && ! empty( $data['trigger'] ) ) { $document = wcpdf_get_document( esc_attr( $data['document_type'] ), esc_attr( $data['order_id'] ) ); $full_permission = WPO_WCPDF()->admin->user_can_manage_document( esc_attr( $data['document_type'] ) ); if ( ! empty( $document ) && ! empty( $order = $document->order ) && $full_permission ) { switch ( esc_attr( $data['event'] ) ) { case 'mark': $this->mark_document_printed( $document, esc_attr( $data['trigger'] ) ); break; case 'unmark': $this->unmark_document_printed( $document ); break; } if ( is_callable( [ $order, 'get_edit_order_url' ] ) ) { wp_redirect( $order->get_edit_order_url() ); } else { wp_redirect( admin_url( 'post.php?action=edit&post=' . esc_attr( $data['order_id'] ) ) ); } } else { $error++; } } else { $error++; } if ( $error > 0 ) { /* translators: 1. document type, 2. mark/unmark */ wp_die( sprintf( esc_html__( 'Document of type %1$s for the selected order could not be %2$s as printed.', 'woocommerce-pdf-invoices-packing-slips' ), esc_attr( $data['document_type'] ), $event_type ) ); } } /** * Check if a document is printed * * @return bool */ public function is_document_printed( $document ) { $is_printed = false; if ( ! empty( $document ) && ! empty( $order = $document->order ) ) { if ( 'shop_order' === $order->get_type() && ! empty( $printed_data = $order->get_meta( "_wcpdf_{$document->slug}_printed" ) ) ) { $is_printed = true; } } return $is_printed; } /** * Check if a document can be manually marked as printed * * @return bool */ public function document_can_be_manually_marked_printed( $document ) { $can_be_manually_marked_printed = false; if ( empty( $document ) || ( property_exists( $document, 'is_bulk' ) && $document->is_bulk ) ) { return $can_be_manually_marked_printed; } $document->save_settings(); $can_be_manually_marked_printed = false; $document_exists = is_callable( array( $document, 'exists' ) ) ? $document->exists() : false; $document_printed = $document_exists && is_callable( array( $document, 'printed' ) ) ? $document->printed() : false; $triggers = isset( $document->latest_settings['mark_printed'] ) && is_array( $document->latest_settings['mark_printed'] ) ? $document->latest_settings['mark_printed'] : []; $manually_print_enabled = in_array( 'manually', $triggers ) ? true : false; if ( $document_exists && ! $document_printed && $manually_print_enabled ) { $can_be_manually_marked_printed = true; } return apply_filters( 'wpo_wcpdf_document_can_be_manually_marked_printed', $can_be_manually_marked_printed, $document ); } /** * Get document printed data * * @return array */ public function get_document_printed_data( $document ) { $data = []; if ( ! empty( $document ) && $this->is_document_printed( $document ) && ! empty( $order = $document->order ) ) { if ( 'shop_order' === $order->get_type() && ! empty( $printed_data = $order->get_meta( "_wcpdf_{$document->slug}_printed" ) ) ) { $data = $printed_data; } } return apply_filters( 'wpo_wcpdf_document_printed_data', $data, $document ); } /** * Enable PHP error output */ public function enable_debug () { error_reporting( E_ALL ); ini_set( 'display_errors', 1 ); } public function wc_webhook_topic_hooks( $topic_hooks, $wc_webhook ) { $documents = WPO_WCPDF()->documents->get_documents(); foreach ($documents as $document) { $topic_hooks["order.{$document->type}-saved"] = array( "wpo_wcpdf_webhook_order_{$document->slug}_saved", ); } return $topic_hooks; } public function wc_webhook_topic_events( $topic_events ) { $documents = WPO_WCPDF()->documents->get_documents(); foreach ($documents as $document) { $topic_events[] = "{$document->type}-saved"; } return $topic_events; } public function wc_webhook_topics( $topics ) { $documents = WPO_WCPDF()->documents->get_documents(); foreach ($documents as $document) { /* translators: document title */ $topics["order.{$document->type}-saved"] = esc_html( sprintf( __( 'Order %s Saved', 'woocommerce-pdf-invoices-packing-slips' ), $document->get_title() ) ); } return $topics; } public function wc_webhook_trigger( $document, $order ) { do_action( "wpo_wcpdf_webhook_order_{$document->slug}_saved", $order->get_id() ); } } endif; // class_exists