# 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';
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mapasculturais.gitbook.io/documentacao-para-desenvolvedores/formacao-para-desenvolvedores/introducao.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
