Quando você define um campo como readonly, o navegador bloqueia o campo e envia os dados de volta ao servidor após o envio. Outro atributo é disabledque bloqueia o campo e não envia dados de volta ao servidor.
Nos dois casos, você pode definir com força o valor para ser o mesmo após o envio. Portanto, mesmo quando o campo estiver definido como readonlyou disabled, e o usuário modificou o HTML e enviou dados diferentes, $form_state['values']permanecerá inalterado.
function _build_element_readonly($element, &$form_state) {
$element['value']['#attributes']['readonly'] = 'readonly';
$element['value']['#value'] = isset($element['value']['#default_value'])
? $element['value']['#default_value']
: '';
return $element;
}
Observe que definimos a #value partir de #default_value. #default_value é a maneira usual de definir o valor padrão que é carregado quando o formulário é criado e $form_state['values']conterá o default_value ou a entrada do usuário. Quando você define #valueexplicitamente, a entrada do usuário é ignorada e #valueserá usada.
De qualquer forma, eu recomendaria usar '#access' => FALSE,ao ocultar elementos do formulário. Ele removerá o elemento completamente, permitindo que você use seus valores.
field_permissionsseria mais fácil do que fazer o trabalho de maneira suja.