From 9d2605dcd0cec5788371736935e60b8064eb6bc3 Mon Sep 17 00:00:00 2001 From: snyk-bot Date: Fri, 14 Mar 2025 03:23:13 +0000 Subject: [PATCH] fix: admin/dashboard/package.json & admin/dashboard/package-lock.json to reduce vulnerabilities --- .distignore | 66 +- .gitignore | 71 +- Gruntfile.js | 408 +- README.md | 578 +- admin/bsf-analytics/class-bsf-analytics.php | 1016 +- .../edit/preview/EditGooglePreviewItem.js | 660 +- .../pages/fonts/preview/GFontVariation.js | 460 +- .../dashboard-app/pages/welcome/Settings.js | 170 +- .../class-bsf-custom-fonts-admin-ajax.php | 682 +- .../includes/class-bsf-custom-fonts-menu.php | 1174 +- admin/dashboard/package-lock.json | 34052 ++++++++-------- admin/dashboard/package.json | 106 +- admin/dashboard/tailwind.config.js | 107 +- classes/class-bsf-custom-fonts-render.php | 1138 +- custom-fonts.php | 182 +- .../class-bcf-google-fonts-compatibility.php | 1458 +- .../class-custom-fonts-update.php | 514 +- package-lock.json | 28780 ++++++------- package.json | 66 +- readme.txt | 578 +- 20 files changed, 36107 insertions(+), 36159 deletions(-) diff --git a/.distignore b/.distignore index 32390a4f..cf0413dd 100644 --- a/.distignore +++ b/.distignore @@ -1,33 +1,33 @@ -# A set of files you probably don't want in your WordPress.org distribution -.distignore -.editorconfig -.git -.gitignore -.gitlab-ci.yml -.travis.yml -.DS_Store -Thumbs.db -behat.yml -bin -circle.yml -composer.json -composer.lock -Gruntfile.js -package.json -package-lock.json -phpunit.xml -phpunit.xml.dist -multisite.xml -multisite.xml.dist -phpcs.xml -phpcs.xml.dist -README.md -wp-cli.local.yml -tests -vendor -node_modules -*.sql -*.tar.gz -*.zip -.github -.wordpress-org +# A set of files you probably don't want in your WordPress.org distribution +.distignore +.editorconfig +.git +.gitignore +.gitlab-ci.yml +.travis.yml +.DS_Store +Thumbs.db +behat.yml +bin +circle.yml +composer.json +composer.lock +Gruntfile.js +package.json +package-lock.json +phpunit.xml +phpunit.xml.dist +multisite.xml +multisite.xml.dist +phpcs.xml +phpcs.xml.dist +README.md +wp-cli.local.yml +tests +vendor +node_modules +*.sql +*.tar.gz +*.zip +.github +.wordpress-org diff --git a/.gitignore b/.gitignore index bec1e4cf..d8c9e775 100644 --- a/.gitignore +++ b/.gitignore @@ -1,35 +1,36 @@ -# ignore PHPStorm extra directories -.idea/ - -# Leave node_modules from git -node_modules/ - -# sass cache -.sass-cache - -# map files -*.map - -# Skip package file from versoning -*.zip - -# ignore git inside subproject -admin/bsf-core/.git - -# ignore PHPCS report files -phpcs-summary.log -phpcs-full.log - -# Exclude OS specific files -.DS_Store - -# Exclude composer's directories -vendor/ - -# Exclude exported settings -borders-for-default-menu.json -defaults.json -no-toggle-border-fix.json - -# Large dist directory - Build files can be in MBs, let's not increase size of the git repo -admin/dashboard/assets/build/ +# ignore PHPStorm extra directories +.idea/ + +# Leave node_modules from git +node_modules/ + +# sass cache +.sass-cache + +# map files +*.map + +# Skip package file from versoning +*.zip + +# ignore git inside subproject +admin/bsf-core/.git + +# ignore PHPCS report files +phpcs-summary.log +phpcs-full.log + +# Exclude OS specific files +.DS_Store + +# Exclude composer's directories +vendor/ + +# Exclude exported settings +borders-for-default-menu.json +defaults.json +no-toggle-border-fix.json + +# Large dist directory - Build files can be in MBs, let's not increase size of the git repo +admin/dashboard/assets/build/ +config.bat diff --git a/Gruntfile.js b/Gruntfile.js index e31af978..b6a66710 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,204 +1,204 @@ -module.exports = function( grunt ) { - - 'use strict'; - var pkg = grunt.file.readJSON('package.json'); - var banner = '/**\n * <%= pkg.homepage %>\n * Copyright (c) <%= grunt.template.today("yyyy") %>\n * This file is generated automatically. Do not edit.\n */\n'; - // Project configuration - grunt.initConfig( { - - rtlcss: { - options: { - config: { - preserveComments: true, - greedy: true - }, - // generate source maps - map: false - }, - dist: { - files: [ - { - expand: true, - cwd: 'admin/dashboard/assets/build', - src: [ - '*.css', - '!*-rtl.css', - ], - dest: 'admin/dashboard/assets/build', - ext: '-rtl.css' - }, - ] - } - }, - - addtextdomain: { - options: { - textdomain: 'custom-fonts', - }, - update_all_domains: { - options: { - updateDomains: true - }, - src: [ '*.php', '**/*.php', '!node_modules/**', '!php-tests/**', '!bin/**' ] - } - }, - - wp_readme_to_markdown: { - your_target: { - files: { - 'README.md': 'readme.txt' - } - }, - }, - - makepot: { - target: { - options: { - domainPath: '/languages', - mainFile: 'custom-fonts.php', - potFilename: 'custom-fonts.pot', - potHeaders: { - poedit: true, - 'x-poedit-keywordslist': true - }, - type: 'wp-plugin', - updateTimestamp: true - } - } - }, - - clean: { - main: ["custom-fonts"], - zip: ["*.zip"] - }, - - copy: { - main: { - options: { - mode: true - }, - src: [ - '**', - '*.zip', - '!node_modules/**', - '!admin/dashboard/node_modules/**', - '!admin/dashboard/package.json', - '!admin/dashboard/package-lock.json', - '!admin/dashboard/postcss.config.js', - '!admin/dashboard/tailwind.config.js', - '!admin/dashboard/webpack.config.js', - '!.git/**', - '!.wordpress-org/**', - '!bin/**', - '!.gitlab-ci.yml', - '!bin/**', - '!tests/**', - '!phpunit.xml.dist', - '!*.sh', - '!*.map', - '!Gruntfile.js', - '!package.json', - '!.gitignore', - '!.distignore', - '!.editorconfig', - '!tailwind.config.js', - '!webpack.config.js', - '!postcss.config.js', - '!phpunit.xml', - '!README.md', - '!codesniffer.ruleset.xml', - '!vendor/**', - '!composer.json', - '!composer.lock', - '!package-lock.json', - '!phpcs.xml', - '!phpcs.xml.dist', - '!admin/dashboard/assets/src/**', - ], - dest: 'custom-fonts/' - } - }, - - compress: { - main: { - options: { - archive: 'custom-fonts-' + pkg.version + '.zip', - mode: 'zip' - }, - files: [ - { - src: [ - './custom-fonts/**' - ] - - } - ] - } - }, - - json2php: { - options: { - // Task-specific options go here. - compress: true, - cover: function (phpArrayString, destFilePath) { - return '\n * Copyright (c) <%= grunt.template.today("yyyy") %>\n * This file is generated automatically. Do not edit.\n */\n'; + // Project configuration + grunt.initConfig( { + + rtlcss: { + options: { + config: { + preserveComments: true, + greedy: true + }, + // generate source maps + map: false + }, + dist: { + files: [ + { + expand: true, + cwd: 'admin/dashboard/assets/build', + src: [ + '*.css', + '!*-rtl.css', + ], + dest: 'admin/dashboard/assets/build', + ext: '-rtl.css' + }, + ] + } + }, + + addtextdomain: { + options: { + textdomain: 'custom-fonts', + }, + update_all_domains: { + options: { + updateDomains: true + }, + src: [ '*.php', '**/*.php', '!node_modules/**', '!php-tests/**', '!bin/**' ] + } + }, + + wp_readme_to_markdown: { + your_target: { + files: { + 'README.md': 'readme.txt' + } + }, + }, + + makepot: { + target: { + options: { + domainPath: '/languages', + mainFile: 'custom-fonts.php', + potFilename: 'custom-fonts.pot', + potHeaders: { + poedit: true, + 'x-poedit-keywordslist': true + }, + type: 'wp-plugin', + updateTimestamp: true + } + } + }, + + clean: { + main: ["custom-fonts"], + zip: ["*.zip"] + }, + + copy: { + main: { + options: { + mode: true + }, + src: [ + '**', + '*.zip', + '!node_modules/**', + '!admin/dashboard/node_modules/**', + '!admin/dashboard/package.json', + '!admin/dashboard/package-lock.json', + '!admin/dashboard/postcss.config.js', + '!admin/dashboard/tailwind.config.js', + '!admin/dashboard/webpack.config.js', + '!.git/**', + '!.wordpress-org/**', + '!bin/**', + '!.gitlab-ci.yml', + '!bin/**', + '!tests/**', + '!phpunit.xml.dist', + '!*.sh', + '!*.map', + '!Gruntfile.js', + '!package.json', + '!.gitignore', + '!.distignore', + '!.editorconfig', + '!tailwind.config.js', + '!webpack.config.js', + '!postcss.config.js', + '!phpunit.xml', + '!README.md', + '!codesniffer.ruleset.xml', + '!vendor/**', + '!composer.json', + '!composer.lock', + '!package-lock.json', + '!phpcs.xml', + '!phpcs.xml.dist', + '!admin/dashboard/assets/src/**', + ], + dest: 'custom-fonts/' + } + }, + + compress: { + main: { + options: { + archive: 'custom-fonts-' + pkg.version + '.zip', + mode: 'zip' + }, + files: [ + { + src: [ + './custom-fonts/**' + ] + + } + ] + } + }, + + json2php: { + options: { + // Task-specific options go here. + compress: true, + cover: function (phpArrayString, destFilePath) { + return 'entities = $args; - - define( 'BSF_ANALYTICS_VERSION', $analytics_version ); - define( 'BSF_ANALYTICS_URI', $this->get_analytics_url( $analytics_path ) ); - - add_action( 'admin_init', array( $this, 'handle_optin_optout' ) ); - add_action( 'admin_notices', array( $this, 'option_notice' ) ); - add_action( 'init', array( $this, 'maybe_track_analytics' ), 99 ); - - $this->set_actions(); - - add_action( 'admin_init', array( $this, 'register_usage_tracking_setting' ) ); - - $this->includes(); - } - - /** - * Setup actions for admin notice style and analytics cron event. - * - * @since 1.0.4 - */ - public function set_actions() { - - foreach ( $this->entities as $key => $data ) { - add_action( 'astra_notice_before_markup_' . $key . '-optin-notice', array( $this, 'enqueue_assets' ) ); - add_action( 'update_option_' . $key . '_analytics_optin', array( $this, 'update_analytics_option_callback' ), 10, 3 ); - add_action( 'add_option_' . $key . '_analytics_optin', array( $this, 'add_analytics_option_callback' ), 10, 2 ); - } - } - - /** - * BSF Analytics URL - * - * @param string $analytics_path directory path to analytics library. - * @return String URL of bsf-analytics directory. - * @since 1.0.0 - */ - public function get_analytics_url( $analytics_path ) { - - $content_dir_path = wp_normalize_path( WP_CONTENT_DIR ); - - $analytics_path = wp_normalize_path( $analytics_path ); - - return str_replace( $content_dir_path, content_url(), $analytics_path ); - } - - /** - * Get API URL for sending analytics. - * - * @return string API URL. - * @since 1.0.0 - */ - private function get_api_url() { - return defined( 'BSF_API_URL' ) ? BSF_API_URL : 'https://support.brainstormforce.com/'; - } - - /** - * Enqueue Scripts. - * - * @since 1.0.0 - * @return void - */ - public function enqueue_assets() { - - /** - * Load unminified if SCRIPT_DEBUG is true. - * - * Directory and Extensions. - */ - $dir_name = ( SCRIPT_DEBUG ) ? 'unminified' : 'minified'; - $file_rtl = ( is_rtl() ) ? '-rtl' : ''; - $css_ext = ( SCRIPT_DEBUG ) ? '.css' : '.min.css'; - - $css_uri = BSF_ANALYTICS_URI . '/assets/css/' . $dir_name . '/style' . $file_rtl . $css_ext; - - wp_enqueue_style( 'bsf-analytics-admin-style', $css_uri, false, BSF_ANALYTICS_VERSION, 'all' ); - } - - /** - * Send analytics API call. - * - * @since 1.0.0 - */ - public function send() { - wp_remote_post( - $this->get_api_url() . 'wp-json/bsf-core/v1/analytics/', - array( - 'body' => BSF_Analytics_Stats::instance()->get_stats(), - 'timeout' => 5, - 'blocking' => false, - ) - ); - } - - /** - * Check if usage tracking is enabled. - * - * @return bool - * @since 1.0.0 - */ - public function is_tracking_enabled() { - - foreach ( $this->entities as $key => $data ) { - - $is_enabled = get_site_option( $key . '_analytics_optin' ) === 'yes' ? true : false; - $is_enabled = $this->is_white_label_enabled( $key ) ? false : $is_enabled; - - if ( apply_filters( $key . '_tracking_enabled', $is_enabled ) ) { - return true; - } - } - - return false; - } - - /** - * Check if WHITE label is enabled for BSF products. - * - * @param string $source source of analytics. - * @return bool - * @since 1.0.0 - */ - public function is_white_label_enabled( $source ) { - - $options = apply_filters( $source . '_white_label_options', array() ); - $is_enabled = false; - - if ( is_array( $options ) ) { - foreach ( $options as $option ) { - if ( true === $option ) { - $is_enabled = true; - break; - } - } - } - - return $is_enabled; - } - - /** - * Display admin notice for usage tracking. - * - * @since 1.0.0 - */ - public function option_notice() { - - if ( ! current_user_can( 'manage_options' ) ) { - return; - } - - foreach ( $this->entities as $key => $data ) { - - $time_to_display = isset( $data['time_to_display'] ) ? $data['time_to_display'] : '+24 hours'; - $usage_doc_link = isset( $data['usage_doc_link'] ) ? $data['usage_doc_link'] : $this->usage_doc_link; - - // Don't display the notice if tracking is disabled or White Label is enabled for any of our plugins. - if ( false !== get_site_option( $key . '_analytics_optin', false ) || $this->is_white_label_enabled( $key ) ) { - continue; - } - - // Show tracker consent notice after 24 hours from installed time. - if ( strtotime( $time_to_display, $this->get_analytics_install_time( $key ) ) > time() ) { - continue; - } - - /* translators: %s product name */ - $notice_string = __( 'Want to help make %1s even more awesome? Allow us to collect non-sensitive diagnostic data and usage information. ', 'custom-fonts' ); - - if ( is_multisite() ) { - $notice_string .= __( 'This will be applicable for all sites from the network.', 'custom-fonts' ); - } - - $language_dir = is_rtl() ? 'rtl' : 'ltr'; - - Astra_Notices::add_notice( - array( - 'id' => $key . '-optin-notice', - 'type' => '', - 'message' => sprintf( - '
-
- %1$s -
- -
', - /* translators: %s usage doc link */ - sprintf( $notice_string . '%4s', esc_html( $data['product_name'] ), $language_dir, esc_url( $usage_doc_link ), __( ' Know More.', 'custom-fonts' ) ), - add_query_arg( - array( - $key . '_analytics_optin' => 'yes', - $key . '_analytics_nonce' => wp_create_nonce( $key . '_analytics_optin' ), - 'bsf_analytics_source' => $key, - ) - ), - __( 'Yes! Allow it', 'custom-fonts' ), - add_query_arg( - array( - $key . '_analytics_optin' => 'no', - $key . '_analytics_nonce' => wp_create_nonce( $key . '_analytics_optin' ), - 'bsf_analytics_source' => $key, - ) - ), - MONTH_IN_SECONDS, - __( 'No Thanks', 'custom-fonts' ) - ), - 'show_if' => true, - 'repeat-notice-after' => false, - 'priority' => 18, - 'display-with-other-notices' => true, - ) - ); - } - } - - /** - * Process usage tracking opt out. - * - * @since 1.0.0 - */ - public function handle_optin_optout() { - - if ( ! current_user_can( 'manage_options' ) ) { - return; - } - - $source = isset( $_GET['bsf_analytics_source'] ) ? sanitize_text_field( wp_unslash( $_GET['bsf_analytics_source'] ) ) : ''; - - if ( ! isset( $_GET[ $source . '_analytics_nonce' ] ) ) { - return; - } - - if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET[ $source . '_analytics_nonce' ] ) ), $source . '_analytics_optin' ) ) { - return; - } - - $optin_status = isset( $_GET[ $source . '_analytics_optin' ] ) ? sanitize_text_field( wp_unslash( $_GET[ $source . '_analytics_optin' ] ) ) : ''; - - if ( 'yes' === $optin_status ) { - $this->optin( $source ); - } elseif ( 'no' === $optin_status ) { - $this->optout( $source ); - } - - wp_safe_redirect( - remove_query_arg( - array( - $source . '_analytics_optin', - $source . '_analytics_nonce', - 'bsf_analytics_source', - ) - ) - ); - } - - /** - * Opt in to usage tracking. - * - * @param string $source source of analytics. - * @since 1.0.0 - */ - private function optin( $source ) { - update_site_option( $source . '_analytics_optin', 'yes' ); - } - - /** - * Opt out to usage tracking. - * - * @param string $source source of analytics. - * @since 1.0.0 - */ - private function optout( $source ) { - update_site_option( $source . '_analytics_optin', 'no' ); - } - - /** - * Load analytics stat class. - * - * @since 1.0.0 - */ - private function includes() { - require_once __DIR__ . '/class-bsf-analytics-stats.php'; - } - - /** - * Register usage tracking option in General settings page. - * - * @since 1.0.0 - */ - public function register_usage_tracking_setting() { - - foreach ( $this->entities as $key => $data ) { - - if ( ! apply_filters( $key . '_tracking_enabled', true ) || $this->is_white_label_enabled( $key ) ) { - return; - } - - $usage_doc_link = isset( $data['usage_doc_link'] ) ? $data['usage_doc_link'] : $this->usage_doc_link; - $author = isset( $data['author'] ) ? $data['author'] : 'Brainstorm Force'; - - register_setting( - 'general', // Options group. - $key . '_analytics_optin', // Option name/database. - array( 'sanitize_callback' => array( $this, 'sanitize_option' ) ) // sanitize callback function. - ); - - add_settings_field( - $key . '-analytics-optin', // Field ID. - __( 'Usage Tracking', 'custom-fonts' ), // Field title. - array( $this, 'render_settings_field_html' ), // Field callback function. - 'general', - 'default', // Settings page slug. - array( - 'type' => 'checkbox', - 'title' => $author, - 'name' => $key . '_analytics_optin', - 'label_for' => $key . '-analytics-optin', - 'id' => $key . '-analytics-optin', - 'usage_doc_link' => $usage_doc_link, - ) - ); - } - } - - /** - * Sanitize Callback Function - * - * @param bool $input Option value. - * @since 1.0.0 - */ - public function sanitize_option( $input ) { - - if ( ! $input || 'no' === $input ) { - return 'no'; - } - - return 'yes'; - } - - /** - * Print settings field HTML. - * - * @param array $args arguments to field. - * @since 1.0.0 - */ - public function render_settings_field_html( $args ) { - ?> -
- - %2s', esc_url( $args['usage_doc_link'] ), __( 'Learn More.', 'custom-fonts' ) ) ); - ?> -
- add_option_to_network( $option, $value ); - } - } - - /** - * Analytics option add callback. - * - * @param string $option Option name. - * @param string $value value of option. - * @since 1.0.0 - */ - public function add_analytics_option_callback( $option, $value ) { - if ( is_multisite() ) { - $this->add_option_to_network( $option, $value ); - } - } - - /** - * Send analaytics track event if tracking is enabled. - * - * @since 1.0.0 - */ - public function maybe_track_analytics() { - - if ( ! $this->is_tracking_enabled() ) { - return; - } - - $analytics_track = get_site_transient( 'bsf_analytics_track' ); - - // If the last data sent is 2 days old i.e. transient is expired. - if ( ! $analytics_track ) { - $this->send(); - set_site_transient( 'bsf_analytics_track', true, 2 * DAY_IN_SECONDS ); - } - } - - /** - * Save analytics option to network. - * - * @param string $option name of option. - * @param string $value value of option. - * @since 1.0.0 - */ - public function add_option_to_network( $option, $value ) { - - // If action coming from general settings page. - if ( isset( $_POST['option_page'] ) && 'general' === $_POST['option_page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing - - if ( get_site_option( $option ) ) { - update_site_option( $option, $value ); - } else { - add_site_option( $option, $value ); - } - } - } - } -} +entities = $args; + + define( 'BSF_ANALYTICS_VERSION', $analytics_version ); + define( 'BSF_ANALYTICS_URI', $this->get_analytics_url( $analytics_path ) ); + + add_action( 'admin_init', array( $this, 'handle_optin_optout' ) ); + add_action( 'admin_notices', array( $this, 'option_notice' ) ); + add_action( 'init', array( $this, 'maybe_track_analytics' ), 99 ); + + $this->set_actions(); + + add_action( 'admin_init', array( $this, 'register_usage_tracking_setting' ) ); + + $this->includes(); + } + + /** + * Setup actions for admin notice style and analytics cron event. + * + * @since 1.0.4 + */ + public function set_actions() { + + foreach ( $this->entities as $key => $data ) { + add_action( 'astra_notice_before_markup_' . $key . '-optin-notice', array( $this, 'enqueue_assets' ) ); + add_action( 'update_option_' . $key . '_analytics_optin', array( $this, 'update_analytics_option_callback' ), 10, 3 ); + add_action( 'add_option_' . $key . '_analytics_optin', array( $this, 'add_analytics_option_callback' ), 10, 2 ); + } + } + + /** + * BSF Analytics URL + * + * @param string $analytics_path directory path to analytics library. + * @return String URL of bsf-analytics directory. + * @since 1.0.0 + */ + public function get_analytics_url( $analytics_path ) { + + $content_dir_path = wp_normalize_path( WP_CONTENT_DIR ); + + $analytics_path = wp_normalize_path( $analytics_path ); + + return str_replace( $content_dir_path, content_url(), $analytics_path ); + } + + /** + * Get API URL for sending analytics. + * + * @return string API URL. + * @since 1.0.0 + */ + private function get_api_url() { + return defined( 'BSF_API_URL' ) ? BSF_API_URL : 'https://support.brainstormforce.com/'; + } + + /** + * Enqueue Scripts. + * + * @since 1.0.0 + * @return void + */ + public function enqueue_assets() { + + /** + * Load unminified if SCRIPT_DEBUG is true. + * + * Directory and Extensions. + */ + $dir_name = ( SCRIPT_DEBUG ) ? 'unminified' : 'minified'; + $file_rtl = ( is_rtl() ) ? '-rtl' : ''; + $css_ext = ( SCRIPT_DEBUG ) ? '.css' : '.min.css'; + + $css_uri = BSF_ANALYTICS_URI . '/assets/css/' . $dir_name . '/style' . $file_rtl . $css_ext; + + wp_enqueue_style( 'bsf-analytics-admin-style', $css_uri, false, BSF_ANALYTICS_VERSION, 'all' ); + } + + /** + * Send analytics API call. + * + * @since 1.0.0 + */ + public function send() { + wp_remote_post( + $this->get_api_url() . 'wp-json/bsf-core/v1/analytics/', + array( + 'body' => BSF_Analytics_Stats::instance()->get_stats(), + 'timeout' => 5, + 'blocking' => false, + ) + ); + } + + /** + * Check if usage tracking is enabled. + * + * @return bool + * @since 1.0.0 + */ + public function is_tracking_enabled() { + + foreach ( $this->entities as $key => $data ) { + + $is_enabled = get_site_option( $key . '_analytics_optin' ) === 'yes' ? true : false; + $is_enabled = $this->is_white_label_enabled( $key ) ? false : $is_enabled; + + if ( apply_filters( $key . '_tracking_enabled', $is_enabled ) ) { + return true; + } + } + + return false; + } + + /** + * Check if WHITE label is enabled for BSF products. + * + * @param string $source source of analytics. + * @return bool + * @since 1.0.0 + */ + public function is_white_label_enabled( $source ) { + + $options = apply_filters( $source . '_white_label_options', array() ); + $is_enabled = false; + + if ( is_array( $options ) ) { + foreach ( $options as $option ) { + if ( true === $option ) { + $is_enabled = true; + break; + } + } + } + + return $is_enabled; + } + + /** + * Display admin notice for usage tracking. + * + * @since 1.0.0 + */ + public function option_notice() { + + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + + foreach ( $this->entities as $key => $data ) { + + $time_to_display = isset( $data['time_to_display'] ) ? $data['time_to_display'] : '+24 hours'; + $usage_doc_link = isset( $data['usage_doc_link'] ) ? $data['usage_doc_link'] : $this->usage_doc_link; + + // Don't display the notice if tracking is disabled or White Label is enabled for any of our plugins. + if ( false !== get_site_option( $key . '_analytics_optin', false ) || $this->is_white_label_enabled( $key ) ) { + continue; + } + + // Show tracker consent notice after 24 hours from installed time. + if ( strtotime( $time_to_display, $this->get_analytics_install_time( $key ) ) > time() ) { + continue; + } + + /* translators: %s product name */ + $notice_string = __( 'Want to help make %1s even more awesome? Allow us to collect non-sensitive diagnostic data and usage information. ', 'custom-fonts' ); + + if ( is_multisite() ) { + $notice_string .= __( 'This will be applicable for all sites from the network.', 'custom-fonts' ); + } + + $language_dir = is_rtl() ? 'rtl' : 'ltr'; + + Astra_Notices::add_notice( + array( + 'id' => $key . '-optin-notice', + 'type' => '', + 'message' => sprintf( + '
+
+ %1$s +
+ +
', + /* translators: %s usage doc link */ + sprintf( $notice_string . '%4s', esc_html( $data['product_name'] ), $language_dir, esc_url( $usage_doc_link ), __( ' Know More.', 'custom-fonts' ) ), + add_query_arg( + array( + $key . '_analytics_optin' => 'yes', + $key . '_analytics_nonce' => wp_create_nonce( $key . '_analytics_optin' ), + 'bsf_analytics_source' => $key, + ) + ), + __( 'Yes! Allow it', 'custom-fonts' ), + add_query_arg( + array( + $key . '_analytics_optin' => 'no', + $key . '_analytics_nonce' => wp_create_nonce( $key . '_analytics_optin' ), + 'bsf_analytics_source' => $key, + ) + ), + MONTH_IN_SECONDS, + __( 'No Thanks', 'custom-fonts' ) + ), + 'show_if' => true, + 'repeat-notice-after' => false, + 'priority' => 18, + 'display-with-other-notices' => true, + ) + ); + } + } + + /** + * Process usage tracking opt out. + * + * @since 1.0.0 + */ + public function handle_optin_optout() { + + if ( ! current_user_can( 'manage_options' ) ) { + return; + } + + $source = isset( $_GET['bsf_analytics_source'] ) ? sanitize_text_field( wp_unslash( $_GET['bsf_analytics_source'] ) ) : ''; + + if ( ! isset( $_GET[ $source . '_analytics_nonce' ] ) ) { + return; + } + + if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET[ $source . '_analytics_nonce' ] ) ), $source . '_analytics_optin' ) ) { + return; + } + + $optin_status = isset( $_GET[ $source . '_analytics_optin' ] ) ? sanitize_text_field( wp_unslash( $_GET[ $source . '_analytics_optin' ] ) ) : ''; + + if ( 'yes' === $optin_status ) { + $this->optin( $source ); + } elseif ( 'no' === $optin_status ) { + $this->optout( $source ); + } + + wp_safe_redirect( + remove_query_arg( + array( + $source . '_analytics_optin', + $source . '_analytics_nonce', + 'bsf_analytics_source', + ) + ) + ); + } + + /** + * Opt in to usage tracking. + * + * @param string $source source of analytics. + * @since 1.0.0 + */ + private function optin( $source ) { + update_site_option( $source . '_analytics_optin', 'yes' ); + } + + /** + * Opt out to usage tracking. + * + * @param string $source source of analytics. + * @since 1.0.0 + */ + private function optout( $source ) { + update_site_option( $source . '_analytics_optin', 'no' ); + } + + /** + * Load analytics stat class. + * + * @since 1.0.0 + */ + private function includes() { + require_once __DIR__ . '/class-bsf-analytics-stats.php'; + } + + /** + * Register usage tracking option in General settings page. + * + * @since 1.0.0 + */ + public function register_usage_tracking_setting() { + + foreach ( $this->entities as $key => $data ) { + + if ( ! apply_filters( $key . '_tracking_enabled', true ) || $this->is_white_label_enabled( $key ) ) { + return; + } + + $usage_doc_link = isset( $data['usage_doc_link'] ) ? $data['usage_doc_link'] : $this->usage_doc_link; + $author = isset( $data['author'] ) ? $data['author'] : 'Brainstorm Force'; + + register_setting( + 'general', // Options group. + $key . '_analytics_optin', // Option name/database. + array( 'sanitize_callback' => array( $this, 'sanitize_option' ) ) // sanitize callback function. + ); + + add_settings_field( + $key . '-analytics-optin', // Field ID. + __( 'Usage Tracking', 'custom-fonts' ), // Field title. + array( $this, 'render_settings_field_html' ), // Field callback function. + 'general', + 'default', // Settings page slug. + array( + 'type' => 'checkbox', + 'title' => $author, + 'name' => $key . '_analytics_optin', + 'label_for' => $key . '-analytics-optin', + 'id' => $key . '-analytics-optin', + 'usage_doc_link' => $usage_doc_link, + ) + ); + } + } + + /** + * Sanitize Callback Function + * + * @param bool $input Option value. + * @since 1.0.0 + */ + public function sanitize_option( $input ) { + + if ( ! $input || 'no' === $input ) { + return 'no'; + } + + return 'yes'; + } + + /** + * Print settings field HTML. + * + * @param array $args arguments to field. + * @since 1.0.0 + */ + public function render_settings_field_html( $args ) { + ?> +
+ + %2s', esc_url( $args['usage_doc_link'] ), __( 'Learn More.', 'custom-fonts' ) ) ); + ?> +
+ add_option_to_network( $option, $value ); + } + } + + /** + * Analytics option add callback. + * + * @param string $option Option name. + * @param string $value value of option. + * @since 1.0.0 + */ + public function add_analytics_option_callback( $option, $value ) { + if ( is_multisite() ) { + $this->add_option_to_network( $option, $value ); + } + } + + /** + * Send analaytics track event if tracking is enabled. + * + * @since 1.0.0 + */ + public function maybe_track_analytics() { + + if ( ! $this->is_tracking_enabled() ) { + return; + } + + $analytics_track = get_site_transient( 'bsf_analytics_track' ); + + // If the last data sent is 2 days old i.e. transient is expired. + if ( ! $analytics_track ) { + $this->send(); + set_site_transient( 'bsf_analytics_track', true, 2 * DAY_IN_SECONDS ); + } + } + + /** + * Save analytics option to network. + * + * @param string $option name of option. + * @param string $value value of option. + * @since 1.0.0 + */ + public function add_option_to_network( $option, $value ) { + + // If action coming from general settings page. + if ( isset( $_POST['option_page'] ) && 'general' === $_POST['option_page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing + + if ( get_site_option( $option ) ) { + update_site_option( $option, $value ); + } else { + add_site_option( $option, $value ); + } + } + } + } +} diff --git a/admin/dashboard/assets/src/dashboard-app/pages/fonts/edit/preview/EditGooglePreviewItem.js b/admin/dashboard/assets/src/dashboard-app/pages/fonts/edit/preview/EditGooglePreviewItem.js index a3fcdc63..039dcbb1 100644 --- a/admin/dashboard/assets/src/dashboard-app/pages/fonts/edit/preview/EditGooglePreviewItem.js +++ b/admin/dashboard/assets/src/dashboard-app/pages/fonts/edit/preview/EditGooglePreviewItem.js @@ -1,330 +1,330 @@ -import React, { useState, useEffect } from "react"; -import { __ } from "@wordpress/i18n"; -import { useSelector, useDispatch } from 'react-redux'; -import { addFontToDB, deleteFontFromDB, editFontToDB } from "../../../../../utils/useApis"; -import Custom_Fonts_Icons from "@Common/svg-icons"; - -const EditGFontVariation = ( - { - id, - weight, - font, - isInGoogleState, - addWeight, - removeWeight, - disable - } -) => { - - const [removeTitle, setRemoveTitle] = useState( __( 'Remove', 'custom-fonts' ) ); - const [addTitle, setAddTitle] = useState( __( 'Add', 'custom-fonts' ) ); - - useEffect(() => { - if (!disable) { - setRemoveTitle( __( 'Remove', 'custom-fonts' ) ); - setAddTitle( __( 'Add', 'custom-fonts' ) ); - } - }, [disable]); - - const getFontWeightTitle = ( weight ) => { - if ( undefined === weight ) { - weight = '400'; - } - let updatedWeight = weight, - oldWeight = weight; - if ( 'italic' === weight ) { - oldWeight = '400italic'; - } - if ( oldWeight.includes('italic') ) { - updatedWeight = `${oldWeight.replace('italic', '')} ` + __( 'Italic', 'custom-fonts' ); - } - switch ( weight ) { - case '100': - case '100italic': - return __( 'Thin ', 'custom-fonts' ) + updatedWeight; - case '200': - case '200italic': - return __( 'Extra Light ', 'custom-fonts' ) + updatedWeight; - case '300': - case '300italic': - return __( 'Light ', 'custom-fonts' ) + updatedWeight; - case '400': - case '400italic': - return __( 'Regular ', 'custom-fonts' ) + updatedWeight; - case '500': - case '500italic': - return __( 'Medium ', 'custom-fonts' ) + updatedWeight; - case '600': - case '600italic': - return __( 'Semi Bold ', 'custom-fonts' ) + updatedWeight; - case '700': - case '700italic': - return __( 'Bold ', 'custom-fonts' ) + updatedWeight; - case '800': - case '800italic': - return __( 'Extra Bold ', 'custom-fonts' ) + updatedWeight; - case '900': - case '900italic': - return __( 'Ultra-Bold ', 'custom-fonts' ) + updatedWeight; - default: - return updatedWeight; - } - } - - const getRenderFontWeight = (weight) => { - if ( undefined === weight ) { - weight = '400'; - } - if ( weight.includes('italic') ) { - return weight.replace( "italic", "" ); - } - return weight; - } - - const getFontStyle = (weight) => { - if ( undefined === weight ) { - weight = '400'; - } - if ( weight.includes('italic') ) { - return "italic"; - } - return "normal"; - } - - return ( -
-
-
- {/* Variation Name */} -
- { getFontWeightTitle(weight) } -
- {/* Variation Preview */} -
- {__('How vexingly quick daft zebras jump!', 'custom-fonts')} -
-
-
- {!isInGoogleState && ( - - )} - {isInGoogleState && ( - - )} -
-
-
- ); -}; - -const EditGooglePreviewItem = ( { fontId, fontName, onFontUpdated } ) => { - const dispatch = useDispatch(); - const editFontId = parseInt( fontId ); - - let editingFontData = null; - const [variationToggleStyle, setVariationToggleStyle] = useState(''); - - const restAllData = useSelector( ( state ) => state.fonts ); - const isDbUpdateRequired = useSelector( ( state ) => state.isDbUpdateRequired); - - useEffect(() =>{ - if(isDbUpdateRequired && editFontData){ - if(fontId) editFontData.variations.length !== 0 ? editFontToDB(dispatch, fontId, editFontData, fontUpdated.bind(this, 'edit')) : deleteFontFromDB(dispatch, fontId, fontUpdated.bind(this, 'delete') ); - } - - }, [isDbUpdateRequired]) - - const fontUpdated = (action) => { - if(action === 'delete'){ - dispatch( { type: 'SET_EDIT_FONT', payload: null } ); - } - onFontUpdated(action); - } - - let toBeEditFont = {}; - let variations = null; - restAllData.forEach(function(individualFont) { - if ( editFontId === individualFont.id && undefined !== bsf_custom_fonts_admin.googleFonts[individualFont.title] ) { - const gFontData = bsf_custom_fonts_admin.googleFonts[individualFont.title]; - variations = gFontData[0] ? gFontData[0] : []; - toBeEditFont = individualFont; - } - }); - - if ( undefined === toBeEditFont['fonts-data'] || ! toBeEditFont['fonts-data'].length ) { - editingFontData = toBeEditFont['fonts-data']; - } - - const [editFontData, setEditGoogleFontData] = useState( editingFontData ); - - useEffect( () => { - let newStyle = ''; - Object.keys( editFontData.variations ).map( ( index ) => { - const variationWeight = (editFontData.variations[index].font_weight).toString(); - newStyle += `.gvariations-wrapper > [data-varweight='${variationWeight}'] { display: block }`; - }); - setVariationToggleStyle( newStyle ); - - document.getElementById('gfont-edit-variation-data').innerHTML = ""; - document.getElementById('gfont-edit-variation-data').innerHTML = JSON.stringify( editFontData ); - - dispatch( { type: 'SET_EDIT_FONT', payload: editFontData } ); - }, [editFontData] ); - - if ( null === variations ) { - return; - } - - const getGoogleFontLink = (font, weight, version) => { - const fontName = font.replace( / /g, "+" ); - // valid URL - https://fonts.googleapis.com/css?family=Poppins:100,800&display=fallback&ver=4.1.5 - return `${bsf_custom_fonts_admin.googleFontAPI}=${fontName}:${weight}&display=fallback&ver=${version+1}`; - } - - const addWeight = (e) => { - let varWt; - if (e.target.dataset.font_weight) { - varWt = e.target.dataset.font_weight.toString(); - } else { - return; - } - - const variations = editFontData.variations; - let style = varWt.includes('italic') ? 'italic' : 'normal'; - variations.push({ - id: (variations.length + 1).toString(), - font_file: '', - font_style: style, - font_weight: varWt - }); - - setEditGoogleFontData({ - ...editFontData, - variations: variations, - }); - dispatch({ type: 'IS_DB_UPDATE_REQUIRED', payload: { isDbUpdateRequired: true, editType: 'add' } }); - } - - const removeWeight = (e) => { - let varWt; - if (e.target.dataset.font_weight) { - varWt = e.target.dataset.font_weight.toString(); - } else { - return; - } - - const newVariation = editFontData.variations.filter( - (variation) => variation.font_weight != varWt - ); - - setEditGoogleFontData({ - ...editFontData, - variations: newVariation, - }); - dispatch({ type: 'IS_DB_UPDATE_REQUIRED', payload: { isDbUpdateRequired: true, editType: 'remove' } }); - } - - const checkWeightPresentInState = (weight) => { - if (!editFontData.variations.length) { - return false; - } - - const new_obs = []; - Object.keys(editFontData.variations).map((index) => { - new_obs.push(editFontData.variations[index].font_weight); - }) - - if ( new_obs.includes(weight) ) { - return true; - } - - return false; - } - - return ( - variations && Object.keys( variations ).map( ( key, i ) => ( -
- - - -
- ) ) - ); -} - -export default EditGooglePreviewItem; +import React, { useState, useEffect } from "react"; +import { __ } from "@wordpress/i18n"; +import { useSelector, useDispatch } from 'react-redux'; +import { addFontToDB, deleteFontFromDB, editFontToDB } from "../../../../../utils/useApis"; +import Custom_Fonts_Icons from "@Common/svg-icons"; + +const EditGFontVariation = ( + { + id, + weight, + font, + isInGoogleState, + addWeight, + removeWeight, + disable + } +) => { + + const [removeTitle, setRemoveTitle] = useState( __( 'Remove', 'custom-fonts' ) ); + const [addTitle, setAddTitle] = useState( __( 'Add', 'custom-fonts' ) ); + + useEffect(() => { + if (!disable) { + setRemoveTitle( __( 'Remove', 'custom-fonts' ) ); + setAddTitle( __( 'Add', 'custom-fonts' ) ); + } + }, [disable]); + + const getFontWeightTitle = ( weight ) => { + if ( undefined === weight ) { + weight = '400'; + } + let updatedWeight = weight, + oldWeight = weight; + if ( 'italic' === weight ) { + oldWeight = '400italic'; + } + if ( oldWeight.includes('italic') ) { + updatedWeight = `${oldWeight.replace('italic', '')} ` + __( 'Italic', 'custom-fonts' ); + } + switch ( weight ) { + case '100': + case '100italic': + return __( 'Thin ', 'custom-fonts' ) + updatedWeight; + case '200': + case '200italic': + return __( 'Extra Light ', 'custom-fonts' ) + updatedWeight; + case '300': + case '300italic': + return __( 'Light ', 'custom-fonts' ) + updatedWeight; + case '400': + case '400italic': + return __( 'Regular ', 'custom-fonts' ) + updatedWeight; + case '500': + case '500italic': + return __( 'Medium ', 'custom-fonts' ) + updatedWeight; + case '600': + case '600italic': + return __( 'Semi Bold ', 'custom-fonts' ) + updatedWeight; + case '700': + case '700italic': + return __( 'Bold ', 'custom-fonts' ) + updatedWeight; + case '800': + case '800italic': + return __( 'Extra Bold ', 'custom-fonts' ) + updatedWeight; + case '900': + case '900italic': + return __( 'Ultra-Bold ', 'custom-fonts' ) + updatedWeight; + default: + return updatedWeight; + } + } + + const getRenderFontWeight = (weight) => { + if ( undefined === weight ) { + weight = '400'; + } + if ( weight.includes('italic') ) { + return weight.replace( "italic", "" ); + } + return weight; + } + + const getFontStyle = (weight) => { + if ( undefined === weight ) { + weight = '400'; + } + if ( weight.includes('italic') ) { + return "italic"; + } + return "normal"; + } + + return ( +
+
+
+ {/* Variation Name */} +
+ { getFontWeightTitle(weight) } +
+ {/* Variation Preview */} +
+ {__('How vexingly quick daft zebras jump!', 'custom-fonts')} +
+
+
+ {!isInGoogleState && ( + + )} + {isInGoogleState && ( + + )} +
+
+
+ ); +}; + +const EditGooglePreviewItem = ( { fontId, fontName, onFontUpdated } ) => { + const dispatch = useDispatch(); + const editFontId = parseInt( fontId ); + + let editingFontData = null; + const [variationToggleStyle, setVariationToggleStyle] = useState(''); + + const restAllData = useSelector( ( state ) => state.fonts ); + const isDbUpdateRequired = useSelector( ( state ) => state.isDbUpdateRequired); + + useEffect(() =>{ + if(isDbUpdateRequired && editFontData){ + if(fontId) editFontData.variations.length !== 0 ? editFontToDB(dispatch, fontId, editFontData, fontUpdated.bind(this, 'edit')) : deleteFontFromDB(dispatch, fontId, fontUpdated.bind(this, 'delete') ); + } + + }, [isDbUpdateRequired]) + + const fontUpdated = (action) => { + if(action === 'delete'){ + dispatch( { type: 'SET_EDIT_FONT', payload: null } ); + } + onFontUpdated(action); + } + + let toBeEditFont = {}; + let variations = null; + restAllData.forEach(function(individualFont) { + if ( editFontId === individualFont.id && undefined !== bsf_custom_fonts_admin.googleFonts[individualFont.title] ) { + const gFontData = bsf_custom_fonts_admin.googleFonts[individualFont.title]; + variations = gFontData[0] ? gFontData[0] : []; + toBeEditFont = individualFont; + } + }); + + if ( undefined === toBeEditFont['fonts-data'] || ! toBeEditFont['fonts-data'].length ) { + editingFontData = toBeEditFont['fonts-data']; + } + + const [editFontData, setEditGoogleFontData] = useState( editingFontData ); + + useEffect( () => { + let newStyle = ''; + Object.keys( editFontData.variations ).map( ( index ) => { + const variationWeight = (editFontData.variations[index].font_weight).toString(); + newStyle += `.gvariations-wrapper > [data-varweight='${variationWeight}'] { display: block }`; + }); + setVariationToggleStyle( newStyle ); + + document.getElementById('gfont-edit-variation-data').innerHTML = ""; + document.getElementById('gfont-edit-variation-data').innerHTML = JSON.stringify( editFontData ); + + dispatch( { type: 'SET_EDIT_FONT', payload: editFontData } ); + }, [editFontData] ); + + if ( null === variations ) { + return; + } + + const getGoogleFontLink = (font, weight, version) => { + const fontName = font.replace( / /g, "+" ); + // valid URL - https://fonts.googleapis.com/css?family=Poppins:100,800&display=fallback&ver=4.1.5 + return `${bsf_custom_fonts_admin.googleFontAPI}=${fontName}:${weight}&display=fallback&ver=${version+1}`; + } + + const addWeight = (e) => { + let varWt; + if (e.target.dataset.font_weight) { + varWt = e.target.dataset.font_weight.toString(); + } else { + return; + } + + const variations = editFontData.variations; + let style = varWt.includes('italic') ? 'italic' : 'normal'; + variations.push({ + id: (variations.length + 1).toString(), + font_file: '', + font_style: style, + font_weight: varWt + }); + + setEditGoogleFontData({ + ...editFontData, + variations: variations, + }); + dispatch({ type: 'IS_DB_UPDATE_REQUIRED', payload: { isDbUpdateRequired: true, editType: 'add' } }); + } + + const removeWeight = (e) => { + let varWt; + if (e.target.dataset.font_weight) { + varWt = e.target.dataset.font_weight.toString(); + } else { + return; + } + + const newVariation = editFontData.variations.filter( + (variation) => variation.font_weight != varWt + ); + + setEditGoogleFontData({ + ...editFontData, + variations: newVariation, + }); + dispatch({ type: 'IS_DB_UPDATE_REQUIRED', payload: { isDbUpdateRequired: true, editType: 'remove' } }); + } + + const checkWeightPresentInState = (weight) => { + if (!editFontData.variations.length) { + return false; + } + + const new_obs = []; + Object.keys(editFontData.variations).map((index) => { + new_obs.push(editFontData.variations[index].font_weight); + }) + + if ( new_obs.includes(weight) ) { + return true; + } + + return false; + } + + return ( + variations && Object.keys( variations ).map( ( key, i ) => ( +
+ + + +
+ ) ) + ); +} + +export default EditGooglePreviewItem; diff --git a/admin/dashboard/assets/src/dashboard-app/pages/fonts/preview/GFontVariation.js b/admin/dashboard/assets/src/dashboard-app/pages/fonts/preview/GFontVariation.js index cb81a351..87322c00 100644 --- a/admin/dashboard/assets/src/dashboard-app/pages/fonts/preview/GFontVariation.js +++ b/admin/dashboard/assets/src/dashboard-app/pages/fonts/preview/GFontVariation.js @@ -1,230 +1,230 @@ -import React, { useEffect, useState } from "react"; -import { useSelector, useDispatch } from 'react-redux'; -import { __ } from "@wordpress/i18n"; -import Custom_Fonts_Icons from "@Common/svg-icons"; - -const GFontVariation = (props) => { - const { weight, font, isInGoogleState, disable } = props; - const googleFont = useSelector( ( state ) => state.googleFont ); - const dispatch = useDispatch(); - const [removeTitle, setRemoveTitle] = useState( __( 'Remove', 'custom-fonts' ) ); - const [addTitle, setAddTitle] = useState( __( 'Add', 'custom-fonts' ) ); - - useEffect(() => { - if (!disable) { - setRemoveTitle( __( 'Remove', 'custom-fonts' ) ); - setAddTitle( __( 'Add', 'custom-fonts' ) ); - } - }, [disable]); - - const getFontWeightTitle = ( weight ) => { - if ( undefined === weight ) { - weight = '400'; - } - let updatedWeight = weight, - oldWeight = weight; - if ( 'italic' === weight ) { - oldWeight = '400italic'; - } - if ( oldWeight.includes('italic') ) { - updatedWeight = `${oldWeight.replace('italic', '')} ` + __( 'Italic', 'custom-fonts' ); - } - switch ( weight ) { - case '100': - case '100italic': - return __( 'Thin ', 'custom-fonts' ) + updatedWeight; - case '200': - case '200italic': - return __( 'Extra Light ', 'custom-fonts' ) + updatedWeight; - case '300': - case '300italic': - return __( 'Light ', 'custom-fonts' ) + updatedWeight; - case '400': - case '400italic': - return __( 'Regular ', 'custom-fonts' ) + updatedWeight; - case '500': - case '500italic': - return __( 'Medium ', 'custom-fonts' ) + updatedWeight; - case '600': - case '600italic': - return __( 'Semi Bold ', 'custom-fonts' ) + updatedWeight; - case '700': - case '700italic': - return __( 'Bold ', 'custom-fonts' ) + updatedWeight; - case '800': - case '800italic': - return __( 'Extra Bold ', 'custom-fonts' ) + updatedWeight; - case '900': - case '900italic': - return __( 'Ultra-Bold ', 'custom-fonts' ) + updatedWeight; - default: - return updatedWeight; - } - } - - const addWeight = (e) => { - e.preventDefault(); - e.stopPropagation(); - setRemoveTitle( __( 'Adding...', 'custom-fonts' ) ); - - const varWt = e.target.dataset.font_weight; - const variations = googleFont.variations; - if ( undefined === varWt ) { - return; - } - let style = varWt.includes('italic') ? 'italic' : 'normal'; - variations.push( { - id: variations.length+1, - font_file: '', - font_style: style, - font_weight: varWt, - }); - dispatch({ - type: "SET_GOOGLE_FONT", - payload: { - font_name: googleFont.font_name, - font_fallback: googleFont.font_fallback, - font_display: googleFont.font_display, - variations: variations, - }, - }); - dispatch({ type: "IS_DB_UPDATE_REQUIRED", payload: {isDbUpdateRequired: true, editType: 'add' }}); - }; - - const removeWeight = (e) => { - e.preventDefault(); - e.stopPropagation(); - setAddTitle( __( 'Removing...', 'custom-fonts' ) ); - - const updatedVariations = googleFont.variations.filter( - (variation) => variation.font_weight !== weight - ); - - dispatch({ - type: "SET_GOOGLE_FONT", - payload: { - font_name: googleFont.font_name ? googleFont.font_name : "", - font_fallback: googleFont.font_fallback ? googleFont.font_fallback : "", - font_display: googleFont.font_display ? googleFont.font_display : "", - variations: updatedVariations, - }, - }); - - dispatch({ type: "IS_DB_UPDATE_REQUIRED", payload: { isDbUpdateRequired: true, editType: 'remove' }}); - }; - - const getRenderFontWeight = (weight) => { - if ( undefined === weight ) { - weight = '400'; - } - if ( weight.includes('italic') ) { - return weight.replace( "italic", "" ); - } - return weight; - } - - const getFontStyle = (weight) => { - if ( undefined === weight ) { - weight = '400'; - } - if ( weight.includes('italic') ) { - return 'italic'; - } else { - return 'normal'; - } - } - - return ( -
-
-
- {/* Variation Name */} -
- { getFontWeightTitle(weight) } -
- {/* Variation Preview */} -
- {__('How vexingly quick daft zebras jump!', 'custom-fonts')} -
-
-
- {!isInGoogleState && ( - - )} - {isInGoogleState && ( - - )} -
-
-
- ); -}; - -export default GFontVariation; +import React, { useEffect, useState } from "react"; +import { useSelector, useDispatch } from 'react-redux'; +import { __ } from "@wordpress/i18n"; +import Custom_Fonts_Icons from "@Common/svg-icons"; + +const GFontVariation = (props) => { + const { weight, font, isInGoogleState, disable } = props; + const googleFont = useSelector( ( state ) => state.googleFont ); + const dispatch = useDispatch(); + const [removeTitle, setRemoveTitle] = useState( __( 'Remove', 'custom-fonts' ) ); + const [addTitle, setAddTitle] = useState( __( 'Add', 'custom-fonts' ) ); + + useEffect(() => { + if (!disable) { + setRemoveTitle( __( 'Remove', 'custom-fonts' ) ); + setAddTitle( __( 'Add', 'custom-fonts' ) ); + } + }, [disable]); + + const getFontWeightTitle = ( weight ) => { + if ( undefined === weight ) { + weight = '400'; + } + let updatedWeight = weight, + oldWeight = weight; + if ( 'italic' === weight ) { + oldWeight = '400italic'; + } + if ( oldWeight.includes('italic') ) { + updatedWeight = `${oldWeight.replace('italic', '')} ` + __( 'Italic', 'custom-fonts' ); + } + switch ( weight ) { + case '100': + case '100italic': + return __( 'Thin ', 'custom-fonts' ) + updatedWeight; + case '200': + case '200italic': + return __( 'Extra Light ', 'custom-fonts' ) + updatedWeight; + case '300': + case '300italic': + return __( 'Light ', 'custom-fonts' ) + updatedWeight; + case '400': + case '400italic': + return __( 'Regular ', 'custom-fonts' ) + updatedWeight; + case '500': + case '500italic': + return __( 'Medium ', 'custom-fonts' ) + updatedWeight; + case '600': + case '600italic': + return __( 'Semi Bold ', 'custom-fonts' ) + updatedWeight; + case '700': + case '700italic': + return __( 'Bold ', 'custom-fonts' ) + updatedWeight; + case '800': + case '800italic': + return __( 'Extra Bold ', 'custom-fonts' ) + updatedWeight; + case '900': + case '900italic': + return __( 'Ultra-Bold ', 'custom-fonts' ) + updatedWeight; + default: + return updatedWeight; + } + } + + const addWeight = (e) => { + e.preventDefault(); + e.stopPropagation(); + setRemoveTitle( __( 'Adding...', 'custom-fonts' ) ); + + const varWt = e.target.dataset.font_weight; + const variations = googleFont.variations; + if ( undefined === varWt ) { + return; + } + let style = varWt.includes('italic') ? 'italic' : 'normal'; + variations.push( { + id: variations.length+1, + font_file: '', + font_style: style, + font_weight: varWt, + }); + dispatch({ + type: "SET_GOOGLE_FONT", + payload: { + font_name: googleFont.font_name, + font_fallback: googleFont.font_fallback, + font_display: googleFont.font_display, + variations: variations, + }, + }); + dispatch({ type: "IS_DB_UPDATE_REQUIRED", payload: {isDbUpdateRequired: true, editType: 'add' }}); + }; + + const removeWeight = (e) => { + e.preventDefault(); + e.stopPropagation(); + setAddTitle( __( 'Removing...', 'custom-fonts' ) ); + + const updatedVariations = googleFont.variations.filter( + (variation) => variation.font_weight !== weight + ); + + dispatch({ + type: "SET_GOOGLE_FONT", + payload: { + font_name: googleFont.font_name ? googleFont.font_name : "", + font_fallback: googleFont.font_fallback ? googleFont.font_fallback : "", + font_display: googleFont.font_display ? googleFont.font_display : "", + variations: updatedVariations, + }, + }); + + dispatch({ type: "IS_DB_UPDATE_REQUIRED", payload: { isDbUpdateRequired: true, editType: 'remove' }}); + }; + + const getRenderFontWeight = (weight) => { + if ( undefined === weight ) { + weight = '400'; + } + if ( weight.includes('italic') ) { + return weight.replace( "italic", "" ); + } + return weight; + } + + const getFontStyle = (weight) => { + if ( undefined === weight ) { + weight = '400'; + } + if ( weight.includes('italic') ) { + return 'italic'; + } else { + return 'normal'; + } + } + + return ( +
+
+
+ {/* Variation Name */} +
+ { getFontWeightTitle(weight) } +
+ {/* Variation Preview */} +
+ {__('How vexingly quick daft zebras jump!', 'custom-fonts')} +
+
+
+ {!isInGoogleState && ( + + )} + {isInGoogleState && ( + + )} +
+
+
+ ); +}; + +export default GFontVariation; diff --git a/admin/dashboard/assets/src/dashboard-app/pages/welcome/Settings.js b/admin/dashboard/assets/src/dashboard-app/pages/welcome/Settings.js index dc367399..0bc08750 100644 --- a/admin/dashboard/assets/src/dashboard-app/pages/welcome/Settings.js +++ b/admin/dashboard/assets/src/dashboard-app/pages/welcome/Settings.js @@ -1,85 +1,85 @@ -import React, { useState } from "react"; -import { __ } from "@wordpress/i18n"; -import { Switch } from '@headlessui/react'; -import apiFetch from '@wordpress/api-fetch'; -import { useSelector, useDispatch } from 'react-redux'; - -const Settings = () => { - const preloading = useSelector( ( state ) => state.optionPreload ); - const [isChecked, updateCheck] = useState( '1' === preloading || true === preloading ? true : false ); - const dispatch = useDispatch(); - - const preloadingUpdate = () => { - updateCheck( ! isChecked ); - const formData = new window.FormData(); - formData.append( 'action', 'bcf_preloading' ); - formData.append( 'security', bsf_custom_fonts_admin.preload_font_nonce ); - formData.append( 'isPreloading', ! isChecked ); - - apiFetch({ - url: bsf_custom_fonts_admin.ajax_url, - method: 'POST', - body: formData, - }) - .then((response) => { - if (response.success) { - dispatch({ - type: 'UPDATE_PRELOADING', - payload: !isChecked, - }); - } - }) - .catch((error) => { - console.error('Error during API request:', error); - dispatch({ - type: 'API_REQUEST_FAILED', - payload: error.message || 'An error occurred. Please try again.', - }); - }); - }; - - const classNames = (...classes) => { - return classes.filter(Boolean).join(' ') - } - return ( -
-

- { __( 'Global Settings', 'custom-fonts' ) } -

-
- -

{ __( 'Preloading your font file will speeds up your website.', 'custom-fonts' ) }

-
-
- ); -}; - -export default Settings; +import React, { useState } from "react"; +import { __ } from "@wordpress/i18n"; +import { Switch } from '@headlessui/react'; +import apiFetch from '@wordpress/api-fetch'; +import { useSelector, useDispatch } from 'react-redux'; + +const Settings = () => { + const preloading = useSelector( ( state ) => state.optionPreload ); + const [isChecked, updateCheck] = useState( '1' === preloading || true === preloading ? true : false ); + const dispatch = useDispatch(); + + const preloadingUpdate = () => { + updateCheck( ! isChecked ); + const formData = new window.FormData(); + formData.append( 'action', 'bcf_preloading' ); + formData.append( 'security', bsf_custom_fonts_admin.preload_font_nonce ); + formData.append( 'isPreloading', ! isChecked ); + + apiFetch({ + url: bsf_custom_fonts_admin.ajax_url, + method: 'POST', + body: formData, + }) + .then((response) => { + if (response.success) { + dispatch({ + type: 'UPDATE_PRELOADING', + payload: !isChecked, + }); + } + }) + .catch((error) => { + console.error('Error during API request:', error); + dispatch({ + type: 'API_REQUEST_FAILED', + payload: error.message || 'An error occurred. Please try again.', + }); + }); + }; + + const classNames = (...classes) => { + return classes.filter(Boolean).join(' ') + } + return ( +
+

+ { __( 'Global Settings', 'custom-fonts' ) } +

+
+ +

{ __( 'Preloading your font file will speeds up your website.', 'custom-fonts' ) }

+
+
+ ); +}; + +export default Settings; diff --git a/admin/dashboard/includes/class-bsf-custom-fonts-admin-ajax.php b/admin/dashboard/includes/class-bsf-custom-fonts-admin-ajax.php index 143d585b..298a2e6a 100644 --- a/admin/dashboard/includes/class-bsf-custom-fonts-admin-ajax.php +++ b/admin/dashboard/includes/class-bsf-custom-fonts-admin-ajax.php @@ -1,341 +1,341 @@ -errors = array( - 'permission' => __( 'Sorry, you are not allowed to do this operation.', 'custom-fonts' ), - 'nonce' => __( 'Nonce validation failed', 'custom-fonts' ), - 'default' => __( 'Sorry, something went wrong.', 'custom-fonts' ), - 'invalid' => __( 'No post data found!', 'custom-fonts' ), - ); - - $ajax_events = array( - 'bcf_add_new_local_font', - 'bcf_add_new_google_font', - 'bcf_delete_font', - 'bcf_edit_font', - 'bcf_preloading', - ); - - foreach ( $ajax_events as $key => $event ) { - add_action( 'wp_ajax_' . $event, array( $this, $event ) ); - } - } - - /** - * Get ajax error message. - * - * @param string $type Message type. - * @return string - * @since 4.0.0 - */ - public function get_error_msg( $type ) { - - if ( ! isset( $this->errors[ $type ] ) ) { - $type = 'default'; - } - - return $this->errors[ $type ]; - } - - /** - * Create the local font post. - * - * @since 2.0.0 - */ - public function bcf_add_new_local_font() { - - $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); - - if ( ! current_user_can( 'edit_theme_options' ) ) { - wp_send_json_error( $response_data ); - } - - /** - * Nonce verification - */ - if ( ! check_ajax_referer( 'add_font_nonce', 'security', false ) ) { - $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); - wp_send_json_error( $response_data ); - } - - $font_data = isset( $_POST['font_data'] ) ? bcf_sanitize_text_field_recursive( json_decode( stripslashes( $_POST['font_data'] ), true ) ) : array(); - $font_variations = ! empty( $font_data['variations'] ) ? $font_data['variations'] : array(); - $font_type = ! empty( $_POST['font_type'] ) ? sanitize_text_field( $_POST['font_type'] ) : 'local'; - - if ( empty( $font_variations ) ) { - $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); - wp_send_json_error( $response_data ); - } - - // Create post object. - $new_font_post = array( - 'post_title' => ! empty( $font_data['font_name'] ) ? $font_data['font_name'] : 'untitled', - 'post_status' => 'publish', - 'post_type' => BSF_CUSTOM_FONTS_POST_TYPE, - ); - - // Insert the post into the database. - $font_post_id = wp_insert_post( $new_font_post ); - - if ( is_wp_error( $font_post_id ) ) { - $response_data = array( 'message' => $font_post_id->get_error_message() ); - wp_send_json_error( $response_data ); - } - - $font_face = bcf_get_font_face_css( $font_post_id, $font_data ); - - update_post_meta( $font_post_id, 'fonts-data', $font_data ); - update_post_meta( $font_post_id, 'fonts-face', $font_face ); - update_post_meta( $font_post_id, 'font-type', $font_type ); - - /** - * Send the response. - */ - $response_data = array( - 'message' => __( 'Successfully created the Font!', 'custom-fonts' ), - ); - wp_send_json_success( $response_data ); - } - - /** - * Create the Google font post. - * - * @since 2.0.0 - */ - public function bcf_add_new_google_font() { - - $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); - - if ( ! current_user_can( 'edit_theme_options' ) ) { - wp_send_json_error( $response_data ); - } - - /** - * Nonce verification - */ - if ( ! check_ajax_referer( 'add_font_nonce', 'security', false ) ) { - $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); - wp_send_json_error( $response_data ); - } - - $font_data = isset( $_POST['font_data'] ) ? bcf_sanitize_text_field_recursive( json_decode( stripslashes( $_POST['font_data'] ), true ) ) : array(); - $font_type = ! empty( $_POST['font_type'] ) ? sanitize_text_field( $_POST['font_type'] ) : 'local'; - - if ( empty( $font_data ) ) { - $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); - wp_send_json_error( $response_data ); - } - - // Create post object. - $new_font_post = array( - 'post_title' => ! empty( $font_data['font_name'] ) ? $font_data['font_name'] : 'untitled', - 'post_status' => 'publish', - 'post_type' => BSF_CUSTOM_FONTS_POST_TYPE, - ); - - // Insert the post into the database. - $font_post_id = wp_insert_post( $new_font_post ); - - if ( 'google' === $font_type ) { - $font_face = bcf_google_fonts_compatibility()->process_google_fonts_locally( $font_data ); - } else { - $font_face = bcf_get_font_face_css( $font_post_id, $font_data, true, false ); - } - - if ( is_wp_error( $font_post_id ) ) { - $response_data = array( 'message' => $font_post_id->get_error_message() ); - wp_send_json_error( $response_data ); - } - - update_post_meta( $font_post_id, 'fonts-data', $font_data ); - update_post_meta( $font_post_id, 'fonts-face', $font_face ); - update_post_meta( $font_post_id, 'font-type', $font_type ); - - /** - * Send the response. - */ - $response_data = array( - 'message' => __( 'Successfully created the Font! ', 'custom-fonts' ), - 'fontId' => $font_post_id, - ); - wp_send_json_success( $response_data ); - } - - /** - * Edit the existing font post. - * - * @since 2.0.0 - */ - public function bcf_edit_font() { - - $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); - - if ( ! current_user_can( 'edit_theme_options' ) ) { - wp_send_json_error( $response_data ); - } - - /** - * Nonce verification - */ - if ( ! check_ajax_referer( 'edit_font_nonce', 'security', false ) ) { - $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); - wp_send_json_error( $response_data ); - } - - $font_data = isset( $_POST['font_data'] ) ? bcf_sanitize_text_field_recursive( json_decode( stripslashes( $_POST['font_data'] ), true ) ) : array(); - $font_variations = ! empty( $font_data['variations'] ) ? $font_data['variations'] : array(); - $font_type = ! empty( $_POST['font_type'] ) ? sanitize_text_field( $_POST['font_type'] ) : 'local'; - $font_id = ! empty( $_POST['font_id'] ) ? absint( $_POST['font_id'] ) : false; - - if ( empty( $font_variations ) || false === $font_id ) { - $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); - wp_send_json_error( $response_data ); - } - - if ( 'google' === $font_type ) { - $font_face = bcf_google_fonts_compatibility()->process_google_fonts_locally( $font_data ); - } else { - $font_face = bcf_get_font_face_css( $font_id, $font_data, true, false ); - } - - update_post_meta( $font_id, 'fonts-data', $font_data ); - update_post_meta( $font_id, 'fonts-face', $font_face ); - update_post_meta( $font_id, 'font-type', $font_type ); - - /** - * Send the response. - */ - $response_data = array( - 'message' => __( 'Successfully updated the Font!', 'custom-fonts' ), - ); - wp_send_json_success( $response_data ); - } - - /** - * Delete the font post. - * - * @since 2.0.0 - */ - public function bcf_delete_font() { - $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); - - if ( ! current_user_can( 'edit_theme_options' ) ) { - wp_send_json_error( $response_data ); - } - - /** - * Nonce verification - */ - if ( ! check_ajax_referer( 'delete_font_nonce', 'security', false ) ) { - $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); - wp_send_json_error( $response_data ); - } - - $font_id = isset( $_POST['font_id'] ) ? absint( $_POST['font_id'] ) : 0; - - if ( ! $font_id ) { - $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); - wp_send_json_error( $response_data ); - } - - if ( BSF_CUSTOM_FONTS_POST_TYPE !== get_post_type( $font_id ) ) { - $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); - wp_send_json_error( $response_data ); - } - - $delete_post_response = wp_delete_post( $font_id ); - - if ( ! is_object( $delete_post_response ) ) { - $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); - wp_send_json_error( $response_data ); - } - - $response_data = array( - 'message' => __( 'Successfully deleted the Font!', 'custom-fonts' ), - ); - wp_send_json_success( $response_data ); - } - - /** - * Preloading the fonts. - * - * @since x.x.x - */ - public function bcf_preloading() { - $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); - - if ( ! current_user_can( 'edit_theme_options' ) ) { - wp_send_json_error( $response_data ); - } - - /** - * Nonce verification - */ - if ( ! check_ajax_referer( 'preload_font_nonce', 'security', false ) ) { - $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); - wp_send_json_error( $response_data ); - } - - $checked = isset( $_POST['isPreloading'] ) && 'true' === $_POST['isPreloading'] ? true : false; - update_option( 'bcf_preloading_fonts', $checked ); - - $response_data = array( - 'message' => __( 'Switched preloading fonts!', 'custom-fonts' ), - ); - wp_send_json_success( $response_data ); - } -} - -BSF_Custom_Fonts_Admin_Ajax::get_instance(); +errors = array( + 'permission' => __( 'Sorry, you are not allowed to do this operation.', 'custom-fonts' ), + 'nonce' => __( 'Nonce validation failed', 'custom-fonts' ), + 'default' => __( 'Sorry, something went wrong.', 'custom-fonts' ), + 'invalid' => __( 'No post data found!', 'custom-fonts' ), + ); + + $ajax_events = array( + 'bcf_add_new_local_font', + 'bcf_add_new_google_font', + 'bcf_delete_font', + 'bcf_edit_font', + 'bcf_preloading', + ); + + foreach ( $ajax_events as $key => $event ) { + add_action( 'wp_ajax_' . $event, array( $this, $event ) ); + } + } + + /** + * Get ajax error message. + * + * @param string $type Message type. + * @return string + * @since 4.0.0 + */ + public function get_error_msg( $type ) { + + if ( ! isset( $this->errors[ $type ] ) ) { + $type = 'default'; + } + + return $this->errors[ $type ]; + } + + /** + * Create the local font post. + * + * @since 2.0.0 + */ + public function bcf_add_new_local_font() { + + $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); + + if ( ! current_user_can( 'edit_theme_options' ) ) { + wp_send_json_error( $response_data ); + } + + /** + * Nonce verification + */ + if ( ! check_ajax_referer( 'add_font_nonce', 'security', false ) ) { + $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); + wp_send_json_error( $response_data ); + } + + $font_data = isset( $_POST['font_data'] ) ? bcf_sanitize_text_field_recursive( json_decode( stripslashes( $_POST['font_data'] ), true ) ) : array(); + $font_variations = ! empty( $font_data['variations'] ) ? $font_data['variations'] : array(); + $font_type = ! empty( $_POST['font_type'] ) ? sanitize_text_field( $_POST['font_type'] ) : 'local'; + + if ( empty( $font_variations ) ) { + $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); + wp_send_json_error( $response_data ); + } + + // Create post object. + $new_font_post = array( + 'post_title' => ! empty( $font_data['font_name'] ) ? $font_data['font_name'] : 'untitled', + 'post_status' => 'publish', + 'post_type' => BSF_CUSTOM_FONTS_POST_TYPE, + ); + + // Insert the post into the database. + $font_post_id = wp_insert_post( $new_font_post ); + + if ( is_wp_error( $font_post_id ) ) { + $response_data = array( 'message' => $font_post_id->get_error_message() ); + wp_send_json_error( $response_data ); + } + + $font_face = bcf_get_font_face_css( $font_post_id, $font_data ); + + update_post_meta( $font_post_id, 'fonts-data', $font_data ); + update_post_meta( $font_post_id, 'fonts-face', $font_face ); + update_post_meta( $font_post_id, 'font-type', $font_type ); + + /** + * Send the response. + */ + $response_data = array( + 'message' => __( 'Successfully created the Font!', 'custom-fonts' ), + ); + wp_send_json_success( $response_data ); + } + + /** + * Create the Google font post. + * + * @since 2.0.0 + */ + public function bcf_add_new_google_font() { + + $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); + + if ( ! current_user_can( 'edit_theme_options' ) ) { + wp_send_json_error( $response_data ); + } + + /** + * Nonce verification + */ + if ( ! check_ajax_referer( 'add_font_nonce', 'security', false ) ) { + $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); + wp_send_json_error( $response_data ); + } + + $font_data = isset( $_POST['font_data'] ) ? bcf_sanitize_text_field_recursive( json_decode( stripslashes( $_POST['font_data'] ), true ) ) : array(); + $font_type = ! empty( $_POST['font_type'] ) ? sanitize_text_field( $_POST['font_type'] ) : 'local'; + + if ( empty( $font_data ) ) { + $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); + wp_send_json_error( $response_data ); + } + + // Create post object. + $new_font_post = array( + 'post_title' => ! empty( $font_data['font_name'] ) ? $font_data['font_name'] : 'untitled', + 'post_status' => 'publish', + 'post_type' => BSF_CUSTOM_FONTS_POST_TYPE, + ); + + // Insert the post into the database. + $font_post_id = wp_insert_post( $new_font_post ); + + if ( 'google' === $font_type ) { + $font_face = bcf_google_fonts_compatibility()->process_google_fonts_locally( $font_data ); + } else { + $font_face = bcf_get_font_face_css( $font_post_id, $font_data, true, false ); + } + + if ( is_wp_error( $font_post_id ) ) { + $response_data = array( 'message' => $font_post_id->get_error_message() ); + wp_send_json_error( $response_data ); + } + + update_post_meta( $font_post_id, 'fonts-data', $font_data ); + update_post_meta( $font_post_id, 'fonts-face', $font_face ); + update_post_meta( $font_post_id, 'font-type', $font_type ); + + /** + * Send the response. + */ + $response_data = array( + 'message' => __( 'Successfully created the Font! ', 'custom-fonts' ), + 'fontId' => $font_post_id, + ); + wp_send_json_success( $response_data ); + } + + /** + * Edit the existing font post. + * + * @since 2.0.0 + */ + public function bcf_edit_font() { + + $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); + + if ( ! current_user_can( 'edit_theme_options' ) ) { + wp_send_json_error( $response_data ); + } + + /** + * Nonce verification + */ + if ( ! check_ajax_referer( 'edit_font_nonce', 'security', false ) ) { + $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); + wp_send_json_error( $response_data ); + } + + $font_data = isset( $_POST['font_data'] ) ? bcf_sanitize_text_field_recursive( json_decode( stripslashes( $_POST['font_data'] ), true ) ) : array(); + $font_variations = ! empty( $font_data['variations'] ) ? $font_data['variations'] : array(); + $font_type = ! empty( $_POST['font_type'] ) ? sanitize_text_field( $_POST['font_type'] ) : 'local'; + $font_id = ! empty( $_POST['font_id'] ) ? absint( $_POST['font_id'] ) : false; + + if ( empty( $font_variations ) || false === $font_id ) { + $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); + wp_send_json_error( $response_data ); + } + + if ( 'google' === $font_type ) { + $font_face = bcf_google_fonts_compatibility()->process_google_fonts_locally( $font_data ); + } else { + $font_face = bcf_get_font_face_css( $font_id, $font_data, true, false ); + } + + update_post_meta( $font_id, 'fonts-data', $font_data ); + update_post_meta( $font_id, 'fonts-face', $font_face ); + update_post_meta( $font_id, 'font-type', $font_type ); + + /** + * Send the response. + */ + $response_data = array( + 'message' => __( 'Successfully updated the Font!', 'custom-fonts' ), + ); + wp_send_json_success( $response_data ); + } + + /** + * Delete the font post. + * + * @since 2.0.0 + */ + public function bcf_delete_font() { + $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); + + if ( ! current_user_can( 'edit_theme_options' ) ) { + wp_send_json_error( $response_data ); + } + + /** + * Nonce verification + */ + if ( ! check_ajax_referer( 'delete_font_nonce', 'security', false ) ) { + $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); + wp_send_json_error( $response_data ); + } + + $font_id = isset( $_POST['font_id'] ) ? absint( $_POST['font_id'] ) : 0; + + if ( ! $font_id ) { + $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); + wp_send_json_error( $response_data ); + } + + if ( BSF_CUSTOM_FONTS_POST_TYPE !== get_post_type( $font_id ) ) { + $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); + wp_send_json_error( $response_data ); + } + + $delete_post_response = wp_delete_post( $font_id ); + + if ( ! is_object( $delete_post_response ) ) { + $response_data = array( 'message' => $this->get_error_msg( 'invalid' ) ); + wp_send_json_error( $response_data ); + } + + $response_data = array( + 'message' => __( 'Successfully deleted the Font!', 'custom-fonts' ), + ); + wp_send_json_success( $response_data ); + } + + /** + * Preloading the fonts. + * + * @since x.x.x + */ + public function bcf_preloading() { + $response_data = array( 'message' => $this->get_error_msg( 'permission' ) ); + + if ( ! current_user_can( 'edit_theme_options' ) ) { + wp_send_json_error( $response_data ); + } + + /** + * Nonce verification + */ + if ( ! check_ajax_referer( 'preload_font_nonce', 'security', false ) ) { + $response_data = array( 'message' => $this->get_error_msg( 'nonce' ) ); + wp_send_json_error( $response_data ); + } + + $checked = isset( $_POST['isPreloading'] ) && 'true' === $_POST['isPreloading'] ? true : false; + update_option( 'bcf_preloading_fonts', $checked ); + + $response_data = array( + 'message' => __( 'Switched preloading fonts!', 'custom-fonts' ), + ); + wp_send_json_success( $response_data ); + } +} + +BSF_Custom_Fonts_Admin_Ajax::get_instance(); diff --git a/admin/dashboard/includes/class-bsf-custom-fonts-menu.php b/admin/dashboard/includes/class-bsf-custom-fonts-menu.php index f13926fe..03c28244 100644 --- a/admin/dashboard/includes/class-bsf-custom-fonts-menu.php +++ b/admin/dashboard/includes/class-bsf-custom-fonts-menu.php @@ -1,587 +1,587 @@ -initialize_hooks(); - } - - /** - * Init Hooks. - * - * @since 2.0.0 - * @return void - */ - public function initialize_hooks() { - - add_action( 'admin_menu', array( $this, 'register_custom_fonts_menu' ) ); - add_action( 'admin_init', array( $this, 'settings_admin_scripts' ) ); - - add_filter( 'upload_mimes', array( $this, 'add_fonts_to_allowed_mimes' ) ); - add_filter( 'wp_check_filetype_and_ext', array( $this, 'update_mime_types' ), 10, 3 ); - } - - /** - * Register custom font menu - * - * @since 1.0.0 - */ - public function register_custom_fonts_menu() { - $title = apply_filters( 'bsf_custom_fonts_menu_title', _x( 'Custom Fonts', 'Menu title', 'custom-fonts' ) ); - add_theme_page( - $title, - $title, - 'edit_theme_options', - self::$plugin_slug, - array( $this, 'render_admin_dashboard' ) - ); - } - - /** - * Allowed mime types and file extensions - * - * @since 1.0.0 - * @param array $mimes Current array of mime types. - * @return array $mimes Updated array of mime types. - */ - public function add_fonts_to_allowed_mimes( $mimes ) { - $mimes['woff'] = 'application/x-font-woff'; - $mimes['woff2'] = 'application/x-font-woff2'; - $mimes['ttf'] = 'application/x-font-ttf'; - // Allow SVG with additional sanitization. - $mimes['svg'] = 'image/svg+xml'; - $mimes['eot'] = 'application/vnd.ms-fontobject'; - $mimes['otf'] = 'font/otf'; - - return $mimes; - } - - /** - * Sanitizes SVG Code string. - * - * @param string $original_content SVG code to sanitize. - * @return string - * @since x.x.x - * */ - public function sanitize_svg( $original_content ) { - - if ( ! $original_content ) { - return ''; - } - - // Define allowed tags and attributes. - $allowed_tags = array( - 'a', - 'circle', - 'clippath', - 'defs', - 'style', - 'desc', - 'ellipse', - 'fegaussianblur', - 'filter', - 'foreignobject', - 'g', - 'image', - 'line', - 'lineargradient', - 'marker', - 'mask', - 'metadata', - 'path', - 'pattern', - 'polygon', - 'polyline', - 'radialgradient', - 'rect', - 'stop', - 'svg', - 'switch', - 'symbol', - 'text', - 'textpath', - 'title', - 'tspan', - 'use', - ); - - $allowed_attributes = array( - 'class', - 'clip-path', - 'clip-rule', - 'fill', - 'fill-opacity', - 'fill-rule', - 'filter', - 'id', - 'mask', - 'opacity', - 'stroke', - 'stroke-dasharray', - 'stroke-dashoffset', - 'stroke-linecap', - 'stroke-linejoin', - 'stroke-miterlimit', - 'stroke-opacity', - 'stroke-width', - 'style', - 'systemlanguage', - 'transform', - 'href', - 'xlink:href', - 'xlink:title', - 'cx', - 'cy', - 'r', - 'requiredfeatures', - 'clippathunits', - 'type', - 'rx', - 'ry', - 'color-interpolation-filters', - 'stddeviation', - 'filterres', - 'filterunits', - 'height', - 'primitiveunits', - 'width', - 'x', - 'y', - 'font-size', - 'display', - 'font-family', - 'font-style', - 'font-weight', - 'text-anchor', - 'marker-end', - 'marker-mid', - 'marker-start', - 'x1', - 'x2', - 'y1', - 'y2', - 'gradienttransform', - 'gradientunits', - 'spreadmethod', - 'markerheight', - 'markerunits', - 'markerwidth', - 'orient', - 'preserveaspectratio', - 'refx', - 'refy', - 'viewbox', - 'maskcontentunits', - 'maskunits', - 'd', - 'patterncontentunits', - 'patterntransform', - 'patternunits', - 'points', - 'fx', - 'fy', - 'offset', - 'stop-color', - 'stop-opacity', - 'xmlns', - 'xmlns:se', - 'xmlns:xlink', - 'xml:space', - 'method', - 'spacing', - 'startoffset', - 'dx', - 'dy', - 'rotate', - 'textlength', - ); - - $is_encoded = false; - - $needle = "\x1f\x8b\x08"; - // phpcs:disable PHPCompatibility.ParameterValues.NewIconvMbstringCharsetDefault.NotSet - if ( function_exists( 'mb_strpos' ) ) { - $is_encoded = 0 === mb_strpos( $original_content, $needle ); - } else { - $is_encoded = 0 === strpos( $original_content, $needle ); - } - // phpcs:enable PHPCompatibility.ParameterValues.NewIconvMbstringCharsetDefault.NotSet - - // phpcs:disable WordPress.PHP.YodaConditions.NotYoda - if ( $is_encoded ) { - $original_content = gzdecode( $original_content ); - if ( $original_content === false ) { - return ''; - } - } - // phpcs:enable WordPress.PHP.YodaConditions.NotYoda - - // Strip php tags. - $content = preg_replace( '/<\?(=|php)(.+?)\?>/i', '', $original_content ); - $content = preg_replace( '/<\?(.*)\?>/Us', '', $content ); - $content = preg_replace( '/<\%(.*)\%>/Us', '', $content ); - - if ( ( false !== strpos( $content, '/Us', '', $content ); - $content = preg_replace( '/\/\*(.*)\*\//Us', '', $content ); - - if ( ( false !== strpos( $content, '/Us', '', $content ); + $content = preg_replace( '/\/\*(.*)\*\//Us', '', $content ); + + if ( ( false !== strpos( $content, '