Configurando o cache de arquivos no WordPress (.htaccess)
Opa.
As linhas abaixo permitem que você configure o cache de imagens, videos, entre outros sem antes precisar passar pelo index.php do WordPress. Isto é interessante não só para o WordPress mas também para qualquer outro projeto.
# Turn on Expires and set default to 0 ExpiresActive On ExpiresDefault A0 # Set up caching on media files for 1 year (forever?) ExpiresDefault A29030400 Header append Cache-Control "public" # Set up caching on media files for 1 week ExpiresDefault A604800 Header append Cache-Control "public" # Set up 2 Hour caching on commonly updated files ExpiresDefault A7200 Header append Cache-Control "proxy-revalidate" # Force no caching for dynamic files ExpiresActive Off Header set Cache-Control "private, no-cache, no-store, proxy-revalidate, no-transform" Header set Pragma "no-cache"
Lembrando que é necessário habilitar os modulos expires e headers do apache.
Creditos: askapache.com
Caminhos para a Certificação ZCE 5.3
Oi Pessoal,
gostaria de falar um pouco sobre a certificação ZCE 5.3. Vou tentar abordar algo que não tenha sido comentado nas várias esquinas da web. Talvez você já tenha lido algo que vou dizer aqui mas de qualquer forma vai aí o meu relato de como me preparei para esta prova.
Primeiro conselho: Estude, e bem. Se você trabalha com o PHP a bons anos e acha que vai conseguir passar na prova sem estudar absolutamente nada é bem possível que você tenha um resultado desagradavel ao final do teste. Porque? Simples, a prova exige conhecimento que vai além das tarefas do dia-a-dia.
Eu sei que não é possível/humano decorar todas as funções, metodos e propriedades de cada SPL/extentions. Porém, tente ao menos lembrar para que serve determinada função e como usa-lá.
O que eu fiz foi pegar o Study Guide 5.3 e ir acompanhando pelo site do php.net(que é a melhor fonte de estudo). Peguei um caderno e fui resumindo tudo tópico a tópico. Além disto, faça testes, quantos puder. Isso vai ajudar muito a você ter confiança. Tente espassar os dias antes de refazer o mesmo teste, isto ajuda a você desreferenciar as perguntas e respostas que você respondeu anteriormente. Não aconselho você ir para o exame sem conseguir atingir ao menos 90% de cada teste.
Eu cheguei a comprar o livro da php arch: Zend PHP 5 Certification Guide. O livro é bom mas não cobre tudo, ou seja, é preciso estudar bem mais pelo php.net.
O que me ajudou bastante também foram os mock tests da PHP arch para o PHP 5. Infelizmente os testes não são mais vendidos. Uma boa solução é procura algo relacionado na web – alá brainbench. Não meça esforços e se lembre: Conhecimento é acumulativo, então qual o problema de estudar um pouco a mais?
Algo que me ajudou bem também foi o practice test do UCertifiy. O programa de estudo deles é bom e merece atenção. Resumindo: Todo esforço é bem vindo.
Tem um mock test gratuito no site brainbench mas tenho que admitir que não o realizei completamente. Fiz algo em torno de 5 questões mas desisti quando vi que se tratava de grandes questões interpretativas. Acredito que se tivesse mais tempo faria.
Faça anotações, o maior número que puder. Anotar facilita a gravar e relembrar. Por mais que sejam muitas funções, metodos, propriedades e funcionalidades, escrevendo você precisa fazer o caminho duas vezes: é preciso primeiro ler e depois escrever. Assim, você dedica um tempo maior memorizando cada função/metodo/propriedade. Pode parecer imbecil mas esta técnica ajuda bastante.
Não vá para a prova com dúvidas, se você não sabe mexer com bitwise ou não sabe pra que serve o safe_mode então estude mais. Não esqueça também de estudar as novas features do php 5.3, static late binding, namespaces, nowdoc, etc.
Procure entender também sobre design patterns. Este é um tema que nem todos sabem muito bem, então procure o maior número possível de artigos que puder sobre: strategy, singleton, factory, mvc, etc.
No dia da prova tente chegar 1 hora antes do início. Isso ajuda a você a manter a calma e se familiarizar com o ambiente. Leve suas anotações e reforce a memorização nos detalhes que você acha mais complicado.
No mais é isto mesmo. Espero que você tenha sucesso nesta nova empreitada e conquista.
Abraços
Deployment no symfony 1.4 – Corrigido
Quem tentou trabalhar com o deployment do symfony – leia symfony 1.4 -, provavelmente já teve problemas. Este artigo, trata de uma particularidade sobre o sistema de deploy do symfony 1.4 em ambiente Windows, que tem uma solução simples e eficaz.
Eu tentei encontrar alguns tópicos relacionados a este assunto mas não encontrei nada. Acredito que isto seja porque poucos tem a possibilidade de usar contas com acesso shell em seus servidores de hospedagem – isto, portanto, faz com que poucos desenvolvedores usem o rsync.
Nem sempre um shared hosting dá a possibilidade do uso de uma conta shell, o que é compreensivel. Bom, se você não tem uma conta shell, passe a ter, e se usa um shared host passe a usar um VPS ou um servidor dedicado. Já tive sérios problema quanto a usar um shared host, mas isto explicarei em outro momento.
Este problema passou a ocorrer quando migrei do symfony 1.2 para o 1.4. É interessante notar que o modo de executar comandos shell no symfony 1.4 mudou. No 1.2 temos o uso do passthru() enquanto no 1.4 temos o proc_open() – um executa um comando shell e retorna sua saída crua e o outro executa um comando (abre um processo) e abre ponteiros de entrada e saída.
O problema na realidade, não está no symfony, mas sim na função proc_open() do php, mais especificamente nos pipes criados pelo PHP na execução do comando rsync – ou qualquer outro comando que venha a ser. Isto acontece somente em determinados momentos onde o stream STDERR é preenchido e faz com que o stream STDOUT congele e gere um loop infinito no Windows – obrigado ao Luceo.
Eu confesso que este problema, não foi tão simples de se resolver, já que se trata de um problema bem especifico do PHP e do Windows. Contudo proponho aqui duas soluções para o problema.
A primeira, e mais correta é alterar o modo de acesso do pipe STDERR na classe sfFilesystem.class.php, linha 291:
$descriptorspec = array(
1 => array('pipe', 'w'), // stdout
2 => array('pipe', 'a'), // stderr
);
Isto faz com que o ponteiro do stream STDERR saia da posição inicial – w mode – e vá para a posição final – a mode. Ou seja, basta mudar o modo de acesso do pipe que o problema se resolve.
A segunda solução é tão simples quanto a apresentada. Basta customizar os parametros inseridos pelo symfony no comando rsync, ou seja, simplesmente omita o parametro –progress. Veja o exemplo abaixo:
[production]
host=smartlinks.com.br
port="22 -i E:/cygwin/home/Augusto/.ssh/id_rsa"
user=smartlinks
dir=/home/smartlinks/website
parameters="-azC --force --delete --exclude-from=config/rsync_exclude.txt"
Lembrando novamente: Este problema acontece somente a partir da versão 1.3 do symfony onde foi mudado a maneira como é executado comandos shell pelo symfony. Anteriormente usava-se o passthru() e agora o proc_open().
Cheguei a abrir um ticket sobre este problema no website do bugtrac do symfony mas até o momento não obtive nenhuma resposta sobre o problema. Assim que tiver alguma posição aviso vocês.
Não cheguei a olhar este assunto no symfony 2.0 mas assim que tiver tempo darei um olhada.
Espero ter ajudado.
DNS 323 – Raid 1 Degraded
Hi,
i will describe a problem that i had with my DNS 323 storage. My storage is working as raid 1 – mirroring of two HD 500 Gbs.
Right. Two days ago i received an email from my storage saying this:
Right Hard Drive Has Failed Sincerely, Your DNS-323
Well, i opened the DNS 323 manager from the browser and i saw this page:
After read some posts about this issue and clicked in the button: Manually Rebuild Now. I was surprise about the time estimated: ~7800 minutes. It was not possible! You can do the calc, 7800 min / 60 = 130 hours / 24 = 5,42 days!!!! Persistent as i am, i waited for 16 hours! For my bad the time estimate still very high: ~6800 minutes.
At this moment i threw the towel in the floor. I turned off the storage, and started again to find a solution about it. I confess that is very simple. Ijust removed the HD with problem, check if had some problems with it: not had. I removed all partitions in the HD and put it back to the storage. The storage formated the HD and syncronized the data with the another HD. This spent ~90 minutes!
Here is my advice. Not click in the “manually rebuild now” button. Just remove the HD with problem, check if it have problems, remove all partitions and put it back to the storage. This is the more easy and correct procedure.
Good luck!
Deployment problem in Symfony 1.4 – FIXED
Whom tried works with the symfony’s deployment – read symfony 1.4 -, probably had problems with it. This article, is about a peculiarity of the symfony deploy interface, in Windows environment, that have a simple and effective solution.
I tried to find related topics about this issue but I didn’t find anything. I believe that just few developers have the possibility to use shell accounts in hosting servers, consequently, the use of these tools, like rsync, are impaired.
Shared hosting not always provides the possibility to use a shell account, which is understandable. Well, if you don’t have a shell account, pay for one, and whether you have a shared hosting, rent a VPS or dedicated server. I had serious problems using a shared host, but I will explain it in another moment.
This problem started to occur when I migrated from symfony 1.2 to 1.4. It’s interesting to note that the way to execute shell commands on symfony 1.4 has changed. At 1.2 we have the passthru() while in the 1.4 we have the proc_open() – the first executes a shell command and returns raw output, the other executes a shell command (open a process) and open file pointers for input and output.
The problem actually isn’t in the symfony, but in the PHP function proc_open(), more specifically in the pipes created by PHP in the execution of rsync command – or any other command.This happens only in few moments where the STDERR stream is filled and it causes a freeze in the STDOUT stream that generates a infinity loop on Windows – Thanks to Luceo.
I confess that this problem was not so simple to fix, this is a very specific problem of PHP and Windows. However I propose two solutions for this problem:
The first solution, the right way, is to change the access mode of the STDERR pipe in the class sfFilesystem.class.php, line 291:
$descriptorspec = array(
1 => array('pipe', 'w'), // stdout
2 => array('pipe', 'a'), // stderr
);
This makes with that the pointer STDERR stream leaves from starting position – “w” mode – and goes to the final position – “a” mode. In others words, just change the pipe access mode and the problem will be resolved.
The second solution is so simple as the first. Simply customize the default rsync parameters of symfony, in others words, omit the parameter –progress. See the example below:
[production] host=www.domain.com port='22 -i E:\cygwin\home\Augusto\.ssh\id_rsa' user=domain dir=/home/domain/website parameters="-azC --force --delete --exclude-from=config/rsync_exclude.txt"
Recalling again: This problem happens only from symfony version 1.3 where was changed the way that’s shell commands are executed by symfony. Previously, it used the passthru() and now is used the proc_open().
I even open a ticket about this problem in the symfony bugtrac’s website but, until now, I didn’t get a reply of this issue. Therefore when I receive a answer I tell to you.
I didn’t look to the symfony 2.0 about this issue but when I have time I will look.
I hope that it helps you.
symfony cli colorido (Cygwin)
Olá a todos,
hoje vou dar um dica simples porém acredito que seja valiosa pra quem trabalho com o symfony no ambiente Windows. Gostaria de deixar em negrito que não aconselho optar pelo Windows como ambiente de produção. Apenas como uma alternativa para ambiente de desenvolvimento.
Você que trabalha ou já trabalhou com o symfony no ambiente Linux, já reparou que o cli do comando symfony apresenta cores. Porém ao trabalhar no Windows você não tem a mesma experiência. Isto é porque o Windows não escapa corretamente os caracteres ANSI. Por isto você não vê as cores.
Pois bem. Esta “colorização” – por assim dizer – pode ser habilitada usando um aplicativo chamado ANSICO do Jason Hood. É simples sua instalação. Basta fazer o download e copiar os arquivos ansicon.exe e ANSI.dll para algum diretório mapeado na variável PATH do seu Windows. Eu preferi fazer isto usando o caminho: c:/windows/system32 . Depois de copiar os arquivos é preciso instalá-lo no registro:
# ansicon -i
Simples, certo? Agora seu symfony exibe as cores em seu cygwin perfeitamente. As cores também ficam habilitadas no shell nativo do windows.
É importante ressaltar que esta “colorização” foi implementada – e passou a ter suporte no windows – somente a partir do symfony 1.3. Portanto se você usa alguma versão inferior a 1.3 este já é um dos motivos para migrar para a versão 1.4.
Espero ter ajudado.
Abraços.
Frontend/Backend – Formatando números e Moedas no Symfony
Bom dia a Todos,
quem já trabalha com symfony há algum tempo já passou por este problema de formatar números e moeda na língua portuguesa. A solução para este “problema” é bem simples e com certeza faz uma grande diferença para o usuário final.
Portanto nossa tarefa de hoje é formatar dados númericos e moedas no symfony. Vamos começar pelo frontend:
Apesar de ser bem documentado esta implementação na documentação do symfony, achei relevante citar esta mesma implementação do frontend aqui. A primeira coisa que você deve fazer é alterar seu apps/frontend/config/settings.yml, isto vale para o backend também. Faça esta mesma modificação em seu backend.
Devemos habilitar 2 parametros: um referente ao i18n e o outro ao culture. São eles:
all:
.settings:
i18n: on
default_culture: pt_BR
A linha i18n serve para habilitar o suporte a internacionalização do symfony e a default_culture creio que dispensa explicações. Não se esqueça de fazer isto no ambiente do backend também pois iremos modificá-lo daqui a pouco.
Ok. Agora mãos a obra. O symfony possui um pacote chamado NumberHelper que nos ajuda a formatar números e moeda: format_number() e format_currency(), respectivamente. Todas as formatações de dados no frontend devem ser feitas na camada VIEW do MVC, neste caso os templates.
Segue um breve exemplo:
IndexSuccess.php
<h1>Produtos List</h1>
<table>
<thead>
<tr>
<th>Id</th>
<th>Label</th>
<th>Descricao</th>
<th>Peso</th>
<th>Comprimento</th>
<th>Largura</th>
<th>Altura</th>
<th>Preco venda</th>
</tr>
</thead>
<tbody>
<?php foreach ($produtos_list as $produtos): ?>
<tr>
<td><a href="<?php echo url_for('produtos/edit?id='.$produtos->getId()) ?>"><?php echo $produtos->getId() ?></a></td>
<td><?php echo $produtos->getLabel() ?></td>
<td><?php echo $produtos->getDescricao() ?></td>
<td><?php echo $produtos->getPeso() ?></td>
<td><?php echo $produtos->getComprimento() ?></td>
<td><?php echo $produtos->getLargura() ?></td>
<td><?php echo $produtos->getAltura() ?></td>
<td><?php echo $produtos->getPrecoVenda() ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<a href="<?php echo url_for('produtos/new') ?>">New</a>
Vamos então formatar o preço de venda do Produto. Para isto basta usarmos a função format_currency:
* É necessário adicionar a linha: no início de nosso template para informarmos ao symfony que estamos usando a classe Number.
Agora dê um refresh em http://aplicacao/produtos e você verá todos os preços formatados. Agora precisamos formatar e permitir que os usuários populem a nossa aplicação usando o formato brasileiro de números e moeda.
Para isto você vai precisar criar um validator para os números em formato brasileiro. Crie uma nova classe chamada myValidatorNumberBR em /lib/validator/:
myValidatorNumberBR.class.php
class myValidatorNumberBR extends sfValidatorBase {
protected function configure($options = array(), $messages = array())
{
$this->setMessage('invalid', '"%value%" não é um número valido.');
}
protected function doClean($value)
{
$float = str_replace(',', '.', $value);
if (!is_numeric($float))
{
throw new sfValidatorError($this, 'invalid', array('value' => $value));
}
$clean = $float;
return $clean;
}
}
Este código acima vai permitir que os usuários insiram números no formato brasileiro: ex: 100,75
Esta quase tudo pronto, basta agora setar o validator de nossos widgets. Abra a classe ProdutosForm em /lib/forms.
class ProdutosForm extends BaseProdutosForm
{
public function configure()
{
$this->setValidators(array(
'id' => new sfValidatorNumber(array('required' => true), array('required' => 'Campo Obrigatório')),
'label' => new sfValidatorString(array('required' => true), array('required' => 'Campo Obrigatório')),
'preco_venda' => new myValidatorNumberBR(array('required' => true), array('required' => 'Campo Obrigatório')),
'peso' => new myValidatorNumberBR(array('required' => true), array('required' => 'Campo Obrigatório')),
'largura' => new myValidatorNumberBR(array('required' => true), array('required' => 'Campo Obrigatório')),
'altura' => new myValidatorNumberBR(array('required' => true), array('required' => 'Campo Obrigatório')),
'comprimento' => new myValidatorNumberBR(array('required' => true), array('required' => 'Campo Obrigatório')),
'descricao' => new sfValidatorString(array('required' => true), array('required' => 'Campo Obrigatório')),
));
}
}
Pronto. Simples não?
Bom, agora nós precisamos fazer a mesma alteração no backend. O admin generator cria todos os templates necessários para a exibição dos módulos, ou seja, os templates são gerados automaticamente e armazenados(temporariamente) no cache. Vide: /cache/backend/ENV/modules/autoProdutos/templates. O mesmo acontece para o actions mas não vamos entrar nesta área aqui.
Nós precisamos sobrescrever nosso template (partial) _list_td_tabular.php e _form_field.php. Veja como ficará nosso _list_td_tabular.php
<?php echo use_helper('Number'); ?>
<td class="sf_admin_text sf_admin_list_td_label">
<?php echo link_to($produtos->getLabel(), 'produtos_edit', $produtos) ?>
</td>
<td class="sf_admin_text sf_admin_list_td_precoVenda">
<?php echo format_currency($produtos->getPrecoVenda(), "R$") ?>
</td>
<td class="sf_admin_text sf_admin_list_td_peso">
<?php echo format_number($produtos->getPeso()) ?>
</td>
Agora nosso _form_field.php:
<?php echo use_helper('Number'); ?>
<?php if ($field->isPartial()): ?>
<?php include_partial('produtos/'.$name, array('form' => $form, 'attributes' => $attributes instanceof sfOutputEscaper ? $attributes->getRawValue() : $attributes)) ?>
<?php elseif ($field->isComponent()): ?>
<?php include_component('produtos', $name, array('form' => $form, 'attributes' => $attributes instanceof sfOutputEscaper ? $attributes->getRawValue() : $attributes)) ?>
<?php else: ?>
<div class="<?php echo $class ?><?php $form[$name]->hasError() and print ' errors' ?>">
<?php echo $form[$name]->renderError() ?>
<div>
<?php echo $form[$name]->renderLabel($label) ?>
<?php if ($name == "preco_venda" or $name == "peso" or $name == "largura" or $name == "altura" or $name == "comprimento") : ?>
<?php echo $form[$name]->render(array( 'value' => format_number($form[$name]->getValue()))); ?
<?php else: ?>
<?php echo $form[$name]->render($attributes instanceof sfOutputEscaper ? $attributes->getRawValue() : $attributes) ?>
<?php endif; ?>
<?php if ($help || $help = $form[$name]->renderHelp()): ?>
<div class="help"><?php echo __($help, array(), 'messages') ?></div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
Veja que neste arquivo nós formatados os números exibidos no formulário. Como já configuramos o validator de nossos campos númericos: altura, largura, etc. O administrador já consegue popular estes campos com a notação brasileira.
Bom, espero que este post ajude.
Abraços
Augusto Morais
hoje vou explicar como formatar númers
EmbedForm no Symfony 1.2
Olá a todos,
recentemente tive um grande problema em relação ao embedforms do symfony. A tarefa era simples, encapsular um formulário dentro de outro com a opção de adicionar ou não um novo registro no BD. Este blog surgiu simplesmente por conta deste problema que enfrentei e vejo que muitos já enfrentaram e vão enfrentar.
Fiquei exatamente 3 dias pesquisando isto e não achei nada exato na internet, algumas dicas aqui e outras ali. Comecei a fazer tudo a minha própria maneira e finalmente consegui. O exemplo a seguir é com base no doctrine. Passei a usá-lo por diversos motivos que agora não entram em questão. Vejo que minha alternativa para este problema não me parece comum e nem a mais correta, porém foi a que encontrei e gostaria muito que outros compartilhassem tal assunto comigo.
Bom, vamos a situação.
Tenho 2 tabelas, uma chamada autor e outra livros, eis aqui o schema.yml:
Livro:
actAs: { Timestampable: ~ }
columns:
autor_id: { type: integer , notnull: true }
isbn: { type: string(50), notnull: true }
titulo: { type: string(50), notnull: true }
relations:
Autor: { onDelete: CASCADE, local: autor_id, foreign: id, foreignAlias: Livros }
Autor:
actAs: { Timestampable: ~ }
columns:
nome: { type: string(255), notnull: true }
sobrenome: { type: string(255), notnull: true }
Simples. A nossa intenção aqui é criar um formulário semelhante a este:

