__( '[Review required] %s', 'ost-editorial-workflow' ), /* translators: %s: post title. */ 'published' => __( '[Published] %s', 'ost-editorial-workflow' ), /* translators: %s: post title. */ 'sent_back' => __( '[Sent back] %s', 'ost-editorial-workflow' ), /* translators: %s: post title. */ 'escalation_reminder' => __( '[Review reminder] %s', 'ost-editorial-workflow' ), /* translators: %s: post title. */ 'escalation_notice' => __( '[Escalation] %s', 'ost-editorial-workflow' ), ); } /** * Send a workflow email. * * @param string $template Template slug. * @param \WP_User $user Recipient. * @param array $vars Merge variables. * @return bool */ public function send( $template, $user, array $vars ) { $opts = get_option( 'ostew_settings', array() ); if ( isset( $opts['notifications_enabled'] ) && ! $opts['notifications_enabled'] ) { return false; // email notifications switched off in settings. } $vars['recipient_name'] = $user->display_name; $subject = $this->subject( $template, $vars ); $body = $this->render( $template, $vars ); $headers = array( 'Content-Type: text/html; charset=UTF-8', 'From: ' . $this->from(), ); $sent = wp_mail( $user->user_email, $subject, $body, $headers ); if ( ! $sent && defined( 'WP_DEBUG' ) && WP_DEBUG ) { error_log( sprintf( '[ost-editorial-workflow] email to %s not sent (template %s)', $user->user_email, $template ) ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log } return (bool) $sent; } /** * Build the subject line. * * @param string $template Template slug. * @param array $vars Merge vars. * @return string */ private function subject( $template, array $vars ) { $formats = $this->subject_formats(); /* translators: %s: post title. */ $format = isset( $formats[ $template ] ) ? $formats[ $template ] : __( '[Update] %s', 'ost-editorial-workflow' ); $subject = sprintf( $format, $vars['post_title'] ); /** * Filter a workflow email subject. * * @param string $subject Subject. * @param string $template Template slug. * @param array $vars Merge vars. */ return apply_filters( 'ostew/email_subject', $subject, $template, $vars ); } /** * Render the inner template inside the base wrapper. * * @param string $template Template slug. * @param array $vars Merge vars. * @return string */ private function render( $template, array $vars ) { $file = $this->template_path( $template ); if ( ! is_readable( $file ) ) { $file = $this->template_path( 'review-request' ); } $vars['content'] = $this->capture( $file, $vars ); $body = $this->capture( $this->template_path( 'base' ), $vars ); /** * Filter the full rendered email body. * * @param string $body HTML body. * @param string $template Template slug. * @param array $vars Merge vars. */ return apply_filters( 'ostew/email_body', $body, $template, $vars ); } /** * Map a template slug to its file (slug uses underscores; files use hyphens). * * @param string $name Slug or file base. * @return string */ private function template_path( $name ) { $name = str_replace( '_', '-', $name ); return OSTEW_DIR . 'templates/emails/' . $name . '.php'; } /** * Include a template with vars in scope and capture the output. * * @param string $file Absolute path. * @param array $vars Merge vars. * @return string */ private function capture( $file, array $vars ) { if ( ! is_readable( $file ) ) { return ''; } ob_start(); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract extract( $vars ); include $file; return (string) ob_get_clean(); } /** * The From header value (configurable via ostew_settings, sensible defaults). * * @return string */ private function from() { $opts = get_option( 'ostew_settings', array() ); $name = ! empty( $opts['from_name'] ) ? $opts['from_name'] : get_bloginfo( 'name' ); $email = ! empty( $opts['from_email'] ) ? $opts['from_email'] : get_option( 'admin_email' ); return sprintf( '%s <%s>', $name, $email ); } }