PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.2.0
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.2.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
← All changes | classes/Visualizer/Source/Csv.php +60 -4 3.0.63.2.0 View file →
@@ -61,11 +61,23 @@
61 61 */
62 62 private function _fetchSeries( &$handle ) {
63 63 // read column titles
64 64 $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;
67 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 + }
79 +
68 80 if ( ! $labels || ! $types ) {
69 81 return false;
70 82 }
71 83
@@ -81,9 +93,12 @@
81 93 $types = array();
82 94 }
83 95
84 96 for ( $i = 0, $len = count( $labels ); $i < $len; $i++ ) {
85 - $default_type = $i == 0 ? 'string' : 'number';
97 + $default_type = $i === 0 ? 'string' : 'number';
98 +
99 + $labels[ $i ] = $this->toUTF8( $labels[ $i ] );
100 +
86 101 $this->_series[] = array(
87 102 'label' => $labels[ $i ],
88 103 'type' => isset( $types[ $i ] ) ? $types[ $i ] : $default_type,
89 104 );
@@ -130,10 +145,10 @@
130 145 return false;
131 146 }
132 147
133 148 // fetch data
149 + // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
134 150 while ( ( $data = fgetcsv( $handle, 0, VISUALIZER_CSV_DELIMITER, VISUALIZER_CSV_ENCLOSURE ) ) !== false ) {
135 -
136 151 $this->_data[] = $this->_normalizeData( $data );
137 152 }
138 153
139 154 // close file handle
@@ -154,5 +169,46 @@
154 169 public function getSourceName() {
155 170 return __CLASS__;
156 171 }
157 172
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 + }
158 214 }