formulário
Ok. Perceba no checkbox Novo Autor. É nisto que vou trabalhar neste artigo. A opção de escolher um autor já cadastrado ou adicionar um novo autor.
Bom, vamos lá. A primeira coisa que devemos fazer é modificar nosso LivroForm.class.php para a seguinte estrutura:
class LivroForm extends BaseLivroForm
{
public function configure()
{
$autorForm = new AutorForm();
//Adicionando Checkbox "adicionar novo cliente"
$this->getWidgetSchema()->offsetSet(
'add_new_autor', new sfWidgetFormInputCheckbox(array(
'label' => 'Novo Autor')));
$this->embedForm('new_autor', $autorForm);
$this->widgetSchema['autor_id']->setOption(
'add_empty', 'Escolher Autor');
$this->validatorSchema['autor_id']->setMessage(
'required', 'Por favor, escolha um autor ou crie um novo.');
$this->setValidatorSchema(
new LivroValidatorSchema($this->validatorSchema->getFields()));
// Inserindo campos extras (checkbox no caso)
$this->validatorSchema->setOption('allow_extra_fields', true);
$this->validatorSchema->setOption('filter_extra_fields', false);
}
public function updateObject($values = null)
{
parent::updateObject();
if ($this->values['autor_id'] <> 0)
{
//Salvando nosso livro com o ID do autor Setado no template
$livro = new Livro();
$livro->fromArray($this->values);
$livro->save();
return $this->object;
} else {
//Salvando nosso autor criado
$autor = new Autor();
$autor->fromArray($this->values['new_autor']);
$autor->save();
//Salvando nosso Livro com o nosso autor criado
$this->getObject()->setAutor($autor);
$this->getObject()->save();
return $this->object;
}
}
}
Ok. Gostaria somente de comentar aqui a linha 43: $autor->save() e 47: $this->getObject()->save(). Na linha 43 nós estamos salvando o nosso novo cliente. Após salvar, nós pegamos o objeto autor e setamos no nosso objeto Boleto(linha 46). Logo depois nós salvamos nosso boleto, linha 47.
Nós precisamos modificar nosso validator para aceitar os novos campos adicionados (checkbox e o formulario encapsulado, autor).
Crie um arquivo chamado LivroValidatorSchema.class.php em /lib/validators:
class LivroValidatorSchema extends sfValidatorSchema {
protected function doClean($values)
{
if (is_null($values)) {
$values = array();
}
if (!is_array($values)) {
throw new InvalidArgumentException(
'You must pass an array parameter to the clean() method');
}
if (isset($values['add_new_autor'])) {
$values['autor_id'] = '';
$this->offsetUnset('autor_id');
} else {
if (isset($values['new_autor'])) {
$values['new_autor'] = '';
unset($values['new_autor']);
}
$this->offsetUnset('new_autor');
}
return parent::doClean($values);
}
}
obs.: o código acima foi tirado de: http://forum.symfony-project.org/index.php/m/65120/
Agora está quase tudo pronto. Falta agora modificar nosso actions:
protected function processForm(sfWebRequest $request, sfForm $form)
{
$form->bind($request->getParameter($form->getName()));
if ($form->isValid()) {
$form->updateObject();
//$livro = $form->save();
//$this->redirect('livro/edit?id='.$livro->getId());
$this->redirect('livro/index');
}
}
Perceba que a linha 6 está comentada: $livro = $form->save(); Está linha deve ser comentada mesmo pois quem vai salvar nosso objeto é o metodo updateObject. Caso você salve aqui você perceberá que os registros serão duplicados e está não é nossa intenção.
Agora você precisa adaptar seu form lá em templates para ter a mesma estrutura apresentada no inicio do artigo.
Este artigo foi criado rapidamente e sem preocupação com organização. Num próximo momento faço isto descentemente.
Aguardo comentários de todos.
Abraços
Augusto Morais
Deixe um comentário
