4 Commits

Author SHA1 Message Date
FrankZamora
bf304f08fc fix(css): centrar verticalmente contenido del hero section
Agrega propiedades flexbox al contenedor .hero-section para que el
contenido (título y badges) se muestre centrado verticalmente cuando
no hay badges de categorías.

Cambios:
- display: flex
- align-items: center
- justify-content: center

También incluye specs OpenSpec para arquitectura del tema.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 14:44:50 -06:00
FrankZamora
30b30b065b feat: add OpenSpec slash commands for Claude Code
- Remove .claude/ from .gitignore to share commands with team
- Add /openspec:proposal command for creating change proposals
- Add /openspec:apply command for implementing changes
- Add /openspec:archive command for archiving completed changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 12:59:05 -06:00
FrankZamora
b2d5cdfb57 feat: install and configure OpenSpec for spec-driven development
- Add openspec/ directory with AGENTS.md and project.md
- Add root AGENTS.md stub for AI assistants
- Create Claude Code slash commands:
  - /openspec:proposal - Create change proposals
  - /openspec:apply - Implement changes
  - /openspec:archive - Archive completed changes
- Configure project.md with ROI Theme conventions and architecture

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 12:57:08 -06:00
FrankZamora
b40e5b671a chore: backup before OpenSpec installation 2025-12-05 12:51:08 -06:00
17 changed files with 3164 additions and 4 deletions

View File

@@ -0,0 +1,17 @@
Implement the OpenSpec change: $ARGUMENTS
**Guardrails**
- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
- Keep changes tightly scoped to the requested outcome.
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
**Steps**
Track these steps as TODOs and complete them one by one.
1. Read `changes/<id>/proposal.md`, `design.md` (if present), and `tasks.md` to confirm scope and acceptance criteria.
2. Work through tasks sequentially, keeping edits minimal and focused on the requested change.
3. Confirm completion before updating statuses—make sure every item in `tasks.md` is finished.
4. Update the checklist after all work is done so each task is marked `- [x]` and reflects reality.
5. Reference `openspec list` or `openspec show <item>` when additional context is required.
**Reference**
- Use `openspec show <id> --json --deltas-only` if you need additional context from the proposal while implementing.

View File

@@ -0,0 +1,21 @@
Archive the completed OpenSpec change: $ARGUMENTS
**Guardrails**
- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
- Keep changes tightly scoped to the requested outcome.
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
**Steps**
1. Determine the change ID to archive:
- If this prompt already includes a specific change ID (for example inside a `<ChangeId>` block populated by slash-command arguments), use that value after trimming whitespace.
- If the conversation references a change loosely (for example by title or summary), run `openspec list` to surface likely IDs, share the relevant candidates, and confirm which one the user intends.
- Otherwise, review the conversation, run `openspec list`, and ask the user which change to archive; wait for a confirmed change ID before proceeding.
- If you still cannot identify a single change ID, stop and tell the user you cannot archive anything yet.
2. Validate the change ID by running `openspec list` (or `openspec show <id>`) and stop if the change is missing, already archived, or otherwise not ready to archive.
3. Run `openspec archive <id> --yes` so the CLI moves the change and applies spec updates without prompts (use `--skip-specs` only for tooling-only work).
4. Review the command output to confirm the target specs were updated and the change landed in `changes/archive/`.
5. Validate with `openspec validate --strict` and inspect with `openspec show <id>` if anything looks off.
**Reference**
- Use `openspec list` to confirm change IDs before archiving.
- Inspect refreshed specs with `openspec list --specs` and address any validation issues before handing off.

View File

