# Architecture — PCDesigner

This document is the canonical map of the PCDesigner / Web 2 Print Solution plugin (v2.4.9). When in doubt, code wins; please update this document when you change the structure.

## 1. Bird's-eye view

```
                  ┌─────────────────────────────────────┐
                  │   Customer (storefront)             │
                  │   — Studio editor (Fabric.js)       │
                  │   — Cart / checkout                 │
                  │   — My Designs                      │
                  └──────────────┬──────────────────────┘
                                 │ AJAX / REST
                                 ▼
   ┌──────────────────────────────────────────────────────┐
   │   WordPress + WooCommerce                            │
   │                                                      │
   │   PCDesigner plugin (this repo)                      │
   │   ├── Bootstrap (nbdesigner.php)                     │
   │   ├── Core controller (class.nbdesigner.php)         │
   │   ├── REST/AJAX surface (class-api.php, ...)         │
   │   ├── Editor / Builder (views/, templates/)          │
   │   ├── Output pipeline (class-output.php, lib/tcpdf)  │
   │   ├── Marketplace (Launcher/)                        │
   │   ├── Background processes (export-pdf, preview)     │
   │   └── Cloud bridge (class-printcart-*.php)           │
   │                                                      │
   └──────────────┬───────────────────────────────────────┘
                  │
                  ▼
   ┌──────────────────────────────────────────────────────┐
   │   Printcart Cloud SaaS                               │
   │   — Licensing                                         │
   │   — Multi-store sync                                  │
   │   — AI design services                                │
   │   — Marketplace clearing                              │
   │   — Cloud rendering & storage (S3 / GCS / Dropbox)    │
   │   — Firebase live chat                                │
   └──────────────────────────────────────────────────────┘
```

## 2. Boot sequence

`nbdesigner.php` runs on every WP request:

1. Defines all `NBDESIGNER_*` constants from `wp_upload_dir()`.
2. Resolves URL quirks for multisite + WPML.
3. Requires ~40 PHP files in deterministic order — order matters because some classes depend on globals from earlier ones.
4. Instantiates `Nbdesigner_Plugin`, `My_Design_Endpoint`, `Nbdesigner_Compatibility`.
5. Registers activation/deactivation hooks.
6. Declares HPOS compatibility for WooCommerce.
7. Optionally re-defines `K_PATH_FONTS` (TCPDF font path).
8. Fires `do_action( 'nbd_loaded' )` — the official extension hook.

When you add a new class file, append a `require_once` after the relevant peers, never alphabetically.

## 3. Module catalogue

### 3.1 Core controller

`includes/class.nbdesigner.php` (~7,535 LOC) is the hub. It registers:

- All AJAX handlers (`add_action('wp_ajax_*', ...)`).
- WooCommerce cart / checkout / order hooks.
- Admin menu pages and asset enqueues.
- Setup wizard entry point.
- License event scheduling (`nbdesigner_lincense_event` — typo intentional).

Because the file is so large, treat it as a registry: avoid adding more than a method or two; any new feature should live in its own class.

### 3.2 REST + AJAX surface

| File | Namespace |
|---|---|
| `includes/class-api.php` | REST `nbd/v1` (gallery generator, public reads) |
| `includes/class-printcart-custom-api-wc.php` | WC REST `wc/v3/printcart/*` (auth handshake) |
| `includes/class-printcart-api.php` | Outbound to `api.printcart.com/v1` (license, tiers) |
| `includes/class-printcart-general.php` | AJAX bridge for dashboard widget |

AJAX actions are registered across many files but discoverable with:

```bash
grep -rn "add_action.*wp_ajax" includes/
```

### 3.3 Editor & builder

| Concern | Location |
|---|---|
| Customer editor templates | `templates/studio.php`, `templates/mobile.php`, `templates/quick-view*.php` |
| Modern layout views | `views/modern/` |
| Vista layout views | `views/vista/` |
| Editor partials | `views/editor_components/` |
| Admin product builder | `views/product-builder/`, `includes/class.product-builder.php` |
| Fabric extensions | `assets/js/fabric.curvedText.js`, `assets/js/fabric.removeColor.js` |
| Bundles | `assets/js/designer.min.js`, `designer-modern.min.js`, `app-modern.min.js`, `app-vista.min.js`, `app-product-builder.js` |

### 3.4 Output pipeline

```
Front-end save  →  AJAX nbd_save_customer_design
                   ├── stores SVG + JSON in
                   │    wp-content/uploads/nbdesigner/designs/<key>/
                   └── inserts row in wp_nbdesigner_mydesigns

Front-end download (PDF/JPEG)
   ├── sync   → class-output.php → lib/tcpdf
   └── async  → background-processes/export-pdf.php (WP_Background_Process)

Print-ready  → optional ICC profile from data/_icc/ (16 profiles)
            → cloud upload via class-printcart-api.php (S3/GCS/Dropbox)
```

