(string) ( $away['from'] ?? '' ), 'until' => (string) ( $away['until'] ?? '' ), 'note' => (string) ( $away['note'] ?? '' ), ); } /** * Whether the owner is away today. * * @return bool */ public static function active() { $away = self::get(); return '' !== $away['until'] && $away['until'] >= wp_date( 'Y-m-d' ) && $away['from'] <= wp_date( 'Y-m-d' ); } /** * The last day away, as people read it, e.g. "15 November 2026". * * @return string */ public static function until_text() { $until = date_create_immutable( self::get()['until'] . ' 12:00', wp_timezone() ); return $until ? wp_date( get_option( 'date_format' ), $until->getTimestamp() ) : ''; } /** * Starts or ends the away time. * * @param string $until Last day away, Y-m-d, or "" to end it. * @param string $note What people should know, e.g. who stands in, optional. * @return bool */ public static function set( $until, $note = '' ) { if ( '' === $until ) { $away = self::get(); // The list of what came in stays for a few days. $away['until'] = $away['from'] && $away['until'] > wp_date( 'Y-m-d' ) ? wp_date( 'Y-m-d', time() - DAY_IN_SECONDS ) : $away['until']; return update_option( self::OPTION, $away, false ); } if ( ! preg_match( '/^\d{4}-\d{2}-\d{2}$/', $until ) || $until < wp_date( 'Y-m-d' ) ) { return false; } return update_option( self::OPTION, array( 'from' => wp_date( 'Y-m-d' ), 'until' => $until, 'note' => mb_substr( sanitize_textarea_field( $note ), 0, 300 ), ), false ); } /** * Without the AI assistant, a short confirmation of its own; with it, the assistant writes it * and says when the answer comes. * * @param int $lead_id Lead ID. */ public static function reply( $lead_id ) { if ( ! self::active() || Ai::enabled() ) { return; } $lead = Leads::get( (int) $lead_id ); if ( ! $lead || 'new' !== $lead->status || in_array( $lead->form_plugin, array( 'manual', 'woocommerce', 'order' ), true ) || ! is_email( $lead->email ) ) { return; } // One answer a day per address, so a form sent twice gets one. if ( get_transient( 'dealroot_away_' . md5( strtolower( $lead->email ) ) ) ) { return; } set_transient( 'dealroot_away_' . md5( strtolower( $lead->email ) ), 1, DAY_IN_SECONDS ); $business = Ai::business(); $note = self::get()['note']; $body = sprintf( /* translators: 1: date, 2: name of the business */ __( "Thank you for your message. We are away until %1\$s and will answer you personally after that.\n\nKind regards\n%2\$s", 'dealroot' ), self::until_text(), $business ); if ( '' !== $note ) { $body = str_replace( "\n\n", "\n\n" . $note . "\n\n", $body ); } /* translators: %s: name of the business */ Ai::mail( $lead->email, sprintf( __( 'Your message to %s', 'dealroot' ), $business ), $body, true ); } /** * Enquiries that came while the owner was away and still wait, those likely worth the most first. * * @return object[] */ public static function waiting() { global $wpdb; $away = self::get(); if ( '' === $away['from'] ) { return array(); } $from = date_create_immutable( $away['from'] . ' 00:00', wp_timezone() ); $leads = (array) $wpdb->get_results( $wpdb->prepare( "SELECT * FROM %i WHERE status = 'new' AND form_plugin NOT IN ('manual', 'woocommerce') AND ai_kind NOT IN ('spam', 'job') AND created_at >= %s ORDER BY created_at DESC LIMIT 100", Installer::table(), gmdate( 'Y-m-d H:i:s', $from ? $from->getTimestamp() : time() ) ) ); foreach ( $leads as $lead ) { $worth = null !== $lead->ai_budget ? (float) $lead->ai_budget : ( null !== $lead->value ? (float) $lead->value : 0.0 ); /** * Filters what a lead is likely worth, e.g. with the expected value of Dealroot Pro. * * @param float $worth Amount in the currency of the site. * @param object $lead Lead. */ $lead->worth = (float) apply_filters( 'dealroot_lead_worth', $worth, $lead ); } usort( $leads, static function ( $a, $b ) { $order = $b->worth <=> $a->worth; return 0 !== $order ? $order : strcmp( $a->created_at, $b->created_at ); } ); return $leads; } /** * On the overview: while away, that the mode is on; back again, what came in. */ public static function panel() { $away = self::get(); if ( '' === $away['until'] ) { return; } $active = self::active(); $back = ! $active && $away['until'] < wp_date( 'Y-m-d' ) && $away['until'] >= wp_date( 'Y-m-d', time() - self::SHOW_DAYS * DAY_IN_SECONDS ); if ( ! $active && ! $back ) { return; } $leads = self::waiting(); $currency = (string) Settings::get( 'currency' ); ?>

  1. name ) ? $lead->name : $lead->email ); ?> ai_summary ? $lead->ai_summary : $lead->form_name ), 90, '…' ) ); ?> worth > 0 ) : ?> worth, $currency ) ); ?>