@@ -0,0 +1,22 @@
Create an OpenSpec change proposal for: $ARGUMENTS
**Guardrails**
- Favor straightforward, minimal implementations first and add complexity only when it is requested or clearly required.
- Keep changes tightly scoped to the requested outcome.
- Refer to `openspec/AGENTS.md` (located inside the `openspec/` directory—run `ls openspec` or `openspec update` if you don't see it) if you need additional OpenSpec conventions or clarifications.
- Identify any vague or ambiguous details and ask the necessary follow-up questions before editing files.
- Do not write any code during the proposal stage. Only create design documents (proposal.md, tasks.md, design.md, and spec deltas). Implementation happens in the apply stage after approval.
**Steps**
1. Review `openspec/project.md`, run `openspec list` and `openspec list --specs`, and inspect related code or docs (e.g., via `rg`/`ls`) to ground the proposal in current behaviour; note any gaps that require clarification.
2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, and `design.md` (when needed) under `openspec/changes/<id>/`.
3. Map the change into concrete capabilities or requirements, breaking multi-scope efforts into distinct spec deltas with clear relationships and sequencing.
4. Capture architectural reasoning in `design.md` when the solution spans multiple systems, introduces new patterns, or demands trade-off discussion before committing to specs.
5. Draft spec deltas in `changes/<id>/specs/<capability>/spec.md` (one folder per capability) using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement and cross-reference related capabilities when relevant.
6. Draft `tasks.md` as an ordered list of small, verifiable work items that deliver user-visible progress, include validation (tests, tooling), and highlight dependencies or parallelizable work.
7. Validate with `openspec validate <id> --strict` and resolve every issue before sharing the proposal.
**Reference**
- Use `openspec show <id> --json --deltas-only` or `openspec show <spec> --type spec` to inspect details when validation fails.
- Search existing requirements with `rg -n "Requirement:|Scenario:" openspec/specs` before writing new ones.
- Explore the codebase with `rg <keyword>`, `ls`, or direct file reads so proposals align with current implementation realities.

43
.commitlintrc.json Normal file
View File

@@ -0,0 +1,43 @@
{
"extends": ["@commitlint/config-conventional"],
"rules": {
"type-enum": [
2,
"always",
[
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"build",
"ci",
"chore",
"revert"
]
],
"scope-enum": [
2,
"always",
[
"theme",
"templates",
"assets",
"css",
"js",
"php",
"admin",
"api",
"schema",
"seo",
"config",
"deps"
]
],
"subject-case": [2, "always", "lower-case"],
"subject-max-length": [2, "always", 72],
"body-max-line-length": [2, "always", 72]
}
}

1
.gitignore vendored
View File

@@ -73,5 +73,4 @@ _testing-suite/
# Claude Code tools # Claude Code tools
.playwright-mcp/ .playwright-mcp/
.serena/ .serena/
.claude/
nul nul

1
.husky/commit-msg Normal file
View File

@@ -0,0 +1 @@
npx --no -- commitlint --edit $1

1
.husky/pre-commit Normal file
View File

@@ -0,0 +1 @@
npm test

18
AGENTS.md Normal file
View File

@@ -0,0 +1,18 @@
<!-- OPENSPEC:START -->
# OpenSpec Instructions
These instructions are for AI assistants working in this project.
Always open `@/openspec/AGENTS.md` when the request:
- Mentions planning or proposals (words like proposal, spec, change, plan)
- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
- Sounds ambiguous and you need the authoritative spec before coding
Use `@/openspec/AGENTS.md` to learn:
- How to create and apply change proposals
- Spec format and conventions
- Project structure and guidelines
Keep this managed block so 'openspec update' can refresh the instructions.
<!-- OPENSPEC:END -->

View File

@@ -133,6 +133,9 @@ final class HeroRenderer implements RendererInterface
'padding' => "{$paddingVertical} 0", 'padding' => "{$paddingVertical} 0",
'margin-bottom' => $marginBottom, 'margin-bottom' => $marginBottom,
'min-height' => $minHeight, 'min-height' => $minHeight,
'display' => 'flex',
'align-items' => 'center',
'justify-content' => 'center',
]); ]);
$cssRules[] = $this->cssGenerator->generate('.hero-section__title', [ $cssRules[] = $this->cssGenerator->generate('.hero-section__title', [

456
openspec/AGENTS.md Normal file
View File

@@ -0,0 +1,456 @@
# OpenSpec Instructions
Instructions for AI coding assistants using OpenSpec for spec-driven development.
## TL;DR Quick Checklist
- Search existing work: `openspec spec list --long`, `openspec list` (use `rg` only for full-text search)
- Decide scope: new capability vs modify existing capability
- Pick a unique `change-id`: kebab-case, verb-led (`add-`, `update-`, `remove-`, `refactor-`)
- Scaffold: `proposal.md`, `tasks.md`, `design.md` (only if needed), and delta specs per affected capability
- Write deltas: use `## ADDED|MODIFIED|REMOVED|RENAMED Requirements`; include at least one `#### Scenario:` per requirement
- Validate: `openspec validate [change-id] --strict` and fix issues
- Request approval: Do not start implementation until proposal is approved
## Three-Stage Workflow
### Stage 1: Creating Changes
Create proposal when you need to:
- Add features or functionality
- Make breaking changes (API, schema)
- Change architecture or patterns
- Optimize performance (changes behavior)
- Update security patterns
Triggers (examples):
- "Help me create a change proposal"
- "Help me plan a change"
- "Help me create a proposal"
- "I want to create a spec proposal"
- "I want to create a spec"
Loose matching guidance:
- Contains one of: `proposal`, `change`, `spec`
- With one of: `create`, `plan`, `make`, `start`, `help`
Skip proposal for:
- Bug fixes (restore intended behavior)
- Typos, formatting, comments
- Dependency updates (non-breaking)
- Configuration changes
- Tests for existing behavior
**Workflow**
1. Review `openspec/project.md`, `openspec list`, and `openspec list --specs` to understand current context.
2. Choose a unique verb-led `change-id` and scaffold `proposal.md`, `tasks.md`, optional `design.md`, and spec deltas under `openspec/changes/<id>/`.
3. Draft spec deltas using `## ADDED|MODIFIED|REMOVED Requirements` with at least one `#### Scenario:` per requirement.
4. Run `openspec validate <id> --strict` and resolve any issues before sharing the proposal.
### Stage 2: Implementing Changes
Track these steps as TODOs and complete them one by one.
1. **Read proposal.md** - Understand what's being built
2. **Read design.md** (if exists) - Review technical decisions
3. **Read tasks.md** - Get implementation checklist
4. **Implement tasks sequentially** - Complete in order
5. **Confirm completion** - Ensure every item in `tasks.md` is finished before updating statuses
6. **Update checklist** - After all work is done, set every task to `- [x]` so the list reflects reality
7. **Approval gate** - Do not start implementation until the proposal is reviewed and approved
### Stage 3: Archiving Changes
After deployment, create separate PR to:
- Move `changes/[name]/``changes/archive/YYYY-MM-DD-[name]/`
- Update `specs/` if capabilities changed
- Use `openspec archive <change-id> --skip-specs --yes` for tooling-only changes (always pass the change ID explicitly)
- Run `openspec validate --strict` to confirm the archived change passes checks
## Before Any Task
**Context Checklist:**
- [ ] Read relevant specs in `specs/[capability]/spec.md`
- [ ] Check pending changes in `changes/` for conflicts
- [ ] Read `openspec/project.md` for conventions
- [ ] Run `openspec list` to see active changes
- [ ] Run `openspec list --specs` to see existing capabilities
**Before Creating Specs:**
- Always check if capability already exists
- Prefer modifying existing specs over creating duplicates
- Use `openspec show [spec]` to review current state
- If request is ambiguous, ask 12 clarifying questions before scaffolding
### Search Guidance
- Enumerate specs: `openspec spec list --long` (or `--json` for scripts)
- Enumerate changes: `openspec list` (or `openspec change list --json` - deprecated but available)
- Show details:
- Spec: `openspec show <spec-id> --type spec` (use `--json` for filters)
- Change: `openspec show <change-id> --json --deltas-only`
- Full-text search (use ripgrep): `rg -n "Requirement:|Scenario:" openspec/specs`
## Quick Start
### CLI Commands
```bash
# Essential commands
openspec list # List active changes
openspec list --specs # List specifications
openspec show [item] # Display change or spec
openspec validate [item] # Validate changes or specs
openspec archive <change-id> [--yes|-y] # Archive after deployment (add --yes for non-interactive runs)
# Project management
openspec init [path] # Initialize OpenSpec
openspec update [path] # Update instruction files
# Interactive mode
openspec show # Prompts for selection
openspec validate # Bulk validation mode
# Debugging
openspec show [change] --json --deltas-only
openspec validate [change] --strict
```
### Command Flags
- `--json` - Machine-readable output
- `--type change|spec` - Disambiguate items
- `--strict` - Comprehensive validation
- `--no-interactive` - Disable prompts
- `--skip-specs` - Archive without spec updates
- `--yes`/`-y` - Skip confirmation prompts (non-interactive archive)
## Directory Structure
```
openspec/
├── project.md # Project conventions
├── specs/ # Current truth - what IS built
│ └── [capability]/ # Single focused capability
│ ├── spec.md # Requirements and scenarios
│ └── design.md # Technical patterns
├── changes/ # Proposals - what SHOULD change
│ ├── [change-name]/
│ │ ├── proposal.md # Why, what, impact
│ │ ├── tasks.md # Implementation checklist
│ │ ├── design.md # Technical decisions (optional; see criteria)
│ │ └── specs/ # Delta changes
│ │ └── [capability]/
│ │ └── spec.md # ADDED/MODIFIED/REMOVED
│ └── archive/ # Completed changes
```
## Creating Change Proposals
### Decision Tree
```
New request?
├─ Bug fix restoring spec behavior? → Fix directly
├─ Typo/format/comment? → Fix directly
├─ New feature/capability? → Create proposal
├─ Breaking change? → Create proposal
├─ Architecture change? → Create proposal
└─ Unclear? → Create proposal (safer)
```
### Proposal Structure
1. **Create directory:** `changes/[change-id]/` (kebab-case, verb-led, unique)
2. **Write proposal.md:**
```markdown
# Change: [Brief description of change]
## Why
[1-2 sentences on problem/opportunity]
## What Changes
- [Bullet list of changes]
- [Mark breaking changes with **BREAKING**]
## Impact
- Affected specs: [list capabilities]
- Affected code: [key files/systems]
```
3. **Create spec deltas:** `specs/[capability]/spec.md`
```markdown
## ADDED Requirements
### Requirement: New Feature
The system SHALL provide...
#### Scenario: Success case
- **WHEN** user performs action
- **THEN** expected result
## MODIFIED Requirements
### Requirement: Existing Feature
[Complete modified requirement]
## REMOVED Requirements
### Requirement: Old Feature
**Reason**: [Why removing]
**Migration**: [How to handle]
```
If multiple capabilities are affected, create multiple delta files under `changes/[change-id]/specs/<capability>/spec.md`—one per capability.
4. **Create tasks.md:**
```markdown
## 1. Implementation
- [ ] 1.1 Create database schema
- [ ] 1.2 Implement API endpoint
- [ ] 1.3 Add frontend component
- [ ] 1.4 Write tests
```
5. **Create design.md when needed:**
Create `design.md` if any of the following apply; otherwise omit it:
- Cross-cutting change (multiple services/modules) or a new architectural pattern
- New external dependency or significant data model changes
- Security, performance, or migration complexity
- Ambiguity that benefits from technical decisions before coding
Minimal `design.md` skeleton:
```markdown
## Context
[Background, constraints, stakeholders]
## Goals / Non-Goals
- Goals: [...]
- Non-Goals: [...]
## Decisions
- Decision: [What and why]
- Alternatives considered: [Options + rationale]
## Risks / Trade-offs
- [Risk] → Mitigation
## Migration Plan
[Steps, rollback]
## Open Questions
- [...]
```
## Spec File Format
### Critical: Scenario Formatting
**CORRECT** (use #### headers):
```markdown
#### Scenario: User login success
- **WHEN** valid credentials provided
- **THEN** return JWT token
```
**WRONG** (don't use bullets or bold):
```markdown
- **Scenario: User login** ❌
**Scenario**: User login ❌
### Scenario: User login ❌
```
Every requirement MUST have at least one scenario.
### Requirement Wording
- Use SHALL/MUST for normative requirements (avoid should/may unless intentionally non-normative)
### Delta Operations
- `## ADDED Requirements` - New capabilities
- `## MODIFIED Requirements` - Changed behavior
- `## REMOVED Requirements` - Deprecated features
- `## RENAMED Requirements` - Name changes
Headers matched with `trim(header)` - whitespace ignored.
#### When to use ADDED vs MODIFIED
- ADDED: Introduces a new capability or sub-capability that can stand alone as a requirement. Prefer ADDED when the change is orthogonal (e.g., adding "Slash Command Configuration") rather than altering the semantics of an existing requirement.
- MODIFIED: Changes the behavior, scope, or acceptance criteria of an existing requirement. Always paste the full, updated requirement content (header + all scenarios). The archiver will replace the entire requirement with what you provide here; partial deltas will drop previous details.
- RENAMED: Use when only the name changes. If you also change behavior, use RENAMED (name) plus MODIFIED (content) referencing the new name.
Common pitfall: Using MODIFIED to add a new concern without including the previous text. This causes loss of detail at archive time. If you arent explicitly changing the existing requirement, add a new requirement under ADDED instead.
Authoring a MODIFIED requirement correctly:
1) Locate the existing requirement in `openspec/specs/<capability>/spec.md`.
2) Copy the entire requirement block (from `### Requirement: ...` through its scenarios).
3) Paste it under `## MODIFIED Requirements` and edit to reflect the new behavior.
4) Ensure the header text matches exactly (whitespace-insensitive) and keep at least one `#### Scenario:`.
Example for RENAMED:
```markdown
## RENAMED Requirements
- FROM: `### Requirement: Login`
- TO: `### Requirement: User Authentication`
```
## Troubleshooting
### Common Errors
**"Change must have at least one delta"**
- Check `changes/[name]/specs/` exists with .md files
- Verify files have operation prefixes (## ADDED Requirements)
**"Requirement must have at least one scenario"**
- Check scenarios use `#### Scenario:` format (4 hashtags)
- Don't use bullet points or bold for scenario headers
**Silent scenario parsing failures**
- Exact format required: `#### Scenario: Name`
- Debug with: `openspec show [change] --json --deltas-only`
### Validation Tips
```bash
# Always use strict mode for comprehensive checks
openspec validate [change] --strict
# Debug delta parsing
openspec show [change] --json | jq '.deltas'
# Check specific requirement
openspec show [spec] --json -r 1
```
## Happy Path Script
```bash
# 1) Explore current state
openspec spec list --long
openspec list
# Optional full-text search:
# rg -n "Requirement:|Scenario:" openspec/specs
# rg -n "^#|Requirement:" openspec/changes
# 2) Choose change id and scaffold
CHANGE=add-two-factor-auth
mkdir -p openspec/changes/$CHANGE/{specs/auth}
printf "## Why\n...\n\n## What Changes\n- ...\n\n## Impact\n- ...\n" > openspec/changes/$CHANGE/proposal.md
printf "## 1. Implementation\n- [ ] 1.1 ...\n" > openspec/changes/$CHANGE/tasks.md
# 3) Add deltas (example)
cat > openspec/changes/$CHANGE/specs/auth/spec.md << 'EOF'
## ADDED Requirements
### Requirement: Two-Factor Authentication
Users MUST provide a second factor during login.
#### Scenario: OTP required
- **WHEN** valid credentials are provided
- **THEN** an OTP challenge is required
EOF
# 4) Validate
openspec validate $CHANGE --strict
```
## Multi-Capability Example
```
openspec/changes/add-2fa-notify/
├── proposal.md
├── tasks.md
└── specs/
├── auth/
│ └── spec.md # ADDED: Two-Factor Authentication
└── notifications/
└── spec.md # ADDED: OTP email notification
```
auth/spec.md
```markdown
## ADDED Requirements
### Requirement: Two-Factor Authentication
...
```
notifications/spec.md
```markdown
## ADDED Requirements
### Requirement: OTP Email Notification
...
```
## Best Practices
### Simplicity First
- Default to <100 lines of new code
- Single-file implementations until proven insufficient
- Avoid frameworks without clear justification
- Choose boring, proven patterns
### Complexity Triggers
Only add complexity with:
- Performance data showing current solution too slow
- Concrete scale requirements (>1000 users, >100MB data)
- Multiple proven use cases requiring abstraction
### Clear References
- Use `file.ts:42` format for code locations
- Reference specs as `specs/auth/spec.md`
- Link related changes and PRs
### Capability Naming
- Use verb-noun: `user-auth`, `payment-capture`
- Single purpose per capability
- 10-minute understandability rule
- Split if description needs "AND"
### Change ID Naming
- Use kebab-case, short and descriptive: `add-two-factor-auth`
- Prefer verb-led prefixes: `add-`, `update-`, `remove-`, `refactor-`
- Ensure uniqueness; if taken, append `-2`, `-3`, etc.
## Tool Selection Guide
| Task | Tool | Why |
|------|------|-----|
| Find files by pattern | Glob | Fast pattern matching |
| Search code content | Grep | Optimized regex search |
| Read specific files | Read | Direct file access |
| Explore unknown scope | Task | Multi-step investigation |
## Error Recovery
### Change Conflicts
1. Run `openspec list` to see active changes
2. Check for overlapping specs
3. Coordinate with change owners
4. Consider combining proposals
### Validation Failures
1. Run with `--strict` flag
2. Check JSON output for details
3. Verify spec file format
4. Ensure scenarios properly formatted
### Missing Context
1. Read project.md first
2. Check related specs
3. Review recent archives
4. Ask for clarification
## Quick Reference
### Stage Indicators
- `changes/` - Proposed, not yet built
- `specs/` - Built and deployed
- `archive/` - Completed changes
### File Purposes
- `proposal.md` - Why and what
- `tasks.md` - Implementation steps
- `design.md` - Technical decisions
- `spec.md` - Requirements and behavior
### CLI Essentials
```bash
openspec list # What's in progress?
openspec show [item] # View details
openspec validate --strict # Is it correct?
openspec archive <change-id> [--yes|-y] # Mark complete (add --yes for automation)
```
Remember: Specs are truth. Changes are proposals. Keep them in sync.

91
openspec/project.md Normal file
View File

@@ -0,0 +1,91 @@
# Project Context
## Purpose
ROI Theme es un tema WordPress profesional siguiendo Clean Architecture para el sitio analisisdepreciosunitarios.com. Proporciona un sistema de componentes configurables con panel de administración y renderizado frontend dinámico.
## Tech Stack
- **CMS**: WordPress 6.x
- **Lenguaje**: PHP 8.x (strict types)
- **Patrón**: Clean Architecture (Domain, Application, Infrastructure)
- **Frontend**: Bootstrap 5, Bootstrap Icons
- **Base de Datos**: MySQL (tabla normalizada `wp_roi_theme_component_settings`)
- **CLI**: WP-CLI para sincronización de schemas
## Project Conventions
### Code Style
- `declare(strict_types=1)` en todos los archivos PHP
- Namespaces: `ROITheme\[Context]\[Component]\[Layer]`
- Clases finales por defecto
- Propiedades `private`/`protected`
- Escaping WordPress: `esc_html()`, `esc_attr()`, `esc_url()`, `esc_textarea()`
### Nomenclatura (NO NEGOCIABLE)
| Contexto | Formato | Ejemplo |
|-----------------------------|--------------|----------------------------------|
| component_name (JSON/BD) | kebab-case | "featured-image" |
| Nombre archivo schema | kebab-case | featured-image.json |
| Carpeta de módulo | PascalCase | FeaturedImage/ |
| Namespace PHP | PascalCase | ROITheme\Public\FeaturedImage\...|
| Clase Renderer/FormBuilder | PascalCase | FeaturedImageRenderer |
### Architecture Patterns
- **Clean Architecture**: Domain → Application → Infrastructure
- Domain NO depende de capas superiores
- Domain NO puede tener WordPress, echo/print, HTML
- Application NO puede tener WordPress
- Infrastructure implementa interfaces de Domain
- DI via constructor (interfaces, no clases concretas)
### Estructura del Tema
```
roi-theme/
├── Schemas/ # JSON schemas (kebab-case)
├── Shared/ # Código compartido
│ ├── Domain/Contracts/ # Interfaces
│ ├── Application/UseCases/ # Casos de uso
│ └── Infrastructure/ # Implementaciones
├── Public/[PascalCase]/ # Renderers frontend
├── Admin/[PascalCase]/ # FormBuilders admin
└── functions.php # Bootstrap
```
### Testing Strategy
- Validación de arquitectura: `php Shared/Infrastructure/Scripts/validate-architecture.php [nombre]`
- Tests unitarios pendientes de implementar
### Git Workflow
- Conventional Commits: `feat:`, `fix:`, `refactor:`, `docs:`
- Branch principal: `main`
- Tags para releases: `v1.0.0`, `v2.0.0`
## Domain Context
El sistema maneja componentes UI configurables para un sitio de análisis de precios unitarios (construcción). Cada componente tiene:
- **Schema JSON**: Define campos configurables
- **Renderer**: Genera HTML + CSS dinámico desde BD
- **FormBuilder**: Panel admin para configurar valores
### Flujo de 5 Fases para Componentes
1. Schema JSON → `Schemas/[nombre].json`
2. Sincronización → `wp roi-theme sync-component [nombre]`
3. Renderer → `Public/[Nombre]/Infrastructure/Ui/[Nombre]Renderer.php`
4. FormBuilder → `Admin/[Nombre]/Infrastructure/Ui/[Nombre]FormBuilder.php`
5. Validación → `validate-architecture.php [nombre]`
## Important Constraints
- CERO CSS hardcodeado en PHP (usar CSSGeneratorService)
- NO usar global $wpdb en Domain/Application
- NO instanciar servicios directamente (usar DI)
- NO modificar campos en BD manualmente
- Variables CSS del tema: `--color-navy-dark`, `--color-orange-primary`
## External Dependencies
- WordPress 6.x core
- Bootstrap 5 (CSS/JS)
- Bootstrap Icons
- WP-CLI (`C:\xampp\php_8.0.30_backup\wp-cli.phar`)
## Referencias Documentación
- Arquitectura: `_planeacion/roi-theme/_arquitectura/`
- Template HTML: `_planeacion/roi-theme/roi-theme-template/index.html`
- Design System: `_planeacion/roi-theme/_arquitectura/01-design-system/`

View File

@@ -0,0 +1,215 @@
# Especificacion de Arquitectura Limpia
## Purpose
Define la implementacion de Clean Architecture para ROITheme, un tema WordPress que sigue principios de Domain-Driven Design con separacion fisica de contextos delimitados (Admin, Public, Shared).
## Requirements
### Requirement: Separacion Fisica de Contextos
The system MUST organize code into three physically delimited contexts: Admin/, Public/, and Shared/.
#### Scenario: Codigo pertenece al contexto de administracion
- **WHEN** el codigo maneja operaciones CRUD, configuracion o funcionalidad del panel admin
- **THEN** el codigo DEBE colocarse en el directorio `Admin/`
- **AND** el codigo NO DEBE importar del directorio `Public/`
#### Scenario: Codigo pertenece al contexto publico/frontend
- **WHEN** el codigo maneja renderizado, visualizacion o presentacion frontend
- **THEN** el codigo DEBE colocarse en el directorio `Public/`
- **AND** el codigo NO DEBE importar del directorio `Admin/`
#### Scenario: Codigo es compartido entre contextos
- **WHEN** el codigo es usado por AMBOS contextos Admin/ y Public/
- **THEN** el codigo DEBE colocarse en el directorio `Shared/` raiz
- **AND** tanto Admin/ como Public/ PUEDEN importar de Shared/
---
### Requirement: Organizacion Granular de Codigo Compartido
The system MUST implement three levels of shared code to avoid mixing context-specific shared code.
#### Scenario: Codigo compartido solo dentro del contexto Admin
- **WHEN** el codigo es reutilizado por multiples modulos Admin pero NO por Public
- **THEN** el codigo DEBE colocarse en el directorio `Admin/Shared/`
- **AND** los modulos de Public/ NO DEBEN importar de `Admin/Shared/`
#### Scenario: Codigo compartido solo dentro del contexto Public
- **WHEN** el codigo es reutilizado por multiples modulos Public pero NO por Admin
- **THEN** el codigo DEBE colocarse en el directorio `Public/Shared/`
- **AND** los modulos de Admin/ NO DEBEN importar de `Public/Shared/`
#### Scenario: Codigo compartido entre ambos contextos
- **WHEN** el codigo es reutilizado por AMBOS modulos Admin/ y Public/
- **THEN** el codigo DEBE colocarse en el directorio `Shared/` raiz
- **AND** esto incluye ValueObjects, Exceptions y Contracts base
---
### Requirement: Cada Contexto Sigue las Capas de Clean Architecture
Each context (Admin/, Public/, Shared/) MUST internally implement the three Clean Architecture layers: Domain, Application, Infrastructure.
#### Scenario: Estructura de modulo dentro del contexto Admin
- **GIVEN** un componente llamado "Navbar" en el contexto Admin
- **WHEN** el modulo es creado
- **THEN** la estructura DEBE ser: Admin/Navbar/ con subcarpetas Domain/, Application/, Infrastructure/
#### Scenario: Estructura de modulo dentro del contexto Public
- **GIVEN** un componente llamado "Navbar" en el contexto Public
- **WHEN** el modulo es creado
- **THEN** la estructura DEBE ser: Public/Navbar/ con subcarpetas Domain/, Application/, Infrastructure/
---
### Requirement: Cumplimiento de Direccion de Dependencias
The system MUST enforce that dependencies flow ONLY from outer layers to inner layers.
#### Scenario: Infrastructure depende de Application y Domain
- **WHEN** el codigo esta en la capa Infrastructure
- **THEN** PUEDE importar de la capa Application
- **AND** PUEDE importar de la capa Domain
#### Scenario: Application depende solo de Domain
- **WHEN** el codigo esta en la capa Application
- **THEN** PUEDE importar de la capa Domain
- **AND** NO DEBE importar de la capa Infrastructure
#### Scenario: Domain no tiene dependencias externas
- **WHEN** el codigo esta en la capa Domain
- **THEN** NO DEBE importar de la capa Application
- **AND** NO DEBE importar de la capa Infrastructure
- **AND** NO DEBE importar funciones o globales de WordPress
---
### Requirement: La Capa Domain Contiene Solo Logica de Negocio Pura
The Domain layer MUST contain only pure business logic without framework dependencies.
#### Scenario: Validacion de contenido de capa Domain
- **WHEN** el codigo se coloca en la capa Domain
- **THEN** PUEDE contener Entities, Value Objects, Domain Services, Interfaces, Exceptions
- **AND** NO DEBE contener global $wpdb, $_POST, $_GET, $_SESSION, add_action, add_filter, HTML, CSS, JavaScript
#### Scenario: Implementacion de entidad Domain
- **GIVEN** una entidad Domain como NavbarConfiguration
- **WHEN** la entidad es implementada
- **THEN** DEBE contener reglas de negocio y validacion
- **AND** NO DEBE contener logica de persistencia
- **AND** NO DEBE referenciar APIs de WordPress
---
### Requirement: La Capa Application Orquesta Domain
The Application layer MUST orchestrate domain entities without containing business logic.
#### Scenario: Implementacion de Use Case
- **WHEN** un Use Case es implementado
- **THEN** DEBE coordinar entidades y servicios de domain
- **AND** DEBE depender de interfaces, NO de implementaciones concretas
- **AND** NO DEBE contener reglas de validacion de negocio
#### Scenario: Uso de DTOs para transferencia de datos
- **WHEN** los datos cruzan limites entre capas
- **THEN** se DEBEN usar DTOs (Data Transfer Objects)
- **AND** los DTOs DEBEN ser contenedores de datos simples sin logica de negocio
---
### Requirement: Infrastructure Implementa Interfaces
The Infrastructure layer MUST implement interfaces defined in Domain/Application layers.
#### Scenario: Implementacion de Repository
- **GIVEN** una RepositoryInterface definida en Domain
- **WHEN** el repository es implementado
- **THEN** DEBE colocarse en Infrastructure/Persistence/
- **AND** DEBE implementar la interface de Domain
- **AND** PUEDE usar global $wpdb o APIs de WordPress
#### Scenario: Integracion con WordPress
- **WHEN** se necesita codigo especifico de WordPress
- **THEN** DEBE colocarse en la capa Infrastructure
- **AND** NO DEBE filtrarse a las capas Domain o Application
---
### Requirement: Los Modulos Son Autocontenidos e Independientes
Each module (Navbar, Footer, Toolbar, etc.) MUST be self-contained and independent from other modules.
#### Scenario: Aislamiento de modulos
- **WHEN** un modulo como Admin/Navbar/ es implementado
- **THEN** NO DEBE importar de Admin/Footer/
- **AND** NO DEBE importar de Admin/Toolbar/
- **AND** SOLO PUEDE importar de Shared/
#### Scenario: Eliminacion de modulos
- **WHEN** un modulo necesita ser eliminado
- **THEN** borrar la carpeta del modulo NO DEBE romper otros modulos
- **AND** no se DEBERIAN requerir cambios de codigo en otros modulos
---
### Requirement: Admin y Public Son Bounded Contexts Separados
Admin/ and Public/ MUST be treated as separate bounded contexts because they have different responsibilities.
#### Scenario: Responsabilidad del contexto Admin
- **WHEN** el codigo maneja administracion de componentes
- **THEN** la entidad Domain se enfoca en configuracion, validacion, estados draft/published
- **AND** los Use Cases se enfocan en operaciones Save, Update, Delete, Get
#### Scenario: Responsabilidad del contexto Public
- **WHEN** el codigo maneja renderizado de componentes
- **THEN** la entidad Domain se enfoca en estado activo, caching, filtrado por permisos
- **AND** los Use Cases se enfocan en operaciones GetActive, Render, Cache
#### Scenario: No hay duplicacion de domain
- **WHEN** Admin/Navbar/Domain/ y Public/Navbar/Domain/ ambos existen
- **THEN** NO son duplicados sino bounded contexts especializados
- **AND** Admin se enfoca en configuracion/gestion
- **AND** Public se enfoca en renderizado/visualizacion
---
### Requirement: Validacion de Arquitectura Antes de Commit
The system MUST validate architectural compliance before committing code.
#### Scenario: Validacion de capa Domain
- **WHEN** se valida codigo de la capa Domain
- **THEN** grep por global $wpdb DEBE retornar vacio
- **AND** grep por add_action DEBE retornar vacio
- **AND** grep por $_POST DEBE retornar vacio
#### Scenario: Validacion de dependencias de modulos
- **WHEN** se validan dependencias entre modulos
- **THEN** imports de Admin/Navbar/ desde Admin/Footer/ NO DEBEN existir
- **AND** imports de Public/Navbar/ desde Public/Footer/ NO DEBEN existir
---
### Requirement: Realizacion de Beneficios de la Arquitectura
The architecture MUST provide measurable benefits.
#### Scenario: Asignacion granular de trabajo
- **WHEN** un desarrollador es asignado a trabajar en Admin/Navbar/
- **THEN** puede acceder SOLO a esa carpeta
- **AND** no puede ver ni modificar Public/ u otros modulos de Admin/
#### Scenario: Eliminacion facil de modulos
- **WHEN** un componente ya no es necesario
- **THEN** eliminarlo requiere solo borrar la carpeta
- **AND** no se necesitan otras modificaciones de codigo
#### Scenario: Codigo compartido consistente
- **WHEN** se encuentra un bug en un ValueObject compartido
- **THEN** arreglarlo en Shared/Domain/ValueObjects/ lo arregla para TODOS los modulos
- **AND** no se necesita actualizar codigo duplicado

View File

@@ -0,0 +1,350 @@
# Especificacion de Estandares de Codigo
## Purpose
Define los principios SOLID, estandares de POO (Programacion Orientada a Objetos) y estandares generales de codigo que DEBEN seguirse en el desarrollo de ROITheme.
## Requirements
### Requirement: Principio de Responsabilidad Unica (SRP)
Each class MUST have exactly one reason to change and one responsibility.
#### Scenario: Responsabilidad de clase Use Case
- **WHEN** se crea una clase Use Case
- **THEN** DEBE manejar exactamente UNA operacion (Save, Get, Delete, etc.)
- **AND** NO DEBE combinar multiples operaciones en una clase
#### Scenario: Validacion de tamano de clase
- **WHEN** se crea un archivo de clase
- **THEN** DEBERIA tener menos de 300 lineas
- **AND** DEBERIA tener maximo 3-5 metodos privados
- **AND** el nombre de la clase DEBE describir su unica responsabilidad
#### Scenario: Violacion de SRP
- **WHEN** una clase contiene save(), get(), delete(), validate(), sendEmail()
- **THEN** DEBE dividirse en clases Use Case separadas
- **AND** cada clase maneja solo una operacion
---
### Requirement: Principio Abierto/Cerrado (OCP)
Classes MUST be open for extension but closed for modification.
#### Scenario: Agregar nuevo tipo de componente
- **WHEN** se necesita un nuevo tipo de componente
- **THEN** se DEBE crear una nueva subclase
- **AND** la clase BaseComponent existente NO DEBE modificarse
- **AND** NO se DEBERIAN agregar cadenas if/elseif para nuevos tipos
#### Scenario: Extender funcionalidad base
- **GIVEN** que existe una clase abstracta BaseComponent
- **WHEN** se necesita comportamiento especializado
- **THEN** se DEBE usar herencia para extender
- **AND** la clase base DEBE permanecer sin cambios
---
### Requirement: Principio de Sustitucion de Liskov (LSP)
Subclasses MUST be substitutable for their base classes without breaking functionality.
#### Scenario: Uso polimorfico
- **GIVEN** una funcion que acepta parametro BaseComponent
- **WHEN** cualquier subclase es pasada
- **THEN** la funcion DEBE funcionar correctamente
- **AND** NO se DEBERIAN lanzar excepciones inesperadas
#### Scenario: Cumplimiento de contrato
- **WHEN** una subclase sobrescribe un metodo padre
- **THEN** DEBE respetar el contrato del metodo original
- **AND** las precondiciones NO DEBEN ser mas restrictivas
- **AND** las postcondiciones NO DEBEN ser mas permisivas
---
### Requirement: Principio de Segregacion de Interfaces (ISP)
Interfaces MUST be small and specific, not large and general.
#### Scenario: Validacion de tamano de interface
- **WHEN** se define una interface
- **THEN** DEBE tener maximo 3-5 metodos
- **AND** cada metodo DEBE relacionarse con la misma capacidad
#### Scenario: Evitar interfaces gordas
- **WHEN** existen multiples capacidades no relacionadas
- **THEN** se DEBEN crear interfaces separadas
- **AND** las clases implementan solo las interfaces que usan
- **AND** NO se permiten metodos dummy "No implementado"
#### Scenario: Diseno correcto de interface
- **WHEN** se necesita funcionalidad de cache
- **THEN** se DEBE usar CacheInterface con get(), set(), delete()
- **AND** ValidatorInterface con validate() es separada
---
### Requirement: Principio de Inversion de Dependencias (DIP)
High-level modules MUST depend on abstractions, not concrete implementations.
#### Scenario: Inyeccion por constructor con interfaces
- **WHEN** una clase necesita dependencias
- **THEN** el constructor DEBE recibir interfaces, NO clases concretas
- **AND** NO debe haber new ClaseConcreta() dentro del cuerpo de la clase
#### Scenario: Cableado del Contenedor DI
- **WHEN** se necesitan implementaciones concretas
- **THEN** el DIContainer DEBE manejar el cableado
- **AND** las clases permanecen desacopladas de las implementaciones
#### Scenario: Dependencia incorrecta
- **WHEN** el constructor hace this->repo = new WordPressNavbarRepository()
- **THEN** esto DEBE refactorizarse para recibir NavbarRepositoryInterface
- **AND** el DIContainer proporciona la implementacion concreta
---
### Requirement: Encapsulacion de Propiedades
Class properties MUST be encapsulated with controlled access.
#### Scenario: Visibilidad de propiedades
- **WHEN** se define una propiedad de clase
- **THEN** DEBE ser private o protected
- **AND** el acceso DEBE ser via metodos getter
- **AND** la mutacion DEBE ser via metodos setter o metodos de negocio
#### Scenario: Encapsulacion de Value Object
- **GIVEN** un ValueObject como ComponentName
- **WHEN** es construido
- **THEN** la validacion DEBE ocurrir en el constructor
- **AND** el valor DEBE ser inmutable despues de la construccion
- **AND** los detalles internos NO DEBEN exponerse
---
### Requirement: Guias de Herencia
Inheritance MUST be used appropriately with limited depth.
#### Scenario: Limite de profundidad de herencia
- **WHEN** se usa herencia
- **THEN** la profundidad maxima DEBE ser 2-3 niveles
- **AND** las cadenas de herencia profundas DEBEN evitarse
#### Scenario: Comportamiento comun en clase base
- **WHEN** multiples clases comparten comportamiento comun
- **THEN** se DEBERIA crear una clase base abstracta
- **AND** las subclases especializan con comportamiento adicional
---
### Requirement: Polimorfismo Correcto
Methods MUST accept base types or interfaces to enable polymorphism.
#### Scenario: Tipos de parametros de metodo
- **WHEN** un metodo acepta parametro de componente
- **THEN** el type hint DEBERIA ser BaseComponent o ComponentInterface
- **AND** cualquier subclase/implementacion DEBE funcionar correctamente
#### Scenario: Polimorfismo de repository
- **WHEN** un Use Case usa un repository
- **THEN** DEBE aceptar RepositoryInterface
- **AND** WordPressRepository y MockRepository funcionan transparentemente
---
### Requirement: Estandares PHP Estrictos
All PHP code MUST follow strict type safety and naming conventions.
#### Scenario: Declaracion de tipos estrictos
- **WHEN** se crea un archivo PHP
- **THEN** DEBE comenzar con declare(strict_types=1)
- **AND** los tipos de retorno DEBEN declararse
- **AND** los tipos de parametros DEBEN declararse
#### Scenario: Convencion de namespace
- **WHEN** se crea una clase
- **THEN** el namespace DEBE seguir ROITheme\[Contexto]\[Componente]\[Capa]
- **AND** DEBE soportar autoloading PSR-4
#### Scenario: Declaracion de clase
- **WHEN** se crea una clase
- **THEN** DEBERIA ser final por defecto
- **AND** solo hacerla no-final cuando se pretende herencia
- **AND** el nombre de clase DEBE ser PascalCase
---
### Requirement: Modularidad del Codigo
Code MUST be organized into independent and cohesive modules.
#### Scenario: Independencia de modulos
- **WHEN** se crea un modulo
- **THEN** DEBE ser autocontenido
- **AND** NO DEBE depender de otros modulos (solo de Shared/)
- **AND** eliminarlo NO DEBE romper otros modulos
#### Scenario: Alta cohesion
- **WHEN** el codigo se coloca en un modulo
- **THEN** todo el codigo DEBE relacionarse con el proposito de ese modulo
- **AND** el codigo no relacionado DEBE estar en Shared/ u otro modulo
#### Scenario: Bajo acoplamiento
- **WHEN** los modulos interactuan
- **THEN** DEBEN comunicarse a traves de interfaces de Shared/
- **AND** las dependencias directas entre modulos estan prohibidas
---
### Requirement: DRY - No Te Repitas
Code duplication MUST be eliminated through appropriate abstraction.
#### Scenario: Ubicacion de codigo compartido
- **WHEN** el codigo es usado por multiples modulos
- **THEN** DEBE moverse al nivel apropiado de Shared/
- **AND** los modulos DEBEN importar de Shared/
#### Scenario: Deteccion de duplicacion
- **WHEN** existe codigo similar en 2+ lugares
- **THEN** DEBE refactorizarse a Shared/
- **AND** las ubicaciones originales importan de Shared/
---
### Requirement: KISS - Mantenlo Simple
Solutions MUST be simple and avoid over-engineering.
#### Scenario: Uso de patrones
- **WHEN** se considera un patron de diseno
- **THEN** DEBE resolver un problema real
- **AND** se DEBEN preferir soluciones mas simples
- **AND** la abstraccion excesiva DEBE evitarse
#### Scenario: Claridad del codigo
- **WHEN** se escribe codigo
- **THEN** DEBERIA ser auto-documentado
- **AND** los comentarios DEBERIAN ser innecesarios para entender
- **AND** la logica compleja DEBERIA extraerse a metodos bien nombrados
---
### Requirement: Separacion de Responsabilidades por Capa
Each layer MUST have distinct responsibilities.
#### Scenario: Responsabilidades por capa
- **WHEN** se escribe codigo
- **THEN** Domain contiene logica de negocio
- **AND** Application contiene orquestacion
- **AND** Infrastructure contiene implementacion tecnica
- **AND** UI contiene solo presentacion
#### Scenario: Validacion de responsabilidades cruzadas
- **WHEN** se valida ubicacion de codigo
- **THEN** SQL NO DEBE estar en Domain/Application
- **AND** HTML NO DEBE estar en Domain/Application
- **AND** logica de negocio NO DEBE estar en Infrastructure
---
### Requirement: Limites de Tamano de Archivo
Files MUST be kept small and focused.
#### Scenario: Tamano de archivo de clase
- **WHEN** se crea un archivo de clase
- **THEN** DEBERIA tener menos de 300 lineas
- **AND** si es mas grande, DEBERIA dividirse en clases mas pequenas
#### Scenario: Tamano de metodo
- **WHEN** se escribe un metodo
- **THEN** DEBERIA tener menos de 30 lineas
- **AND** metodos complejos DEBERIAN extraerse a metodos auxiliares
---
### Requirement: Convenciones de Nomenclatura
Names MUST be clear, descriptive, and follow conventions.
#### Scenario: Nomenclatura de clases
- **WHEN** se nombra una clase
- **THEN** el nombre DEBE describir su unica responsabilidad
- **AND** las clases Use Case DEBEN nombrarse [Accion][Entidad]UseCase
- **AND** las clases Repository DEBEN nombrarse [Implementacion][Entidad]Repository
#### Scenario: Nomenclatura de metodos
- **WHEN** se nombra un metodo
- **THEN** DEBE describir lo que hace el metodo
- **AND** DEBERIA comenzar con un verbo
- **AND** metodos booleanos DEBERIAN comenzar con is/has/can
#### Scenario: Nomenclatura de variables
- **WHEN** se nombra una variable
- **THEN** DEBE ser descriptiva
- **AND** las abreviaturas DEBEN evitarse
- **AND** nombres de una letra solo para contadores de bucle
---
### Requirement: Validacion Pre-Commit
Code MUST pass validation before commit.
#### Scenario: Verificacion de cumplimiento SOLID
- **WHEN** el codigo esta listo para commit
- **THEN** SRP cada clase tiene una responsabilidad
- **AND** OCP nuevas caracteristicas via extension, no modificacion
- **AND** LSP las subclases son sustituibles
- **AND** ISP las interfaces son pequenas 3-5 metodos
- **AND** DIP el constructor recibe interfaces
#### Scenario: Verificacion de cumplimiento POO
- **WHEN** el codigo esta listo para commit
- **THEN** las propiedades son private/protected
- **AND** la profundidad de herencia es max 2-3 niveles
- **AND** el polimorfismo esta implementado correctamente
- **AND** la abstraccion oculta complejidad
#### Scenario: Verificacion de calidad
- **WHEN** el codigo esta listo para commit
- **THEN** los archivos tienen menos de 300 lineas
- **AND** los nombres son claros y descriptivos
- **AND** no existe duplicacion de codigo
- **AND** no hay sobre-ingenieria presente
---
### Requirement: Escaping Obligatorio en Output HTML
All HTML output MUST use WordPress escaping functions for security.
#### Scenario: Escaping de textos
- **WHEN** se genera output de texto en HTML
- **THEN** DEBE usar esc_html() para contenido de texto
#### Scenario: Escaping de atributos
- **WHEN** se genera un atributo HTML
- **THEN** DEBE usar esc_attr() para valores de atributos
#### Scenario: Escaping de URLs
- **WHEN** se genera una URL en href o src
- **THEN** DEBE usar esc_url() para URLs
#### Scenario: Escaping de textareas
- **WHEN** se genera contenido para textarea
- **THEN** DEBE usar esc_textarea() para el valor
#### Scenario: Prohibicion de output sin escaping
- **WHEN** se revisa codigo de Renderer o FormBuilder
- **THEN** NO DEBE existir echo o print de variables sin escaping
- **AND** NO DEBE existir interpolacion directa de variables en HTML

View File

@@ -0,0 +1,406 @@
# Especificacion de Flujo de Componentes
## Purpose
Define el flujo de trabajo de 5 fases para crear componentes en ROITheme, incluyendo convenciones de nomenclatura, estructura de archivos y validacion.
## Requirements
### Requirement: Nomenclatura NO NEGOCIABLE
The system MUST follow strict naming conventions that are NON-NEGOTIABLE.
#### Scenario: Nomenclatura de component_name en JSON y BD
- **WHEN** se define el nombre del componente en JSON o base de datos
- **THEN** DEBE usar kebab-case
- **AND** ejemplo: featured-image, hero-section, top-bar
#### Scenario: Nomenclatura de archivo schema JSON
- **WHEN** se crea un archivo de schema JSON
- **THEN** el nombre DEBE ser kebab-case
- **AND** ejemplo: featured-image.json, hero-section.json
#### Scenario: Nomenclatura de carpeta de modulo
- **WHEN** se crea la carpeta del modulo
- **THEN** DEBE usar PascalCase
- **AND** ejemplo: FeaturedImage/, HeroSection/, TopBar/
#### Scenario: Nomenclatura de namespace PHP
- **WHEN** se define el namespace PHP
- **THEN** DEBE usar PascalCase
- **AND** patron: ROITheme\[Contexto]\[Componente]\[Capa]
#### Scenario: Nomenclatura de clases Renderer y FormBuilder
- **WHEN** se nombran las clases Renderer o FormBuilder
- **THEN** DEBEN usar PascalCase
- **AND** ejemplo: FeaturedImageRenderer, HeroSectionFormBuilder
#### Scenario: Conversion kebab-case a PascalCase
- **WHEN** se convierte de kebab-case a PascalCase
- **THEN** se eliminan los guiones
- **AND** se capitaliza cada palabra
- **AND** ejemplo: featured-image se convierte en FeaturedImage
---
### Requirement: Fase 1 - Creacion de Schema JSON
The first step MUST be creating the component JSON schema.
#### Scenario: Ubicacion del schema
- **WHEN** se crea un schema JSON
- **THEN** DEBE colocarse en Schemas/[nombre-en-kebab-case].json
- **AND** ejemplo: Schemas/featured-image.json
#### Scenario: Campo component_name en schema
- **WHEN** se define component_name en el schema
- **THEN** DEBE usar kebab-case
- **AND** ejemplo: component_name con valor featured-image
#### Scenario: Fuente del schema
- **WHEN** se extrae informacion para el schema
- **THEN** DEBE basarse en _planeacion/roi-theme/roi-theme-template/index.html
- **AND** DEBEN extraerse TODOS los campos CSS y textos del HTML
#### Scenario: Campos obligatorios de visibilidad
- **WHEN** se crea un schema
- **THEN** DEBE incluir is_enabled como boolean
- **AND** DEBE incluir show_on_desktop como boolean
- **AND** DEBE incluir show_on_mobile como boolean
#### Scenario: Grupos JSON estandar con priorities
- **WHEN** se estructura un schema JSON
- **THEN** DEBE organizar campos en los 12 grupos estandar con priorities fijas
- **AND** VISIBILITY DEBE tener priority 10
- **AND** CONTENT DEBE tener priority 20
- **AND** TYPOGRAPHY DEBE tener priority 30
- **AND** COLORS DEBE tener priority 40
- **AND** SPACING DEBE tener priority 50
- **AND** VISUAL_EFFECTS DEBE tener priority 60
- **AND** BEHAVIOR DEBE tener priority 70
- **AND** LAYOUT DEBE tener priority 80
- **AND** LINKS, ICONS, MEDIA, FORMS DEBEN tener priority 90
#### Scenario: Tipos de campo validos en schema
- **WHEN** se define un campo en el schema JSON
- **THEN** el type DEBE ser uno de: boolean, text, textarea, url, select, color
- **AND** si type es select DEBE incluir array de options
- **AND** si type es boolean el default DEBE ser true o false
- **AND** si type es color el default DEBE ser formato hexadecimal (#RRGGBB)
#### Scenario: Campo heading_level para semantica HTML
- **WHEN** un componente tiene titulo principal
- **THEN** el grupo TYPOGRAPHY DEBE incluir campo heading_level
- **AND** heading_level DEBE ser tipo select con options h1, h2, h3, h4, h5, h6
- **AND** heading_level es critico para jerarquia semantica y SEO
#### Scenario: Campos de accesibilidad en MEDIA
- **WHEN** un componente tiene imagenes
- **THEN** el grupo MEDIA DEBE incluir campo image_alt
- **AND** image_alt es obligatorio para accesibilidad (WCAG)
- **WHEN** la imagen puede compartirse en redes sociales
- **THEN** DEBE incluir campo is_og_image como boolean
#### Scenario: Campos tipicos del grupo BEHAVIOR
- **WHEN** un componente tiene comportamiento interactivo
- **THEN** el grupo BEHAVIOR puede incluir is_sticky, sticky_offset, collapse_on_mobile
- **AND** para Table of Contents puede incluir generate_jump_links, enable_scrollspy
- **AND** para animaciones puede incluir animation_type
---
### Requirement: Fase 2 - Sincronizacion JSON a BD
The second step MUST synchronize the JSON schema with the database.
#### Scenario: Comando de sincronizacion
- **WHEN** se necesita sincronizar un componente
- **THEN** ejecutar wp roi-theme sync-component [nombre]
- **AND** ejemplo: wp roi-theme sync-component featured-image
#### Scenario: Tabla destino
- **WHEN** se sincroniza
- **THEN** los datos van a la tabla wp_roi_theme_component_settings
#### Scenario: Preservacion de valores
- **WHEN** se sincroniza un schema actualizado
- **THEN** los valores existentes del usuario DEBEN preservarse
- **AND** solo se agregan campos nuevos
#### Scenario: Conversion de valores para almacenamiento
- **WHEN** se sincroniza un campo a BD
- **THEN** arrays y objects DEBEN convertirse con json_encode()
- **AND** booleans DEBEN convertirse a '1' o '0'
- **AND** otros tipos DEBEN convertirse a string con cast
---
### Requirement: Fase 3 - Creacion del Renderer
The third step MUST create the Renderer that converts DB data to HTML + CSS.
#### Scenario: Ubicacion del Renderer
- **WHEN** se crea un Renderer
- **THEN** DEBE colocarse en Public/[PascalCase]/Infrastructure/Ui/[PascalCase]Renderer.php
- **AND** ejemplo: Public/FeaturedImage/Infrastructure/Ui/FeaturedImageRenderer.php
#### Scenario: Inyeccion de CSSGeneratorInterface
- **WHEN** se implementa un Renderer
- **THEN** DEBE inyectar CSSGeneratorInterface via constructor
- **AND** NO DEBE tener CSS hardcodeado
#### Scenario: Generacion de CSS
- **WHEN** se genera CSS en el Renderer
- **THEN** DEBE usar $this->cssGenerator->generate()
- **AND** CERO CSS hardcodeado en el codigo PHP
#### Scenario: Validacion de visibilidad
- **WHEN** el Renderer procesa un componente
- **THEN** DEBE validar is_enabled, show_on_desktop, show_on_mobile
- **AND** NO renderizar si no cumple condiciones de visibilidad
#### Scenario: Clases responsive Bootstrap para visibilidad
- **WHEN** el Renderer genera HTML para show_on_desktop y show_on_mobile
- **THEN** DEBE usar clases Bootstrap d-none, d-lg-block, d-lg-none
- **AND** NO DEBE usar CSS custom para visibilidad responsive
- **AND** el breakpoint principal es lg (992px)
#### Scenario: Tabla de decision para visibilidad responsive
- **GIVEN** campos show_on_desktop y show_on_mobile del componente
- **WHEN** show_on_desktop es false AND show_on_mobile es true
- **THEN** aplicar clase d-lg-none (solo visible en mobile)
- **WHEN** show_on_desktop es true AND show_on_mobile es false
- **THEN** aplicar clases d-none d-lg-block (solo visible en desktop)
- **WHEN** show_on_desktop es false AND show_on_mobile es false
- **THEN** NO renderizar componente y retornar string vacio
- **WHEN** show_on_desktop es true AND show_on_mobile es true
- **THEN** NO aplicar clases de visibilidad (visible en ambos)
#### Scenario: Metodo supports
- **WHEN** se implementa el metodo supports()
- **THEN** DEBE retornar el nombre en kebab-case
- **AND** ejemplo: return 'featured-image'
---
### Requirement: Contrato de CSSGeneratorInterface
The CSS generation service MUST follow a specific contract defined in Shared.
#### Scenario: Ubicacion de CSSGeneratorInterface
- **WHEN** se necesita la interface de generacion CSS
- **THEN** DEBE estar en Shared/Domain/Contracts/CSSGeneratorInterface.php
#### Scenario: Firma del metodo generate
- **WHEN** se implementa CSSGeneratorInterface
- **THEN** DEBE tener metodo generate(string $selector, array $styles): string
- **AND** $selector es el selector CSS (ej: '.navbar')
- **AND** $styles es array asociativo de propiedades CSS
- **AND** retorna string CSS formateado
#### Scenario: Conversion de propiedades CSS
- **WHEN** CSSGeneratorService procesa array de estilos
- **THEN** DEBE convertir snake_case a kebab-case
- **AND** ejemplo: background_color se convierte en background-color
---
### Requirement: Fase 4 - Creacion del FormBuilder
The fourth step MUST create the FormBuilder for the admin panel.
#### Scenario: Ubicacion del FormBuilder
- **WHEN** se crea un FormBuilder
- **THEN** DEBE colocarse en Admin/[PascalCase]/Infrastructure/Ui/[PascalCase]FormBuilder.php
- **AND** ejemplo: Admin/FeaturedImage/Infrastructure/Ui/FeaturedImageFormBuilder.php
#### Scenario: Inyeccion de AdminDashboardRenderer
- **WHEN** se implementa un FormBuilder
- **THEN** DEBE inyectar AdminDashboardRenderer
---
### Requirement: Contrato de AdminDashboardRenderer
The admin panel rendering service MUST follow a specific contract.
#### Scenario: Ubicacion de AdminDashboardRenderer
- **WHEN** se necesita el renderer del panel admin
- **THEN** DEBE estar en Admin/Shared/Infrastructure/Ui/AdminDashboardRenderer.php
#### Scenario: Responsabilidad de AdminDashboardRenderer
- **WHEN** se usa AdminDashboardRenderer
- **THEN** DEBE generar el HTML de controles de formulario
- **AND** DEBE aplicar el Design System del admin (gradiente, bordes)
- **AND** DEBE usar Bootstrap 5 form controls
#### Scenario: Design System del admin
- **WHEN** se implementa la UI del admin
- **THEN** DEBE usar gradiente #0E2337 a #1e3a5f
- **AND** borde naranja #FF8600
- **AND** Bootstrap 5 form controls
#### Scenario: Registro en getComponents
- **WHEN** se registra el FormBuilder
- **THEN** DEBE registrarse en getComponents() con ID en kebab-case
- **AND** ejemplo: 'featured-image'
---
### Requirement: Fase 5 - Validacion de Arquitectura
The fifth and final step MUST validate the component architecture.
#### Scenario: Comando de validacion
- **WHEN** se necesita validar un componente
- **THEN** ejecutar php Shared/Infrastructure/Scripts/validate-architecture.php [nombre]
- **AND** ejemplo: php Shared/Infrastructure/Scripts/validate-architecture.php featured-image
#### Scenario: Elementos validados
- **WHEN** se ejecuta la validacion
- **THEN** DEBE validar estructura de carpetas
- **AND** DEBE validar schema JSON
- **AND** DEBE validar datos en BD
- **AND** DEBE validar Renderer
- **AND** DEBE validar FormBuilder
- **AND** DEBE validar cumplimiento SOLID
---
### Requirement: Estructura de Archivos por Componente
A complete component MUST have a specific file structure.
#### Scenario: Estructura de componente en Public
- **GIVEN** un componente FeaturedImage en Public
- **WHEN** esta completo
- **THEN** DEBE existir Public/FeaturedImage/Infrastructure/Ui/FeaturedImageRenderer.php
#### Scenario: Estructura de componente en Admin
- **GIVEN** un componente FeaturedImage en Admin
- **WHEN** esta completo
- **THEN** DEBE existir Admin/FeaturedImage/Infrastructure/Ui/FeaturedImageFormBuilder.php
#### Scenario: Archivo schema
- **GIVEN** un componente FeaturedImage
- **WHEN** se necesita el schema
- **THEN** DEBE existir en Schemas/featured-image.json
---
### Requirement: Variables CSS del Tema
Code MUST use the theme CSS variables.
#### Scenario: Variables de color disponibles
- **WHEN** se necesitan colores
- **THEN** DEBEN usarse las variables como --color-navy-dark y --color-orange-primary
#### Scenario: Prohibicion de CSS hardcodeado
- **WHEN** se genera CSS
- **THEN** NO DEBE haber colores hardcodeados en PHP
- **AND** DEBE usarse CSSGeneratorService
---
### Requirement: Reglas NO Negociables del Flujo
These rules MUST always be followed, without exceptions.
#### Scenario: Creacion de archivos
- **WHEN** se van a crear archivos para un componente
- **THEN** DEBE leerse primero el template HTML
- **AND** NO crear archivos sin esa referencia
#### Scenario: Campos de visibilidad
- **WHEN** se crea un schema
- **THEN** NO DEBE omitirse ninguno de los 3 campos obligatorios de visibilidad
#### Scenario: CSS en Renderers
- **WHEN** se implementa un Renderer
- **THEN** NO DEBE haber CSS inline
- **AND** todo via CSSGeneratorService
#### Scenario: Instanciacion de servicios
- **WHEN** se necesita un servicio
- **THEN** NO instanciar directamente con new Service()
- **AND** DEBE usarse Inyeccion de Dependencias
#### Scenario: Modificacion de campos en BD
- **WHEN** se necesita modificar campos
- **THEN** NO modificar campos en BD manualmente
- **AND** modificar el schema JSON y sincronizar
#### Scenario: Validacion de arquitectura
- **WHEN** se completa un componente
- **THEN** NO saltarse la validacion de arquitectura
- **AND** ejecutar validate-architecture.php
#### Scenario: Fases completas
- **WHEN** se crea un componente
- **THEN** NO crear componentes sin completar las 5 fases
- **AND** cada fase es obligatoria
---
### Requirement: Comandos WP-CLI
WP-CLI commands MUST be executed with the correct configuration.
#### Scenario: Ubicacion de WP-CLI
- **WHEN** se necesita ejecutar WP-CLI
- **THEN** usar C:\xampp\php_8.0.30_backup\wp-cli.phar
#### Scenario: Sincronizar un componente
- **WHEN** se sincroniza un componente especifico
- **THEN** ejecutar powershell -Command "php 'C:\xampp\php_8.0.30_backup\wp-cli.phar' roi-theme sync-component [nombre]"
#### Scenario: Sincronizar todos los componentes
- **WHEN** se sincroniza todo
- **THEN** ejecutar powershell -Command "php 'C:\xampp\php_8.0.30_backup\wp-cli.phar' roi-theme sync-all-components"
---
### Requirement: Flujo de 5 Fases Secuencial
Component creation MUST follow the exact sequence.
#### Scenario: Flujo completo de 5 fases
- **WHEN** se crea un nuevo componente
- **THEN** Fase 1 es crear Schema JSON en Schemas/[nombre].json
- **AND** Fase 2 es sincronizar con wp roi-theme sync-component [nombre]
- **AND** Fase 3 es crear Renderer en Public/[Nombre]/Infrastructure/Ui/[Nombre]Renderer.php
- **AND** Fase 4 es crear FormBuilder en Admin/[Nombre]/Infrastructure/Ui/[Nombre]FormBuilder.php
- **AND** Fase 5 es validar con validate-architecture.php [nombre]
#### Scenario: No saltar fases
- **WHEN** se desarrolla un componente
- **THEN** NO se DEBE saltar ninguna fase
- **AND** cada fase depende de la anterior
- **AND** la validacion final es obligatoria
---
### Requirement: Checklist de Componente Completo
A component MUST pass the checklist to be considered complete.
#### Scenario: Checklist de archivos
- **WHEN** se verifica un componente
- **THEN** DEBE existir Schemas/[nombre-kebab].json
- **AND** DEBE existir Public/[NombrePascal]/Infrastructure/Ui/[NombrePascal]Renderer.php
- **AND** DEBE existir Admin/[NombrePascal]/Infrastructure/Ui/[NombrePascal]FormBuilder.php
#### Scenario: Checklist de codigo
- **WHEN** se verifica el codigo
- **THEN** schema tiene los 3 campos de visibilidad
- **AND** Renderer inyecta CSSGeneratorInterface
- **AND** Renderer no tiene CSS hardcodeado
- **AND** supports() retorna kebab-case
- **AND** FormBuilder registrado con ID kebab-case
- **AND** validacion de arquitectura pasa
#### Scenario: Checklist de BD
- **WHEN** se verifica la base de datos
- **THEN** datos sincronizados en wp_roi_theme_component_settings
- **AND** component_name en kebab-case

View File

@@ -0,0 +1,255 @@
# Especificacion de Patrones WordPress
## Purpose
Define como integrar WordPress con Clean Architecture en ROITheme. WordPress tiene caracteristicas propias que requieren patrones especificos para mantener la arquitectura limpia.
## Requirements
### Requirement: Ubicacion de Hooks de WordPress
WordPress hooks (add_action, add_filter) MUST be located ONLY in Infrastructure.
#### Scenario: Hooks prohibidos en Domain
- **WHEN** el codigo esta en la capa Domain
- **THEN** NO DEBE contener add_action
- **AND** NO DEBE contener add_filter
- **AND** NO DEBE registrar callbacks de WordPress
#### Scenario: Hooks prohibidos en Application
- **WHEN** el codigo esta en la capa Application
- **THEN** NO DEBE contener add_action
- **AND** NO DEBE contener add_filter
#### Scenario: Ubicacion correcta de hooks
- **WHEN** se necesitan hooks de WordPress
- **THEN** DEBEN colocarse en Infrastructure/Wordpress/[Componente]HooksRegistrar.php
- **AND** los hooks DEBEN delegar a Use Cases
- **AND** los hooks NO DEBEN contener logica de negocio
---
### Requirement: Encapsulacion de wpdb
Access to global $wpdb MUST be encapsulated in Infrastructure repositories.
#### Scenario: wpdb prohibido en Domain
- **WHEN** el codigo esta en la capa Domain
- **THEN** NO DEBE contener global $wpdb
- **AND** NO DEBE hacer consultas directas a base de datos
#### Scenario: wpdb prohibido en Application
- **WHEN** el codigo esta en la capa Application
- **THEN** NO DEBE contener global $wpdb
- **AND** DEBE usar interfaces de repository
#### Scenario: Ubicacion correcta de wpdb
- **WHEN** se necesita acceso a base de datos
- **THEN** DEBE usarse en Infrastructure/Persistence/WordPress[Componente]Repository.php
- **AND** el repository DEBE implementar una interface definida en Domain
---
### Requirement: Ubicacion de wp_enqueue_scripts
Functions wp_enqueue_style and wp_enqueue_script MUST be located ONLY in Infrastructure.
#### Scenario: Enqueue prohibido en Domain
- **WHEN** el codigo esta en la capa Domain
- **THEN** NO DEBE contener wp_enqueue_style
- **AND** NO DEBE contener wp_enqueue_script
#### Scenario: Enqueue prohibido en Application
- **WHEN** el codigo esta en la capa Application
- **THEN** NO DEBE contener funciones de enqueue
- **AND** NO DEBE conocer detalles de assets
#### Scenario: Ubicacion correcta de enqueue
- **WHEN** se necesita cargar assets
- **THEN** DEBE colocarse en Infrastructure/Services/[Componente]AssetEnqueuer.php
- **AND** DEBE registrarse via hooks en Infrastructure
---
### Requirement: Ubicacion de register_post_type
CPT and taxonomy registration MUST be located ONLY in Infrastructure.
#### Scenario: CPT no es concepto de Domain
- **WHEN** se considera donde registrar un Custom Post Type
- **THEN** NO DEBE ir en Domain porque no es concepto de negocio
- **AND** NO DEBE ir en Application
- **AND** ES un detalle de implementacion de WordPress
#### Scenario: Ubicacion correcta de CPT
- **WHEN** se necesita registrar un Custom Post Type
- **THEN** DEBE colocarse en Infrastructure/Wordpress/[Componente]CPTRegistrar.php
---
### Requirement: Ubicacion de add_shortcode
Shortcodes MUST be located ONLY in Infrastructure and delegate to Use Cases.
#### Scenario: Shortcode prohibido en Domain y Application
- **WHEN** el codigo esta en Domain o Application
- **THEN** NO DEBE contener add_shortcode
#### Scenario: Ubicacion correcta de shortcode
- **WHEN** se necesita un shortcode
- **THEN** DEBE colocarse en Infrastructure/Wordpress/[Componente]ShortcodeRegistrar.php
- **AND** DEBE delegar la logica a un Use Case
---
### Requirement: Ubicacion de Options API
WordPress Options API MUST be encapsulated in Infrastructure repositories.
#### Scenario: Options prohibidas en Domain y Application
- **WHEN** el codigo esta en Domain o Application
- **THEN** NO DEBE contener get_option
- **AND** NO DEBE contener update_option
- **AND** NO DEBE contener delete_option
#### Scenario: Ubicacion correcta de Options
- **WHEN** se necesita acceso a opciones de WordPress
- **THEN** DEBE colocarse en Infrastructure/Persistence/WordPressSettingsRepository.php
- **AND** DEBE implementar una interface de Application
---
### Requirement: Evitar functions.php Gigante
The functions.php file MUST contain only bootstrap, not logic.
#### Scenario: functions.php correcto
- **WHEN** se implementa functions.php
- **THEN** DEBE contener solo Autoloader, Container DI y Bootstrap
- **AND** NO DEBE contener logica de negocio
- **AND** NO DEBE contener definiciones de funciones de negocio
---
### Requirement: Evitar Logica en Templates
Templates MUST contain only rendering, not business logic.
#### Scenario: Template prohibido con logica
- **WHEN** un template de WordPress existe
- **THEN** NO DEBE contener global $wpdb
- **AND** NO DEBE contener validaciones de negocio
- **AND** NO DEBE contener consultas a base de datos
- **AND** NO DEBE contener cadenas if/elseif complejas
#### Scenario: Template correcto
- **WHEN** se crea un template
- **THEN** DEBE recibir un ViewModel preparado
- **AND** DEBE contener solo HTML con escaping
- **AND** DEBE usar esc_html(), esc_attr(), esc_url()
---
### Requirement: Evitar wpdb Disperso
Usage of wpdb MUST NOT be scattered throughout the code.
#### Scenario: wpdb centralizado
- **WHEN** se necesita acceso a base de datos
- **THEN** DEBE usarse SOLO en repositories
- **AND** los repositories DEBEN estar en Infrastructure/Persistence/
- **AND** multiples archivos NO DEBEN tener global $wpdb
#### Scenario: Beneficios de centralizacion
- **WHEN** wpdb esta centralizado en repositories
- **THEN** cambiar la base de datos requiere modificar solo repositories
- **AND** el testing es posible via mocks de interface
- **AND** la logica de negocio permanece pura
---
### Requirement: Evitar Variables Globales Masivas
Code MUST NOT use massive global variables.
#### Scenario: Globales prohibidas
- **WHEN** se escribe codigo
- **THEN** NO DEBE usar global $roi_config
- **AND** NO DEBE usar singletons dispersos
- **AND** NO DEBE crear estado global
#### Scenario: Solucion con Dependency Injection
- **WHEN** se necesitan dependencias compartidas
- **THEN** DEBE usarse un Container de Inyeccion de Dependencias
- **AND** las dependencias se inyectan via constructor
- **AND** no hay estado global
---
### Requirement: Codigo Testeable
Code MUST be testable without WordPress installed.
#### Scenario: Domain testeable
- **WHEN** se escribe codigo de Domain
- **THEN** DEBE ser testeable sin base de datos
- **AND** DEBE ser testeable sin WordPress
- **AND** DEBE ser testeable sin UI
#### Scenario: Mocks via interfaces
- **WHEN** se escriben tests
- **THEN** las dependencias se mockean via interfaces
- **AND** los tests unitarios NO requieren setup complejo
- **AND** Domain puede probarse de forma aislada
---
### Requirement: Arbol de Decisiones WordPress
WordPress code MUST be located according to code type.
#### Scenario: Determinar ubicacion de hooks
- **WHEN** el codigo es add_action o add_filter
- **THEN** va en Infrastructure/Wordpress/[Componente]HooksRegistrar.php
#### Scenario: Determinar ubicacion de wpdb
- **WHEN** el codigo usa global $wpdb
- **THEN** va en Infrastructure/Persistence/WordPress[Componente]Repository.php
#### Scenario: Determinar ubicacion de enqueue
- **WHEN** el codigo usa wp_enqueue_style o wp_enqueue_script
- **THEN** va en Infrastructure/Services/[Componente]AssetEnqueuer.php
#### Scenario: Determinar ubicacion de CPT
- **WHEN** el codigo usa register_post_type o register_taxonomy
- **THEN** va en Infrastructure/Wordpress/[Componente]CPTRegistrar.php
#### Scenario: Determinar ubicacion de shortcode
- **WHEN** el codigo usa add_shortcode
- **THEN** va en Infrastructure/Wordpress/[Componente]ShortcodeRegistrar.php
#### Scenario: Determinar ubicacion de options
- **WHEN** el codigo usa get_option o update_option
- **THEN** va en Infrastructure/Persistence/WordPressSettingsRepository.php
#### Scenario: Determinar ubicacion de nonces
- **WHEN** el codigo usa wp_nonce_field o check_admin_referer
- **THEN** va en Infrastructure/Api/Wordpress/[Componente]Controller.php
---
### Requirement: Comandos de Validacion WordPress
Code MUST be validated with specific commands.
#### Scenario: Validar Domain sin WordPress
- **WHEN** se valida la capa Domain
- **THEN** grep por global $wpdb DEBE retornar vacio
- **AND** grep por add_action DEBE retornar vacio
- **AND** grep por $_POST DEBE retornar vacio
#### Scenario: Validar Application sin WordPress
- **WHEN** se valida la capa Application
- **THEN** grep por global $wpdb DEBE retornar vacio
- **AND** grep por add_action DEBE retornar vacio
- **AND** grep por wp_enqueue DEBE retornar vacio

1259
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,12 @@
{ {
"name": "roi-theme", "name": "roi-theme",
"version": "1.0.0", "version": "1.0.0",
"description": "WordPress theme con Clean Architecture para analisisdepreciosunitarios.com", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build:bootstrap": "node build-bootstrap-subset.js", "build:bootstrap": "node build-bootstrap-subset.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1",
"prepare": "husky"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -18,9 +19,11 @@
"url": "https://github.com/prime-leads-app/roi-theme/issues" "url": "https://github.com/prime-leads-app/roi-theme/issues"
}, },
"homepage": "https://github.com/prime-leads-app/roi-theme#readme", "homepage": "https://github.com/prime-leads-app/roi-theme#readme",
"description": "",
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^20.1.0",
"@commitlint/config-conventional": "^20.0.0",
"glob": "^13.0.0", "glob": "^13.0.0",
"husky": "^9.1.7",
"purgecss": "^7.0.2" "purgecss": "^7.0.2"
} }
} }