PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.3.2
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.3.2
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/Json.php +72 -114 3.10.43.3.2 View file →
@@ -59,28 +59,8 @@
59 59 */
60 60 protected $_paging;
61 61
62 62 /**
63 - * The headers.
64 - *
65 - * @since ?
66 - *
67 - * @access protected
68 - * @var array
69 - */
70 - protected $_headers;
71 -
72 - /**
73 - * The other headers.
74 - *
75 - * @since 3.4.11
76 - *
77 - * @access protected
78 - * @var array
79 - */
80 - protected $_additional_headers;
81 -
82 - /**
83 63 * The array that contains the definition of the data.
84 64 *
85 65 * @since 1.0.0
86 66 *
@@ -110,19 +90,9 @@
110 90 }
111 91 if ( isset( $this->_args['paging'] ) ) {
112 92 $this->_paging = trim( $this->_args['paging'] );
113 93 }
114 - if ( isset( $this->_args['auth'] ) && ! empty( $this->_args['auth'] ) ) {
115 - $this->_headers = array( 'auth' => $this->_args['auth'] );
116 - } elseif ( isset( $this->_args['username'] ) && isset( $this->_args['password'] ) ) {
117 - $this->_headers = array( 'username' => $this->_args['username'], 'password' => $this->_args['password'] );
118 - }
119 - if ( isset( $this->_args['method'] ) ) {
120 - $this->_headers['method'] = $this->_args['method'];
121 - }
122 - if ( isset( $this->_args['additional_headers'] ) ) {
123 - $this->_additional_headers = $this->_args['additional_headers'];
124 - }
94 +
125 95 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Constructor called for params = %s', print_r( $params, true ) ), 'debug', __FILE__, __LINE__ );
126 96 }
127 97
128 98 /**
@@ -137,9 +107,9 @@
137 107 if ( false !== $roots ) {
138 108 return $roots;
139 109 }
140 110 $roots = $this->getRootElements( 'root', '', array(), $this->getJSON() );
141 - if ( is_null( $roots ) ) {
111 + if ( empty( $roots ) ) {
142 112 $this->_error = esc_html__( 'This does not appear to be a valid JSON feed. Please try again.', 'visualizer' );
143 113 return false;
144 114 }
145 115 return $roots;
@@ -183,15 +153,9 @@
183 153
184 154 $paging = array();
185 155 foreach ( $leaf as $key => $value ) {
186 156 // the paging element's value will most probably contain the url of the feed.
187 - if ( ! is_string( $value ) ) {
188 - continue;
189 - }
190 -
191 - // strip the url off the request parameters e.g. format=json as sometimes the pagination urls may not contain them.
192 - $url = wp_parse_url( $value );
193 - if ( 0 === stripos( $value, $this->_url ) || false !== stripos( $this->_url, $url['path'] ) ) {
157 + if ( is_string( $value ) && 0 === stripos( $value, $this->_url ) ) {
194 158 $paging[] = $key;
195 159 }
196 160 }
197 161
@@ -207,9 +171,9 @@
207 171 * @since ?
208 172 *
209 173 * @access public
210 174 */
211 - public function fetch() {
175 + public function parse() {
212 176 $url = $this->_url;
213 177 $data = array();
214 178 $page = 1;
215 179
@@ -215,16 +179,14 @@
215 179
216 180 while ( ! is_null( $url ) && $page++ < apply_filters( 'visualizer_json_fetch_pages', 5, $this->_url ) ) {
217 181 $array = $this->getJSON( $url );
218 182 if ( is_null( $array ) ) {
219 - break;
183 + return $data;
220 184 }
221 185
222 186 $root = explode( self::TAG_SEPARATOR, $this->_root );
223 - if ( count( $root ) > 1 ) {
224 - // get rid of the first element as that is the faux root element indicator
225 - array_shift( $root );
226 - }
187 + // get rid of the first element as that is the faux root element indicator
188 + array_shift( $root );
227 189 $leaf = $array;
228 190 foreach ( $root as $tag ) {
229 191 if ( array_key_exists( $tag, $leaf ) ) {
230 192 $leaf = $leaf[ $tag ];
@@ -241,13 +203,8 @@
241 203 $leaf = $temp;
242 204 }
243 205 }
244 206
245 - // JSONs that do not have a root element may fall into this condition e.g. /wp-json/wp/v2/posts
246 - if ( empty( $leaf ) ) {
247 - $leaf = $array;
248 - }
249 -
250 207 // now that we have got the final array we need to operate on, we will use this as the collection of series.
251 208 // lets check if the series is a flat-series e.g. https://api.exchangeratesapi.io/latest
252 209 // in this, all values of `$leaf` would be a string, not an array.
253 210 $values = array_values( $leaf );
@@ -280,13 +237,11 @@
280 237
281 238 $url = $this->getNextPage( $array );
282 239 }
283 240
284 - $this->_data = $data;
241 + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Parsed data endpoint %s with rooot %s is %s = ', $this->_url, $this->_root, print_r( $data, true ) ), 'debug', __FILE__, __LINE__ );
285 242
286 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Parsed data endpoint %s with root %s is %s', $this->_url, $this->_root, print_r( $data, true ) ), 'debug', __FILE__, __LINE__ );
287 -
288 - return true;
243 + return $data;
289 244 }
290 245
291 246 /**
292 247 * Determines which keys are common to all the data and returns an array with only those elements.
@@ -310,9 +265,8 @@
310 265 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Extracting data only for the common keys = %s', print_r( $keys, true ) ), 'debug', __FILE__, __LINE__ );
311 266
312 267 $rows = array();
313 268 foreach ( $data as $datum ) {
314 - $row = array();
315 269 foreach ( $datum as $key => $value ) {
316 270 if ( in_array( $key, $keys, true ) ) {
317 271 $row[ $key ] = $value;
318 272 }
@@ -363,12 +317,11 @@
363 317 * @access private
364 318 */
365 319 private function getRootElements( $parent, $now, $root, $array ) {
366 320 if ( is_null( $array ) ) {
367 - return null;
321 + return array();
368 322 }
369 323
370 - $root[] = $parent;
371 324 foreach ( $array as $key => $value ) {
372 325 if ( is_array( $value ) && ! empty( $value ) ) {
373 326 if ( ! is_numeric( $key ) ) {
374 327 $now = sprintf( '%s%s%s', $parent, self::TAG_SEPARATOR, $key );
@@ -378,10 +331,10 @@
378 331 }
379 332 $root = $this->getRootElements( $now, $key, $root, $value );
380 333 }
381 334 }
382 - $roots = array_unique( $root );
383 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Roots found for %s = %s', $this->_url, print_r( $roots, true ) ), 'debug', __FILE__, __LINE__ );
335 + $roots = array_filter( array_unique( $root ) );
336 + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Roots found for %s = ', $this->_url, print_r( $roots, true ) ), 'debug', __FILE__, __LINE__ );
384 337 return $roots;
385 338 }
386 339
387 340 /**
@@ -394,21 +347,16 @@
394 347 private function getJSON( $url = null ) {
395 348 if ( is_null( $url ) ) {
396 349 $url = $this->_url;
397 350 }
398 -
399 - $response = $this->connect( $url );
400 - if ( is_wp_error( $response ) || ! in_array( intval( $response['response']['code'] ), array( 200, 201 ), true ) ) {
401 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Error while fetching JSON endpoint %s = %s', $url, print_r( $response, true ) ), 'error', __FILE__, __LINE__ );
351 + // allow hooks to use any other args such as method=POST.
352 + $response = wp_remote_request( $url, apply_filters( 'visualizer_json_args', array( 'method' => 'GET' ), $url ) );
353 + if ( is_wp_error( $response ) ) {
354 + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Error while fetching JSON endpoint %s = ', $url, print_r( $response, true ) ), 'error', __FILE__, __LINE__ );
402 355 return null;
403 356 }
404 357
405 - // this filter can be used to rearrange columns e.g. in candlestick charts
406 - // or to add additional data to the root.
407 - $bom = pack( 'H*', 'EFBBBF' );
408 - $response_body = wp_remote_retrieve_body( $response );
409 - $response_body = preg_replace( "/^$bom/", '', $response_body );
410 - $array = apply_filters( 'visualizer_json_massage_data', json_decode( $response_body, true ), $url );
358 + $array = json_decode( wp_remote_retrieve_body( $response ), true );
411 359
412 360 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'JSON array for the endpoint is %s = ', print_r( $array, true ) ), 'debug', __FILE__, __LINE__ );
413 361
414 362 return $array;
@@ -413,69 +361,50 @@
413 361
414 362 return $array;
415 363 }
416 364
365 +
417 366 /**
418 - * Sets the authentication/authorization headers and connects to the endpoint.
367 + * Fetches series information. This is fetched only through the UI and not while refreshing the chart data.
419 368 *
420 - * @since ?
369 + * @since 1.0.0
421 370 *
422 371 * @access private
423 372 */
424 - private function connect( $url ) {
425 - $args = array( 'method' => 'GET' );
426 - if ( ! empty( $this->_headers ) ) {
427 - $args = array( 'method' => strtoupper( $this->_headers['method'] ) );
428 - if ( array_key_exists( 'auth', $this->_headers ) ) {
429 - if ( ! empty( $this->_headers['auth'] ) ) {
430 - $header_auth = explode( ':', $this->_headers['auth'] );
431 - $header_key = explode( ' ', reset( $header_auth ) );
432 - $args['headers'] = array( 'Authorization' => reset( $header_key ) . ' ' . base64_encode( end( $header_key ) . ':' . end( $header_auth ) ) );
373 + private function _fetchSeries() {
374 + $params = $this->_args;
375 + $headers = array_filter( $params['header'] );
376 + $types = array_filter( $params['type'] );
377 + $header_row = $type_row = array();
378 + if ( $headers ) {
379 + foreach ( $headers as $header ) {
380 + if ( ! empty( $types[ $header ] ) ) {
381 + $this->_series[] = array(
382 + 'label' => $header,
383 + 'type' => $types[ $header ],
384 + );
433 385 }
434 - } elseif ( array_key_exists( 'username', $this->_headers ) && array_key_exists( 'password', $this->_headers ) && ! empty( $this->_headers['username'] ) && ! empty( $this->_headers['password'] ) ) {
435 - $args['headers'] = array( 'Authorization' => 'Basic ' . base64_encode( $this->_headers['username'] . ':' . $this->_headers['password'] ) );
436 386 }
437 387 }
438 388
439 - $args = apply_filters( 'visualizer_json_args', $args, $url );
440 - if ( ! empty( $this->_additional_headers ) ) {
441 - $this->_additional_headers = explode( ',', $this->_additional_headers );
442 - $this->_additional_headers = array_filter( $this->_additional_headers );
443 - if ( ! empty( $this->_additional_headers ) ) {
444 - $this->_additional_headers = array_map(
445 - function( $headers ) {
446 - $headers = explode( ':', $headers );
447 - $headers = array_map( 'trim', $headers );
448 - return $headers;
449 - },
450 - $this->_additional_headers
451 - );
452 - foreach ( $this->_additional_headers as $additional_headers ) {
453 - $header_key = reset( $additional_headers );
454 - $header_value = end( $additional_headers );
455 - $args['headers'][ $header_key ] = $header_value;
456 - }
457 - }
458 - }
389 + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Series found for %s = ', $this->_url, print_r( $this->_series, true ) ), 'debug', __FILE__, __LINE__ );
459 390
460 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Connecting to %s with args = %s ', $url, print_r( $args, true ) ), 'debug', __FILE__, __LINE__ );
461 - return wp_remote_request( $url, $args );
391 + return true;
462 392 }
463 393
464 394 /**
465 - * Refresh the data for the provided series.
395 + * Fetches data information.
466 396 *
467 - * @since ?
397 + * @since 1.0.0
468 398 *
469 - * @access public
399 + * @access private
470 400 */
471 - public function refresh( $series ) {
472 - $this->_series = $series;
473 - $this->fetch();
401 + private function _fetchData() {
402 + $params = $this->_args;
474 403
475 404 $headers = wp_list_pluck( $this->_series, 'label' );
476 - $data = array();
477 - foreach ( $this->_data as $line ) {
405 + $data = $this->parse();
406 + foreach ( $data as $line ) {
478 407 $data_row = array();
479 408 foreach ( $line as $header => $value ) {
480 409 // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
481 410 if ( in_array( $header, $headers ) ) {
@@ -481,11 +410,40 @@
481 410 if ( in_array( $header, $headers ) ) {
482 411 $data_row[] = $value;
483 412 }
484 413 }
485 - $data[] = $this->_normalizeData( $data_row );
414 + $this->_data[] = $this->_normalizeData( $data_row );
486 415 }
487 - $this->_data = $data;
416 +
417 + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Data found for %s = ', $this->_url, print_r( $this->_data, true ) ), 'debug', __FILE__, __LINE__ );
418 +
419 + return true;
420 + }
421 +
422 + /**
423 + * Fetches information from source, parses it and builds series and data arrays.
424 + *
425 + * @since 1.0.0
426 + *
427 + * @access public
428 + * @return boolean TRUE on success, otherwise FALSE.
429 + */
430 + public function fetch() {
431 + $this->_fetchSeries();
432 + $this->_fetchData();
433 + return true;
434 + }
435 +
436 + /**
437 + * Refresh the data for the provided series.
438 + *
439 + * @since ?
440 + *
441 + * @access public
442 + */
443 + public function refresh( $series ) {
444 + $this->_series = $series;
445 + $this->_fetchData();
488 446 return true;
489 447 }
490 448
491 449 /**