Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable public newsletter posts #272

Merged
merged 20 commits into from
Aug 18, 2020
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8bd193f
feat: enable public newsletter rewrites
dkoo Jul 20, 2020
af8c5c5
feat: editor sidebar UI for toggling public meta option
dkoo Jul 20, 2020
7952fbd
fix: better hook for disabling autosave on published newsletters
dkoo Jul 20, 2020
d37761f
fix: remove unnecessary args for admin_enqueue_scripts hook
dkoo Jul 20, 2020
bd7477f
Merge branch 'master' into add/allow-public-newsletter-posts
dkoo Aug 11, 2020
78ab685
fix: fatal from using transition_post_status instead of publish hook
dkoo Aug 11, 2020
af3dc0c
feat: enable archive pages for newsletters with public posts only
dkoo Aug 12, 2020
5acafbe
feat: disable Newspack Campaigns on Newsletter CPTs
dkoo Aug 12, 2020
7abc67d
feat: set page title to "Page not found" for non-public newsletters
dkoo Aug 12, 2020
ab78785
fix: move wpseo_title filter
dkoo Aug 12, 2020
367b9fd
Merge branch 'master' of https://github.com/Automattic/newspack-newsl…
dkoo Aug 12, 2020
1d9997b
fix: check for publish status in CC and Mailchimp
dkoo Aug 12, 2020
ce05d0c
feat: disable Jetpack Related Posts module on newsletter posts
dkoo Aug 12, 2020
96c89ea
Merge branch 'master' of https://github.com/Automattic/newspack-newsl…
dkoo Aug 13, 2020
91b596c
feat: allow Posts Inserter block to be rendered on front-end
dkoo Aug 13, 2020
89cf0b7
chore: restore private status of render_mjml_component method
dkoo Aug 13, 2020
82b31e9
chore: add @return statement to docblock
dkoo Aug 13, 2020
6815be4
fix: feedback from PR
dkoo Aug 14, 2020
c15f2e6
fix: send button behavior after newsletter has been sent
dkoo Aug 14, 2020
cbaa4d3
feat: add settings option to enable/disable Jetpack Related Posts
dkoo Aug 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 171 additions & 10 deletions includes/class-newspack-newsletters.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,15 @@ public static function instance() {
public function __construct() {
add_action( 'init', [ __CLASS__, 'register_cpt' ] );
add_action( 'init', [ __CLASS__, 'register_meta' ] );
add_action( 'init', [ __CLASS__, 'register_blocks' ] );
add_action( 'rest_api_init', [ __CLASS__, 'rest_api_init' ] );
add_action( 'default_title', [ __CLASS__, 'default_title' ], 10, 2 );
add_filter( 'display_post_states', [ __CLASS__, 'display_post_states' ], 10, 2 );
add_action( 'pre_get_posts', [ __CLASS__, 'maybe_display_public_archive_posts' ] );
add_action( 'template_redirect', [ __CLASS__, 'maybe_display_public_post' ] );
add_filter( 'post_row_actions', [ __CLASS__, 'display_view_or_preview_link_in_admin' ] );
add_filter( 'newspack_newsletters_assess_has_disabled_popups', [ __CLASS__, 'disable_campaigns_for_newsletters' ], 11 );
add_filter( 'jetpack_relatedposts_filter_options', [ __CLASS__, 'disable_jetpack_related_posts' ] );
add_action( 'save_post_' . self::NEWSPACK_NEWSLETTERS_CPT, [ $this, 'save' ], 10, 3 );

self::set_service_provider( self::service_provider() );
Expand Down Expand Up @@ -201,6 +207,17 @@ public static function register_meta() {
'auth_callback' => '__return_true',
]
);
\register_meta(
'post',
'is_public',
[
'object_subtype' => self::NEWSPACK_NEWSLETTERS_CPT,
'show_in_rest' => true,
'type' => 'boolean',
'single' => true,
'auth_callback' => '__return_true',
]
);
}

