PluginProbe
Caddy – WooCommerce Side Cart & Free Shipping Bar / trunk
Caddy – WooCommerce Side Cart & Free Shipping Bar vtrunk
3.2.0 3.1.1 trunk 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8 1.8.1 1.8.2 1.9 1.9.2 1.9.3 All 46 releases
caddy / caddy.php

caddy.php in Caddy – WooCommerce Side Cart & Free Shipping Bar trunk, at caddy.php

334 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: Caddy – WooCommerce Side Cart & Free Shipping Bar
4 * Plugin URI: https://usecaddy.com
5 * Description: A high performance, conversion-boosting side cart for your WooCommerce store that improves the shopping experience & helps grow your sales.
6 * Version: 3.2.0
7 * Author: Caddy
8 * Author URI: https://usecaddy.com
9 * License: GPL-2.0+
10 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
11 * Text Domain: caddy
12 * Domain Path: /languages
13 * Requires at least: 6.5
14 * Requires PHP: 7.4
15 *
16 * WC requires at least: 7.0
17 * WC tested up to: 10.9.4
18 */
19
20 // If this file is called directly, abort.
21 if ( ! defined( 'WPINC' ) ) {
22 die;
23 }
24
25 /*
26 * Define all constants for the plugin
27 */
28 if ( ! defined( 'CADDY_VERSION' ) ) {
29 define( 'CADDY_VERSION', '3.2.0' );
30 }
31 if ( ! defined( 'CADDY_PLUGIN_FILE' ) ) {
32 define( 'CADDY_PLUGIN_FILE', __FILE__ );
33 }
34 if ( ! defined( 'CADDY_DIR_URL' ) ) {
35 define( 'CADDY_DIR_URL', untrailingslashit( plugins_url( '/', CADDY_PLUGIN_FILE ) ) );
36 }
37
38 // If Caddy Premium v3+ is active, bail out — Premium replaces all free functionality.
39 // For older Premium versions (< 3.0.0) we must NOT bail, because they depend on
40 // classes from the free plugin (e.g. Caddy_Admin). We show an upgrade notice instead.
41 if ( defined( 'CADDY_PREMIUM_VERSION' ) || defined( 'CADDY_PREMIUM_PLUGIN_FILE' ) ) {
42 $caddy_premium_ver = defined( 'CADDY_PREMIUM_VERSION' ) ? CADDY_PREMIUM_VERSION : '0';
43 if ( version_compare( $caddy_premium_ver, '3.0.0', '>=' ) ) {
44 return;
45 }
46 // Old Premium detected — continue loading so it doesn't crash, and warn the admin.
47 add_action( 'admin_notices', function () {
48 if ( ! current_user_can( 'update_plugins' ) ) {
49 return;
50 }
51 echo '<div class="notice notice-error"><p>';
52 echo '<strong>' . esc_html__( 'Caddy Pro update required:', 'caddy' ) . '</strong> ';
53 echo esc_html__( 'Your version of Caddy Pro is not compatible with Caddy 3.0. Please update Caddy Pro to version 3.0 or later to avoid errors.', 'caddy' );
54 echo '</p></div>';
55 } );
56 }
57
58 if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
59 require_once( ABSPATH . '/wp-admin/includes/plugin.php' );
60 }
61
62 $caddy_wc_missing = false;
63 if ( is_multisite() ) {
64 if ( is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
65 $caddy_wc_missing = ! is_plugin_active_for_network( 'woocommerce/woocommerce.php' );
66 } else {
67 $caddy_wc_missing = ! is_plugin_active( 'woocommerce/woocommerce.php' );
68 }
69 } else {
70 $caddy_wc_missing = ! is_plugin_active( 'woocommerce/woocommerce.php' );
71 }
72
73 if ( $caddy_wc_missing ) {
74 add_action( 'admin_notices', 'caddy_wc_requirements_error' );
75 return;
76 }
77 unset( $caddy_wc_missing );
78
79 /**
80 * If WC requirements are not match
81 */
82 function caddy_wc_requirements_error() {
83 ?>
84 <div class="error notice"><p>
85 <strong><?php esc_html_e( 'The WooCommerce plugin needs to be installed and activated in order for Caddy to work properly.', 'caddy' ); ?></strong> <?php esc_html_e( 'Please activate WooCommerce to enable Caddy.', 'caddy' ); ?>
86 </p></div>
87 <?php
88 }
89
90 /**
91 * The code that runs during plugin activation.
92 * This action is documented in includes/class-caddy-activator.php
93 */
94 function caddy_activate() {
95 require_once plugin_dir_path( __FILE__ ) . 'includes/class-caddy-activator.php';
96 Caddy_Activator::activate();
97
98 // Ask for telemetry consent on the post-activation screen instead of nagging
99 // with an admin notice. Sites that already answered are not asked again.
100 if ( class_exists( 'Pulse_Telemetry_Client' ) ) {
101 Pulse_Telemetry_Client::flag_activation( 'caddy' );
102 }
103 }
104
105 /**
106 * The code that runs during plugin deactivation.
107 * This action is documented in includes/class-caddy-deactivator.php
108 */
109 function caddy_deactivate() {
110 require_once plugin_dir_path( __FILE__ ) . 'includes/class-caddy-deactivator.php';
111 Caddy_Deactivator::deactivate();
112 }
113
114 register_activation_hook( __FILE__, 'caddy_activate' );
115 register_deactivation_hook( __FILE__, 'caddy_deactivate' );
116
117 /**
118 * The core plugin class that is used to define internationalization,
119 * admin-specific hooks, and public-facing site hooks.
120 */
121 require plugin_dir_path( __FILE__ ) . 'includes/class-caddy.php';
122
123 /**
124 * The plugin class that is used to register and load the cart widget.
125 */
126 require plugin_dir_path( __FILE__ ) . 'includes/class-caddy-cart-widget.php';
127
128 /**
129 * The plugin class that is used to register and load the saved items widget.
130 */
131 require plugin_dir_path( __FILE__ ) . 'includes/class-caddy-saved-items-widget.php';
132
133 /**
134 * Elementor integration (registers Caddy widgets when Elementor is active)
135 */
136 require plugin_dir_path( __FILE__ ) . 'includes/integrations/elementor/class-caddy-elementor.php';
137 add_action( 'init', array( 'Caddy_Elementor', 'init' ) );
138
139 /**
140 * Load notices
141 */
142 require_once plugin_dir_path( __FILE__ ) . 'includes/class-caddy-notices.php';
143
144 /**
145 * Load composer
146 */
147 if (file_exists(__DIR__ . '/vendor/autoload.php')) {
148 require_once __DIR__ . '/vendor/autoload.php';
149 }
150
151 /**
152 * Pulse client: deactivation survey + optional (opt-in) telemetry,
153 * reporting to the Pulse Hub. Replaces Caddy's legacy email survey.
154 */
155 require_once plugin_dir_path( __FILE__ ) . 'includes/pulse-client/class-pulse-client.php';
156 require_once plugin_dir_path( __FILE__ ) . 'includes/pulse-client/class-pulse-survey-client.php';
157 require_once plugin_dir_path( __FILE__ ) . 'includes/pulse-client/class-pulse-telemetry-client.php';
158
159 if ( ! defined( 'CADDY_PULSE_HUB_URL' ) ) {
160 // The Caddy Hub lives on the Caddy store (validates Caddy licenses locally).
161 // Override via wp-config or the `pulse_hub_url` filter.
162 define( 'CADDY_PULSE_HUB_URL', 'https://usecaddy.com' );
163 }
164
165 add_action( 'plugins_loaded', 'caddy_boot_pulse_client' );
166 function caddy_boot_pulse_client() {
167 // Registered on plugins_loaded (not admin_init) so the telemetry client's own
168 // admin_init hook is added before admin_init fires. Admin-only work, so bail on
169 // front-end and cron requests. is_admin() is true for admin-ajax, so the survey
170 // and opt-in AJAX handlers still register.
171 if ( ! is_admin() ) {
172 return;
173 }
174
175 // Caddy Pro reports under the same 'caddy' slug and carries the license key +
176 // pro tier, so it is the authority when installed. Bail here to avoid a second
177 // survey modal, telemetry notice, and duplicate AJAX handlers when both are active.
178 if ( defined( 'CADDY_PREMIUM_VERSION' ) ) {
179 return;
180 }
181
182 // Caddy Free has no license, so license_key stays empty and the hub treats it
183 // as anonymous + hardened. Caddy Pro passes its EDD license key here instead.
184 $common = array(
185 'brand' => 'caddy',
186 'plugin_slug' => 'caddy',
187 'hub_url' => CADDY_PULSE_HUB_URL,
188 'license_key' => '',
189 'tier' => 'free',
190 'plugin_version' => CADDY_VERSION,
191 'privacy_url' => 'https://usecaddy.com/privacy-policy',
192 'branding' => array(
193 'name' => 'Caddy',
194 'logo' => plugins_url( 'admin/img/caddy-logo.svg', CADDY_PLUGIN_FILE ),
195 ),
196 );
197
198 new Pulse_Survey_Client(
199 array_merge(
200 $common,
201 array(
202 'plugin_basename' => plugin_basename( CADDY_PLUGIN_FILE ),
203 )
204 )
205 );
206
207 new Pulse_Telemetry_Client(
208 array_merge(
209 $common,
210 array(
211 'custom_data' => 'caddy_pulse_feature_snapshot',
212 'parent_slug' => 'caddy',
213 'settings_url' => admin_url( 'admin.php?page=caddy' ),
214 )
215 )
216 );
217
218 // Native toggle style + Privacy settings row. Registered here (not at file
219 // scope) so they never double up when Pro supersedes Free above.
220 add_filter( 'pulse_telemetry_toggle_control_caddy', 'caddy_pulse_toggle_control', 10, 3 );
221 add_action( 'caddy_general_settings_end', 'caddy_pulse_render_privacy_setting' );
222 }
223
224 /**
225 * Render the Pulse telemetry opt-out using Caddy's native toggle style, so it
226 * matches the other settings switches. Keeps the `pulse-tel-toggle` input class
227 * so the client's AJAX handler still binds.
228 *
229 * @param string $html Default control markup.
230 * @param bool $enabled Current opt-in state.
231 * @param string $id Input id.
232 * @return string
233 */
234 function caddy_pulse_toggle_control( $html, $enabled, $id ) {
235 ob_start();
236 ?>
237 <div class="cc-toggle cc-toggle--size-small">
238 <input type="checkbox" id="<?php echo esc_attr( $id ); ?>" class="pulse-tel-toggle" value="enabled" <?php checked( $enabled ); ?> />
239 <label for="<?php echo esc_attr( $id ); ?>">
240 <div class="cc-toggle__switch" data-checked="On" data-unchecked="Off"></div>
241 </label>
242 </div>
243 <?php
244 return ob_get_clean();
245 }
246
247 /**
248 * Render the Pulse "Privacy" telemetry toggle at the end of the General
249 * settings tab. Hooks the plugin's own settings-end action so the shared
250 * settings partial does not need editing.
251 */
252 function caddy_pulse_render_privacy_setting() {
253 echo '<h2><i class="dashicons dashicons-lightbulb section-icons"></i>&nbsp;' . esc_html__( 'Help Improve Caddy', 'caddy' ) . '</h2>';
254 do_action( 'pulse_telemetry_settings_caddy' );
255 }
256
257 /**
258 * Feature-usage snapshot for telemetry (only sent when the user opts in).
259 *
260 * @return array
261 */
262 function caddy_pulse_feature_snapshot() {
263 // These options store the strings 'enabled'/'disabled' (or a numeric
264 // amount for the shipping meter), so compare explicitly. A bool cast
265 // would read 'disabled' as true.
266 return array(
267 'free_shipping_meter' => (float) get_option( 'cc_free_shipping_amount', 0 ) > 0,
268 'save_for_later' => 'enabled' === get_option( 'cc_enable_sfl_options', 'disabled' ),
269 'recommendations' => 'enabled' === get_option( 'cc_product_recommendation', 'disabled' ),
270 );
271 }
272
273 /**
274 * Begins execution of the plugin.
275 *
276 * Since everything within the plugin is registered via hooks,
277 * then kicking off the plugin from this point in the file does
278 * not affect the page life cycle.
279 *
280 * @since 1.0.0
281 */
282 function caddy_run() {
283
284 $plugin = new Caddy();
285 $plugin->run();
286
287 }
288
289 caddy_run();
290
291 /**
292 * Determine whether Caddy Pro is installed and licensed.
293 *
294 * The license option is written by Caddy Pro and remains in the database after
295 * Pro is deactivated or deleted, so it cannot be trusted on its own. Pro must
296 * also be loaded for its settings and screens to exist.
297 *
298 * @return bool True when Pro is active and its license is valid.
299 */
300 function caddy_pro_is_active() {
301
302 return class_exists( 'Caddy_Premium' ) && 'valid' === get_option( 'caddy_premium_edd_license_status' );
303 }
304
305 /**
306 * Add plugin settings link.
307 *
308 * @param $caddy_links
309 *
310 * @return mixed
311 */
312 function caddy_add_settings_link( $caddy_links ) {
313
314 $caddy_links = array_merge( array( '<a href="' . esc_url( admin_url( '/admin.php?page=caddy&amp;tab=settings' ) ) . '">' . esc_html__( 'Settings', 'caddy' ) . '</a>' ), $caddy_links );
315
316 return $caddy_links;
317 }
318
319 $caddy_plugin = plugin_basename( __FILE__ );
320 add_filter( "plugin_action_links_$caddy_plugin", 'caddy_add_settings_link' );
321
322 /**
323 * Declaring WooCommerce HPOS support
324 *
325 */
326 add_action( 'before_woocommerce_init', function() {
327 if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
328 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
329 }
330 } );
331
332 // Initialize the admin notice dismissal library
333 add_action('admin_init', array('PAnD', 'init'));
334