Entidades
"A plataforma inteira é desenvolvida em torno de seis entidades principais: Agentes, Espaços, Eventos, Projetos, Oportunidades e Inscrições"
O Mapas Culturais utiliza o Doctrine como ORM. Para o Doctrine, as entidades representam um mapeamento entre o modelo orientado a objetos e o modelo relacional do banco de dados.
Uma classe de entidade representa uma tabela. Enquanto uma instância dessa classe representa uma entrada nesta tabela.
O Mapas Culturais implementa na classe MapasCulturais\Entity uma abstração em cima das entidades do Doctrine.
Essa implementação ocorre de modo a facilitar a validação da entidade, as operações CRUD e, ao mesmo tempo, cuidar das permissões, impedindo que um usuário faça operações e/ou visualize informações que ele não tem permissão. Todas as entidades do mapas estendem esta classe.
Para se aprofundar nas entidades vale a leitura da documentação Working With Objects do Doctrine. Lembrando que o Mapas faz uma abstração em cima do Doctrine.
Trabalhando com Entidades (CRUD e os Repositórios)
Operação de Inserção
Para inserir uma nova entrada em uma tabela, ou em outras palavras, criar um novo objeto de uma determinada entidade, deve-se instanciar um novo objeto da classe desejada, definir ao menos os atributos obrigatórios e chamar o método save do objeto.
Você pode também, antes de salvar, verificar se há erros de validação no objeto.
$agent = new \MapasCulturais\Entities\Agent;
$agent->name = 'Fulano';
$agent->type = 1; // agente do tipo individual
$agent->shortDescription = 'Descrição do fulano';
if (!($errors = $agent->getValidationErrors())) {
$agent->save(true); // passar true para o método save faz o flush do objeto no banco de dados
}Operação de Leitura (Recuperando Entidade do Banco de Dados)
Para recuperar um objeto do banco de dados você deve utilizar o repositório da entidade.
O repositório da entidade pode ser acessado pelo método repo da aplicação.
$app = MapasCulturais\App::i();
// pega o agente de id 1
$agent = $app->repo('Agent')->find(1);
// pega um agente de nome 'Fulano'
$agent = $app->repo('Agent')->findOneBy(['name' => 'Fulano']);
// pega todos os agentes de nome 'Fulano'
$agents = $app->repo('Agent')->findBy(['name' => 'Fulano']);Operação de Atualização
Para modificar um objeto após recuperá-lo do banco de dados, você deve modificar suas propriedades e utilizar o método save.
$app = MapasCulturais\App::i();
// pega o agente de id 1
$agent = $app->repo('Agent')->find(1);
$agent->name = 'Ciclano';
$agent->save(true);Operação de Deleção
Para deletar um objeto você deve utilizar o método delete, do mesmo:
$app = MapasCulturais\App::i();
// pega o agente de id 1
$agent = $app->repo('Agent')->find(1);
$agent->delete(true);Permissões no Nível do Modelo e Diagrama de Permissões
O sistema de permissões do Mapas Culturais é implementado no nível do modelo. Esta abordagem auxilia na prevenção de bugs, uma vez que o controle do que um usuário pode ver, criar, modificar, ou deletar, acontece automaticamente, disparando uma exceção PermissionDenied quando uma operação não permitida for executada.
Considerando que usuário não está autenticado, o exemplo abaixo disparará a exceção no momento da execução do save(true):
$app = MapasCulturais\App::i();
// pega o agente de id 1
$agent = $app->repo('Agent')->find(1);
if ($app->user->is('guest')) {
$agent->name = 'Ciclano';
$agent->save(true);
}Ou do delete:
$agent = $app->repo('Agent')->find(1);
if ($app->user->is('guest')) {
$agent->delete(true);
}O mesmo acontece quando um usuário tenta modificar ou apagar um objeto que não lhe pertence e ao qual ele não tem controle.
As permissões são implementadas em funções com o prefixo canUser (por exemplo, canUserModify), e podem ser verificadas através do método canUser da entidade.
// se o usuário autenticado pode modificar o objeto $agent, imprime um botão editar
if ($agent->canUser('modify')) {
echo "<button>editar</button>";
}Os métodos canUser recebem o usuário ao qual a permissão está sendo testada e devem ser implementados como protegidos:
class Agent {
protected function canUserDoSomething($user) {
if($user->is('admin')) {
return true;
} else {
return false;
}
}
}
$agent->canUser('doSomething'); // retorna true se o usuário logado for admin, false de outra formaPode-se verificar a permissão antes de efetuar uma operação utilizando o método checkPermission, que dispara uma exceção de PermissionDenied quando o método canUser da permissão retornar false. Esta função é muito útil nos controladores, como veremos no próximo capítulo.
$agent->checkPermission('doSomething'); // dispara a exceção se o usuário logado não for um adminAgente Relacionado com Controle (permissão @control)
@todo
Diagrama de Permissões

