tableName = $this->wpdb->prefix . 'roi_theme_components'; } /** * Guardar componente * * INSERT si no existe, UPDATE si existe * * @param Component $component * @return Component Componente guardado (con timestamps actualizados) */ public function save(Component $component): Component { $componentName = $component->name()->value(); // Verificar si ya existe $existing = $this->findByName($componentName); $data = [ 'component_name' => $componentName, 'configuration' => json_encode($component->configuration()->toArray()), 'visibility' => json_encode($component->visibility()->toArray()), 'is_enabled' => $component->isEnabled() ? 1 : 0, 'schema_version' => $component->schemaVersion(), 'updated_at' => current_time('mysql') ]; if ($existing === null) { // INSERT $data['created_at'] = current_time('mysql'); $this->wpdb->insert( $this->tableName, $data, ['%s', '%s', '%s', '%d', '%s', '%s', '%s'] ); } else { // UPDATE $this->wpdb->update( $this->tableName, $data, ['component_name' => $componentName], ['%s', '%s', '%s', '%d', '%s', '%s'], ['%s'] ); } // Return the saved component by fetching it from the database return $this->getByName($component->name()); } /** * Buscar componente por nombre * * @param ComponentName $name Nombre del componente * @return Component|null Null si no existe */ public function findByName(ComponentName $name): ?Component { $sql = $this->wpdb->prepare( "SELECT * FROM {$this->tableName} WHERE component_name = %s LIMIT 1", $name->value() ); $row = $this->wpdb->get_row($sql, ARRAY_A); if ($row === null) { return null; } return $this->rowToEntity($row); } /** * Obtener componente por nombre (lanza excepción si no existe) * * @param ComponentName $name * @return Component * @throws ComponentNotFoundException */ public function getByName(ComponentName $name): Component { $component = $this->findByName($name); if ($component === null) { throw ComponentNotFoundException::withName($name->value()); } return $component; } /** * Obtener todos los componentes * * @return Component[] */ public function findAll(): array { $sql = "SELECT * FROM {$this->tableName} ORDER BY component_name ASC"; $rows = $this->wpdb->get_results($sql, ARRAY_A); if (empty($rows)) { return []; } return array_map( fn($row) => $this->rowToEntity($row), $rows ); } /** * Eliminar componente * * @param ComponentName $name Nombre del componente * @return bool True si eliminó exitosamente */ public function delete(ComponentName $name): bool { $result = $this->wpdb->delete( $this->tableName, ['component_name' => $name->value()], ['%s'] ); return $result !== false; } /** * Obtener componentes habilitados * * @return Component[] */ public function findEnabled(): array { $sql = "SELECT * FROM {$this->tableName} WHERE is_enabled = 1 ORDER BY component_name ASC"; $rows = $this->wpdb->get_results($sql, ARRAY_A); if (empty($rows)) { return []; } return array_map( fn($row) => $this->rowToEntity($row), $rows ); } /** * Verificar si existe un componente con el nombre dado * * @param ComponentName $name * @return bool */ public function exists(ComponentName $name): bool { return $this->findByName($name) !== null; } /** * Obtener cantidad total de componentes * * @return int */ public function count(): int { $sql = "SELECT COUNT(*) FROM {$this->tableName}"; return (int) $this->wpdb->get_var($sql); } /** * Obtener componentes por grupo de configuración * * @param string $group Grupo de configuración (visibility, content, styles, general) * @return Component[] */ public function findByConfigGroup(string $group): array { // For now, return all components as we don't have a specific column for groups // This would require additional schema design return $this->findAll(); } /** * Convertir fila de BD a Entity * * @param array $row Fila de la base de datos * @return Component */ private function rowToEntity(array $row): Component { // Decodificar JSON $configuration = json_decode($row['configuration'], true) ?? []; $visibility = json_decode($row['visibility'], true) ?? []; // Crear Value Objects $name = new ComponentName($row['component_name']); $config = ComponentConfiguration::fromArray($configuration); $vis = ComponentVisibility::fromArray($visibility); // Crear Entity return new Component( $name, $config, $vis, (bool) $row['is_enabled'], $row['schema_version'] ); } }