<?php declare(strict_types = 1);
namespace MailPoet\WooCommerce;
if (!defined('ABSPATH')) exit;
use MailPoet\Logging\LoggerFactory;
/**
* Makes an in-memory WooCommerce data object (order, customer, product, ...)
* safe to use as email or automation preview sample data.
*
* Preview helpers assign the object a placeholder ID (e.g. 12345) so templates
* render realistic content. Without this trait two things go wrong if a hook or
* integration touches the object while the preview renders:
*
* - save() / save_meta_data() / delete() treat the placeholder ID as an
* existing record and overwrite or remove the real order/customer 12345.
* - read_meta_data() lazy-loads the real record's meta from the database,
* leaking it into the preview.
*
* Mixing this trait into a thin subclass of the WooCommerce type turns those
* operations into safe no-ops.
*/
trait NonPersistablePreviewData {
// phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- declares the WC_Data::get_id() dependency.
abstract public function get_id();
/**
* @return int|string The placeholder ID; nothing is written to the database.
*/
public function save() {
$this->logPreviewPersistAttempt('save');
return $this->get_id();
}
public function save_meta_data() { // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- overrides WC_Data::save_meta_data().
$this->logPreviewPersistAttempt('save_meta_data');
}
/**
* @param bool $forceDelete
* @return bool Always false; preview data is never removed from the database.
*/
public function delete($forceDelete = false) {
$this->logPreviewPersistAttempt('delete');
return false;
}
/**
* Prevents lazy-loading the real record's meta for the placeholder ID.
*
* @param bool $forceRead
*/
public function read_meta_data($forceRead = false) { // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps -- overrides WC_Data::read_meta_data().
if (!is_array($this->meta_data)) { // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
$this->meta_data = []; // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
}
}
private function logPreviewPersistAttempt(string $method): void {
try {
LoggerFactory::getInstance()->getLogger(LoggerFactory::TOPIC_EMAIL_EDITOR)->error(
sprintf(
'Blocked %s() on preview-only WooCommerce data (%s, ID %s). An integration tried to persist email-preview sample data.',
$method,
static::class,
(string)$this->get_id()
)
);
} catch (\Throwable $e) {
// Ignore: logging failures must not affect preview rendering.
}
}
}