PluginProbe
Mailchimp List Subscribe Form / 1.8.1
Mailchimp List Subscribe Form v1.8.1
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.1, at mailchimp.php

1,101 lines 37.7 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.1
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.1' );
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 (
568 ! current_user_can( MCSF_CAP_THRESHOLD ) ||
569 ! isset( $_POST['update_mc_list_id_nonce'] ) ||
570 ! wp_verify_nonce( sanitize_key( $_POST['update_mc_list_id_nonce'] ), 'update_mc_list_id_action' )
571 ) {
572 wp_die( 'Security check failed.' );
573 }
574
575 if ( empty( $_POST['mc_list_id'] ) ) {
576 $msg = esc_html__( 'Please choose a valid list', 'mailchimp' );
577 admin_notice_error( $msg );
578 return;
579 }
580
581 $api = mailchimp_sf_get_api();
582 if ( ! $api ) { return; }
583
584 // we *could* support paging, but few users have that many lists (and shouldn't)
585 $lists = $api->get( 'lists', 100, array( 'fields' => 'lists.id,lists.name,lists.email_type_option' ) );
586
587 if ( ! isset( $lists['lists'] ) || is_wp_error( $lists['lists'] ) ) {
588 return;
589 }
590
591 $lists = $lists['lists'];
592
593 if ( is_array( $lists ) && ! empty( $lists ) ) {
594
595 /**
596 * If our incoming list ID (the one chosen in the select dropdown)
597 * is in our array of lists, the set it to be the active list
598 */
599 foreach ( $lists as $key => $list ) {
600 if ( isset( $_POST['mc_list_id'] ) && $list['id'] === $_POST['mc_list_id'] ) {
601 $list_id = sanitize_text_field( wp_unslash( $_POST['mc_list_id'] ) );
602 $list_name = $list['name'];
603 $list_key = $key;
604 }
605
606 $merge_fields = mailchimp_sf_get_merge_vars( $list['id'], false, false );
607 $interests = mailchimp_sf_get_interest_categories( $list['id'], false, false );
608 if ( ! empty( $merge_fields ) ) {
609 update_option( 'mailchimp_sf_merge_fields_' . $list['id'], $merge_fields );
610 }
611 if ( ! empty( $interests ) ) {
612 update_option( 'mailchimp_sf_interest_groups_' . $list['id'], $interests );
613 }
614 }
615
616 $orig_list = get_option( 'mc_list_id' );
617 if ( '' !== $list_id ) {
618 update_option( 'mc_list_id', $list_id );
619 update_option( 'mc_list_name', $list_name );
620 update_option( 'mc_email_type_option', $lists[ $list_key ]['email_type_option'] );
621
622 // See if the user changed the list
623 $new_list = false;
624 if ( $orig_list !== $list_id ) {
625 // The user changed the list, Reset the Form Defaults
626 mailchimp_sf_set_form_defaults( $list_name );
627
628 $new_list = true;
629 }
630
631 // Grab the merge vars and interest groups
632 $mv = mailchimp_sf_get_merge_vars( $list_id, $new_list );
633 $igs = mailchimp_sf_get_interest_categories( $list_id, $new_list );
634
635 $igs_text = ' ';
636 if ( is_array( $igs ) ) {
637 /* translators: %s: count (number) */
638 $igs_text .= sprintf( esc_html__( 'and %s Sets of Interest Groups', 'mailchimp' ), count( $igs ) );
639 }
640
641 $msg = sprintf(
642 /* translators: %s: count (number) */
643 __( '<b>Success!</b> Loaded and saved the info for %d Merge Variables', 'mailchimp' ) . $igs_text,
644 count( $mv )
645 ) . ' ' .
646 esc_html__( 'from your list' ) . ' "' . $list_name . '"<br/><br/>' .
647 esc_html__( 'Now you should either Turn On the Mailchimp Widget or change your options below, then turn it on.', 'mailchimp' );
648
649 admin_notice_success( $msg );
650 }
651
652 // Update the lists option.
653 update_option( 'mailchimp_sf_lists', $lists );
654 }
655 }
656
657 /**
658 * Get merge vars
659 *
660 * @param string $list_id List ID
661 * @param bool $new_list Whether this is a new list
662 * @param bool $update_option Whether to update the option
663 * @return array
664 */
665 function mailchimp_sf_get_merge_vars( $list_id, $new_list, $update_option = true ) {
666 $api = mailchimp_sf_get_api();
667 $mv = $api->get( 'lists/' . $list_id . '/merge-fields', 80 );
668
669 // if we get an error back from the api, exit this process.
670 if ( is_wp_error( $mv ) ) {
671 return;
672 }
673
674 $mv['merge_fields'] = mailchimp_sf_add_email_field( $mv['merge_fields'] );
675 if ( $update_option ) {
676 update_option( 'mc_merge_vars', $mv['merge_fields'] );
677 }
678
679 foreach ( $mv['merge_fields'] as $mv_var ) {
680 $opt = 'mc_mv_' . $mv_var['tag'];
681 if ( $new_list ) {
682 $public = $mv_var['public'] ?? false;
683 if ( ! $public ) {
684 // This is a hidden field, so we don't want to include it.
685 update_option( $opt, 'off' );
686 } else {
687 // We need to set the option to 'on' so that it shows up in the form.
688 update_option( $opt, 'on' );
689 }
690 }
691 }
692 return $mv['merge_fields'];
693 }
694
695 /**
696 * Add email field
697 *
698 * @param array $merge Merge
699 * @return array
700 */
701 function mailchimp_sf_add_email_field( $merge ) {
702 $email = array(
703 'tag' => 'EMAIL',
704 'name' => esc_html__( 'Email Address', 'mailchimp' ),
705 'type' => 'email',
706 'required' => true,
707 'public' => true,
708 'display_order' => 1,
709 'default_value' => null,
710 );
711 array_unshift( $merge, $email );
712 return $merge;
713 }
714
715 /**
716 * Get interest categories
717 *
718 * @param string $list_id List ID
719 * @param bool $new_list Whether this is a new list
720 * @param bool $update_option Whether to update the option
721 * @return array
722 */
723 function mailchimp_sf_get_interest_categories( $list_id, $new_list, $update_option = true ) {
724 $api = mailchimp_sf_get_api();
725 $igs = $api->get( 'lists/' . $list_id . '/interest-categories', 60 );
726
727 // if we get an error back from the api, exis
728 if ( is_wp_error( $igs ) ) {
729 return;
730 }
731
732 if ( is_array( $igs ) ) {
733 $key = 0;
734 foreach ( $igs['categories'] as $ig ) {
735 $groups = $api->get( 'lists/' . $list_id . '/interest-categories/' . $ig['id'] . '/interests', 60 );
736 $igs['categories'][ $key ]['groups'] = $groups['interests'];
737 $opt = 'mc_show_interest_groups_' . $ig['id'];
738
739 // turn them all on by default
740 if ( $new_list ) {
741 update_option( $opt, 'on' );
742 }
743 ++$key;
744 }
745 }
746
747 if ( $update_option ) {
748 update_option( 'mc_interest_groups', $igs['categories'] );
749 }
750
751 return $igs['categories'];
752 }
753
754
755 /**
756 * Outputs the Settings/Options page
757 */
758 function mailchimp_sf_setup_page() {
759 $path = plugin_dir_path( __FILE__ );
760 require_once $path . '/includes/admin/templates/settings.php';
761 }
762
763 /**
764 * Register the widget.
765 *
766 * @return void
767 */
768 function mailchimp_sf_register_widgets() {
769 if ( mailchimp_sf_get_api() ) {
770 register_widget( 'Mailchimp_SF_Widget' );
771 }
772 }
773 add_action( 'widgets_init', 'mailchimp_sf_register_widgets' );
774
775 /**
776 * Add shortcode
777 *
778 * @return string
779 */
780 function mailchimp_sf_shortcode() {
781 ob_start();
782 mailchimp_sf_signup_form();
783 return ob_get_clean();
784 }
785 add_shortcode( 'mailchimpsf_form', 'mailchimp_sf_shortcode' );
786
787 /**
788 * Cleans up merge fields and interests to make them
789 * API 3.0-friendly.
790 *
791 * @param [type] $merge Merge fields
792 * @param [type] $igs Interest groups
793 * @param string $email_type Email type
794 * @param string $email Email
795 * @param string|false $status Status The subscription status ('subscribed', 'unsubscribed', 'pending', etc.) or false if an error occurred.
796 * @param string $double_optin Whether double opt-in is enabled. "1" for enabled and "" for disabled.
797 * @return stdClass
798 */
799 function mailchimp_sf_subscribe_body( $merge, $igs, $email_type, $email, $status, $double_optin ) {
800 $body = new stdClass();
801 $body->email_address = $email;
802 $body->email_type = $email_type;
803 $body->merge_fields = $merge;
804
805 if ( ! empty( $igs ) ) {
806 $body->interests = $igs;
807 }
808
809 // Early return for already subscribed users
810 if ( 'subscribed' === $status ) {
811 return $body;
812 }
813
814 // Subscribe the email immediately unless double opt-in is enabled
815 // "unsubscribed" and "subscribed" existing emails have been excluded at this stage
816 // "pending" emails should follow double opt-in rules
817 $body->status = $double_optin ? 'pending' : 'subscribed';
818
819 return $body;
820 }
821
822 /**
823 * Check the status of a subscriber in the list.
824 *
825 * @param string $endpoint API endpoint to check the status.
826 * @return string|false The subscription status ('subscribed', 'unsubscribed', 'pending', etc.) or false if the API returned 404 or an error occurred.
827 */
828 function mailchimp_sf_check_status( $endpoint ) {
829 $endpoint .= '?fields=status';
830 $api = mailchimp_sf_get_api();
831 $subscriber = $api->get( $endpoint, null );
832 if ( is_wp_error( $subscriber ) ) {
833 return false;
834 }
835 return $subscriber['status'];
836 }
837
838 /**
839 * Validate phone
840 *
841 * @param array $opt_val Option value
842 * @param array $data Data
843 * @return void
844 */
845 function mailchimp_sf_merge_validate_phone( $opt_val, $data ) {
846 // This filters out all 'falsey' elements
847 $opt_val = array_filter( $opt_val );
848 // If they weren't all empty
849 if ( ! $opt_val ) {
850 return;
851 }
852
853 $opt_val = implode( '-', $opt_val );
854 if ( strlen( $opt_val ) < 12 ) {
855 $opt_val = '';
856 }
857
858 if ( ! preg_match( '/[0-9]{0,3}-[0-9]{0,3}-[0-9]{0,4}/A', $opt_val ) ) {
859 /* translators: %s: field name */
860 $message = sprintf( esc_html__( '%s must consist of only numbers', 'mailchimp' ), esc_html( $data['name'] ) );
861 $error = new WP_Error( 'mc_phone_validation', $message );
862 return $error;
863 }
864
865 return $opt_val;
866 }
867
868 /**
869 * Validate address
870 *
871 * @param array $opt_val Option value
872 * @param array $data Data
873 * @return mixed
874 */
875 function mailchimp_sf_merge_validate_address( $opt_val, $data ) {
876 if ( 'Y' === $data['required'] ) {
877 if ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) {
878 /* translators: %s: field name */
879 $message = sprintf( esc_html__( 'You must fill in %s.', 'mailchimp' ), esc_html( $data['name'] ) );
880 $error = new WP_Error( 'invalid_address_merge', $message );
881 return $error;
882 }
883 } elseif ( empty( $opt_val['addr1'] ) || empty( $opt_val['city'] ) ) {
884 return false;
885 }
886
887 $merge = new stdClass();
888 $merge->addr1 = $opt_val['addr1'];
889 $merge->addr2 = $opt_val['addr2'];
890 $merge->city = $opt_val['city'];
891 $merge->state = $opt_val['state'];
892 $merge->zip = $opt_val['zip'];
893 $merge->country = $opt_val['country'];
894 return $merge;
895 }
896
897 /**
898 * Verify key
899 *
900 * @param MailChimp_API $api API instance
901 * @return mixed
902 */
903 function mailchimp_sf_verify_key( $api ) {
904 $user = $api->get( '' );
905 if ( is_wp_error( $user ) ) {
906 return $user;
907 }
908
909 // Might as well set this data if we have it already.
910 $valid_roles = array( 'owner', 'admin', 'manager' );
911 if ( isset( $user['role'] ) && in_array( $user['role'], $valid_roles, true ) ) {
912 update_option( 'mc_api_key', $api->key );
913 update_option( 'mc_user', $user );
914 update_option( 'mc_datacenter', $api->datacenter );
915
916 } else {
917 $msg = esc_html__( 'API Key must belong to "Owner", "Admin", or "Manager."', 'mailchimp' );
918 return new WP_Error( 'mc-invalid-role', $msg );
919 }
920 }
921
922 /**
923 * Update profile URL.
924 *
925 * @param string $email Email
926 * @return string
927 */
928 function mailchimp_sf_update_profile_url( $email ) {
929 $dc = get_option( 'mc_datacenter' );
930 // This is the expected encoding for emails.
931 $eid = base64_encode( $email ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- ignoring because this is the expected data for the endpoint
932 $user = get_option( 'mc_user' );
933 $list_id = get_option( 'mc_list_id' );
934 $url = 'http://' . $dc . '.list-manage.com/subscribe/send-email?u=' . $user['account_id'] . '&id=' . $list_id . '&e=' . $eid;
935 return $url;
936 }
937
938 /**
939 * Delete options
940 *
941 * @param array $options Options
942 * @return void
943 */
944 function mailchimp_sf_delete_options( $options = array() ) {
945 foreach ( $options as $option ) {
946 delete_option( $option );
947 }
948 }
949
950 /**********************
951 * Utility Functions *
952 **********************/
953 /**
954 * Utility function to allow placement of plugin in plugins, mu-plugins, child or parent theme's plugins folders
955 *
956 * This function must be ran _very early_ in the load process, as it sets up important constants for the rest of the plugin
957 */
958 function mailchimp_sf_where_am_i() {
959 $locations = array(
960 'plugins' => array(
961 'dir' => plugin_dir_path( __FILE__ ),
962 'url' => plugins_url(),
963 ),
964 'mu_plugins' => array(
965 'dir' => plugin_dir_path( __FILE__ ),
966 'url' => plugins_url(),
967 ),
968 'template' => array(
969 'dir' => trailingslashit( get_template_directory() ) . 'plugins/',
970 'url' => trailingslashit( get_template_directory_uri() ) . 'plugins/',
971 ),
972 'stylesheet' => array(
973 'dir' => trailingslashit( get_stylesheet_directory() ) . 'plugins/',
974 'url' => trailingslashit( get_stylesheet_directory_uri() ) . 'plugins/',
975 ),
976 );
977
978 // Set defaults
979 $mscf_dirbase = trailingslashit( basename( __DIR__ ) ); // Typically wp-mailchimp/ or mailchimp/
980 $mscf_dir = trailingslashit( plugin_dir_path( __FILE__ ) );
981 $mscf_url = trailingslashit( plugins_url( '', __FILE__ ) );
982
983 // Try our hands at finding the real location
984 foreach ( $locations as $key => $loc ) {
985 $dir = trailingslashit( $loc['dir'] ) . $mscf_dirbase;
986 $url = trailingslashit( $loc['url'] ) . $mscf_dirbase;
987 if ( is_file( $dir . basename( __FILE__ ) ) ) {
988 $mscf_dir = $dir;
989 $mscf_url = $url;
990 break;
991 }
992 }
993
994 // Define our complete filesystem path
995 define( 'MCSF_DIR', $mscf_dir );
996
997 // Define our complete URL to the plugin folder
998 define( 'MCSF_URL', $mscf_url );
999 }
1000
1001
1002 /**
1003 * MODIFIED VERSION of wp_verify_nonce from WP Core. Core was not overridden to prevent problems when replacing
1004 * something universally.
1005 *
1006 * Verify that correct nonce was used with time limit.
1007 *
1008 * The user is given an amount of time to use the token, so therefore, since the
1009 * UID and $action remain the same, the independent variable is the time.
1010 *
1011 * @param string $nonce Nonce that was used in the form to verify
1012 * @param string|int $action Should give context to what is taking place and be the same when nonce was created.
1013 * @return bool Whether the nonce check passed or failed.
1014 */
1015 function mailchimp_sf_verify_nonce( $nonce, $action = -1 ) {
1016 $user = wp_get_current_user();
1017 $uid = (int) $user->ID;
1018 if ( ! $uid ) {
1019 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
1020 }
1021
1022 if ( empty( $nonce ) ) {
1023 return false;
1024 }
1025
1026 $token = 'MAILCHIMP';
1027 $i = wp_nonce_tick();
1028
1029 // Nonce generated 0-12 hours ago
1030 $expected = substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
1031 if ( hash_equals( $expected, $nonce ) ) {
1032 return 1;
1033 }
1034
1035 // Nonce generated 12-24 hours ago
1036 $expected = substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
1037 if ( hash_equals( $expected, $nonce ) ) {
1038 return 2;
1039 }
1040
1041 // Invalid nonce
1042 return false;
1043 }
1044
1045
1046 /**
1047 * MODIFIED VERSION of wp_create_nonce from WP Core. Core was not overridden to prevent problems when replacing
1048 * something universally.
1049 *
1050 * Creates a cryptographic token tied to a specific action, user, and window of time.
1051 *
1052 * @param string $action Scalar value to add context to the nonce.
1053 * @return string The token.
1054 */
1055 function mailchimp_sf_create_nonce( $action = -1 ) {
1056 $user = wp_get_current_user();
1057 $uid = (int) $user->ID;
1058 if ( ! $uid ) {
1059 /** This filter is documented in wp-includes/pluggable.php */
1060 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action );
1061 }
1062
1063 $token = 'MAILCHIMP';
1064 $i = wp_nonce_tick();
1065
1066 return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 );
1067 }
1068
1069 /**
1070 * Get Mailchimp Access Token.
1071 *
1072 * @since 1.6.0
1073 * @return string|bool
1074 */
1075 function mailchimp_sf_get_access_token() {
1076 $access_token = get_option( 'mailchimp_sf_access_token' );
1077 if ( empty( $access_token ) ) {
1078 return false;
1079 }
1080
1081 $data_encryption = new Mailchimp_Data_Encryption();
1082 $access_token = $data_encryption->decrypt( $access_token );
1083
1084 // If decryption fails, display notice to user to re-authenticate.
1085 if ( false === $access_token ) {
1086 update_option( 'mailchimp_sf_auth_error', true );
1087 }
1088
1089 return $access_token;
1090 }
1091
1092 /**
1093 * Should display Mailchimp Signup form.
1094 *
1095 * @since 1.6.0
1096 * @return bool
1097 */
1098 function mailchimp_sf_should_display_form() {
1099 return mailchimp_sf_get_api() && ! get_option( 'mailchimp_sf_auth_error' ) && get_option( 'mc_list_id' );
1100 }
1101