Descubra o porque do arquivo desaparecer e como evitar que o Drupal o apague!
Esses dias passamos por um dificuldade em um projeto aqui na Taller cuja causa e solução gostaria de compartilhar…
O cenário era o seguinte: havia um formulário customizado disponível para o administrador do site com um campo para envio de um arquivo, salvo no diretório de arquivos públicos do Drupal. Um link para este arquivo era disponibilizado para o usuário final, em uma página. Periodicamente, o link do arquivo enviado previamente “sumia” da página onde deveria estar.
Era um problema difícil de reproduzir e fiquei um bom tempo investigando se a variável onde era salva a referência para o arquivo poderia estar sendo sobrescrita ou apagada por algum código.
Depois de finalmente conseguir reproduzir o problema e com as dicas de um colega, foi possível verificar que a variável estava correta, mas o arquivo em si estava sendo removido do sistema de arquivos!
O Drupal se encarrega de limpar, a cada execução da cron, todos os arquivos temporários expirados e não utilizados. Isso é feito da seguinte maneira:
- Para verificar quais arquivos não são utilizados, é examinada a tabela file_usage do banco de dados.
- Para verificar quais arquivos estão expirados, é comparada a diferença entre a data atual e a data de criação do arquivo (coluna timestamp da tabela file_managed) com o valor da constante DRUPAL_MAXIMUM_TEMP_FILE_AGE (padrão 21600 segundos, ou seja, 6 horas).
Ou seja, a cada seis horas, quando executada a cron, nosso arquivo era jogado fora…
A solução adotada foi fazer com que o Drupal enxergasse que este arquivo não era temporário e não deveria ser apagado. Isso deve ser feito sempre ao trabalhar com elementos do tipo managed_file em formulários, conforme documentado na API.
Para atingir esse objetivo, no submit do nosso formulário customizado, acrescentamos:
if (!empty($form_state['values'][my_file_field])) {
// Load the file.
$file = file_load($form_state['values'][my_file_field]);
// Change status to permanent.
$file->status = FILE_STATUS_PERMANENT;
// Save.
file_save($file);
// Record that this module is using the file (to prevent deletion
// during cron execution).
// Modules have no id, but file_usage_add requires this parameter.
file_usage_add($file, 'my_custom_module', 'module', 0);
}
Onde my_custom_module é o nome de nosso módulo emy_file_field é o nome do nosso elemento, definido na criação do formulário como:
$form[my_file_field] = array(
'#type' => 'managed_file',
'#choose_file_text' => 'Selecionar arquivo',
'#change_file_text' => 'Alterar arquivo',
);
E pronto. Assim, evitamos que o Drupal apague nosso arquivo. Espero que esta breve dica ajude a prevenir problemas parecidos.