<?php declare(strict_types=1); namespace Arcanedev\Html; use Arcanedev\Html\Contracts\Html as HtmlContract; use Arcanedev\Html\Elements\A; use Arcanedev\Html\Elements\Button; use Arcanedev\Html\Elements\Div; use Arcanedev\Html\Elements\Dl; use Arcanedev\Html\Elements\Element; use Arcanedev\Html\Elements\Fieldset; use Arcanedev\Html\Elements\File; use Arcanedev\Html\Elements\Form; use Arcanedev\Html\Elements\I; use Arcanedev\Html\Elements\Img; use Arcanedev\Html\Elements\Input; use Arcanedev\Html\Elements\Label; use Arcanedev\Html\Elements\Legend; use Arcanedev\Html\Elements\Option; use Arcanedev\Html\Elements\Select; use Arcanedev\Html\Elements\Span; use Arcanedev\Html\Elements\Textarea; use Arcanedev\Html\Elements\Ul; use Arcanedev\Html\Entities\Attributes\ClassAttribute; use DateTimeImmutable; use Illuminate\Support\Str; /** * Class Html * * @author ARCANEDEV <arcanedev.maroc@gmail.com> */ class Html implements HtmlContract { /* ----------------------------------------------------------------- | Constants | ----------------------------------------------------------------- */ const HTML_DATE_FORMAT = 'Y-m-d'; const HTML_TIME_FORMAT = 'H:i:s'; /* ----------------------------------------------------------------- | Main Methods | ----------------------------------------------------------------- */ /** * Make an `a` tag. * * @param string|null $href * @param string|null $value * * @return \Arcanedev\Html\Elements\A */ public function a($href = null, $value = null) { return A::make() ->attributeIfNotNull($href, 'href', $href) ->html($value); } /** * Make a `button` tag. * * @param string|null $content * @param string|null $type * * @return \Arcanedev\Html\Elements\Button */ public function button($content = null, $type = null) { return Button::make() ->attributeIfNotNull($type, 'type', $type) ->html($content); } /** * Make a checkbox input. * * @param string|null $name * @param bool|null $checked * @param string|null $value * * @return \Arcanedev\Html\Elements\Input */ public function checkbox($name = null, $checked = null, $value = '1') { return Input::make() ->attribute('type', 'checkbox') ->attributeIfNotNull($name, 'name', $name) ->attributeIfNotNull($name, 'id', $name) ->attributeIfNotNull($value, 'value', $value) ->attributeIf((bool) $checked, 'checked'); } /** * Parse and render `class` attribute. * * @param iterable|string $classes * * @return string */ public function class($classes): string { return ClassAttribute::make($classes)->render(); } /** * Make a date input. * * @param string|null $name * @param string|null $value * @param bool $format * * @return \Arcanedev\Html\Elements\Input */ public function date($name = null, $value = null, bool $format = true) { $input = $this->input('date', $name, $value); if ( ! $format || ! $input->hasAttribute('value') || empty($value = $input->getAttribute('value')->value()) ) { return $input; } return $input->value(static::formatDateTime($value, static::HTML_DATE_FORMAT));; } /** * Make a datetime input. * * @param string|null $name * @param string|null $value * @param bool $format * * @return \Arcanedev\Html\Elements\Input */ public function datetime($name = null, $value = null, $format = true) { $input = $this->input('datetime-local', $name, $value); if ( ! $format || ! $input->hasAttribute('value') || empty($value = $input->getAttribute('value')->value()) ) { return $input; } return $input->value( $this->formatDateTime($value, static::HTML_DATE_FORMAT.'\T'.static::HTML_TIME_FORMAT) ); } /** * Make a div element. * * @param \Arcanedev\Html\Elements\HtmlElement|string|null $content * * @return \Arcanedev\Html\Elements\Div */ public function div($content = null) { return Div::make()->addChild($content); } /** * Make a custom tag element. * * @param string $tag * * @return \Arcanedev\Html\Elements\Element */ public function element($tag) { return Element::withTag($tag); } /** * Make an email input. * * @param string|null $name * @param string|null $value * * @return \Arcanedev\Html\Elements\Input */ public function email($name = null, $value = null) { return $this->input('email', $name, $value); } /** * Make a fieldset tag. * * @param \Arcanedev\Html\Elements\HtmlElement|string|null $legend * * @return \Arcanedev\Html\Elements\Fieldset */ public function fieldset($legend = null) { return is_null($legend) ? Fieldset::make() : Fieldset::make()->legend($legend); } /** * Make a file input. * * @param string|null $name * * @return \Arcanedev\Html\Elements\File */ public function file($name = null) { return File::make() ->attributeIfNotNull($name, 'name', $name) ->attributeIfNotNull($name, 'id', $name); } /** * Make a form input. * * @param string $method * @param string|null $action * * @return \Arcanedev\Html\Elements\Form */ public function form($method = 'POST', $action = null) { return Form::make() ->method($method) ->attributeIfNotNull($action, 'action', $action); } /** * Make a hidden input. * * @param string|null $name * @param string|null $value * * @return \Arcanedev\Html\Elements\Input */ public function hidden($name = null, $value = null) { return $this->input('hidden', $name, $value); } /** * Make an i tag. * * @param string|null $content * * @return \Arcanedev\Html\Elements\I */ public function i($content = null) { return I::make()->html($content); } /** * Make an input tag. * * @param string|null $type * @param string|null $name * @param string|null $value * * @return \Arcanedev\Html\Elements\Input */ public function input($type = null, $name = null, $value = null) { $hasValue = $name && ! is_null($value) && $type !== 'password'; return Input::make() ->attributeIfNotNull($type, 'type', $type) ->attributeIfNotNull($name, 'name', $name) ->attributeIfNotNull($name, 'id', $name) ->attributeIf($hasValue, 'value', $value); } /** * Make an image tag. * * @param string|null $src * @param string|null $alt * * @return \Arcanedev\Html\Elements\Img */ public function img($src = null, $alt = null) { return Img::make() ->attributeIfNotNull($src, 'src', $src) ->attributeIfNotNull($alt, 'alt', $alt); } /** * Make a label tag. * * @param \Arcanedev\Html\Elements\HtmlElement|iterable|string|null $content * @param string|null $for * * @return \Arcanedev\Html\Elements\Label */ public function label($content = null, $for = null) { return Label::make() ->attributeIfNotNull($for, 'for', $for) ->children($content); } /** * Make a legend tag. * * @param \Arcanedev\Html\Elements\HtmlElement|string|null $content * * @return \Arcanedev\Html\Elements\Legend */ public function legend($content = null) { return Legend::make()->html($content); } /** * Make a mailto link. * * @param string $email * @param string|null $content * * @return \Arcanedev\Html\Elements\A */ public function mailto($email, $content = null) { return $this->a("mailto:{$email}", $content ?: $email); } /** * Make an option tag. * * @param string|null $text * @param string|null $value * @param bool $selected * * @return \Arcanedev\Html\Elements\Option */ public function option($text = null, $value = null, $selected = false) { return Option::make() ->text($text) ->value($value) ->selectedIf($selected); } /** * Make a password input. * * @param string|null $name * * @return \Arcanedev\Html\Elements\Input */ public function password($name = null) { return $this->input('password', $name); } /** * Make a radio input. * * @param string|null $name * @param bool|null $checked * @param string|null $value * * @return \Arcanedev\Html\Elements\Input */ public function radio($name = null, $checked = null, $value = null) { return $this->input('radio', $name, $value) ->attributeIfNotNull($name, 'id', $value === null ? $name : ($name.'_'.Str::slug($value))) ->attributeIf(( ! is_null($value)) || $checked, 'checked'); } /** * Make a range input. * * @param string|null $name * @param string|null $value * @param string|null $min * @param string|null $max * @param string|null $step * * @return \Arcanedev\Html\Elements\Input */ public function range($name = null, $value = null, $min = null, $max = null, $step = null) { return $this->input('range', $name, $value) ->attributeIfNotNull($min, 'min', $min) ->attributeIfNotNull($max, 'max', $max) ->attributeIfNotNull($step, 'step', $step); } /** * Make a reset button. * * @param string|null $text * * @return \Arcanedev\Html\Elements\Button */ public function reset($text = null) { return $this->button($text, 'reset'); } /** * Make a select tag. * * @param string|null $name * @param array|iterable $options * @param string|iterable|null $value * * @return \Arcanedev\Html\Elements\Select */ public function select($name = null, $options = [], $value = null) { return Select::make() ->attributeIfNotNull($name, 'name', $name) ->attributeIfNotNull($name, 'id', $name) ->options($options) ->value($value); } /** * Make a span tag. * * @param \Arcanedev\Html\Elements\HtmlElement|string|null $content * * @return \Arcanedev\Html\Elements\Span */ public function span($content = null) { return Span::make()->children($content); } /** * Make a submit button. * * @param string|null $text * * @return \Arcanedev\Html\Elements\Button */ public function submit($text = null) { return $this->button($text, 'submit'); } /** * Make a tel link. * * @param string $phoneNumber * @param string|null $text * * @return \Arcanedev\Html\Elements\A */ public function telLink($phoneNumber, $text = null) { return $this->a("tel:{$phoneNumber}", $text ?: $phoneNumber); } /** * Make a text input. * * @param string $name * @param string|null $value * * @return \Arcanedev\Html\Elements\Input */ public function text($name, $value = null) { return $this->input('text', $name, $value); } /** * Make a textarea tag. * * @param string|null $name * @param string|null $value * * @return \Arcanedev\Html\Elements\Textarea */ public function textarea($name = null, $value = null) { return Textarea::make() ->attributeIfNotNull($name, 'name', $name) ->attributeIfNotNull($name, 'id', $name) ->value($value); } /** * Make a time input. * * @param string|null $name * @param string|null $value * @param bool $format * * @return \Arcanedev\Html\Elements\Input */ public function time($name = null, $value = null, $format = true) { $input = $this->input('time', $name, $value); return $format && $input->hasAttribute('value') && ! empty($value = $input->getAttribute('value')->value()) ? $input->value(static::formatDateTime($value, self::HTML_TIME_FORMAT)) : $input; } /** * Make a number input. * * @param string|null $name * @param string|null $value * @param string|float|int|null $min * @param string|float|int|null $max * @param string|float|int|null $step * * @return \Arcanedev\Html\Elements\Input */ public function number($name = null, $value = null, $min = null, $max = null, $step = null) { return $this->input('number', $name, $value) ->attributeIfNotNull($min, 'min', $min) ->attributeIfNotNull($max, 'max', $max) ->attributeIfNotNull($step, 'step', $step); } /** * Make an ordered list. * * @param array $attributes * * @return \Arcanedev\Html\Elements\Ol */ public function ol(array $attributes = []) { return Elements\Ol::make()->attributes($attributes); } /** * Make an unordered list. * * @param array $attributes * * @return \Arcanedev\Html\Elements\Ul */ public function ul(array $attributes = []) { return Ul::make()->attributes($attributes); } /** * Make a description list. * * @param array $attributes * * @return \Arcanedev\Html\Elements\Dl */ public function dl(array $attributes = []) { return Dl::make()->attributes($attributes); } /* ----------------------------------------------------------------- | Other Methods | ----------------------------------------------------------------- */ /** * Format the date/time value. * * @param string $value * @param string $format * * @return string */ protected static function formatDateTime(string $value, string $format): string { try { if ( ! empty($value)) $value = (new DateTimeImmutable($value))->format($format); } catch (\Exception $e) { // Do nothing... } return $value; } }