plugin_name = $plugin_name; $this->version = $version; } // ------------------------------------------------------------------// // PRO state // ------------------------------------------------------------------// /** * Whether the PRO add-on is installed and running. * * This edition reads no licence option: it only checks whether the * companion plugin is loaded. Unlocking happens inside the add-on, so no * feature of this plugin is gated by a licence check. * * While the add-on is absent the premium options stay visible as plain * text pointing to the separate plugin. * * @return bool */ public function is_pro_active() { return defined( 'FSWEB_COMMENTS_CORE_PRO_VERSION' ); } /** * URL of the product page. * * @return string */ private function pro_url() { return defined( 'FSWEB_COMMENTS_CORE_PRO_URL' ) ? FSWEB_COMMENTS_CORE_PRO_URL : 'https://flowsyncweb.com/'; } // ------------------------------------------------------------------// // Assets // ------------------------------------------------------------------// /** * Enqueue the admin stylesheet on our screens. * * The version comes from the file timestamp so a changed stylesheet is * never served from the browser cache. * * @param string $hook_suffix Current admin page. * @return void */ public function enqueue_styles( $hook_suffix ) { if ( ! $this->is_plugin_screen( $hook_suffix ) ) { return; } $stylesheet = FSWEB_COMMENTS_CORE_DIR . 'admin/css/fsweb-comments-core-admin.css'; wp_enqueue_style( $this->plugin_name, FSWEB_COMMENTS_CORE_URL . 'admin/css/fsweb-comments-core-admin.css', array(), file_exists( $stylesheet ) ? (string) filemtime( $stylesheet ) : $this->version ); } /** * Enqueue the admin script on our screens. * * @param string $hook_suffix Current admin page. * @return void */ public function enqueue_scripts( $hook_suffix ) { if ( ! $this->is_plugin_screen( $hook_suffix ) ) { return; } $script = FSWEB_COMMENTS_CORE_DIR . 'admin/js/fsweb-comments-core-admin.js'; wp_enqueue_script( $this->plugin_name, FSWEB_COMMENTS_CORE_URL . 'admin/js/fsweb-comments-core-admin.js', array(), file_exists( $script ) ? (string) filemtime( $script ) : $this->version, true ); } /** * Whether the current screen belongs to the plugin. * * @param string $hook_suffix Current admin page. * @return bool */ private function is_plugin_screen( $hook_suffix ) { if ( false !== strpos( (string) $hook_suffix, 'fsweb-comments-core' ) ) { return true; } $screen = get_current_screen(); return $screen && 'fsweb_review' === $screen->post_type; } // ------------------------------------------------------------------// // Menu // ------------------------------------------------------------------// /** * Register the submenu pages. * * With the add-on installed it owns the overview and both builders, so the * free edition only keeps the settings screen and the PRO page. * * @return void */ public function add_admin_menu() { $parent = 'edit.php?post_type=fsweb_review'; if ( ! $this->is_pro_active() ) { add_submenu_page( $parent, __( 'Overview', 'fsweb-comments-core' ), __( 'Overview', 'fsweb-comments-core' ), 'manage_options', 'fsweb-comments-core', array( $this, 'render_overview_page' ), 3 ); add_submenu_page( $parent, __( 'Form Builder', 'fsweb-comments-core' ), __( 'Form Builder', 'fsweb-comments-core' ), 'manage_options', 'fsweb-comments-core-builder', array( $this, 'render_builder_page' ), 4 ); add_submenu_page( $parent, __( 'Views Builder', 'fsweb-comments-core' ), __( 'Views Builder', 'fsweb-comments-core' ), 'manage_options', 'fsweb-comments-core-views', array( $this, 'render_views_page' ), 5 ); } add_submenu_page( $parent, __( 'Settings', 'fsweb-comments-core' ), __( 'Settings', 'fsweb-comments-core' ), 'manage_options', 'fsweb-comments-core-settings', array( $this, 'render_settings_page' ), 6 ); // The offer only exists while the add-on is not installed: with the // companion plugin there is nothing left to sell here. if ( ! $this->is_pro_active() ) { add_submenu_page( $parent, __( 'Go PRO', 'fsweb-comments-core' ), '' . esc_html__( 'Go PRO', 'fsweb-comments-core' ) . '', 'manage_options', 'fsweb-comments-core-go-pro', array( $this, 'render_go_pro_page' ), 7 ); } } /** * URL of one of our screens. * * @param string $slug Screen slug. * @return string */ private function page_url( $slug ) { return admin_url( 'edit.php?post_type=fsweb_review&page=' . $slug ); } // ------------------------------------------------------------------// // Shared UI // ------------------------------------------------------------------// /** * Screens shown in the hero navigation. * * @param string $current Slug of the current screen. * @return array */ private function nav_screens( $current ) { $screens = array(); $pro = $this->is_pro_active(); if ( $pro ) { $screens['fsweb-comments-core-pro'] = array( 'label' => __( 'Dashboard', 'fsweb-comments-core' ), 'icon' => 'dashicons-dashboard', ); } else { $screens['fsweb-comments-core'] = array( 'label' => __( 'Overview', 'fsweb-comments-core' ), 'icon' => 'dashicons-dashboard', ); } $screens['fsweb-comments-core-builder'] = array( 'label' => __( 'Form Builder', 'fsweb-comments-core' ), 'icon' => 'dashicons-feedback', ); $screens['fsweb-comments-core-views'] = array( 'label' => __( 'Views Builder', 'fsweb-comments-core' ), 'icon' => 'dashicons-layout', ); $screens['fsweb-comments-core-settings'] = array( 'label' => __( 'Settings', 'fsweb-comments-core' ), 'icon' => 'dashicons-admin-generic', ); if ( $pro ) { $screens['fsweb-comments-core-license'] = array( 'label' => __( 'License', 'fsweb-comments-core' ), 'icon' => 'dashicons-awards', ); } if ( ! $this->is_pro_active() ) { $screens['fsweb-comments-core-go-pro'] = array( 'label' => __( 'Go PRO', 'fsweb-comments-core' ), 'icon' => 'dashicons-star-filled', ); } return $screens; } /** * Render the hero header shared by every screen. * * @param string $title Screen title. * @param string $description One-line description. * @param string $current Slug of the current screen. * @return void */ private function render_hero( $title, $description, $current = '' ) { $screens = $this->nav_screens( $current ); ?>

