Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 87 |
|
0.00% |
0 / 5 |
CRAP | n/a |
0 / 0 |
|
| Automattic\Jetpack\Jetpack_Mu_Wpcom\EventCountdown\register_block | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
| Automattic\Jetpack\Jetpack_Mu_Wpcom\EventCountdown\load_assets | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
| Automattic\Jetpack\Jetpack_Mu_Wpcom\EventCountdown\enqueue_block_editor_assets | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| Automattic\Jetpack\Jetpack_Mu_Wpcom\EventCountdown\render_email | |
0.00% |
0 / 62 |
|
0.00% |
0 / 1 |
182 | |||
| Automattic\Jetpack\Jetpack_Mu_Wpcom\EventCountdown\get_email_event_timestamp | |
0.00% |
0 / 11 |
|
0.00% |
0 / 1 |
56 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * Event Countdown Block |
| 4 | * |
| 5 | * @package automattic/jetpack-mu-wpcom |
| 6 | */ |
| 7 | |
| 8 | namespace Automattic\Jetpack\Jetpack_Mu_Wpcom\EventCountdown; |
| 9 | |
| 10 | require_once __DIR__ . '/../../../utils.php'; |
| 11 | |
| 12 | /** |
| 13 | * Registers the block for use in Gutenberg |
| 14 | * This is done via an action so that we can disable |
| 15 | * registration if we need to. |
| 16 | */ |
| 17 | function register_block() { |
| 18 | register_block_type( |
| 19 | 'jetpack/event-countdown', |
| 20 | array( |
| 21 | 'render_callback' => __NAMESPACE__ . '\load_assets', |
| 22 | 'render_email_callback' => __NAMESPACE__ . '\render_email', |
| 23 | ) |
| 24 | ); |
| 25 | } |
| 26 | add_action( 'init', __NAMESPACE__ . '\register_block' ); |
| 27 | |
| 28 | /** |
| 29 | * Load assets on frontend. |
| 30 | * |
| 31 | * @param array $attr Array containing the EventCountdown block attributes. |
| 32 | * @param string $content String containing the EventCountdown block content. |
| 33 | * |
| 34 | * @return string |
| 35 | */ |
| 36 | function load_assets( $attr, $content ) { |
| 37 | // A block's view assets will not be required in wp-admin. |
| 38 | if ( ! is_admin() ) { |
| 39 | \jetpack_mu_wpcom_enqueue_assets( 'wpcom-blocks-event-countdown-view', array( 'js', 'css' ) ); |
| 40 | } |
| 41 | |
| 42 | return $content; |
| 43 | } |
| 44 | |
| 45 | /** |
| 46 | * Load assets on the editor. |
| 47 | */ |
| 48 | function enqueue_block_editor_assets() { |
| 49 | \jetpack_mu_wpcom_enqueue_assets( 'wpcom-blocks-event-countdown-editor', array( 'js', 'css' ) ); |
| 50 | } |
| 51 | add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\enqueue_block_editor_assets' ); |
| 52 | |
| 53 | /** |
| 54 | * WooCommerce Email Editor render callback. Email can't run the countdown |
| 55 | * script, so render the time left at send time plus the event date. |
| 56 | * |
| 57 | * @param string $block_content The saved block markup. |
| 58 | * @param array $parsed_block The parsed block. |
| 59 | * @param object $rendering_context The email rendering context. |
| 60 | * @return string |
| 61 | */ |
| 62 | function render_email( $block_content, array $parsed_block, $rendering_context ) { |
| 63 | if ( ! class_exists( '\Automattic\WooCommerce\EmailEditor\Integrations\Utils\Table_Wrapper_Helper' ) || |
| 64 | ! class_exists( '\Automattic\WooCommerce\EmailEditor\Integrations\Utils\Html_Processing_Helper' ) ) { |
| 65 | return ''; |
| 66 | } |
| 67 | |
| 68 | $timestamp = get_email_event_timestamp( $parsed_block['attrs'] ?? array(), (string) $block_content ); |
| 69 | if ( null === $timestamp ) { |
| 70 | return ''; |
| 71 | } |
| 72 | |
| 73 | $title = ''; |
| 74 | if ( preg_match( '/class="event-countdown__event-title"[^>]*>\s*<p>(.*?)<\/p>/s', (string) $block_content, $m ) ) { |
| 75 | $title = trim( wp_strip_all_tags( $m[1] ) ); |
| 76 | } |
| 77 | |
| 78 | // Outlook does not inherit color into nested tables, so paint it on every cell like the engine's Text renderer. |
| 79 | $email_attrs = $parsed_block['email_attrs'] ?? array(); |
| 80 | $theme_styles = is_object( $rendering_context ) && method_exists( $rendering_context, 'get_theme_styles' ) ? (array) $rendering_context->get_theme_styles() : array(); |
| 81 | $color = $email_attrs['color'] ?? $theme_styles['color']['text'] ?? '#000000'; |
| 82 | // @phan-suppress-next-line PhanUndeclaredClassMethod -- Optional WooCommerce dependency, checked with class_exists() above. |
| 83 | $color = \Automattic\WooCommerce\EmailEditor\Integrations\Utils\Html_Processing_Helper::sanitize_color( is_string( $color ) ? $color : '' ); |
| 84 | |
| 85 | // Each line is a stacked table with cell padding for the gaps: Outlook ignores margins on <p> and tables. |
| 86 | $lines = array(); |
| 87 | $remaining = $timestamp - time(); |
| 88 | if ( $remaining > 0 ) { |
| 89 | if ( $remaining >= DAY_IN_SECONDS ) { |
| 90 | $count = (int) floor( $remaining / DAY_IN_SECONDS ); |
| 91 | $label = _nx( 'day until', 'days until', $count, 'Countdown days remaining', 'jetpack-mu-wpcom' ); |
| 92 | } elseif ( $remaining >= HOUR_IN_SECONDS ) { |
| 93 | $count = (int) floor( $remaining / HOUR_IN_SECONDS ); |
| 94 | $label = _nx( 'hour until', 'hours until', $count, 'Countdown hours remaining', 'jetpack-mu-wpcom' ); |
| 95 | } else { |
| 96 | $count = max( 1, (int) floor( $remaining / MINUTE_IN_SECONDS ) ); |
| 97 | $label = _nx( 'minute until', 'minutes until', $count, 'Countdown minutes remaining', 'jetpack-mu-wpcom' ); |
| 98 | } |
| 99 | |
| 100 | $lines[] = array( number_format_i18n( $count ), 'font-size: 56px; line-height: 56px; font-weight: 700; padding: 0 0 4px;' ); |
| 101 | $lines[] = array( $label, 'font-size: 14px; line-height: 20px; font-weight: 600; text-transform: uppercase; letter-spacing: 1px; padding: 0 0 16px;' ); |
| 102 | } |
| 103 | if ( '' !== $title ) { |
| 104 | $lines[] = array( $title, 'font-size: 28px; line-height: 34px; font-weight: 700; padding: 0 0 8px;' ); |
| 105 | } |
| 106 | $lines[] = array( |
| 107 | sprintf( |
| 108 | /* translators: 1: event date, 2: event time. */ |
| 109 | __( '%1$s at %2$s', 'jetpack-mu-wpcom' ), |
| 110 | wp_date( get_option( 'date_format' ), $timestamp ), |
| 111 | wp_date( get_option( 'time_format' ), $timestamp ) |
| 112 | ), |
| 113 | 'font-size: 14px; line-height: 20px; padding: 0;', |
| 114 | ); |
| 115 | |
| 116 | $body = ''; |
| 117 | foreach ( $lines as $line ) { |
| 118 | // @phan-suppress-next-line PhanUndeclaredClassMethod -- Optional WooCommerce dependency, checked with class_exists() above. |
| 119 | $body .= \Automattic\WooCommerce\EmailEditor\Integrations\Utils\Table_Wrapper_Helper::render_table_wrapper( |
| 120 | esc_html( $line[0] ), |
| 121 | array( |
| 122 | 'width' => '100%', |
| 123 | 'style' => 'border-collapse: separate;', |
| 124 | ), |
| 125 | array( |
| 126 | 'align' => 'center', |
| 127 | 'style' => 'text-align: center; mso-line-height-rule: exactly; color: ' . $color . '; ' . $line[1], |
| 128 | ) |
| 129 | ); |
| 130 | } |
| 131 | |
| 132 | // The engine sets margin-top on every block after the first; core renderers add no other margin. |
| 133 | $margin_style = (string) \WP_Style_Engine::compile_css( array_intersect_key( $email_attrs, array_flip( array( 'margin-top' ) ) ), '' ); |
| 134 | |
| 135 | // @phan-suppress-next-line PhanUndeclaredClassMethod -- Optional WooCommerce dependency, checked with class_exists() above. |
| 136 | return \Automattic\WooCommerce\EmailEditor\Integrations\Utils\Table_Wrapper_Helper::render_table_wrapper( |
| 137 | $body, |
| 138 | array( |
| 139 | 'class' => 'wp-block-jetpack-event-countdown', |
| 140 | 'width' => '100%', |
| 141 | 'style' => trim( $margin_style . ' min-width: 100%; border-collapse: separate;' ), |
| 142 | ), |
| 143 | array( |
| 144 | 'align' => 'center', |
| 145 | 'style' => 'text-align: center; word-break: break-word; color: ' . $color . '; padding: 16px 0;', |
| 146 | ) |
| 147 | ); |
| 148 | } |
| 149 | |
| 150 | /** |
| 151 | * Resolve the event time as a unix timestamp. Newer posts store `eventTimestamp`; |
| 152 | * older ones only have the `eventDate` string in the saved markup. |
| 153 | * |
| 154 | * @param array $attrs Block attributes. |
| 155 | * @param string $block_content The saved block markup. |
| 156 | * @return int|null |
| 157 | */ |
| 158 | function get_email_event_timestamp( array $attrs, $block_content ) { |
| 159 | if ( ! empty( $attrs['eventTimestamp'] ) && is_numeric( $attrs['eventTimestamp'] ) ) { |
| 160 | return (int) $attrs['eventTimestamp']; |
| 161 | } |
| 162 | |
| 163 | if ( ! preg_match( '/class="event-countdown__date"[^>]*>(.*?)<\/div>/s', $block_content, $m ) ) { |
| 164 | return null; |
| 165 | } |
| 166 | |
| 167 | $date = trim( wp_strip_all_tags( $m[1] ) ); |
| 168 | if ( '' === $date ) { |
| 169 | return null; |
| 170 | } |
| 171 | if ( preg_match( '/^\d+$/', $date ) ) { |
| 172 | return (int) $date; |
| 173 | } |
| 174 | |
| 175 | $datetime = date_create_immutable( $date, wp_timezone() ); |
| 176 | return $datetime ? $datetime->getTimestamp() : null; |
| 177 | } |