*/ public static function placeholders() { return array( '{first_name}' => __( 'first name of the person', 'dealroot' ), '{name}' => __( 'full name', 'dealroot' ), '{form}' => __( 'name of the form', 'dealroot' ), '{site}' => __( 'name of your website', 'dealroot' ), '{my_name}' => __( 'your name', 'dealroot' ), ); } /** * Replies to start with, in the language loaded. * * @return array[] */ public static function defaults() { return array( array( 'title' => __( 'Thanks, we will call', 'dealroot' ), 'subject' => __( 'Your enquiry', 'dealroot' ), 'body' => __( "Hello {first_name},\n\nthank you for your enquiry. We will call you back today.\n\nBest regards\n{my_name}\n{site}", 'dealroot' ), ), array( 'title' => __( 'Ask for a time', 'dealroot' ), 'subject' => __( 'Your enquiry', 'dealroot' ), 'body' => __( "Hello {first_name},\n\nthank you for your message. When is a good time to call you?\n\nBest regards\n{my_name}\n{site}", 'dealroot' ), ), array( 'title' => __( 'Ask for details', 'dealroot' ), 'subject' => __( 'A question about your enquiry', 'dealroot' ), 'body' => __( "Hello {first_name},\n\nthank you for your enquiry. So that we can make you a fitting offer, could you tell us a little more about what you need and by when?\n\nBest regards\n{my_name}\n{site}", 'dealroot' ), ), ); } /** * The replies of the site. The ones to start with are in the language of the enquiry, so a * customer is not answered in the language of the screen of the team. * * @param object|null $lead Lead the reply is for. * @return array[] */ public static function all( $lead = null ) { $saved = Settings::get( 'replies' ); $locale = Ai::customer_locale( $lead ); if ( ! is_array( $saved ) || ! $saved ) { return Ai::in_locale( $locale, array( self::class, 'defaults' ) ); } // Saved replies keep what was written, but the parts still as they came, e.g. the subject // "Your enquiry", are taken in the language of the enquiry. $rows = self::sanitize( $saved ); $known = self::known_texts(); $own = null; foreach ( $rows as $i => $row ) { foreach ( array( 'title', 'subject', 'body' ) as $part ) { $key = $part . '|' . self::normalize( $row[ $part ] ); if ( isset( $known[ $key ] ) ) { $own = null !== $own ? $own : Ai::in_locale( $locale, array( self::class, 'defaults' ) ); $rows[ $i ][ $part ] = $own[ $known[ $key ] ][ $part ] ?? $row[ $part ]; } } } return $rows; } /** * The texts of the replies to start with, in the languages the replies were likely saved in: * English, the language of the site, of the screen and of the team. * * @return array "part|text" => position of the reply. */ private static function known_texts() { static $known = null; if ( null !== $known ) { return $known; } $known = array(); foreach ( array_unique( array( 'en_US', get_locale(), get_user_locale(), Ai::team_locale() ) ) as $locale ) { foreach ( (array) Ai::in_locale( $locale, array( self::class, 'defaults' ) ) as $i => $reply ) { foreach ( array( 'title', 'subject', 'body' ) as $part ) { $known[ $part . '|' . self::normalize( $reply[ $part ] ) ] = $i; } } } return $known; } /** * A text compared without regard to line endings and spaces at its ends. * * @param string $text Text. * @return string */ private static function normalize( $text ) { return trim( str_replace( "\r\n", "\n", (string) $text ) ); } /** * Replies from the settings form: rows without a text are dropped. * * @param mixed $rows Raw rows. * @return array[] */ public static function sanitize( $rows ) { $clean = array(); foreach ( is_array( $rows ) ? $rows : array() as $row ) { if ( ! is_array( $row ) ) { continue; } $body = trim( mb_substr( sanitize_textarea_field( (string) ( $row['body'] ?? '' ) ), 0, 2000 ) ); if ( '' === $body ) { continue; } $clean[] = array( 'title' => mb_substr( sanitize_text_field( (string) ( $row['title'] ?? '' ) ), 0, 60 ), 'subject' => mb_substr( sanitize_text_field( (string) ( $row['subject'] ?? '' ) ), 0, 150 ), 'body' => $body, ); if ( count( $clean ) >= self::MAX ) { break; } } return $clean; } /** * A text with the details of a lead in place of the placeholders. * * @param string $text Text. * @param object $lead Lead. * @return string */ public static function fill( $text, $lead ) { $name = trim( (string) $lead->name ); $first = '' !== $name ? (string) strtok( $name, ' ' ) : ''; $user = wp_get_current_user(); $text = strtr( (string) $text, array( '{first_name}' => $first, '{name}' => $name, '{form}' => (string) $lead->form_name, '{site}' => wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ), '{my_name}' => $user && $user->exists() ? $user->display_name : '', ) ); // "Hello ," when the name is not known. $text = (string) preg_replace( '/[ \t]+([,.!?])/u', '$1', $text ); return trim( (string) preg_replace( "/\n{3,}/", "\n\n", $text ) ); } }