$screen ) : ?>
is_pro_active() ) { return; } ?> pro_tag(); ?>

'string', 'default' => 'open', 'sanitize_callback' => array( $this, 'sanitize_form_status' ), ) ); register_setting( 'fsweb_comments_core_settings', 'fsweb_comments_core_require_email', array( 'type' => 'string', 'default' => '1', 'sanitize_callback' => array( $this, 'sanitize_require_email' ), ) ); register_setting( 'fsweb_comments_core_settings', 'fsweb_comments_core_default_theme', array( 'type' => 'string', 'default' => 'default', 'sanitize_callback' => array( $this, 'sanitize_default_theme' ), ) ); } /** * Sanitise the "require email" checkbox. * * The value is stored as '1' or '0': a boolean false would be dropped by * update_option() when the option does not exist yet, and the default * would silently win. * * @param mixed $value Raw value. * @return string '1' when required, '0' otherwise. */ public function sanitize_require_email( $value ) { return ( '1' === $value || 1 === $value || true === $value || 'true' === $value ) ? '1' : '0'; } /** * Sanitise the form status option. * * @param string $value Raw value. * @return string */ public function sanitize_form_status( $value ) { return 'closed' === $value ? 'closed' : 'open'; } /** * Sanitise the default theme option. * * @param string $value Raw value. * @return string */ public function sanitize_default_theme( $value ) { return 'dark' === $value ? 'dark' : 'default'; } // ------------------------------------------------------------------// // Screens // ------------------------------------------------------------------// /** * Overview screen. * * @return void */ public function render_overview_page() { if ( ! current_user_can( 'manage_options' ) ) { return; } $counts = wp_count_posts( 'fsweb_review' ); $pending = isset( $counts->pending ) ? (int) $counts->pending : 0; $publish = isset( $counts->publish ) ? (int) $counts->publish : 0; $average = $this->get_average_rating(); $status = get_option( 'fsweb_comments_core_form_status', 'open' ); ?>

