Сниппет: Как установить атрибут disabled полю CCK

Главные вкладки

Аватар пользователя beerman beerman 1 марта 2009 в 6:19

В очередной раз перекапывая 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.

ЗЫ. Поможите с переводом. Я как собака, понимаю, о чем написано, а по-русски сказать не могу.

Комментарии

Аватар пользователя gorr gorr 1 марта 2009 в 9:34

Спасибо, интересный сниппет.
Пишут, что установка атрибута #disabled элементу формы в хуке form_alter не срабатывает, потому что это свойство не передается детям этого элемента.
Поэтому делается добавление еще одного обработчика в массив #after_build, но внутри него уже не $element['#disabled'] присутствует, а это свойство заносится в массив атрибутов элемента $element['#attributes']['disabled'], который впоследствии обрабатывается в темизационной функции. Такое преобразование происходит в функции _form_builder_handle_input_element executes(), которая вызывается раньше, чем обработчики, назначенные в #after_build.
Ну и для назначения свойства 'disabled' всем детям указанного элемента нужно рекурсивно пробежаться по ним, что и делается в функции _mysnippet_fix_disabled().