Skip to content

Commit e5b1803

Browse files
Merge branch 'development' of https://github.com/codeinwp/visualizer into 3.1.3
2 parents ea9875d + 548dcc8 commit e5b1803

File tree

11 files changed

+202
-61
lines changed

11 files changed

+202
-61
lines changed

classes/Visualizer/Gutenberg/Block.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ public function enqueue_gutenberg_scripts() {
8686
if ( VISUALIZER_PRO ) {
8787
$type = 'pro';
8888
if ( apply_filters( 'visualizer_is_business', false ) ) {
89-
$type = 'business';
89+
$type = 'developer';
9090
}
9191
}
9292

classes/Visualizer/Module/Chart.php

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public function __construct( Visualizer_Plugin $plugin ) {
6161

6262
$this->_addAjaxAction( Visualizer_Plugin::ACTION_FETCH_DB_DATA, 'getQueryData' );
6363
$this->_addAjaxAction( Visualizer_Plugin::ACTION_SAVE_DB_QUERY, 'saveQuery' );
64+
$this->_addAjaxAction( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY, 'saveFilter' );
6465
}
6566

6667
/**
@@ -592,7 +593,9 @@ public function uploadData() {
592593

593594
if ( ! isset( $_POST['chart_data_src'] ) || Visualizer_Plugin::CF_SOURCE_FILTER !== $_POST['chart_data_src'] ) {
594595
// delete the filters in case this chart is being uploaded from other data sources
595-
delete_post_meta( $chart_id, 'visualizer-filter-config' );
596+
delete_post_meta( $chart_id, Visualizer_Plugin::CF_FILTER_CONFIG );
597+
delete_post_meta( $chart_id, '__transient-' . Visualizer_Plugin::CF_FILTER_CONFIG );
598+
delete_post_meta( $chart_id, '__transient-' . Visualizer_Plugin::CF_DB_QUERY );
596599

597600
// delete "import from db" specific parameters.
598601
delete_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY );
@@ -609,7 +612,7 @@ public function uploadData() {
609612
} elseif ( isset( $_FILES['local_data'] ) && $_FILES['local_data']['error'] == 0 ) {
610613
$source = new Visualizer_Source_Csv( $_FILES['local_data']['tmp_name'] );
611614
} elseif ( isset( $_POST['chart_data'] ) && strlen( $_POST['chart_data'] ) > 0 ) {
612-
$source = apply_filters( 'visualizer_pro_handle_chart_data', $_POST['chart_data'], '' );
615+
$source = apply_filters( 'visualizer_pro_handle_chart_data', $_POST['chart_data'], '', $chart_id, $_POST );
613616
} else {
614617
$render->message = esc_html__( 'CSV file with chart data was not uploaded. Please, try again.', 'visualizer' );
615618
}
@@ -846,4 +849,33 @@ public function saveQuery() {
846849
defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
847850
}
848851
}
852+
853+
854+
/**
855+
* Saves the filter query and the schedule.
856+
*
857+
* @access public
858+
*/
859+
public function saveFilter() {
860+
check_ajax_referer( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY . Visualizer_Plugin::VERSION, 'security' );
861+
862+
$chart_id = filter_input(
863+
INPUT_GET,
864+
'chart',
865+
FILTER_VALIDATE_INT,
866+
array(
867+
'options' => array(
868+
'min_range' => 1,
869+
),
870+
)
871+
);
872+
873+
$hours = $_POST['refresh'];
874+
875+
do_action( 'visualizer_save_filter', $chart_id, $hours );
876+
877+
if ( ! ( defined( 'VISUALIZER_DO_NOT_DIE' ) && VISUALIZER_DO_NOT_DIE ) ) {
878+
defined( 'WP_TESTS_DOMAIN' ) ? wp_die() : exit();
879+
}
880+
}
849881
}

