Customizer Search - Version 1.1.4

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 Nikschavan
Plugin Icon 128x128 Customizer Search
Version 1.1.4
Comparing to
See all releases

Code changes from version 1.1.3 to 1.1.4

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. ' );
184
+
185
+ if ( is_multisite() ) {
186
+ $notice_string .= __( 'This will be applicable for all sites from the network.' );
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.', 'astra' ) ),
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' ),
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' )
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' ),
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' ), // 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.' );
381
+
382
+ if ( is_multisite() ) {
383
+ esc_html_e( ' This will be applicable for all sites from the network.' );
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.' ) ) );
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
+ }
customizer-search.php CHANGED
@@ -7,12 +7,12 @@
7
  * Author URI: https://www.brainstormforce.com/
8
  * Text Domain: customizer-search
9
  * Domain Path: /languages
10
- * Version: 1.1.3
11
  *
12
  * @package Customizer_Search
13
  */
14
 
15
- define( 'BSFCS_VER', '1.1.3' );
16
  define( 'BSFCS_DIR', plugin_dir_path( __FILE__ ) );
17
  define( 'BSFCS_URL', plugins_url( '/', __FILE__ ) );
18
  define( 'BSFCS_PATH', plugin_basename( __FILE__ ) );
@@ -21,3 +21,11 @@ define( 'BSFCS_PATH', plugin_basename( __FILE__ ) );
21
  * Load the plugin.
22
  */
23
  require_once 'class-customizer-search.php';
 
 
 
 
 
 
 
 
7
  * Author URI: https://www.brainstormforce.com/
8
  * Text Domain: customizer-search
9
  * Domain Path: /languages
10
+ * Version: 1.1.4
11
  *
12
  * @package Customizer_Search
13
  */
14
 
15
+ define( 'BSFCS_VER', '1.1.4' );
16
  define( 'BSFCS_DIR', plugin_dir_path( __FILE__ ) );
17
  define( 'BSFCS_URL', plugins_url( '/', __FILE__ ) );
18
  define( 'BSFCS_PATH', plugin_basename( __FILE__ ) );
21
  * Load the plugin.
22
  */
23
  require_once 'class-customizer-search.php';
24
+
25
+ if ( is_admin() ) {
26
+ // Admin Notice Library Settings.
27
+ require_once 'lib/notices/class-astra-notices.php';
28
+ }
29
+
30
+ // BSF Analytics library.
31
+ require_once 'admin/bsf-analytics/class-bsf-analytics.php';
languages/customizer-search.pot CHANGED
@@ -1,29 +1,77 @@
1
- # Copyright (C) 2018 Brainstorm Force
2
  # This file is distributed under the same license as the Customizer Search package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: Customizer Search 1.1.1\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/customizer-search\n"
8
- "POT-Creation-Date: 2018-03-04 05:02:50+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
- "PO-Revision-Date: 2018-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
15
- "X-Generator: grunt-wp-i18n 0.5.4\n"
16
- "X-Poedit-KeywordsList: "
17
- "__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_"
18
- "attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n"
19
  "Language: en\n"
20
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
21
  "X-Poedit-Country: United States\n"
22
  "X-Poedit-SourceCharset: UTF-8\n"
 
 
 
23
  "X-Poedit-Basepath: ../\n"
24
  "X-Poedit-SearchPath-0: .\n"
25
  "X-Poedit-Bookmarks: \n"
26
  "X-Textdomain-Support: yes\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  #: templates/admin-customize-js-templates.php:20
29
  msgid "Search"
1
+ # Copyright (C) 2020 Brainstorm Force
2
  # This file is distributed under the same license as the Customizer Search package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: Customizer Search 1.1.4\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/customizer-search\n"
8
+ "POT-Creation-Date: 2020-06-15 05:32:03+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
12
+ "PO-Revision-Date: 2020-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
 
 
 
 
15
  "Language: en\n"
16
  "Plural-Forms: nplurals=2; plural=(n != 1);\n"
17
  "X-Poedit-Country: United States\n"
18
  "X-Poedit-SourceCharset: UTF-8\n"
19
+ "X-Poedit-KeywordsList: "
20
+ "__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_"
21
+ "attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n"
22
  "X-Poedit-Basepath: ../\n"
23
  "X-Poedit-SearchPath-0: .\n"
24
  "X-Poedit-Bookmarks: \n"
25
  "X-Textdomain-Support: yes\n"
