File manager - Edit - /var/www/html/transparencia/app/Services/AngraMapaDoSiteCollector.php
Back
<?php namespace App\Services; use Carbon\Carbon; use Illuminate\Http\Client\ConnectionException; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Str; class AngraMapaDoSiteCollector { private string $base; public function __construct() { $this->base = rtrim(config('mapa-do-site.angra_base', 'https://angra.rj.gov.br'), '/'); } /** * @return array{ * base: string, * has_database: bool, * totals: array<string, int>, * blocks: array<int, array{id: string, title: string, description?: string, items: array<int, array{title: string, href: string, external: bool}>}> * } */ public function collect(): array { $blocks = []; $totals = []; $structures = $this->collectStructures(); $blocks[] = $this->finalizeBlock( 'estruturas', 'Estrutura organizacional (secretarias, autarquias, diretorias)', $structures, 'Todas as unidades ativas publicadas no portal institucional.' ); $totals['estruturas'] = $blocks[count($blocks) - 1]['total']; $secretarios = $this->collectSecretarioPages(); $blocks[] = $this->finalizeBlock( 'secretarios', 'Páginas de gestores (prefeito, vice, secretários)', $secretarios ); $totals['secretarios'] = $blocks[count($blocks) - 1]['total']; if ($this->hasAngraDatabase()) { $htmlPages = $this->collectHtmlPages(); $blocks[] = $this->finalizeBlock( 'paginas-html', 'Páginas de conteúdo (/servicos)', $htmlPages['items'], 'Páginas HTML publicadas no portal (exibidas as mais recentes no mapa).', $htmlPages['total'] ); $totals['paginas_html'] = $htmlPages['total']; $noticias = $this->collectNoticias(); $blocks[] = $this->finalizeBlock( 'noticias', 'Notícias', $noticias['items'], 'Notícias publicadas e ativas (exibidas as mais recentes no mapa).', $noticias['total'] ); $totals['noticias'] = $noticias['total']; $conselhos = $this->collectConselhos(); $blocks[] = $this->finalizeBlock('conselhos', 'Conselhos municipais', $conselhos['items'], null, $conselhos['total']); $totals['conselhos'] = $conselhos['total']; $parques = $this->collectParques(); $blocks[] = $this->finalizeBlock('parques', 'Parques e jardins', $parques['items'], null, $parques['total']); $totals['parques'] = $parques['total']; $carta = $this->collectCartaServicos(); $blocks[] = $this->finalizeBlock('carta-servicos', 'Carta de serviços', $carta['items'], null, $carta['total']); $totals['carta_servicos'] = $carta['total']; $legislacao = $this->collectLegislacao(); $blocks[] = $this->finalizeBlock('legislacao', 'Legislação municipal', $legislacao['items'], null, $legislacao['total']); $totals['legislacao'] = $legislacao['total']; $licitacoes = $this->collectLicitacoes(); $blocks[] = $this->finalizeBlock('licitacoes', 'Licitações e procedimentos', $licitacoes['items'], null, $licitacoes['total']); $totals['licitacoes'] = $licitacoes['total']; $contratos = $this->collectContratos(); $blocks[] = $this->finalizeBlock('contratos', 'Contratos', $contratos['items'], null, $contratos['total']); $totals['contratos'] = $contratos['total']; } return [ 'base' => $this->base, 'has_database' => $this->hasAngraDatabase(), 'totals' => $totals, 'blocks' => array_values(array_filter($blocks, fn (array $b) => ! empty($b['items']))), ]; } private function accordionLimit(): int { return max(1, (int) config('mapa-do-site.accordion_limit', 100)); } /** * @param array<int, array{title: string, href: string, external: bool}> $items * @return array{id: string, title: string, description?: string, items: array, total: int, truncated?: bool, more_url?: string, more_label?: string} */ private function finalizeBlock(string $id, string $title, array $items, ?string $description = null, ?int $total = null): array { $limit = $this->accordionLimit(); $total = $total ?? count($items); $block = [ 'id' => $id, 'title' => $title, 'items' => $items, 'total' => $total, ]; if ($description !== null) { $block['description'] = $description; } if ($total > $limit) { $block['items'] = array_slice($items, 0, $limit); $block['truncated'] = true; $more = config("mapa-do-site.more_links.{$id}"); if (is_array($more) && ! empty($more['url'])) { $block['more_url'] = str_replace('{base}', $this->base, $more['url']); $block['more_label'] = $more['label'] ?? __('Ver mais'); } } return $block; } public function hasAngraDatabase(): bool { try { DB::connection('angra_site')->getPdo(); return Schema::connection('angra_site')->hasTable('structures'); } catch (\Throwable) { return false; } } /** * @return array<int, array{title: string, href: string, external: bool}> */ private function collectStructures(): array { try { $response = Http::timeout(15)->get($this->base.'/secretarias_dados'); if (! $response->successful()) { return $this->collectStructuresFromMenu(); } $items = $response->json(); if (! is_array($items)) { return []; } $byId = collect($items)->keyBy('id'); $links = []; foreach ($items as $structure) { if (! is_array($structure) || ($structure['status'] ?? '') !== 'ATIVADO') { continue; } $href = $this->buildStructureUrl($structure, $byId); if (! $href) { continue; } $type = $this->structureTypeLabel($structure['type'] ?? ''); $name = $structure['name'] ?? $structure['slug'] ?? 'Unidade'; $links[] = [ 'title' => $type ? "{$name} ({$type})" : $name, 'href' => $href, 'external' => true, ]; } usort($links, fn ($a, $b) => strcasecmp($a['title'], $b['title'])); return $links; } catch (ConnectionException) { return $this->collectStructuresFromMenu(); } } /** * @return array<int, array{title: string, href: string, external: bool}> */ private function collectStructuresFromMenu(): array { try { $response = Http::timeout(10)->get($this->base.'/menu'); $items = $response->successful() ? $response->json() : []; if (! is_array($items)) { return []; } $links = []; foreach ($items as $item) { if (! is_array($item) || empty($item['url'])) { continue; } $parentSlug = $item['url']; $links[] = $this->externalLink($item['nome'] ?? $parentSlug, "{$this->base}/secretarias/{$parentSlug}"); foreach (['executivas', 'diretorias', 'superintendencias'] as $childKey) { $segment = match ($childKey) { 'executivas' => 'executivas', 'diretorias' => 'diretorias', 'superintendencias' => 'superintendencias', default => $childKey, }; foreach ($item[$childKey] ?? [] as $child) { if (! is_array($child) || empty($child['url'])) { continue; } $links[] = $this->externalLink( $child['nome'] ?? $child['url'], "{$this->base}/secretarias/{$parentSlug}/{$segment}/{$child['url']}" ); } } } return $links; } catch (ConnectionException) { return []; } } /** * @return array<int, array{title: string, href: string, external: bool}> */ private function collectSecretarioPages(): array { $static = [ $this->externalLink('O Prefeito', "{$this->base}/prefeito"), $this->externalLink('Vice-Prefeito', "{$this->base}/vice-prefeito"), ]; if (! $this->hasAngraDatabase()) { return $static; } $structures = DB::connection('angra_site') ->table('structures') ->where('status', 'ATIVADO') ->whereNotNull('slug') ->where('slug', '!=', '') ->orderBy('name') ->get(['name', 'slug', 'manager']); foreach ($structures as $structure) { $slug = $structure->slug; $label = $structure->manager ?: $structure->name; $static[] = $this->externalLink("Gestor: {$label}", "{$this->base}/secretario/{$slug}"); $static[] = $this->externalLink("Formação acadêmica – {$structure->name}", "{$this->base}/secretario/{$slug}/formacao-academica"); $static[] = $this->externalLink("Competências – {$structure->name}", "{$this->base}/secretario/competencias-e-atribuicoes/{$slug}"); } return $static; } /** * @return array{items: array<int, array{title: string, href: string, external: bool}>, total: int} */ private function collectHtmlPages(): array { $query = DB::connection('angra_site') ->table('htmls') ->where('status', 'ATIVADO') ->whereNotNull('slug') ->where('slug', '!=', ''); if (Schema::connection('angra_site')->hasColumn('htmls', 'display_context')) { $query->whereIn('display_context', ['INDEPENDENT', 'BOTH']); } $total = $query->count(); $limit = $this->accordionLimit(); if (Schema::connection('angra_site')->hasColumn('htmls', 'updated_at')) { $query->orderByDesc('updated_at'); } elseif (Schema::connection('angra_site')->hasColumn('htmls', 'created_at')) { $query->orderByDesc('created_at'); } else { $query->orderByDesc('id'); } $items = $query ->limit($limit) ->get(['title', 'slug', 'summary']) ->map(function ($row) { $title = trim((string) ($row->title ?: $row->summary ?: $row->slug)); return $this->externalLink($title, "{$this->base}/servicos/{$row->slug}"); }) ->all(); return ['items' => $items, 'total' => $total]; } /** * @return array{items: array<int, array{title: string, href: string, external: bool}>, total: int} */ private function collectNoticias(): array { if (! Schema::connection('angra_site')->hasTable('news')) { return ['items' => [], 'total' => 0]; } $query = DB::connection('angra_site') ->table('news') ->where('status', 'ATIVADO') ->whereNotNull('slug') ->where('slug', '!=', ''); $total = $query->count(); $limit = $this->accordionLimit(); $items = $query ->orderByDesc('created_at') ->limit($limit) ->get(['title', 'slug', 'created_at']) ->map(function ($row) { $date = Carbon::parse($row->created_at)->format('d-m-Y'); $title = Str::limit((string) $row->title, 120); return $this->externalLink($title, "{$this->base}/noticias/{$date}/{$row->slug}"); }) ->all(); return ['items' => $items, 'total' => $total]; } /** * @return array{items: array<int, array{title: string, href: string, external: bool}>, total: int} */ private function collectConselhos(): array { if (! Schema::connection('angra_site')->hasTable('conselhos')) { return ['items' => [], 'total' => 0]; } $query = DB::connection('angra_site') ->table('conselhos') ->where('status', 'ATIVADO') ->whereNotNull('slug') ->where('slug', '!=', ''); $total = $query->count(); $limit = $this->accordionLimit(); $items = $query ->orderByDesc('id') ->limit($limit) ->get(['nome', 'slug']) ->map(fn ($row) => $this->externalLink( (string) ($row->nome ?: $row->slug), "{$this->base}/conselhos/{$row->slug}" )) ->all(); return ['items' => $items, 'total' => $total]; } /** * @return array{items: array<int, array{title: string, href: string, external: bool}>, total: int} */ private function collectParques(): array { if (! Schema::connection('angra_site')->hasTable('parques')) { return ['items' => [], 'total' => 0]; } $query = DB::connection('angra_site') ->table('parques') ->where('status', 'ATIVADO') ->whereNotNull('slug') ->where('slug', '!=', ''); $total = $query->count(); $limit = $this->accordionLimit(); $items = $query ->orderByDesc('id') ->limit($limit) ->get(['nome', 'slug']) ->map(fn ($row) => $this->externalLink( (string) ($row->nome ?: $row->slug), "{$this->base}/servicos/parques-e-jardins/{$row->slug}" )) ->all(); return ['items' => $items, 'total' => $total]; } /** * @return array{items: array<int, array{title: string, href: string, external: bool}>, total: int} */ private function collectCartaServicos(): array { if (! Schema::connection('angra_site')->hasTable('carta_servicos')) { return ['items' => [], 'total' => 0]; } $titleColumn = Schema::connection('angra_site')->hasColumn('carta_servicos', 'cds_titulo') ? 'cds_titulo' : null; $query = DB::connection('angra_site')->table('carta_servicos'); if (Schema::connection('angra_site')->hasColumn('carta_servicos', 'cds_status')) { $query->where('cds_status', '3'); } $idColumn = Schema::connection('angra_site')->hasColumn('carta_servicos', 'id_cds') ? 'id_cds' : 'id'; $total = $query->count(); $limit = $this->accordionLimit(); $items = $query ->orderByDesc($idColumn) ->limit($limit) ->get(array_filter([$idColumn, $titleColumn])) ->map(function ($row) use ($idColumn, $titleColumn) { $id = $row->{$idColumn}; $title = $titleColumn ? (string) ($row->{$titleColumn} ?: "Serviço #{$id}") : "Serviço #{$id}"; return $this->externalLink(Str::limit($title, 120), "{$this->base}/servicos/servico/{$id}"); }) ->all(); return ['items' => $items, 'total' => $total]; } /** * @return array{items: array<int, array{title: string, href: string, external: bool}>, total: int} */ private function collectLegislacao(): array { if (! Schema::connection('angra_site')->hasTable('legislacao')) { return ['items' => [], 'total' => 0]; } $query = DB::connection('angra_site')->table('legislacao'); $total = $query->count(); $limit = $this->accordionLimit(); $items = $query ->orderByDesc('id_legislacao') ->limit($limit) ->get(['id_legislacao', 'nr_legislacao', 'ds_legislacao_sem_html']) ->map(function ($row) { $title = trim((string) ($row->nr_legislacao ?: $row->ds_legislacao_sem_html ?: "Legislação #{$row->id_legislacao}")); return $this->externalLink( Str::limit(strip_tags($title), 120), "{$this->base}/legislacao/{$row->id_legislacao}" ); }) ->all(); return ['items' => $items, 'total' => $total]; } /** * @return array{items: array<int, array{title: string, href: string, external: bool}>, total: int} */ private function collectLicitacoes(): array { if (! Schema::connection('angra_site')->hasTable('licitacoes_procedimentos')) { return ['items' => [], 'total' => 0]; } $query = DB::connection('angra_site')->table('licitacoes_procedimentos'); $total = $query->count(); $limit = $this->accordionLimit(); $items = $query ->orderByDesc('id') ->limit($limit) ->get(['id', 'nr_processo', 'ds_objeto']) ->map(function ($row) { $title = trim((string) ($row->nr_processo ?: Str::limit((string) $row->ds_objeto, 80) ?: "Processo #{$row->id}")); return $this->externalLink($title, "{$this->base}/licitacoes-e-procedimentos/{$row->id}"); }) ->all(); return ['items' => $items, 'total' => $total]; } /** * @return array{items: array<int, array{title: string, href: string, external: bool}>, total: int} */ private function collectContratos(): array { if (! Schema::connection('angra_site')->hasTable('contratos')) { return ['items' => [], 'total' => 0]; } $columns = ['id']; if (Schema::connection('angra_site')->hasColumn('contratos', 'con_titulo')) { $columns[] = 'con_titulo'; } if (Schema::connection('angra_site')->hasColumn('contratos', 'con_numero')) { $columns[] = 'con_numero'; } $query = DB::connection('angra_site')->table('contratos'); $total = $query->count(); $limit = $this->accordionLimit(); $orderColumn = Schema::connection('angra_site')->hasColumn('contratos', 'created_at') ? 'created_at' : 'id'; $items = $query ->orderByDesc($orderColumn) ->limit($limit) ->get($columns) ->map(function ($row) { $title = trim((string) ($row->con_numero ?? $row->con_titulo ?? 'Contrato')); return $this->externalLink( Str::limit($title, 120), "{$this->base}/contratos/{$row->id}" ); }) ->all(); return ['items' => $items, 'total' => $total]; } private function buildStructureUrl(array $structure, Collection $byId): ?string { $slug = $structure['slug'] ?? null; if (! $slug) { return null; } $parentId = $structure['structure_id'] ?? null; if (! $parentId) { return "{$this->base}/secretarias/{$slug}"; } $root = $this->findRootSecretaria($structure, $byId); if (! $root) { return "{$this->base}/secretarias/{$slug}"; } $segment = match ($structure['type'] ?? '') { 'SECRETARIA_EXECUTIVA' => 'executivas', 'DIRETORIA' => 'diretorias', 'SUPERINTENDENCIA' => 'superintendencias', default => null, }; if (! $segment) { return "{$this->base}/secretarias/{$slug}"; } return "{$this->base}/secretarias/{$root['slug']}/{$segment}/{$slug}"; } /** * @return array<string, mixed>|null */ private function findRootSecretaria(array $structure, Collection $byId): ?array { $current = $structure; $guard = 0; while ($guard < 20) { $guard++; if (empty($current['structure_id'])) { return in_array($current['type'] ?? '', ['SECRETARIA', 'AUTARQUIA', 'FUNDACAO', 'GABINETE_PREFEITURA', 'GABINETE_VICE_PREFEITURA'], true) ? $current : null; } $parent = $byId->get($current['structure_id']); if (! is_array($parent)) { return null; } $current = $parent; } return null; } private function structureTypeLabel(string $type): string { return match ($type) { 'SECRETARIA' => 'Secretaria', 'SECRETARIA_EXECUTIVA' => 'Secretaria Executiva', 'AUTARQUIA' => 'Autarquia', 'FUNDACAO' => 'Fundação', 'DIRETORIA' => 'Diretoria', 'SUPERINTENDENCIA' => 'Superintendência', 'GABINETE_PREFEITURA' => 'Gabinete do Prefeito', 'GABINETE_VICE_PREFEITURA' => 'Gabinete do Vice-Prefeito', default => $type, }; } /** * @return array{title: string, href: string, external: bool} */ private function externalLink(string $title, string $href): array { return [ 'title' => $title, 'href' => $href, 'external' => true, ]; } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings