Skip to content

Commit

Permalink
Merge pull request #350 from Automattic/master
Browse files Browse the repository at this point in the history
Alpha release Dec 15
  • Loading branch information
adekbadek authored Dec 15, 2020
2 parents 9945470 + 69472f3 commit 20cb428
Show file tree
Hide file tree
Showing 15 changed files with 345 additions and 195 deletions.
61 changes: 33 additions & 28 deletions includes/class-newspack-popups-inserter.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public static function popups_for_post() {
return [ Newspack_Popups_Model::retrieve_preview_popup( Newspack_Popups::previewed_popup_id() ) ];
}

// Campaigns disabled for this page.
if ( self::assess_has_disabled_popups() ) {
return [];
}

// 1. Get all inline popups.
$popups_to_maybe_display = Newspack_Popups_Model::retrieve_inline_popups();

Expand Down Expand Up @@ -80,8 +85,8 @@ public static function popups_for_post() {
$found_popup = Newspack_Popups_Model::retrieve_popup_by_id( $sitewide_default );
if (
$found_popup &&
// Prevent inline sitewide default from being added - all inline popups are there.
'inline' !== $found_popup['options']['placement']
// Prevent non-overlay sitewide default from being added.
Newspack_Popups_Model::is_overlay( $found_popup )
) {
array_push(
$popups_to_maybe_display,
Expand All @@ -96,7 +101,7 @@ public static function popups_for_post() {
$popups_to_maybe_display_deduped = array_filter(
$popups_to_maybe_display,
function ( $campaign ) use ( &$has_overlay ) {
if ( 'inline' !== $campaign['options']['placement'] ) {
if ( Newspack_Popups_Model::is_overlay( $campaign ) ) {
if ( $has_overlay ) {
return false;
} else {
Expand All @@ -108,16 +113,10 @@ function ( $campaign ) use ( &$has_overlay ) {
}
);

$popups_to_display = array_filter(
return array_filter(
$popups_to_maybe_display_deduped,
[ __CLASS__, 'should_display' ]
);

if ( ! empty( $popups_to_display ) ) {
return $popups_to_display;
}

return [];
}

/**
Expand All @@ -129,6 +128,7 @@ public function __construct() {
add_action( 'after_header', [ $this, 'insert_popups_after_header' ] ); // This is a Newspack theme hook. When used with other themes, popups won't be inserted on archive pages.
add_action( 'wp_head', [ $this, 'insert_popups_amp_access' ] );
add_action( 'wp_head', [ $this, 'register_amp_scripts' ] );
add_action( 'before_header', [ $this, 'insert_before_header' ] );

// Always enqueue scripts, since this plugin's scripts are handling pageview sending via GTAG.
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
Expand Down Expand Up @@ -173,9 +173,8 @@ function() {
* Process popups and insert into post and page content if needed.
*
* @param string $content The content of the post.
* @param bool $enqueue_assets Whether assets should be enqueued.
*/
public static function insert_popups_in_content( $content = '', $enqueue_assets = true ) {
public static function insert_popups_in_content( $content = '' ) {
// Avoid duplicate execution.
if ( true === self::$the_content_has_rendered ) {
return $content;
Expand All @@ -201,13 +200,8 @@ public static function insert_popups_in_content( $content = '', $enqueue_assets
return $content;
}

// Campaigns disabled for this page.
if ( self::assess_has_disabled_popups() ) {
return $content;
}

// If the current post is a Campaign, ignore.
if ( Newspack_Popups::NEWSPACK_PLUGINS_CPT == get_post_type() ) {
if ( Newspack_Popups::NEWSPACK_POPUPS_CPT == get_post_type() ) {
return $content;
}

Expand All @@ -217,7 +211,7 @@ public static function insert_popups_in_content( $content = '', $enqueue_assets
return $content;
}

$popups = self::popups_for_post();
$popups = array_filter( self::popups_for_post(), [ 'Newspack_Popups_Model', 'should_be_inserted_in_page_content' ] );

if ( empty( $popups ) ) {
return $content;
Expand All @@ -239,16 +233,21 @@ public static function insert_popups_in_content( $content = '', $enqueue_assets
$inline_popups = [];
$overlay_popups = [];
foreach ( $popups as $popup ) {
if ( 'inline' === $popup['options']['placement'] ) {
if ( Newspack_Popups_Model::is_inline( $popup ) ) {
$percentage = intval( $popup['options']['trigger_scroll_progress'] ) / 100;
$popup['precise_position'] = $total_length * $percentage;
$popup['is_inserted'] = false;
$inline_popups[] = $popup;
} else {
} elseif ( Newspack_Popups_Model::is_overlay( $popup ) ) {
$overlay_popups[] = $popup;
}
}

// Return early if there are no popups to insert. This can happen if e.g. the only popup is an above header one.
if ( empty( $inline_popups ) && empty( $overlay_popups ) ) {
return $content;
}

// 2. Iterate overall blocks and insert inline campaigns.
$pos = 0;
$output = '';
Expand Down Expand Up @@ -291,13 +290,19 @@ public static function insert_popups_after_header() {
if ( is_singular() ) {
return;
}
$popups = array_filter( self::popups_for_post(), [ 'Newspack_Popups_Model', 'should_be_inserted_in_page_content' ] );
foreach ( $popups as $popup ) {
echo Newspack_Popups_Model::generate_popup( $popup ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}

$popups = self::popups_for_post();

if ( ! empty( $popups ) ) {
foreach ( $popups as $popup ) {
echo Newspack_Popups_Model::generate_popup( $popup ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Insert popups markup before header.
*/
public static function insert_before_header() {
$before_header_popups = array_filter( self::popups_for_post(), [ 'Newspack_Popups_Model', 'should_be_inserted_above_page_header' ] );
foreach ( $before_header_popups as $popup ) {
echo Newspack_Popups_Model::generate_popup( $popup ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
}

Expand Down Expand Up @@ -356,7 +361,7 @@ public static function popup_shortcode( $atts = array() ) {
public static function create_single_popup_access_payload( $popup ) {
$popup_id_string = Newspack_Popups_Model::canonize_popup_id( esc_attr( $popup['id'] ) );
$frequency = $popup['options']['frequency'];
if ( 'inline' !== $popup['options']['placement'] && 'always' === $frequency ) {
if ( Newspack_Popups_Model::is_overlay( $popup ) && 'always' === $frequency ) {
$frequency = 'once';
}
return [
Expand Down
118 changes: 89 additions & 29 deletions includes/class-newspack-popups-model.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@
* API endpoints
*/
final class Newspack_Popups_Model {
/**
* Possible placements of overlay popups.
*
* @var array
*/
protected static $overlay_placements = [ 'top', 'bottom', 'center' ];

/**
* Possible placements of inline popups.
*
* @var array
*/
protected static $inline_placements = [ 'inline', 'above_header' ];

/**
* Retrieve all Popups (first 100).
Expand All @@ -20,7 +33,7 @@ final class Newspack_Popups_Model {
*/
public static function retrieve_popups( $include_unpublished = false ) {
$args = [
'post_type' => Newspack_Popups::NEWSPACK_PLUGINS_CPT,
'post_type' => Newspack_Popups::NEWSPACK_POPUPS_CPT,
'post_status' => $include_unpublished ? [ 'publish', 'draft' ] : 'publish',
'posts_per_page' => 100,
];
Expand All @@ -31,7 +44,7 @@ public static function retrieve_popups( $include_unpublished = false ) {
foreach ( $popups as &$popup ) {
// UI will not allow for setting inline as sitewide default, but there may be
// legacy popups from before this update.
if ( 'inline' !== $popup['options']['placement'] ) {
if ( self::is_overlay( $popup ) ) {
$popup['sitewide_default'] = absint( $sitewide_default_id ) === absint( $popup['id'] );
}
}
Expand All @@ -57,7 +70,7 @@ public static function set_sitewide_popup( $id ) {
}

// Such update will not be permitted by the UI, but it's handled just to be explicit about it.
if ( 'inline' === $popup['options']['placement'] ) {
if ( self::is_inline( $popup ) ) {
return new \WP_Error(
'newspack_popups_inline_sitewide',
esc_html__( 'An inline Campaign cannot be a sitewide default.', 'newspack-popups' ),
Expand Down Expand Up @@ -153,7 +166,7 @@ public static function set_popup_options( $id, $options ) {
update_post_meta( $id, $key, $value );
break;
case 'placement':
if ( ! in_array( $value, [ 'center', 'top', 'bottom', 'inline' ] ) ) {
if ( ! in_array( $value, array_merge( self::$overlay_placements, self::$inline_placements ) ) ) {
return new \WP_Error(
'newspack_popups_invalid_option_value',
esc_html__( 'Invalid placement value.', 'newspack-popups' ),
Expand All @@ -165,6 +178,8 @@ public static function set_popup_options( $id, $options ) {
}
update_post_meta( $id, $key, $value );
break;
case 'trigger_type':
case 'trigger_scroll_progress':
case 'utm_suppression':
case 'selected_segment_id':
update_post_meta( $id, $key, esc_attr( $value ) );
Expand All @@ -189,11 +204,12 @@ public static function set_popup_options( $id, $options ) {
*/
public static function retrieve_inline_popups() {
$args = [
'post_type' => Newspack_Popups::NEWSPACK_PLUGINS_CPT,
'post_status' => 'publish',
'meta_key' => 'placement',
'post_type' => Newspack_Popups::NEWSPACK_POPUPS_CPT,
'post_status' => 'publish',
'meta_key' => 'placement',
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
'meta_value' => 'inline',
'meta_value' => self::$inline_placements,
'meta_compare' => 'IN',
];

return self::retrieve_popups_with_query( new WP_Query( $args ) );
Expand All @@ -206,13 +222,13 @@ public static function retrieve_inline_popups() {
*/
public static function retrieve_overlay_test_popups() {
$args = [
'post_type' => Newspack_Popups::NEWSPACK_PLUGINS_CPT,
'post_type' => Newspack_Popups::NEWSPACK_POPUPS_CPT,
'post_status' => 'publish',
'meta_query' => [ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
[
'key' => 'placement',
'value' => 'inline',
'compare' => '!=',
'value' => self::$overlay_placements,
'compare' => 'IN',
],
[
'key' => 'frequency',
Expand All @@ -237,14 +253,14 @@ public static function retrieve_category_overlay_popup() {
}

$args = [
'post_type' => Newspack_Popups::NEWSPACK_PLUGINS_CPT,
'post_type' => Newspack_Popups::NEWSPACK_POPUPS_CPT,
'posts_per_page' => 1,
'post_status' => 'publish',
'category__in' => array_column( $post_categories, 'term_id' ),
'meta_key' => 'placement',
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
'meta_value' => 'inline',
'meta_compare' => '!=',
'meta_value' => self::$overlay_placements,
'meta_compare' => 'IN',
];

$popups = self::retrieve_popups_with_query( new WP_Query( $args ) );
Expand Down Expand Up @@ -293,7 +309,7 @@ public static function retrieve_preview_popup( $post_id ) {
*/
public static function retrieve_popup_by_id( $post_id, $include_drafts = false ) {
$args = [
'post_type' => Newspack_Popups::NEWSPACK_PLUGINS_CPT,
'post_type' => Newspack_Popups::NEWSPACK_POPUPS_CPT,
'posts_per_page' => 1,
'p' => $post_id,
];
Expand Down Expand Up @@ -386,18 +402,21 @@ public static function create_popup_object( $campaign_post, $include_categories
return $popup;
}

switch ( $popup['options']['trigger_type'] ) {
case 'scroll':
$popup['options']['trigger_delay'] = 0;
break;
case 'time':
default:
$popup['options']['trigger_scroll_progress'] = 0;
break;
};
if ( ! in_array( $popup['options']['placement'], [ 'top', 'bottom' ], true ) ) {
$popup['options']['placement'] = 'center';
if ( self::is_overlay( $popup ) ) {
switch ( $popup['options']['trigger_type'] ) {
case 'scroll':
$popup['options']['trigger_delay'] = 0;
break;
case 'time':
default:
$popup['options']['trigger_scroll_progress'] = 0;
break;
};
if ( ! in_array( $popup['options']['placement'], [ 'top', 'bottom' ], true ) ) {
$popup['options']['placement'] = 'center';
}
}

return $popup;
}

Expand Down Expand Up @@ -438,9 +457,51 @@ protected static function get_delay( $popup ) {
* @return boolean True if it is an inline popup.
*/
public static function is_inline( $popup ) {
if ( ! isset( $popup['options'], $popup['options']['placement'] ) ) {
return false;
}
return 'inline' === $popup['options']['placement'];
}

/**
* Get popups which should be inserted above page header.
*
* @param object $popup The popup object.
* @return boolean True if the popup should be inserted above page header.
*/
public static function should_be_inserted_above_page_header( $popup ) {
if ( self::is_inline( $popup ) ) {
return 'above_header' === $popup['options']['placement'];
} else {
// Insert time-triggered overlay popups above the header, this way they will be
// visible before scrolling below the fold.
return 'time' === $popup['options']['trigger_type'];
}
}

/**
* Get popups which should be inserted in page content.
*
* @param object $popup The popup object.
* @return boolean True if the popup should be inserted in page content.
*/
public static function should_be_inserted_in_page_content( $popup ) {
return self::should_be_inserted_above_page_header( $popup ) === false;
}

/**
* Is it an overlay popup or not.
*
* @param object $popup The popup object.
* @return boolean True if it is an overlay popup.
*/
public static function is_overlay( $popup ) {
if ( ! isset( $popup['options'], $popup['options']['placement'] ) ) {
return false;
}
return in_array( $popup['options']['placement'], self::$overlay_placements, true );
}

/**
* Does the popup have newsletter prompt?
*
Expand Down Expand Up @@ -557,7 +618,7 @@ protected static function get_analytics_events( $popup, $body, $element_id ) {

$has_link = preg_match( '/<a\s/', $body ) !== 0;
$has_form = preg_match( '/<form\s/', $body ) !== 0;
$has_dismiss_form = 'inline' !== $popup['options']['placement'];
$has_dismiss_form = self::is_overlay( $popup );
$has_not_interested_form = self::get_dismiss_text( $popup );

$analytics_events = [
Expand Down Expand Up @@ -735,8 +796,7 @@ function ( $evts ) use ( $analytics_events ) {
* @return string The generated markup.
*/
public static function generate_popup( $popup ) {

if ( isset( $popup['options'], $popup['options']['placement'] ) && 'inline' === $popup['options']['placement'] ) {
if ( ! self::is_overlay( $popup ) ) {
return self::generate_inline_popup( $popup );
}

Expand Down
4 changes: 2 additions & 2 deletions includes/class-newspack-popups-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static function init() {
*/
public static function add_plugin_page() {
add_submenu_page(
'edit.php?post_type=' . Newspack_Popups::NEWSPACK_PLUGINS_CPT,
'edit.php?post_type=' . Newspack_Popups::NEWSPACK_POPUPS_CPT,
__( 'Campaigns Settings', 'newspack-popups' ),
__( 'Settings', 'newspack-popups' ),
'manage_options',
Expand Down Expand Up @@ -137,7 +137,7 @@ public static function is_non_interactive() {
public static function admin_enqueue_scripts() {
$screen = get_current_screen();

if ( Newspack_Popups::NEWSPACK_PLUGINS_CPT . '_page_' . self::NEWSPACK_POPUPS_SETTINGS_PAGE !== $screen->base ) {
if ( Newspack_Popups::NEWSPACK_POPUPS_CPT . '_page_' . self::NEWSPACK_POPUPS_SETTINGS_PAGE !== $screen->base ) {
return;
}

Expand Down
Loading

0 comments on commit 20cb428

Please sign in to comment.