Файловый менеджер - Редактировать - /home/tuudkjt/globeasy/wp-includes/ID3/Queue.tar
Назад
Queue.php 0000777 00000043770 15251772651 0006376 0 ustar 00 <?php namespace EasyWPSMTP\Queue; use DateTime; use DateTimeZone; use EasyWPSMTP\Admin\DebugEvents\DebugEvents; use EasyWPSMTP\Tasks\Queue\SendEnqueuedEmailTask; use EasyWPSMTP\WP; use EasyWPSMTP\WPMailArgs; use Exception; /** * Class Queue. * * @since 2.6.0 */ class Queue { /** * The email being currently handled. * * @since 2.6.0 * * @var Email */ private $email; /** * A list of registered hooks at the time * of email sending. * * @since 2.6.0 * * @var array */ private $registered_wp_mail_hooks = []; /** * Whether the queue is currently enabled. * * @since 2.6.0 * * @return bool */ public function is_enabled() { /** * Filters whether the queue is currently enabled. * * @since 2.6.0 * * @param bool $enabled Whether the queue is currently enabled. */ return apply_filters( 'easy_wp_smtp_queue_is_enabled', false ); } /** * Short-circuit and handle an ongoing PHPMailer `send` call. * * @since 2.6.0 * * @return bool */ public function enqueue_email() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks if ( ! $this->is_valid_db() ) { return false; } global $phpmailer; $wp_mail_args = easy_wp_smtp()->get_processor()->get_filtered_wp_mail_args(); $initiator = easy_wp_smtp()->get_wp_mail_initiator(); $processor = easy_wp_smtp()->get_processor(); $initiator_state = [ 'file' => $initiator->get_file(), 'line' => $initiator->get_line(), 'backtrace' => $initiator->get_backtrace(), ]; $connection_data = [ 'from_email' => $processor->get_filtered_from_email(), 'from_name' => $processor->get_filtered_from_name(), ]; // Keep a reference to the original attachments, // if something goes wrong while enqueueing the email. $original_attachments = $phpmailer->getAttachments(); // Obfuscate attachment paths for the enqueued email. $processed_attachments = ( new Attachments() )->process_attachments( $original_attachments ); // Set obfuscated path attachments. $this->set_attachments( $processed_attachments ); // Add queued date header in the same format as "Date" header. $phpmailer->addCustomHeader( 'X-EasyWPSMTP-Queued', $phpmailer::rfcDate() ); $email = ( new Email() ) ->set_wp_mail_args( $wp_mail_args ) ->set_initiator_state( $initiator_state ) ->set_connection_data( $connection_data ) ->set_mailer_state( $phpmailer->get_state() ); // Add the email to the queue. try { $this->add_email( $email ); } catch ( Exception $e ) { // Cleanup any obfuscated path attachments. $this->cleanup_attachments(); // Reset original attachments. $this->set_attachments( $original_attachments ); $message = sprintf( /* translators: %1$s - exception message. */ esc_html__( '[Emails Queue] Skipped enqueueing email. %1$s.', 'easy-wp-smtp' ), esc_html( $e->getMessage() ) ); DebugEvents::add_debug( $message ); return false; } return true; } /** * Send an email. Can only be called * by a running SendEnqueuedEmailTask. * * @since 2.6.0 * * @param int|string $email_id Email's ID. */ public function send_email( $email_id ) { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks // This method can't be called directly. if ( ! doing_action( SendEnqueuedEmailTask::ACTION ) ) { $message = sprintf( /* translators: %1$d - email ID. */ esc_html__( '[Emails Queue] Skipped email sending from the queue. Queue::send_email method was called directly. Email ID: %1$d.', 'easy-wp-smtp' ), $email_id ); DebugEvents::add_debug( $message ); return; } try { $email = $this->get_email( $email_id ); } catch ( Exception $e ) { $this->delete_email( $email_id ); $message = sprintf( /* translators: %1$s - exception message; %2$s - email ID. */ esc_html__( '[Emails Queue] Skipped email sending from the queue. %1$s. Email ID: %2$s', 'easy-wp-smtp' ), esc_html( $e->getMessage() ), $email_id ); DebugEvents::add_debug( $message ); return; } // Bail early if the email still enqueued, or already processed. if ( $email->get_status() !== Email::STATUS_PROCESSING ) { $message = sprintf( /* translators: %1$d - email ID; %2$s - email status. */ esc_html__( '[Emails Queue] Skipped email sending from the queue. Wrong email status. Email ID: %1$d, email status: %2$s.', 'easy-wp-smtp' ), $email_id, $email->get_status() ); DebugEvents::add_debug( $message ); return; } // Keep a reference to the email // being sent so that it's accessible // across hooks. $this->email = $email; // Un-hook all user-defined hooks. $this->clear_wp_mail_hooks(); // Stop enqueueing emails. add_filter( 'easy_wp_smtp_mail_catcher_send_enqueue_email', '__return_false', PHP_INT_MAX ); // Re-hook Processor functionality, before applying PHPMailer state, // so that From and From Name are correctly filtered. easy_wp_smtp()->get_processor()->hooks(); // Apply the email's PHPMailer state. add_action( 'phpmailer_init', [ $this, 'apply_mailer_state' ], PHP_INT_MAX ); // Retrieve original wp_mail arguments. $wp_mail_args = new WPMailArgs( $email->get_wp_mail_args() ); // Inject user-filtered From and From Name. $wp_mail_headers = $wp_mail_args->get_headers(); $wp_mail_headers[] = $this->get_connection_from_header( $email->get_connection_data() ); // Inject the original initiator state. add_filter( 'easy_wp_smtp_wp_mail_initiator_set_initiator', [ $this, 'apply_initiator_state' ] ); // Send the email. wp_mail( $wp_mail_args->get_to_email(), $wp_mail_args->get_subject(), $wp_mail_args->get_message(), $wp_mail_headers, $wp_mail_args->get_attachments() ); // Update the email. try { $this->email->set_status( Email::STATUS_PROCESSED ) ->set_date_processed( new DateTime( 'now', new DateTimeZone( 'UTC' ) ) ) ->anonymize() ->save(); } catch ( Exception $e ) { $this->delete_email( $email_id ); $message = sprintf( /* translators: %1$s - exception message; %2$d - email ID. */ esc_html__( '[Emails Queue] Failed to update queue record after sending email from the queue. %1$s. Email ID: %2$d', 'easy-wp-smtp' ), esc_html( $e->getMessage() ), $email_id ); DebugEvents::add_debug( $message ); } // Cleanup any attachments. $this->cleanup_attachments(); // Stop injecting the original initiator state. remove_filter( 'easy_wp_smtp_wp_mail_initiator_set_initiator', [ $this, 'apply_initiator_state' ] ); // Stop applying PHPMailer state. remove_action( 'phpmailer_init', [ $this, 'apply_mailer_state' ], PHP_INT_MAX ); // Clear the email reference. $this->email = null; // Re-hook all user-defined hooks. $this->restore_wp_mail_hooks(); // Start enqueueing emails again. remove_filter( 'easy_wp_smtp_mail_catcher_send_enqueue_email', '__return_false', PHP_INT_MAX ); } /** * Return the current email's WPMailInitiator state. * * @since 2.6.0 * * @return array WPMailInitiator state. */ public function apply_initiator_state() { return $this->email->get_initiator_state(); } /** * Apply state to the current mailer. * * @since 2.6.0 * * @param PHPMailer $phpmailer PHPMailer instance. */ public function apply_mailer_state( &$phpmailer ) { $phpmailer->set_state( $this->email->get_mailer_state() ); } /** * Get the table name. * * @since 2.6.0 * * @return string Table name, prefixed. */ public static function get_table_name() { global $wpdb; return $wpdb->prefix . 'easywpsmtp_emails_queue'; } /** * Count processing or processed emails since a given date. * * @since 2.6.0 * * @param null|DateTime $since_datetime Date to count from, or null for all emails. * * @return int Email count. */ public function count_processed_emails( ?DateTime $since_datetime = null ) { if ( ! $this->is_valid_db() ) { return 0; } global $wpdb; $table = self::get_table_name(); $where = $wpdb->prepare( 'status IN (%d, %d)', Email::STATUS_PROCESSING, Email::STATUS_PROCESSED ); if ( ! is_null( $since_datetime ) ) { $where .= $wpdb->prepare( ' AND date_processed >= %s', $since_datetime->format( WP::datetime_mysql_format() ) ); } // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $count = $wpdb->get_var( "SELECT COUNT(*) FROM $table WHERE $where;" ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared return (int) $count; } /** * Count queued emails. * * @since 2.6.0 * * @return int Email count. */ public function count_queued_emails() { if ( ! $this->is_valid_db() ) { return 0; } global $wpdb; $table = self::get_table_name(); $where = $wpdb->prepare( 'status = %d', Email::STATUS_QUEUED ); // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $count = $wpdb->get_var( "SELECT COUNT(*) FROM $table WHERE $where;" ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared return (int) $count; } /** * Schedule emails for sending. * * @since 2.6.0 */ public function process() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks if ( ! $this->is_valid_db() ) { return; } /** * Filters the amount of emails the queue should process. * * @since 2.6.0 * * @param int|null $count Amount of emails to process. */ $count = apply_filters( 'easy_wp_smtp_queue_process_count', null ); // If the queue has been disabled, just process all emails. if ( ! $this->is_enabled() ) { $count = null; } $emails = $this->get_emails( $count ); $task = new SendEnqueuedEmailTask(); foreach ( $emails as $email ) { try { $email->set_status( Email::STATUS_PROCESSING ) ->set_date_processed( new DateTime( 'now', new DateTimeZone( 'UTC' ) ) ) ->save(); } catch ( Exception $e ) { $this->delete_email( $email->get_id() ); $message = sprintf( /* translators: %1$s - exception message. */ esc_html__( '[Emails Queue] Skipped processing enqueued email. %1$s. Email ID: %2$d', 'easy-wp-smtp' ), esc_html( $e->getMessage() ), $email->get_id() ); DebugEvents::add_debug( $message ); continue; } $task->schedule( $email->get_id() ); } } /** * Cleanup emails processed before a given date. * * @since 2.6.0 */ public function cleanup() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks /** * Filters the date before which emails should * be removed from the queue. * * @since 2.6.0 * * @param DateTime|null $datetime Date before which to remove emails. */ $datetime = apply_filters( 'easy_wp_smtp_queue_cleanup_before_datetime', null ); // If the queue has been disabled, just cleanup all emails. if ( ! $this->is_enabled() ) { $datetime = null; } $this->delete_emails_before( $datetime ); } /** * Whether the DB table exists. * * @since 2.6.0 * * @return bool */ public function is_valid_db() { global $wpdb; static $is_valid = null; // Return cached value only if table already exists. if ( $is_valid === true ) { return true; } $table = self::get_table_name(); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching $is_valid = (bool) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s;', $table ) ); return $is_valid; } /** * Set current email's attachments. * * @since 2.6.0 * * @param array $attachments List of attachments. */ private function set_attachments( $attachments ) { global $phpmailer; $phpmailer->clearAttachments(); foreach ( $attachments as $attachment ) { [ $path, , $name, $encoding, $type, , $disposition ] = $attachment; try { $phpmailer->addAttachment( $path, $name, $encoding, $type, $disposition ); } catch ( Exception $e ) { continue; } } } /** * Remove email attachments after sending. * * @since 2.6.0 */ private function cleanup_attachments() { global $phpmailer; $attachments = $phpmailer->getAttachments(); ( new Attachments() )->delete_attachments( $attachments ); } /** * Get the From/From Name header * from an email's connection data. * * @since 2.6.0 * * @param array $connection_data Email's connection data. */ private function get_connection_from_header( $connection_data ) { [ 'from_email' => $from_email, 'from_name' => $from_name, ] = $connection_data; $from = ( $from_name === '' ? $from_email : sprintf( '%1s <%2s>', $from_name, $from_email ) ); $from_header = sprintf( 'From:%s', $from ); return $from_header; } /** * Return a list of the `wp_mail` related hooks * that should be de-registered before sending * an enqueued email. * * @since 2.6.0 * * @return array List of hooks. */ private function get_wp_mail_hooks() { return [ 'wp_mail', 'pre_wp_mail', 'wp_mail_from', 'wp_mail_from_name', 'wp_mail_succeeded', 'wp_mail_failed', ]; } /** * Clear any user-defined `wp_mail` related hooks * before sending an enqueued email. * * @since 2.6.0 */ private function clear_wp_mail_hooks() { global $wp_filter; $wp_mail_hooks = array_intersect_key( $wp_filter, array_flip( $this->get_wp_mail_hooks() ) ); foreach ( $wp_mail_hooks as $hook_name => $hook ) { foreach ( $hook->callbacks as $priority => $callbacks ) { foreach ( $callbacks as $callback ) { $this->registered_wp_mail_hooks[] = [ $hook_name, $callback['function'], $priority, $callback['accepted_args'], ]; } } remove_all_filters( $hook_name ); } } /** * Re-register any previous de-registered `wp_mail` related hooks * after sending an enqueued email. * * @since 2.6.0 */ private function restore_wp_mail_hooks() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks foreach ( $this->registered_wp_mail_hooks as $hook ) { [ $hook_name, $callback, $priority, $accepted_args ] = $hook; add_filter( $hook_name, $callback, $priority, $accepted_args ); } } /** * Add an email to the queue. * * @since 2.6.0 * * @param Email $email The email to enqueue. * * @throws Exception When email couldn't be saved. */ private function add_email( Email $email ) { if ( ! $this->is_valid_db() ) { return; } $email->set_date_enqueued( new DateTime( 'now', new DateTimeZone( 'UTC' ) ) ) ->set_status( Email::STATUS_QUEUED ) ->save(); } /** * Get an email. * * @since 2.6.0 * * @param int|string $email_id The email's ID. * * @return null|Email The email, or null if not found. */ private function get_email( $email_id ) { if ( ! $this->is_valid_db() ) { return null; } global $wpdb; $table = self::get_table_name(); $where = $wpdb->prepare( 'ID = %d', (int) $email_id ); // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $data = $wpdb->get_row( "SELECT * FROM $table WHERE $where" ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $email = Email::from_data( $data ); return $email; } /** * Get queued emails from the queue. * * @since 2.6.0 * * @param null|int $count Amount of emails to return, or null for all emails. * * @return Email[] Array of emails. */ private function get_emails( $count = null ) { if ( ! $this->is_valid_db() ) { return []; } global $wpdb; $table = self::get_table_name(); $where = $wpdb->prepare( 'status = %d', Email::STATUS_QUEUED ); $limit = ''; if ( ! is_null( $count ) ) { $limit = $wpdb->prepare( 'LIMIT 0, %d', max( 0, intval( $count ) ) ); } // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $data = $wpdb->get_results( "SELECT * FROM $table WHERE $where ORDER BY date_enqueued ASC $limit;" ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $emails = []; foreach ( $data as $row ) { try { $emails[] = Email::from_data( $row ); } catch ( Exception $e ) { $this->delete_email( $row->id ); $message = sprintf( /* translators: %1$s - exception message. */ esc_html__( '[Emails Queue] Skipped processing enqueued email. %1$s. Email ID: %2$d', 'easy-wp-smtp' ), esc_html( $e->getMessage() ), $row->id ); DebugEvents::add_debug( $message ); } } return $emails; } /** * Delete emails processed before a given date. * * @since 2.6.0 * * @param DateTime|null $before_datetime Date before which to remove emails, or null for all emails. */ private function delete_emails_before( $before_datetime ) { if ( ! $this->is_valid_db() ) { return; } global $wpdb; $table = self::get_table_name(); $where = $wpdb->prepare( 'status = %d', Email::STATUS_PROCESSED ); if ( is_a( $before_datetime, DateTime::class ) ) { $where .= $wpdb->prepare( ' AND date_processed < %s', $before_datetime->format( WP::datetime_mysql_format() ) ); } // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $wpdb->query( "DELETE FROM $table WHERE $where" ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared } /** * Delete an email. * * @since 2.6.0 * * @param int $email_id ID of the email. */ private function delete_email( $email_id ) { if ( ! $this->is_valid_db() ) { return; } global $wpdb; $table = self::get_table_name(); // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared $wpdb->query( $wpdb->prepare( "DELETE FROM $table WHERE ID = %d", $email_id ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared } } Migration.php 0000777 00000003474 15251772651 0007240 0 ustar 00 <?php namespace EasyWPSMTP\Queue; use EasyWPSMTP\Migrations\MigrationAbstract; /** * Class Migration. * * @since 2.6.0 */ class Migration extends MigrationAbstract { /** * Version of the database table(s) for queue functionality. * * @since 2.6.0 */ const DB_VERSION = 1; /** * Option key where we save the current DB version for queue functionality. * * @since 2.6.0 */ const OPTION_NAME = 'easy_wp_smtp_queue_db_version'; /** * Option key where we save any errors while creating the queue DB table. * * @since 2.6.0 */ const ERROR_OPTION_NAME = 'easy_wp_smtp_queue_db_error'; /** * Whether the queue is enabled. * * @since 2.6.0 * * @return bool */ public static function is_enabled() { return easy_wp_smtp()->get_queue()->is_enabled(); } /** * Initial migration - create the table structure. * * @since 2.6.0 */ protected function migrate_to_1() { global $wpdb; $table = Queue::get_table_name(); $collate = ! empty( $wpdb->collate ) ? "COLLATE='{$wpdb->collate}'" : ''; /* * Create the table. */ $sql = " CREATE TABLE `$table` ( `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `data` LONGTEXT NULL, `status` TINYINT UNSIGNED NOT NULL DEFAULT '0', `date_enqueued` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `date_processed` TIMESTAMP NULL, PRIMARY KEY (id), INDEX status (status), INDEX date_processed (date_processed) ) ENGINE='InnoDB' {$collate};"; $result = $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching if ( ! empty( $wpdb->last_error ) ) { update_option( self::ERROR_OPTION_NAME, $wpdb->last_error, false ); } // Save the current version to DB. if ( $result !== false ) { $this->update_db_ver( 1 ); } } } Email.php 0000777 00000025246 15251772651 0006337 0 ustar 00 <?php namespace EasyWPSMTP\Queue; use DateTime; use DateTimeZone; use EasyWPSMTP\WP; use Exception; /** * Class Email. * * @since 2.6.0 */ class Email { /** * This email is enqueued. * * @since 2.6.0 */ const STATUS_QUEUED = 0; /** * This email is being processed. * * @since 2.6.0 */ const STATUS_PROCESSING = 1; /** * This email has been processed. * * @since 2.6.0 */ const STATUS_PROCESSED = 2; /** * ID of the email. * * @since 2.6.0 * * @var int */ private $id = 0; /** * Serialized WPMailInitiator state of this email. * * @since 2.6.0 * * @var array */ private $initiator_state = []; /** * Serialized arguments of this email's original wp_mail call. * * @since 2.6.0 * * @var array */ private $wp_mail_args = []; /** * Serialized connection data of this email. * * @since 2.6.0 * * @var array */ private $connection_data = []; /** * Serialized MailCatcher state of this email. * * @since 2.6.0 * * @var array */ private $mailer_state = []; /** * Status of this email. * * @since 2.6.0 * * @var int */ private $status = 0; /** * Date and time this email was enqueued at. * * @since 2.6.0 * * @var DateTime */ private $date_enqueued; /** * Date and time this email was processed at. * * @since 2.6.0 * * @var DateTime */ private $date_processed; /** * Email constructor. * * @since 2.6.0 */ public function __construct() { $this->date_enqueued = new DateTime( 'now', new DateTimeZone( 'UTC' ) ); } /** * Get a list of allowed statuses. * * @since 2.6.0 * * @return array */ public static function get_statuses() { return [ self::STATUS_QUEUED, self::STATUS_PROCESSING, self::STATUS_PROCESSED, ]; } /** * Construct an email from an array of data. * * @since 2.6.0 * * @param object $data Database row object. * * @return Email * @throws Exception If supplied data is missing or malformed. */ public static function from_data( $data ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh if ( is_null( $data ) ) { throw new Exception( esc_html__( 'Record not found in DB', 'easy-wp-smtp' ) ); } if ( ! is_object( $data ) || ! property_exists( $data, 'data' ) || ! isset( $data->id, $data->status, $data->date_enqueued ) ) { throw new Exception( esc_html__( 'Invalid record format', 'easy-wp-smtp' ) ); } // Data can be null if email has been anonymized. // Only check for valid JSON if data isn't null. if ( ! is_null( $data->data ) && ! WP::is_json( $data->data ) ) { throw new Exception( sprintf( /* translators: %1$s - JSON error message. */ esc_html__( 'Data JSON decoding error: %1$s', 'easy-wp-smtp' ), esc_html( json_last_error_msg() ) ) ); } $email = new Email(); $email_data = is_null( $data->data ) ? [] : json_decode( $data->data, true ); $email_data = wp_parse_args( $email_data, [ 'initiator_state' => [], 'wp_mail_args' => [], 'connection_data' => [], 'mailer_state' => [], ] ); $email->id = (int) $data->id; $email->initiator_state = $email_data['initiator_state']; $email->wp_mail_args = $email_data['wp_mail_args']; $email->connection_data = $email_data['connection_data']; $email->mailer_state = $email_data['mailer_state']; $email->status = (int) $data->status; $email->date_enqueued = $email->get_datetime( $data->date_enqueued ); if ( isset( $data->date_processed ) ) { $email->date_processed = $email->get_datetime( $data->date_processed ); } return $email; } /** * Get this email's ID. * * @since 2.6.0 * * @return int */ public function get_id() { return (int) $this->id; } /** * Get this email's status. * * @since 2.6.0 * * @return int */ public function get_status() { return $this->status; } /** * Set this email's status. * * @since 2.6.0 * * @param int $status Email status. * * @return Email */ public function set_status( $status ) { $status = (int) $status; if ( ! in_array( $status, self::get_statuses(), true ) ) { $status = self::STATUS_QUEUED; } $this->status = $status; return $this; } /** * Get this email's `wp_mail` call arguments. * * @since 2.6.0 * * @return array */ public function get_wp_mail_args() { return $this->wp_mail_args; } /** * Set this email's `wp_mail` call arguments. * * @since 2.6.0 * * @param array $args Array of arguments. * * @return Email */ public function set_wp_mail_args( $args ) { $args = wp_parse_args( $args, [ 'headers' => '', 'attachments' => [], ] ); $this->wp_mail_args = $args; return $this; } /** * Get this email's MailCatcher state. * * @since 2.6.0 * * @return array */ public function get_connection_data() { return $this->connection_data; } /** * Set this email's connection data. * * @since 2.6.0 * * @param array $data Connection data. * * @return Email */ public function set_connection_data( $data ) { $this->connection_data = wp_parse_args( $data, [ 'from_email' => '', 'from_name' => '', ] ); return $this; } /** * Get this email's MailCatcher state. * * @since 2.6.0 * * @return array */ public function get_mailer_state() { return $this->mailer_state; } /** * Set this email's MailCatcher state. * * @since 2.6.0 * * @param array $state MailCatcher state. * * @return Email */ public function set_mailer_state( $state ) { $this->mailer_state = wp_parse_args( $state, [ 'CharSet' => '', 'ContentType' => '', 'Encoding' => '', 'CustomHeader' => '', 'Subject' => '', 'Body' => '', 'AltBody' => '', 'ReplyTo' => '', 'to' => '', 'cc' => '', 'bcc' => '', 'attachment' => '', ] ); return $this; } /** * Get this email's WPMailInitiator state. * * @since 2.6.0 * * @return array */ public function get_initiator_state() { return $this->initiator_state; } /** * Set this email's WPMailInitiator state. * * @since 2.6.0 * * @param array $state MailCatcher state. * * @return Email */ public function set_initiator_state( $state ) { $this->initiator_state = wp_parse_args( $state, [ 'file' => '', 'line' => '', 'backtrace' => '', ] ); return $this; } /** * Get the date and time this email * was enqueued at. * * @since 2.6.0 * * @return DateTime */ public function get_date_enqueued() { return $this->date_enqueued; } /** * Set the date and time this email * was enqueued at. * * @since 2.6.0 * * @param DateTime $datetime Date and time of enqueueing. * * @return Email */ public function set_date_enqueued( $datetime ) { $this->date_enqueued = $this->get_datetime( $datetime ); return $this; } /** * Get the date and time this email * was processed at. * * @since 2.6.0 * * @return DateTime */ public function get_date_processed() { return $this->date_processed; } /** * Set the date and time this email * was processed at. * * @since 2.6.0 * * @param DateTime $datetime Date and time of processing. * * @return Email */ public function set_date_processed( $datetime ) { $this->date_processed = $this->get_datetime( $datetime ); return $this; } /** * Convert a database string to a DateTime * object, if necessary. * * @since 2.6.0 * * @param string $datetime Date and time. * * @return DateTime */ private function get_datetime( $datetime ) { if ( ! is_a( $datetime, DateTime::class ) ) { // Validate the date. Time is ignored. $mm = substr( $datetime, 5, 2 ); $jj = substr( $datetime, 8, 2 ); $aa = substr( $datetime, 0, 4 ); $valid_date = wp_checkdate( $mm, $jj, $aa, $datetime ); $timezone = new DateTimeZone( 'UTC' ); if ( $valid_date ) { $datetime = DateTime::createFromFormat( WP::datetime_mysql_format(), $datetime, $timezone ); } else { $datetime = new DateTime( 'now', $timezone ); } } return $datetime; } /** * Erase any potentially sensitive data. * * @since 2.6.0 * * @return Email */ public function anonymize() { $this->initiator_state = null; $this->wp_mail_args = null; $this->connection_data = null; $this->mailer_state = null; return $this; } /** * Save a new or modified email in DB. * * @since 2.6.0 * * @return int New or updated email ID. * @throws Exception If data can't be encoded, * or a database error occurred. */ public function save() { global $wpdb; $table = Queue::get_table_name(); $data = [ 'initiator_state' => $this->initiator_state, 'wp_mail_args' => $this->wp_mail_args, 'connection_data' => $this->connection_data, 'mailer_state' => $this->mailer_state, ]; $data = array_filter( $data ); if ( ! empty( $data ) ) { $data = wp_json_encode( [ 'initiator_state' => $this->initiator_state, 'wp_mail_args' => $this->wp_mail_args, 'connection_data' => $this->connection_data, 'mailer_state' => $this->mailer_state, ] ); if ( $data === false ) { throw new Exception( sprintf( /* translators: %1$s - JSON error message. */ esc_html__( 'Data JSON encoding error: %1$s', 'easy-wp-smtp' ), esc_html( json_last_error_msg() ) ) ); } } else { $data = null; } if ( (bool) $this->get_id() ) { // Update the existing DB table record. $result = $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching $table, [ 'data' => $data, 'status' => $this->status, 'date_processed' => $this->get_date_processed()->format( WP::datetime_mysql_format() ), ], [ 'id' => $this->get_id(), ], [ '%s', // data. '%s', // status. '%s', // date_processed. ], [ '%d', ] ); $email_id = $this->get_id(); } else { // Create a new DB table record. $result = $wpdb->insert( $table, [ 'data' => $data, 'status' => $this->status, 'date_enqueued' => $this->get_date_enqueued()->format( WP::datetime_mysql_format() ), ], [ '%s', // data. '%s', // status. '%s', // date_enqueued. ] ); $email_id = $wpdb->insert_id; } if ( $result === false ) { throw new Exception( sprintf( /* translators: %1$s - Database error message. */ esc_html__( 'Insert/update SQL query error: %1$s', 'easy-wp-smtp' ), esc_html( $wpdb->last_error ) ) ); } return (int) $email_id; } } Attachments.php 0000777 00000014051 15251772651 0007553 0 ustar 00 <?php namespace EasyWPSMTP\Queue; use EasyWPSMTP\Uploads; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; /** * Class Attachments. * * @since 2.6.0 */ class Attachments { /** * Process a list of file attachments. * * @since 2.6.0 * * @param array $attachments List of attachments. * * @return array List of attachments. */ public function process_attachments( $attachments ) { $attachments = array_map( function ( $attachment ) { [ $path, , $name, , , $is_string_attachment ] = $attachment; $path = $this->process_attachment( $path, $name, $is_string_attachment ); if ( ! empty( $path ) ) { $attachment[0] = $path; } return $attachment; }, $attachments ); return $attachments; } /** * Process an attachment,obfuscating its path * and storing its file on disk. * * @since 2.6.0 * * @param string $path The path to obfuscate. * @param string $name The name of the file at $path. * @param bool $is_string_attachment Whether this attachment is a string attachment. * * @return string|false New path of the attachment, or false for no path. */ private function process_attachment( $path, $name = '', $is_string_attachment = false ) { $file_content = $this->get_attachment_file_content( $path, $is_string_attachment ); if ( $file_content === false ) { return false; } if ( ! $is_string_attachment && $name === '' ) { $name = wp_basename( $path ); } $name = sanitize_file_name( $name ); $obfuscated_path = $this->store_file( $file_content, $name ); if ( empty( $obfuscated_path ) ) { return $path; } return $obfuscated_path; } /** * Return the contents of a given file. * * @since 2.6.0 * * @param string $path The file's path. * @param bool $is_string_attachment Whether this file is a string attachment. * * @return string File contents. */ private function get_attachment_file_content( $path, $is_string_attachment ) { if ( ! $is_string_attachment ) { if ( ! file_exists( $path ) ) { return false; } return file_get_contents( $path ); } return $path; } /** * Store a file. * * @since 2.6.0 * * @param string $file_content The file's contents. * @param string $original_filename The original file's name. * * @return string The file's path. */ private function store_file( $file_content, $original_filename ) { $uploads_directory = $this->get_uploads_directory(); if ( is_wp_error( $uploads_directory ) ) { return false; } if ( ! is_dir( $uploads_directory ) ) { wp_mkdir_p( $uploads_directory ); // Check if the .htaccess exists in the root upload directory, if not - create it. Uploads::create_upload_dir_htaccess_file(); // Check if the index.html exists in the directories, if not - create them. Uploads::create_index_html_file( Uploads::upload_dir()['path'] ); Uploads::create_index_html_file( $uploads_directory ); } $file_extension = pathinfo( $original_filename, PATHINFO_EXTENSION ); $filename = wp_unique_filename( $uploads_directory, wp_generate_password( 32, false, false ) . '.' . $file_extension ); $uploads_directory = trailingslashit( $uploads_directory ); if ( ! is_writeable( $uploads_directory ) ) { return false; } $upload_path = $uploads_directory . $filename; if ( file_put_contents( $upload_path, $file_content ) !== false ) { // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents return $upload_path; } return false; } /** * Delete attachments, removing their files from disk. * * @since 2.6.0 * * @param null|array $attachments List of attachments to cleanup, or null for all attachments. * @param null|DateTime $before_datetime The datetime attachments should be older than * to be removed, or null for all attachments. * * @return void. */ public function delete_attachments( $attachments = null, $before_datetime = null ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh $uploads_directory = $this->get_uploads_directory(); if ( is_wp_error( $uploads_directory ) || ! is_dir( $uploads_directory ) ) { return; } $files = []; // If no attachment list is provided, just iterate over all files in our uploads directory. if ( is_null( $attachments ) ) { $nodes = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $uploads_directory, RecursiveDirectoryIterator::SKIP_DOTS ), RecursiveIteratorIterator::CHILD_FIRST ); $files = []; foreach ( $nodes as $fileinfo ) { if ( ! $fileinfo->isDir() ) { $files[] = $fileinfo->getRealPath(); } } } else { // Map attachments to their paths. $files = wp_list_pluck( $attachments, 0 ); // Exclude any files that aren't in our uploads directory. $files = array_filter( $files, function ( $file ) use ( $uploads_directory ) { return trailingslashit( dirname( $file ) ) === $uploads_directory; } ); } // Skip any file that doesn't exist. $files = array_filter( $files, function ( $file ) { return file_exists( $file ); } ); if ( ! is_null( $before_datetime ) ) { // Skip any file that isn't older than the provided datetime. $before_timestamp = $before_datetime->getTimestamp(); $files = array_filter( $files, function ( $file ) use ( $before_timestamp ) { return ( filemtime( $file ) !== false && filemtime( $file ) < $before_timestamp ); } ); } foreach ( $files as $file ) { @unlink( $file ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged } } /** * Get the upload directory path. * * @since 2.6.0 * * @return string|WP_Error The upload directory path. */ private function get_uploads_directory() { $uploads_directory = Uploads::upload_dir(); if ( is_wp_error( $uploads_directory ) ) { return $uploads_directory; } return trailingslashit( trailingslashit( $uploads_directory['path'] ) . 'queue_attachments' ); } }
| ver. 1.6 |
Github
|
.
| PHP 8.1.34 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка