| @@ -93,9 +93,8 @@ | ||
| 93 | 93 | /** |
| 94 | 94 | * This is for when user select report as monthly, we will have the day number, instead of text. |
| 95 | 95 | * |
| 96 | 96 | * @var int |
| 97 | - * @sanitize_text_field | |
| 98 | 97 | * @defender_property |
| 99 | 98 | */ |
| 100 | 99 | public int $day_n = 1; |
| 101 | 100 | |
| @@ -250,14 +249,14 @@ | ||
| 250 | 249 | $est->setTimestamp( $this->last_sent ); |
| 251 | 250 | } |
| 252 | 251 | |
| 253 | 252 | // Est should be set as the last send. Create now timestamp. |
| 254 | - $now = new DateTime( 'now', wp_timezone() ); | |
| 255 | - $interval = DateInterval::createFromDateString( (string) $est->getOffset() . 'seconds' ); | |
| 256 | - $time_parts = array_pad( explode( ':', (string) $this->time ), 2, 0 ); | |
| 257 | - [ $hour, $min ] = $time_parts; | |
| 258 | - $hour = (int) $hour; | |
| 259 | - $min = (int) $min; | |
| 253 | + $now = new DateTime( 'now', wp_timezone() ); | |
| 254 | + $interval = DateInterval::createFromDateString( (string) $est->getOffset() . 'seconds' ); | |
| 255 | + $time_parts = array_pad( explode( ':', (string) $this->time ), 2, 0 ); | |
| 256 | + [ $hour, $min ] = $time_parts; | |
| 257 | + $hour = (int) $hour; | |
| 258 | + $min = (int) $min; | |
| 260 | 259 | switch ( $this->frequency ) { |
| 261 | 260 | case 'daily': |
| 262 | 261 | // Set the time. |
| 263 | 262 | $est->add( $interval ); |
| @@ -268,9 +267,9 @@ | ||
| 268 | 267 | $est->setTime( $hour, $min, 0 ); |
| 269 | 268 | } |
| 270 | 269 | break; |
| 271 | 270 | case 'weekly': |
| 272 | - if ( empty( $this->day ) ) { | |
| 271 | + if ( '' === $this->day || null === $this->day ) { | |
| 273 | 272 | break; |
| 274 | 273 | } |
| 275 | 274 | $est->modify( 'this ' . $this->day ); |
| 276 | 275 | $est->add( $interval ); |
| @@ -447,8 +446,31 @@ | ||
| 447 | 446 | return $data; |
| 448 | 447 | } |
| 449 | 448 | |
| 450 | 449 | /** |
| 450 | + * Prepare data for persistence. | |
| 451 | + * | |
| 452 | + * Recipients are indexed by email in memory (see after_load()), so re-index them back to | |
| 453 | + * sequential arrays before storing. Otherwise they are JSON-encoded as objects, which on | |
| 454 | + * downgrade breaks Defender 5 with "all_subscribers.slice is not a function". | |
| 455 | + * | |
| 456 | + * @param array $data The data array to import values from. | |
| 457 | + * | |
| 458 | + * @return array | |
| 459 | + */ | |
| 460 | + protected function prepare_data( $data = array() ): array { | |
| 461 | + $data = parent::prepare_data( $data ); | |
| 462 | + | |
| 463 | + foreach ( array( 'in_house_recipients', 'out_house_recipients', 'all_subscribers' ) as $key ) { | |
| 464 | + if ( isset( $data[ $key ] ) && is_array( $data[ $key ] ) ) { | |
| 465 | + $data[ $key ] = array_values( $data[ $key ] ); | |
| 466 | + } | |
| 467 | + } | |
| 468 | + | |
| 469 | + return $data; | |
| 470 | + } | |
| 471 | + | |
| 472 | + /** | |
| 451 | 473 | * Overrided method to manipulate user details dynamically. |
| 452 | 474 | */ |
| 453 | 475 | protected function after_load(): void { |
| 454 | 476 | $in_house_recipients = array(); |
| @@ -483,9 +505,9 @@ | ||
| 483 | 505 | private function get_email_indexed_recipients( array $recipients ): array { |
| 484 | 506 | $email_indexed_recipients = array(); |
| 485 | 507 | |
| 486 | 508 | foreach ( $recipients as $recipient ) { |
| 487 | - if ( empty( $recipient['email'] ) ) { | |
| 509 | + if ( ! isset( $recipient['email'] ) ) { | |
| 488 | 510 | continue; |
| 489 | 511 | } |
| 490 | 512 | |
| 491 | 513 | $email = trim( $recipient['email'] ); |