> For the complete documentation index, see [llms.txt](https://mapasculturais.gitbook.io/documentacao-para-desenvolvedores/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mapasculturais.gitbook.io/documentacao-para-desenvolvedores/formacao-para-desenvolvedores/introducao.md).

# Introdução

{% embed url="<https://www.youtube.com/embed/l_178OxSuoM>" %}

Considera-se como requisitos, que o desenvolvedor possua conhecimento ao menos intermediário de PH&#x50;**,** de orientação a objetos e de Git e SQL (PostgresSQL). &#x20;

O desenvolvedor deve possuir o docker e o docker-compose funcionando em seu computador, de preferência em ambiente Linux ou MacOS.

## Tecnologias Envolvidas

No backend, o Mapas Culturais é desenvolvido em PHP utilizando o [Slim v2](https://www.slimframework.com/docs/v2/) como microframework e o [Doctrine](https://www.doctrine-project.org/index.html) como ORM, entre outras bibliotecas como o [Respect\Validation](https://respect-validation.readthedocs.io/).

No frontend, são utilizados o [AngularJS](https://angularjs.org/), [X-editable](https://vitalets.github.io/x-editable/) e [leaflet](https://leafletjs.com/), entre outras bibliotecas.

## Entidades Principais, Auxiliares e Diagrama de Relacionamento de Entidade

A plataforma inteira é desenvolvida em torno de seis entidades principais, a saber:

* [Agent](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/Agent.php): Agentes;
* [Space](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/Space.php): Espaços;
* [Event](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/Event.php): Eventos;
* [Project](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/Project.php): Projetos;
* [Opportunity](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/Opportunity.php): Oportunidades;
* [Registration](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/Registration.php): Inscrições.

Cada uma das entidades principais conta com uma entidade auxiliar para salvamento de metadados ([AgentMeta](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/AgentMeta.php), [SpaceMeta](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/SpaceMeta.php), [EventMeta](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/EventMeta.php), [ProjectMeta](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/ProjectMeta.php), [OpportunityMeta](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/OpportunityMeta.php) e [RegistrationMeta](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/RegistrationMeta.php)).

E, também, conta com as entidades secundárias, que auxiliam no desenvolvimento das funcionalidades, como as mais importantes, listadas abaixo:

* [File](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/File.php): Arquivos;
* [Term](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/Term.php) e [TermRelation](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/TermRelation.php): Termos de taxonomias;
* [AgentRelation](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/AgentRelation.php): Agentes relacionados;
* [PermissionCache](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/PermissionCache.php) e [PermissionCachePending](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/Entities/PermissionCachePending.php): Cache de permissão.

### **Diagrama de Relacionamento de Entidade**

![](/files/-MlBuQ6qwCb8JOjvefqc)

### **Subindo Ambiente de Desenvolvimento**

Após clonar o [repositório](https://github.com/mapasculturais/mapasculturais/) do Mapas Culturais, entre, pela linha de comando na pasta [dev-scripts](https://github.com/mapasculturais/mapasculturais/tree/master/dev-scripts), e execute o script [start-dev.sh](https://github.com/mapasculturais/mapasculturais/blob/master/dev-scripts/start-dev.sh).&#x20;

Este script utiliza o Docker Compose para iniciar o ambiente utilizando o [Dockerfile de desenvolvimento](https://github.com/mapasculturais/mapasculturais/blob/master/compose/local/Dockerfile), que é baseado no php7.2-cli e se utiliza do built-in web server do PHP. Assim, possibilitando a utilização do [PsySH](https://psysh.org/) no desenvolvimento.

```
dev-scripts]$ ./start-dev.sh
Creating dev-scripts_mapas_run ... done

aguardando o banco de dados subir corretamente...
conectado com sucesso ao banco pgsql:host=db;port=5432;dbname=mapas;user=mapas;

.
.
.
.

PHP 7.2.34 Development Server started at Wed Aug 25 00:30:56 2021
Listening on http://0.0.0.0:80
Document root is /var/www/html
```

Após a inicialização, a aplicação constará rodando e *ouvindo* a porta 80 de seu computador. Acesse <http://localhost/> em seu navegador.

## Script `shell.sh` e breakpoint com `eval(\psy\sh())`

E, também, na pasta `dev-scripts`, há o script `shell.sh` que inicializa um console para debug interativo da aplicação, contendo algumas funções auxiliares para facilitar o debug da aplicação, como a função `login`. Para executar este script é necessário que a aplicação já esteja rodando com o script `start-dev.sh`.

```
dev-scripts]$ ./shell.sh

================================
VARIÁVEIS DISPONÍVEIS: 
  $app, $em
  
para logar: login(id do usuário);

para criar uma ApiQuery: api($entity, $params); (exemplo: api('agent', ['@select' => 'id,name']))

para adicionar uma role a um usuário: role::add($user_id, 'roleName', $subsite_id = null); (exemplo role::add(1, 'saasSuperAdmin'))
para remover uma role a um usuário: role::remove($user_id, 'roleName', $subsite_id = null); (exemplo role::remove(1, 'saasSuperAdmin'))


Psy Shell v0.10.7 (PHP 7.2.34 — cli) by Justin Hileman
New version is available (current: v0.10.7, latest: v0.10.8)
From protected/tools/psysh.php:169:
    167: ";
    168: 
  > 169: eval(\psy\sh());
>>>
```

É possível definir breakpoints em qualquer ponto do código, pausando a execução e abrindo o console de debug na linha de comando. Basta adicionar o código `eval(\psy\sh());` no ponto desejado do código.

No exemplo abaixo, o código foi colocado na linha 32 do Site Controller:

```
=========================================================================
(GET) / - timestamp: 2021-08-25 04:00:46.738476
Psy Shell v0.10.7 (PHP 7.2.34 — cli-server) by Justin Hileman
From protected/application/lib/MapasCulturais/Controllers/Site.php:32:
    30:      */
    31:     function GET_index(){
  > 32:         eval(\psy\sh());
    33:         $this->render('index');
    34:     }
>>> 
```

Para sair do console e continuar a execução do script, utilize o comando `exit` ou pressione `Ctrl+d`.

Recomenda-se ler a [documentação do PsySH](https://psysh.org/#docs), especialmente a parte que descreve os [comandos](https://github.com/bobthecow/psysh/wiki/Commands). Abaixo, alguns comandos úteis:

* `ls` e `ls -l`: Lista as variáveis acessíveis no escopo;
* `trace`: Exibe o stack até o ponto do código;
* `doc {target}`: Exibe a documentação do {target}, onde {target} pode ser uma função, classe ou objeto;
* `help` ou `?`: Exibe a lista dos comandos disponíveis.

Pode-se inspecionar uma variável digitando o nome dela, por exemplo, o `$app->plugins`, um array com as instâncias dos plugins ativos no ambiente:

```
>>> $app->plugins
=> [
     "EvaluationMethodTechnical" => EvaluationMethodTechnical\Plugin {#248},
     "EvaluationMethodSimple" => EvaluationMethodSimple\Plugin {#250},
     "EvaluationMethodDocumentary" => EvaluationMethodDocumentary\Plugin {#252},
     "MultipleLocalAuth" => MultipleLocalAuth\Plugin {#257},
     "AldirBlanc" => AldirBlanc\Plugin {#265},
     "AldirBlancDataprev" => AldirBlancDataprev\Plugin {#267},
   ]
```

## Ciclo de Vida da Aplicação

Todas as requisições se iniciam no arquivo [src/index.php](https://github.com/mapasculturais/mapasculturais/blob/master/src/index.php), arquivo responsável por fazer o Bootstrap da aplicação.&#x20;

O Bootstrap define uma série de [constantes](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/bootstrap-common.php#L2), inicializa o [autoloader](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/bootstrap.php#L4) de classes, lê o arquivo de [configuração](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/bootstrap.php#L13), [instancia e inicializa](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/bootstrap.php#L23) o objeto da aplicação e [executa aplicação](https://github.com/mapasculturais/mapasculturais/blob/master/src/index.php#L4).

Durante a inicialização da aplicação são executadas as seguintes operações, nesta ordem:

1. Inicialização da sessão;
2. Inicialização dos caches da aplicação;
3. Registro do autoloader de classes de plugins e temas;
4. Inicialização do Doctrine;
5. Instanciação do tema;
6. Instanciação do Slim;
7. Inicialização dos plugins;
8. Inicialização dos módulos;
9. Inicialização do logger;
10. Inicialização do storage driver;
11. Inclusão dos middlewares;
12. Inicialização do gerenciador de rotas;
13. Registro de:
    * Metadados e tipos de entidade;
    * Controladores;
    * Roles;
    * Grupos de arquivos;
    * Tamanhos de imagens;
    * Grupos de metalist;
    * Taxonomias;
    * Execução dos registros dos módulos e plugins.
14. Inicialização do autenticador;
15. Inicialização do tema.

Após a inicialização, a requisição é encaminhada para o [gerenciador de rotas](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/RoutesManager.php) que decidirá para qual [controller e action a requisição seguirá](https://github.com/mapasculturais/mapasculturais/blob/master/src/protected/application/lib/MapasCulturais/RoutesManager.php#L106).

Uma vez no controlador, este poderá renderizar uma visão utilizando o método `$this->render('template-name');`; poderá retornar um JSON utilizando o método `$this->json(['data' => 'value']);`; um JSON de erro utilizando o método `$this->errorJson(['errorData' => 'value'], 400);`; um 404 utilizando `$app->pass()`; uma permissão negada utilizando `throw new \MapasCulturais\Exceptions\PermissionDenied`; etc.

## Visão Geral dos Hooks

Hooking (enganchar em inglês) é a forma que o Mapas Culturais oferece ao desenvolvedor para que ele possa alterar ou estender o comportamento padrão da aplicação, sem que para isso, ele precise modificar seu código.&#x20;

Há hooks espalhados por toda a aplicação e estes estão divididos basicamente em dois grandes grupos: os hooks de template (template hooks), que como o nome diz são definidos nos arquivos de template dos temas, plugins ou módulos, e os hooks da aplicação, que são definidos no core da aplicação.

### **Template Hooks**

Os template hooks são definidos chamando o método `applyTemplateHook` do tema, que recebe dois parâmetros para nomear o hook, `$name` e `$sufix`, além dos argumentos que serão passados para o callback *enganchado*. Os hooks definidos por este método receberão o nome `template(controllerId.actionName.nome-do-hook):sufix`. Costuma-se utilizar quatro sufixos para cada nome de hook: `before`, `begin`, `end` e `after`, como no exemplo abaixo, possibilitando que sejam incluídos código antes, no início, no fim ou depois da div:

```
<?php $this->applyTemplateHook('minha-div', 'before') ?>
<div id='minha-div'>
   <?php $this->applyTemplateHook('minha-div', 'begin') ?>
   <!-- aqui vai o conteúdo da div -->
   <?php $this->applyTemplateHook('minha-div', 'end') ?>
</div>
<?php $this->applyTemplateHook('minha-div', 'after') ?>
```

### **Hooks da Aplicação**

Os hooks da aplicação são os que estão espalhados nas classes do core do Mapas Culturais. Estes são definidos utilizando os métodos `applyHook` ou `applyHookBoundTo` da aplicação (classe `MapasCulturais\App`).

### **Habilitando logs de hook**

Para habilitar o log dos hooks chamados na requisição, utilize a chave de configuração `app.log.hook` da seguinte maneira:

* `true`: Para habilitar o log de todos os hooks;
* `'agent'`: Habilita o log de todos os hooks que tenham a palavra `agent`;
* `'(agent|space).save'`: Habilita log para os hooks que contenham `agent.save` ou `space.save`. *a configuração aceita expressões regulares e é case sensitive.*

### **Utilizando os hooks**

Costuma-se utilizar os hooks no método `_init` do tema, módulo ou plugin para adicionar um texto no início da `div#minha-div` na home da aplicação (controller `Site`, action `GET_index`), como no exemplo abaixo:

```
$app->hook('template(site.index.minha-div):begin', function () {
   echo '<p> Texto inserido no início da div </p>';
});
```

## MagicGetter e MagicSetter

O Mapas Culturais implementa em dois [traits](https://www.php.net/manual/pt_BR/language.oop5.traits.php) os métodos mágicos [\_\_get](https://www.php.net/manual/pt_BR/language.oop5.overloading.php#object.get) e [\_\_set](https://www.php.net/manual/pt_BR/language.oop5.overloading.php#object.set), da maneira exemplificada abaixo:

```
class MinhaClasse {
   use MagicGetter, MagicSetter;

   protected $_nome;

   function getNome() {
      return $this->_nome;
   }

   function setNome($val) {
      $this->_nome = strtoupper($val);
   }
}

$obj = new MinhaClasse;
$obj->nome = 'teste';

echo $obj->nome; // imprimirá 'TESTE';
```
