Changeset 3732012
- Timestamp:
- 10/07/2026 07:15:39 AM (3 weeks ago)
- Location:
- printess-editor
- Files:
-
- 4 edited
- 1 copied
-
tags/1.6.98 (copied) (copied from printess-editor/trunk )
-
tags/1.6.98/printess.php (modified) (12 diffs)
-
tags/1.6.98/readme.txt (modified) (2 diffs)
-
trunk/printess.php (modified) (12 diffs)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
printess-editor/tags/1.6.98/printess.php
r3730705 r3732012 5 5 * Plugin URI: https://printess.com/kb/integrations/woo-commerce/index.html 6 6 * Developer: Bastian Kröger (support@printess.com); Alexander Oser (support@printess.com) 7 * Version: 1.6.9 57 * Version: 1.6.98 8 8 * Author: Printess 9 9 * Author URI: https://printess.com … … 12 12 * Requires at least: 5.9 13 13 * Requires PHP: 8.1 14 * Requires Plugins: woocommerce 14 15 * Tested up to: 7.0 15 16 * License: MIT … … 913 914 914 915 /** 916 * Shortens an api error for the order note and the admin notice. 917 * 918 * A non 2xx error from the Printess api carries the whole production payload, which is far too 919 * much for a notice or an order note. The full text stays in the log. 920 * 921 * @param string $message The exception message. 922 * @param int $limit The maximum number of characters to keep. 923 */ 924 function printess_shorten_failure_message( $message, $limit = 300 ) { 925 $message = trim( preg_replace( '/\s+/', ' ', (string) $message ) ); 926 927 if ( strlen( $message ) <= $limit ) { 928 return $message; 929 } 930 931 return substr( $message, 0, $limit ) . '…'; 932 } 933 934 /** 935 * Records a failed Printess request where support and the merchant can both find it: 936 * the WooCommerce log, and a note on the order itself. 937 * 938 * The Printess api throws on a transport failure and on any non 2xx response. Every request 939 * handler that can reach it has to end up here instead of letting the exception escape, because 940 * an uncaught exception in a hook is a fatal error and the merchant only sees a blank page. 941 * 942 * @param string $context Where the failure happened. 943 * @param string $message What went wrong, in words a merchant can act on. 944 * @param mixed $order The order, or null when it could not be loaded. 945 * @param mixed $item_id The order line item id, or null when it is not known. 946 * @param mixed $save_token The Printess save token, or null when it is not known. 947 */ 948 function printess_log_production_failure( $context, $message, $order = null, $item_id = null, $save_token = null ) { 949 $logger = wc_get_logger(); 950 951 if ( isset( $logger ) ) { 952 $logger->error( 953 'Printess Editor Integration: ' . $context . ': ' . $message 954 . ' (order: ' . ( $order instanceof WC_Order ? $order->get_id() : 'unknown' ) 955 . ', line item: ' . ( ! empty( $item_id ) ? $item_id : 'unknown' ) 956 . ', save token: ' . ( ! empty( $save_token ) ? $save_token : 'unknown' ) . ')', 957 array( 'source' => 'printess-editor' ) 958 ); 959 } 960 961 if ( $order instanceof WC_Order ) { 962 /* translators: %s: the reason the Printess request failed. */ 963 $order->add_order_note( sprintf( __( 'Printess: %s', 'printess-editor' ), printess_shorten_failure_message( $message ) ) ); 964 } 965 } 966 967 /** 968 * Remembers a message for the next admin screen this user opens. 969 * 970 * @param string $message The message to show. 971 */ 972 function printess_set_admin_notice( $message ) { 973 $user_id = get_current_user_id(); 974 975 if ( $user_id > 0 ) { 976 set_transient( 'printess_admin_notice_' . $user_id, $message, MINUTE_IN_SECONDS ); 977 } 978 } 979 980 /** 981 * Prints and clears the message stored by printess_set_admin_notice(). 982 */ 983 function printess_render_admin_notice() { 984 $user_id = get_current_user_id(); 985 986 if ( $user_id <= 0 ) { 987 return; 988 } 989 990 $key = 'printess_admin_notice_' . $user_id; 991 $message = get_transient( $key ); 992 993 if ( false === $message || empty( $message ) ) { 994 return; 995 } 996 997 delete_transient( $key ); 998 999 echo '<div class="notice notice-error is-dismissible"><p>' . esc_html( $message ) . '</p></div>'; 1000 } 1001 1002 /** 1003 * Sends the merchant back to the order they came from. 1004 * 1005 * @param mixed $order_id The order id. 1006 */ 1007 function printess_redirect_to_order( $order_id ) { 1008 $query_string = http_build_query( 1009 array( 1010 'post' => $order_id, 1011 'action' => 'edit', 1012 ) 1013 ); 1014 1015 $redirect = admin_url( 'post.php?' . $query_string ); 1016 wp_safe_redirect( $redirect ); 1017 die; 1018 } 1019 1020 /** 915 1021 * Sends the order line item to the Printess api for production. 916 1022 * … … 921 1027 * @param mixed $dropship_data_dto The dropship data. 922 1028 * @param int $copies The number of copies that should be produced (quantity). 1029 * @throws \Exception In case the line item cannot be produced. 923 1030 */ 924 1031 function printess_produce( $product, $order_id, $line_item_id, $line_item, $save_token, $dropship_data_dto = null, $copies = 1 ) { 1032 if ( ! $product ) { 1033 // get_product() returns false once the catalogue product behind the line has been deleted. 1034 throw new \Exception( esc_html__( 'The product of this order line no longer exists, so it cannot be sent to production.', 'printess-editor' ) ); 1035 } 1036 925 1037 $printess_host = PrintessAdminSettings::get_host(); 926 1038 $site_url = get_site_url(); … … 1056 1168 ); 1057 1169 1170 if ( ! is_array( $response ) || ! isset( $response['jobId'] ) || empty( $response['jobId'] ) ) { 1171 // Storing an empty job id would leave the line looking queued forever, so fail loudly. 1172 throw new \Exception( esc_html__( 'Printess accepted the production request but did not return a job id.', 'printess-editor' ) ); 1173 } 1174 1058 1175 return $response['jobId']; 1059 1176 } … … 1284 1401 } 1285 1402 1286 $order = new WC_Order( $order_id ); 1287 $items = $order->get_items(); 1288 1289 printess_handle_order_items( $order, $items ); 1403 $order = null; 1404 1405 try { 1406 $order = new WC_Order( $order_id ); 1407 $items = $order->get_items(); 1408 1409 printess_handle_order_items( $order, $items ); 1410 } catch ( \Throwable $ex ) { 1411 /* 1412 * This runs while the order changes to processing, so it can sit inside a payment gateway's 1413 * callback. A Printess failure must never break that transition: log it, note it on the 1414 * order, and let the merchant send the line to production by hand from the order screen. 1415 */ 1416 printess_log_production_failure( 'Unable to send an order to production', $ex->getMessage(), $order, null, null ); 1417 } 1290 1418 } 1291 1419 … … 2935 3063 $printess_thumbnail_url = filter_input( INPUT_GET, 'ptu', FILTER_SANITIZE_URL ); 2936 3064 3065 $order = null; 3066 3067 try { 2937 3068 $order = new WC_Order( $order_id ); 2938 3069 $item = $order->get_item( $line_item_id ); 2939 3070 $approval_mode = PrintessAdminSettings::get_approval_mode(); 2940 3071 2941 if ( 'manual' === $approval_mode ) { 2942 $item->delete_meta_data( '_printess-job-id' ); 2943 } else { 2944 $order_items = array( $line_item_id => $item ); 2945 printess_handle_order_items( $order, $order_items ); 2946 } 3072 if ( ! $item ) { 3073 throw new \Exception( esc_html__( 'This order line could not be found.', 'printess-editor' ) ); 3074 } 3075 3076 if ( 'manual' === $approval_mode ) { 3077 $item->delete_meta_data( '_printess-job-id' ); 3078 } else { 3079 $order_items = array( $line_item_id => $item ); 3080 printess_handle_order_items( $order, $order_items ); 3081 } 2947 3082 2948 3083 $item->delete_meta_data( '_printess-result' ); … … 2950 3085 $item->update_meta_data( '_printess-thumbnail-url', $printess_thumbnail_url, true ); 2951 3086 $item->save_meta_data(); 2952 2953 $query_string = http_build_query( 2954 array( 2955 'post' => $order_id, 2956 'action' => 'edit', 2957 ) 2958 ); 2959 2960 $redirect = admin_url( 'post.php?' . $query_string ); 2961 wp_safe_redirect( $redirect ); 2962 die; 3087 } catch ( \Throwable $ex ) { 3088 printess_log_production_failure( 'Unable to save an edited order line item', $ex->getMessage(), $order, $line_item_id, $printess_save_token ); 3089 /* translators: %s: the reason the Printess request failed. */ 3090 printess_set_admin_notice( sprintf( __( 'Printess could not save the edited order line: %s', 'printess-editor' ), printess_shorten_failure_message( $ex->getMessage() ) ) ); 3091 } 3092 3093 printess_redirect_to_order( $order_id ); 2963 3094 } 2964 3095 } … … 2972 3103 2973 3104 if ( isset( $action ) && isset( $nonce ) && (('printess_approve_order_line_item' === $action && wp_verify_nonce( $nonce, 'printess_approve_order_line_item' )) || ('printess_reproduce_order_line_item' === $action && wp_verify_nonce( $nonce, 'printess_reproduce_order_line_item' ))) ) { 2974 $order_id = filter_input( INPUT_GET, 'order_id', FILTER_SANITIZE_NUMBER_INT ); 2975 $line_item_id = filter_input( INPUT_GET, 'item_id', FILTER_SANITIZE_NUMBER_INT ); 2976 $printess_save_token = filter_input( INPUT_GET, 'pst', FILTER_SANITIZE_SPECIAL_CHARS ); 2977 $order = new WC_Order( $order_id ); 2978 $item = $order->get_item( $line_item_id ); 2979 2980 $job_id = $item->get_meta( '_printess-job-id', true ); 2981 2982 if(null !== $job_id && !empty($job_id)) { 2983 $item->delete_meta_data( '_printess-job-id'); 2984 } 2985 2986 $order_items = array( $line_item_id => $item ); 2987 printess_handle_order_items( $order, $order_items ); 2988 2989 $item->delete_meta_data( '_printess-result' ); 2990 $item->save_meta_data(); 2991 2992 $query_string = http_build_query( 2993 array( 2994 'post' => $order_id, 2995 'action' => 'edit', 2996 ) 2997 ); 2998 2999 $redirect = admin_url( 'post.php?' . $query_string ); 3000 wp_safe_redirect( $redirect ); 3001 die; 3105 $order_id = filter_input( INPUT_GET, 'order_id', FILTER_SANITIZE_NUMBER_INT ); 3106 $line_item_id = filter_input( INPUT_GET, 'item_id', FILTER_SANITIZE_NUMBER_INT ); 3107 $printess_save_token = filter_input( INPUT_GET, 'pst', FILTER_SANITIZE_SPECIAL_CHARS ); 3108 $order = null; 3109 3110 try { 3111 $order = new WC_Order( $order_id ); 3112 $item = $order->get_item( $line_item_id ); 3113 3114 if ( ! $item ) { 3115 throw new \Exception( esc_html__( 'This order line could not be found.', 'printess-editor' ) ); 3116 } 3117 3118 $job_id = $item->get_meta( '_printess-job-id', true ); 3119 3120 if ( null !== $job_id && ! empty( $job_id ) ) { 3121 $item->delete_meta_data( '_printess-job-id' ); 3122 } 3123 3124 $order_items = array( $line_item_id => $item ); 3125 printess_handle_order_items( $order, $order_items ); 3126 3127 $item->delete_meta_data( '_printess-result' ); 3128 $item->save_meta_data(); 3129 } catch ( \Throwable $ex ) { 3130 printess_log_production_failure( 'Unable to approve an order line item', $ex->getMessage(), $order, $line_item_id, $printess_save_token ); 3131 /* translators: %s: the reason the Printess request failed. */ 3132 printess_set_admin_notice( sprintf( __( 'Printess could not send this order line to production: %s', 'printess-editor' ), printess_shorten_failure_message( $ex->getMessage() ) ) ); 3133 } 3134 3135 printess_redirect_to_order( $order_id ); 3002 3136 } 3003 3137 } … … 3011 3145 $line_item_id = filter_input( INPUT_GET, 'item_id', FILTER_SANITIZE_NUMBER_INT ); 3012 3146 $printess_save_token = filter_input( INPUT_GET, 'pst', FILTER_SANITIZE_SPECIAL_CHARS ); 3013 $order = new WC_Order( $order_id ); 3014 $item = $order->get_item( $line_item_id ); 3015 $job_id = $item->get_meta( '_printess-job-id', true ); 3016 3017 $printess_host = PrintessAdminSettings::get_host(); 3018 3019 if(null !== $job_id && !empty($job_id)) { 3020 $api_endpoint = '/production/status/get'; 3021 $response = PrintessApi::send_post_request( 3022 $printess_host . $api_endpoint, 3023 PrintessAdminSettings::get_service_token(), 3024 ["jobId" => $job_id] 3025 ); 3026 3027 if(null !== $response && false === $response["isFinalStatus"] && false === $response["isSuccess"] && null === $response["enqueuedOn"]) { 3028 //this production job does not exist anymore... somehow mark it 3029 echo esc_html__( "This production job does not exist anymore.", 'printess-editor' ); 3030 die; 3031 } else { 3032 $response["isFailure"] = false === $response["isSuccess"]; 3033 3034 if(array_key_exists("result", $response) && array_key_exists("ff", $response["result"])) { 3035 $formFieldLink = $response["result"]["ff"]; 3036 3037 if(null != $formFieldLink && !empty($formFieldLink)) { 3038 $formFields = PrintessApi::send_get_request($formFieldLink); 3039 3040 if(null != $formFields && is_array($formFields) && array_key_exists("environment", $formFields)) { 3041 $item->update_meta_data( '_printess-form-fields', wp_json_encode( $formFields["environment"] ), true ); 3042 } 3043 } 3044 } 3045 3046 $item->update_meta_data( '_printess-result', wp_json_encode( $response ), true ); 3047 $item->save_meta_data(); 3048 } 3049 } else { 3050 $order_items = array( $line_item_id => $item ); 3051 3052 //Download production status 3053 $api_endpoint = '/orders/list'; 3054 $response = PrintessApi::send_post_request( 3055 $printess_host . $api_endpoint, 3056 PrintessAdminSettings::get_service_token(), 3057 ["saveToken" => $printess_save_token] 3058 ); 3059 3060 if(0 == $response["count"]) { 3061 echo esc_html__( "No order found for save token", 'printess-editor' ); 3062 die; 3063 } 3064 3065 if(count($response["orders"]) > 0) { 3066 $response = $response["orders"][0]; 3067 3068 if(array_key_exists("result", $response) && array_key_exists("ff", $response["result"])) { 3069 $formFieldLink = $response["result"]["ff"]; 3070 3071 if(null != $formFieldLink && !empty($formFieldLink)) { 3072 $formFields = PrintessApi::send_get_request($formFieldLink); 3073 3074 if(null != $formFields && is_array($formFields) && array_key_exists("environment", $formFields)) { 3075 $item->update_meta_data( '_printess-form-fields', wp_json_encode( $formFields["environment"] ), true ); 3076 } 3077 } 3078 } 3079 3080 $item->update_meta_data( '_printess-result', wp_json_encode( $response ), true ); 3081 $item->save_meta_data(); 3082 } else { 3083 echo esc_html__( "No order found for save token", 'printess-editor' ); 3084 die; 3085 } 3147 $order = null; 3148 3149 try { 3150 $order = new WC_Order( $order_id ); 3151 $item = $order->get_item( $line_item_id ); 3152 3153 if ( ! $item ) { 3154 throw new \Exception( esc_html__( 'This order line could not be found.', 'printess-editor' ) ); 3155 } 3156 3157 $job_id = $item->get_meta( '_printess-job-id', true ); 3158 3159 $printess_host = PrintessAdminSettings::get_host(); 3160 3161 if(null !== $job_id && !empty($job_id)) { 3162 $api_endpoint = '/production/status/get'; 3163 $response = PrintessApi::send_post_request( 3164 $printess_host . $api_endpoint, 3165 PrintessAdminSettings::get_service_token(), 3166 ["jobId" => $job_id] 3167 ); 3168 3169 if ( ! is_array( $response ) ) { 3170 throw new \Exception( esc_html__( 'Printess returned an unexpected production status.', 'printess-editor' ) ); 3171 } 3172 3173 if(false === ($response["isFinalStatus"] ?? null) && false === ($response["isSuccess"] ?? null) && null === ($response["enqueuedOn"] ?? null)) { 3174 //this production job does not exist anymore... somehow mark it 3175 printess_set_admin_notice( __( 'This production job does not exist anymore.', 'printess-editor' ) ); 3176 printess_redirect_to_order( $order_id ); 3177 } else { 3178 $response["isFailure"] = false === ($response["isSuccess"] ?? null); 3179 3180 if(array_key_exists("result", $response) && array_key_exists("ff", $response["result"])) { 3181 $formFieldLink = $response["result"]["ff"]; 3182 3183 if(null != $formFieldLink && !empty($formFieldLink)) { 3184 $formFields = PrintessApi::send_get_request($formFieldLink); 3185 3186 if(null != $formFields && is_array($formFields) && array_key_exists("environment", $formFields)) { 3187 $item->update_meta_data( '_printess-form-fields', wp_json_encode( $formFields["environment"] ), true ); 3188 } 3189 } 3190 } 3191 3192 $item->update_meta_data( '_printess-result', wp_json_encode( $response ), true ); 3193 $item->save_meta_data(); 3194 } 3195 } else { 3196 $order_items = array( $line_item_id => $item ); 3197 3198 //Download production status 3199 $api_endpoint = '/orders/list'; 3200 $response = PrintessApi::send_post_request( 3201 $printess_host . $api_endpoint, 3202 PrintessAdminSettings::get_service_token(), 3203 ["saveToken" => $printess_save_token] 3204 ); 3205 3206 if ( ! is_array( $response ) ) { 3207 throw new \Exception( esc_html__( 'Printess returned an unexpected production status.', 'printess-editor' ) ); 3208 } 3209 3210 if(0 == ($response["count"] ?? 0)) { 3211 printess_set_admin_notice( __( 'No order found for save token', 'printess-editor' ) ); 3212 printess_redirect_to_order( $order_id ); 3213 } 3214 3215 if(is_array($response["orders"] ?? null) && count($response["orders"]) > 0) { 3216 $response = $response["orders"][0]; 3217 3218 if(array_key_exists("result", $response) && array_key_exists("ff", $response["result"])) { 3219 $formFieldLink = $response["result"]["ff"]; 3220 3221 if(null != $formFieldLink && !empty($formFieldLink)) { 3222 $formFields = PrintessApi::send_get_request($formFieldLink); 3223 3224 if(null != $formFields && is_array($formFields) && array_key_exists("environment", $formFields)) { 3225 $item->update_meta_data( '_printess-form-fields', wp_json_encode( $formFields["environment"] ), true ); 3226 } 3227 } 3228 } 3229 3230 $item->update_meta_data( '_printess-result', wp_json_encode( $response ), true ); 3231 $item->save_meta_data(); 3232 } else { 3233 printess_set_admin_notice( __( 'No order found for save token', 'printess-editor' ) ); 3234 printess_redirect_to_order( $order_id ); 3235 } 3236 } 3237 } catch ( \Throwable $ex ) { 3238 printess_log_production_failure( 'Unable to check the production status of an order line item', $ex->getMessage(), $order, $line_item_id, $printess_save_token ); 3239 /* translators: %s: the reason the Printess request failed. */ 3240 printess_set_admin_notice( sprintf( __( 'Printess could not check the production status: %s', 'printess-editor' ), printess_shorten_failure_message( $ex->getMessage() ) ) ); 3086 3241 } 3087 3242 3088 $query_string = http_build_query( 3089 array( 3090 'post' => $order_id, 3091 'action' => 'edit', 3092 ) 3093 ); 3094 3095 $redirect = admin_url( 'post.php?' . $query_string ); 3096 wp_safe_redirect( $redirect ); 3097 die; 3243 printess_redirect_to_order( $order_id ); 3098 3244 } 3099 3245 } … … 3215 3361 } 3216 3362 3217 $template_name = $template_names[ $i ];3218 $is_merge_template = $is_merge_template[ $i ] ;3363 $template_name = $template_names[ $i ] ?? null; 3364 $is_merge_template = $is_merge_template[ $i ] ?? null; 3219 3365 3220 3366 if ( isset( $template_name ) ) { … … 4230 4376 add_filter('woocommerce_add_to_cart_validation', 'printess_validate_cart_item', 10, 2); 4231 4377 4378 add_action( 'admin_notices', 'printess_render_admin_notice' ); 4379 4232 4380 // PRODUCT. 4233 4381 add_action( 'admin_head', 'printess_admin_head' ); -
printess-editor/tags/1.6.98/readme.txt
r3730705 r3732012 5 5 Tested up to: 7.0 6 6 WC Tested up to: 10.5.3 7 Stable tag: 1.6.9 57 Stable tag: 1.6.98 8 8 Requires PHP: 8.1 9 9 License: MIT … … 437 437 - Fixed inconsistent version metadata that stopped WordPress from offering the latest update. 438 438 - Removed the WooCommerce.com marketplace header, which caused misleading "connect your store" notices on the plugins screen. 439 440 = 1.6.96 = 441 - Declared WooCommerce as a required plugin (WordPress 6.5+), so the plugin can only be activated while WooCommerce is active. 442 443 = 1.6.97 = 444 - Fixed a PHP warning ("Trying to access array offset on null") logged when saving a variable product whose variations have no merge template ticked. 445 446 = 1.6.98 = 447 - Fixed a blank page when approving an order line, checking its production status or saving an edited one: a failing Printess request (network error, expired service token, deleted product) threw an uncaught exception. 448 - Added: such failures are now written to the WooCommerce log under "printess-editor", added as an order note, and shown as an error notice on the order screen, instead of breaking the page. 449 - Fixed: a Printess failure while an order moves to processing can no longer break that status change. -
printess-editor/trunk/printess.php
r3730705 r3732012 5 5 * Plugin URI: https://printess.com/kb/integrations/woo-commerce/index.html 6 6 * Developer: Bastian Kröger (support@printess.com); Alexander Oser (support@printess.com) 7 * Version: 1.6.9 57 * Version: 1.6.98 8 8 * Author: Printess 9 9 * Author URI: https://printess.com … … 12 12 * Requires at least: 5.9 13 13 * Requires PHP: 8.1 14 * Requires Plugins: woocommerce 14 15 * Tested up to: 7.0 15 16 * License: MIT … … 913 914 914 915 /** 916 * Shortens an api error for the order note and the admin notice. 917 * 918 * A non 2xx error from the Printess api carries the whole production payload, which is far too 919 * much for a notice or an order note. The full text stays in the log. 920 * 921 * @param string $message The exception message. 922 * @param int $limit The maximum number of characters to keep. 923 */ 924 function printess_shorten_failure_message( $message, $limit = 300 ) { 925 $message = trim( preg_replace( '/\s+/', ' ', (string) $message ) ); 926 927 if ( strlen( $message ) <= $limit ) { 928 return $message; 929 } 930 931 return substr( $message, 0, $limit ) . '…'; 932 } 933 934 /** 935 * Records a failed Printess request where support and the merchant can both find it: 936 * the WooCommerce log, and a note on the order itself. 937 * 938 * The Printess api throws on a transport failure and on any non 2xx response. Every request 939 * handler that can reach it has to end up here instead of letting the exception escape, because 940 * an uncaught exception in a hook is a fatal error and the merchant only sees a blank page. 941 * 942 * @param string $context Where the failure happened. 943 * @param string $message What went wrong, in words a merchant can act on. 944 * @param mixed $order The order, or null when it could not be loaded. 945 * @param mixed $item_id The order line item id, or null when it is not known. 946 * @param mixed $save_token The Printess save token, or null when it is not known. 947 */ 948 function printess_log_production_failure( $context, $message, $order = null, $item_id = null, $save_token = null ) { 949 $logger = wc_get_logger(); 950 951 if ( isset( $logger ) ) { 952 $logger->error( 953 'Printess Editor Integration: ' . $context . ': ' . $message 954 . ' (order: ' . ( $order instanceof WC_Order ? $order->get_id() : 'unknown' ) 955 . ', line item: ' . ( ! empty( $item_id ) ? $item_id : 'unknown' ) 956 . ', save token: ' . ( ! empty( $save_token ) ? $save_token : 'unknown' ) . ')', 957 array( 'source' => 'printess-editor' ) 958 ); 959 } 960 961 if ( $order instanceof WC_Order ) { 962 /* translators: %s: the reason the Printess request failed. */ 963 $order->add_order_note( sprintf( __( 'Printess: %s', 'printess-editor' ), printess_shorten_failure_message( $message ) ) ); 964 } 965 } 966 967 /** 968 * Remembers a message for the next admin screen this user opens. 969 * 970 * @param string $message The message to show. 971 */ 972 function printess_set_admin_notice( $message ) { 973 $user_id = get_current_user_id(); 974 975 if ( $user_id > 0 ) { 976 set_transient( 'printess_admin_notice_' . $user_id, $message, MINUTE_IN_SECONDS ); 977 } 978 } 979 980 /** 981 * Prints and clears the message stored by printess_set_admin_notice(). 982 */ 983 function printess_render_admin_notice() { 984 $user_id = get_current_user_id(); 985 986 if ( $user_id <= 0 ) { 987 return; 988 } 989 990 $key = 'printess_admin_notice_' . $user_id; 991 $message = get_transient( $key ); 992 993 if ( false === $message || empty( $message ) ) { 994 return; 995 } 996 997 delete_transient( $key ); 998 999 echo '<div class="notice notice-error is-dismissible"><p>' . esc_html( $message ) . '</p></div>'; 1000 } 1001 1002 /** 1003 * Sends the merchant back to the order they came from. 1004 * 1005 * @param mixed $order_id The order id. 1006 */ 1007 function printess_redirect_to_order( $order_id ) { 1008 $query_string = http_build_query( 1009 array( 1010 'post' => $order_id, 1011 'action' => 'edit', 1012 ) 1013 ); 1014 1015 $redirect = admin_url( 'post.php?' . $query_string ); 1016 wp_safe_redirect( $redirect ); 1017 die; 1018 } 1019 1020 /** 915 1021 * Sends the order line item to the Printess api for production. 916 1022 * … … 921 1027 * @param mixed $dropship_data_dto The dropship data. 922 1028 * @param int $copies The number of copies that should be produced (quantity). 1029 * @throws \Exception In case the line item cannot be produced. 923 1030 */ 924 1031 function printess_produce( $product, $order_id, $line_item_id, $line_item, $save_token, $dropship_data_dto = null, $copies = 1 ) { 1032 if ( ! $product ) { 1033 // get_product() returns false once the catalogue product behind the line has been deleted. 1034 throw new \Exception( esc_html__( 'The product of this order line no longer exists, so it cannot be sent to production.', 'printess-editor' ) ); 1035 } 1036 925 1037 $printess_host = PrintessAdminSettings::get_host(); 926 1038 $site_url = get_site_url(); … … 1056 1168 ); 1057 1169 1170 if ( ! is_array( $response ) || ! isset( $response['jobId'] ) || empty( $response['jobId'] ) ) { 1171 // Storing an empty job id would leave the line looking queued forever, so fail loudly. 1172 throw new \Exception( esc_html__( 'Printess accepted the production request but did not return a job id.', 'printess-editor' ) ); 1173 } 1174 1058 1175 return $response['jobId']; 1059 1176 } … … 1284 1401 } 1285 1402 1286 $order = new WC_Order( $order_id ); 1287 $items = $order->get_items(); 1288 1289 printess_handle_order_items( $order, $items ); 1403 $order = null; 1404 1405 try { 1406 $order = new WC_Order( $order_id ); 1407 $items = $order->get_items(); 1408 1409 printess_handle_order_items( $order, $items ); 1410 } catch ( \Throwable $ex ) { 1411 /* 1412 * This runs while the order changes to processing, so it can sit inside a payment gateway's 1413 * callback. A Printess failure must never break that transition: log it, note it on the 1414 * order, and let the merchant send the line to production by hand from the order screen. 1415 */ 1416 printess_log_production_failure( 'Unable to send an order to production', $ex->getMessage(), $order, null, null ); 1417 } 1290 1418 } 1291 1419 … … 2935 3063 $printess_thumbnail_url = filter_input( INPUT_GET, 'ptu', FILTER_SANITIZE_URL ); 2936 3064 3065 $order = null; 3066 3067 try { 2937 3068 $order = new WC_Order( $order_id ); 2938 3069 $item = $order->get_item( $line_item_id ); 2939 3070 $approval_mode = PrintessAdminSettings::get_approval_mode(); 2940 3071 2941 if ( 'manual' === $approval_mode ) { 2942 $item->delete_meta_data( '_printess-job-id' ); 2943 } else { 2944 $order_items = array( $line_item_id => $item ); 2945 printess_handle_order_items( $order, $order_items ); 2946 } 3072 if ( ! $item ) { 3073 throw new \Exception( esc_html__( 'This order line could not be found.', 'printess-editor' ) ); 3074 } 3075 3076 if ( 'manual' === $approval_mode ) { 3077 $item->delete_meta_data( '_printess-job-id' ); 3078 } else { 3079 $order_items = array( $line_item_id => $item ); 3080 printess_handle_order_items( $order, $order_items ); 3081 } 2947 3082 2948 3083 $item->delete_meta_data( '_printess-result' ); … … 2950 3085 $item->update_meta_data( '_printess-thumbnail-url', $printess_thumbnail_url, true ); 2951 3086 $item->save_meta_data(); 2952 2953 $query_string = http_build_query( 2954 array( 2955 'post' => $order_id, 2956 'action' => 'edit', 2957 ) 2958 ); 2959 2960 $redirect = admin_url( 'post.php?' . $query_string ); 2961 wp_safe_redirect( $redirect ); 2962 die; 3087 } catch ( \Throwable $ex ) { 3088 printess_log_production_failure( 'Unable to save an edited order line item', $ex->getMessage(), $order, $line_item_id, $printess_save_token ); 3089 /* translators: %s: the reason the Printess request failed. */ 3090 printess_set_admin_notice( sprintf( __( 'Printess could not save the edited order line: %s', 'printess-editor' ), printess_shorten_failure_message( $ex->getMessage() ) ) ); 3091 } 3092 3093 printess_redirect_to_order( $order_id ); 2963 3094 } 2964 3095 } … … 2972 3103 2973 3104 if ( isset( $action ) && isset( $nonce ) && (('printess_approve_order_line_item' === $action && wp_verify_nonce( $nonce, 'printess_approve_order_line_item' )) || ('printess_reproduce_order_line_item' === $action && wp_verify_nonce( $nonce, 'printess_reproduce_order_line_item' ))) ) { 2974 $order_id = filter_input( INPUT_GET, 'order_id', FILTER_SANITIZE_NUMBER_INT ); 2975 $line_item_id = filter_input( INPUT_GET, 'item_id', FILTER_SANITIZE_NUMBER_INT ); 2976 $printess_save_token = filter_input( INPUT_GET, 'pst', FILTER_SANITIZE_SPECIAL_CHARS ); 2977 $order = new WC_Order( $order_id ); 2978 $item = $order->get_item( $line_item_id ); 2979 2980 $job_id = $item->get_meta( '_printess-job-id', true ); 2981 2982 if(null !== $job_id && !empty($job_id)) { 2983 $item->delete_meta_data( '_printess-job-id'); 2984 } 2985 2986 $order_items = array( $line_item_id => $item ); 2987 printess_handle_order_items( $order, $order_items ); 2988 2989 $item->delete_meta_data( '_printess-result' ); 2990 $item->save_meta_data(); 2991 2992 $query_string = http_build_query( 2993 array( 2994 'post' => $order_id, 2995 'action' => 'edit', 2996 ) 2997 ); 2998 2999 $redirect = admin_url( 'post.php?' . $query_string ); 3000 wp_safe_redirect( $redirect ); 3001 die; 3105 $order_id = filter_input( INPUT_GET, 'order_id', FILTER_SANITIZE_NUMBER_INT ); 3106 $line_item_id = filter_input( INPUT_GET, 'item_id', FILTER_SANITIZE_NUMBER_INT ); 3107 $printess_save_token = filter_input( INPUT_GET, 'pst', FILTER_SANITIZE_SPECIAL_CHARS ); 3108 $order = null; 3109 3110 try { 3111 $order = new WC_Order( $order_id ); 3112 $item = $order->get_item( $line_item_id ); 3113 3114 if ( ! $item ) { 3115 throw new \Exception( esc_html__( 'This order line could not be found.', 'printess-editor' ) ); 3116 } 3117 3118 $job_id = $item->get_meta( '_printess-job-id', true ); 3119 3120 if ( null !== $job_id && ! empty( $job_id ) ) { 3121 $item->delete_meta_data( '_printess-job-id' ); 3122 } 3123 3124 $order_items = array( $line_item_id => $item ); 3125 printess_handle_order_items( $order, $order_items ); 3126 3127 $item->delete_meta_data( '_printess-result' ); 3128 $item->save_meta_data(); 3129 } catch ( \Throwable $ex ) { 3130 printess_log_production_failure( 'Unable to approve an order line item', $ex->getMessage(), $order, $line_item_id, $printess_save_token ); 3131 /* translators: %s: the reason the Printess request failed. */ 3132 printess_set_admin_notice( sprintf( __( 'Printess could not send this order line to production: %s', 'printess-editor' ), printess_shorten_failure_message( $ex->getMessage() ) ) ); 3133 } 3134 3135 printess_redirect_to_order( $order_id ); 3002 3136 } 3003 3137 } … … 3011 3145 $line_item_id = filter_input( INPUT_GET, 'item_id', FILTER_SANITIZE_NUMBER_INT ); 3012 3146 $printess_save_token = filter_input( INPUT_GET, 'pst', FILTER_SANITIZE_SPECIAL_CHARS ); 3013 $order = new WC_Order( $order_id ); 3014 $item = $order->get_item( $line_item_id ); 3015 $job_id = $item->get_meta( '_printess-job-id', true ); 3016 3017 $printess_host = PrintessAdminSettings::get_host(); 3018 3019 if(null !== $job_id && !empty($job_id)) { 3020 $api_endpoint = '/production/status/get'; 3021 $response = PrintessApi::send_post_request( 3022 $printess_host . $api_endpoint, 3023 PrintessAdminSettings::get_service_token(), 3024 ["jobId" => $job_id] 3025 ); 3026 3027 if(null !== $response && false === $response["isFinalStatus"] && false === $response["isSuccess"] && null === $response["enqueuedOn"]) { 3028 //this production job does not exist anymore... somehow mark it 3029 echo esc_html__( "This production job does not exist anymore.", 'printess-editor' ); 3030 die; 3031 } else { 3032 $response["isFailure"] = false === $response["isSuccess"]; 3033 3034 if(array_key_exists("result", $response) && array_key_exists("ff", $response["result"])) { 3035 $formFieldLink = $response["result"]["ff"]; 3036 3037 if(null != $formFieldLink && !empty($formFieldLink)) { 3038 $formFields = PrintessApi::send_get_request($formFieldLink); 3039 3040 if(null != $formFields && is_array($formFields) && array_key_exists("environment", $formFields)) { 3041 $item->update_meta_data( '_printess-form-fields', wp_json_encode( $formFields["environment"] ), true ); 3042 } 3043 } 3044 } 3045 3046 $item->update_meta_data( '_printess-result', wp_json_encode( $response ), true ); 3047 $item->save_meta_data(); 3048 } 3049 } else { 3050 $order_items = array( $line_item_id => $item ); 3051 3052 //Download production status 3053 $api_endpoint = '/orders/list'; 3054 $response = PrintessApi::send_post_request( 3055 $printess_host . $api_endpoint, 3056 PrintessAdminSettings::get_service_token(), 3057 ["saveToken" => $printess_save_token] 3058 ); 3059 3060 if(0 == $response["count"]) { 3061 echo esc_html__( "No order found for save token", 'printess-editor' ); 3062 die; 3063 } 3064 3065 if(count($response["orders"]) > 0) { 3066 $response = $response["orders"][0]; 3067 3068 if(array_key_exists("result", $response) && array_key_exists("ff", $response["result"])) { 3069 $formFieldLink = $response["result"]["ff"]; 3070 3071 if(null != $formFieldLink && !empty($formFieldLink)) { 3072 $formFields = PrintessApi::send_get_request($formFieldLink); 3073 3074 if(null != $formFields && is_array($formFields) && array_key_exists("environment", $formFields)) { 3075 $item->update_meta_data( '_printess-form-fields', wp_json_encode( $formFields["environment"] ), true ); 3076 } 3077 } 3078 } 3079 3080 $item->update_meta_data( '_printess-result', wp_json_encode( $response ), true ); 3081 $item->save_meta_data(); 3082 } else { 3083 echo esc_html__( "No order found for save token", 'printess-editor' ); 3084 die; 3085 } 3147 $order = null; 3148 3149 try { 3150 $order = new WC_Order( $order_id ); 3151 $item = $order->get_item( $line_item_id ); 3152 3153 if ( ! $item ) { 3154 throw new \Exception( esc_html__( 'This order line could not be found.', 'printess-editor' ) ); 3155 } 3156 3157 $job_id = $item->get_meta( '_printess-job-id', true ); 3158 3159 $printess_host = PrintessAdminSettings::get_host(); 3160 3161 if(null !== $job_id && !empty($job_id)) { 3162 $api_endpoint = '/production/status/get'; 3163 $response = PrintessApi::send_post_request( 3164 $printess_host . $api_endpoint, 3165 PrintessAdminSettings::get_service_token(), 3166 ["jobId" => $job_id] 3167 ); 3168 3169 if ( ! is_array( $response ) ) { 3170 throw new \Exception( esc_html__( 'Printess returned an unexpected production status.', 'printess-editor' ) ); 3171 } 3172 3173 if(false === ($response["isFinalStatus"] ?? null) && false === ($response["isSuccess"] ?? null) && null === ($response["enqueuedOn"] ?? null)) { 3174 //this production job does not exist anymore... somehow mark it 3175 printess_set_admin_notice( __( 'This production job does not exist anymore.', 'printess-editor' ) ); 3176 printess_redirect_to_order( $order_id ); 3177 } else { 3178 $response["isFailure"] = false === ($response["isSuccess"] ?? null); 3179 3180 if(array_key_exists("result", $response) && array_key_exists("ff", $response["result"])) { 3181 $formFieldLink = $response["result"]["ff"]; 3182 3183 if(null != $formFieldLink && !empty($formFieldLink)) { 3184 $formFields = PrintessApi::send_get_request($formFieldLink); 3185 3186 if(null != $formFields && is_array($formFields) && array_key_exists("environment", $formFields)) { 3187 $item->update_meta_data( '_printess-form-fields', wp_json_encode( $formFields["environment"] ), true ); 3188 } 3189 } 3190 } 3191 3192 $item->update_meta_data( '_printess-result', wp_json_encode( $response ), true ); 3193 $item->save_meta_data(); 3194 } 3195 } else { 3196 $order_items = array( $line_item_id => $item ); 3197 3198 //Download production status 3199 $api_endpoint = '/orders/list'; 3200 $response = PrintessApi::send_post_request( 3201 $printess_host . $api_endpoint, 3202 PrintessAdminSettings::get_service_token(), 3203 ["saveToken" => $printess_save_token] 3204 ); 3205 3206 if ( ! is_array( $response ) ) { 3207 throw new \Exception( esc_html__( 'Printess returned an unexpected production status.', 'printess-editor' ) ); 3208 } 3209 3210 if(0 == ($response["count"] ?? 0)) { 3211 printess_set_admin_notice( __( 'No order found for save token', 'printess-editor' ) ); 3212 printess_redirect_to_order( $order_id ); 3213 } 3214 3215 if(is_array($response["orders"] ?? null) && count($response["orders"]) > 0) { 3216 $response = $response["orders"][0]; 3217 3218 if(array_key_exists("result", $response) && array_key_exists("ff", $response["result"])) { 3219 $formFieldLink = $response["result"]["ff"]; 3220 3221 if(null != $formFieldLink && !empty($formFieldLink)) { 3222 $formFields = PrintessApi::send_get_request($formFieldLink); 3223 3224 if(null != $formFields && is_array($formFields) && array_key_exists("environment", $formFields)) { 3225 $item->update_meta_data( '_printess-form-fields', wp_json_encode( $formFields["environment"] ), true ); 3226 } 3227 } 3228 } 3229 3230 $item->update_meta_data( '_printess-result', wp_json_encode( $response ), true ); 3231 $item->save_meta_data(); 3232 } else { 3233 printess_set_admin_notice( __( 'No order found for save token', 'printess-editor' ) ); 3234 printess_redirect_to_order( $order_id ); 3235 } 3236 } 3237 } catch ( \Throwable $ex ) { 3238 printess_log_production_failure( 'Unable to check the production status of an order line item', $ex->getMessage(), $order, $line_item_id, $printess_save_token ); 3239 /* translators: %s: the reason the Printess request failed. */ 3240 printess_set_admin_notice( sprintf( __( 'Printess could not check the production status: %s', 'printess-editor' ), printess_shorten_failure_message( $ex->getMessage() ) ) ); 3086 3241 } 3087 3242 3088 $query_string = http_build_query( 3089 array( 3090 'post' => $order_id, 3091 'action' => 'edit', 3092 ) 3093 ); 3094 3095 $redirect = admin_url( 'post.php?' . $query_string ); 3096 wp_safe_redirect( $redirect ); 3097 die; 3243 printess_redirect_to_order( $order_id ); 3098 3244 } 3099 3245 } … … 3215 3361 } 3216 3362 3217 $template_name = $template_names[ $i ];3218 $is_merge_template = $is_merge_template[ $i ] ;3363 $template_name = $template_names[ $i ] ?? null; 3364 $is_merge_template = $is_merge_template[ $i ] ?? null; 3219 3365 3220 3366 if ( isset( $template_name ) ) { … … 4230 4376 add_filter('woocommerce_add_to_cart_validation', 'printess_validate_cart_item', 10, 2); 4231 4377 4378 add_action( 'admin_notices', 'printess_render_admin_notice' ); 4379 4232 4380 // PRODUCT. 4233 4381 add_action( 'admin_head', 'printess_admin_head' ); -
printess-editor/trunk/readme.txt
r3730705 r3732012 5 5 Tested up to: 7.0 6 6 WC Tested up to: 10.5.3 7 Stable tag: 1.6.9 57 Stable tag: 1.6.98 8 8 Requires PHP: 8.1 9 9 License: MIT … … 437 437 - Fixed inconsistent version metadata that stopped WordPress from offering the latest update. 438 438 - Removed the WooCommerce.com marketplace header, which caused misleading "connect your store" notices on the plugins screen. 439 440 = 1.6.96 = 441 - Declared WooCommerce as a required plugin (WordPress 6.5+), so the plugin can only be activated while WooCommerce is active. 442 443 = 1.6.97 = 444 - Fixed a PHP warning ("Trying to access array offset on null") logged when saving a variable product whose variations have no merge template ticked. 445 446 = 1.6.98 = 447 - Fixed a blank page when approving an order line, checking its production status or saving an edited one: a failing Printess request (network error, expired service token, deleted product) threw an uncaught exception. 448 - Added: such failures are now written to the WooCommerce log under "printess-editor", added as an order note, and shown as an error notice on the order screen, instead of breaking the page. 449 - Fixed: a Printess failure while an order moves to processing can no longer break that status change.
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)