Custom Fonts - Version 1.2.2

Version Description

  • New: Users can now share non-personal usage data to help us test and develop better products. ( https://store.brainstormforce.com/usage-tracking/?utm_source=wp_dashboard&utm_medium=general_settings&utm_campaign=usage_tracking )
Download this release

Release Info

Developer brainstormworg
Plugin Icon 128x128 Custom Fonts
Version 1.2.2
Comparing to
See all releases

Code changes from version 1.2.1 to 1.2.2

admin/bsf-analytics/assets/css/minified/style-rtl.min.css ADDED
@@ -0,0 +1 @@
 
1
+ #bsf-optin-notice{padding:1px 12px;border-right-color:#007cba}#bsf-optin-notice .notice-container{padding-top:10px;padding-bottom:12px}#bsf-optin-notice .notice-content{margin:0}#bsf-optin-notice .notice-heading{padding:0 0 12px 20px}#bsf-optin-notice .button-primary{margin-left:5px}
admin/bsf-analytics/assets/css/minified/style.min.css ADDED
@@ -0,0 +1 @@
 
1
+ #bsf-optin-notice{padding:1px 12px;border-left-color:#007cba}#bsf-optin-notice .notice-container{padding-top:10px;padding-bottom:12px}#bsf-optin-notice .notice-content{margin:0}#bsf-optin-notice .notice-heading{padding:0 20px 12px 0}#bsf-optin-notice .button-primary{margin-right:5px}
admin/bsf-analytics/assets/css/unminified/style-rtl.css ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #bsf-optin-notice {
2
+ padding: 1px 12px;
3
+ border-right-color: #007cba;
4
+ }
5
+
6
+ #bsf-optin-notice .notice-container {
7
+ padding-top: 10px;
8
+ padding-bottom: 12px;
9
+ }
10
+
11
+ #bsf-optin-notice .notice-content {
12
+ margin: 0;
13
+ }
14
+
15
+ #bsf-optin-notice .notice-heading {
16
+ padding: 0 0 12px 20px;
17
+ }
18
+
19
+ #bsf-optin-notice .button-primary {
20
+ margin-left: 5px;
21
+ }
admin/bsf-analytics/assets/css/unminified/style.css ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #bsf-optin-notice {
2
+ padding: 1px 12px;
3
+ border-left-color: #007cba;
4
+ }
5
+
6
+ #bsf-optin-notice .notice-container {
7
+ padding-top: 10px;
8
+ padding-bottom: 12px;
9
+ }
10
+
11
+ #bsf-optin-notice .notice-content {
12
+ margin: 0;
13
+ }
14
+
15
+ #bsf-optin-notice .notice-heading {
16
+ padding: 0 20px 12px 0;
17
+ }
18
+
19
+ #bsf-optin-notice .button-primary {
20
+ margin-right: 5px;
21
+ }
admin/bsf-analytics/class-bsf-analytics-stats.php ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * BSF analytics stat class file.
4
+ *
5
+ * @package bsf-analytics
6
+ */
7
+
8
+ if ( ! defined( 'ABSPATH' ) ) {
9
+ exit; // Exit if accessed directly.
10
+ }
11
+
12
+ if ( ! class_exists( 'BSF_Analytics_Stats' ) ) {
13
+ /**
14
+ * BSF analytics stat class.
15
+ */
16
+ class BSF_Analytics_Stats {
17
+
18
+ /**
19
+ * Active plugins.
20
+ *
21
+ * Holds the sites active plugins list.
22
+ *
23
+ * @var array
24
+ */
25
+ private $plugins;
26
+
27
+ /**
28
+ * Instance of BSF_Analytics_Stats.
29
+ *
30
+ * Holds only the first object of class.
31
+ *
32
+ * @var object
33
+ */
34
+ private static $instance = null;
35
+
36
+ /**
37
+ * Create only once instance of a class.
38
+ *
39
+ * @return object
40
+ * @since 1.0.0
41
+ */
42
+ public static function instance() {
43
+ if ( null === self::$instance ) {
44
+ self::$instance = new self();
45
+ }
46
+
47
+ return self::$instance;
48
+ }
49
+
50
+ /**
51
+ * Get stats.
52
+ *
53
+ * @return array stats data.
54
+ * @since 1.0.0
55
+ */
56
+ public function get_stats() {
57
+ return apply_filters( 'bsf_core_stats', $this->get_default_stats() );
58
+ }
59
+
60
+ /**
61
+ * Retrieve stats for site.
62
+ *
63
+ * @return array stats data.
64
+ * @since 1.0.0
65
+ */
66
+ private function get_default_stats() {
67
+ return array(
68
+ 'graupi_version' => defined( 'BSF_UPDATER_VERSION' ) ? BSF_UPDATER_VERSION : false,
69
+ 'domain_name' => get_site_url(),
70
+ 'php_os' => PHP_OS,
71
+ 'server_software' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? filter_var( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ), FILTER_SANITIZE_STRING ) : '',
72
+ 'mysql_version' => $this->get_mysql_version(),
73
+ 'php_version' => $this->get_php_version(),
74
+ 'php_max_input_vars' => ini_get( 'max_input_vars' ), // phpcs:ignore:PHPCompatibility.IniDirectives.NewIniDirectives.max_input_varsFound
75
+ 'php_post_max_size' => ini_get( 'post_max_size' ),
76
+ 'php_max_execution_time' => ini_get( 'max_execution_time' ),
77
+ 'php_memory_limit' => ini_get( 'memory_limit' ),
78
+ 'zip_installed' => extension_loaded( 'zip' ),
79
+ 'imagick_availabile' => extension_loaded( 'imagick' ),
80
+ 'xmlreader_exists' => class_exists( 'XMLReader' ),
81
+ 'gd_available' => extension_loaded( 'gd' ),
82
+ 'curl_version' => $this->get_curl_version(),
83
+ 'curl_ssl_version' => $this->get_curl_ssl_version(),
84
+ 'is_writable' => $this->is_content_writable(),
85
+
86
+ 'wp_version' => get_bloginfo( 'version' ),
87
+ 'user_count' => $this->get_user_count(),
88
+ 'site_language' => get_locale(),
89
+ 'timezone' => wp_timezone_string(),
90
+ 'is_ssl' => is_ssl(),
91
+ 'is_multisite' => is_multisite(),
92
+ 'network_url' => network_site_url(),
93
+ 'external_object_cache' => (bool) wp_using_ext_object_cache(),
94
+ 'wp_debug' => WP_DEBUG,
95
+ 'wp_debug_display' => WP_DEBUG_DISPLAY,
96
+ 'script_debug' => SCRIPT_DEBUG,
97
+
98
+ 'active_plugins' => $this->get_active_plugins(),
99
+
100
+ 'active_theme' => get_template(),
101
+ 'active_stylesheet' => get_stylesheet(),
102
+ );
103
+ }
104
+
105
+ /**
106
+ * Get installed PHP version.
107
+ *
108
+ * @return float PHP version.
109
+ * @since 1.0.0
110
+ */
111
+ private function get_php_version() {
112
+ if ( defined( 'PHP_MAJOR_VERSION' ) && defined( 'PHP_MINOR_VERSION' ) && defined( 'PHP_RELEASE_VERSION' ) ) { // phpcs:ignore
113
+ return PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
114
+ }
115
+
116
+ return phpversion();
117
+ }
118
+
119
+ /**
120
+ * User count on site.
121
+ *
122
+ * @return int User count.
123
+ * @since 1.0.0
124
+ */
125
+ private function get_user_count() {
126
+ if ( is_multisite() ) {
127
+ $user_count = get_user_count();
128
+ } else {
129
+ $count = count_users();
130
+ $user_count = $count['total_users'];
131
+ }
132
+
133
+ return $user_count;
134
+ }
135
+
136
+ /**
137
+ * Get active plugin's data.
138
+ *
139
+ * @return array active plugin's list.
140
+ * @since 1.0.0
141
+ */
142
+ private function get_active_plugins() {
143
+ if ( ! $this->plugins ) {
144
+ // Ensure get_plugin_data function is loaded.
145
+ if ( ! function_exists( 'get_plugin_data' ) ) {
146
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
147
+ }
148
+
149
+ $plugins = wp_get_active_and_valid_plugins();
150
+ $plugins = array_map( 'get_plugin_data', $plugins );
151
+ $this->plugins = array_map( array( $this, 'format_plugin' ), $plugins );
152
+ }
153
+
154
+ return $this->plugins;
155
+ }
156
+
157
+ /**
158
+ * Format plugin data.
159
+ *
160
+ * @param string $plugin plugin.
161
+ * @return array formatted plugin data.
162
+ * @since 1.0.0
163
+ */
164
+ public function format_plugin( $plugin ) {
165
+ return array(
166
+ 'name' => html_entity_decode( $plugin['Name'], ENT_COMPAT, 'UTF-8' ),
167
+ 'url' => $plugin['PluginURI'],
168
+ 'version' => $plugin['Version'],
169
+ 'slug' => $plugin['TextDomain'],
170
+ 'author_name' => html_entity_decode( wp_strip_all_tags( $plugin['Author'] ), ENT_COMPAT, 'UTF-8' ),
171
+ 'author_url' => $plugin['AuthorURI'],
172
+ );
173
+ }
174
+
175
+ /**
176
+ * Curl SSL version.
177
+ *
178
+ * @return float SSL version.
179
+ * @since 1.0.0
180
+ */
181
+ private function get_curl_ssl_version() {
182
+ $curl = array();
183
+ if ( function_exists( 'curl_version' ) ) {
184
+ $curl = curl_version(); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_version
185
+ }
186
+
187
+ return isset( $curl['ssl_version'] ) ? $curl['ssl_version'] : false;
188
+ }
189
+
190
+ /**
191
+ * Get cURL version.
192
+ *
193
+ * @return float cURL version.
194
+ * @since 1.0.0
195
+ */
196
+ private function get_curl_version() {
197
+ if ( function_exists( 'curl_version' ) ) {
198
+ $curl = curl_version(); // phpcs:ignore WordPress.WP.AlternativeFunctions.curl_curl_version
199
+ }
200
+
201
+ return isset( $curl['version'] ) ? $curl['version'] : false;
202
+ }
203
+
204
+ /**
205
+ * Get MySQL version.
206
+ *
207
+ * @return float MySQL version.
208
+ * @since 1.0.0
209
+ */
210
+ private function get_mysql_version() {
211
+ global $wpdb;
212
+ return $wpdb->db_version();
213
+ }
214
+
215
+ /**
216
+ * Check if content directory is writable.
217
+ *
218
+ * @return bool
219
+ * @since 1.0.0
220
+ */
221
+ private function is_content_writable() {
222
+ $upload_dir = wp_upload_dir();
223
+ return wp_is_writable( $upload_dir['basedir'] );
224
+ }
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Polyfill for sites using WP version less than 5.3
230
+ */
231
+ if ( ! function_exists( 'wp_timezone_string' ) ) {
232
+ /**
233
+ * Get timezone string.
234
+ *
235
+ * @return string timezone string.
236
+ * @since 1.0.0
237
+ */
238
+ function wp_timezone_string() {
239
+ $timezone_string = get_option( 'timezone_string' );
240
+
241
+ if ( $timezone_string ) {
242
+ return $timezone_string;
243
+ }
244
+
245
+ $offset = (float) get_option( 'gmt_offset' );
246
+ $hours = (int) $offset;
247
+ $minutes = ( $offset - $hours );
248
+
249
+ $sign = ( $offset < 0 ) ? '-' : '+';
250
+ $abs_hour = abs( $hours );
251
+ $abs_mins = abs( $minutes * 60 );
252
+ $tz_offset = sprintf( '%s%02d:%02d', $sign, $abs_hour, $abs_mins );
253
+
254
+ return $tz_offset;
255
+ }
256
+ }
admin/bsf-analytics/class-bsf-analytics.php ADDED
@@ -0,0 +1,525 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * BSF analytics class file.
4
+ *
5
+ * @version 1.0.0
6
+ *
7
+ * @package bsf-analytics
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
+
14
+ if ( ! class_exists( 'BSF_Analytics' ) ) {
15
+
16
+ /**
17
+ * BSF analytics
18
+ */
19
+ class BSF_Analytics {
20
+
21
+ /**
22
+ * Member Variable
23
+ *
24
+ * @var string Usage tracking document URL
25
+ */
26
+ private $usage_doc_link = 'https://store.brainstormforce.com/usage-tracking/?utm_source=wp_dashboard&utm_medium=general_settings&utm_campaign=usage_tracking';
27
+
28
+ /**
29
+ * Setup actions, load files.
30
+ *
31
+ * @since 1.0.0
32
+ */
33
+ public function __construct() {
34
+
35
+ define( 'BSF_ANALYTICS_FILE', __FILE__ );
36
+ define( 'BSF_ANALYTICS_VERSION', '1.0.2' );
37
+ define( 'BSF_ANALYTICS_PATH', dirname( __FILE__ ) );
38
+ define( 'BSF_ANALYTICS_URI', $this->bsf_analytics_url() );
39
+
40
+ add_action( 'admin_init', array( $this, 'handle_optin_optout' ) );
41
+ add_action( 'cron_schedules', array( $this, 'every_two_days_schedule' ) );
42
+ add_action( 'admin_notices', array( $this, 'option_notice' ) );
43
+ add_action( 'astra_notice_before_markup_bsf-optin-notice', array( $this, 'enqueue_assets' ) );
44
+
45
+ add_action( 'init', array( $this, 'schedule_unschedule_event' ) );
46
+
47
+ if ( ! has_action( 'bsf_analytics_send', array( $this, 'send' ) ) ) {
48
+ add_action( 'bsf_analytics_send', array( $this, 'send' ) );
49
+ }
50
+
51
+ add_action( 'admin_init', array( $this, 'register_usage_tracking_setting' ) );
52
+
53
+ add_action( 'update_option_bsf_analytics_optin', array( $this, 'update_analytics_option_callback' ), 10, 3 );
54
+ add_action( 'add_option_bsf_analytics_optin', array( $this, 'add_analytics_option_callback' ), 10, 2 );
55
+
56
+ $this->includes();
57
+ }
58
+
59
+ /**
60
+ * BSF Analytics URL
61
+ *
62
+ * @return String URL of bsf-analytics directory.
63
+ * @since 1.0.0
64
+ */
65
+ public function bsf_analytics_url() {
66
+
67
+ $path = wp_normalize_path( BSF_ANALYTICS_PATH );
68
+ $theme_dir = wp_normalize_path( get_template_directory() );
69
+
70
+ if ( strpos( $path, $theme_dir ) !== false ) {
71
+ return rtrim( get_template_directory_uri() . '/admin/bsf-analytics/', '/' );
72
+ } else {
73
+ return rtrim( plugin_dir_url( BSF_ANALYTICS_FILE ), '/' );
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Get API URL for sending analytics.
79
+ *
80
+ * @return string API URL.
81
+ * @since 1.0.0
82
+ */
83
+ private function get_api_url() {
84
+ return defined( 'BSF_API_URL' ) ? BSF_API_URL : 'https://support.brainstormforce.com/';
85
+ }
86
+
87
+ /**
88
+ * Enqueue Scripts.
89
+ *
90
+ * @since 1.0.0
91
+ * @return void
92
+ */
93
+ public function enqueue_assets() {
94
+
95
+ /**
96
+ * Load unminified if SCRIPT_DEBUG is true.
97
+ *
98
+ * Directory and Extensions.
99
+ */
100
+ $dir_name = ( SCRIPT_DEBUG ) ? 'unminified' : 'minified';
101
+ $file_rtl = ( is_rtl() ) ? '-rtl' : '';
102
+ $css_ext = ( SCRIPT_DEBUG ) ? '.css' : '.min.css';
103
+
104
+ $css_uri = BSF_ANALYTICS_URI . '/assets/css/' . $dir_name . '/style' . $file_rtl . $css_ext;
105
+
106
+ wp_enqueue_style( 'bsf-analytics-admin-style', $css_uri, false, BSF_ANALYTICS_VERSION, 'all' );
107
+ }
108
+
109
+ /**
110
+ * Send analytics API call.
111
+ *
112
+ * @since 1.0.0
113
+ */
114
+ public function send() {
115
+ wp_remote_post(
116
+ $this->get_api_url() . 'wp-json/bsf-core/v1/analytics/',
117
+ array(
118
+ 'body' => BSF_Analytics_Stats::instance()->get_stats(),
119
+ 'timeout' => 5,
120
+ 'blocking' => false,
121
+ )
122
+ );
123
+ }
124
+
125
+ /**
126
+ * Check if usage tracking is enabled.
127
+ *
128
+ * @return bool
129
+ * @since 1.0.0
130
+ */
131
+ public function is_tracking_enabled() {
132
+ $is_enabled = get_site_option( 'bsf_analytics_optin' ) === 'yes' ? true : false;
133
+ $is_enabled = $this->is_white_label_enabled() ? false : $is_enabled;
134
+
135
+ return apply_filters( 'bsf_tracking_enabled', $is_enabled );
136
+ }
137
+
138
+ /**
139
+ * Check if WHITE label is enabled for BSF products.
140
+ *
141
+ * @return bool
142
+ * @since 1.0.0
143
+ */
144
+ public function is_white_label_enabled() {
145
+
146
+ $options = apply_filters( 'bsf_white_label_options', array() );
147
+ $is_enabled = false;
148
+
149
+ if ( is_array( $options ) ) {
150
+ foreach ( $options as $option ) {
151
+ if ( true === $option ) {
152
+ $is_enabled = true;
153
+ break;
154
+ }
155
+ }
156
+ }
157
+
158
+ return $is_enabled;
159
+ }
160
+
161
+ /**
162
+ * Display admin notice for usage tracking.
163
+ *
164
+ * @since 1.0.0
165
+ */
166
+ public function option_notice() {
167
+
168
+ if ( ! current_user_can( 'manage_options' ) ) {
169
+ return;
170
+ }
171
+
172
+ // Don't display the notice if tracking is disabled or White Label is enabled for any of our plugins.
173
+ if ( false !== get_site_option( 'bsf_analytics_optin', false ) || $this->is_white_label_enabled() ) {
174
+ return;
175
+ }
176
+
177
+ // Show tracker consent notice after 24 hours from installed time.
178
+ if ( strtotime( '+24 hours', $this->get_analytics_install_time() ) > time() ) {
179
+ return;
180
+ }
181
+
182
+ /* translators: %s product name */
183
+ $notice_string = __( 'Want to help make <strong>%1s</strong> even more awesome? Allow us to collect non-sensitive diagnostic data and usage information. ', 'custom-fonts' );
184
+
185
+ if ( is_multisite() ) {
186
+ $notice_string .= __( 'This will be applicable for all sites from the network.', 'custom-fonts' );
187
+ }
188
+
189
+ $language_dir = is_rtl() ? 'rtl' : 'ltr';
190
+
191
+ Astra_Notices::add_notice(
192
+ array(
193
+ 'id' => 'bsf-optin-notice',
194
+ 'type' => '',
195
+ 'message' => sprintf(
196
+ '<div class="notice-content">
197
+ <div class="notice-heading">
198
+ %1$s
199
+ </div>
200
+ <div class="astra-notices-container">
201
+ <a href="%2$s" class="astra-notices button-primary">
202
+ %3$s
203
+ </a>
204
+ <a href="%4$s" data-repeat-notice-after="%5$s" class="astra-notices button-secondary">
205
+ %6$s
206
+ </a>
207
+ </div>
208
+ </div>',
209
+ /* translators: %s usage doc link */
210
+ sprintf( $notice_string . '<span dir="%2s"><a href="%3s" target="_blank" rel="noreferrer noopener">%4s</a><span>', esc_html( $this->get_product_name() ), $language_dir, esc_url( $this->usage_doc_link ), __( ' Know More.', 'custom-fonts' ) ),
211
+ add_query_arg(
212
+ array(
213
+ 'bsf_analytics_optin' => 'yes',
214
+ 'bsf_analytics_nonce' => wp_create_nonce( 'bsf_analytics_optin' ),
215
+ )
216
+ ),
217
+ __( 'Yes! Allow it', 'custom-fonts' ),
218
+ add_query_arg(
219
+ array(
220
+ 'bsf_analytics_optin' => 'no',
221
+ 'bsf_analytics_nonce' => wp_create_nonce( 'bsf_analytics_optin' ),
222
+ )
223
+ ),
224
+ MONTH_IN_SECONDS,
225
+ __( 'No Thanks', 'custom-fonts' )
226
+ ),
227
+ 'show_if' => true,
228
+ 'repeat-notice-after' => false,
229
+ 'priority' => 18,
230
+ 'display-with-other-notices' => true,
231
+ )
232
+ );
233
+ }
234
+
235
+ /**
236
+ * Process usage tracking opt out.
237
+ *
238
+ * @since 1.0.0
239
+ */
240
+ public function handle_optin_optout() {
241
+ if ( ! isset( $_GET['bsf_analytics_nonce'] ) ) {
242
+ return;
243
+ }
244
+
245
+ if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['bsf_analytics_nonce'] ) ), 'bsf_analytics_optin' ) ) {
246
+ return;
247
+ }
248
+
249
+ $optin_status = isset( $_GET['bsf_analytics_optin'] ) ? sanitize_text_field( wp_unslash( $_GET['bsf_analytics_optin'] ) ) : '';
250
+
251
+ if ( 'yes' === $optin_status ) {
252
+ $this->optin();
253
+ } elseif ( 'no' === $optin_status ) {
254
+ $this->optout();
255
+ }
256
+
257
+ wp_safe_redirect(
258
+ remove_query_arg(
259
+ array(
260
+ 'bsf_analytics_optin',
261
+ 'bsf_analytics_nonce',
262
+ )
263
+ )
264
+ );
265
+ }
266
+
267
+ /**
268
+ * Opt in to usage tracking.
269
+ *
270
+ * @since 1.0.0
271
+ */
272
+ private function optin() {
273
+ update_site_option( 'bsf_analytics_optin', 'yes' );
274
+ }
275
+
276
+ /**
277
+ * Opt out to usage tracking.
278
+ *
279
+ * @since 1.0.0
280
+ */
281
+ private function optout() {
282
+ update_site_option( 'bsf_analytics_optin', 'no' );
283
+ }
284
+
285
+ /**
286
+ * Add two days event schedule variables.
287
+ *
288
+ * @param array $schedules scheduled array data.
289
+ * @since 1.0.0
290
+ */
291
+ public function every_two_days_schedule( $schedules ) {
292
+ $schedules['every_two_days'] = array(
293
+ 'interval' => 2 * DAY_IN_SECONDS,
294
+ 'display' => __( 'Every two days', 'custom-fonts' ),
295
+ );
296
+
297
+ return $schedules;
298
+ }
299
+
300
+ /**
301
+ * Schedule usage tracking event.
302
+ *
303
+ * @since 1.0.0
304
+ */
305
+ private function schedule_event() {
306
+ if ( ! wp_next_scheduled( 'bsf_analytics_send' ) && $this->is_tracking_enabled() ) {
307
+ wp_schedule_event( time(), 'every_two_days', 'bsf_analytics_send' );
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Unschedule usage tracking event.
313
+ *
314
+ * @since 1.0.0
315
+ */
316
+ private function unschedule_event() {
317
+ wp_clear_scheduled_hook( 'bsf_analytics_send' );
318
+ }
319
+
320
+ /**
321
+ * Load analytics stat class.
322
+ *
323
+ * @since 1.0.0
324
+ */
325
+ private function includes() {
326
+ require_once __DIR__ . '/class-bsf-analytics-stats.php';
327
+ }
328
+
329
+ /**
330
+ * Register usage tracking option in General settings page.
331
+ *
332
+ * @since 1.0.0
333
+ */
334
+ public function register_usage_tracking_setting() {
335
+
336
+ if ( ! apply_filters( 'bsf_tracking_enabled', true ) || $this->is_white_label_enabled() ) {
337
+ return;
338
+ }
339
+
340
+ register_setting(
341
+ 'general', // Options group.
342
+ 'bsf_analytics_optin', // Option name/database.
343
+ array( 'sanitize_callback' => array( $this, 'sanitize_option' ) ) // sanitize callback function.
344
+ );
345
+
346
+ add_settings_field(
347
+ 'bsf-analytics-optin', // Field ID.
348
+ __( 'Usage Tracking', 'custom-fonts' ), // Field title.
349
+ array( $this, 'render_settings_field_html' ), // Field callback function.
350
+ 'general' // Settings page slug.
351
+ );
352
+ }
353
+
354
+ /**
355
+ * Sanitize Callback Function
356
+ *
357
+ * @param bool $input Option value.
358
+ * @since 1.0.0
359
+ */
360
+ public function sanitize_option( $input ) {
361
+
362
+ if ( ! $input || 'no' === $input ) {
363
+ return 'no';
364
+ }
365
+
366
+ return 'yes';
367
+ }
368
+
369
+ /**
370
+ * Print settings field HTML.
371
+ *
372
+ * @since 1.0.0
373
+ */
374
+ public function render_settings_field_html() {
375
+ ?>
376
+ <fieldset>
377
+ <label for="bsf-analytics-optin">
378
+ <input id="bsf-analytics-optin" type="checkbox" value="1" name="bsf_analytics_optin" <?php checked( get_site_option( 'bsf_analytics_optin', 'no' ), 'yes' ); ?>>
379
+ <?php
380
+ esc_html_e( 'Allow Brainstorm Force products to track non-sensitive usage tracking data.', 'custom-fonts' );
381
+
382
+ if ( is_multisite() ) {
383
+ esc_html_e( ' This will be applicable for all sites from the network.', 'custom-fonts' );
384
+ }
385
+ ?>
386
+ </label>
387
+ <?php
388
+ echo wp_kses_post( sprintf( '<a href="%1s" target="_blank" rel="noreferrer noopener">%2s</a>', esc_url( $this->usage_doc_link ), __( 'Learn More.', 'custom-fonts' ) ) );
389
+ ?>
390
+ </fieldset>
391
+ <?php
392
+ }
393
+
394
+ /**
395
+ * Get current product name.
396
+ *
397
+ * @return string $plugin_data['Name] Name of plugin.
398
+ * @since 1.0.0
399
+ */
400
+ private function get_product_name() {
401
+
402
+ $base = wp_normalize_path( dirname( __FILE__ ) );
403
+ $theme_dir = wp_normalize_path( get_template_directory() );
404
+
405
+ if ( false !== strpos( $base, $theme_dir ) ) {
406
+ $theme = wp_get_theme( get_template() );
407
+ return $theme->get( 'Name' );
408
+ }
409
+
410
+ $base = plugin_basename( __FILE__ );
411
+
412
+ $exploded_path = explode( '/', $base, 2 );
413
+ $plugin_slug = $exploded_path[0];
414
+
415
+ return $this->get_plugin_name( $plugin_slug );
416
+ }
417
+
418
+ /**
419
+ * Get plugin name by plugin slug.
420
+ *
421
+ * @param string $plugin_slug Plugin slug.
422
+ * @return string $plugin_info['Name'] Plugin name.
423
+ */
424
+ private function get_plugin_name( $plugin_slug ) {
425
+
426
+ $plugins = get_option( 'active_plugins' );
427
+
428
+ if ( ! function_exists( 'get_plugin_data' ) ) {
429
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
430
+ }
431
+
432
+ foreach ( $plugins as $plugin_file ) {
433
+ if ( 0 === strpos( $plugin_file, $plugin_slug ) ) {
434
+ $plugin_path = WP_PLUGIN_DIR . '/' . $plugin_file;
435
+ $plugin_data = get_plugin_data( $plugin_path );
436
+ return $plugin_data['Name'];
437
+ }
438
+ }
439
+ }
440
+
441
+ /**
442
+ * Set analytics installed time in option.
443
+ *
444
+ * @return string $time analytics installed time.
445
+ * @since 1.0.0
446
+ */
447
+ private function get_analytics_install_time() {
448
+
449
+ $time = get_site_option( 'bsf_analytics_installed_time' );
450
+
451
+ if ( ! $time ) {
452
+ $time = time();
453
+ update_site_option( 'bsf_analytics_installed_time', time() );
454
+ }
455
+
456
+ return $time;
457
+ }
458
+
459
+ /**
460
+ * Schedule/unschedule cron event on updation of option.
461
+ *
462
+ * @param string $old_value old value of option.
463
+ * @param string $value value of option.
464
+ * @param string $option Option name.
465
+ * @since 1.0.0
466
+ */
467
+ public function update_analytics_option_callback( $old_value, $value, $option ) {
468
+ $this->add_option_to_network( $value );
469
+ }
470
+
471
+ /**
472
+ * Analytics option add callback.
473
+ *
474
+ * @param string $option Option name.
475
+ * @param string $value value of option.
476
+ * @since 1.0.0
477
+ */
478
+ public function add_analytics_option_callback( $option, $value ) {
479
+ $this->add_option_to_network( $value );
480
+ }
481
+
482
+ /**
483
+ * Schedule or unschedule event based on analytics option value.
484
+ *
485
+ * @since 1.0.0
486
+ */
487
+ public function schedule_unschedule_event() {
488
+
489
+ if ( true === $this->is_white_label_enabled() ) {
490
+ $this->unschedule_event();
491
+ return;
492
+ }
493
+
494
+ $analytics_option = get_site_option( 'bsf_analytics_optin' );
495
+
496
+ if ( 'no' === $analytics_option ) {
497
+ $this->unschedule_event();
498
+ } elseif ( 'yes' === $analytics_option ) {
499
+ $this->schedule_event();
500
+ }
501
+ }
502
+
503
+ /**
504
+ * Save analytics option to network.
505
+ *
506
+ * @param string $value value of option.
507
+ * @since 1.0.0
508
+ */
509
+ public function add_option_to_network( $value ) {
510
+
511
+ // If action coming from general settings page.
512
+ if ( isset( $_POST['option_page'] ) && 'general' === $_POST['option_page'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
513
+
514
+ if ( get_site_option( 'bsf_analytics_optin' ) ) {
515
+ update_site_option( 'bsf_analytics_optin', $value );
516
+ } else {
517
+ add_site_option( 'bsf_analytics_optin', $value );
518
+ }
519
+ }
520
+ }
521
+ }
522
+
523
+ new BSF_Analytics();
524
+
525
+ }
custom-fonts.php CHANGED
@@ -6,7 +6,7 @@
6
  * Author: Brainstorm Force
7
  * Author URI: http://www.brainstormforce.com
8
  * Text Domain: custom-fonts
9
- * Version: 1.2.1
10
  *
11
  * @package Bsf_Custom_Fonts
12
  */
@@ -25,9 +25,20 @@ define( 'BSF_CUSTOM_FONTS_FILE', __FILE__ );
25
  define( 'BSF_CUSTOM_FONTS_BASE', plugin_basename( BSF_CUSTOM_FONTS_FILE ) );
26
  define( 'BSF_CUSTOM_FONTS_DIR', plugin_dir_path( BSF_CUSTOM_FONTS_FILE ) );
27
  define( 'BSF_CUSTOM_FONTS_URI', plugins_url( '/', BSF_CUSTOM_FONTS_FILE ) );
28
- define( 'BSF_CUSTOM_FONTS_VER', '1.2.1' );
29
 
30
  /**
31
  * BSF Custom Fonts
32
  */
33
  require_once BSF_CUSTOM_FONTS_DIR . 'classes/class-bsf-custom-fonts.php';
 
 
 
 
 
 
 
 
 
 
 
6
  * Author: Brainstorm Force
7
  * Author URI: http://www.brainstormforce.com
8
  * Text Domain: custom-fonts
9
+ * Version: 1.2.2
10
  *
11
  * @package Bsf_Custom_Fonts
12
  */
25
  define( 'BSF_CUSTOM_FONTS_BASE', plugin_basename( BSF_CUSTOM_FONTS_FILE ) );
26
  define( 'BSF_CUSTOM_FONTS_DIR', plugin_dir_path( BSF_CUSTOM_FONTS_FILE ) );
27
  define( 'BSF_CUSTOM_FONTS_URI', plugins_url( '/', BSF_CUSTOM_FONTS_FILE ) );
28
+ define( 'BSF_CUSTOM_FONTS_VER', '1.2.2' );
29
 
30
  /**
31
  * BSF Custom Fonts
32
  */
33
  require_once BSF_CUSTOM_FONTS_DIR . 'classes/class-bsf-custom-fonts.php';
34
+
35
+ if ( is_admin() ) {
36
+
37
+ /**
38
+ * Admin Notice Library Settings
39
+ */
40
+ require_once BSF_CUSTOM_FONTS_DIR . 'lib/notices/class-astra-notices.php';
41
+ }
42
+
43
+ // BSF Analytics library.
44
+ require_once BSF_CUSTOM_FONTS_DIR . 'admin/bsf-analytics/class-bsf-analytics.php';
languages/custom-fonts.pot CHANGED
@@ -1,14 +1,14 @@
1
- # Copyright (C) 2018 Brainstorm Force
2
  # This file is distributed under the same license as the Custom Fonts package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Custom Fonts 1.0.5\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/custom-fonts\n"
7
- "POT-Creation-Date: 2018-08-03 13:21:42+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
- "PO-Revision-Date: 2018-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
  "Language: en\n"
@@ -22,13 +22,57 @@ msgstr ""
22
  "X-Poedit-SearchPath-0: .\n"
23
  "X-Poedit-Bookmarks: \n"
24
  "X-Textdomain-Support: yes\n"
25
- "X-Generator: grunt-wp-i18n1.0.2\n"
26
 
27
- #: classes/class-bsf-custom-fonts-render.php:101
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  msgid "Custom"
29
  msgstr ""
30
 
31
- #: classes/class-bsf-custom-fonts-render.php:288
32
  #. translators: 1: Astra theme from wordpress.org
33
  msgid "Custom Fonts Plugin requires minimum 1.0.16 version of the Astra Theme."
34
  msgstr ""
@@ -37,117 +81,141 @@ msgstr ""
37
  msgid "Custom Fonts"
38
  msgstr ""
39
 
40
- #: includes/class-bsf-custom-fonts-admin.php:105
41
  msgid "The name of the font as it appears in the customizer options."
42
  msgstr ""
43
 
44
- #: includes/class-bsf-custom-fonts-admin.php:139
45
- #: includes/class-bsf-custom-fonts-admin.php:154
46
  msgid "Font .woff2"
47
  msgstr ""
48
 
49
- #: includes/class-bsf-custom-fonts-admin.php:139
50
- #: includes/class-bsf-custom-fonts-admin.php:154
51
  msgid "Upload the font's woff2 file or enter the URL."
52
  msgstr ""
53
 
54
- #: includes/class-bsf-custom-fonts-admin.php:140
55
- #: includes/class-bsf-custom-fonts-admin.php:155
56
  msgid "Font .woff"
57
  msgstr ""
58
 
59
- #: includes/class-bsf-custom-fonts-admin.php:140
60
- #: includes/class-bsf-custom-fonts-admin.php:155
61
  msgid "Upload the font's woff file or enter the URL."
62
  msgstr ""
63
 
64
- #: includes/class-bsf-custom-fonts-admin.php:141
65
- #: includes/class-bsf-custom-fonts-admin.php:156
66
  msgid "Font .ttf"
67
  msgstr ""
68
 
69
- #: includes/class-bsf-custom-fonts-admin.php:141
70
- #: includes/class-bsf-custom-fonts-admin.php:156
71
  msgid "Upload the font's ttf file or enter the URL."
72
  msgstr ""
73
 
74
- #: includes/class-bsf-custom-fonts-admin.php:142
75
- #: includes/class-bsf-custom-fonts-admin.php:157
76
  msgid "Font .eot"
77
  msgstr ""
78
 
79
- #: includes/class-bsf-custom-fonts-admin.php:142
80
- #: includes/class-bsf-custom-fonts-admin.php:157
81
  msgid "Upload the font's eot file or enter the URL."
82
  msgstr ""
83
 
84
- #: includes/class-bsf-custom-fonts-admin.php:143
85
- #: includes/class-bsf-custom-fonts-admin.php:158
86
  msgid "Font .svg"
87
  msgstr ""
88
 
89
- #: includes/class-bsf-custom-fonts-admin.php:143
90
- #: includes/class-bsf-custom-fonts-admin.php:158
91
  msgid "Upload the font's svg file or enter the URL."
92
  msgstr ""
93
 
94
- #: includes/class-bsf-custom-fonts-admin.php:176
95
- #: includes/class-bsf-custom-fonts-admin.php:201
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  msgid "Upload"
97
  msgstr ""
98
 
99
- #: includes/class-bsf-custom-fonts-taxonomy.php:82
100
  msgid "Font"
101
  msgstr ""
102
 
103
- #: includes/class-bsf-custom-fonts-taxonomy.php:84
104
  msgid "Search Fonts"
105
  msgstr ""
106
 
107
- #: includes/class-bsf-custom-fonts-taxonomy.php:85
108
  msgid "All Fonts"
109
  msgstr ""
110
 
111
- #: includes/class-bsf-custom-fonts-taxonomy.php:86
112
  msgid "Parent Font"
113
  msgstr ""
114
 
115
- #: includes/class-bsf-custom-fonts-taxonomy.php:87
116
  msgid "Parent Font:"
117
  msgstr ""
118
 
119
- #: includes/class-bsf-custom-fonts-taxonomy.php:88
120
  msgid "Edit Font"
121
  msgstr ""
122
 
123
- #: includes/class-bsf-custom-fonts-taxonomy.php:89
124
  msgid "Update Font"
125
  msgstr ""
126
 
127
- #: includes/class-bsf-custom-fonts-taxonomy.php:90
128
  msgid "Add New Font"
129
  msgstr ""
130
 
131
- #: includes/class-bsf-custom-fonts-taxonomy.php:91
132
  msgid "New Font Name"
133
  msgstr ""
134
 
135
- #: includes/class-bsf-custom-fonts-taxonomy.php:92
136
  msgid "No fonts found"
137
  msgstr ""
138
 
139
- #: includes/white-label.php:12 includes/white-label.php:17
140
  msgid "Custom Fonts Branding"
141
  msgstr ""
142
 
143
- #: includes/white-label.php:23
144
  msgid "Plugin Name:"
145
  msgstr ""
146
 
147
- #: includes/white-label.php:28
148
  msgid "Plugin Description:"
149
  msgstr ""
150
 
 
 
 
 
151
  #. Plugin URI of the plugin/theme
152
  msgid "http://www.wpastra.com/"
153
  msgstr ""
@@ -166,7 +234,7 @@ msgstr ""
166
  msgid "http://www.brainstormforce.com"
167
  msgstr ""
168
 
169
- #: includes/class-bsf-custom-fonts-taxonomy.php:83
170
  msgctxt "Admin menu name"
171
  msgid "Custom Fonts"
172
  msgstr ""
1
+ # Copyright (C) 2020 Brainstorm Force
2
  # This file is distributed under the same license as the Custom Fonts package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Custom Fonts 1.2.2\n"
6
  "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/custom-fonts\n"
7
+ "POT-Creation-Date: 2020-06-15 10:19:55+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=utf-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
11
+ "PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
  "Language: en\n"
22
  "X-Poedit-SearchPath-0: .\n"
23
  "X-Poedit-Bookmarks: \n"
24
  "X-Textdomain-Support: yes\n"
25
+ "X-Generator: grunt-wp-i18n 1.0.3\n"
26
 
27
+ #: admin/bsf-analytics/class-bsf-analytics.php:183
28
+ #. translators: %s product name
29
+ msgid ""
30
+ "Want to help make <strong>%1s</strong> even more awesome? Allow us to "
31
+ "collect non-sensitive diagnostic data and usage information. "
32
+ msgstr ""
33
+
34
+ #: admin/bsf-analytics/class-bsf-analytics.php:186
35
+ msgid "This will be applicable for all sites from the network."
36
+ msgstr ""
37
+
38
+ #: admin/bsf-analytics/class-bsf-analytics.php:210
39
+ #. translators: %s usage doc link
40
+ msgid " Know More."
41
+ msgstr ""
42
+
43
+ #: admin/bsf-analytics/class-bsf-analytics.php:217
44
+ msgid "Yes! Allow it"
45
+ msgstr ""
46
+
47
+ #: admin/bsf-analytics/class-bsf-analytics.php:225
48
+ msgid "No Thanks"
49
+ msgstr ""
50
+
51
+ #: admin/bsf-analytics/class-bsf-analytics.php:294
52
+ msgid "Every two days"
53
+ msgstr ""
54
+
55
+ #: admin/bsf-analytics/class-bsf-analytics.php:348
56
+ msgid "Usage Tracking"
57
+ msgstr ""
58
+
59
+ #: admin/bsf-analytics/class-bsf-analytics.php:380
60
+ msgid "Allow Brainstorm Force products to track non-sensitive usage tracking data."
61
+ msgstr ""
62
+
63
+ #: admin/bsf-analytics/class-bsf-analytics.php:383
64
+ msgid " This will be applicable for all sites from the network."
65
+ msgstr ""
66
+
67
+ #: admin/bsf-analytics/class-bsf-analytics.php:388
68
+ msgid "Learn More."
69
+ msgstr ""
70
+
71
+ #: classes/class-bsf-custom-fonts-render.php:106
72
  msgid "Custom"
73
  msgstr ""
74
 
75
+ #: classes/class-bsf-custom-fonts-render.php:298
76
  #. translators: 1: Astra theme from wordpress.org
77
  msgid "Custom Fonts Plugin requires minimum 1.0.16 version of the Astra Theme."
78
  msgstr ""
81
  msgid "Custom Fonts"
82
  msgstr ""
83
 
84
+ #: includes/class-bsf-custom-fonts-admin.php:107
85
  msgid "The name of the font as it appears in the customizer options."
86
  msgstr ""
87
 
88
+ #: includes/class-bsf-custom-fonts-admin.php:141
89
+ #: includes/class-bsf-custom-fonts-admin.php:170
90
  msgid "Font .woff2"
91
  msgstr ""
92
 
93
+ #: includes/class-bsf-custom-fonts-admin.php:141
94
+ #: includes/class-bsf-custom-fonts-admin.php:170
95
  msgid "Upload the font's woff2 file or enter the URL."
96
  msgstr ""
97
 
98
+ #: includes/class-bsf-custom-fonts-admin.php:142
99
+ #: includes/class-bsf-custom-fonts-admin.php:171
100
  msgid "Font .woff"
101
  msgstr ""
102
 
103
+ #: includes/class-bsf-custom-fonts-admin.php:142
104
+ #: includes/class-bsf-custom-fonts-admin.php:171
105
  msgid "Upload the font's woff file or enter the URL."
106
  msgstr ""
107
 
108
+ #: includes/class-bsf-custom-fonts-admin.php:143
109
+ #: includes/class-bsf-custom-fonts-admin.php:172
110
  msgid "Font .ttf"
111
  msgstr ""
112
 
113
+ #: includes/class-bsf-custom-fonts-admin.php:143
114
+ #: includes/class-bsf-custom-fonts-admin.php:172
115
  msgid "Upload the font's ttf file or enter the URL."
116
  msgstr ""
117
 
118
+ #: includes/class-bsf-custom-fonts-admin.php:144
119
+ #: includes/class-bsf-custom-fonts-admin.php:173
120
  msgid "Font .eot"
121
  msgstr ""
122
 
123
+ #: includes/class-bsf-custom-fonts-admin.php:144
124
+ #: includes/class-bsf-custom-fonts-admin.php:173
125
  msgid "Upload the font's eot file or enter the URL."
126
  msgstr ""
127
 
128
+ #: includes/class-bsf-custom-fonts-admin.php:145
129
+ #: includes/class-bsf-custom-fonts-admin.php:174
130
  msgid "Font .svg"
131
  msgstr ""
132
 
133
+ #: includes/class-bsf-custom-fonts-admin.php:145
134
+ #: includes/class-bsf-custom-fonts-admin.php:174
135
  msgid "Upload the font's svg file or enter the URL."
136
  msgstr ""
137
 
138
+ #: includes/class-bsf-custom-fonts-admin.php:146
139
+ #: includes/class-bsf-custom-fonts-admin.php:175
140
+ msgid "Font .otf"
141
+ msgstr ""
142
+
143
+ #: includes/class-bsf-custom-fonts-admin.php:146
144
+ #: includes/class-bsf-custom-fonts-admin.php:175
145
+ msgid "Upload the font's otf file or enter the URL."
146
+ msgstr ""
147
+
148
+ #: includes/class-bsf-custom-fonts-admin.php:150
149
+ #: includes/class-bsf-custom-fonts-admin.php:179
150
+ msgid "Font Display"
151
+ msgstr ""
152
+
153
+ #: includes/class-bsf-custom-fonts-admin.php:151
154
+ #: includes/class-bsf-custom-fonts-admin.php:181
155
+ msgid "Select font-display property for this font"
156
+ msgstr ""
157
+
158
+ #: includes/class-bsf-custom-fonts-admin.php:207
159
+ #: includes/class-bsf-custom-fonts-admin.php:288
160
  msgid "Upload"
161
  msgstr ""
162
 
163
+ #: includes/class-bsf-custom-fonts-taxonomy.php:84
164
  msgid "Font"
165
  msgstr ""
166
 
167
+ #: includes/class-bsf-custom-fonts-taxonomy.php:86
168
  msgid "Search Fonts"
169
  msgstr ""
170
 
171
+ #: includes/class-bsf-custom-fonts-taxonomy.php:87
172
  msgid "All Fonts"
173
  msgstr ""
174
 
175
+ #: includes/class-bsf-custom-fonts-taxonomy.php:88
176
  msgid "Parent Font"
177
  msgstr ""
178
 
179
+ #: includes/class-bsf-custom-fonts-taxonomy.php:89
180
  msgid "Parent Font:"
181
  msgstr ""
182
 
183
+ #: includes/class-bsf-custom-fonts-taxonomy.php:90
184
  msgid "Edit Font"
185
  msgstr ""
186
 
187
+ #: includes/class-bsf-custom-fonts-taxonomy.php:91
188
  msgid "Update Font"
189
  msgstr ""
190
 
191
+ #: includes/class-bsf-custom-fonts-taxonomy.php:92
192
  msgid "Add New Font"
193
  msgstr ""
194
 
195
+ #: includes/class-bsf-custom-fonts-taxonomy.php:93
196
  msgid "New Font Name"
197
  msgstr ""
198
 
199
+ #: includes/class-bsf-custom-fonts-taxonomy.php:94
200
  msgid "No fonts found"
201
  msgstr ""
202
 
203
+ #: includes/white-label.php:18 includes/white-label.php:23
204
  msgid "Custom Fonts Branding"
205
  msgstr ""
206
 
207
+ #: includes/white-label.php:29
208
  msgid "Plugin Name:"
209
  msgstr ""
210
 
211
+ #: includes/white-label.php:34
212
  msgid "Plugin Description:"
213
  msgstr ""
214
 
215
+ #: lib/notices/class-astra-notices.php:125
216
+ msgid "WordPress Nonce not validated."
217
+ msgstr ""
218
+
219
  #. Plugin URI of the plugin/theme
220
  msgid "http://www.wpastra.com/"
221
  msgstr ""
234
  msgid "http://www.brainstormforce.com"
235
  msgstr ""
236
 
237
+ #: includes/class-bsf-custom-fonts-taxonomy.php:85
238
  msgctxt "Admin menu name"
239
  msgid "Custom Fonts"
240
  msgstr ""
lib/notices/class-astra-notices.php ADDED
@@ -0,0 +1,365 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Astra Sites Notices
4
+ *
5
+ * Closing notice on click on `astra-notice-close` class.
6
+ *
7
+ * If notice has the data attribute `data-repeat-notice-after="%2$s"` then notice close for that SPECIFIC TIME.
8
+ * If notice has NO data attribute `data-repeat-notice-after="%2$s"` then notice close for the CURRENT USER FOREVER.
9
+ *
10
+ * > Create custom close notice link in the notice markup. E.g.
11
+ * `<a href="#" data-repeat-notice-after="<?php echo MONTH_IN_SECONDS; ?>" class="astra-notice-close">`
12
+ * It close the notice for 30 days.
13
+ *
14
+ * @package Astra Sites
15
+ * @since 1.2.2
16
+ */
17
+
18
+ if ( ! defined( 'ABSPATH' ) ) {
19
+ exit; // Exit if accessed directly.
20
+ }
21
+
22
+ if ( ! class_exists( 'Astra_Notices' ) ) :
23
+
24
+ /**
25
+ * Astra_Notices
26
+ *
27
+ * @since 1.2.2
28
+ */
29
+ class Astra_Notices {
30
+
31
+ /**
32
+ * Notices
33
+ *
34
+ * @access private
35
+ * @var array Notices.
36
+ * @since 1.2.2
37
+ */
38
+ private static $version = '1.1.5';
39
+
40
+ /**
41
+ * Notices
42
+ *
43
+ * @access private
44
+ * @var array Notices.
45
+ * @since 1.2.2
46
+ */
47
+ private static $notices = array();
48
+
49
+ /**
50
+ * Instance
51
+ *
52
+ * @access private
53
+ * @var object Class object.
54
+ * @since 1.2.2
55
+ */
56
+ private static $instance;
57
+
58
+ /**
59
+ * Initiator
60
+ *
61
+ * @since 1.2.2
62
+ * @return object initialized object of class.
63
+ */
64
+ public static function get_instance() {
65
+ if ( ! isset( self::$instance ) ) {
66
+ self::$instance = new self();
67
+ }
68
+ return self::$instance;
69
+ }
70
+
71
+ /**
72
+ * Constructor
73
+ *
74
+ * @since 1.2.2
75
+ */
76
+ public function __construct() {
77
+ add_action( 'admin_notices', array( $this, 'show_notices' ), 30 );
78
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
79
+ add_action( 'wp_ajax_astra-notice-dismiss', array( $this, 'dismiss_notice' ) );
80
+ add_filter( 'wp_kses_allowed_html', array( $this, 'add_data_attributes' ), 10, 2 );
81
+ }
82
+
83
+ /**
84
+ * Filters and Returns a list of allowed tags and attributes for a given context.
85
+ *
86
+ * @param Array $allowedposttags Array of allowed tags.
87
+ * @param String $context Context type (explicit).
88
+ * @since 1.2.2
89
+ * @return Array
90
+ */
91
+ public function add_data_attributes( $allowedposttags, $context ) {
92
+ $allowedposttags['a']['data-repeat-notice-after'] = true;
93
+
94
+ return $allowedposttags;
95
+ }
96
+
97
+ /**
98
+ * Add Notice.
99
+ *
100
+ * @since 1.2.2
101
+ * @param array $args Notice arguments.
102
+ * @return void
103
+ */
104
+ public static function add_notice( $args = array() ) {
105
+ self::$notices[] = $args;
106
+ }
107
+
108
+ /**
109
+ * Dismiss Notice.
110
+ *
111
+ * @since 1.2.2
112
+ * @return void
113
+ */
114
+ public function dismiss_notice() {
115
+
116
+ if ( ! apply_filters( 'astra_notices_user_cap_check', current_user_can( 'manage_options' ) ) ) {
117
+ return;
118
+ }
119
+
120
+ $notice_id = ( isset( $_POST['notice_id'] ) ) ? sanitize_key( $_POST['notice_id'] ) : '';
121
+ $repeat_notice_after = ( isset( $_POST['repeat_notice_after'] ) ) ? absint( $_POST['repeat_notice_after'] ) : '';
122
+ $nonce = ( isset( $_POST['nonce'] ) ) ? sanitize_key( $_POST['nonce'] ) : '';
123
+
124
+ if ( false === wp_verify_nonce( $nonce, 'astra-notices' ) ) {
125
+ wp_send_json_error( esc_html_e( 'WordPress Nonce not validated.', 'custom-fonts' ) );
126
+ }
127
+
128
+ // Valid inputs?
129
+ if ( ! empty( $notice_id ) ) {
130
+
131
+ if ( ! empty( $repeat_notice_after ) ) {
132
+ set_transient( $notice_id, true, $repeat_notice_after );
133
+ } else {
134
+ update_user_meta( get_current_user_id(), $notice_id, 'notice-dismissed' );
135
+ }
136
+
137
+ wp_send_json_success();
138
+ }
139
+
140
+ wp_send_json_error();
141
+ }
142
+
143
+ /**
144
+ * Enqueue Scripts.
145
+ *
146
+ * @since 1.2.2
147
+ * @return void
148
+ */
149
+ public function enqueue_scripts() {
150
+ wp_register_script( 'astra-notices', self::_get_uri() . 'notices.js', array( 'jquery' ), self::$version, true );
151
+ wp_localize_script(
152
+ 'astra-notices',
153
+ 'astraNotices',
154
+ array(
155
+ '_notice_nonce' => wp_create_nonce( 'astra-notices' ),
156
+ )
157
+ );
158
+ }
159
+
160
+ /**
161
+ * Rating priority sort
162
+ *
163
+ * @since 1.5.2
164
+ * @param array $array1 array one.
165
+ * @param array $array2 array two.
166
+ * @return array
167
+ */
168
+ public function sort_notices( $array1, $array2 ) {
169
+ if ( ! isset( $array1['priority'] ) ) {
170
+ $array1['priority'] = 10;
171
+ }
172
+ if ( ! isset( $array2['priority'] ) ) {
173
+ $array2['priority'] = 10;
174
+ }
175
+
176
+ return $array1['priority'] - $array2['priority'];
177
+ }
178
+
179
+ /**
180
+ * Notice Types
181
+ *
182
+ * @since 1.2.2
183
+ * @return void
184
+ */
185
+ public function show_notices() {
186
+
187
+ $defaults = array(
188
+ 'id' => '', // Optional, Notice ID. If empty it set `astra-notices-id-<$array-index>`.
189
+ 'type' => 'info', // Optional, Notice type. Default `info`. Expected [info, warning, notice, error].
190
+ 'message' => '', // Optional, Message.
191
+ 'show_if' => true, // Optional, Show notice on custom condition. E.g. 'show_if' => if( is_admin() ) ? true, false, .
192
+ 'repeat-notice-after' => '', // Optional, Dismiss-able notice time. It'll auto show after given time.
193
+ 'display-notice-after' => false, // Optional, Dismiss-able notice time. It'll auto show after given time.
194
+ 'class' => '', // Optional, Additional notice wrapper class.
195
+ 'priority' => 10, // Priority of the notice.
196
+ 'display-with-other-notices' => true, // Should the notice be displayed if other notices are being displayed from Astra_Notices.
197
+ 'is_dismissible' => true,
198
+ );
199
+
200
+ // Count for the notices that are rendered.
201
+ $notices_displayed = 0;
202
+
203
+ // sort the array with priority.
204
+ usort( self::$notices, array( $this, 'sort_notices' ) );
205
+
206
+ foreach ( self::$notices as $key => $notice ) {
207
+
208
+ $notice = wp_parse_args( $notice, $defaults );
209
+
210
+ $notice['id'] = self::get_notice_id( $notice, $key );
211
+
212
+ $notice['classes'] = self::get_wrap_classes( $notice );
213
+
214
+ // Notices visible after transient expire.
215
+ if ( isset( $notice['show_if'] ) && true === $notice['show_if'] ) {
216
+
217
+ // don't display the notice if it is not supposed to be displayed with other notices.
218
+ if ( 0 !== $notices_displayed && false === $notice['display-with-other-notices'] ) {
219
+ continue;
220
+ }
221
+
222
+ if ( self::is_expired( $notice ) ) {
223
+
224
+ self::markup( $notice );
225
+ ++$notices_displayed;
226
+ }
227
+ }
228
+ }
229
+
230
+ }
231
+
232
+ /**
233
+ * Markup Notice.
234
+ *
235
+ * @since 1.2.2
236
+ * @param array $notice Notice markup.
237
+ * @return void
238
+ */
239
+ public static function markup( $notice = array() ) {
240
+
241
+ wp_enqueue_script( 'astra-notices' );
242
+
243
+ do_action( 'astra_notice_before_markup' );
244
+
245
+ do_action( "astra_notice_before_markup_{$notice['id']}" );
246
+
247
+ ?>
248
+ <div id="<?php echo esc_attr( $notice['id'] ); ?>" class="<?php echo esc_attr( $notice['classes'] ); ?>" data-repeat-notice-after="<?php echo esc_attr( $notice['repeat-notice-after'] ); ?>">
249
+ <div class="notice-container">
250
+ <?php do_action( "astra_notice_inside_markup_{$notice['id']}" ); ?>
251
+ <?php echo wp_kses_post( $notice['message'] ); ?>
252
+ </div>
253
+ </div>
254
+ <?php
255
+
256
+ do_action( "astra_notice_after_markup_{$notice['id']}" );
257
+
258
+ do_action( 'astra_notice_after_markup' );
259
+
260
+ }
261
+
262
+ /**
263
+ * Notice classes.
264
+ *
265
+ * @since 1.2.2
266
+ *
267
+ * @param array $notice Notice arguments.
268
+ * @return array Notice wrapper classes.
269
+ */
270
+ private static function get_wrap_classes( $notice ) {
271
+ $classes = array( 'astra-notice', 'notice' );
272
+
273
+ if ( $notice['is_dismissible'] ) {
274
+ $classes[] = 'is-dismissible';
275
+ }
276
+
277
+ $classes[] = $notice['class'];
278
+ if ( isset( $notice['type'] ) && '' !== $notice['type'] ) {
279
+ $classes[] = 'notice-' . $notice['type'];
280
+ }
281
+
282
+ return esc_attr( implode( ' ', $classes ) );
283
+ }
284
+
285
+ /**
286
+ * Get Notice ID.
287
+ *
288
+ * @since 1.2.2
289
+ *
290
+ * @param array $notice Notice arguments.
291
+ * @param int $key Notice array index.
292
+ * @return string Notice id.
293
+ */
294
+ private static function get_notice_id( $notice, $key ) {
295
+ if ( isset( $notice['id'] ) && ! empty( $notice['id'] ) ) {
296
+ return $notice['id'];
297
+ }
298
+
299
+ return 'astra-notices-id-' . $key;
300
+ }
301
+
302
+ /**
303
+ * Is notice expired?
304
+ *
305
+ * @since 1.2.2
306
+ *
307
+ * @param array $notice Notice arguments.
308
+ * @return boolean
309
+ */
310
+ private static function is_expired( $notice ) {
311
+ $transient_status = get_transient( $notice['id'] );
312
+
313
+ if ( false === $transient_status ) {
314
+
315
+ if ( isset( $notice['display-notice-after'] ) && false !== $notice['display-notice-after'] ) {
316
+
317
+ if ( 'delayed-notice' !== get_user_meta( get_current_user_id(), $notice['id'], true ) &&
318
+ 'notice-dismissed' !== get_user_meta( get_current_user_id(), $notice['id'], true ) ) {
319
+ set_transient( $notice['id'], 'delayed-notice', $notice['display-notice-after'] );
320
+ update_user_meta( get_current_user_id(), $notice['id'], 'delayed-notice' );
321
+
322
+ return false;
323
+ }
324
+ }
325
+
326
+ // Check the user meta status if current notice is dismissed or delay completed.
327
+ $meta_status = get_user_meta( get_current_user_id(), $notice['id'], true );
328
+
329
+ if ( empty( $meta_status ) || 'delayed-notice' === $meta_status ) {
330
+ return true;
331
+ }
332
+ }
333
+
334
+ return false;
335
+ }
336
+
337
+ /**
338
+ * Get URI
339
+ *
340
+ * @return mixed URL.
341
+ */
342
+ public static function _get_uri() { // phpcs:ignore PSR2.Methods.MethodDeclaration.Underscore
343
+ $path = wp_normalize_path( dirname( __FILE__ ) );
344
+ $theme_dir = wp_normalize_path( get_template_directory() );
345
+ $plugin_dir = wp_normalize_path( WP_PLUGIN_DIR );
346
+
347
+ if ( strpos( $path, $theme_dir ) !== false ) {
348
+ return trailingslashit( get_template_directory_uri() . str_replace( $theme_dir, '', $path ) );
349
+ } elseif ( strpos( $path, $plugin_dir ) !== false ) {
350
+ return plugin_dir_url( __FILE__ );
351
+ } elseif ( strpos( $path, dirname( plugin_basename( __FILE__ ) ) ) !== false ) {
352
+ return plugin_dir_url( __FILE__ );
353
+ }
354
+
355
+ return; // phpcs:ignore Squiz.PHP.NonExecutableCode.ReturnNotRequired
356
+ }
357
+
358
+ }
359
+
360
+ /**
361
+ * Kicking this off by calling 'get_instance()' method
362
+ */
363
+ Astra_Notices::get_instance();
364
+
365
+ endif;
lib/notices/notices.js ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Customizer controls toggles
3
+ *
4
+ * @package Astra
5
+ */
6
+
7
+ ( function( $ ) {
8
+
9
+ /**
10
+ * Helper class for the main Customizer interface.
11
+ *
12
+ * @since 1.2.2
13
+ * @class ASTCustomizer
14
+ */
15
+ AstraNotices = {
16
+
17
+ /**
18
+ * Initializes our custom logic for the Customizer.
19
+ *
20
+ * @since 1.2.2
21
+ * @method init
22
+ */
23
+ init: function()
24
+ {
25
+ this._bind();
26
+ },
27
+
28
+ /**
29
+ * Binds events for the Astra Portfolio.
30
+ *
31
+ * @since 1.2.2
32
+ * @access private
33
+ * @method _bind
34
+ */
35
+ _bind: function()
36
+ {
37
+ $( document ).on('click', '.astra-notice-close', AstraNotices._dismissNoticeNew );
38
+ $( document ).on('click', '.astra-notice .notice-dismiss', AstraNotices._dismissNotice );
39
+ },
40
+
41
+ _dismissNotice: function( event ) {
42
+ event.preventDefault();
43
+
44
+ var repeat_notice_after = $( this ).parents('.astra-notice').data( 'repeat-notice-after' ) || '';
45
+ var notice_id = $( this ).parents('.astra-notice').attr( 'id' ) || '';
46
+
47
+ AstraNotices._ajax( notice_id, repeat_notice_after );
48
+ },
49
+
50
+ _dismissNoticeNew: function( event ) {
51
+ event.preventDefault();
52
+
53
+ var repeat_notice_after = $( this ).attr( 'data-repeat-notice-after' ) || '';
54
+ var notice_id = $( this ).parents('.astra-notice').attr( 'id' ) || '';
55
+
56
+ var $el = $( this ).parents('.astra-notice');
57
+ $el.fadeTo( 100, 0, function() {
58
+ $el.slideUp( 100, function() {
59
+ $el.remove();
60
+ });
61
+ });
62
+
63
+ AstraNotices._ajax( notice_id, repeat_notice_after );
64
+
65
+ var link = $( this ).attr( 'href' ) || '';
66
+ var target = $( this ).attr( 'target' ) || '';
67
+ if( '' !== link && '_blank' === target ) {
68
+ window.open(link , '_blank');
69
+ }
70
+ },
71
+
72
+ _ajax: function( notice_id, repeat_notice_after ) {
73
+
74
+ if( '' === notice_id ) {
75
+ return;
76
+ }
77
+
78
+ $.ajax({
79
+ url: ajaxurl,
80
+ type: 'POST',
81
+ data: {
82
+ action : 'astra-notice-dismiss',
83
+ nonce : astraNotices._notice_nonce,
84
+ notice_id : notice_id,
85
+ repeat_notice_after : parseInt( repeat_notice_after ),
86
+ },
87
+ });
88
+
89
+ }
90
+ };
91
+
92
+ $( function() {
93
+ AstraNotices.init();
94
+ } );
95
+ } )( jQuery );
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: brainstormforce
3
  Donate link: https://www.paypal.me/BrainstormForce
4
  Tags: Beaver Builder, Elementor, Astra, woff2, woff, ttf, svg, eot, otf, Custom Fonts, Font, Typography
5
  Requires at least: 4.4
6
- Tested up to: 5.4
7
- Stable tag: 1.2.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -17,9 +17,9 @@ This plugin helps you easily embed custom fonts files (woff2, woff, ttf, svg, eo
17
  Currently, it works with:
18
 
19
  * <a href="https://wpastra.com/?utm_source=wp-repo&utm_campaign=custom-fonts&utm_medium=description">Astra Theme</a>
20
- * <a href="https://www.wpbeaverbuilder.com/?fla=713">Beaver Builder Theme</a>
21
- * <a href="https://www.wpbeaverbuilder.com/?fla=713">Beaver Builder Plugin</a>
22
- * <a href="https://elementor.com/?ref=1352">Elementor Page Builder</a>
23
 
24
  How does it work?
25
 
@@ -43,6 +43,9 @@ If you're not using any of the supported plugins and theme, you can write the cu
43
 
44
  == Changelog ==
45
 
 
 
 
46
  = 1.2.1 =
47
  - Improvement: Hardened the security of plugin
48
  - Improvement: Compatibility with latest WordPress PHP_CodeSniffer rules
@@ -80,4 +83,4 @@ If you're not using any of the supported plugins and theme, you can write the cu
80
  - Changed the plugin name to be Custom Fonts instead of BSF Custom Fonts.
81
 
82
  = 1.0.0 =
83
- - Initial release.
3
  Donate link: https://www.paypal.me/BrainstormForce
4
  Tags: Beaver Builder, Elementor, Astra, woff2, woff, ttf, svg, eot, otf, Custom Fonts, Font, Typography
5
  Requires at least: 4.4
6
+ Tested up to: 5.4.2
7
+ Stable tag: 1.2.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
17
  Currently, it works with:
18
 
19
  * <a href="https://wpastra.com/?utm_source=wp-repo&utm_campaign=custom-fonts&utm_medium=description">Astra Theme</a>
20
+ * <a href="https://www.wpbeaverbuilder.com/">Beaver Builder Theme</a>
21
+ * <a href="https://www.wpbeaverbuilder.com/">Beaver Builder Plugin</a>
22
+ * <a href="https://elementor.com/">Elementor Page Builder</a>
23
 
24
  How does it work?
25
 
43
 
44
  == Changelog ==
45
 
46
+ = 1.2.2 =
47
+ - New: Users can now share non-personal usage data to help us test and develop better products. ( https://store.brainstormforce.com/usage-tracking/?utm_source=wp_dashboard&utm_medium=general_settings&utm_campaign=usage_tracking )
48
+
49
  = 1.2.1 =
50
  - Improvement: Hardened the security of plugin
51
  - Improvement: Compatibility with latest WordPress PHP_CodeSniffer rules
83
  - Changed the plugin name to be Custom Fonts instead of BSF Custom Fonts.
84
 
85
  = 1.0.0 =
86
+ - Initial release.