HEX
Server: Apache
System: Linux vpshost11508.publiccloud.com.br 5.15.179-grsec-vpshost-10.lc.el8.x86_64 #1 SMP Mon Apr 7 12:04:45 -03 2025 x86_64
User: wicomm2 (10002)
PHP: 8.3.0
Disabled: apache_child_terminate,dl,escapeshellarg,escapeshellcmd,exec,link,mail,openlog,passthru,pcntl_alarm,pcntl_exec,pcntl_fork,pcntl_get_last_error,pcntl_getpriority,pcntl_setpriority,pcntl_signal,pcntl_signal_dispatch,pcntl_sigprocmask,pcntl_sigtimedwait,pcntl_sigwaitinfo,pcntl_strerror,pcntl_wait,pcntl_waitpid,pcntl_wexitstatus,pcntl_wifexited,pcntl_wifsignaled,pcntl_wifstopped,pcntl_wstopsig,pcntl_wtermsig,php_check_syntax,php_strip_whitespace,popen,proc_close,proc_open,shell_exec,symlink,system
Upload Files
File: /home/storage/5/78/dd/wicomm2/public_html/clientes/performance-healthcheck/result.php
<?php
declare(strict_types=1);

// Debug defensivo: mostra o erro real quando o Apache devolve 500 genérico.
error_reporting(E_ALL);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');

