tag = new HtmlTag(TagName::DIV); $classes = ['card', "card--{$this->variant}"]; $this->attributes = HtmlAttributes::empty() ->withClass(implode(' ', $classes)); foreach ($this->additionalAttributes->attributes as $name => $value) { $this->attributes = $this->attributes->with($name, $value); } $this->content = $this->buildContent($bodyContent); } public static function create(string $bodyContent): self { return new self(bodyContent: $bodyContent); } public static function withTitle(string $title, string $bodyContent): self { return new self(bodyContent: $bodyContent, title: $title); } public static function withImage(string $imageSrc, string $bodyContent, ?string $imageAlt = null): self { return new self(bodyContent: $bodyContent, imageSrc: $imageSrc, imageAlt: $imageAlt); } public function withSubtitle(string $subtitle): self { // Note: Can't access bodyContent from constructor, need to rebuild from content return new self( bodyContent: '', // Will be rebuilt in buildContent title: $this->title, subtitle: $subtitle, footer: $this->footer, imageSrc: $this->imageSrc, imageAlt: $this->imageAlt, variant: $this->variant, additionalAttributes: $this->additionalAttributes ); } public function withFooter(string|HtmlElement $footer): self { return new self( bodyContent: '', // Will be rebuilt in buildContent title: $this->title, subtitle: $this->subtitle, footer: (string) $footer, imageSrc: $this->imageSrc, imageAlt: $this->imageAlt, variant: $this->variant, additionalAttributes: $this->additionalAttributes ); } public function withVariant(string $variant): self { return new self( bodyContent: '', // Will be rebuilt in buildContent title: $this->title, subtitle: $this->subtitle, footer: $this->footer, imageSrc: $this->imageSrc, imageAlt: $this->imageAlt, variant: $variant, additionalAttributes: $this->additionalAttributes ); } private function buildContent(string $bodyContent): string { $elements = []; // Image if ($this->imageSrc !== null) { $imgAttrs = HtmlAttributes::empty() ->with('src', $this->imageSrc) ->withClass('card__image'); if ($this->imageAlt !== null) { $imgAttrs = $imgAttrs->with('alt', $this->imageAlt); } $elements[] = StandardHtmlElement::create(TagName::IMG, $imgAttrs); } // Header (title + subtitle) if ($this->title !== null || $this->subtitle !== null) { $headerElements = []; if ($this->title !== null) { $headerElements[] = StandardHtmlElement::create( TagName::H3, HtmlAttributes::empty()->withClass('card__title'), $this->title ); } if ($this->subtitle !== null) { $headerElements[] = StandardHtmlElement::create( TagName::P, HtmlAttributes::empty()->withClass('card__subtitle'), $this->subtitle ); } $elements[] = StandardHtmlElement::create( TagName::DIV, HtmlAttributes::empty()->withClass('card__header'), implode('', array_map('strval', $headerElements)) ); } // Body $elements[] = StandardHtmlElement::create( TagName::DIV, HtmlAttributes::empty()->withClass('card__body'), $bodyContent ); // Footer if ($this->footer !== null) { $elements[] = StandardHtmlElement::create( TagName::DIV, HtmlAttributes::empty()->withClass('card__footer'), $this->footer ); } return implode('', array_map('strval', $elements)); } public function __toString(): string { return (string) StandardHtmlElement::create( $this->tag->name, $this->attributes, $this->content ); } }