PluginProbe
Store Locator for WordPress📍 / trunk
Store Locator for WordPress📍 vtrunk
trunk 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2
storelocator / storelocator.php

storelocator.php in Store Locator for WordPress📍 trunk, at storelocator.php

362 lines 15.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Plugin Name: Store Locator
5 * Version: 1.2.2
6 * Plugin URI: https://locatestore.com/
7 * Description: Create a store locator for your website in minutes. Add all the store locations in google sheets and embed map on your website. There is no coding involved here.
8 * Author: Micro.company
9 * Author URI: https://micro.company/
10 * License: GPLv2 or later
11 */
12
13 /**
14 * Display instructional notice on top of dashboard pages.
15 * Removed when user dismisses the notice.
16 */
17 // exit if accessed directly
18 if (!defined('ABSPATH')) {
19 exit;
20 }
21
22 $storelocator_active_plugin = [];
23 $base = plugin_basename(__FILE__);
24 $wp_plugins_dir = defined('WP_PLUGIN_DIR') ? WP_PLUGIN_DIR : $wp_content_dir . '/plugins';
25 if (is_admin()) {
26 if (!function_exists('get_plugin_data')) {
27 require_once(ABSPATH . 'wp-admin/includes/plugin.php');
28 }
29 $storelocator_active_plugin[$base] = get_plugin_data($wp_plugins_dir . '/' . $base, true, false);
30 }
31
32 define('STLR_PLUGIN_DIR', str_replace('\\', '/', dirname(__FILE__)));
33 define('STLR_DIR_URL', plugin_dir_url(__FILE__));
34
35 function storelocator_settings_link($links)
36 {
37 $settings_link = '<a href="options-general.php?page=storelocator">Settings</a>';
38 $support_link = '<a href="https://reach.at/storelocator" target="_blank">Support</a>';
39
40 array_push($links, $settings_link);
41 array_push($links, $support_link);
42
43 return $links;
44 }
45
46 $plugin = plugin_basename(__FILE__);
47 add_filter(
48 "plugin_action_links_$plugin",
49 'storelocator_settings_link'
50 );
51
52
53
54 function storelocator_activation_redirect($plugin)
55 {
56 if ($plugin == plugin_basename(__FILE__)) {
57 exit(wp_redirect(admin_url('admin.php?page=storelocator')));
58 }
59 }
60 add_action(
61 'activated_plugin',
62 'storelocator_activation_redirect'
63 );
64
65
66
67 function storelocator_getting_started_notice()
68 {
69
70 global $current_user;
71 $user_id = $current_user->ID;
72 /* Check that the user hasn't already clicked to ignore the message */
73 if (!get_user_meta($user_id, 'storelocator_getting_started_notice') && !(isset($_GET['page']) && $_GET['page'] == 'storelocator')) {
74
75 printf(__('<div class="notice" style="display: flex;flex-direction:column;gap:10px;padding:20px;">
76 <a href="https://locatestore.com" class="logo" ><img src="%2$s" width="150px" alt="Storelocator logo"/></a>
77 <div>
78 <h4 style="margin: 0;">Getting started with your Store Locator 🚀</h4>
79
80 <ol>
81 <li>Install the <a href="https://workspace.google.com/marketplace/app/store_locator/734551689349" target="_blank" rel="noreferrer">Google marketplace addon.</a></li>
82 <li><a href="https://sheets.new" target="_blank" rel="noreferrer">Create a new Google Sheet</a> and go to <em>Extensions > Store Locator > Get started</em>.</li>
83 <li>Copy the Store Locator URL / shortcode and visit <a href="options-general.php?page=storelocator">plugin settings</a>.</li>
84 </ol>
85 </div>
86 <a href="%1$s">Dismiss</a>
87 </div>'), '?storelocator_notice_ignore=1',STLR_DIR_URL . "storelocator-logo.png");
88 }
89 }
90 add_action('admin_notices', 'storelocator_getting_started_notice');
91
92
93 function storelocator_notice_ignore()
94 {
95 global $current_user;
96 $user_id = $current_user->ID;
97 /* If user clicks to ignore the notice, add that to their user meta */
98 if (isset($_GET['storelocator_notice_ignore']) && '1' == $_GET['storelocator_notice_ignore']) {
99 add_user_meta($user_id, 'storelocator_getting_started_notice', 'true', true);
100 }
101 }
102 add_action('admin_init', 'storelocator_notice_ignore');
103
104 /**
105 * Convert shortcode into embedded iframe.
106 */
107
108
109 function storelocator_embed_shortcode($atts)
110 {
111 $atts = array_change_key_case((array) $atts, CASE_LOWER);
112 extract(shortcode_atts(array(
113 'id' => '',
114 'width' => '100%',
115 'height' => "600"
116 ), $atts));
117 if (true || !($id == '')) {
118 // add source = wp
119 return '<iframe src="' . esc_url("https://locatestore.com/" . $id . "?source=wordpress") . '" allow="geolocation" width="' . esc_attr($width) . '" height="' . esc_attr($height) . '" frameBorder="0" allowfullscreen style="width:100% !important;max-width:100% !important;margin:10px;"></iframe>';
120 } else {
121 return "⚠ Please enter a valid storelocator id.";
122 }
123 }
124 add_shortcode('storelocator', 'storelocator_embed_shortcode');
125
126 /**
127 * Register OEmbed config. This automatically loads the iframe from plain url.
128 */
129
130 wp_oembed_add_provider('https://locatestore.com/*', "https://locatestore.com/services/oembed");
131
132 /**
133 * Automatically generate storelocator page.
134 */
135
136 function storelocator_check_page_existence($page_slug)
137 {
138 $page = get_page_by_path($page_slug, OBJECT, 'page');
139
140 return isset($page);
141 }
142 function add_storelocator_page($url, $path)
143 {
144 try {
145 if (storelocator_check_page_existence($path)) throw new Exception("Page already exists");
146 $storelocator_page = array(
147 'post_title' => 'Store Locator',
148 'post_name' => $path,
149 'post_content' => '[storelocator id="' . substr($url, 24) . '"]',
150 'post_status' => 'publish',
151 'post_author' => 1,
152 'post_type' => 'page',
153 );
154 wp_insert_post($storelocator_page, true);
155 update_option("storelocator_url", $url);
156 update_option("storelocator_path", $path);
157
158 return true;
159 } catch (Exception $e) {
160 return false;
161 }
162 }
163
164 /**
165 * Create settings menu
166 */
167
168 // Refer below link to understand how to add multiple settings section to same page
169 // http://www.mendoweb.be/blog/wordpress-settings-api-multiple-forms-on-same-page/
170 function storelocator_add_menu()
171 {
172
173 add_menu_page(
174 'StoreLocator', // page <title>Title</title>
175 'StoreLocator', // menu link text
176 'manage_options', // capability to access the page
177 'storelocator', // page URL slug
178 'storelocator_settings_template', // callback function /w content
179 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/Pgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDIwMDEwOTA0Ly9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9UUi8yMDAxL1JFQy1TVkctMjAwMTA5MDQvRFREL3N2ZzEwLmR0ZCI+CjxzdmcgdmVyc2lvbj0iMS4wIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiB3aWR0aD0iNTEyLjAwMDAwMHB0IiBoZWlnaHQ9IjUxMi4wMDAwMDBwdCIgdmlld0JveD0iMCAwIDUxMi4wMDAwMDAgNTEyLjAwMDAwMCIKIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIG1lZXQiPgoKPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsNTEyLjAwMDAwMCkgc2NhbGUoMC4xMDAwMDAsLTAuMTAwMDAwKSIKZmlsbD0iIzAwMDAwMCIgc3Ryb2tlPSJub25lIj4KPHBhdGggZD0iTTIzODcgNTA0OSBjLTQ4NCAtNDcgLTk2NCAtMjg1IC0xMjYzIC02MjcgLTI0MyAtMjc4IC0zODcgLTYxOSAtNDM0Ci0xMDMxIC0xNiAtMTM1IC03IC00ODkgMTUgLTYzMSAxMDAgLTYzOSA0MTMgLTEzMTAgODkxIC0xOTA4IDI2NyAtMzM1IDYyNAotNjc3IDc4MiAtNzUwIDc3IC0zNSAxNzcgLTQ4IDI1NCAtMzQgMTM1IDI1IDIzOSA5NyA0ODIgMzMzIDczNCA3MTEgMTIyMQoxNjI2IDEzMTYgMjQ3NCAxNCAxMzAgMTIgNDMyIC00IDU1NSAtNTQgMzk5IC0xOTQgNzIyIC00MzAgOTkyIC0zNzggNDMzCi0xMDIxIDY4MyAtMTYwOSA2Mjd6IG00NDMgLTMxNSBjNjM2IC0xMDYgMTE1OSAtNTg5IDEzMTQgLTEyMTQgMzcgLTE1MSA0NgotMjI1IDQ2IC00MDIgMCAtMTEwIC02IC0xOTAgLTIwIC0yNzEgLTEwMCAtNTg5IC01MjggLTEwODcgLTEwOTUgLTEyNzYgLTE4NgotNjIgLTI3OCAtNzUgLTUxNSAtNzUgLTIzNyAwIC0zMjkgMTMgLTUxNSA3NSAtNTcwIDE5MCAtOTk1IDY4NyAtMTA5NiAxMjgyCi0xOCAxMDMgLTIwIDE1MSAtMTcgMzEyIDQgMTYxIDkgMjA4IDMyIDMwOSAxMTEgNDc5IDQwNyA4NjcgODM2IDEwOTQgMzEzIDE2NQo2NzcgMjI0IDEwMzAgMTY2eiIvPgo8cGF0aCBkPSJNMTU2NyA0MDg4IGMtMTkgLTE1IC0xOTUgLTM4NSAtMjA0IC00MjkgLTE1IC03OCAzNyAtMTU5IDEzMCAtMjAwCjQzIC0xOSA2OSAtMjMgMTUyIC0yMyAxNjEgMCAyMjggNDAgMjk4IDE3OSBsMzYgNzAgMSAtNDggYzAgLTI2IDcgLTYxIDE0IC03NgoxOSAtMzYgODAgLTkwIDEyMyAtMTA3IDkwIC0zOCAyMzYgLTMzIDMyMSAxMCA1MSAyNiAxMTIgODYgMTEyIDExMSAwIDggNSAxNQoxMCAxNSA2IDAgMTAgLTcgMTAgLTE1IDAgLTI0IDYxIC04NSAxMTAgLTExMCAxMDMgLTUyIDI0NSAtNTEgMzQ0IDMgNjkgMzgKMTA2IDg3IDExNSAxNTQgbDcgNTMgMzIgLTY1IGMxOCAtMzUgNDUgLTc3IDYwIC05MyA1NiAtNTkgMTY1IC05MyAyNjcgLTg0CjE1NSAxNSAyNTUgOTMgMjU1IDIwMCAwIDM4IC0xODEgNDM2IC0yMDcgNDU1IC0xMyA5IC0yMjggMTIgLTk5MyAxMiAtNzY1IDAKLTk4MCAtMyAtOTkzIC0xMnoiLz4KPHBhdGggZD0iTTE3NjAgMzMyMCBjLTE0IC00IC00OSAtOCAtNzcgLTkgbC01MyAtMSAtMiAtNDIyIC0zIC00MjMgLTgyIC0zCi04MyAtMyAwIC04OSAwIC05MCAxMTAwIDAgMTEwMCAwIDAgOTAgMCA5MCAtODAgMCAtODAgMCAtMiA0MjMgLTMgNDIyIC02NSA2CmMtMzYgMyAtNzcgMTAgLTkyIDE0IGwtMjggNyAtMiAtNDMzIC0zIC00MzQgLTc0NSAwIC03NDUgMCAtMyA0MzMgYy0yIDMzNiAtNQo0MzIgLTE1IDQzMSAtNiAtMSAtMjMgLTUgLTM3IC05eiIvPgo8L2c+Cjwvc3ZnPgo=', // menu icon
180 null // priority
181 );
182 }
183 add_action('admin_menu', 'storelocator_add_menu');
184
185
186 function storelocator_settings_template()
187 {
188 $storelocator_url = sanitize_text_field(get_option('storelocator_url_input'));
189 $storelocator_path = sanitize_text_field(get_option('storelocator_path_input'));
190
191 $current_url = sanitize_text_field(get_option("storelocator_url"));
192 $current_path = sanitize_text_field(get_option("storelocator_path"));
193
194
195 $valid_url_pattern = "/^https:\/\/locatestore.com\/.{3,}$/i";
196 $valid_old_url_pattern = "/^https:\/\/storelocator.site\/.{3,}$/i";
197 $valid_path_pattern = "/^([A-Za-z0-9-_])+$/";
198
199 $is_valid_url = (preg_match($valid_url_pattern, $storelocator_url) == 1) || (preg_match($valid_old_url_pattern, $storelocator_url) == 1);
200 $is_valid_path = preg_match($valid_path_pattern, $storelocator_path) == 1;
201 $has_path_changed = ($current_path !== $storelocator_path);
202 $has_url_changed = ($current_url !== $storelocator_url);
203
204 // Defaults to true. Is false only when page generation fails.
205 $page_generated = true;
206
207
208 if ($is_valid_url && $is_valid_path) {
209 try {
210 if ($has_path_changed || !storelocator_check_page_existence($current_path)) {
211 $page_generated = add_storelocator_page($storelocator_url, $storelocator_path);
212 } elseif ($has_url_changed) {
213 $page = get_page_by_path($current_path, OBJECT, 'page');
214 $page->post_content = '[storelocator id="' . substr($storelocator_url, 24) . '"]';
215 wp_update_post($page, true);
216 update_option("storelocator_url", $storelocator_url);
217 }
218 } catch (Exception $e) {
219 }
220 }
221
222 $errors = array();
223
224 if (!$is_valid_url && false !== get_option('storelocator_url_input')) array_push($errors, "Invalid store locator URL. Please enter a valid URL of the form <code>https://locatestore.com/&lt;id&gt;</code>");
225 if (!$is_valid_path && false !== get_option('storelocator_path_input')) array_push($errors, "Invalid store locator path. Path names can only contain alphabets, digits and the characters <code>-</code> and <code>_</code> ");
226 if (!$page_generated) array_push($errors, "Couldn't generate the store locator page. Are you sure the page doesn't already exist ?");
227
228
229
230 require_once(STLR_PLUGIN_DIR . '/settings.php');
231 }
232
233 /*
234 * Settings template
235 */
236
237 function storelocator_plugin_settings_init()
238 {
239
240 add_settings_section('storelocator-settings-section-generate-page', '', '', 'storelocator');
241
242 add_settings_field('storelocator-url-input', 'Store Locator URL', 'storelocator_url_callback', 'storelocator', 'storelocator-settings-section-generate-page');
243 register_setting('storelocator-settings-generate-page', 'storelocator_url_input', array('type' => 'string', 'sanitize_callback' => 'sanitize_text_field'));
244
245 add_settings_field('storelocator-path-input', 'Wordpress page URL', 'storelocator_path_callback', 'storelocator', 'storelocator-settings-section-generate-page');
246 register_setting('storelocator-settings-generate-page', 'storelocator_path_input', array('type' => 'string', 'sanitize_callback' => 'sanitize_text_field'));
247 }
248 add_action('admin_init', 'storelocator_plugin_settings_init');
249
250
251
252 function storelocator_url_callback()
253 {
254 $storelocator_url = get_option('storelocator_url_input');
255
256 ?>
257 <input name="storelocator_url_input" class="regular-text" type="text" style="margin:0" placeholder="https://locatestore.com/<id>" value="<?php echo isset($storelocator_url) ? esc_attr($storelocator_url) : '' ?>" />
258 <?php
259 }
260
261 function storelocator_path_callback()
262 {
263 $storelocator_path = get_option('storelocator_path_input');
264
265 ?> <div style="display:flex;flex-wrap:wrap;"> <code style="display:flex;flex-direction:column;justify-content:center;border:1px solid gray;border-right:0;margin:0;">
266 <div><?php echo get_site_url(); ?>/</div>
267 </code>
268 <input name="storelocator_path_input" class="regular-text" id="storelocator_path_input" type="text" style="max-width:147px;margin:0;" placeholder="storelocator" value="<?php echo esc_attr(get_option('storelocator_path_input') === false ? 'storelocator' : get_option('storelocator_path_input')); ?>" />
269 </div>
270 <?php
271 }
272
273 // For reset. Will be removed in production.
274
275 function storelocator_reset_handler()
276 {
277 delete_option('storelocator_path_input');
278 delete_option('storelocator_url_input');
279 delete_option('storelocator_url');
280 delete_option('storelocator_path');
281 wp_die();
282 }
283 add_action('wp_ajax_reset', 'storelocatorreset_handler');
284
285
286
287
288 function storelocator_admin_enqueue_scripts()
289 {
290 require_once(STLR_PLUGIN_DIR . '/feedback-form.php');
291 wp_enqueue_style('storelocator-modal-css', plugin_dir_url(__FILE__) . 'css/modal.css');
292 storelocator_add_feedback_form();
293 }
294 add_action('admin_enqueue_scripts', 'storelocator_admin_enqueue_scripts');
295
296 function storelocator_submit_uninstall_reason_action()
297 {
298 global $wp_version, $storelocator_active_plugin, $current_user;
299
300 if (!isset($_REQUEST['storelocator_ajax_nonce']) || !wp_verify_nonce($_REQUEST['storelocator_ajax_nonce'], 'storelocator_ajax_nonce')) {
301 wp_die('Invalid request', 'Invalid request', array('response' => 403));
302 }
303
304 if (!current_user_can('manage_options')) {
305 wp_die('Unauthorized', 'Unauthorized', array('response' => 403));
306 }
307
308 $reason_id = isset($_REQUEST['reason_id']) ? stripcslashes(sanitize_text_field($_REQUEST['reason_id'])) : '';
309 $basename = isset($_REQUEST['plugin']) ? stripcslashes(sanitize_text_field($_REQUEST['plugin'])) : '';
310
311 if (empty($reason_id) || empty($basename)) {
312 exit;
313 }
314
315 $reason_info = isset($_REQUEST['reason_info']) ? stripcslashes(sanitize_textarea_field($_REQUEST['reason_info'])) : '';
316 if (!empty($reason_info)) {
317 $reason_info = substr($reason_info, 0, 255);
318 }
319 $is_anonymous = isset($_REQUEST['is_anonymous']) && 1 == $_REQUEST['is_anonymous'];
320
321 $options = array(
322 'product' => 'STORELOCATOR_WP_PLUGIN',
323 'reason_id' => $reason_id,
324 'reason_info' => $reason_info,
325 );
326
327 if (!$is_anonymous) {
328
329
330 $options['url'] = get_site_url();
331 $options['wp_version'] = $wp_version;
332 $options['plugin_version'] = $storelocator_active_plugin[$basename]['Version'];
333
334 $options['email'] = $current_user->data->user_email;
335 }
336
337 /* send data */
338
339 wp_remote_post(
340 "https://locatestore.com/services/wordpress/churn",
341 array(
342 'method' => 'POST',
343 'body' => $options,
344 'timeout' => 15,
345 )
346 );
347 exit;
348 }
349 add_action('wp_ajax_storelocator_submit_uninstall_reason_action', 'storelocator_submit_uninstall_reason_action');
350
351
352 /**
353 * Proper ob_end_flush() for all levels
354 *
355 * This replaces the WordPress `wp_ob_end_flush_all()` function
356 * with a replacement that doesn't cause PHP notices.
357 */
358 remove_action('shutdown', 'wp_ob_end_flush_all', 1);
359 add_action('shutdown', function () {
360 while (@ob_end_flush());
361 });
362