Custom Login - Version 3.2.8

Version Description

Download this release

Release Info

Developer austyfrosty
Plugin Icon 128x128 Custom Login
Version 3.2.8
Comparing to
See all releases

Code changes from version 3.2.5 to 3.2.8

README.md CHANGED
@@ -3,7 +3,7 @@
3
  **Donate link:** https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7431290
4
  **Tags:** admin, branding, customization, custom login, login, logo, error, login error, custom login pro
5
  **Requires at least:** 4.0
6
- **Tested up to:** 4.5
7
  **Stable tag:** trunk
8
  **License:** GPLv2 or later
9
  **License URI:** http://www.gnu.org/licenses/gpl-2.0.html
@@ -17,7 +17,7 @@ Custom Login 2.0 was 140% faster than version 1.0, and version 3.0 is now even b
17
  For more information visit the official [Custom Login](https://frosty.media/plugins/custom-login/) page.
18
 
19
  > <strong>Support</strong><br>
20
- > [Austin](http://austin.passy.co) and the [Frosty Media](https://frosty.media/) team will always try our best to support the Custom Login plugin on the WordPress.org forum, but please note that we can not guarantee a response in a timely manner. If you have an issue we would appriciate you using GitHub or purchasing priority support on our site.
21
  >
22
  > Any extensions purchased on [Frosty Media](https://frosty.media/) (not hosted on WordPress.org) will not be supported on the WordPress.org forum. You can always browse our *small* but growing [documentation](https://frosty.media/docs) for further assistance. You need a valid license key to make support submissions *on our site*. We thank you in advance.
23
 
@@ -62,7 +62,7 @@ Activate the plugin and customize your WordPress login screen. It's as easy as m
62
  ### links ###
63
 
64
  * Premium Plugins: [https://frosty.media/plugins](https://frosty.media/plugins/ "Premium WordPress Plugins by Frosty")
65
- * Austins Blog: [https:/austin.passy.co/](http://austin.passy.co/ "Austin Passy's blog")
66
  * Austin on Twitter: @[TheFrosty](https:/twitter.com/TheFrosty "Austin TheFrosty' Passy on Twitter")
67
  * Frosty Media on Twitter: @[Frosty_Media](https:/twitter.com/Frosty_Media "Frosty Media on Twitter")
68
  * **Development welcomed on [GitHub](https://github.com/thefrosty/custom-login)**
@@ -131,33 +131,6 @@ Custom Login showcase on the [Flickr group](http://flickr.com/groups/custom-logi
131
 
132
  ## Changelog ##
133
 
134
- ### Version 3.2.5 (04/13/16) ###
135
-
136
- * WordPress 4.5 compatible update (moves Custom Login css after WordPress' login style sheet).
137
- * Fix issue where toggling the 'active' checkbox in the header doesn't activate or de-activate the plugin settings (updates via AJAX now).
138
-
139
- ### Version 3.2.4 (09/16/15) ###
140
-
141
- * Fix PHP Fatal error.
142
- ** PHP Fatal error: Call to a member function get_permalink() on a non-object in /includes/admin/dashboard.php:114
143
-
144
- ### Version 3.2.2 (05/04/15) ###
145
-
146
- * May the fourth be with you.
147
- * Cleaned up dashboard JS errors.
148
-
149
- ### Version 3.2.2 (04/29/15) ###
150
-
151
- * Update version number.
152
- * Fix upgrade notice showing when not needed.
153
- * Add class 'notice' and 'is-dismissible' to notice.
154
- * Cleanup admin dashboard empty ob_get_clean() notice.
155
-
156
- ### Version 3.2.1 (04/20/15) ###
157
-
158
- * Fix: XSS security flaw.
159
- * Fix: Settings page not showing. (Fixes Issue: [#6](https://github.com/thefrosty/custom-login/pull/6) /ht @[DrewAPicture](https://github.com/DrewAPicture).
160
-
161
  ### Version 3.2 (02/09/15) ###
162
 
163
  * Message: Celebrate 500,000 downloads. Visit the settings page or [this post](https://frosty.media/?p=26056) to get any extension for free! *Restrictions may apply.
3
  **Donate link:** https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7431290
4
  **Tags:** admin, branding, customization, custom login, login, logo, error, login error, custom login pro
5
  **Requires at least:** 4.0
6
+ **Tested up to:** 4.1
7
  **Stable tag:** trunk
8
  **License:** GPLv2 or later
9
  **License URI:** http://www.gnu.org/licenses/gpl-2.0.html
17
  For more information visit the official [Custom Login](https://frosty.media/plugins/custom-login/) page.
18
 
19
  > <strong>Support</strong><br>
20
+ > [Austin](https://austin.passy.co) and the [Frosty Media](https://frosty.media/) team will always try our best to support the Custom Login plugin on the WordPress.org forum, but please note that we can not guarantee a response in a timely manner. If you have an issue we would appriciate you using GitHub or purchasing priority support on our site.
21
  >
22
  > Any extensions purchased on [Frosty Media](https://frosty.media/) (not hosted on WordPress.org) will not be supported on the WordPress.org forum. You can always browse our *small* but growing [documentation](https://frosty.media/docs) for further assistance. You need a valid license key to make support submissions *on our site*. We thank you in advance.
23
 
62
  ### links ###
63
 
64
  * Premium Plugins: [https://frosty.media/plugins](https://frosty.media/plugins/ "Premium WordPress Plugins by Frosty")
65
+ * Austins Blog: [https:/austin.passy.co/](https://austin.passy.co/ "Austin Passy's blog")
66
  * Austin on Twitter: @[TheFrosty](https:/twitter.com/TheFrosty "Austin TheFrosty' Passy on Twitter")
67
  * Frosty Media on Twitter: @[Frosty_Media](https:/twitter.com/Frosty_Media "Frosty Media on Twitter")
68
  * **Development welcomed on [GitHub](https://github.com/thefrosty/custom-login)**
131
 
132
  ## Changelog ##
133
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
  ### Version 3.2 (02/09/15) ###
135
 
136
  * Message: Celebrate 500,000 downloads. Visit the settings page or [this post](https://frosty.media/?p=26056) to get any extension for free! *Restrictions may apply.
css/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
css/chosen/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
css/login/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
custom-login.php CHANGED
@@ -3,14 +3,14 @@
3
  * Plugin Name: Custom Login
4
  * Plugin URI: https://frosty.media/plugins/custom-login
5
  * Description: A simple way to customize your WordPress <code>wp-login.php</code> screen! A <a href="https://frosty.media/">Frosty Media</a> plugin.
6
- * Version: 3.2.5
7
  * Author: Austin Passy
8
- * Author URI: http://austin.passy.co
9
  * Text Domain: custom-login
10
  * GitHub Plugin URI: https://github.com/thefrosty/custom-login
11
  * GitHub Branch: master
12
  *
13
- * @copyright 2012 - 2016
14
  * @author Austin Passy
15
  * @link http://austin.passy.co/
16
  * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
@@ -22,337 +22,329 @@
22
  * @class Custom_Login
23
  */
24
 
25
- if ( ! class_exists( 'Custom_Login' ) ) :
26
 
27
- /**
28
- * Main Custom_Login Class
29
- *
30
- * @since 2.0
31
- */
32
- final class Custom_Login {
33
-
34
- /** Singleton *************************************************************/
35
- private static $instance;
36
-
37
- /**
38
- * Plugin vars
39
- *
40
- * @return string
41
- */
42
- var $version = '3.2.5',
43
- $menu_page,
44
- $prefix;
45
-
46
- /**
47
- * Private settings
48
- */
49
- public $settings_api;
50
-
51
- /**
52
- * Main Instance
53
- *
54
- * @staticvar array $instance
55
- * @return Custom_Login The one true instance
56
- */
57
- public static function instance() {
58
- if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Custom_Login ) ) {
59
- self::$instance = new Custom_Login;
60
- self::$instance->setup_constants();
61
-
62
- add_action( 'plugins_loaded', array( self::$instance, 'plugin_textdomain' ) );
63
-
64
- self::$instance->includes();
65
- self::$instance->actions();
66
- }
67
-
68
- return self::$instance;
69
- }
70
-
71
- /**
72
- * Setup plugin constants
73
- *
74
- * @access private
75
- * @since 3.0
76
- * @return void
77
- */
78
- private function setup_constants() {
79
-
80
- // API URL
81
- if ( ! defined( 'CUSTOM_LOGIN_API_URL' ) ) {
82
- define( 'CUSTOM_LOGIN_API_URL', 'https://frosty.media/' );
83
- }
84
-
85
- // Plugin version
86
- if ( ! defined( 'CUSTOM_LOGIN_VERSION' ) ) {
87
- define( 'CUSTOM_LOGIN_VERSION', $this->version );
88
- }
89
-
90
- // Plugin Root File
91
- if ( ! defined( 'CUSTOM_LOGIN_FILE' ) ) {
92
- define( 'CUSTOM_LOGIN_FILE', __FILE__ );
93
- }
94
-
95
- // Plugin Folder Path
96
- if ( ! defined( 'CUSTOM_LOGIN_DIR' ) ) {
97
- define( 'CUSTOM_LOGIN_DIR', plugin_dir_path( CUSTOM_LOGIN_FILE ) );
98
- }
99
-
100
- // Plugin Folder URL
101
- if ( ! defined( 'CUSTOM_LOGIN_URL' ) ) {
102
- define( 'CUSTOM_LOGIN_URL', plugin_dir_url( CUSTOM_LOGIN_FILE ) );
103
- }
104
-
105
- // Plugin Root Basename
106
- if ( ! defined( 'CUSTOM_LOGIN_BASENAME' ) ) {
107
- define( 'CUSTOM_LOGIN_BASENAME', plugin_basename( CUSTOM_LOGIN_FILE ) );
108
- }
109
-
110
- // Plugin Dirname
111
- if ( ! defined( 'CUSTOM_LOGIN_DIRNAME' ) ) {
112
- define( 'CUSTOM_LOGIN_DIRNAME', dirname( CUSTOM_LOGIN_BASENAME ) );
113
- }
114
-
115
- // Plugin Settings Name
116
- if ( ! defined( 'CUSTOM_LOGIN_OPTION' ) ) {
117
- define( 'CUSTOM_LOGIN_OPTION', str_replace( '-', '_', CUSTOM_LOGIN_DIRNAME ) );
118
- }
119
- }
120
-
121
- /**
122
- * Load the plugin translations
123
- *
124
- */
125
- public function plugin_textdomain() {
126
- load_plugin_textdomain( CUSTOM_LOGIN_DIRNAME, false, CUSTOM_LOGIN_DIRNAME . '/languages/' );
127
- }
128
-
129
- /**
130
- * Includes required functions
131
- *
132
- */
133
- private function includes() {
134
-
135
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-common.php' );
136
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-cron.php' );
137
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-extensions.php' );
138
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-templates.php' );
139
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-scripts-styles.php' );
140
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-settings-api.php' );
141
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-settings-upgrades.php' );
142
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-wp-login.php' );
143
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/functions.php' );
144
-
145
- if ( is_admin() ) {
146
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/admin/dashboard.php' );
147
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/admin/plugins.php' );
148
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/admin/import-export.php' );
149
- require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/admin/tracking.php' );
150
- }
151
- }
152
-
153
- /**
154
- * To infinity and beyond
155
- */
156
- private function actions() {
157
-
158
- $this->prefix = CUSTOM_LOGIN_OPTION;
159
-
160
- register_activation_hook( CUSTOM_LOGIN_FILE, array( $this, 'activate' ) );
161
-
162
- add_action( 'login_head', array( $this, 'cl_version_in_header' ), 1 );
163
- add_action( 'wp_head', array( $this, 'cl_version_in_header' ) );
164
- add_action( 'admin_menu', array( $this, 'admin_menu' ), 9 );
165
- add_action( 'admin_init', array( $this, 'load_settings' ), 8 );
166
- add_action( $this->prefix . '_after_sanitize_options', array( $this, 'delete_transients' ), 8 );
167
-
168
- add_action( 'admin_notices', array( $this, 'show_notifications' ) );
169
- add_action( 'admin_init', array( $this, 'notification_ignore' ) );
170
-
171
- do_action( $this->prefix . '_actions' );
172
- }
173
-
174
- /**
175
- * Runs on plugin install.
176
- *
177
- * @since 3.1
178
- * @return void
179
- */
180
- function activate() {
181
- }
182
-
183
- /**
184
- * Adds CL Version to the <head> tag
185
- *
186
- * @since 3.0.0
187
- * @return void
188
- */
189
- function cl_version_in_header() {
190
- echo '<meta name="generator" content="Custom Login v' . CUSTOM_LOGIN_VERSION . '" />' . "\n";
191
- }
192
-
193
- /**
194
- * Register the plugin page
195
- */
196
- public function admin_menu() {
197
-
198
- $capability = CL_Common::get_option( 'capability', 'general', 'manage_options' );
199
-
200
- $this->menu_page = add_options_page(
201
- __( 'Custom Login Settings', CUSTOM_LOGIN_DIRNAME ),
202
- __( 'Custom Login', CUSTOM_LOGIN_DIRNAME ),
203
- $capability,
204
- CUSTOM_LOGIN_DIRNAME,
205
- array( $this, 'settings_page' )
206
- );
207
- }
208
-
209
- /**
210
- * Display the plugin settings options page
211
- */
212
- public function settings_page() { ?>
213
-
214
- <div class="wrap">
215
- <?php $this->settings_api->settings_html(); ?>
216
- </div><?php
217
- }
218
-
219
- /**
220
- * Display the plugin settings options page
221
- */
222
- public function load_settings() {
223
-
224
- include( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/default-settings.php' );
225
- $this->settings_api = new CL_Settings_API(
226
- $sections,
227
- $fields,
228
- array(
229
- 'option_name' => CUSTOM_LOGIN_OPTION,
230
- 'option_group' => CUSTOM_LOGIN_OPTION . '_group',
231
- 'domain' => CUSTOM_LOGIN_DIRNAME,
232
- 'prefix' => $this->prefix,
233
- 'version' => $this->version,
234
- 'menu_page' => $this->menu_page,
235
- 'nonce' => CUSTOM_LOGIN_OPTION . '_nonce_' . CUSTOM_LOGIN_BASENAME,
236
- 'file' => CUSTOM_LOGIN_FILE,
237
- )
238
- );
239
- $this->settings_api->admin_init();
240
- }
241
-
242
- /**
243
- * Hook into the 'sanitize_options' hook in the Settings API
244
- * and remove the transient settings for the style and script.
245
- *
246
- * @since 3.0.0
247
- */
248
- public function delete_transients() {
249
- delete_transient( CL_Common::get_transient_key( 'style' ) );
250
- delete_transient( CL_Common::get_transient_key( 'script' ) );
251
- }
252
-
253
- /**
254
- * Show global notifications if they are allowed.
255
- *
256
- */
257
- function show_notifications() {
258
-
259
- $is_cl_screen = CL_Common::is_settings_page();
260
- $transient_key = CL_Common::get_transient_key( 'announcement' );
261
- $ignore_key = CUSTOM_LOGIN_OPTION . '_ignore_announcement';
262
- $old_message = get_option( CUSTOM_LOGIN_OPTION . '_announcement_message' );
263
- $user_meta = get_user_meta( get_current_user_id(), $ignore_key, true );
264
- $capability = CL_Common::get_option( 'capability', 'general', 'manage_options' );
265
-
266
- /**
267
- * delete_user_meta( get_current_user_id(), $ignore_key, 1 );
268
- * delete_transient( $transient_key );
269
- * update_option( CUSTOM_LOGIN_OPTION . '_announcement_message', '' ); //*/
270
-
271
- // Current user can't manage options
272
- if ( ! current_user_can( $capability ) ) {
273
- return;
274
- }
275
-
276
- if ( ! $is_cl_screen ) {
277
-
278
- // Let's not show this at all if not on out menu page. @since 3.1
279
- return;
280
-
281
- // Global notifications
282
- if ( 'off' === CL_Common::get_option( 'admin_notices', 'general', 'off' ) ) {
283
- return;
284
- }
285
-
286
- // Make sure 'Frosty_Media_Notifications' isn't activated
287
- if ( class_exists( 'Frosty_Media_Notifications' ) ) {
288
- return;
289
- }
290
- }
291
-
292
- // https://raw.github.com/thefrosty/custom-login/master/extensions.json
293
- $message_url = esc_url( add_query_arg( array( 'edd_action' => 'cl_announcements' ), trailingslashit( CUSTOM_LOGIN_API_URL ) . 'cl-checkin-api/' ) );
294
-
295
- $announcement = CL_Common::wp_remote_get(
296
- $message_url,
297
- $transient_key,
298
- DAY_IN_SECONDS,
299
- 'CustomLogin' // We need our custom $user_agent
300
- );
301
-
302
- // Bail if errors
303
- if ( is_wp_error( $announcement ) ) {
304
- return;
305
- }
306
-
307
- // Bail if false or empty
308
- if ( ! $announcement || empty( $announcement ) ) {
309
- return;
310
- }
311
-
312
- if ( trim( $old_message ) !== trim( $announcement->message ) && ! empty( $old_message ) ) {
313
- delete_user_meta( get_current_user_id(), $ignore_key );
314
- delete_transient( $transient_key );
315
- update_option( CUSTOM_LOGIN_OPTION . '_announcement_message', $announcement->message );
316
- }
317
-
318
- $html = '<div class="updated"><p>';
319
- $html .= ! $is_cl_screen ? // If we're on our settings page let not show the dismiss notice link.
320
- sprintf( '%2$s <span class="alignright">| <a href="%3$s">%1$s</a></span>',
321
- __( 'Dismiss', CUSTOM_LOGIN_DIRNAME ),
322
- $announcement->message,
323
- esc_url( add_query_arg( $ignore_key, wp_create_nonce( $ignore_key ), admin_url( 'options-general.php?page=custom-login' ) ) ),
324
- esc_url( admin_url( 'options-general.php?page=custom-login#custom_login_general' ) )
325
- ) :
326
- sprintf( '%s', $announcement->message );
327
- $html .= '</p></div>';
328
-
329
- if ( ( ! $user_meta && 1 !== $user_meta ) || $is_cl_screen ) {
330
- echo $html;
331
- }
332
- }
333
-
334
- /**
335
- * Remove the admin notification.
336
- *
337
- * @return void
338
- */
339
- function notification_ignore() {
340
-
341
- $ignore_key = CUSTOM_LOGIN_OPTION . '_ignore_announcement';
342
-
343
- // Bail if not set
344
- if ( ! isset( $_GET[ $ignore_key ] ) ) {
345
- return;
346
- }
347
-
348
- // Check nonce
349
- check_admin_referer( $ignore_key, $ignore_key );
350
 
351
- // If user clicks to ignore the notice, add that to their user meta
352
- add_user_meta( get_current_user_id(), $ignore_key, 1, true );
353
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
354
 
355
- }
356
 
357
  endif; // End if class_exists check
358
 
@@ -365,13 +357,13 @@ endif; // End if class_exists check
365
  *
366
  * Example: <?php $custom_login = CUSTOMLOGIN(); ?>
367
  *
368
- * @return Custom_Login
369
  */
370
- if ( ! function_exists( 'CUSTOMLOGIN' ) ) {
371
- function CUSTOMLOGIN() {
372
- return Custom_Login::instance();
373
- }
374
  }
375
 
376
  // Out of the frying pan, and into the fire.
377
- CUSTOMLOGIN();
3
  * Plugin Name: Custom Login
4
  * Plugin URI: https://frosty.media/plugins/custom-login
5
  * Description: A simple way to customize your WordPress <code>wp-login.php</code> screen! A <a href="https://frosty.media/">Frosty Media</a> plugin.
6
+ * Version: 3.2
7
  * Author: Austin Passy
8
+ * Author URI: https://austin.passy.co
9
  * Text Domain: custom-login
10
  * GitHub Plugin URI: https://github.com/thefrosty/custom-login
11
  * GitHub Branch: master
12
  *
13
+ * @copyright 2012 - 2015
14
  * @author Austin Passy
15
  * @link http://austin.passy.co/
16
  * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22
  * @class Custom_Login
23
  */
24
 
25
+ if ( !class_exists( 'Custom_Login' ) ) :
26
 
27
+ /**
28
+ * Main Custom_Login Class
29
+ *
30
+ * @since 2.0
31
+ */
32
+ final class Custom_Login {
33
+
34
+ /** Singleton *************************************************************/
35
+ private static $instance;
36
+
37
+ /**
38
+ * Plugin vars
39
+ * @return string
40
+ */
41
+ var $version = '3.2',
42
+ $menu_page,
43
+ $prefix;
44
+
45
+ /**
46
+ * Private settings
47
+ */
48
+ public $settings_api;
49
+
50
+ /**
51
+ * Main Instance
52
+ *
53
+ * @staticvar array $instance
54
+ * @return The one true instance
55
+ */
56
+ public static function instance() {
57
+ if ( ! isset( self::$instance ) && ! ( self::$instance instanceof Custom_Login ) ) {
58
+ self::$instance = new Custom_Login;
59
+ self::$instance->setup_constants();
60
+
61
+ add_action( 'plugins_loaded', array( self::$instance, 'plugin_textdomain' ) );
62
+
63
+ self::$instance->includes();
64
+ self::$instance->actions();
65
+ }
66
+ return self::$instance;
67
+ }
68
+
69
+ /**
70
+ * Setup plugin constants
71
+ *
72
+ * @access private
73
+ * @since 3.0
74
+ * @return void
75
+ */
76
+ private function setup_constants() {
77
+
78
+ // API URL
79
+ if ( ! defined( 'CUSTOM_LOGIN_API_URL' ) ) {
80
+ define( 'CUSTOM_LOGIN_API_URL', 'https://frosty.media/' );
81
+ }
82
+
83
+ // Plugin version
84
+ if ( ! defined( 'CUSTOM_LOGIN_VERSION' ) ) {
85
+ define( 'CUSTOM_LOGIN_VERSION', $this->version );
86
+ }
87
+
88
+ // Plugin Root File
89
+ if ( ! defined( 'CUSTOM_LOGIN_FILE' ) ) {
90
+ define( 'CUSTOM_LOGIN_FILE', __FILE__ );
91
+ }
92
+
93
+ // Plugin Folder Path
94
+ if ( ! defined( 'CUSTOM_LOGIN_DIR' ) ) {
95
+ define( 'CUSTOM_LOGIN_DIR', plugin_dir_path( CUSTOM_LOGIN_FILE ) );
96
+ }
97
+
98
+ // Plugin Folder URL
99
+ if ( ! defined( 'CUSTOM_LOGIN_URL' ) ) {
100
+ define( 'CUSTOM_LOGIN_URL', plugin_dir_url( CUSTOM_LOGIN_FILE ) );
101
+ }
102
+
103
+ // Plugin Root Basename
104
+ if ( ! defined( 'CUSTOM_LOGIN_BASENAME' ) ) {
105
+ define( 'CUSTOM_LOGIN_BASENAME', plugin_basename( CUSTOM_LOGIN_FILE ) );
106
+ }
107
+
108
+ // Plugin Dirname
109
+ if ( ! defined( 'CUSTOM_LOGIN_DIRNAME' ) ) {
110
+ define( 'CUSTOM_LOGIN_DIRNAME', dirname( CUSTOM_LOGIN_BASENAME ) );
111
+ }
112
+
113
+ // Plugin Settings Name
114
+ if ( ! defined( 'CUSTOM_LOGIN_OPTION' ) ) {
115
+ define( 'CUSTOM_LOGIN_OPTION', str_replace( '-', '_', CUSTOM_LOGIN_DIRNAME ) );
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Load the plugin translations
121
+ *
122
+ */
123
+ public function plugin_textdomain() {
124
+ load_plugin_textdomain( CUSTOM_LOGIN_DIRNAME, false, CUSTOM_LOGIN_DIRNAME . '/languages/' );
125
+ }
126
+
127
+ /**
128
+ * Includes required functions
129
+ *
130
+ */
131
+ private function includes() {
132
+
133
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-common.php' );
134
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-cron.php' );
135
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-extensions.php' );
136
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-templates.php' );
137
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-scripts-styles.php' );
138
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-settings-api.php' );
139
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-settings-upgrades.php' );
140
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/class-cl-wp-login.php' );
141
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/functions.php' );
142
+
143
+ if ( is_admin() ) {
144
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/admin/dashboard.php' );
145
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/admin/plugins.php' );
146
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/admin/import-export.php' );
147
+ require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/admin/tracking.php' );
148
+ // require_once( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/admin/roost.php' ); // Not enabled until global domains available.
149
+ }
150
+ }
151
+
152
+ /**
153
+ * To infinity and beyond
154
+ */
155
+ private function actions() {
156
+
157
+ $this->prefix = CUSTOM_LOGIN_OPTION;
158
+
159
+ register_activation_hook( CUSTOM_LOGIN_FILE, array( $this, 'activate' ) );
160
+
161
+ add_action( 'login_head', array( $this, 'cl_version_in_header' ), 1 );
162
+ add_action( 'wp_head', array( $this, 'cl_version_in_header' ) );
163
+ add_action( 'admin_menu', array( $this, 'admin_menu' ), 9 );
164
+ add_action( 'admin_init', array( $this, 'load_settings' ), 8 );
165
+ add_action( $this->prefix . '_after_sanitize_options', array( $this, 'delete_transients' ), 8 );
166
+
167
+ add_action( 'admin_notices', array( $this, 'show_notifications' ) );
168
+ add_action( 'admin_init', array( $this, 'notification_ignore' ) );
169
+
170
+ do_action( $this->prefix . '_actions' );
171
+ }
172
+
173
+ /**
174
+ * Runs on plugin install.
175
+ *
176
+ * @since 3.1
177
+ * @return void
178
+ */
179
+ function activate() {
180
+ }
181
+
182
+ /**
183
+ * Adds CL Version to the <head> tag
184
+ *
185
+ * @since 3.0.0
186
+ * @return void
187
+ */
188
+ function cl_version_in_header(){
189
+ echo '<meta name="generator" content="Custom Login v' . CUSTOM_LOGIN_VERSION . '" />' . "\n";
190
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
 
192
+ /**
193
+ * Register the plugin page
194
+ */
195
+ public function admin_menu() {
196
+
197
+ $capability = CL_Common::get_option( 'capability', 'general', 'manage_options' );
198
+
199
+ $this->menu_page = add_options_page(
200
+ __( 'Custom Login Settings', CUSTOM_LOGIN_DIRNAME ),
201
+ __( 'Custom Login', CUSTOM_LOGIN_DIRNAME ),
202
+ $capability,
203
+ CUSTOM_LOGIN_DIRNAME,
204
+ array( $this, 'settings_page' )
205
+ );
206
+ }
207
+
208
+ /**
209
+ * Display the plugin settings options page
210
+ */
211
+ public function settings_page() { ?>
212
+
213
+ <div class="wrap">
214
+ <?php $this->settings_api->settings_html(); ?>
215
+ </div><?php
216
+ }
217
+
218
+ /**
219
+ * Display the plugin settings options page
220
+ */
221
+ public function load_settings() {
222
+
223
+ include( trailingslashit( CUSTOM_LOGIN_DIR ) . 'includes/default-settings.php' );
224
+ $this->settings_api = new CL_Settings_API(
225
+ $sections,
226
+ $fields,
227
+ array(
228
+ 'option_name' => CUSTOM_LOGIN_OPTION,
229
+ 'option_group' => CUSTOM_LOGIN_OPTION . '_group',
230
+ 'domain' => CUSTOM_LOGIN_DIRNAME,
231
+ 'prefix' => $this->prefix,
232
+ 'version' => $this->version,
233
+ 'menu_page' => $this->menu_page,
234
+ 'nonce' => CUSTOM_LOGIN_OPTION . '_nonce_' . CUSTOM_LOGIN_BASENAME,
235
+ 'file' => CUSTOM_LOGIN_FILE,
236
+ )
237
+ );
238
+ $this->settings_api->admin_init();
239
+ }
240
+
241
+ /**
242
+ * Hook into the 'sanitize_options' hook in the Settings API
243
+ * and remove the transient settings for the style and script.
244
+ *
245
+ * @since 3.0.0
246
+ */
247
+ public function delete_transients() {
248
+ delete_transient( CL_Common::get_transient_key( 'style' ) );
249
+ delete_transient( CL_Common::get_transient_key( 'script' ) );
250
+ }
251
+
252
+ /**
253
+ * Show global notifications if they are allowed.
254
+ *
255
+ */
256
+ function show_notifications() {
257
+
258
+ $is_cl_screen = CL_Common::is_settings_page();
259
+ $transient_key = CL_Common::get_transient_key( 'announcement' );
260
+ $ignore_key = CUSTOM_LOGIN_OPTION . '_ignore_announcement';
261
+ $old_message = get_option( CUSTOM_LOGIN_OPTION . '_announcement_message' );
262
+ $user_meta = get_user_meta( get_current_user_id(), $ignore_key, true );
263
+ $capability = CL_Common::get_option( 'capability', 'general', 'manage_options' );
264
+
265
+ /**
266
+ delete_user_meta( get_current_user_id(), $ignore_key, 1 );
267
+ delete_transient( $transient_key );
268
+ update_option( CUSTOM_LOGIN_OPTION . '_announcement_message', '' ); //*/
269
+
270
+ // Current user can't manage options
271
+ if ( !current_user_can( $capability ) )
272
+ return;
273
+
274
+ if ( !$is_cl_screen ) {
275
+
276
+ // Let's not show this at all if not on out menu page. @since 3.1
277
+ return;
278
+
279
+ // Global notifications
280
+ if ( 'off' === CL_Common::get_option( 'admin_notices', 'general', 'off' ) )
281
+ return;
282
+
283
+ // Make sure 'Frosty_Media_Notifications' isn't activated
284
+ if ( class_exists( 'Frosty_Media_Notifications' ) )
285
+ return;
286
+ }
287
+
288
+ // https://raw.github.com/thefrosty/custom-login/master/extensions.json
289
+ $message_url = add_query_arg( array( 'edd_action' => 'cl_announcements' ), trailingslashit( CUSTOM_LOGIN_API_URL ) . 'cl-checkin-api/' );
290
+
291
+ $announcement = CL_Common::wp_remote_get(
292
+ $message_url,
293
+ $transient_key,
294
+ DAY_IN_SECONDS,
295
+ 'CustomLogin' // We need our custom $user_agent
296
+ );
297
+
298
+ // Bail if errors
299
+ if ( is_wp_error( $announcement ) )
300
+ return;
301
+
302
+ // Bail if false or empty
303
+ if ( !$announcement || empty( $announcement ) )
304
+ return;
305
+
306
+ if ( trim( $old_message ) !== trim( $announcement->message ) && !empty( $old_message ) ) {
307
+ delete_user_meta( get_current_user_id(), $ignore_key );
308
+ delete_transient( $transient_key );
309
+ update_option( CUSTOM_LOGIN_OPTION . '_announcement_message', $announcement->message );
310
+ }
311
+
312
+ $html = '<div class="updated"><p>';
313
+ $html .= !$is_cl_screen ? // If we're on our settings page let not show the dismiss notice link.
314
+ sprintf( '%2$s <span class="alignright">| <a href="%3$s">%1$s</a></span>',
315
+ __( 'Dismiss', CUSTOM_LOGIN_DIRNAME ),
316
+ $announcement->message,
317
+ esc_url( add_query_arg( $ignore_key, wp_create_nonce( $ignore_key ), admin_url( 'options-general.php?page=custom-login' ) ) ),
318
+ esc_url( admin_url( 'options-general.php?page=custom-login#custom_login_general' ) )
319
+ ) :
320
+ sprintf( '%s', $announcement->message );
321
+ $html .= '</p></div>';
322
+
323
+ if ( ( !$user_meta && 1 !== $user_meta ) || $is_cl_screen )
324
+ echo $html;
325
+ }
326
+
327
+ /**
328
+ * Remove the admin notification.
329
+ *
330
+ * @return void
331
+ */
332
+ function notification_ignore() {
333
+
334
+ $ignore_key = CUSTOM_LOGIN_OPTION . '_ignore_announcement';
335
+
336
+ // Bail if not set
337
+ if ( !isset( $_GET[$ignore_key] ) )
338
+ return;
339
+
340
+ // Check nonce
341
+ check_admin_referer( $ignore_key, $ignore_key );
342
+
343
+ // If user clicks to ignore the notice, add that to their user meta
344
+ add_user_meta( get_current_user_id(), $ignore_key, 1, true );
345
+ }
346
 
347
+ }
348
 
349
  endif; // End if class_exists check
350
 
357
  *
358
  * Example: <?php $custom_login = CUSTOMLOGIN(); ?>
359
  *
360
+ * @return The one true Instance
361
  */
362
+ if ( !function_exists( 'CUSTOMLOGIN' ) ) {
363
+ function CUSTOMLOGIN() {
364
+ return Custom_Login::instance();
365
+ }
366
  }
367
 
368
  // Out of the frying pan, and into the fire.
369
+ CUSTOMLOGIN();
includes/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
includes/admin/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
includes/admin/dashboard.php CHANGED
@@ -20,287 +20,258 @@ if ( ! defined( 'ABSPATH' ) ) exit;
20
  */
21
  class CL_Dashboard {
22
 
23
- /** Singleton *************************************************************/
24
- private static $instance;
25
-
26
- private $id;
27
-
28
- private static $headers = array();
29
- private static $scripts = array();
30
-
31
- const FEED_URL = 'https://frosty.media/feed/';
32
-
33
- /**
34
- * Main Instance
35
- *
36
- * @staticvar array $instance
37
- * @return CL_Dashboard The one true instance
38
- */
39
- public static function instance() {
40
- if ( ! isset( self::$instance ) ) {
41
- self::$instance = new self;
42
- self::$instance->id = sprintf( '%s-dashboard', CUSTOM_LOGIN_DIRNAME );
43
- self::$instance->actions();
44
- }
45
- return self::$instance;
46
- }
47
-
48
- private function actions() {
49
-
50
- if ( !is_admin() )
51
- return;
52
-
53
- add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widget' ) );
54
- // add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
55
- add_action( 'admin_enqueue_scripts', array( $this, 'inline_scripts' ) );
56
- add_action( 'admin_footer', array( $this, 'admin_footer' ) );
57
- }
58
-
59
- /**
60
- * Check if the dashboard widget is allowed.
61
- *
62
- * @access private
63
- * @return bool
64
- */
65
- private function dashboard_allowed() {
66
- $dashboard = CL_Common::get_option( 'dashboard_widget', 'general', 'off' );
67
-
68
- if ( 'on' === $dashboard )
69
- return true;
70
-
71
- return false;
72
- }
73
-
74
- /**
75
- * Add Dashboard widget
76
- */
77
- public function add_dashboard_widget() {
78
-
79
- if ( !$this->dashboard_allowed() )
80
- return;
81
-
82
- wp_add_dashboard_widget(
83
- $this->id,
84
- __( 'Frosty Media', CUSTOM_LOGIN_DIRNAME ),
85
- array( $this, 'widget' )
86
- );
87
- }
88
-
89
- /**
90
- * Scripts & Styles
91
- */
92
- public function enqueue_scripts() {
93
-
94
- if ( $this->dashboard_allowed() ) {
95
- wp_enqueue_style( $this->id, $this->add_query_arg( 'css' ), null, null, 'screen' );
96
- }
97
- else {
98
- wp_enqueue_script( $this->id, $this->add_query_arg( 'js' ), array( 'jquery' ), null, true );
99
- }
100
- }
101
-
102
- public function admin_footer() {
103
- if ( $this->dashboard_allowed() ) {
104
- echo $this->CSS( false );
105
- }
106
- else {
107
- echo $this->jQuery( false );
108
- }
109
- }
110
-
111
- private function get_feed( $count = 1, $feed = self::FEED_URL ) {
112
- return CL_Common::fetch_rss_items( $count, $feed );
113
- }
114
-
115
- private function get_feed_url() {
116
-
117
- $rss_items = $this->get_feed();
118
-
119
- if ( false !== $rss_items && isset( $rss_items[0] ) ) {
120
-
121
- $feed_url = preg_replace( '/#.*/', '', esc_url( $rss_items[0]->get_permalink(), null, 'display' ) );
122
-
123
- return esc_url( add_query_arg( array( 'utm_medium' => 'wpadmin_dashboard', 'utm_term' => 'newsitem', 'utm_campaign' => CUSTOM_LOGIN_DIRNAME ), $feed_url ) );
124
- }
125
-
126
- return esc_url( self::FEED_URL );
127
- }
128
-
129
- private function get_feed_title() {
130
-
131
- $rss_items = $this->get_feed();
132
-
133
- return isset( $rss_items[0] ) ? esc_html( $rss_items[0]->get_title() ) : 'Unknown';
134
- }
135
-
136
- /**
137
- * Dashboard widget
138
- */
139
- public function widget() {
140
-
141
- // FEED
142
- $rss_items = $this->get_feed();
143
-
144
- $content = '<div class="rss-widget">';
145
- $content .= '<ul>';
146
-
147
- if ( !$rss_items ) {
148
- $content .= '<li>' . __( 'Error fetching feed', CUSTOM_LOGIN_DIRNAME ) . '</li>';
149
- }
150
- else {
151
- $count = 1;
152
- foreach ( $rss_items as $key => $item ) {
153
- $feed_url = preg_replace( '/#.*/', '', esc_url( $item->get_permalink(), null, 'display' ) );
154
- $content .= '<li>';
155
- $content .= '<a class="rsswidget" href="' . esc_url( add_query_arg( array( 'utm_medium' => 'wpadmin_dashboard', 'utm_term' => 'newsitem', 'utm_campaign' => CUSTOM_LOGIN_DIRNAME ), $feed_url ) ) . '">' . esc_html( $item->get_title() ) . '</a>';
156
- $content .= $count === 1 ? '&nbsp;&nbsp;&nbsp;<span class="rss-date">' . $item->get_date( get_option( 'date_format' ) ) . '</span>' : '';
157
- $content .= $count === 1 ? '<div class="rssSummary">' . strip_tags( wp_trim_words( $item->get_description(), 28 ) ) . '</div>' : '';
158
- $content .= '</li>';
159
- $count++;
160
- }
161
- }
162
- $content .= '</ul>';
163
- $content .= '</div>';
164
-
165
-
166
- // Plugins
167
- $rss_items = $this->get_feed( 3, sprintf( '%s?post_type=plugin&plugin_tag=custom-login-extension', self::FEED_URL ) );
168
-
169
- $content .= '<div class="rss-widget">';
170
- $content .= '<ul>';
171
- //$content .= '<li><strong>' . __( 'Custom Login Extensions:', CUSTOM_LOGIN_DIRNAME ) . '</strong></li>';
172
-
173
- if ( !$rss_items ) {
174
- $content .= '<li>' . __( 'Error fetching feed', CUSTOM_LOGIN_DIRNAME ) . '</li>';
175
- }
176
- else {
177
- foreach ( $rss_items as $item ) {
178
- $url = preg_replace( '/#.*/', '', esc_url( $item->get_permalink(), null, 'display' ) );
179
- $content .= '<li>';
180
- $content .= '<a class="rsswidget" href="' . esc_url( add_query_arg( array( 'utm_medium' => 'wpadmin_dashboard', 'utm_term' => 'newsitem', 'utm_campaign' => CUSTOM_LOGIN_DIRNAME ), $url ) ) . '">' . esc_html( $item->get_title() ) . '</a>';
181
- # $content .= '<div class="rssSummary">' . strip_tags( wp_trim_words( $item->get_description(), 10 ) ) . '</div>';
182
- $content .= '</li>';
183
- }
184
- }
185
- $content .= '</ul>';
186
- $content .= '</div>';
187
-
188
- $content .= '<div class="rss-widget">';
189
- $content .= '<ul class="social">';
190
- $content .= '<li>';
191
- $content .= '<a href="https://www.facebook.com/FrostyMediaWP"><span class="dashicons dashicons-facebook"></span>/FrostyMediaWP</a> | ';
192
- $content .= '<a href="https://twitter.com/Frosty_Media"><span class="dashicons dashicons-twitter"></span>/Frosty_Media</a> | ';
193
- $content .= '<a href="https://twitter.com/TheFrosty"><span class="dashicons dashicons-twitter"></span>/TheFrosty</a>';
194
- $content .= '</li>';
195
- $content .= '</ul>';
196
-
197
- $content .= '</div>';
198
-
199
- echo $content;
200
- }
201
-
202
- /**
203
- * Generate the custom CSS/JS.
204
- *
205
- */
206
- public function inline_scripts() {
207
-
208
- if ( isset( $_GET[ $this->id ] ) && intval( $_GET[ $this->id ] ) === 1 ) {
209
-
210
- if ( isset( $_GET['type'] ) && $_GET['type'] === 'css' ) {
211
-
212
- if ( !headers_sent() ) {
213
- header("content-type:text/css");
214
- }
215
- ob_start();
216
- str_replace( ob_end_clean(), '', ob_end_clean() );
217
- $this->CSS();
218
- if ( ob_get_level() ) echo ob_get_clean();
219
- die;
220
- }
221
- elseif ( isset( $_GET['type'] ) && $_GET['type'] === 'js' ) {
222
-
223
- if ( !headers_sent() ) {
224
- header("content-type:application/x-javascript");
225
- }
226
- ob_start();
227
- str_replace( ob_end_clean(), '', ob_end_clean() );
228
- $this->jQuery();
229
- if ( ob_get_level() ) echo ob_get_clean();
230
- die;
231
- }
232
- }
233
- }
234
-
235
- public function clean_ob_contents( $contents ) {
236
- return str_replace( $contents, '', $contents );
237
- }
238
-
239
- /**
240
- * Helper function to return the proper query arg.
241
- */
242
- private function add_query_arg( $type = 'js' ) {
243
- $url = add_query_arg(
244
- array(
245
- $this->id => '1',
246
- 'type' => $type
247
- ),
248
- trailingslashit( admin_url() )
249
- );
250
- return esc_url( $url );
251
- }
252
-
253
- /**
254
- * Create the CSS.
255
- *
256
- * @param bool $remove_wrapper
257
- */
258
- private function CSS( $remove_wrapper = true ) {
259
- if ( !$remove_wrapper ) { ?>
260
- <style>
261
- <?php }
262
- #<?php echo $this->id; ?> .inside {
263
- margin: 0;
264
- padding: 0;
265
- }
266
- #<?php echo $this->id; ?> .rss-widget {
267
- border-bottom: 1px solid #eee;
268
- font-size: 13px;
269
- padding: 8px 12px 10px;
270
- }
271
- <?php if ( !$remove_wrapper ) { ?>
272
- </style>
273
- <?php }
274
- }
275
-
276
- /**
277
- * Create the jQuery.
278
- *
279
- * @param bool $remove_wrapper
280
- */
281
- private function jQuery( $remove_wrapper = true ) {
282
- if ( !$remove_wrapper ) { ?>
283
- <script>
284
- <?php } ?>
285
- jQuery(document).ready(function($) {
286
-
287
- var CL_Timeout = 200;
288
-
289
- if ( !$('#dashboard_primary .rss-widget').eq(1).length ) {
290
- CL_Timeout = 2500;
291
- }
292
-
293
- setTimeout( function() {
294
- $('#dashboard_primary .rss-widget:eq(1) ul').append('<a class="rsswidget" href="<?php echo $this->get_feed_url(); ?>">FrostyMedia: <?php echo $this->get_feed_title(); ?></a>');
295
- }, CL_Timeout );
296
-
297
- });
298
- <?php if ( !$remove_wrapper ) { ?>
299
- </script>
300
- <?php }
301
- }
302
-
303
  }
304
 
305
  // Only load on the WordPress Dashboard (index.php) page.
306
- add_action( 'load-index.php', array( 'CL_Dashboard', 'instance' ), 99 );
20
  */
21
  class CL_Dashboard {
22
 
23
+ /** Singleton *************************************************************/
24
+ private static $instance;
25
+
26
+ private $id;
27
+
28
+ /**
29
+ * Main Instance
30
+ *
31
+ * @staticvar array $instance
32
+ * @return The one true instance
33
+ */
34
+ public static function instance() {
35
+ if ( ! isset( self::$instance ) ) {
36
+ self::$instance = new self;
37
+ self::$instance->id = sprintf( '%s-dashboard', CUSTOM_LOGIN_DIRNAME );
38
+ self::$instance->actions();
39
+ }
40
+ return self::$instance;
41
+ }
42
+
43
+ private function actions() {
44
+
45
+ add_action( 'wp_dashboard_setup', array( $this, 'add_dashboard_widget' ) );
46
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
47
+ add_action( 'admin_enqueue_scripts', array( $this, 'inline_scripts' ) );
48
+ }
49
+
50
+ /**
51
+ * Check if the dashboard widget is allowed.
52
+ *
53
+ * @access private
54
+ * @return bool
55
+ */
56
+ private function dashboard_allowed() {
57
+ $tracking = CL_Common::get_option( 'dashboard_widget', 'general', 'off' );
58
+
59
+ if ( 'on' === $tracking )
60
+ return true;
61
+
62
+ return false;
63
+ }
64
+
65
+ /**
66
+ * Add Dashboard widget
67
+ */
68
+ public function add_dashboard_widget() {
69
+
70
+ if ( !$this->dashboard_allowed() )
71
+ return;
72
+
73
+ wp_add_dashboard_widget(
74
+ $this->id,
75
+ __( 'Frosty Media', CUSTOM_LOGIN_DIRNAME ),
76
+ array( $this, 'widget' )
77
+ );
78
+ }
79
+
80
+ /**
81
+ * Scripts & Styles
82
+ */
83
+ public function enqueue_scripts() {
84
+
85
+ if ( $this->dashboard_allowed() ) {
86
+ wp_enqueue_style( $this->id, $this->add_query_arg( 'css' ), null, null, 'screen' );
87
+ }
88
+ else {
89
+ wp_enqueue_script( $this->id, $this->add_query_arg( 'js' ), array( 'jquery' ), null, true );
90
+ }
91
+ }
92
+
93
+ private function get_feed( $count = 1, $feed = 'https://frosty.media/feed/' ) {
94
+ return CL_Common::fetch_rss_items( $count, $feed );
95
+ }
96
+
97
+ private function get_feed_url( $key = 0 ) {
98
+
99
+ $rss_items = $this->get_feed();
100
+ $feed_url = preg_replace( '/#.*/', '', esc_url( $rss_items[ $key ]->get_permalink(), null, 'display' ) );
101
+
102
+ return add_query_arg( array( 'utm_medium' => 'wpadmin_dashboard', 'utm_term' => 'newsitem', 'utm_campaign' => CUSTOM_LOGIN_DIRNAME ), $feed_url );
103
+ }
104
+
105
+ private function get_feed_title( $key = 0 ) {
106
+ $rss_items = $this->get_feed();
107
+
108
+ return esc_html( $rss_items[ $key ]->get_title() );
109
+ }
110
+
111
+ /**
112
+ * Dashboard widget
113
+ */
114
+ public function widget() {
115
+
116
+ // FEED
117
+ $rss_items = $this->get_feed( 1, 'https://frosty.media/feed/' );
118
+
119
+ $content = '<div class="rss-widget">';
120
+ $content .= '<ul>';
121
+
122
+ if ( !$rss_items ) {
123
+ $content .= '<li>' . __( 'Error fetching feed', CUSTOM_LOGIN_DIRNAME ) . '</li>';
124
+ }
125
+ else {
126
+ $count = 1;
127
+ foreach ( $rss_items as $key => $item ) {
128
+ $feed_url = preg_replace( '/#.*/', '', esc_url( $item->get_permalink(), null, 'display' ) );
129
+ $content .= '<li>';
130
+ $content .= '<a class="rsswidget" href="' . add_query_arg( array( 'utm_medium' => 'wpadmin_dashboard', 'utm_term' => 'newsitem', 'utm_campaign' => CUSTOM_LOGIN_DIRNAME ), $feed_url ) . '">' . esc_html( $item->get_title() ) . '</a>';
131
+ $content .= $count === 1 ? '&nbsp;&nbsp;&nbsp;<span class="rss-date">' . $item->get_date( get_option( 'date_format' ) ) . '</span>' : '';
132
+ $content .= $count === 1 ? '<div class="rssSummary">' . strip_tags( wp_trim_words( $item->get_description(), 28 ) ) . '</div>' : '';
133
+ $content .= '</li>';
134
+ $count++;
135
+ }
136
+ }
137
+ $content .= '</ul>';
138
+ $content .= '</div>';
139
+
140
+
141
+ // Plugins
142
+ $rss_items = CL_Common::fetch_rss_items( 3, 'https://frosty.media/feed/?post_type=plugin&plugin_tag=custom-login-extension' );
143
+
144
+ $content .= '<div class="rss-widget">';
145
+ $content .= '<ul>';
146
+ //$content .= '<li><strong>' . __( 'Custom Login Extensions:', CUSTOM_LOGIN_DIRNAME ) . '</strong></li>';
147
+
148
+ if ( !$rss_items ) {
149
+ $content .= '<li>' . __( 'Error fetching feed', CUSTOM_LOGIN_DIRNAME ) . '</li>';
150
+ }
151
+ else {
152
+ foreach ( $rss_items as $item ) {
153
+ $url = preg_replace( '/#.*/', '', esc_url( $item->get_permalink(), null, 'display' ) );
154
+ $content .= '<li>';
155
+ $content .= '<a class="rsswidget" href="' . add_query_arg( array( 'utm_medium' => 'wpadmin_dashboard', 'utm_term' => 'newsitem', 'utm_campaign' => CUSTOM_LOGIN_DIRNAME ), $url ) . '">' . esc_html( $item->get_title() ) . '</a>';
156
+ # $content .= '<div class="rssSummary">' . strip_tags( wp_trim_words( $item->get_description(), 10 ) ) . '</div>';
157
+ $content .= '</li>';
158
+ }
159
+ }
160
+ $content .= '</ul>';
161
+ $content .= '</div>';
162
+
163
+ $content .= '<div class="rss-widget">';
164
+ $content .= '<ul class="social">';
165
+ $content .= '<li>';
166
+ $content .= '<a href="https://www.facebook.com/FrostyMediaWP"><span class="dashicons dashicons-facebook"></span>/FrostyMediaWP</a> | ';
167
+ $content .= '<a href="https://twitter.com/Frosty_Media"><span class="dashicons dashicons-twitter"></span>/Frosty_Media</a> | ';
168
+ $content .= '<a href="https://twitter.com/TheFrosty"><span class="dashicons dashicons-twitter"></span>/TheFrosty</a>';
169
+ $content .= '</li>';
170
+ $content .= '</ul>';
171
+
172
+ $content .= '</div>';
173
+
174
+ echo $content;
175
+ }
176
+
177
+ /**
178
+ * Generate the custom CSS/JS.
179
+ *
180
+ */
181
+ public function inline_scripts() {
182
+
183
+ if ( isset( $_GET[ $this->id ] ) && intval( $_GET[ $this->id ] ) === 1 ) {
184
+
185
+ if ( isset( $_GET['type'] ) && $_GET['type'] === 'css' ) {
186
+
187
+ if ( !headers_sent() ) {
188
+ header("content-type:text/css");
189
+ }
190
+ ob_start();
191
+ str_replace( ob_end_clean(), '', ob_end_clean() );
192
+ $this->CSS();
193
+ echo ob_get_clean();
194
+ die;
195
+ }
196
+ elseif ( isset( $_GET['type'] ) && $_GET['type'] === 'js' ) {
197
+
198
+ if ( !headers_sent() ) {
199
+ header("content-type:application/x-javascript");
200
+ }
201
+ ob_start();
202
+ str_replace( ob_end_clean(), '', ob_end_clean() );
203
+ $this->jQuery();
204
+ echo ob_get_clean();
205
+ die;
206
+ }
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Helper function to return the proper query arg.
212
+ */
213
+ private function add_query_arg( $type = 'js' ) {
214
+ $url = add_query_arg(
215
+ array(
216
+ $this->id => '1',
217
+ 'type' => $type
218
+ ),
219
+ trailingslashit( admin_url() )
220
+ );
221
+ return esc_url( $url );
222
+ }
223
+
224
+ /**
225
+ * Create the CSS.
226
+ *
227
+ * @param bool $remove_wrapper
228
+ */
229
+ private function CSS( $remove_wrapper = true ) {
230
+ if ( !$remove_wrapper ) { ?>
231
+ <style>
232
+ <?php } ?>
233
+ #<?php echo $this->id; ?> .inside {
234
+ margin: 0;
235
+ padding: 0;
236
+ }
237
+ #<?php echo $this->id; ?> .rss-widget {
238
+ border-bottom: 1px solid #eee;
239
+ font-size: 13px;
240
+ padding: 8px 12px 10px;
241
+ }
242
+ <?php if ( !$remove_wrapper ) { ?>
243
+ </style>
244
+ <?php }
245
+ }
246
+
247
+ /**
248
+ * Create the jQuery.
249
+ *
250
+ * @param bool $remove_wrapper
251
+ */
252
+ private function jQuery( $remove_wrapper = true ) {
253
+ if ( !$remove_wrapper ) { ?>
254
+ <script>
255
+ <?php } ?>
256
+ jQuery(document).ready(function($) {
257
+
258
+ var CL_Timeout = 200;
259
+
260
+ if ( !$('#dashboard_primary .rss-widget').eq(1).length ) {
261
+ CL_Timeout = 2500;
262
+ }
263
+
264
+ setTimeout( function() {
265
+ $('#dashboard_primary .rss-widget:eq(1) ul').append('<a class="rsswidget" href="<?php echo $this->get_feed_url(); ?>">FrostyMedia: <?php echo $this->get_feed_title(); ?></a>');
266
+ }, CL_Timeout );
267
+
268
+ });
269
+ <?php if ( !$remove_wrapper ) { ?>
270
+ </script>
271
+ <?php }
272
+ }
273
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  }
275
 
276
  // Only load on the WordPress Dashboard (index.php) page.
277
+ add_action( 'load-index.php', array( 'CL_Dashboard', 'instance' ) );
includes/admin/import-export.php CHANGED
@@ -79,13 +79,13 @@ class CL_Import_Export {
79
  'name' => 'export',
80
  'label' => __( 'Export', CUSTOM_LOGIN_DIRNAME ),
81
  'desc' => sprintf( __( 'This textarea is always pre-filled with the current settings. Copy these settings for import at a later time, or <a href="%s">download</a> them.', CUSTOM_LOGIN_DIRNAME ),
82
- esc_url( wp_nonce_url(
83
  add_query_arg( array( 'action' => CUSTOM_LOGIN_OPTION . '_download_export' ),
84
  ''
85
  ),
86
  'export',
87
  'cl_nonce'
88
- ) )
89
  ),
90
  'default' => $this->get_custom_login_settings(),
91
  'type' => 'textarea',
79
  'name' => 'export',
80
  'label' => __( 'Export', CUSTOM_LOGIN_DIRNAME ),
81
  'desc' => sprintf( __( 'This textarea is always pre-filled with the current settings. Copy these settings for import at a later time, or <a href="%s">download</a> them.', CUSTOM_LOGIN_DIRNAME ),
82
+ wp_nonce_url(
83
  add_query_arg( array( 'action' => CUSTOM_LOGIN_OPTION . '_download_export' ),
84
  ''
85
  ),
86
  'export',
87
  'cl_nonce'
88
+ )
89
  ),
90
  'default' => $this->get_custom_login_settings(),
91
  'type' => 'textarea',
includes/admin/roost.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @package CustomLogin
4
+ * @subpackage Classes/CL_Roost
5
+ * @author Austin Passy <http://austin.passy.co>
6
+ * @copyright Copyright (c) 2015, Austin Passy
7
+ * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
8
+ */
9
+
10
+ // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
12
+
13
+ // Is Roost allowed?
14
+ if ( !defined( 'CL_ALLOW_ROOST' ) ) return;
15
+
16
+ /**
17
+ * Roost (push notifications) signup
18
+ *
19
+ * @access public
20
+ * @since 3.2
21
+ * @return void
22
+ */
23
+ class CL_Roost {
24
+
25
+ /**
26
+ * Roost API Key.
27
+ *
28
+ * @access private
29
+ */
30
+ private $api_key;
31
+
32
+ /**
33
+ * Get things going
34
+ *
35
+ * @access public
36
+ * @return void
37
+ */
38
+ public function __construct() {
39
+
40
+ $this->api_key = '7fe37450d6104fd8929240faa803caf1';
41
+
42
+ add_action( 'admin_action_' . CUSTOM_LOGIN_OPTION . '_allow_push', array( $this, 'admin_action_hook' ) );
43
+ add_action( CUSTOM_LOGIN_OPTION . '_settings_sidebars', array( $this, 'settings_sidebar' ), 23 );
44
+ }
45
+
46
+ /**
47
+ * Action hook called on 'admin_action_' $_REQUEST
48
+ *
49
+ * @return void
50
+ */
51
+ public function admin_action_hook() {
52
+
53
+ add_action( 'admin_head', array( $this, 'admin_head' ), 99 );
54
+ }
55
+
56
+ /**
57
+ * Output our script to the admin header.
58
+ *
59
+ * @ref https://goroost.com/push-notification-documentation#document-2
60
+ * @return void
61
+ */
62
+ public function admin_head() {
63
+ echo '<script src="https://cdn.goroost.com/roostjs/' . $this->api_key . '" async></script>';
64
+ echo "<script>\n";
65
+ echo "var _roost = _roost || [];\n";
66
+ echo "_roost.push([\"segments_add\", \"customlogin\"]);\n";
67
+ echo "</script>\n";
68
+ }
69
+
70
+ /**
71
+ * Box with a link to output our script.
72
+ *
73
+ * @return string
74
+ */
75
+ public function settings_sidebar( $args ) {
76
+
77
+ $user_agent = $_SERVER['HTTP_USER_AGENT'];
78
+
79
+ if ( !preg_match('/macintosh|mac os x/i', $user_agent ) )
80
+ return;
81
+
82
+ if ( !preg_match('/safari/i', $user_agent ) )
83
+ return;
84
+
85
+ $content = sprintf( __( 'Stay up to date with desktop push notifications: <a href="%s">click here</a>, then click "allow".', CUSTOM_LOGIN_DIRNAME ), add_query_arg( 'action', sprintf( '%s_allow_push', CUSTOM_LOGIN_OPTION ), admin_url() ) );
86
+
87
+ CUSTOMLOGIN()->settings_api->postbox( 'custom-login-roost', sprintf( __( '%sPush Notifications', CUSTOM_LOGIN_DIRNAME ), '*' ), $content );
88
+ }
89
+
90
+ }
91
+ new CL_Roost;
includes/admin/tracking.php CHANGED
@@ -144,7 +144,7 @@ class CL_Tracking {
144
 
145
  $this->setup_data( $extra_data );
146
 
147
- $response = wp_remote_post( esc_url_raw( $this->api ), array(
148
  'method' => 'POST',
149
  'timeout' => apply_filters( 'cl_wp_remote_post_timeout', (int) 15 ),
150
  'redirection' => 5,
@@ -186,13 +186,15 @@ class CL_Tracking {
186
 
187
  $options = get_option( $this->option, array() );
188
 
 
 
189
  $options['tracking'] = 'on';
190
  update_option( $this->option, $options );
191
  update_option( 'custom_login_hide_tracking_notice', '1' );
192
 
193
  $this->send_checkin( true, array( 'on_activation' => 'admin notice', 'mailchimp_sub' => 'yes' ) );
194
 
195
- wp_redirect( esc_url( remove_query_arg( 'action' ) ) );
196
  exit;
197
  }
198
 
@@ -206,11 +208,13 @@ class CL_Tracking {
206
 
207
  $options = get_option( $this->option, array() );
208
 
 
 
209
  $options['tracking'] = 'off';
210
  update_option( $this->option, $options );
211
  update_option( 'custom_login_hide_tracking_notice', '1' );
212
 
213
- wp_redirect( esc_url( remove_query_arg( 'action' ) ) );
214
  exit;
215
  }
216
 
144
 
145
  $this->setup_data( $extra_data );
146
 
147
+ $response = wp_remote_post( $this->api, array(
148
  'method' => 'POST',
149
  'timeout' => apply_filters( 'cl_wp_remote_post_timeout', (int) 15 ),
150
  'redirection' => 5,
186
 
187
  $options = get_option( $this->option, array() );
188
 
189
+ #var_dump( $options ); exit;
190
+
191
  $options['tracking'] = 'on';
192
  update_option( $this->option, $options );
193
  update_option( 'custom_login_hide_tracking_notice', '1' );
194
 
195
  $this->send_checkin( true, array( 'on_activation' => 'admin notice', 'mailchimp_sub' => 'yes' ) );
196
 
197
+ wp_redirect( remove_query_arg( 'action' ) );
198
  exit;
199
  }
200
 
208
 
209
  $options = get_option( $this->option, array() );
210
 
211
+ #var_dump( $options ); exit;
212
+
213
  $options['tracking'] = 'off';
214
  update_option( $this->option, $options );
215
  update_option( 'custom_login_hide_tracking_notice', '1' );
216
 
217
+ wp_redirect( remove_query_arg( 'action' ) );
218
  exit;
219
  }
220
 
includes/class-cl-common.php CHANGED
@@ -11,88 +11,67 @@
11
  if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
  class CL_Common {
14
-
15
- /**
16
- * Return the RSS feed object.
17
- *
18
- * @param string $feed The feed to fetch.
19
- *
20
- * @return object
21
- */
22
- public static function fetch_feed( $feed ) {
23
-
24
- if ( !function_exists( 'fetch_feed' ) ) {
25
- include_once( ABSPATH . WPINC . '/feed.php' );
26
- }
27
-
28
- return fetch_feed( $feed );
29
- }
30
-
31
- /**
32
- * Fetch RSS items from the feed.
33
- *
34
- * @param int $num Number of items to fetch.
35
- * @param string $feed The feed to fetch.
36
- * @return array|bool False on error, array of RSS items on success.
37
- */
38
- public static function fetch_rss_items( $num, $feed ) {
39
-
40
- $rss = self::fetch_feed( $feed );
41
- $maxitems = 0;
42
-
43
- if ( !is_wp_error( $rss ) ) { // Checks that the object is created correctly
44
-
45
- // Figure out how many total items there are, but limit it to 5.
46
- $maxitems = $rss->get_item_quantity( $num );
47
-
48
- // Build an array of all the items, starting with element 0 (first element).
49
- $rss_items = $rss->get_items( 0, $maxitems );
50
-
51
- }
52
- else {
53
- return false;
54
- }
55
-
56
- // If the feed was erroneous
57
- if ( !$rss_items || $maxitems == 0 ) {
58
- $md5 = md5( $feed );
59
- delete_transient( 'feed_' . $md5 );
60
- delete_transient( 'feed_mod_' . $md5 );
61
- $rss = self::fetch_feed( $feed );
62
- $rss_items = $rss->get_items( 0, $rss->get_item_quantity( $num ) );
63
- }
64
-
65
- return $rss_items;
66
- }
67
-
68
- /**
69
- * Helper function to return the data URI.
70
- *
71
- * @return string
72
- */
73
- public static function get_data_uri( $_image, $mime = '' ) {
74
-
75
- $image = trailingslashit( CUSTOM_LOGIN_URL );
76
- $image .= $_image;
77
-
78
- $data = file_exists( $image ) ? base64_encode( file_get_contents( $image ) ) : '';
79
-
80
- return !empty( $data ) ? 'data:image/' . $mime . ';base64,' . $data : '';
81
- }
82
-
83
- /**
84
- * Get's the cached transient key.
85
- *
86
- * @return string
87
- */
88
- public static function get_transient_key( $input ) {
89
-
90
- $len = is_multisite() ? 40 : 45;
91
- $key = 'custom_login_';
92
- $key = $key . substr( md5( $input ), 0, $len - strlen( $key ) );
93
-
94
- return $key;
95
- }
96
 
97
  /**
98
  * Get the value of a settings field
@@ -100,119 +79,119 @@ class CL_Common {
100
  * @param string $option settings field name
101
  * @param string $subsection the section name this field belongs to
102
  * @param string $default default text if it's not found
103
- *
104
  * @return string
105
  */
106
  public static function get_option( $option, $subsection = '', $default = '' ) {
107
-
108
- $section = CUSTOM_LOGIN_OPTION . '_' . $subsection;
109
- $setting = get_option( $section, array() );
110
-
111
- if ( isset( $setting[$option] ) ) {
112
- return $setting[$option];
113
- }
114
-
115
- return $default;
116
  }
117
 
118
  /**
119
- * Get all values of a settings section
120
- *
121
- * @param string $subsection the section name this field belongs to
122
- *
123
- * @return array
124
- */
125
  public static function get_options( $subsection = 'design' ) {
126
-
127
- $section = CUSTOM_LOGIN_OPTION . '_' . $subsection;
128
- $settings = get_option( $section, array() );
129
-
130
- return $settings;
131
  }
132
-
133
- /**
134
- * Helper function to make remote calls
135
- *
136
- * @since 3.0.0
137
- * @updated 3.0.8
138
- */
139
  public static function wp_remote_get( $url = false, $transient_key, $expiration = null, $user_agent = 'WordPress' ) {
140
-
141
- if ( !$url ) return false;
142
-
143
- if ( 'WordPress' == $user_agent ) {
144
- global $wp_version;
145
- $_version = $wp_version;
146
- }
147
- else {
148
- $_version = CUSTOM_LOGIN_VERSION;
149
- }
150
-
151
- $expiration = null !== $expiration ? $expiration : WEEK_IN_SECONDS;
152
-
153
- # delete_transient( $transient_key );
154
- if ( false === ( $json = get_transient( $transient_key ) ) ) {
155
-
156
- $response = wp_remote_get(
157
- esc_url( $url ),
158
- array(
159
- 'timeout' => apply_filters( 'cl_wp_remote_get_timeout', (int) 15 ),
160
- 'sslverify' => false,
161
- 'user-agent' => $user_agent . '/' . $_version . '; ' . get_bloginfo( 'url' ),
162
- )
163
- );
164
-
165
- if ( !is_wp_error( $response ) ) {
166
-
167
- if ( isset( $response['body'] ) && strlen( $response['body'] ) > 0 ) {
168
-
169
- $json = json_decode( wp_remote_retrieve_body( $response ) );
170
-
171
- // Discount, double check?
172
- if ( is_wp_error( $json ) )
173
- return false;
174
-
175
- // Cache the results for '$expiration'
176
- set_transient( $transient_key, $json, $expiration );
177
-
178
- // Return the data
179
- return $json;
180
- }
181
- }
182
- else {
183
- return false; // Error, lets return!
184
- }
185
- }
186
-
187
- return $json;
188
- }
189
-
190
- /**
191
- * Helper function check if we're on our settings page.
192
- *
193
- * @since 3.0.9
194
- */
195
- public static function is_settings_page( $page = '' ) {
196
-
197
- $return = true;
198
- $screen = get_current_screen();
199
-
200
- if ( null !== $screen ) {
201
-
202
- if ( $screen->id != ( CUSTOMLOGIN()->menu_page ) )
203
- $return = false;
204
- }
205
- else {
206
- global $pagenow;
207
-
208
- if ( 'options-general.php' != $pagenow )
209
- $return = false;
210
-
211
- if ( !isset( $_GET['page'] ) || CUSTOM_LOGIN_DIRNAME != $_GET['page'] )
212
- $return = false;
213
- }
214
-
215
- return $return;
216
- }
217
-
218
- }
11
  if ( !defined( 'ABSPATH' ) ) exit;
12
 
13
  class CL_Common {
14
+
15
+ /**
16
+ * Fetch RSS items from the feed.
17
+ *
18
+ * @param int $num Number of items to fetch.
19
+ * @param string $feed The feed to fetch.
20
+ * @return array|bool False on error, array of RSS items on success.
21
+ */
22
+ public static function fetch_rss_items( $num, $feed ) {
23
+
24
+ if ( !function_exists( 'fetch_feed' ) )
25
+ include_once( ABSPATH . WPINC . '/feed.php' );
26
+
27
+ $rss = fetch_feed( $feed );
28
+
29
+ // Bail if feed doesn't work
30
+ if ( !$rss || is_wp_error( $rss ) )
31
+ return false;
32
+
33
+ $rss_items = $rss->get_items( 0, $rss->get_item_quantity( $num ) );
34
+
35
+ // If the feed was erroneous
36
+ if ( !$rss_items ) {
37
+ $md5 = md5( $feed );
38
+ delete_transient( 'feed_' . $md5 );
39
+ delete_transient( 'feed_mod_' . $md5 );
40
+ $rss = fetch_feed( $feed );
41
+ $rss_items = $rss->get_items( 0, $rss->get_item_quantity( $num ) );
42
+ }
43
+
44
+ return $rss_items;
45
+ }
46
+
47
+ /**
48
+ * Helper function to return the data URI.
49
+ *
50
+ * @return string
51
+ */
52
+ public static function get_data_uri( $_image, $mime = '' ) {
53
+
54
+ $image = trailingslashit( CUSTOM_LOGIN_URL );
55
+ $image .= $_image;
56
+
57
+ $data = file_exists( $image ) ? base64_encode( file_get_contents( $image ) ) : '';
58
+
59
+ return !empty( $data ) ? 'data:image/' . $mime . ';base64,' . $data : '';
60
+ }
61
+
62
+ /**
63
+ * Get's the cached transient key.
64
+ *
65
+ * @return string
66
+ */
67
+ public static function get_transient_key( $input ) {
68
+
69
+ $len = is_multisite() ? 40 : 45;
70
+ $key = 'custom_login_';
71
+ $key = $key . substr( md5( $input ), 0, $len - strlen( $key ) );
72
+
73
+ return $key;
74
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
  /**
77
  * Get the value of a settings field
79
  * @param string $option settings field name
80
  * @param string $subsection the section name this field belongs to
81
  * @param string $default default text if it's not found
82
+ *
83
  * @return string
84
  */
85
  public static function get_option( $option, $subsection = '', $default = '' ) {
86
+
87
+ $section = CUSTOM_LOGIN_OPTION . '_' . $subsection;
88
+ $setting = get_option( $section, array() );
89
+
90
+ if ( isset( $setting[$option] ) ) {
91
+ return $setting[$option];
92
+ }
93
+
94
+ return $default;
95
  }
96
 
97
  /**
98
+ * Get all values of a settings section
99
+ *
100
+ * @param string $subsection the section name this field belongs to
101
+ *
102
+ * @return array
103
+ */
104
  public static function get_options( $subsection = 'design' ) {
105
+
106
+ $section = CUSTOM_LOGIN_OPTION . '_' . $subsection;
107
+ $settings = get_option( $section, array() );
108
+
109
+ return $settings;
110
  }
111
+
112
+ /**
113
+ * Helper function to make remote calls
114
+ *
115
+ * @since 3.0.0
116
+ * @updated 3.0.8
117
+ */
118
  public static function wp_remote_get( $url = false, $transient_key, $expiration = null, $user_agent = 'WordPress' ) {
119
+
120
+ if ( !$url ) return false;
121
+
122
+ if ( 'WordPress' == $user_agent ) {
123
+ global $wp_version;
124
+ $_version = $wp_version;
125
+ }
126
+ else {
127
+ $_version = CUSTOM_LOGIN_VERSION;
128
+ }
129
+
130
+ $expiration = null !== $expiration ? $expiration : WEEK_IN_SECONDS;
131
+
132
+ # delete_transient( $transient_key );
133
+ if ( false === ( $json = get_transient( $transient_key ) ) ) {
134
+
135
+ $response = wp_remote_get(
136
+ esc_url( $url ),
137
+ array(
138
+ 'timeout' => apply_filters( 'cl_wp_remote_get_timeout', (int) 15 ),
139
+ 'sslverify' => false,
140
+ 'user-agent' => $user_agent . '/' . $_version . '; ' . get_bloginfo( 'url' ),
141
+ )
142
+ );
143
+
144
+ if ( !is_wp_error( $response ) ) {
145
+
146
+ if ( isset( $response['body'] ) && strlen( $response['body'] ) > 0 ) {
147
+
148
+ $json = json_decode( wp_remote_retrieve_body( $response ) );
149
+
150
+ // Discount, double check?
151
+ if ( is_wp_error( $json ) )
152
+ return false;
153
+
154
+ // Cache the results for '$expiration'
155
+ set_transient( $transient_key, $json, $expiration );
156
+
157
+ // Return the data
158
+ return $json;
159
+ }
160
+ }
161
+ else {
162
+ return false; // Error, lets return!
163
+ }
164
+ }
165
+
166
+ return $json;
167
+ }
168
+
169
+ /**
170
+ * Helper function check if we're on our settings page.
171
+ *
172
+ * @since 3.0.9
173
+ */
174
+ public static function is_settings_page( $page = '' ) {
175
+
176
+ $return = true;
177
+ $screen = get_current_screen();
178
+
179
+ if ( null !== $screen ) {
180
+
181
+ if ( $screen->id != ( CUSTOMLOGIN()->menu_page ) )
182
+ $return = false;
183
+ }
184
+ else {
185
+ global $pagenow;
186
+
187
+ if ( 'options-general.php' != $pagenow )
188
+ $return = false;
189
+
190
+ if ( !isset( $_GET['page'] ) || CUSTOM_LOGIN_DIRNAME != $_GET['page'] )
191
+ $return = false;
192
+ }
193
+
194
+ return $return;
195
+ }
196
+
197
+ }
includes/class-cl-extensions.php CHANGED
@@ -217,7 +217,7 @@ class CL_Extensions {
217
  $html .= '<div class="col span_1_of_3 eddri-addon">';
218
  $html .= '<div class="eddri-addon-container">';
219
  $html .= '<div class="eddri-img-wrap">';
220
- $html .= '<a href="' . esc_url( add_query_arg( array( 'utm_source' => 'wordpressorg', 'utm_medium' => 'custom-login', 'utm_campaign' => 'eddri' ), $extension['url'] ) ) . '" target="_blank"><img class="eddri-thumbnail" src="' . $extension['image'] . '"></a>';
221
  $html .= '<p>' . $extension['description'] . '</p>';
222
  $html .= '</div>';
223
 
@@ -230,9 +230,9 @@ class CL_Extensions {
230
  $html .= '<ul>';
231
  foreach( $extension['links'] as $link ) {
232
  $html .= '<li>';
233
- $html .= $link['description'] . ' (' . $link['price'] . '): <a href="' . esc_url( add_query_arg( array( 'edd_action' => 'straight_to_gateway', 'download_id' => $link['download_id'], 'edd_options[price_id]' => $link['price_id'] ), $this->checkout_url ) ) . '">PayPal</a>';
234
  $html .= ' | ';
235
- $html .= '<a href="' . esc_url( add_query_arg( array( 'edd_action' => 'add_to_cart', 'download_id' => $link['download_id'], 'edd_options[price_id]' => $link['price_id'] ), $this->checkout_url ) ) . '">Credit Card</a>';
236
  $html .= '</li>';
237
  }
238
  $html .= '</ul>';
217
  $html .= '<div class="col span_1_of_3 eddri-addon">';
218
  $html .= '<div class="eddri-addon-container">';
219
  $html .= '<div class="eddri-img-wrap">';
220
+ $html .= '<a href="' . add_query_arg( array( 'utm_source' => 'wordpressorg', 'utm_medium' => 'custom-login', 'utm_campaign' => 'eddri' ), $extension['url'] ) . '" target="_blank"><img class="eddri-thumbnail" src="' . $extension['image'] . '"></a>';
221
  $html .= '<p>' . $extension['description'] . '</p>';
222
  $html .= '</div>';
223
 
230
  $html .= '<ul>';
231
  foreach( $extension['links'] as $link ) {
232
  $html .= '<li>';
233
+ $html .= $link['description'] . ' (' . $link['price'] . '): <a href="' . add_query_arg( array( 'edd_action' => 'straight_to_gateway', 'download_id' => $link['download_id'], 'edd_options[price_id]' => $link['price_id'] ), $this->checkout_url ) . '">PayPal</a>';
234
  $html .= ' | ';
235
+ $html .= '<a href="' . add_query_arg( array( 'edd_action' => 'add_to_cart', 'download_id' => $link['download_id'], 'edd_options[price_id]' => $link['price_id'] ), $this->checkout_url ) . '">Credit Card</a>';
236
  $html .= '</li>';
237
  }
238
  $html .= '</ul>';
includes/class-cl-settings-api.php CHANGED
@@ -1,188 +1,174 @@
1
  <?php
2
 
3
  // Exit if accessed directly
4
- if ( ! defined( 'ABSPATH' ) ) {
5
- exit;
6
- }
7
 
8
  /**
9
  * Custom Login Settings API
10
  */
11
  class CL_Settings_API {
12
-
13
- /**
14
- * Version
15
- */
16
- var $api_version = '2.1.0';
17
-
18
- /**
19
- * @var array
20
- */
21
- private $settings_sections = array();
22
- private $settings_fields = array();
23
- private $settings_sidebars = array();
24
- private $localize_array = array();
25
-
26
- /**
27
- * @var array
28
- */
29
- private $settings = array();
30
-
31
- /**
32
- * Fire away captain!
33
- */
34
  public function __construct( $sections = array(), $fields = array(), $args = array() ) {
35
-
36
- $this->settings = $args;
37
-
38
- if ( ! empty( $sections ) ) {
39
- $this->set_sections( $sections );
40
- }
41
-
42
- if ( ! empty( $fields ) ) {
43
- $this->set_fields( $fields );
44
- }
45
-
46
- add_action( 'load-' . $this->settings['menu_page'], array( $this, 'init' ), 89 );
47
- add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
48
- add_action( 'admin_footer', array( $this, 'wp_localize_script' ), 99 );
49
- add_action( 'wp_ajax_' . $this->settings['prefix'] . '_get_form', array( $this, 'get_form' ), 99 );
50
- add_action( 'wp_ajax_' . $this->settings['prefix'] . '_activate_check', array( $this, 'activate_check_ajax' ) );
51
- }
52
-
53
- /**
54
- * Fire any actions needed a little late
55
- *
56
- * @return void
57
- */
58
- public function init() {
59
-
60
- add_action( 'admin_notices', array( $this, 'upgrade_notices' ) );
61
- add_action( $this->settings['prefix'] . '_sticky_admin_notice', array(
62
- $this,
63
- 'sticky_admin_notice_social_links',
64
- ), 10 );
65
- add_action( $this->settings['prefix'] . '_before_submit_button', array( $this, 'is_active_toggle' ), 10 );
66
- add_action( $this->settings['prefix'] . '_settings_sidebars', array( $this, 'about_the_author' ), 19 );
67
- add_action( $this->settings['prefix'] . '_settings_sidebars', array( $this, 'sidebar_feed' ), 20 );
68
- }
69
-
70
- /**
71
- * Enqueue scripts and styles
72
- */
73
  public function admin_enqueue_scripts( $hook ) {
74
- if ( 'settings_page_' . $this->settings['domain'] !== $hook ) {
75
- return;
76
- }
77
-
78
- /* Core */
79
- wp_enqueue_media();
80
- wp_enqueue_script( array( 'wp-color-picker', 'plugin-install' ) );
81
- wp_enqueue_style( array( 'wp-color-picker', 'thickbox', 'plugin-install' ) );
82
-
83
- /* jQuery Chosen */
84
- wp_enqueue_script( 'chosen', plugins_url( 'js/chosen.jquery.min.js', $this->settings['file'] ), array( 'jquery' ), '1.3.0', true );
85
- wp_enqueue_style( 'chosen', plugins_url( 'css/chosen/chosen.min.css', $this->settings['file'] ), null, '1.3.0', 'screen' );
86
-
87
- /* jQuery Sticky */
88
- wp_enqueue_script( 'sticky', plugins_url( 'js/jquery.sticky.js', $this->settings['file'] ), array( 'jquery' ), '1.0.0', true );
89
-
90
- /* Ace */
91
- wp_enqueue_script( 'ace', plugins_url( 'js/ace/src-min-noconflict/ace.js', $this->settings['file'] ), null, '20.12.14', true );
92
-
93
- /* Dashicons */
94
- wp_enqueue_style( 'dashicons' );
95
-
96
- /* Admin */
97
- wp_enqueue_script( $this->settings['domain'], plugins_url( 'js/admin.js', $this->settings['file'] ), array(
98
- 'jquery',
99
- 'jquery-form',
100
- ), $this->settings['version'], true );
101
- wp_enqueue_style( $this->settings['domain'], plugins_url( 'css/admin.css', $this->settings['file'] ), false, $this->settings['version'], 'screen' );
102
-
103
- do_action( "{$this->settings['domain']}_admin_enqueue_scripts" );
104
- }
105
-
106
- /**
107
- * Localize our script array.
108
- */
109
  public function wp_localize_script() {
110
- $this->localize_array['prefix'] = $this->settings['prefix'];
111
- $this->localize_array['blog_id'] = get_current_blog_id();
112
- $this->localize_array['nonce'] = wp_create_nonce( $this->settings['nonce'] );
113
- wp_localize_script( $this->settings['domain'], 'cl_settings_api', $this->localize_array );
114
  }
115
 
116
- /**
117
- * Set settings sections
118
- *
119
- * @param array $sections setting sections array
120
- */
121
  public function set_sections( $sections ) {
122
-
123
- $sections = apply_filters( $this->settings['prefix'] . '_add_settings_sections', $sections );
124
- $this->settings_sections = $sections;
125
-
126
- return $this;
127
  }
128
 
129
  /**
130
  * Add a single section
131
  *
132
- * @param array $section
133
  */
134
  public function add_section( $section ) {
135
-
136
- $this->settings_sections[] = $section;
137
-
138
- return $this;
139
  }
140
 
141
  /**
142
  * Set settings fields
143
  *
144
- * @param array $fields settings fields array
145
  */
146
  public function set_fields( $fields ) {
147
-
148
- $fields = apply_filters( $this->settings['prefix'] . '_add_settings_fields', $fields );
149
- $this->settings_fields = $fields;
150
-
151
- return $this;
152
  }
153
 
154
  /**
155
  * Add a single field
156
  *
157
- * @param array $section
158
- * @param array $field
159
  */
160
  public function add_field( $section, $field ) {
 
 
 
 
 
 
 
161
 
162
- $defaults = array(
163
- 'name' => '',
164
- 'label' => '',
165
- 'desc' => '',
166
- 'type' => 'text',
167
- );
168
-
169
- $args = wp_parse_args( $field, $defaults );
170
- $this->settings_fields[ $section ][] = $args;
171
-
172
- return $this;
173
  }
174
 
175
  /**
176
  * Add a single section
177
  *
178
- * @param array $section
179
  */
180
  public function add_sidebar( $sidebar = array() ) {
181
-
182
- $sidebar = apply_filters( $this->settings['prefix'] . '_add_settings_sidebar', $sidebar );
183
- if ( ! empty( $sidebar ) ) {
184
- $this->settings_sidebars[] = $sidebar;
185
- }
186
  }
187
 
188
  /**
@@ -194,487 +180,474 @@ class CL_Settings_API {
194
  * registers them to WordPress and ready for use.
195
  */
196
  public function admin_init() {
197
-
198
- //register settings sections
199
- foreach ( $this->settings_sections as $section ) {
200
- if ( false == get_option( $section['id'] ) && ( isset( $section['option'] ) && false !== $section['option'] ) ) {
201
- add_option( $section['id'] );
202
- }
203
-
204
- add_settings_section( $section['id'], $section['title'], '__return_false', $section['id'] );
205
- }
206
-
207
- //register settings fields
208
- foreach ( $this->settings_fields as $section => $field ) {
209
- foreach ( $field as $option ) {
210
-
211
- $type = isset( $option['type'] ) ? $option['type'] : 'text';
212
-
213
- $args = array(
214
- 'id' => $option['name'],
215
- 'desc' => isset( $option['desc'] ) ? $option['desc'] : '',
216
- 'name' => $option['label'],
217
- 'section' => $section,
218
- 'size' => isset( $option['size'] ) ? $option['size'] : null,
219
- 'options' => isset( $option['options'] ) ? $option['options'] : '',
220
- 'default' => isset( $option['default'] ) ? $option['default'] : '',
221
- 'sanitize' => isset( $option['sanitize'] ) ? $option['sanitize'] : '',
222
- 'callback' => isset( $option['class'] ) ? $option['class'] : $this,
223
- );
224
- $args = wp_parse_args( $args, $option );
225
-
226
- add_settings_field( $section . '[' . $option['name'] . ']', $option['label'], array(
227
- $args['callback'],
228
- 'callback_' . $type,
229
- ), $section, $section, $args );
230
- }
231
- }
232
-
233
- // creates our settings in the options table
234
- foreach ( $this->settings_sections as $section ) {
235
- register_setting( $section['id'], $section['id'], array( $this, 'sanitize_options' ) );
236
- }
237
  }
238
 
239
  /**
240
  * Displays a text field for a settings field
241
  *
242
- * @param array $args settings field args
243
- *
244
- * @updated 2.0.2
245
  */
246
  function callback_text( $args ) {
247
 
248
- $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
249
- $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
250
- $type = isset( $args['type'] ) && ! is_null( $args['type'] ) ? $args['type'] : 'text';
251
-
252
- $html = sprintf( '<input type="%1$s" class="%2$s-text" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s">', $type, $size, $args['section'], $args['id'], $value );
253
- $html .= ! empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
254
-
255
- echo $html;
256
  }
257
 
258
  /**
259
  * Displays a text field for a settings field
260
  *
261
- * @param array $args settings field args
262
- *
263
- * @since 2.0.2
264
  */
265
  function callback_text_number( $args ) {
266
-
267
- $args['type'] = 'number';
268
- $this->callback_text( $args );
269
  }
270
 
271
  /**
272
  * Displays a text field for a settings field
273
  *
274
- * @param array $args settings field args
275
  */
276
  function callback_text_array( $args ) {
277
-
278
- $value = $this->get_option( $args['id'], $args['section'], $args['default'] );
279
- $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
280
-
281
- $html = '<ul style="margin-top:0">';
282
-
283
- if ( is_array( $value ) ) {
284
- foreach ( $value as $key => $val ) {
285
- $html .= '<li>';
286
- $html .= sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s][]" value="%4$s" data-key="%5$s">', $size, $args['section'], $args['id'], esc_attr( $val ), $key );
287
- $html .= sprintf( '<a href="#" class="button dodelete-%1$s[%2$s]">-</a>', $args['section'], $args['id'] );
288
- $html .= '</li>';
289
- }
290
- } else {
291
- $html .= '<li>';
292
- $html .= sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s][]" value="%4$s" data-key="0" data-array="false">', $size, $args['section'], $args['id'], esc_attr( $value ) );
293
- $html .= sprintf( '<a href="#" class="button dodelete-%1$s[%2$s]">-</a>', $args['section'], $args['id'] );
294
- $html .= '</li>';
295
- }
296
-
297
- $html .= '</ul>';
298
- $html .= sprintf( '<a href="#" class="button docopy-%1$s[%2$s]">+</a>', $args['section'], $args['id'] );
299
-
300
- $html .= ! empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
301
-
302
- echo $html;
303
- }
304
-
305
- /**
306
- * Displays a text field for a settings field
307
- *
308
- * @param array $args settings field args
309
- */
 
310
  function callback_colorpicker( $args ) {
311
-
312
- $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
313
- $check = esc_attr( $this->get_option( $args['id'] . '_checkbox', $args['section'], $args['default'] ) );
314
- $opacity = esc_attr( $this->get_option( $args['id'] . '_opacity', $args['section'], $args['default'] ) );
315
- $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'small';
316
- $options = array( '1', '0.9', '0.8', '0.7', '0.6', '0.5', '0.4', '0.3', '0.2', '0.1', '0', );
317
- $class = 'on' != $check ? ' hidden' : '';
318
-
319
- /* Localize the array */
320
- $this->localize_array['callback_colorpicker'][] = array( 'id' => $args['id'], 'section' => $args['section'] );
321
-
322
- /* Color */
323
- $html = '<div class="cl-colorpicker-wrap">';
324
- $html .= sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s" style="float:left">', $size, $args['section'], $args['id'], $value );
325
-
326
- /* Allow Opacity */
327
- $html .= '<div class="checkbox-wrap">';
328
- $html .= sprintf( '<input type="hidden" name="%1$s[%2$s]" value="off" >', $args['section'], $args['id'] . '_checkbox' );
329
- $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s]" name="%1$s[%2$s]" value="on"%4$s >', $args['section'], $args['id'] . '_checkbox', $check, checked( $check, 'on', false ) );
330
- $html .= sprintf( __( '<label for="%1$s[%2$s]">Opacity</label>', $this->settings['domain'] ), $args['section'], $args['id'] . '_checkbox' );
331
- $html .= '</div>';
332
-
333
- /* Opacity */
334
- $html .= sprintf( '<select class="%1$s%4$s" name="%2$s[%3$s]" id="%2$s[%3$s]" style="margin-left:70px;">', $size, $args['section'], $args['id'] . '_opacity', $class );
335
- foreach ( $options as $key ) {
336
- $html .= sprintf( '<option value="%s"%s>%s</option>', $key, selected( $opacity, $key, false ), $key );
337
- }
338
- $html .= '</select>';
339
- $html .= '<br class="clear">';
340
- $html .= '</div>';
341
-
342
- $html .= ! empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
343
-
344
- echo $html;
345
  }
346
 
347
  /**
348
  * Displays a checkbox for a settings field
349
  *
350
- * @param array $args settings field args
351
  */
352
  function callback_checkbox( $args ) {
353
 
354
- $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
355
-
356
- $html = '<div class="checkbox-wrap">';
357
- $html .= sprintf( '<input type="hidden" name="%1$s[%2$s]" value="off" >', $args['section'], $args['id'] );
358
- $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s]" name="%1$s[%2$s]" value="on"%4$s >', $args['section'], $args['id'], $value, checked( $value, 'on', false ) );
359
- $html .= sprintf( '<label for="%1$s[%2$s]"></label>', $args['section'], $args['id'] );
360
- $html .= '</div>';
 
 
361
 
362
- $html .= ! empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
363
-
364
- echo $html;
365
  }
366
 
367
  /**
368
  * Displays a multicheckbox a settings field
369
  *
370
- * @param array $args settings field args
371
  */
372
  function callback_multicheck( $args ) {
373
 
374
- $value = $this->get_option( $args['id'], $args['section'], $args['default'] );
375
-
376
- $html = '<div class="checkbox-wrap">';
377
- $html .= '<ul>';
378
- foreach ( $args['options'] as $key => $label ) {
379
- $checked = isset( $value[ $key ] ) ? $value[ $key ] : '0';
380
- $html .= '<li>';
381
- $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s][%3$s]" name="%1$s[%2$s][%3$s]" value="%3$s"%4$s >', $args['section'], $args['id'], $key, checked( $checked, $key, false ) );
382
- $html .= sprintf( '<label for="%1$s[%2$s][%4$s]" title="%3$s"> %3$s</label>', $args['section'], $args['id'], $label, $key );
383
- $html .= '</li>';
384
- }
385
- $html .= '</ul>';
386
- $html .= '</div>';
387
-
388
- $html .= ! empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
389
-
390
- echo $html;
391
  }
392
 
393
  /**
394
  * Displays a multicheckbox a settings field
395
  *
396
- * @param array $args settings field args
397
  */
398
  function callback_radio( $args ) {
399
 
400
- $value = $this->get_option( $args['id'], $args['section'], $args['default'] );
401
-
402
- $html = '<div class="radio-wrap">';
403
- $html .= '<ul>';
404
- foreach ( $args['options'] as $key => $label ) {
405
- $html .= '<li>';
406
- $html .= sprintf( '<input type="radio" class="radio" id="%1$s[%2$s][%3$s]" name="%1$s[%2$s]" value="%3$s"%4$s >', $args['section'], $args['id'], $key, checked( $value, $key, false ) );
407
- $html .= sprintf( '<label for="%1$s[%2$s][%4$s]" title="%3$s"> %3$s</label><br>', $args['section'], $args['id'], $label, $key );
408
- $html .= '</li>';
409
- }
410
- $html .= '</ul>';
411
- $html .= '</div>';
412
-
413
- $html .= ! empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
414
-
415
- echo $html;
416
  }
417
 
418
  /**
419
  * Displays a selectbox for a settings field
420
  *
421
- * @param array $args settings field args
422
  */
423
  function callback_select( $args ) {
424
 
425
- $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
426
- $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
 
 
 
 
 
 
 
 
 
 
 
427
 
428
- /* Localize the array */
429
- $this->localize_array['callback_select'][] = array( 'id' => $args['id'], 'section' => $args['section'] );
430
-
431
- $html = sprintf( '<select class="%1$s" name="%2$s[%3$s]" id="%2$s[%3$s]">', $size, $args['section'], $args['id'] );
432
- foreach ( $args['options'] as $key => $label ) {
433
- $html .= sprintf( '<option value="%s"%s>%s</option>', $key, selected( $value, $key, false ), $label );
434
- }
435
- $html .= sprintf( '</select>' );
436
-
437
- $html .= ! empty( $args['desc'] ) ? sprintf( '<br><span class="description"> %s</span>', $args['desc'] ) : '';
438
-
439
- echo $html;
440
  }
441
 
442
  /**
443
  * Displays a textarea for a settings field
444
  *
445
- * @param array $args settings field args
446
  */
447
  function callback_textarea( $args ) {
448
 
449
- $value = esc_textarea( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
450
- $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
451
- $extra = isset( $args['extra'] ) && is_array( $args['extra'] ) ? $args['extra'] : null;
452
- $param = '';
453
-
454
- if ( null !== $extra ) {
455
- foreach ( $extra as $p_key => $p_value ) {
456
- $param .= $p_key . '="' . $p_value . '"';
457
- }
458
- }
459
-
460
- $html = sprintf( '<textarea rows="5" cols="55" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]"%5$s>%4$s</textarea>', $size, $args['section'], $args['id'], stripslashes( $value ), $param );
461
- $html .= ! empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
462
-
463
- echo $html;
464
  }
465
 
466
  /**
467
  * Displays a HTML for a settings field
468
  *
469
- * @param array $args settings field args
470
  */
471
  function callback_html( $args ) {
472
- static $counter = 0;
473
-
474
- $html = isset( $args['desc'] ) ? sprintf( '<div class="section-%s-%d">%s</div><hr>', $args['section'], $counter, $args['desc'] ) : '';
475
- $counter ++;
476
-
477
- echo $html;
478
  }
479
 
480
  /**
481
  * Displays raw HTML for a settings field
482
  *
483
- * @param array $args settings field args
484
  */
485
  function callback_raw( $args ) {
486
-
487
- $html = isset( $args['desc'] ) ? sprintf( '<div class="raw-html">%s</div>', $args['desc'] ) : '';
488
-
489
- echo $html;
490
  }
491
 
492
  /**
493
  * Displays a rich text textarea for a settings field
494
  *
495
- * @param array $args settings field args
496
  */
497
  function callback_wysiwyg( $args ) {
498
 
499
- $value = wpautop( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
500
- $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : '500px';
501
-
502
- $html = sprintf( '<div style="width: %s">', $size );
503
-
504
- ob_start();
505
- wp_editor( $value, $args['section'] . '[' . $args['id'] . ']', array(
506
- 'teeny' => true,
507
- 'textarea_rows' => 10,
508
- ) );
509
-
510
- $html .= ob_get_clean();
511
- $html .= '</div>';
512
-
513
- $html .= ! empty( $args['desc'] ) ? sprintf( '<br><span class="description"> %s</span>', $args['desc'] ) : '';
514
-
515
- echo $html;
516
  }
517
 
518
  /**
519
  * Displays a file upload field for a settings field
520
  *
521
- * @param array $args settings field args
522
  */
523
  function callback_file( $args ) {
524
- static $counter = 0;
525
-
526
- $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
527
- $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
528
- $id = $args['section'] . '[' . $args['id'] . ']';
529
-
530
- /* Localize the array */
531
- $this->localize_array['callback_file'][] = array( 'id' => $args['id'], 'section' => $args['section'] );
532
-
533
- $html = sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s">', $size, $args['section'], $args['id'], $value );
534
- $html .= '<input type="button" class="button ' . $args['id'] . '-browse" id="' . $id . '_button" value="Browse" style="margin-left:5px" >';
535
- $html .= '<input type="button" class="button ' . $args['id'] . '-clear" id="' . $id . '_clear" value="Clear" style="margin-left:5px" >';
536
-
537
- $html .= ! empty( $args['desc'] ) ? sprintf( '<br><span class="description"> %s</span>', $args['desc'] ) : '';
538
-
539
- /* Image */
540
- $html .= '<div id="' . $id . '_preview" class="' . $id . '_preview">';
541
- if ( $value != '' ) {
542
- $check_image = preg_match( '/(^.*\.jpg|jpeg|png|gif|ico*)/i', $value );
543
- if ( $check_image ) {
544
- $html .= '<div class="img-wrapper">';
545
- $html .= '<img src="' . $value . '" alt="" >';
546
- $html .= '<a href="#" class="remove_file_button" rel="' . $id . '">Remove Image</a>';
547
- $html .= '</div>';
548
- }
549
- }
550
- $html .= '</div>';
551
-
552
- echo $html;
553
  }
554
 
555
  /**
556
  * Displays a password field for a settings field
557
  *
558
- * @param array $args settings field args
559
  */
560
  function callback_password( $args ) {
561
 
562
- $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
563
- $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular';
564
-
565
- $html = sprintf( '<input type="password" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s">', $size, $args['section'], $args['id'], $value );
566
- $html .= ! empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
567
-
568
- echo $html;
569
  }
570
 
571
  /**
572
  * Sanitize callback for Settings API
573
- */
574
  function sanitize_options( $options ) {
575
-
576
- if ( is_null( $options ) ) {
577
- return $options;
578
- }
579
-
580
- do_action( $this->settings['prefix'] . '_before_sanitize_options', $options );
581
-
582
- foreach ( $options as $option_slug => $option_value ) {
583
- $sanitize_callback = $this->get_sanitize_callback( $option_slug );
584
-
585
- // If callback is set, call it
586
- if ( $sanitize_callback ) {
587
- $options[ $option_slug ] = call_user_func( $sanitize_callback, $option_value );
588
- continue;
589
- }
590
-
591
- // Treat everything that's not an array as a string
592
- if ( ! is_array( $option_value ) ) {
593
- $options[ $option_slug ] = sanitize_text_field( $option_value );
594
- continue;
595
- }
596
- }
597
-
598
- do_action( $this->settings['prefix'] . '_after_sanitize_options', $options );
599
-
600
- return $options;
601
- }
602
-
603
  /**
604
  * Get sanitization callback for given option slug
605
- *
606
  * @param string $slug option slug
607
- *
608
  * @return mixed string or bool false
609
- */
610
  function get_sanitize_callback( $slug = '' ) {
611
-
612
- if ( empty( $slug ) ) {
613
- return false;
614
- }
615
-
616
- // Iterate over registered fields and see if we can find proper callback
617
- foreach ( $this->settings_fields as $section => $options ) {
618
- foreach ( $options as $option ) {
619
- if ( $option['name'] != $slug ) {
620
- continue;
621
- }
622
-
623
- // Return the callback name
624
- return isset( $option['sanitize'] ) && is_callable( $option['sanitize'] ) ? $option['sanitize'] : false;
625
- }
626
- }
627
-
628
- return false;
629
- }
630
-
631
  /**
632
  * Outpute our settings HTML
633
  *
634
  */
635
- public function settings_html() { ?>
636
-
637
- <div class="cl-container">
638
-
639
- <div class="cl-header">
640
- <h3><?php _e( 'Custom Login', $this->settings['domain'] ); ?></h3>
641
- <span><?php echo $this->settings['version']; ?></span>
642
- <div>
643
- <?php echo sprintf( __( 'A %s plugin', $this->settings['domain'] ), '<strong><a href="https://frosty.media/" target="_blank">Frosty Media</a></strong>' ); ?>
644
- &nbsp;&nbsp;|&nbsp;&nbsp;<a href="https://twitter.com/Frosty_Media"><span
645
- class="dashicons dashicons-twitter"></span></a>
646
- </div>
647
- </div><!-- #cl-header -->
648
-
649
- <div id="cl-notices">
650
- <h2></h2>
651
- </div><!-- #cl-text -->
652
-
653
- <div id="cl-sticky">
654
- <div class="wrap">
655
- <div id="sticky-admin-notice">
656
- <?php do_action( $this->settings['prefix'] . '_sticky_admin_notice' ); ?>
657
- </div>
658
- <div class="alignright">
659
- <?php do_action( $this->settings['prefix'] . '_before_submit_button' ); ?>
660
- <?php submit_button( __( 'Save Changes', $this->settings['domain'] ), 'primary', 'cl_save', false ); ?>
661
- </div>
662
- <br class="clear">
663
- </div>
664
- </div><!-- #cl-sticky -->
665
-
666
- <div class="cl-sidebar">
667
- <?php $this->show_navigation(); ?>
668
- <?php do_action( $this->settings['prefix'] . '_settings_sidebars', $this->settings_sidebars ); ?>
669
- </div><!-- #cl-header -->
670
-
671
- <div class="cl-main">
672
- <?php $this->show_forms(); ?>
673
- </div><!-- #cl-header -->
674
-
675
- </div><!-- #cl-wrapper -->
676
- <?php
677
- }
678
 
679
  /**
680
  * Show navigation as lists
@@ -682,7 +655,7 @@ class CL_Settings_API {
682
  * Shows all the settings section labels as list items
683
  */
684
  private function show_navigation() {
685
-
686
  $html = '<ul class="cl-sections-menu">';
687
  foreach ( $this->settings_sections as $tab ) {
688
  $html .= sprintf( '<li><a href="%1$s">%2$s</a></li>', isset( $tab['href'] ) ? $tab['href'] : '#' . $tab['id'], $tab['title'] );
@@ -698,23 +671,22 @@ class CL_Settings_API {
698
  * This function displays every sections in a different form
699
  */
700
  private function show_forms() {
701
-
702
- foreach ( $this->settings_sections as $form ) {
703
- $form_id = $form['id']; ?>
704
- <div id="<?php echo $form_id; ?>" class="group">
705
- <form action="options.php" id="<?php echo $form_id; ?>form" method="post">
706
- <?php do_action( $this->settings['prefix'] . '_form_top_' . $form_id, $form ); ?>
707
- <?php settings_fields( $form_id ); ?>
708
- <?php do_settings_sections( $form_id ); ?>
709
- <?php do_action( $this->settings['prefix'] . '_form_bottom_' . $form_id, $form ); ?>
710
- <?php if ( isset( $form['submit'] ) && $form['submit'] ) {
711
- submit_button( sprintf( __( 'Save %s', $this->settings['domain'] ), $form['title'] ) );
712
- } ?>
713
- </form>
714
- </div><?php
715
- # var_dump( $form_id, get_option( $form_id ) );
716
- }
717
- do_action( $this->settings['prefix'] . '_after_settings_sections_form' );
718
  }
719
 
720
  /**
@@ -723,91 +695,61 @@ class CL_Settings_API {
723
  * This function displays every sections in a different form
724
  */
725
  public function get_form() {
726
-
727
- check_ajax_referer( $this->settings['nonce'], 'nonce' );
728
-
729
- if ( isset( $_POST['form_id'] ) ) {
730
-
731
- $setting_form = array();
732
- $setting_form['error'] = 1;
733
-
734
- foreach ( $this->settings_sections as $form ) {
735
- $form_id = $form['id'];
736
- if ( str_replace( '#', '', $_POST['form_id'] ) !== $form_id ) {
737
- continue;
738
- }
739
- ob_start(); ?>
740
- <form action="options.php" id="<?php echo $form_id; ?>form" method="post">
741
- <?php do_action( $this->settings['prefix'] . '_form_top_' . $form['id'], $form ); ?>
742
- <?php settings_fields( $form['id'] ); ?>
743
- <?php do_settings_sections( $form['id'] ); ?>
744
- <?php do_action( $this->settings['prefix'] . '_form_bottom_' . $form['id'], $form ); ?>
745
- <?php submit_button( sprintf( __( 'Save %s Changes', $this->settings['domain'] ), $form_id ) ); ?>
746
- </form><?php
747
- $setting_form['error'] = 0;
748
- $setting_form['html'] = ob_get_clean();
749
- }
750
-
751
- header( 'Content-Type: application/json' );
752
- echo json_encode( $setting_form );
753
- die();
754
- }
755
- }
756
-
757
- /**
758
- * Show the section settings forms
759
- *
760
- * This function displays every sections in a different form
761
- */
762
- public function activate_check_ajax() {
763
-
764
- if ( empty( $_POST ) || ! check_ajax_referer( $this->settings['nonce'], 'nonce', false ) ) {
765
- wp_send_json_error();
766
- }
767
-
768
- $settings = CL_Common::get_options( 'general' );
769
- $active_value = isset( $_POST['active_value'] ) && 'true' == $_POST['active_value'] ? 'on' : 'off';
770
-
771
- if ( $settings['active'] !== $active_value ) {
772
- $settings['active'] = $active_value;
773
-
774
- if ( update_option( CUSTOM_LOGIN_OPTION . '_general', $settings ) ) {
775
- wp_send_json_success();
776
- } else {
777
- wp_send_json_error();
778
- }
779
- }
780
-
781
- wp_send_json_success();
782
- }
783
-
784
- /**
785
- * Create a potbox widget.
786
- *
787
- * @param string $id ID of the postbox.
788
- * @param string $title Title of the postbox.
789
- * @param string $content Content of the postbox.
790
- */
791
- public function postbox( $id, $title, $content, $group = false ) { ?>
792
-
793
- <div class="metabox-holder<?php if ( $group ) {
794
- echo ' group';
795
- } ?>" id="<?php echo $id; ?>">
796
- <div class="postbox">
797
- <h3><?php echo $title; ?></h3>
798
- <div class="inside"><?php echo $content; ?></div>
799
- </div>
800
- </div><?php
801
- }
802
-
803
- /**
804
- * Global 'active' checkbox notification.
805
- *
806
- * @ref http://codepen.io/pklada/pen/jEGwMB
807
- */
808
- function is_active_toggle() { ?>
809
- <label class="tgl">
810
- <span class="tgl_input"></span>
811
  <span class="tgl_body">
812
  <span class="tgl_switch"></span>
813
  <span class="tgl_track">
@@ -815,141 +757,140 @@ class CL_Settings_API {
815
  <span class="tgl_bgd tgl_bgd-negative"></span>
816
  </span>
817
  </span>
818
- </label><?php
819
- }
820
-
821
- /**
822
- * Box with latest plugins from Extendd.com for sidebar
823
- */
824
- function about_the_author( $args ) {
825
-
826
- $content = sprintf( '%s: <a href="https://wordpress.org/support/view/plugin-reviews/custom-login" class="star-rating" target="_blank">
827
  <i class="dashicons dashicons-star-filled"></i>
828
  <i class="dashicons dashicons-star-filled"></i>
829
  <i class="dashicons dashicons-star-filled"></i>
830
  <i class="dashicons dashicons-star-filled"></i>
831
  <i class="dashicons dashicons-star-filled"></i>
832
  </a>', _x( 'Rate', 'rate; as in rate this plugin', $this->settings['domain'] ) );
833
-
834
- $content .= '<ul>';
835
- $content .= sprintf( '<li>%s: <a href="http://austin.passy.co" target="_blank">Austin Passy</a></li>', _x( 'Author', 'the author of this plugin', $this->settings['domain'] ) );
836
- $content .= sprintf( '<li>%s: <a href="https://twitter.com/TheFrosty" target="_blank">TheFrosty</a></li>', __( 'Twitter', $this->settings['domain'] ) );
837
- $content .= '</ul>';
838
-
839
- $content .= sprintf( __( '<small>If you have suggestions for a new add-on, feel free to open a support request on <a href="%s" target="_blank">GitHub</a>. Want regular updates? Follow me on <a href="%s" target="_blank">Twitter</a> or visit my <a href="%s" target="_blank">blog</a>.</small>' ),
840
- 'https://github.com/thefrosty/custom-login/issues',
841
- 'https://twitter.com/TheFrosty',
842
- 'http://austin.passy.co'
843
- );
844
-
845
- $this->postbox( 'frosty-media-author', __( 'Custom Login', $this->settings['domain'] ), $content );
846
- }
847
-
848
- /**
849
- * Box with latest plugins from Extendd.com for sidebar
850
- */
851
- function sidebar_feed( $args ) {
852
-
853
- $defaults = array(
854
- 'items' => 6,
855
- 'feed' => 'https://frosty.media/feed/?post_type=plugin&plugin_tag=custom-login-extension',
856
- );
857
-
858
- $args = wp_parse_args( $args, $defaults );
859
-
860
- $rss_items = CL_Common::fetch_rss_items( $args['items'], $args['feed'] );
861
-
862
- $content = '<ul>';
863
- if ( ! $rss_items ) {
864
- $content .= '<li>' . __( 'Error fetching feed', $this->settings['domain'] ) . '</li>';
865
- } else {
866
- foreach ( $rss_items as $item ) {
867
- $url = preg_replace( '/#.*/', '', esc_url( $item->get_permalink(), null, 'display' ) );
868
- $content .= '<li>';
869
- $content .= '<a href="' . $url . '?utm_source=wpadmin&utm_medium=sidebarwidget&utm_term=newsite&utm_campaign=' . $this->settings['prefix'] . '_settings-api" target="_blank">' . esc_html( $item->get_title() ) . '</a>';
870
- $content .= '</li>';
871
- }
872
- }
873
- $content .= '</ul>';
874
-
875
- $this->postbox( 'custom-login-extensions', sprintf( __( 'Custom Login Extensions %s', $this->settings['domain'] ), '<small class="dashicons dashicons-external"></small>' ), $content );
876
- }
877
-
878
- /**
879
- * Display Upgrade Notices
880
- *
881
- * @access private
882
- * @since 3.0.3
883
- * @return void
884
- */
885
- public function upgrade_notices() {
886
-
887
- $show_upgrade_notice = false;
888
-
889
- // Version < 2.0
890
- if ( false !== get_option( 'custom_login_settings', false ) ) {
891
- $show_upgrade_notice = true;
892
- }
893
-
894
- // Version > 2.0
895
- if ( false !== get_option( 'custom_login', false ) ) {
896
- $show_upgrade_notice = true;
897
- }
898
-
899
- if ( $show_upgrade_notice && ( '' === get_option( CUSTOM_LOGIN_OPTION . '_general', '' ) ) ) {
900
- remove_action( 'admin_notice', array( CL_Settings_Upgrade::instance(), 'upgrade_notices' ) );
901
- printf(
902
- '<div class="error"><p>' . esc_html__( 'Custom Login has detected old settings. If you wish to use them please run %sthis%s script before making any changes below.', CUSTOM_LOGIN_DIRNAME ) . '</p></div>',
903
- '<a href="' . esc_url( admin_url( 'options.php?page=custom-login-upgrades' ) ) . '">',
904
- '</a>'
905
- );
906
- }
907
- }
908
-
909
- /**
910
- * Box with latest plugins from Extendd.com for sidebar
911
- */
912
- public function sticky_admin_notice_social_links() {
913
-
914
- $content = '<ul class="social">';
915
- $content .= '<li><a href="https://www.facebook.com/FrostyMediaWP" target="_blank"><span class="dashicons dashicons-facebook"></span></a></li>';
916
- $content .= '<li><a href="https://twitter.com/Frosty_Media" target="_blank"><span class="dashicons dashicons-twitter"></span></a></li>';
917
- $content .= '<li><a href="https://plus.google.com/+FrostyMedia/" target="_blank"><span class="dashicons dashicons-googleplus"></span></a></li>';
918
- $content .= '<li><a href="http://eepurl.com/bbj0bD" target="_blank"><span class="dashicons dashicons-email"></span></a></li>';
919
- $content .= '</ul>';
920
-
921
- echo $content;
922
- }
923
-
 
924
  /**
925
  * Replace all square brackets with and underscore.
926
  *
927
- * @param string $input
928
- *
929
  * @return string
930
  */
931
- private function replace_bracket_underscore( $input ) {
932
- return preg_replace( '/[\[\]]/', '_', $input );
933
- }
934
 
935
  /**
936
  * Get the value of a settings field
937
  *
938
- * @param string $option settings field name
939
- * @param string $section the section name this field belongs to
940
- * @param string $default default text if it's not found
941
- *
942
  * @return string
943
  */
944
- function get_option( $option, $section, $default = '' ) {
945
-
946
- $options = get_option( $section, array() );
947
-
948
- if ( isset( $options[ $option ] ) ) {
949
- return $options[ $option ];
950
- }
951
-
952
- return $default;
953
- }
954
 
955
  }
1
  <?php
2
 
3
  // Exit if accessed directly
4
+ if ( ! defined( 'ABSPATH' ) ) exit;
 
 
5
 
6
  /**
7
  * Custom Login Settings API
8
  */
9
  class CL_Settings_API {
10
+
11
+ /**
12
+ * Version
13
+ */
14
+ var $api_version = '2.0.3';
15
+
16
+ /**
17
+ * @var array
18
+ */
19
+ private $settings_sections = array();
20
+ private $settings_fields = array();
21
+ private $settings_sidebars = array();
22
+ private $localize_array = array();
23
+
24
+ /**
25
+ * @var array
26
+ */
27
+ private $settings = array();
28
+
29
+ /**
30
+ * Fire away captain!
31
+ */
32
  public function __construct( $sections = array(), $fields = array(), $args = array() ) {
33
+
34
+ $this->settings = $args;
35
+
36
+ if ( !empty( $sections ) ) {
37
+ $this->set_sections( $sections );
38
+ }
39
+
40
+ if ( !empty( $fields ) ) {
41
+ $this->set_fields( $fields );
42
+ }
43
+
44
+ add_action( 'load-' . $this->settings['menu_page'], array( $this, 'init' ), 89 );
45
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
46
+ add_action( 'admin_footer', array( $this, 'wp_localize_script' ), 99 );
47
+ add_action( 'wp_ajax_' . $this->settings['prefix'] . '_get_form', array( $this, 'get_form' ), 99 );
48
+ }
49
+
50
+ /**
51
+ * Fire any actions needed a little late
52
+ *
53
+ * @return void
54
+ */
55
+ public function init() {
56
+
57
+ add_action( 'admin_notices', array( $this, 'upgrade_notices' ) );
58
+ add_action( $this->settings['prefix'] . '_sticky_admin_notice', array( $this, 'sticky_admin_notice_social_links' ), 10 );
59
+ add_action( $this->settings['prefix'] . '_before_submit_button', array( $this, 'is_active_toggle' ), 10 );
60
+ add_action( $this->settings['prefix'] . '_settings_sidebars', array( $this, 'about_the_author' ), 19 );
61
+ add_action( $this->settings['prefix'] . '_settings_sidebars', array( $this, 'sidebar_feed' ), 20 );
62
+ }
63
+
64
+ /**
65
+ * Enqueue scripts and styles
66
+ */
 
 
 
 
67
  public function admin_enqueue_scripts( $hook ) {
68
+ if ( 'settings_page_' . $this->settings['domain'] !== $hook )
69
+ return;
70
+
71
+ /* Core */
72
+ wp_enqueue_media();
73
+ wp_enqueue_script( array( 'wp-color-picker', 'plugin-install' ) );
74
+ wp_enqueue_style( array( 'wp-color-picker', 'thickbox', 'plugin-install' ) );
75
+
76
+ /* jQuery Chosen */
77
+ wp_enqueue_script( 'chosen', plugins_url( 'js/chosen.jquery.min.js', $this->settings['file'] ), array( 'jquery' ), '1.3.0', true );
78
+ wp_enqueue_style( 'chosen', plugins_url( 'css/chosen/chosen.min.css', $this->settings['file'] ), null, '1.3.0', 'screen' );
79
+
80
+ /* jQuery Sticky */
81
+ wp_enqueue_script( 'sticky', plugins_url( 'js/jquery.sticky.js', $this->settings['file'] ), array( 'jquery' ), '1.0.0', true );
82
+
83
+ /* Ace */
84
+ wp_enqueue_script( 'ace', plugins_url( 'js/ace/src-min-noconflict/ace.js', $this->settings['file'] ), null, '20.12.14', true );
85
+
86
+ /* Dashicons */
87
+ wp_enqueue_style( 'dashicons' );
88
+
89
+ /* Admin */
90
+ wp_enqueue_script( $this->settings['domain'], plugins_url( 'js/admin.js', $this->settings['file'] ), array( 'jquery', 'jquery-form' ), $this->settings['version'], true );
91
+ wp_enqueue_style( $this->settings['domain'], plugins_url( 'css/admin.css', $this->settings['file'] ), false, $this->settings['version'], 'screen' );
92
+
93
+ do_action( "{$this->settings['domain']}_admin_enqueue_scripts" );
94
+ }
95
+
96
+ /**
97
+ * Localize our script array.
98
+ */
 
 
 
 
99
  public function wp_localize_script() {
100
+ $this->localize_array['prefix'] = $this->settings['prefix'];
101
+ $this->localize_array['blog_id'] = get_current_blog_id();
102
+ $this->localize_array['nonce'] = wp_create_nonce( $this->settings['nonce'] );
103
+ wp_localize_script( $this->settings['domain'], 'cl_settings_api', $this->localize_array );
104
  }
105
 
106
+ /**
107
+ * Set settings sections
108
+ *
109
+ * @param array $sections setting sections array
110
+ */
111
  public function set_sections( $sections ) {
112
+
113
+ $sections = apply_filters( $this->settings['prefix'] . '_add_settings_sections', $sections );
114
+ $this->settings_sections = $sections;
115
+ return $this;
 
116
  }
117
 
118
  /**
119
  * Add a single section
120
  *
121
+ * @param array $section
122
  */
123
  public function add_section( $section ) {
124
+
125
+ $this->settings_sections[] = $section;
126
+ return $this;
 
127
  }
128
 
129
  /**
130
  * Set settings fields
131
  *
132
+ * @param array $fields settings fields array
133
  */
134
  public function set_fields( $fields ) {
135
+
136
+ $fields = apply_filters( $this->settings['prefix'] . '_add_settings_fields', $fields );
137
+ $this->settings_fields = $fields;
138
+ return $this;
 
139
  }
140
 
141
  /**
142
  * Add a single field
143
  *
144
+ * @param array $section
145
+ * @param array $field
146
  */
147
  public function add_field( $section, $field ) {
148
+
149
+ $defaults = array(
150
+ 'name' => '',
151
+ 'label' => '',
152
+ 'desc' => '',
153
+ 'type' => 'text',
154
+ );
155
 
156
+ $args = wp_parse_args( $field, $defaults );
157
+ $this->settings_fields[$section][] = $args;
158
+ return $this;
 
 
 
 
 
 
 
 
159
  }
160
 
161
  /**
162
  * Add a single section
163
  *
164
+ * @param array $section
165
  */
166
  public function add_sidebar( $sidebar = array() ) {
167
+
168
+ $sidebar = apply_filters( $this->settings['prefix'] . '_add_settings_sidebar', $sidebar );
169
+ if ( !empty( $sidebar ) ) {
170
+ $this->settings_sidebars[] = $sidebar;
171
+ }
172
  }
173
 
174
  /**
180
  * registers them to WordPress and ready for use.
181
  */
182
  public function admin_init() {
183
+
184
+ //register settings sections
185
+ foreach ( $this->settings_sections as $section ) {
186
+ if ( false == get_option( $section['id'] ) && ( isset( $section['option'] ) && false !== $section['option'] ) ) {
187
+ add_option( $section['id'] );
188
+ }
189
+
190
+ add_settings_section( $section['id'], $section['title'], '__return_false', $section['id'] );
191
+ }
192
+
193
+ //register settings fields
194
+ foreach ( $this->settings_fields as $section => $field ) {
195
+ foreach ( $field as $option ) {
196
+
197
+ $type = isset( $option['type'] ) ? $option['type'] : 'text';
198
+
199
+ $args = array(
200
+ 'id' => $option['name'],
201
+ 'desc' => isset( $option['desc'] ) ? $option['desc'] : '',
202
+ 'name' => $option['label'],
203
+ 'section' => $section,
204
+ 'size' => isset( $option['size'] ) ? $option['size'] : null,
205
+ 'options' => isset( $option['options'] ) ? $option['options'] : '',
206
+ 'default' => isset( $option['default'] ) ? $option['default'] : '',
207
+ 'sanitize' => isset( $option['sanitize'] ) ? $option['sanitize'] : '',
208
+ 'class' => isset( $option['class'] ) ? $option['class'] : $this,
209
+ );
210
+ $args = wp_parse_args( $args, $option );
211
+
212
+ add_settings_field( $section . '[' . $option['name'] . ']', $option['label'], array( $args['class'], 'callback_' . $type ), $section, $section, $args );
213
+ }
214
+ }
215
+
216
+ // creates our settings in the options table
217
+ foreach ( $this->settings_sections as $section ) {
218
+ register_setting( $section['id'], $section['id'], array( $this, 'sanitize_options' ) );
219
+ }
 
 
 
220
  }
221
 
222
  /**
223
  * Displays a text field for a settings field
224
  *
225
+ * @param array $args settings field args
226
+ * @updated 2.0.2
 
227
  */
228
  function callback_text( $args ) {
229
 
230
+ $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
231
+ $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
232
+ $type = isset( $args['type'] ) && !is_null( $args['type'] ) ? $args['type'] : 'text';
233
+
234
+ $html = sprintf( '<input type="%1$s" class="%2$s-text" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s">', $type, $size, $args['section'], $args['id'], $value );
235
+ $html .= !empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
236
+
237
+ echo $html;
238
  }
239
 
240
  /**
241
  * Displays a text field for a settings field
242
  *
243
+ * @param array $args settings field args
244
+ * @since 2.0.2
 
245
  */
246
  function callback_text_number( $args ) {
247
+
248
+ $args['type'] = 'number';
249
+ $this->callback_text( $args );
250
  }
251
 
252
  /**
253
  * Displays a text field for a settings field
254
  *
255
+ * @param array $args settings field args
256
  */
257
  function callback_text_array( $args ) {
258
+
259
+ $value = $this->get_option( $args['id'], $args['section'], $args['default'] );
260
+ $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
261
+
262
+ $html = '<ul style="margin-top:0">';
263
+
264
+ if ( is_array( $value ) ) {
265
+ foreach ( $value as $key => $val ) {
266
+ $html .= '<li>';
267
+ $html .= sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s][]" value="%4$s" data-key="%5$s">', $size, $args['section'], $args['id'], esc_attr( $val ), $key );
268
+ $html .= sprintf( '<a href="#" class="button dodelete-%1$s[%2$s]">-</a>', $args['section'], $args['id'] );
269
+ $html .= '</li>';
270
+ }
271
+ }
272
+ else {
273
+ $html .= '<li>';
274
+ $html .= sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s][]" value="%4$s" data-key="0" data-array="false">', $size, $args['section'], $args['id'], esc_attr( $value ) );
275
+ $html .= sprintf( '<a href="#" class="button dodelete-%1$s[%2$s]">-</a>', $args['section'], $args['id'] );
276
+ $html .= '</li>';
277
+ }
278
+
279
+ $html .= '</ul>';
280
+ $html .= sprintf( '<a href="#" class="button docopy-%1$s[%2$s]">+</a>', $args['section'], $args['id'] );
281
+
282
+ $html .= !empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
283
+
284
+ echo $html;
285
+ }
286
+
287
+ /**
288
+ * Displays a text field for a settings field
289
+ *
290
+ * @param array $args settings field args
291
+ */
292
  function callback_colorpicker( $args ) {
293
+
294
+ $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
295
+ $check = esc_attr( $this->get_option( $args['id'] . '_checkbox', $args['section'], $args['default'] ) );
296
+ $opacity = esc_attr( $this->get_option( $args['id'] . '_opacity', $args['section'], $args['default'] ) );
297
+ $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'small';
298
+ $options = array( '1', '0.9', '0.8', '0.7', '0.6', '0.5', '0.4', '0.3', '0.2', '0.1', '0', );
299
+ $class = 'on' != $check ? ' hidden' : '';
300
+
301
+ /* Localize the array */
302
+ $this->localize_array['callback_colorpicker'][] = array( 'id' => $args['id'], 'section' => $args['section'] );
303
+
304
+ /* Color */
305
+ $html = '<div class="cl-colorpicker-wrap">';
306
+ $html .= sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s" style="float:left">', $size, $args['section'], $args['id'], $value );
307
+
308
+ /* Allow Opacity */
309
+ $html .= '<div class="checkbox-wrap">';
310
+ $html .= sprintf( '<input type="hidden" name="%1$s[%2$s]" value="off" >', $args['section'], $args['id'] . '_checkbox' );
311
+ $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s]" name="%1$s[%2$s]" value="on"%4$s >', $args['section'], $args['id'] . '_checkbox', $check, checked( $check, 'on', false ) );
312
+ $html .= sprintf( __( '<label for="%1$s[%2$s]">Opacity</label>', $this->settings['domain'] ), $args['section'], $args['id'] . '_checkbox' );
313
+ $html .= '</div>';
314
+
315
+ /* Opacity */
316
+ $html .= sprintf( '<select class="%1$s%4$s" name="%2$s[%3$s]" id="%2$s[%3$s]" style="margin-left:70px;">', $size, $args['section'], $args['id'] . '_opacity', $class );
317
+ foreach ( $options as $key ) {
318
+ $html .= sprintf( '<option value="%s"%s>%s</option>', $key, selected( $opacity, $key, false ), $key );
319
+ }
320
+ $html .= '</select>';
321
+ $html .= '<br class="clear">';
322
+ $html .= '</div>';
323
+
324
+ $html .= !empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
325
+
326
+ echo $html;
327
  }
328
 
329
  /**
330
  * Displays a checkbox for a settings field
331
  *
332
+ * @param array $args settings field args
333
  */
334
  function callback_checkbox( $args ) {
335
 
336
+ $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
337
+
338
+ $html = '<div class="checkbox-wrap">';
339
+ $html .= sprintf( '<input type="hidden" name="%1$s[%2$s]" value="off" >', $args['section'], $args['id'] );
340
+ $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s]" name="%1$s[%2$s]" value="on"%4$s >', $args['section'], $args['id'], $value, checked( $value, 'on', false ) );
341
+ $html .= sprintf( '<label for="%1$s[%2$s]"></label>', $args['section'], $args['id'] );
342
+ $html .= '</div>';
343
+
344
+ $html .= !empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
345
 
346
+ echo $html;
 
 
347
  }
348
 
349
  /**
350
  * Displays a multicheckbox a settings field
351
  *
352
+ * @param array $args settings field args
353
  */
354
  function callback_multicheck( $args ) {
355
 
356
+ $value = $this->get_option( $args['id'], $args['section'], $args['default'] );
357
+
358
+ $html = '<div class="checkbox-wrap">';
359
+ $html .= '<ul>';
360
+ foreach ( $args['options'] as $key => $label ) {
361
+ $checked = isset( $value[$key] ) ? $value[$key] : '0';
362
+ $html .= '<li>';
363
+ $html .= sprintf( '<input type="checkbox" class="checkbox" id="%1$s[%2$s][%3$s]" name="%1$s[%2$s][%3$s]" value="%3$s"%4$s >', $args['section'], $args['id'], $key, checked( $checked, $key, false ) );
364
+ $html .= sprintf( '<label for="%1$s[%2$s][%4$s]" title="%3$s"> %3$s</label>', $args['section'], $args['id'], $label, $key );
365
+ $html .= '</li>';
366
+ }
367
+ $html .= '</ul>';
368
+ $html .= '</div>';
369
+
370
+ $html .= !empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
371
+
372
+ echo $html;
373
  }
374
 
375
  /**
376
  * Displays a multicheckbox a settings field
377
  *
378
+ * @param array $args settings field args
379
  */
380
  function callback_radio( $args ) {
381
 
382
+ $value = $this->get_option( $args['id'], $args['section'], $args['default'] );
383
+
384
+ $html = '<div class="radio-wrap">';
385
+ $html .= '<ul>';
386
+ foreach ( $args['options'] as $key => $label ) {
387
+ $html .= '<li>';
388
+ $html .= sprintf( '<input type="radio" class="radio" id="%1$s[%2$s][%3$s]" name="%1$s[%2$s]" value="%3$s"%4$s >', $args['section'], $args['id'], $key, checked( $value, $key, false ) );
389
+ $html .= sprintf( '<label for="%1$s[%2$s][%4$s]" title="%3$s"> %3$s</label><br>', $args['section'], $args['id'], $label, $key );
390
+ $html .= '</li>';
391
+ }
392
+ $html .= '</ul>';
393
+ $html .= '</div>';
394
+
395
+ $html .= !empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
396
+
397
+ echo $html;
398
  }
399
 
400
  /**
401
  * Displays a selectbox for a settings field
402
  *
403
+ * @param array $args settings field args
404
  */
405
  function callback_select( $args ) {
406
 
407
+ $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
408
+ $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
409
+
410
+ /* Localize the array */
411
+ $this->localize_array['callback_select'][] = array( 'id' => $args['id'], 'section' => $args['section'] );
412
+
413
+ $html = sprintf( '<select class="%1$s" name="%2$s[%3$s]" id="%2$s[%3$s]">', $size, $args['section'], $args['id'] );
414
+ foreach ( $args['options'] as $key => $label ) {
415
+ $html .= sprintf( '<option value="%s"%s>%s</option>', $key, selected( $value, $key, false ), $label );
416
+ }
417
+ $html .= sprintf( '</select>' );
418
+
419
+ $html .= !empty( $args['desc'] ) ? sprintf( '<br><span class="description"> %s</span>', $args['desc'] ) : '';
420
 
421
+ echo $html;
 
 
 
 
 
 
 
 
 
 
 
422
  }
423
 
424
  /**
425
  * Displays a textarea for a settings field
426
  *
427
+ * @param array $args settings field args
428
  */
429
  function callback_textarea( $args ) {
430
 
431
+ $value = esc_textarea( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
432
+ $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
433
+ $extra = isset( $args['extra'] ) && is_array( $args['extra'] ) ? $args['extra'] : null;
434
+ $param = '';
435
+
436
+ if ( null !== $extra ) {
437
+ foreach( $extra as $p_key => $p_value ) {
438
+ $param .= $p_key . '="' . $p_value . '"';
439
+ }
440
+ }
441
+
442
+ $html = sprintf( '<textarea rows="5" cols="55" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]"%5$s>%4$s</textarea>', $size, $args['section'], $args['id'], stripslashes( $value ), $param );
443
+ $html .= !empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
444
+
445
+ echo $html;
446
  }
447
 
448
  /**
449
  * Displays a HTML for a settings field
450
  *
451
+ * @param array $args settings field args
452
  */
453
  function callback_html( $args ) {
454
+ static $counter = 0;
455
+
456
+ $html = isset( $args['desc'] ) ? sprintf( '<div class="section-%s-%d">%s</div><hr>', $args['section'], $counter, $args['desc'] ) : '';
457
+ $counter++;
458
+
459
+ echo $html;
460
  }
461
 
462
  /**
463
  * Displays raw HTML for a settings field
464
  *
465
+ * @param array $args settings field args
466
  */
467
  function callback_raw( $args ) {
468
+
469
+ $html = isset( $args['desc'] ) ? sprintf( '<div class="raw-html">%s</div>', $args['desc'] ) : '';
470
+
471
+ echo $html;
472
  }
473
 
474
  /**
475
  * Displays a rich text textarea for a settings field
476
  *
477
+ * @param array $args settings field args
478
  */
479
  function callback_wysiwyg( $args ) {
480
 
481
+ $value = wpautop( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
482
+ $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : '500px';
483
+
484
+ $html = sprintf( '<div style="width: %s">', $size );
485
+
486
+ ob_start();
487
+ wp_editor( $value, $args['section'] . '[' . $args['id'] . ']', array( 'teeny' => true, 'textarea_rows' => 10 ) );
488
+
489
+ $html .= ob_get_clean();
490
+ $html .= '</div>';
491
+
492
+ $html .= !empty( $args['desc'] ) ? sprintf( '<br><span class="description"> %s</span>', $args['desc'] ) : '';
493
+
494
+ echo $html;
 
 
 
495
  }
496
 
497
  /**
498
  * Displays a file upload field for a settings field
499
  *
500
+ * @param array $args settings field args
501
  */
502
  function callback_file( $args ) {
503
+ static $counter = 0;
504
+
505
+ $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
506
+ $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
507
+ $id = $args['section'] . '[' . $args['id'] . ']';
508
+
509
+ /* Localize the array */
510
+ $this->localize_array['callback_file'][] = array( 'id' => $args['id'], 'section' => $args['section'] );
511
+
512
+ $html = sprintf( '<input type="text" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s">', $size, $args['section'], $args['id'], $value );
513
+ $html .= '<input type="button" class="button '. $args['id'] .'-browse" id="'. $id .'_button" value="Browse" style="margin-left:5px" >';
514
+ $html .= '<input type="button" class="button '. $args['id'] .'-clear" id="'. $id .'_clear" value="Clear" style="margin-left:5px" >';
515
+
516
+ $html .= !empty( $args['desc'] ) ? sprintf( '<br><span class="description"> %s</span>', $args['desc'] ) : '';
517
+
518
+ /* Image */
519
+ $html .= '<div id="' . $id . '_preview" class="' . $id . '_preview">';
520
+ if ( $value != '' ) {
521
+ $check_image = preg_match( '/(^.*\.jpg|jpeg|png|gif|ico*)/i', $value );
522
+ if ( $check_image ) {
523
+ $html .= '<div class="img-wrapper">';
524
+ $html .= '<img src="' . $value . '" alt="" >';
525
+ $html .= '<a href="#" class="remove_file_button" rel="' . $id . '">Remove Image</a>';
526
+ $html .= '</div>';
527
+ }
528
+ }
529
+ $html .= '</div>';
530
+
531
+ echo $html;
532
  }
533
 
534
  /**
535
  * Displays a password field for a settings field
536
  *
537
+ * @param array $args settings field args
538
  */
539
  function callback_password( $args ) {
540
 
541
+ $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['default'] ) );
542
+ $size = isset( $args['size'] ) && !is_null( $args['size'] ) ? $args['size'] : 'regular';
543
+
544
+ $html = sprintf( '<input type="password" class="%1$s-text" id="%2$s[%3$s]" name="%2$s[%3$s]" value="%4$s">', $size, $args['section'], $args['id'], $value );
545
+ $html .= !empty( $args['desc'] ) ? sprintf( '<span class="description"> %s</span>', $args['desc'] ) : '';
546
+
547
+ echo $html;
548
  }
549
 
550
  /**
551
  * Sanitize callback for Settings API
552
+ */
553
  function sanitize_options( $options ) {
554
+
555
+ if ( is_null( $options ) )
556
+ return $options;
557
+
558
+ do_action( $this->settings['prefix'] . '_before_sanitize_options', $options );
559
+
560
+ foreach( $options as $option_slug => $option_value ) {
561
+ $sanitize_callback = $this->get_sanitize_callback( $option_slug );
562
+
563
+ // If callback is set, call it
564
+ if ( $sanitize_callback ) {
565
+ $options[ $option_slug ] = call_user_func( $sanitize_callback, $option_value );
566
+ continue;
567
+ }
568
+
569
+ // Treat everything that's not an array as a string
570
+ if ( !is_array( $option_value ) ) {
571
+ $options[ $option_slug ] = sanitize_text_field( $option_value );
572
+ continue;
573
+ }
574
+ }
575
+
576
+ do_action( $this->settings['prefix'] . '_after_sanitize_options', $options );
577
+
578
+ return $options;
579
+ }
580
+
 
581
  /**
582
  * Get sanitization callback for given option slug
583
+ *
584
  * @param string $slug option slug
585
+ *
586
  * @return mixed string or bool false
587
+ */
588
  function get_sanitize_callback( $slug = '' ) {
589
+
590
+ if ( empty( $slug ) )
591
+ return false;
592
+
593
+ // Iterate over registered fields and see if we can find proper callback
594
+ foreach( $this->settings_fields as $section => $options ) {
595
+ foreach ( $options as $option ) {
596
+ if ( $option['name'] != $slug )
597
+ continue;
598
+ // Return the callback name
599
+ return isset( $option['sanitize'] ) && is_callable( $option['sanitize'] ) ? $option['sanitize'] : false;
600
+ }
601
+ }
602
+ return false;
603
+ }
604
+
 
 
 
 
605
  /**
606
  * Outpute our settings HTML
607
  *
608
  */
609
+ public function settings_html() { ?>
610
+
611
+ <div class="cl-container">
612
+
613
+ <div class="cl-header">
614
+ <h3><?php _e( 'Custom Login', $this->settings['domain'] ); ?></h3>
615
+ <span><?php echo $this->settings['version']; ?></span>
616
+ <div>
617
+ <?php echo sprintf( __( 'A %s plugin', $this->settings['domain'] ), '<strong><a href="https://frosty.media/" target="_blank">Frosty Media</a></strong>' ); ?>
618
+ &nbsp;&nbsp;|&nbsp;&nbsp;<a href="https://twitter.com/Frosty_Media"><span class="dashicons dashicons-twitter"></span></a>
619
+ </div>
620
+ </div><!-- #cl-header -->
621
+
622
+ <div id="cl-notices">
623
+ <h2></h2>
624
+ </div><!-- #cl-text -->
625
+
626
+ <div id="cl-sticky">
627
+ <div class="wrap">
628
+ <div id="sticky-admin-notice">
629
+ <?php do_action( $this->settings['prefix'] . '_sticky_admin_notice' ); ?>
630
+ </div>
631
+ <div class="alignright">
632
+ <?php do_action( $this->settings['prefix'] . '_before_submit_button' ); ?>
633
+ <?php submit_button( __( 'Save Changes', $this->settings['domain'] ), 'primary', 'cl_save', false ); ?>
634
+ </div>
635
+ <br class="clear">
636
+ </div>
637
+ </div><!-- #cl-sticky -->
638
+
639
+ <div class="cl-sidebar">
640
+ <?php $this->show_navigation(); ?>
641
+ <?php do_action( $this->settings['prefix'] . '_settings_sidebars', $this->settings_sidebars ); ?>
642
+ </div><!-- #cl-header -->
643
+
644
+ <div class="cl-main">
645
+ <?php $this->show_forms(); ?>
646
+ </div><!-- #cl-header -->
647
+
648
+ </div><!-- #cl-wrapper -->
649
+ <?php
650
+ }
 
651
 
652
  /**
653
  * Show navigation as lists
655
  * Shows all the settings section labels as list items
656
  */
657
  private function show_navigation() {
658
+
659
  $html = '<ul class="cl-sections-menu">';
660
  foreach ( $this->settings_sections as $tab ) {
661
  $html .= sprintf( '<li><a href="%1$s">%2$s</a></li>', isset( $tab['href'] ) ? $tab['href'] : '#' . $tab['id'], $tab['title'] );
671
  * This function displays every sections in a different form
672
  */
673
  private function show_forms() {
674
+
675
+ foreach ( $this->settings_sections as $form ) {
676
+ $form_id = $form['id']; ?>
677
+ <div id="<?php echo $form_id; ?>" class="group">
678
+ <form action="options.php" id="<?php echo $form_id; ?>form" method="post" >
679
+ <?php do_action( $this->settings['prefix'] . '_form_top_' . $form_id, $form ); ?>
680
+ <?php settings_fields( $form_id ); ?>
681
+ <?php do_settings_sections( $form_id ); ?>
682
+ <?php do_action( $this->settings['prefix'] . '_form_bottom_' . $form_id, $form ); ?>
683
+ <?php if ( isset( $form['submit'] ) && $form['submit'] )
684
+ submit_button( sprintf( __( 'Save %s', $this->settings['domain'] ), $form['title'] ) ); ?>
685
+ </form>
686
+ </div><?php
687
+ # var_dump( $form_id, get_option( $form_id ) );
688
+ }
689
+ do_action( $this->settings['prefix'] . '_after_settings_sections_form' );
 
690
  }
691
 
692
  /**
695
  * This function displays every sections in a different form
696
  */
697
  public function get_form() {
698
+
699
+ check_ajax_referer( $this->settings['nonce'], 'nonce' );
700
+
701
+ if ( isset( $_POST['form_id'] ) ) {
702
+
703
+ $setting_form = array();
704
+ $setting_form['error'] = 1;
705
+
706
+ foreach ( $this->settings_sections as $form ) {
707
+ $form_id = $form['id'];
708
+ if ( str_replace( '#', '', $_POST['form_id'] ) !== $form_id ) {
709
+ continue;
710
+ }
711
+ ob_start(); ?><form action="options.php" id="<?php echo $form_id; ?>form" method="post" >
712
+ <?php do_action( $this->settings['prefix'] . '_form_top_' . $form['id'], $form ); ?>
713
+ <?php settings_fields( $form['id'] ); ?>
714
+ <?php do_settings_sections( $form['id'] ); ?>
715
+ <?php do_action( $this->settings['prefix'] . '_form_bottom_' . $form['id'], $form ); ?>
716
+ <?php submit_button( sprintf( __( 'Save %s Changes', $this->settings['domain'] ), $form_id ) ); ?>
717
+ </form><?php
718
+ $setting_form['error'] = 0;
719
+ $setting_form['html'] = ob_get_clean();
720
+ }
721
+
722
+ header('Content-Type: application/json');
723
+ echo json_encode( $setting_form );
724
+ die();
725
+ }
726
+ }
727
+
728
+ /**
729
+ * Create a potbox widget.
730
+ *
731
+ * @param string $id ID of the postbox.
732
+ * @param string $title Title of the postbox.
733
+ * @param string $content Content of the postbox.
734
+ */
735
+ public function postbox( $id, $title, $content, $group = false ) { ?>
736
+
737
+ <div class="metabox-holder<?php if ( $group ) echo ' group'; ?>" id="<?php echo $id; ?>">
738
+ <div class="postbox">
739
+ <h3><?php echo $title; ?></h3>
740
+ <div class="inside"><?php echo $content; ?></div>
741
+ </div>
742
+ </div><?php
743
+ }
744
+
745
+ /**
746
+ * Global 'active' checkbox notification.
747
+ *
748
+ * @ref http://codepen.io/pklada/pen/jEGwMB
749
+ */
750
+ function is_active_toggle() { ?>
751
+ <label class="tgl">
752
+ <span class="tgl_input"></span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
753
  <span class="tgl_body">
754
  <span class="tgl_switch"></span>
755
  <span class="tgl_track">
757
  <span class="tgl_bgd tgl_bgd-negative"></span>
758
  </span>
759
  </span>
760
+ </label><?php
761
+ }
762
+
763
+ /**
764
+ * Box with latest plugins from Extendd.com for sidebar
765
+ */
766
+ function about_the_author( $args ) {
767
+
768
+ $content = sprintf( '%s: <a href="https://wordpress.org/support/view/plugin-reviews/custom-login" class="star-rating" target="_blank">
769
  <i class="dashicons dashicons-star-filled"></i>
770
  <i class="dashicons dashicons-star-filled"></i>
771
  <i class="dashicons dashicons-star-filled"></i>
772
  <i class="dashicons dashicons-star-filled"></i>
773
  <i class="dashicons dashicons-star-filled"></i>
774
  </a>', _x( 'Rate', 'rate; as in rate this plugin', $this->settings['domain'] ) );
775
+
776
+ $content .= '<ul>';
777
+ $content .= sprintf( '<li>%s: <a href="https://austin.passy.co" target="_blank">Austin Passy</a></li>', _x( 'Author', 'the author of this plugin', $this->settings['domain'] ) );
778
+ $content .= sprintf( '<li>%s: <a href="https://twitter.com/TheFrosty" target="_blank">TheFrosty</a></li>', __( 'Twitter', $this->settings['domain'] ) );
779
+ $content .= '</ul>';
780
+
781
+ $content .= sprintf( __( '<small>If you have suggestions for a new add-on, feel free to open a support request on <a href="%s" target="_blank">GitHub</a>. Want regular updates? Follow me on <a href="%s" target="_blank">Twitter</a> or visit my <a href="%s" target="_blank">blog</a>.</small>' ),
782
+ 'https://github.com/thefrosty/custom-login/issues',
783
+ 'https://twitter.com/TheFrosty',
784
+ 'https://austin.passy.co'
785
+ );
786
+
787
+ $this->postbox( 'frosty-media-author', __( 'Custom Login', $this->settings['domain'] ), $content );
788
+ }
789
+
790
+ /**
791
+ * Box with latest plugins from Extendd.com for sidebar
792
+ */
793
+ function sidebar_feed( $args ) {
794
+
795
+ $defaults = array(
796
+ 'items' => 6,
797
+ 'feed' => 'https://frosty.media/feed/?post_type=plugin&plugin_tag=custom-login-extension',
798
+ );
799
+
800
+ $args = wp_parse_args( $args, $defaults );
801
+
802
+ $rss_items = CL_Common::fetch_rss_items( $args['items'], $args['feed'] );
803
+
804
+ $content = '<ul>';
805
+ if ( !$rss_items ) {
806
+ $content .= '<li>' . __( 'Error fetching feed', $this->settings['domain'] ) . '</li>';
807
+ }
808
+ else {
809
+ foreach ( $rss_items as $item ) {
810
+ $url = preg_replace( '/#.*/', '', esc_url( $item->get_permalink(), null, 'display' ) );
811
+ $content .= '<li>';
812
+ $content .= '<a href="' . $url . '?utm_source=wpadmin&utm_medium=sidebarwidget&utm_term=newsite&utm_campaign=' . $this->settings['prefix'] . '_settings-api" target="_blank">' . esc_html( $item->get_title() ) . '</a>';
813
+ $content .= '</li>';
814
+ }
815
+ }
816
+ $content .= '</ul>';
817
+
818
+ $this->postbox( 'custom-login-extensions', sprintf( __( 'Custom Login Extensions %s', $this->settings['domain'] ), '<small class="dashicons dashicons-external"></small>' ), $content );
819
+ }
820
+
821
+ /**
822
+ * Display Upgrade Notices
823
+ *
824
+ * @access private
825
+ * @since 3.0.3
826
+ * @return void
827
+ */
828
+ public function upgrade_notices() {
829
+
830
+ $show_upgrade_notice = false;
831
+
832
+ // Version < 2.0
833
+ if ( false !== get_option( 'custom_login_settings', false ) ) {
834
+ $show_upgrade_notice = true;
835
+ }
836
+
837
+ // Version > 2.0
838
+ if ( false !== get_option( 'custom_login', false ) ) {
839
+ $show_upgrade_notice = true;
840
+ }
841
+
842
+ if ( $show_upgrade_notice && ( '' === get_option( CUSTOM_LOGIN_OPTION . '_general', '' ) ) ) {
843
+ remove_action( 'admin_notice', array( CL_Settings_Upgrade::instance(), 'upgrade_notices' ) );
844
+ printf(
845
+ '<div class="error"><p>' . esc_html__( 'Custom Login has detected old settings. If you wish to use them please run %sthis%s script before making any changes below.', CUSTOM_LOGIN_DIRNAME ) . '</p></div>',
846
+ '<a href="' . esc_url( admin_url( 'options.php?page=custom-login-upgrades' ) ) . '">',
847
+ '</a>'
848
+ );
849
+ }
850
+ }
851
+
852
+ /**
853
+ * Box with latest plugins from Extendd.com for sidebar
854
+ */
855
+ public function sticky_admin_notice_social_links() {
856
+
857
+ $content = '<ul class="social">';
858
+ $content .= '<li><a href="https://www.facebook.com/FrostyMediaWP" target="_blank"><span class="dashicons dashicons-facebook"></span></a></li>';
859
+ $content .= '<li><a href="https://twitter.com/Frosty_Media" target="_blank"><span class="dashicons dashicons-twitter"></span></a></li>';
860
+ $content .= '<li><a href="https://plus.google.com/+FrostyMedia/" target="_blank"><span class="dashicons dashicons-googleplus"></span></a></li>';
861
+ $content .= '<li><a href="http://eepurl.com/bbj0bD" target="_blank"><span class="dashicons dashicons-email"></span></a></li>';
862
+ $content .= '</ul>';
863
+
864
+ echo $content;
865
+ }
866
+
867
  /**
868
  * Replace all square brackets with and underscore.
869
  *
870
+ * @param string $input
 
871
  * @return string
872
  */
873
+ private function replace_bracket_underscore( $input ) {
874
+ return preg_replace( '/[\[\]]/', '_', $input );
875
+ }
876
 
877
  /**
878
  * Get the value of a settings field
879
  *
880
+ * @param string $option settings field name
881
+ * @param string $section the section name this field belongs to
882
+ * @param string $default default text if it's not found
 
883
  * @return string
884
  */
885
+ function get_option( $option, $section, $default = '' ) {
886
+
887
+ $options = get_option( $section, array() );
888
+
889
+ if ( isset( $options[$option] ) ) {
890
+ return $options[$option];
891
+ }
892
+
893
+ return $default;
894
+ }
895
 
896
  }
includes/class-cl-settings-upgrades.php CHANGED
@@ -14,7 +14,7 @@ class CL_Settings_Upgrade {
14
 
15
  /** Singleton *************************************************************/
16
  private static $instance;
17
-
18
  protected $parent;
19
 
20
  /**
@@ -31,9 +31,9 @@ class CL_Settings_Upgrade {
31
  }
32
  return self::$instance;
33
  }
34
-
35
  private function actions() {
36
-
37
  add_action( 'admin_notices', array( $this, 'upgrade_notices' ) );
38
  add_action( 'admin_menu', array( $this, 'add_submenu_page' ) );
39
  add_action( 'wp_ajax_custom_login_trigger_upgrades', array( $this, 'trigger_upgrades' ) );
@@ -47,41 +47,41 @@ class CL_Settings_Upgrade {
47
  * @return void
48
  */
49
  public function upgrade_notices() {
50
-
51
  if ( isset( $_GET['page'] ) && $_GET['page'] == ( 'custom-login-upgrades' || 'custom-login' ) )
52
  return; // Don't show notices on the upgrades page
53
-
54
  $cl_version = get_option( CUSTOM_LOGIN_OPTION . '_version' );
55
-
56
  if ( ! $cl_version ) {
57
  // 2.0 is the first version to use this option so we must add it
58
  $cl_version = '2.0';
59
  }
60
-
61
  $cl_version = preg_replace( '/[^0-9.].*/', '', $cl_version );
62
-
63
  // Version less than 2.0 (settings exist)
64
  if ( false !== ( $old_settings = get_option( 'custom_login_settings', false ) ) ) {
65
-
66
  // New install
67
  if ( !$old_settings )
68
  return;
69
-
70
  if ( !empty( $old_settings ) && !empty( $old_settings['version'] ) )
71
  $cl_version = $old_settings['version'];
72
-
73
  // Versions less than 2.0
74
  if ( version_compare( $cl_version, '2.0', '<' ) ) {
75
  printf(
76
  '<div class="updated"><p>' . __( 'Custom Login needs to upgrade the settings, please click <a href="%s">here</a> to start the upgrade.', CUSTOM_LOGIN_DIRNAME ) . '</p></div>',
77
- esc_url( add_query_arg( array( 'ver' => '2.0' ), admin_url( 'options.php?page=custom-login-upgrades' ) ) )
78
  );
79
  }
80
  } // 2.0
81
-
82
  // Version less than 3.0 (settings exist)
83
  if ( false !== ( $old_settings = get_option( 'custom_login', false ) ) ) {
84
-
85
  // Versions less than 3.0
86
  if ( version_compare( $cl_version, '3.0', '<' ) ) {
87
  printf(
@@ -90,16 +90,16 @@ class CL_Settings_Upgrade {
90
  );
91
  }
92
  } // 3.0
93
-
94
  // Version less than 3.1
95
- if ( version_compare( CUSTOM_LOGIN_VERSION, '3.1', '<' ) ) {
96
  printf(
97
- '<div class="notice is-dismissible"><p>' . __( 'Custom Login needs to upgrade the database, please click <a href="%s">here</a> to start the upgrade.', CUSTOM_LOGIN_DIRNAME ) . '</p></div>',
98
- esc_url( add_query_arg( array( 'ver' => '3.1' ), admin_url( 'options.php?page=custom-login-upgrades' ) ) )
99
  );
100
  } // 3.1
101
  }
102
-
103
  /**
104
  * Add Submenu Upgrade page
105
  *
@@ -107,8 +107,8 @@ class CL_Settings_Upgrade {
107
  * @since 1.0
108
  * @return void
109
  */
110
- public function add_submenu_page() {
111
-
112
  add_submenu_page(
113
  null,
114
  __( 'Custom Login Upgrades', CUSTOM_LOGIN_DIRNAME ),
@@ -154,7 +154,7 @@ class CL_Settings_Upgrade {
154
  </div>
155
  <?php
156
  }
157
-
158
  /**
159
  * Triggers all upgrade functions
160
  *
@@ -164,57 +164,57 @@ class CL_Settings_Upgrade {
164
  * @since 2.0
165
  */
166
  public function trigger_upgrades() {
167
-
168
  check_ajax_referer( 'CL_Settings_Upgrade' . basename( __FILE__ ), 'nonce' );
169
-
170
  $cl_version = get_option( CUSTOM_LOGIN_OPTION . '_version' );
171
-
172
  if ( ! $cl_version ) {
173
  // 2.0 is the first version to use this option so we must add it
174
  $cl_version = '2.0';
175
  add_option( CUSTOM_LOGIN_OPTION . '_version', $cl_version );
176
  }
177
-
178
  // Version less than 2.0
179
  if ( false !== ( $old_settings = get_option( 'custom_login_settings', false ) ) ) {
180
-
181
  $cl_version = '1.0';
182
-
183
  if ( !empty( $old_settings ) && !empty( $old_settings['version'] ) )
184
  $cl_version = $old_settings['version'];
185
-
186
  if ( version_compare( $cl_version, '2.0', '<' ) ) {
187
  $this->cl_v20_upgrades();
188
  }
189
-
190
  } // 2.0
191
-
192
  // Version less than 3.0
193
  if ( false !== ( $old_settings = get_option( 'custom_login', false ) ) ) {
194
-
195
  $cl_version = '2.0';
196
-
197
  if ( !empty( $old_settings ) && !empty( $old_settings['version'] ) )
198
  $cl_version = $old_settings['version'];
199
-
200
  if ( version_compare( $cl_version, '3.0', '<' ) ) {
201
  $this->cl_v30_upgrades();
202
  }
203
-
204
  } // 3.0
205
-
206
  // Version less than 3.1
207
  if ( version_compare( $cl_version, '3.1', '<' ) ) {
208
  $this->cl_v31_upgrades();
209
  } // 3.1
210
-
211
  update_option( CUSTOM_LOGIN_OPTION . '_version', CUSTOM_LOGIN_VERSION );
212
-
213
  if ( DOING_AJAX ) {
214
  die( 'complete' );
215
  }
216
  }
217
-
218
  /**
219
  * Upgrade routine for v2.0
220
  *
@@ -223,10 +223,10 @@ class CL_Settings_Upgrade {
223
  * @return void
224
  */
225
  private function cl_v20_upgrades() {
226
-
227
  $old_settings = get_option( 'custom_login_settings' );
228
  $new_settings = get_option( 'custom_login', array() );
229
-
230
  $new_settings['version'] = $this->parent->version;
231
  $new_settings['active'] = true === $old_settings['custom'] ? 'on' : 'off';
232
  $new_settings['html_background_color'] = CL_Scripts_Styles::is_rgba( $old_settings['html_background_color'] ) ? CL_Scripts_Styles::rgba2hex( $old_settings['html_background_color'] ) : $old_settings['html_background_color'];
@@ -275,12 +275,12 @@ class CL_Settings_Upgrade {
275
  $new_settings['custom_css'] = wp_filter_nohtml_kses( $old_settings['custom_css'] );
276
  $new_settings['custom_html'] = wp_kses_post( $old_settings['custom_html'] );
277
  $new_settings['custom_jquery'] = wp_specialchars_decode( stripslashes( $old_settings['custom_jquery'] ), 1, 0, 1 );
278
-
279
  update_option( 'custom_login', $new_settings );
280
  delete_option( 'custom_login_settings' );
281
  return true;
282
  }
283
-
284
  /**
285
  * Upgrade routine for v3.0
286
  *
@@ -289,11 +289,11 @@ class CL_Settings_Upgrade {
289
  * @return void
290
  */
291
  private function cl_v30_upgrades() {
292
-
293
  $old_settings = get_option( 'custom_login', array() );
294
  $design_settings = get_option( CUSTOM_LOGIN_OPTION . '_design', array() );
295
  $general_settings = get_option( CUSTOM_LOGIN_OPTION . '_general', array() );
296
-
297
  /** Design */
298
  $design_settings['html_background_color'] = $this->get_old_setting( $old_settings, 'html_background_color' );
299
  $design_settings['html_background_color_checkbox'] = $this->get_old_setting( $old_settings, 'html_background_color_checkbox' );
@@ -302,7 +302,7 @@ class CL_Settings_Upgrade {
302
  $design_settings['html_background_position'] = $this->get_old_setting( $old_settings, 'html_background_position' );
303
  $design_settings['html_background_repeat'] = $this->get_old_setting( $old_settings, 'html_background_repeat' );
304
  $design_settings['html_background_size'] = $this->get_old_setting( $old_settings, 'html_background_size' );
305
-
306
  $design_settings['logo_force_form_max_width'] = 'off'; // New
307
  $design_settings['hide_wp_logo'] = $this->get_old_setting( $old_settings, 'hide_wp_logo' );
308
  $design_settings['logo_background_url'] = $this->get_old_setting( $old_settings, 'logo_background_url' );
@@ -311,9 +311,9 @@ class CL_Settings_Upgrade {
311
  $design_settings['logo_background_position'] = $this->get_old_setting( $old_settings, 'logo_background_position' );
312
  $design_settings['logo_background_repeat'] = $this->get_old_setting( $old_settings, 'logo_background_repeat' );
313
  $design_settings['logo_background_size'] = $this->get_old_setting( $old_settings, 'logo_background_size' );
314
-
315
  $design_settings['login_form_width'] = ''; // New
316
-
317
  $design_settings['login_form_background_color'] = $this->get_old_setting( $old_settings, 'login_form_background_color' );
318
  $design_settings['login_form_background_color_checkbox'] = $this->get_old_setting( $old_settings, 'login_form_background_color_checkbox' );
319
  $design_settings['login_form_background_color_opacity'] = $this->get_old_setting( $old_settings, 'login_form_background_color_opacity' );
@@ -321,7 +321,7 @@ class CL_Settings_Upgrade {
321
  $design_settings['login_form_background_position'] = $this->get_old_setting( $old_settings, 'login_form_background_position' );
322
  $design_settings['login_form_background_repeat'] = $this->get_old_setting( $old_settings, 'login_form_background_repeat' );
323
  $design_settings['login_form_background_size'] = $this->get_old_setting( $old_settings, 'login_form_background_size' );
324
-
325
  $design_settings['login_form_border_radius'] = $this->get_old_setting( $old_settings, 'login_form_border_radius' );
326
  $design_settings['login_form_border_size'] = $this->get_old_setting( $old_settings, 'login_form_border_size' );
327
  $design_settings['login_form_border_color'] = $this->get_old_setting( $old_settings, 'login_form_border_color' );
@@ -331,11 +331,11 @@ class CL_Settings_Upgrade {
331
  $design_settings['login_form_box_shadow_color'] = $this->get_old_setting( $old_settings, 'login_form_box_shadow_color' );
332
  $design_settings['login_form_box_shadow_color_checkbox'] = $this->get_old_setting( $old_settings, 'login_form_box_shadow_color_checkbox' );
333
  $design_settings['login_form_box_shadow_color_opacity'] = $this->get_old_setting( $old_settings, 'login_form_box_shadow_color_opacity' );
334
-
335
  $design_settings['label_color'] = $this->get_old_setting( $old_settings, 'label_color' );
336
  $design_settings['label_color_checkbox'] = $this->get_old_setting( $old_settings, 'label_color_checkbox' );
337
  $design_settings['label_color_opacity'] = $this->get_old_setting( $old_settings, 'label_color_opacity' );
338
-
339
  $design_settings['nav_color'] = $this->get_old_setting( $old_settings, 'nav_color' );
340
  $design_settings['nav_color_checkbox'] = $this->get_old_setting( $old_settings, 'nav_color_checkbox' );
341
  $design_settings['nav_color_opacity'] = $this->get_old_setting( $old_settings, 'nav_color_opacity' );
@@ -348,12 +348,12 @@ class CL_Settings_Upgrade {
348
  $design_settings['nav_text_shadow_hover_color'] = $this->get_old_setting( $old_settings, 'nav_text_shadow_hover_color' );
349
  $design_settings['nav_text_shadow_hover_color_checkbox'] = $this->get_old_setting( $old_settings, 'nav_text_shadow_hover_color_checkbox' );
350
  $design_settings['nav_text_shadow_hover_color_opacity'] = $this->get_old_setting( $old_settings, 'nav_text_shadow_hover_color_opacity' );
351
-
352
  $design_settings['custom_css'] = wp_filter_nohtml_kses( $this->get_old_setting( $old_settings, 'custom_css' ) );
353
  $design_settings['animate.css'] = 'off'; // New
354
  $design_settings['custom_html'] = wp_kses_post( $this->get_old_setting( $old_settings, 'custom_html' ) );
355
  $design_settings['custom_jquery'] = wp_specialchars_decode( stripslashes( $this->get_old_setting( $old_settings, 'custom_jquery' ) ), 1, 0, 1 );
356
-
357
  /** General */
358
  $general_settings['active'] = $this->get_old_setting( $old_settings, 'active', 'on' );
359
  $general_settings['capability'] = 'manage_options'; // New
@@ -361,14 +361,14 @@ class CL_Settings_Upgrade {
361
  $general_settings['admin_notices'] = 'off'; // New
362
  $general_settings['wp_shake_js'] = 'off'; // New
363
  $general_settings['remove_login_css'] = 'off'; // New
364
- $general_settings['lostpassword_text'] = 'off'; // New
365
-
366
  update_option( CUSTOM_LOGIN_OPTION . '_design', $design_settings );
367
  update_option( CUSTOM_LOGIN_OPTION . '_general', $general_settings );
368
  delete_option( 'custom_login' );
369
  return true;
370
  }
371
-
372
  /**
373
  * Upgrade routine for v3.1
374
  *
@@ -377,36 +377,36 @@ class CL_Settings_Upgrade {
377
  * @return void
378
  */
379
  private function cl_v31_upgrades() {
380
-
381
  $general_settings = get_option( CUSTOM_LOGIN_OPTION . '_general', array() );
382
-
383
- // Remove old settings
384
  unset( $general_settings['allow_password_reset'] );
385
  unset( $general_settings['auth_timeout'] );
386
  unset( $general_settings['auth_timeout_remember'] );
387
-
388
  // Leave
389
  $general_settings['active'] = $this->get_old_setting( $general_settings, 'active', 'on' );
390
-
391
  // New settings
392
  $general_settings['dashboard_widget'] = 'off';
393
-
394
  update_option( CUSTOM_LOGIN_OPTION . '_general', $general_settings );
395
-
396
  // Update tracking options name
397
  update_option( CUSTOM_LOGIN_OPTION . '_tracking_last_send', get_option( 'cl_tracking_last_send' ) );
398
  update_option( CUSTOM_LOGIN_OPTION . '_tracking_notice', get_option( 'cl_tracking_notice' ) );
399
  delete_option( 'cl_tracking_last_send' );
400
  delete_option( 'cl_tracking_notice' );
401
-
402
  delete_option( CUSTOM_LOGIN_OPTION . '_announcement_message' );
403
-
404
  /** Cleanup Cron Events */
405
  wp_clear_scheduled_hook( 'cl_daily_scheduled_events' );
406
  wp_clear_scheduled_hook( 'cl_weekly_scheduled_events' );
407
  return true;
408
  }
409
-
410
  /**
411
  * Helper function to check if option isset
412
  *
@@ -415,12 +415,12 @@ class CL_Settings_Upgrade {
415
  private function get_old_setting( $setting = array(), $option = null, $default = '' ) {
416
  if ( is_null( $option ) )
417
  return $default;
418
-
419
  if ( isset( $setting[$option] ) )
420
  return $setting[$option];
421
-
422
  return $default;
423
  }
424
-
425
  }
426
- CL_Settings_Upgrade::instance();
14
 
15
  /** Singleton *************************************************************/
16
  private static $instance;
17
+
18
  protected $parent;
19
 
20
  /**
31
  }
32
  return self::$instance;
33
  }
34
+
35
  private function actions() {
36
+
37
  add_action( 'admin_notices', array( $this, 'upgrade_notices' ) );
38
  add_action( 'admin_menu', array( $this, 'add_submenu_page' ) );
39
  add_action( 'wp_ajax_custom_login_trigger_upgrades', array( $this, 'trigger_upgrades' ) );
47
  * @return void
48
  */
49
  public function upgrade_notices() {
50
+
51
  if ( isset( $_GET['page'] ) && $_GET['page'] == ( 'custom-login-upgrades' || 'custom-login' ) )
52
  return; // Don't show notices on the upgrades page
53
+
54
  $cl_version = get_option( CUSTOM_LOGIN_OPTION . '_version' );
55
+
56
  if ( ! $cl_version ) {
57
  // 2.0 is the first version to use this option so we must add it
58
  $cl_version = '2.0';
59
  }
60
+
61
  $cl_version = preg_replace( '/[^0-9.].*/', '', $cl_version );
62
+
63
  // Version less than 2.0 (settings exist)
64
  if ( false !== ( $old_settings = get_option( 'custom_login_settings', false ) ) ) {
65
+
66
  // New install
67
  if ( !$old_settings )
68
  return;
69
+
70
  if ( !empty( $old_settings ) && !empty( $old_settings['version'] ) )
71
  $cl_version = $old_settings['version'];
72
+
73
  // Versions less than 2.0
74
  if ( version_compare( $cl_version, '2.0', '<' ) ) {
75
  printf(
76
  '<div class="updated"><p>' . __( 'Custom Login needs to upgrade the settings, please click <a href="%s">here</a> to start the upgrade.', CUSTOM_LOGIN_DIRNAME ) . '</p></div>',
77
+ add_query_arg( array( 'ver' => '2.0' ), admin_url( 'options.php?page=custom-login-upgrades' ) )
78
  );
79
  }
80
  } // 2.0
81
+
82
  // Version less than 3.0 (settings exist)
83
  if ( false !== ( $old_settings = get_option( 'custom_login', false ) ) ) {
84
+
85
  // Versions less than 3.0
86
  if ( version_compare( $cl_version, '3.0', '<' ) ) {
87
  printf(
90
  );
91
  }
92
  } // 3.0
93
+
94
  // Version less than 3.1
95
+ if ( version_compare( $cl_version, '3.1', '<' ) ) {
96
  printf(
97
+ '<div class="updated"><p>' . __( 'Custom Login needs to upgrade the database, please click <a href="%s">here</a> to start the upgrade.', CUSTOM_LOGIN_DIRNAME ) . '</p></div>',
98
+ add_query_arg( array( 'ver' => '3.1' ), admin_url( 'options.php?page=custom-login-upgrades' ) )
99
  );
100
  } // 3.1
101
  }
102
+
103
  /**
104
  * Add Submenu Upgrade page
105
  *
107
  * @since 1.0
108
  * @return void
109
  */
110
+ public function add_submenu_page() {
111
+
112
  add_submenu_page(
113
  null,
114
  __( 'Custom Login Upgrades', CUSTOM_LOGIN_DIRNAME ),
154
  </div>
155
  <?php
156
  }
157
+
158
  /**
159
  * Triggers all upgrade functions
160
  *
164
  * @since 2.0
165
  */
166
  public function trigger_upgrades() {
167
+
168
  check_ajax_referer( 'CL_Settings_Upgrade' . basename( __FILE__ ), 'nonce' );
169
+
170
  $cl_version = get_option( CUSTOM_LOGIN_OPTION . '_version' );
171
+
172
  if ( ! $cl_version ) {
173
  // 2.0 is the first version to use this option so we must add it
174
  $cl_version = '2.0';
175
  add_option( CUSTOM_LOGIN_OPTION . '_version', $cl_version );
176
  }
177
+
178
  // Version less than 2.0
179
  if ( false !== ( $old_settings = get_option( 'custom_login_settings', false ) ) ) {
180
+
181
  $cl_version = '1.0';
182
+
183
  if ( !empty( $old_settings ) && !empty( $old_settings['version'] ) )
184
  $cl_version = $old_settings['version'];
185
+
186
  if ( version_compare( $cl_version, '2.0', '<' ) ) {
187
  $this->cl_v20_upgrades();
188
  }
189
+
190
  } // 2.0
191
+
192
  // Version less than 3.0
193
  if ( false !== ( $old_settings = get_option( 'custom_login', false ) ) ) {
194
+
195
  $cl_version = '2.0';
196
+
197
  if ( !empty( $old_settings ) && !empty( $old_settings['version'] ) )
198
  $cl_version = $old_settings['version'];
199
+
200
  if ( version_compare( $cl_version, '3.0', '<' ) ) {
201
  $this->cl_v30_upgrades();
202
  }
203
+
204
  } // 3.0
205
+
206
  // Version less than 3.1
207
  if ( version_compare( $cl_version, '3.1', '<' ) ) {
208
  $this->cl_v31_upgrades();
209
  } // 3.1
210
+
211
  update_option( CUSTOM_LOGIN_OPTION . '_version', CUSTOM_LOGIN_VERSION );
212
+
213
  if ( DOING_AJAX ) {
214
  die( 'complete' );
215
  }
216
  }
217
+
218
  /**
219
  * Upgrade routine for v2.0
220
  *
223
  * @return void
224
  */
225
  private function cl_v20_upgrades() {
226
+
227
  $old_settings = get_option( 'custom_login_settings' );
228
  $new_settings = get_option( 'custom_login', array() );
229
+
230
  $new_settings['version'] = $this->parent->version;
231
  $new_settings['active'] = true === $old_settings['custom'] ? 'on' : 'off';
232
  $new_settings['html_background_color'] = CL_Scripts_Styles::is_rgba( $old_settings['html_background_color'] ) ? CL_Scripts_Styles::rgba2hex( $old_settings['html_background_color'] ) : $old_settings['html_background_color'];
275
  $new_settings['custom_css'] = wp_filter_nohtml_kses( $old_settings['custom_css'] );
276
  $new_settings['custom_html'] = wp_kses_post( $old_settings['custom_html'] );
277
  $new_settings['custom_jquery'] = wp_specialchars_decode( stripslashes( $old_settings['custom_jquery'] ), 1, 0, 1 );
278
+
279
  update_option( 'custom_login', $new_settings );
280
  delete_option( 'custom_login_settings' );
281
  return true;
282
  }
283
+
284
  /**
285
  * Upgrade routine for v3.0
286
  *
289
  * @return void
290
  */
291
  private function cl_v30_upgrades() {
292
+
293
  $old_settings = get_option( 'custom_login', array() );
294
  $design_settings = get_option( CUSTOM_LOGIN_OPTION . '_design', array() );
295
  $general_settings = get_option( CUSTOM_LOGIN_OPTION . '_general', array() );
296
+
297
  /** Design */
298
  $design_settings['html_background_color'] = $this->get_old_setting( $old_settings, 'html_background_color' );
299
  $design_settings['html_background_color_checkbox'] = $this->get_old_setting( $old_settings, 'html_background_color_checkbox' );
302
  $design_settings['html_background_position'] = $this->get_old_setting( $old_settings, 'html_background_position' );
303
  $design_settings['html_background_repeat'] = $this->get_old_setting( $old_settings, 'html_background_repeat' );
304
  $design_settings['html_background_size'] = $this->get_old_setting( $old_settings, 'html_background_size' );
305
+
306
  $design_settings['logo_force_form_max_width'] = 'off'; // New
307
  $design_settings['hide_wp_logo'] = $this->get_old_setting( $old_settings, 'hide_wp_logo' );
308
  $design_settings['logo_background_url'] = $this->get_old_setting( $old_settings, 'logo_background_url' );
311
  $design_settings['logo_background_position'] = $this->get_old_setting( $old_settings, 'logo_background_position' );
312
  $design_settings['logo_background_repeat'] = $this->get_old_setting( $old_settings, 'logo_background_repeat' );
313
  $design_settings['logo_background_size'] = $this->get_old_setting( $old_settings, 'logo_background_size' );
314
+
315
  $design_settings['login_form_width'] = ''; // New
316
+
317
  $design_settings['login_form_background_color'] = $this->get_old_setting( $old_settings, 'login_form_background_color' );
318
  $design_settings['login_form_background_color_checkbox'] = $this->get_old_setting( $old_settings, 'login_form_background_color_checkbox' );
319
  $design_settings['login_form_background_color_opacity'] = $this->get_old_setting( $old_settings, 'login_form_background_color_opacity' );
321
  $design_settings['login_form_background_position'] = $this->get_old_setting( $old_settings, 'login_form_background_position' );
322
  $design_settings['login_form_background_repeat'] = $this->get_old_setting( $old_settings, 'login_form_background_repeat' );
323
  $design_settings['login_form_background_size'] = $this->get_old_setting( $old_settings, 'login_form_background_size' );
324
+
325
  $design_settings['login_form_border_radius'] = $this->get_old_setting( $old_settings, 'login_form_border_radius' );
326
  $design_settings['login_form_border_size'] = $this->get_old_setting( $old_settings, 'login_form_border_size' );
327
  $design_settings['login_form_border_color'] = $this->get_old_setting( $old_settings, 'login_form_border_color' );
331
  $design_settings['login_form_box_shadow_color'] = $this->get_old_setting( $old_settings, 'login_form_box_shadow_color' );
332
  $design_settings['login_form_box_shadow_color_checkbox'] = $this->get_old_setting( $old_settings, 'login_form_box_shadow_color_checkbox' );
333
  $design_settings['login_form_box_shadow_color_opacity'] = $this->get_old_setting( $old_settings, 'login_form_box_shadow_color_opacity' );
334
+
335
  $design_settings['label_color'] = $this->get_old_setting( $old_settings, 'label_color' );
336
  $design_settings['label_color_checkbox'] = $this->get_old_setting( $old_settings, 'label_color_checkbox' );
337
  $design_settings['label_color_opacity'] = $this->get_old_setting( $old_settings, 'label_color_opacity' );
338
+
339
  $design_settings['nav_color'] = $this->get_old_setting( $old_settings, 'nav_color' );
340
  $design_settings['nav_color_checkbox'] = $this->get_old_setting( $old_settings, 'nav_color_checkbox' );
341
  $design_settings['nav_color_opacity'] = $this->get_old_setting( $old_settings, 'nav_color_opacity' );
348
  $design_settings['nav_text_shadow_hover_color'] = $this->get_old_setting( $old_settings, 'nav_text_shadow_hover_color' );
349
  $design_settings['nav_text_shadow_hover_color_checkbox'] = $this->get_old_setting( $old_settings, 'nav_text_shadow_hover_color_checkbox' );
350
  $design_settings['nav_text_shadow_hover_color_opacity'] = $this->get_old_setting( $old_settings, 'nav_text_shadow_hover_color_opacity' );
351
+
352
  $design_settings['custom_css'] = wp_filter_nohtml_kses( $this->get_old_setting( $old_settings, 'custom_css' ) );
353
  $design_settings['animate.css'] = 'off'; // New
354
  $design_settings['custom_html'] = wp_kses_post( $this->get_old_setting( $old_settings, 'custom_html' ) );
355
  $design_settings['custom_jquery'] = wp_specialchars_decode( stripslashes( $this->get_old_setting( $old_settings, 'custom_jquery' ) ), 1, 0, 1 );
356
+
357
  /** General */
358
  $general_settings['active'] = $this->get_old_setting( $old_settings, 'active', 'on' );
359
  $general_settings['capability'] = 'manage_options'; // New
361
  $general_settings['admin_notices'] = 'off'; // New
362
  $general_settings['wp_shake_js'] = 'off'; // New
363
  $general_settings['remove_login_css'] = 'off'; // New
364
+ $general_settings['lostpassword_text'] = 'off'; // New
365
+
366
  update_option( CUSTOM_LOGIN_OPTION . '_design', $design_settings );
367
  update_option( CUSTOM_LOGIN_OPTION . '_general', $general_settings );
368
  delete_option( 'custom_login' );
369
  return true;
370
  }
371
+
372
  /**
373
  * Upgrade routine for v3.1
374
  *
377
  * @return void
378
  */
379
  private function cl_v31_upgrades() {
380
+
381
  $general_settings = get_option( CUSTOM_LOGIN_OPTION . '_general', array() );
382
+
383
+ // Remove old settings
384
  unset( $general_settings['allow_password_reset'] );
385
  unset( $general_settings['auth_timeout'] );
386
  unset( $general_settings['auth_timeout_remember'] );
387
+
388
  // Leave
389
  $general_settings['active'] = $this->get_old_setting( $general_settings, 'active', 'on' );
390
+
391
  // New settings
392
  $general_settings['dashboard_widget'] = 'off';
393
+
394
  update_option( CUSTOM_LOGIN_OPTION . '_general', $general_settings );
395
+
396
  // Update tracking options name
397
  update_option( CUSTOM_LOGIN_OPTION . '_tracking_last_send', get_option( 'cl_tracking_last_send' ) );
398
  update_option( CUSTOM_LOGIN_OPTION . '_tracking_notice', get_option( 'cl_tracking_notice' ) );
399
  delete_option( 'cl_tracking_last_send' );
400
  delete_option( 'cl_tracking_notice' );
401
+
402
  delete_option( CUSTOM_LOGIN_OPTION . '_announcement_message' );
403
+
404
  /** Cleanup Cron Events */
405
  wp_clear_scheduled_hook( 'cl_daily_scheduled_events' );
406
  wp_clear_scheduled_hook( 'cl_weekly_scheduled_events' );
407
  return true;
408
  }
409
+
410
  /**
411
  * Helper function to check if option isset
412
  *
415
  private function get_old_setting( $setting = array(), $option = null, $default = '' ) {
416
  if ( is_null( $option ) )
417
  return $default;
418
+
419
  if ( isset( $setting[$option] ) )
420
  return $setting[$option];
421
+
422
  return $default;
423
  }
424
+
425
  }
426
+ CL_Settings_Upgrade::instance();
includes/class-cl-wp-login.php CHANGED
@@ -8,308 +8,283 @@
8
  */
9
 
10
  // Exit if accessed directly
11
- if ( ! defined( 'ABSPATH' ) ) {
12
- exit;
13
- }
14
 
15
  class CL_WP_Login {
16
 
17
- /** Singleton *************************************************************/
18
- private static $instance;
19
-
20
- /**
21
- * Main Instance
22
- *
23
- * @staticvar array $instance
24
- * @return self The one true instance
25
- */
26
- public static function instance() {
27
- if ( ! isset( self::$instance ) ) {
28
- self::$instance = new self;
29
- self::$instance->init();
30
- }
31
-
32
- return self::$instance;
33
- }
34
-
35
- private function init() {
36
-
37
- if ( 'off' === CL_Common::get_option( 'active', 'general', 'off' ) ) {
38
- return;
39
- }
40
-
41
- $this->actions();
42
- $this->filters();
43
- }
44
-
45
- private function actions() {
46
-
47
- add_action( 'login_enqueue_scripts', array( $this, 'login_enqueue_scripts' ) );
48
- add_action( 'login_footer', array( $this, 'login_footer_html' ), 8 );
49
- add_action( 'login_footer', array( $this, 'login_footer_jquery' ), 19 );
50
-
51
- add_action( 'init', array( $this, 'login_remove_scripts' ) );
52
- add_action( 'login_head', array( $this, 'login_head' ), 10 );
53
- add_filter( 'login_headerurl', array( $this, 'login_headerurl' ) );
54
- add_filter( 'login_headertitle', array( $this, 'login_headertitle' ) );
55
- }
56
-
57
- private function filters() {
58
-
59
- # add_filter( 'auth_cookie_expiration', array( $this, 'auth_cookie_expiration' ), 99, 3 ); // @removed 3.1
60
- # add_filter( 'allow_password_reset', array( $this, 'allow_password_reset' ) ); // @removed 3.1
61
- add_filter( 'gettext', array( $this, 'remove_lostpassword_text' ), 20, 2 );
62
- }
63
-
64
- /**
65
- *************************************************************
66
- **************** ACTIONS **********************************
67
- *************************************************************
68
- */
69
-
70
- /**
71
- * Enqueue additional scripts.
72
- *
73
- * @since 2.0
74
- * @updated 3.2
75
- */
76
- function login_enqueue_scripts() {
77
- global $cl_css_atts;
78
-
79
- $cl_css_atts = array(
80
- 'version' => CUSTOM_LOGIN_VERSION,
81
- 'trans_key' => CL_Common::get_transient_key( 'style' ),
82
- );
83
- $cl_css_atts = wp_parse_args( CL_Common::get_options( 'design' ), $cl_css_atts );
84
-
85
- ob_start();
86
- echo "<style type=\"text/css\">\n";
87
- CL_Templates::get_template_part( 'wp-login', 'style' );
88
- echo "\n</style>\n";
89
- echo ob_get_clean();
90
-
91
- /**
92
- * Animate.css
93
- * @ref https://github.com/daneden/animate.css/blob/master/animate.min.css
94
- */
95
- $animate_css = CL_Common::get_option( 'animate.css', 'design', 'off' );
96
- if ( 'on' == $animate_css ) {
97
- wp_enqueue_style( 'animate.css', plugins_url( 'css/animate.min.css', CUSTOM_LOGIN_FILE ), array( 'login' ), '08112014', 'screen' );
98
- }
99
-
100
- /* Custom jQuery */
101
- $jquery = CL_Common::get_option( 'custom_jquery', 'design', '' );
102
- if ( '' != $jquery ) {
103
- wp_enqueue_script( array( 'jquery' ) );
104
- }
105
- }
106
-
107
- /**
108
- * If there is custom HTML set in the settings echo it to the
109
- * 'login_footer' hook in wp-login.php.
110
- *
111
- * @return string|void
112
- */
113
- public function login_footer_html() {
114
-
115
- $custom_html = CL_Common::get_option( 'custom_html', 'design', false );
116
-
117
- if ( $custom_html ) {
118
- $html = wp_kses_post( $custom_html );
119
- $html .= "\n";
120
-
121
- echo $html;
122
- }
123
- }
124
-
125
- /**
126
- * Database access to the scripts and styles.
127
- *
128
- * @since 2.1
129
- * @return string|void
130
- */
131
- public function login_footer_jquery() {
132
-
133
- $jquery = CL_Common::get_option( 'custom_jquery', 'design', '' );
134
-
135
- if ( '' != $jquery ) {
136
-
137
- global $cl_js_atts;
138
-
139
- $cl_js_atts = array(
140
- 'version' => CUSTOM_LOGIN_VERSION,
141
- 'trans_key' => CL_Common::get_transient_key( 'script' ),
142
- );
143
- $cl_js_atts = wp_parse_args( CL_Common::get_options( 'design' ), $cl_js_atts );
144
-
145
- foreach ( $cl_js_atts as $atts => $value ) {
146
- if ( 'custom_jquery' !== $atts && 'version' !== $atts && 'trans_key' !== $atts ) {
147
- unset( $cl_js_atts[ $atts ] );
148
- }
149
- }
150
-
151
- ob_start();
152
- echo "<script type=\"text/javascript\">\n";
153
- CL_Templates::get_template_part( 'wp-login', 'script' );
154
- echo "\n</script>\n";
155
- echo ob_get_clean();
156
- }
157
- }
158
-
159
- /**
160
- * Finds the global page for the wp-login.php. When on the page
161
- * remove default stylesheets so we can add our own.
162
- *
163
- * @return void
164
- */
165
- function login_remove_scripts() {
166
- global $pagenow;
167
-
168
- if ( 'wp-login.php' == $pagenow ) {
169
-
170
- $suffix = is_rtl() ? '-rtl' : '';
171
- $suffix .= defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; // Don't have minified version in place.
172
-
173
- /**
174
- * User reports on messed up checkboxes
175
- *
176
- * Probobly easier to use WordPress login CSS
177
- *
178
- * wp_deregister_style( array( 'login' ) );
179
- *
180
- * wp_enqueue_style( 'forms', get_admin_url( get_current_blog_id(), "css/forms{$suffix}.css", 'admin' ), null, CUSTOM_LOGIN_VERSION, 'screen' );
181
- * wp_enqueue_style( 'l10n', get_admin_url( get_current_blog_id(), "css/l10n{$suffix}.css", 'admin' ), null, CUSTOM_LOGIN_VERSION, 'screen' );
182
- * wp_register_style( 'login', plugins_url( "css/login/login{$suffix}.css", CUSTOM_LOGIN_FILE ), array( 'buttons' ), CUSTOM_LOGIN_VERSION, 'all' );
183
- */
184
-
185
- if ( 'on' === CL_Common::get_option( 'remove_login_css', 'general' ) ) {
186
- add_filter( 'wp_admin_css', '__return_false' );
187
- wp_deregister_style( array( 'login' ) );
188
- }
189
- }
190
- }
191
-
192
- /**
193
- * Actions hooked into login_head
194
- *
195
- */
196
- public function login_head() {
197
- global $cl_css_atts;
198
-
199
- $cl_css_atts = array(
200
- 'version' => CUSTOM_LOGIN_VERSION,
201
- 'trans_key' => CL_Common::get_transient_key( 'style' ),
202
- );
203
- $cl_css_atts = wp_parse_args( CL_Common::get_options( 'design' ), $cl_css_atts );
204
-
205
- ob_start();
206
- echo "<style type=\"text/css\">\n";
207
- CL_Templates::get_template_part( 'wp-login', 'style' );
208
- echo "\n</style>\n";
209
- echo ob_get_clean();
210
-
211
- if ( 'on' === CL_Common::get_option( 'wp_shake_js', 'general' ) ) {
212
- remove_action( 'login_head', 'wp_shake_js', 12 );
213
- }
214
- }
215
-
216
- /**
217
- * Replace the default link to your URL
218
- */
219
- public function login_headerurl() {
220
-
221
- if ( ! is_multisite() ) {
222
- return home_url();
223
- }
224
- }
225
-
226
- /**
227
- * Replace the default title to your description
228
- */
229
- public function login_headertitle() {
230
-
231
- if ( ! is_multisite() ) {
232
- return get_bloginfo( 'description' );
233
- }
234
- }
235
-
236
- /**
237
- *************************************************************
238
- **************** FILTERS **********************************
239
- *************************************************************
240
- */
241
-
242
- /**
243
- * Allow password reset.
244
- *
245
- * @added 3.0.5
246
- * @updated 3.0.8
247
- * @disabled 3.1.0
248
- * @ref https://wordpress.org/plugins/configure-login-timeout/
249
- * @removed 3.1
250
- */
251
- public function auth_cookie_expiration( $seconds, $user_id, $remember ) {
252
-
253
- $expire_in = 0;
254
-
255
- if ( $remember ) {
256
- $expire_in = (int) CL_Common::get_option( 'auth_timeout_remember', 'general', 14 * DAY_IN_SECONDS );
257
- if ( $expire_in <= 0 ) {
258
- $expire_in = 14 * DAY_IN_SECONDS;
259
- }
260
- } else {
261
- $expire_in = (int) CL_Common::get_option( 'auth_timeout', 'general', 2 * DAY_IN_SECONDS );
262
- if ( $expire_in <= 0 ) {
263
- $expire_in = 2 * DAY_IN_SECONDS;
264
- }
265
- }
266
-
267
- // check for Year 2038 problem - http://en.wikipedia.org/wiki/Year_2038_problem
268
- if ( PHP_INT_MAX - time() < $expire_in ) {
269
- $expire_in = PHP_INT_MAX - time() - 5;
270
- }
271
-
272
- return $expire_in;
273
- }
274
-
275
- /**
276
- * Allow password reset.
277
- *
278
- * 'on' equals don't allow. :/
279
- *
280
- * @updated 3.0.5
281
- * @removed 3.1
282
- */
283
- public function allow_password_reset( $user_id ) {
284
- if ( 'on' === CL_Common::get_option( 'allow_password_reset', 'general', 'off' ) ) {
285
- return false;
286
- }
287
-
288
- return true;
289
- }
290
-
291
- /**
292
- * Remove the "Lost your password?" text.
293
- */
294
- public function remove_lostpassword_text( $translated_text, $untranslated_text ) {
295
- global $pagenow;
296
-
297
- if ( 'wp-login.php' == $pagenow ) {
298
-
299
- if ( 'off' !== CL_Common::get_option( 'lostpassword_text', 'general' ) ) {
300
- //make the changes to the text
301
- switch ( $untranslated_text ) {
302
-
303
- case 'Lost your password?':
304
- $translated_text = '';
305
- break;
306
- }
307
- }
308
- }
309
-
310
- return $translated_text;
311
- }
312
-
313
  }
314
-
315
  add_action( CUSTOM_LOGIN_OPTION . '_actions', array( 'CL_WP_Login', 'instance' ) );
8
  */
9
 
10
  // Exit if accessed directly
11
+ if ( !defined( 'ABSPATH' ) ) exit;
 
 
12
 
13
  class CL_WP_Login {
14
 
15
+ /** Singleton *************************************************************/
16
+ private static $instance;
17
+
18
+ /**
19
+ * Main Instance
20
+ *
21
+ * @staticvar array $instance
22
+ * @return The one true instance
23
+ */
24
+ public static function instance() {
25
+ if ( ! isset( self::$instance ) ) {
26
+ self::$instance = new self;
27
+ self::$instance->init();
28
+ }
29
+ return self::$instance;
30
+ }
31
+
32
+ private function init() {
33
+
34
+ if ( 'off' === CL_Common::get_option( 'active', 'general', 'off' ) )
35
+ return;
36
+
37
+ $this->actions();
38
+ $this->filters();
39
+ }
40
+
41
+ private function actions() {
42
+
43
+ add_action( 'login_enqueue_scripts', array( $this, 'login_enqueue_scripts' ) );
44
+ add_action( 'login_footer', array( $this, 'login_footer_html' ), 8 );
45
+ add_action( 'login_footer', array( $this, 'login_footer_jquery' ), 19 );
46
+
47
+ add_action( 'init', array( $this, 'login_remove_scripts' ) );
48
+ add_action( 'login_head', array( $this, 'login_head' ), 10 );
49
+ add_filter( 'login_headerurl', array( $this, 'login_headerurl' ) );
50
+ add_filter( 'login_headertitle', array( $this, 'login_headertitle' ) );
51
+ }
52
+
53
+ private function filters() {
54
+
55
+ # add_filter( 'auth_cookie_expiration', array( $this, 'auth_cookie_expiration' ), 99, 3 ); // @removed 3.1
56
+ # add_filter( 'allow_password_reset', array( $this, 'allow_password_reset' ) ); // @removed 3.1
57
+ add_filter( 'gettext', array( $this, 'remove_lostpassword_text' ), 20, 2 );
58
+ }
59
+
60
+ /**
61
+ *************************************************************
62
+ **************** ACTIONS **********************************
63
+ *************************************************************
64
+ */
65
+
66
+ /**
67
+ * Enqueue additional scripts.
68
+ *
69
+ * @since 2.0
70
+ * @updated 3.2
71
+ */
72
+ function login_enqueue_scripts() {
73
+ global $cl_css_atts;
74
+
75
+ $cl_css_atts = array(
76
+ 'version' => CUSTOM_LOGIN_VERSION,
77
+ 'trans_key' => CL_Common::get_transient_key( 'style' ),
78
+ );
79
+ $cl_css_atts = wp_parse_args( CL_Common::get_options( 'design' ), $cl_css_atts );
80
+
81
+ ob_start();
82
+ echo "<style type=\"text/css\">\n";
83
+ CL_Templates::get_template_part( 'wp-login', 'style' );
84
+ echo "\n</style>\n";
85
+ echo ob_get_clean();
86
+
87
+ /**
88
+ * Animate.css
89
+ * @ref https://github.com/daneden/animate.css/blob/master/animate.min.css
90
+ */
91
+ $animate_css = CL_Common::get_option( 'animate.css', 'design', 'off' );
92
+ if ( 'on' == $animate_css ) {
93
+ wp_enqueue_style( 'animate.css', plugins_url( 'css/animate.min.css', CUSTOM_LOGIN_FILE ), array( 'login' ), '08112014', 'screen' );
94
+ }
95
+
96
+ /* Custom jQuery */
97
+ $jquery = CL_Common::get_option( 'custom_jquery', 'design', '' );
98
+ if ( '' != $jquery ) {
99
+ wp_enqueue_script( array( 'jquery' ) );
100
+ }
101
+ }
102
+
103
+ /**
104
+ * If there is custom HTML set in the settings echo it to the
105
+ * 'login_footer' hook in wp-login.php.
106
+ *
107
+ * @return string|void
108
+ */
109
+ public function login_footer_html() {
110
+
111
+ $custom_html = CL_Common::get_option( 'custom_html', 'design', false );
112
+
113
+ if ( $custom_html ) {
114
+ $html = wp_kses_post( $custom_html );
115
+ $html .= "\n";
116
+
117
+ echo $html;
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Database access to the scripts and styles.
123
+ *
124
+ * @since 2.1
125
+ * @return string|void
126
+ */
127
+ public function login_footer_jquery() {
128
+
129
+ $jquery = CL_Common::get_option( 'custom_jquery', 'design', '' );
130
+
131
+ if ( '' != $jquery ) {
132
+
133
+ global $cl_js_atts;
134
+
135
+ $cl_js_atts = array(
136
+ 'version' => CUSTOM_LOGIN_VERSION,
137
+ 'trans_key' => CL_Common::get_transient_key( 'script' ),
138
+ );
139
+ $cl_js_atts = wp_parse_args( CL_Common::get_options( 'design' ), $cl_js_atts );
140
+
141
+ foreach( $cl_js_atts as $atts => $value ) {
142
+ if ( 'custom_jquery' !== $atts && 'version' !== $atts && 'trans_key' !== $atts )
143
+ unset( $cl_js_atts[$atts] );
144
+ }
145
+
146
+ ob_start();
147
+ echo "<script type=\"text/javascript\">\n";
148
+ CL_Templates::get_template_part( 'wp-login', 'script' );
149
+ echo "\n</script>\n";
150
+ echo ob_get_clean();
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Finds the global page for the wp-login.php. When on the page
156
+ * remove default stylesheets so we can add our own.
157
+ *
158
+ * @return void
159
+ */
160
+ function login_remove_scripts() {
161
+ global $pagenow;
162
+
163
+ if ( 'wp-login.php' == $pagenow ) {
164
+
165
+ $suffix = is_rtl() ? '-rtl' : '';
166
+ $suffix .= defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; // Don't have minified version in place.
167
+
168
+ /**
169
+ * User reports on messed up checkboxes
170
+ *
171
+ * Probobly easier to use WordPress login CSS
172
+ *
173
+ wp_deregister_style( array( 'login' ) );
174
+
175
+ wp_enqueue_style( 'forms', get_admin_url( get_current_blog_id(), "css/forms{$suffix}.css", 'admin' ), null, CUSTOM_LOGIN_VERSION, 'screen' );
176
+ wp_enqueue_style( 'l10n', get_admin_url( get_current_blog_id(), "css/l10n{$suffix}.css", 'admin' ), null, CUSTOM_LOGIN_VERSION, 'screen' );
177
+ wp_register_style( 'login', plugins_url( "css/login/login{$suffix}.css", CUSTOM_LOGIN_FILE ), array( 'buttons' ), CUSTOM_LOGIN_VERSION, 'all' );
178
+ */
179
+
180
+ if ( 'on' === CL_Common::get_option( 'remove_login_css', 'general' ) ) {
181
+ add_filter( 'wp_admin_css', '__return_false' );
182
+ wp_deregister_style( array( 'login' ) );
183
+ }
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Actions hooked into login_head
189
+ *
190
+ */
191
+ public function login_head() {
192
+
193
+ if ( 'on' === CL_Common::get_option( 'wp_shake_js', 'general' ) ) {
194
+ remove_action( 'login_head', 'wp_shake_js', 12 );
195
+ }
196
+ }
197
+
198
+ /**
199
+ * Replace the default link to your URL
200
+ */
201
+ public function login_headerurl() {
202
+
203
+ if ( !is_multisite() ) return home_url();
204
+ }
205
+
206
+ /**
207
+ * Replace the default title to your description
208
+ */
209
+ public function login_headertitle() {
210
+
211
+ if ( !is_multisite() ) return get_bloginfo( 'description' );
212
+ }
213
+
214
+ /**
215
+ *************************************************************
216
+ **************** FILTERS **********************************
217
+ *************************************************************
218
+ */
219
+
220
+ /**
221
+ * Allow password reset.
222
+ *
223
+ * @added 3.0.5
224
+ * @updated 3.0.8
225
+ * @disabled 3.1.0
226
+ * @ref https://wordpress.org/plugins/configure-login-timeout/
227
+ * @removed 3.1
228
+ */
229
+ public function auth_cookie_expiration( $seconds, $user_id, $remember ) {
230
+
231
+ $expire_in = 0;
232
+
233
+ if ( $remember ) {
234
+ $expire_in = (int) CL_Common::get_option( 'auth_timeout_remember', 'general', 14 * DAY_IN_SECONDS );
235
+ if ( $expire_in <= 0 )
236
+ $expire_in = 14 * DAY_IN_SECONDS;
237
+ }
238
+ else {
239
+ $expire_in = (int) CL_Common::get_option( 'auth_timeout', 'general', 2 * DAY_IN_SECONDS );
240
+ if ( $expire_in <= 0 )
241
+ $expire_in = 2 * DAY_IN_SECONDS;
242
+ }
243
+
244
+ // check for Year 2038 problem - http://en.wikipedia.org/wiki/Year_2038_problem
245
+ if ( PHP_INT_MAX - time() < $expire_in ) {
246
+ $expire_in = PHP_INT_MAX - time() - 5;
247
+ }
248
+
249
+ return $expire_in;
250
+ }
251
+
252
+ /**
253
+ * Allow password reset.
254
+ *
255
+ * 'on' equals don't allow. :/
256
+ *
257
+ * @updated 3.0.5
258
+ * @removed 3.1
259
+ */
260
+ public function allow_password_reset( $user_id ) {
261
+ if ( 'on' === CL_Common::get_option( 'allow_password_reset', 'general', 'off' ) )
262
+ return false;
263
+
264
+ return true;
265
+ }
266
+
267
+ /**
268
+ * Remove the "Lost your password?" text.
269
+ */
270
+ public function remove_lostpassword_text( $translated_text, $untranslated_text ) {
271
+ global $pagenow;
272
+
273
+ if ( 'wp-login.php' == $pagenow ) {
274
+
275
+ if ( 'off' !== CL_Common::get_option( 'lostpassword_text', 'general' ) ) {
276
+ //make the changes to the text
277
+ switch( $untranslated_text ) {
278
+
279
+ case 'Lost your password?':
280
+ $translated_text = '';
281
+ break;
282
+ }
283
+ }
284
+ }
285
+
286
+ return $translated_text;
287
+ }
288
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
289
  }
 
290
  add_action( CUSTOM_LOGIN_OPTION . '_actions', array( 'CL_WP_Login', 'instance' ) );
includes/libraries/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
includes/libraries/edd-remote-install-client/EDD_Remote_Install_Client.php CHANGED
@@ -124,7 +124,7 @@ class CL_Remote_Install_Client {
124
  'license' => urlencode( $_GET['license'] )
125
  );
126
 
127
- $download_link = esc_url( add_query_arg($api_params, $this->api_url) );
128
 
129
  ///////////// NEW /////////////////
130
  $download_id = $this->get_remote_download_id( $_GET['name'] );
@@ -314,7 +314,7 @@ class CL_Remote_Install_Client {
314
  );
315
 
316
  // Call the custom API.
317
- $response = wp_remote_get( esc_url( add_query_arg( $api_params, $this->api_url ) ), array( 'timeout' => 15, 'sslverify' => false ) );
318
 
319
  // make sure the response came back okay
320
  if ( is_wp_error( $response ) )
@@ -371,7 +371,7 @@ class CL_Remote_Install_Client {
371
  'item_name' => urlencode( $download_title )
372
  );
373
 
374
- $response = wp_remote_get( esc_url( add_query_arg( $api_params, $this->api_url ) ), array( 'timeout' => 15, 'sslverify' => false ) );
375
 
376
  if ( !is_wp_error( $response ) )
377
  $download_id = json_decode( wp_remote_retrieve_body( $response ) );
@@ -388,7 +388,7 @@ class CL_Remote_Install_Client {
388
  'expires' => rawurlencode( base64_encode( strtotime( '+1 hour' ) ) )
389
  ), $this->api_url );
390
 
391
- return apply_filters( 'edd_sl_encoded_package_url', esc_url( $package_url ) );
392
 
393
  }
394
  }
124
  'license' => urlencode( $_GET['license'] )
125
  );
126
 
127
+ $download_link = add_query_arg($api_params, $this->api_url);
128
 
129
  ///////////// NEW /////////////////
130
  $download_id = $this->get_remote_download_id( $_GET['name'] );
314
  );
315
 
316
  // Call the custom API.
317
+ $response = wp_remote_get( add_query_arg( $api_params, $this->api_url ), array( 'timeout' => 15, 'sslverify' => false ) );
318
 
319
  // make sure the response came back okay
320
  if ( is_wp_error( $response ) )
371
  'item_name' => urlencode( $download_title )
372
  );
373
 
374
+ $response = wp_remote_get( add_query_arg( $api_params, $this->api_url ), array( 'timeout' => 15, 'sslverify' => false ) );
375
 
376
  if ( !is_wp_error( $response ) )
377
  $download_id = json_decode( wp_remote_retrieve_body( $response ) );
388
  'expires' => rawurlencode( base64_encode( strtotime( '+1 hour' ) ) )
389
  ), $this->api_url );
390
 
391
+ return apply_filters( 'edd_sl_encoded_package_url', $package_url );
392
 
393
  }
394
  }
includes/libraries/edd-remote-install-client/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
includes/libraries/edd-remote-install-client/css/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
includes/libraries/edd-remote-install-client/js/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
js/_notes/dwsync.xml ADDED
@@ -0,0 +1 @@
 
1
+ <?xml version="1.0" encoding="utf-8" ?>
js/admin.js CHANGED
@@ -35,27 +35,9 @@
35
  */
36
  $('span.tgl_input').replaceWith( $('input[id="custom_login_general[active]"]').clone() );
37
 
38
- $(document).on('change', 'input[id="custom_login_general[active]"]', function() {
 
39
  $('input[id="custom_login_general[active]"]').prop('checked', this.checked);
40
- $.ajax({
41
- type: "POST",
42
- data: {
43
- action: cl_settings_api.prefix + '_activate_check',
44
- nonce: cl_settings_api.nonce,
45
- active_value: this.checked.toString()
46
- },
47
- dataType: "json",
48
- url: ajaxurl
49
- })
50
- .done(function (response) {
51
- if (response.success) {
52
- } else {
53
-
54
- }
55
- })
56
- .fail(function () {
57
- throw new Error('Error');
58
- });
59
  });
60
 
61
  /**
35
  */
36
  $('span.tgl_input').replaceWith( $('input[id="custom_login_general[active]"]').clone() );
37
 
38
+ $(document).on('click change', 'input[id="custom_login_general[active]"]', function() {
39
+ // console.log(this.checked);
40
  $('input[id="custom_login_general[active]"]').prop('checked', this.checked);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  });
42
 
43
  /**
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: austyfrosty, frostymedia
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7431290
4
  Tags: admin, branding, customization, custom login, login, logo, error, login error, custom login pro
5
  Requires at least: 4.0
6
- Tested up to: 4.5
7
  Stable tag: trunk
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -17,12 +17,12 @@ Custom Login 2.0 was 140% faster than version 1.0, and version 3.0 is now even b
17
  For more information visit the official [Custom Login](https://frosty.media/plugins/custom-login/) page.
18
 
19
  > <strong>Support</strong><br>
20
- > [Austin](http://austin.passy.co) and the [Frosty Media](https://frosty.media/) team will always try our best to support the Custom Login plugin on the WordPress.org forum, but please note that we can not guarantee a response in a timely manner. If you have an issue we would appriciate you using GitHub or purchasing priority support on our site.
21
  >
22
- > Any extensions purchased on [Frosty Media](https://frosty.media/) (not hosted on WordPress.org) will not be supported on the WordPress.org forum. You can always browse our *small* but growing [documentation](https://frosty.media/docs) for further assistance. You need a valid license key to make support submissions *on our site*. We thank you in advance.
23
 
24
  > <strong>Bug Reports</strong><br>
25
- > Bug reports for Custom Login are [welcomed on GitHub](https://github.com/thefrosty/custom-login).
26
 
27
  = Video =
28
 
@@ -37,8 +37,8 @@ There are currently 5 premium extensions available, with more coming (suggestion
37
  * [Stealth Login](https://frosty.media/plugins/custom-login-stealth-login/?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login Stealth Login") - obscure your login URL.
38
  * [Page Template](https://frosty.media/plugins/custom-login-page-template/?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login Page Template") - add a login form to any WordPress page.
39
  * [Login Redirects](https://frosty.media/plugins/custom-login-redirects/?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login Redirects") - Manage login redirects.
40
- * [No Password](https://frosty.media/plugins/custom-login-no-password-login/?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login No Password logins") - allow users to login without a password.
41
- * [Style Pack #1](https://frosty.media/plugins/custom-login-style-pack-1?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login Style Pack #1") - four pre-designed login styles.
42
 
43
  **Extensions in development/extension ideas**
44
 
@@ -62,7 +62,7 @@ Activate the plugin and customize your WordPress login screen. It's as easy as m
62
  = links =
63
 
64
  * Premium Plugins: [https://frosty.media/plugins](https://frosty.media/plugins/ "Premium WordPress Plugins by Frosty")
65
- * Austins Blog: [https:/austin.passy.co/](http://austin.passy.co/ "Austin Passy's blog")
66
  * Austin on Twitter: @[TheFrosty](https:/twitter.com/TheFrosty "Austin TheFrosty' Passy on Twitter")
67
  * Frosty Media on Twitter: @[Frosty_Media](https:/twitter.com/Frosty_Media "Frosty Media on Twitter")
68
  * **Development welcomed on [GitHub](https://github.com/thefrosty/custom-login)**
@@ -115,33 +115,6 @@ Custom Login showcase on the [Flickr group](http://flickr.com/groups/custom-logi
115
 
116
  == Changelog ==
117
 
118
- = Version 3.2.5 (04/13/16) =
119
-
120
- * WordPress 4.5 compatible update (moves Custom Login css after WordPress' login style sheet).
121
- * Fix issue where toggling the 'active' checkbox in the header doesn't activate or de-activate the plugin settings (updates via AJAX now).
122
-
123
- = Version 3.2.4 (09/16/15) =
124
-
125
- * Fix PHP Fatal error.
126
- ** PHP Fatal error: Call to a member function get_permalink() on a non-object in /includes/admin/dashboard.php:114
127
-
128
- = Version 3.2.2 (05/04/15) =
129
-
130
- * May the fourth be with you.
131
- * Cleaned up dashboard JS errors.
132
-
133
- = Version 3.2.2 (04/29/15) =
134
-
135
- * Update version number.
136
- * Fix upgrade notice showing when not needed.
137
- * Add class 'notice' and 'is-dismissible' to notice.
138
- * Cleanup admin dashboard empty ob_get_clean() notice.
139
-
140
- = Version 3.2.1 (04/20/15) =
141
-
142
- * Fix: XSS security flaw.
143
- * Fix: Settings page not showing. (Fixes Issue: [#6](https://github.com/thefrosty/custom-login/pull/6) /ht @[DrewAPicture](https://github.com/DrewAPicture).
144
-
145
  = Version 3.2 (02/09/15) =
146
 
147
  * Message: Celebrate 500,000 downloads. Visit the settings page or [this post](https://frosty.media/?p=26056) to get any extension for free! *Restrictions may apply.
@@ -216,7 +189,7 @@ Custom Login showcase on the [Flickr group](http://flickr.com/groups/custom-logi
216
  = Version 3.0.2 (01/12/15) =
217
 
218
  * Fix: Logo background size width &amp; height settings not transfering over in upgrade process.
219
- * Fix: Checking "Remove lost password text" removes the text instead of the other way around. [forum](https://wordpress.org/support/topic/lost-your-password-1)
220
 
221
  = Version 3.0.1 (01/11/15) =
222
 
@@ -244,4 +217,4 @@ Celebrate 500,000 downloads w/ a FREE extension! Update to version 3.2 for more
244
  Fixes unable to login to admin site.
245
 
246
  = 3.0.5 =
247
- Complete rewrite of Custom Login, be sure to run the update script to keep your old settings.
3
  Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7431290
4
  Tags: admin, branding, customization, custom login, login, logo, error, login error, custom login pro
5
  Requires at least: 4.0
6
+ Tested up to: 4.1
7
  Stable tag: trunk
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
17
  For more information visit the official [Custom Login](https://frosty.media/plugins/custom-login/) page.
18
 
19
  > <strong>Support</strong><br>
20
+ > [Austin](https://austin.passy.co) and the [Frosty Media](https://frosty.media/) team will always try our best to support the Custom Login plugin on the WordPress.org forum, but please note that we can not guarantee a response in a timely manner. If you have an issue we would appriciate you using GitHub or purchasing priority support on our site.
21
  >
22
+ > Any extensions purchased on [Frosty Media](https://frosty.media/) (not hosted on WordPress.org) will not be supported on the WordPress.org forum. You can always browse our *small* but growing [documentation](https://frosty.media/docs) for further assistance. You need a valid license key to make support submissions *on our site*. We thank you in advance.
23
 
24
  > <strong>Bug Reports</strong><br>
25
+ > Bug reports for Custom Login are [welcomed on GitHub](https://github.com/thefrosty/custom-login).
26
 
27
  = Video =
28
 
37
  * [Stealth Login](https://frosty.media/plugins/custom-login-stealth-login/?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login Stealth Login") - obscure your login URL.
38
  * [Page Template](https://frosty.media/plugins/custom-login-page-template/?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login Page Template") - add a login form to any WordPress page.
39
  * [Login Redirects](https://frosty.media/plugins/custom-login-redirects/?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login Redirects") - Manage login redirects.
40
+ * [No Password](https://frosty.media/plugins/custom-login-no-password-login/?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login No Password logins") - allow users to login without a password.
41
+ * [Style Pack #1](https://frosty.media/plugins/custom-login-style-pack-1?utm_source=wordpressorg&utm_medium=custom-login&utm_campaign=readme.txt "Custom Login Style Pack #1") - four pre-designed login styles.
42
 
43
  **Extensions in development/extension ideas**
44
 
62
  = links =
63
 
64
  * Premium Plugins: [https://frosty.media/plugins](https://frosty.media/plugins/ "Premium WordPress Plugins by Frosty")
65
+ * Austins Blog: [https:/austin.passy.co/](https://austin.passy.co/ "Austin Passy's blog")
66
  * Austin on Twitter: @[TheFrosty](https:/twitter.com/TheFrosty "Austin TheFrosty' Passy on Twitter")
67
  * Frosty Media on Twitter: @[Frosty_Media](https:/twitter.com/Frosty_Media "Frosty Media on Twitter")
68
  * **Development welcomed on [GitHub](https://github.com/thefrosty/custom-login)**
115
 
116
  == Changelog ==
117
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  = Version 3.2 (02/09/15) =
119
 
120
  * Message: Celebrate 500,000 downloads. Visit the settings page or [this post](https://frosty.media/?p=26056) to get any extension for free! *Restrictions may apply.
189
  = Version 3.0.2 (01/12/15) =
190
 
191
  * Fix: Logo background size width &amp; height settings not transfering over in upgrade process.
192
+ * Fix: Checking "Remove lost password text" removes the text instead of the other way around. [forum](https://wordpress.org/support/topic/lost-your-password-1)
193
 
194
  = Version 3.0.1 (01/11/15) =
195
 
217
  Fixes unable to login to admin site.
218
 
219
  = 3.0.5 =
220
+ Complete rewrite of Custom Login, be sure to run the update script to keep your old settings.
templates/wp-login-script.php CHANGED
@@ -10,7 +10,7 @@ global $cl_js_atts;
10
  extract( $cl_js_atts, EXTR_SKIP );
11
 
12
  /* Cache ALL THE THINGS! */
13
- //if ( false === ( $js = get_transient( $trans_key ) ) ) :
14
 
15
  $js = '';
16
 
@@ -22,7 +22,7 @@ extract( $cl_js_atts, EXTR_SKIP );
22
  *
23
  * Plugin URI : https://frosty.media/plugins/custom-login/
24
  * Version : $version
25
- * Author URI : http://austin.passy.co/
26
  * Extensions : https://frosty.media/plugin/tag/custom-login-extension/
27
  */\n\n";
28
 
@@ -33,16 +33,16 @@ extract( $cl_js_atts, EXTR_SKIP );
33
  if ( !empty( $custom_jquery ) ) {
34
 
35
  $js .= "\n\n/* Custom JS */\n";
36
- $js .= wp_specialchars_decode( stripslashes( $custom_jquery ) );
37
  $js .= "\n\n";
38
 
39
  }
40
 
41
  $js .= '}(jQuery));';
42
 
43
- // /* WP Magic */
44
- // set_transient( $trans_key, $js, YEAR_IN_SECONDS/2 ); // Cache for six months
45
- //endif;
46
 
47
  /* Out of the frying pan, and into the fire! */
48
  echo $js;
10
  extract( $cl_js_atts, EXTR_SKIP );
11
 
12
  /* Cache ALL THE THINGS! */
13
+ if ( false === ( $js = get_transient( $trans_key ) ) ) :
14
 
15
  $js = '';
16
 
22
  *
23
  * Plugin URI : https://frosty.media/plugins/custom-login/
24
  * Version : $version
25
+ * Author URI : https://austin.passy.co/
26
  * Extensions : https://frosty.media/plugin/tag/custom-login-extension/
27
  */\n\n";
28
 
33
  if ( !empty( $custom_jquery ) ) {
34
 
35
  $js .= "\n\n/* Custom JS */\n";
36
+ $js .= wp_specialchars_decode( stripslashes( $custom_jquery ), 1, 0, 1 );
37
  $js .= "\n\n";
38
 
39
  }
40
 
41
  $js .= '}(jQuery));';
42
 
43
+ /* WP Magic */
44
+ set_transient( $trans_key, $js, YEAR_IN_SECONDS/2 ); // Cache for six months
45
+ endif;
46
 
47
  /* Out of the frying pan, and into the fire! */
48
  echo $js;
templates/wp-login-style.php CHANGED
@@ -11,7 +11,7 @@ global $cl_css_atts;
11
  extract( $cl_css_atts, EXTR_SKIP );
12
 
13
  /* Cache ALL THE THINGS! */
14
- //if ( false === ( $css = get_transient( $trans_key ) ) ) :
15
 
16
  $css = '';
17
  $close_rule = "}\n";
@@ -27,13 +27,13 @@ extract( $cl_css_atts, EXTR_SKIP );
27
  *
28
  * Plugin URI : https://frosty.media/plugins/custom-login/
29
  * Version : $version
30
- * Author URI : http://austin.passy.co/
31
  * Extensions : https://frosty.media/plugin/tag/custom-login-extension/
32
  */\n\n";
33
 
34
  /* Custom user input */
35
  if ( !empty( $custom_css ) ) {
36
- $custom_css = wp_specialchars_decode( stripslashes( $custom_css ) );
37
 
38
  $css .= "/* START Custom CSS */\n";
39
  $css .= str_replace(
@@ -327,9 +327,9 @@ extract( $cl_css_atts, EXTR_SKIP );
327
 
328
  }
329
 
330
- // /* WP Magic */
331
- // set_transient( $trans_key, $css, YEAR_IN_SECONDS/2 ); // Cache for six months
332
- //endif;
333
 
334
  /* Out of the frying pan, and into the fire! */
335
  echo $css;
11
  extract( $cl_css_atts, EXTR_SKIP );
12
 
13
  /* Cache ALL THE THINGS! */
14
+ if ( false === ( $css = get_transient( $trans_key ) ) ) :
15
 
16
  $css = '';
17
  $close_rule = "}\n";
27
  *
28
  * Plugin URI : https://frosty.media/plugins/custom-login/
29
  * Version : $version
30
+ * Author URI : https://austin.passy.co/
31
  * Extensions : https://frosty.media/plugin/tag/custom-login-extension/
32
  */\n\n";
33
 
34
  /* Custom user input */
35
  if ( !empty( $custom_css ) ) {
36
+ $custom_css = wp_specialchars_decode( stripslashes( $custom_css ), 1, 0, 1 );
37
 
38
  $css .= "/* START Custom CSS */\n";
39
  $css .= str_replace(
327
 
328
  }
329
 
330
+ /* WP Magic */
331
+ set_transient( $trans_key, $css, YEAR_IN_SECONDS/2 ); // Cache for six months
332
+ endif;
333
 
334
  /* Out of the frying pan, and into the fire! */
335
  echo $css;