/**
Expand All @@ -221,9 +238,6 @@ public function save( $post_id, $post, $update ) {
* Register the custom post type.
*/
public static function register_cpt() {
if ( ! current_user_can( 'edit_others_posts' ) ) {
return;
}
$labels = [
'name' => _x( 'Newsletters', 'post type general name', 'newspack-newsletters' ),
'singular_name' => _x( 'Newsletter', 'post type singular name', 'newspack-newsletters' ),
Expand All @@ -242,17 +256,53 @@ public static function register_cpt() {
];

$cpt_args = [
'labels' => $labels,
'public' => false,
'show_ui' => true,
'show_in_rest' => true,
'supports' => [ 'editor', 'title', 'custom-fields' ],
'taxonomies' => [],
'menu_icon' => 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0Ij48cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMGg1di0yaC01Yy00LjM0IDAtOC0zLjY2LTgtOHMzLjY2LTggOC04IDggMy42NiA4IDh2MS40M2MwIC43OS0uNzEgMS41Ny0xLjUgMS41N3MtMS41LS43OC0xLjUtMS41N1YxMmMwLTIuNzYtMi4yNC01LTUtNXMtNSAyLjI0LTUgNSAyLjI0IDUgNSA1YzEuMzggMCAyLjY0LS41NiAzLjU0LTEuNDcuNjUuODkgMS43NyAxLjQ3IDIuOTYgMS40NyAxLjk3IDAgMy41LTEuNiAzLjUtMy41N1YxMmMwLTUuNTItNC40OC0xMC0xMC0xMHptMCAxM2MtMS42NiAwLTMtMS4zNC0zLTNzMS4zNC0zIDMtMyAzIDEuMzQgMyAzLTEuMzQgMy0zIDN6IiBmaWxsPSJ3aGl0ZSIvPjwvc3ZnPgo=',
'has_archive' => true,
'labels' => $labels,
'public' => true,
'public_queryable' => true,
'query_var' => true,
'rewrite' => [ 'slug' => 'newsletter' ],
'show_ui' => true,
'show_in_rest' => true,
'supports' => [ 'editor', 'title', 'custom-fields' ],
'taxonomies' => [],
'menu_icon' => 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0Ij48cGF0aCBkPSJNMTIgMkM2LjQ4IDIgMiA2LjQ4IDIgMTJzNC40OCAxMCAxMCAxMGg1di0yaC01Yy00LjM0IDAtOC0zLjY2LTgtOHMzLjY2LTggOC04IDggMy42NiA4IDh2MS40M2MwIC43OS0uNzEgMS41Ny0xLjUgMS41N3MtMS41LS43OC0xLjUtMS41N1YxMmMwLTIuNzYtMi4yNC01LTUtNXMtNSAyLjI0LTUgNSAyLjI0IDUgNSA1YzEuMzggMCAyLjY0LS41NiAzLjU0LTEuNDcuNjUuODkgMS43NyAxLjQ3IDIuOTYgMS40NyAxLjk3IDAgMy41LTEuNiAzLjUtMy41N1YxMmMwLTUuNTItNC40OC0xMC0xMC0xMHptMCAxM2MtMS42NiAwLTMtMS4zNC0zLTNzMS4zNC0zIDMtMyAzIDEuMzQgMyAzLTEuMzQgMy0zIDN6IiBmaWxsPSJ3aGl0ZSIvPjwvc3ZnPgo=',
];
\register_post_type( self::NEWSPACK_NEWSLETTERS_CPT, $cpt_args );
}

/**
* Register blocks server-side for front-end rendering.
*/
public static function register_blocks() {
register_block_type(
'newspack-newsletters/posts-inserter',
[
'render_callback' => [ __CLASS__, 'render_posts_inserter_block' ],
]
);
}

/**
* Server-side render callback for Posts Inserter block.
*
* @param array $attributes Block attributes.
* @return string HTML of block content to render.
*/
public static function render_posts_inserter_block( $attributes ) {
$markup = '';

if ( empty( $attributes['innerBlocksToInsert'] ) || ! is_array( $attributes['innerBlocksToInsert'] ) ) {
return $markup;
}

foreach ( $attributes['innerBlocksToInsert'] as $inner_block ) {
$markup .= $inner_block['innerHTML'];
}

return wp_kses_post( $markup );
}

/**
* Filter post states in admin posts list.
*
Expand All @@ -267,6 +317,7 @@ public static function display_post_states( $post_states, $post ) {

$post_status = get_post_status_object( $post->post_status );
$is_sent = 'publish' === $post_status->name;
$is_public = get_post_meta( $post->ID, 'is_public', true );

if ( $is_sent ) {
$sent_date = get_the_time( 'U', $post );
Expand All @@ -281,11 +332,121 @@ public static function display_post_states( $post_states, $post ) {
/* translators: Absolute time stamp of sent/published date */
$post_states[ $post_status->name ] = sprintf( __( 'Sent %1$s', 'newspack-newsletters' ), get_the_time( get_option( 'date_format' ), $post ) );
}

