'precios-unitarios', * 'posts_per_page' => 6, * 'columns' => 3 * ]); * ``` * * @package ROITheme\Shared\Application\UseCases\RenderPostGrid */ final readonly class RenderPostGridRequest { public function __construct( public string $category = '', public string $excludeCategory = '', public string $tag = '', public string $author = '', public int $postsPerPage = 9, public int $columns = 3, public string $orderby = 'date', public string $order = 'DESC', public bool $showPagination = false, public int $offset = 0, public string $excludePosts = '', public bool $showThumbnail = true, public bool $showExcerpt = true, public bool $showMeta = true, public bool $showCategories = true, public int $excerptLength = 20, public string $class = '', public string $id = '', public int $paged = 1 ) {} /** * Factory method: Crear desde array de atributos del shortcode * * @param array $atts Atributos sanitizados del shortcode * @return self */ public static function fromArray(array $atts): self { return new self( category: (string) ($atts['category'] ?? ''), excludeCategory: (string) ($atts['exclude_category'] ?? ''), tag: (string) ($atts['tag'] ?? ''), author: (string) ($atts['author'] ?? ''), postsPerPage: self::clampInt((int) ($atts['posts_per_page'] ?? 9), 1, 50), columns: self::clampInt((int) ($atts['columns'] ?? 3), 1, 4), orderby: self::sanitizeOrderby((string) ($atts['orderby'] ?? 'date')), order: self::sanitizeOrder((string) ($atts['order'] ?? 'DESC')), showPagination: self::toBool($atts['show_pagination'] ?? false), offset: max(0, (int) ($atts['offset'] ?? 0)), excludePosts: (string) ($atts['exclude_posts'] ?? ''), showThumbnail: self::toBool($atts['show_thumbnail'] ?? true), showExcerpt: self::toBool($atts['show_excerpt'] ?? true), showMeta: self::toBool($atts['show_meta'] ?? true), showCategories: self::toBool($atts['show_categories'] ?? true), excerptLength: max(1, (int) ($atts['excerpt_length'] ?? 20)), class: (string) ($atts['class'] ?? ''), id: (string) ($atts['id'] ?? ''), paged: max(1, (int) ($atts['paged'] ?? 1)) ); } /** * Convertir a array de parametros para QueryBuilder * * @return array */ public function toQueryParams(): array { return [ 'category' => $this->category, 'exclude_category' => $this->excludeCategory, 'tag' => $this->tag, 'author' => $this->author, 'posts_per_page' => $this->postsPerPage, 'orderby' => $this->orderby, 'order' => $this->order, 'offset' => $this->offset, 'exclude_posts' => $this->excludePosts, 'paged' => $this->paged, ]; } /** * Convertir a array de opciones para Renderer * * @return array */ public function toRenderOptions(): array { return [ 'columns' => $this->columns, 'show_thumbnail' => $this->showThumbnail, 'show_excerpt' => $this->showExcerpt, 'show_meta' => $this->showMeta, 'show_categories' => $this->showCategories, 'excerpt_length' => $this->excerptLength, 'class' => $this->class, 'id' => $this->id, 'show_pagination' => $this->showPagination, 'posts_per_page' => $this->postsPerPage, ]; } private static function clampInt(int $value, int $min, int $max): int { return max($min, min($max, $value)); } private static function toBool(mixed $value): bool { if (is_bool($value)) { return $value; } return $value === 'true' || $value === '1' || $value === 1; } private static function sanitizeOrderby(string $value): string { $allowed = ['date', 'title', 'modified', 'rand', 'comment_count']; return in_array($value, $allowed, true) ? $value : 'date'; } private static function sanitizeOrder(string $value): string { $upper = strtoupper($value); return in_array($upper, ['ASC', 'DESC'], true) ? $upper : 'DESC'; } }