PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 4.0.8
Visualizer – Tables & Charts Manager with Built-in AI Generator v4.0.8
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 All 149 releases
← All changes | classes/Visualizer/Render/Layout.php +1200 -29 3.1.24.0.8 View file →
@@ -27,8 +27,15 @@
27 27 */
28 28 class Visualizer_Render_Layout extends Visualizer_Render {
29 29
30 30 /**
31 + * Fallback time for live update option.
32 + *
33 + * @var float
34 + */
35 + public static $live_option_fallback_hour = 0.16; // 10 minutes
36 +
37 + /**
31 38 * Renders template.
32 39 *
33 40 * @since 1.0.0
34 41 *
@@ -48,28 +55,31 @@
48 55 return call_user_func( array( __CLASS__, '_render' . str_replace( ' ', '', ucwords( str_replace( '-', ' ', $layout ) ) ) ), func_get_args() );
49 56 }
50 57
51 58 /**
52 - * Show the fake editor (just an empty div).
53 - *
54 - * @access public
55 - */
56 - public static function _renderFauxEditor( $args ) {
57 - echo '<div id="chart-lhs" class="visualizer-editor-lhs" style="display: none"></div>';
58 - }
59 -
60 - /**
61 59 * Show the DB query box.
62 60 *
63 61 * @access public
64 62 */
65 63 public static function _renderDbQuery( $args ) {
64 + global $wpdb;
66 65 $query = $args[1];
67 - ?>
66 + if ( ! $query ) {
67 + $query = '
68 +/* List Posts published per. month */
69 +SELECT CONCAT( YEAR(post_date), "/", MONTH(post_date) ) as date, COUNT(*) AS post_count
70 +FROM ' . $wpdb->prefix . 'posts
71 +WHERE post_type = "post" AND post_status = "publish"
72 +GROUP BY YEAR(post_date), MONTH(post_date)
73 +ORDER BY YEAR(post_date) DESC, MONTH(post_date) DESC;';
74 + }
75 + ?>
68 76 <div id='visualizer-db-query' style="display: none">
69 77 <div class="visualizer-db-query-form">
70 78 <div>
71 79 <form id='db-query-form'>
80 + <input type="hidden" name="chart_id" value="<?php echo $args[2]; ?>">
81 + <?php do_action( 'visualizer_db_query_add_layout', $args ); ?>
72 82 <textarea name='query' class='visualizer-db-query' placeholder="<?php _e( 'Your query goes here', 'visualizer' ); ?>"><?php echo $query; ?></textarea>
73 83 </form>
74 84 <div class='db-wizard-error'></div>
75 85 </div>
@@ -78,16 +88,36 @@
78 88 </div>
79 89 </div>
80 90 <div class='db-wizard-hints'>
81 91 <ul>
82 - <li><?php echo sprintf( __( 'For examples of queries and links to resources that you can use with this feature, please click %1$shere%2$s', 'visualizer' ), '<a href="' . VISUALIZER_DB_QUERY_DOC_URL . '" target="_blank">', '</a>' ); ?></li>
83 - <li><?php echo sprintf( __( 'Use %1$sControl+Space%2$s for autocompleting keywords or table names.', 'visualizer' ), '<span class="visualizer-emboss">', '</span>' ); ?></li>
92 + <li><?php echo __( 'Your database prefix is:', 'visualizer' ); ?> <span class="visualizer-emboss"><?php echo $wpdb->prefix; ?></span></li>
93 + <li>
94 + <?php
95 + echo sprintf(
96 + // translators: %1$s - HTML link tag, %2$s - HTML closing link tag.
97 + __( 'For examples of queries and links to resources that you can use with this feature, please click %1$shere%2$s', 'visualizer' ),
98 + '<a href="' . VISUALIZER_DB_QUERY_DOC_URL . '" target="_blank">',
99 + '</a>'
100 + );
101 + ?>
102 + </li>
103 + <li>
104 + <?php
105 + echo sprintf(
106 + // translators: %1$s - HTML link tag, %2$s - HTML closing link tag.
107 + __( 'Use %1$sShift+Space%2$s for autocompleting keywords or table names.', 'visualizer' ),
108 + '<span class="visualizer-emboss">',
109 + '</span>'
110 + );
111 + ?>
112 + </li>
113 + <?php do_action( 'visualizer_db_query_add_hints', $args ); ?>
84 114 </ul>
85 115 </div>
86 116 <div class='db-wizard-results'></div>
87 117
88 118 </div>
89 - <?php
119 + <?php
90 120 }
91 121
92 122 /**
93 123 * Show the DB wizard's results table.
@@ -97,33 +127,1174 @@
97 127 public static function _renderDbWizardResults( $args ) {
98 128 $headers = $args[1];
99 129 $results = $args[2];
100 130 ob_start();
101 - ?>
131 + ?>
102 132 <table cellspacing="0" width="100%" id="results">
103 133 <thead>
104 134 <tr>
105 - <?php
106 - foreach ( $headers as $header ) {
107 - echo '<th>' . $header['label'] . '</th>';
108 - }
109 - ?>
135 + <?php
136 + foreach ( $headers as $header ) {
137 + echo '<th>' . $header['label'] . '</th>';
138 + }
139 + ?>
110 140 </tr>
111 141 </thead>
112 142 <tfoot>
113 143 </tfoot>
114 - <tbody>
115 - <?php
116 - foreach ( $results as $result ) {
117 - echo '<tr>';
118 - foreach ( $result as $r ) {
119 - echo '<td>' . $r . '</td>';
144 + <tbody>
145 + <?php
146 + foreach ( $results as $result ) {
147 + echo '<tr>';
148 + foreach ( $result as $r ) {
149 + echo '<td>' . $r . '</td>';
150 + }
151 + echo '</tr>';
120 152 }
121 - echo '</tr>';
153 + ?>
154 + </tbody>
155 + </table>
156 + <?php
157 + return ob_get_clean();
122 158 }
123 - ?>
159 +
160 + /**
161 + * Show the JSON/REST parameters boxes.
162 + *
163 + * @access public
164 + */
165 + public static function _renderJsonScreen( $args ) {
166 + $id = $args[1];
167 + $action = esc_url(
168 + add_query_arg(
169 + array(
170 + 'action' => Visualizer_Plugin::ACTION_JSON_SET_DATA,
171 + 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_JSON_SET_DATA . Visualizer_Plugin::VERSION ),
172 + 'chart' => $id,
173 + ),
174 + admin_url( 'admin-ajax.php' )
175 + )
176 + );
177 +
178 + $is_wc_source = get_post_meta( $id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE, true );
179 + $url = get_post_meta( $id, Visualizer_Plugin::CF_JSON_URL, true );
180 + $root = get_post_meta( $id, Visualizer_Plugin::CF_JSON_ROOT, true );
181 + $paging = get_post_meta( $id, Visualizer_Plugin::CF_JSON_PAGING, true );
182 + $headers = get_post_meta( $id, Visualizer_Plugin::CF_JSON_HEADERS, true );
183 + if ( empty( $headers ) ) {
184 + $headers = array();
185 + }
186 + if ( $headers && empty( $headers['method'] ) ) {
187 + $headers['method'] = 'get';
188 + }
189 + $methods = apply_filters( 'visualizer_json_request_methods', array( 'GET', 'POST' ) );
190 +
191 + $auth = isset( $headers['auth'] ) ? $headers['auth'] : '';
192 + $auth_username = is_array( $auth ) && isset( $auth['username'] ) ? $auth['username'] : '';
193 + $auth_password = is_array( $auth ) && isset( $auth['password'] ) ? $auth['password'] : '';
194 + $auth_string = is_string( $auth ) ? $auth : '';
195 +
196 + // open the headers by default?
197 + $headers_open = ! empty( $auth_username ) || ! empty( $auth_string );
198 + ?>
199 + <div id="visualizer-json-screen" style="display: none">
200 + <div class="visualizer-json-form">
201 + <h3 class="viz-step step1"><?php _e( 'STEP 1: Specify the JSON endpoint/URL', 'visualizer' ); ?></h3>
202 + <div>
203 + <form id="json-endpoint-form">
204 + <div class="json-wizard-hints">
205 + <ul class="info">
206 + <li>
207 + <?php
208 + echo sprintf(
209 + // translators: %1$s - HTML link tag, %2$s - HTML closing link tag.
210 + __( 'If you want to add authentication or headers to the endpoint or change the request in any way, please refer to our document %1$shere%2$s.', 'visualizer' ),
211 + '<a href="https://docs.themeisle.com/article/1043-visualizer-how-to-extend-rest-endpoints-with-json-response" target="_blank">',
212 + '</a>'
213 + );
214 + ?>
215 + </li>
216 + </ul>
217 + </div>
218 +
219 + <input
220 + type="url"
221 + id="vz-import-json-url"
222 + name="url"
223 + value="<?php echo esc_url( $url ); ?>"
224 + placeholder="<?php esc_html_e( 'Please enter the URL', 'visualizer' ); ?>"
225 + class="visualizer-input json-form-element"
226 + <?php echo $is_wc_source ? 'readonly' : ''; ?>
227 + >
228 + <button class="button button-secondary button-small" id="visualizer-json-fetch"><?php esc_html_e( 'Fetch Endpoint', 'visualizer' ); ?></button>
229 +
230 + <div class="visualizer-json-subform">
231 + <h3 class="viz-substep <?php echo $headers_open ? 'open' : ''; ?>"><?php _e( 'Headers', 'visualizer' ); ?></h3>
232 + <div class="json-wizard-headers">
233 + <div class="json-wizard-header">
234 + <div><?php _e( 'Request Type', 'visualizer' ); ?></div>
235 + <div>
236 + <select name="method" class="json-form-element">
237 + <?php foreach ( $methods as $method ) { ?>
238 + <option value="<?php echo $method; ?>" <?php $headers && selected( $headers['method'], $method ); ?>><?php echo $method; ?></option>
239 + <?php } ?>
240 + </select>
241 + </div>
242 + </div>
243 + <div class="json-wizard-header">
244 + <div><?php _e( 'Credentials', 'visualizer' ); ?></div>
245 + <div>
246 + <input
247 + type="text"
248 + id="vz-import-json-username"
249 + name="username"
250 + value="<?php echo esc_attr( $auth_username ); ?>"
251 + placeholder="<?php esc_html_e( 'Username/Access Key', 'visualizer' ); ?>"
252 + class="json-form-element">
253 + &
254 + <input
255 + type="password"
256 + id="vz-import-json-password"
257 + name="password"
258 + value="<?php echo esc_attr( $auth_password ); ?>"
259 + placeholder="<?php esc_html_e( 'Password/Secret Key', 'visualizer' ); ?>"
260 + class="json-form-element">
261 + </div>
262 + </div>
263 + <div class="json-wizard-header">
264 + <div></div>
265 + <div><?php esc_html_e( 'OR', 'visualizer' ); ?></div>
266 + </div>
267 + <div class="json-wizard-header">
268 + <div><?php esc_html_e( 'Authorization', 'visualizer' ); ?></div>
269 + <div>
270 + <input
271 + type="text"
272 + id="vz-import-json-auth"
273 + name="auth"
274 + value="<?php echo esc_attr( $auth_string ); ?>"
275 + placeholder="<?php esc_html_e( 'e.g. SharedKey <AccountName>:<Signature>', 'visualizer' ); ?>"
276 + class="visualizer-input json-form-element">
277 + </div>
278 + </div>
279 + <div class="json-wizard-header">
280 + <div class="field-title"><?php esc_html_e( 'Additional headers', 'visualizer' ); ?></div>
281 + <div>
282 + <textarea name="additional_headers" class="visualizer-input" placeholder="<?php esc_html_e( 'Key:Value, Key2:Value2,...', 'visualizer' ); ?>"><?php echo esc_textarea( isset( $headers['additional_headers'] ) ? $headers['additional_headers'] : '' ); ?></textarea>
283 + </div>
284 + </div>
285 + </div>
286 + </div>
287 + </form>
288 + </div>
289 + <h3 class="viz-step step2 <?php echo empty( $url ) ? 'ui-state-disabled' : ''; ?> json-root-form"><?php _e( 'STEP 2: Choose the JSON root', 'visualizer' ); ?></h3>
290 + <div>
291 + <form id="json-root-form">
292 + <input type="hidden" name="chart" value="<?php echo $id; ?>">
293 + <select name="root" id="vz-import-json-root" class="json-form-element">
294 + <?php
295 + if ( ! empty( $root ) ) {
296 + ?>
297 + <option value="<?php echo esc_attr( $root ); ?>"><?php echo esc_html( str_replace( Visualizer_Source_Json::TAG_SEPARATOR, Visualizer_Source_Json::TAG_SEPARATOR_VIEW, $root ) ); ?></option>
298 + <?php
299 + }
300 + ?>
301 + </select>
302 + <button class="button button-secondary button-small" id="visualizer-json-parse"><?php esc_html_e( 'Parse Endpoint', 'visualizer' ); ?></button>
303 + </form>
304 + </div>
305 + <h3 class="viz-step step3 <?php echo empty( $root ) ? 'ui-state-disabled' : ''; ?>"><?php _e( 'STEP 3: Specify miscellaneous parameters', 'visualizer' ); ?></h3>
306 + <div>
307 + <form id="json-conclude-form-helper">
308 + <div class="<?php echo apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature' ); ?>">
309 + <div class="json-pagination">
310 + <select name="paging" id="vz-import-json-paging" class="json-form-element" data-template='<?php echo sprintf( 'Get results from the first %d pages using %s', apply_filters( 'visualizer_json_fetch_pages', 5, $url ), '?' ); ?>'>
311 + <option value="0" class="static"><?php _e( 'Get results from the first page only', 'visualizer' ); ?></option>
312 + <?php
313 + if ( ! empty( $paging ) ) {
314 + ?>
315 + <option value="<?php echo esc_attr( $paging ); ?>"><?php echo esc_html( sprintf( 'Get results from the first %d pages using %s', apply_filters( 'visualizer_json_fetch_pages', 5, $url ), str_replace( Visualizer_Source_Json::TAG_SEPARATOR, Visualizer_Source_Json::TAG_SEPARATOR_VIEW, $paging ) ) ); ?></option>
316 + <?php
317 + }
318 + ?>
319 + </select>
320 + <?php
321 + if ( ! Visualizer_Module::is_pro() ) {
322 + ?>
323 + <br/>
324 + <br/>
325 + <br/>
326 + <br/>
327 + <?php
328 + }
329 + ?>
330 + <?php echo apply_filters( 'visualizer_pro_upsell', '' ); ?>
331 + </div>
332 + </div>
333 + </form>
334 + </div>
335 + <h3 class="viz-step step4 ui-state-disabled"><?php _e( 'STEP 4: Select the data to display in the chart', 'visualizer' ); ?></h3>
336 + <div>
337 + <form id="json-conclude-form" action="<?php echo $action; ?>" method="post" target="thehole">
338 + <div class="json-wizard-hints html-table-editor-hints">
339 + <ul class="info">
340 + <li><?php _e( 'If you see Invalid Data in the table, you may have selected the wrong root to fetch data from. Please select an alternative from the JSON root dropdown.', 'visualizer' ); ?></li>
341 + <li><?php _e( 'Select whether to include the data in the chart. Each column selected will form one series.', 'visualizer' ); ?></li>
342 + <li><?php _e( 'If a column is selected to be included, specify its data type.', 'visualizer' ); ?></li>
343 + <li><?php _e( 'You can use drag/drop to reorder the columns but this column position is not saved. So when you reload the table, you may have to reorder again.', 'visualizer' ); ?></li>
344 + <li><?php _e( 'You can select any number of columns but the chart type selected will determine how many will display in the chart.', 'visualizer' ); ?></li>
345 + <li><?php _e( 'Once you have made your selection, click \'Show Chart\' on the right to view the chart.', 'visualizer' ); ?></li>
346 + </ul>
347 + </div>
348 + <div class="json-table"></div>
349 + <button class="button button-primary" style="display: none" id="visualizer-json-conclude"></button>
350 + </form>
351 + </div>
352 + </div>
353 + </div>
354 + <?php
355 + }
356 +
357 + /**
358 + * Show the simple editor(s).
359 + *
360 + * @access public
361 + */
362 + public static function _renderSimpleEditorScreen( $args ) {
363 + $chart_id = $args[1];
364 + $action = esc_url(
365 + add_query_arg(
366 + array(
367 + 'action' => Visualizer_Plugin::ACTION_UPLOAD_DATA,
368 + 'nonce' => wp_create_nonce( 'visualizer-upload-data' ),
369 + 'chart' => $chart_id,
370 + ),
371 + admin_url( 'admin-ajax.php' )
372 + )
373 + );
374 + ?>
375 + <div class="viz-simple-editor">
376 + <div class="viz-simple-editor-type viz-table-editor">
377 + <form id="table-editor-form" action="<?php echo $action; ?>" method="post" target="thehole">
378 + <div class="html-table-editor-hints">
379 + <ul class="info">
380 + <li><?php _e( 'Select whether to include the data in the chart. Each column selected will form one series.', 'visualizer' ); ?></li>
381 + <li><?php _e( 'If a column is selected to be included, specify its data type.', 'visualizer' ); ?></li>
382 + <li><?php _e( 'You can use drag/drop to reorder the columns but this column position is not saved. So when you reload the table, you may have to reorder again.', 'visualizer' ); ?></li>
383 + <li><?php _e( 'You can select any number of columns but the chart type selected will determine how many will display in the chart.', 'visualizer' ); ?></li>
384 + </ul>
385 + </div>
386 + <div class="viz-html-table">
387 + <?php Visualizer_Render_Layout::show( 'editor-table', null, $chart_id, 'viz-html-table', true, true ); ?>
388 + </div>
389 + <input type="hidden" name="table_data" value="yes">
390 + <input type="hidden" name="editor-type" value="table">
391 + </form>
392 + </div>
393 +
394 + <?php Visualizer_Render_Layout::show( 'text-editor', $chart_id ); ?>
395 +
396 + </div>
397 + <?php
398 + }
399 +
400 + /**
401 + * Show the text area editor.
402 + *
403 + * @access public
404 + */
405 + public static function _renderTextEditor( $args ) {
406 + $chart_id = $args[1];
407 + $csv = apply_filters( Visualizer_Plugin::FILTER_GET_CHART_DATA_AS, array(), $chart_id, 'csv-display' );
408 + $data = '';
409 + if ( ! empty( $csv ) && isset( $csv['string'] ) ) {
410 + $data = str_replace( PHP_EOL, "\n", stripslashes( $csv['string'] ) );
411 + }
412 + ?>
413 + <div class="viz-simple-editor-type viz-text-editor">
414 + <textarea id="edited_text"><?php echo $data; ?></textarea>
415 + </div>
416 + <?php
417 + }
418 +
419 + /**
420 + * Show the JSON endpoint's parsed table.
421 + *
422 + * @access public
423 + */
424 + public static function _renderEditorTable( $args ) {
425 + $data = $args[1];
426 + $chart_id = $args[2];
427 + $class = $args[3];
428 + $echo = $args[4];
429 + $editable_data = $args[5];
430 + $series = get_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, true );
431 + $headers = array();
432 +
433 + if ( is_null( $data ) ) {
434 + foreach ( $series as $column ) {
435 + $headers[] = $column['label'];
436 + }
437 + $chart = get_post( $chart_id );
438 + $type = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, true );
439 + $data = Visualizer_Module::get_chart_data( $chart, $type );
440 + } else {
441 + $headers = array_keys( $data[0] );
442 + }
443 +
444 + $classes = implode( ' ', array( 'viz-editor-table', $class ) );
445 +
446 + if ( $series ) {
447 + $temp = $series;
448 + $series = array();
449 + foreach ( $temp as $array ) {
450 + $series[ $array['label'] ] = $array['type'];
451 + }
452 + }
453 + if ( ! $echo ) {
454 + ob_start();
455 + }
456 + ?>
457 + <table cellspacing="0" width="100%" class="results cell-border stripe <?php echo $classes; ?>">
458 + <thead>
459 + <tr>
460 + <th><?php _e( 'Label', 'visualizer' ); ?></th>
461 + <?php
462 + foreach ( $headers as $header ) {
463 + if ( $editable_data ) {
464 + echo '<th><input type="text" name="header[]" value="' . esc_attr( $header ) . '"></th>';
465 + } else {
466 + echo '<th>' . $header . '</th>';
467 + }
468 + }
469 + ?>
470 + </tr>
471 + </thead>
472 + <tbody>
473 + <tr>
474 + <th><?php _e( 'Data Type', 'visualizer' ); ?></th>
475 + <?php
476 + $index = 0;
477 + foreach ( $headers as $header ) {
478 + echo '<td>';
479 + if ( $editable_data ) {
480 + echo '<select name="type[]">';
481 + } else {
482 + echo '<input name="header[]" type="hidden" value="' . $header . '">';
483 + echo '<select name="type[' . $header . ']" class="viz-select-data-type">';
484 + }
485 + echo '<option value="" title="' . __( 'Exclude from chart', 'visualizer' ) . '">' . __( 'Exclude', 'visualizer' ) . '</option>';
486 + echo '<option value="0" disabled title="' . __( 'Include in chart and select data type', 'visualizer' ) . '">--' . __( 'OR', 'visualizer' ) . '--</option>';
487 +
488 + foreach ( Visualizer_Source::getAllowedTypes() as $type ) {
489 + $selected = array_key_exists( $header, $series ) && $type === $series[ $header ] ? 'selected' : '';
490 + echo '<option value="' . $type . '" ' . $selected . '>' . $type . '</option>';
491 + }
492 +
493 + echo '</select></td>';
494 + }
495 + ?>
496 + </tr>
497 + <?php
498 + // for remote sources, the data exists inside 'data'.
499 + if ( array_key_exists( 'data', $data ) ) {
500 + $data = $data['data'];
501 + }
502 +
503 + foreach ( $data as $row ) {
504 + echo '<tr>';
505 + echo '<th>' . __( 'Value', 'visualizer' ) . '</th>';
506 + $index = 0;
507 + if ( empty( $row ) ) {
508 + echo '<td></td>';
509 + continue;
510 + }
511 + foreach ( array_values( $row ) as $value ) {
512 + if ( $editable_data ) {
513 + echo '<td><input type="text" name="data' . $index++ . '[]" value="' . esc_attr( stripslashes( $value ) ) . '"></td>';
514 + } else {
515 + echo '<td>' . ( is_array( $value ) ? __( 'Invalid Data', 'visualizer' ) : $value ) . '</td>';
516 + }
517 + }
518 +
519 + echo '</tr>';
520 + }
521 + ?>
124 522 </tbody>
125 523 </table>
126 - <?php
127 - return ob_get_clean();
524 + <?php
525 + if ( ! $echo ) {
526 + return ob_get_clean();
527 + }
528 + }
529 +
530 + /**
531 + * Generates the permissions tab.
532 + *
533 + * @access private
534 + */
535 + private static function _renderPermissions( $args ) {
536 + $chart_id = $args[1];
537 +
538 + // ignore for unit tests because Travis throws the error "Indirect modification of overloaded property Visualizer_Render_Page_Data::$permissions has no effect".
539 + if ( defined( 'WP_TESTS_DOMAIN' ) && function_exists( 'tests_add_filter' ) ) {
540 + return;
541 + }
542 +
543 + $permissions = apply_filters( 'visualizer_pro_get_permissions', null, $chart_id );
544 + if ( is_array( $permissions ) ) {
545 + $permissions = $permissions['permissions'];
546 + } else {
547 + $permissions = array();
548 + }
549 + if ( ! isset( $permissions['read'] ) ) {
550 + $permissions['read'] = 'all';
551 + }
552 + if ( ! isset( $permissions['edit'] ) ) {
553 + $permissions['edit'] = 'roles';
554 + $permissions['edit-specific'] = 'administrator';
555 + }
556 +
557 + Visualizer_Render_Sidebar::_renderGroupStart( esc_html__( 'Permissions', 'visualizer' ) . '<span class="dashicons dashicons-lock"></span>', '', apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature', 'chart-permissions' ), 'vz-permissions' );
558 + echo '<div style="position: relative">';
559 + Visualizer_Render_Sidebar::_renderSectionStart();
560 + Visualizer_Render_Sidebar::_renderSectionDescription( esc_html__( 'Configure permissions for the chart.', 'visualizer' ) );
561 + Visualizer_Render_Sidebar::_renderSectionEnd();
562 +
563 + Visualizer_Render_Sidebar::_renderSectionStart( esc_html__( 'Who can see this chart?', 'visualizer' ), false );
564 + Visualizer_Render_Sidebar::_renderSelectItem(
565 + '',
566 + 'permissions[read]',
567 + $permissions['read'],
568 + array(
569 + 'all' => esc_html__( 'All Users', 'visualizer' ),
570 + 'users' => esc_html__( 'Select Users', 'visualizer' ),
571 + 'roles' => esc_html__( 'Select Roles', 'visualizer' ),
572 + ),
573 + '',
574 + false,
575 + array( 'visualizer-permission', 'visualizer-permission-type', 'visualizer-permission-read' ),
576 + array(
577 + 'permission-type' => 'read',
578 + )
579 + );
580 +
581 + $options = apply_filters( 'visualizer_pro_get_permissions_data', array(), isset( $permissions['read'] ) ? $permissions['read'] : 'roles' );
582 +
583 + Visualizer_Render_Sidebar::_renderSelectItem(
584 + '',
585 + 'permissions[read-specific][]',
586 + isset( $permissions['read-specific'] ) ? $permissions['read-specific'] : array(),
587 + $options,
588 + '',
589 + true,
590 + array( 'visualizer-permission', 'visualizer-permission-specific', 'visualizer-permission-read-specific' )
591 + );
592 + Visualizer_Render_Sidebar::_renderSectionEnd();
593 +
594 + Visualizer_Render_Sidebar::_renderSectionStart( esc_html__( 'Who can edit this chart?', 'visualizer' ), false );
595 + Visualizer_Render_Sidebar::_renderSelectItem(
596 + '',
597 + 'permissions[edit]',
598 + $permissions['edit'],
599 + array(
600 + 'all' => esc_html__( 'All Users', 'visualizer' ),
601 + 'users' => esc_html__( 'Select Users', 'visualizer' ),
602 + 'roles' => esc_html__( 'Select Roles', 'visualizer' ),
603 + ),
604 + '',
605 + false,
606 + array( 'visualizer-permission', 'visualizer-permission-type', 'visualizer-permission-edit' ),
607 + array(
608 + 'permission-type' => 'edit',
609 + )
610 + );
611 +
612 + $options = apply_filters( 'visualizer_pro_get_permissions_data', array(), isset( $permissions['edit'] ) ? $permissions['edit'] : 'roles' );
613 +
614 + Visualizer_Render_Sidebar::_renderSelectItem(
615 + '',
616 + 'permissions[edit-specific][]',
617 + isset( $permissions['edit-specific'] ) ? $permissions['edit-specific'] : array(),
618 + $options,
619 + '',
620 + true,
621 + array( 'visualizer-permission', 'visualizer-permission-specific', 'visualizer-permission-edit-specific' )
622 + );
623 + Visualizer_Render_Sidebar::_renderSectionEnd();
624 + echo apply_filters( 'visualizer_pro_upsell', '', 'chart-permissions', 'https://docs.themeisle.com/article/1280-how-to-customize-permissions' );
625 + echo '</div>';
626 + Visualizer_Render_Sidebar::_renderGroupEnd();
627 + }
628 +
629 + /**
630 + * Show the Settings tab for this chart.
631 + *
632 + * @access public
633 + */
634 + public static function _renderTabAdvanced( $args ) {
635 + $chart_id = $args[1];
636 + $sidebar = $args[2];
637 +
638 + $chart_options = get_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, true );
639 + $backend_title = isset( $chart_options['backend-title'] ) && ! empty( $chart_options['backend-title'] ) ? $chart_options['backend-title'] : '';
640 +
641 + ?>
642 + <ul class="viz-group-wrapper full-height">
643 + <li class="viz-group open" id="vz-chart-settings">
644 + <ul class="viz-group-content">
645 + <ul class="viz-group-wrapper">
646 + <form id="settings-form" action="<?php echo esc_url( add_query_arg( 'nonce', wp_create_nonce() ) ); ?>" method="post">
647 + <input type="hidden" id="chart-img" name="chart-img">
648 + <input type="hidden" id="backend-title" name="backend-title" value="<?php echo esc_html( $backend_title ); ?>">
649 + <?php echo $sidebar; ?>
650 + <?php self::_renderPermissions( $args ); ?>
651 + <input type="hidden" name="save" value="1">
652 + </form>
653 + <form id="cancel-form" action="<?php echo esc_url( add_query_arg( 'nonce', wp_create_nonce() ) ); ?>" method="post">
654 + <input type="hidden" name="cancel" value="1">
655 + </form>
656 + </ul>
657 + </ul>
658 + </li>
659 + <?php
660 + }
661 +
662 + /**
663 + * Show the Docs tab for this chart.
664 + *
665 + * @access public
666 + */
667 + public static function _renderTabHelp( $args ) {
668 + $chart_id = $args[1];
669 + $type = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, true );
670 + switch ( $type ) {
671 + case 'tabular':
672 + $type = 'table';
673 + break;
674 + case 'polarArea':
675 + $type = 'polar-area';
676 + break;
677 + case 'radar':
678 + $type = 'radar-spider';
679 + break;
680 + }
681 +
682 + $displayType = str_replace( '-', '/', $type );
683 + ?>
684 + <ul class="viz-group-wrapper full-height">
685 + <li class="viz-group open" id="vz-chart-help">
686 + <ul class="viz-group-wrapper">
687 + <?php
688 + // open this tab by default.
689 + Visualizer_Render_Sidebar::_renderGroupStart( esc_html__( 'Documentation', 'visualizer' ), '', 'open' );
690 + Visualizer_Render_Sidebar::_renderSectionStart( esc_html__( 'General', 'visualizer' ), true );
691 + ?>
692 + <h4><span class="dashicons dashicons-editor-help"></span><a href="<?php echo VISUALIZER_MAIN_DOC; ?>" target="_blank"><?php _e( 'Main documentation page', 'visualizer' ); ?></a></h4>
693 + <h4><span class="dashicons dashicons-media-code"></span><a href="<?php echo VISUALIZER_CODE_SNIPPETS_URL; ?>" target="_blank"><?php _e( 'Custom code snippets', 'visualizer' ); ?></a></h4>
694 + <?php
695 + Visualizer_Render_Sidebar::_renderSectionEnd();
696 + // translators: %s - the chart type.
697 + Visualizer_Render_Sidebar::_renderSectionStart( sprintf( __( '%s chart', 'visualizer' ), ucwords( $displayType ) ), true );
698 + ?>
699 + <h4><span class="dashicons dashicons-video-alt2"></span>&nbsp;<a href="<?php echo str_replace( '#', "$type-chart", VISUALIZER_DEMO_URL ); ?>" target="_blank"><?php _e( 'View demo', 'visualizer' ); ?></a></h4>
700 + <h4><span class="dashicons dashicons-search"></span><a href="<?php echo str_replace( '#', $type, VISUALIZER_DOC_COLLECTION ); ?>" target="_blank">
701 + <?php
702 + echo sprintf(
703 + // translators: %s - the chart type.
704 + __( 'Articles containing "%s"', 'visualizer' ),
705 + $displayType
706 + );
707 + ?>
708 + </a>
709 + </h4>
710 + <?php
711 + Visualizer_Render_Sidebar::_renderSectionEnd();
712 + Visualizer_Render_Sidebar::_renderGroupEnd();
713 + ?>
714 + </ul>
715 + </li>
716 + </ul>
717 +
718 + <?php
719 + }
720 +
721 + /**
722 + * Show the Data Source tab for this chart.
723 + *
724 + * @access public
725 + */
726 + public static function _renderTabBasic( $args ) {
727 + $chart_id = $args[1];
728 +
729 + $upload_link = esc_url(
730 + add_query_arg(
731 + array(
732 + 'action' => Visualizer_Plugin::ACTION_UPLOAD_DATA,
733 + 'nonce' => wp_create_nonce( 'visualizer-upload-data' ),
734 + 'chart' => $chart_id,
735 + ),
736 + admin_url( 'admin-ajax.php' )
737 + )
738 + );
739 +
740 + // this will allow us to open the correct source tab by default.
741 + $source_of_chart = strtolower( get_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, true ) );
742 + // Import from woocommerce report.
743 + $is_woocommerce_source = strtolower( get_post_meta( $chart_id, Visualizer_Plugin::CF_IS_WOOCOMMERCE_SOURCE, true ) );
744 + if ( ! empty( $is_woocommerce_source ) ) {
745 + $source_of_chart .= '_wc';
746 + }
747 + // both import from wp and import from db have the same source so we need to differentiate.
748 + $filter_config = get_post_meta( $chart_id, Visualizer_Plugin::CF_FILTER_CONFIG, true );
749 + // if filter config is present, then its import from wp.
750 + if ( ! empty( $filter_config ) ) {
751 + $source_of_chart .= '_wp';
752 + }
753 + $editor_type = get_post_meta( $chart_id, Visualizer_Plugin::CF_EDITOR, true );
754 + if (
755 + $editor_type ||
756 + ! Visualizer_Module::is_pro() // Use Manual Source for non-pro users since it is the only unlocked source.
757 + ) {
758 + $source_of_chart = 'visualizer_source_manual';
759 + }
760 +
761 + $type = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, true );
762 + $lib = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_LIBRARY, true );
763 + ?>
764 + <ul class="viz-group-wrapper full-height">
765 + <li class="viz-group open" id="vz-chart-source">
766 + <ul class="viz-group-content">
767 + <ul class="viz-group-wrapper">
768 + <!-- manual -->
769 + <li class="viz-group visualizer_source_manual">
770 + <h2 class="viz-group-title viz-sub-group visualizer-editor-tab" data-current="chart" role="button" tabindex="0"><?php _e( 'Manual Data', 'visualizer' ); ?></h2>
771 + <div class="viz-group-content edit-data-content">
772 + <form id="editor-form" action="<?php echo $upload_link; ?>" method="post" target="thehole">
773 + <input type="hidden" id="chart-data" name="chart_data">
774 + <input type="hidden" id="chart-data-src" name="chart_data_src">
775 +
776 + <?php if ( Visualizer_Module::can_show_feature( 'simple-editor' ) ) { ?>
777 + <div>
778 + <p class="viz-group-description viz-editor-selection">
779 + <?php _e( 'Use the', 'visualizer' ); ?>
780 + <select name="editor-type" id="viz-editor-type">
781 + <?php
782 + if ( empty( $editor_type ) ) {
783 + $editor_type = Visualizer_Module::is_pro() ? 'excel' : 'text';
784 + }
785 + foreach ( apply_filters( 'visualizer_editors', array( 'text' => __( 'Text', 'visualizer' ), 'table' => __( 'Simple', 'visualizer' ) ) ) as $e_type => $e_label ) {
786 + ?>
787 + <option value="<?php echo $e_type; ?>" <?php selected( $editor_type, $e_type ); ?> ><?php echo $e_label; ?></option>
788 + <?php } ?>
789 + </select>
790 + <?php _e( 'editor to manually edit the chart data.', 'visualizer' ); ?>
791 + </p>
792 + <input type="button" id="editor-undo" class="button button-secondary" style="display: none" value="<?php _e( 'Undo Changes', 'visualizer' ); ?>">
793 + <input type="button" id="editor-button" class="button button-primary "
794 + value="<?php _e( 'Edit Data', 'visualizer' ); ?>" data-current="chart"
795 + data-t-editor="<?php _e( 'Show Chart', 'visualizer' ); ?>"
796 + data-t-chart="<?php _e( 'Edit Data', 'visualizer' ); ?>"
797 + >
798 + <p class="viz-group-description viz-info-msg" style="display:none"><?php echo sprintf( __( 'Please make sure you click \'Show Chart\' before you save the chart.', 'visualizer' ) ); ?></p>
799 + </div>
800 + <?php } else { ?>
801 + <input type="button" id="editor-undo" class="button button-secondary" style="display: none" value="<?php _e( 'Undo Changes', 'visualizer' ); ?>">
802 + <input type="button" id="editor-chart-button" class="button button-primary "
803 + value="<?php _e( 'View Editor', 'visualizer' ); ?>" data-current="chart"
804 + data-t-editor="<?php _e( 'Show Chart', 'visualizer' ); ?>"
805 + data-t-chart="<?php _e( 'View Editor', 'visualizer' ); ?>"
806 + >
807 + <p class="viz-group-description viz-info-msg" style="display:none"><?php echo sprintf( __( 'Please make sure you click \'Show Chart\' before you save the chart.', 'visualizer' ) ); ?></p>
808 + <?php } ?>
809 + </form>
810 + </div>
811 + </li>
812 +
813 + <!-- import from file -->
814 + <li class="viz-group visualizer_source_csv <?php echo apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature', 'import-file' ); ?> ">
815 + <h2 class="viz-group-title viz-sub-group visualizer-src-tab" role="button" tabindex="0"><?php _e( 'Import data from file', 'visualizer' ); ?><span class="dashicons dashicons-lock"></span></h2>
816 + <div class="viz-group-content">
817 + <div>
818 + <p class="viz-group-description"><?php esc_html_e( 'Select and upload your data file here. Supported formats: CSV, XLSX. The first row should contain the column headings. The second row should contain the series type (string, number, boolean, date, datetime, timeofday).', 'visualizer' ); ?></p>
819 + <p class="viz-group-description viz-info-msg">
820 + <b>
821 + <?php
822 + echo sprintf(
823 + // translators: $s - the chart type with the link attached.
824 + __( 'If you are unsure about how to format your data CSV then please take a look at this sample: %s. If you are using non-English characters, please make sure you save the file in UTF-8 encoding.', 'visualizer' ),
825 + '<a href="' . VISUALIZER_ABSURL . 'samples/' . $type . '.csv" target="_blank">' . $type . '.csv</a>'
826 + );
827 + ?>
828 + </b>
829 + </p>
830 + <form id="vz-csv-file-form" action="<?php echo $upload_link; ?>" method="post"
831 + target="thehole" enctype="multipart/form-data">
832 + <input type="hidden" id="remote-data" name="remote_data">
833 + <div class="">
834 + <input type="file" id="csv-file" name="local_data" accept=".csv,.xlsx">
835 + </div>
836 + <input type="button" class="button button-primary" id="vz-import-file"
837 + value="<?php _e( 'Import', 'visualizer' ); ?>">
838 + </form>
839 + <?php echo apply_filters( 'visualizer_pro_upsell', '', 'import-file' ); ?>
840 + </div>
841 + </div>
842 + </li>
843 + <!-- import from url -->
844 + <li class="viz-group visualizer-import-url visualizer_source_csv_remote visualizer_source_json <?php echo apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature', 'import-url' ); ?> ">
845 + <h2 class="viz-group-title viz-sub-group visualizer-src-tab" role="button" tabindex="0"><?php _e( 'Import data from URL', 'visualizer' ); ?><span class="dashicons dashicons-lock"></span></h2>
846 + <ul class="viz-group-content">
847 + <!-- import from csv url -->
848 + <li class="viz-subsection">
849 + <span class="viz-section-title" role="button" tabindex="0"><?php _e( 'Import from CSV / XLSX', 'visualizer' ); ?></span>
850 + <div class="only-pro-anchor">
851 + <div class="viz-section-items section-items">
852 + <p class="viz-group-description">
853 + <?php
854 + echo sprintf(
855 + // translators: %1$s - HTML link tag, %2$s - HTML closing link tag.
856 + __( 'You can use this to import data from a remote CSV or Excel (XLSX) file, or %1$sGoogle Spreadsheet%2$s.', 'visualizer' ),
857 + '<a href="https://docs.themeisle.com/article/607-how-can-i-populate-data-from-google-spreadsheet" target="_blank" >',
858 + '</a>'
859 + );
860 + ?>
861 + </p>
862 + <p class="viz-group-description viz-info-msg">
863 + <b>
864 + <?php
865 + echo sprintf(
866 + // translators: %s - the chart type with the link attached.
867 + __( 'If you are unsure about how to format your data CSV then please take a look at this sample: %s. If you are using non-English characters, please make sure you save the file in UTF-8 encoding.', 'visualizer' ),
868 + '<a href="' . VISUALIZER_ABSURL . 'samples/' . $type . '.csv" target="_blank">' . $type . '.csv</a>'
869 + );
870 + ?>
871 + </b>
872 + </p>
873 + <form id="vz-one-time-import" action="<?php echo $upload_link; ?>" method="post"
874 + target="thehole" enctype="multipart/form-data">
875 + <div class="remote-file-section">
876 + <input type="url" id="vz-schedule-url" name="remote_data" value="<?php echo esc_attr( get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_URL, true ) ); ?>" placeholder="<?php esc_html_e( 'Please enter the URL of a CSV or XLSX file', 'visualizer' ); ?>" class="visualizer-input visualizer-remote-url">
877 + </div>
878 + <select name="vz-import-time" id="vz-import-time" class="visualizer-select">
879 + <?php
880 + $hours = get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_SCHEDULE, true );
881 + $schedules = apply_filters(
882 + 'visualizer_chart_schedules', array(
883 + '-1' => __( 'One-time', 'visualizer' ),
884 + ),
885 + 'csv',
886 + $chart_id
887 + );
888 + foreach ( $schedules as $num => $name ) {
889 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
890 + $extra = self::is_hour_selected( $hours, $num ) ? 'selected' : '';
891 + ?>
892 + <option value="<?php echo esc_attr( $num ); ?>" <?php echo esc_attr( $extra ); ?>><?php echo esc_html( $name ); ?></option>
893 + <?php
894 + }
895 + do_action( 'visualizer_chart_schedules_spl', 'csv', $chart_id, 1 );
896 + ?>
897 + </select>
898 +
899 + <?php
900 + if ( ! Visualizer_Module::is_pro() ) {
901 + ?>
902 + <input type="button" id="view-remote-file" class="button button-primary" value="<?php _e( 'Import', 'visualizer' ); ?>">
903 + <?php
904 + } else {
905 + ?>
906 + <input type="button" id="vz-save-schedule" class="button button-primary" value="<?php _e( 'Import & Save schedule', 'visualizer' ); ?>">
907 + <?php
908 + }
909 + ?>
910 + <?php echo apply_filters( 'visualizer_pro_upsell', '', 'import-url' ); ?>
911 + </form>
912 + </div>
913 + </div>
914 + </li>
915 + <!-- import from json url -->
916 + <li class="viz-subsection">
917 + <span class="viz-section-title visualizer_source_json" role="button" tabindex="0"><?php _e( 'Import from JSON', 'visualizer' ); ?></span>
918 + <div class="only-pro-anchor">
919 + <div class="viz-section-items section-items">
920 + <p class="viz-group-description"><?php _e( 'You can choose here to import/synchronize your chart data with a remote JSON source. For more info check <a href="https://docs.themeisle.com/article/1052-how-to-generate-charts-from-json-data-rest-endpoints" target="_blank" >this</a> tutorial', 'visualizer' ); ?></p>
921 + <form id="vz-import-json" action="<?php echo $upload_link; ?>" method="post" target="thehole" enctype="multipart/form-data">
922 + <div class="remote-file-section">
923 + <?php
924 + $bttn_label = 'visualizer_source_json' === $source_of_chart ? __( 'Modify Parameters', 'visualizer' ) : __( 'Create Parameters', 'visualizer' );
925 + if ( Visualizer_Module::is_pro() ) {
926 + ?>
927 + <p class="viz-group-description"><?php _e( 'How often do you want to check the URL', 'visualizer' ); ?></p>
928 + <select name="time" id="vz-json-time" class="visualizer-select json-form-element" data-chart="<?php echo $chart_id; ?>">
929 + <?php
930 + $hours = get_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE, true );
931 + $schedules = apply_filters(
932 + 'visualizer_chart_schedules', array(
933 + '-1' => __( 'One-time', 'visualizer' ),
934 + ),
935 + 'json',
936 + $chart_id
937 + );
938 + foreach ( $schedules as $num => $name ) {
939 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
940 + $extra = self::is_hour_selected( $hours, $num ) ? 'selected' : '';
941 + ?>
942 + <option value="<?php echo esc_attr( $num ); ?>" <?php echo esc_attr( $extra ); ?>><?php echo esc_html( $name ); ?></option>
943 + <?php
944 + }
945 + do_action( 'visualizer_chart_schedules_spl', 'json', $chart_id, 1 );
946 + ?>
947 + </select>
948 + <?php
949 + }
950 + ?>
951 + </div>
952 +
953 + <input type="button" id="json-chart-button" class="button button-secondary show-chart-toggle"
954 + value="<?php echo $bttn_label; ?>" data-current="chart"
955 + data-t-filter="<?php _e( 'Show Chart', 'visualizer' ); ?>"
956 + data-t-chart="<?php echo $bttn_label; ?>">
957 + <?php
958 + if ( Visualizer_Module::is_pro() ) {
959 + ?>
960 + <input type="button" id="json-chart-save-button" class="button button-primary "
961 + value="<?php _e( 'Save Schedule', 'visualizer' ); ?>">
962 + <?php
963 + }
964 + ?>
965 + <?php echo apply_filters( 'visualizer_pro_upsell', '', 'import-url' ); ?>
966 + </form>
967 + </div>
968 + </div>
969 + </li>
970 + </ul>
971 + </li>
972 + <!-- import from chart -->
973 + <li class="viz-group viz-import-from-other <?php echo apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature' ); ?>">
974 + <h2 class="viz-group-title viz-sub-group"
975 + data-current="chart" role="button" tabindex="0"><?php _e( 'Import from other chart', 'visualizer' ); ?><span
976 + class="dashicons dashicons-lock"></span></h2>
977 + <div class="viz-group-content edit-data-content">
978 + <div>
979 + <p class="viz-group-description"><?php _e( 'You can import here data from your previously created charts', 'visualizer' ); ?></p>
980 + <form>
981 + <select name="vz-import-from-chart" id="chart-id" class="visualizer-select">
982 + <?php
983 + $fetch_link = esc_url(
984 + add_query_arg(
985 + array(
986 + 'action' => Visualizer_Module::is_pro() ? Visualizer_Pro::ACTION_FETCH_DATA : '',
987 + 'nonce' => Visualizer_Module::is_pro() ? wp_create_nonce( Visualizer_Pro::ACTION_FETCH_DATA ) : wp_create_nonce(),
988 + ),
989 + admin_url( 'admin-ajax.php' )
990 + )
991 + );
992 + $query_args_charts = array(
993 + 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
994 + 'posts_per_page' => 300,
995 + 'no_found_rows' => true,
996 + );
997 + $charts = array();
998 + $query = new WP_Query( $query_args_charts );
999 + while ( $query->have_posts() ) {
1000 + $chart = $query->next_post();
1001 + $settings = get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true );
1002 +
1003 + $title = '#' . $chart->ID;
1004 + if ( ! empty( $settings['title'] ) ) {
1005 + $title = $settings['title'];
1006 + }
1007 + // for ChartJS, title is an array.
1008 + if ( is_array( $title ) && isset( $title['text'] ) ) {
1009 + $title = $title['text'];
1010 + }
1011 + if ( empty( $title ) ) {
1012 + $title = '#' . $chart->ID;
1013 + }
1014 +
1015 + ?>
1016 + <option value="<?php echo $chart->ID; ?>"><?php echo $title; ?></option>
1017 + <?php
1018 + }
1019 + ?>
1020 +
1021 + </select>
1022 + </form>
1023 + <input type="button" id="existing-chart" class="button button-primary"
1024 + value="<?php _e( 'Import Chart', 'visualizer' ); ?>"
1025 + data-viz-link="<?php echo $fetch_link; ?>">
1026 + <?php
1027 + if ( ! Visualizer_Module_Admin::proFeaturesEnabled() ) {
1028 + echo apply_filters( 'visualizer_pro_upsell', '', 'import-chart' );
1029 + }
1030 + ?>
1031 + </div>
1032 + </div>
1033 + </li>
1034 +
1035 + <?php
1036 + $save_filter = esc_url(
1037 + add_query_arg(
1038 + array(
1039 + 'action' => Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY,
1040 + 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY . Visualizer_Plugin::VERSION ),
1041 + 'chart' => $chart_id,
1042 + ), admin_url( 'admin-ajax.php' )
1043 + )
1044 + );
1045 + ?>
1046 + <!-- import from WordPress -->
1047 + <li class="viz-group visualizer_source_query_wp <?php echo esc_attr( apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature', 'import-wp' ) ); ?> ">
1048 + <h2 class="viz-group-title viz-sub-group" role="button" tabindex="0"><?php _e( 'Import from WordPress', 'visualizer' ); ?><span
1049 + class="dashicons dashicons-lock"></span></h2>
1050 + <div class="viz-group-content edit-data-content">
1051 + <div>
1052 + <p class="viz-group-description"><?php _e( 'You can import data from WordPress here.', 'visualizer' ); ?></p>
1053 + <form id="vz-filter-wizard" action="<?php echo esc_url( $save_filter ); ?>" method="post" target="thehole">
1054 + <?php
1055 + $is_wp_source = 'visualizer_source_query_wp' === $source_of_chart;
1056 + $hours = get_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, true );
1057 + $bttn_label = $is_wp_source ? '1. ' . __( 'Modify Data Source', 'visualizer' ) : '1. ' . __( 'Choose Data Source', 'visualizer' );
1058 + ?>
1059 +
1060 + <!-- Step 1: Choose / modify data source -->
1061 + <input type="button" id="filter-chart-button" class="button button-secondary show-chart-toggle vz-import-step-btn" value="<?php echo esc_attr( $bttn_label ); ?>" data-current="chart" data-t-filter="<?php esc_attr_e( 'Show Chart', 'visualizer' ); ?>" data-t-chart="<?php echo esc_attr( $bttn_label ); ?>">
1062 +
1063 + <!-- Step 2: Sync schedule toggle -->
1064 + <div id="vz-wp-sync-step">
1065 + <button type="button" id="vz-wp-sync-btn" class="vz-import-step-toggle" aria-expanded="<?php echo $is_wp_source ? 'true' : 'false'; ?>">
1066 + <?php echo '2. ' . __( 'Set Sync Schedule', 'visualizer' ); ?>
1067 + <span class="dashicons dashicons-arrow-down-alt2"></span>
1068 + </button>
1069 + <div id="vz-wp-sync-options"<?php echo $is_wp_source ? '' : ' style="display:none"'; ?>>
1070 + <select name="refresh" id="vz-filter-import-time" class="visualizer-select">
1071 + <?php
1072 + $schedules = apply_filters(
1073 + 'visualizer_chart_schedules', array(
1074 + '-1' => __( 'One-time', 'visualizer' ),
1075 + ),
1076 + 'wp',
1077 + $chart_id
1078 + );
1079 + foreach ( $schedules as $num => $name ) {
1080 + $extra = self::is_hour_selected( $hours, $num ) ? 'selected' : '';
1081 + ?>
1082 + <option value="<?php echo esc_attr( $num ); ?>" <?php echo esc_attr( $extra ); ?>><?php echo esc_html( $name ); ?></option>
1083 + <?php
1084 + }
1085 + do_action( 'visualizer_chart_schedules_spl', 'wp', $chart_id, 1 );
1086 + ?>
1087 + </select>
1088 + <input type="button" id="db-filter-save-button" class="button button-primary" value="<?php _e( 'Save Schedule', 'visualizer' ); ?>">
1089 + </div>
1090 + </div>
1091 + </form>
1092 + <?php echo apply_filters( 'visualizer_pro_upsell', '', 'import-wp', 'https://docs.themeisle.com/article/1278-how-to-import-data-from-wordpress' ); ?>
1093 + </div>
1094 + </div>
1095 + </li>
1096 +
1097 + <!-- import from WooCommerce -->
1098 + <?php
1099 + if ( class_exists( 'WooCommerce', false ) ) :
1100 + $wc_source = strtolower( get_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_WOOCOMMERCE_SOURCE, true ) );
1101 + $wc_source_list = apply_filters(
1102 + 'visualizer_woocommerce_report_endpoints',
1103 + array(
1104 + array(
1105 + 'name' => esc_html__( 'Sales', 'visualizer' ),
1106 + 'endpoint' => esc_attr( 'sales' ),
1107 + ),
1108 + array(
1109 + 'name' => esc_html__( 'Top Sellers', 'visualizer' ),
1110 + 'endpoint' => esc_attr( 'top_sellers' ),
1111 + ),
1112 + array(
1113 + 'name' => esc_html__( 'Coupons Totals', 'visualizer' ),
1114 + 'endpoint' => esc_attr( 'coupons/totals' ),
1115 + ),
1116 + array(
1117 + 'name' => esc_html__( 'Customers Totals', 'visualizer' ),
1118 + 'endpoint' => esc_attr( 'customers/totals' ),
1119 + ),
1120 + array(
1121 + 'name' => esc_html__( 'Orders Totals', 'visualizer' ),
1122 + 'endpoint' => esc_attr( 'orders/totals' ),
1123 + ),
1124 + array(
1125 + 'name' => esc_html__( 'Products Totals', 'visualizer' ),
1126 + 'endpoint' => esc_attr( 'products/totals' ),
1127 + ),
1128 + array(
1129 + 'name' => esc_html__( 'Reviews Totals', 'visualizer' ),
1130 + 'endpoint' => esc_attr( 'reviews/totals' ),
1131 + ),
1132 + )
1133 + );
1134 + ?>
1135 + <li class="viz-group visualizer_woocommerce_source<?php echo 'visualizer_source_json_wc' === $source_of_chart ? ' open' : ''; ?> <?php echo apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature', 'import-wc-report' ); ?> ">
1136 + <h2 class="viz-group-title viz-sub-group" role="button" tabindex="0"><?php _e( 'Import from WooCommerce Reports', 'visualizer' ); ?><span class="dashicons dashicons-lock"></span></h2>
1137 + <div class="viz-group-content edit-data-content">
1138 + <div>
1139 + <p class="viz-group-description"><?php _e( 'You can choose here to import/synchronize your chart data with a WooCommerce report API. For more info check <a href="https://woocommerce.github.io/woocommerce-rest-api-docs/?shell#reports" target="_blank" >this</a> tutorial', 'visualizer' ); ?></p>
1140 + <form id="vz-import-woo-report" action="<?php echo $upload_link; ?>" method="post" target="thehole" enctype="multipart/form-data">
1141 + <div class="remote-file-section">
1142 + <?php
1143 + $bttn_label = 'visualizer_source_json_wc' === $source_of_chart ? __( 'Modify Parameters', 'visualizer' ) : __( 'Create Parameters', 'visualizer' );
1144 + ?>
1145 + <p class="viz-group-description"><?php _e( 'How often do you want to check the URL', 'visualizer' ); ?></p>
1146 + <select name="time" id="vz-woo-time" class="visualizer-select json-form-element" data-chart="<?php echo $chart_id; ?>">
1147 + <?php
1148 + $hours = get_post_meta( $chart_id, Visualizer_Plugin::CF_JSON_SCHEDULE, true );
1149 + $schedules = apply_filters(
1150 + 'visualizer_chart_schedules', array(
1151 + '-1' => __( 'One-time', 'visualizer' ),
1152 + ),
1153 + 'json',
1154 + $chart_id
1155 + );
1156 + foreach ( $schedules as $num => $name ) {
1157 + $extra = self::is_hour_selected( $hours, $num ) ? 'selected' : '';
1158 + ?>
1159 + <option value="<?php echo esc_attr( $num ); ?>" <?php echo esc_attr( $extra ); ?>><?php echo esc_html( $name ); ?></option>
1160 + <?php
1161 + }
1162 + do_action( 'visualizer_chart_schedules_spl', 'json', $chart_id, 1 );
1163 + ?>
1164 + </select>
1165 + <p class="viz-group-description"><?php _e( 'Select report endpoint', 'visualizer' ); ?></p>
1166 + <select name="vz_woo_source" id="vz-woo-source" class="visualizer-select json-form-element" data-chart="<?php echo $chart_id; ?>">
1167 + <option value=""></option>
1168 + <?php
1169 + if ( ! empty( $wc_source_list ) ) {
1170 + foreach ( $wc_source_list as $api ) {
1171 + if ( isset( $api['name'] ) && $api['endpoint'] ) {
1172 + echo sprintf( '<option value="%2$s" %3$s>%1$s</option>', $api['name'], $api['endpoint'], selected( $wc_source, $api['endpoint'], false ) ); // phpcs:ignore
1173 + }
1174 + }
1175 + }
1176 + ?>
1177 + </select>
1178 + </div>
1179 +
1180 + <input type="button" id="woo-chart-button" class="button button-secondary show-chart-toggle"
1181 + value="<?php echo $bttn_label; ?>" data-current="chart"
1182 + data-t-filter="<?php _e( 'Show Chart', 'visualizer' ); ?>"
1183 + data-t-chart="<?php echo $bttn_label; ?>"
1184 + <?php empty( $wc_source ) ? 'disabled' : ''; ?>
1185 + >
1186 + <input type="button" id="woo-chart-save-button" class="button button-primary "
1187 + value="<?php _e( 'Save Schedule', 'visualizer' ); ?>" <?php empty( $wc_source ) ? 'disabled' : ''; ?>>
1188 + </form>
1189 + <?php echo apply_filters( 'visualizer_pro_upsell', '', 'import-wc-report' ); ?>
1190 + </div>
1191 + </div>
1192 + </li>
1193 + <?php endif; ?>
1194 + <?php
1195 + $save_query = esc_url(
1196 + add_query_arg(
1197 + array(
1198 + 'action' => Visualizer_Plugin::ACTION_SAVE_DB_QUERY,
1199 + 'security' => wp_create_nonce( Visualizer_Plugin::ACTION_SAVE_DB_QUERY . Visualizer_Plugin::VERSION ),
1200 + 'chart' => $chart_id,
1201 + ), admin_url( 'admin-ajax.php' )
1202 + )
1203 + );
1204 + ?>
1205 + <!-- import from db -->
1206 + <li class="viz-group visualizer_source_query <?php echo esc_attr( apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature', 'db-query' ) ); ?>">
1207 + <h2 class="viz-group-title viz-sub-group" role="button" tabindex="0"><?php _e( 'Import from database', 'visualizer' ); ?><span
1208 + class="dashicons dashicons-lock"></span></h2>
1209 + <div class="viz-group-content edit-data-content">
1210 + <div>
1211 + <p class="viz-group-description"><?php _e( 'You can import data from the database here.', 'visualizer' ); ?></p>
1212 + <form id="vz-db-wizard" action="<?php echo esc_url( $save_query ); ?>" method="post" target="thehole">
1213 + <?php
1214 + $is_db_source = 'visualizer_source_query' === $source_of_chart;
1215 + $hours = get_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, true );
1216 + $bttn_label = $is_db_source ? __( '1. Modify Data Source', 'visualizer' ) : __( '1. Choose Data Source', 'visualizer' );
1217 + ?>
1218 +
1219 + <!-- Step 1: Choose / modify data source -->
1220 + <input type="hidden" name="params" id="viz-db-wizard-params">
1221 + <input type="button" id="db-chart-button" class="button button-secondary show-chart-toggle vz-import-step-btn" value="<?php echo esc_attr( $bttn_label ); ?>" data-current="chart" data-t-filter="<?php esc_attr_e( 'Show Chart', 'visualizer' ); ?>" data-t-chart="<?php echo esc_attr( $bttn_label ); ?>">
1222 +
1223 + <!-- Step 2: Sync schedule toggle -->
1224 + <div id="vz-db-sync-step">
1225 + <button type="button" id="vz-db-sync-btn" class="vz-import-step-toggle" aria-expanded="<?php echo $is_db_source ? 'true' : 'false'; ?>">
1226 + <?php echo '2. ' . __( 'Set Sync Schedule', 'visualizer' ); ?>
1227 + <span class="dashicons dashicons-arrow-down-alt2"></span>
1228 + </button>
1229 + <div id="vz-db-sync-options"<?php echo $is_db_source ? '' : ' style="display:none"'; ?>>
1230 + <select name="refresh" id="vz-db-import-time" class="visualizer-select">
1231 + <?php
1232 + $schedules = apply_filters(
1233 + 'visualizer_chart_schedules', array(
1234 + '-1' => __( 'One-time', 'visualizer' ),
1235 + ),
1236 + 'db',
1237 + $chart_id
1238 + );
1239 + foreach ( $schedules as $num => $name ) {
1240 + $extra = self::is_hour_selected( $hours, $num ) ? 'selected' : '';
1241 + ?>
1242 + <option value="<?php echo esc_attr( $num ); ?>" <?php echo esc_attr( $extra ); ?>><?php echo esc_html( $name ); ?></option>
1243 + <?php
1244 + }
1245 + do_action( 'visualizer_chart_schedules_spl', 'db', $chart_id, 1 );
1246 + ?>
1247 + </select>
1248 + <input type="button" id="db-chart-save-button" class="button button-primary" value="<?php _e( 'Save Schedule', 'visualizer' ); ?>">
1249 + </div>
1250 + </div>
1251 + <?php echo apply_filters( 'visualizer_pro_upsell', '', 'db-query', 'https://docs.themeisle.com/article/1279-how-to-import-data-from-a-database' ); ?>
1252 + </form>
1253 + </div>
1254 + </div>
1255 + </li>
1256 + </ul>
1257 + </li>
1258 + </ul>
1259 + </ul>
1260 +
1261 + <span id="visualizer-chart-id" data-id="<?php echo $chart_id; ?>" data-chart-source="<?php echo esc_attr( $source_of_chart ); ?>" data-chart-type="<?php echo esc_attr( $type ); ?>" data-chart-lib="<?php echo esc_attr( $lib ); ?>"></span>
1262 + <iframe id="thehole" name="thehole"></iframe>
1263 + <?php
1264 + }
1265 +
1266 + /**
1267 + * Check if the given hour is selected.
1268 + *
1269 + * @param int|float|string $hour The hour.
1270 + * @param int|float|string $reference The number.
1271 + *
1272 + * @return bool
1273 + */
1274 + public static function is_hour_selected( $hour, $reference ) {
1275 +
1276 + if ( ! is_numeric( $hour ) || ! is_numeric( $reference ) ) {
1277 + return false;
1278 + }
1279 +
1280 + $hour = floatval( $hour );
1281 + $reference = floatval( $reference );
1282 +
1283 + if ( self::is_live_update_option( $reference ) ) {
1284 + $reference = self::$live_option_fallback_hour;
1285 + }
1286 +
1287 + return abs( $hour - $reference ) < 0.000001;
1288 + }
1289 +
1290 + /**
1291 + * Check if the reference option is deprecated live update option.
1292 + *
1293 + * @param float $reference_hour The reference hour.
1294 + *
1295 + * @return bool
1296 + */
1297 + public static function is_live_update_option( $reference_hour ) {
1298 + return abs( $reference_hour ) < 0.000001;
128 1299 }
129 1300 }