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