| 1 |
<?php |
| 2 |
|
| 3 |
namespace FluentCart\App\Services\Report; |
| 4 |
|
| 5 |
use DateInterval; |
| 6 |
use DatePeriod; |
| 7 |
use FluentCart\App\App; |
| 8 |
use FluentCart\App\Services\Report\Concerns\CanParseAddressField; |
| 9 |
use FluentCart\App\Services\Report\Concerns\HasRange; |
| 10 |
use FluentCart\Framework\Database\Orm\Builder; |
| 11 |
use FluentCart\Framework\Support\DateTime; |
| 12 |
use FluentCartPro\App\Modules\Licensing\Models\License; |
| 13 |
|
| 14 |
class LicenseReportService extends ReportService |
| 15 |
{ |
| 16 |
use HasRange, CanParseAddressField; |
| 17 |
|
| 18 |
protected $summary = []; |
| 19 |
|
| 20 |
protected $forcedGroupKey = []; |
| 21 |
|
| 22 |
protected function modifyQuery(Builder $query): Builder |
| 23 |
{ |
| 24 |
return $query->with('product')->orderBy('created_at'); |
| 25 |
} |
| 26 |
|
| 27 |
public function getModel(): string |
| 28 |
{ |
| 29 |
if (!class_exists(License::class)) { |
| 30 |
throw new \Exception(__('The required plugin is not installed or the License class is missing.', 'fluent-cart')); |
| 31 |
} |
| 32 |
|
| 33 |
return License::class; |
| 34 |
} |
| 35 |
|
| 36 |
protected function prepareReportData(): void |
| 37 |
{ |
| 38 |
$this->data->each(function ($item) { |
| 39 |
|
| 40 |
}); |
| 41 |
} |
| 42 |
|
| 43 |
public function getLicenseLineChart($groupKey, $startDate, $endDate) |
| 44 |
{ |
| 45 |
global $wpdb; |
| 46 |
|
| 47 |
$startDate = new DateTime($startDate); |
| 48 |
$endDate = new DateTime($endDate); |
| 49 |
|
| 50 |
$this->forcedGroupKey = $groupKey; |
| 51 |
|
| 52 |
if (!$this->forcedGroupKey || $this->forcedGroupKey === 'default') { |
| 53 |
$groupKey = ReportHelper::defineGroupKey($startDate, $endDate); |
| 54 |
} |
| 55 |
|
| 56 |
switch ($groupKey) { |
| 57 |
case 'yearly': |
| 58 |
$dateFormat = "YEAR(created_at) AS year"; |
| 59 |
$groupBy = "YEAR(created_at)"; |
| 60 |
break; |
| 61 |
case 'monthly': |
| 62 |
$dateFormat = "YEAR(created_at) AS year, MONTH(created_at) AS month"; |
| 63 |
$groupBy = "YEAR(created_at), MONTH(created_at)"; |
| 64 |
break; |
| 65 |
default: |
| 66 |
$dateFormat = "DATE(created_at) AS date"; |
| 67 |
$groupBy = "DATE(created_at)"; |
| 68 |
break; |
| 69 |
} |
| 70 |
|
| 71 |
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching |
| 72 |
$results = $wpdb->get_results( |
| 73 |
$wpdb->prepare( |
| 74 |
"SELECT {$dateFormat}, COUNT(*) AS license_count FROM {$wpdb->prefix}fct_licenses WHERE created_at BETWEEN %s AND %s GROUP BY {$groupBy} ORDER BY {$groupBy}", |
| 75 |
$startDate->format('Y-m-d 00:00:00'), |
| 76 |
$endDate->format('Y-m-d 23:59:59') |
| 77 |
) |
| 78 |
); |
| 79 |
|
| 80 |
$lineChartData = []; |
| 81 |
|
| 82 |
if ($groupKey === 'yearly') { |
| 83 |
$yearMap = []; |
| 84 |
foreach ($results as $row) { |
| 85 |
$yearMap[$row->year] = (int)$row->license_count; |
| 86 |
} |
| 87 |
|
| 88 |
for ($y = (int)$startDate->format('Y'); $y <= (int)$endDate->format('Y'); $y++) { |
| 89 |
$lineChartData[] = [ |
| 90 |
'year' => $y, |
| 91 |
'license_count' => isset($yearMap[$y]) ? $yearMap[$y] : 0, |
| 92 |
]; |
| 93 |
} |
| 94 |
} elseif ($groupKey === 'monthly') { |
| 95 |
$monthMap = []; |
| 96 |
foreach ($results as $row) { |
| 97 |
$key = "{$row->year}-{$row->month}"; |
| 98 |
$monthMap[$key] = (int)$row->license_count; |
| 99 |
} |
| 100 |
|
| 101 |
$period = new DatePeriod($startDate, new DateInterval('P1M'), (clone $endDate)->modify('first day of next month')); |
| 102 |
foreach ($period as $date) { |
| 103 |
$year = $date->format('Y'); |
| 104 |
$month = $date->format('n'); |
| 105 |
$key = "{$year}-{$month}"; |
| 106 |
$lineChartData[] = [ |
| 107 |
'year' => (int)$year, |
| 108 |
'month' => (int)$month, |
| 109 |
'license_count' => isset($monthMap[$key]) ? $monthMap[$key] : 0, |
| 110 |
]; |
| 111 |
} |
| 112 |
} else { |
| 113 |
$dateMap = []; |
| 114 |
foreach ($results as $row) { |
| 115 |
$dateMap[$row->date] = (int)$row->license_count; |
| 116 |
} |
| 117 |
|
| 118 |
$period = new DatePeriod($startDate, new DateInterval('P1D'), $endDate->modify('+1 day')); |
| 119 |
foreach ($period as $date) { |
| 120 |
$formatted = $date->format('Y-m-d'); |
| 121 |
$lineChartData[] = [ |
| 122 |
'date' => $formatted, |
| 123 |
'license_count' => isset($dateMap[$formatted]) ? $dateMap[$formatted] : 0, |
| 124 |
]; |
| 125 |
} |
| 126 |
} |
| 127 |
|
| 128 |
return [ |
| 129 |
'lineChartData' => $lineChartData, |
| 130 |
]; |
| 131 |
} |
| 132 |
|
| 133 |
public function getLicensePieChart($startDate, $endDate): array |
| 134 |
{ |
| 135 |
|
| 136 |
$totalSubquery = App::db()->table('fct_licenses') |
| 137 |
->selectRaw('COUNT(*) AS total_activation_count') |
| 138 |
->where('status', '=', 'active'); |
| 139 |
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Static query with no variables |
| 140 |
$results = App::db()->table('fct_licenses as l') |
| 141 |
->selectRaw(' |
| 142 |
l.product_id, |
| 143 |
COALESCE(p.post_title, ?) AS post_title, |
| 144 |
COUNT(*) AS activation_count, |
| 145 |
ROUND(COUNT(*) * 100.0 / total.total_activation_count, 2) AS percentage |
| 146 |
', [__('Unknown Product', 'fluent-cart')]) |
| 147 |
->leftJoin('posts as p', 'p.ID', '=', 'l.product_id') |
| 148 |
->crossJoinSub($totalSubquery, 'total') |
| 149 |
->where('l.status', '=', 'active') |
| 150 |
->groupByRaw('l.product_id, p.post_title, total.total_activation_count') |
| 151 |
->orderByDesc('activation_count') |
| 152 |
->get() |
| 153 |
->toArray(); |
| 154 |
|
| 155 |
return [ |
| 156 |
'pieChartData' => $results |
| 157 |
]; |
| 158 |
|
| 159 |
} |
| 160 |
|
| 161 |
public function getSummary($startDate, $endDate): array |
| 162 |
{ |
| 163 |
|
| 164 |
$this->summary = [ |
| 165 |
'totalLicense' => App::db()->table('fct_licenses')->count(), |
| 166 |
'totalActiveLicense' => App::db()->table('fct_licenses')->where('status', 'active')->count(), |
| 167 |
'totalInactiveLicense' => App::db()->table('fct_licenses')->where('status', 'disabled')->count(), |
| 168 |
'totalExpiredLicense' => App::db()->table('fct_licenses')->where('status', 'expired')->count(), |
| 169 |
'totalActivatedSites' => App::db()->table('fct_licenses')->sum('activation_count'), |
| 170 |
'totalLicensedProducts' => App::db()->table('fct_product_meta') |
| 171 |
->where('meta_key', 'license_settings') |
| 172 |
->count('object_id'), |
| 173 |
]; |
| 174 |
return [ |
| 175 |
'summaryData' => $this->summary |
| 176 |
]; |
| 177 |
} |
| 178 |
|
| 179 |
|
| 180 |
} |
| 181 |
|