$data_local) { $precisa_atualizar = true; } } // Ação if ($precisa_atualizar) { $conteudo_md = @file_get_contents($url_markdown_raw); if ($conteudo_md === false) { echo json_encode(['ok' => false, 'msg' => 'Erro ao baixar MD.', 'url' => $url_markdown_raw]); exit; } $config = [ 'usuario' => $usuario, 'repositorio' => $repositorio, 'branch' => $branch, 'site_gitea' => $site_gitea ]; // Processa o Scrapping $dados_processados = _realizarScraping($conteudo_md, $variacao, $path_item, $config); // Gera o JSON final $json_final = json_encode($dados_processados, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); file_put_contents($caminho_json_local, $json_final); echo $json_final; exit; } else { readfile($caminho_json_local); exit; } } // --- Funções de Parsing --- function _realizarScraping($markdown, $variacao, $path_original, $config) { // Configura data para Horário de Brasília (GMT-3) try { $dataBrasilia = new DateTime('now', new DateTimeZone('America/Sao_Paulo')); $dataGeracao = $dataBrasilia->format('Y-m-d H:i:s'); } catch (Exception $e) { // Fallback caso o servidor não tenha timezone configurado $dataGeracao = date('Y-m-d H:i:s') . ' (Server Time)'; } $json = [ 'meta' => [ 'path_original' => $path_original, 'variacao' => $variacao, 'gerado_em' => $dataGeracao ] ]; // Mapeamento de campos especiais que vão para a RAIZ $mapeamentoEspeciais = [ 'identificador_do_registro' => 'ark', 'visualizacao_publica_ark' => 'link_visualizacao_publica', 'visualizacao_no_meta_museu_da_matematica_editora_moan' => 'link_meta_museu', 'denominacao' => 'titulo', 'outras_denominacoes' => 'outras_denominacoes', 'tipo_de_bem_objeto_original' => 'tipo_bem', 'categoria_museologica' => 'categoria_museologica', 'subcategoria' => 'subcategoria' ]; $linhas = explode("\n", $markdown); $secaoAtual = 'inicio'; $chaveAtual = null; $dadosSecoes = []; $dadosSecoes[$secaoAtual] = []; foreach ($linhas as $linha) { $linha = trim($linha); if ($linha === '') continue; // 1. TÍTULOS (##) if (preg_match('/^#{2,4}\s+(.*)$/', $linha, $matches)) { $nomeSecaoRaw = $matches[1]; $secaoAtual = _limparChave($nomeSecaoRaw); $chaveAtual = null; if (!isset($dadosSecoes[$secaoAtual])) { $dadosSecoes[$secaoAtual] = []; } continue; } // 2. CHAVE-VALOR (**Chave:** Valor) if (preg_match('/.*\*\*(.+?):\*\*\s*(.*)$/', $linha, $matches)) { $chaveRaw = $matches[1]; $valorInicial = $matches[2]; $chaveLimpa = _limparChave($chaveRaw); $valorLimpo = _limparTextoGeral($valorInicial); if (array_key_exists($chaveLimpa, $mapeamentoEspeciais)) { $chaveRaiz = $mapeamentoEspeciais[$chaveLimpa]; $json[$chaveRaiz] = $valorLimpo; $chaveAtual = null; } else { $chaveAtual = $chaveLimpa; $dadosSecoes[$secaoAtual][$chaveAtual] = $valorLimpo; } continue; } // 3. ITENS DE LISTA (- Item) if (preg_match('/^-\s+(.*)$/', $linha, $matches) && !preg_match('/^-{3,}$/', $linha)) { $itemLista = _limparTextoGeral($matches[1]); if ($chaveAtual) { if (!is_array($dadosSecoes[$secaoAtual][$chaveAtual])) { $valAtual = $dadosSecoes[$secaoAtual][$chaveAtual]; if ($valAtual === '') { $dadosSecoes[$secaoAtual][$chaveAtual] = []; } else { $dadosSecoes[$secaoAtual][$chaveAtual] = [$valAtual]; } } $dadosSecoes[$secaoAtual][$chaveAtual][] = $itemLista; } else { if (!isset($dadosSecoes[$secaoAtual]['lista_geral'])) { $dadosSecoes[$secaoAtual]['lista_geral'] = []; } $dadosSecoes[$secaoAtual]['lista_geral'][] = $itemLista; } continue; } // 4. TEXTO GERAL if (substr($linha, 0, 3) !== '```') { $textoLimpo = _limparTextoGeral($linha); if ($textoLimpo === '') continue; if ($chaveAtual) { $valAtual = $dadosSecoes[$secaoAtual][$chaveAtual]; if (is_array($valAtual)) { $chaveAtual = null; goto texto_geral_rotulo; } if ($valAtual !== '') { $dadosSecoes[$secaoAtual][$chaveAtual] .= " " . $textoLimpo; } else { $dadosSecoes[$secaoAtual][$chaveAtual] = $textoLimpo; } } else { texto_geral_rotulo: if (!isset($dadosSecoes[$secaoAtual]['texto_geral'])) { $dadosSecoes[$secaoAtual]['texto_geral'] = ''; } $sep = ($dadosSecoes[$secaoAtual]['texto_geral'] !== '') ? " " : ""; $dadosSecoes[$secaoAtual]['texto_geral'] .= $sep . $textoLimpo; } } } // --- MONTAGEM DO JSON FINAL --- foreach ($dadosSecoes as $nomeSecao => $conteudo) { if ($nomeSecao === 'inicio' && empty($conteudo)) continue; if (empty($conteudo)) continue; if (count($conteudo) === 1 && isset($conteudo['lista_geral'])) { $json[$nomeSecao] = $conteudo['lista_geral']; } elseif (count($conteudo) === 1 && isset($conteudo['texto_geral'])) { $json[$nomeSecao] = $conteudo['texto_geral']; } else { $objetoLimpo = []; foreach ($conteudo as $k => $v) { if ($k === 'lista_geral') { $objetoLimpo['itens'] = $v; } elseif ($k === 'texto_geral') { $objetoLimpo['descricao_geral'] = $v; } else { $objetoLimpo[$k] = $v; } } $json[$nomeSecao] = $objetoLimpo; } } return $json; } /** * LIMPEZA AGRESSIVA PARA CHAVES */ function _limparChave($texto) { // 1. Remove qualquer caractere que NÃO seja Letra, Número ou Espaço $texto = preg_replace('/[^\p{L}\p{N}\s]/u', '', $texto); // 2. Transliteração $texto = iconv('UTF-8', 'ASCII//TRANSLIT', $texto); // 3. Formatação $texto = trim($texto); $texto = strtolower($texto); $texto = preg_replace('/\s+/', '_', $texto); return $texto; } /** * Limpeza para Valores (Mantém pontuação básica, remove emojis) */ function _limparTextoGeral($texto) { // Remove apenas símbolos gráficos e emojis $texto = preg_replace('/[\p{So}\p{Sk}\p{Sm}\p{Sc}\p{Co}\p{Cn}]/u', '', $texto); return trim($texto); } function _obterDataModificacaoRemota($url) { $options = [ 'http' => [ 'method' => 'HEAD', 'header' => "User-Agent: PHP-Script\r\n" ] ]; $context = stream_context_create($options); $headers = @get_headers($url, 1, $context); if ($headers && isset($headers['Last-Modified'])) { return strtotime($headers['Last-Modified']); } return false; } ?>