add_meta_data( self::ITEM_META, $token, true );
if ( $sides ) {
$item->add_meta_data( __( 'Print', 'printblob' ), Cart::sides_label( array_keys( $sides ) ), true );
}
}
/**
* @param int $item_id Order item ID.
* @param \WC_Order_Item $item Order item.
* @param int $order_id Order ID.
*/
public static function link_design_to_order( $item_id, $item, $order_id ): void {
if ( ! $item instanceof \WC_Order_Item_Product ) {
return;
}
$design = self::design_for_item( $item );
if ( $design ) {
Design_Store::mark_ordered( $design->ID, (int) $order_id );
Review_Request::order_with_design();
}
}
/** The design reference is internal; the order screen shows the design itself. */
public static function hide_item_meta( array $keys ): array {
$keys[] = self::ITEM_META;
return $keys;
}
public static function design_for_item( \WC_Order_Item_Product $item ): ?\WP_Post {
$token = (string) $item->get_meta( self::ITEM_META );
return $token ? Design_Store::find_by_token( $token ) : null;
}
/**
* The design of an item an order screen shows: every design of the item's order is looked up with its first item.
*
* @param \WC_Order_Item_Product $item The item.
*/
private static function shown_design( \WC_Order_Item_Product $item ): ?\WP_Post {
static $by_order = array();
$token = (string) $item->get_meta( self::ITEM_META );
if ( '' === $token ) {
return null;
}
$order_id = $item->get_order_id();
if ( ! isset( $by_order[ $order_id ] ) ) {
$order = $item->get_order();
$by_order[ $order_id ] = $order instanceof \WC_Order ? Design_Store::designs_by_token( Design_Store::order_tokens( $order ) ) : array();
}
return $by_order[ $order_id ][ $token ] ?? null;
}
/** Whether the screen shown is WooCommerce's order edit screen, with or without its custom order tables. */
public static function on_edit_screen(): bool {
return class_exists( OrderUtil::class ) && OrderUtil::is_order_edit_screen();
}
/**
* @param int $item_id Order item ID.
* @param \WC_Order_Item $item Order item.
*/
public static function render_admin_design( $item_id, $item ): void {
if ( ! $item instanceof \WC_Order_Item_Product || ! current_user_can( 'edit_shop_orders' ) ) {
return;
}
$design = self::shown_design( $item );
if ( ! $design ) {
return;
}
echo '
';
foreach ( Design_Store::sides( $design->ID ) as $side => $data ) {
echo '';
echo wp_get_attachment_image( (int) $data['preview_id'], 'thumbnail', false, array( 'class' => 'printblob-order-design__preview' ) );
echo '';
self::side_links( $design->ID, (string) $side, (int) $item_id );
echo '';
echo '';
}
/**
* Fires after a designed item's previews and print file links on the order screen.
*
* @param \WC_Order_Item_Product $item Order item.
* @param int $design_id Design ID.
*/
do_action( 'printblob_order_item_design', $item, $design->ID );
echo '
';
static $offered = false;
if ( ! $offered ) {
$offered = true;
$order = $item->get_order();
if ( $order instanceof \WC_Order && self::pro_hint_due() ) {
echo wp_kses_post( self::pro_hint( Design_Store::print_file_count( $order ) ) );
}
}
}
/** What another plugin's links under a designed side may hold (printblob_order_design_links): a link, with an icon. */
public const LINKS_HTML = array(
'a' => array(
'href' => true,
'download' => true,
'class' => true,
),
'span' => array(
'class' => true,
'aria-hidden' => true,
),
);
/**
* A designed side's downloads on the order screen: its preview; its print file where one was made (orders placed
* before PrintBlob 1.4.0, or by PrintBlob Pro); what other plugins add (printblob_order_design_links); and, while
* Pro is not active, its print file and the customer's original images as the PrintBlob Pro add-on's controls, or,
* where Pro is installed without a licence that lets it run, that no print file was made and why.
*
* @param int $design_id The design.
* @param string $side One of its sides.
* @param int $item_id The order item.
* @param bool|null $pro_active Whether Pro's features run; Settings::pro_active() when null.
* @param bool|null $pro_installed Whether Pro is installed; Settings::pro_installed() when null.
*/
public static function side_links( int $design_id, string $side, int $item_id, ?bool $pro_active = null, ?bool $pro_installed = null ): void {
$pro_active = $pro_active ?? Settings::pro_active();
$locked = ! $pro_active && ! ( $pro_installed ?? Settings::pro_installed() );
$data = Design_Store::sides( $design_id )[ $side ] ?? array();
$label = Product_Settings::side_label( $side );
$preview = wp_get_attachment_url( (int) ( $data['preview_id'] ?? 0 ) );
echo '
';
}
/**
* A designed side's downloads as side_links() prints them.
*
* @param int $design_id The design.
* @param string $side One of its sides.
* @param int $item_id The order item.
* @param bool|null $pro_active Whether Pro's features run; Settings::pro_active() when null.
* @param bool|null $pro_installed Whether Pro is installed; Settings::pro_installed() when null.
*/
public static function side_links_html( int $design_id, string $side, int $item_id, ?bool $pro_active = null, ?bool $pro_installed = null ): string {
ob_start();
self::side_links( $design_id, $side, $item_id, $pro_active, $pro_installed );
return (string) ob_get_clean();
}
/**
* One quiet line under an order's first designed item about the PrintBlob Pro add-on's ZIP of its print files, while
* Pro is not active and until this admin dismisses it.
*
* @param int $files The order's print files.
* @param bool|null $pro_active Whether Pro is active; Settings::pro_active() when null.
* @param int|null $user_id The admin; the current user when null.
*/
public static function pro_hint( int $files, ?bool $pro_active = null, ?int $user_id = null ): string {
if ( $files < 1 || ! self::pro_hint_due( $pro_active, $user_id ) ) {
return '';
}
return sprintf(
'