Adding custom placeholders
To create a new placeholder, you have to do two things:
- Create a new class that extends
\WPDesk\ShopMagic\Workflow\Placeholder\Placeholder
abstract class. - Inform ShopMagic that a new placeholder is available.
Creating a new placeholder class
Each placeholder has access to data (user, order, etc.) through \WPDesk\ShopMagic\Workflow\Event\DataLayer
class, which is just a container, holding requested resources and giving you access to them.
For example, requesting order based data is as simple as that:
class MyPlaceholder extends \WPDesk\ShopMagic\Workflow\Placeholder\Placeholder {
// Skip the rest of the class for brevity
public function value( $params = [] ): string {
// We need to check if data if available!
if ($this->resources->has(\WC_Order::class)) {
// Get our order data here.
$order = $this->resources->get(\WC_Order::class);
return (string) $order->get_id();
}
return 'no id';
}
}
Creating a new placeholder that depends on the order data
To facilitate the creation of an order-dependant placeholder, it's best to extend \WPDesk\ShopMagic\Workflow\Placeholder\Builtin\WooCommerceOrderBasedPlaceholder
class and override two primary methods: get_slug
and value
.
The get_slug
method defines the shortcode for the placeholder. It should be in the {{order.placeholder_name}}
format.
To further facilitate and standardize the naming convention, you can use a parent::get_slug
method that returns a prefix based on the data required by the placeholder.
Example
A placeholder with shortcode {{order.some_name}}
can have a slug defined as:
public function get_slug(): string {
return 'some_name';
}
// This function can be introduced in shared parent class to avoid typing group
// all the time.
// Actually, WooCommerceOrderBasedPlaceholder has this group defined for you already,
// so most of the time, you can omit this method in your class.
public function get_group_slug(): string {
return 'order';
}
The value
method should return a value to substitute a placeholder shortcode. The value method receives only one parameter:
- optional array
$parameters
with the values of placeholder parameters.
Example
To substitute for {{order.download_url}} the order download url, you can use:
public function value( array $parameters ) {
return $this->get_order()->download_url();
}
To add fallback for shortcode when the download URL is not available, you can use {{order.download_url | fallback:'https://shopmagic.app/' }}
public function value( array $parameters ) {
$download_url = $this->get_order()->download_url();
if ( empty( $download_url ) && ! empty( $parameters['fallback'] ) ) {
return $parameters['fallback'];
}
return $this->get_order()->download_url();
}
Informing the ShopMagic plugin about a new placeholder
To integrate a newly created placeholder class, you should use a filter shopmagic/core/placeholders
and add a new class to the placeholder hashmap.
Example
Let's create a new placeholder with a name {{order.nice_id}}
that shows an interesting order id in the format "Your order id is: 11".
As we need the order to get the order id, that class depends on the WooCommerce WC_Order data.
namespace YourNamespace;
class NiceOrderId extends \WPDesk\ShopMagic\Workflow\Placeholder\Builtin\WooCommerceOrderBasedPlaceholder {
public function get_slug() {
return 'nice_id';
}
/**
* @param array $parameters
*
* @return string
*/
public function value( array $parameters ) {
return "Your order id is: {$this->get_order()->get_id()}";
}
}
Then we need to inform the ShopMagic placeholder factory using the shopmagic/core/placeholders
filter.
/**
* @param \WPDesk\ShopMagic\Workflow\Placeholder\Placeholder[] $hashmap Hashmap with built in placeholders.
*
* @return \WPDesk\ShopMagic\Workflow\Placeholder\Placeholder[] Hashmap with appended placeholder.
*/
function integrate_custom_shopmagic_placeholder( array $hashmap ) {
require_once(__DIR__ . '/path/to/placeholder/class/if/no/autoloading/used.php');
$hashmap[] = new \YourNamespace\NiceOrderId();
return $hashmap;
}
add_filter('shopmagic/core/placeholders', 'integrate_custom_shopmagic_placeholder');