plugin_name = $plugin_name;
$this->version = $version;
$this->loader = $loader;
$this->settings = $this->get_settings();
$this->loader->add_action( 'save_post', $this, 'record_first_model', 20, 2 );
$this->loader->add_action( 'admin_notices', $this, 'show_review_notice' );
$this->loader->add_action( 'admin_post_threedvieweronline_review', $this, 'handle_review_choice' );
$this->loader->add_action( 'wp_ajax_threedvieweronline_review', $this, 'handle_review_choice' );
}
/**
* Register the JavaScript & CSS for the admin area.
*
* @since 1.0.0
*/
/** Return whether this content has a configured model, without loading it. */
private function has_configured_model( $post ) {
if ( 'product' === $post->post_type && '' !== threedvieweronline_url( get_post_meta( $post->ID, 'threed_model_url', true ) ) ) {
return true;
}
$pending = parse_blocks( $post->post_content );
while ( $pending ) {
$block = array_pop( $pending );
if ( 'dvieweronline/dvieweronline-iframe' === $block['blockName'] && '' !== threedvieweronline_url( $block['attrs']['iframeSrc'] ?? '' ) ) {
return true;
}
foreach ( $block['innerBlocks'] ?? array() as $child ) {
$pending[] = $child;
}
}
if ( preg_match_all( '/' . get_shortcode_regex( array( '3Dvo-model' ) ) . '/s', $post->post_content, $matches, PREG_SET_ORDER ) ) {
foreach ( $matches as $match ) {
if ( '[' === $match[1] && ']' === $match[6] ) {
continue; // Escaped shortcode, displayed as text.
}
$atts = shortcode_parse_atts( $match[3] );
if ( is_array( $atts ) && '' !== threedvieweronline_url( $atts['url'] ?? '' ) ) {
return true;
}
}
}
return false;
}
/** Start the clock only after published content is configured. */
public function record_first_model( $post_id, $post ) {
if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ||
! in_array( $post->post_type, array( 'product', 'page', 'post' ), true ) || 'publish' !== $post->post_status ) {
return;
}
if ( $this->has_configured_model( $post ) ) {
add_option( 'threedvieweronline_first_model', time(), '', false );
update_option( 'threedvieweronline_review_post', $post_id, false );
}
}
/** Local, per-administrator choices; no tracking request is sent. */
public function handle_review_choice() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__( 'You do not have permission to do this.', '3dvieweronline-wp' ) );
}
if ( wp_doing_ajax() ) {
check_ajax_referer( 'threedvieweronline_review', '_wpnonce' );
} else {
check_admin_referer( 'threedvieweronline_review' );
}
$choice = isset( $_POST['choice'] ) && is_string( $_POST['choice'] ) ? sanitize_key( wp_unslash( $_POST['choice'] ) ) : '';
if ( ! in_array( $choice, array( 'review', 'later', 'dismiss' ), true ) ) {
wp_die( esc_html__( 'Invalid review choice.', '3dvieweronline-wp' ) );
}
update_user_meta( get_current_user_id(), 'threedvieweronline_review_after', 'later' === $choice ? time() + 30 * DAY_IN_SECONDS : -1 );
if ( wp_doing_ajax() ) {
wp_send_json_success();
}
wp_safe_redirect( admin_url( 'admin.php?page=threed-setting' ) );
exit;
}
public function show_review_notice() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$screen = get_current_screen();
if ( ! $screen || ( 'toplevel_page_threed-setting' !== $screen->id &&
( 'post' !== $screen->base || ! in_array( $screen->post_type, array( 'product', 'page', 'post' ), true ) ) ) ) {
return;
}
$first = (int) get_option( 'threedvieweronline_first_model', 0 );
$after = (int) get_user_meta( get_current_user_id(), 'threedvieweronline_review_after', true );
$post = get_post( (int) get_option( 'threedvieweronline_review_post', 0 ) );
if ( ! $first || time() < $first + DAY_IN_SECONDS || -1 === $after || time() < $after ||
! $post || 'publish' !== $post->post_status || ! $this->has_configured_model( $post ) ) {
return;
}
if ( 'toplevel_page_threed-setting' !== $screen->id ) {
$current = get_post();
if ( ! $current || ! $this->has_configured_model( $current ) ) {
return;
}
}
?>
base && in_array( $screen->post_type, array( 'page', 'post' ), true ) ) {
wp_enqueue_script( $this->plugin_name . '-common-js', plugins_url( '/admin/js/threedvieweronline-common-admin.js', THREED_PLUGIN_FILE ), array( 'jquery' ), $this->version, true );
wp_enqueue_style( $this->plugin_name . '-common-style', plugins_url( '/admin/css/threedvieweronline-common-admin.css', THREED_PLUGIN_FILE ), array(), $this->version );
}
if ( ! $screen || ( 'product' !== $screen->post_type && 'toplevel_page_threed-setting' !== $screen->id ) ) {
return;
}
wp_enqueue_script( $this->plugin_name . '-common-js', plugins_url( '/admin/js/threedvieweronline-common-admin.js', THREED_PLUGIN_FILE ), array( 'jquery' ), $this->version, true );
wp_enqueue_style( $this->plugin_name . '-common-style', plugins_url( '/admin/css/threedvieweronline-common-admin.css', THREED_PLUGIN_FILE ), array(), $this->version );
if ( 'toplevel_page_threed-setting' === $screen->id ) {
$this->enqueue_styles();
$this->enqueue_scripts();
}
}
/**
* Enque the styles.
*
* @since 1.0.0
*/
public function enqueue_styles() {
wp_enqueue_style( $this->plugin_name . '-font-awesome', plugins_url( '/admin/css/font-awesome/css/font-awesome.min.css', THREED_PLUGIN_FILE ), array(), $this->version, 'all' );
wp_enqueue_style( $this->plugin_name, plugins_url( '/admin/css/threedvieweronline-iframe-admin.css', THREED_PLUGIN_FILE ), array(), $this->version, 'all' );
}
/**
* Enque the scripts.
*
* @since 1.0.0
*/
public function enqueue_scripts() {
wp_enqueue_media();
wp_enqueue_script( $this->plugin_name, plugins_url( '/admin/js/threedvieweronline-iframe-admin.js', THREED_PLUGIN_FILE ), array( 'jquery' ), $this->version, false );
}
/**
* Enquees block assets.
*
* @since 1.0.0
*/
public function register_blocks() {
wp_register_script( $this->plugin_name . '-blocks', plugins_url( '/dist/blocks.build.js', THREED_PLUGIN_FILE ), array( 'wp-blocks', 'wp-i18n', 'wp-element', 'wp-block-editor', 'wp-components' ), $this->version, true );
wp_set_script_translations( $this->plugin_name . '-blocks', '3dvieweronline-wp', THREED_PLUGIN_DIR . '/languages' );
wp_register_style( $this->plugin_name . '-blocks-style', plugins_url( '/dist/blocks.style.build.css', THREED_PLUGIN_FILE ), array(), $this->version );
wp_register_style( $this->plugin_name . '-editor', plugins_url( '/dist/blocks.editor.build.css', THREED_PLUGIN_FILE ), array(), $this->version );
register_block_type( THREED_PLUGIN_DIR . '/blocks/iframe' );
register_block_type( THREED_PLUGIN_DIR . '/blocks/product', array( 'render_callback' => array( $this, 'render_product_block' ) ) );
}
public function render_product_block( $attributes, $content, $block ) {
if ( ! function_exists( 'wc_get_product' ) ) {
return '';
}
$post_id = ! empty( $block->context['postId'] ) ? absint( $block->context['postId'] ) : get_the_ID();
$product = wc_get_product( $post_id );
if ( ! $product ) {
return '';
}
$html = threedvieweronline_iframe( get_post_meta( $product->get_id(), 'threed_model_url', true ), array(
'width' => get_post_meta( $product->get_id(), 'threed_piframe_width', true ),
'height' => get_post_meta( $product->get_id(), 'threed_piframe_height', true ),
) );
return '' !== $html ? '' . $html . '
' : '';
}
/**
* Register the tinymce button
*
* @since 1.0.0
*/
public function threed_add_my_custom_tinymce_button() {
global $typenow;
if ( ! in_array( $typenow, array( 'product' ), true ) ) {
return;
}
if ( 'true' === get_user_option( 'rich_editing' ) ) {
add_filter( 'mce_external_plugins', array( $this, 'threed_mce_external_plugins_callack' ) );
add_filter( 'mce_buttons', array( $this, 'threed_mce_buttons_callack' ) );
}
}
/**
* Add Tinymce plugin file.
*
* @param array $plugin_array Contains tiymce plugin files paths.
* @since 1.0.0
*/
public function threed_mce_external_plugins_callack( $plugin_array ) {
$plugin_array['threed_mce_button1'] = plugins_url( '/admin/js/threed-mce-button1.js', THREED_PLUGIN_FILE );
return $plugin_array;
}
/**
* Add Tinymce button.
*
* @param array $buttons Contains tiymce buttons.
* @since 1.0.0
*/
public function threed_mce_buttons_callack( $buttons ) {
array_push( $buttons, 'threed_mce_button1' );
return $buttons;
}
/**
* Register the product meta boxes
*
* @param array $post_type contains postype slug.
* @since 1.0.0
*/
public function threed_product_register_meta_boxes( $post_type ) {
if ( 'product' === $post_type ) {
add_meta_box( 'threed-viewer-online', __( '3D Viewer Online', '3dvieweronline-wp' ), array( $this, 'threed_product_meta_box_callback' ), 'product' );
}
}
/**
* Meta Box callback prints the html
*
* @param WP_Post $post contains cuurent post object.
* @since 1.0.0
*/
public function threed_product_meta_box_callback( $post ) {
if ( 'product' === $post->post_type ) {
// Add an nonce field so we can check for it later.
wp_nonce_field( 'threed_viewer_online', 'threed_viewer_online_nonce' );
// Use get_post_meta to retrieve an existing value from the database.
$value = get_post_meta( $post->ID, 'threed_model_url', true );
$piwidth = get_post_meta( $post->ID, 'threed_piframe_width', true );
$piheight = get_post_meta( $post->ID, 'threed_piframe_height', true );
// Display the form, using the current value.
?>
settings['threed_iframe_width'] ) && '' !== $this->settings['threed_iframe_width'] ) {
$piwidth = $this->settings['threed_iframe_width'];
} else {
$piwidth = '100%';
}
}
if ( '' === $piheight ) {
if ( isset( $this->settings['threed_iframe_height'] ) && '' !== $this->settings['threed_iframe_height'] ) {
$piheight = $this->settings['threed_iframe_height'];
} else {
$piheight = '500px';
}
}
$pos = strpos( $piwidth, '%' );
if ( false === $pos ) {
$pos1 = strpos( $piwidth, 'px' );
if ( false === $pos1 ) {
$piwidth = $piwidth . 'px';
}
}
$pos = strpos( $piheight, '%' );
if ( false === $pos ) {
$pos1 = strpos( $piheight, 'px' );
if ( false === $pos1 ) {
$piheight = $piheight . 'px';
}
}
if ( '' !== $value ) {
echo wp_kses(
threedvieweronline_iframe( $value, array( 'width' => $piwidth, 'height' => $piheight, 'lazy' => false ) ),
array( 'iframe' => array( 'class' => true, 'id' => true, 'src' => true, 'title' => true, 'style' => true, 'loading' => true, 'allowfullscreen' => true ) )
);
}
?>
'' . esc_html__( 'Settings', '3dvieweronline-wp' ) . '',
);
return array_merge( $action_links, $links );
}
/**
* Show row meta on the plugin screen.
*
* @param mixed $links Plugin Row Meta.
* @param mixed $file Plugin Base file.
*
* @return array
*/
public static function plugin_row_meta( $links, $file ) {
if ( THREED_PLUGIN_BASENAME === $file ) {
$row_meta = array(
'youraccount' => '' . esc_html__( 'Your account', '3dvieweronline-wp' ) . '',
'howtousetheplugin' => '' . esc_html__( 'Get help', '3dvieweronline-wp' ) . '',
'contactus' => '' . esc_html__( 'Contact us', '3dvieweronline-wp' ) . '',
);
return array_merge( $links, $row_meta );
}
return (array) $links;
}
/**
* Register the plugin settings link.
*
* @since 1.0.0
*/
public function admin_menu() {
$settings_page = add_menu_page(
'3D Viewer Online WordPress Plugin',
'3D Viewer Online',
'manage_options',
'threed-setting',
array( $this, 'output' ),
plugins_url( 'assets/images/icon.png', THREED_PLUGIN_FILE ),
'80'
);
add_action( 'load-' . $settings_page, array( $this, 'settings_page_init' ) );
}
/**
* Retrieve all display on page options.
*
* @since 1.0.0
*/
public function getDisplayIframeOptions() {
return array(
'after-product-title' => 'After product title',
'after-product-short-description' => 'After product short description',
'after-add-to-cart-button' => 'After add to cart button',
);
}
/**
* Retrieve the settings of the plugin.
*
* @since 1.0.0
* @return array The settings of the plugin.
*/
public function get_settings() {
$settings = get_option( 'settings-threed-iframe', array() );
return $this->settings = is_array( $settings ) ? $settings : array();
}
/**
* Retrieve the setting value.
*
* @since 1.0.0
* @return array The settings of the plugin.
*/
public function getSettingValue( $setting ) {
if ( isset( $this->settings[ $setting ] ) ) {
return $this->settings[ $setting ];
}
return '';
}
/**
* Add a update message for settings.
*
* @since 1.0.0
* @access public
* @var string $message update Message.
*/
public function add_message( $message ) {
$this->messages[] = $message;
}
/**
* Add a error message for settings.
*
* @since 1.0.0
* @access public
* @var string $error error Message.
*/
public function add_error( $error ) {
$this->errors[] = $error;
}
/**
* Retrieve the messages + errors of the plugin.
*
* @since 1.0.0
*/
public function show_messages() {
$returndata = '';
if ( count( $this->errors ) > 0 ) {
foreach ( $this->errors as $error ) {
$returndata .= '' . esc_html( $error ) . '
';
}
} elseif ( count( $this->messages ) > 0 ) {
foreach ( $this->messages as $message ) {
$returndata .= '' . esc_html( $message ) . '
';
}
}
return $returndata;
}
/**
* Init method for setting page.
*
* @since 1.0.0
*/
public function settings_page_init() {
// Save settings if data has been posted.
if ( ! empty( $_POST['threed-save'] ) ) {
// Check if nonce is set.
if ( ! current_user_can( 'manage_options' ) || ! isset( $_POST['_wpnonce'] ) || ! is_string( $_POST['_wpnonce'] ) ) {
return false;
}
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'threed_viewer_settings' ) ) {
return false;
}
$this->save();
}
}
/**
* Retrieve Settings form.
* Handles the display of the main settings page in admin.
*
* @since 1.0.0
*/
public function output() {
$this->show_setup_guide();
require_once THREED_PLUGIN_DIR . '/admin/partials/threedvieweronline-iframe-admin-display.php';
}
/**
* Save the settings.
* Handles the save & update settings in database.
*
* @since 1.0.0
*/
public function save() {
// Check if nonce is set.
if ( ! current_user_can( 'manage_options' ) || ! isset( $_POST['_wpnonce'] ) || ! is_string( $_POST['_wpnonce'] ) ) {
return false;
}
// Verify the nonce.
if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'threed_viewer_settings' ) ) {
return false;
}
foreach ( array( 'threed_enable_product_tab', 'threed_enable_product_icon', 'threed_tab_title', 'threed_icon_display', 'threed_icon' ) as $field ) {
if ( isset( $_POST[ $field ] ) && ! is_string( $_POST[ $field ] ) ) {
return false;
}
}
if ( ! $this->validation( $_POST ) ) {
return false;
}
$settings = $this->get_settings();
$settings['threed_enable_product_tab'] = isset( $_POST['threed_enable_product_tab'] ) && 'on' === $_POST['threed_enable_product_tab'] ? 'on' : 'off';
$settings['threed_enable_product_icon'] = isset( $_POST['threed_enable_product_icon'] ) && 'on' === $_POST['threed_enable_product_icon'] ? 'on' : 'off';
$settings['threed_tab_title'] = isset( $_POST['threed_tab_title'] ) ? sanitize_text_field( wp_unslash( $_POST['threed_tab_title'] ) ) : '';
$threed_icon_display = isset( $_POST['threed_icon_display'] ) ? sanitize_key( wp_unslash( $_POST['threed_icon_display'] ) ) : '';
$settings['threed_icon_display'] = array_key_exists( $threed_icon_display, $this->getDisplayIframeOptions() ) ? $threed_icon_display : 'after-product-title';
$settings['threed_icon'] = isset( $_POST['threed_icon'] ) ? esc_url_raw( wp_unslash( $_POST['threed_icon'] ), array( 'http', 'https' ) ) : '';
$settings['threed_iframe_width'] = threedvieweronline_dimension( isset( $settings['threed_iframe_width'] ) ? $settings['threed_iframe_width'] : '', '100%' );
$settings['threed_iframe_height'] = threedvieweronline_dimension( isset( $settings['threed_iframe_height'] ) ? $settings['threed_iframe_height'] : '', '500px' );
update_option( 'settings-threed-iframe', $settings, true );
$this->settings = get_option( 'settings-threed-iframe' );
$this->add_message( esc_html__( 'Your settings have been saved.', '3dvieweronline-wp' ) );
}
/**
* Validate request data.
* Handles the request data.
*
* @since 1.0.0
*/
public function validation( $data ) {
$supported_image = array( 'jpg', 'jpeg', 'png' );
$error = 0;
if ( isset( $data['threed_enable_product_tab'] ) && 'on' === $data['threed_enable_product_tab'] ) {
if ( isset( $data['threed_tab_title'] ) && empty( $data['threed_tab_title'] ) ) {
$this->add_error( esc_html__( 'Product Tab Title is required.', '3dvieweronline-wp' ) );
$error = 1;
}
}
if ( isset( $data['threed_icon'] ) && ! empty( $data['threed_icon'] ) ) {
$icon_url = threedvieweronline_url( wp_unslash( $data['threed_icon'] ) );
$path = wp_parse_url( $icon_url, PHP_URL_PATH );
$image_ext = is_string( $path ) ? strtolower( pathinfo( $path, PATHINFO_EXTENSION ) ) : '';
$image_ext = str_replace( '.', '', $image_ext );
if ( ! in_array( $image_ext, $supported_image ,true ) ) {
$this->add_error( esc_html__( '3D Icon must be a file of type: jpeg, png, jpg.', '3dvieweronline-wp' ) );
$error = 1;
}
}
if ( $error ) {
return false;
}
return true;
}
}