From 772195507e770539869273a1e9b9f58fb4fb867c Mon Sep 17 00:00:00 2001 From: devsabbirhossain Date: Mon, 24 Jun 2024 13:30:38 +0600 Subject: [PATCH] fixed sub-category issue --- includes/Admin/Actions.php | 58 +++ includes/Admin/exportImport/CSVExporter.php | 398 ++++++++++++++++++ includes/Admin/exportImport/Showcases.php | 88 ++++ includes/Admin/views/admin-page.php | 20 +- .../Admin/views/settings/export-import.php | 82 +++- includes/Plugin.php | 1 + includes/Shortcodes/Shortcodes.php | 4 +- src/css/admin/admin.scss | 15 + 8 files changed, 638 insertions(+), 28 deletions(-) create mode 100644 includes/Admin/Actions.php create mode 100644 includes/Admin/exportImport/CSVExporter.php create mode 100644 includes/Admin/exportImport/Showcases.php diff --git a/includes/Admin/Actions.php b/includes/Admin/Actions.php new file mode 100644 index 0000000..f268c1b --- /dev/null +++ b/includes/Admin/Actions.php @@ -0,0 +1,58 @@ +process_step( 1 ); + $exporter->export(); + + wp_safe_redirect( wp_get_referer() ); + exit(); + } + + /** + * Import showcase data. + * + * @since 1.1.6 + * @return void + */ + public static function import_showcase_data() { + check_admin_referer( 'wcc_showcase_import' ); + $posted = wp_unslash( $_POST ); + + // if export type not set, die. + if ( empty( $export_type ) ) { + wp_die( esc_html__( 'Import type not found!', 'wc-category-showcase' ) ); + } + } +} diff --git a/includes/Admin/exportImport/CSVExporter.php b/includes/Admin/exportImport/CSVExporter.php new file mode 100644 index 0000000..7c944cb --- /dev/null +++ b/includes/Admin/exportImport/CSVExporter.php @@ -0,0 +1,398 @@ +capability ) ); + } + + /** + * Generate the CSV file. + * + * @since 1.0.2 + * + * @param int $step Step number. + */ + public function process_step( $step ) { + $this->page = absint( $step ); + global $wp_filesystem; + if ( empty( $wp_filesystem ) ) { + require_once ABSPATH . 'wp-admin/includes/file.php'; + WP_Filesystem(); + } + + if ( 1 === $this->page ) { + $wp_filesystem->delete( $this->get_file_path() ); + } + + $rows = $this->prepare_rows( $this->get_rows() ); + + $file = $this->get_file(); + + if ( 100 === $this->get_percent_complete() ) { + $file = chr( 239 ) . chr( 187 ) . chr( 191 ) . $this->get_column_headers() . $file; + } + + $file .= $rows; + $wp_filesystem->put_contents( $this->get_file_path(), $file, FS_CHMOD_FILE ); + } + + /** + * Serve the file and remove once sent to the client. + * + * @since 1.0.2 + */ + public function export() { + $this->send_headers(); + $this->send_content( $this->get_file() ); + global $wp_filesystem; + if ( empty( $wp_filesystem ) ) { + require_once ABSPATH . 'wp-admin/includes/file.php'; + WP_Filesystem(); + } + $wp_filesystem->delete( $this->get_file_path() ); + die(); + } + + /** + * Set filename to export to. + * + * @param string $filename Filename to export to. + */ + public function set_filename( $filename ) { + $this->filename = sanitize_file_name( str_replace( '.csv', '', $filename ) . '.csv' ); + } + + /** + * Generate and return a filename. + * + * @return string + */ + public function get_filename() { + $date = wp_date( 'Ymd' ); + return sanitize_file_name( "{$this->export_type}-$date.csv" ); + } + + /** + * Get total % complete. + * + * @since 1.0.2 + * @return int + */ + public function get_percent_complete() { + return $this->total_count ? floor( ( $this->get_total_exported() / $this->total_count ) * 100 ) : 100; + } + + /** + * Get count of records exported. + * + * @since 1.0.2 + * @return int + */ + public function get_total_exported() { + return ( ( $this->page - 1 ) * $this->limit ) + $this->exported_count; + } + + /** + * Get file path to export to. + * + * @since 1.0.2 + * @return string + */ + protected function get_file_path() { + $upload_dir = wp_upload_dir(); + + return trailingslashit( $upload_dir['basedir'] ) . $this->get_filename(); + } + + /** + * Get the file contents. + * + * @since 1.0.2 + * @return string + */ + protected function get_file() { + $file = ''; + global $wp_filesystem; + if ( empty( $wp_filesystem ) ) { + require_once ABSPATH . 'wp-admin/includes/file.php'; + WP_Filesystem(); + } + + // check if file exists. + if ( $wp_filesystem->exists( $this->get_file_path() ) ) { + $file = $wp_filesystem->get_contents( $this->get_file_path() ); + } else { + // create file if not exists. + $wp_filesystem->put_contents( $this->get_file_path(), $file, FS_CHMOD_FILE ); + } + + return $file; + } + + /** + * Export rows in CSV format. + * + * @param array $rows Rows to export. + * + * @since 1.0.2 + * @return string + */ + protected function prepare_rows( $rows ) { + $buffer = fopen( 'php://output', 'w' ); + ob_start(); + + array_walk( $rows, array( $this, 'prepare_row' ), $buffer ); + + return apply_filters( "wc_category_showcase_{$this->export_type}_export_rows", ob_get_clean(), $this ); + } + + /** + * Export rows to an array ready for the CSV. + * + * @since 1.0.2 + * + * @param array $row Data to export. + * @param string $key Column being exported. + * @param resource $buffer Output buffer. + */ + protected function prepare_row( $row, $key, $buffer ) { + $columns = $this->get_columns(); + $export_row = array(); + + foreach ( $columns as $column ) { + if ( isset( $row[ $column ] ) ) { + $export_row[] = $this->format_data( $row[ $column ] ); + } else { + $export_row[] = ''; + } + } + + $this->fputcsv( $buffer, $export_row ); + + ++ $this->exported_count; + } + + /** + * Format and escape data ready for the CSV file. + * + * @since 1.0.2 + * + * @param mixed $data Data to format. + * + * @return string + */ + protected function format_data( $data ) { + if ( ! is_scalar( $data ) ) { + if ( is_a( $data, DateTime::class ) ) { + $data = $data->date( 'Y-m-d G:i:s' ); + } else { + $data = ''; // Not supported. + } + } elseif ( is_bool( $data ) ) { + $data = $data ? 1 : 0; + } + + $use_mb = function_exists( 'mb_convert_encoding' ); + + if ( $use_mb ) { + $encoding = mb_detect_encoding( $data, 'UTF-8, ISO-8859-1', true ); + $data = 'UTF-8' === $encoding ? $data : utf8_encode( $data ); + } + + return $this->escape_data( $data ); + } + + /** + * Escape a string to be used in a CSV context + * + * @since 1.0.2 + * + * @param string $data CSV field to escape. + * + * @return string + */ + protected function escape_data( $data ) { + $active_content_triggers = array( '=', '+', '-', '@' ); + + if ( in_array( mb_substr( $data, 0, 1 ), $active_content_triggers, true ) ) { + $data = "'" . $data; + } + + return $data; + } + + /** + * Get column headers in CSV format. + * + * @since 1.0.2 + * @return string + */ + protected function get_column_headers() { + $columns = $this->get_columns(); + $export_row = array(); + $buffer = fopen( 'php://output', 'w' ); + ob_start(); + + foreach ( $columns as $column ) { + $export_row[] = $this->format_data( $column ); + } + + $this->fputcsv( $buffer, $export_row ); + + return ob_get_clean(); + } + + /** + * Write to the CSV file, ensuring escaping works across versions of + * PHP. + * + * PHP 5.5.4 uses '\' as the default escape character. This is not RFC-4180 compliant. + * \0 disables the escape character. + * + * @since 1.0.2 + * + * @param resource $buffer Resource we are writing to. + * @param array $export_row Row to export. + */ + protected function fputcsv( $buffer, $export_row ) { + + if ( version_compare( PHP_VERSION, '5.5.4', '<' ) ) { + ob_start(); + $temp = fopen( 'php://output', 'w' ); // @codingStandardsIgnoreLine + fputcsv( $temp, $export_row, $this->delimiter, '"' ); // @codingStandardsIgnoreLine + fclose( $temp ); // @codingStandardsIgnoreLine + $row = ob_get_clean(); + $row = str_replace( '\\"', '\\""', $row ); + fwrite( $buffer, $row ); // @codingStandardsIgnoreLine + } else { + fputcsv( $buffer, $export_row, $this->delimiter, '"', "\0" ); // @codingStandardsIgnoreLine + } + } + + /** + * Set the export headers. + * + * @since 1.0.2 + * @return void + */ + protected function send_headers() { + ignore_user_abort( true ); + nocache_headers(); + header( 'Content-Type: text/csv; charset=utf-8' ); + header( 'Content-Disposition: attachment; filename=' . $this->get_filename() ); + header( 'Pragma: no-cache' ); + header( 'Expires: 0' ); + } + + /** + * Set the export content. + * + * @since 1.0.2 + * + * @param string $content All CSV content. + */ + protected function send_content( $content ) { + echo wp_kses_post( $content ); + } +} diff --git a/includes/Admin/exportImport/Showcases.php b/includes/Admin/exportImport/Showcases.php new file mode 100644 index 0000000..95b813c --- /dev/null +++ b/includes/Admin/exportImport/Showcases.php @@ -0,0 +1,88 @@ + $post_type, + 'post_status' => 'publish', + 'posts_per_page' => -1, + ); + + $items = get_posts( $args ); + + $rows = array(); + + foreach ( $items as $item ) { + $rows[] = $this->generate_row_data( $item ); + } + + return $rows; + } + + /** + * Take an item and generate row data from it for export. + * + * @param object|array $item Showcase object. + * + * @return array + */ + protected function generate_row_data( $item ) { + $props = array(); + foreach ( $this->get_columns() as $column ) { + $value = null; + switch ( $column ) { + default: + $value = ''; + if ( $item->$column ) { + $value = $item->$column; + } + $value = apply_filters( 'wc_category_showcase_export_column_' . $column, $value, $item ); + } + + $props[ $column ] = $value; + } + + return $props; + } +} diff --git a/includes/Admin/views/admin-page.php b/includes/Admin/views/admin-page.php index 2be2dfd..fbcea66 100644 --- a/includes/Admin/views/admin-page.php +++ b/includes/Admin/views/admin-page.php @@ -20,12 +20,20 @@