attribute_name;
add_action( $taxonomy . '_add_form_fields', array( $this, 'add_product_attribute_term_fields' ) );
add_action( $taxonomy . '_edit_form_fields', array( $this, 'edit_product_attribute_term_fields' ), 10, 1 );
add_filter(
"manage_edit-{$taxonomy}_columns",
function ( $columns ) use ( $taxonomy ) {
return $this->add_term_visual_column( $columns, $taxonomy );
}
);
add_filter(
"manage_{$taxonomy}_custom_column",
function ( $content, $column, $term_id ) use ( $taxonomy ) {
return $this->render_term_visual_column( $content, $column, $term_id, $taxonomy );
},
10,
3
);
}
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_visual_attribute_script' ) );
add_filter( 'woocommerce_json_search_found_product_attribute_terms', array( $this, 'add_visual_data_to_attribute_terms' ), 10, 2 );
}
/**
* Add visual swatch data to attribute term search results.
*
* @internal
*
* @param array|\WP_Error $terms The list of matched terms.
* @param string $taxonomy The terms taxonomy.
* @return array|\WP_Error
*/
public function add_visual_data_to_attribute_terms( $terms, string $taxonomy ) {
if ( is_wp_error( $terms ) || empty( $terms ) || ! VisualAttributeTermMeta::is_visual_attribute_taxonomy( $taxonomy ) ) {
return $terms;
}
// Because `$terms` might be filtered by a plugin, make sure we only operate on valid terms.
$valid_terms = array_filter(
$terms,
static function ( $term ) {
return is_object( $term ) && isset( $term->term_id );
}
);
$term_ids = array_map( 'intval', wp_list_pluck( $valid_terms, 'term_id' ) );
$visuals = VisualAttributeTermMeta::get_term_visuals( $term_ids );
foreach ( $valid_terms as $term ) {
/**
* Term object with dynamic visual property.
*
* @var \stdClass $term
*/
$term->visual = $visuals[ $term->term_id ] ?? VisualAttributeTermMeta::get_empty_visual();
}
return $terms;
}
/**
* Add custom fields for product attribute terms.
*
* @internal
*
* @param string $taxonomy Taxonomy slug.
* @return void
*/
public function add_product_attribute_term_fields( $taxonomy ): void {
if ( ! VisualAttributeTermMeta::is_visual_attribute_taxonomy( $taxonomy ) ) {
return;
}
self::render_div_visual_attribute_fields( 'term-' );
}
/**
* Edit custom fields for product attribute terms.
*
* @internal
*
* @param \WP_Term $term Current term.
* @return void
*/
public function edit_product_attribute_term_fields( $term ): void {
if ( ! VisualAttributeTermMeta::is_visual_attribute_taxonomy( $term->taxonomy ) ) {
return;
}
self::render_table_visual_attribute_fields( $term );
}
/**
* Render visual fields for the add attribute term modal.
*
* @internal
*
* @return void
*/
public static function render_add_attribute_term_modal_fields(): void {
self::render_div_visual_attribute_fields( 'wc-modal-add-attribute-term-' );
}
/**
* Render visual attribute fields for add forms.
*
* @param string $field_id_prefix Field ID prefix.
* @return void
*/
private static function render_div_visual_attribute_fields( string $field_id_prefix ): void {
?>
term_id, 'color', true );
$color_value = is_string( $color_value ) ? $color_value : '';
$image_value = absint( get_term_meta( $term->term_id, 'image', true ) );
$visual_type = $image_value > 0 ? VisualAttributeTermMeta::TYPE_IMAGE : VisualAttributeTermMeta::TYPE_COLOR;
$field_prefix = 'term-';
?>
|
|
|
|
|
|
|
|
|
id ) ) {
return;
}
$is_product_editor_screen = 'product' === $screen->id;
if ( $is_product_editor_screen && array_key_exists( 'wc-visual', wc_get_attribute_types() ) ) {
wp_enqueue_media();
WCAdminAssets::register_script( 'wp-admin-scripts', 'visual-attribute-picker', true, array( 'wp-components' ) );
return;
}
$is_attribute_term_screen = 0 === strpos( $screen->id, 'edit-pa_' );
$taxonomy = $this->get_current_taxonomy();
if ( $is_attribute_term_screen && VisualAttributeTermMeta::is_visual_attribute_taxonomy( $taxonomy ) ) {
wp_enqueue_media();
WCAdminAssets::register_script( 'wp-admin-scripts', 'visual-attribute-picker', true, array( 'wp-components' ) );
}
}
/**
* Save product attribute term fields.
*
* @internal
*
* @param mixed $term_id Term ID being saved.
* @param mixed $tt_id Term taxonomy ID.
* @param string $taxonomy Taxonomy slug.
* @return void
*/
public function save_product_attribute_term_fields( $term_id, $tt_id = '', $taxonomy = '' ): void {
if ( $this->is_ajax_add_attribute_request() ) {
return;
}
VisualAttributeTermMeta::save_term_visual_from_request( (int) $term_id, $taxonomy, $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
}
/**
* Add visual column for product attribute terms.
*
* @internal
*
* @param array $columns Existing columns.
* @param string $taxonomy Taxonomy slug.
* @return array
*/
public function add_term_visual_column( $columns, $taxonomy ): array {
if ( ! VisualAttributeTermMeta::is_visual_attribute_taxonomy( $taxonomy ) ) {
return $columns;
}
$new_columns = array();
foreach ( $columns as $key => $label ) {
if ( 'slug' === $key ) {
$new_columns['visual'] = __( 'Visual', 'woocommerce' );
}
$new_columns[ $key ] = $label;
}
if ( ! isset( $new_columns['visual'] ) ) {
$new_columns['visual'] = __( 'Visual', 'woocommerce' );
}
return $new_columns;
}
/**
* Render visual column for product attribute terms.
*
* @internal
*
* @param mixed $content Column output so far.
* @param string $column Current column key.
* @param int $term_id Term ID.
* @param string $taxonomy Taxonomy slug.
* @return mixed
*/
public function render_term_visual_column( $content, $column, $term_id, $taxonomy ) {
if ( 'visual' !== $column || ! VisualAttributeTermMeta::is_visual_attribute_taxonomy( $taxonomy ) ) {
return $content;
}
$image_id = absint( get_term_meta( $term_id, 'image', true ) );
if ( $image_id && wp_attachment_is_image( $image_id ) ) {
$thumbnail = wp_get_attachment_image( $image_id, array( 32, 32 ) );
return $thumbnail ? $thumbnail : '–';
}
$color_value = sanitize_hex_color( get_term_meta( $term_id, 'color', true ) );
if ( ! $color_value ) {
return '–';
}
$swatch = sprintf(
'',
esc_attr( $color_value )
);
return $swatch . esc_html( strtoupper( $color_value ) );
}
/**
* Check whether the current request is the add attribute AJAX action.
*
* @return bool
*/
private function is_ajax_add_attribute_request(): bool {
$action = isset( $_REQUEST['action'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return wp_doing_ajax() && 'woocommerce_add_new_attribute' === $action;
}
/**
* Get current taxonomy from request.
*
* @return string
*/
private function get_current_taxonomy(): string {
return isset( $_GET['taxonomy'] ) ? sanitize_text_field( wp_unslash( $_GET['taxonomy'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
/**
* Get the default color terms to create for a new wc-visual attribute.
*
* @return array
*/
private static function get_default_color_terms(): array {
return array(
'black' => array(
'label' => __( 'Black', 'woocommerce' ),
'color' => '#121212',
),
'white' => array(
'label' => __( 'White', 'woocommerce' ),
'color' => '#FFFFFF',
),
'gray' => array(
'label' => __( 'Gray', 'woocommerce' ),
'color' => '#6E6E6E',
),
'red' => array(
'label' => __( 'Red', 'woocommerce' ),
'color' => '#D32F2F',
),
'blue' => array(
'label' => __( 'Blue', 'woocommerce' ),
'color' => '#1976D2',
),
'green' => array(
'label' => __( 'Green', 'woocommerce' ),
'color' => '#388E3C',
),
'yellow' => array(
'label' => __( 'Yellow', 'woocommerce' ),
'color' => '#FBE02D',
),
'pink' => array(
'label' => __( 'Pink', 'woocommerce' ),
'color' => '#EC407A',
),
'brown' => array(
'label' => __( 'Brown', 'woocommerce' ),
'color' => '#5D4037',
),
);
}
/**
* Seed default color terms for a newly created wc-visual attribute.
*
* @internal
*
* @param int $attribute_id Attribute ID.
* @return void
*/
public static function seed_visual_attribute_terms( int $attribute_id ): void {
if ( 0 >= $attribute_id ) {
return;
}
$attribute = wc_get_attribute( $attribute_id );
if (
! $attribute ||
! isset( $attribute->slug, $attribute->type ) ||
'wc-visual' !== $attribute->type
) {
return;
}
$taxonomy = $attribute->slug;
// Taxonomy is registered on init from the cached list but not yet available
// at process_add_attribute time (cache invalidated after wc_create_attribute).
// Use the same WC filter seams as WC_Post_Types::register_taxonomies().
if ( ! taxonomy_exists( $taxonomy ) ) {
/**
* Filters the object types for a WooCommerce taxonomy.
*
* @param array $objects Object types.
*
* @since 11.0.0
*/
$objects = apply_filters( "woocommerce_taxonomy_objects_{$taxonomy}", array( 'product' ) );
/**
* Filters the arguments for a WooCommerce taxonomy.
*
* @param array $args Taxonomy arguments.
*
* @since 11.0.0
*/
$args = apply_filters(
"woocommerce_taxonomy_args_{$taxonomy}",
array(
'hierarchical' => false,
'public' => false,
'show_ui' => false,
'show_in_menu' => false,
)
);
register_taxonomy( $taxonomy, $objects, $args );
}
foreach ( self::get_default_color_terms() as $slug => $term ) {
if ( get_term_by( 'slug', $slug, $taxonomy ) ) {
continue;
}
$result = wp_insert_term( $term['label'], $taxonomy, array( 'slug' => $slug ) );
if ( is_wp_error( $result ) || empty( $result['term_id'] ) ) {
continue;
}
VisualAttributeTermMeta::save_term_visual( (int) $result['term_id'], $term['color'], 0 );
}
}
}