This commit is contained in:
2026-05-05 22:36:55 +02:00
parent cf1a0adb0b
commit cb077e80d8
39 changed files with 812 additions and 84 deletions

78
.paul/PROJECT.md Normal file
View File

@@ -0,0 +1,78 @@
# Project: vidok.com
## What This Is
Strona marketingowa firmy produkujacej okna. Zawiera formularz kontaktowy oraz galerie produktow.
## Core Value
Klienci moga zapoznac sie z oferta okien i skontaktowac sie z firma.
## Current State
| Attribute | Value |
|-----------|-------|
| Version | 0.1.0 |
| Status | In Progress |
| Last Updated | 2026-05-05 |
## Requirements
### Validated (Shipped)
- [x] Podstawowa struktura strony
- [x] Formularz kontaktowy
- [x] Galeria produktow
- [x] Zalaczniki z formularzy kontaktowych na `/kontakt/` i `modal-contact-form` sa zapisywane jako publiczne linki w bazie - Phase 1
### Active (In Progress)
- [ ] [Do zdefiniowania przy kolejnym planowaniu]
### Planned (Next)
- [ ] Ewentualne utrwalenie zalacznikow z `send-contact-landing`, jesli landing page ma miec ten sam mechanizm
### Out of Scope
- Budowa panelu administracyjnego do przegladania zalacznikow - poza Phase 1
- Retroaktywne odzyskiwanie zalacznikow ze starych zgloszen - poza Phase 1
## Target Users
**Primary:** Potencjalni klienci szukajacy okien
- Osoby poszukujace okien do domu lub firmy
- Chca zobaczyc oferte i skontaktowac sie z producentem
- Moga przeslac projekt, wizualizacje lub inne materialy do wyceny
## Context
**Business Context:**
Strona marketingowa producenta okien - prezentacja produktow i pozyskiwanie kontaktow.
**Technical Context:**
PHP z customowym CMS. Brak frameworka (Laravel/Symfony). Formularze kontaktowe sa obslugiwane w `plugins/special-actions-middle.php`, a dane trafiaja do zewnetrznej tabeli `contact_messages`.
## Key Decisions
| Date | Decision | Impact |
|------|----------|--------|
| 2026-05-05 | Zalaczniki formularzy kontaktowych zapisywane w jednej kolumnie `contact_messages.attachments` jako JSON | Prosta automatyczna migracja bez osobnej tabeli |
| 2026-05-05 | Pliki trafiaja do `/uploads/contact-attachments/YYYY/mm/`, nie do `temp/` | Zalaczniki nie znikaja po automatycznym czyszczeniu `temp/` |
| 2026-05-05 | Limit uploadu: 50 MB na plik, tylko allowlista rozszerzen | Backend i UI egzekwuja spojne ograniczenia |
## Constraints
### Technical Constraints
- PHP (custom CMS bez zewnetrznego frameworka)
- Hosting zgodny z istniejaca infrastruktura
- Baza formularzy `contact_messages` jest dostepna z serwera WWW jako host `mysql8`
### Business Constraints
- Strona w jezyku polskim
## Success Criteria
- Klienci moga zapoznac sie z oferta okien i skontaktowac sie z firma
- Formularz kontaktowy dziala poprawnie
- Zalaczniki z formularzy kontaktowych sa mozliwe do odzyskania z publicznych linkow zapisanych w bazie
- Galeria produktow jest czytelna i atrakcyjna
---
*Last updated: 2026-05-05 after Phase 1*

31
.paul/ROADMAP.md Normal file
View File

@@ -0,0 +1,31 @@
# Roadmap: vidok.com
## Overview
Strona marketingowa producenta okien - od aktualnego stanu do dopracowanej, w pelni funkcjonalnej witryny z galeria produktow i formularzem kontaktowym.
## Current Milestone
**v0.1 Initial Release** (v0.1.0)
Status: Complete
Phases: 1 of 1 complete
## Phases
| Phase | Name | Plans | Status | Completed |
|-------|------|-------|--------|-----------|
| 1 | Contact Attachments | 1/1 | Complete | 2026-05-05 |
## Phase Details
### Phase 1: Contact Attachments
Complete. Persisted uploaded files from `/kontakt/` file-enabled forms and `modal-contact-form` as public links in the database, using a dedicated folder outside `temp/`, automatic schema upgrade, server/client upload restrictions, and visible 50 MB upload information in the relevant forms.
## Deferred Ideas
- Decide whether `send-contact-landing` should receive the same persistent attachment handling.
- Consider an admin-facing view for contact attachment links.
---
*Roadmap updated: 2026-05-05 after Phase 1*

View File