classes/Visualizer/Module/Setup.php

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function __construct( Visualizer_Plugin $plugin ) {
4545
register_activation_hook( VISUALIZER_BASEFILE, array( $this, 'activate' ) );
4646
register_deactivation_hook( VISUALIZER_BASEFILE, array( $this, 'deactivate' ) );
4747
$this->_addAction( 'visualizer_schedule_refresh_db', 'refreshDbChart' );
48-
$this->_addFilter( 'visualizer_schedule_refresh_chart', 'refresh_db_for_chart', null, 10, 3 );
48+
$this->_addFilter( 'visualizer_schedule_refresh_chart', 'refresh_db_for_chart', 10, 3 );
4949

5050
$this->_addAction( 'activated_plugin', 'onActivation' );
5151
$this->_addAction( 'init', 'setupCustomPostTypes' );
@@ -169,12 +169,11 @@ public function deactivate() {
169169
}
170170

171171
/**
172-
* Refresh the specific chart from the db. This is mostly for charts that have 0 refresh time i.e. live data.
172+
* Refresh the specific chart from the db.
173173
*
174174
* @param WP_Post $chart The chart object.
175175
* @param int $chart_id The chart id.
176-
* @param bool $force If this is true, then the chart data will be refreshed no matter if the chart requests live data or cached data.
177-
* If false, data will be refreshed only if the chart requests live data.
176+
* @param bool $force If this is true, then the chart data will be force refreshed. If false, data will be refreshed only if the chart requests live data.
178177
*
179178
* @access public
180179
*/
@@ -187,6 +186,16 @@ public function refresh_db_for_chart( $chart, $chart_id, $force = false ) {
187186
$chart = get_post( $chart_id );
188187
}
189188

189+
if ( ! $chart ) {
190+
return $chart;
191+
}
192+
193+
// check if the source is correct.
194+
$source = get_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, true );
195+
if ( $source !== 'Visualizer_Source_Query' ) {
196+
return $chart;
197+
}
198+
190199
// check if its a live-data chart or a cached-data chart.
191200
if ( ! $force ) {
192201
$hours = get_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, true );
@@ -196,15 +205,10 @@ public function refresh_db_for_chart( $chart, $chart_id, $force = false ) {
196205
}
197206
}
198207

199-
// check if the source is correct.
200-
$source = get_post_meta( $chart_id, Visualizer_Plugin::CF_SOURCE, true );
201-
if ( $source !== 'Visualizer_Source_Query_Params' ) {
202-
return $chart;
203-
}
204-
205208
$params = get_post_meta( $chart_id, Visualizer_Plugin::CF_DB_QUERY, true );
206209
$source = new Visualizer_Source_Query( $params );
207210
$source->fetch( false );
211+
208212
$error = $source->get_error();
209213
if ( empty( $error ) ) {
210214
update_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, $source->getSeries() );
@@ -246,7 +250,8 @@ public function refreshDbChart() {
246250
continue;
247251
}
248252

249-
$this->refresh_db_for_chart( null, $chart_id, false );
253+
// if the time is nigh, we force an update.
254+
$this->refresh_db_for_chart( null, $chart_id, true );
250255
$hours = get_post_meta( $chart_id, Visualizer_Plugin::CF_DB_SCHEDULE, true );
251256
$new_schedules[ $chart_id ] = time() + $hours * HOUR_IN_SECONDS;
252257
}

