422 ) ); } // begin transaction $wpdb->query( 'START TRANSACTION' ); $result_term = wp_insert_term( $data['name'], $taxonomy, array( 'slug' => $data['slug'] ) ); if ( is_wp_error( $result_term ) ) { $wpdb->query( 'ROLLBACK' ); return $result_term; } $result_sync = add_term_meta( $result_term['term_id'], Prodigy::PRODIGY_REMOTE_ATTRIBUTE_ID, $data['id'], true ); if ( is_wp_error( $result_sync ) ) { $wpdb->query( 'ROLLBACK' ); return $result_sync; } $wpdb->query( 'COMMIT' ); return $result_term['term_id']; } /** * @param int $remote_id * @param string $slug * * @return bool|WP_Error */ public function delete( int $remote_id, string $slug ) { $attributes_obj = new Prodigy_Attribute_Taxonomies(); $result_attributes = $attributes_obj->delete_by_remote_id( $remote_id ); if ( empty( $result_attributes ) ) { return new WP_Error( 'delete_attribute_taxonomies_error', 'Error is deleting taxonomies', array( 'status' => 422 ) ); } $result_unregister = unregister_taxonomy( $slug ); if ( is_wp_error( $result_unregister ) ) { return $result_unregister; } return unregister_taxonomy( $slug ); } /** * @param string $attribute_slug * @param array $new_options * * @return array */ public function update_attribute_options( string $attribute_slug, array $new_options ): array { $result = array(); $current_options_data = Prodigy_Taxonomies::get_attribute_options_by_slug( $attribute_slug ); $current_options = $this->get_associated_options( (array) $current_options_data ); $to_remove = $this->array_options_diff( $current_options, $new_options ); $to_add = $this->array_options_diff( $new_options, $current_options ); if ( ! empty( $to_remove ) ) { $result = $this->delete_options( $attribute_slug, $to_remove ); } if ( ! empty( $to_add ) ) { $result = $this->add_collection( $attribute_slug, $to_add ); } return $result; } /** * * @param string $attribute_slug * @param array $to_remove * * @return array */ private function delete_options( string $attribute_slug, array $to_remove ): array { global $wpdb; $data = array(); foreach ( $to_remove as $item ) { $term = Prodigy_Taxonomies::get_taxonomy_by_different_slugs( $attribute_slug, $item['slug'] ); $delete_term_result = wp_delete_term( $term->term_id, $attribute_slug ); if ( is_wp_error( $delete_term_result ) ) { if ( PRODIGY_DEBUG_MODE ) { $message = 'Error deleting attribute option: ' . $delete_term_result->get_error_message(); Prodigy_Logger::add_record( Prodigy_Logger::TYPE_ERROR, $message ); } new WP_Error( $delete_term_result->get_error_message(), array( 'status' => $delete_term_result->get_error_data()['status'] ?? \WP_Http::UNPROCESSABLE_ENTITY ) ); return array(); } if ( $delete_term_result ) { $id = $item['id']; $data[ $item['id'] ]['success'] = true; $data[ $item['id'] ]['option_id'] = (int) $id; } else { $data[ $item['id'] ]['success'] = false; $data[ $item['id'] ]['option_id'] = false; } } return $data; } /** * @param array $current_options * @param array $new_options * * @return array */ private function array_options_diff( array $current_options, array $new_options ): array { $field1 = 'id'; $field2 = 'slug'; $lookup = array(); foreach ( $new_options as $item ) { $key = $item[ $field1 ] . '|' . $item[ $field2 ]; $lookup[ $key ] = true; } return array_filter( $current_options, function ( $item ) use ( $lookup, $field1, $field2 ) { $key = $item[ $field1 ] . '|' . $item[ $field2 ]; return ! isset( $lookup[ $key ] ); } ); } /** * @param array $options_data * * @return array */ private function get_associated_options( array $options_data ): array { $assocArray = array(); foreach ( $options_data as $key => $item ) { $assocArray[ $key ]['id'] = (int) $item->meta_value; $assocArray[ $key ]['slug'] = $item->slug; } return $assocArray; } /** * @param string $taxonomy * @param array $list_attributes * * @return array */ public function add_collection( string $taxonomy, array $list_attributes ): array { $data = array(); foreach ( $list_attributes as $attribute ) { $local_slug = $attribute['slug']; if ( Prodigy_Taxonomies::get_taxonomy_by_different_slugs( $taxonomy, $local_slug ) ) { continue; } $remote_id_info = Prodigy_Product_Attributes::get_term_id_by_meta_key( Prodigy::PRODIGY_REMOTE_ATTRIBUTE_ID, $attribute['id'] ); if ( ! empty( $remote_id_info ) ) { continue; } $result_attributes = $this->add( $attribute, $taxonomy ); if ( is_wp_error( $result_attributes ) ) { $data[ $attribute['id'] ]['success'] = false; $data[ $attribute['id'] ]['option_id'] = false; $data[ $attribute['id'] ]['error'] = $result_attributes->get_error_message(); } else { $data[ $attribute['id'] ]['success'] = true; $data[ $attribute['id'] ]['option_id'] = (int) $result_attributes; } } return $data; } /** * @param int $id * * @return object|null */ public static function get_by_remote_id( int $id ): ?object { global $wpdb; $table_name = $wpdb->prefix . self::TABLE; return $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM {$table_name} WHERE remote_id = %d', $id ) ); } /** * @param string $taxonomy * @param string $slug * * @return array|object|\stdClass|null */ public static function get_attributes_by_different_slugs( string $taxonomy, string $slug ) { global $wpdb; return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->terms} as tr LEFT JOIN {$wpdb->term_taxonomy} as tt ON (tr.term_id = tt.term_id) WHERE tr.slug=%s AND tt.taxonomy=%s ", array( $slug, $taxonomy, ) ) ); } /** * @param array $ids * * @return array|false|null */ public static function get_attributes_by_ids( array $ids ) { global $wpdb; $ids = array_map( 'absint', $ids ); $ids = array_filter( $ids ); if ( empty( $ids ) ) { return array(); } $table_name = $wpdb->prefix . self::TABLE; $placeholders = implode( ', ', array_fill( 0, count( $ids ), '%d' ) ); $results = $wpdb->get_results( $wpdb->prepare( // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $table_name and $placeholders are safe (prefix+constant, format string). 'SELECT * FROM ' . $table_name . ' WHERE id IN (' . $placeholders . ') ORDER BY FIELD(id, ' . $placeholders . ')', array_merge( $ids, $ids ) ) ); return array_column( $results, 'slug', 'id' ); } /** * @return array|false|null */ public static function get_attributes_list() { global $wpdb; $table_name = $wpdb->prefix . self::TABLE; $results = $wpdb->get_results( "SELECT * FROM $table_name", ARRAY_A ); return array_column( $results, 'slug', 'id' ); } }