render_hero( __( 'Comments Core', 'fsweb-comments-core' ), __( 'Collect reviews, moderate them and display them anywhere with a shortcode.', 'fsweb-comments-core' ), 'fsweb-comments-core' ); ?>

[fsweb_reviews layout="slider" count="6" slides="3"]

[fsweb_review_form]


render_hero( __( 'Form Builder', 'fsweb-comments-core' ), __( 'Build the review form field by field, with extra types and multiple steps.', 'fsweb-comments-core' ), 'fsweb-comments-core-builder' ); ?>

render_locked_field( __( 'Date', 'fsweb-comments-core' ) ); $this->render_locked_field( __( 'Select', 'fsweb-comments-core' ) ); $this->render_locked_field( __( 'URL', 'fsweb-comments-core' ) ); ?>

render_locked_field( __( 'Multi-step form', 'fsweb-comments-core' ), __( 'Split the form into steps with a progress indicator.', 'fsweb-comments-core' ) ); $this->render_locked_field( __( 'Redirect after submit', 'fsweb-comments-core' ), __( 'Send the visitor to a thank-you page after the review is accepted.', 'fsweb-comments-core' ) ); $this->render_locked_field( __( 'Saved forms', 'fsweb-comments-core' ), __( 'Keep several forms and choose one per shortcode with [fsweb_review_form id="..."].', 'fsweb-comments-core' ) ); ?>

render_hero( __( 'Views Builder', 'fsweb-comments-core' ), __( 'Design the review card and pick the layout, the skin and the CSS for each view.', 'fsweb-comments-core' ), 'fsweb-comments-core-views' ); ?>

render_locked_field( __( 'Infinite slider', 'fsweb-comments-core' ), __( 'Autoplay and seamless looping past the last card.', 'fsweb-comments-core' ) ); ?>

render_locked_field( __( 'Skin', 'fsweb-comments-core' ), __( 'Dark, minimal, colorful and flat, ready to use.', 'fsweb-comments-core' ) ); $this->render_locked_field( __( 'Custom CSS', 'fsweb-comments-core' ), __( 'Write the CSS of each view without touching the theme.', 'fsweb-comments-core' ) ); $this->render_locked_field( __( 'Card composition', 'fsweb-comments-core' ), __( 'Choose which components appear in the card and in which order.', 'fsweb-comments-core' ) ); ?>

render_hero( __( 'Settings', 'fsweb-comments-core' ), __( 'Control the submissions and the appearance of the reviews.', 'fsweb-comments-core' ), 'fsweb-comments-core-settings' ); ?>

is_pro_active() ) : ?>

render_locked_field( __( 'Custom CSS', 'fsweb-comments-core' ), __( 'Extra CSS loaded after the plugin styles.', 'fsweb-comments-core' ) ); ?>

is_pro_active() ) { ?>

render_hero( __( 'Comments Core PRO', 'fsweb-comments-core' ), __( 'The PRO add-on is installed and running.', 'fsweb-comments-core' ), 'fsweb-comments-core-go-pro' ); ?>


render_hero( __( 'Comments Core PRO', 'fsweb-comments-core' ), __( 'Unlock the builders, the extra skins and the automatic updates with a single license.', 'fsweb-comments-core' ), 'fsweb-comments-core-go-pro' ); ?>

'fsweb_review', 'post_status' => 'publish', 'posts_per_page' => 500, 'fields' => 'ids', 'no_found_rows' => true, ) ); if ( empty( $ids ) ) { return ''; } $total = 0; $rated = 0; foreach ( $ids as $id ) { $rating = (int) get_post_meta( $id, 'fsweb_rating', true ); if ( $rating > 0 ) { $total += $rating; $rated++; } } if ( 0 === $rated ) { return ''; } return number_format_i18n( $total / $rated, 1 ); } }