💻
Documentação para desenvolvedores
  • Formação para desenvolvedores
    • Introdução
    • Entidades
    • Controladores
    • Backend dos Temas
    • Frontend dos Temas
    • Plugins
    • Módulo AngularJS
  • 📖Livro de receitas
    • Criação de um Tema
    • Adicionando campos adicionais ao seu tema
    • Gerando certificados personalizados para os selos
  • APIs
    • Guia de Hooks
Powered by GitBook
On this page
  • Registrando um Controlador
  • Criando uma Rota (GET, POST, PUT, PATCH, DELETE, ALL)
  • Retornando JSON, Erro ou Renderizando Visão
  • Retornando JSON
  • Retornando Erro
  • Renderizando uma Visão
  • EntityController
  • Endpoints
  • Requested Entity
  • Requerendo Autenticação e Checagem de Permissão
  • Requerendo Autenticação
  • Checando a Permissão em uma Entidade
  • Traits de controladores
  • ControllerUploads

Was this helpful?

  1. Formação para desenvolvedores

Controladores

PreviousEntidadesNextBackend dos Temas

Last updated 3 years ago

Was this helpful?

Os controladores são instâncias de classes que estendem a classe abstrata e precisam ser registrados na aplicação.

class Teste extends \MapasCulturais\Controller {
   function GET_index() {
      echo 'teste';
   }
}

Registrando um Controlador

Para registrar um controlador, deve-se utilizar o método App::registerController, dando um id e a classe do controlador. Este registro deve ser feito no método register dos temas, plugins ou módulos.

Abaixo, o exemplo de registro do controller de classe Teste com o id teste:

   function register() {
      $app = App::i();

      $app->registerController('teste', Controllers\Teste::class);
   }

Registrado o controller, é possível acessar a rota padrão (GET_index) pelo id registrado: http://localhost/teste/.

Criando uma Rota (GET, POST, PUT, PATCH, DELETE, ALL)

Para criar uma rota basta criar um método utilizando o tipo de requisição (GET_, POST_, PUT_, PATCH_ e DELETE_), como prefixo. Para aceitar qualquer tipo de requisição, deve-se utilizar o prefixo ALL_.

class Teste extends \MapasCulturais\Controller {
   // POST http://localhost/teste/
   function POST_index() { }

   // GET http://localhost/teste/meuTeste/
   function GET_meuTeste() { }

   // PUT http://localhost/teste/meuTeste/
   function PUT_meuTest() { }

   // GET|POST|PUT|PATCH|DELETE http://localhost/teste/outroTeste/
   function ALL_outroTeste() { }

Retornando JSON, Erro ou Renderizando Visão

Retornando JSON

    public function json($data, $status = 200){
        $app = App::i();
        $app->contentType('application/json');
        $app->halt($status, json_encode($data));
    }

Então, para retornar um JSON basta invocar este método passando como primeiro parâmetro os dados a serem codificados como JSON. E como segundo parâmetro opcional, o código http de retorno da requisição.

   /* GET http://localhost/teste/objeto/ 
    * retorna status 200
    * {
         "id": 13,
         "name": "Nome"
      }
    */
    function GET_objeto() {
      $objeto = (object) [
         'id' => 13,
         'name' => 'Nome'
      ];
      $this->json($objeto);
    }

Retornando Erro

  • 404: Para retornar um erro 404, deve-se utilizar o método App::pass.

   function GET_objetoInexistente() {
      $app = App::i();
      $app->pass();
   }
  • JSON de erro: Para retornar um erro em formato JSON, utiliza-se o método errorJson do controller, informando os dados a serem codificados e o código http de retorno da requisição, como no exemplo a seguir:

   /* GET http://localhost/teste/erroDeValidacao/ 
    * retorna status 400
    * {
        "error": true,
        "data": {
          "name": ["o campo "nome" é obrigatório"],
          "shortDescription":["o campo "descrição curta" é obrigatório"]
        }
      }
    */
   function GET_erroDeValidacao () {
      $errors = [
         'name' => ['o campo "nome" é obrigatório'],
         'shortDescription' => ['o campo "descrição curta" é obrigatório']
      ];

      $this->errorJson($errors, 400);
   }
  • Erro customizado: Para retornar um erro customizado, utiliza-se o método halt da aplicação:

   function GET_permissaoNegada() {
      $app = App::i();
      $app->halt(403, "Permissão Negada!");
   }

Renderizando uma Visão

As visões são arquivos de template que ficam dentro da pasta views/{$controller_slug} do tema, módulo ou plugin, onde $controller_slug, por padrão, é o id do controller.

Para renderizar uma visão, utiliza-se o método render do controlador, que deve receber como primeiro parâmetro obrigatório o nome do arquivo de template e, como segundo parâmetro opcional, um array com as variáveis a serem enviadas à visão, como no exemplo a seguir:

function GET_lista () {
   $items = [
      'Primeiro item da lista',
      'Segundo item da lista',
      'Terceiro item da lista'
   ];
   $this->render('lista',['items' = $items]);
}

O arquivo de visão views/lista.php:

<?php foreach($items as $item): ?>
   <?= $item ?>
<?php endforeach; ?>

EntityController

Endpoints

  • POST_index: Endpoint para criação de entidades;

  • PUT_single: Endpoint para substituição da entidade (na prática acontece um update na entidade);

  • PATCH_single: Endpoint para atualização da entidade;

  • DELETE_single: Deleta a entidade;

  • POST_validateProperties: Valida os campos enviados, sem considerar os campos não enviados;

  • POST_validateEntity: Valida a entidade completa, considerando inclusive os campos não enviados;

