PluginProbe
Mailchimp List Subscribe Form / 1.8.0
Mailchimp List Subscribe Form v1.8.0
1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 All 55 releases
mailchimp / mailchimp.php

mailchimp.php in Mailchimp List Subscribe Form 1.8.0, at mailchimp.php

1,096 lines 37.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Mailchimp
4 * Plugin URI: https://mailchimp.com/help/connect-or-disconnect-list-subscribe-for-wordpress/
5 * Description: Add a Mailchimp signup form block, widget or shortcode to your WordPress site.
6 * Text Domain: mailchimp
7 * Version: 1.8.0
8 * Requires at least: 6.4
9 * Requires PHP: 7.0
10 * PHP tested up to: 8.3
11 * Author: Mailchimp
12 * Author URI: https://mailchimp.com/
13 * License: GPL-2.0-or-later
14 * License URI: https://spdx.org/licenses/GPL-2.0-or-later.html
15 *
16 * @package Mailchimp
17 **/
18
19 /**
20 * Copyright 2008-2012 Mailchimp.com (email : api@mailchimp.com)
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 */
36
37 // Check if the autoload file exists
38 if ( is_readable( __DIR__ . '/vendor/autoload.php' ) ) {
39 require_once __DIR__ . '/vendor/autoload.php';
40 } else {
41 add_action(
42 'admin_notices',
43 function () {
44 ?>
45 <div class="notice notice-error">
46 <p>
47 <?php
48 echo wp_kses_post(
49 sprintf(
50 /* translators: 1: Command to run, e.g., <code>composer install</code>, 2: Support URL, e.g., https://wordpress.org/support/plugin/mailchimp/. */
51 __( 'The composer autoload file is not found or not readable. Please contact <a href="%2$s" target="_blank">support</a> if you\'re a user. Please run %1$s if you\'re a developer in a development environment.', 'mailchimp' ),
52 '<code>composer install</code>',
53 'https://wordpress.org/support/plugin/mailchimp/'
54 )
55 );
56 ?>
57 </p>
58 </div>
59 <?php
60 }
61 );
62
63 // Exit early.
64 return;
65 }
66
67 use function Mailchimp\WordPress\Includes\Admin\{admin_notice_error, admin_notice_success};
68
69 // Version constant for easy CSS refreshes
70 define( 'MCSF_VER', '1.8.0' );
71
72 // What's our permission (capability) threshold
73 define( 'MCSF_CAP_THRESHOLD', 'manage_options' );
74
75 // Define our location constants, both MCSF_DIR and MCSF_URL
76 mailchimp_sf_where_am_i();
77
78 // Get our Mailchimp API class in scope
79 if ( ! class_exists( 'MailChimp_API' ) ) {
80 $path = plugin_dir_path( __FILE__ );
81 require_once $path . 'lib/mailchimp/mailchimp.php';
82 }
83
84 // Encryption utility class.
85 require_once plugin_dir_path( __FILE__ ) . 'includes/class-mailchimp-data-encryption.php';
86
87 // includes the widget code so it can be easily called either normally or via ajax
88 require_once 'mailchimp_widget.php';
89
90 // includes the backwards compatibility functions
91 require_once 'mailchimp_compat.php';
92
93 // Upgrade routines.
94 require_once 'mailchimp_upgrade.php';
95
96 // Init Admin functions.
97 require_once plugin_dir_path( __FILE__ ) . 'includes/class-mailchimp-admin.php';
98 $admin = new Mailchimp_Admin();
99 $admin->init();
100
101 // Init the blocks.
102 require_once plugin_dir_path( __FILE__ ) . 'includes/blocks/class-mailchimp-list-subscribe-form-blocks.php';
103 $block = new Mailchimp_List_Subscribe_Form_Blocks();
104 $block->init();
105
106 // Form submission handler class.
107 require_once plugin_dir_path( __FILE__ ) . 'includes/class-mailchimp-form-submission.php';
108 $form_submission = new Mailchimp_Form_Submission();
109 $form_submission->init();
110
111 // Deprecated functions.
112 require_once plugin_dir_path( __FILE__ ) . 'includes/mailchimp-deprecated-functions.php';
113
114 /**
115 * Do the following plugin setup steps here
116 *
117 * Resource (JS & CSS) enqueuing
118 *
119 * @return void
120 */
121 function mailchimp_sf_plugin_init() {
122
123 if ( get_option( 'mc_list_id' ) && get_option( 'mc_merge_field_migrate' ) !== '1' && mailchimp_sf_get_api() !== false ) {
124 mailchimp_sf_update_merge_fields();
125 }
126
127 // Bring in our appropriate JS and CSS resources
128 mailchimp_sf_load_resources();
129 }
130
131 add_action( 'init', 'mailchimp_sf_plugin_init' );
132
133 /**
134 * Add the settings link to the Mailchimp plugin row
135 *
136 * @param array $links - Links for the plugin
137 * @return array - Links
138 */
139 function mailchimp_sf_plugin_action_links( $links ) {
140 $settings_page = add_query_arg( array( 'page' => 'mailchimp_sf_options' ), admin_url( 'admin.php' ) );
141 $settings_link = '<a href="' . esc_url( $settings_page ) . '">' . esc_html__( 'Settings', 'mailchimp' ) . '</a>';
142 array_unshift( $links, $settings_link );
143 return $links;
144 }
145
146 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'mailchimp_sf_plugin_action_links', 10, 1 );
147
148 /**
149 * Loads the appropriate JS and CSS resources depending on
150 * settings and context (admin or not)
151 *
152 * @return void
153 */
154 function mailchimp_sf_load_resources() {
155 // JS
156 if ( ! is_admin() ) {
157 wp_enqueue_script( 'mailchimp_sf_main_js', MCSF_URL . 'assets/js/mailchimp.js', array( 'jquery', 'jquery-form' ), MCSF_VER, true );
158 // some javascript to get ajax version submitting to the proper location
159 global $wp_scripts;
160 $wp_scripts->localize(
161 'mailchimp_sf_main_js',
162 'mailchimpSF',
163 array(
164 'ajax_url' => trailingslashit( home_url() ),
165 )
166 );
167
168 // Datepicker theme
169 wp_enqueue_style( 'flick', MCSF_URL . 'assets/css/flick/flick.css', array(), MCSF_VER );
170
171 // Datepicker JS
172 wp_enqueue_script( 'jquery-ui-datepicker' );
173 }
174
175 if ( get_option( 'mc_nuke_all_styles' ) !== '1' ) {
176 wp_enqueue_style( 'mailchimp_sf_main_css', home_url( '?mcsf_action=main_css&ver=' . MCSF_VER, 'relative' ), array(), MCSF_VER );
177 global $wp_styles;
178 $wp_styles->add_data( 'mailchimp_sf_ie_css', 'conditional', 'IE' );
179 }
180 }
181
182 /**
183 * Loads jQuery Datepicker for the date-pick class
184 **/
185 function mc_datepicker_load() {
186 require_once MCSF_DIR . '/views/datepicker.php';
187 }
188
189 if ( ! is_admin() ) {
190 add_action( 'wp_head', 'mc_datepicker_load' );
191 }
192
193 /**
194 * Handles requests that as light-weight a load as possible.
195 * typically, JS or CSS
196 *
197 * @return void
198 */
199 function mailchimp_sf_early_request_handler() {
200 if ( isset( $_GET['mcsf_action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- ignoring because this is only adding CSS
201 switch ( $_GET['mcsf_action'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- ignoring because this is only adding CSS
202 case 'main_css':
203 header( 'Content-type: text/css' );
204 mailchimp_sf_main_css();
205 exit;
206 }
207 }
208 }
209
210 add_action( 'init', 'mailchimp_sf_early_request_handler', 0 );
211
212 /**
213 * Outputs the front-end CSS. This checks several options, so it
214 * was best to put it in a Request-handled script, as opposed to
215 * a static file.
216 */
217 function mailchimp_sf_main_css() {
218 require_once MCSF_DIR . '/views/css/frontend.php';
219 }
220
221
222 /**
223 * Add our settings page to the admin menu
224 *
225 * @return void
226 */
227 function mailchimp_sf_add_pages() {
228 // Add settings page for users who can edit plugins
229 add_menu_page(
230 esc_html__( 'Mailchimp Setup', 'mailchimp' ),
231 esc_html__( 'Mailchimp', 'mailchimp' ),
232 MCSF_CAP_THRESHOLD,
233 'mailchimp_sf_options',
234 'mailchimp_sf_setup_page',
235 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1Mi4wMyA1NSI+PGRlZnM+PHN0eWxlPi5jbHMtMXtmaWxsOiNmZmY7fTwvc3R5bGU+PC9kZWZzPjx0aXRsZT5Bc3NldCAxPC90aXRsZT48ZyBpZD0iTGF5ZXJfMiIgZGF0YS1uYW1lPSJMYXllciAyIj48ZyBpZD0iTGF5ZXJfMS0yIiBkYXRhLW5hbWU9IkxheWVyIDEiPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTExLjY0LDI4LjU0YTQuNzUsNC43NSwwLDAsMC0xLjE3LjA4Yy0yLjc5LjU2LTQuMzYsMi45NC00LjA1LDZhNi4yNCw2LjI0LDAsMCwwLDUuNzIsNS4yMSw0LjE3LDQuMTcsMCwwLDAsLjgtLjA2YzIuODMtLjQ4LDMuNTctMy41NSwzLjEtNi41N0MxNS41MSwyOS44MywxMy4yMSwyOC42MywxMS42NCwyOC41NFptMi43Nyw4LjA3YTEuMTcsMS4xNywwLDAsMS0xLjEuNTUsMS41MywxLjUzLDAsMCwxLTEuMzctMS41OEE0LDQsMCwwLDEsMTIuMjMsMzRhMS40NCwxLjQ0LDAsMCwwLS41NS0xLjc0LDEuNDgsMS40OCwwLDAsMC0xLjEyLS4yMSwxLjQ0LDEuNDQsMCwwLDAtLjkyLjY0LDMuMzksMy4zOSwwLDAsMC0uMzQuNzlsMCwuMTFjLS4xMy4zNC0uMzMuNDUtLjQ3LjQzcy0uMTYtLjA1LS4yMS0uMjFhMywzLDAsMCwxLC43OC0yLjU1LDIuNDYsMi40NiwwLDAsMSwyLjExLS43NiwyLjUsMi41LDAsMCwxLDEuOTEsMS4zOSwzLjE5LDMuMTksMCwwLDEtLjIzLDIuODJsLS4wOS4yQTEuMTYsMS4xNiwwLDAsMCwxMywzNmEuNzQuNzQsMCwwLDAsLjYzLjMyLDEuMzgsMS4zOCwwLDAsMCwuMzQsMGMuMTUsMCwuMy0uMDcuMzksMEEuMjQuMjQsMCwwLDEsMTQuNDEsMzYuNjFaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNTEsMzMuODhhMy44NCwzLjg0LDAsMCwwLTEuMTUtMWwtLjExLS4zNy0uMTQtLjQyYTUuNTcsNS41NywwLDAsMCwuNS0zLjMyLDUuNDMsNS40MywwLDAsMC0xLjU0LTMsMTAuMDksMTAuMDksMCwwLDAtNC4yNC0yLjI2YzAtLjY3LDAtMS40My0uMDYtMS45YTEyLjgzLDEyLjgzLDAsMCwwLS40OS0zLjI1LDEwLjQ2LDEwLjQ2LDAsMCwwLTEuMy0yLjkyYzIuMTQtMi41NiwzLjI5LTUuMjEsMy4yOS03LjU3LDAtMy44My0zLTYuMy03LjU5LTYuM2ExOS4zLDE5LjMsMCwwLDAtNy4yMiwxLjZsLS4zNC4xNEwyOC43LDEuNTJBNi4zMSw2LjMxLDAsMCwwLDI0LjQzLDAsMTQuMDcsMTQuMDcsMCwwLDAsMTcuNiwyLjJhMzYuOTMsMzYuOTMsMCwwLDAtNi43OCw1LjIxYy00LjYsNC4zOC04LjMsOS42My05LjkxLDE0QTEyLjUxLDEyLjUxLDAsMCwwLDAsMjYuNTRhNi4xNiw2LjE2LDAsMCwwLDIuMTMsNC40bC43OC42NkExMC40NCwxMC40NCwwLDAsMCwyLjc0LDM1YTkuMzYsOS4zNiwwLDAsMCwzLjIxLDYsMTAsMTAsMCwwLDAsNS4xMywyLjQzLDIwLjE5LDIwLjE5LDAsMCwwLDcuMzEsOEEyMy4zMywyMy4zMywwLDAsMCwzMC4xNyw1NUgzMWEyMy4yNywyMy4yNywwLDAsMCwxMi0zLjE2LDE5LjEsMTkuMSwwLDAsMCw3LjgyLTkuMDZsMCwwQTE2Ljg5LDE2Ljg5LDAsMCwwLDUyLDM3LjIzLDUuMTcsNS4xNywwLDAsMCw1MSwzMy44OFptLTEuNzgsOC4yMWMtMyw3LjI5LTEwLjMsMTEuMzUtMTksMTEuMDktOC4wNi0uMjQtMTQuOTQtNC41LTE4LTExLjQzYTcuOTQsNy45NCwwLDAsMS01LjEyLTIuMDYsNy41Niw3LjU2LDAsMCwxLTIuNjEtNC44NUE4LjMxLDguMzEsMCwwLDEsNSwzMUwzLjMyLDI5LjU2Qy00LjQyLDIzLDE5Ljc3LTMuODYsMjcuNTEsMi44OWwyLjY0LDIuNTgsMS40NC0uNjFjNi43OS0yLjgxLDEyLjMtMS40NSwxMi4zLDMsMCwyLjMzLTEuNDgsNS4wNS0zLjg2LDcuNTJhNy41NCw3LjU0LDAsMCwxLDIsMy40OCwxMSwxMSwwLDAsMSwuNDIsMi44MmMwLDEsLjA5LDMuMTYuMDksMy4ybDEsLjI3QTguNjQsOC42NCwwLDAsMSw0Ny4yLDI3YTMuNjYsMy42NiwwLDAsMSwxLjA2LDIuMDZBNCw0LDAsMCwxLDQ3LjU1LDMyLDEwLjE1LDEwLjE1LDAsMCwxLDQ4LDMzLjA4Yy4yLjY0LjM1LDEuMTguMzcsMS4yNS43NCwwLDEuODkuODUsMS44OSwyLjg5QTE1LjI5LDE1LjI5LDAsMCwxLDQ5LjE4LDQyLjA5WiIvPjxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTQ4LDM2YTEuMzYsMS4zNiwwLDAsMC0uODYtLjE2LDExLjc2LDExLjc2LDAsMCwwLS44Mi0yLjc4QTE3Ljg5LDE3Ljg5LDAsMCwxLDQwLjQ1LDM2YTIzLjY0LDIzLjY0LDAsMCwxLTcuODEuODRjLTEuNjktLjE0LTIuODEtLjYzLTMuMjMuNzRhMTguMywxOC4zLDAsMCwwLDgsLjgxLjE0LjE0LDAsMCwxLC4xNi4xMy4xNS4xNSwwLDAsMS0uMDkuMTVzLTMuMTQsMS40Ni04LjE0LS4wOGEyLjU4LDIuNTgsMCwwLDAsMS44MywxLjkxLDguMjQsOC4yNCwwLDAsMCwxLjQ0LjM5YzYuMTksMS4wNiwxMi0yLjQ3LDEzLjI3LTMuMzYuMS0uMDcuMTYsMCwuMDguMTJsLS4xMy4xOGMtMS41OSwyLjA2LTUuODgsNC40NC0xMS40NSw0LjQ0LTIuNDMsMC00Ljg2LS44Ni01Ljc1LTIuMTctMS4zOC0yLS4wNy01LDIuMjQtNC43MWwxLC4xMWEyMS4xMywyMS4xMywwLDAsMCwxMC41LTEuNjhjMy4xNS0xLjQ2LDQuMzQtMy4wNyw0LjE2LTQuMzdBMS44NywxLjg3LDAsMCwwLDQ2LDI4LjM0YTYuOCw2LjgsMCwwLDAtMy0xLjQxYy0uNS0uMTQtLjg0LS4yMy0xLjItLjM1LS42NS0uMjEtMS0uMzktMS0xLjYxLDAtLjUzLS4xMi0yLjQtLjE2LTMuMTYtLjA2LTEuMzUtLjIyLTMuMTktMS4zNi00YTEuOTIsMS45MiwwLDAsMC0xLS4zMSwxLjg2LDEuODYsMCwwLDAtLjU4LjA2LDMuMDcsMy4wNywwLDAsMC0xLjUyLjg2LDUuMjQsNS4yNCwwLDAsMS00LDEuMzJjLS44LDAtMS42NS0uMTYtMi42Mi0uMjJsLS41NywwYTUuMjIsNS4yMiwwLDAsMC01LDQuNTdjLS41NiwzLjgzLDIuMjIsNS44MSwzLDdhMSwxLDAsMCwxLC4yMi41Mi44My44MywwLDAsMS0uMjguNTVoMGE5LjgsOS44LDAsMCwwLTIuMTYsOS4yLDcuNTksNy41OSwwLDAsMCwuNDEsMS4xMmMyLDQuNzMsOC4zLDYuOTMsMTQuNDMsNC45M2ExNS4wNiwxNS4wNiwwLDAsMCwyLjMzLTEsMTIuMjMsMTIuMjMsMCwwLDAsMy41Ny0yLjY3LDEwLjYxLDEwLjYxLDAsMCwwLDMtNS44MkM0OC42LDM2LjcsNDguMzMsMzYuMjMsNDgsMzZabS04LjI1LTcuODJjMCwuNS0uMzEuOTEtLjY4LjlzLS42Ni0uNDItLjY1LS45Mi4zMS0uOTEuNjgtLjlTMzkuNzIsMjcuNjgsMzkuNzEsMjguMThabS0xLjY4LTZjLjcxLS4xMiwxLjA2LjYyLDEuMzIsMS44NWEzLjY0LDMuNjQsMCwwLDEtLjA1LDIsNC4xNCw0LjE0LDAsMCwwLTEuMDYsMCw0LjEzLDQuMTMsMCwwLDEtLjY4LTEuNjRDMzcuMjksMjMuMjMsMzcuMzEsMjIuMzQsMzgsMjIuMjNabS0yLjQsNi41N2EuODIuODIsMCwwLDEsMS4xMS0uMTljLjQ1LjIyLjY5LjY3LjUzLDFhLjgyLjgyLDAsMCwxLTEuMTEuMTlDMzUuNywyOS41OCwzNS40NywyOS4xMywzNS42MywyOC44Wm0tMi44LS4zN2MtLjA3LjExLS4yMy4wOS0uNTcuMDZhNC4yNCw0LjI0LDAsMCwwLTIuMTQuMjIsMiwyLDAsMCwxLS40OS4xNC4xNi4xNiwwLDAsMS0uMTEsMCwuMTUuMTUsMCwwLDEtLjA1LS4xMi44MS44MSwwLDAsMSwuMzItLjUxLDIuNDEsMi40MSwwLDAsMSwxLjI3LS41MywxLjk0LDEuOTQsMCwwLDEsMS43NS41N0EuMTkuMTksMCwwLDEsMzIuODMsMjguNDNabS01LjExLTEuMjZjLS4xMiwwLS4xNy0uMDctLjE5LS4xNHMuMjgtLjU2LjYyLS44MWEzLjYsMy42LDAsMCwxLDMuNTEtLjQyQTMsMywwLDAsMSwzMywyNi44N2MuMTIuMi4xNS4zNS4wNy40NHMtLjQ0LDAtLjk1LS4yNGE0LjE4LDQuMTgsMCwwLDAtMi0uNDNBMjEuODUsMjEuODUsMCwwLDAsMjcuNzEsMjcuMTdaIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMzUuNSwxMy4yOWMuMSwwLC4xNi0uMTUuMDctLjJhMTEsMTEsMCwwLDAtNC42OS0xLjIzLjA5LjA5LDAsMCwxLS4wNy0uMTQsNC43OCw0Ljc4LDAsMCwxLC44OC0uODkuMDkuMDksMCwwLDAtLjA2LS4xNiwxMi40NiwxMi40NiwwLDAsMC01LjYxLDIsLjA5LjA5LDAsMCwxLS4xMy0uMDksNi4xNiw2LjE2LDAsMCwxLC41OS0xLjQ1LjA4LjA4LDAsMCwwLS4xMS0uMTFBMjIuNzksMjIuNzksMCwwLDAsMjAsMTYuMjRhLjA5LjA5LDAsMCwwLC4xMi4xM0ExOS41MywxOS41MywwLDAsMSwyNywxMy4zMiwxOS4xLDE5LjEsMCwwLDEsMzUuNSwxMy4yOVoiLz48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik0yOC4zNCw2LjQyUzI2LjIzLDQsMjUuNiwzLjhDMjEuNjksMi43NCwxMy4yNCw4LjU3LDcuODQsMTYuMjcsNS42NiwxOS4zOSwyLjUzLDI0LjksNCwyNy43NGExMS40MywxMS40MywwLDAsMCwxLjc5LDEuNzJBNi42NSw2LjY1LDAsMCwxLDEwLDI2Ljc4LDM0LjIxLDM0LjIxLDAsMCwxLDIwLjgsMTEuNjIsNTUuMDksNTUuMDksMCwwLDEsMjguMzQsNi40MloiLz48L2c+PC9nPjwvc3ZnPg=='
236 );
237 }
238 add_action( 'admin_menu', 'mailchimp_sf_add_pages' );
239
240 /**
241 * Request handler
242 *
243 * @return void
244 */
245 function mailchimp_sf_request_handler() {
246 if ( isset( $_POST['mcsf_action'] ) ) {
247 switch ( $_POST['mcsf_action'] ) {
248 case 'logout':
249 // Check capability & Verify nonce
250 if (
251 ! current_user_can( MCSF_CAP_THRESHOLD ) ||
252 ! isset( $_POST['_mcsf_nonce_action'] ) ||
253 ! wp_verify_nonce( sanitize_key( $_POST['_mcsf_nonce_action'] ), 'mc_logout' )
254 ) {
255 wp_die( 'Cheatin&rsquo; huh?' );
256 }
257
258 // erase auth information
259 $options = array( 'mc_api_key', 'mailchimp_sf_access_token', 'mc_datacenter', 'mailchimp_sf_auth_error', 'mailchimp_sf_waiting_for_login' );
260 mailchimp_sf_delete_options( $options );
261 break;
262 case 'change_form_settings':
263 if (
264 ! current_user_can( MCSF_CAP_THRESHOLD ) ||
265 ! isset( $_POST['_mcsf_nonce_action'] ) ||
266 ! wp_verify_nonce( sanitize_key( $_POST['_mcsf_nonce_action'] ), 'update_general_form_settings' )
267 ) {
268 wp_die( 'Cheatin&rsquo; huh?' );
269 }
270
271 // Update the form settings
272 mailchimp_sf_save_general_form_settings();
273 break;
274 }
275 }
276 }
277 add_action( 'init', 'mailchimp_sf_request_handler' );
278
279 /**
280 * Update merge fields
281 *
282 * @return void
283 */
284 function mailchimp_sf_update_merge_fields() {
285 mailchimp_sf_get_merge_vars( get_option( 'mc_list_id' ), true );
286 mailchimp_sf_get_interest_categories( get_option( 'mc_list_id' ), true );
287 update_option( 'mc_merge_field_migrate', true );
288 }
289
290 /**
291 * Get auth key
292 *
293 * @param mixed $salt Salt
294 * @return string
295 */
296 function mailchimp_sf_auth_nonce_key( $salt = null ) {
297 if ( is_null( $salt ) ) {
298 $salt = mailchimp_sf_auth_nonce_salt();
299 }
300 return 'social_authentication' . md5( AUTH_KEY . $salt );
301 }
302
303 /**
304 * Return auth nonce salt
305 *
306 * @return string
307 */
308 function mailchimp_sf_auth_nonce_salt() {
309 return md5( microtime() . isset( $_SERVER['SERVER_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_ADDR'] ) ) : '' );
310 }
311
312 /**
313 * Creates new Mailchimp API v3 object
314 *
315 * @return MailChimp_API | false
316 */
317 function mailchimp_sf_get_api() {
318 // Check for the access token first.
319 $access_token = mailchimp_sf_get_access_token();
320 $data_center = get_option( 'mc_datacenter' );
321 if ( ! empty( $access_token ) && ! empty( $data_center ) ) {
322 return new MailChimp_API( $access_token, $data_center );
323 }
324
325 // Check for the API key if the access token is not available.
326 $key = get_option( 'mc_api_key' );
327 if ( $key ) {
328 return new MailChimp_API( $key );
329 }
330
331 return false;
332 }
333
334 /**
335 * Checks to see if we're storing a password, if so, we need
336 * to upgrade to the API key
337 *
338 * @return bool
339 **/
340 function mailchimp_sf_needs_upgrade() {
341 $igs = get_option( 'mc_interest_groups' );
342
343 if ( false !== $igs // we have an option
344 && (
345 empty( $igs ) || // it can be an empty array (no interest groups)
346 ( is_array( $igs ) && isset( $igs[0]['id'] ) ) // OR it should be a populated array that's well-formed
347 )
348 ) {
349 return false; // no need to upgrade
350 } else {
351 return true; // yeah, let's do it
352 }
353 }
354
355 /**
356 * Deletes all Mailchimp options
357 *
358 * TODO: The options names should be moved to a config file
359 * or to a class dedicated to options
360 **/
361 function mailchimp_sf_delete_setup() {
362 $options = array(
363 'mc_user_id',
364 'mc_use_unsub_link',
365 'mc_list_id',
366 'mc_list_name',
367 'mc_interest_groups',
368 'mc_merge_vars',
369 );
370
371 $igs = get_option( 'mc_interest_groups' );
372 if ( is_array( $igs ) ) {
373 foreach ( $igs as $ig ) {
374 $opt = 'mc_show_interest_groups_' . $ig['id'];
375 $options[] = $opt;
376 }
377 }
378
379 $mv = get_option( 'mc_merge_vars' );
380 if ( is_array( $mv ) ) {
381 foreach ( $mv as $mv_var ) {
382 $opt = 'mc_mv_' . $mv_var['tag'];
383 $options[] = $opt;
384 }
385 }
386
387 mailchimp_sf_delete_options( $options );
388 }
389
390 /**
391 * Gets or sets a frontend message based on parameter passed to it
392 *
393 * Used to convey error messages to the user outside of the WP Admin
394 *
395 * On the plugin settings page, WP admin notices are used exclusively
396 * instead of the frontend message.
397 *
398 * @param mixed $msg Message
399 * @return string/bool depending on get/set
400 */
401 function mailchimp_sf_frontend_msg( $msg = null ) {
402 global $mcsf_msgs;
403
404 // Make sure we're formed properly
405 if ( ! is_array( $mcsf_msgs ) ) {
406 $mcsf_msgs = array();
407 }
408
409 // See if we're getting
410 if ( is_null( $msg ) ) {
411 return implode( '', $mcsf_msgs );
412 }
413
414 // Must be setting
415 $mcsf_msgs[] = $msg;
416 return true;
417 }
418
419 /**
420 * Gets or sets a frontend message based on parameter passed to it
421 *
422 * TODO: Deprecate this function in favor of mailchimp_sf_frontend_msg()
423 *
424 * @param mixed $msg Message
425 * @return string/bool depending on get/set
426 */
427 function mailchimp_sf_global_msg( $msg = null ) {
428 return mailchimp_sf_frontend_msg( $msg );
429 }
430
431 /**
432 * Sets the default options for the option form
433 *
434 * @param string $list_name The Mailchimp list name.
435 * @return void
436 */
437 function mailchimp_sf_set_form_defaults( $list_name = '' ) {
438 update_option( 'mc_header_content', esc_html__( 'Sign up for', 'mailchimp' ) . ' ' . $list_name );
439 update_option( 'mc_submit_text', esc_html__( 'Subscribe', 'mailchimp' ) );
440
441 update_option( 'mc_custom_style', 'off' );
442 update_option( 'mc_double_optin', true );
443 update_option( 'mc_use_unsub_link', 'off' );
444
445 update_option( 'mc_form_border_width', '1' );
446 update_option( 'mc_form_border_color', 'E0E0E0' );
447 update_option( 'mc_form_background', 'FFFFFF' );
448 update_option( 'mc_form_text_color', '3F3F3f' );
449 }
450
451 /**
452 * Saves the General Form settings on the options page
453 *
454 * @return void
455 **/
456 function mailchimp_sf_save_general_form_settings() {
457
458 /*Enable double optin toggle*/
459 if ( isset( $_POST['mc_double_optin'] ) ) {
460 update_option( 'mc_double_optin', true );
461 $msg = esc_html__( 'Double opt-in turned On!', 'mailchimp' );
462 admin_notice_success( $msg );
463 } elseif ( get_option( 'mc_double_optin' ) !== false ) {
464 update_option( 'mc_double_optin', false );
465 $msg = esc_html__( 'Double opt-in turned Off!', 'mailchimp' );
466 admin_notice_success( $msg );
467 }
468
469 /* NUKE the CSS! */
470 if ( isset( $_POST['mc_nuke_all_styles'] ) ) {
471 update_option( 'mc_nuke_all_styles', true );
472 $msg = esc_html__( 'Mailchimp CSS turned Off!', 'mailchimp' );
473 admin_notice_success( $msg );
474 } elseif ( get_option( 'mc_nuke_all_styles' ) !== false ) {
475 update_option( 'mc_nuke_all_styles', false );
476 $msg = esc_html__( 'Mailchimp CSS turned On!', 'mailchimp' );
477 admin_notice_success( $msg );
478 }
479
480 /* Update existing */
481 if ( isset( $_POST['mc_update_existing'] ) ) {
482 update_option( 'mc_update_existing', true );
483 $msg = esc_html__( 'Update existing subscribers turned On!' );
484 admin_notice_success( $msg );
485 } elseif ( get_option( 'mc_update_existing' ) !== false ) {
486 update_option( 'mc_update_existing', false );
487 $msg = esc_html__( 'Update existing subscribers turned Off!' );
488 admin_notice_success( $msg );
489 }
490
491 if ( isset( $_POST['mc_use_unsub_link'] ) ) {
492 update_option( 'mc_use_unsub_link', 'on' );
493 $msg = esc_html__( 'Unsubscribe link turned On!', 'mailchimp' );
494 admin_notice_success( $msg );
495 } elseif ( get_option( 'mc_use_unsub_link' ) !== 'off' ) {
496 update_option( 'mc_use_unsub_link', 'off' );
497 $msg = esc_html__( 'Unsubscribe link turned Off!', 'mailchimp' );
498 admin_notice_success( $msg );
499 }
500
501 $content = isset( $_POST['mc_header_content'] ) ? wp_kses_post( wp_unslash( $_POST['mc_header_content'] ) ) : '';
502 $content = str_replace( "\r\n", '<br/>', $content );
503 update_option( 'mc_header_content', $content );
504
505 $content = isset( $_POST['mc_subheader_content'] ) ? wp_kses_post( wp_unslash( $_POST['mc_subheader_content'] ) ) : '';
506 $content = str_replace( "\r\n", '<br/>', $content );
507 update_option( 'mc_subheader_content', $content );
508
509 $submit_text = isset( $_POST['mc_submit_text'] ) ? sanitize_text_field( wp_unslash( $_POST['mc_submit_text'] ) ) : '';
510 $submit_text = str_replace( "\r\n", '', $submit_text );
511 update_option( 'mc_submit_text', $submit_text );
512
513 // Set Custom Style option
514 update_option( 'mc_custom_style', isset( $_POST['mc_custom_style'] ) ? 'on' : 'off' );
515
516 // we told them not to put these things we are replacing in, but let's just make sure they are listening...
517 if ( isset( $_POST['mc_form_border_width'] ) ) {
518 update_option( 'mc_form_border_width', str_replace( 'px', '', absint( $_POST['mc_form_border_width'] ) ) );
519 }
520 if ( isset( $_POST['mc_form_border_color'] ) ) {
521 update_option( 'mc_form_border_color', str_replace( '#', '', sanitize_text_field( wp_unslash( $_POST['mc_form_border_color'] ) ) ) );
522 }
523 if ( isset( $_POST['mc_form_background'] ) ) {
524 update_option( 'mc_form_background', str_replace( '#', '', sanitize_text_field( wp_unslash( $_POST['mc_form_background'] ) ) ) );
525 }
526 if ( isset( $_POST['mc_form_text_color'] ) ) {
527 update_option( 'mc_form_text_color', str_replace( '#', '', sanitize_text_field( wp_unslash( $_POST['mc_form_text_color'] ) ) ) );
528 }
529
530 // IF NOT DEV MODE
531 $igs = get_option( 'mc_interest_groups' );
532 if ( is_array( $igs ) ) {
533 foreach ( $igs as $mv_var ) {
534 $opt = 'mc_show_interest_groups_' . $mv_var['id'];
535 if ( isset( $_POST[ $opt ] ) ) {
536 update_option( $opt, 'on' );
537 } else {
538 update_option( $opt, 'off' );
539 }
540 }
541 }
542
543 $mv = get_option( 'mc_merge_vars' );
544 if ( is_array( $mv ) ) {
545 foreach ( $mv as $mv_var ) {
546 $opt = 'mc_mv_' . $mv_var['tag'];
547 if ( isset( $_POST[ $opt ] ) || 'Y' === $mv_var['required'] ) {
548 update_option( $opt, 'on' );
549 } else {
550 update_option( $opt, 'off' );
551 }
552 }
553 }
554
555 $msg = esc_html__( 'Successfully Updated your List Subscribe Form Settings!', 'mailchimp' );
556 admin_notice_success( $msg );
557 }
558
559 /**
560 * Sees if the user changed the list, and updates options accordingly
561 **/
562 function mailchimp_sf_change_list_if_necessary() {
563 if ( ! isset( $_POST['mc_list_id'] ) ) {
564 return;
565 }
566
567 if ( empty( $_POST['mc_list_id'] ) ) {
568 $msg = esc_html__( 'Please choose a valid list', 'mailchimp' );
569 admin_notice_error( $msg );
570 return;
571 }
572
573 // Simple permission check before going through all this
574 if ( ! current_user_can( MCSF_CAP_THRESHOLD ) ) { return; }
575
576 $api = mailchimp_sf_get_api();
577 if ( ! $api ) { return; }
578
579 // we *could* support paging, but few users have that many lists (and shouldn't)
580 $lists = $api->get( 'lists', 100, array( 'fields' => 'lists.id,lists.name,lists.email_type_option' ) );
581
582 if ( ! isset( $lists['lists'] ) || is_wp_error( $lists['lists'] ) ) {
583 return;
584 }
585
586 $lists = $lists['lists'];
587
588 if ( is_array( $lists ) && ! empty( $lists ) ) {
589
590 /**
591 * If our incoming list ID (the one chosen in the select dropdown)
592 * is in our array of lists, the set it to be the active list
593 */
594 foreach ( $lists as $key => $list ) {
595 if ( isset( $_POST['mc_list_id'] ) && $list['id'] === $_POST['mc_list_id'] ) {
596 $list_id = sanitize_text_field( wp_unslash( $_POST['mc_list_id'] ) );
597 $list_name = $list['name'];
598 $list_key = $key;
599 }
600
601 $merge_fields = mailchimp_sf_get_merge_vars( $list['id'], false, false );
602 $interests = mailchimp_sf_get_interest_categories( $list['id'], false, false );
603 if ( ! empty( $merge_fields ) ) {
604 update_option( 'mailchimp_sf_merge_fields_' . $list['id'], $merge_fields );
605 }
606 if ( ! empty( $interests ) ) {
607 update_option( 'mailchimp_sf_interest_groups_' . $list['id'], $interests );
608 }
609 }
610
611 $orig_list = get_option( 'mc_list_id' );
612 if ( '' !== $list_id ) {
613 update_option( 'mc_list_id', $list_id );
614 update_option( 'mc_list_name', $list_name );
615 update_option( 'mc_email_type_option', $lists[ $list_key ]['email_type_option'] );
616
617 // See if the user changed the list
618 $new_list = false;
619 if ( $orig_list !== $list_id ) {
620 // The user changed the list, Reset the Form Defaults
621 mailchimp_sf_set_form_defaults( $list_name );
622
623 $new_list = true;
624 }
625
626 // Grab the merge vars and interest groups
627 $mv = mailchimp_sf_get_merge_vars( $list_id, $new_list );
628 $igs = mailchimp_sf_get_interest_categories( $list_id, $new_list );
629
630 $igs_text = ' ';
631 if ( is_array( $igs ) ) {
632 /* translators: %s: count (number) */
633 $igs_text .= sprintf( esc_html__( 'and %s Sets of Interest Groups', 'mailchimp' ), count( $igs ) );
634 }
635
636 $msg = sprintf(
637 /* translators: %s: count (number) */
638 __( '<b>Success!</b> Loaded and saved the info for %d Merge Variables', 'mailchimp' ) . $igs_text,
639 count( $mv )
640 ) . ' ' .
641 esc_html__( 'from your list' ) . ' "' . $list_name . '"<br/><br/>' .
642 esc_html__( 'Now you should either Turn On the Mailchimp Widget or change your options below, then turn it on.', 'mailchimp' );
643
644 admin_notice_success( $msg );
645 }
646
647 // Update the lists option.
648 update_option( 'mailchimp_sf_lists', $lists );
649 }
650 }
651
652 /**
653 * Get merge vars
654 *
655 * @param string $list_id List ID
656 * @param bool $new_list Whether this is a new list
657 * @param bool $update_option Whether to update the option
658 * @return array
659 */
660 function mailchimp_sf_get_merge_vars( $list_id, $new_list, $update_option = true ) {
661 $api = mailchimp_sf_get_api();
662 $mv = $api->get( 'lists/' . $list_id . '/merge-fields', 80 );
663
664 // if we get an error back from the api, exit this process.
665 if ( is_wp_error( $mv ) ) {
666 return;
667 }
668
669 $mv['merge_fields'] = mailchimp_sf_add_email_field( $mv['merge_fields'] );
670 if ( $update_option ) {
671 update_option( 'mc_merge_vars', $mv['merge_fields'] );
672 }
673
674 foreach ( $mv['merge_fields'] as $mv_var ) {
675 $opt = 'mc_mv_' . $mv_var['tag'];
676 if ( $new_list ) {
677 $public = $mv_var['public'] ?? false;
678 if ( ! $public ) {
679 // This is a hidden field, so we don't want to include it.
680 update_option( $opt, 'off' );
681 } else {
682 // We need to set the option to 'on' so that it shows up in the form.
683 update_option( $opt, 'on' );
684 }
685 }
686 }
687 return $mv['merge_fields'];
688 }
689
690 /**
691 * Add email field
692 *
693 * @param array $merge Merge
694 * @return array
695 */
696 function mailchimp_sf_add_email_field( $merge ) {
697 $email = array(
698 'tag' => 'EMAIL',
699 'name' => esc_html__( 'Email Address', 'mailchimp' ),
700 'type' => 'email',
701 'required' => true,
702 'public' => true,
703 'display_order' => 1,
704 'default_value' => null,
705 );
706 array_unshift( $merge, $email );
707 return $merge;
708 }
709
710 /**
711 * Get interest categories
712 *
713 * @param string $list_id List ID
714 * @param bool $new_list Whether this is a new list
715 * @param bool $update_option Whether to update the option
716 * @return array
717 */
718 function mailchimp_sf_get_interest_categories( $list_id, $new_list, $update_option = true ) {
719 $api = mailchimp_sf_get_api();
720 $igs = $api->get( 'lists/' . $list_id . '/interest-categories', 60 );
721
722 // if we get an error back from the api, exis
723 if ( is_wp_error( $igs ) ) {
724 return;
725 }
726
727 if ( is_array( $igs ) ) {
728 $key = 0;
729 foreach ( $igs['categories'] as $ig ) {
730 $groups = $api->get( 'lists/' . $list_id . '/interest-categories/' . $ig['id'] . '/interests', 60 );
731 $igs['categories'][ $key ]['groups'] = $groups['interests'];
732 $opt = 'mc_show_interest_groups_' . $ig['id'];
733
734 // turn them all on by default
735 if ( $new_list ) {
736 update_option( $opt, 'on' );
737 }
738 ++$key;
739 }
740 }
741
742 if ( $update_option ) {
743 update_option( 'mc_interest_groups', $igs['categories'] );
744 }
745
746 return $igs['categories'];
747 }
748
749
750 /**
751 * Outputs the Settings/Options page
752 */
753 function mailchimp_sf_setup_page() {
754 $path = plugin_dir_path( __FILE__ );
755 require_once $path . '/includes/admin/templates/settings.php';
756 }
757
758 /**
759 * Register the widget.
760 *
761 * @return void
762 */
763 function mailchimp_sf_register_widgets() {
764 if ( mailchimp_sf_get_api() ) {
765 register_widget( 'Mailchimp_SF_Widget' );
766 }
767 }
768 add_action( 'widgets_init', 'mailchimp_sf_register_widgets' );
769
770 /**
771 * Add shortcode
772 *
773 * @return string
774 */
775 function mailchimp_sf_shortcode() {
776 ob_start();
777 mailchimp_sf_signup_form();
778 return ob_get_clean();
779 }
780 add_shortcode( 'mailchimpsf_form', 'mailchimp_sf_shortcode' );
781
782 /**
783 * Cleans up merge fields and interests to make them
784 * API 3.0-friendly.
785 *
786 * @param [type] $merge Merge fields
787 * @param [type] $igs Interest groups
788 * @param string $email_type Email type
789 * @param string $email Email
790 * @param string|false $status Status The subscription status ('subscribed', 'unsubscribed', 'pending', etc.) or false if an error occurred.
791 * @param string $double_optin Whether double opt-in is enabled. "1" for enabled and "" for disabled.
792 * @return stdClass
793 */
794 function mailchimp_sf_subscribe_body( $merge, $igs, $email_type, $email, $status, $double_optin ) {
795 $body = new stdClass();
796 $body->email_address = $email;
797 $body->email_type = $email_type;
798 $body->merge_fields = $merge;
799
800 if ( ! empty( $igs ) ) {
801 $body->interests = $igs;
802 }
803
804 // Early return for already subscribed users
805 if ( 'subscribed' === $status ) {
806 return $body;
807 }
808
809 // Subscribe the email immediately unless double opt-in is enabled
810 // "unsubscribed" and "subscribed" existing emails have been excluded at this stage
811 // "pending" emails should follow double opt-in rules
812 $body->status = $double_optin ? 'pending' : 'subscribed';
813
814 return $body;
815 }
816
817 /**
818 * Check the status of a subscriber in the list.
819 *
820 * @param string $endpoint API endpoint to check the status.
821 * @return string|false The subscription status ('subscribed', 'unsubscribed', 'pending', etc.) or false if the API returned 404 or an error occurred.
822 */
823 function mailchimp_sf_check_status( $endpoint ) {
824 $endpoint .= '?fields=status';
825 $api = mailchimp_sf_get_api();
826 $subscriber = $api->get( $endpoint, null );
827 if ( is_wp_error( $subscriber ) ) {
828 return false;
829 }
830 return $subscriber['status'];
831 }
832
833 /**
834 * Validate phone
835 *
836 * @param array $opt_val Option value
837 * @param array $data Data
838 * @return void
839 */
840 function mailchimp_sf_merge_validate_phone( $opt_val, $data ) {
841 // This filters out all 'falsey' elements
842 $opt_val = array_filter( $opt_val );
843 // If they weren't all empty
844 if ( ! $opt_val ) {
845 return;
846 }
847
848 $opt_val = implode( '-', $opt_val );
849 if ( strlen( $opt_val ) < 12 ) {
850 $opt_val = '';
851 }
852
853 if ( ! preg_match( '/[0-9]{0,3}-[0-9]{0,3}-[0-9]{0,4}/A', $opt_val ) ) {
854 /* translators: %s: field name */
855 $message = sprintf( esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) );
856 $error = new WP_Error( 'mc_phone_validation', $message );
857 return $error;
858 }
859
860 return $opt_val;
861 }
862
863 /**
864 * Validate address
865 *
866 * @param array $opt_val Option value
867 * @param array $data Data
868 * @return mixed
869 */
870 function mailchimp_sf_merge_validate_address( $opt_val, $data ) {
871 if ( 'Y' === $data['required'] ) {
872 if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) {
873 /* translators: %s: field name */
874 $message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) );
875 $error = new WP_Error( 'invalid_address_merge', $message );
876 return $error;
877 }
878 } elseif ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) {
879 return false;
880 }
881
882 $merge = new stdClass();
883 $merge->addr1 = $opt_val['addr1'];
884 $merge->addr2 = $opt_val['addr2'];
885 $merge->city = $opt_val['city'];
886 $merge->state = $opt_val['state'];
887 $merge->zip = $opt_val['zip'];
888 $merge->country = $opt_val['country'];
889 return $merge;
890 }
891
892 /**
893 * Verify key
894 *
895 * @param MailChimp_API $api API instance
896 * @return mixed
897 */
898 function mailchimp_sf_verify_key( $api ) {
899 $user = $api->get( '' );
900 if ( is_wp_error( $user ) ) {
901 return $user;
902 }
903
904 // Might as well set this data if we have it already.
905 $valid_roles = array( 'owner', 'admin', 'manager' );
906 if ( isset( $user['role'] ) && in_array( $user['role'], $valid_roles, true ) ) {
907 update_option( 'mc_api_key', $api->key );
908 update_option( 'mc_user', $user );
909 update_option( 'mc_datacenter', $api->datacenter );
910
911 } else {
912 $msg = esc_html__( 'API Key must belong to "Owner", "Admin", or "Manager."', 'mailchimp' );
913 return new WP_Error( 'mc-invalid-role', $msg );
914 }
915 }
916
917 /**
918 * Update profile URL.
919 *
920 * @param string $email Email
921 * @return string
922 */
923 function mailchimp_sf_update_profile_url( $email ) {
924 $dc = get_option( 'mc_datacenter' );
925 // This is the expected encoding for emails.
926 $eid = base64_encode( $email ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- ignoring because this is the expected data for the endpoint
927 $user = get_option( 'mc_user' );
928 $list_id = get_option( 'mc_list_id' );
929 $url = 'http://' . $dc . '.list-manage.com/subscribe/send-email?u=' . $user['account_id'] . '&id=' . $list_id . '&e=' . $eid;
930 return $url;
931 }
932
933 /**
934 * Delete options
935 *
936 * @param array $options Options
937 * @return void
938 */
939 function mailchimp_sf_delete_options( $options = array() ) {
940 foreach ( $options as $option ) {
941 delete_option( $option );
942 }
943 }
944
945 /**********************
946 * Utility Functions *
947 **********************/
948 /**
949 * Utility function to allow placement of plugin in plugins, mu-plugins, child or parent theme's plugins folders
950 *
951 * This function must be ran _very early_ in the load process, as it sets up important constants for the rest of the plugin
952 */
953 function mailchimp_sf_where_am_i() {
954 $locations = array(
955 'plugins' => array(
956 'dir' => plugin_dir_path( __FILE__ ),
957 'url' => plugins_url(),
958 ),
959 'mu_plugins' => array(
960 'dir' => plugin_dir_path( __FILE__ ),
961 'url' => plugins_url(),
962 ),
963 'template' => array(
964 'dir' => trailingslashit( get_template_directory() ) . 'plugins/',
965 'url' => trailingslashit( get_template_directory_uri() ) . 'plugins/',
966 ),
967 'stylesheet' => array(
968 'dir' => trailingslashit( get_stylesheet_directory() ) . 'plugins/',
969 'url' => trailingslashit( get_stylesheet_directory_uri() ) . 'plugins/',
970 ),
971 );
972
973 // Set defaults
974 $mscf_dirbase = trailingslashit( basename( __DIR__ ) ); // Typically wp-mailchimp/ or mailchimp/
975 $mscf_dir = trailingslashit( plugin_dir_path( __FILE__ ) );
976 $mscf_url = trailingslashit( plugins_url( '', __FILE__ ) );
977
978 // Try our hands at finding the real location
979 foreach ( $locations as $key => $loc ) {
980 $dir = trailingslashit( $loc['dir'] ) . $mscf_dirbase;
981 $url = trailingslashit( $loc['url'] ) . $mscf_dirbase;
982 if ( is_file( $dir . basename( __FILE__ ) ) ) {
983 $mscf_dir = $dir;
984 $mscf_url = $url;
985 break;
986 }
987 }
988
989 // Define our complete filesystem path
990 define( 'MCSF_DIR', $mscf_dir );
991
992 // Define our complete URL to the plugin folder
993 define( 'MCSF_URL', $mscf_url );
994 }
995
996
997 /**
998 * MODIFIED VERSION of wp_verify_nonce from WP Core. Core was not overridden to prevent problems when replacing
999 * something universally.
1000 *
1001 * Verify that correct nonce was used with time limit.
1002 *
1003 * The user is given an amount of time to use the token, so therefore, since the
1004 * UID and $action remain the same, the independent variable is the time.
1005 *
1006 * @param string $nonce Nonce that was used in the form to verify
1007 * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
1008 * @return bool Whether the nonce check passed or failed.
1009 */
1010 function mailchimp_sf_verify_nonce( $nonce, $action = -1 ) {
1011 $user = wp_get_current_user();
1012 $uid = (int) $user->ID;
1013 if ( ! $uid ) {
1014 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
1015 }
1016
1017 if ( empty( $nonce ) ) {
1018 return false;
1019 }
1020
1021 $token = 'MAILCHIMP';
1022 $i = wp_nonce_tick();
1023
1024 // Nonce generated 0-12 hours ago
1025 $expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
1026 if ( hash_equals( $expected, $nonce ) ) {
1027 return 1;
1028 }
1029
1030 // Nonce generated 12-24 hours ago
1031 $expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
1032 if ( hash_equals( $expected, $nonce ) ) {
1033 return 2;
1034 }
1035
1036 // Invalid nonce
1037 return false;
1038 }
1039
1040
1041 /**
1042 * MODIFIED VERSION of wp_create_nonce from WP Core. Core was not overridden to prevent problems when replacing
1043 * something universally.
1044 *
1045 * Creates a cryptographic token tied to a specific action, user, and window of time.
1046 *
1047 * @param string $action Scalar value to add context to the nonce.
1048 * @return string The token.
1049 */
1050 function mailchimp_sf_create_nonce( $action = -1 ) {
1051 $user = wp_get_current_user();
1052 $uid = (int) $user->ID;
1053 if ( ! $uid ) {
1054 /** This filter is documented in wp-includes/pluggable.php */
1055 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
1056 }
1057
1058 $token = 'MAILCHIMP';
1059 $i = wp_nonce_tick();
1060
1061 return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
1062 }
1063
1064 /**
1065 * Get Mailchimp Access Token.
1066 *
1067 * @since 1.6.0
1068 * @return string|bool
1069 */
1070 function mailchimp_sf_get_access_token() {
1071 $access_token = get_option( 'mailchimp_sf_access_token' );
1072 if ( empty( $access_token ) ) {
1073 return false;
1074 }
1075
1076 $data_encryption = new Mailchimp_Data_Encryption();
1077 $access_token = $data_encryption->decrypt( $access_token );
1078
1079 // If decryption fails, display notice to user to re-authenticate.
1080 if ( false === $access_token ) {
1081 update_option( 'mailchimp_sf_auth_error', true );
1082 }
1083
1084 return $access_token;
1085 }
1086
1087 /**
1088 * Should display Mailchimp Signup form.
1089 *
1090 * @since 1.6.0
1091 * @return bool
1092 */
1093 function mailchimp_sf_should_display_form() {
1094 return mailchimp_sf_get_api() && ! get_option( 'mailchimp_sf_auth_error' ) && get_option( 'mc_list_id' );
1095 }
1096