Files
michaelschiemer/src/Framework/Discovery/ValueObjects/TemplateCollection.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

349 lines
8.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Discovery\ValueObjects;
use App\Framework\Core\ValueObjects\Byte;
use App\Framework\Filesystem\ValueObjects\FilePath;
use ArrayIterator;
use Countable;
use IteratorAggregate;
/**
* Immutable collection of TemplateMapping value objects
*
* Provides type-safe operations for template collections with filtering,
* searching, and memory-efficient operations.
*/
final readonly class TemplateCollection implements Countable, IteratorAggregate
{
/** @var array<TemplateMapping> */
private array $templates;
public function __construct(TemplateMapping ...$templates)
{
$this->templates = array_values($templates);
}
/**
* Add a template to the collection
*/
public function add(TemplateMapping $template): self
{
$templates = $this->templates;
$templates[] = $template;
return new self(...$templates);
}
/**
* Add multiple templates to the collection
*/
public function addMany(TemplateMapping ...$templates): self
{
return new self(...array_merge($this->templates, $templates));
}
/**
* Filter templates by name pattern
*/
public function filterByName(string $namePattern): self
{
$filtered = array_filter(
$this->templates,
fn (TemplateMapping $template) => $template->matchesName($namePattern)
);
return new self(...$filtered);
}
/**
* Filter templates by type
*/
public function filterByType(string $type): self
{
$filtered = array_filter(
$this->templates,
fn (TemplateMapping $template) => $template->isType($type)
);
return new self(...$filtered);
}
/**
* Filter templates by directory
*/
public function filterByDirectory(string $directory): self
{
$normalizedDirectory = rtrim($directory, '/');
$filtered = array_filter(
$this->templates,
fn (TemplateMapping $template) => dirname($template->path->toString()) === $normalizedDirectory
);
return new self(...$filtered);
}
/**
* Filter templates by extension
*/
public function filterByExtension(string $extension): self
{
$extension = ltrim($extension, '.');
$filtered = array_filter(
$this->templates,
fn (TemplateMapping $template) => $template->getExtension() === $extension
);
return new self(...$filtered);
}
/**
* Find template by exact name and type
*/
public function findExact(string $name, string $type = 'view'): ?TemplateMapping
{
foreach ($this->templates as $template) {
if ($template->name === $name && $template->type === $type) {
return $template;
}
}
return null;
}
/**
* Find template by name (any type)
*/
public function findByName(string $name): ?TemplateMapping
{
foreach ($this->templates as $template) {
if ($template->name === $name) {
return $template;
}
}
return null;
}
/**
* Find template by file path
*/
public function findByPath(FilePath $path): ?TemplateMapping
{
foreach ($this->templates as $template) {
if ($template->path->equals($path)) {
return $template;
}
}
return null;
}
/**
* Get templates grouped by type
* @return array<string, self>
*/
public function groupByType(): array
{
$grouped = [];
foreach ($this->templates as $template) {
if (! isset($grouped[$template->type])) {
$grouped[$template->type] = [];
}
$grouped[$template->type][] = $template;
}
return array_map(
fn (array $templates) => new self(...$templates),
$grouped
);
}
/**
* Get templates grouped by directory
* @return array<string, self>
*/
public function groupByDirectory(): array
{
$grouped = [];
foreach ($this->templates as $template) {
$directory = dirname($template->path->toString());
if (! isset($grouped[$directory])) {
$grouped[$directory] = [];
}
$grouped[$directory][] = $template;
}
return array_map(
fn (array $templates) => new self(...$templates),
$grouped
);
}
/**
* Get unique template names
* @return array<int, string>
*/
public function getUniqueNames(): array
{
$names = array_map(fn (TemplateMapping $template) => $template->name, $this->templates);
return array_unique($names);
}
/**
* Get unique template types
* @return array<int, string>
*/
public function getUniqueTypes(): array
{
$types = array_map(fn (TemplateMapping $template) => $template->type, $this->templates);
return array_unique($types);
}
/**
* Get unique directories
*/
public function getUniqueDirectories(): array
{
$directories = array_map(
fn (TemplateMapping $template) => dirname($template->path->toString()),
$this->templates
);
return array_unique($directories);
}
/**
* Remove duplicate templates based on unique identifier
*/
public function deduplicate(): self
{
$seen = [];
$unique = [];
foreach ($this->templates as $template) {
$key = $template->getUniqueId();
if (! isset($seen[$key])) {
$seen[$key] = true;
$unique[] = $template;
}
}
return new self(...$unique);
}
/**
* Sort templates by name
*/
public function sortedByName(): self
{
$sorted = $this->templates;
usort($sorted, fn (TemplateMapping $a, TemplateMapping $b) => $a->name <=> $b->name);
return new self(...$sorted);
}
/**
* Sort templates by type, then by name
*/
public function sortedByTypeAndName(): self
{
$sorted = $this->templates;
usort($sorted, function (TemplateMapping $a, TemplateMapping $b) {
$typeComparison = $a->type <=> $b->type;
return $typeComparison !== 0 ? $typeComparison : $a->name <=> $b->name;
});
return new self(...$sorted);
}
/**
* Check if collection is empty
*/
public function isEmpty(): bool
{
return empty($this->templates);
}
/**
* Get first template or null
*/
public function first(): ?TemplateMapping
{
return $this->templates[0] ?? null;
}
/**
* Get last template or null
*/
public function last(): ?TemplateMapping
{
return end($this->templates) ?: null;
}
/**
* Convert to array of TemplateMapping objects
*/
public function toArray(): array
{
return $this->templates;
}
/**
* Convert to legacy array format for backward compatibility
*/
public function toLegacyArray(): array
{
$legacy = [];
foreach ($this->templates as $template) {
// Group by template name with variants by type
if (! isset($legacy[$template->name])) {
$legacy[$template->name] = [];
}
$legacy[$template->name][$template->type] = $template->path->toString();
}
return $legacy;
}
/**
* Get memory footprint of entire collection
*/
public function getMemoryFootprint(): Byte
{
$totalBytes = 0;
foreach ($this->templates as $template) {
$totalBytes += $template->getMemoryFootprint()->toBytes();
}
// Add overhead for collection structure
$totalBytes += count($this->templates) * 8; // approximate pointer overhead
return Byte::fromBytes($totalBytes);
}
// Countable interface implementation
public function count(): int
{
return count($this->templates);
}
// IteratorAggregate interface implementation
public function getIterator(): ArrayIterator
{
return new ArrayIterator($this->templates);
}
}