if ( $is_public ) {
$post_states[ $post_status->name ] .= __( ' | Published as a post', 'newspack-newsletters' );
}
}

return $post_states;
}

/**
* Filter out non-public newsletter posts on newsletter archive pages.
*
* @param array $query The WP query object.
*/
public static function maybe_display_public_archive_posts( $query ) {
if ( is_admin() || ! $query->is_main_query() || ! is_post_type_archive( self::NEWSPACK_NEWSLETTERS_CPT ) ) {
return;
}

$meta_query = $query->get( 'meta_query' );

if ( empty( $meta_query ) || ! is_array( $meta_query ) ) {
$meta_query = [];
}

$meta_query[] = [
'key' => 'is_public',
'value' => '1',
'meta_compare' => '=',
];

$query->set( 'meta_query', $meta_query );
}

/**
* Decide whether this newsletter should be publicly viewable as a post.
* Triggers a 404 if the current page is a single Newsletter and not marked public.
*/
public static function maybe_display_public_post() {
if (
current_user_can( 'edit_others_posts' ) ||
! is_singular( self::NEWSPACK_NEWSLETTERS_CPT )
) {
return;
}

$is_public = get_post_meta( get_the_ID(), 'is_public', true );

// If not marked public, make it a 404 to non-logged-in users.
if ( empty( $is_public ) ) {
global $wp_query;

// Replace document title with 'Page not found'.
add_filter(
'wpseo_title',
function( $title ) {
return str_replace( get_the_title(), __( 'Page not found', 'newspack-newsletters' ), $title );
}
);

status_header( 404 );
nocache_headers();
include get_query_template( '404' );
die();
}
}

/**
* Make "View" links say "Preview" if the newsletter is not marked as public.
*
* @param array $actions Array of action links to be shown in admin posts list.
* @return array Filtered array of action links.
*/
public static function display_view_or_preview_link_in_admin( $actions ) {
if ( 'publish' !== get_post_status() || self::NEWSPACK_NEWSLETTERS_CPT !== get_post_type() ) {
return $actions;
}

$is_public = get_post_meta( get_the_ID(), 'is_public', true );

if ( empty( $is_public ) && isset( $actions['view'] ) ) {
$actions['view'] = '<a href="' . esc_url( get_the_permalink() ) . '" rel="bookmark" aria-label="View ' . esc_attr( get_the_title() ) . '">Preview</a>';
}

return $actions;
}

/**
* Disable Newspack Campaigns on Newsletter posts.
*
* @param array $disabled Disabled status to filter.
* @return array|boolean Unfiltered disabled status, or true to disable.
*/
public static function disable_campaigns_for_newsletters( $disabled ) {
if ( self::NEWSPACK_NEWSLETTERS_CPT === get_post_type() ) {
return true;
}

return $disabled;
}

/**
* Disable Jetpack Related Posts on Newsletter posts.
adekbadek marked this conversation as resolved.
Show resolved Hide resolved
*
* @param array $options Options array for Jetpack Related Posts.
* @return array Filtered options array.
*/
public static function disable_jetpack_related_posts( $options ) {
if ( self::NEWSPACK_NEWSLETTERS_CPT === get_post_type() ) {
$options['enabled'] = false;
}

return $options;
}

