class-import-manager.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. <?php
  2. // Admin UI + handlers for importing the InPrint and Delivered protocol CSVs.
  3. defined('ABSPATH') || exit;
  4. class Import_Manager {
  5. public function __construct() {
  6. add_action('admin_menu', array($this, 'add_import_submenu'));
  7. add_action('admin_post_import_inprint_protocol', array($this, 'handle_import_inprint_protocol'));
  8. add_action('admin_post_import_delivered_protocol', array($this, 'handle_import_delivered_protocol'));
  9. }
  10. public function add_import_submenu() {
  11. add_submenu_page(
  12. 'woocommerce',
  13. __('Import Protocols', 'studiou-wc-ord-print-statuses'),
  14. __('Import Protocols', 'studiou-wc-ord-print-statuses'),
  15. 'manage_woocommerce',
  16. 'studiou-import-protocols',
  17. array($this, 'render_import_page')
  18. );
  19. }
  20. public function render_import_page() {
  21. ?>
  22. <div class="wrap">
  23. <h1><?php echo esc_html(get_admin_page_title()); ?></h1>
  24. <h2><?php esc_html_e('Import InPrint Protocol', 'studiou-wc-ord-print-statuses'); ?></h2>
  25. <p>
  26. <?php
  27. printf(
  28. /* translators: list of required CSV header names. */
  29. esc_html__('Required CSV headers: %s', 'studiou-wc-ord-print-statuses'),
  30. '<code>order_no</code>, <code>externalorder</code>, <code>externalorderdate</code>'
  31. );
  32. ?>
  33. </p>
  34. <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" enctype="multipart/form-data">
  35. <input type="hidden" name="action" value="import_inprint_protocol">
  36. <?php wp_nonce_field('import_inprint_protocol', 'import_inprint_protocol_nonce'); ?>
  37. <input type="file" name="inprint_csv" accept=".csv,text/csv" required>
  38. <?php submit_button(__('Import InPrint Protocol', 'studiou-wc-ord-print-statuses')); ?>
  39. </form>
  40. <h2><?php esc_html_e('Import Delivered Protocol', 'studiou-wc-ord-print-statuses'); ?></h2>
  41. <p>
  42. <?php
  43. printf(
  44. /* translators: list of required CSV header names. */
  45. esc_html__('Required CSV headers: %s', 'studiou-wc-ord-print-statuses'),
  46. '<code>order_no</code>'
  47. );
  48. ?>
  49. </p>
  50. <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" enctype="multipart/form-data">
  51. <input type="hidden" name="action" value="import_delivered_protocol">
  52. <?php wp_nonce_field('import_delivered_protocol', 'import_delivered_protocol_nonce'); ?>
  53. <input type="file" name="delivered_csv" accept=".csv,text/csv" required>
  54. <?php submit_button(__('Import Delivered Protocol', 'studiou-wc-ord-print-statuses')); ?>
  55. </form>
  56. </div>
  57. <?php
  58. }
  59. public function handle_import_inprint_protocol() {
  60. $this->run_import('inprint_csv', 'import_inprint_protocol', 'import_inprint_protocol_nonce', 'import_inprint_protocol');
  61. }
  62. public function handle_import_delivered_protocol() {
  63. $this->run_import('delivered_csv', 'import_delivered_protocol', 'import_delivered_protocol_nonce', 'import_delivered_protocol');
  64. }
  65. /**
  66. * Common pipeline: capability check → nonce → file validation → parse → dispatch → redirect.
  67. *
  68. * @param string $file_field
  69. * @param string $action Protocol id (inprint|delivered) used to pick the DB handler.
  70. * @param string $nonce_field
  71. * @param string $nonce_action
  72. */
  73. private function run_import($file_field, $action, $nonce_field, $nonce_action) {
  74. if (!current_user_can('manage_woocommerce')) {
  75. wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'studiou-wc-ord-print-statuses'));
  76. }
  77. check_admin_referer($nonce_action, $nonce_field);
  78. $file = $this->validated_upload($file_field);
  79. if ($file === null) {
  80. $this->redirect_back();
  81. }
  82. $csv_data = Studiou_DB_Manager::parse_csv($file['tmp_name']);
  83. if (empty($csv_data)) {
  84. UtilsLog::message(
  85. __('CSV file could not be parsed or contained no data rows.', 'studiou-wc-ord-print-statuses'),
  86. 'error'
  87. );
  88. $this->redirect_back();
  89. }
  90. if ($action === 'import_inprint_protocol') {
  91. $result = Studiou_DB_Manager::import_inprint_protocol($csv_data);
  92. } else {
  93. $result = Studiou_DB_Manager::import_delivered_protocol($csv_data);
  94. }
  95. $this->emit_import_summary($result);
  96. $this->redirect_back();
  97. }
  98. /**
  99. * Validate the file upload superglobal entry. Emits a notice and returns null on failure.
  100. *
  101. * @return array|null
  102. */
  103. private function validated_upload($field) {
  104. if (!isset($_FILES[$field]) || !is_array($_FILES[$field])) {
  105. UtilsLog::message(__('No file uploaded.', 'studiou-wc-ord-print-statuses'), 'error');
  106. return null;
  107. }
  108. $file = $_FILES[$field];
  109. if (isset($file['error']) && $file['error'] !== UPLOAD_ERR_OK) {
  110. UtilsLog::message(
  111. sprintf(
  112. /* translators: %d is the PHP upload error code. */
  113. __('File upload failed (error code %d).', 'studiou-wc-ord-print-statuses'),
  114. (int) $file['error']
  115. ),
  116. 'error'
  117. );
  118. return null;
  119. }
  120. if (empty($file['tmp_name']) || !is_uploaded_file($file['tmp_name'])) {
  121. UtilsLog::message(__('Uploaded file is not accessible.', 'studiou-wc-ord-print-statuses'), 'error');
  122. return null;
  123. }
  124. return $file;
  125. }
  126. private function emit_import_summary($result) {
  127. $updated = isset($result['updated_count']) ? (int) $result['updated_count'] : 0;
  128. $errors = isset($result['errors']) && is_array($result['errors']) ? $result['errors'] : array();
  129. UtilsLog::message(
  130. sprintf(
  131. _n(
  132. '%d order updated successfully.',
  133. '%d orders updated successfully.',
  134. $updated,
  135. 'studiou-wc-ord-print-statuses'
  136. ),
  137. $updated
  138. ),
  139. $updated > 0 ? 'success' : 'info'
  140. );
  141. if (!empty($errors)) {
  142. UtilsLog::message(
  143. sprintf(
  144. /* translators: 1: error count, 2: comma-separated error messages. */
  145. __('%1$d errors occurred: %2$s', 'studiou-wc-ord-print-statuses'),
  146. count($errors),
  147. esc_html(implode(', ', $errors))
  148. ),
  149. 'error'
  150. );
  151. }
  152. }
  153. private function redirect_back() {
  154. wp_safe_redirect(admin_url('admin.php?page=studiou-import-protocols'));
  155. exit;
  156. }
  157. }