339 lines
11 KiB
Markdown
339 lines
11 KiB
Markdown
# Database Schema
|
|
|
|
**Updated:** 2026-05-05 | **Total tables:** ~32 | **Engine:** MySQL InnoDB | **Prefix:** `pp_`
|
|
|
|
Schema inferred from Medoo ORM queries in PHP source files. No migration files found — schema managed manually.
|
|
|
|
---
|
|
|
|
## Content — Articles
|
|
|
|
**`pp_articles`** — Main article/content records
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `hash` | VARCHAR | Unique identifier for external reference |
|
|
| `status` | TINYINT | Published/draft/archived |
|
|
| `date_add` | DATETIME | Creation timestamp |
|
|
| `views` | INT | View counter |
|
|
| `password` | VARCHAR | Optional password protection |
|
|
| `pixieset` | VARCHAR | Pixieset gallery identifier |
|
|
|
|
**`pp_articles_langs`** — Language-specific article content
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `article_id` | INT | FK → `pp_articles.id` |
|
|
| `lang_id` | INT | FK → `pp_langs.id` |
|
|
| `title` | VARCHAR | Article title |
|
|
| `content` | LONGTEXT | Rich text content |
|
|
| `seo_link` | VARCHAR | URL slug |
|
|
| `noindex` | TINYINT | SEO noindex flag |
|
|
|
|
**`pp_articles_images`** — Article gallery images
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `article_id` | INT | FK → `pp_articles.id` |
|
|
| `src` | VARCHAR | Image filename/path |
|
|
| `o` | INT | Sort order |
|
|
| `favorite` | TINYINT | Flagged as favorite |
|
|
| `to_delete` | TINYINT | Soft-delete flag |
|
|
|
|
**`pp_articles_files`** — Downloadable file attachments
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `article_id` | INT | FK → `pp_articles.id` |
|
|
| `src` | VARCHAR | File path |
|
|
| `name` | VARCHAR | Display name |
|
|
| `to_delete` | TINYINT | Soft-delete flag |
|
|
|
|
**`pp_articles_pages`** — Article-to-Page assignments
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `article_id` | INT | FK → `pp_articles.id` |
|
|
| `page_id` | INT | FK → `pp_pages.id` |
|
|
| `o` | INT | Sort order on page |
|
|
| `status` | TINYINT | Visibility on this page |
|
|
|
|
**`pp_articles_tags`** — Many-to-many: Articles ↔ Tags
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `article_id` | INT | FK → `pp_articles.id` |
|
|
| `tag_id` | INT | FK → `pp_tags.id` |
|
|
|
|
**`pp_articles_additional_params`** — Custom field definitions per article
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `article_id` | INT | FK → `pp_articles.id` |
|
|
| `name` | VARCHAR | Field name |
|
|
| `language` | VARCHAR | Language code |
|
|
| `status` | TINYINT | Active/inactive |
|
|
|
|
**`pp_articles_additional_values`** — Custom field values
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `param_id` | INT | FK → `pp_articles_additional_params.id` |
|
|
| `article_id` | INT | FK → `pp_articles.id` |
|
|
| `value` | TEXT | Field value |
|
|
| `language_id` | INT | FK → `pp_langs.id` |
|
|
|
|
---
|
|
|
|
## Content — Pages & Layouts
|
|
|
|
**`pp_pages`** — Website page hierarchy
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `menu_id` | INT | FK → `pp_menus.id` |
|
|
| `parent_id` | INT | Self-referencing for nested pages |
|
|
| `page_type` | VARCHAR | Type identifier |
|
|
| `sort_type` | VARCHAR | Article sort order |
|
|
| `status` | TINYINT | Published/hidden |
|
|
| `start` | TINYINT | Homepage flag |
|
|
| `o` | INT | Sort order in navigation |
|
|
| `cache` | TINYINT | Page-level cache toggle |
|
|
|
|
**`pp_pages_langs`** — Page language translations
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `page_id` | INT | FK → `pp_pages.id` |
|
|
| `lang_id` | INT | FK → `pp_langs.id` |
|
|
| `title` | VARCHAR | Page title |
|
|
| `seo_link` | VARCHAR | URL slug |
|
|
|
|
**`pp_layouts`** — Template layout containers
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `layout_id` | INT | Parent layout reference |
|
|
| `name` | VARCHAR | Layout name |
|
|
| `html` | LONGTEXT | Desktop HTML with `[PLACEHOLDER:id]` tags |
|
|
| `m_html` | LONGTEXT | Mobile HTML |
|
|
| `css` | TEXT | Inline CSS |
|
|
| `m_css` | TEXT | Mobile inline CSS |
|
|
| `js` | TEXT | Inline JS |
|
|
| `m_js` | TEXT | Mobile inline JS |
|
|
| `status` | TINYINT | Active/inactive |
|
|
|
|
**`pp_layouts_pages`** — Layout-to-page assignments
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `layout_id` | INT | FK → `pp_layouts.id` |
|
|
| `page_id` | INT | FK → `pp_pages.id` |
|
|
|
|
---
|
|
|
|
## Content — Static Containers & Banners
|
|
|
|
**`pp_scontainers`** — Reusable static content blocks
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `status` | TINYINT | Active/inactive |
|
|
|
|
**`pp_scontainers_langs`** — Static container translations
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `scontainer_id` | INT | FK → `pp_scontainers.id` |
|
|
| `lang_id` | INT | FK → `pp_langs.id` |
|
|
| `html` | LONGTEXT | Content HTML |
|
|
|
|
**`pp_banners`** — Promotional banners
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `name` | VARCHAR | Banner name |
|
|
| `status` | TINYINT | Active/inactive |
|
|
|
|
**`pp_banners_langs`** — Banner language versions
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `id_banner` | INT | FK → `pp_banners.id` |
|
|
| `id_lang` | INT | FK → `pp_langs.id` |
|
|
| `title` | VARCHAR | Banner title |
|
|
| `content` | TEXT | Banner content/HTML |
|
|
|
|
---
|
|
|
|
## Navigation & Taxonomy
|
|
|
|
**`pp_menus`** — Navigation menu definitions
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `name` | VARCHAR | Menu name |
|
|
|
|
**`pp_tags`** — Article tags/categories
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `name` | VARCHAR | Tag name |
|
|
|
|
**`pp_authors`** — Article author profiles
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
|
|
**`pp_authors_langs`** — Author translations
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `author_id` | INT | FK → `pp_authors.id` |
|
|
| `lang_id` | INT | FK → `pp_langs.id` |
|
|
|
|
---
|
|
|
|
## Users & Access Control
|
|
|
|
**`pp_users`** — Admin panel users
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `login` | VARCHAR | Username |
|
|
| `password` | VARCHAR | MD5 hash (security concern — see concerns.md) |
|
|
| `status` | TINYINT | Active/inactive |
|
|
| `active_to` | DATE | Account expiry date |
|
|
| `admin` | TINYINT | Super-admin flag |
|
|
| `error_logged_count` | INT | Failed login counter |
|
|
|
|
**`pp_users_privileges`** — User permission assignments
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id_user` | INT | FK → `pp_users.id` |
|
|
| `name` | VARCHAR | Privilege name (string key) |
|
|
|
|
---
|
|
|
|
## Multi-language
|
|
|
|
**`pp_langs`** — Available language configurations
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `start` | TINYINT | Default language flag |
|
|
| `domain` | VARCHAR | Domain for this language |
|
|
| `main_domain` | VARCHAR | Primary domain |
|
|
| `o` | INT | Sort order |
|
|
| `status` | TINYINT | Active/inactive |
|
|
|
|
**`pp_langs_translations`** — UI string translations
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| Dynamic columns per language ID | VARCHAR | Translation strings |
|
|
|
|
---
|
|
|
|
## Newsletter
|
|
|
|
**`pp_newsletter`** — Email subscribers
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `email` | VARCHAR | Subscriber email |
|
|
| `status` | TINYINT | Active/unsubscribed |
|
|
|
|
**`pp_newsletter_send`** — Sent campaign log
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `email_template_id` | INT | FK → `pp_newsletter_templates.id` |
|
|
|
|
**`pp_newsletter_templates`** — Email campaign templates
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
| `name` | VARCHAR | Template name |
|
|
| `subject` | VARCHAR | Email subject |
|
|
| `html` | LONGTEXT | Email HTML body |
|
|
|
|
---
|
|
|
|
## Contacts & Locations
|
|
|
|
**`pp_contacts_maps`** — Location/contact point entries
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `id` | INT | PK, AUTO_INCREMENT |
|
|
|
|
**`pp_contacts_maps_products`** — Product associations for locations
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `map_id` | INT | FK → `pp_contacts_maps.id` |
|
|
| `product_id` | INT | Product reference |
|
|
|
|
**`pp_contacts_maps_provinces`** — Province associations for locations
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `map_id` | INT | FK → `pp_contacts_maps.id` |
|
|
| `province_id` | INT | Province reference |
|
|
|
|
**`pp_contact_emails`** — Contact form submissions
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `email` | VARCHAR | Sender email |
|
|
| `phone` | VARCHAR | Sender phone |
|
|
| `title` | VARCHAR | Subject |
|
|
| `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
|
|
|
|
**`pp_seo_additional`** — Per-article SEO metadata
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `article_id` | INT | FK → `pp_articles.id` |
|
|
| `lang_id` | INT | FK → `pp_langs.id` |
|
|
|
|
**`pp_settings`** — Global CMS configuration (key-value store)
|
|
| Column | Type | Notes |
|
|
|--------|------|-------|
|
|
| `param` | VARCHAR | Setting key (e.g., `google_map_key`, `email_host`) |
|
|
| `value` | TEXT | Setting value |
|
|
|
|
---
|
|
|
|
## Schema Characteristics
|
|
|
|
| Property | Value |
|
|
|----------|-------|
|
|
| Engine | MySQL InnoDB |
|
|
| Table prefix | `pp_` |
|
|
| Soft deletes | `to_delete` column on `pp_articles_images`, `pp_articles_files` |
|
|
| Multi-language | All content tables have `_langs` counterpart |
|
|
| Migrations | None — schema managed manually |
|
|
| Timestamps | `date_add` on articles; not standardized across all tables |
|
|
|
|
## Key Relationships
|
|
|
|
- **1:N** — `pp_articles` → `pp_articles_images`, `pp_articles_files`, `pp_articles_langs`
|
|
- **N:N** — `pp_articles` ↔ `pp_tags` (via `pp_articles_tags`)
|
|
- **N:N** — `pp_articles` ↔ `pp_pages` (via `pp_articles_pages`)
|
|
- **Hierarchical** — `pp_pages.parent_id` self-reference for nested page tree
|
|
- **Language join** — all content tables join `pp_langs` on `lang_id` for translation
|