The Sample class
WooCommerce Product Sample uses the Sample
object class which extends the WooCommerce WC_Data
class in the same way that the WC_Product
class does. Since a product sample, ultimately, is itself a product, this is the most obvious approach. This way, every property and method can be inherited and, eventually, adjusted to describe the sample properties, relative to the regular product it relates to.
The main difference with a regular product is that a sample is not stored as a separate row in the wp_posts
table. Instead, the information about the product sample is a set of metadata stored in the wp_postmeta
table with the same ID as the regular product. For this reason, from the perspective of the interaction with the database, the Sample
class doesn't use a WC_Data_Store
class. It rather defines its own read
, save
, update
or delete
methods that take care of the retrieval, update and deletion of the sample-related metadata from the wp_postmeta
table.
Still, the Sample
class is designed to closely replicate the same properties and methods of the WC_Product
class. This allows developers to extend the plugin using the knowledge they already have about the WC_Product
class.
For example, consider the following code snippet:
global $product;
echo $product->get_price();
// output: 10
This can easily be recognized as a fragment that outputs the price of a product. Similarly, the following code snippet does the same thing but with the sample price instead:
global $product;
$sample = new Barn2\Plugin\WC_Product_Sample\Sample( $product );
echo $sample->get_price();
// output: 1
In this code snippet, you can see that a sample object can be instantiated from the $product
object it refers to. This can be done by passing either the $product
object itself or its ID (although the former method, when viable, is preferred as it prevents an unnecessary call to the wc_get_product
function). Then, every property and method can be accessed the same way developers are already used to with the $product
object. The only difference is that the sample object will be returning the product sample properties instead of the regular product ones (when they are different, of course).
Whether the $sample
object will return the same result the $product
object does is just a matter of how the sample is configured. For example, if a sample is set to come from the same stock of the regular product, then all the inventory properties and methods (stock quantity, stock status, weight and dimensions) are going to return the exact same values the regular product does (and no additional, unnecessary data will be stored in the database).
The product property
Every sample can be instantiated from the product object it refers to. Because of the tight connection between a sample and the regular product it represents, a reference of the regular product is stored as a property of the sample object so that it can always be referred to when needed. This way, even for those properties or methods that are not replicated in the Sample class design, developers can always refer to the connected product and use its properties and methods instead.
Let's consider the following example. A store owner wants to disable the possibility to order samples of all the products that are currently on sale. This can be easily done with the following code snippet:
add_filter( 'wsa_sample_should_add_button', 'my_wsa_sample_should_add_button', 10, 2 );
function my_wsa_sample_should_add_button( $is_button_visible, $sample ) {
$product = $sample->get_product();
return $is_button_visible && ! $product->is_on_sale();
}
It is important to notice that, in the case of product variations, the product
property of a sample refers to the variation. If it is necessary to reference the variable product that variation is a child of, it will be possible to use the parent_product
property instead, which is going to be instantiated only if the current product is a variation.
Use of the sample object in action and filter callback functions
Similar to what happens with properties and methods, the Sample
class replicates also many of the action and filter hooks associated with a WC_Product
class. For example, when retrieving a sample property, the value can be filtered using the wsa_sample_get_{$prop}
filter hook the exact same way one can use the woocommerce_product_get_{$prop}
filter hook for the same purpose. Let's consider the following code snippet:
add_filter( 'wsa_sample_get_price', 'my_wsa_sample_get_price', 10, 2 );
function my_wsa_sample_get_price( $price, $sample ) {
if ( ! $sample->is_virtual() ) {
$price += 2;
}
return $price;
}
The fragment above increases the price of samples of non-virtual products by 2 (e.g. $5 becomes $7). As you can see, the $sample
object has the same is_virtual()
conditional method a regular $product
object does and we don't need to refer to the connected product object.