Metadados, Taxonomias e Termos, e Arquivos
Metadados
Como falado anteriormente, cada entidade principal, agentes, espaços, eventos, projetos, oportunidades e inscrições, conta com uma entidade secundária auxiliar para salvamento de metadados. Diferentemente das outras entidades auxiliares, que veremos em seguida.
Para cada entidade principal temos uma tabela própria para a entidade secundária, por exemplo, temos uma tabela agent_meta para salvar os metadados dos agentes. A estrutura dessas entidades é a seguinte:
id: int;key: string;value: string;owner: tipo da entidade principal, ou seja Agent, Space, Event, Project, Opportunity ou Registration (mapeado para a colunaobject_id).
Os metadados das entidades precisam ser registrados antes de serem utilizados. No método register de plugins ou temas, podemos registrar metadados da seguinte maneira:
function register() {
$this->registerAgentMetadata('numeroDeFilhos', [
'label' => 'Metadado para salvar a informação de quantos filhos o agente tem',
'type' => 'number',
// campo privado, somente quem puder ver dados privados ($agent->canUser('viewPrivateData')) poderá ver esta informação
'private' => true,
'default' => 0,
'validations' => [
'required' => 'O número de filhos é obrigatório',
// sintaxe do Respect/Validation
'v::intVal()->positive()' => 'O número de filhos deve ser um número inteiro positivo'
],
'serialize' => function ($val) {
return (string) (int) $val;
},
'unserialize' => function ($val) {
return (int) $val;
}
])
}Os seguintes métodos estão disponíveis para utilização em Plugins, Módulos e Temas:
registerAgentMetadata;registerEventMetadata;registerOpportunityMetadata;registerProjectMetadata;registerRegistrationMetadata;registerSealMetadata;registerSpaceMetadata;registerUserMetadata.
Após registrar o metadado, você pode utilizá-lo como se fosse um atributo do objeto, usando a chave registrada diretamente:
$agent->numeroDeFilhos = 4;
$agent->save();
echo $agent->numeroDeFilhos;É importante utilizar os metadados dessa maneira, pois é nesta implementação que é feita a verificação das permissões para visualização dos metadados privados.
Ou seja, acessar os metadados através do getter getMetadata NÃO é uma boa prática
Taxonomias e Termos
A implementação das taxonomias é feita em torno das entidades Term e TermRelation, e do trait EntityTaxonomies.
Uma vez registrada uma taxonomia, você pode acessar e definir os termos que uma entidade principal utiliza desta taxonomia da seguinte maneira, utilizando como exemplo a taxonomia tag:
$tags = $agent->terms['tag'];
$tags[] = 'mapas';
$agent->terms['tag'] = $tags;
$agent->save();A operação do exemplo acima adicionará uma entrada na tabela term para o termo mapas da taxonomia tag, isso ocorre somente se ainda não houver o termo. E, adicionará outra entrada na tabela term_relation relacionando o termo criado ao agente.
Arquivos
A funcionalidade de anexar arquivos nas entidades é implementada pela entidade secundária File e pelos traits EntityFiles, que implementa a parte do modelo. E, pelo ControllerUploads que automatiza os uploads dos arquivos.
Cada entidade que utiliza o trait EntityFiles tem uma entidade auxiliar, por exemplo, a entidade Agent tem a entidade auxiliar AgentFile que tem a propriedade owner do tipo Agent.
Além disso, a entidade principal recebe do trait alguns métodos gets que auxiliam a obtenção dos arquivos anexos. O principal deles é o getFiles, acessível pelo magic getter por ->files.
>>> $agent->files
[
"avatar" => MapasCulturais\Entities\AgentFile {#9645
+__isInitialized__: true,
…2
},
"downloads" => [
MapasCulturais\Entities\AgentFile {#9654},
MapasCulturais\Entities\AgentFile {#9656},
]
]Traits de Entidades
Os seguintes traits estão disponíveis e são utilizados nas diversas entidades:
EntityAgentRelation: Implementa a funcionalidade de relacionar agentes na entidade. É utilizado por todas as entidades onde é preciso definir administradores para conceder permissão de controle sobre a entidade;
EntityArchive: Implementa a funcionalidade de arquivar e desarquivar uma entidade (
Entity::STATUS_ARCHIVE = -2). É utilizado nas entidades principais;EntityAvatar: Implementa um getter para o grupo de arquivos
avatar. É utilizado pelas entidades que têm a funcionalidade de avatar;EntityDraft: Implementa a funcionalidade de entidades em rascunho. É utilizado pelas entidades principais;
EntityFiles: Implementa a funcionalidade de arquivos anexos às entidades;
EntityGeoLocation: Implementa a funcionalidade de geolocalização. É utilizado nas entidades
AgenteSpace;EntityMetaLists: Implementa a funcionalidade de listas (links e vídeos);
EntityMetadata: Implementa os metadados para os agentes. É utilizado pelas entidades que possuem a entidade secundária auxiliar para salvamento de metadados;
EntityNested: Implementa a funcionalidade de entidades hierárquicas. É utilizado pelas entidades com a propriedade
parent, ou seja,Agent,Space,ProjecteOpportunity;EntityOpportunities: Implementa um getter para retornar as oportunidades vinculadas a entidade. Utilizado nas entidades
Agent,Space,ProjecteEvent;EntityOriginSubsite: Implementa nas entidades métodos relacionados ao SaaS. É utilizado nas entidades que têm a propriedade
subsite, mapeamento para a colunasubsite_id;EntityOwnerAgent: Implementa a funcionalidade de agente proprietário da entidade. É utilizado pelas entidades que têm um agente
owner("Assinado por", no rodapé da página);EntityPermissionCache: Implementa a funcionalidade de cache de permissão para a entidade. Como esse cache só é utilizado pela API de busca do Mapas Culturais, este trait é utilizado pelas entidades que disponibilizam a API ou que são utilizadas nas queries da API, a saber,
Agent,EvaluationMethodConfiguration,Event,Notification,Opportunity,Project,Registration,Request,SealeSpace;EntityRevision: Implementa a funcionalidade de revisões para as entidades. É utilizada nas entidades
Agent,Space,RegistrationeRegistrationEvaluation;EntitySealRelation: Implementa a funcionalidade da aplicação de selos nas entidades. Utilizado em
Agent,Event,Opportunity,ProjecteSpace;EntitySoftDelete: Implementa o soft delete (lixeira) para as entidades. Utilizado em
Agent,Event,Opportunity,Project,Seal,Space,SubsiteeUserApp;EntityTaxonomies: Implementa a funcionalidade de aplicar termos de taxonomias (tags, linguagem e área de atuação) nas entidades. Utilizado nas entidades
Agent,Event,Opportunity,ProjecteSpace;EntityTypes: Implementa o campo
typenas entidades. Utilizado emAgent,EvaluationMethodConfiguration,Event,Opportunity,ProjecteSpace.
Last updated
Was this helpful?