# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

adsPRO is a PHP web application for managing Google Ads, Facebook Ads, and Google Merchant Center campaigns. It tracks campaign performance (ROAS, budgets, conversions), manages product feeds, and provides AI-powered suggestions for product titles/descriptions. The UI is in Polish.

## Tech Stack

- **PHP** (no framework, custom MVC-like architecture)
- **MySQL** via Medoo ORM (`$mdb` global) and RedBeanPHP (`\R::`) in legacy endpoints
- **Frontend**: jQuery, DataTables, Highcharts, Select2, Bootstrap 5, Font Awesome 6
- **SCSS** for styling (`layout/style.scss` → `layout/style.css`)
- **Google Ads REST API** v23 (direct cURL, no SDK)
- **Facebook Ads Graph API** (direct cURL)
- **AI services**: OpenAI, Claude, Gemini APIs for product text suggestions

## Architecture

### Request Flow

`index.php` is the single entry point. `.htaccess` rewrites all non-static requests to it. The router uses a `$route_aliases` map and fallback URL segment parsing (`/module/action`) to set `$_GET['module']` and `$_GET['action']`. `\controls\Site::route()` instantiates `\controls\{Module}` and calls the action method.

Other entry points:
- `ajax.php` — AJAX requests (same autoloader, session-based auth with IP binding)
- `api.php` — external API endpoints (domain tester, Open Page Rank)
- `cron.php` — legacy cron (task reminders, recurring tasks)

### Autoloader & Namespace Convention

`spl_autoload_register` maps namespaces to filesystem paths:
- `\controls\Campaigns` → `autoload/controls/class.Campaigns.php`
- `\factory\Clients` → `autoload/factory/class.Clients.php`
- `\services\GoogleAdsApi` → `autoload/services/class.GoogleAdsApi.php`
- `\view\Site` → `autoload/view/class.Site.php`

File naming: `class.{ClassName}.php`. Root-level classes (no namespace): `autoload/class.{Name}.php`.

### Layer Responsibilities

- **`autoload/controls/`** — Controllers. Handle request params via `\S::get()`, call factory/services, return HTML (via `\Tpl::view()`) or `echo json_encode()` + `exit` for AJAX.
- **`autoload/factory/`** — Data access layer. Static methods wrapping `$mdb` queries. Named after domain entities (Clients, Campaigns, Products, etc.).
- **`autoload/services/`** — External API integrations (GoogleAdsApi, FacebookAdsApi, ClaudeApi, OpenAiApi, GeminiApi, SupplementalFeed).
- **`autoload/view/`** — View helpers. Thin wrappers that call `\Tpl::view()` with template path and data.
- **`templates/{module}/`** — PHP template files rendered by `Tpl::view()`. Templates access data via `$this->varName`.

### Key Base Classes

- **`\S`** — Static utility: `get()` reads POST/GET, `get_session()`/`set_session()` for sessions, `alert()` for flash messages, `send_email()` for SMTP.
- **`\Tpl`** — Template engine. `Tpl::view('module/template', [...])` renders `templates/module/template.php`. Looks in `templates_user/` first (override), then `templates/`.
- **`\DbModel`** — Active Record base class. Subclasses set `$table`; provides `save()`, `delete()`.
- **`\Cache`** — File-based cache in `temp/` directory. `Cache::store($key, $data, $ttl)` / `Cache::fetch($key)`.

### Settings Storage

App settings (API keys, cron state, feature flags) are stored in a `settings` DB table as key-value pairs. Access via `\services\GoogleAdsApi::get_setting($key)` / `set_setting($key, $value)` — these are used globally, not just for Google Ads.

## Database Migrations

Numbered SQL files in `migrations/` (e.g., `001_google_ads_settings.sql`). Run via:

```bash
php install.php                    # apply pending migrations
php install.php --force            # re-apply all migrations
php install.php --with_demo        # include demo_data.sql
```

Tracks applied migrations in `schema_migrations` table.

## Cron System

Multiple cron endpoints called externally (e.g., every 1-5 minutes):

| Endpoint | Purpose |
|---|---|
| `/cron.php` | Legacy: task reminders, recurring tasks |
| `/cron/cron_universal` | Google Ads campaigns + products sync (backfill window) |
| `/cron/cron_campaigns_product_alerts_merchant` | Product alerts from Merchant Center |
| `/cron/cron_products_urls` | Fetch product URLs from Merchant Center |
| `/cron/cron_facebook_ads` | Facebook Ads sync (30-day window) |

Progress is tracked in `cron_sync_status` table with phases (pending → fetch → aggregate_30 → done). Dashboard at `/settings` shows real-time progress with ETA calculations.

## Supplemental Feeds

`\services\SupplementalFeed::generate_for_client($id)` generates TSV files in `feeds/` directory (e.g., `feeds/supplemental_1.tsv`) for Google Merchant Center. Managed via `/feeds` UI.

## Coding Conventions

- All classes use static methods extensively
- Database access uses the global `$mdb` (Medoo instance) — never instantiate a new connection
- AJAX endpoints: `echo json_encode([...])` then `exit`
- Page actions: return HTML string from `\Tpl::view()`
- POST/GET params: always use `\S::get('param_name')`, never `$_POST`/`$_GET` directly
- Flash messages: `\S::alert('message')` then `header('Location: ...')` + `exit`
- Timezone: `Europe/Warsaw`
- Currency display: `\S::number_display($value)` formats as "1 234,56 zł"
- All user-facing strings are in Polish

## Adding a New Module

1. Create controller: `autoload/controls/class.{ModuleName}.php` (namespace `controls`)
2. Create factory: `autoload/factory/class.{ModuleName}.php` (namespace `factory`)
3. Optionally create view helper: `autoload/view/class.{ModuleName}.php` (namespace `view`)
4. Create templates: `templates/{module_name}/main_view.php` etc.
5. Add route aliases in `index.php` `$route_aliases` array if clean URLs are needed
6. Add sidebar link in `templates/site/layout-logged.php`

## Frontend Libraries (in `libraries/`)

- `medoo/` — Medoo PHP database framework (SQL builder)
- `rb.php` — RedBeanPHP ORM (used in legacy `api.php`, `cron.php`)
- `phpmailer/` — Email sending
- `framework/` — jQuery UI, Bootstrap, various jQuery plugins
- `functions.js` — Shared JS utilities
- `adspro-dialog.js/.css` — Custom modal dialog component
