395 lines
13 KiB
PHP
395 lines
13 KiB
PHP
<?php
|
||
/**
|
||
* Gutenberg Blocks registration class.
|
||
*
|
||
* @since 1.9.10
|
||
*
|
||
* @package OMAPI
|
||
* @author Thomas Griffin
|
||
*/
|
||
|
||
// Exit if accessed directly.
|
||
if ( ! defined( 'ABSPATH' ) ) {
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Gutenberg Blocks registration class.
|
||
*
|
||
* @since 1.9.10
|
||
*/
|
||
class OMAPI_Blocks {
|
||
|
||
/**
|
||
* Holds the class object.
|
||
*
|
||
* @since 1.9.10
|
||
*
|
||
* @var object
|
||
*/
|
||
public static $instance;
|
||
|
||
/**
|
||
* Path to the file.
|
||
*
|
||
* @since 1.9.10
|
||
*
|
||
* @var string
|
||
*/
|
||
public $file = __FILE__;
|
||
|
||
/**
|
||
* Holds the base class object.
|
||
*
|
||
* @since 1.9.10
|
||
*
|
||
* @var object
|
||
*/
|
||
public $base;
|
||
|
||
/**
|
||
* The data to be localized for JS.
|
||
*
|
||
* @since 2.2.0
|
||
*
|
||
* @var array
|
||
*/
|
||
protected $data_for_js = array();
|
||
|
||
/**
|
||
* The campaign options list array.
|
||
*
|
||
* @var null|array
|
||
*/
|
||
protected static $campaigns_list = null;
|
||
|
||
/**
|
||
* Primary class constructor.
|
||
*
|
||
* @since 1.9.10
|
||
*/
|
||
public function __construct() {
|
||
// Set our object.
|
||
$this->set();
|
||
|
||
if ( function_exists( 'register_block_type' ) ) {
|
||
|
||
// Register our blocks.
|
||
$this->register_blocks();
|
||
|
||
add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ) );
|
||
|
||
// Register the global post campaign switch meta.
|
||
register_meta(
|
||
'post',
|
||
'om_disable_all_campaigns',
|
||
array(
|
||
'show_in_rest' => true,
|
||
'single' => true,
|
||
'type' => 'boolean',
|
||
)
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Sets our object instance and base class instance.
|
||
*
|
||
* @since 1.9.10
|
||
*/
|
||
public function set() {
|
||
self::$instance = $this;
|
||
$this->base = OMAPI::get_instance();
|
||
}
|
||
|
||
/**
|
||
* Register OptinMonster Gutenberg blocks on the backend.
|
||
*
|
||
* @since 1.9.10
|
||
*/
|
||
public function register_blocks() {
|
||
$use_blocks_json = version_compare( $GLOBALS['wp_version'], '5.8', '>=' );
|
||
$block_type = plugin_dir_path( OMAPI_FILE ) . 'assets/js/';
|
||
$args = array(
|
||
'render_callback' => array( $this, 'get_output' ),
|
||
);
|
||
|
||
if ( ! $use_blocks_json ) {
|
||
$block_type = 'optinmonster/campaign-selector';
|
||
$args['attributes'] = array(
|
||
'slug' => array(
|
||
'type' => 'string',
|
||
),
|
||
'followrules' => array(
|
||
'type' => 'boolean',
|
||
),
|
||
);
|
||
}
|
||
|
||
register_block_type( $block_type, $args );
|
||
}
|
||
|
||
/**
|
||
* Load OptinMonster Gutenberg block scripts.
|
||
*
|
||
* @since 1.9.10
|
||
*/
|
||
public function enqueue_block_editor_assets() {
|
||
global $pagenow;
|
||
|
||
$version = $this->base->asset_version();
|
||
$css_handle = $this->base->plugin_slug . '-blocks-admin';
|
||
wp_enqueue_style( $css_handle, $this->base->url . 'assets/dist/css/blocks-admin.min.css', array(), $version );
|
||
|
||
if ( function_exists( 'wp_add_inline_style' ) ) {
|
||
$data = get_post_type()
|
||
? get_post_type_object( get_post_type() )
|
||
: array();
|
||
|
||
$css = $this->base->get_min_css_view_contents( 'disable-warning-css.php', (object) $data );
|
||
wp_add_inline_style( $css_handle, $css );
|
||
}
|
||
|
||
$campaign_selector_handle = $this->base->plugin_slug . '-gutenberg-campaign-selector';
|
||
wp_enqueue_script(
|
||
$campaign_selector_handle,
|
||
$this->base->url . 'assets/dist/js/campaign-selector.min.js',
|
||
array( 'wp-blocks', 'wp-i18n', 'wp-element' ),
|
||
$version,
|
||
true
|
||
);
|
||
|
||
OMAPI_Utils::add_inline_script( $campaign_selector_handle, 'OMAPI', $this->get_data_for_js() );
|
||
|
||
$is_widgets_page = 'widgets.php' === $pagenow;
|
||
|
||
// Prevent enqueueing sidebar settings on widgets screen...
|
||
if ( ! $is_widgets_page && ! is_customize_preview() ) {
|
||
wp_enqueue_script(
|
||
$this->base->plugin_slug . '-gutenberg-sidebar-settings',
|
||
$this->base->url . 'assets/dist/js/om-settings.min.js',
|
||
array( $campaign_selector_handle, 'wp-plugins', 'wp-edit-post', 'wp-element' ),
|
||
$version
|
||
);
|
||
}
|
||
|
||
if ( version_compare( $GLOBALS['wp_version'], '5.3', '>=' ) ) {
|
||
wp_enqueue_script(
|
||
$this->base->plugin_slug . '-gutenberg-format-button',
|
||
$this->base->url . 'assets/dist/js/om-format.min.js',
|
||
array(
|
||
$campaign_selector_handle,
|
||
'wp-rich-text',
|
||
'wp-element',
|
||
$is_widgets_page && version_compare( $GLOBALS['wp_version'], '5.8.0', '>=' )
|
||
? 'wp-edit-widgets'
|
||
: 'wp-editor',
|
||
),
|
||
$version
|
||
);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Get OptinMonster data for Gutenberg JS.
|
||
*
|
||
* @since 2.2.0
|
||
*
|
||
* @param string $key The js data to get, by key.
|
||
*
|
||
* @return array Array of data for JS.
|
||
*/
|
||
public function get_data_for_js( $key = null ) {
|
||
if ( empty( $this->data_for_js ) ) {
|
||
|
||
// For translation of strings.
|
||
$i18n = array(
|
||
'title' => esc_html__( 'OptinMonster', 'optin-monster-api' ),
|
||
'description' => esc_html__( 'Select and display one of your OptinMonster inline campaigns.', 'optin-monster-api' ),
|
||
'campaign_select' => esc_html__( 'Select Campaign...', 'optin-monster-api' ),
|
||
'campaign_select_display' => esc_html__( 'Select and display your email marketing call-to-action campaigns from OptinMonster', 'optin-monster-api' ),
|
||
'create_new_popup' => esc_html__( 'Create New Popup Campaign', 'optin-monster-api' ),
|
||
'create_new_inline' => esc_html__( 'Create New Inline Campaign', 'optin-monster-api' ),
|
||
'block_settings' => esc_html__( 'OptinMonster Block Settings', 'optin-monster-api' ),
|
||
'settings' => esc_html__( 'OptinMonster Settings', 'optin-monster-api' ),
|
||
'campaign_selected' => esc_html__( 'Campaign', 'optin-monster-api' ),
|
||
'followrules_label' => esc_html__( 'Use Output Settings', 'optin-monster-api' ),
|
||
/* translators: %s - Output Settings (linked).*/
|
||
'followrules_help' => esc_html__( 'Ensure this campaign follows any conditions you\'ve selected in its %s', 'optin-monster-api' ),
|
||
'output_settings' => esc_html__( 'Output Settings', 'optin-monster-api' ),
|
||
'no_sites' => esc_html__( 'Please create a free account or connect an existing account to use an OptinMonster block.', 'optin-monster-api' ),
|
||
'no_sites_button_create_account' => esc_html__( 'Create a Free Account', 'optin-monster-api' ),
|
||
'no_sites_button_connect_account' => esc_html__( 'Connect an Existing Account', 'optin-monster-api' ),
|
||
'no_inline_campaigns' => esc_html__( 'You don’t have any inline campaigns yet!', 'optin-monster-api' ),
|
||
'no_campaigns_help' => esc_html__( 'Create an inline campaign to display in your posts and pages.', 'optin-monster-api' ),
|
||
'create_inline_campaign' => esc_html__( 'Create Your First Inline Campaign', 'optin-monster-api' ),
|
||
'create_popup_campaign' => esc_html__( 'Create Your First Popup', 'optin-monster-api' ),
|
||
'no_campaigns_button_help' => esc_html__( 'Learn how to create your first campaign', 'optin-monster-api' ),
|
||
'found_error' => esc_html__( 'An error was encountered', 'optin-monster-api' ),
|
||
'disable_all' => esc_html__( 'Disable all OptinMonster campaigns.', 'optin-monster-api' ),
|
||
'view_all' => esc_html__( 'View All Campaigns', 'optin-monster-api' ),
|
||
'not_connected' => esc_html__( 'You Have Not Connected with OptinMonster', 'optin-monster-api' ),
|
||
'no_campaigns_yet' => esc_html__( 'You don’t have any campaigns created yet.', 'optin-monster-api' ),
|
||
'update_selected_popup' => esc_html__( 'Update Selected OptinMonster Campaign', 'optin-monster-api' ),
|
||
'open_popup' => esc_html__( 'Open an OptinMonster Popup', 'optin-monster-api' ),
|
||
'remove_popup' => esc_html__( 'Remove Campaign Link', 'optin-monster-api' ),
|
||
'upgrade_monsterlink' => esc_html__( 'Unlock access to the OptinMonster click-to-load feature called MonsterLinks by upgrading your subscription.', 'optin-monster-api' ),
|
||
'upgrade' => esc_html__( 'Upgrade Now', 'optin-monster-api' ),
|
||
);
|
||
$i18n['description'] = html_entity_decode( $i18n['description'], ENT_COMPAT, 'UTF-8' );
|
||
|
||
$campaigns = $this->get_campaign_options();
|
||
$site_ids = $this->base->get_site_ids();
|
||
$post = get_post();
|
||
|
||
$this->data_for_js = array(
|
||
'logoUrl' => $this->base->url . 'assets/css/images/icons/archie-icon.svg',
|
||
'i18n' => $i18n,
|
||
'campaigns' => array(
|
||
'inline' => ! empty( $campaigns['inline'] ) ? $campaigns['inline'] : array(),
|
||
'other' => ! empty( $campaigns['other'] ) ? $campaigns['other'] : array(),
|
||
),
|
||
'site_ids' => ! empty( $site_ids ) ? $site_ids : array(),
|
||
'post' => $post,
|
||
'omEnv' => defined( 'OPTINMONSTER_ENV' ) ? OPTINMONSTER_ENV : '',
|
||
'canMonsterlink' => $this->base->has_rule_type( 'monster-link' ),
|
||
'templatesUri' => OMAPI_Urls::templates(),
|
||
'playbooksUri' => OMAPI_Urls::playbooks(),
|
||
'campaignsUri' => OMAPI_Urls::campaigns(),
|
||
'settingsUri' => OMAPI_Urls::settings(),
|
||
'wizardUri' => OMAPI_Urls::wizard(),
|
||
'upgradeUri' => OMAPI_Urls::upgrade( 'gutenberg', '--FEATURE--' ),
|
||
'apiUrl' => esc_url_raw( OPTINMONSTER_APIJS_URL ),
|
||
'omUserId' => $this->base->get_option( 'accountUserId' ),
|
||
'outputSettingsUrl' => OMAPI_Urls::campaign_output_settings( '%s' ),
|
||
'editUrl' => OMAPI_Urls::om_app(
|
||
'campaigns/--CAMPAIGN_SLUG--/edit/',
|
||
rawurlencode( OMAPI_Urls::campaign_output_settings( '--CAMPAIGN_SLUG--' ) )
|
||
),
|
||
'monsterlink' => esc_url_raw( OPTINMONSTER_SHAREABLE_LINK ) . '/c/',
|
||
'wpVersion' => $GLOBALS['wp_version'],
|
||
'customFieldsSupported' => post_type_supports( get_post_type( $post ), 'custom-fields' ),
|
||
'pluginUrl' => esc_url_raw( plugin_dir_url( dirname( __FILE__ ) ) ),
|
||
);
|
||
}
|
||
|
||
if ( $key ) {
|
||
return isset( $this->data_for_js[ $key ] ) ? $this->data_for_js[ $key ] : null;
|
||
}
|
||
|
||
return $this->data_for_js;
|
||
}
|
||
|
||
/**
|
||
* Does the user have any associated OM sites registered?
|
||
*
|
||
* @since 2.2.0
|
||
*
|
||
* @return boolean
|
||
*/
|
||
public function has_sites() {
|
||
$site_ids = $this->base->get_site_ids();
|
||
|
||
return ! empty( $site_ids );
|
||
}
|
||
|
||
/**
|
||
* Get campaign options.
|
||
*
|
||
* @since 2.2.0
|
||
*
|
||
* @param boolean $titles_only Whether to include titles only, or separate data as array.
|
||
*
|
||
* @return array Array of campaign options.
|
||
*/
|
||
public function get_campaign_options( $titles_only = false ) {
|
||
if ( null === self::$campaigns_list ) {
|
||
$campaigns_list = array(
|
||
'inline' => array(),
|
||
'other' => array(),
|
||
);
|
||
|
||
if ( $this->has_sites() ) {
|
||
$campaigns = $this->base->get_campaigns();
|
||
|
||
if ( ! empty( $campaigns ) ) {
|
||
foreach ( $campaigns as $campaign ) {
|
||
$title = mb_strlen( $campaign->post_title, 'UTF-8' ) > 100
|
||
? mb_substr( $campaign->post_title, 0, 97, 'UTF-8' ) . '...'
|
||
: $campaign->post_title;
|
||
$title .= ' (' . $campaign->post_name . ')';
|
||
|
||
$type = 'inline' === $campaign->campaign_type ? 'inline' : 'other';
|
||
|
||
$campaigns_list[ $type ][ $campaign->post_name ] = array(
|
||
'title' => $title,
|
||
'pending' => empty( $campaign->enabled ),
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
self::$campaigns_list = $campaigns_list;
|
||
}
|
||
|
||
if ( $titles_only && ! empty( self::$campaigns_list ) ) {
|
||
$list = array();
|
||
foreach ( self::$campaigns_list as $type => $type_list ) {
|
||
foreach ( $type_list as $campaign_name => $args ) {
|
||
$list[ $type ][ $campaign_name ] = $args['title'] . ( $args['pending'] ? ' [Pending]' : '' );
|
||
}
|
||
}
|
||
|
||
return $list;
|
||
}
|
||
|
||
return self::$campaigns_list;
|
||
}
|
||
|
||
/**
|
||
* Get form HTML to display in a OptinMonster Gutenberg block.
|
||
*
|
||
* @param array $atts Attributes passed by OptinMonster Gutenberg block.
|
||
*
|
||
* @since 1.9.10
|
||
*
|
||
* @return string
|
||
*/
|
||
public function get_output( $atts ) {
|
||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||
$context = ! empty( $_REQUEST['context'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['context'] ) ) : '';
|
||
$is_rest = defined( 'REST_REQUEST' ) && REST_REQUEST;
|
||
$is_gutes = $is_rest && 'edit' === $context;
|
||
|
||
// Our Guten-block handles the embed output manually.
|
||
if ( $is_gutes ) {
|
||
return;
|
||
}
|
||
|
||
// Unslash and sanitize the shortcode attributes.
|
||
$atts = array_map( 'sanitize_text_field', wp_unslash( $atts ) );
|
||
|
||
// Gutenberg block shortcodes default to following the rules.
|
||
// See assets/js/campaign-selector.js, attributes.followrules.
|
||
if ( ! isset( $atts['followrules'] ) ) {
|
||
$atts['followrules'] = true;
|
||
}
|
||
$atts['followrules'] = wp_validate_boolean( $atts['followrules'] );
|
||
|
||
$output = $this->base->shortcode->shortcode( $atts );
|
||
|
||
if (
|
||
! empty( $output )
|
||
&& ! wp_script_is( $this->base->plugin_slug . '-api-script', 'enqueued' )
|
||
) {
|
||
|
||
// Need to enqueue the base api script.
|
||
$this->base->output->api_script();
|
||
}
|
||
|
||
// Just return the shortcode output to the frontend.
|
||
return $output;
|
||
}
|
||
|
||
}
|