register_shutdown_function(function () {
  $e = error_get_last();
  if (!$e) return;
  if (!in_array($e['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) return;

  // Alguns setups do Apache substituem o corpo quando o status é 500.
  // Para não perder a mensagem, respondemos 200 e imprimimos o erro em texto puro.
  http_response_code(200);
  header('Content-Type: text/plain; charset=utf-8');
  echo "PHP fatal error (status forçado 200 para não ser substituído pelo Apache)\n";
  echo "Type: {$e['type']}\n";
  echo "Message: {$e['message']}\n";
  echo "File: {$e['file']}\n";
  echo "Line: {$e['line']}\n";
});

set_exception_handler(function (Throwable $e) {
  http_response_code(200);
  header('Content-Type: text/plain; charset=utf-8');
  echo "Uncaught exception (status 200)\n";
  echo "Class: " . get_class($e) . "\n";
  echo "Message: " . $e->getMessage() . "\n";
  echo "File: " . $e->getFile() . "\n";
  echo "Line: " . $e->getLine() . "\n";
  echo "Trace:\n" . $e->getTraceAsString() . "\n";
  exit;
});

set_error_handler(function (int $severity, string $message, string $file, int $line) {
  // Converte warnings/notices em exceção para ficar visível.
  throw new ErrorException($message, 0, $severity, $file, $line);
});

// Log local para casos em que o browser ainda não mostra.
ini_set('log_errors', '1');
ini_set('error_log', __DIR__ . '/php-error.log');

require __DIR__ . '/config.php';

$config = app_config();

function h(string $v): string {
  return htmlspecialchars($v, ENT_QUOTES, 'UTF-8');
}

$id = (string)($_GET['id'] ?? '');
$reportId = (string)($_GET['report_id'] ?? '');

if ($id === '') {
  http_response_code(400);
  ?><!doctype html><html lang="pt-br"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Erro</title><link rel="stylesheet" href="styles.css"></head><body><main class="wrap"><section class="card"><h2>id ausente</h2><p class="muted">Abra esta página como <b>result.php?id=...</b></p><a class="btn" href="./">Voltar</a></section></main></body></html><?php
  exit;
}

$error = null;
$client = [];
$history = [];

function md_get_client_strict(array $config, string $id): array {
  // 1) Try the standard getter
  $client = md_get_client($config, $id);

  $name = (string)($client['client_name'] ?? '');
  $url = (string)($client['client_url'] ?? '');

  if ($name !== '' || $url !== '') return $client;

  // 2) Fallback: force _fields on the documents endpoint (some accounts return a minimal doc)
  $entity = md_entity($config);
  $fields = 'id,client_name,client_url,client_plataform,client_plataforma,performance_history';
  $docUrl = vtex_base($config) . "/api/dataentities/{$entity}/documents/{$id}?_fields={$fields}";
  $r = http_request('GET', $docUrl, vtex_headers($config), null, 60);
  if ($r['ok'] && is_array($r['data'])) {
    $client2 = $r['data'];
    $name2 = (string)($client2['client_name'] ?? '');
    $url2 = (string)($client2['client_url'] ?? '');
    if ($name2 !== '' || $url2 !== '') return $client2;
  }

  // 3) Fallback: locate the record via search and then return it
  $rows = md_search_clients($config, 200);
  foreach ($rows as $row) {
    $rid = (string)($row['id'] ?? ($row['Id'] ?? ($row['documentId'] ?? '')));
    if ($rid !== '' && $rid === $id) return $row;
  }

  return $client;
}

try {
  $client = md_get_client_strict($config, $id);
  $history = md_history_as_array($client);
} catch (Throwable $e) {
  $error = $e->getMessage();
}

// Rodar uma nova análise e salvar no histórico
if (!$error && $_SERVER['REQUEST_METHOD'] === 'POST' && (string)($_POST['action'] ?? '') === 'run') {
  $strategy = (string)($_POST['strategy'] ?? 'mobile');
  $strategy = in_array($strategy, ['mobile', 'desktop'], true) ? $strategy : 'mobile';

  try {
    $targetUrl = (string)($client['client_url'] ?? ($client['clientUrl'] ?? ($client['url'] ?? '')));
    if ($targetUrl === '') throw new RuntimeException('client_url ausente');

    $psi = run_lighthouse($config, $targetUrl, $strategy);
    $summary = extract_lighthouse_summary($psi);
    $report = gemini_report($config, $client, $summary, $strategy);

    $newReportId = bin2hex(random_bytes(8));

    $item = [
      'report_id' => $newReportId,
      'created_at' => now_iso((string)($config['app']['timezone'] ?? 'America/Sao_Paulo')),
      'strategy' => $strategy,
      'scores' => $summary['scores'] ?? [],
      'metrics' => $summary['metrics'] ?? [],
      'lighthouse_raw' => $summary['lighthouse_raw'] ?? new stdClass(),
      'gemini_report' => $report,
    ];

    $history[] = $item;

    md_patch_client($config, $id, ['performance_history' => $history]);

    header('Location: result.php?id=' . rawurlencode($id) . '&report_id=' . rawurlencode($newReportId));
    exit;
  } catch (Throwable $e) {
    $error = $e->getMessage();
  }
}

// Selecionar item do histórico
$selected = null;
if (!$error && $history) {
  if ($reportId !== '') {
    foreach ($history as $hitem) {
      if (($hitem['report_id'] ?? '') === $reportId) {
        $selected = $hitem;
        break;
      }
    }
  }
  if ($selected === null) {
    $selected = $history[count($history) - 1];
  }
}

$clientName = (string)($client['client_name'] ?? '');
$clientUrl = (string)($client['client_url'] ?? ($client['clientUrl'] ?? ($client['url'] ?? '')));
$platformRaw = $client['client_plataform'] ?? ($client['client_plataforma'] ?? '');
$platform = is_array($platformRaw) ? json_encode($platformRaw, JSON_UNESCAPED_UNICODE) : (string)$platformRaw;

$scores = $selected['scores'] ?? [];
$scorePerf = isset($scores['performance']) ? (int)$scores['performance'] : null;
$scoreAcc = isset($scores['accessibility']) ? (int)$scores['accessibility'] : null;
$scoreBp  = isset($scores['best-practices']) ? (int)$scores['best-practices'] : null;
$scoreSeo = isset($scores['seo']) ? (int)$scores['seo'] : null;
$scorePwa = isset($scores['pwa']) ? (int)$scores['pwa'] : null;

$report = $selected['gemini_report'] ?? [];
$summaryText = (string)($report['summary'] ?? '');
$priority = is_array($report['priority_actions'] ?? null) ? $report['priority_actions'] : [];
$risks = is_array($report['risks'] ?? null) ? $report['risks'] : [];
$notes = is_array($report['notes'] ?? null) ? $report['notes'] : [];

$createdAt = (string)($selected['created_at'] ?? '');
$strategySel = (string)($selected['strategy'] ?? '');

?>
<!doctype html>
<html lang="pt-br">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title><?php echo h($clientName !== '' ? $clientName : 'Histórico'); ?></title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="wrap">

    <header class="top">
      <div>
        <h1><?php echo h($clientName !== '' ? $clientName : 'Cliente'); ?></h1>
        <p class="muted">
          <?php if ($clientUrl !== ''): ?><?php echo h($clientUrl); ?><?php endif; ?>
          <?php if ($platform !== ''): ?> <span class="dot">•</span> <?php echo h($platform); ?><?php endif; ?>
          <?php if ($createdAt !== ''): ?> <span class="dot">•</span> <?php echo h($createdAt); ?><?php endif; ?>
          <?php if ($strategySel !== ''): ?> <span class="dot">•</span> <?php echo h($strategySel); ?><?php endif; ?>
        </p>
      </div>
      <div class="row">
        <a class="btn" href="./">Voltar</a>
      </div>
    </header>

    <?php if ($error): ?>
      <section class="card">
        <h2>Erro</h2>
        <p class="muted"><?php echo h($error); ?></p>
        <p class="muted">Se a listagem do index funciona e aqui falha, o ID pode não existir ou o documento pode estar restrito.</p>
      </section>
    <?php else: ?>

      <section class="card">
        <h2>Nova análise</h2>
        <form method="post" class="row" style="align-items:flex-end; flex-wrap:wrap; gap:12px;">
          <input type="hidden" name="action" value="run">
          <div style="min-width:220px;">
            <label class="muted" for="strategy">Strategy</label>
            <select id="strategy" name="strategy" class="input" style="margin-top:6px;">
              <option value="mobile">mobile</option>
              <option value="desktop">desktop</option>
            </select>
          </div>
          <div>
            <button class="btn" type="submit">Rodar e salvar</button>
          </div>
          <div class="muted" style="padding-bottom:2px;">
            A execução chama Lighthouse, depois gera leitura com Gemini, e por fim adiciona um novo objeto no performance_history.
          </div>
        </form>
      </section>

      <section class="card" style="margin-top:12px;">
        <h2>Histórico</h2>
        <?php if (!$history): ?>
          <p class="muted">Sem análises salvas ainda.</p>
        <?php else: ?>
          <div style="overflow:auto;">
            <table class="table">
              <thead>
                <tr>
                  <th>Data</th>
                  <th>Strategy</th>
                  <th>Perf</th>
                  <th>A11y</th>
                  <th>BP</th>
                  <th>SEO</th>
                  <th>PWA</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                <?php foreach (array_reverse($history) as $it): ?>
                  <?php
                    $itId = (string)($it['report_id'] ?? '');
                    $itAt = (string)($it['created_at'] ?? '');
                    $itSt = (string)($it['strategy'] ?? '');
                    $itScores = is_array($it['scores'] ?? null) ? $it['scores'] : [];
                    $itPerf = isset($itScores['performance']) ? (int)$itScores['performance'] : null;
                    $itAcc = isset($itScores['accessibility']) ? (int)$itScores['accessibility'] : null;
                    $itBp = isset($itScores['best-practices']) ? (int)$itScores['best-practices'] : null;
                    $itSeo = isset($itScores['seo']) ? (int)$itScores['seo'] : null;
                    $itPwa = isset($itScores['pwa']) ? (int)$itScores['pwa'] : null;
                    $isActive = ($reportId !== '' && $itId === $reportId) || ($reportId === '' && $selected && ($selected['report_id'] ?? '') === $itId);
                  ?>
                  <tr>
                    <td><?php echo h($itAt); ?></td>
                    <td><?php echo h($itSt); ?></td>
                    <td><?php echo $itPerf === null ? '—' : (int)$itPerf; ?></td>
                    <td><?php echo $itAcc === null ? '—' : (int)$itAcc; ?></td>
                    <td><?php echo $itBp === null ? '—' : (int)$itBp; ?></td>
                    <td><?php echo $itSeo === null ? '—' : (int)$itSeo; ?></td>
                    <td><?php echo $itPwa === null ? '—' : (int)$itPwa; ?></td>
                    <td style="white-space:nowrap;">
                      <a class="btn" style="padding:8px 10px;" href="result.php?id=<?php echo rawurlencode($id); ?>&report_id=<?php echo rawurlencode($itId); ?>"><?php echo $isActive ? 'Aberto' : 'Abrir'; ?></a>
                    </td>
                  </tr>
                <?php endforeach; ?>
              </tbody>
            </table>
          </div>
        <?php endif; ?>
      </section>

      <?php if ($selected): ?>
        <section class="cards" style="margin-top:12px;">
          <div class="card">
            <h2>Scores</h2>
            <div class="grid">
              <div class="pill"><span>Performance</span><b><?php echo $scorePerf === null ? '—' : (int)$scorePerf; ?></b></div>
              <div class="pill"><span>Acessibilidade</span><b><?php echo $scoreAcc === null ? '—' : (int)$scoreAcc; ?></b></div>
              <div class="pill"><span>Boas práticas</span><b><?php echo $scoreBp === null ? '—' : (int)$scoreBp; ?></b></div>
              <div class="pill"><span>SEO</span><b><?php echo $scoreSeo === null ? '—' : (int)$scoreSeo; ?></b></div>
              <div class="pill"><span>PWA</span><b><?php echo $scorePwa === null ? '—' : (int)$scorePwa; ?></b></div>
            </div>
          </div>

          <div class="card">
            <h2>Leitura executiva</h2>
            <?php if ($summaryText === ''): ?>
              <p class="muted">Sem resumo gerado.</p>
            <?php else: ?>
              <p class="text"><?php echo h($summaryText); ?></p>
            <?php endif; ?>
          </div>
        </section>

        <section class="card" style="margin-top:12px;">
          <h2>Ações prioritárias</h2>
          <?php if (!$priority): ?>
            <p class="muted">Sem itens retornados.</p>
          <?php else: ?>
            <ul class="list">
              <?php foreach ($priority as $item): ?>
                <?php
                  $t = (string)($item['title'] ?? '');
                  $w = (string)($item['why'] ?? '');
                  $how = (string)($item['how'] ?? '');
                  $imp = (string)($item['expected_impact'] ?? '');
                ?>
                <li>
                  <b><?php echo h($t); ?></b>
                  <?php if ($w !== ''): ?><div class="muted"><?php echo h($w); ?></div><?php endif; ?>
                  <?php if ($how !== ''): ?><div class="text"><?php echo h($how); ?></div><?php endif; ?>
                  <?php if ($imp !== ''): ?><div class="tag">Impacto: <?php echo h($imp); ?></div><?php endif; ?>
                </li>
              <?php endforeach; ?>
            </ul>
          <?php endif; ?>
        </section>

        <section class="card" style="margin-top:12px;">
          <h2>Riscos e observações</h2>
          <div class="cols">
            <div>
              <h3>Riscos</h3>
              <?php if (!$risks): ?>
                <p class="muted">Sem itens retornados.</p>
              <?php else: ?>
                <ul class="list">
                  <?php foreach ($risks as $r): ?>
                    <?php $rt = (string)($r['title'] ?? ''); $rc = (string)($r['context'] ?? ''); ?>
                    <li>
                      <b><?php echo h($rt); ?></b>
                      <?php if ($rc !== ''): ?><div class="muted"><?php echo h($rc); ?></div><?php endif; ?>
                    </li>
                  <?php endforeach; ?>
                </ul>
              <?php endif; ?>
            </div>
            <div>
              <h3>Notas</h3>
              <?php if (!$notes): ?>
                <p class="muted">Sem itens retornados.</p>
              <?php else: ?>
                <ul class="list">
                  <?php foreach ($notes as $n): ?>
                    <li><?php echo h((string)$n); ?></li>
                  <?php endforeach; ?>
                </ul>
              <?php endif; ?>
            </div>
          </div>
        </section>

        <section class="card" style="margin-top:12px;">
          <h2>JSON bruto</h2>
          <details>
            <summary>Ver Lighthouse completo salvo</summary>
            <pre class="code"><?php echo h(json_encode($selected['lighthouse_raw'] ?? new stdClass(), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); ?></pre>
          </details>
        </section>
      <?php endif; ?>

    <?php endif; ?>

  </main>
</body>
</html>