" (its title, PrintBlob, is not translated). */
public const SCREEN = 'toplevel_page_printblob';
public const SCREEN_PREFIX = 'printblob_page_';
public static function register(): void {
add_action( 'admin_menu', array( __CLASS__, 'add' ) );
add_filter( 'menu_order', array( __CLASS__, 'after_products' ), 11 );
add_filter( 'admin_footer_text', array( __CLASS__, 'footer_text' ) );
add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue' ) );
add_filter( 'site_status_test_result', array( Overview::class, 'keep_print_folder' ) );
}
public static function url(): string {
return admin_url( 'admin.php?page=' . self::SLUG );
}
public static function add(): void {
$overview = __( 'PrintBlob overview', 'printblob' );
add_menu_page( $overview, 'PrintBlob', self::CAPABILITY, self::SLUG, array( Overview::class, 'render' ), FACTS['menu_icon'], '55.7' );
add_submenu_page( self::SLUG, $overview, __( 'Overview', 'printblob' ), self::CAPABILITY, self::SLUG, array( Overview::class, 'render' ) );
add_submenu_page( self::SLUG, __( 'PrintBlob settings', 'printblob' ), __( 'Settings', 'printblob' ), self::CAPABILITY, 'admin.php?page=wc-settings&tab=printblob' );
/**
* Fires after PrintBlob's menu, its Overview and Settings are added, for other code's items under it.
*
* @param string $parent_slug The menu's slug, the parent of its items.
*/
do_action( 'printblob_admin_menu', self::SLUG );
if ( ! Settings::pro_active() ) {
add_submenu_page( self::SLUG, __( 'Print queue', 'printblob' ), __( 'Print queue', 'printblob' ), self::CAPABILITY, Print_Queue::PAGE, array( Print_Queue::class, 'render' ) );
}
add_submenu_page( self::SLUG, __( 'PrintBlob Pro', 'printblob' ), __( 'PrintBlob Pro', 'printblob' ), self::CAPABILITY, Pro::PAGE, array( Pro::class, 'compare_page' ) );
if ( ! Settings::pro_active() && current_user_can( self::CAPABILITY ) ) {
global $submenu;
// add_submenu_page() runs a slug through plugin_basename(), which turns the "//" of an address into "/"; WordPress 7.1 prints an item's slug as its link unescaped.
$submenu[ self::SLUG ][] = array( '' . esc_html__( 'Get Pro', 'printblob' ) . '', self::CAPABILITY, esc_url( Pro::checkout_url( 'menu' ) ), __( 'Get PrintBlob Pro', 'printblob' ), 'printblob-get-pro' ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- The documented way to add a menu item that leaves the admin.
}
add_submenu_page( 'woocommerce', $overview, 'PrintBlob', self::CAPABILITY, 'admin.php?page=' . self::SLUG );
}
/**
* WooCommerce orders its menu as WooCommerce, then Products; PrintBlob follows Products.
*
* @param string[] $order Menu slugs in order.
*/
public static function after_products( $order ) {
if ( ! is_array( $order ) ) {
return $order;
}
$order = array_values( array_diff( $order, array( self::SLUG ) ) );
// WooCommerce's own ordering moves Products after WooCommerce and leaves its first place in the list too: the
// place WordPress keeps is the last one.
$products = array_keys( $order, 'edit.php?post_type=product', true );
if ( array() === $products ) {
return $order;
}
array_splice( $order, (int) end( $products ) + 1, 0, array( self::SLUG ) );
return $order;
}
/**
* On PrintBlob's own screens, one line in the admin footer asking for a review on WordPress.org.
*
* @param string $text The footer's text.
*/
public static function footer_text( $text ) {
if ( 'own' !== self::surface() || ! current_user_can( self::CAPABILITY ) ) {
return $text;
}
return self::footer_html();
}
public static function footer_html(): string {
return sprintf(
/* translators: %s: five stars, linking to PrintBlob's reviews on WordPress.org. */
esc_html__( 'If PrintBlob helps your shop, please rate it %s on WordPress.org.', 'printblob' ),
'★★★★★'
);
}
/**
* Refuses an admin-post request without the nonce of `$action` (action_url() makes it) or from a user without
* `$capability`.
*/
public static function guard( string $action, string $capability = self::CAPABILITY ): void {
check_admin_referer( $action );
self::allow( $capability );
}
/** Refuses a user without `$capability`. */
public static function allow( string $capability = self::CAPABILITY ): void {
if ( ! current_user_can( $capability ) ) {
wp_die( esc_html__( 'You are not allowed to do this.', 'printblob' ), 403 );
}
}
/** Ends the request with a redirect back to the screen it came from, or to `$fallback` (the dashboard when empty). */
public static function back( string $fallback = '' ): void {
$back = wp_get_referer();
wp_safe_redirect( $back ? $back : ( '' !== $fallback ? $fallback : admin_url() ) );
exit;
}
/**
* The address of one of PrintBlob's admin-post actions, with a nonce named after it (raw: escape it where printed).
*
* @param string $action The action.
* @param array $args More query arguments.
*/
public static function action_url( string $action, array $args = array() ): string {
return wp_nonce_url( add_query_arg( array( 'action' => $action ) + $args, admin_url( 'admin-post.php' ) ), $action );
}
/**
* A ✓ or ✗, or a neutral – for neither, with what it means in words, beside it or only for screen readers.
*
* @param bool|null $yes Which mark; null for neither.
* @param string $words What it means.
* @param bool $shown Whether the words are shown beside it.
*/
public static function mark_html( ?bool $yes, string $words, bool $shown = true ): string {
return sprintf(
'%2$s%3$s',
null === $yes ? 'none' : ( $yes ? 'yes' : 'no' ),
null === $yes ? '–' : ( $yes ? '✓' : '✗' ),
$shown ? ' ' . esc_html( $words ) . '' : '' . esc_html( $words ) . ''
);
}
/**
* Which of PrintBlob's admin surfaces the screen shown is: `own` (its own screens), `product` or `order` (the edit
* screens its controls are on), `plugins`, or '' for any other. Worked out once a request, by the first hook that
* asks after WordPress has set the screen.
*/
public static function surface(): string {
static $surface = null;
if ( null !== $surface ) {
return $surface;
}
$screen = get_current_screen();
if ( ! $screen ) {
return '';
}
if ( Settings::on_own_screen() ) {
$surface = 'own';
} elseif ( 'post' === $screen->base && 'product' === $screen->post_type ) {
$surface = 'product';
} elseif ( Order::on_edit_screen() ) {
$surface = 'order';
} else {
$surface = 'plugins' === $screen->id ? 'plugins' : '';
}
return $surface;
}
/** Whether the admin screen shown has PrintBlob on it: its own screens, and the product and order screens. */
public static function on_printblob_surface(): bool {
return in_array( self::surface(), array( 'own', 'product', 'order' ), true );
}
/** PrintBlob's admin styles: its own screens, and the product and order screens, where its Pro controls are. */
public static function enqueue(): void {
if ( ! self::on_printblob_surface() ) {
return;
}
wp_enqueue_style( 'printblob-admin', plugins_url( 'assets/admin/admin.css', FILE ), array( 'dashicons' ), VERSION );
}
}