classes/Visualizer/Module/Sources.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public function addProUpsell( $old, $feature = null ) {
136136
if ( empty( $feature ) || ( in_array( $feature, $biz_features ) && ! apply_filters( 'visualizer_is_business', false ) ) ) {
137137
$plan = 'PRO';
138138
if ( in_array( $feature, $biz_features ) ) {
139-
$plan = 'BUSINESS';
139+
$plan = 'DEVELOPER';
140140
}
141141
$return = '<div class="only-pro-content">';
142142
$return .= ' <div class="only-pro-container">';

classes/Visualizer/Plugin.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class Visualizer_Plugin {
4141
const CF_SETTINGS = 'visualizer-settings';
4242

4343
const CF_SOURCE_FILTER = 'visualizer-source-filter';
44+
const CF_FILTER_CONFIG = 'visualizer-filter-config';
4445

4546
// custom actions
4647
const ACTION_GET_CHARTS = 'visualizer-get-charts';
@@ -61,6 +62,7 @@ class Visualizer_Plugin {
6162
*/
6263
const ACTION_FETCH_DB_DATA = 'visualizer-fetch-db-data';
6364
const ACTION_SAVE_DB_QUERY = 'visualizer-save-db-query';
65+
const ACTION_SAVE_FILTER_QUERY = 'visualizer-save-filter-query';
6466

6567
// custom filters
6668
const FILTER_CHART_WRAPPER_CLASS = 'visualizer-chart-wrapper-class';

classes/Visualizer/Render/Page/Data.php

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ protected function _renderSidebarContent() {
7676

7777
// this will allow us to open the correct source tab by default.
7878
$source_of_chart = strtolower( get_post_meta( $this->chart->ID, Visualizer_Plugin::CF_SOURCE, true ) );
79+
// both import from wp and import from db have the same source so we need to differentiate.
80+
$filter_config = get_post_meta( $this->chart->ID, Visualizer_Plugin::CF_FILTER_CONFIG, true );
81+
// if filter config is present, then its import from wp.
82+
if ( ! empty( $filter_config ) ) {
83+
$source_of_chart .= '_wp';
84+
}
7985
$type = get_post_meta( $this->chart->ID, Visualizer_Plugin::CF_CHART_TYPE, true );
8086
?>
8187
<span id="visualizer-chart-id" data-id="<?php echo $this->chart->ID; ?>" data-chart-source="<?php echo $source_of_chart; ?>" data-chart-type="<?php echo $type; ?>"></span>
@@ -215,16 +221,49 @@ class="dashicons dashicons-lock"></span></h2>
215221
</div>
216222
</li>
217223

218-
<li class="viz-group <?php echo apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature', 'schedule-chart' ); ?> ">
224+
<?php
225+
$save_filter = add_query_arg(
226+
array(
227+
'action' => Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY,
228+
'security' => wp_create_nonce( Visualizer_Plugin::ACTION_SAVE_FILTER_QUERY . Visualizer_Plugin::VERSION ),
229+
'chart' => $this->chart->ID,
230+
), admin_url( 'admin-ajax.php' )
231+
);
232+
?>
233+
<li class="viz-group visualizer_source_query_wp <?php echo apply_filters( 'visualizer_pro_upsell_class', 'only-pro-feature', 'schedule-chart' ); ?> ">
219234
<h2 class="viz-group-title viz-sub-group"><?php _e( 'Import from WordPress', 'visualizer' ); ?><span
220235
class="dashicons dashicons-lock"></span></h2>
221236
<div class="viz-group-content edit-data-content">
222237
<div>
223238
<p class="viz-group-description"><?php _e( 'You can import data from WordPress here.', 'visualizer' ); ?></p>
224-
<input type="button" id="filter-chart-button" class="button button-primary "
225-
value="<?php _e( 'Create Filters', 'visualizer' ); ?>" data-current="chart"
226-
data-t-filter="<?php _e( 'Show Chart', 'visualizer' ); ?>"
227-
data-t-chart="<?php _e( 'Create Filters', 'visualizer' ); ?>">
239+
<form id="vz-filter-wizard" action="<?php echo $save_filter; ?>" method="post" target="thehole">
240+
<p class="viz-group-description"><?php _e( 'How often do you want to refresh the data from WordPress.', 'visualizer' ); ?></p>
241+
<select name="refresh" id="vz-filter-import-time" class="visualizer-select">
242+
<?php
243+
$bttn_label = 'visualizer_source_query_wp' === $source_of_chart ? __( 'Modify Filter', 'visualizer' ) : __( 'Create Filter', 'visualizer' );
244+
$hours = get_post_meta( $this->chart->ID, Visualizer_Plugin::CF_DB_SCHEDULE, true );
245+
$schedules = apply_filters(
246+
'visualizer_schedules', array(
247+
'0' => __( 'Live', 'visualizer' ),
248+
'1' => __( 'Each hour', 'visualizer' ),
249+
'12' => __( 'Each 12 hours', 'visualizer' ),
250+
'24' => __( 'Each day', 'visualizer' ),
251+
'72' => __( 'Each 3 days', 'visualizer' ),
252+
)
253+
);
254+
foreach ( $schedules as $num => $name ) {
255+
$extra = $num == $hours ? 'selected' : '';
256+
?>
257+
<option value="<?php echo $num; ?>" <?php echo $extra; ?>><?php echo $name; ?></option>
258+
<?php
259+
}
260+
?>
261+
</select>
262+
263+
<input type="button" id="filter-chart-button" class="button button-secondary" value="<?php echo $bttn_label; ?>" data-current="chart" data-t-filter="<?php _e( 'Show Chart', 'visualizer' ); ?>" data-t-chart="<?php echo $bttn_label; ?>">
264+
<input type="button" id="db-filter-save-button" class="button button-primary" value="<?php _e( 'Save Schedule', 'visualizer' ); ?>">
265+
<?php echo apply_filters( 'visualizer_pro_upsell', '', 'db-query' ); ?>
266+
</form>
228267
<?php echo apply_filters( 'visualizer_pro_upsell', '', 'schedule-chart' ); ?>
229268
</div>
230269
</div>
@@ -244,42 +283,38 @@ class="dashicons dashicons-lock"></span></h2>
244283
class="dashicons dashicons-lock"></span></h2>
245284
<div class="viz-group-content edit-data-content">
246285
<div>
247-
<p class="viz-group-description"><?php _e( 'You can import data from the database here.', 'visualizer' ); ?></p>
248-
<form id="vz-db-wizard" action="<?php echo $save_query; ?>" method="post" target="thehole">
249-
<p class="viz-group-description"><?php _e( 'How often do you want to refresh the data from the database.', 'visualizer' ); ?></p>
250-
<select name="refresh" id="vz-db-import-time" class="visualizer-select">
251-
<?php
252-
$bttn_label = 'visualizer_source_query' === $source_of_chart ? __( 'Modify Query', 'visualizer' ) : __( 'Create Query', 'visualizer' );
253-
$hours = get_post_meta( $this->chart->ID, Visualizer_Plugin::CF_DB_SCHEDULE, true );
254-
$schedules = apply_filters(
255-
'visualizer_schedules', array(
256-
'0' => __( 'Live', 'visualizer' ),
257-
'1' => __( 'Each hour', 'visualizer' ),
258-
'12' => __( 'Each 12 hours', 'visualizer' ),
259-
'24' => __( 'Each day', 'visualizer' ),
260-
'72' => __( 'Each 3 days', 'visualizer' ),
261-
)
262-
);
263-
foreach ( $schedules as $num => $name ) {
264-
$extra = $num == $hours ? 'selected' : '';
286+
<p class="viz-group-description"><?php _e( 'You can import data from the database here.', 'visualizer' ); ?></p>
287+
<form id="vz-db-wizard" action="<?php echo $save_query; ?>" method="post" target="thehole">
288+
<p class="viz-group-description"><?php _e( 'How often do you want to refresh the data from the database.', 'visualizer' ); ?></p>
289+
<select name="refresh" id="vz-db-import-time" class="visualizer-select">
290+
<?php
291+
$bttn_label = 'visualizer_source_query' === $source_of_chart ? __( 'Modify Query', 'visualizer' ) : __( 'Create Query', 'visualizer' );
292+
$hours = get_post_meta( $this->chart->ID, Visualizer_Plugin::CF_DB_SCHEDULE, true );
293+
$schedules = apply_filters(
294+
'visualizer_schedules', array(
295+
'0' => __( 'Live', 'visualizer' ),
296+
'1' => __( 'Each hour', 'visualizer' ),
297+
'12' => __( 'Each 12 hours', 'visualizer' ),
298+
'24' => __( 'Each day', 'visualizer' ),
299+
'72' => __( 'Each 3 days', 'visualizer' ),
300+
)
301+
);
302+
foreach ( $schedules as $num => $name ) {
303+
$extra = $num == $hours ? 'selected' : '';
304+
?>
305+
<option value="<?php echo $num; ?>" <?php echo $extra; ?>><?php echo $name; ?></option>
306+
<?php
307+
}
265308
?>
266-
<option value="<?php echo $num; ?>" <?php echo $extra; ?>><?php echo $name; ?></option>
267-
<?php
268-
}
269-
?>
270-
</select>
271-
<input type="hidden" name="params" id="viz-db-wizard-params">
272-
273-
<input type="button" id="db-chart-button" class="button button-secondary "
274-
value="<?php echo $bttn_label; ?>" data-current="chart"
275-
data-t-filter="<?php _e( 'Show Chart', 'visualizer' ); ?>"
276-
data-t-chart="<?php echo $bttn_label; ?>">
277-
<input type="button" id="db-chart-save-button" class="button button-primary "
278-
value="<?php _e( 'Save Schedule', 'visualizer' ); ?>">
309+
</select>
310+
<input type="hidden" name="params" id="viz-db-wizard-params">
311+
312+
<input type="button" id="db-chart-button" class="button button-secondary" value="<?php echo $bttn_label; ?>" data-current="chart" data-t-filter="<?php _e( 'Show Chart', 'visualizer' ); ?>" data-t-chart="<?php echo $bttn_label; ?>">
313+
<input type="button" id="db-chart-save-button" class="button button-primary" value="<?php _e( 'Save Schedule', 'visualizer' ); ?>">
279314
<?php echo apply_filters( 'visualizer_pro_upsell', '', 'db-query' ); ?>
280-
</form>
281-
</div>
282-
</div>
315+
</form>
316+
</div>
317+
</div>
283318
</li>
284319

285320
<?php

classes/Visualizer/Render/Sidebar.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ protected function _renderAnimationSettings() {
363363
self::_renderCheckboxItem(
364364
esc_html__( 'Animate on startup', 'visualizer' ),
365365
'animation[startup]',
366-
$this->animation['startup'],
366+
isset( $this->animation['startup'] ) ? $this->animation['startup'] : 0,
367367
true,
368368
esc_html__( 'Determines if the chart will animate on the initial draw.', 'visualizer' )
369369
);

classes/Visualizer/Render/Sidebar/Type/DataTable.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ protected function _renderTableSettings() {
364364
*/
365365
protected function _renderColumnSettings() {
366366
self::_renderGroupStart( esc_html__( 'Column Settings', 'visualizer' ) );
367-
for ( $i = 0, $cnt = count( $this->__series ) - 1; $i < $cnt; $i++ ) {
367+
for ( $i = 0, $cnt = count( $this->__series ); $i < $cnt; $i++ ) {
368368
if ( ! empty( $this->__series[ $i ]['label'] ) ) {
369369
self::_renderSectionStart( esc_html( $this->__series[ $i ]['label'] ), false );
370370
$this->_renderFormatField( $i );

classes/Visualizer/Source/Csv.php

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,20 @@ public function __construct( $filename = null ) {
6262
private function _fetchSeries( &$handle ) {
6363
// read column titles
6464
$labels = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE );
65-
// read series types
66-
$types = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE );
65+
$types = null;
66+
67+
if ( false !== strpos( $this->_filename, 'tqx=out:csv' ) ) {
68+
$attributes = $this->_fetchSeriesForGoogleQueryLanguage( $labels );
69+
if ( ! $attributes['abort'] ) {
70+
$labels = $attributes['labels'];
71+
$types = $attributes['types'];
72+
}
73+
}
74+
75+
if ( is_null( $types ) ) {
76+
// read series types
77+
$types = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE );
78+
}
6779

6880
if ( ! $labels || ! $types ) {
6981
return false;
@@ -158,4 +170,45 @@ public function getSourceName() {
158170
return __CLASS__;
159171
}
160172

173+
/**
174+
* Adds support for QueryLanguage https://developers.google.com/chart/interactive/docs/querylanguage
175+
* where the user can provide something like /gviz/tq?tq=select%20A%2C%20B%20&tqx=out:csv after the URL of the raw spreadsheet
176+
* to get the subset of data specified by the query
177+
* this will conflate the heading and the type into one value viz. for heading XXX and type string, the value will become "XXX string"
178+
* so we need to split them apart logically
179+
* also the $types variable now contains the first row because the header and the type got conflated
180+
*/
181+
private function _fetchSeriesForGoogleQueryLanguage( $labels, $types = array() ) {
182+
$new_labels = array();
183+
$new_types = array();
184+
$abort = false;
185+
foreach ( $labels as $label ) {
186+
// get the index of the last space
187+
$index = strrpos( $label, ' ' );
188+
if ( $index === false ) {
189+
// no space here? something has gone wrong; abort the entire process.
190+
$abort = true;
191+
break;
192+
}
193+
$type = trim( substr( $label, $index + 1 ) );
194+
if ( ! self::_validateTypes( array( $type ) ) ) {
195+
// some other data type? abort the entire process.
196+
$abort = true;
197+
break;
198+
}
199+
$label = substr( $label, 0, $index );
200+
$new_labels[] = $label;
201+
$new_types[] = $type;
202+
}
203+
if ( ! $abort ) {
204+
$labels = $new_labels;
205+
$types = $new_types;
206+
}
207+
208+
return array(
209+
'abort' => $abort,
210+
'labels' => $labels,
211+
'types' => $types,
212+
);
213+
}
161214
}

0 commit comments

Comments
 (0)