';
return 'data:image/svg+xml;base64,' . base64_encode( $svg ); // phpcs:ignore
}
/**
* Pages.
*
* @return array slug => [title, view]
*/
public static function pages() {
$pages = array(
self::SLUG => array( __( 'Dashboard', 'spinix-migration' ), 'dashboard', 'home' ),
self::SLUG . '-backups' => array( __( 'Backups', 'spinix-migration' ), 'backups', 'archive' ),
self::SLUG . '-import' => array( __( 'Import / Restore', 'spinix-migration' ), 'import', 'upload' ),
self::SLUG . '-tools' => array( __( 'Downloads & Tools', 'spinix-migration' ), 'tools', 'tools' ),
self::SLUG . '-settings' => array( __( 'Schedule & Settings', 'spinix-migration' ), 'settings', 'clock' ),
self::SLUG . '-health' => array( __( 'System Health', 'spinix-migration' ), 'health', 'pulse' ),
);
/**
* Admin pages: slug => [ title, view, icon ]. Add-ons can add views (rendered by their own JS).
*/
return (array) apply_filters( 'spinix_admin_pages', $pages );
}
/**
* Branding (name, logo, colors). Filterable for white-label add-ons.
*
* @return array
*/
public static function branding() {
return (array) apply_filters(
'spinix_branding',
array(
'name' => 'Spinix Migration & Backup',
'menu' => 'Spinix',
'tagline' => __( 'Backup · Migrate · Restore', 'spinix-migration' ),
'logo' => '',
'menu_icon' => self::icon(),
'color' => '',
'color2' => '',
'show_footer' => true,
'show_version' => true,
)
);
}
/**
* Register menu.
*/
public static function menu() {
$cap = Spinix_Ajax::cap();
$brand = self::branding();
add_menu_page( $brand['name'], $brand['menu'], $cap, self::SLUG, array( __CLASS__, 'render' ), $brand['menu_icon'], 76 );
foreach ( self::pages() as $slug => $p ) {
$menu_title = $p[0];
if ( 'backups' === $p[1] ) {
$n = self::backup_count();
$menu_title = $p[0] . ' ' . (int) $n . '';
}
add_submenu_page( self::SLUG, $p[0] . ' ‹ ' . $brand['menu'], $menu_title, $cap, $slug, array( __CLASS__, 'render' ) );
}
}
/**
* Number of .spinix backups in the storage folder (cheap: no file is opened).
*
* @return int
*/
public static function backup_count() {
$base = Spinix_Storage::base_dir();
if ( ! is_dir( $base ) ) {
return 0;
}
$a = glob( $base . '/*.spinix' );
$b = glob( $base . '/*.SPINIX' );
return count( array_unique( array_merge( $a ? $a : array(), $b ? $b : array() ) ) );
}
/**
* Style for the backup count bubble in the WordPress admin menu.
*/
public static function menu_css() {
if ( ! current_user_can( Spinix_Ajax::cap() ) ) {
return;
}
wp_add_inline_style( 'admin-menu', '#adminmenu .spinix-count{display:inline-block;min-width:18px;height:18px;padding:0 6px;margin-left:6px;border-radius:9px;background:#5b4dff;color:#fff;font-size:11px;font-weight:600;line-height:18px;text-align:center;vertical-align:text-bottom;box-sizing:border-box}' );
}
/**
* Plugins list links.
*
* @param array $links Links.
* @return array
*/
public static function action_links( $links ) {
array_unshift( $links, '' . esc_html__( 'Open Spinix', 'spinix-migration' ) . '' );
return $links;
}
/**
* Is this one of our pages?
*
* @return string|null View.
*/
private static function current_view() {
$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : ''; // phpcs:ignore
$pages = self::pages();
return isset( $pages[ $page ] ) ? $pages[ $page ][1] : null;
}
/**
* Enqueue assets.
*/
public static function assets() {
$view = self::current_view();
if ( ! $view ) {
return;
}
$ver = SPINIX_VERSION . '.' . filemtime( SPINIX_DIR . 'assets/js/admin.js' );
wp_enqueue_style( 'spinix-admin', SPINIX_URL . 'assets/css/admin.css', array(), $ver );
wp_enqueue_script( 'spinix-admin', SPINIX_URL . 'assets/js/admin.js', array(), $ver, true );
$urls = array();
$nav = array();
foreach ( self::pages() as $slug => $p ) {
$urls[ $p[1] ] = admin_url( 'admin.php?page=' . $slug );
$nav[] = array( $p[1], isset( $p[2] ) ? $p[2] : 'tools', $p[0] );
}
$config = array(
'ajax' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( Spinix_Ajax::NONCE ),
'download' => wp_nonce_url( admin_url( 'admin-post.php?action=spinix_download' ), 'spinix_download' ),
'view' => $view,
'urls' => $urls,
'version' => SPINIX_VERSION,
'home' => home_url(),
'login' => wp_login_url(),
'chunk' => Spinix_Uploader::chunk_size(),
'folder' => Spinix_Storage::base_dir(),
'php' => PHP_VERSION,
'encryption' => (bool) Spinix_Crypto::best_cipher(),
'settings' => Spinix_Scheduler::settings(),
'backupCount' => self::backup_count(),
'i18n' => self::strings(),
'nav' => $nav,
'branding' => self::branding(),
);
/**
* Data passed to the admin app (add-ons can add their own keys).
*/
$config = apply_filters( 'spinix_admin_config', $config, $view );
wp_localize_script( 'spinix-admin', 'SpinixConfig', $config );
/**
* Add-ons enqueue their admin scripts here (depend on 'spinix-admin').
*/
do_action( 'spinix_admin_enqueue', $view );
}
/**
* Render the app shell.
*/
public static function render() {
echo 'Spinix Migration & Backup
';
echo '
';
}
/**
* Admin notices outside our pages.
*/
public static function notices() {
if ( self::current_view() || ! current_user_can( Spinix_Ajax::cap() ) ) {
return;
}
try {
$active = Spinix_Job::active();
} catch ( Throwable $e ) {
return;
}
if ( $active && in_array( $active->data['type'], array( 'restore', 'rollback' ), true ) ) {
echo '';
}
}
/**
* UI strings (translatable).
*
* @return array
*/
private static function strings() {
return array(
'dashboard' => __( 'Dashboard', 'spinix-migration' ),
'backups' => __( 'Backups', 'spinix-migration' ),
'import' => __( 'Import / Restore', 'spinix-migration' ),
'tools' => __( 'Downloads & Tools', 'spinix-migration' ),
'settings' => __( 'Schedule & Settings', 'spinix-migration' ),
'health' => __( 'System Health', 'spinix-migration' ),
'confirmDelete' => __( 'Delete this backup permanently?', 'spinix-migration' ),
'leaveWarning' => __( 'A restore is running. If you leave now, your website may be left broken. Stay on this page until it finishes.', 'spinix-migration' ),
'leaveBackup' => __( 'A backup is running. Leaving will pause it (you can resume later).', 'spinix-migration' ),
);
}
}