- Move 12 markdown files from root to docs/ subdirectories - Organize documentation by category: • docs/troubleshooting/ (1 file) - Technical troubleshooting guides • docs/deployment/ (4 files) - Deployment and security documentation • docs/guides/ (3 files) - Feature-specific guides • docs/planning/ (4 files) - Planning and improvement proposals Root directory cleanup: - Reduced from 16 to 4 markdown files in root - Only essential project files remain: • CLAUDE.md (AI instructions) • README.md (Main project readme) • CLEANUP_PLAN.md (Current cleanup plan) • SRC_STRUCTURE_IMPROVEMENTS.md (Structure improvements) This improves: ✅ Documentation discoverability ✅ Logical organization by purpose ✅ Clean root directory ✅ Better maintainability
106 lines
2.9 KiB
PHP
106 lines
2.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Application\Analytics\ValueObject;
|
|
|
|
use App\Framework\Core\ValueObjects\Percentage;
|
|
use App\Framework\Exception\ErrorCode;
|
|
use App\Framework\Exception\FrameworkException;
|
|
|
|
/**
|
|
* Browser usage breakdown for analytics reporting
|
|
*/
|
|
final readonly class BrowserBreakdown
|
|
{
|
|
public function __construct(
|
|
public int $chrome,
|
|
public int $firefox,
|
|
public int $safari,
|
|
public int $edge,
|
|
) {
|
|
if ($chrome < 0 || $firefox < 0 || $safari < 0 || $edge < 0) {
|
|
throw FrameworkException::create(
|
|
ErrorCode::VAL_BUSINESS_RULE_VIOLATION,
|
|
'Browser counts cannot be negative'
|
|
)->withData([
|
|
'chrome' => $chrome,
|
|
'firefox' => $firefox,
|
|
'safari' => $safari,
|
|
'edge' => $edge,
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create from legacy array format: ['Chrome' => 65, 'Firefox' => 20, ...]
|
|
* @param array<string, int> $data
|
|
*/
|
|
public static function fromArray(array $data): self
|
|
{
|
|
return new self(
|
|
chrome: $data['Chrome'] ?? 0,
|
|
firefox: $data['Firefox'] ?? 0,
|
|
safari: $data['Safari'] ?? 0,
|
|
edge: $data['Edge'] ?? 0,
|
|
);
|
|
}
|
|
|
|
public function getTotal(): int
|
|
{
|
|
return $this->chrome + $this->firefox + $this->safari + $this->edge;
|
|
}
|
|
|
|
public function getChromePercentage(): Percentage
|
|
{
|
|
return Percentage::fromRatio($this->chrome, $this->getTotal());
|
|
}
|
|
|
|
public function getFirefoxPercentage(): Percentage
|
|
{
|
|
return Percentage::fromRatio($this->firefox, $this->getTotal());
|
|
}
|
|
|
|
public function getSafariPercentage(): Percentage
|
|
{
|
|
return Percentage::fromRatio($this->safari, $this->getTotal());
|
|
}
|
|
|
|
public function getEdgePercentage(): Percentage
|
|
{
|
|
return Percentage::fromRatio($this->edge, $this->getTotal());
|
|
}
|
|
|
|
/**
|
|
* @return array<string, int>
|
|
*/
|
|
public function toArray(): array
|
|
{
|
|
return [
|
|
'Chrome' => $this->chrome,
|
|
'Firefox' => $this->firefox,
|
|
'Safari' => $this->safari,
|
|
'Edge' => $this->edge,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Legacy format for backward compatibility
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function toAnalyticsArray(): array
|
|
{
|
|
return [
|
|
'Chrome' => $this->chrome,
|
|
'Firefox' => $this->firefox,
|
|
'Safari' => $this->safari,
|
|
'Edge' => $this->edge,
|
|
'chrome_percentage' => $this->getChromePercentage()->format(),
|
|
'firefox_percentage' => $this->getFirefoxPercentage()->format(),
|
|
'safari_percentage' => $this->getSafariPercentage()->format(),
|
|
'edge_percentage' => $this->getEdgePercentage()->format(),
|
|
'total' => $this->getTotal(),
|
|
];
|
|
}
|
|
}
|