Completed
Pull Request — master (#236)
by Sudar
07:59 queued 03:50
created

EmailLogger::log_email()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 82
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 2.0004

Importance

Changes 13
Bugs 0 Features 0
Metric Value
cc 2
eloc 27
c 13
b 0
f 0
nc 2
nop 1
dl 0
loc 82
ccs 20
cts 21
cp 0.9524
crap 2.0004
rs 9.488

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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, 'on_email_failed' ) );
17
18
		/**
19
		 * These actions are required for logging BuddyPress emails, since BuddyPress does
20
		 * not use wp_mail for sending emails.
21
		 *
22
		 * Support for BuddyPress was added in v2.3.2
23
		 *
24
		 * @link https://github.com/sudar/email-log/issues/249
25
		 */
26
		add_action( 'bp_send_email_success', array( $this, 'log_buddy_press_email' ), 10, 2 );
27
		add_action( 'bp_send_email_failure', array( $this, 'log_buddy_press_email' ), 10, 2 );
28
	}
29
30
	/**
31
	 * Logs email to database.
32
	 *
33
	 * @param array $original_mail_info Information about email.
34
	 *
35
	 * @return array Information about email.
36
	 */
37 1
	public function log_email( $original_mail_info ) {
38
		/**
39
		 * Hook to modify wp_mail contents before Email Log plugin logs.
40
		 *
41
		 * @param array $original_mail_info {
42
		 *     @type string|array $to
43
		 *     @type string       $subject
44
		 *     @type string       $message
45
		 *     @type string|array $headers
46
		 *     @type string|array $attachment
47
		 * }
48
		 *
49
		 * @since 2.0.0
50
		 */
51 1
		$original_mail_info = apply_filters( 'el_wp_mail_log', $original_mail_info );
52
53
		// Sometimes the array passed to the `wp_mail` filter may not contain all the required keys.
54
		// See https://wordpress.org/support/topic/illegal-string-offset-attachments/.
55 1
		$mail_info = wp_parse_args(
56 1
			$original_mail_info,
57
			array(
58 1
				'to'          => '',
59
				'subject'     => '',
60
				'message'     => '',
61
				'headers'     => '',
62
				'attachments' => array(),
63
			)
64
		);
65
66
		$log = array(
67 1
			'to_email'        => \EmailLog\Util\stringify( $mail_info['to'] ),
68 1
			'subject'         => $mail_info['subject'],
69 1
			'message'         => $mail_info['message'],
70 1
			'headers'         => \EmailLog\Util\stringify( $mail_info['headers'], "\n" ),
71 1
			'attachment_name' => \EmailLog\Util\stringify( $mail_info['attachments'] ),
72 1
			'sent_date'       => current_time( 'mysql' ),
73 1
			'ip_address'      => $_SERVER['REMOTE_ADDR'],
74 1
			'result'          => 1,
75
		);
76
77 1
		if ( empty( $log['attachment_name'] ) ) {
78 1
			$log['attachments'] = 'false';
79
		} else {
80
			$log['attachments'] = 'true';
81
		}
82
83
		/**
84
		 * Filters the mail info right before inserting on the table.
85
		 *
86
		 * Masked fields would use this filter to avoid modifying the original data sent to
87
		 * `wp_mail() function`
88
		 *
89
		 * @param array $log                Email Log that is about to be inserted into db.
90
		 * @param array $original_mail_info Original mail info that was passed to `wp_mail` filter.
91
		 *
92
		 * @since 2.3.2
93
		 */
94 1
		$log = apply_filters( 'el_email_log_before_insert', $log, $original_mail_info );
95
96 1
		$email_log = email_log();
97 1
		$email_log->table_manager->insert_log( $log );
98
99
		/**
100
		 * Fires the `el_email_log_inserted` action right after the log is inserted in to DB.
101
		 *
102
		 * @since 2.3.0
103
		 *
104
		 * @param array $log {
105
		 *      @type string $to
106
		 *      @type string $subject
107
		 *      @type string $message
108
		 *      @type string $headers
109
		 *      @type string $attachments
110
		 *      @type string $attachment_name
111
		 *      @type string $sent_date
112
		 *      @type string $ip_address
113
		 *      @type bool   $result
114
		 * }
115
		 */
116 1
		do_action( 'el_email_log_inserted', $log );
117
118 1
		return $original_mail_info;
119
	}
120
121
	/**
122
	 * Updates the failed email in the DB.
123
	 *
124
	 * @since 2.3.0
125
	 *
126
	 * @param \WP_Error $wp_error The error instance.
127
	 */
128
	public function on_email_failed( $wp_error ) {
129
		if ( ! ( $wp_error instanceof \WP_Error ) ) {
0 ignored issues
show
introduced by
$wp_error is always a sub-type of WP_Error.
Loading history...
130
			return;
131
		}
132
133
		// @see wp-includes/pluggable.php#500
134
		$mail_error_data = $wp_error->get_error_data( 'wp_mail_failed' );
135
136
		$this->mark_email_log_as_failed( $mail_error_data );
137
	}
138
139
	/**
140
	 * Prepare BuddyPress emails to log into database.
141
	 *
142
	 * @since 2.3.2
143
	 *
144
	 * @param bool      $status  Mail sent status.
145
	 * @param \BP_Email $bp_mail Information about email.
146
	 */
147
	public function log_buddy_press_email( $status, $bp_mail ) {
148
		if ( ! class_exists( '\\BP_Email' ) ) {
149
			return;
150
		}
151
152
		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...
153
			return;
154
		}
155
156
		$log = array(
157
			'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

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