PluginProbe
WP Go Maps Block / trunk
WP Go Maps Block vtrunk
trunk 1.0.0
wp-go-maps-block / wp-go-maps-block.php

wp-go-maps-block.php in WP Go Maps Block trunk, at wp-go-maps-block.php

444 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 * Plugin Name: WP Go Maps Block
4 * Plugin URI: https://wordpress.org/plugins/wp-go-maps-block
5 * Description: The easiest-to-use Google Maps plugin is now available as a standalone block! Create custom Google or OpenLayers maps with high-quality markers, and easily add your map to WordPress posts or pages.
6 * Version: 1.0.0
7 * Author: WP Go Maps (formerly WP Google Maps)
8 * Author URI: https://www.wpgmaps.com
9 * Text Domain: wp-go-maps-block
10 * License: GPLv2
11 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
12 */
13
14 /*
15 * 1.0.0 - TBD
16 * Launch!
17 */
18
19 namespace WPGMZA\Standalone\Gutenberg;
20
21 if(!defined('ABSPATH')){
22 exit;
23 }
24
25 class MapBlock {
26 const SHORTCODE_PROXY_SLUG = 'wpgmza';
27
28 private $cachedVersion = null;
29
30 /**
31 * Constructor
32 */
33 public function __construct(){
34 $this->hooks();
35 }
36
37 /**
38 * All hooks and shortcode registers happen here
39 *
40 * @return void
41 */
42 public function hooks(){
43 add_action('enqueue_block_assets', array($this, 'onEnqueueBlockAssets'));
44 add_action('init', array($this, 'onInit'));
45
46 add_filter('wpgmza_internal_engine_build_version_plugins', array($this, 'getBuildVersion'));
47 }
48
49 /**
50 * On init delegate
51 *
52 * @return void
53 */
54 public function onInit(){
55 if($this->checkRequirements()){
56 $this->registerBlock();
57 }
58 }
59
60 /**
61 * On block assets enqueue delegate
62 *
63 * @return void
64 */
65 public function onEnqueueBlockAssets(){
66 if(!is_admin() || !$this->checkRequirements()){
67 return;
68 }
69
70 $versionString = $this->getVersion();
71
72 $blockAssets = array(
73 "wp-blocks",
74 "wp-i18n"
75 );
76
77 if(!wp_script_is('wp-edit-widgets') && !wp_script_is('wp-customize-widgets')){
78 $blockAssets[] = "wp-editor";
79 }
80
81 $path = plugin_dir_url(__FILE__);
82 wp_register_script(
83 "wpgmza-standalone-map-block",
84 $path . "js/block.js",
85 $blockAssets,
86 $versionString
87 );
88
89 wp_localize_script("wpgmza-standalone-map-block", 'wpgmzaStandaloneBlockLocalized',
90 array(
91 'defaultIcon' => $path . 'images/icon.png',
92 'blinkyIcon' => $path . 'images/blinky.png',
93 'hasFullPlugin' => $this->hasFullPlugin() ? 'true' : 'false',
94 'fullPluginLink' => admin_url('plugin-install.php?tab=plugin-information&plugin=wp-google-maps'),
95 'fullPluginNotices' => array(
96 (object) array( "title" => __('Want to add unlimited markers to your maps?', 'wp-go-maps-block') ),
97 (object) array( "title" => __('Want to create polygons and polylines?', 'wp-go-maps-block') ),
98 (object) array( "title" => __('Need to add shapes to your maps?', 'wp-go-maps-block') ),
99 (object) array( "title" => __('Did you know we also have a Store locator?', 'wp-go-maps-block') ),
100 ),
101 'fullPluginFeatures' => array(
102 __('Unlimited Markers', 'wp-go-maps-block'),
103 __('Store Locator', 'wp-go-maps-block'),
104 __('Map Themes', 'wp-go-maps-block'),
105 __('Polygons & Polylines', 'wp-go-maps-block'),
106 __('Much more!', 'wp-go-maps-block')
107 ),
108 'mapListPageLink' => admin_url('admin.php?page=wp-google-maps-menu')
109 )
110 );
111
112 wp_register_style(
113 "wpgmza-standalone-map-block",
114 $path . "css/block.css",
115 array(),
116 $versionString
117 );
118
119 /* For the previews, also enqueue OL - We will only do OL for now */
120 wp_register_style('wpgmza_block_ol_api_call', $path . 'lib/ol.css', array(), $versionString);
121 wp_register_script('wpgmza_block_ol_api_call', $path . 'lib/ol.js', array(), $versionString);
122 }
123
124 /**
125 * Register the map block
126 *
127 * @return void
128 */
129 public function registerBlock(){
130 $path = plugin_dir_path(__FILE__);
131
132 register_block_type_from_metadata(
133 $path,
134 array(
135 'render_callback' => array($this, 'onRender')
136 )
137 );
138 }
139
140 /**
141 * Render the map block, without the use of a shortcode specifically
142 *
143 * @return void
144 */
145 public function onRender($attributes){
146 $html = "";
147
148 /* Prepare the attributes */
149 $defaults = array(
150 "id" => "1",
151 "zoom" => false,
152 "width" => false,
153 "height" => false,
154 "map_engine" => "open-layers",
155 "google_maps_api_key" => "",
156 "lat" => "",
157 "lng" => "",
158 "address" => "",
159 "alignment" => "center",
160 "infowindow_mode" => "click"
161 );
162
163 /* Leverage shortcode_atts to combine defaults with passed attributes */
164 $attributes = shortcode_atts($defaults, $attributes);
165
166 /* Convert attributes over into an object */
167 $attributes = (object) $attributes;
168
169 /* Attribute cleanup */
170 $attributes->id = !empty($attributes->id) && !empty(intval($attributes->id)) ? intval($attributes->id) : 1;
171 $attributes->map_engine = !empty($attributes->map_engine) ? $attributes->map_engine : 'open-layers';
172
173 /* Escape the attributes */
174 foreach($attributes as $key => $value){
175 $attributes->{$key} = esc_attr($value);
176 }
177
178 if(!$this->hasFullPlugin()){
179 /* Only our block plugin is in use */
180 $styles = array(
181 'display' => 'block',
182 'width' => !empty($attributes->width) ? esc_attr($attributes->width) : '100%',
183 'height' => !empty($attributes->height) ? esc_attr($attributes->height) : '400px',
184 'overflow' => 'hidden',
185 'position' => 'relative'
186 );
187
188 $classes = array('wpgmza_map', 'wpgmza_standalone_map_block');
189 if(!empty($attributes->classname)){
190 $classes[] = trim($attributes->classname);
191 }
192
193 switch($attributes->alignment){
194 case 'left':
195 $classes[] = "wpgmza-auto-left";
196 break;
197 case 'center':
198 $classes[] = "wpgmza-auto-center";
199 break;
200 case 'right':
201 $classes[] = "wpgmza-auto-right";
202 break;
203 }
204
205 $elemAttributes = array(
206 "id" => "wpgmza_map_block_{$attributes->id}",
207 "class" => implode(" ", $classes),
208 "style" => $this->prepareInlineAttributes($styles, ";", ":", ""),
209 "data-maps-engine" => $attributes->map_engine,
210 "data-build-engine" => 'standalone-block',
211 "data-icon" => plugin_dir_url(__FILE__) . 'images/icon.png',
212 "data-lat" => $attributes->lat,
213 "data-lng" => $attributes->lng,
214 "data-zoom" => $attributes->zoom,
215 "data-address" => $attributes->address,
216 "data-infowindow-mode" => $attributes->infowindow_mode
217 );
218
219
220 $elemAttributes = $this->prepareInlineAttributes($elemAttributes);
221 $html = "<div class='wpgmza_map_wrapper'><div {$elemAttributes}></div></div>";
222 } else {
223 /* Full plugin is in use, we need to proxy it */
224 $styles = array(
225 'width' => !empty($attributes->width) ? esc_attr($attributes->width) : '100%',
226 'height' => !empty($attributes->height) ? esc_attr($attributes->height) : '400px',
227 );
228
229 $classes = array();
230 if(!empty($attributes->classname)){
231 $classes[] = trim($attributes->classname);
232 }
233
234 switch($attributes->alignment){
235 case 'left':
236 $classes[] = "wpgmza-proxied-left";
237 break;
238 case 'center':
239 $classes[] = "wpgmza-proxied-center";
240 break;
241 case 'right':
242 $classes[] = "wpgmza-proxied-right";
243 break;
244 }
245
246 $elemAttributes = array(
247 "class" => implode(" ", $classes),
248 "style" => $this->prepareInlineAttributes($styles, ";", ":", ""),
249 "data-lat" => $attributes->lat,
250 "data-lng" => $attributes->lng,
251 "data-zoom" => $attributes->zoom,
252 "data-address" => $attributes->address,
253 "data-infowindow-mode" => $attributes->infowindow_mode
254 );
255
256 $elemAttributes = $this->prepareInlineAttributes($elemAttributes);
257
258 /* Prepare the proxied shortcode */
259 $proxy = (object) array(
260 "shortcode" => self::SHORTCODE_PROXY_SLUG,
261 'attributes' => array(
262 'id' => $attributes->id
263 )
264 );
265
266 $proxy->attributes = $this->prepareInlineAttributes($proxy->attributes);
267 $proxyShortcode = do_shortcode("[{$proxy->shortcode} {$proxy->attributes}]");
268
269
270 $html = "<div class='wpgmza_map_wrapper proxied'><div {$elemAttributes}>{$proxyShortcode}</div></div>";
271 }
272
273 /* Asset Handling */
274 $this->onEnqueueShortcodeAssets($attributes);
275
276 return $html;
277 }
278
279 /**
280 * For WP Go Maps Support team
281 *
282 * We add a build version to the system so that it can be identified when debugging a site
283 *
284 * @param array $versions The current versions
285 *
286 * @return array
287 */
288 public function getBuildVersion($versions){
289 if(is_array($versions)){
290 $versions['standalone'] = $this->getVersion();
291 }
292 return $versions;
293 }
294
295 /**
296 * Load all the frontend assets for the shortcode (driven by block) to render
297 *
298 * This includes the API, based on attribute engine selection and the main client JS which will do the actual work
299 *
300 * @param object $attributes
301 *
302 * @return void
303 */
304 private function onEnqueueShortcodeAssets($attributes){
305 if($this->hasFullPlugin()){
306 /* User has switched to using the full plugin, we will keep the blocks working by polyfilling their logic */
307 $this->onEnqueuePolyfillAssets();
308 return;
309 }
310
311 $versionString = $this->getVersion();
312 $path = plugin_dir_url(__FILE__);
313
314 wp_enqueue_style("wpgmza_block_client", $path . "css/client.css", array(), $versionString);
315 wp_enqueue_script('wpgmza_block_client', $path . 'js/client.js', array('jquery'), $versionString);
316
317 $engine = !empty($attributes->map_engine) ? $attributes->map_engine : 'open-layers';
318
319 switch($engine){
320 case 'google-maps':
321 $libraries = array('geometry', 'places', 'visualization', 'marker');
322
323 $params = (object) array(
324 'v' => 'quarterly',
325 'language' => get_locale(),
326 'key' => !empty($attributes->google_maps_api_key) ? trim($attributes->google_maps_api_key) : '',
327 'libraries' => implode(',', $libraries),
328 );
329
330 switch($params->language){
331 case 'he_IL':
332 $params->language = 'iw';
333 break;
334 }
335
336 $params->language = substr($params->language, 0, 2);
337 $url = '//maps.google.com/maps/api/js?' . http_build_query($params);
338
339 wp_enqueue_script('wpgmza_block_google_api_call', $url, array(), $versionString);
340 break;
341 case 'open-layers':
342 default:
343 wp_enqueue_style('wpgmza_block_ol_api_call', $path . 'lib/ol.css', array(), $versionString);
344 wp_enqueue_script('wpgmza_block_ol_api_call', $path . 'lib/ol.js', array(), $versionString);
345 break;
346 }
347 }
348
349 /**
350 * Load polyfill assets to allow the blocks created with the block plugin to
351 * work as expected, even though the full plugin has been installed as well
352 *
353 * This means leveraging the full plugin core API instead of hand-rolling each feature for the block
354 *
355 * @return void
356 */
357 private function onEnqueuePolyfillAssets(){
358 $versionString = $this->getVersion();
359 $path = plugin_dir_url(__FILE__);
360
361 wp_enqueue_style("wpgmza_block_polyfill", $path . "css/block-polyfill.css", array(), $versionString);
362 wp_enqueue_script('wpgmza_block_polyfill', $path . 'js/block-polyfill.js', array('jquery', 'wpgmza'), $versionString);
363 }
364
365 /**
366 * Check if the block can be registered
367 *
368 * This might become disabled if WP Go Maps plugin is installed, or if the Gutenberg core is not accessible
369 *
370 * @return bool
371 */
372 private function checkRequirements(){
373 if(function_exists('register_block_type')){
374 return true;
375 }
376 return false;
377 }
378
379 /**
380 * Check if the user has also installed our full plugin, if so, that takes preference
381 *
382 * We would ideally still load this block, but change it to be managed by the core plugin
383 *
384 * Perhaps load additional client assets to help with that management
385 *
386 * @return bool
387 */
388 private function hasFullPlugin(){
389 if(class_exists('WPGMZA\Plugin')){
390 return true;
391 }
392 return false;
393 }
394
395 /**
396 * Combines inline attributes
397 *
398 * @param array $data The data to be combined
399 * @param string $separator Symbol to use for separate 'rows'
400 * @param string $assigner Symbol to use for key/value assignments
401 * @param string $capsule What to wrap values in, if anything
402 *
403 * @return string
404 */
405 private function prepareInlineAttributes($data, $separator = " ", $assigner = "=", $capsule = "\""){
406 if(is_array($data)){
407 $output = "";
408 foreach($data as $key => $value){
409 if(is_array($value)){
410 $value = $this->prepareInlineAttributes($value, $separator, $assigner, $capsule);
411 }
412
413 $value = esc_attr($value);
414
415 $output .= "{$key}{$assigner}{$capsule}{$value}{$capsule}{$separator}";
416 }
417
418 return $output;
419 }
420 return $data;
421 }
422
423 /**
424 * Get a version string for scripts
425 *
426 * @return string
427 */
428 protected function getVersion(){
429 if($this->cachedVersion != null)
430 return $this->cachedVersion;
431
432 $subject = file_get_contents(plugin_dir_path(__FILE__) . 'wp-go-maps-block.php');
433 if(preg_match('/Version:\s*(.+)/', $subject, $m))
434 $this->cachedVersion = trim($m[1]);
435
436 return $this->cachedVersion;
437 }
438 }
439
440
441 add_action('plugins_loaded', function() {
442 $mapBlockInstance = new MapBlock();
443 });
444