Al-HUWAITI Shell
Al-huwaiti


Server : Apache
System : Linux webd003.cluster111.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64
User : edevmultrx ( 811899)
PHP Version : 7.4.33
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
Directory :  /home/edevmultrx/www/terra-d-oro/api/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/edevmultrx/www/terra-d-oro/api/sync.php
<?php
/**
 * Terra D'Oro — iCal Sync API Endpoint
 * Route: /api/sync (POST or GET with ?key=TOKEN)
 *
 * Triggers SyncManager to pull all external iCal feeds (Airbnb / Booking.com)
 * and reconcile them with the local SQLite database.
 *
 * AUTHENTICATION:
 *   ?key=YOUR_SYNC_KEY   (defined as SYNC_KEY in core/config.php)
 *   OR an Authorization: Bearer YOUR_SYNC_KEY header.
 *
 * This endpoint is designed to be called by:
 *   1. A server cron job every 15 minutes:
 *      curl -s "https://terradoro.com/api/sync?key=TOKEN"
 *   2. Nina's admin panel (manual sync button in admin/ical-sync.php).
 *   3. The init script (php core/init.php) for initial setup verification.
 *
 * Responds with JSON regardless of success or failure.
 */

declare(strict_types=1);

// ── Bootstrap ─────────────────────────────────────────────────────────────────

if (!defined('ROOT_PATH')) {
    define('ROOT_PATH', dirname(__DIR__));
}
require_once ROOT_PATH . '/core/config.php';
require_once ROOT_PATH . '/core/db.php';
require_once ROOT_PATH . '/core/helpers.php';
require_once ROOT_PATH . '/core/ical/ICalParser.php';
require_once ROOT_PATH . '/core/ical/SyncManager.php';

// ── JSON response helper ───────────────────────────────────────────────────────

function json_respond(int $status, array $data): never
{
    http_response_code($status);
    header('Content-Type: application/json; charset=utf-8');
    header('Cache-Control: no-store, no-cache');
    header('X-Content-Type-Options: nosniff');
    echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
    exit;
}

// ── Authentication ────────────────────────────────────────────────────────────

// Accept key via query string or Authorization header
$provided_key = $_GET['key']
    ?? (str_replace('Bearer ', '', $_SERVER['HTTP_AUTHORIZATION'] ?? ''))
    ?: null;

if (!$provided_key || !hash_equals(SYNC_KEY, $provided_key)) {
    json_respond(401, [
        'error'   => 'Unauthorized',
        'message' => 'Valid ?key= parameter or Authorization: Bearer header required.',
    ]);
}

// ── Method guard ──────────────────────────────────────────────────────────────

$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
if (!in_array($method, ['GET', 'POST'], true)) {
    json_respond(405, ['error' => 'Method Not Allowed']);
}

// ── Optional scope parameters ─────────────────────────────────────────────────

// ?unit_id=1  → sync only that unit's sources
// ?force=1    → bypass the ICAL_SYNC_INTERVAL throttle (not yet implemented in SM,
//               but passed through for future use)
$unit_id = isset($_GET['unit_id']) ? (int) $_GET['unit_id'] : null;

// ── Run sync ──────────────────────────────────────────────────────────────────

$started = microtime(true);

try {
    $manager = new SyncManager($db);

    $stats = $unit_id
        ? $manager->syncUnit($unit_id)
        : $manager->syncAll();

    $elapsed = round(microtime(true) - $started, 3);

    json_respond(200, [
        'ok'       => true,
        'elapsed'  => $elapsed . 's',
        'scope'    => $unit_id ? "unit_id={$unit_id}" : 'all',
        'stats'    => $stats,
        'synced_at' => date('c'),
    ]);

} catch (\Throwable $e) {
    $elapsed = round(microtime(true) - $started, 3);

    $detail = DEBUG ? $e->getMessage() : 'Internal server error during sync.';

    json_respond(500, [
        'ok'      => false,
        'elapsed' => $elapsed . 's',
        'error'   => $detail,
    ]);
}

Al-HUWAITI Shell