PluginProbe
M Chart / 1.0
M Chart v1.0
2.3.2 2.3.1 2.3 2.2.2 2.2.1 2.2 trunk 1.0 1.1 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.10 1.10.1 1.11 1.11.1 1.11.2 1.12 1.2 1.2.1 1.3 1.3.1 1.3.2 All 53 releases
← All changes | components/class-m-chart.php +136 -1068 2.31.0 View file →
@@ -1,267 +1,77 @@
1 1 <?php
2 2
3 -if ( ! defined( 'ABSPATH' ) ) {
4 - exit;
5 -}
6 -
7 3 class M_Chart {
8 - public $version = '2.3';
9 - public $slug = 'm-chart';
10 - public $plugin_name = 'Chart';
11 - public $chart_meta_fields = [
12 - 'library' => 'chartjs',
13 - 'type' => 'line',
14 - 'parse_in' => 'rows',
15 - 'labels' => true,
16 - 'shared' => false,
17 - 'subtitle' => '',
18 - 'y_title' => '',
19 - 'y_units' => '',
20 - 'y_min' => false,
21 - 'y_min_value' => 0,
22 - 'x_title' => '',
23 - 'x_units' => '',
24 - 'height' => 600,
25 - 'legend' => true,
26 - 'source' => '',
27 - 'source_url' => '',
28 - 'data' => [],
29 - 'set_names' => [],
30 - 'data_point_colors' => false,
31 - 'mean_point' => true,
32 - 'sample_points' => false,
33 - 'constrain_y_axis' => false,
34 - 'include_source' => false,
35 - ];
36 - public $get_chart_default_args = [
37 - 'show' => 'chart',
4 + public $dev = true;
5 + public $slug = 'm-chart';
6 + public $plugin_name = 'Chart';
7 + public $chart_meta_fields = array(
8 + 'library' => 'highcharts',
9 + 'type' => 'line',
10 + 'parse_in' => 'rows',
11 + 'labels' => true,
12 + 'subtitle' => '',
13 + 'y_title' => '',
14 + 'y_units' => '',
15 + 'y_min' => false,
16 + 'x_title' => '',
17 + 'x_units' => '',
18 + 'height' => 400,
19 + 'legend' => true,
20 + 'source' => '',
21 + 'source_url' => '',
22 + 'data' => array(),
23 + );
24 + public $get_chart_default_args = array(
25 + 'img' => 'no',
38 26 'width' => 'responsive',
39 - 'share' => '',
40 - ];
41 - public $parse_options = [
27 + );
28 + public $parse_options = array(
42 29 'columns',
43 30 'rows',
44 - ];
31 + );
45 32 public $options_set;
46 33 public $plugin_url;
47 - public $is_iframe = false;
48 - public $instance = 1;
49 - public $iframe_csp_nonce = '';
50 - public $settings = [
51 - 'library' => 'chartjs',
52 - 'show_library' => 'no',
53 - 'performance' => 'default',
54 - 'image_multiplier' => '2',
55 - 'image_width' => '900',
56 - 'default_height' => '600',
57 - 'embeds' => '',
58 - 'defer_rendering' => 'enabled',
59 - 'default_theme' => '_default',
60 - 'locale' => 'en-US',
61 - 'csv_delimiter' => ',',
62 - ];
63 - public $csv_delimiters = [
64 - ',' => 'Comma',
65 - "\t" => 'Tab',
66 - ' ' => 'Space',
67 - ';' => 'Semicolon',
68 - ];
69 - public $library_class;
70 - public $icon = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjY0IDY0IDI0IDI0IiB3aWR0aD0iMjRweCIgaGVpZ2h0PSIyNHB4Ij4KICA8cGF0aCBmaWxsPSJjdXJyZW50Q29sb3IiIGQ9Ik0gNzYuNjU3IDY1LjUgTCA3Ni42NTcgNzUuMzQ0IEwgODYuNSA3NS4zNDQgQyA4Ni41IDY5LjkwOSA4Mi4wOTEgNjUuNSA3Ni42NTcgNjUuNSBaIE0gNzQuNjg4IDc2LjMyOCBMIDc0LjY4OCA2Ni44MzMgQyA2OS41NTcgNjcuMTc0IDY1LjUgNzEuNDM5IDY1LjUgNzYuNjU3IEMgNjUuNSA4Mi4wOTEgNjkuOTA5IDg2LjUgNzUuMzQzIDg2LjUgQyA4MC41NjIgODYuNSA4NC44MjggODIuNDQzIDg1LjE2NyA3Ny4zMTMgTCA3NC42ODggNzcuMzEzIEwgNzQuNjg4IDc2LjMyOCBaIi8+Cjwvc3ZnPg==';
71 - public $logo = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyBpZD0idXVpZC03OGNkNDE3YS0zN2NjLTQ0NTAtODU2ZC00MzBlMTliYjhmOTEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDQzNyAzNzAuMDU2Ij4KICA8ZyBpZD0idXVpZC1hMDM3MTk0ZS1hN2QzLTQ4NTktOGEwZi0wMmIzMWI0YmQ3MzEiIHRyYW5zZm9ybT0ibWF0cml4KDEsIDAsIDAsIDEsIDM4LjQwMzk5OSwgNTUuOTM3MDA0KSI+CiAgICA8cmVjdCB4PSIyODEuNDAxIiB5PSIxNDguNTExIiB3aWR0aD0iODguNzEiIGhlaWdodD0iMTQxLjQ1IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyIvPgogICAgPHJlY3QgeD0iLTkuOTE5IiB5PSIyNjQuODIxIiB3aWR0aD0iODguNzEiIGhlaWdodD0iMjUuMTMiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7Ii8+CiAgICA8cmVjdCB4PSItOS45MTkiIHk9Ii0zMS43NzkiIHdpZHRoPSI4OC43MSIgaGVpZ2h0PSIyODQuMjEiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7Ii8+CiAgICA8cmVjdCB4PSIyODEuNDAxIiB5PSItMzEuNzc5IiB3aWR0aD0iODguNzEiIGhlaWdodD0iMTY3Ljg3IiBzdHlsZT0ic3Ryb2tlLXdpZHRoOiAxOyIvPgogICAgPHJlY3QgeD0iMTg2LjI4MSIgeT0iMTk0LjU1MSIgd2lkdGg9IjgyLjc5IiBoZWlnaHQ9Ijk1LjQiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7Ii8+CiAgICA8cmVjdCB4PSI5MS4wODEiIHk9IjIzNS40MTEiIHdpZHRoPSI4Mi45NCIgaGVpZ2h0PSI1NC41NSIgc3R5bGU9InN0cm9rZS13aWR0aDogMTsiLz4KICAgIDxwb2x5Z29uIHBvaW50cz0iMjgxLjQwMSAtMzEuNzc5IDE4MC4xMDEgNjUuMTExIDE4MC4xMDEgMTc2LjcwMSAyODEuNDAxIDc5LjcxMSAyODEuNDAxIC0zMS43NzkiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7Ii8+CiAgICA8cG9seWdvbiBwb2ludHM9Ijc4LjgwMSA3OS43MTEgMTgwLjEwMSAxNzYuNzAxIDE4MC4xMDEgNjUuMTExIDc4LjgwMSAtMzEuNzc5IDc4LjgwMSA3OS43MTEiIHN0eWxlPSJzdHJva2Utd2lkdGg6IDE7Ii8+CiAgPC9nPgo8L3N2Zz4=';
72 34
73 35 private $admin;
36 + private $highcharts;
74 37 private $parse;
75 - private $block;
76 - private $fs;
77 - private $resolved_settings;
78 - private $libraries = [
79 - 'chartjs' => 'Chart.js',
80 - ];
38 + private $valid_libraries = array(
39 + 'highcharts',
40 + );
81 41
82 42 /**
83 43 * Constructor
84 44 */
85 45 public function __construct() {
86 - // Initiate Freemius first so it loads as early as possible
87 - // Must run synchronously here at file load so Freemius detects m-chart.php as the plugin file
88 - $this->freemius();
46 + add_action( 'init', array( $this, 'init' ) );
47 + add_action( 'save_post', array( $this, 'save_post' ) );
89 48
90 - $this->plugin_url = $this->plugin_url();
91 -
92 - add_action( 'init', [ $this, 'init' ] );
93 - add_action( 'plugins_loaded', [ $this, 'plugins_loaded' ] );
94 - add_action( 'save_post', [ $this, 'save_post' ] );
95 - // Doing this early as possible because it sets is_iframe which we might need to use for other things
96 - add_action( 'template_redirect', [ $this, 'template_redirect' ], 0 );
97 - add_action( 'm_chart_update_post_meta', [ $this, 'm_chart_update_post_meta' ], 10, 2 );
98 -
99 - // Doing this before the default so it's already done before anything else
100 - add_filter( 'm_chart_get_chart_image_tag', [ $this, 'm_chart_get_chart_image_tag' ], 9, 3 );
101 - add_filter( 'the_content', [ $this, 'the_content' ] );
102 - add_filter( 'm_chart_image_support', [ $this, 'm_chart_image_support' ], 10, 2 );
103 - add_filter( 'm_chart_instant_preview_support', [ $this, 'm_chart_instant_preview_support' ], 10, 2 );
104 - add_filter( 'm_chart_library_class', [ $this, 'm_chart_library_class' ], 10, 2 );
105 -
106 - add_shortcode( 'm-chart', [ $this, 'chart_shortcode' ] );
107 - // Backwards-compatible alias for content created before the rename
108 - add_shortcode( 'chart', [ $this, 'chart_shortcode' ] );
109 -
110 - // Initiate the block class
111 - $this->block();
49 + add_shortcode( 'chart', array( $this, 'chart_shortcode' ) );
112 50 }
113 51
114 52 /**
115 - * Initiate and return the Freemius SDK instance
116 - *
117 - * Lazily builds the instance on first call and caches it
118 - * The SDK lives in components/external/freemius rather than the usual plugin root /freemius
119 - * M Chart core (m-chart) is the free version so is_premium is false
120 - * M Chart Pro (m-chart-pro) is a separate plugin sold under the same Freemius product via parallel activation
121 - *
122 - * @return Freemius the Freemius SDK instance for M Chart
123 - */
124 - public function freemius() {
125 - if ( isset( $this->fs ) ) {
126 - return $this->fs;
127 - }
128 -
129 - require_once __DIR__ . '/external/freemius/start.php';
130 -
131 - $this->fs = fs_dynamic_init( [
132 - 'id' => '30258',
133 - 'slug' => 'm-chart',
134 - 'premium_slug' => 'm-chart-pro',
135 - 'type' => 'plugin',
136 - 'public_key' => 'pk_b1eafc082abd31243874041aaaaab',
137 - 'is_premium' => false,
138 - 'has_premium_version' => true,
139 - 'has_addons' => false,
140 - 'has_paid_plans' => true,
141 - 'is_org_compliant' => true,
142 - 'parallel_activation' => [
143 - 'enabled' => true,
144 - 'premium_version_basename' => 'm-chart-pro/m-chart-pro.php',
145 - ],
146 - 'menu' => [
147 - // Anchor on the Charts CPT itself so the Freemius pages are plugin-level (m-chart-account, m-chart-pricing)
148 - // The CPT slug contains ".php?" so get_slug() falls back to the m-chart affix rather than an m-chart-settings- prefix
149 - 'slug' => 'edit.php?post_type=m-chart',
150 - // Surface the Freemius Account page as a submenu link under the Charts menu
151 - 'account' => true,
152 - 'contact' => false,
153 - 'support' => false,
154 - ],
155 - ] );
156 -
157 - $this->freemius_filters();
158 -
159 - do_action( 'm_chart_fs_loaded' );
160 -
161 - return $this->fs;
162 - }
163 -
164 - /**
165 - * Register Freemius filters that brand the pricing and opt-in screens
166 - *
167 - * pricing/css_path points Freemius at our stylesheet which is enqueued on the pricing page after its own CSS
168 - * pricing/show_annual_in_monthly shows the real annual price rather than the monthly equivalent of the annual plan
169 - *
170 - * The css_path and plugin_icon paths run through Freemius's fs_asset_url which maps a path to a URL by stripping WP_PLUGIN_DIR
171 - * __DIR__ resolves to the plugin's real path which differs from WP_PLUGIN_DIR when the plugin is symlinked
172 - * plugin_basename normalizes it back to the plugins-dir-relative path so the URL resolves in every install
173 - *
174 - * The opt-in / connect screen has no css_path filter so we inline our stylesheet on the connect/before action instead
175 - * It prints after Freemius's own connect.css so equal-specificity overrides win on source order
176 - */
177 - private function freemius_filters() {
178 - $this->fs->add_filter( 'pricing/css_path', function () {
179 - return WP_PLUGIN_DIR . '/' . plugin_basename( __DIR__ . '/css/m-chart-freemius-pricing.css' );
180 - } );
181 -
182 - // Re-point the pricing page contact links at M Chart's own support/contact pages
183 - // Freemius wraps the pricing output in this filter so the inline script is scoped to that screen
184 - $this->fs->add_filter( 'templates/pricing.php', function ( $html ) {
185 - $script_path = __DIR__ . '/js/m-chart-freemius-pricing.js';
186 -
187 - if ( ! file_exists( $script_path ) ) {
188 - return $html;
189 - }
190 -
191 - return $html
192 - . "<script id=\"m-chart-freemius-pricing\">\n"
193 - . file_get_contents( $script_path ) // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- local plugin asset
194 - . "</script>\n";
195 - } );
196 -
197 - $this->fs->add_filter( 'plugin_icon', function () {
198 - return WP_PLUGIN_DIR . '/' . plugin_basename( __DIR__ . '/images/m-chart-logo-square-rounded.svg' );
199 - } );
200 -
201 - $this->fs->add_filter( 'pricing/show_annual_in_monthly', '__return_false' );
202 -
203 - $this->fs->add_action( 'connect/before', function () {
204 - $css_path = __DIR__ . '/css/m-chart-freemius-connect.css';
205 -
206 - if ( ! file_exists( $css_path ) ) {
207 - return;
208 - }
209 -
210 - echo "<style id=\"m-chart-freemius-connect\">\n";
211 - echo file_get_contents( $css_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents -- local plugin asset
212 - echo "</style>\n";
213 - } );
214 -
215 - // Swap Freemius's casual interjection headings for professional wording
216 - // These are admin-notice titles keyed by id and the trailing "!" / "..." is appended by the SDK so it carries over
217 - // Values are left unescaped since Freemius escapes them at the output site
218 - // Deferred to init since freemius() runs at construct and the __() calls would load the text domain before WordPress is ready
219 - add_action( 'init', function () {
220 - fs_override_i18n( [
221 - 'yee-haw' => __( 'Success', 'm-chart' ),
222 - 'woot' => __( 'Success', 'm-chart' ),
223 - 'right-on' => __( 'Success', 'm-chart' ),
224 - 'oops' => __( 'Error', 'm-chart' ),
225 - 'hmm' => __( 'Heads up', 'm-chart' ),
226 - 'hey' => __( 'Hello', 'm-chart' ),
227 - ], $this->slug );
228 - } );
229 - }
230 -
231 - /**
232 53 * Admin object accessor
233 54 */
234 55 public function admin() {
235 56 if ( ! $this->admin ) {
236 57 require_once __DIR__ . '/class-m-chart-admin.php';
237 - $this->admin = new M_Chart_Admin();
58 + $this->admin = new M_Chart_Admin;
238 59 }
239 60
240 61 return $this->admin;
241 62 }
242 -
243 - /**
244 - * Block object accessor
245 - */
246 - public function block() {
247 - if ( ! $this->block ) {
248 - require_once __DIR__ . '/class-m-chart-block.php';
249 - $this->block = new M_Chart_Block();
250 - }
251 63
252 - return $this->block;
253 - }
254 -
255 64 /**
256 - * Library object accessor
65 + * Highcharts object accessor
257 66 */
258 - public function library( $library = false ) {
259 - if ( ! $library ) {
260 - $library = $this->get_library();
67 + public function highcharts() {
68 + if ( ! $this->highcharts ) {
69 + require_once __DIR__ . '/class-m-chart-highcharts.php';
70 + $this->highcharts = new M_Chart_Highcharts;
261 71 }
262 72
263 - return apply_filters( 'm_chart_library_class', $this->library_class, $library );
73 + return $this->highcharts;
264 74 }
265 75
266 76 /**
267 77 * Parse object accessor
@@ -267,11 +77,10 @@
267 77 * Parse object accessor
268 78 */
269 79 public function parse() {
270 80 if ( ! $this->parse ) {
271 - require_once __DIR__ . '/class-m-chart-parsed-data-point.php';
272 81 require_once __DIR__ . '/class-m-chart-parse.php';
273 - $this->parse = new M_Chart_Parse();
82 + $this->parse = new M_Chart_Parse;
274 83 }
275 84
276 85 return $this->parse;
277 86 }
@@ -282,12 +91,12 @@
282 91 public function init() {
283 92 // Register the units taxonomy
284 93 register_taxonomy(
285 94 $this->slug . '-units',
286 - [ $this->slug ],
287 - [
95 + array( $this->slug ),
96 + array(
288 97 'hierarchical' => true,
289 - 'labels' => [
98 + 'labels' => array(
290 99 'name' => esc_html__( 'Chart Units', 'm-chart' ),
291 100 'singular_name' => esc_html__( 'Chart Unit', 'm-chart' ),
292 101 'search_items' => esc_html__( 'Search Chart Units', 'm-chart' ),
293 102 'all_items' => esc_html__( 'All Chart Units', 'm-chart' ),
@@ -297,41 +106,26 @@
297 106 'update_item' => esc_html__( 'Update Chart Unit', 'm-chart' ),
298 107 'add_new_item' => esc_html__( 'Add New Chart Unit', 'm-chart' ),
299 108 'new_item_name' => esc_html__( 'Chart Unit Name', 'm-chart' ),
300 109 'menu_name' => esc_html__( 'Chart Units', 'm-chart' ),
301 - ],
302 - 'show_ui' => true,
303 - 'query_var' => true,
304 - 'rewrite' => [
305 - 'slug' => $this->slug . '-units',
306 - ],
307 - ]
110 + ),
111 + 'show_ui' => true,
112 + 'query_var' => true,
113 + 'rewrite' => array(
114 + 'slug' => $this->slug . '-units',
115 + ),
116 + )
308 117 );
309 118
310 - // Register the library taxonomy
311 - register_taxonomy(
312 - $this->slug . '-library',
313 - [ $this->slug ],
314 - [
315 - 'hierarchical' => false,
316 - 'show_ui' => false,
317 - 'query_var' => true,
318 - 'rewrite' => [
319 - 'slug' => $this->slug . '-library',
320 - ],
321 - ]
322 - );
119 + // Get the public taxonomies so the custom post type can use them
120 + $taxonomies = get_taxonomies( array( 'public' => true ) );
323 121
324 122 // Register the charts custom post type
325 123 register_post_type(
326 124 $this->slug,
327 - [
328 - 'labels' => [
125 + array(
126 + 'labels' => array(
329 127 'name' => esc_html__( 'Charts', 'm-chart' ),
330 - // Top-level admin menu label defaults to 'name' so we set it explicitly to brand the menu as M Chart
331 - 'menu_name' => esc_html__( 'M Chart', 'm-chart' ),
332 - // First submenu item label defaults to menu_name so we set it back to Charts (parent reads M Chart, list reads Charts)
333 - 'all_items' => esc_html__( 'Charts', 'm-chart' ),
334 128 'singular_name' => esc_html__( 'Chart', 'm-chart' ),
335 129 'add_new' => esc_html__( 'Add Chart', 'm-chart' ),
336 130 'add_new_item' => esc_html__( 'Add Chart', 'm-chart' ),
337 131 'edit' => esc_html__( 'Edit', 'm-chart' ),
@@ -341,105 +135,42 @@
341 135 'view_item' => esc_html__( 'View Chart', 'm-chart' ),
342 136 'search_items' => esc_html__( 'Search Charts', 'm-chart' ),
343 137 'not_found' => esc_html__( 'No Charts found', 'm-chart' ),
344 138 'not_found_in_trash' => esc_html__( 'No Charts found in the Trash', 'm-chart' ),
345 - ],
346 - 'register_meta_box_cb' => is_admin() ? [ $this->admin(), 'meta_boxes' ] : null,
139 + ),
140 + 'register_meta_box_cb' => is_admin() ? array( $this->admin(), 'meta_boxes' ) : null,
347 141 'public' => true,
348 - 'show_in_rest' => true,
349 142 'hierarchical' => false,
350 143 'exclude_from_search' => false,
351 144 'menu_position' => 9,
352 - 'menu_icon' => 'data:image/svg+xml;base64,' . $this->logo,
145 + 'menu_icon' => 'dashicons-chart-pie',
353 146 'query_var' => true,
354 147 'can_export' => true,
355 148 'has_archive' => 'charts',
356 - 'description' => esc_html__( 'Manage data sets and display them as charts in WordPress.', 'm-chart' ),
357 - 'rewrite' => [
358 - 'slug' => 'chart',
359 - ],
360 - 'supports' => [
149 + 'description' => esc_html__( 'Manage data sets and display them as charts in WordPress.', $this->slug ),
150 + 'rewrite' => array( 'slug' => 'chart' ),
151 + 'supports' => array(
361 152 'author',
362 153 'title',
363 154 'excerpt',
364 155 'comments',
365 - ],
366 - 'taxonomies' => [
367 - 'category',
368 - 'post_tag',
369 - $this->slug . '-units',
370 - ],
371 - ]
156 + ),
157 + 'taxonomies' => $taxonomies,
158 + )
372 159 );
373 160
161 + $this->plugin_url = $this->plugin_url();
162 +
374 163 // Register the graphing library scripts
375 164 wp_register_script(
376 - 'chartjs',
377 - $this->plugin_url . '/components/external/chartjs/chart.js',
378 - [],
379 - $this->version
165 + 'highcharts-js',
166 + $this->plugin_url . '/components/external/highcharts/highcharts.js',
167 + array( 'jquery' )
380 168 );
381 -
382 - wp_register_script(
383 - 'chartjs-helper',
384 - $this->plugin_url . '/components/js/m-chart-chartjs-helper.min.js',
385 - [ 'chartjs' ],
386 - $this->version
387 - );
388 -
389 - wp_register_script(
390 - 'chartjs-datalabels',
391 - $this->plugin_url . '/components/external/chartjs/chartjs-plugin-datalabels.js',
392 - [ 'chartjs' ],
393 - $this->version
394 - );
395 -
396 - wp_register_script(
397 - 'chartjs-treemap',
398 - $this->plugin_url . '/components/external/chartjs/chartjs-chart-treemap.min.js',
399 - [ 'chartjs' ],
400 - $this->version
401 - );
402 -
403 - wp_register_script(
404 - 'chartjs-boxplot',
405 - $this->plugin_url . '/components/external/chartjs/chartjs-chart-boxplot.min.js',
406 - [ 'chartjs' ],
407 - $this->version
408 - );
409 -
410 - // The venn UMD build reads the global Chart at load time so the chartjs dependency is required
411 - wp_register_script(
412 - 'chartjs-venn',
413 - $this->plugin_url . '/components/external/chartjs/chartjs-chart-venn.min.js',
414 - [ 'chartjs' ],
415 - $this->version
416 - );
417 -
418 - // Add endpoint needed for iframe embed support
419 - add_rewrite_endpoint( 'embed', EP_PERMALINK );
420 -
421 - // Check if we need to run any upgrades
422 - $current_version = get_site_option( 'm_chart_version' );
423 -
424 - if ( version_compare( $current_version, '1.7', 'lt' ) ) {
425 - $this->upgrade_to_1_7();
426 - }
427 -
428 - if ( version_compare( $current_version, '1.7.4', 'lt' ) ) {
429 - $this->upgrade_to_1_7_4();
430 - }
431 169 }
432 170
433 171 /**
434 - * Do plugins loaded stuff
435 - */
436 - public function plugins_loaded() {
437 - load_plugin_textdomain( 'm-chart', false, plugin_basename( dirname( __FILE__ ) ) . '/languages/' );
438 - }
439 -
440 - /**
441 - * WP VIP's CDN was breaking the chart library's ability to handle embedded SVGs so this should circumvent that
172 + * VIP's CDN was breaking Highcharts ability to handle embedded SVGs so this should circumvent that
442 173 * If you wanted to say, watermark your charts, SVGs suddenly become very important
443 174 *
444 175 * @param string $path option additional path to be used (e.g. components)
445 176 *
@@ -447,27 +178,17 @@
447 178 */
448 179 public function plugin_url( $path = '' ) {
449 180 if ( is_admin() ) {
450 181 $url_base = parse_url( admin_url() );
451 - } else {
182 + }
183 + else
184 + {
452 185 $url_base = parse_url( home_url() );
453 186 }
454 187
455 188 $url_path = parse_url( plugins_url( $path, __DIR__ ) );
456 189
457 - // Check for a port value if one exists we make sure it's honored
458 - $port = '';
459 -
460 - if ( isset( $url_base['port'] ) && 80 != $url_base['port'] ) {
461 - $port = ':' . $url_base['port'];
462 - }
463 -
464 - $scheme = $url_base['scheme'] ?? 'https';
465 - $host = $url_base['host'] ?? '';
466 - $path = $url_path['path'] ?? '';
467 - $query = $url_path['query'] ?? '';
468 -
469 - return $scheme . '://' . $host . $port . preg_replace( '#/$#', '', $path ) . ( '' === $query ? '' : '?' . $query );
190 + return $url_base['scheme'] . '://' . $url_base['host'] . preg_replace( '#/$#', '', $url_path['path'] ) . ( empty( $url_path['query'] ) ? '' : '?' . $url_path['query'] );
470 191 }
471 192
472 193 /**
473 194 * Get chart post meta
@@ -474,79 +195,18 @@
474 195 *
475 196 * @param int $post_id WP post ID of the post you want post meta from
476 197 * @param string $field optional field to be returend instead of all post meta
477 198 *
478 - * @return array $post_meta the meta for a give post ID
199 + * @return string URL to the plugin directory with path if parameter was passed
479 200 */
480 201 public function get_post_meta( $post_id, $field = false ) {
481 - $raw_post_meta = get_post_meta( $post_id, $this->slug, true );
202 + $post_meta = get_post_meta( $post_id, $this->slug, true );
203 + $post_meta = wp_parse_args( $post_meta, $this->chart_meta_fields );
482 204
483 - $post_meta = $raw_post_meta;
484 -
485 - $defaults = $this->chart_meta_fields;
486 -
487 - // Make sure the correct library is set in the default chart meta fields
488 - if ( ! $post_meta ) {
489 - // get_current_screen() is only defined in admin context
490 - // This guards the call so REST and front-end contexts don't fatal
491 - $current_screen = is_admin() && function_exists( 'get_current_screen' )
492 - ? get_current_screen()
493 - : null;
494 -
495 - // If we're we're adding a new chart and a library is specified in the get vars we use it
496 - if (
497 - is_admin()
498 - && null != $current_screen
499 - && 'post' == $current_screen->base
500 - && 'add' == $current_screen->action
501 - && isset( $_GET['library'] )
502 - && $this->is_valid_library( $_GET['library'] )
503 - ) {
504 - $defaults['library'] = $_GET['library'];
505 - } else {
506 - $defaults['library'] = $this->get_library();
507 - }
508 - }
509 -
510 - // Default chart height comes from the plugin settings so new charts honor the site default
511 - // Saved charts already have a height so wp_parse_args leaves theirs alone
512 - $defaults['height'] = (int) $this->get_settings( 'default_height' );
513 -
514 - $post_meta = wp_parse_args( $post_meta, $defaults );
515 -
516 - // Theme default is based off of an option so we'll handle that here
517 - if ( ! isset( $post_meta['theme'] ) ) {
518 - $settings = $this->get_settings();
519 - $post_meta['theme'] = $settings['default_theme'];
520 - }
521 -
522 - // If there's no subtitle set we'll set an empty one
523 - if ( ! isset( $post_meta['subtitle'] ) ) {
524 - $post_meta['subtitle'] = '';
525 - }
526 -
527 - // If there's no y min value set we'll set it to 0
528 - if ( ! isset( $post_meta['y_min_value'] ) ) {
529 - $post_meta['y_min_value'] = 0;
530 - }
531 -
532 - // If the data has the old legacy format we need to update it
533 - if ( isset( $post_meta['data'] ) && ! isset( $post_meta['data']['sets'] ) ) {
534 - $data = $post_meta['data'];
535 - $post_meta['data'] = [];
536 - $post_meta['data']['sets'][] = $data;
537 - }
538 -
539 - // If there's no set_names value set we'll set it to an empty array
540 - if ( ! isset( $post_meta['set_names'] ) ) {
541 - $post_meta['set_names'] = [];
542 - }
543 -
544 - $post_meta = apply_filters( 'm_chart_get_post_meta', $post_meta, $raw_post_meta, $post_id );
545 -
546 205 if ( $field && isset( $post_meta[ $field ] ) ) {
547 206 return $post_meta[ $field ];
548 - } elseif ( $field ) {
207 + }
208 + elseif ( $field ) {
549 209 return null;
550 210 }
551 211
552 212 return $post_meta;
@@ -552,9 +212,9 @@
552 212 return $post_meta;
553 213 }
554 214
555 215 /**
556 - * Update the post meta and set unit terms if appropriate
216 + * Update the post meta based and set unit terms if appropriate
557 217 *
558 218 * @param int $post_id WP post ID of the post you want to attach post meta to
559 219 * @param array $meta an array of the post meta you want to attach to the post
560 220 */
@@ -562,9 +222,9 @@
562 222 // Make sure the meta is formatted correctly and validated
563 223 $parsed_meta = $this->validate_post_meta( $meta );
564 224
565 225 // Set unit terms
566 - $terms = [];
226 + $terms = array();
567 227
568 228 if ( '' != $parsed_meta['y_units'] ) {
569 229 $terms[] = $parsed_meta['y_units'];
570 230 }
@@ -574,14 +234,11 @@
574 234 }
575 235
576 236 wp_set_object_terms( $post_id, $terms, $this->slug . '-units' );
577 237
578 - // Set library as a post_tag
579 - wp_set_object_terms( $post_id, $parsed_meta['library'], $this->slug . '-library' );
580 -
581 238 // Save meta to the post
582 239 update_post_meta( $post_id, $this->slug, $parsed_meta );
583 - do_action( 'm_chart_update_post_meta', $post_id, $parsed_meta, $meta );
240 + do_action( 'm_chart_update_post_meta', $post_id, $parsed_meta );
584 241 }
585 242
586 243 /**
587 244 * Parses a $meta array and returns a cleaned and validated array
@@ -591,16 +248,11 @@
591 248 * @return array of cleaned/validated post meta
592 249 */
593 250 public function validate_post_meta( $meta ) {
594 251 // Need to set checkboxes before checking or they can't be deselected
595 - $chart_meta['labels'] = false;
596 - $chart_meta['y_min'] = false;
597 - $chart_meta['legend'] = false;
598 - $chart_meta['data_point_colors'] = false;
599 - $chart_meta['mean_point'] = false;
600 - $chart_meta['sample_points'] = false;
601 - $chart_meta['constrain_y_axis'] = false;
602 - $chart_meta['include_source'] = false;
252 + $chart_meta['labels'] = false;
253 + $chart_meta['y_min'] = false;
254 + $chart_meta['legend'] = false;
603 255
604 256 // Filter values so we know the data is clean
605 257 foreach ( $this->chart_meta_fields as $field => $default ) {
606 258 if ( isset( $meta[ $field ] ) ) {
@@ -606,56 +258,37 @@
606 258 if ( isset( $meta[ $field ] ) ) {
607 259 if ( 'source_url' == $field && '' != $meta[ $field ] ) {
608 260 $chart_meta[ $field ] = esc_url_raw( $meta[ $field ] );
609 261 } elseif ( 'data' == $field ) {
610 - $chart_meta[ $field ]['sets'] = $meta[ $field ];
611 - } elseif ( 'set_names' == $field ) {
612 - $chart_meta[ $field ] = array_values( $meta[ $field ] );
613 - } elseif ( in_array( $field, [ 'labels', 'y_min', 'legend', 'data_point_colors', 'mean_point', 'sample_points', 'constrain_y_axis', 'include_source' ] ) ) {
262 + $chart_meta[ $field ] = $meta[ $field ];
263 + } elseif ( in_array( $field, array( 'labels', 'y_min', 'legend' ) ) ) {
614 264 $chart_meta[ $field ] = (bool) $meta[ $field ];
615 265 } elseif ( 'height' == $field ) {
616 266 $chart_meta[ $field ] = absint( $meta[ $field ] );
617 267
618 - if ( $chart_meta[ $field ] > 1500 ) {
619 - $chart_meta[ $field ] = 1500;
620 - } elseif ( $chart_meta[ $field ] < 300 ) {
268 + if ( $chart_meta[ $field ] > 900 ) {
269 + $chart_meta[ $field ] = 900;
270 + } else if ( $chart_meta[ $field ] < 300 ) {
621 271 $chart_meta[ $field ] = 300;
622 272 }
623 - } elseif ( 'y_min_value' == $field ) {
624 - $chart_meta[ $field ] = floatval( $meta[ $field ] );
625 273 } else {
626 274 $chart_meta[ $field ] = wp_filter_nohtml_kses( $meta[ $field ] );
627 275 }
628 - } elseif ( ! isset( $chart_meta[ $field ] ) ) {
276 + }
277 + elseif ( ! isset( $chart_meta[ $field ] ) ) {
629 278 // Fall back on the default value if there wasn't one in the given meta
630 - // Height honors the default_height setting so the save path agrees with get_post_meta()
631 - if ( 'height' === $field ) {
632 - $chart_meta[ $field ] = (int) $this->get_settings( 'default_height' );
633 - } else {
634 - $chart_meta[ $field ] = $default;
635 - }
279 + $chart_meta[ $field ] = $default;
636 280 }
637 281 }
638 282
639 - // The theme meta it isn't included in the chart_meta_fields class var so we handle it here
640 - if ( isset( $meta['theme'] ) && preg_match( '#^[a-zA-Z0-9-_]+$#', $meta['theme'] ) ) {
641 - $chart_meta['theme'] = $meta['theme'];
283 + // If the data value is not an array we asume it is JSON encoded (i.e. from Handsontable)
284 + if ( ! is_array( $chart_meta['data'] ) && '' != $chart_meta['data'] ) {
285 + $chart_meta['data'] = json_decode( stripslashes( $chart_meta['data'] ) );
642 286 }
643 287
644 - // If the data value is not an array we asume it is JSON encoded (i.e. from Jspreadsheet CE)
645 - if ( ! is_array( $chart_meta['data']['sets'] ) && '' != $chart_meta['data']['sets'] ) {
646 - $decoded = json_decode( stripslashes( $chart_meta['data']['sets'] ) );
647 - $chart_meta['data']['sets'] = is_array( $decoded ) ? $decoded : [];
648 - }
649 -
650 288 // Validate the data array
651 - foreach ( $chart_meta['data']['sets'] as $key => $data ) {
652 - $chart_meta['data'][ $key ] = $this->validate_data( $data );
653 - }
289 + $chart_meta['data'] = $this->validate_data( $chart_meta['data'] );
654 290
655 - // Allow plugins to validate their own custom meta
656 - $chart_meta = apply_filters( 'm_chart_validate_post_meta', $chart_meta, $meta );
657 -
658 291 return $chart_meta;
659 292 }
660 293
661 294 /**
@@ -669,19 +302,19 @@
669 302 if ( ! is_array( $data ) ) {
670 303 return wp_filter_nohtml_kses( $data );
671 304 }
672 305
673 - foreach ( $data as $key => $value ) {
674 - if ( is_array( $value ) ) {
675 - $data[ $key ] = $this->validate_data( $value );
676 - } else {
677 - $value = $value ?? '';
678 - $data[ $key ] = wp_filter_nohtml_kses( $value );
679 - }
680 - }
306 + foreach ( $data as $key => $value ) {
307 + if ( is_array( $value ) ) {
308 + $data[ $key ] = $this->validate_data( $value );
309 + }
310 + else {
311 + $data[ $key ] = wp_filter_nohtml_kses( $value );
312 + }
313 + }
681 314
682 - return $data;
683 - }
315 + return $data;
316 + }
684 317
685 318
686 319 /**
687 320 * Hook to save_post action and save chart related post meta
@@ -700,45 +333,13 @@
700 333 * @param array $args an array of args
701 334 *
702 335 * @return string HTML and Javascript needed to display a chart (or if appropriate an HTML image tag)
703 336 */
704 - public function get_chart( $post_id = null, $args = [] ) {
705 - if ( ! $post_id ) {
706 - $post_id = get_the_ID();
707 - }
708 -
709 - do_action( 'm_chart_get_chart_start', $post_id, $args );
710 -
711 - // Normalize historic usage of 'img' argument
712 - if ( isset( $args['img'] ) && 'yes' == $args['img'] ) {
713 - $args['show'] = 'image';
714 - unset( $args['img'] );
715 - }
716 -
337 + public function get_chart( $post_id, $args = array() ) {
717 338 $args = wp_parse_args( $args, $this->get_chart_default_args );
718 339
719 - $library = $this->get_post_meta( $post_id, 'library' );
720 -
721 - // If it's not a valid library we don't proceed
722 - if ( ! $this->is_valid_library( $library ) ) {
723 - return;
724 - }
725 -
726 - // Make sure we isntantiate the library so any library specific filters/setup get run
727 - $this->library( $library );
728 -
729 - // If they want the table of data we'll return that
730 - if ( 'table' == $args['show'] ) {
731 - return $this->build_table( $post_id );
732 - }
733 -
734 340 // If they want the image version or the request is happening from a feed we return the image tag
735 - if (
736 - 'image' == $args['show']
737 - || is_feed()
738 - || $this->is_amp_endpoint()
739 - || apply_filters( 'm_chart_show_image', false, $post_id, $args )
740 - ) {
341 + if ( 'yes' == $args['img'] || is_feed() ) {
741 342 $image = $this->get_chart_image( $post_id );
742 343
743 344 // Default behavior is to return the full size image but with the width/height values halved
744 345 // This should result in an image that looks nice on retina or better screens
@@ -746,123 +347,40 @@
746 347 $image['height'] = $image['height'] / 2;
747 348
748 349 $image = apply_filters( 'm_chart_get_chart_image_tag', $image, $post_id, $args );
749 350
750 - $classes = $this->slug . ' ' . $this->slug . '-' . $post_id;
751 -
752 - if ( $this->is_amp_endpoint() ) {
753 - ob_start();
754 - ?>
755 -<figure class="m-chart-image-figure">
756 - <amp-img src="<?php echo esc_url( $image['url'] ); ?>"
757 - width="<?php echo absint( $image['width'] ); ?>" height="<?php echo absint( $image['height'] ); ?>"
758 - alt="<?php echo esc_attr( get_the_title( $post_id ) ); ?>"
759 - class="<?php echo esc_attr( $classes ); ?>"></amp-img>
760 - <?php if ( has_action( 'm_chart_screen_reader_text' ) ) : ?>
761 - <?php wp_enqueue_style( 'm-chart-frontend', $this->plugin_url . '/components/css/m-chart-frontend.css', [], $this->version ); ?>
762 - <div class="screen-reader-text">
763 - <?php do_action( 'm_chart_screen_reader_text', $post_id, $args ); ?>
764 - </div>
765 - <?php endif; ?>
766 -</figure>
767 - <?php
768 - return ob_get_clean();
769 - } else {
770 - ob_start();
771 - ?>
772 -<figure class="m-chart-image-figure">
773 - <img src="<?php echo esc_url( $image['url'] ); ?>"
774 - width="<?php echo absint( $image['width'] ); ?>" height="<?php echo absint( $image['height'] ); ?>"
775 - alt="<?php echo esc_attr( get_the_title( $post_id ) ); ?>"
776 - class="<?php echo esc_attr( $classes ); ?>" />
777 - <?php if ( has_action( 'm_chart_screen_reader_text' ) ) : ?>
778 - <?php wp_enqueue_style( 'm-chart-frontend', $this->plugin_url . '/components/css/m-chart-frontend.css', [], $this->version ); ?>
779 - <div class="screen-reader-text">
780 - <?php do_action( 'm_chart_screen_reader_text', $post_id, $args ); ?>
781 - </div>
782 - <?php endif; ?>
783 -</figure>
784 - <?php
785 - return ob_get_clean();
786 - }
351 + ob_start();
352 + ?>
353 + <img src="<?php echo esc_url( $image['url'] ); ?>" alt="<?php echo esc_attr( $image['name'] ); ?>" width="<?php echo absint( $image['width'] ); ?>" height="<?php echo absint( $image['height'] ); ?>" />
354 + <?php
355 + return ob_get_clean();
787 356 }
788 357
789 - $settings = $this->get_settings();
358 + $library = $this->get_post_meta( $post_id, 'library' );
790 359
791 - if (
792 - ! is_admin()
793 - && 'enabled' == $settings['embeds']
794 - && ! $this->is_iframe
795 - ) {
796 - return $this->get_chart_iframe( $post_id, $args );
360 + // If it's not a valid library we don't proceed
361 + if ( ! $this->is_valid_library( $library ) ) {
362 + return;
797 363 }
798 364
799 365 // If we haven't enqueued the right library yet lets do it
800 - if ( ! wp_script_is( $library, 'enqueued' ) ) {
801 - wp_enqueue_script( $library );
802 - wp_enqueue_script( 'chartjs-helper' );
366 + if ( ! wp_script_is( $library . '-js', 'enqueued' ) ) {
367 + wp_enqueue_script( $library . '-js' );
803 368 }
804 369
805 - // Ship the visually hidden rule the screen reader data table relies on
806 - // so it never depends on the active theme defining .screen-reader-text
807 - wp_enqueue_style( 'm-chart-frontend', $this->plugin_url . '/components/css/m-chart-frontend.css', [], $this->version );
808 -
809 - $template = __DIR__ . '/templates/' . $library . '-chart.php';
810 -
811 370 ob_start();
812 - do_action( 'm_chart_get_chart_begin', $post_id, $args );
813 - require apply_filters( 'm_chart_chart_template', $template, $library, $post_id );
814 - do_action( 'm_chart_get_chart_end', $post_id, $args );
815 - $this->instance++;
371 + require __DIR__ . '/templates/' . $library . '-chart.php';
816 372 return ob_get_clean();
817 373 }
818 374
819 375 /**
820 - * Returns a charts data as an HTML table
821 - *
822 - * @param int $post_id WP post ID of the chart you want
823 - *
824 - * @return string HTML table
825 - */
826 - public function build_table( $post_id ) {
827 - $post = get_post( $post_id );
828 - $post_meta = $this->get_post_meta( $post_id );
829 - $library = m_chart()->get_post_meta( $post->ID, 'library' );
830 -
831 - $table = '';
832 -
833 - $multiple = count( $post_meta['data']['sets'] ) > 1 ? true : false;
834 -
835 - foreach ( $post_meta['data']['sets'] as $set => $data ) {
836 - $classes = $this->slug . '-table ' . $this->slug . '-table-' . $post_id . '-' . $set;
837 -
838 - m_chart()->parse()->parse_data( $data, $post_meta['parse_in'] );
839 -
840 - $template = __DIR__ . '/templates/table.php';
841 -
842 - ob_start();
843 - require apply_filters( 'm_chart_table_template', $template, $library, $post->ID );
844 - $table .= ob_get_clean();
845 - }
846 -
847 - return $table;
848 - }
849 -
850 - /**
851 376 * Return an array of image values for a chart
852 377 *
853 378 * @param int $post_id WP post ID of the chart you want an image for
854 379 *
855 - * @return array an array of image values url, width, height, etc...
380 + * @return array an arry of image values url, width, height, etc...
856 381 */
857 382 public function get_chart_image( $post_id ) {
858 - $settings = $this->get_settings();
859 -
860 - // If we aren't generating images we'll return false
861 - if ( 'default' != $settings['performance'] ) {
862 - return false;
863 - }
864 -
865 383 if ( ! $thumbnail_id = get_post_meta( $post_id, '_thumbnail_id', true ) ) {
866 384 return false;
867 385 }
868 386
@@ -869,154 +387,26 @@
869 387 if ( ! $thumbnail = wp_get_attachment_image_src( $thumbnail_id, 'full' ) ) {
870 388 return false;
871 389 }
872 390
873 - return [
391 + return array(
874 392 'url' => $thumbnail[0],
875 393 'file' => basename( $thumbnail[0] ),
876 394 'width' => $thumbnail[1],
877 395 'height' => $thumbnail[2],
878 396 'name' => get_the_title( $thumbnail_id ),
879 - ];
397 + );
880 398 }
881 399
882 400 /**
883 - * Filter the m_chart_get_chart_image_tag hook and return a plaecholder if appropriate
401 + * Return a chart via the [chart id="x"] short code
884 402 *
885 - * @param array|bool an array of image values or false if no image could be found
886 - * @param int $post_id WP post ID of the chart you want an image for
887 - *
888 - * @return array an array of image values url, width, height, etc...
889 - */
890 - public function m_chart_get_chart_image_tag( $img, $post_id ) {
891 - if ( $img ) {
892 - return $img;
893 - }
894 -
895 - $url = $this->plugin_url . '/components/images/chart-placeholder.png';
896 -
897 - return [
898 - 'url' => $url,
899 - 'file' => basename( $url ),
900 - 'width' => 640,
901 - 'height' => 480,
902 - 'name' => get_the_title( $post_id ),
903 - ];
904 - }
905 -
906 - /**
907 - * Filter the the_content hook and return chart code if this is a chart
908 - *
909 - * @param string $content content from the current post
910 - *
911 - * @return string original content or chart code
912 - */
913 - public function the_content( $content ) {
914 - // Make sure we're dealing with a chart
915 - if ( get_post_type() != $this->slug ) {
916 - // We aren't dealing with a chart so we'll just stop here
917 - return $content;
918 - }
919 -
920 - // Call the get_chart method and let it do it's thing
921 - return $this->get_chart();
922 - }
923 -
924 - /**
925 - * Hook to the m_chart_image_support filter and indicate that Chart.js supports images
926 - *
927 - * @param string $supports_images yes/no whether the library supports image generation
928 - * @param string $library the library in question
929 - *
930 - * @return string yes/no whether the library supports images
931 - */
932 - public function m_chart_image_support( $supports_images, $library ) {
933 - if ( $library != $this->chart_meta_fields['library'] ) {
934 - return $supports_images;
935 - }
936 -
937 - return 'yes';
938 - }
939 -
940 - /**
941 - * Hook to the m_chart_instant_preview_support filter and indicate that Chart.js supports instant previews
942 - *
943 - * @param string $supports_images yes/no whether the library supports instant previews
944 - * @param string $library the library in question
945 - *
946 - * @return string yes/no whether the library supports instant previews
947 - */
948 - public function m_chart_instant_preview_support( $supports_instant_preview, $library ) {
949 - if ( $library != $this->chart_meta_fields['library'] ) {
950 - return $supports_instant_preview;
951 - }
952 -
953 - return 'yes';
954 - }
955 -
956 - /**
957 - * Hook to the m_chart_library_class filter and return the library class if appropriate
958 - *
959 - * @param string $library_class the library class
960 - * @param string $library the library in question
961 - *
962 - * @return class the library class for this library
963 - */
964 - public function m_chart_library_class( $library_class, $library ) {
965 - // If Chart.js wasn't requested we'll stop here ()
966 - if ( $library != $this->chart_meta_fields['library'] ) {
967 - return $library_class;
968 - }
969 -
970 - if ( ! $this->library_class instanceof M_Chart_Chartjs ) {
971 - require_once __DIR__ . '/class-m-chart-chartjs.php';
972 - $this->library_class = new M_Chart_Chartjs();
973 - }
974 -
975 - return $this->library_class;
976 - }
977 -
978 - /**
979 - * Return an iframe for a given chart
980 - *
981 - * @param int $post_id WP post ID of the chart you want
982 - * @param array $args an array of args
983 - *
984 - * @return string HTML needed to display a chart via an iframe
985 - */
986 - public function get_chart_iframe( $post_id, $args = [] ) {
987 - $post_meta = $this->get_post_meta( $post_id );
988 -
989 - $src_url = add_query_arg( $args, get_permalink( $post_id ) . 'embed/' );
990 -
991 - $defer_lazy = 'enabled' === $this->get_settings( 'defer_rendering' );
992 -
993 - ob_start();
994 - ?>
995 -<iframe id="m-chart-container-<?php echo absint( $post_id ); ?>-<?php echo absint( $this->instance ); ?>"
996 - class="m-chart-iframe" width="100%" height="<?php echo absint( $post_meta['height'] + 1 ); ?>"
997 - title="<?php echo esc_attr( get_the_title( $post_id ) ); ?>"
998 - src="<?php echo esc_url( $src_url ); ?>"<?php echo $defer_lazy ? ' loading="lazy"' : ''; ?>></iframe>
999 - <?php
1000 - if ( 'show' == $args['share'] ) {
1001 - unset( $args['share'] );
1002 - require apply_filters( 'm_chart_share_template', __DIR__ . '/templates/share.php' );
1003 - }
1004 - $this->instance++;
1005 - return ob_get_clean();
1006 - }
1007 -
1008 - /**
1009 - * Return a chart via the [m-chart id="x"] short code
1010 - *
1011 - * Also registered under the legacy [chart] name for backwards compatibility
1012 - *
1013 403 * @param array $args an array of arguments passed by the WP short code API
1014 404 *
1015 405 * @return string the chart requested in Javascript or HTML form
1016 406 */
1017 407 public function chart_shortcode( $args ) {
1018 - $default_args = $this->get_chart_default_args;
408 + $default_args = $this->get_chart_default_args;
1019 409 $default_args['id'] = '';
1020 410
1021 411 $args = shortcode_atts( $default_args, $args );
1022 412
@@ -1022,9 +412,9 @@
1022 412
1023 413 $post_id = $args['id'];
1024 414 unset( $args['id'] );
1025 415
1026 - // Did we get what looks like a chart ID?
416 + // Did we get a chart ID?
1027 417 if ( ! is_numeric( $post_id ) ) {
1028 418 return;
1029 419 }
1030 420
@@ -1058,9 +448,9 @@
1058 448 *
1059 449 * @return array an array of generated and/or compiled unit terms
1060 450 */
1061 451 public function get_unit_terms() {
1062 - $terms = get_terms( $this->slug . '-units', [ 'hide_empty' => false ] );
452 + $terms = get_terms( $this->slug . '-units', array( 'hide_empty' => false ) );
1063 453
1064 454 if ( empty( $terms ) ) {
1065 455 $terms = $this->generate_unit_terms();
1066 456 }
@@ -1068,9 +458,9 @@
1068 458 return $this->compile_unit_terms( $terms );
1069 459 }
1070 460
1071 461 /**
1072 - * Helper function that compiles the chart unit terms for use
462 + * Helper function that returns the chart unit terms
1073 463 *
1074 464 * @param array an array of unit terms
1075 465 *
1076 466 * @return array an array of compiled unit terms
@@ -1075,10 +465,10 @@
1075 465 *
1076 466 * @return array an array of compiled unit terms
1077 467 */
1078 468 public function compile_unit_terms( $terms ) {
1079 - $compiled_terms = [];
1080 - $parents = [];
469 + $compiled_terms = array();
470 + $parents = array();
1081 471
1082 472 foreach ( $terms as $unit ) {
1083 473 if ( 0 == $unit->parent ) {
1084 474 $parents[ $unit->term_id ] = $unit->name;
@@ -1102,11 +492,11 @@
1102 492 * @return array an array of the newly generated unit terms
1103 493 */
1104 494 public function generate_unit_terms() {
1105 495 // Load the default terms array
1106 - $default_terms = require __DIR__ . '/array-default-unit-terms.php';
496 + $default_terms = require __DIR__ .'/array-default-unit-terms.php';
1107 497
1108 - $terms = [];
498 + $terms = array();
1109 499
1110 500 foreach ( $default_terms as $parent_term => $child_terms ) {
1111 501 $parent = (object) wp_insert_term( $parent_term, $this->slug . '-units' );
1112 502 $terms[] = get_term( $parent->term_id, $this->slug . '-units' );
@@ -1111,9 +501,9 @@
1111 501 $parent = (object) wp_insert_term( $parent_term, $this->slug . '-units' );
1112 502 $terms[] = get_term( $parent->term_id, $this->slug . '-units' );
1113 503
1114 504 foreach ( $child_terms as $child_term ) {
1115 - $term = (object) wp_insert_term( $child_term, $this->slug . '-units', [ 'parent' => $parent->term_id ] );
505 + $term = (object) wp_insert_term( $child_term, $this->slug . '-units', array( 'parent' => $parent->term_id ) );
1116 506 $terms[] = get_term( $term->term_id, $this->slug . '-units' );
1117 507 }
1118 508 }
1119 509
@@ -1120,76 +510,8 @@
1120 510 return $terms;
1121 511 }
1122 512
1123 513 /**
1124 - * Looks for the embed endpoint and serves up the requested chart if appropriate
1125 - */
1126 - public function template_redirect() {
1127 - global $wp_query;
1128 -
1129 - // Make sure this is a chart with the embed endpoint in the URL
1130 - if ( ! isset( $wp_query->query['post_type'] ) || ! isset( $wp_query->query['embed'] ) || 'm-chart' != $wp_query->query['post_type'] ) {
1131 - return;
1132 - }
1133 -
1134 - $post = get_post();
1135 -
1136 - if ( ! $post ) {
1137 - wp_die(
1138 - esc_html__( 'The chart could not be found', 'm-chart' ),
1139 - esc_html__( 'Chart not found', 'm-chart' ),
1140 - [ 'response' => 404 ]
1141 - );
1142 - }
1143 -
1144 - $settings = $this->get_settings();
1145 -
1146 - if ( 'enabled' != $settings['embeds'] ) {
1147 - wp_die(
1148 - esc_html__( 'Embeds of this type are not enabled', 'm-chart' ),
1149 - esc_html__( 'Embeds disabled', 'm-chart' ),
1150 - [ 'response' => 403 ]
1151 - );
1152 - exit;
1153 - }
1154 -
1155 - $this->is_iframe = true;
1156 -
1157 - $scripts = [
1158 - 'jquery',
1159 - $this->get_post_meta( $post->ID, 'library' ),
1160 - ];
1161 -
1162 - unset( $_GET['action'], $_GET['share'] );
1163 -
1164 - // This prevents issues when embedding with outside sites
1165 - header_remove( 'X-Frame-Options' );
1166 -
1167 - status_header( 200 );
1168 -
1169 - require __DIR__ . '/templates/iframe.php';
1170 - exit;
1171 - }
1172 -
1173 - /**
1174 - * Hook to the m_chart_update_post_meta action and call the required library specific function
1175 - *
1176 - * @param int $post_id WP post ID of the post you want chart args for
1177 - * @param array $parsed_meta the parsed chart meta passed by the action hook
1178 - */
1179 - public function m_chart_update_post_meta( $post_id, $parsed_meta ) {
1180 - $library = $this->library( $parsed_meta['library'] );
1181 -
1182 - // The chart's library plugin may be inactive (e.g. Highcharts charts after the
1183 - // extension was removed) in which case there's no library object to notify
1184 - if ( ! is_object( $library ) || ! method_exists( $library, 'm_chart_update_post_meta' ) ) {
1185 - return;
1186 - }
1187 -
1188 - $library->m_chart_update_post_meta( $post_id, $parsed_meta );
1189 - }
1190 -
1191 - /**
1192 514 * If the passed library is valid return TRUE otherwise FALSE
1193 515 *
1194 516 * @param string library string (i.e. 'highcharts')
1195 517 *
@@ -1195,256 +517,14 @@
1195 517 *
1196 518 * @return bool
1197 519 */
1198 520 public function is_valid_library( $library ) {
1199 - $libraries = $this->get_libraries();
1200 -
1201 - if ( ! isset( $libraries[ $library ] ) ) {
521 + if ( ! in_array( $library, $this->valid_libraries ) ) {
1202 522 return false;
1203 523 }
1204 524
1205 525 return true;
1206 526 }
1207 -
1208 - /**
1209 - * If current page is an AMP page returns true
1210 - *
1211 - * @return bool
1212 - */
1213 - public function is_amp_endpoint() {
1214 - if ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) {
1215 - return true;
1216 - }
1217 -
1218 - return false;
1219 - }
1220 -
1221 - /**
1222 - * Return the M Chart settings
1223 - *
1224 - * @return array current settings
1225 - */
1226 - public function get_settings( $setting = false ) {
1227 - // Memoize the resolved settings, get_post_meta() calls this on every invocation
1228 - // and the option + filter pipeline doesn't need to re-run within a request
1229 - // Invalidated via reset_settings() when the settings are saved
1230 - if ( isset( $this->resolved_settings ) ) {
1231 - $settings = $this->resolved_settings;
1232 - } else {
1233 - // Allow third party libraries to modify the default settings
1234 - $default_settings = apply_filters( 'm_chart_default_settings', $this->settings );
1235 -
1236 - $settings = (array) get_option( $this->slug, $default_settings );
1237 - $settings = wp_parse_args( $settings, $default_settings );
1238 -
1239 - // Make sure the set library is still valid
1240 - if ( ! $this->is_valid_library( $settings['library'] ) ) {
1241 - $settings['library'] = 'chartjs';
1242 - }
1243 -
1244 - $settings = apply_filters( 'm_chart_get_settings', $settings );
1245 -
1246 - $this->resolved_settings = $settings;
1247 - }
1248 -
1249 - if ( $setting && isset( $settings[ $setting ] ) ) {
1250 - return $settings[ $setting ];
1251 - } elseif ( $setting ) {
1252 - return null;
1253 - }
1254 -
1255 - return $settings;
1256 - }
1257 -
1258 - /**
1259 - * Drop the memoized settings so the next get_settings() call re-resolves them
1260 - *
1261 - * Called after the settings option is updated
1262 - */
1263 - public function reset_settings() {
1264 - $this->resolved_settings = null;
1265 - }
1266 -
1267 - /**
1268 - * Return an array of available charting libraries
1269 - *
1270 - * @return array current settings
1271 - */
1272 - public function get_libraries() {
1273 - return apply_filters( 'm_chart_get_libraries', $this->libraries );
1274 - }
1275 -
1276 - /**
1277 - * Return the chart types that support multiple data sets (multi-sheet tab bar)
1278 - *
1279 - * This is the single authoritative source for this list
1280 - * The value is passed to window.m_chart_admin.multi_sheet_types so the React UI always stays in sync with PHP
1281 - * Filtered via 'm_chart_multi_sheet_types' so library plugins can add or remove types
1282 - *
1283 - * @return array
1284 - */
1285 - public function get_multi_sheet_types() {
1286 - return apply_filters( 'm_chart_multi_sheet_types', [
1287 - 'scatter',
1288 - 'bubble',
1289 - 'radar',
1290 - 'radar-area',
1291 - 'boxplot',
1292 - 'violin',
1293 - ] );
1294 - }
1295 -
1296 - /**
1297 - * Return the current library
1298 - *
1299 - * @return string current library
1300 - */
1301 - public function get_library() {
1302 - if ( isset( $_GET['library'] ) && $this->is_valid_library( $_GET['library'] ) ) {
1303 - return $_GET['library'];
1304 - }
1305 -
1306 - return $this->get_settings( 'library' );
1307 - }
1308 -
1309 - /**
1310 - * Return the locale array
1311 - *
1312 - * When PHP's Intl extension is available, labels are generated in each locale's native language using Locale::getDisplayName()
1313 - * Falls back to the English labels in array-locale-codes.php otherwise
1314 - *
1315 - * @return array locales as used by Intl.NumberFormat
1316 - */
1317 - public function get_locales() {
1318 - $locales = require __DIR__ . '/array-locale-codes.php';
1319 -
1320 - if ( ! class_exists( 'Locale' ) ) {
1321 - return $locales;
1322 - }
1323 -
1324 - foreach ( $locales as $code => $english_label ) {
1325 - $native = Locale::getDisplayName( $code, $code );
1326 -
1327 - if ( $native ) {
1328 - $locales[ $code ] = esc_html( $native );
1329 - }
1330 - }
1331 -
1332 - return $locales;
1333 - }
1334 -
1335 - /**
1336 - * Return a recursively merged array out of the two given
1337 - *
1338 - * @param array a multi dimensional array that will be merged into
1339 - * @param array a multi dimensional array that will be merged recursively into the first one
1340 - *
1341 - * @return array the merged array
1342 - */
1343 - public function array_merge_recursive( &$a, $b ) {
1344 - foreach ( $b as $child => $value ) {
1345 - if ( isset( $a[ $child ] ) ) {
1346 - // New value exists so we'll need to move a level down
1347 - if ( is_array( $a[ $child ] ) && is_array( $value ) ) {
1348 - $this->array_merge_recursive( $a[ $child ], $value );
1349 - } else {
1350 - // New value is not an array so we override the old value with the new one
1351 - $a[ $child ] = $value;
1352 - }
1353 - } else {
1354 - // New value doesn't exist so we can just add it
1355 - $a[ $child ] = $value;
1356 - }
1357 - }
1358 -
1359 - return $a;
1360 - }
1361 -
1362 - /**
1363 - * Do things needed for version 1.7
1364 - */
1365 - public function upgrade_to_1_7() {
1366 - // Get all charts
1367 - $charts = get_posts(
1368 - [
1369 - 'post_type' => m_chart()->slug,
1370 - 'posts_per_page' => -1,
1371 - 'post_status' => 'any',
1372 - 'tax_query' => [
1373 - [
1374 - 'taxonomy' => 'post_tag',
1375 - 'field' => 'slug',
1376 - 'terms' => 'highcharts',
1377 - 'operator' => 'NOT IN',
1378 - ],
1379 - ],
1380 - ]
1381 - );
1382 -
1383 - // Add highcharts post_tag to all charts
1384 - foreach ( $charts as $chart ) {
1385 - wp_set_object_terms( $chart->ID, 'highcharts', 'post_tag' );
1386 - }
1387 -
1388 - // Update version
1389 - update_site_option( 'm_chart_version', '1.7' );
1390 - }
1391 -
1392 - /**
1393 - * Do things needed for version 1.7.4
1394 - */
1395 - public function upgrade_to_1_7_4() {
1396 - // Get all charts tagged with highcharts
1397 - $highcharts_charts = get_posts(
1398 - [
1399 - 'post_type' => m_chart()->slug,
1400 - 'posts_per_page' => -1,
1401 - 'post_status' => 'any',
1402 - 'tax_query' => [
1403 - [
1404 - 'taxonomy' => 'post_tag',
1405 - 'field' => 'slug',
1406 - 'terms' => 'highcharts',
1407 - 'operator' => 'IN',
1408 - ],
1409 - ],
1410 - ]
1411 - );
1412 -
1413 - foreach ( $highcharts_charts as $chart ) {
1414 - // Add highcharts as a term to the m-chart-library taxonomy
1415 - wp_set_object_terms( $chart->ID, 'highcharts', m_chart()->slug . '-library' );
1416 - // Remove highcharts as a term from the post_tag taxonomy
1417 - wp_remove_object_terms( $chart->ID, 'highcharts', 'post_tag' );
1418 - }
1419 -
1420 - // Get all charts tagged with chartjs
1421 - $chartjs_charts = get_posts(
1422 - [
1423 - 'post_type' => m_chart()->slug,
1424 - 'posts_per_page' => -1,
1425 - 'post_status' => 'any',
1426 - 'tax_query' => [
1427 - [
1428 - 'taxonomy' => 'post_tag',
1429 - 'field' => 'slug',
1430 - 'terms' => 'chartjs',
1431 - 'operator' => 'IN',
1432 - ],
1433 - ],
1434 - ]
1435 - );
1436 -
1437 - foreach ( $chartjs_charts as $chart ) {
1438 - // Add chartjs as a term to the m-chart-library taxonomy
1439 - wp_set_object_terms( $chart->ID, 'chartjs', m_chart()->slug . '-library' );
1440 - // Remove chartjs as a term from the post_tag taxonomy
1441 - wp_remove_object_terms( $chart->ID, 'chartjs', 'post_tag' );
1442 - }
1443 -
1444 - // Update version
1445 - update_site_option( 'm_chart_version', '1.7.4' );
1446 - }
1447 527 }
1448 528
1449 529 /**
1450 530 * Plugin object accessor
@@ -1451,22 +531,10 @@
1451 531 */
1452 532 function m_chart() {
1453 533 global $m_chart;
1454 534
1455 - if ( ! $m_chart instanceof M_Chart ) {
1456 - $m_chart = new M_Chart();
535 + if ( ! $m_chart ) {
536 + $m_chart = new M_Chart;
1457 537 }
1458 538
1459 539 return $m_chart;
1460 -}
1461 -
1462 -/**
1463 - * Freemius SDK accessor
1464 - *
1465 - * Thin global wrapper that delegates to the core class so Freemius ecosystem code and conventions keep working
1466 - * The actual configuration lives in M_Chart::freemius()
1467 - *
1468 - * @return Freemius the Freemius SDK instance for M Chart
1469 - */
1470 -function m_chart_fs() {
1471 - return m_chart()->freemius();
1472 540 }