261 lines
8.4 KiB
PHP
261 lines
8.4 KiB
PHP
<?php
|
|
|
|
function buscarOuCriarJson($path_item, $variacao, $usuario, $repositorio, $branch, $site_gitea) {
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
// URL RAW
|
|
$url_markdown_raw = "$site_gitea/$usuario/$repositorio/raw/branch/$branch/$path_item/README.md";
|
|
|
|
// Nome do arquivo local
|
|
$nome_base = str_replace('/', '_b_', $path_item);
|
|
if ($variacao) {
|
|
$nome_base .= "_p_" . $variacao;
|
|
}
|
|
|
|
$caminho_json_local = __DIR__ . '/' . $nome_base . ".json";
|
|
|
|
// Verificação de Datas
|
|
$precisa_atualizar = false;
|
|
|
|
if (!file_exists($caminho_json_local)) {
|
|
$precisa_atualizar = true;
|
|
} else {
|
|
$data_local = filemtime($caminho_json_local);
|
|
$data_remota = _obterDataModificacaoRemota($url_markdown_raw);
|
|
|
|
if ($data_remota === false || $data_remota > $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;
|
|
}
|
|
?>
|