ID ); if ( ! $variation instanceof WC_Product_Variation ) { return; } $loop = absint( $loop ); echo '
'; if ( $auto ) { printf( ' %2$s', esc_attr( $auto ), /* translators: %s: a hex color, like #dc4a24. */ esc_html( sprintf( __( 'Color from the photo: %s', 'purplish' ), $auto ) ) ); } else { echo esc_html( $args['empty_auto'] ); } echo '
'; } /** * Sets the field values on the variation before WooCommerce saves it. * WooCommerce checked the nonce and the edit_products capability before * this action, and calls save() after it. * * @param WC_Product_Variation $variation Variation being saved. * @param int $loop Index of the variation in the form. * @return void */ public function save( $variation, $loop ) { // phpcs:disable WordPress.Security.NonceVerification.Missing -- WooCommerce verified the save-variations nonce. $loop = absint( $loop ); if ( ! isset( $_POST['purplish_mode'][ $loop ] ) ) { return; } $mode = sanitize_key( wp_unslash( $_POST['purplish_mode'][ $loop ] ) ); $custom = isset( $_POST['purplish_custom_color'][ $loop ] ) ? sanitize_text_field( wp_unslash( $_POST['purplish_custom_color'][ $loop ] ) ) : ''; // phpcs:enable WordPress.Security.NonceVerification.Missing // apply() checks the color: empty removes it, anything not hex is ignored. self::apply( $variation, $mode, $custom ); } /** * Sets the field values on a simple product before WooCommerce saves * it. WooCommerce checked the nonce and the edit_product capability * before this action, and calls save() after it. * * @param \WC_Product $product Product being saved. * @return void */ public function save_product( $product ) { // phpcs:disable WordPress.Security.NonceVerification.Missing -- WooCommerce verified the product edit nonce. if ( ! $product->is_type( 'simple' ) || ! isset( $_POST['purplish_product_mode'] ) ) { return; } $mode = sanitize_key( wp_unslash( $_POST['purplish_product_mode'] ) ); $custom = isset( $_POST['purplish_product_custom_color'] ) ? sanitize_text_field( wp_unslash( $_POST['purplish_product_custom_color'] ) ) : ''; // phpcs:enable WordPress.Security.NonceVerification.Missing self::apply( $product, $mode, $custom ); } /** * Sets a mode and custom color on a variation or simple product, * without saving it. * * @param \WC_Product $variation Variation or simple product. * @param string $mode `auto`, `custom` or `off`. Anything else counts as `auto`. * @param string $custom Hex color. Empty removes the saved one; anything else that isn't a hex color is ignored. * @return void */ public static function apply( $variation, $mode, $custom ) { if ( ! in_array( $mode, Meta::modes(), true ) || Meta::MODE_AUTO === $mode ) { $variation->delete_meta_data( Meta::MODE ); } else { $variation->update_meta_data( Meta::MODE, $mode ); } if ( Meta::MODE_CUSTOM !== $mode ) { return; } if ( '' === trim( $custom ) ) { // Cleared in the picker: fall back to the term or photo color. $variation->delete_meta_data( Meta::CUSTOM_COLOR ); return; } $custom = sanitize_hex_color( $custom ); if ( $custom ) { $variation->update_meta_data( Meta::CUSTOM_COLOR, $custom ); } } /** * Loads WordPress's Iris color picker and the field's script and styles * on the product editor. * * @return void */ public function enqueue_assets() { $screen = get_current_screen(); if ( ! $screen || 'product' !== $screen->id ) { return; } $asset = include PURPLISH_DIR . 'build/admin.asset.php'; wp_enqueue_script( 'purplish-admin', PURPLISH_URL . 'build/admin.js', array_merge( $asset['dependencies'], array( 'jquery', 'iris' ) ), $asset['version'], true ); // Same field as WooCommerce's own color settings: a hex text field with // a swatch, at the height WooCommerce gives selects in this panel. wp_add_inline_style( 'woocommerce_admin_styles', '.purplish-variation-color { clear: both; }' . '.purplish-variation-color:not(:has(.purplish-mode option[value="custom"]:checked)) .purplish-custom-color { display: none; }' . '.purplish-color-field { position: relative; display: block; }' // The ID matches WooCommerce's own #variable_product_options input rule, so this padding wins. . '#variable_product_options .purplish-color-field input.purplish-color-input { width: 100%; padding-left: 48px; font-family: Consolas, Monaco, monospace; text-transform: lowercase; }' . '.wc-wp-version-gte-70 #variable_product_options .purplish-color-field .purplish-color-input { height: 50px; }' // The General tab floats its fields at half width; the field's wrapper follows. . '#woocommerce-product-data .purplish-product-color .purplish-color-field { float: left; width: 50%; }' . '.wc-wp-version-gte-70 #woocommerce-product-data .purplish-product-color .purplish-color-field { width: 55%; }' . '#woocommerce-product-data .purplish-product-color .purplish-color-field input.purplish-color-input { float: none; width: 100%; box-sizing: border-box; padding-left: 48px; font-family: Consolas, Monaco, monospace; }' . '.purplish-color-swatch { position: absolute; z-index: 1; left: 10px; top: calc(50% + 1px); width: 28px; height: 28px; transform: translateY(-50%); border-radius: 2px; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2); cursor: pointer; }' . '.purplish-color-swatch.is-empty { background: linear-gradient(to top right, #fff calc(50% - 1px), #cc1818 50%, #fff calc(50% + 1px)); }' . '.purplish-color-field .iris-picker { position: absolute; z-index: 100; top: 100%; left: 0; margin-top: 4px; box-shadow: 0 3px 12px rgba(0, 0, 0, 0.15); }' . '.purplish-swatch { display: inline-block; width: 1.25em; height: 1.25em; border-radius: 50%; vertical-align: middle; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15); }' ); } }