No Description

abstract-wc-csv-batch-exporter.php 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. /**
  3. * Handles Batch CSV export.
  4. *
  5. * Based on https://pippinsplugins.com/batch-processing-for-big-data/
  6. *
  7. * @package WooCommerce\Export
  8. * @version 3.1.0
  9. */
  10. defined( 'ABSPATH' ) || exit;
  11. /**
  12. * Include dependencies.
  13. */
  14. if ( ! class_exists( 'WC_CSV_Exporter', false ) ) {
  15. require_once WC_ABSPATH . 'includes/export/abstract-wc-csv-exporter.php';
  16. }
  17. /**
  18. * WC_CSV_Exporter Class.
  19. */
  20. abstract class WC_CSV_Batch_Exporter extends WC_CSV_Exporter {
  21. /**
  22. * Page being exported
  23. *
  24. * @var integer
  25. */
  26. protected $page = 1;
  27. /**
  28. * Constructor.
  29. */
  30. public function __construct() {
  31. $this->column_names = $this->get_default_column_names();
  32. }
  33. /**
  34. * Get file path to export to.
  35. *
  36. * @return string
  37. */
  38. protected function get_file_path() {
  39. $upload_dir = wp_upload_dir();
  40. return trailingslashit( $upload_dir['basedir'] ) . $this->get_filename();
  41. }
  42. /**
  43. * Get CSV headers row file path to export to.
  44. *
  45. * @return string
  46. */
  47. protected function get_headers_row_file_path() {
  48. return $this->get_file_path() . '.headers';
  49. }
  50. /**
  51. * Get the contents of the CSV headers row file. Defaults to the original known headers.
  52. *
  53. * @since 3.1.0
  54. * @return string
  55. */
  56. public function get_headers_row_file() {
  57. $file = chr( 239 ) . chr( 187 ) . chr( 191 ) . $this->export_column_headers();
  58. if ( @file_exists( $this->get_headers_row_file_path() ) ) { // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
  59. $file = @file_get_contents( $this->get_headers_row_file_path() ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPress.WP.AlternativeFunctions.file_system_read_file_get_contents
  60. }
  61. return $file;
  62. }
  63. /**
  64. * Get the file contents.
  65. *
  66. * @since 3.1.0
  67. * @return string
  68. */
  69. public function get_file() {
  70. $file = '';
  71. if ( @file_exists( $this->get_file_path() ) ) { // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
  72. $file = @file_get_contents( $this->get_file_path() ); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPress.WP.AlternativeFunctions.file_system_read_file_get_contents
  73. } else {
  74. @file_put_contents( $this->get_file_path(), '' ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_file_put_contents, Generic.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
  75. @chmod( $this->get_file_path(), 0664 ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.chmod_chmod, WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents, Generic.PHP.NoSilencedErrors.Discouraged
  76. }
  77. return $file;
  78. }
  79. /**
  80. * Serve the file and remove once sent to the client.
  81. *
  82. * @since 3.1.0
  83. */
  84. public function export() {
  85. $this->send_headers();
  86. $this->send_content( $this->get_headers_row_file() . $this->get_file() );
  87. @unlink( $this->get_file_path() ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink, Generic.PHP.NoSilencedErrors.Discouraged
  88. @unlink( $this->get_headers_row_file_path() ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink, Generic.PHP.NoSilencedErrors.Discouraged
  89. die();
  90. }
  91. /**
  92. * Generate the CSV file.
  93. *
  94. * @since 3.1.0
  95. */
  96. public function generate_file() {
  97. if ( 1 === $this->get_page() ) {
  98. @unlink( $this->get_file_path() ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink, Generic.PHP.NoSilencedErrors.Discouraged,
  99. // We need to initialize the file here.
  100. $this->get_file();
  101. }
  102. $this->prepare_data_to_export();
  103. $this->write_csv_data( $this->get_csv_data() );
  104. }
  105. /**
  106. * Write data to the file.
  107. *
  108. * @since 3.1.0
  109. * @param string $data Data.
  110. */
  111. protected function write_csv_data( $data ) {
  112. if ( ! file_exists( $this->get_file_path() ) || ! is_writeable( $this->get_file_path() ) ) {
  113. return false;
  114. }
  115. $fp = fopen( $this->get_file_path(), 'a+' );
  116. if ( $fp ) {
  117. fwrite( $fp, $data );
  118. fclose( $fp );
  119. }
  120. // Add all columns when finished.
  121. if ( 100 === $this->get_percent_complete() ) {
  122. $header = chr( 239 ) . chr( 187 ) . chr( 191 ) . $this->export_column_headers();
  123. // We need to use a temporary file to store headers, this will make our life so much easier.
  124. @file_put_contents( $this->get_headers_row_file_path(), $header ); //phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_file_put_contents, Generic.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.file_system_read_file_put_contents
  125. }
  126. }
  127. /**
  128. * Get page.
  129. *
  130. * @since 3.1.0
  131. * @return int
  132. */
  133. public function get_page() {
  134. return $this->page;
  135. }
  136. /**
  137. * Set page.
  138. *
  139. * @since 3.1.0
  140. * @param int $page Page Nr.
  141. */
  142. public function set_page( $page ) {
  143. $this->page = absint( $page );
  144. }
  145. /**
  146. * Get count of records exported.
  147. *
  148. * @since 3.1.0
  149. * @return int
  150. */
  151. public function get_total_exported() {
  152. return ( ( $this->get_page() - 1 ) * $this->get_limit() ) + $this->exported_row_count;
  153. }
  154. /**
  155. * Get total % complete.
  156. *
  157. * @since 3.1.0
  158. * @return int
  159. */
  160. public function get_percent_complete() {
  161. return $this->total_rows ? floor( ( $this->get_total_exported() / $this->total_rows ) * 100 ) : 100;
  162. }
  163. }