PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.11.7
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.11.7
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/Module.php +47 -22 3.10.03.11.7 View file →
@@ -137,9 +137,9 @@
137 137 * @uses add_filter() To register filter hook.
138 138 *
139 139 * @access protected
140 140 * @param string $tag The name of the filter to hook the $method to.
141 - * @param type $method The name of the method to be called when the filter is applied.
141 + * @param string $method The name of the method to be called when the filter is applied.
142 142 * @param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action.
143 143 * @param int $accepted_args optional. The number of arguments the function accept (default 1).
144 144 * @return Visualizer_Module
145 145 */
@@ -234,9 +234,8 @@
234 234 $title = 'visualizer#' . $chart_id;
235 235 }
236 236
237 237 $filename = $title;
238 -
239 238 switch ( $type ) {
240 239 case 'csv':
241 240 $final = $this->_getCSV( $rows, $filename, false );
242 241 break;
@@ -271,8 +270,11 @@
271 270 $bom = chr( 0xEF ) . chr( 0xBB ) . chr( 0xBF );
272 271 // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
273 272 $fp = function_exists( 'tmpfile' ) ? @tmpfile() : null;
274 273 if ( null === $fp ) {
274 + if ( ! function_exists( 'wp_tempnam' ) ) {
275 + require_once ABSPATH . 'wp-admin/includes/file.php';
276 + }
275 277 $fp = fopen( wp_tempnam(), 'w+' );
276 278 }
277 279 if ( ! apply_filters( 'vizualizer_export_include_series_type', true ) ) {
278 280 unset( $rows[1] );
@@ -320,11 +322,11 @@
320 322 * @param array $rows The array of data.
321 323 * @param string $filename The name of the file to use.
322 324 */
323 325 private function _getExcel( $rows, $filename ) {
324 - // PHPExcel did not like sheet names longer than 31 characters and we will assume the same with PhpSpreadsheet
325 - $chart = substr( $filename, 0, 30 );
326 - $filename .= '.xlsx';
326 + // OpenSpout allows for long sheet names, but let's keep the same limit for compatibility.
327 + $chart = substr( $filename, 0, 30 );
328 + $filename .= '.xlsx';
327 329 if ( ! apply_filters( 'vizualizer_export_include_series_type', true ) ) {
328 330 unset( $rows[1] );
329 331 $rows = array_values( $rows );
330 332 $rows = array_map(
@@ -335,24 +337,34 @@
335 337 );
336 338 }
337 339 $vendor_file = VISUALIZER_ABSPATH . '/vendor/autoload.php';
338 340 if ( is_readable( $vendor_file ) ) {
339 - include_once( $vendor_file );
341 + include_once $vendor_file;
340 342 }
341 - $xlsData = '';
342 - if ( class_exists( 'PhpOffice\PhpSpreadsheet\Spreadsheet' ) ) {
343 - $doc = new PhpOffice\PhpSpreadsheet\Spreadsheet();
344 - $doc->getActiveSheet()->fromArray( $rows, null, 'A1' );
345 - $doc->getActiveSheet()->setTitle( sanitize_title( $chart ) );
346 - $doc = apply_filters( 'visualizer_excel_doc', $doc );
347 - $writer = PhpOffice\PhpSpreadsheet\IOFactory::createWriter( $doc, 'Xlsx' );
348 - ob_start();
349 - $writer->save( 'php://output' );
350 - $xlsData = ob_get_contents();
351 - ob_end_clean();
343 + $xlsData = '';
344 + if ( class_exists( 'OpenSpout\Writer\Common\Creator\WriterEntityFactory' ) ) {
345 + try {
346 + // Use OpenSpout to create the XLSX file in memory.
347 + $writer = \OpenSpout\Writer\Common\Creator\WriterEntityFactory::createXLSXWriter();
348 + $writer->openToFile( 'php://output' ); // Open to output instead of a file.
349 + $writer->getCurrentSheet()->setName( sanitize_title( $chart ) );
350 +
351 + // Write rows.
352 + foreach ( $rows as $row ) {
353 + $rowFromValues = \OpenSpout\Writer\Common\Creator\WriterEntityFactory::createRowFromArray( $row );
354 + $writer->addRow( $rowFromValues );
355 + }
356 +
357 + ob_start();
358 + $writer->close(); // Saves and closes the file in the output buffer.
359 + $xlsData = ob_get_clean();
360 + } catch ( Exception $e ) {
361 + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'OpenSpout writer error: ' . $e->getMessage(), 'error', __FILE__, __LINE__ );
362 + error_log( 'OpenSpout writer error: ' . $e->getMessage() );
363 + }
352 364 } else {
353 - do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Class PhpOffice\PhpSpreadsheet\Spreadsheet does not exist!', 'error', __FILE__, __LINE__ );
354 - error_log( 'Class PhpOffice\PhpSpreadsheet\Spreadsheet does not exist!' );
365 + do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, 'Class OpenSpout\Writer\Common\Creator\WriterEntityFactory does not exist!', 'error', __FILE__, __LINE__ );
366 + error_log( 'Class OpenSpout\Writer\Common\Creator\WriterEntityFactory does not exist!' );
355 367 }
356 368 return array(
357 369 'csv' => 'data:application/vnd.ms-excel;base64,' . base64_encode( $xlsData ),
358 370 'name' => $filename,
@@ -519,8 +531,12 @@
519 531
520 532 require_once( ABSPATH . 'wp-admin/includes/file.php' );
521 533 WP_Filesystem();
522 534 global $wp_filesystem;
535 + if ( ! is_a( $wp_filesystem, 'WP_Filesystem_Base' ) ) {
536 + $creds = request_filesystem_credentials( site_url() );
537 + wp_filesystem( $creds );
538 + }
523 539
524 540 $multisite_arg = '/';
525 541 if ( is_multisite() && ! is_main_site() ) {
526 542 $multisite_arg = '/sites/' . get_current_blog_id() . '/';
@@ -627,9 +643,9 @@
627 643 $settings['cssClassNames'] = $classes;
628 644 }
629 645
630 646 $img_path = VISUALIZER_ABSURL . 'images';
631 - $css .= ".locker,.locker-loader{position:absolute;top:0;left:0;width:100%;height:100%}.locker{z-index:1000;opacity:.8;background-color:#fff;-ms-filter:\"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)\";filter:alpha(opacity=80)}.locker-loader{z-index:1001;background:url($img_path/ajax-loader.gif) no-repeat center center}.dt-button{display:none!important}.visualizer-front-container.visualizer-lazy-render{content-visibility: auto;}.google-visualization-controls-categoryfilter label.google-visualization-controls-label {vertical-align: middle;}.google-visualization-controls-categoryfilter li.goog-inline-block {margin: 0 0.2em;}.google-visualization-controls-categoryfilter li {padding: 0 0.2em;}";
647 + $css .= ".locker,.locker-loader{position:absolute;top:0;left:0;width:100%;height:100%}.locker{z-index:1000;opacity:.8;background-color:#fff;-ms-filter:\"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)\";filter:alpha(opacity=80)}.locker-loader{z-index:1001;background:url($img_path/ajax-loader.gif) no-repeat center center}.dt-button{display:none!important}.visualizer-front-container.visualizer-lazy-render{content-visibility: auto;}.google-visualization-controls-categoryfilter label.google-visualization-controls-label {vertical-align: middle;}.google-visualization-controls-categoryfilter li.goog-inline-block {margin: 0 0.2em;}.google-visualization-controls-categoryfilter li {padding: 0 0.2em;}.visualizer-front-container .dataTables_scrollHeadInner{margin: 0 auto;}";
632 648 $css .= '</style>';
633 649
634 650 $arguments = array( $css, $settings );
635 651 apply_filters_ref_array( 'visualizer_inline_css', array( &$arguments ) );
@@ -730,13 +746,22 @@
730 746 /**
731 747 * Gets the features for the provided license type.
732 748 */
733 749 public static final function get_features_for_license( $plan ) {
750 + $is_new_personal = apply_filters( 'visualizer_is_new_personal', false );
734 751 switch ( $plan ) {
735 752 case 1:
736 - return array( 'import-wp', 'db-query', 'import-wc-report' );
753 + $features = array( 'import-wp', 'import-wc-report', 'import-file', 'import-url' );
754 + if ( ! $is_new_personal ) {
755 + $features[] = 'db-query';
756 + }
757 + return $features;
737 758 case 2:
738 - return array( 'schedule-chart', 'chart-permissions' );
759 + $features = array( 'schedule-chart', 'chart-permissions', 'import-chart', 'data-filter-configuration', 'frontend-actions' );
760 + if ( $is_new_personal ) {
761 + $features[] = 'db-query';
762 + }
763 + return $features;
739 764 }
740 765 }
741 766
742 767 /**