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 forma
Pode-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 admin
Agente 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
Agent
eSpace;
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
,Project
eOpportunity
;EntityOpportunities: Implementa um getter para retornar as oportunidades vinculadas a entidade. Utilizado nas entidades
Agent
,Space
,Project
eEvent
;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
,Seal
eSpace
;EntityRevision: Implementa a funcionalidade de revisões para as entidades. É utilizada nas entidades
Agent
,Space
,Registration
eRegistrationEvaluation
;EntitySealRelation: Implementa a funcionalidade da aplicação de selos nas entidades. Utilizado em
Agent
,Event
,Opportunity
,Project
eSpace
;EntitySoftDelete: Implementa o soft delete (lixeira) para as entidades. Utilizado em
Agent
,Event
,Opportunity
,Project
,Seal
,Space
,Subsite
eUserApp
;EntityTaxonomies: Implementa a funcionalidade de aplicar termos de taxonomias (tags, linguagem e área de atuação) nas entidades. Utilizado nas entidades
Agent
,Event
,Opportunity
,Project
eSpace
;EntityTypes: Implementa o campo
type
nas entidades. Utilizado emAgent
,EvaluationMethodConfiguration
,Event
,Opportunity
,Project
eSpace
.
Last updated
Was this helpful?