You've already forked wc-licensed-product
226 lines
8.1 KiB
PHP
226 lines
8.1 KiB
PHP
|
|
<?php
|
||
|
|
/**
|
||
|
|
* Dashboard Widget Controller
|
||
|
|
*
|
||
|
|
* @package Jeremias\WcLicensedProduct\Admin
|
||
|
|
*/
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
namespace Jeremias\WcLicensedProduct\Admin;
|
||
|
|
|
||
|
|
use Jeremias\WcLicensedProduct\License\License;
|
||
|
|
use Jeremias\WcLicensedProduct\License\LicenseManager;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Handles the WordPress admin dashboard widget for license statistics
|
||
|
|
*/
|
||
|
|
final class DashboardWidgetController
|
||
|
|
{
|
||
|
|
private LicenseManager $licenseManager;
|
||
|
|
|
||
|
|
public function __construct(LicenseManager $licenseManager)
|
||
|
|
{
|
||
|
|
$this->licenseManager = $licenseManager;
|
||
|
|
$this->registerHooks();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Register WordPress hooks
|
||
|
|
*/
|
||
|
|
private function registerHooks(): void
|
||
|
|
{
|
||
|
|
add_action('wp_dashboard_setup', [$this, 'registerDashboardWidget']);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Register the dashboard widget
|
||
|
|
*/
|
||
|
|
public function registerDashboardWidget(): void
|
||
|
|
{
|
||
|
|
if (!current_user_can('manage_woocommerce')) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
wp_add_dashboard_widget(
|
||
|
|
'wclp_license_statistics',
|
||
|
|
__('License Statistics', 'wc-licensed-product'),
|
||
|
|
[$this, 'renderWidget']
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Render the dashboard widget content
|
||
|
|
*/
|
||
|
|
public function renderWidget(): void
|
||
|
|
{
|
||
|
|
$stats = $this->licenseManager->getStatistics();
|
||
|
|
$licensesUrl = admin_url('admin.php?page=wc-licensed-product-licenses');
|
||
|
|
?>
|
||
|
|
<style>
|
||
|
|
.wclp-widget-stats {
|
||
|
|
display: grid;
|
||
|
|
grid-template-columns: repeat(2, 1fr);
|
||
|
|
gap: 12px;
|
||
|
|
margin-bottom: 16px;
|
||
|
|
}
|
||
|
|
.wclp-stat-card {
|
||
|
|
background: #f8f9fa;
|
||
|
|
border: 1px solid #e2e4e7;
|
||
|
|
border-radius: 4px;
|
||
|
|
padding: 12px;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
.wclp-stat-card.highlight {
|
||
|
|
border-left: 3px solid #7f54b3;
|
||
|
|
}
|
||
|
|
.wclp-stat-card.warning {
|
||
|
|
border-left: 3px solid #f0b849;
|
||
|
|
}
|
||
|
|
.wclp-stat-card.danger {
|
||
|
|
border-left: 3px solid #dc3232;
|
||
|
|
}
|
||
|
|
.wclp-stat-card.success {
|
||
|
|
border-left: 3px solid #46b450;
|
||
|
|
}
|
||
|
|
.wclp-stat-number {
|
||
|
|
font-size: 28px;
|
||
|
|
font-weight: 600;
|
||
|
|
color: #1d2327;
|
||
|
|
line-height: 1.2;
|
||
|
|
}
|
||
|
|
.wclp-stat-label {
|
||
|
|
font-size: 12px;
|
||
|
|
color: #646970;
|
||
|
|
text-transform: uppercase;
|
||
|
|
letter-spacing: 0.5px;
|
||
|
|
margin-top: 4px;
|
||
|
|
}
|
||
|
|
.wclp-widget-divider {
|
||
|
|
border-top: 1px solid #e2e4e7;
|
||
|
|
margin: 16px 0;
|
||
|
|
}
|
||
|
|
.wclp-status-list {
|
||
|
|
display: flex;
|
||
|
|
flex-wrap: wrap;
|
||
|
|
gap: 8px;
|
||
|
|
}
|
||
|
|
.wclp-status-badge {
|
||
|
|
display: inline-flex;
|
||
|
|
align-items: center;
|
||
|
|
gap: 4px;
|
||
|
|
padding: 4px 10px;
|
||
|
|
border-radius: 12px;
|
||
|
|
font-size: 12px;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
.wclp-status-badge.active {
|
||
|
|
background: #d4edda;
|
||
|
|
color: #155724;
|
||
|
|
}
|
||
|
|
.wclp-status-badge.inactive {
|
||
|
|
background: #e2e3e5;
|
||
|
|
color: #383d41;
|
||
|
|
}
|
||
|
|
.wclp-status-badge.expired {
|
||
|
|
background: #f8d7da;
|
||
|
|
color: #721c24;
|
||
|
|
}
|
||
|
|
.wclp-status-badge.revoked {
|
||
|
|
background: #d6d8db;
|
||
|
|
color: #1b1e21;
|
||
|
|
}
|
||
|
|
.wclp-widget-footer {
|
||
|
|
margin-top: 16px;
|
||
|
|
padding-top: 12px;
|
||
|
|
border-top: 1px solid #e2e4e7;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
.wclp-widget-footer a {
|
||
|
|
text-decoration: none;
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
|
||
|
|
<div class="wclp-widget-stats">
|
||
|
|
<div class="wclp-stat-card highlight">
|
||
|
|
<div class="wclp-stat-number"><?php echo esc_html(number_format_i18n($stats['total'])); ?></div>
|
||
|
|
<div class="wclp-stat-label"><?php esc_html_e('Total Licenses', 'wc-licensed-product'); ?></div>
|
||
|
|
</div>
|
||
|
|
<div class="wclp-stat-card success">
|
||
|
|
<div class="wclp-stat-number"><?php echo esc_html(number_format_i18n($stats['by_status'][License::STATUS_ACTIVE])); ?></div>
|
||
|
|
<div class="wclp-stat-label"><?php esc_html_e('Active', 'wc-licensed-product'); ?></div>
|
||
|
|
</div>
|
||
|
|
<div class="wclp-stat-card warning">
|
||
|
|
<div class="wclp-stat-number"><?php echo esc_html(number_format_i18n($stats['expiring_soon'])); ?></div>
|
||
|
|
<div class="wclp-stat-label"><?php esc_html_e('Expiring Soon', 'wc-licensed-product'); ?></div>
|
||
|
|
</div>
|
||
|
|
<div class="wclp-stat-card danger">
|
||
|
|
<div class="wclp-stat-number"><?php echo esc_html(number_format_i18n($stats['by_status'][License::STATUS_EXPIRED])); ?></div>
|
||
|
|
<div class="wclp-stat-label"><?php esc_html_e('Expired', 'wc-licensed-product'); ?></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="wclp-widget-divider"></div>
|
||
|
|
|
||
|
|
<h4 style="margin: 0 0 8px 0; font-size: 13px; color: #1d2327;">
|
||
|
|
<?php esc_html_e('Status Breakdown', 'wc-licensed-product'); ?>
|
||
|
|
</h4>
|
||
|
|
<div class="wclp-status-list">
|
||
|
|
<span class="wclp-status-badge active">
|
||
|
|
<span class="dashicons dashicons-yes-alt" style="font-size: 14px; width: 14px; height: 14px;"></span>
|
||
|
|
<?php printf(
|
||
|
|
esc_html__('Active: %d', 'wc-licensed-product'),
|
||
|
|
$stats['by_status'][License::STATUS_ACTIVE]
|
||
|
|
); ?>
|
||
|
|
</span>
|
||
|
|
<span class="wclp-status-badge inactive">
|
||
|
|
<span class="dashicons dashicons-marker" style="font-size: 14px; width: 14px; height: 14px;"></span>
|
||
|
|
<?php printf(
|
||
|
|
esc_html__('Inactive: %d', 'wc-licensed-product'),
|
||
|
|
$stats['by_status'][License::STATUS_INACTIVE]
|
||
|
|
); ?>
|
||
|
|
</span>
|
||
|
|
<span class="wclp-status-badge expired">
|
||
|
|
<span class="dashicons dashicons-clock" style="font-size: 14px; width: 14px; height: 14px;"></span>
|
||
|
|
<?php printf(
|
||
|
|
esc_html__('Expired: %d', 'wc-licensed-product'),
|
||
|
|
$stats['by_status'][License::STATUS_EXPIRED]
|
||
|
|
); ?>
|
||
|
|
</span>
|
||
|
|
<span class="wclp-status-badge revoked">
|
||
|
|
<span class="dashicons dashicons-dismiss" style="font-size: 14px; width: 14px; height: 14px;"></span>
|
||
|
|
<?php printf(
|
||
|
|
esc_html__('Revoked: %d', 'wc-licensed-product'),
|
||
|
|
$stats['by_status'][License::STATUS_REVOKED]
|
||
|
|
); ?>
|
||
|
|
</span>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="wclp-widget-divider"></div>
|
||
|
|
|
||
|
|
<h4 style="margin: 0 0 8px 0; font-size: 13px; color: #1d2327;">
|
||
|
|
<?php esc_html_e('License Types', 'wc-licensed-product'); ?>
|
||
|
|
</h4>
|
||
|
|
<p style="margin: 0; font-size: 13px; color: #646970;">
|
||
|
|
<span class="dashicons dashicons-calendar-alt" style="font-size: 14px; width: 14px; height: 14px; vertical-align: text-bottom;"></span>
|
||
|
|
<?php printf(
|
||
|
|
esc_html__('Time-limited: %d', 'wc-licensed-product'),
|
||
|
|
$stats['expiring']
|
||
|
|
); ?>
|
||
|
|
|
|
||
|
|
<span class="dashicons dashicons-infinity" style="font-size: 14px; width: 14px; height: 14px; vertical-align: text-bottom;"></span>
|
||
|
|
<?php printf(
|
||
|
|
esc_html__('Lifetime: %d', 'wc-licensed-product'),
|
||
|
|
$stats['lifetime']
|
||
|
|
); ?>
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<div class="wclp-widget-footer">
|
||
|
|
<a href="<?php echo esc_url($licensesUrl); ?>" class="button button-secondary">
|
||
|
|
<?php esc_html_e('View All Licenses', 'wc-licensed-product'); ?>
|
||
|
|
</a>
|
||
|
|
</div>
|
||
|
|
<?php
|
||
|
|
}
|
||
|
|
}
|