/**
* Add newspack_popups_is_sitewide_default to Popup object.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function __construct() {
$this->controller = new Newspack_Newsletters_Constant_Contact_Controller( $this );

add_action( 'save_post_' . Newspack_Newsletters::NEWSPACK_NEWSLETTERS_CPT, [ $this, 'save' ], 10, 3 );
add_action( 'publish_' . Newspack_Newsletters::NEWSPACK_NEWSLETTERS_CPT, [ $this, 'send' ], 10, 2 );
add_action( 'transition_post_status_' . Newspack_Newsletters::NEWSPACK_NEWSLETTERS_CPT, [ $this, 'send' ], 10, 3 );
add_action( 'wp_trash_post', [ $this, 'trash' ], 10, 1 );

parent::__construct( $this );
Expand Down Expand Up @@ -374,45 +374,50 @@ public function save( $post_id, $post, $update ) {
/**
* Send a campaign.
*
* @param integer $post_id Post ID to send.
* @param string $new_status New status of the post.
* @param string $old_status Old status of the post.
* @param WP_POST $post Post to send.
*/
public function send( $post_id, $post ) {
public function send( $new_status, $old_status, $post ) {
$post_id = $post->ID;

if ( ! Newspack_Newsletters::validate_newsletter_id( $post_id ) ) {
return new WP_Error(
'newspack_newsletters_incorrect_post_type',
__( 'Post is not a Newsletter.', 'newspack-newsletters' )
);
}

try {
$sync_result = $this->sync( $post );
if ( 'publish' === $new_status && 'publish' !== $old_status ) {
adekbadek marked this conversation as resolved.
Show resolved Hide resolved
try {
$sync_result = $this->sync( $post );

if ( is_wp_error( $sync_result ) ) {
return $sync_result;
}

$cc_campaign_id = get_post_meta( $post_id, 'cc_campaign_id', true );
if ( ! $cc_campaign_id ) {
return new WP_Error(
'newspack_newsletters_no_campaign_id',
__( 'Constant Contact campaign ID not found.', 'newspack-newsletters' )
);
}
if ( is_wp_error( $sync_result ) ) {
return $sync_result;
}

$cc = new ConstantContact( $this->api_key() );
$schedule = new Schedule();
$cc_campaign_id = get_post_meta( $post_id, 'cc_campaign_id', true );
if ( ! $cc_campaign_id ) {
return new WP_Error(
'newspack_newsletters_no_campaign_id',
__( 'Constant Contact campaign ID not found.', 'newspack-newsletters' )
);
}

$cc->campaignScheduleService->addSchedule( $this->access_token(), $cc_campaign_id, $schedule ); //phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
} catch ( CtctException $e ) {
$wp_error = $this->manage_ctct_exception( $e );
$transient = sprintf( 'newspack_newsletters_error_%s_%s', $post->ID, get_current_user_id() );
set_transient( $transient, implode( ' ', $wp_error->get_error_messages() ), 45 );
return $wp_error;
} catch ( Exception $e ) {
$transient = sprintf( 'newspack_newsletters_error_%s_%s', $post->ID, get_current_user_id() );
set_transient( $transient, $e->getMessage(), 45 );
return;
$cc = new ConstantContact( $this->api_key() );
$schedule = new Schedule();

$cc->campaignScheduleService->addSchedule( $this->access_token(), $cc_campaign_id, $schedule ); //phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
} catch ( CtctException $e ) {
$wp_error = $this->manage_ctct_exception( $e );
$transient = sprintf( 'newspack_newsletters_error_%s_%s', $post->ID, get_current_user_id() );
set_transient( $transient, implode( ' ', $wp_error->get_error_messages() ), 45 );
return $wp_error;
} catch ( Exception $e ) {
$transient = sprintf( 'newspack_newsletters_error_%s_%s', $post->ID, get_current_user_id() );
set_transient( $transient, $e->getMessage(), 45 );
return;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ public function save( $post_id, $post, $update );
/**
* Send a campaign.
*
* @param integer $post_id Post ID to send.
* @param string $new_status New status of the post.
* @param string $old_status Old status of the post.
* @param \WP_POST $post Post to send.
*/
public function send( $post_id, $post );
public function send( $new_status, $old_status, $post );

/**
* After Newsletter post is deleted, clean up by deleting corresponding ESP campaign.
Expand Down
Loading