Completed
Pull Request — dev/2.3.2 (#251)
by Sudar
16:52 queued 10:38
created

EmailLogger::log_buddy_press_email()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 12
nc 4
nop 2
dl 0
loc 20
ccs 0
cts 0
cp 0
crap 20
rs 9.8666
c 1
b 0
f 0
1
<?php namespace EmailLog\Core;
2
3
/**
4
 * Log's emails sent through `wp_mail`.
5
 *
6
 * @package EmailLog\Core
7
 * @since   2.0
8
 */
9
class EmailLogger implements Loadie {
10
11
	/**
12
	 * Load the logger.
13
	 */
14
	public function load() {
15
		add_filter( 'wp_mail', array( $this, 'log_email' ) );
16
		add_action( 'wp_mail_failed', array( $this, 'update_email_fail_status' ) );
17
18
		/**
19
		 * These actions are required for logging BuddyPress emails, since BuddyPress does
20
		 * not use wp_mail for sending emails.
21
		 */
22
		add_action( 'bp_send_email_success', array( $this, 'log_buddy_press_email' ), 10, 2 );
23
		add_action( 'bp_send_email_failure', array( $this, 'log_buddy_press_email' ), 10, 2 );
24
	}
25
26 1
	/**
27
	 * Logs email to database.
28
	 *
29
	 * @param array $original_mail_info Information about email.
30
	 *
31
	 * @return array Information about email.
32
	 */
33
	public function log_email( $original_mail_info ) {
34
		/**
35
		 * Hook to modify wp_mail contents before Email Log plugin logs.
36
		 *
37
		 * @param array $original_mail_info {
38
		 *     @type string|array $to
39
		 *     @type string       $subject
40 1
		 *     @type string       $message
41
		 *     @type string|array $headers
42
		 *     @type string|array $attachment
43
		 * }
44 1
		 *
45 1
		 * @since 2.0.0
46
		 */
47 1
		$original_mail_info = apply_filters( 'el_wp_mail_log', $original_mail_info );
48 1
49 1
		// Sometimes the array passed to the `wp_mail` filter may not contain all the required keys.
50 1
		// See https://wordpress.org/support/topic/illegal-string-offset-attachments/.
51 1
		$mail_info = wp_parse_args(
52
			$original_mail_info,
53 1
			array(
54
				'to'          => '',
55
				'subject'     => '',
56 1
				'message'     => '',
57 1
				'headers'     => '',
58 1
				'attachments' => array(),
59 1
			)
60 1
		);
61 1
62 1
		$log = array(
63 1
			'to_email'        => \EmailLog\Util\stringify( $mail_info['to'] ),
64 1
			'subject'         => $mail_info['subject'],
65
			'message'         => $mail_info['message'],
66 1
			'headers'         => \EmailLog\Util\stringify( $mail_info['headers'], "\n" ),
67 1
			'attachment_name' => \EmailLog\Util\stringify( $mail_info['attachments'] ),
68 1
			'sent_date'       => current_time( 'mysql' ),
69
			'ip_address'      => $_SERVER['REMOTE_ADDR'],
70
			'result'          => 1,
71
		);
72
73
		if ( empty( $log['attachment_name'] ) ) {
74
			$log['attachments'] = 'false';
75
		} else {
76
			$log['attachments'] = 'true';
77
		}
78
79
		/**
80
		 * Filters the mail info right before inserting on the table.
81
		 *
82
		 * Masked fields would use this filter to avoid modifying the original data sent to
83 1
		 * `wp_mail() function`
84
		 *
85 1
		 * @param array $log                Email Log that is about to be inserted into db.
86 1
		 * @param array $original_mail_info Original mail info that was passed to `wp_mail` filter.
87
		 *
88
		 * @since 2.3.2
89
		 */
90
		$log = apply_filters( 'el_email_log_before_insert', $log, $original_mail_info );
91
92
		$email_log = email_log();
93
		$email_log->table_manager->insert_log( $log );
94
95
		/**
96
		 * Fires the `el_email_log_inserted` action right after the log is inserted in to DB.
97
		 *
98
		 * @since 2.3.0
99
		 *
100
		 * @param array $log {
101
		 *      @type string $to
102
		 *      @type string $subject
103
		 *      @type string $message
104
		 *      @type string $headers
105 1
		 *      @type string $attachments
106
		 *      @type string $attachment_name
107 1
		 *      @type string $sent_date
108
		 *      @type string $ip_address
109
		 *      @type bool   $result
110
		 * }
111
		 */
112
		do_action( 'el_email_log_inserted', $log );
113
114
		return $original_mail_info;
115
	}
116
117
	/**
118
	 * Updates the failed email in the DB.
119
	 *
120
	 * @since 2.3.0
121
	 *
122
	 * @param \WP_Error $wp_error The error instance.
123
	 */
124
	public function update_email_fail_status( $wp_error ) {
125
		if ( ! ( $wp_error instanceof \WP_Error ) ) {
0 ignored issues
show
introduced by
$wp_error is always a sub-type of WP_Error.
Loading history...
126
			return;
127
		}
128
129
		// @see wp-includes/pluggable.php#500
130
		$mail_error_data = $wp_error->get_error_data( 'wp_mail_failed' );
131
132
		$this->mark_email_log_as_failed( $mail_error_data );
133
	}
134
135
	/**
136
	 * Prepare BuddyPress emails to log into database.
137
	 *
138
	 * @since 2.3.2
139
	 *
140
	 * @param bool      $status  Mail sent status.
141
	 * @param \BP_Email $bp_mail Information about email.
142
	 */
143
	public function log_buddy_press_email( $status, $bp_mail ) {
144
		if ( ! class_exists( '\\BP_Email' ) ) {
145
			return;
146
		}
147
148
		if ( $bp_mail instanceof \BP_Email ) {
0 ignored issues
show
Bug introduced by
The type BP_Email was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
149
			return;
150
		}
151
152
		$log = array(
153
			'to'      => array_shift( $bp_mail->get_to() )->get_address(),
0 ignored issues
show
Bug introduced by
$bp_mail->get_to() cannot be passed to array_shift() as the parameter $array expects a reference. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

153
			'to'      => array_shift( /** @scrutinizer ignore-type */ $bp_mail->get_to() )->get_address(),
Loading history...
154
			'subject' => $bp_mail->get_subject( 'replace-tokens' ),
155
			'message' => $bp_mail->get_content( 'replace-tokens' ),
156
			'headers' => $bp_mail->get_headers( 'replace-tokens ' ),
157
		);
158
159
		$this->log_email( $log );
160
161
		if ( ! $status ) {
162
			$this->mark_email_log_as_failed( $log );
163
		}
164
	}
165
166
	/**
167
	 * Mark email log as failed.
168
	 *
169
	 * @since 2.3.2
170
	 *
171
	 * @param array $log Email Log.
172
	 */
173
	protected function mark_email_log_as_failed( $log ) {
174
		if ( ! is_array( $log ) ) {
0 ignored issues
show
introduced by
The condition is_array($log) is always true.
Loading history...
175
			return;
176
		}
177
178
		if ( ! isset( $log['to'], $log['subject'] ) ) {
179
			return;
180
		}
181
182
		$email_log = email_log();
183
184
		$log_item_id = $email_log->table_manager->fetch_log_item_by_item_data( $log );
185
186
		if ( empty( $log_item_id ) ) {
187
			return;
188
		}
189
190
		$email_log->table_manager->set_log_item_fail_status_by_id( $log_item_id );
191
	}
192
}
193