'simple', 'label_template' => 'a4_two_up', 'label_width' => 10, 'label_height' => 20, 'label_rotate' => 0, 'logo_width' => 40, 'label_items' => true, 'label_logo' => true, 'label_orderid' => true, 'label_orderdate' => true, 'label_printdate' => true, 'label_onecol' => false, ]; } /** * {@inheritDoc} */ public function settingsSchema(): array { return [ 'invoice_template' => [ 'type' => 'select', 'label' => __( 'قالب فاکتور', 'rahkar-toolkit' ), 'options' => TemplateRegistry::choices( TemplateRegistry::invoices() ), 'default' => 'simple', 'section' => 'templates', ], 'label_template' => [ 'type' => 'select', 'label' => __( 'قالب برچسب پستی', 'rahkar-toolkit' ), 'options' => TemplateRegistry::choices( TemplateRegistry::labels() ), 'default' => 'a4_two_up', 'section' => 'templates', ], 'label_width' => [ 'type' => 'number', 'label' => __( 'عرض لیبل حرارتی (سانتی‌متر)', 'rahkar-toolkit' ), 'help' => __( 'فقط برای قالب لیبل حرارتی. اندازه‌ی کاغذ در مرورگر باید دقیقاً همین باشد و مقیاس روی ۱۰۰٪ — هر «fit to page» چیدمان میلیمتری را تغییر می‌دهد.', 'rahkar-toolkit' ), 'default' => 10, 'min' => 1, 'max' => 100, 'step' => 0.5, 'section' => 'thermal', ], 'label_height' => [ 'type' => 'number', 'label' => __( 'ارتفاع لیبل حرارتی (سانتی‌متر)', 'rahkar-toolkit' ), 'default' => 20, 'min' => 1, 'max' => 100, 'step' => 0.5, 'section' => 'thermal', ], 'label_rotate' => [ 'type' => 'select', 'label' => __( 'چرخش نرم‌افزاری', 'rahkar-toolkit' ), 'options' => [ '0' => __( 'بدون چرخش', 'rahkar-toolkit' ), '90' => __( '۹۰ درجه (ساعتگرد)', 'rahkar-toolkit' ), '270' => __( '۲۷۰ درجه (پادساعتگرد)', 'rahkar-toolkit' ), ], 'help' => __( 'برخی درایورهای لیبل‌زن صفحه‌ی رستری‌شده‌ی مرورگر را نمی‌چرخانند. این گزینه محتوا را با CSS می‌چرخاند و ابعاد صفحه را جابه‌جا می‌کند تا برچسب مستقل از درایور صاف چاپ شود.', 'rahkar-toolkit' ), 'default' => '0', 'section' => 'thermal', ], 'logo_width' => [ 'type' => 'number', 'label' => __( 'حداکثر عرض لوگو روی لیبل (میلی‌متر)', 'rahkar-toolkit' ), 'default' => 40, 'min' => 5, 'max' => 100, 'section' => 'thermal', ], 'label_logo' => [ 'type' => 'checkbox', 'label' => __( 'نمایش لوگو', 'rahkar-toolkit' ), 'default' => true, 'section' => 'thermal', ], 'label_orderid' => [ 'type' => 'checkbox', 'label' => __( 'نمایش شناسه سفارش', 'rahkar-toolkit' ), 'default' => true, 'section' => 'thermal', ], 'label_orderdate' => [ 'type' => 'checkbox', 'label' => __( 'نمایش تاریخ سفارش', 'rahkar-toolkit' ), 'default' => true, 'section' => 'thermal', ], 'label_printdate' => [ 'type' => 'checkbox', 'label' => __( 'نمایش تاریخ چاپ', 'rahkar-toolkit' ), 'default' => true, 'section' => 'thermal', ], 'label_items' => [ 'type' => 'checkbox', 'label' => __( 'نمایش فهرست کالاها', 'rahkar-toolkit' ), 'help' => __( 'روی رول‌های کوتاه (مثلاً ۵ سانتی‌متر) جا نمی‌شود؛ برای آن‌ها خاموشش کنید.', 'rahkar-toolkit' ), 'default' => true, 'section' => 'thermal', ], 'label_onecol' => [ 'type' => 'checkbox', 'label' => __( 'گیرنده و فرستنده زیر هم', 'rahkar-toolkit' ), 'help' => __( 'برای رول‌های باریک که دو ستون کنار هم در آن‌ها جا نمی‌شود.', 'rahkar-toolkit' ), 'default' => false, 'section' => 'thermal', ], ]; } /** * {@inheritDoc} */ public function settingsSections(): array { return [ 'templates' => __( 'انتخاب قالب', 'rahkar-toolkit' ), 'thermal' => __( 'لیبل حرارتی رول', 'rahkar-toolkit' ), ]; } /** * {@inheritDoc} */ public function register(): void { // The context mask already keeps this module off the storefront. What it // cannot express is that, inside wp-admin, everything here belongs to the // order screens — so until this point both handlers were opened on every // admin page view, dashboard and post editor included. add_action( 'admin_post_' . Hooks::ORDER_PRINT, static fn() => Plugin::make( PrintEndpoint::class )->handle() ); // Bulk actions, on both order list tables. foreach ( [ 'bulk_actions-woocommerce_page_wc-orders', 'bulk_actions-edit-shop_order' ] as $filter ) { add_filter( $filter, static fn( $actions ): array => Plugin::make( AdminUi::class )->addBulkActions( $actions ) ); } foreach ( [ 'handle_bulk_actions-woocommerce_page_wc-orders', 'handle_bulk_actions-edit-shop_order' ] as $filter ) { add_filter( $filter, static fn( $redirectTo, $action, $ids ): string => Plugin::make( AdminUi::class )->handleBulk( $redirectTo, $action, $ids ), 10, 3 ); } // Buttons on the order-edit screen. This hook fires on both screens with the // order object, which makes it the version-stable place for the single-order // entry point — the row-action hooks differ between them. add_action( 'woocommerce_admin_order_data_after_order_details', static fn( $order ) => Plugin::make( AdminUi::class )->editScreenButtons( $order ) ); // Per-row icons in the orders list. Same filter WooCommerce uses for its own // action icons, and it fires on both list tables. add_filter( 'woocommerce_admin_order_actions', static fn( $actions, $order ): array => Plugin::make( AdminUi::class )->rowActions( $actions, $order ), 10, 2 ); // `admin_footer` fires on every admin page, so the screen test happens in // this closure — which lives in a file that is already open — rather than // inside `listAssets()`. Testing it there would load the handler on every // admin page just to be told this is not an order list. $onOrderList = static function (): bool { $screen = get_current_screen(); return $screen && in_array( $screen->id, [ 'woocommerce_page_wc-orders', 'edit-shop_order' ], true ); }; add_action( 'admin_head', static function () use ( $onOrderList ): void { if ( $onOrderList() ) { Plugin::make( AdminUi::class )->listStyles(); } } ); add_action( 'admin_footer', static function () use ( $onOrderList ): void { if ( $onOrderList() ) { Plugin::make( AdminUi::class )->listAssets(); } } ); } }