Files
adsPRO/.paul/codebase/architecture.md
2026-05-06 23:19:35 +02:00

6.0 KiB

Architecture

Entry points

File Purpose
index.php Main router. Autoloader (lines 3-12), session init, $route_aliases table (lines 40-59), URL-segment fallback (lines 70-79), auth via session or persistent cookie (lines 88-102), public-path whitelist for /api/*, /cron/*, /login (lines 106-118). Default module: campaigns/main_view.
ajax.php AJAX handler. Same autoloader. Session regeneration on first request, IP binding check (lines 28-33). Responses: echo json_encode(...); exit.
api.php External API endpoints (~1350 lines). Uses RedBeanPHP. Helpers api_json_response() and api_validate_api_key().
cron.php Legacy cron. Calls \Cron::tasks_emails() and \Cron::recursive_tasks().

Modern cron routes (dispatched through index.php → \controls\Cron):

Route Purpose
/cron/cron_universal Google Ads campaigns + products daily snapshot
/cron/cron_campaigns_product_alerts_merchant Product alerts from Merchant Center
/cron/cron_products_urls Bulk fetch product URLs
/cron/cron_facebook_ads Facebook Ads sync (30-day window)
/cron/cron_xml_feed_import Import supplemental/product XML feeds

Routing

index.php builds a request URL into $_GET['module'] and $_GET['action']:

  1. Apply $route_aliases map (e.g. /loginusers/login_form).
  2. Fallback: /$seg0/$seg1module=$seg0, action=$seg1.
  3. Default: campaigns/main_view.
  4. \controls\Site::route() instantiates \controls\{Module} and calls action method.

Layers

Controllers — autoload/controls/ (namespace \controls)

Static action methods. Pattern:

$id = (int) \S::get('client_id');
$rows = \factory\Campaigns::get_campaigns_list($id);
echo json_encode($rows); exit;          // AJAX
return \Tpl::view('campaigns/main_view', ['clients' => $rows]); // page

Representative files: autoload/controls/class.Campaigns.php, autoload/controls/class.Products.php, autoload/controls/class.Cron.php (~5,200 lines — see concerns.md).

Factories — autoload/factory/ (namespace \factory)

Static methods wrapping $mdb queries. Examples:

Services — autoload/services/ (namespace \services)

External API integrations (see integrations.md).

Views — autoload/view/ (namespace \view)

Thin orchestrators. autoload/view/class.Site.php wraps controller output in site/layout-logged.php, injecting campaign_alerts_count, user, current_module, flash alerts.

Templates — templates/{module}/

Rendered via \Tpl::view('module/file', $data). Lookup order: templates_user/ (override) → templates/. Data accessed in templates as $this->varName (magic __get). Output captured with ob_start/ob_get_clean.

Modules

Module Controller Purpose
campaigns \controls\Campaigns Google Ads campaign list, history, charts, alerts
products \controls\Products Merchant Center product feed, AI title/desc suggestions
clients \controls\Clients Merchant accounts (Google Ads ID, Merchant ID, settings)
users \controls\Users Auth, settings, API key, cron status dashboard
feeds \controls\Feeds Supplemental TSV feed generation
logs \controls\Logs System event log viewer
campaign_alerts \controls\CampaignAlerts AI-detected campaign issues
campaign_terms \controls\CampaignTerms Search term aggregation, keyword suggestions
facebook_ads \controls\FacebookAds Facebook Ads sync and tracking
allegro \controls\Allegro Allegro.pl marketplace integration (legacy)
cron \controls\Cron Cron execution dispatcher and status UI
site layout only layout-logged.php, layout-unlogged.php
html components Reusable form elements (input, textarea, select, etc.)

Database schema (selected)

Migrations in migrations/ (30+ files, e.g. 001_google_ads_settings.sql). Tracked in schema_migrations. Run via php install.php (--force, --with_demo).

Key tables:

  • settings — global key-value config store
  • clients — merchant accounts (Google Ads Customer ID, Merchant ID)
  • campaigns, campaigns_history — campaign metadata + daily snapshots
  • cron_sync_status — pipeline phase tracking (pending → fetch → aggregate_30 → done)
  • campaign_alerts, campaign_search_terms_history, campaign_ad_groups, campaign_keywords, campaign_negative_keywords
  • products, products_aggregate, products_keyword_planner_terms, products_merchant_sync_log
  • logs — structured event log (level/source/message/context JSON/client_id)
  • facebook_campaigns, facebook_campaigns_history, facebook_ad_sets, facebook_ads, facebook_ads_history

Request flow

Page (HTML): request → .htaccessindex.php → routing → auth → \view\Site::show()\controls\Site::route() → controller action → factory → \Tpl::view(...) → wrapped in site/layout-logged.php → response.

AJAX (JSON): POST/GET → ajax.php → session+IP check → controller action → echo json_encode(...); exit.

Cron (JSON): external GET → index.php (whitelisted) → \controls\Cron::cron_universal() → service API call → write to *_history + cron_sync_statusself::output_cron_response([...]).

Auth

Session-based, with persistent cookie. Cookie stores JSON {email, hash} (salted). On revisit, index.php lines 92-102 verify and rehydrate session. AJAX adds IP binding ($_SESSION['ip'] vs $_SERVER['REMOTE_ADDR']); mismatch → session_destroy().