PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 4.0.0
Visualizer – Tables & Charts Manager with Built-in AI Generator v4.0.0
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/Module/AIBuilder.php +18 -35 4.0.74.0.0 View file →
@@ -94,19 +94,8 @@
94 94 }
95 95 }
96 96
97 97 /**
98 - * Verify that the current user can edit a chart.
99 - *
100 - * @param int $chart_id Chart ID.
101 - */
102 - private function _verify_chart_access( $chart_id ): void {
103 - if ( ! self::can_edit_chart( $chart_id ) ) {
104 - wp_send_json_error( array( 'message' => __( 'Unauthorized.', 'visualizer' ) ), 403 );
105 - }
106 - }
107 -
108 - /**
109 98 * Persist chart data + series from a source.
110 99 *
111 100 * @param int $chart_id Chart ID.
112 101 * @param Visualizer_Source $source Data source instance.
@@ -169,9 +158,8 @@
169 158 $chart_id = intval( isset( $_POST['chart_id'] ) ? $_POST['chart_id'] : 0 );
170 159 if ( ! $chart_id || ! get_post( $chart_id ) ) {
171 160 wp_send_json_error( array( 'message' => __( 'Chart not found.', 'visualizer' ) ) );
172 161 }
173 - $this->_verify_chart_access( $chart_id );
174 162 wp_send_json_success(
175 163 array(
176 164 'upload_nonce' => wp_create_nonce( 'visualizer-ai-upload-' . $chart_id ),
177 165 )
@@ -191,9 +179,8 @@
191 179 $chart = $chart_id ? get_post( $chart_id ) : null;
192 180 if ( ! $chart || $chart->post_type !== Visualizer_Plugin::CPT_VISUALIZER ) {
193 181 wp_send_json_error( array( 'message' => __( 'Chart not found.', 'visualizer' ) ) );
194 182 }
195 - $this->_verify_chart_access( $chart_id );
196 183
197 184 $series = get_post_meta( $chart_id, Visualizer_Plugin::CF_SERIES, true );
198 185 $data = Visualizer_Module::get_chart_data( $chart, '', false );
199 186 $code = get_post_meta( $chart_id, self::CF_D3_CODE, true );
@@ -218,9 +205,9 @@
218 205
219 206 /**
220 207 * Determines whether a remote URL serves an XLSX file.
221 208 *
222 - * Uses the shared remote-fetch policy and checks ZIP magic number (PK\x03\x04).
209 + * Uses wp_safe_remote_get() and checks ZIP magic number (PK\x03\x04).
223 210 *
224 211 * @access private
225 212 * @param string $url The remote URL to probe.
226 213 * @return bool TRUE if the file appears to be XLSX, FALSE otherwise.
@@ -230,17 +217,16 @@
230 217 if ( ! $tmpfile ) {
231 218 return false;
232 219 }
233 220
234 - $response = Visualizer_Remote_Fetch::request(
221 + $response = wp_safe_remote_get(
235 222 $url,
236 223 array(
237 - 'timeout' => 15,
238 - 'redirection' => 5,
239 - 'stream' => true,
240 - 'filename' => $tmpfile,
241 - 'headers' => array( 'Range' => 'bytes=0-3' ),
242 - 'limit_response_size' => 4,
224 + 'timeout' => 15,
225 + 'redirection' => 5,
226 + 'stream' => true,
227 + 'filename' => $tmpfile,
228 + 'headers' => array( 'Range' => 'bytes=0-3' ),
243 229 )
244 230 );
245 231
246 232 if ( is_wp_error( $response ) ) {
@@ -271,9 +257,8 @@
271 257 }
272 258 if ( ! get_post( $chart_id ) ) {
273 259 wp_send_json_error( array( 'message' => __( 'Chart not found.', 'visualizer' ) ) );
274 260 }
275 - $this->_verify_chart_access( $chart_id );
276 261
277 262 $source_type = isset( $_POST['source_type'] ) ? sanitize_key( $_POST['source_type'] ) : 'csv_string';
278 263 $source = null;
279 264 $tmp_files = array();
@@ -311,8 +296,19 @@
311 296 wp_send_json_error( array( 'message' => __( 'No URL provided.', 'visualizer' ) ) );
312 297 }
313 298 $url = wp_unslash( $_POST['file_url'] );
314 299
300 + // Allow local absolute paths in dev (same CSVs used by Classic).
301 + if ( is_string( $url ) && file_exists( $url ) && is_readable( $url ) ) {
302 + $ext = strtolower( pathinfo( $url, PATHINFO_EXTENSION ) );
303 + if ( 'xlsx' === $ext && class_exists( 'Visualizer_Source_Xlsx' ) ) {
304 + $source = new Visualizer_Source_Xlsx( $url );
305 + } else {
306 + $source = new Visualizer_Source_Csv( $url );
307 + }
308 + break;
309 + }
310 +
315 311 if ( function_exists( 'wp_http_validate_url' ) ) {
316 312 $validated_url = wp_http_validate_url( (string) $url );
317 313 $url = false === $validated_url ? false : (string) $validated_url;
318 314 } else {
@@ -368,11 +364,8 @@
368 364 break;
369 365
370 366 // ── Database query ────────────────────────────────────────────────
371 367 case 'db_query':
372 - if ( ! current_user_can( 'manage_options' ) || ! is_super_admin() || ! Visualizer_Module::is_pro() ) {
373 - wp_send_json_error( array( 'message' => __( 'Action not allowed for this user.', 'visualizer' ) ), 403 );
374 - }
375 368 if ( empty( $_POST['db_query'] ) ) {
376 369 wp_send_json_error( array( 'message' => __( 'No query provided.', 'visualizer' ) ) );
377 370 }
378 371 $query = wp_unslash( $_POST['db_query'] );
@@ -438,9 +431,8 @@
438 431 $chart_id = intval( isset( $_POST['chart_id'] ) ? $_POST['chart_id'] : 0 );
439 432 if ( ! $chart_id || ! get_post( $chart_id ) ) {
440 433 wp_send_json_error( array( 'message' => __( 'Chart not found.', 'visualizer' ) ) );
441 434 }
442 - $this->_verify_chart_access( $chart_id );
443 435
444 436 $prompt = isset( $_POST['prompt'] ) ? sanitize_textarea_field( wp_unslash( $_POST['prompt'] ) ) : '';
445 437 $series = isset( $_POST['series'] ) ? wp_unslash( $_POST['series'] ) : '';
446 438 $data = isset( $_POST['data'] ) ? wp_unslash( $_POST['data'] ) : '';
@@ -501,12 +493,8 @@
501 493 $workflow_id = $response_body['data']['workflowId'];
502 494 }
503 495 }
504 496
505 - if ( ! empty( $workflow_id ) ) {
506 - set_transient( 'viz_ai_wf_' . $workflow_id, get_current_user_id(), 6 * HOUR_IN_SECONDS );
507 - }
508 -
509 497 wp_send_json_success(
510 498 array(
511 499 'workflow_id' => $workflow_id,
512 500 )
@@ -527,12 +515,8 @@
527 515 if ( empty( $workflow_id ) ) {
528 516 wp_send_json_error( array( 'message' => __( 'Missing workflow ID.', 'visualizer' ) ) );
529 517 }
530 518
531 - if ( (int) get_transient( 'viz_ai_wf_' . $workflow_id ) !== get_current_user_id() ) {
532 - wp_send_json_error( array( 'message' => __( 'Unauthorized.', 'visualizer' ) ), 403 );
533 - }
534 -
535 519 $agents_url = VISUALIZER_AGENTS_URL;
536 520 $workflow_slug = $this->_get_workflow_slug();
537 521 $headers = $this->_get_agents_headers();
538 522
@@ -572,9 +556,8 @@
572 556
573 557 if ( ! $chart_id || ! get_post( $chart_id ) ) {
574 558 wp_send_json_error( array( 'message' => __( 'Chart not found.', 'visualizer' ) ) );
575 559 }
576 - $this->_verify_chart_access( $chart_id );
577 560 if ( empty( $code ) ) {
578 561 wp_send_json_error( array( 'message' => __( 'No chart code found. Generate a chart first.', 'visualizer' ) ) );
579 562 }
580 563