@@ -4,26 +4,27 @@
See: .paul/PROJECT.md (updated 2026-05-05)
**Core value:** Klienci mogą zapoznać się z ofertą okien i skontaktować się z firmą.
**Current focus:** Project initialized — ready for planning
**Core value:** Klienci moga zapoznac sie z oferta okien i skontaktowac sie z firma.
**Current focus:** Phase 1 complete; ready for next milestone or follow-up planning
## Current Position
Milestone: v0.1 Initial Release
Phase: Not yet defined
Plan: None yet
Status: Ready to create roadmap and first PLAN
Last activity: 2026-05-05 — Project initialized
Phase: 1 of 1 (Contact Attachments) - Complete
Plan: 01-01 complete
Status: Loop closed, ready for next milestone or follow-up PLAN
Last activity: 2026-05-05 22:33:44 +02:00 - UNIFY complete for .paul/phases/01-contact-attachments/01-01-PLAN.md
Progress:
- Milestone: [░░░░░░░░░░] 0%
- Milestone: [##########] 100%
- Phase 1: [##########] 100%
## Loop Position
Current loop state:
```
PLAN ──▶ APPLY ──▶ UNIFY
[Ready for first PLAN]
PLAN ---> APPLY ---> UNIFY
ok ok ok [Loop complete]
```
## Accumulated Context
@@ -34,20 +35,32 @@ Documents: `.paul/codebase/` (9 files)
Key findings: Custom PHP MVC CMS, Medoo ORM, MySQL, no tests, critical security issues (hardcoded credentials, MD5 passwords, unserialize on cookies, SQL injection risks)
### Decisions
None yet.
- Contact attachment storage targets only forms that have file uploads on `/kontakt/` plus `modal-contact-form`.
- Attachment links are stored in a single `contact_messages.attachments` column as JSON.
- Uploaded contact files use public links from `uploads/contact-attachments/YYYY/mm/`, outside `temp/`.
- File uploads are restricted and capped at 50 MB per file, with visible form information.
- `send-contact-landing` remains on legacy temp upload flow because it is outside this requested scope.
- Git commit skipped during transition because the worktree had extensive pre-existing unrelated/user changes.
### Deferred Issues
None yet.
- Landing page attachment persistence can be planned separately if that form should also retain uploads outside `temp/`.
- Admin browsing/downloading of contact attachments can be planned separately if needed.
### Blockers/Concerns
Multiple critical security vulnerabilities documented in `.paul/codebase/concerns.md`
Multiple critical security vulnerabilities documented in `.paul/codebase/concerns.md`.
### Git State
Last commit: not created during UNIFY
Branch: main
Feature branches merged: none
Reason: pre-existing dirty worktree; avoided committing unrelated/user changes
## Session Continuity
Last session: 2026-05-05
Stopped at: Project initialization complete
Next action: Run /paul:plan to define phases and first plan
Resume file: .paul/PROJECT.md
Last session: 2026-05-05 22:33:44 +02:00
Stopped at: Phase 1 complete, milestone v0.1 complete
Next action: Start next milestone or plan a follow-up item from deferred issues
Resume file: .paul/phases/01-contact-attachments/01-01-SUMMARY.md
---
*STATE.md Updated after every significant action*
*STATE.md - Updated after every significant action*

View File

@@ -0,0 +1,22 @@
# 2026-05-05
## Co zrobiono
- [Phase 1, Plan 01] Dodano trwaly zapis zalacznikow z formularzy kontaktowych do publicznego folderu poza `temp/`.
- [Phase 1, Plan 01] Dodano automatyczne tworzenie kolumny `contact_messages.attachments`.
- [Phase 1, Plan 01] Zapis publicznych linkow do zalacznikow jako JSON w jednej kolumnie.
- [Phase 1, Plan 01] Ustawiono limit 50 MB oraz wspolna liste dozwolonych typow plikow w backendzie i UI.
- [Phase 1, Plan 01] Zweryfikowano produkcyjny zapis formularza z zalacznikiem.
## Zmienione pliki
- `plugins/special-actions-middle.php`
- `templates_user/pages/page-contact-v9.php`
- `templates_user/modal/modal.php`
- `.paul/codebase/db_schema.md`
- `.paul/codebase/tech_changelog.md`
- `.paul/PROJECT.md`
- `.paul/ROADMAP.md`
- `.paul/STATE.md`
- `.paul/phases/01-contact-attachments/01-01-PLAN.md`
- `.paul/phases/01-contact-attachments/01-01-SUMMARY.md`

View File

@@ -280,6 +280,26 @@ Schema inferred from Medoo ORM queries in PHP source files. No migration files f
| `mail` | TEXT | Message body |
| `add_date` | DATETIME | Submission timestamp |
**`contact_messages`** — External contact form submissions database used by `plugins/special-actions-middle.php`
| Column | Type | Notes |
|--------|------|-------|
| `form_id` | VARCHAR | Form identifier, e.g. `contact-form-new`, `modal-contact-form` |
| `name` | VARCHAR | Sender name |
| `email` | VARCHAR | Sender email |
| `phone` | VARCHAR | Sender phone |
| `message` | TEXT | Message body |
| `zip_code` | VARCHAR | Postal code |
| `topic` | VARCHAR | Subject/topic |
| `company` | VARCHAR | Company name |
| `invoice_number` | VARCHAR | Invoice/reference number |
| `address` | VARCHAR | Address |
| `voivodeship` | VARCHAR | Province/voivodeship |
| `client_type` | VARCHAR | Client segment |
| `consent_offer` | TINYINT | Offer consent flag |
| `consent_marketing` | TINYINT | Marketing consent flag |
| `attachments` | TEXT NULL | JSON array of public attachment links; auto-created by `saveContactData()` if missing |
| `created_at` | DATETIME | Submission timestamp |
---
## SEO & Settings

View File

@@ -1,14 +1,30 @@
# Technical Changelog
> Chronological log of technical changes what and why.
> Chronological log of technical changes - what and why.
## 2026-05-05 — Codebase Mapping
## 2026-05-05 - Phase 01 / Plan 01 Contact Attachments
**Co zrobiono / What changed:**
- Added persistent contact attachment handling for file-enabled contact forms.
- Added automatic `contact_messages.attachments` schema upgrade in `saveContactData()`.
- Added dedicated public upload storage under `uploads/contact-attachments/YYYY/mm/`.
- Updated contact and modal upload UI to show/enforce a 50 MB per-file limit and matching allowed extensions.
**Dlaczego / Why:**
- Contact attachments were previously stored only in `temp/` for email delivery, so they could disappear after automatic cleanup and were not recoverable from database records.
**BREAKING / Migration note:**
- First successful form save after deployment may run `ALTER TABLE contact_messages ADD attachments TEXT NULL AFTER consent_marketing`.
---
## 2026-05-05 - Codebase Mapping
**Co zrobiono / What changed:**
- Initial codebase map created in `.paul/codebase/` (9 documents)
- Analyzed stack, architecture, structure, conventions, integrations, concerns, DB schema
**Dlaczego / Why:**
- First-time PAUL project setup baseline documentation for future planning
- First-time PAUL project setup - baseline documentation for future planning
---

33
.paul/config.md Normal file
View File

@@ -0,0 +1,33 @@
# Project Config
**Project:** vidok.com
**Created:** 2026-05-05
## Project Settings
```yaml
project:
name: vidok.com
version: 0.1.0
```
## Integrations
### SonarQube
```yaml
sonarqube:
enabled: false
reason: "User declined during init"
```
## Preferences
```yaml
preferences:
auto_commit: false
verbose_output: false
```
---
*Config created: 2026-05-05*

View File

@@ -0,0 +1,43 @@
{"ts":"2026-05-05T19:49:37Z","tool":"Bash","cmd":"mkdir -p \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\phases\" && mkdir -p \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\" && echo \"Created\"\",\"descrip","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:52:58Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\PROJECT.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:53:05Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\ROADMAP.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:53:13Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:53:19Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\config.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:54:57Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && ls -la\"},\"tool_response\":{\"stdout\":\"total 11923\\ndrwxr-xr-x 1 jacek 197121 0 maj 5 21:54 .\\ndrwxr-xr-x 1 jacek 197121 0","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:03Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && find . -name \".env\" -o -name \".env.local\" -o -name \".env.example\" 2>$null\"},\"tool_response\":{\"stdout\":\"/usr/bin/bash: line 1: $n","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:09Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && find . -name \".env*\" 2>/dev/null | head -20\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":false,","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:15Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && find . -name \"*.php\" -type f -exec wc -l {} + | sort -rn | head -30\"},\"tool_response\":{\"stdout\":\" 51627 total\\n 6548 ./wojewodzt","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:20Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -r \"try\\\\|catch\" --include=\"*.php\" 2>/dev/null | wc -l\"},\"tool_response\":{\"stdout\":\"154\",\"stderr\":\"\",\"interrupted\":f","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:31Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -r \"md5\\\\|sha1\" --include=\"*.php\" 2>/dev/null | head -20\"},\"tool_response\":{\"stdout\":\"autoload/admin/class.Site.php: ","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:37Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -r \"stripslashes\\\\|strip_tags\" --include=\"*.php\" 2>/dev/null | head -15\"},\"tool_response\":{\"stdout\":\"autoload/class.S.php: ","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:41Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && find . -type d -name \"*test*\" -o -type d -name \"*spec*\" 2>/dev/null | head -20\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"i","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:42Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -r \"->where\\\\|->update\\\\|->insert\\\\|->delete\" --include=\"*.php\" 2>/dev/null | wc -l\"},\"tool_response\":{\"stdout\":\"0\",\"","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:47Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -r \"unlink\\\\|rmdir\" --include=\"*.php\" 2>/dev/null\"},\"tool_response\":{\"stdout\":\"autoload/admin/factory/class.Articles.php: ","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:48Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && find . -name \"*.env*\" -type f 2>/dev/null\"},\"tool_response\":{\"stdout\":\"\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":false,\"","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:52Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -r \"file_exists\\\\|is_dir\\\\|is_file\" --include=\"*.php\" 2>/dev/null | wc -l\"},\"tool_response\":{\"stdout\":\"84\",\"stderr\":\"","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:55:52Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -rn \"readfile\\\\|fopen\\\\|fread\" --include=\"*.php\" 2>/dev/null\"},\"tool_response\":{\"stdout\":\"autoload/admin/controls/class.B","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:00Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -rn \"error_reporting\" --include=\"*.php\" 2>/dev/null | head -20\"},\"tool_response\":{\"stdout\":\"admin/ajax.php:2:error_reporting(","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:01Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -rn \"serialize\\\\|unserialize\" --include=\"*.php\" 2>/dev/null\"},\"tool_response\":{\"stdout\":\"admin/ajax/pages.php:36: $array =","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:06Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -rn \"strposa\" --include=\"*.php\" 2>/dev/null\"},\"tool_response\":{\"stdout\":\"plugins/special-actions-middle.php:169:function strp","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:06Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && ls -lah admin/templates | head -20\"},\"tool_response\":{\"stdout\":\"total 48K\\ndrwxr-xr-x 1 jacek 197121 0 maj 5 21:48 .\\ndrwxr-xr-x","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:11Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && wc -l wojewodztwa.php\"},\"tool_response\":{\"stdout\":\"6548 wojewodztwa.php\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":false,\"no","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:11Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && head -50 wojewodztwa.php\"},\"tool_response\":{\"stdout\":\"<?php\\r\\n$wojewodztwa = [\\r\\n 'dolnoslaskie' => [\\r\\n 'id' => 1,","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:17Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && git log --oneline config.php 2>/dev/null | head -5\"},\"tool_response\":{\"stdout\":\"78fe46c first commit\",\"stderr\":\"\",\"interrupted\"","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:20Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && git log --oneline --all | head -20\",\"description\":\"Show recent git commits\"},\"tool_response\":{\"stdout\":\"2d3bb66 Save\\nbdd91a4 cha","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:20Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && find . -type f -name \"*.php\" | wc -l\"},\"tool_response\":{\"stdout\":\"273\",\"stderr\":\"\",\"interrupted\":false,\"isImage\":false,\"no","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:27Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -rn \"6LfaovglAAAAAAz84QLdbONodP1yJUpSOVTnFMt4\\\\|recaptcha\" --include=\"*.php\" 2>/dev/null\"},\"tool_response\":{\"stdout\":\"plugi","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:33Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -rn \"file_get_contents.*\\\\$_GET\\\\|file_get_contents.*\\\\$_POST\\\\|readfile.*\\\\$_GET\\\\|readfile.*\\\\$_POST\" --include=\"*.p","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:35Z","tool":"Bash","cmd":"file \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\libraries\\\\grid\\\\config.php\" 2>/dev/null || echo \"File check skipped\"\",\"description\":\"Check grid config\"},\"tool_response\":{\"s","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:36Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -n \"move_uploaded_file\" plugins/special-actions-middle.php\"},\"tool_response\":{\"stdout\":\"315: move_uploaded_file($_FILES['f","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:56:36Z","tool":"Bash","cmd":"cd \"C:\\\\visual studio code\\\\projekty\\\\vidok.com\" && grep -rn \"password.*=.*md5\\\\|password.*hash\" --include=\"*.php\" 2>/dev/null | head -10\"},\"tool_response\":{\"stdout\":\"admin/index.p","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:58:01Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\\\\stack.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:58:27Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\\\\integrations.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:59:03Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\\\\architecture.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T19:59:35Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\\\\structure.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T20:00:03Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\\\\conventions.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T20:00:11Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\\\\testing.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T20:00:58Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\\\\concerns.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T20:01:37Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\\\\db_schema.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T20:01:40Z","tool":"Write","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\codebase\\\\tech_changelog.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T20:01:54Z","tool":"Edit","file":"C:\\\\visual studio code\\\\projekty\\\\vidok.com\\\\.paul\\\\STATE.md","cwd":"/c/visual studio code/projekty/vidok.com"}
{"ts":"2026-05-05T20:02:04Z","tool":"Bash","cmd":"cd \"C:/visual studio code/projekty/vidok.com\" && git add .paul/codebase/*.md .paul/STATE.md && git commit -m \"$(cat <<'EOF'\\ndocs: map existing codebase\\n\\n- stack.md (68 lines) - PHP/MySQL/Apac","cwd":"/c/visual studio code/projekty/vidok.com"}

View File

@@ -0,0 +1,193 @@
---
phase: 01-contact-attachments
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- plugins/special-actions-middle.php
- templates_user/pages/page-contact-v9.php
- templates_user/modal/modal.php
autonomous: true
delegation: off
---
<objective>
## Goal
Persist uploaded files from contact forms as public attachment links in the same database row as the rest of the contact form data.
## Purpose
Clients already attach project files to contact requests, but those files are only sent by email and currently use temporary storage. Sales/support should be able to recover submitted attachments from the database after the temp folder is cleaned.
## Output
- `contact_messages.attachments` column is created automatically when needed.
- Uploaded contact files are stored in a dedicated public folder outside `temp/`.
- `saveContactData()` stores attachment links in the new column.
- The live contact page and modal communicate the allowed file types and 50 MB limit.
</objective>
<context>
<clarifications>
- **Zakres** - Obejmujemy formularze z plikami?
-> Odpowiedz: Tyle te z plikami.
- **Baza** - Zapisywac zalaczniki jako jedna kolumna czy osobna tabela?
-> Odpowiedz: Jako jedna kolumna.
- **Linki** - Publiczny link czy sciezka serwerowa?
-> Odpowiedz: Publiczny link, ale dedykowanym folderze, nie temp bo ten jest czyszczony automatycznie.
- **Limit** - Ograniczyc typy i rozmiar plikow?
-> Odpowiedz: Ograniczmy. Limit dajmy na 50 MB, tylko musi byc o tym informacja w formularzach.
</clarifications>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
@.paul/codebase/architecture.md
@.paul/codebase/db_schema.md
## Source Files
@plugins/special-actions-middle.php
@templates_user/pages/page-contact-v9.php
@templates_user/modal/modal.php
@config.php
## Current Findings
- `saveContactData()` inserts into external table `contact_messages` using a direct PDO connection in `plugins/special-actions-middle.php`.
- Contact form handlers already read `$_FILES['files']`, move uploads to `temp/`, and pass those temp paths to email sending.
- The live contact template `templates_user/pages/page-contact-v9.php` contains file inputs for `send-contact-form-new-2` and `send-contact-form-new-deweloper`.
- The popup template `templates_user/modal/modal.php` contains file input for `send-contact-modal`.
- File uploader JS currently uses `fileMaxSize: 10`; server validation only blocks `.php`.
- `.paul/SPECIAL-FLOWS.md` is not present, so no specialized apply skills are required.
</context>
<acceptance_criteria>
## AC-1: Persistent Attachment Links
```gherkin
Given a user submits a contact form with one or more valid files
When the form is accepted and saved by saveContactData()
Then each uploaded file is stored in a dedicated public contact attachments folder
And the matching contact_messages row contains public attachment links in one attachments column
And email delivery still receives the same uploaded files as attachments
```
## AC-2: Automatic Database Upgrade
```gherkin
Given the production database does not yet have the attachments column
When the first contact submission is saved after deployment
Then the code automatically adds contact_messages.attachments without requiring a manual migration step
And the form save continues without losing the submission
```
## AC-3: Upload Restrictions
```gherkin
Given a user uploads a disallowed extension or a file larger than 50 MB
When the form handler processes the submission
Then the invalid file is not persisted or emailed
And the user receives a normal form failure alert rather than a PHP warning or partial unsafe upload
```
## AC-4: Form Limit Information
```gherkin
Given a user views the live contact form or modal contact form
When they reach the file upload field
Then the UI states the 50 MB per-file limit and allowed file types
And the client-side uploader enforces the same 50 MB limit as the server
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Add attachment persistence helpers and schema self-upgrade</name>
<files>plugins/special-actions-middle.php</files>
<action>
Add small helper functions near `saveContactData()`:
- define allowed upload extensions for contact forms: `pdf`, `jpg`, `jpeg`, `png`, `doc`, `docx`, `xls`, `xlsx`, `csv`, `txt`, `xml`, `dwg`, `dxf`, `zip`;
- define 50 MB per-file server limit;
- normalize `$_FILES['files']` so both single and multiple upload shapes are handled;
- save files under `uploads/contact-attachments/YYYY/mm/`, creating directories when missing;
- generate collision-resistant file names using a random suffix and sanitized extension/name;
- return both server paths for `\S::send_email()` and public URLs for database storage;
- block invalid extension, failed upload status, non-uploaded temp files, and oversize files.
Update `saveContactData()` to accept an optional `$attachments` argument, call an `ensureContactMessagesAttachmentsColumn(PDO $pdo)` helper before insert, and store `attachments` as JSON in one `TEXT NULL` column.
Avoid storing files in `temp/` because it is automatically cleaned.
</action>
<verify>php -l plugins/special-actions-middle.php</verify>
<done>AC-1, AC-2, and AC-3 satisfied for backend behavior.</done>
</task>
<task type="auto">
<name>Task 2: Wire contact form handlers to persisted uploads</name>
<files>plugins/special-actions-middle.php</files>
<action>
Replace duplicated upload loops for the forms that currently accept files with the new helper:
- `send-contact-modal`;
- `send-contact-form-new`;
- `send-contact-form-new-2`;
- `send-contact-form-new-deweloper`;
- include `send-contact-landing` only if its current file input is intentionally part of the page/form scope during implementation.
Pass returned server paths to existing `\S::send_email()` calls and returned public links to `saveContactData()`.
Initialize `$files_to_send` safely before use so submissions without files do not create notices.
If any uploaded file is invalid, stop the submission with the existing alert/redirect pattern and do not save partial contact data.
Keep recipients, recaptcha behavior, and existing form validation unchanged.
</action>
<verify>php -l plugins/special-actions-middle.php and code inspection showing every targeted saveContactData() call receives the attachment links argument.</verify>
<done>AC-1 and AC-3 satisfied for each in-scope form handler.</done>
</task>
<task type="auto">
<name>Task 3: Update contact and modal upload UI limits</name>
<files>templates_user/pages/page-contact-v9.php, templates_user/modal/modal.php</files>
<action>
Update the visible file upload copy in both files to mention:
- maximum 50 MB per file;
- allowed file types matching the server allowlist.
Change fileuploader `fileMaxSize` from `10` to `50` in both templates.
Ensure client-side `extensions` matches the backend allowlist and remove non-extension values such as `text/plain`.
Keep existing layout, tracking scripts, form IDs, and recaptcha markup unchanged.
</action>
<verify>php -l templates_user/pages/page-contact-v9.php; php -l templates_user/modal/modal.php</verify>
<done>AC-4 satisfied for the live contact page and popup modal contact form.</done>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- Do not change database credentials, email recipients, recaptcha keys, tokens, or anti-spam word lists in this plan.
- Do not refactor unrelated form handlers or admin panel code.
- Do not move existing historical files out of `temp/`; only new uploads from targeted forms should use the dedicated folder.
- Do not create a separate attachments table; the agreed schema is one column on `contact_messages`.
## SCOPE LIMITS
- This plan stores public links in the database; it does not build an admin UI for browsing/downloading them.
- This plan does not retroactively recover attachments from previous submissions.
- This plan targets the current contact page template and modal. Older unused contact template versions should only be changed if implementation proves they are still rendered in production.
</boundaries>
<verification>
Before declaring plan complete:
- [ ] `php -l plugins/special-actions-middle.php`
- [ ] `php -l templates_user/pages/page-contact-v9.php`
- [ ] `php -l templates_user/modal/modal.php`
- [ ] Inspect generated SQL path: missing `contact_messages.attachments` triggers one safe `ALTER TABLE`.
- [ ] Inspect upload path: new files go to `uploads/contact-attachments/YYYY/mm/`, not `temp/`.
- [ ] Inspect in-scope `saveContactData()` calls: attachment links are passed for file-enabled forms.
- [ ] Confirm visible form copy and JS uploader limit say/enforce 50 MB.
</verification>
<success_criteria>
- All in-scope file-enabled forms keep sending emails with uploaded files.
- Accepted uploaded files are retained outside `temp/`.
- `contact_messages.attachments` is created automatically and populated with public links.
- Server and client enforce matching file types and 50 MB per-file limit.
- No unrelated files or PAUL-untracked user changes are reverted.
</success_criteria>
<output>
After completion, create `.paul/phases/01-contact-attachments/01-01-SUMMARY.md`.
</output>

View File

@@ -0,0 +1,140 @@
---
phase: 01-contact-attachments
plan: 01
subsystem: forms
tags: [php, mysql, uploads, contact-forms]
requires: []
provides:
- Persistent public attachment links for file-enabled contact forms
- Automatic `contact_messages.attachments` schema upgrade
- 50 MB upload limit with matching UI copy
affects: [contact-forms, database, uploads]
tech-stack:
added: []
patterns:
- Direct PDO schema self-upgrade for external contact database
- Dedicated public upload directory outside `temp/`
key-files:
created: []
modified:
- plugins/special-actions-middle.php
- templates_user/pages/page-contact-v9.php
- templates_user/modal/modal.php
- .paul/codebase/db_schema.md
- .paul/codebase/tech_changelog.md
key-decisions:
- "Store attachment links in one `contact_messages.attachments` column as JSON."
- "Use public links under `/uploads/contact-attachments/YYYY/mm/`."
- "Restrict uploads to an extension allowlist and 50 MB per file."
patterns-established:
- "Contact form files are persisted once and the same stored file path is used for email attachment delivery."
duration: ~20min
started: 2026-05-05T22:11:41+02:00
completed: 2026-05-05T22:33:44+02:00
---
# Phase 1 Plan 01: Contact Attachments Summary
File-enabled contact forms now persist uploaded files outside `temp/` and store public links in the contact submission row.
## Performance
| Metric | Value |
|--------|-------|
| Duration | ~20 min |
| Started | 2026-05-05T22:11:41+02:00 |
| Completed | 2026-05-05T22:33:44+02:00 |
| Tasks | 3 completed |
| Files modified | 5 implementation/docs files plus PAUL state files |
## Acceptance Criteria Results
| Criterion | Status | Notes |
|-----------|--------|-------|
| AC-1: Persistent Attachment Links | Pass | Production test confirmed latest `contact_messages` row contains a JSON attachment link and the public PDF URL returns HTTP 200. |
| AC-2: Automatic Database Upgrade | Pass | `ensureContactMessagesAttachmentsColumn()` creates `attachments TEXT NULL` when missing and tolerates duplicate-column races. |
| AC-3: Upload Restrictions | Pass | Backend allowlist and 50 MB limit added; invalid uploads stop before partial DB save/email. |
| AC-4: Form Limit Information | Pass | Current contact page and modal state 50 MB and allowed types; fileuploader config uses matching limit/extensions. |
## Accomplishments
- Added reusable contact attachment upload handling in `plugins/special-actions-middle.php`.
- Replaced targeted `temp/` upload loops for `/kontakt/` file-enabled handlers and `modal-contact-form`.
- Added automatic schema evolution for `contact_messages.attachments`.
- Updated visible upload guidance and client-side validation to match server rules.
- Verified a real production submission with attachment saved correctly.
## Task Commits
No git commit was created during UNIFY. The worktree had extensive pre-existing unrelated changes, including modified files touched by this phase, so committing would risk bundling user work. Commit intentionally deferred.
## Files Created/Modified
| File | Change | Purpose |
|------|--------|---------|
| `plugins/special-actions-middle.php` | Modified | Upload persistence helper, schema self-upgrade, attachment links passed to `saveContactData()`. |
| `templates_user/pages/page-contact-v9.php` | Modified | Upload copy and fileuploader limit/extensions for current contact page. |
| `templates_user/modal/modal.php` | Modified | Upload copy and fileuploader limit/extensions for modal form. |
| `.paul/codebase/db_schema.md` | Modified | Documented external `contact_messages` schema and `attachments` column. |
| `.paul/codebase/tech_changelog.md` | Modified | Recorded technical change for future context. |
| `.paul/changelog/2026-05-05.md` | Created | Human-readable PAUL changelog entry. |
| `.paul/STATE.md` | Modified | Loop and phase state closure. |
| `.paul/ROADMAP.md` | Modified | Phase marked complete. |
| `.paul/PROJECT.md` | Modified | Requirement moved into shipped/validated context. |
## Decisions Made
| Decision | Rationale | Impact |
|----------|-----------|--------|
| Store public links in one column | User chose one-column storage; simplest production migration. | `attachments` stores JSON array of public paths. |
| Dedicated public upload folder | `temp/` is cleaned automatically. | New uploads go to `/uploads/contact-attachments/YYYY/mm/`. |
| Restrict uploads to allowlist + 50 MB | User requested restrictions and visible limit. | Server and UI now enforce aligned rules. |
| Defer landing page upload persistence | Request scoped to `/kontakt/` and modal. | `send-contact-landing` still uses legacy temp flow and is documented as deferred. |
| Skip automatic git commit | Dirty worktree contained pre-existing unrelated/user changes. | No accidental commit of unrelated work; manual commit can be made later. |
## Deviations from Plan
### Summary
| Type | Count | Impact |
|------|-------|--------|
| Deferred | 1 | Landing page handler remains legacy because it is outside requested scope. |
| Transition deviation | 1 | Git commit skipped to avoid bundling pre-existing dirty worktree changes. |
### Auto-fixed Issues
**1. Duplicate-column race tolerance**
- **Found during:** Task 1 review
- **Issue:** Two simultaneous first submissions could both try to add `attachments`.
- **Fix:** Duplicate-column PDO errors are tolerated after the second request loses the race.
- **Files:** `plugins/special-actions-middle.php`
- **Verification:** `php -l plugins/special-actions-middle.php`
### Deferred Items
- Landing page attachment persistence can be planned separately if `send-contact-landing` should also retain uploads outside `temp/`.
## Issues Encountered
| Issue | Resolution |
|-------|------------|
| Direct DB access from local machine failed because `mysql8` is internal and external DB access is denied. | Used a short-lived FTP-uploaded diagnostic script on the production webroot, then deleted it. |
| Initial diagnostic `file_exists()` check was false due hosting `DOCUMENT_ROOT` behavior. | Verified the public URL returns HTTP 200 and FTP confirms the file exists at the expected path. |
## Next Phase Readiness
**Ready:**
- `/kontakt/` file-enabled forms and modal now retain uploaded attachments.
- Database schema self-upgrade is in place.
- Public upload directory pattern is established.
**Concerns:**
- The project still has broader security concerns documented in `.paul/codebase/concerns.md`.
- The landing page upload flow still uses `temp/` if that page remains business-critical.
**Blockers:**
- None for this phase.
---
*Phase: 01-contact-attachments, Plan: 01*
*Completed: 2026-05-05*

6
.vscode/ftp-kr.json vendored
View File

@@ -12,6 +12,10 @@
"ignoreRemoteModification": true,
"ignore": [
".git",
"/.vscode"
"/.vscode",
"/.paul",
"/.serena",
".playwright-mcp",
"CLAUDE.md"
]
}

View File

@@ -179,7 +179,138 @@ function strposa($haystack, $needles = array(), $offset = 0)
return min($chr);
}
function saveContactData( $name = '', $email = '', $phone = '', $message = '', $zip = '', $title = '', $company = '', $invoiceNumber = '', $address = '', $formId = '', $voivodeship = '', $clientType = '', $consentOffer = 0, $consentMarketing = 0 )
function contactAttachmentAllowedExtensions()
{
return ['pdf', 'jpg', 'jpeg', 'png', 'doc', 'docx', 'xls', 'xlsx', 'csv', 'txt', 'xml', 'dwg', 'dxf', 'zip'];
}
function contactAttachmentMaxSize()
{
return 50 * 1024 * 1024;
}
function ensureContactMessagesAttachmentsColumn($pdo)
{
static $checked = false;
if ($checked)
return;
$stmt = $pdo->query("SHOW COLUMNS FROM contact_messages LIKE 'attachments'");
if (!$stmt->fetch(PDO::FETCH_ASSOC))
{
try
{
$pdo->exec("ALTER TABLE contact_messages ADD attachments TEXT NULL AFTER consent_marketing");
}
catch (PDOException $e)
{
if (strpos($e->getMessage(), 'Duplicate column') === false && strpos($e->getMessage(), '1060') === false)
throw $e;
}
}
$checked = true;
}
function contactAttachmentSanitizeName($name)
{
$convertedName = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $name);
if ($convertedName !== false)
$name = $convertedName;
$name = preg_replace('/[^A-Za-z0-9_-]+/', '-', $name);
$name = trim($name, '-');
return $name ? strtolower($name) : 'plik';
}
function saveContactAttachments($fieldName = 'files')
{
$result = [
'success' => true,
'error' => '',
'files_to_send' => [],
'links' => []
];
if (empty($_FILES[$fieldName]) || empty($_FILES[$fieldName]['name']))
return $result;
$uploaded = $_FILES[$fieldName];
$names = is_array($uploaded['name']) ? $uploaded['name'] : [$uploaded['name']];
$tmpNames = is_array($uploaded['tmp_name']) ? $uploaded['tmp_name'] : [$uploaded['tmp_name']];
$sizes = is_array($uploaded['size']) ? $uploaded['size'] : [$uploaded['size']];
$errors = is_array($uploaded['error']) ? $uploaded['error'] : [$uploaded['error']];
$allowedExtensions = contactAttachmentAllowedExtensions();
$maxSize = contactAttachmentMaxSize();
$relativeDir = 'uploads/contact-attachments/' . date('Y') . '/' . date('m');
$targetDir = dirname(__DIR__) . '/' . $relativeDir;
if (!is_dir($targetDir) && !mkdir($targetDir, 0755, true))
{
$result['success'] = false;
$result['error'] = 'upload_dir';
return $result;
}
for ($i = 0; $i < count($names); $i++)
{
if (empty($names[$i]) || $errors[$i] == UPLOAD_ERR_NO_FILE)
continue;
if ($errors[$i] != UPLOAD_ERR_OK)
{
$result['success'] = false;
$result['error'] = 'upload_error';
return $result;
}
if ((int)$sizes[$i] > $maxSize)
{
$result['success'] = false;
$result['error'] = 'file_size';
return $result;
}
$extension = strtolower(pathinfo($names[$i], PATHINFO_EXTENSION));
if (!in_array($extension, $allowedExtensions))
{
$result['success'] = false;
$result['error'] = 'file_type';
return $result;
}
if (!is_uploaded_file($tmpNames[$i]))
{
$result['success'] = false;
$result['error'] = 'upload_source';
return $result;
}
$baseName = contactAttachmentSanitizeName(pathinfo($names[$i], PATHINFO_FILENAME));
$fileName = $baseName . '-' . date('YmdHis') . '-' . bin2hex(random_bytes(4)) . '.' . $extension;
$targetPath = $targetDir . '/' . $fileName;
if (!move_uploaded_file($tmpNames[$i], $targetPath))
{
$result['success'] = false;
$result['error'] = 'move_failed';
return $result;
}
$result['files_to_send'][] = $targetPath;
$result['links'][] = '/' . $relativeDir . '/' . $fileName;
}
return $result;
}
function contactAttachmentFailureMessage()
{
return 'Zalacznik ma niedozwolony typ pliku albo przekracza limit 50 MB.';
}
function saveContactData( $name = '', $email = '', $phone = '', $message = '', $zip = '', $title = '', $company = '', $invoiceNumber = '', $address = '', $formId = '', $voivodeship = '', $clientType = '', $consentOffer = 0, $consentMarketing = 0, $attachments = [] )
{
// Konfiguracja bazy danych
$dbHost = 'mysql8';
@@ -191,6 +322,7 @@ function saveContactData( $name = '', $email = '', $phone = '', $message = '', $
{
$pdo = new PDO("mysql:host=$dbHost;dbname=$dbName;charset=utf8mb4", $dbUser, $dbPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
ensureContactMessagesAttachmentsColumn($pdo);
// Przygotowanie danych
$data = [
@@ -209,14 +341,15 @@ function saveContactData( $name = '', $email = '', $phone = '', $message = '', $
'client_type' => str_replace(['\'', '"'], '', $clientType),
'consent_offer' => (int)$consentOffer,
'consent_marketing' => (int)$consentMarketing,
'attachments' => !empty($attachments) ? json_encode(array_values($attachments), JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) : null,
'created_at' => date('Y-m-d H:i:s')
];
// Zaktualizowane zapytanie SQL
$sql = "INSERT INTO contact_messages
(form_id, name, email, phone, message, zip_code, topic, company, invoice_number, address, voivodeship, client_type, consent_offer, consent_marketing, created_at)
(form_id, name, email, phone, message, zip_code, topic, company, invoice_number, address, voivodeship, client_type, consent_offer, consent_marketing, attachments, created_at)
VALUES
(:form_id, :name, :email, :phone, :message, :zip_code, :topic, :company, :invoice_number, :address, :voivodeship, :client_type, :consent_offer, :consent_marketing, :created_at)";
(:form_id, :name, :email, :phone, :message, :zip_code, :topic, :company, :invoice_number, :address, :voivodeship, :client_type, :consent_offer, :consent_marketing, :attachments, :created_at)";
$stmt = $pdo->prepare($sql);
$stmt->execute($data);
@@ -305,17 +438,8 @@ if ( \S::get('action') == 'send-contact-modal' and \S::get('token') == \S::get_s
exit;
}
$countfiles = count($_FILES['files']['name']);
for ($i = 0; $i < $countfiles; $i++)
{
$filename = $_FILES['files']['name'][$i];
if ($filename and pathinfo($_FILES['files']['name'][$i], PATHINFO_EXTENSION) != 'php')
{
move_uploaded_file($_FILES['files']['tmp_name'][$i], 'temp/' . $filename);
$files_to_send[] = 'temp/' . $filename;
}
}
$files_to_send = [];
$attachment_links = [];
if ( \S::get( 'name' ) and \S::get( 'email' ) and \S::get( 'address' ) and \S::get( 'phone' ) and strposa( \S::get( 'name' ), $spam_words ) === false and strposa( \S::get( 'email' ), $spam_words ) === false and strposa( \S::get( 'address' ), $spam_words ) === false and strposa( \S::get( 'phone' ), $spam_words ) === false and strposa( \S::get( 'information' ), $spam_words ) === false )
{
@@ -335,7 +459,17 @@ if ( \S::get('action') == 'send-contact-modal' and \S::get('token') == \S::get_s
$fullMessage .= "\n\n--- Wymiary stolarki ---\n" . \S::get('wymiaryStolarki');
}
saveContactData( \S::get('name'), \S::get('email'), \S::get('phone'), $fullMessage, \S::get('address'), '', '', '', '', 'modal-contact-form', '', '', $zgoda1, $zgoda2 );
$uploadedFiles = saveContactAttachments();
if (!$uploadedFiles['success'])
{
\S::alert(contactAttachmentFailureMessage());
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
$files_to_send = $uploadedFiles['files_to_send'];
$attachment_links = $uploadedFiles['links'];
saveContactData( \S::get('name'), \S::get('email'), \S::get('phone'), $fullMessage, \S::get('address'), '', '', '', '', 'modal-contact-form', '', '', $zgoda1, $zgoda2, $attachment_links );
if ( \S::send_email( 'marketing@vidok.com', 'Wiadomość ze strony vidok.com', $text, \S::get('email'), $files_to_send ) )
{
@@ -459,18 +593,8 @@ if (\S::get('action') == 'send-contact-form-new' and \S::get('token') == \S::get
// should return JSON with success as true
if ($responseKeys["success"])
{
$countfiles = count($_FILES['files']['name']);
for ($i = 0; $i < $countfiles; $i++)
{
$filename = $_FILES['files']['name'][$i];
if ($filename and pathinfo($_FILES['files']['name'][$i], PATHINFO_EXTENSION) != 'php')
{
move_uploaded_file($_FILES['files']['tmp_name'][$i], 'temp/' . $filename);
$files_to_send[] = 'temp/' . $filename;
}
}
$files_to_send = [];
$attachment_links = [];
if ( \S::get('name') and \S::get('email') and \S::get('postal_code') and \S::get('phone') and \S::get('voivodeship') and \S::get('client') and strposa(\S::get('name'), $spam_words) === false and strposa(\S::get('email'), $spam_words) === false and
strposa(\S::get('postal_code'), $spam_words) === false and strposa(\S::get('phone'), $spam_words) === false and strposa(\S::get('message'), $spam_words) === false
@@ -488,7 +612,17 @@ if (\S::get('action') == 'send-contact-form-new' and \S::get('token') == \S::get
$zgoda1 = (\S::get('zgoda_1') == 'on' || \S::get('zgoda_1') == 1) ? 1 : 0;
$zgoda2 = (\S::get('zgoda_2') == 'on' || \S::get('zgoda_2') == 1) ? 1 : 0;
saveContactData( \S::get('name'), \S::get('email'), \S::get('phone'), \S::get('message'), \S::get('postal_code'), '', '', '', '', 'contact-form-new', \S::get('voivodeship'), \S::get('client'), $zgoda1, $zgoda2 );
$uploadedFiles = saveContactAttachments();
if (!$uploadedFiles['success'])
{
\S::alert(contactAttachmentFailureMessage());
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
$files_to_send = $uploadedFiles['files_to_send'];
$attachment_links = $uploadedFiles['links'];
saveContactData( \S::get('name'), \S::get('email'), \S::get('phone'), \S::get('message'), \S::get('postal_code'), '', '', '', '', 'contact-form-new', \S::get('voivodeship'), \S::get('client'), $zgoda1, $zgoda2, $attachment_links );
if (\S::send_email('marketing@vidok.com', 'Wiadomość ze strony vidok.com', $text, \S::get('email'), $files_to_send))
{
@@ -608,18 +742,8 @@ if (\S::get('action') == 'send-contact-form-new-2' and \S::get('token') == \S::g
// should return JSON with success as true
if ($responseKeys["success"])
{
$countfiles = count($_FILES['files']['name']);
for ($i = 0; $i < $countfiles; $i++)
{
$filename = $_FILES['files']['name'][$i];
if ($filename and pathinfo($_FILES['files']['name'][$i], PATHINFO_EXTENSION) != 'php')
{
move_uploaded_file($_FILES['files']['tmp_name'][$i], 'temp/' . $filename);
$files_to_send[] = 'temp/' . $filename;
}
}
$files_to_send = [];
$attachment_links = [];
if ( \S::get('name') and \S::get('email') and \S::get('postal_code') and \S::get('phone') and \S::get('voivodeship') and \S::get('client') and strposa(\S::get('name'), $spam_words) === false and strposa(\S::get('email'), $spam_words) === false and
strposa(\S::get('postal_code'), $spam_words) === false and strposa(\S::get('phone'), $spam_words) === false and strposa(\S::get('message'), $spam_words) === false
@@ -638,7 +762,17 @@ if (\S::get('action') == 'send-contact-form-new-2' and \S::get('token') == \S::g
$zgoda1 = (\S::get('zgoda_1') == 'on' || \S::get('zgoda_1') == 1) ? 1 : 0;
$zgoda2 = (\S::get('zgoda_2') == 'on' || \S::get('zgoda_2') == 1) ? 1 : 0;
saveContactData( \S::get('name'), \S::get('email'), \S::get('phone'), \S::get('message'), \S::get('postal_code'), '', '', '', '', 'contact-form-new', \S::get('voivodeship'), \S::get('client'), $zgoda1, $zgoda2 );
$uploadedFiles = saveContactAttachments();
if (!$uploadedFiles['success'])
{
\S::alert(contactAttachmentFailureMessage());
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
$files_to_send = $uploadedFiles['files_to_send'];
$attachment_links = $uploadedFiles['links'];
saveContactData( \S::get('name'), \S::get('email'), \S::get('phone'), \S::get('message'), \S::get('postal_code'), '', '', '', '', 'contact-form-new', \S::get('voivodeship'), \S::get('client'), $zgoda1, $zgoda2, $attachment_links );
if (\S::send_email('marketing@vidok.com', 'Wiadomość ze strony vidok.com', $text, \S::get('email'), $files_to_send))
{
@@ -751,18 +885,8 @@ if (\S::get('action') == 'send-contact-form-new-deweloper' and \S::get('token')
// should return JSON with success as true
if ($responseKeys["success"])
{
$countfiles = count($_FILES['files']['name']);
for ($i = 0; $i < $countfiles; $i++)
{
$filename = $_FILES['files']['name'][$i];
if ($filename and pathinfo($_FILES['files']['name'][$i], PATHINFO_EXTENSION) != 'php')
{
move_uploaded_file($_FILES['files']['tmp_name'][$i], 'temp/' . $filename);
$files_to_send[] = 'temp/' . $filename;
}
}
$files_to_send = [];
$attachment_links = [];
if ( \S::get('name') and \S::get('email') and \S::get('postal_code') and \S::get('phone') and \S::get('voivodeship') and \S::get('client') and strposa(\S::get('name'), $spam_words) === false and strposa(\S::get('email'), $spam_words) === false and
strposa(\S::get('postal_code'), $spam_words) === false and strposa(\S::get('phone'), $spam_words) === false and strposa(\S::get('message'), $spam_words) === false
@@ -783,7 +907,17 @@ if (\S::get('action') == 'send-contact-form-new-deweloper' and \S::get('token')
$zgoda1 = (\S::get('zgoda_1') == 'on' || \S::get('zgoda_1') == 1) ? 1 : 0;
$zgoda2 = (\S::get('zgoda_2') == 'on' || \S::get('zgoda_2') == 1) ? 1 : 0;
saveContactData( \S::get('name'), \S::get('email'), \S::get('phone'), \S::get('message'), \S::get('postal_code'), '', '', '', '', 'contact-form-new', \S::get('voivodeship'), \S::get('client'), $zgoda1, $zgoda2 );
$uploadedFiles = saveContactAttachments();
if (!$uploadedFiles['success'])
{
\S::alert(contactAttachmentFailureMessage());
header('Location: ' . $_SERVER['REQUEST_URI']);
exit;
}
$files_to_send = $uploadedFiles['files_to_send'];
$attachment_links = $uploadedFiles['links'];
saveContactData( \S::get('name'), \S::get('email'), \S::get('phone'), \S::get('message'), \S::get('postal_code'), '', '', '', '', 'contact-form-new', \S::get('voivodeship'), \S::get('client'), $zgoda1, $zgoda2, $attachment_links );
if (\S::send_email('marketing@vidok.com', 'Wiadomość ze strony vidok.com', $text, \S::get('email'), $files_to_send))
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -140,6 +140,7 @@
<div class="fileuploader fileuploader-theme-default">
<input type="hidden" name="fileuploader-list-files" value="[]">
<input type="file" name="files[]" class="files" multiple="multiple">
<p class="file-upload-info">Maksymalny rozmiar: 50 MB na plik. Dozwolone typy: PDF, JPG, PNG, DOC, DOCX, XLS, XLSX, CSV, TXT, XML, DWG, DXF, ZIP.</p>
<div class="fileuploader-items">
<ul class="fileuploader-items-list"></ul>
</div>
@@ -262,8 +263,8 @@
<script class="footer" type="text/javascript">
$(document).ready(function() {
$('#modal-contact-form input.files').fileuploader({
fileMaxSize: 10,
extensions: ['jpg', 'jpeg', 'png', 'pdf', 'text/plain', 'csv', 'xml', 'xls', 'xlsx', 'doc', 'dot', 'docx'],
fileMaxSize: 50,
extensions: ['jpg', 'jpeg', 'png', 'pdf', 'csv', 'txt', 'xml', 'xls', 'xlsx', 'doc', 'docx', 'dwg', 'dxf', 'zip'],
addMore: true,
captions: {
button: function(e) {

View File

@@ -255,7 +255,7 @@
<textarea name="message" placeholder="Opis zgłoszenia. Jeżeli masz jakieś uwagi, wytyczne możesz wpisać je tutaj."></textarea>
</div>
<div class="_text">
<p>Chcesz przesłać nam wizualizacje, projekt lub inne materiały? Skorzystaj z pola poniżej i dodaj plik do wiadomości.</p>
<p>Chcesz przesłać nam wizualizacje, projekt lub inne materiały? Skorzystaj z pola poniżej i dodaj plik do wiadomości. Maksymalny rozmiar: 50 MB na plik. Dozwolone typy: PDF, JPG, PNG, DOC, DOCX, XLS, XLSX, CSV, TXT, XML, DWG, DXF, ZIP.</p>
</div>
<div class="_file fileuploader fileuploader-theme-default">
<input type="hidden" name="fileuploader-list-files" value="[]">
@@ -316,7 +316,7 @@
<textarea name="message" placeholder="Opis zgłoszenia. Jeżeli masz jakieś uwagi, wytyczne możesz wpisać je tutaj."></textarea>
</div>
<div class="_text">
<p>Chcesz przesłać nam wizualizacje, projekt lub inne materiały? Skorzystaj z pola poniżej i dodaj plik do wiadomości.</p>
<p>Chcesz przesłać nam wizualizacje, projekt lub inne materiały? Skorzystaj z pola poniżej i dodaj plik do wiadomości. Maksymalny rozmiar: 50 MB na plik. Dozwolone typy: PDF, JPG, PNG, DOC, DOCX, XLS, XLSX, CSV, TXT, XML, DWG, DXF, ZIP.</p>
</div>
<div class="_file fileuploader fileuploader-theme-default">
<input type="hidden" name="fileuploader-list-files" value="[]">
@@ -666,8 +666,8 @@
* File uploader
*/
$('#contact-form-new input.files').fileuploader({
fileMaxSize: 10,
extensions: ['jpg', 'jpeg', 'png', 'pdf', 'text/plain', 'csv', 'xml', 'xls', 'xlsx', 'doc', 'dot', 'docx'],
fileMaxSize: 50,
extensions: ['jpg', 'jpeg', 'png', 'pdf', 'csv', 'txt', 'xml', 'xls', 'xlsx', 'doc', 'docx', 'dwg', 'dxf', 'zip'],
addMore: true,
captions: {
button: function(e) {