如何解决如何将 WC_Data_Store 转换为 WC_Product_Variable_Data_Store_CPT 或具有 $prices_array 属性的东西?
我必须执行以下反射代码,因为我可用的 WooCommerce 版本有一个错误 (v4.9.2)。
请查看下面代码中的注释:
// checked before the existence of the class with class_exists
$rp = new ReflectionProperty('WC_Product_Variable_Data_Store_CPT','prices_array');
$rp->setAccessible(true);
var_dump('start'); // echoes something to the html code
$protected_prices_array = $rp->getValue($ths); // crashes the PHP script instance
var_dump('stop'); // this is not printed anymore
如果需要,我可以提供更多代码。
目前我正在尝试继承给定的类,看看我是否可以解决这个错误。
在临时站点上,我有 PHP 7.4.16。
更新 1
我在自己的 function my_read_price_data( $ths,&$product,$for_display = false ) { ...
中有此代码,它与 WC 数据存储的 read_price_data 公共方法相同,该方法访问受保护的价格数组属性。
更新 2
/**
* Modified function from WC.
*
* @param WC_Product_Variable_Data_Store_CPT $ths
* @param WC_Product_Variable $product
* @param boolean $for_display
* @return void
*/
function my_read_price_data( $ths,$for_display = false ) {
/**
* Transient name for storing prices for this product (note: Max transient length is 45)
*
* @since 2.5.0 a single transient is used per product for all prices,rather than many transients per product.
*/
$transient_name = 'wc_var_prices_' . $product->get_id();
$transient_version = WC_Cache_Helper::get_transient_version( 'product' );
$price_hash = my_get_price_hash($ths,$product,$for_display); // with this it does not crash (*)
// NOTE: maybe inherit from WC_Product_Variable_Data_Store_CPT to not use reflection.
$rp = new ReflectionProperty('WC_Product_Variable_Data_Store_CPT','prices_array'); // the class exists
$rp->setAccessible(true);
var_dump('start');
$protected_prices_array = $rp->getValue($ths); // (*) until this
var_dump('stop');
// Check if prices array is stale.
if ( ! isset( $protected_prices_array['version'] ) || $protected_prices_array['version'] !== $transient_version ) {
$rp->setValue($ths,array(
'version' => $transient_version,));
}
$protected_prices_array = $rp->getValue($ths);
/**
* $this->prices_array is an array of values which may have been modified from what is stored in transients - this may not match $transient_cached_prices_array.
* If the value has already been generated,we don't need to grab the values again so just return them. They are already filtered.
*/
if ( empty( $protected_prices_array[ $price_hash ] ) ) {
$transient_cached_prices_array = array_filter( (array) json_decode( strval( get_transient( $transient_name ) ),true ) );
// If the product version has changed since the transient was last saved,reset the transient cache.
if ( ! isset( $transient_cached_prices_array['version'] ) || $transient_version !== $transient_cached_prices_array['version'] ) {
$transient_cached_prices_array = array(
'version' => $transient_version,);
}
// If the prices are not stored for this hash,generate them and add to the transient.
if ( empty( $transient_cached_prices_array[ $price_hash ] ) ) {
$prices_array = array(
'price' => array(),'regular_price' => array(),'sale_price' => array(),);
$variation_ids = $product->get_visible_children();
if ( is_callable( '_prime_post_caches' ) ) {
_prime_post_caches( $variation_ids );
}
foreach ( $variation_ids as $variation_id ) {
$variation = wc_get_product( $variation_id );
if ( $variation ) {
$price = apply_filters( 'woocommerce_variation_prices_price',$variation->get_price( 'edit' ),$variation,$product );
$regular_price = apply_filters( 'woocommerce_variation_prices_regular_price',$variation->get_regular_price( 'edit' ),$product );
$sale_price = apply_filters( 'woocommerce_variation_prices_sale_price',$variation->get_sale_price( 'edit' ),$product );
// Skip empty prices.
if ( '' === $price ) {
continue;
}
// If sale price does not equal price,the product is not yet on sale.
if ( $sale_price === $regular_price || $sale_price !== $price ) {
$sale_price = $regular_price;
}
// If we are getting prices for display,we need to account for taxes.
if ( $for_display ) {
if ( 'incl' === get_option( 'woocommerce_tax_display_shop' ) ) {
$price = '' === $price ? '' : wc_get_price_including_tax(
$variation,array(
'qty' => 1,'price' => $price,)
);
$regular_price = '' === $regular_price ? '' : wc_get_price_including_tax(
$variation,'price' => $regular_price,)
);
$sale_price = '' === $sale_price ? '' : wc_get_price_including_tax(
$variation,'price' => $sale_price,)
);
} else {
$price = '' === $price ? '' : wc_get_price_excluding_tax(
$variation,)
);
$regular_price = '' === $regular_price ? '' : wc_get_price_excluding_tax(
$variation,)
);
$sale_price = '' === $sale_price ? '' : wc_get_price_excluding_tax(
$variation,)
);
}
}
$prices_array['price'][ $variation_id ] = wc_format_decimal( $price,wc_get_price_decimals() );
$prices_array['regular_price'][ $variation_id ] = wc_format_decimal( $regular_price,wc_get_price_decimals() );
$prices_array['sale_price'][ $variation_id ] = wc_format_decimal( $sale_price,wc_get_price_decimals() );
$prices_array = apply_filters( 'woocommerce_variation_prices_array',$prices_array,$for_display );
}
}
// Add all pricing data to the transient array.
foreach ( $prices_array as $key => $values ) {
$transient_cached_prices_array[ $price_hash ][ $key ] = $values;
}
set_transient( $transient_name,wp_json_encode( $transient_cached_prices_array ),DAY_IN_SECONDS * 30 );
}
/**
* Give plugins one last chance to filter the variation prices array which has been generated and store locally to the class.
* This value may differ from the transient cache. It is filtered once before storing locally.
*/
$protected_prices_array = $rp->getValue($ths);
$protected_prices_array[$price_hash] = apply_filters( 'woocommerce_variation_prices',$transient_cached_prices_array[ $price_hash ],$for_display );
$rp->setValue($ths,$protected_prices_array);
}
return $rp->getValue($ths)[ $price_hash ];
}
更新 3
上面的函数 my_read_price_data 被调用:
/**
* Function modified from WC.
*
* @param WC_Product_Variable $p
* @param boolean $for_display
* @return void
*/
function my_get_variation_prices( $p,$for_display = false ) {
$ds = $p->get_data_store(); // $p->data_store;
$prices = my_read_price_data($ds,$p,$for_display);
foreach ( $prices as $price_key => $variation_prices ) {
$prices[ $price_key ] = asort( $variation_prices );
}
return $prices;
}
这是由以下函数调用的,该函数是 WC 函数的修改版本,但这次修改是为了将输出更改为客户端想要的内容:
function my_get_price_html( $price = '' ) {
global $product;
$prices = my_get_variation_prices($product,true);
if ( empty( $prices['price'] ) ) {
$price = apply_filters( 'woocommerce_variable_empty_price_html','',$product );
} else {
$min_price = current( $prices['price'] );
$max_price = end( $prices['price'] );
$min_reg_price = current( $prices['regular_price'] );
$max_reg_price = end( $prices['regular_price'] );
if ( $min_price !== $max_price ) {
$price = wc_format_price_range( $min_price,$max_price );
} elseif ( $product->is_on_sale() && $min_reg_price === $max_reg_price ) {
$price = my_wc_format_sale_price( $prices['regular_price'],$prices['price'] );
} else {
$price = wc_price( $min_price );
}
$price = apply_filters( 'woocommerce_variable_price_html',$price . $product->get_price_suffix(),$product );
}
return apply_filters( 'woocommerce_get_price_html',$price,$product );
}
正如你在上面看到的,我使用了 my_wc_format_sale_price,它在这里:
/**
* Format a sale price for display.
*
* @since 3.0.0
* @param float $regular_price Regular price.
* @param float $sale_price Sale price.
* @return string
*/
function my_wc_format_sale_price( $regular_price,$sale_price ) {
$price = '<span>' . get_my_percent($regular_price,$sale_price) . '</span> <ins>' . ( is_numeric( $sale_price ) ? wc_price( $sale_price ) : $sale_price ) . '</ins>';
return apply_filters( 'woocommerce_format_sale_price',$regular_price,$sale_price );
}
我认为这是最后一个重要的函数(它有一个文档注释说它返回一个字符串):
function get_my_percent($regular_price,$sale_price) {
$a = ($regular_price - $sale_price) / $regular_price * 100;
return "$a% reducere";
}
更新 4
我通过 https://stackoverflow.com/a/21429652/258462 发现了以下内容。
提供给反射机制的对象似乎与预期类型不同。
来自 WooCommerce 4.9.2 的源代码:
/**
* WC Variable Product Data Store: Stored in CPT.
*
* @version 3.0.0
*/
class WC_Product_Variable_Data_Store_CPT extends WC_Product_Data_Store_CPT implements WC_Object_Data_Store_Interface,WC_Product_Variable_Data_Store_Interface {
/**
* Cached & hashed prices array for child variations.
*
* @var array
*/
protected $prices_array = array()
...
那么问题是如何将 WC_Data_Store
转换为具有 $prices_array
属性的内容?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。