### 3.5 Marketplace (Launcher)

`includes/launcher/` is a self-contained module:

- `class.launcher.php` — boot
- `class.designer.php` — designer profile
- `class.design.php` — design entity
- `class.withdraw.php` — payouts
- `class.generate.preview.process.php` — async preview generation
- `api/`, `emails/`

Tied to custom table `wp_nbdesigner_user_designs`.

### 3.6 Settings + options

`includes/options/` is the field framework. `includes/settings/*.php` defines the tabs (general, appearance, colors, frontend, libraries, live-chat, output, printing_option, request-quote, upload, launcher).

All options share the `nbdesigner_*` prefix and read through `nbdesigner_get_option($key, $default)` (defined in `class-helper.php`).

### 3.7 Cloud bridge

`class-printcart-api.php`:

- Stores `nbdesigner_printcart_api_sid`, `nbdesigner_printcart_api_secret`, `nbdesigner_printcart_api_token` (autoload OFF).
- Calls `wp_remote_get/post` with Basic Auth.
- Exposes helpers: `check_tier()`, `sync_store()`, `validate_license()`.

Outbound cron: `nbdesigner_lincense_event` (daily). Do not rename without a migration.

### 3.8 Compatibility layer

`includes/class-compatibility.php` adapts to:

- WPML (re-uses `icl_get_home_url` for multisite domains)
- WooCommerce HPOS
- Dokan multivendor
- Theme-specific quirks (Flatsome, Astra, OceanWP)

### 3.9 Background processing

| File | Purpose |
|---|---|
| `includes/background-processes.php` | Loader for queues |
| `includes/background-processes/export-pdf.php` | PDF render queue |
| `includes/launcher/class.generate.preview.process.php` | Marketplace preview queue |

These extend `WP_Background_Process` (adapted from `WP_Async_Task` library).

### 3.10 Internationalisation

- `langs/web-to-print-online-designer.pot` — POT template
- `data/language/en_US.json` — editor UI strings
- `views/nbdesigner-translate.php` — runtime injection

## 4. Database schema

```sql
CREATE TABLE wp_nbdesigner_templates (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  product_id BIGINT UNSIGNED,
  variation_id BIGINT UNSIGNED,
  user_id BIGINT UNSIGNED,
  name VARCHAR(255),
  folder VARCHAR(255),
  thumbnail VARCHAR(255),
  publish TINYINT,
  priority INT,
  hit INT,
  sales INT,
  vote DECIMAL(3,2),
  type VARCHAR(50),
  resource TEXT,
  tags VARCHAR(500),
  colors VARCHAR(255),
  created_date DATETIME,
  updated_date DATETIME,
  KEY idx_product (product_id),
  KEY idx_publish (publish, priority)
);

CREATE TABLE wp_nbdesigner_mydesigns (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  design_id VARCHAR(64),
  user_id BIGINT UNSIGNED,
  product_id BIGINT UNSIGNED,
  cart_item_key VARCHAR(64),
  state ENUM('draft','saved'),
  created_date DATETIME,
  updated_date DATETIME,
  KEY idx_user (user_id),
  KEY idx_state (state)
);

CREATE TABLE wp_nbdesigner_user_designs (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  designer_id BIGINT UNSIGNED,
  product_id BIGINT UNSIGNED,
  category_id BIGINT UNSIGNED,
  name VARCHAR(255),
  thumbnail VARCHAR(255),
  price DECIMAL(10,2),
  created_date DATETIME,
  published TINYINT,
  KEY idx_designer (designer_id),
  KEY idx_published (published)
);

CREATE TABLE wp_nbdesigner_options (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  product_id BIGINT UNSIGNED,
  fields LONGTEXT,
  KEY idx_product (product_id)
);
```

(Field types are reverse-engineered; adjust to actual `class-install.php` if you migrate.)

## 5. Filesystem layout (uploads)

```
wp-content/uploads/nbdesigner/
├── fonts/            (custom fonts uploaded via admin)
├── php-fonts/        (TCPDF compiled fonts; K_PATH_FONTS)
├── cliparts/         (clipart library)
├── download/         (rendered downloads ready for customer)
├── designs/          (one folder per saved design)
│   └── <key>/        (SVG, JSON, preview, source uploads)
├── pdfs/             (rendered PDFs)
├── temp/             (transient render artefacts; safe to purge)
├── admindesign/      (admin templates)
├── suggest_designs/  (designer marketplace previews)
├── uploads/          (raw user uploads)
├── data/             (per-store config dumps)
└── logs/             (debug logs when WP_DEBUG_LOG=1)
```

`.htaccess` should deny `.php` execution in this tree. Verify with `class-install.php`.

## 6. Hook reference

Most-used WC hooks (consumer side):

