*/ public $words; /** * Email domain (reserved). * * @var string */ public $domain; /** * Price decimals. * * @var int */ public $decimals; /** * Order status weights. * * @var array */ public $statuses; /** * Category IDs of this batch (children; the parent first when there are no children). * * @var int[] */ public $terms; /** * IDs of other batches' objects, for a run that makes none of that type. * * @var array */ private $fallback; /** * Pools read in this step. * * @var array */ private $pools = array(); /** * Objects made by the current item, for `apwc_test_data_created` (Runner fires it). * * @var array */ private $created = array(); /** * Products loaded in this step. * * @var array */ private $products = array(); /** * Constructor. * * @since 1.0.0 * @param array $state Run state. */ public function __construct( array $state ) { $options = (array) ( $state['options'] ?? array() ); $this->batch = (string) ( $state['batches'][0] ?? '' ); $this->label = (string) ( $options['label'] ?? '' ); $this->from = (int) ( $state['window'][0] ?? time() - 90 * DAY_IN_SECONDS ); $this->to = (int) ( $state['window'][1] ?? time() ); $this->variable_share = (int) ( $options['variable_share'] ?? 40 ); $this->guest_share = (int) ( $options['guest_share'] ?? 30 ); $this->status = 'publish' === ( $options['status'] ?? '' ) ? 'publish' : 'private'; $this->terms = array_map( 'intval', (array) ( $state['terms']['children'] ?? array() ) ); $this->fallback = array_map( static fn( $ids ) => array_map( 'intval', (array) $ids ), (array) ( $state['fallback'] ?? array() ) ); $this->decimals = function_exists( 'wc_get_price_decimals' ) ? (int) wc_get_price_decimals() : 2; /** * Filter the word banks generated names, addresses and reviews come from. Replace a bank with * a non-empty list of strings; anything else keeps the default bank. * * @since 1.0.0 * @param array $banks first_names, last_names, adjectives, nouns, materials, * colours, sizes, categories, streets, cities, companies, reviews. */ $this->words = Words::banks( apply_filters( 'apwc_test_data_words', Words::defaults() ) ); /** * Filter the email domain of generated customers and guests. Only reserved domains are used * (ending in .test, .example or .invalid, or exactly example.com, .net or .org); anything else * falls back to example.test. * * @since 1.0.0 * @param string $domain Domain. */ $this->domain = Words::domain( apply_filters( 'apwc_test_data_email_domain', Words::DOMAIN ) ); /** * Filter how often each order status is generated (weights). Core statuses only: completed, * processing, on-hold, pending, cancelled, failed, refunded. * * @since 1.0.0 * @param array $weights Status => weight. */ $this->statuses = Plan::statuses( apply_filters( 'apwc_test_data_order_statuses', Plan::STATUSES ) ); } /** * IDs orders and reviews pick from: this batch's own objects, else other batches' (fallback). * Types: `products` (parents), `customers`, `coupons`, `orders` (this batch only). * * @since 1.0.0 * @param string $type Type. * @return int[] */ public function pool( string $type ): array { if ( ! isset( $this->pools[ $type ] ) ) { $limits = array( 'products' => 1000, 'customers' => 5000, 'coupons' => 200, 'orders' => 10000, ); $source = 'orders' === $type ? 'order_parents' : $type; $ids = isset( $limits[ $type ] ) ? Marker::ids( $source, $this->batch, 0, $limits[ $type ] ) : array(); // Only signed objects: never one that merely carries the marker. $ids = Marker::only_signed( array( 'customers' => 'user', 'orders' => 'order', )[ $type ] ?? 'post', $ids, $this->batch ); if ( ! $ids && 'orders' !== $type ) { $ids = $this->fallback[ $type ] ?? array(); } $this->pools[ $type ] = array_values( $ids ); } return $this->pools[ $type ]; } /** * A product, loaded once per step. * * @since 1.0.0 * @param int $id Product ID. * @return \WC_Product|null */ public function product( int $id ) { if ( ! array_key_exists( $id, $this->products ) ) { $product = wc_get_product( $id ); $this->products[ $id ] = $product instanceof \WC_Product ? $product : false; } return $this->products[ $id ] ? $this->products[ $id ] : null; } /** * Forget pools (after a phase that adds to them). * * @since 1.0.0 * @return void */ public function reset_pools(): void { $this->pools = array(); } /** * Note an object the current item made (the Runner fires `apwc_test_data_created` for it * once the item is done, outside the item's error handling). * * @since 1.0.0 * @param string $type Type. * @param int $id Object ID. * @return void */ public function created( string $type, int $id ): void { $this->created[] = array( $type, $id ); } /** * The objects noted since the last call. * * @since 1.0.0 * @return array */ public function take_created(): array { $created = $this->created; $this->created = array(); return $created; } }