| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- <?php
- // Manages custom order fields rendered in the "Print Information" panel.
- defined('ABSPATH') || exit;
- class Order_Fields_Manager {
- /**
- * Meta key → translatable label for fields rendered as `datetime-local`.
- * The render and save loops both walk this map.
- */
- private static function datetime_fields() {
- return array(
- 'to_print_date' => __('Prepare To Print Date', 'studiou-wc-ord-print-statuses'),
- 'in_print_date' => __('In Print Date', 'studiou-wc-ord-print-statuses'),
- 'external_ref_ord_date' => __('External Order Date', 'studiou-wc-ord-print-statuses'),
- 'external_ref_ord_delivered' => __('External Order Delivered', 'studiou-wc-ord-print-statuses'),
- );
- }
- /**
- * Meta key → translatable label for plain text fields.
- */
- private static function text_fields() {
- return array(
- 'external_ref_ord_no' => __('External Order Number', 'studiou-wc-ord-print-statuses'),
- );
- }
- public function __construct() {
- add_action('woocommerce_admin_order_data_after_order_details', array($this, 'display_custom_order_fields'));
- add_action('woocommerce_process_shop_order_meta', array($this, 'save_custom_order_fields'));
- }
- public function display_custom_order_fields($order) {
- ?>
- <div class="order_data_column">
- <h4><?php esc_html_e('Print Information', 'studiou-wc-ord-print-statuses'); ?></h4>
- <?php
- foreach (self::datetime_fields() as $key => $label) {
- woocommerce_wp_text_input(array(
- 'id' => $key,
- 'label' => $label,
- 'type' => 'datetime-local',
- 'value' => $this->mysql_to_datetime_local($order->get_meta($key)),
- 'wrapper_class' => 'form-field-wide',
- ));
- }
- foreach (self::text_fields() as $key => $label) {
- woocommerce_wp_text_input(array(
- 'id' => $key,
- 'label' => $label,
- 'value' => $order->get_meta($key),
- 'wrapper_class' => 'form-field-wide',
- ));
- }
- ?>
- </div>
- <?php
- }
- public function save_custom_order_fields($order_id) {
- if (!current_user_can('edit_shop_order', $order_id) && !current_user_can('edit_shop_orders')) {
- return;
- }
- $order = wc_get_order($order_id);
- if (!$order) {
- return;
- }
- foreach (array_keys(self::datetime_fields()) as $field) {
- if (isset($_POST[$field])) {
- $order->update_meta_data($field, $this->datetime_local_to_mysql($_POST[$field]));
- }
- }
- foreach (array_keys(self::text_fields()) as $field) {
- if (isset($_POST[$field])) {
- $order->update_meta_data($field, sanitize_text_field(wp_unslash($_POST[$field])));
- }
- }
- $order->save();
- }
- /**
- * Convert a MySQL datetime string (as written by current_time('mysql')) to
- * the HTML5 `datetime-local` format. Done as pure string reformatting so
- * the value's timezone is preserved — current_time('mysql') already uses
- * WP local time, and the browser interprets datetime-local as local time.
- * Using strtotime()/date() here would re-interpret the value in the server
- * timezone and drift on UTC-server / non-UTC-site configurations.
- */
- private function mysql_to_datetime_local($value) {
- $value = trim((string) $value);
- if ($value === '') {
- return '';
- }
- // Accepts 'YYYY-MM-DD HH:MM[:SS]' or 'YYYY-MM-DDTHH:MM[:SS]'.
- if (preg_match('/^(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2})/', $value, $m)) {
- return $m[1] . 'T' . $m[2];
- }
- return '';
- }
- /**
- * Convert an HTML5 datetime-local form value to a MySQL datetime string.
- * No timezone conversion — the form value and the stored value are both
- * treated as WP local time (matching current_time('mysql')).
- */
- private function datetime_local_to_mysql($value) {
- $value = sanitize_text_field(wp_unslash($value));
- if ($value === '') {
- return '';
- }
- if (preg_match('/^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2})(?::(\d{2}))?$/', $value, $m)) {
- $seconds = isset($m[3]) ? $m[3] : '00';
- return $m[1] . ' ' . $m[2] . ':' . $seconds;
- }
- return '';
- }
- }
|