@codigodoleo/wp-kit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cspell.json +104 -0
- package/.editorconfig +13 -0
- package/.eslintignore +3 -0
- package/.eslintrc.json +24 -0
- package/.github/workflows/publish-npm.yml +32 -0
- package/.github/workflows/release-please.yml +25 -0
- package/.gitkeep +0 -0
- package/.husky/_/post-merge +0 -0
- package/.prettierignore +4 -0
- package/.prettierrc +8 -0
- package/.vscode/settings.json +19 -0
- package/CHANGELOG.md +47 -0
- package/README.md +115 -0
- package/VSCODE_EXTENSIONS.md +11 -0
- package/bin/index.js +4 -0
- package/docs/HOOKS-SYSTEM.md +172 -0
- package/git-deploy.sh +74 -0
- package/index.php +17 -0
- package/lib/cli.js +15 -0
- package/lib/commands/init.js +132 -0
- package/lib/core/generator.js +261 -0
- package/lib/core/hook-manager.js +172 -0
- package/lib/core/infer-ci-capabilities.js +119 -0
- package/lib/prompts/index.js +105 -0
- package/lib/prompts/loadModulePrompts.js +27 -0
- package/lib/utils/generate-from-template.js +17 -0
- package/lib/utils/git.js +17 -0
- package/lib/utils/logger.js +28 -0
- package/modules/deploy/index.js +39 -0
- package/modules/deploy/prompts.js +27 -0
- package/modules/deploy/templates/.github/workflows/ci.yml.hbs +103 -0
- package/modules/deploy/templates/.gitlab/gitlab-ci.yml.hbs +154 -0
- package/modules/deploy/templates/bitbucket-pipelines.yml.hbs +97 -0
- package/modules/docs/index.js +3 -0
- package/modules/docs/prompts.js +8 -0
- package/modules/docs/templates/README.md.hbs +160 -0
- package/modules/docs/templates/docs/Arquitetura.md +399 -0
- package/modules/docs/templates/docs/Deploy-Pipeline.md +113 -0
- package/modules/docs/templates/docs/Desenvolvimento.md +1116 -0
- package/modules/docs/templates/docs/Getting-Started.md +493 -0
- package/modules/docs/templates/docs/Infraestrutura.md +211 -0
- package/modules/docs/templates/docs/Monitoramento.md +302 -0
- package/modules/docs/templates/docs/Sync-the-Production-DB-with-the-Staging-DB.md +8 -0
- package/modules/docs/templates/docs/Troubleshooting.md +3 -0
- package/modules/git/.commitlintrc.json +136 -0
- package/modules/git/.github/PULL_REQUEST_TEMPLATE.md +42 -0
- package/modules/git/.gitlab/merge_request_templates/default.md +42 -0
- package/modules/git/.gitmessage +29 -0
- package/modules/git/.husky/commit-msg +4 -0
- package/modules/git/.husky/pre-commit +27 -0
- package/modules/git/.lintstagedrc.json +7 -0
- package/modules/git/.vscode/commit-instructions.md +59 -0
- package/modules/git/.vscode/conventional-commits.code-snippets +62 -0
- package/modules/git/.vscode/copilot.json +39 -0
- package/modules/git/docs/CONVENTIONAL-COMMITS.md +131 -0
- package/modules/git/index.js +137 -0
- package/modules/git/prompts.js +23 -0
- package/modules/git/templates/.lando.yml.hbs +13 -0
- package/modules/git/templates/package.json.hbs +15 -0
- package/modules/git/templates/workspace.json.hbs +114 -0
- package/modules/lint/.eslintignore +36 -0
- package/modules/lint/.eslintrc.json +8 -0
- package/modules/lint/.prettierignore +36 -0
- package/modules/lint/.prettierrc.json +29 -0
- package/modules/lint/.stylelintignore +19 -0
- package/modules/lint/.stylelintrc.json +9 -0
- package/modules/lint/index.js +15 -0
- package/modules/lint/pint.json +26 -0
- package/modules/lint/prompts.js +16 -0
- package/modules/lint/templates/.lando.yml.hbs +10 -0
- package/modules/lint/templates/package.json.hbs +16 -0
- package/modules/lint/templates/workspace.json.hbs +56 -0
- package/modules/php/index.js +3 -0
- package/modules/php/prompts.js +8 -0
- package/modules/php/scripts/php-wrapper.sh +38 -0
- package/modules/php/scripts/pint-wrapper.sh +44 -0
- package/modules/php/templates/.lando.yml.hbs +11 -0
- package/modules/php/templates/composer.json.hbs +6 -0
- package/modules/php/templates/workspace.json.hbs +74 -0
- package/modules/redis/prompts.js +8 -0
- package/modules/redis/templates/.lando.yml.hbs +8 -0
- package/modules/sage/index.js +20 -0
- package/modules/sage/prompts.js +16 -0
- package/modules/sage/templates/.lando.yml.hbs +64 -0
- package/modules/sage/templates/theme/composer.json.hbs +18 -0
- package/modules/sage/templates/theme/package.json.hbs +11 -0
- package/modules/sage/templates/theme/style.css.hbs +13 -0
- package/modules/sage/templates/theme/vite.config.js.hbs +53 -0
- package/modules/sage/templates/workspace.json.hbs +67 -0
- package/modules/test-directory/assets/module-file.txt +1 -0
- package/modules/test-directory/index.js +19 -0
- package/modules/test-directory/prompts.js +8 -0
- package/modules/test-directory/test-assets/file1.txt +1 -0
- package/modules/test-directory/test-assets/file2.txt +1 -0
- package/modules/test-directory/test-assets/subfolder/config.json +4 -0
- package/package.json +54 -0
- package/release-please-config.json +17 -0
- package/server/php/php.ini +48 -0
- package/server/www/rocket.conf +283 -0
- package/templates/.editorconfig.hbs +39 -0
- package/templates/.env.hbs +48 -0
- package/templates/.gitignore.hbs +86 -0
- package/templates/.lando.yml.hbs +44 -0
- package/templates/README.md.hbs +12 -0
- package/templates/composer.json.hbs +60 -0
- package/templates/package.json.hbs +47 -0
- package/templates/server/cmd/install-wp.sh.hbs +58 -0
- package/templates/server/www/vhosts.conf.hbs +71 -0
- package/templates/workspace.json.hbs +177 -0
- package/test-copy-directory.js +43 -0
- package/test-overwrite.js +45 -0
- package/wp-config.php +190 -0
|
@@ -0,0 +1,1116 @@
|
|
|
1
|
+
# 💻 Desenvolvimento
|
|
2
|
+
|
|
3
|
+
Guia completo de desenvolvimento para o projeto Pipefy Website, com foco em qualidade, padrões e boas práticas profissionais.
|
|
4
|
+
|
|
5
|
+
## 🌊 **Git Workflow (GitFlow Modificado)**
|
|
6
|
+
|
|
7
|
+
### **Estratégia de Branching**
|
|
8
|
+
|
|
9
|
+
Nossa estratégia é baseada no **GitFlow**, com uma modificação importante: **todas as branches são criadas a partir da `master`** para garantir que features em desenvolvimento não sejam levadas acidentalmente para produção.
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
graph LR
|
|
13
|
+
A[master] --> B[feature/new-feature]
|
|
14
|
+
A --> C[feature/another-feature]
|
|
15
|
+
A --> D[hotfix/critical-fix]
|
|
16
|
+
A --> E[release/v1.2.0]
|
|
17
|
+
|
|
18
|
+
B --> F[MR to development]
|
|
19
|
+
C --> F
|
|
20
|
+
E --> G[MR to staging]
|
|
21
|
+
F --> H[development]
|
|
22
|
+
G --> I[staging]
|
|
23
|
+
H --> J[MR to staging]
|
|
24
|
+
J --> I
|
|
25
|
+
I --> K[MR to master]
|
|
26
|
+
K --> L[master]
|
|
27
|
+
|
|
28
|
+
D --> M[MR to master]
|
|
29
|
+
M --> L
|
|
30
|
+
D --> N[MR to development]
|
|
31
|
+
N --> H
|
|
32
|
+
|
|
33
|
+
style A fill:#ff6b6b
|
|
34
|
+
style H fill:#feca57
|
|
35
|
+
style I fill:#48dbfb
|
|
36
|
+
style L fill:#1dd1a1
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### **Tipos de Branches**
|
|
40
|
+
|
|
41
|
+
| Branch Type | Prefixo | Origem | Destino | Merge Via | Finalidade |
|
|
42
|
+
|-------------|---------|--------|---------|-----------|------------|
|
|
43
|
+
| **Feature** | `feature/` | `master` | `development` | **MR** | Novas funcionalidades |
|
|
44
|
+
| **Bugfix** | `bugfix/` | `master` | `development` | **MR** | Correções não-críticas |
|
|
45
|
+
| **Hotfix** | `hotfix/` | `master` | `master` + `development` | **MR** | Correções críticas |
|
|
46
|
+
| **Release** | `release/` | `master` | `staging` → `master` | **MR** | Preparação de releases |
|
|
47
|
+
| **Chore** | `chore/` | `master` | `development` | **MR** | Manutenção, docs, etc. |
|
|
48
|
+
|
|
49
|
+
### **Nomenclatura de Branches**
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# ✅ Correto (sempre em inglês)
|
|
53
|
+
feature/user-authentication
|
|
54
|
+
feature/payment-integration
|
|
55
|
+
bugfix/header-responsive-issue
|
|
56
|
+
hotfix/critical-security-patch
|
|
57
|
+
release/v1.2.0
|
|
58
|
+
chore/update-dependencies
|
|
59
|
+
|
|
60
|
+
# ❌ Incorreto
|
|
61
|
+
feature/autenticacao-usuario
|
|
62
|
+
feature/NewFeature
|
|
63
|
+
bugfix/bug_fix
|
|
64
|
+
feature-payment
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## 🔄 **Workflow de Desenvolvimento**
|
|
68
|
+
|
|
69
|
+
### **1. Criando uma Nova Feature**
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# 1. Sempre partir da master atualizada
|
|
73
|
+
git checkout master
|
|
74
|
+
git pull origin master
|
|
75
|
+
|
|
76
|
+
# 2. Criar branch seguindo padrão
|
|
77
|
+
git checkout -b feature/user-profile-enhancement
|
|
78
|
+
|
|
79
|
+
# 3. Desenvolver com commits bem documentados
|
|
80
|
+
git add .
|
|
81
|
+
git commit -m "feat: add user profile avatar upload functionality"
|
|
82
|
+
|
|
83
|
+
# 4. Push da branch
|
|
84
|
+
git push origin feature/user-profile-enhancement
|
|
85
|
+
|
|
86
|
+
# 5. Criar Merge Request para development (OBRIGATÓRIO)
|
|
87
|
+
# Via GitLab interface - NUNCA merge direto
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### **2. Fluxo de Merge Requests (Processo Obrigatório)**
|
|
91
|
+
|
|
92
|
+
```mermaid
|
|
93
|
+
graph TD
|
|
94
|
+
A[Feature Branch] --> B[Create MR to development]
|
|
95
|
+
B --> C[Code Review]
|
|
96
|
+
C --> D{Review Approved?}
|
|
97
|
+
D -->|No| E[Address Feedback]
|
|
98
|
+
E --> C
|
|
99
|
+
D -->|Yes| F[✅ Merge to development via MR]
|
|
100
|
+
F --> G[Auto Deploy to development-www.pipefy.com]
|
|
101
|
+
G --> H[QA Testing]
|
|
102
|
+
H --> I[✅ Create MR: development → staging]
|
|
103
|
+
I --> J[Code Review + Approval]
|
|
104
|
+
J --> K[✅ Merge to staging via MR]
|
|
105
|
+
K --> L[Deploy to staging-www.pipefy.com]
|
|
106
|
+
L --> M[Final Validation]
|
|
107
|
+
M --> N[✅ Create MR: staging → master]
|
|
108
|
+
N --> O[Final Code Review + Approval]
|
|
109
|
+
O --> P[✅ Merge to master via MR]
|
|
110
|
+
P --> Q[Deploy to www.pipefy.com]
|
|
111
|
+
|
|
112
|
+
style F fill:#1dd1a1
|
|
113
|
+
style K fill:#1dd1a1
|
|
114
|
+
style P fill:#1dd1a1
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### **3. Preparação de Release (Via Merge Requests)**
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# 1. Criar branch de release a partir da master
|
|
121
|
+
git checkout master
|
|
122
|
+
git pull origin master
|
|
123
|
+
git checkout -b release/v1.2.0
|
|
124
|
+
|
|
125
|
+
# 2. Atualizar versões e changelog
|
|
126
|
+
# - Atualizar version em style.css
|
|
127
|
+
# - Atualizar CHANGELOG.md
|
|
128
|
+
# - Commit de preparação
|
|
129
|
+
|
|
130
|
+
git add .
|
|
131
|
+
git commit -m "chore: prepare release v1.2.0"
|
|
132
|
+
git push origin release/v1.2.0
|
|
133
|
+
|
|
134
|
+
# 3. MERGE REQUEST para staging (OBRIGATÓRIO)
|
|
135
|
+
# Via GitLab interface:
|
|
136
|
+
# - Create MR: release/v1.2.0 → staging
|
|
137
|
+
# - Assign reviewers
|
|
138
|
+
# - Wait for approval
|
|
139
|
+
# - Merge via MR
|
|
140
|
+
|
|
141
|
+
# 4. Após validação em staging, MERGE REQUEST para master (OBRIGATÓRIO)
|
|
142
|
+
# Via GitLab interface:
|
|
143
|
+
# - Create MR: staging → master
|
|
144
|
+
# - Assign senior reviewers
|
|
145
|
+
# - Wait for approval
|
|
146
|
+
# - Merge via MR
|
|
147
|
+
|
|
148
|
+
# 5. Criar tag (APÓS merge para master)
|
|
149
|
+
git checkout master
|
|
150
|
+
git pull origin master
|
|
151
|
+
git tag -a v1.2.0 -m "Release version 1.2.0"
|
|
152
|
+
git push origin v1.2.0
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### **4. Processo de Hotfix (Via Merge Requests)**
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# 1. Criar hotfix a partir da master
|
|
159
|
+
git checkout master
|
|
160
|
+
git pull origin master
|
|
161
|
+
git checkout -b hotfix/critical-security-patch
|
|
162
|
+
|
|
163
|
+
# 2. Implementar correção crítica
|
|
164
|
+
git add .
|
|
165
|
+
git commit -m "fix: patch critical security vulnerability in user authentication"
|
|
166
|
+
git push origin hotfix/critical-security-patch
|
|
167
|
+
|
|
168
|
+
# 3. DUAS Merge Requests simultâneas (OBRIGATÓRIO)
|
|
169
|
+
#
|
|
170
|
+
# MR 1: hotfix → master (para produção imediata)
|
|
171
|
+
# - Create MR: hotfix/critical-security-patch → master
|
|
172
|
+
# - Assign senior reviewers
|
|
173
|
+
# - Mark as URGENT
|
|
174
|
+
# - Merge after approval
|
|
175
|
+
#
|
|
176
|
+
# MR 2: hotfix → development (para sincronização)
|
|
177
|
+
# - Create MR: hotfix/critical-security-patch → development
|
|
178
|
+
# - Assign reviewers
|
|
179
|
+
# - Merge after MR 1 is completed
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## 📋 **Merge Request Guidelines**
|
|
183
|
+
|
|
184
|
+
### **Template de Merge Request**
|
|
185
|
+
|
|
186
|
+
```markdown
|
|
187
|
+
## 🎯 Merge Request Title
|
|
188
|
+
Brief description of changes
|
|
189
|
+
|
|
190
|
+
## 📝 Description
|
|
191
|
+
Detailed description of what this MR does and why.
|
|
192
|
+
|
|
193
|
+
## 🔗 Related Issues
|
|
194
|
+
- Closes #123
|
|
195
|
+
- Relates to #456
|
|
196
|
+
|
|
197
|
+
## 🧪 Testing
|
|
198
|
+
- [ ] Unit tests pass
|
|
199
|
+
- [ ] Integration tests pass
|
|
200
|
+
- [ ] Manual testing completed
|
|
201
|
+
- [ ] Tested in local environment
|
|
202
|
+
|
|
203
|
+
## 📋 Checklist
|
|
204
|
+
- [ ] Code follows project standards
|
|
205
|
+
- [ ] All tests pass
|
|
206
|
+
- [ ] Documentation updated
|
|
207
|
+
- [ ] CHANGELOG.md updated (if user-facing)
|
|
208
|
+
- [ ] No breaking changes (or properly documented)
|
|
209
|
+
|
|
210
|
+
## 🖼️ Screenshots (if applicable)
|
|
211
|
+
Before/After screenshots for UI changes
|
|
212
|
+
|
|
213
|
+
## 🚀 Deployment Notes
|
|
214
|
+
Any special deployment considerations
|
|
215
|
+
|
|
216
|
+
## 👥 Reviewers
|
|
217
|
+
@senior-dev @team-lead
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### **Aprovações Obrigatórias por Branch**
|
|
221
|
+
|
|
222
|
+
| Target Branch | Reviewers Required | Auto-merge | Finalidade |
|
|
223
|
+
|---------------|-------------------|------------|------------|
|
|
224
|
+
| **development** | 1 senior dev | ❌ | Features, bugfixes |
|
|
225
|
+
| **staging** | 2 senior devs | ❌ | Release preparation |
|
|
226
|
+
| **master** | 2 senior devs + 1 lead | ❌ | Production releases |
|
|
227
|
+
|
|
228
|
+
### **Configuração GitLab (Merge Request Rules)**
|
|
229
|
+
|
|
230
|
+
```yaml
|
|
231
|
+
# .gitlab/merge_request_templates/default.md
|
|
232
|
+
push_rules:
|
|
233
|
+
development:
|
|
234
|
+
required_approvals: 1
|
|
235
|
+
required_approval_groups: ["senior-developers"]
|
|
236
|
+
allow_force_push: false
|
|
237
|
+
|
|
238
|
+
staging:
|
|
239
|
+
required_approvals: 2
|
|
240
|
+
required_approval_groups: ["senior-developers"]
|
|
241
|
+
allow_force_push: false
|
|
242
|
+
require_code_owner_reviews: true
|
|
243
|
+
|
|
244
|
+
master:
|
|
245
|
+
required_approvals: 2
|
|
246
|
+
required_approval_groups: ["senior-developers", "tech-leads"]
|
|
247
|
+
allow_force_push: false
|
|
248
|
+
require_code_owner_reviews: true
|
|
249
|
+
dismiss_stale_reviews: true
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## 🚫 **Práticas Proibidas**
|
|
253
|
+
|
|
254
|
+
### **❌ Nunca Fazer**
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
# ❌ PROIBIDO: Merge direto sem MR
|
|
258
|
+
git checkout staging
|
|
259
|
+
git merge development # NUNCA!
|
|
260
|
+
|
|
261
|
+
# ❌ PROIBIDO: Push direto para branches protegidas
|
|
262
|
+
git push origin master # NUNCA!
|
|
263
|
+
|
|
264
|
+
# ❌ PROIBIDO: Commits diretos em branches protegidas
|
|
265
|
+
git checkout master
|
|
266
|
+
git commit -m "quick fix" # NUNCA!
|
|
267
|
+
|
|
268
|
+
# ❌ PROIBIDO: Force push em branches compartilhadas
|
|
269
|
+
git push --force origin development # NUNCA!
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### **✅ Sempre Fazer**
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
# ✅ CORRETO: Sempre via Merge Request
|
|
276
|
+
# 1. Create branch
|
|
277
|
+
git checkout -b feature/my-feature
|
|
278
|
+
|
|
279
|
+
# 2. Develop and commit
|
|
280
|
+
git commit -m "feat: add new functionality"
|
|
281
|
+
|
|
282
|
+
# 3. Push branch
|
|
283
|
+
git push origin feature/my-feature
|
|
284
|
+
|
|
285
|
+
# 4. Create MR via GitLab interface
|
|
286
|
+
# 5. Wait for review and approval
|
|
287
|
+
# 6. Merge via GitLab interface
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## 📦 **Gerenciamento de Dependências com Composer**
|
|
291
|
+
|
|
292
|
+
### **Configuração do Composer**
|
|
293
|
+
|
|
294
|
+
```json
|
|
295
|
+
{
|
|
296
|
+
"name": "pipefy/wordpress-website",
|
|
297
|
+
"description": "Pipefy WordPress Website",
|
|
298
|
+
"type": "project",
|
|
299
|
+
"require": {
|
|
300
|
+
"php": ">=8.0",
|
|
301
|
+
"composer/installers": "^2.0",
|
|
302
|
+
"wpackagist-plugin/advanced-custom-fields-pro": "*",
|
|
303
|
+
"wpackagist-plugin/wp-rocket": "*"
|
|
304
|
+
},
|
|
305
|
+
"require-dev": {
|
|
306
|
+
"phpunit/phpunit": "^9.0",
|
|
307
|
+
"squizlabs/php_codesniffer": "*",
|
|
308
|
+
"dealerdirect/phpcodesniffer-composer-installer": "*",
|
|
309
|
+
"wp-coding-standards/wpcs": "*"
|
|
310
|
+
},
|
|
311
|
+
"repositories": [
|
|
312
|
+
{
|
|
313
|
+
"type": "composer",
|
|
314
|
+
"url": "https://wpackagist.org"
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
"type": "package",
|
|
318
|
+
"package": {
|
|
319
|
+
"name": "advanced-custom-fields/advanced-custom-fields-pro",
|
|
320
|
+
"version": "6.0.0",
|
|
321
|
+
"type": "wordpress-plugin",
|
|
322
|
+
"dist": {
|
|
323
|
+
"type": "zip",
|
|
324
|
+
"url": "https://connect.advancedcustomfields.com/..."
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
],
|
|
329
|
+
"extra": {
|
|
330
|
+
"installer-paths": {
|
|
331
|
+
"dist/wp-content/plugins/{$name}/": ["type:wordpress-plugin"],
|
|
332
|
+
"dist/wp-content/themes/{$name}/": ["type:wordpress-theme"]
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
"autoload": {
|
|
336
|
+
"psr-4": {
|
|
337
|
+
"Pipefy\\": "dist/wp-content/themes/pipefy-2020/inc/"
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
"scripts": {
|
|
341
|
+
"install-plugins": "composer install --no-dev",
|
|
342
|
+
"test": "phpunit",
|
|
343
|
+
"lint": "phpcs --standard=WordPress dist/wp-content/themes/pipefy-2020/",
|
|
344
|
+
"format": "phpcbf --standard=WordPress dist/wp-content/themes/pipefy-2020/"
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### **Instalação de Plugins**
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
# Plugins do repositório WordPress.org
|
|
353
|
+
composer require wpackagist-plugin/contact-form-7
|
|
354
|
+
|
|
355
|
+
# Plugins premium (configurar repositório privado)
|
|
356
|
+
composer require advanced-custom-fields/advanced-custom-fields-pro
|
|
357
|
+
|
|
358
|
+
# Plugins de desenvolvimento
|
|
359
|
+
composer require --dev phpunit/phpunit
|
|
360
|
+
|
|
361
|
+
# Atualizar todas as dependências
|
|
362
|
+
composer update
|
|
363
|
+
|
|
364
|
+
# Instalar apenas dependências de produção
|
|
365
|
+
composer install --no-dev --optimize-autoloader
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### **Estrutura de Plugins Recomendada**
|
|
369
|
+
|
|
370
|
+
```
|
|
371
|
+
dist/wp-content/
|
|
372
|
+
├── 📂 plugins/ # Plugins via Composer
|
|
373
|
+
│ ├── 📂 advanced-custom-fields-pro/
|
|
374
|
+
│ ├── 📂 contact-form-7/
|
|
375
|
+
│ └── 📂 wp-rocket/
|
|
376
|
+
├── 📂 mu-plugins/ # Must-use plugins (custom)
|
|
377
|
+
│ ├── 📄 pipefy-core.php # Core functionality
|
|
378
|
+
│ ├── 📄 pipefy-security.php # Security enhancements
|
|
379
|
+
│ └── 📄 pipefy-performance.php # Performance optimizations
|
|
380
|
+
└── 📂 themes/pipefy-2020/
|
|
381
|
+
└── 📂 vendor/ # Autoloaded classes
|
|
382
|
+
└── 📂 composer/
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## 🏷️ **Versionamento e Releases**
|
|
386
|
+
|
|
387
|
+
### **Semantic Versioning (SemVer)**
|
|
388
|
+
|
|
389
|
+
Seguimos o padrão **SemVer**: `MAJOR.MINOR.PATCH`
|
|
390
|
+
|
|
391
|
+
```
|
|
392
|
+
v1.2.3
|
|
393
|
+
│ │ │
|
|
394
|
+
│ │ └── PATCH: Bug fixes, hotfixes
|
|
395
|
+
│ └──── MINOR: New features, backward compatible
|
|
396
|
+
└────── MAJOR: Breaking changes, major updates
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### **Versionamento do WordPress Core**
|
|
400
|
+
|
|
401
|
+
```bash
|
|
402
|
+
# Arquivo: dist/wp-content/themes/pipefy-2020/style.css
|
|
403
|
+
/*
|
|
404
|
+
Theme Name: Pipefy 2020
|
|
405
|
+
Description: Custom WordPress theme for Pipefy website
|
|
406
|
+
Version: 1.2.3
|
|
407
|
+
Author: Pipefy Dev Team
|
|
408
|
+
*/
|
|
409
|
+
|
|
410
|
+
# Arquivo: dist/wp-content/themes/pipefy-2020/functions.php
|
|
411
|
+
define('PIPEFY_THEME_VERSION', '1.2.3');
|
|
412
|
+
|
|
413
|
+
# Uso no tema
|
|
414
|
+
wp_enqueue_style('pipefy-main', get_theme_file_uri('assets/css/main.css'), [], PIPEFY_THEME_VERSION);
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### **Automatização de Releases**
|
|
418
|
+
|
|
419
|
+
```yaml
|
|
420
|
+
# .gitlab-ci.yml - Job de Release
|
|
421
|
+
create_release:
|
|
422
|
+
stage: release
|
|
423
|
+
script:
|
|
424
|
+
- echo "Creating release v${CI_COMMIT_TAG}"
|
|
425
|
+
- |
|
|
426
|
+
# Atualizar version no style.css
|
|
427
|
+
sed -i "s/Version: .*/Version: ${CI_COMMIT_TAG#v}/" dist/wp-content/themes/pipefy-2020/style.css
|
|
428
|
+
|
|
429
|
+
# Atualizar version no functions.php
|
|
430
|
+
sed -i "s/PIPEFY_THEME_VERSION', '.*'/PIPEFY_THEME_VERSION', '${CI_COMMIT_TAG#v}'/" dist/wp-content/themes/pipefy-2020/functions.php
|
|
431
|
+
|
|
432
|
+
# Commit das mudanças
|
|
433
|
+
git add .
|
|
434
|
+
git commit -m "chore: bump version to ${CI_COMMIT_TAG}"
|
|
435
|
+
git push origin HEAD:master
|
|
436
|
+
|
|
437
|
+
- echo "Release ${CI_COMMIT_TAG} created successfully"
|
|
438
|
+
only:
|
|
439
|
+
- tags
|
|
440
|
+
when: manual
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### **CHANGELOG.md Structure**
|
|
444
|
+
|
|
445
|
+
```markdown
|
|
446
|
+
# Changelog
|
|
447
|
+
|
|
448
|
+
All notable changes to this project will be documented in this file.
|
|
449
|
+
|
|
450
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
451
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
452
|
+
|
|
453
|
+
## [Unreleased]
|
|
454
|
+
|
|
455
|
+
### Added
|
|
456
|
+
- New feature in development
|
|
457
|
+
|
|
458
|
+
### Changed
|
|
459
|
+
- Improved existing functionality
|
|
460
|
+
|
|
461
|
+
### Fixed
|
|
462
|
+
- Bug fixes
|
|
463
|
+
|
|
464
|
+
## [1.2.3] - 2025-06-05
|
|
465
|
+
|
|
466
|
+
### Added
|
|
467
|
+
- User profile avatar upload functionality
|
|
468
|
+
- Enhanced security measures for file uploads
|
|
469
|
+
- New Gutenberg block for testimonials
|
|
470
|
+
|
|
471
|
+
### Changed
|
|
472
|
+
- Improved performance of image loading
|
|
473
|
+
- Updated WordPress core to latest version
|
|
474
|
+
- Refactored authentication system
|
|
475
|
+
|
|
476
|
+
### Fixed
|
|
477
|
+
- Fixed responsive header issue on mobile devices
|
|
478
|
+
- Resolved caching issue with dynamic content
|
|
479
|
+
- Fixed accessibility issues in navigation
|
|
480
|
+
|
|
481
|
+
### Security
|
|
482
|
+
- Patched XSS vulnerability in contact form
|
|
483
|
+
- Updated dependencies with security fixes
|
|
484
|
+
|
|
485
|
+
## [1.2.2] - 2025-05-23
|
|
486
|
+
...
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
## 📝 **Padrões de Código e Nomenclatura**
|
|
490
|
+
|
|
491
|
+
### **Nomenclatura em Inglês (Obrigatório)**
|
|
492
|
+
|
|
493
|
+
```php
|
|
494
|
+
// ✅ Correto
|
|
495
|
+
class UserProfileManager {
|
|
496
|
+
private $userRepository;
|
|
497
|
+
|
|
498
|
+
public function updateUserAvatar($userId, $avatarData) {
|
|
499
|
+
// implementation
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
private function validateImageFormat($imageData) {
|
|
503
|
+
// implementation
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// ❌ Incorreto
|
|
508
|
+
class GerenciadorPerfilUsuario {
|
|
509
|
+
private $repositorioUsuario;
|
|
510
|
+
|
|
511
|
+
public function atualizarAvatarUsuario($idUsuario, $dadosAvatar) {
|
|
512
|
+
// implementation
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
### **Padrões de Naming Convention**
|
|
518
|
+
|
|
519
|
+
```php
|
|
520
|
+
// Classes: PascalCase
|
|
521
|
+
class PaymentProcessor {}
|
|
522
|
+
class UserAuthenticationService {}
|
|
523
|
+
|
|
524
|
+
// Methods/Functions: camelCase
|
|
525
|
+
public function processPayment() {}
|
|
526
|
+
private function validateCreditCard() {}
|
|
527
|
+
|
|
528
|
+
// Variables: camelCase
|
|
529
|
+
$userName = 'john_doe';
|
|
530
|
+
$isUserLoggedIn = true;
|
|
531
|
+
$paymentGatewayConfig = [];
|
|
532
|
+
|
|
533
|
+
// Constants: UPPER_SNAKE_CASE
|
|
534
|
+
define('MAX_UPLOAD_SIZE', 5242880);
|
|
535
|
+
const API_BASE_URL = 'https://api.pipefy.com';
|
|
536
|
+
|
|
537
|
+
// Files: kebab-case
|
|
538
|
+
user-profile-manager.php
|
|
539
|
+
payment-gateway-config.php
|
|
540
|
+
|
|
541
|
+
// CSS Classes: BEM Methodology
|
|
542
|
+
.user-profile {}
|
|
543
|
+
.user-profile__avatar {}
|
|
544
|
+
.user-profile__avatar--large {}
|
|
545
|
+
.user-profile__info {}
|
|
546
|
+
.user-profile__info--highlighted {}
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
### **BEM (Block Element Modifier) CSS**
|
|
550
|
+
|
|
551
|
+
```scss
|
|
552
|
+
// Block: componente independente
|
|
553
|
+
.hero-section {
|
|
554
|
+
padding: 2rem;
|
|
555
|
+
background: #fff;
|
|
556
|
+
|
|
557
|
+
// Element: parte do block
|
|
558
|
+
&__title {
|
|
559
|
+
font-size: 2.5rem;
|
|
560
|
+
font-weight: bold;
|
|
561
|
+
color: #333;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
&__subtitle {
|
|
565
|
+
font-size: 1.2rem;
|
|
566
|
+
color: #666;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
&__button {
|
|
570
|
+
padding: 1rem 2rem;
|
|
571
|
+
background: #007cba;
|
|
572
|
+
color: white;
|
|
573
|
+
border: none;
|
|
574
|
+
|
|
575
|
+
// Modifier: variação do element
|
|
576
|
+
&--large {
|
|
577
|
+
padding: 1.5rem 3rem;
|
|
578
|
+
font-size: 1.2rem;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
&--secondary {
|
|
582
|
+
background: #666;
|
|
583
|
+
color: white;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// Modifier: variação do block
|
|
588
|
+
&--dark-theme {
|
|
589
|
+
background: #333;
|
|
590
|
+
color: white;
|
|
591
|
+
|
|
592
|
+
.hero-section__title {
|
|
593
|
+
color: white;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
### **DRY (Don't Repeat Yourself) Principles**
|
|
600
|
+
|
|
601
|
+
```php
|
|
602
|
+
// ❌ Código repetitivo
|
|
603
|
+
class UserController {
|
|
604
|
+
public function updateProfile($userId, $data) {
|
|
605
|
+
$user = get_user_by('ID', $userId);
|
|
606
|
+
if (!$user) {
|
|
607
|
+
wp_send_json_error('User not found', 404);
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
if (!current_user_can('edit_user', $userId)) {
|
|
612
|
+
wp_send_json_error('Insufficient permissions', 403);
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// Update logic
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
public function deleteProfile($userId) {
|
|
620
|
+
$user = get_user_by('ID', $userId);
|
|
621
|
+
if (!$user) {
|
|
622
|
+
wp_send_json_error('User not found', 404);
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
if (!current_user_can('delete_user', $userId)) {
|
|
627
|
+
wp_send_json_error('Insufficient permissions', 403);
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// Delete logic
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
// ✅ Aplicando DRY
|
|
636
|
+
class UserController {
|
|
637
|
+
private function validateUserAccess($userId, $capability) {
|
|
638
|
+
$user = get_user_by('ID', $userId);
|
|
639
|
+
if (!$user) {
|
|
640
|
+
wp_send_json_error('User not found', 404);
|
|
641
|
+
return false;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
if (!current_user_can($capability, $userId)) {
|
|
645
|
+
wp_send_json_error('Insufficient permissions', 403);
|
|
646
|
+
return false;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
return $user;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
public function updateProfile($userId, $data) {
|
|
653
|
+
$user = $this->validateUserAccess($userId, 'edit_user');
|
|
654
|
+
if (!$user) return;
|
|
655
|
+
|
|
656
|
+
// Update logic
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
public function deleteProfile($userId) {
|
|
660
|
+
$user = $this->validateUserAccess($userId, 'delete_user');
|
|
661
|
+
if (!$user) return;
|
|
662
|
+
|
|
663
|
+
// Delete logic
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
## 🏗️ **Arquitetura de Código (Padrões Laravel)**
|
|
669
|
+
|
|
670
|
+
### **Service Layer Pattern**
|
|
671
|
+
|
|
672
|
+
```php
|
|
673
|
+
// app/Services/UserService.php
|
|
674
|
+
namespace Pipefy\Services;
|
|
675
|
+
|
|
676
|
+
class UserService {
|
|
677
|
+
private $userRepository;
|
|
678
|
+
private $emailService;
|
|
679
|
+
|
|
680
|
+
public function __construct(UserRepository $userRepository, EmailService $emailService) {
|
|
681
|
+
$this->userRepository = $userRepository;
|
|
682
|
+
$this->emailService = $emailService;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
public function createUser(array $userData): User {
|
|
686
|
+
$this->validateUserData($userData);
|
|
687
|
+
|
|
688
|
+
$user = $this->userRepository->create($userData);
|
|
689
|
+
$this->emailService->sendWelcomeEmail($user);
|
|
690
|
+
|
|
691
|
+
return $user;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
private function validateUserData(array $data): void {
|
|
695
|
+
if (empty($data['email'])) {
|
|
696
|
+
throw new InvalidArgumentException('Email is required');
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
|
|
700
|
+
throw new InvalidArgumentException('Invalid email format');
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
```
|
|
705
|
+
|
|
706
|
+
### **Repository Pattern**
|
|
707
|
+
|
|
708
|
+
```php
|
|
709
|
+
// app/Repositories/UserRepository.php
|
|
710
|
+
namespace Pipefy\Repositories;
|
|
711
|
+
|
|
712
|
+
interface UserRepositoryInterface {
|
|
713
|
+
public function find(int $id): ?User;
|
|
714
|
+
public function create(array $data): User;
|
|
715
|
+
public function update(int $id, array $data): User;
|
|
716
|
+
public function delete(int $id): bool;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
class UserRepository implements UserRepositoryInterface {
|
|
720
|
+
public function find(int $id): ?User {
|
|
721
|
+
$userData = get_user_by('ID', $id);
|
|
722
|
+
return $userData ? new User($userData) : null;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
public function create(array $data): User {
|
|
726
|
+
$userId = wp_insert_user($data);
|
|
727
|
+
|
|
728
|
+
if (is_wp_error($userId)) {
|
|
729
|
+
throw new Exception('Failed to create user: ' . $userId->get_error_message());
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
return $this->find($userId);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
public function update(int $id, array $data): User {
|
|
736
|
+
$data['ID'] = $id;
|
|
737
|
+
$result = wp_update_user($data);
|
|
738
|
+
|
|
739
|
+
if (is_wp_error($result)) {
|
|
740
|
+
throw new Exception('Failed to update user: ' . $result->get_error_message());
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
return $this->find($id);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
public function delete(int $id): bool {
|
|
747
|
+
return wp_delete_user($id);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
### **Model Layer**
|
|
753
|
+
|
|
754
|
+
```php
|
|
755
|
+
// app/Models/User.php
|
|
756
|
+
namespace Pipefy\Models;
|
|
757
|
+
|
|
758
|
+
class User {
|
|
759
|
+
private $id;
|
|
760
|
+
private $email;
|
|
761
|
+
private $firstName;
|
|
762
|
+
private $lastName;
|
|
763
|
+
private $avatar;
|
|
764
|
+
|
|
765
|
+
public function __construct($userData) {
|
|
766
|
+
$this->id = $userData->ID;
|
|
767
|
+
$this->email = $userData->user_email;
|
|
768
|
+
$this->firstName = $userData->first_name;
|
|
769
|
+
$this->lastName = $userData->last_name;
|
|
770
|
+
$this->avatar = get_user_meta($userData->ID, 'avatar', true);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
public function getId(): int {
|
|
774
|
+
return $this->id;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
public function getEmail(): string {
|
|
778
|
+
return $this->email;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
public function getFullName(): string {
|
|
782
|
+
return trim($this->firstName . ' ' . $this->lastName);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
public function getAvatar(): ?string {
|
|
786
|
+
return $this->avatar;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
public function toArray(): array {
|
|
790
|
+
return [
|
|
791
|
+
'id' => $this->id,
|
|
792
|
+
'email' => $this->email,
|
|
793
|
+
'first_name' => $this->firstName,
|
|
794
|
+
'last_name' => $this->lastName,
|
|
795
|
+
'full_name' => $this->getFullName(),
|
|
796
|
+
'avatar' => $this->avatar
|
|
797
|
+
];
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
```
|
|
801
|
+
|
|
802
|
+
## 🧪 **Qualidade e Testes**
|
|
803
|
+
|
|
804
|
+
### **PHP CodeSniffer (PHPCS)**
|
|
805
|
+
|
|
806
|
+
```bash
|
|
807
|
+
# Instalar dependências de desenvolvimento
|
|
808
|
+
composer require --dev squizlabs/php_codesniffer
|
|
809
|
+
composer require --dev wp-coding-standards/wpcs
|
|
810
|
+
|
|
811
|
+
# Configurar padrões WordPress
|
|
812
|
+
./vendor/bin/phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs
|
|
813
|
+
|
|
814
|
+
# Verificar código
|
|
815
|
+
./vendor/bin/phpcs --standard=WordPress dist/wp-content/themes/pipefy-2020/
|
|
816
|
+
|
|
817
|
+
# Corrigir automaticamente (quando possível)
|
|
818
|
+
./vendor/bin/phpcbf --standard=WordPress dist/wp-content/themes/pipefy-2020/
|
|
819
|
+
```
|
|
820
|
+
|
|
821
|
+
### **Configuração PHPCS**
|
|
822
|
+
|
|
823
|
+
```xml
|
|
824
|
+
<!-- phpcs.xml -->
|
|
825
|
+
<?xml version="1.0"?>
|
|
826
|
+
<ruleset name="Pipefy WordPress Coding Standards">
|
|
827
|
+
<description>Pipefy WordPress coding standards</description>
|
|
828
|
+
|
|
829
|
+
<!-- Include WordPress-Core standards -->
|
|
830
|
+
<rule ref="WordPress-Core">
|
|
831
|
+
<!-- Exclude filename rules -->
|
|
832
|
+
<exclude name="WordPress.Files.FileName"/>
|
|
833
|
+
</rule>
|
|
834
|
+
|
|
835
|
+
<!-- Include WordPress-Extra standards -->
|
|
836
|
+
<rule ref="WordPress-Extra">
|
|
837
|
+
<!-- Allow short array syntax -->
|
|
838
|
+
<exclude name="Generic.Arrays.DisallowShortArraySyntax"/>
|
|
839
|
+
</rule>
|
|
840
|
+
|
|
841
|
+
<!-- Include WordPress-Docs standards -->
|
|
842
|
+
<rule ref="WordPress-Docs"/>
|
|
843
|
+
|
|
844
|
+
<!-- Check only PHP files -->
|
|
845
|
+
<arg name="extensions" value="php"/>
|
|
846
|
+
|
|
847
|
+
<!-- Show colors in output -->
|
|
848
|
+
<arg name="colors"/>
|
|
849
|
+
|
|
850
|
+
<!-- Show progress -->
|
|
851
|
+
<arg value="p"/>
|
|
852
|
+
|
|
853
|
+
<!-- Include paths -->
|
|
854
|
+
<file>dist/wp-content/themes/pipefy-2020/</file>
|
|
855
|
+
<file>dist/wp-content/mu-plugins/</file>
|
|
856
|
+
|
|
857
|
+
<!-- Exclude paths -->
|
|
858
|
+
<exclude-pattern>*/vendor/*</exclude-pattern>
|
|
859
|
+
<exclude-pattern>*/node_modules/*</exclude-pattern>
|
|
860
|
+
<exclude-pattern>*/assets/build/*</exclude-pattern>
|
|
861
|
+
</ruleset>
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
### **Unit Testing**
|
|
865
|
+
|
|
866
|
+
```php
|
|
867
|
+
// tests/Unit/UserServiceTest.php
|
|
868
|
+
namespace Tests\Unit;
|
|
869
|
+
|
|
870
|
+
use PHPUnit\Framework\TestCase;
|
|
871
|
+
use Pipefy\Services\UserService;
|
|
872
|
+
use Pipefy\Repositories\UserRepository;
|
|
873
|
+
use Pipefy\Services\EmailService;
|
|
874
|
+
|
|
875
|
+
class UserServiceTest extends TestCase {
|
|
876
|
+
private $userService;
|
|
877
|
+
private $userRepository;
|
|
878
|
+
private $emailService;
|
|
879
|
+
|
|
880
|
+
protected function setUp(): void {
|
|
881
|
+
$this->userRepository = $this->createMock(UserRepository::class);
|
|
882
|
+
$this->emailService = $this->createMock(EmailService::class);
|
|
883
|
+
$this->userService = new UserService($this->userRepository, $this->emailService);
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
public function testCreateUserWithValidData(): void {
|
|
887
|
+
$userData = [
|
|
888
|
+
'email' => 'test@example.com',
|
|
889
|
+
'first_name' => 'John',
|
|
890
|
+
'last_name' => 'Doe'
|
|
891
|
+
];
|
|
892
|
+
|
|
893
|
+
$expectedUser = new User((object) array_merge($userData, ['ID' => 1]));
|
|
894
|
+
|
|
895
|
+
$this->userRepository
|
|
896
|
+
->expects($this->once())
|
|
897
|
+
->method('create')
|
|
898
|
+
->with($userData)
|
|
899
|
+
->willReturn($expectedUser);
|
|
900
|
+
|
|
901
|
+
$this->emailService
|
|
902
|
+
->expects($this->once())
|
|
903
|
+
->method('sendWelcomeEmail')
|
|
904
|
+
->with($expectedUser);
|
|
905
|
+
|
|
906
|
+
$result = $this->userService->createUser($userData);
|
|
907
|
+
|
|
908
|
+
$this->assertInstanceOf(User::class, $result);
|
|
909
|
+
$this->assertEquals('test@example.com', $result->getEmail());
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
public function testCreateUserWithInvalidEmailThrowsException(): void {
|
|
913
|
+
$this->expectException(InvalidArgumentException::class);
|
|
914
|
+
$this->expectExceptionMessage('Invalid email format');
|
|
915
|
+
|
|
916
|
+
$userData = [
|
|
917
|
+
'email' => 'invalid-email',
|
|
918
|
+
'first_name' => 'John',
|
|
919
|
+
'last_name' => 'Doe'
|
|
920
|
+
];
|
|
921
|
+
|
|
922
|
+
$this->userService->createUser($userData);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
## 📋 **Code Review Guidelines**
|
|
928
|
+
|
|
929
|
+
### **Checklist de Code Review**
|
|
930
|
+
|
|
931
|
+
```markdown
|
|
932
|
+
## Code Review Checklist
|
|
933
|
+
|
|
934
|
+
### ✅ Functionality
|
|
935
|
+
- [ ] Code implements requirements correctly
|
|
936
|
+
- [ ] Edge cases are handled appropriately
|
|
937
|
+
- [ ] Error handling is implemented
|
|
938
|
+
- [ ] Performance considerations are addressed
|
|
939
|
+
|
|
940
|
+
### ✅ Code Quality
|
|
941
|
+
- [ ] Code follows DRY principles
|
|
942
|
+
- [ ] Functions are single-responsibility
|
|
943
|
+
- [ ] Variable and function names are descriptive (in English)
|
|
944
|
+
- [ ] Code is readable and well-structured
|
|
945
|
+
|
|
946
|
+
### ✅ Standards Compliance
|
|
947
|
+
- [ ] Follows WordPress coding standards
|
|
948
|
+
- [ ] BEM methodology for CSS
|
|
949
|
+
- [ ] PSR-12 compliance for PHP
|
|
950
|
+
- [ ] Semantic versioning for releases
|
|
951
|
+
|
|
952
|
+
### ✅ Security
|
|
953
|
+
- [ ] Input validation is implemented
|
|
954
|
+
- [ ] SQL injection prevention
|
|
955
|
+
- [ ] XSS prevention
|
|
956
|
+
- [ ] CSRF protection where needed
|
|
957
|
+
|
|
958
|
+
### ✅ Testing
|
|
959
|
+
- [ ] Unit tests are included
|
|
960
|
+
- [ ] Test coverage is adequate
|
|
961
|
+
- [ ] Integration tests pass
|
|
962
|
+
- [ ] Manual testing completed
|
|
963
|
+
|
|
964
|
+
### ✅ Documentation
|
|
965
|
+
- [ ] Code is properly documented
|
|
966
|
+
- [ ] README updated if needed
|
|
967
|
+
- [ ] CHANGELOG updated for user-facing changes
|
|
968
|
+
- [ ] API documentation updated
|
|
969
|
+
|
|
970
|
+
### ✅ Merge Request Process
|
|
971
|
+
- [ ] MR template properly filled
|
|
972
|
+
- [ ] Target branch is correct
|
|
973
|
+
- [ ] Required approvals obtained
|
|
974
|
+
- [ ] CI/CD pipeline passes
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
### **Commit Message Standards**
|
|
978
|
+
|
|
979
|
+
```bash
|
|
980
|
+
# Formato: type(scope): description
|
|
981
|
+
#
|
|
982
|
+
# Types:
|
|
983
|
+
# feat: nova funcionalidade
|
|
984
|
+
# fix: correção de bug
|
|
985
|
+
# docs: documentação
|
|
986
|
+
# style: formatação, missing semi colons, etc
|
|
987
|
+
# refactor: refatoração de código
|
|
988
|
+
# test: adição de testes
|
|
989
|
+
# chore: manutenção
|
|
990
|
+
|
|
991
|
+
# ✅ Exemplos corretos
|
|
992
|
+
feat(user): add avatar upload functionality
|
|
993
|
+
fix(header): resolve responsive navigation issue
|
|
994
|
+
docs(api): update authentication endpoints
|
|
995
|
+
style(css): format according to BEM methodology
|
|
996
|
+
refactor(auth): extract user validation logic
|
|
997
|
+
test(user): add unit tests for user service
|
|
998
|
+
chore(deps): update composer dependencies
|
|
999
|
+
|
|
1000
|
+
# ❌ Exemplos incorretos
|
|
1001
|
+
added new feature
|
|
1002
|
+
fix bug
|
|
1003
|
+
update code
|
|
1004
|
+
changes
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
## 🎯 **Performance e Otimização**
|
|
1008
|
+
|
|
1009
|
+
### **WordPress Performance Best Practices**
|
|
1010
|
+
|
|
1011
|
+
```php
|
|
1012
|
+
// ✅ Efficient database queries
|
|
1013
|
+
$posts = new WP_Query([
|
|
1014
|
+
'post_type' => 'product',
|
|
1015
|
+
'posts_per_page' => 10,
|
|
1016
|
+
'meta_query' => [
|
|
1017
|
+
[
|
|
1018
|
+
'key' => 'featured',
|
|
1019
|
+
'value' => 'yes',
|
|
1020
|
+
'compare' => '='
|
|
1021
|
+
]
|
|
1022
|
+
],
|
|
1023
|
+
'no_found_rows' => true, // Skip pagination count
|
|
1024
|
+
'update_post_meta_cache' => false, // Skip meta cache if not needed
|
|
1025
|
+
'update_post_term_cache' => false // Skip term cache if not needed
|
|
1026
|
+
]);
|
|
1027
|
+
|
|
1028
|
+
// ✅ Proper asset enqueuing with versioning
|
|
1029
|
+
wp_enqueue_script(
|
|
1030
|
+
'pipefy-main',
|
|
1031
|
+
get_theme_file_uri('assets/js/main.js'),
|
|
1032
|
+
['jquery'],
|
|
1033
|
+
PIPEFY_THEME_VERSION,
|
|
1034
|
+
true
|
|
1035
|
+
);
|
|
1036
|
+
|
|
1037
|
+
// ✅ Conditional loading
|
|
1038
|
+
if (is_front_page()) {
|
|
1039
|
+
wp_enqueue_script('hero-slider', get_theme_file_uri('assets/js/hero-slider.js'));
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// ✅ Efficient image handling
|
|
1043
|
+
function pipefy_get_responsive_image($attachment_id, $sizes = 'full') {
|
|
1044
|
+
return wp_get_attachment_image(
|
|
1045
|
+
$attachment_id,
|
|
1046
|
+
$sizes,
|
|
1047
|
+
false,
|
|
1048
|
+
[
|
|
1049
|
+
'loading' => 'lazy',
|
|
1050
|
+
'decoding' => 'async'
|
|
1051
|
+
]
|
|
1052
|
+
);
|
|
1053
|
+
}
|
|
1054
|
+
```
|
|
1055
|
+
|
|
1056
|
+
### **CSS/SCSS Organization**
|
|
1057
|
+
|
|
1058
|
+
```scss
|
|
1059
|
+
// assets/scss/main.scss
|
|
1060
|
+
// Import order: Variables → Mixins → Base → Components → Pages
|
|
1061
|
+
|
|
1062
|
+
// 1. Variables and configuration
|
|
1063
|
+
@import 'config/variables';
|
|
1064
|
+
@import 'config/breakpoints';
|
|
1065
|
+
@import 'config/colors';
|
|
1066
|
+
|
|
1067
|
+
// 2. Mixins and utilities
|
|
1068
|
+
@import 'mixins/responsive';
|
|
1069
|
+
@import 'mixins/typography';
|
|
1070
|
+
@import 'utilities/helpers';
|
|
1071
|
+
|
|
1072
|
+
// 3. Base styles
|
|
1073
|
+
@import 'base/reset';
|
|
1074
|
+
@import 'base/typography';
|
|
1075
|
+
@import 'base/layout';
|
|
1076
|
+
|
|
1077
|
+
// 4. Components (BEM blocks)
|
|
1078
|
+
@import 'components/header';
|
|
1079
|
+
@import 'components/navigation';
|
|
1080
|
+
@import 'components/hero-section';
|
|
1081
|
+
@import 'components/card';
|
|
1082
|
+
@import 'components/button';
|
|
1083
|
+
|
|
1084
|
+
// 5. Page-specific styles
|
|
1085
|
+
@import 'pages/home';
|
|
1086
|
+
@import 'pages/about';
|
|
1087
|
+
@import 'pages/contact';
|
|
1088
|
+
|
|
1089
|
+
// 6. WordPress specific
|
|
1090
|
+
@import 'wordpress/gutenberg';
|
|
1091
|
+
@import 'wordpress/comments';
|
|
1092
|
+
@import 'wordpress/widgets';
|
|
1093
|
+
```
|
|
1094
|
+
|
|
1095
|
+
## 🚀 **Próximos Passos**
|
|
1096
|
+
|
|
1097
|
+
1. **[Deploy Pipeline](Deploy-Pipeline)** - Processo de CI/CD detalhado
|
|
1098
|
+
2. **[Plugins & Integrações](Plugins-Integracoes)** - Gestão de plugins
|
|
1099
|
+
3. **[Troubleshooting](Troubleshooting)** - Resolução de problemas comuns
|
|
1100
|
+
|
|
1101
|
+
## 📞 **Suporte ao Desenvolvimento**
|
|
1102
|
+
|
|
1103
|
+
- **Code Review**: Equipe senior (ver [CODEOWNERS](https://gitlab.com/pipefy/wordpress/pipefy-website/-/blob/master/CODEOWNERS))
|
|
1104
|
+
- **Standards Issues**: [GitLab Issues - Label: code-quality](https://gitlab.com/pipefy/wordpress/pipefy-website/-/issues?label_name=code-quality)
|
|
1105
|
+
- **Development Discussion**: Slack #dev-website
|
|
1106
|
+
- **Merge Request Help**: [GitLab MR Guidelines](https://docs.gitlab.com/ee/user/project/merge_requests/)
|
|
1107
|
+
|
|
1108
|
+
---
|
|
1109
|
+
|
|
1110
|
+
📝 **Última atualização**: Junho 2025
|
|
1111
|
+
🌊 **Workflow**: GitFlow modificado (branches from master)
|
|
1112
|
+
🏷️ **Versionamento**: Semantic Versioning (SemVer)
|
|
1113
|
+
📦 **Dependencies**: Composer-based plugin management
|
|
1114
|
+
🧪 **Quality**: PHPCS + Unit Tests + Code Review
|
|
1115
|
+
🎨 **Standards**: BEM + DRY + Laravel-inspired architecture
|
|
1116
|
+
✅ **Process**: **Merge Requests obrigatórios para staging/master**
|