  • GET_propertiesMetadata: Retorna JSON com os metadados (descrição) dos campos da entidade;

  • GET_single: Renderiza a single (página de visualização) da entidade;

  • GET_edit: Renderiza a página de edição das entidades.

Requested Entity

Se houver um parâmetro id na URL após o nome da rota, como nos exemplos abaixo, é possível pedir a entidade requisitada para o controlador:

class Agent extends EntityController {
   function GET_dumpEntity() {
      $entity = $this->requestedEntity; // ou $this->getRequestedEntity()

      if (!$entity) { // se não encontrou a entidade, 404
         App::i()->pass();
      }

      echo $entity->id; // imprime o id 33
   }
}

Requerendo Autenticação e Checagem de Permissão

A grande maioria das rotas da aplicação requerem que o usuário esteja autenticado e em muitas há uma checagem de permissão do usuário. As exceções costumam ser as páginas onde há somente a leitura de informações públicas.

Requerendo Autenticação

Para requerer a autenticação basta chamar o método requireAuthentication do controlador, normalmente, na primeira linha do método, como no exemplo a seguir:

   function GET_dumpEntity() {
      $this->requireAuthentication();
   }

Este método fará um redirect do usuário não autenticado para a página de login, retornando após a autenticação para a rota original. Caso o usuário já esteja autenticado o método não fará ação alguma.

Checando a Permissão em uma Entidade

É comum que mesmo o usuário estando autenticado, ele não tenha permissão para realizar uma operação em uma entidade. Por exemplo, um usuário não pode deletar um agente de outro usuário.

Como o sistema de permissões é implementado no nível do modelo, basta chamar o método checkPermission da entidade, informando a permissão a ser verificada.

Abaixo, a implementação completa do endpoint dumpEntity com requerimento de autenticação e com checagem de permissão:

class Agent extends EntityController {
   function GET_dumpEntity() {
      $this->requireAutentication();

      $entity = $this->requestedEntity; // ou $this->getRequestedEntity()

      if (!$entity) { // se não encontrou a entidade, 404
         App::i()->pass();
      }

      $entity->checkPermission('viewPrivateData');

      echo $entity->id; // imprime o id 33
   }
}

Neste exemplo, se o usuário não tiver permissão para ver os dados privados da entidade (método canUserViewPrivateData definido no trait EntityMetadata), será retornado um erro 403 para o usuário.

Traits de controladores

ControllerUploads

Para utilizar o trait ControllerUploads é necessário registrar os grupos de arquivos utilizando o método App::registerFileGroup.

O Mapas Culturais registra, por padrão, quatro grupos para as entidades principais: downloads, header, avatar e gallery.

$this->registerFileGroup('agent', new Definitions\FileGroup(
      'foto-do-documento', // nome do grupo
      ['^image/(jpeg|png)$'], // validação do mime type
      'O arquivo enviado não é uma imagem válida.', // mensagem de erro quando a validação não passa
      true // se é um grupo de um único arquivo
   )
);

Registrado o grupo, pode-se fazer upload do arquivo utilizando um campo file com o nome registrado:

<input type="file" name="foto-do-documento" >

A classe abstrata contém o seguinte método utilizado para retornar JSONs, este pode ser utilizado em qualquer dos controllers:

O é uma classe abstrata que implementa uma série de métodos e endpoints para manipular as entidades:

;

.

: Implementa os endpoints da API de busca do MapasCulturais (endpoints /api/{entity}/find, /api/{entity}/findOne e /api/{entity}/describe);

: Implementa o endpoint /api/{entity}/getChildrenIds. Utilizado pelos controladores de entidades que utilizam o trait EntityNested;

: Implementa os endpoints para manipulação dos agentes relacionados. Utilizado pelos controladores de entidades que utilizam o trait EntityAgentRelation;

: Implementa os endpoints para arquivar e desarquivar entidades. Utilizado pelos controladores de entidades que utilizam o trait EntityArchive;

: Implementa os endpoints para mudança de propriedade (ownerAgent) das entidades. Utilizado pelos controladores de entidades que utilizam o trait EntityOwnerAgent;

: Implementa os endpoints para a funcionalidade entidades em rascunho. Utilizado pelos controladores de entidades que utilizam o trait EntityDraft;

: Implementa os endpoints para manipulação dos MetaLists. Utilizado pelos controladores de entidades que utilizam o trait EntityMetalist;

: Implementa o endpoint para criação de oportunidade. Utilizado pelos controladores de entidades que utilizam o trait EntityOpportunities;

: Implementa os endpoints para manipulação dos selos relacionados às entidades. Utilizado pelos controladores de entidades que utilizam o trait EntitySeals;

: Implementa os endpoints para a funcionalidade de lixeira das entidades. Utilizado pelos controladores de entidades que utilizam o trait EntitySoftDelete;

: Implementa os endpoints /api/{entity}/getTypes e /api/{entity}/getTypeGroups. Utilizado pelos controladores de entidades que utilizam o trait EntityTypes;

: Implementa o upload de arquivos. Utilizado pelos controladores de entidades que utilizam o trait EntityFiles.

MapasCulturais\Controler
EntityController
http://localhost/agent/dumpEntity/33
http://localhost/agent/dumpEntity/id:33
ControllerAPI
ControllerAPINested
ControllerAgentRelation
ControllerArchive
ControllerChangeOwner
ControllerDraft
ControllerMetaLists
ControllerOpportunities
ControllerSealRelation
ControllerSoftDelete
ControllerTypes
ControllerUploads
MapasCulturais\Controler