В очередной раз перекапывая Form API столкнулся с проблемой установки ССК-полю значения disabled.
<?php
/**
* file
* Custom module to set the disabled attribute of CCK fields.
*/
/**
* Implementation of hook_form_alter().
*/
function mysnippet_form_alter(&$form, $form_state, $form_id) {
if (isset($form['type']) && isset($form['#node'])) {
// Use this check to match node edit form for a particular content type.
if ('mytype_node_form' == $form_id) {
$form['#after_build'][] = '_mysnippet_after_build';
}
// Use this check to match node edit form for any content type.
// if ($form['type']['#value'] .'_node_form' == $form_id) {
// $form['#after_build'][] = '_mysnippet_after_build';
// }
}
}
/**
* Custom after_build callback handler.
*/
function _mysnippet_after_build($form, &$form_state) {
// Use this one if the field is placed on top of the form.
_mysnippet_fix_disabled($form['field_myfield']);
// Use this one if the field is placed inside a fieldgroup.
// _mysnippet_fix_disabled($form['group_mygroup']['field_myfield']);
return $form;
}
/**
* Recursively set the disabled attribute of a CCK field
* and all its dependent FAPI elements.
*/
function _mysnippet_fix_disabled(&$elements) {
foreach (element_children($elements) as $key) {
if (isset($elements[$key]) && $elements[$key]) {
// Recurse through all children elements.
_mysnippet_fix_disabled($elements[$key]);
}
}
if (!isset($elements['#attributes'])) {
$elements['#attributes'] = array();
}
$elements['#attributes']['disabled'] = 'disabled';
}
?>
Explanation:
Setting the #disabled attribute of the element in form_alter doesn't work because the FAPI process handler of the CCK field won't transfer the #disabled attribute to its children elements. So we need to find a different method...
We can do this using our own #after_build handler, but here we cannot simple set the $element['#disabled'] attribute of the element. The reason is this attribute is transformed into $element['#attributes']['disabled'] by _form_builder_handle_input_element executes(), which is the format FAPI theme functions know about. However, _form_builder_handle_input_element executes() is executed before #after_build handlers are invoked, so our own handler needs to set the value as the theme functions expect. See form_builder().
Finally, we need to use a recursive function so that we can set the disabled attribute of all the FAPI elements that depend on the CCK field we're interested in. Think for example about a checkboxes element, etc.
ЗЫ. Поможите с переводом. Я как собака, понимаю, о чем написано, а по-русски сказать не могу.
Комментарии
Спасибо, интересный сниппет.
Пишут, что установка атрибута #disabled элементу формы в хуке form_alter не срабатывает, потому что это свойство не передается детям этого элемента.
Поэтому делается добавление еще одного обработчика в массив #after_build, но внутри него уже не $element['#disabled'] присутствует, а это свойство заносится в массив атрибутов элемента $element['#attributes']['disabled'], который впоследствии обрабатывается в темизационной функции. Такое преобразование происходит в функции _form_builder_handle_input_element executes(), которая вызывается раньше, чем обработчики, назначенные в #after_build.
Ну и для назначения свойства 'disabled' всем детям указанного элемента нужно рекурсивно пробежаться по ним, что и делается в функции _mysnippet_fix_disabled().
Спасибо за то что ты был и надеюсь есть!