core = $core;
$this->support = new Support( $core );
add_action( 'admin_menu', [ $this, 'register_menu' ] );
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue' ] );
}
/**
* Capability for the Patchwork menu: the first module capability the current
* user has, or null when they can't manage any module.
*/
public static function menu_cap( Core $core ): ?string {
foreach ( $core->modules() as $module ) {
if ( current_user_can( $module->settings_capability() ) ) return $module->settings_capability();
}
return null;
}
public static function current_user_can_menu( Core $core ): bool {
return self::menu_cap( $core ) !== null;
}
/** Menu icon: the Patchwork mark (3×3 patches in braces), single colour so WP can tint it. */
public static function icon_svg( string $fill = 'black' ): string {
$brace = 'M5 2.5H4C2.9 2.5 2.4 3.2 2.4 4.3v3.3c0 .8-.4 1.3-1.4 1.4v2c1 .1 1.4.6 1.4 1.4v3.3c0 1.1.5 1.8 1.6 1.8h1v-1.6h-.6c-.4 0-.5-.3-.5-.8v-3.2c0-1-.4-1.6-1.2-1.9.8-.3 1.2-.9 1.2-1.9V4.9c0-.5.1-.8.5-.8H5z';
$rects = '';
foreach ( [ 6.1, 8.9, 11.7 ] as $y ) {
foreach ( [ 6.1, 8.9, 11.7 ] as $x ) {
$rects .= sprintf( '', $x, $y );
}
}
$svg = '';
return 'data:image/svg+xml;base64,' . base64_encode( $svg );
}
// ─── Menu ─────────────────────────────────────────────────────────────────
public function register_menu(): void {
$modules = $this->core->modules();
if ( ! $modules ) return;
// The menu shows if the user can manage at least one module.
$menu_cap = self::menu_cap( $this->core );
if ( ! $menu_cap ) return;
add_menu_page( 'Patchwork', 'Patchwork', $menu_cap, self::SLUG, [ $this, 'render_overview' ], self::icon_svg(), 56 );
add_submenu_page( self::SLUG, __( 'Patchwork overview', 'patchwork-order-split' ), __( 'Overview', 'patchwork-order-split' ), $menu_cap, self::SLUG, [ $this, 'render_overview' ] );
foreach ( $modules as $module ) {
add_submenu_page(
self::SLUG,
$module->name(),
self::short_name( $module ),
$module->settings_capability(),
'patchwork-' . $module->id(),
function() use ( $module ) { $this->render_module( $module ); }
);
}
add_submenu_page( self::SLUG, __( 'Get support', 'patchwork-order-split' ), __( 'Support', 'patchwork-order-split' ), $menu_cap, Support::PAGE, [ $this->support, 'render' ] );
}
/** "Patchwork Split" → "Split" inside the Patchwork menu. */
private static function short_name( Module $module ): string {
return preg_replace( '/^Patchwork\s+/i', '', $module->name() );
}
public function enqueue(): void {
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
if ( ! $screen ) return;
$is_patchwork = strpos( $screen->id, self::SLUG ) !== false;
$is_orders = in_array( $screen->id, [ 'woocommerce_page_wc-orders', 'edit-shop_order', 'shop_order' ], true );
if ( ! $is_patchwork && ! $is_orders ) return;
wp_enqueue_style( 'patchwork-core', PATCHWORK_CORE_URL . 'assets/core.css', [], PATCHWORK_CORE_VERSION );
}
// ─── Overview ─────────────────────────────────────────────────────────────
public function render_overview(): void {
$modules = $this->core->modules();
?>
dashboard_card();
$can = current_user_can( $module->settings_capability() );
?>
name() ); ?>
is_pro() ) : ?>
version() ) ); ?>
description() ) : ?>
description() ); ?>
render_catalog(); ?>
core->catalog(), $this->core->modules() );
if ( ! $missing ) return;
?>
__( 'Settings', 'patchwork-order-split' ),
'activity' => __( 'Activity', 'patchwork-order-split' ),
'licence' => __( 'Licence', 'patchwork-order-split' ),
];
if ( ! isset( $tabs[ $tab ] ) ) $tab = 'settings';
?>
name(), $module->description(), $module ); ?>
id() );
} elseif ( $tab === 'licence' ) {
self::render_licence( $module );
} else {
Settings_Page::render( $module );
}
?>
is_pro();
$features = $module->pro_features();
?>
name() ); ?>
is_dev_pro() ) : ?>
upgrade_url() ) : ?>
account_url() ) : ?>
icon();
if ( strpos( $icon, 'dashicons-' ) === 0 ) {
echo '';
} else {
echo '
';
}
}
}