PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 1.0.0
Visualizer – Tables & Charts Manager with Built-in AI Generator v1.0.0
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 3.10.4 All 148 releases
visualizer / classes / Visualizer / Module / Chart.php

Chart.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 1.0.0, at classes/Visualizer/Module/Chart.php

470 lines 15.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // +----------------------------------------------------------------------+
4 // | Copyright 2013 Madpixels (email : visualizer@madpixels.net) |
5 // +----------------------------------------------------------------------+
6 // | This program is free software; you can redistribute it and/or modify |
7 // | it under the terms of the GNU General Public License, version 2, as |
8 // | published by the Free Software Foundation. |
9 // | |
10 // | This program is distributed in the hope that it will be useful, |
11 // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 // | GNU General Public License for more details. |
14 // | |
15 // | You should have received a copy of the GNU General Public License |
16 // | along with this program; if not, write to the Free Software |
17 // | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, |
18 // | MA 02110-1301 USA |
19 // +----------------------------------------------------------------------+
20 // | Author: Eugene Manuilov <eugene@manuilov.org> |
21 // +----------------------------------------------------------------------+
22
23 /**
24 * The module for all stuff related to getting, editing, creating and deleting charts.
25 *
26 * @category Visualizer
27 * @package Module
28 *
29 * @since 1.0.0
30 */
31 class Visualizer_Module_Chart extends Visualizer_Module {
32
33 const NAME = __CLASS__;
34
35 /**
36 * The chart object.
37 *
38 * @since 1.0.0
39 *
40 * @access private
41 * @var WP_Post
42 */
43 private $_chart;
44
45 /**
46 * Constructor.
47 *
48 * @since 1.0.0
49 *
50 * @access public
51 * @param Visualizer_Plugin $plugin The instance of the plugin.
52 */
53 public function __construct( Visualizer_Plugin $plugin ) {
54 parent::__construct( $plugin );
55
56 $this->_addAjaxAction( Visualizer_Plugin::ACTION_GET_CHARTS, 'getCharts' );
57 $this->_addAjaxAction( Visualizer_Plugin::ACTION_DELETE_CHART, 'deleteChart' );
58 $this->_addAjaxAction( Visualizer_Plugin::ACTION_CREATE_CHART, 'renderChartPages' );
59 $this->_addAjaxAction( Visualizer_Plugin::ACTION_EDIT_CHART, 'renderChartPages' );
60 $this->_addAjaxAction( Visualizer_Plugin::ACTION_UPLOAD_DATA, 'uploadData' );
61 $this->_addAjaxAction( Visualizer_Plugin::ACTION_CLONE_CHART, 'cloneChart' );
62 }
63
64 /**
65 * Sends json response.
66 *
67 * @since 1.0.0
68 *
69 * @access private
70 * @param array $results The response array.
71 */
72 private function _sendResponse( $results ) {
73 header( 'Content-type: application/json' );
74 nocache_headers();
75
76 echo json_encode( $results );
77 exit;
78 }
79
80 /**
81 * Returns chart data required for rendering.
82 *
83 * @since 1.0.0
84 *
85 * @access private
86 * @param WP_Post $chart The chart object.
87 * @return array The array of chart data.
88 */
89 private function _getChartArray( WP_Post $chart = null ) {
90 if ( is_null( $chart ) ) {
91 $chart = $this->_chart;
92 }
93
94 return array(
95 'type' => get_post_meta( $chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true ),
96 'series' => get_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, true ),
97 'settings' => get_post_meta( $chart->ID, Visualizer_Plugin::CF_SETTINGS, true ),
98 'data' => unserialize( $chart->post_content ),
99 );
100 }
101
102 /**
103 * Fetches charts from database.
104 *
105 * @since 1.0.0
106 *
107 * @access public
108 */
109 public function getCharts() {
110 $query_args = array(
111 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
112 'posts_per_page' => 9,
113 'paged' => filter_input( INPUT_GET, 'page', FILTER_VALIDATE_INT, array(
114 'options' => array(
115 'min_range' => 1,
116 'default' => 1,
117 )
118 ) )
119 );
120
121 $filter = filter_input( INPUT_GET, 'filter' );
122 if ( $filter && in_array( $filter, Visualizer_Plugin::getChartTypes() ) ) {
123 $query_args['meta_query'] = array(
124 array(
125 'key' => Visualizer_Plugin::CF_CHART_TYPE,
126 'value' => $filter,
127 'compare' => '=',
128 ),
129 );
130 }
131
132 $query = new WP_Query( $query_args );
133
134 $charts = array();
135 while( $query->have_posts() ) {
136 $chart = $query->next_post();
137
138 $chart_data = $this->_getChartArray( $chart );
139 $chart_data['id'] = $chart->ID;
140
141 $charts[] = $chart_data;
142 }
143
144 $this->_sendResponse( array(
145 'success' => true,
146 'data' => $charts,
147 'total' => $query->max_num_pages,
148 ) );
149 }
150
151 /**
152 * Deletes a chart from database.
153 *
154 * @since 1.0.0
155 * @uses wp_delete_post() To delete a chart.
156 *
157 * @access public
158 */
159 public function deleteChart() {
160 $is_post = $_SERVER['REQUEST_METHOD'] == 'POST';
161 $input_method = $is_post ? INPUT_POST : INPUT_GET;
162
163 $chart_id = $success = false;
164 $nonce = Visualizer_Security::verifyNonce( filter_input( $input_method, 'nonce' ) );
165 $capable = current_user_can( 'delete_posts' );
166 if ( $nonce && $capable ) {
167 $chart_id = filter_input( $input_method, 'chart', FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 1 ) ) );
168 if ( $chart_id ) {
169 $chart = get_post( $chart_id );
170 $success = $chart && $chart->post_type == Visualizer_Plugin::CPT_VISUALIZER;
171 }
172 }
173
174 if ( $success ) {
175 wp_delete_post( $chart_id, true );
176 }
177
178 if ( $is_post ) {
179 $this->_sendResponse( array( 'success' => $success ) );
180 }
181
182 wp_redirect( wp_get_referer() );
183 exit;
184 }
185
186 /**
187 * Renders appropriate page for chart builder. Creates new auto draft chart
188 * if no chart has been specified.
189 *
190 * @since 1.0.0
191 *
192 * @access public
193 */
194 public function renderChartPages() {
195 // check chart, if chart not exists, will create new one and redirects to the same page with proper chart id
196 $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT );
197 if ( !$chart_id || !( $chart = get_post( $chart_id ) ) || $chart->post_type != Visualizer_Plugin::CPT_VISUALIZER ) {
198 $default_type = 'line';
199
200 $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $default_type . '.csv' );
201 $source->fetch();
202
203 $chart_id = wp_insert_post( array(
204 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
205 'post_title' => 'Visualization',
206 'post_author' => get_current_user_id(),
207 'post_status' => 'auto-draft',
208 'post_content' => $source->getData(),
209 ) );
210
211 if ( $chart_id && !is_wp_error( $chart_id ) ) {
212 add_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, $default_type );
213 add_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, 1 );
214 add_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
215 add_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
216 add_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, array() );
217 }
218
219 wp_redirect( add_query_arg( 'chart', (int)$chart_id ) );
220 exit;
221 }
222
223 // enqueue and register scripts and styles
224 wp_register_style( 'visualizer-frame', VISUALIZER_ABSURL . 'css/frame.css', array(), Visualizer_Plugin::VERSION );
225
226 wp_register_script( 'visualizer-frame', VISUALIZER_ABSURL . 'js/frame.js', array( 'jquery' ), Visualizer_Plugin::VERSION, true );
227 wp_register_script( 'google-jsapi', '//www.google.com/jsapi', array(), null, true );
228 wp_register_script( 'visualizer-render', VISUALIZER_ABSURL . 'js/render.js', array( 'google-jsapi', 'visualizer-frame' ), Visualizer_Plugin::VERSION, true );
229 wp_register_script( 'visualizer-preview', VISUALIZER_ABSURL . 'js/preview.js', array( 'wp-color-picker', 'visualizer-render' ), Visualizer_Plugin::VERSION, true );
230
231 // dispatch pages
232 $this->_chart = $chart;
233 switch ( filter_input( INPUT_GET, 'tab' ) ) {
234 case 'data':
235 $this->_handleDataPage();
236 break;
237 case 'settings':
238 $this->_handleSettingsPage();
239 break;
240 case 'type':
241 default:
242 $this->_handleTypesPage();
243 break;
244 }
245
246 exit;
247 }
248
249 /**
250 * Handles chart type selection page.
251 *
252 * @since 1.0.0
253 *
254 * @access private
255 */
256 private function _handleTypesPage() {
257 // process post request
258 if ( $_SERVER['REQUEST_METHOD'] == 'POST' && Visualizer_Security::verifyNonce( filter_input( INPUT_POST, 'nonce' ) ) ) {
259 $type = filter_input( INPUT_POST, 'type' );
260 if ( in_array( $type, Visualizer_Plugin::getChartTypes() ) ) {
261 // save new chart type
262 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_TYPE, $type );
263
264 // if the chart has default data, update it with appropriate default data for new type
265 if ( filter_var( get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, true ), FILTER_VALIDATE_BOOLEAN ) ) {
266 $source = new Visualizer_Source_Csv( VISUALIZER_ABSPATH . DIRECTORY_SEPARATOR . 'samples' . DIRECTORY_SEPARATOR . $type . '.csv' );
267 $source->fetch();
268
269 $this->_chart->post_content = $source->getData();
270 wp_update_post( $this->_chart->to_array() );
271
272 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
273 }
274
275 // redirect to next tab
276 wp_redirect( add_query_arg( 'tab', 'data' ) );
277 return;
278 }
279 }
280
281 $render = new Visualizer_Render_Page_Types();
282 $render->type = get_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
283 $render->types = Visualizer_Plugin::getChartTypes();
284 $render->chart = $this->_chart;
285
286 wp_enqueue_style( 'visualizer-frame' );
287 wp_enqueue_script( 'visualizer-frame' );
288
289 wp_iframe( array( $render, 'render') );
290 }
291
292 /**
293 * Handles chart data page.
294 *
295 * @since 1.0.0
296 *
297 * @access private
298 */
299 private function _handleDataPage() {
300 $data = $this->_getChartArray();
301
302 $render = new Visualizer_Render_Page_Data();
303 $render->chart = $this->_chart;
304 $render->type = $data['type'];
305
306 unset( $data['settings']['width'], $data['settings']['height'] );
307
308 wp_enqueue_style( 'visualizer-frame' );
309 wp_enqueue_script( 'visualizer-render' );
310 wp_localize_script( 'visualizer-render', 'visualizer', array(
311 'charts' => array(
312 'canvas' => $data,
313 ),
314 ) );
315
316 wp_iframe( array( $render, 'render') );
317 }
318
319 /**
320 * Handles chart settigns page.
321 *
322 * @since 1.0.0
323 *
324 * @access private
325 */
326 private function _handleSettingsPage() {
327 if ( $_SERVER['REQUEST_METHOD'] == 'POST' && Visualizer_Security::verifyNonce( filter_input( INPUT_GET, 'nonce' ) ) ) {
328 if ( $this->_chart->post_status == 'auto-draft' ) {
329 $this->_chart->post_status = 'publish';
330 wp_update_post( $this->_chart->to_array() );
331 }
332
333 update_post_meta( $this->_chart->ID, Visualizer_Plugin::CF_SETTINGS, $_POST );
334
335 $render = new Visualizer_Render_Page_Send();
336 $render->text = sprintf( '[visualizer id="%d"]', $this->_chart->ID );
337
338 wp_iframe( array( $render, 'render') );
339 return;
340 }
341
342 $data = $this->_getChartArray();
343
344 $sidebar = '';
345 $sidebar_class = 'Visualizer_Render_Sidebar_Type_' . ucfirst( $data['type'] );
346 if ( class_exists( $sidebar_class, true ) ) {
347 $sidebar = new $sidebar_class( $data['settings'] );
348 $sidebar->__series = $data['series'];
349 $sidebar->__data = $data['data'];
350 }
351
352 unset( $data['settings']['width'], $data['settings']['height'] );
353
354 wp_enqueue_style( 'wp-color-picker' );
355 wp_enqueue_style( 'visualizer-frame' );
356
357 wp_enqueue_script( 'visualizer-preview' );
358 wp_localize_script( 'visualizer-render', 'visualizer', array(
359 'charts' => array(
360 'canvas' => $data,
361 ),
362 ) );
363
364 $render = new Visualizer_Render_Page_Settings();
365
366 $render->sidebar = $sidebar;
367 if ( filter_input( INPUT_GET, 'library', FILTER_VALIDATE_BOOLEAN ) ) {
368 $render->button = filter_input( INPUT_GET, 'action' ) == Visualizer_Plugin::ACTION_EDIT_CHART
369 ? esc_html__( 'Save Chart', Visualizer_Plugin::NAME )
370 : esc_html__( 'Create Chart', Visualizer_Plugin::NAME );
371 } else {
372 $render->button = esc_attr__( 'Insert Chart', Visualizer_Plugin::NAME );
373 }
374
375 wp_iframe( array( $render, 'render') );
376 }
377
378 /**
379 * Parses uploaded CSV file and saves new data for the chart.
380 *
381 * @since 1.0.0
382 *
383 * @access public
384 */
385 public function uploadData() {
386 // validate nonce
387 if ( !Visualizer_Security::verifyNonce( filter_input( INPUT_GET, 'nonce' ) ) ) {
388 status_header( 403 );
389 exit;
390 }
391
392 // check chart, if chart exists
393 $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT );
394 if ( !$chart_id || !( $chart = get_post( $chart_id ) ) || $chart->post_type != Visualizer_Plugin::CPT_VISUALIZER ) {
395 status_header( 400 );
396 exit;
397 }
398
399 $render = new Visualizer_Render_Page_Update();
400 if ( !isset( $_FILES['data'] ) || $_FILES['data']['error'] != 0 ) {
401 $render->message = esc_html__( "CSV file with chart data was not uploaded. Please, try again.", Visualizer_Plugin::NAME );
402 } else {
403 $source = new Visualizer_Source_Csv( $_FILES['data']['tmp_name'] );
404 if ( $source->fetch() ) {
405 $chart->post_content = $source->getData();
406 wp_update_post( $chart->to_array() );
407
408 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
409 update_post_meta( $chart->ID, Visualizer_Plugin::CF_SOURCE, $source->getSourceName() );
410 update_post_meta( $chart->ID, Visualizer_Plugin::CF_DEFAULT_DATA, 0 );
411
412 $render->data = $source->getData();
413 $render->series = $source->getSeries();
414 } else {
415 $render->message = esc_html__( "CSV file is broken or incorrect. Please, try again.", Visualizer_Plugin::NAME );
416 }
417 }
418
419 $render->render();
420 exit;
421 }
422
423 /**
424 * Clones the chart.
425 *
426 * @since 1.0.0
427 *
428 * @access public
429 */
430 public function cloneChart() {
431 $chart_id = $success = false;
432 $nonce = Visualizer_Security::verifyNonce( filter_input( INPUT_GET, 'nonce' ), Visualizer_Plugin::ACTION_CLONE_CHART );
433 $capable = current_user_can( 'edit_posts' );
434 if ( $nonce && $capable ) {
435 $chart_id = filter_input( INPUT_GET, 'chart', FILTER_VALIDATE_INT, array( 'options' => array( 'min_range' => 1 ) ) );
436 if ( $chart_id ) {
437 $chart = get_post( $chart_id );
438 $success = $chart && $chart->post_type == Visualizer_Plugin::CPT_VISUALIZER;
439 }
440 }
441
442 $redirect = wp_get_referer();
443 if ( $success ) {
444 $new_chart_id = wp_insert_post( array(
445 'post_type' => Visualizer_Plugin::CPT_VISUALIZER,
446 'post_title' => 'Visualization',
447 'post_author' => get_current_user_id(),
448 'post_status' => $chart->post_status,
449 'post_content' => $chart->post_content,
450 ) );
451
452 if ( $new_chart_id && !is_wp_error( $new_chart_id ) ) {
453 add_post_meta( $new_chart_id, Visualizer_Plugin::CF_CHART_TYPE, get_post_meta( $chart_id, Visualizer_Plugin::CF_CHART_TYPE, true ) );
454 add_post_meta( $new_chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, get_post_meta( $chart_id, Visualizer_Plugin::CF_DEFAULT_DATA, true ) );
455 add_post_meta( $new_chart_id, Visualizer_Plugin::CF_SOURCE, get_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, true ) );
456 add_post_meta( $new_chart_id, Visualizer_Plugin::CF_SERIES, get_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, true ) );
457 add_post_meta( $new_chart_id, Visualizer_Plugin::CF_SETTINGS, get_post_meta( $chart_id, Visualizer_Plugin::CF_SETTINGS, true ) );
458
459 $redirect = add_query_arg( array(
460 'page' => 'visualizer',
461 'type' => filter_input( INPUT_GET, 'type' ),
462 ), admin_url( 'upload.php' ) );
463 }
464 }
465
466 wp_redirect( $redirect );
467 exit;
468 }
469
470 }