26
+ "X-Generator: grunt-wp-i18n 1.0.3\n"
27
+
28
+ #: admin/bsf-analytics/class-bsf-analytics.php:183
29
+ #. translators: %s product name
30
+ msgid ""
31
+ "Want to help make <strong>%1s</strong> even more awesome? Allow us to "
32
+ "collect non-sensitive diagnostic data and usage information. "
33
+ msgstr ""
34
+
35
+ #: admin/bsf-analytics/class-bsf-analytics.php:186
36
+ msgid "This will be applicable for all sites from the network."
37
+ msgstr ""
38
+
39
+ #: admin/bsf-analytics/class-bsf-analytics.php:210
40
+ #. translators: %s usage doc link
41
+ msgid " Know More."
42
+ msgstr ""
43
+
44
+ #: admin/bsf-analytics/class-bsf-analytics.php:217
45
+ msgid "Yes! Allow it"
46
+ msgstr ""
47
+
48
+ #: admin/bsf-analytics/class-bsf-analytics.php:225
49
+ msgid "No Thanks"
50
+ msgstr ""
51
+
52
+ #: admin/bsf-analytics/class-bsf-analytics.php:294
53
+ msgid "Every two days"
54
+ msgstr ""
55
+
56
+ #: admin/bsf-analytics/class-bsf-analytics.php:348
57
+ msgid "Usage Tracking"
58
+ msgstr ""
59
+
60
+ #: admin/bsf-analytics/class-bsf-analytics.php:380
61
+ msgid "Allow Brainstorm Force products to track non-sensitive usage tracking data."
62
+ msgstr ""
63
+
64
+ #: admin/bsf-analytics/class-bsf-analytics.php:383
65
+ msgid " This will be applicable for all sites from the network."
66
+ msgstr ""
67
+
68
+ #: admin/bsf-analytics/class-bsf-analytics.php:388
69
+ msgid "Learn More."
70
+ msgstr ""
71
+
72
+ #: lib/notices/class-astra-notices.php:125
73
+ msgid "WordPress Nonce not validated."
74
+ msgstr ""
75
 
76
  #: templates/admin-customize-js-templates.php:20
77
  msgid "Search"
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.4.0
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.4.0
28
+ */
29
+ class Astra_Notices {
30
+
31
+ /**
32
+ * Notices
33
+ *
34
+ * @access private
35
+ * @var array Notices.
36
+ * @since 1.4.0
37
+ */
38
+ private static $version = '1.1.5';
39
+
40
+ /**
41
+ * Notices
42
+ *
43
+ * @access private
44
+ * @var array Notices.
45
+ * @since 1.4.0
46
+ */
47
+ private static $notices = array();
48
+
49
+ /**
50
+ * Instance
51
+ *
52
+ * @access private
53
+ * @var object Class object.
54
+ * @since 1.4.0
55
+ */
56
+ private static $instance;
57
+
58
+ /**
59
+ * Initiator
60
+ *
61
+ * @since 1.4.0
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.4.0
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.4.0
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.4.0
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.4.0
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.', 'customizer-search' ) );
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.4.0
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.4.0
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.4.0
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.4.0
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.4.0
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.4.0
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.0.0
13
+ * @class ASTCustomizer
14
+ */
15
+ AstraNotices = {
16
+
17
+ /**
18
+ * Initializes our custom logic for the Customizer.
19
+ *
20
+ * @since 1.0.0
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.0.0
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, Nikschavan
3
  Donate link: https://www.paypal.me/BrainstormForce
4
  Tags: customizer, search
5
  Requires at least: 4.6
6
- Tested up to: 5.4
7
- Stable tag: 1.1.3
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -26,6 +26,9 @@ https://www.youtube.com/watch?v=IBFfap_vGzg
26
 
27
  == Changelog ==
28
 
 
 
 
29
  = 1.1.3 =
30
  - Setup plugin translations through https://translate.wordpress.org/projects/wp-plugins/customizer-search/.
31
 
3
  Donate link: https://www.paypal.me/BrainstormForce
4
  Tags: customizer, search
5
  Requires at least: 4.6
6
+ Tested up to: 5.4.2
7
+ Stable tag: 1.1.4
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
26
 
27
  == Changelog ==
28
 
29
+ = 1.1.4 =
30
+ - 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 )
31
+
32
  = 1.1.3 =
33
  - Setup plugin translations through https://translate.wordpress.org/projects/wp-plugins/customizer-search/.
34