```
woocommerce_before_single_product
woocommerce_before_add_to_cart_button
woocommerce_after_add_to_cart_button
woocommerce_add_cart_item_data
woocommerce_get_cart_item_from_session
woocommerce_after_cart_item_name
woocommerce_before_calculate_totals
woocommerce_order_again_cart_item_data
woocommerce_checkout_create_order_line_item
woocommerce_checkout_order_processed
woocommerce_admin_order_actions
woocommerce_hidden_order_itemmeta
woocommerce_product_after_variable_attributes
woocommerce_save_product_variation
```

Plugin-internal hooks:

```
nbd_loaded                    — fires after bootstrap; safe extension point
nbd_before_save_customer_design
nbd_after_save_customer_design
nbd_before_render_pdf
nbd_after_render_pdf
nbd_template_assigned         — when a global template is bound to a product
nbd_artwork_approved
nbd_artwork_rejected
nbd_quote_requested
```

(Names approximate; verify with `grep -rn "do_action" includes/`.)

## 7. Dependency graph

```
nbdesigner.php
   └─→ class-pc-script-hook.php (enqueue)
   └─→ class-util.php          (helpers; required by most)
   └─→ class-template-loader.php (override system)
   └─→ class-settings.php
   └─→ class-helper.php
   └─→ class.nbdesigner.php    (core controller; depends on all above)
   └─→ class.my.design.php
   └─→ class.product-builder.php
   └─→ class.templates-global.php
   └─→ class.template-mapping.php
   └─→ class-shortcodes.php
   └─→ class-api.php
   └─→ class-printcart-*.php
   └─→ class-3d-preview.php
   └─→ launcher/class.launcher.php (and friends)
```

If you change the order, validate by activating on a clean WP and grepping `wp-content/debug.log` for `Class … not found`.

## 8. Front-end architecture (assets/)

```
assets/
├── libs/      (third-party JS — keep versions pinned)
├── js/
│   ├── 3d/                    (Three.js modules)
│   ├── designer.min.js
│   ├── designer-modern.min.js
│   ├── app-modern.min.js
│   ├── app-vista.min.js
│   ├── app-product-builder.js
│   ├── bundle-modern.min.js
│   ├── customizer.js
│   ├── nbd-setup.js
│   └── (legacy Angular admin scripts)
├── css/       (admin + frontend)
├── fonts/     (icon font)
├── images/
├── codemirror/  (in-app code editor for custom CSS/JS)
└── package.json (legacy gulp + webpack toolchain)
```

Build pipeline is currently gulp 3 + node-sass + webpack 4. Migration plan in `docs/PERFORMANCE.md`.

## 9. External services map

| Service | Used for | Auth |
|---|---|---|
| `api.printcart.com/v1` | License, AI, sync | Basic SID:SECRET + token |
| `dashboard.printcart.com` | Setup wizard handshake | OAuth-ish redirect |
| AWS S3 | Optional design storage | IAM keys |
| Google Cloud Storage | Optional design storage | service account JSON |
| Dropbox | Optional design storage | OAuth token |
| Firebase | Live chat realtime + JWT | Firebase config |
| Google Fonts | Font listing & loading | API key |
| Instagram | User photo import | OAuth |
| Unsplash | Stock photos | API key (proxied since v2.4.6) |
| Pexels | Stock photos | API key |
| Freepik | Stock images | API key |
| Facebook Graph | Photo album import | OAuth |

## 10. Extension points for forks

If you fork or build an add-on:

- Hook into `nbd_loaded` for early bootstrap.
- Use `nbdesigner_get_option` / `update_option` to read/write settings.
- Override templates via your theme: copy `templates/<file>` to `<theme>/web-to-print-online-designer/<file>`.
- Add a Fabric tool by enqueueing your script after `designer-modern.min.js` and registering with `window.nbDesigner.registerTool(...)` (verify symbol; this is the convention).
- Register a niche by adding a folder under `includes/niches/<slug>/` (proposed convention; see `pcd-niche-strategist` skill).

## 11. Known smells

- `class.nbdesigner.php` is too big (~7.5k LOC). Refactor target: split into per-domain controllers.
- AngularJS 1.6 in admin. Migrate to vanilla / React island.
- Mixed naming `class-foo.php` and `class.foo.php`. New files use `class-foo.php`.
- `NBDESIGNER_VERSION` constant lags the plugin header by one patch sometimes.
- `nbdesigner_lincense_event` cron name has a typo we keep for backwards compatibility.
- Some AJAX endpoints accept `_REQUEST` instead of `_POST`/`_GET`. Tighten over time.

## 12. Ownership map (proposed)

| Area | Suggested owner |
|---|---|
| Core controller refactor | Senior PHP eng |
| Editor (Fabric / 3D) | Front-end lead |
| Output pipeline | Print engineer |
| Cloud bridge | Cloud team |
| Marketplace | Product manager + payments eng |
| Settings / wizard | UX lead |
| Compatibility / hosting | Support eng |

Adjust to actual team layout.
