diff --git a/core/includes/form.inc b/core/includes/form.inc index 3ebaca1..610c62e 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -2737,26 +2737,22 @@ function form_process_select($element) { } /** - * Returns HTML for a select form element. + * Prepares variables for select element templates. * - * It is possible to group options together; to do this, change the format of - * $options to an associative array in which the keys are group labels, and the - * values are associative arrays in the normal $options format. + * Default template: select.html.twig, * * @param $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #title, #value, #options, #description, #extra, * #multiple, #required, #name, #attributes, #size. - * - * @ingroup themeable */ -function theme_select($variables) { +function template_preprocess_select(&$variables) { $element = $variables['element']; element_set_attributes($element, array('id', 'name', 'size')); _form_set_attributes($element, array('form-select')); - - return '' . form_select_options($element) . ''; + $variables['options'] = form_select_options($element); + $variables['attributes'] = new Attribute($element['#attributes']); } /** @@ -2858,94 +2854,80 @@ function form_get_options($element, $key) { } /** - * Returns HTML for a fieldset form element and its children. + * Prepares variables for fieldset templates. + * + * Default template: fieldset.html.twig. * * @param $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * Properties used: #attributes, #children, #collapsed, #description, #id, - * #title, #value. - * - * @ingroup themeable + * Properties used: #attributes, #id, #title, #description, #children, + * #value. */ -function theme_fieldset($variables) { +function template_preprocess_fieldset(&$variables) { $element = $variables['element']; element_set_attributes($element, array('id')); _form_set_attributes($element, array('form-wrapper')); - if (!empty($element['#description'])) { - $description_id = $element['#attributes']['id'] . '--description'; - $element['#attributes']['aria-describedby'] = $description_id; - } - - $legend_attributes = array(); - if (isset($element['#title_display']) && $element['#title_display'] == 'invisible') { - $legend_attributes['class'][] = 'element-invisible'; - } + $variables['attributes'] = new Attribute($element['#attributes']); - $output = ''; if (!empty($element['#title'])) { - // Always wrap fieldset legends in a SPAN for CSS positioning. - $output .= '' . $element['#title'] . ''; + $variables['title'] = $element['#title']; + $variables['title_attributes'] = new Attribute(array()); + if (isset($element['#title_display']) && $element['#title_display'] == 'invisible') { + $variables['title_attributes']['class'] = array('element-invisible'); + } } - $output .= '
'; - if (!empty($element['#description'])) { - $attributes = array('class' => 'fieldset-description', 'id' => $description_id); - $output .= '' . $element['#description'] . '
'; + if (!empty($element['#description'])) { + $variables['description'] = $element['#description']; + $description_id = $element['#attributes']['id'] . '--description'; + $variables['description_attributes'] = new Attribute(array( + 'id' => $description_id, + 'class' => array('fieldset-description'), + 'aria-describedby' => $description_id, + )); } - $output .= $element['#children']; - if (isset($element['#value'])) { - $output .= $element['#value']; - } - $output .= ''; - $output .= "\n"; - return $output; + + $variables['children'] = $element['#children']; + $variables['value'] = (isset($element['#value'])) ? $element['#value'] : NULL; } /** - * Returns HTML for a details form element and its children. + * Prepares variables for details element templates. + * + * Default template: details.html.twig. * * @param $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * Properties used: #attributes, #children, #collapsed, #description, #id, - * #title, #value. + * Properties used: #attributes, #children, #collapsed, #collapsible, + * #description, #id, #title, #value. * * @ingroup themeable */ -function theme_details($variables) { +function template_preprocess_details(&$variables) { $element = $variables['element']; - element_set_attributes($element, array('id')); - _form_set_attributes($element, array('form-wrapper')); - $output = ''; + $variables['attributes'] = new Attribute($element['#attributes']); + $variables['summary_attributes'] = new Attribute(array()); if (!empty($element['#title'])) { - $summary_attributes = new Attribute(array( - 'role' => 'button', - )); + $variables['summary_attributes']['role'] = 'button'; if (!empty($element['#attributes']['id'])) { - $summary_attributes['aria-controls'] = $element['#attributes']['id']; + $variables['summary_attributes']['aria-controls'] = $element['#attributes']['id']; } - $summary_attributes['aria-expanded'] = empty($element['#attributes']['open']) ? FALSE : TRUE; - $summary_attributes['aria-pressed'] = $summary_attributes['aria-expanded']; - $output .= '' . $element['#title'] . ''; - } - $output .= '
'; - if (!empty($element['#description'])) { - $output .= '
' . $element['#description'] . '
'; - } - $output .= $element['#children']; - if (isset($element['#value'])) { - $output .= $element['#value']; + $variables['summary_attributes']['aria-expanded'] = empty($element['#attributes']['open']) ? FALSE : TRUE; + $variables['summary_attributes']['aria-pressed'] = $variables['summary_attributes']['aria-expanded']; } - $output .= '
'; - $output .= "\n"; - return $output; + + $variables['title'] = !empty($element['#title']) ? $element['#title'] : NULL; + $variables['description'] = !empty($element['#description']) ? $element['#description'] : NULL; + $variables['children'] = isset($element['#children']) ? $element['#children'] : NULL; + $variables['value'] = isset($element['#value']) ? $element['#value'] : NULL; } /** - * Prepares a #type 'radio' render element for theme_input(). + * Prepares a 'radio' #type render element for #theme 'input'. * * @param array $element * An associative array containing the properties of the element. @@ -2972,34 +2954,32 @@ function form_pre_render_radio($element) { } /** - * Returns HTML for a set of radio button form elements. + * Prepares variables for radios templates. + * + * Default template: radios.html.twig. * * @param $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * Properties used: #title, #value, #options, #description, #required, - * #attributes, #children. - * - * @ingroup themeable + * Properties used: #attributes, #id, #children. */ -function theme_radios($variables) { +function template_preprocess_radios(&$variables) { $element = $variables['element']; - $attributes = array(); + $variables['attributes'] = new Attribute(array()); if (isset($element['#id'])) { - $attributes['id'] = $element['#id']; - } - $attributes['class'] = 'form-radios'; - if (!empty($element['#attributes']['class'])) { - $attributes['class'] .= ' ' . implode(' ', $element['#attributes']['class']); + $variables['attributes']['id'] = $element['#id']; } + $variables['attributes']['class'] = (!empty($element['#attributes']['class'])) ? $element['#attributes']['class'] : array(); + $variables['attributes']['class'][] = 'form-radios'; if (isset($element['#attributes']['title'])) { - $attributes['title'] = $element['#attributes']['title']; + $variables['attributes']['title'] = $element['#attributes']['title']; } - return '' . (!empty($element['#children']) ? $element['#children'] : '') . ''; + + $variables['children'] = !empty($element['#children']) ? $element['#children'] : ''; } /** - * Expand a password_confirm field into two text boxes. + * Expands a password_confirm field into two text boxes. */ function form_process_password_confirm($element) { $element['pass1'] = array( @@ -3052,29 +3032,30 @@ function password_confirm_validate($element, &$element_state) { } /** - * Returns HTML for an #date form element. - * + * Prepares a #type 'date' render element for theme('input'). + *` * Supports HTML5 types of 'date', 'datetime', 'datetime-local', and 'time'. * Falls back to a plain textfield. Used as a sub-element by the datetime * element type. * - * @param array $variables - * An associative array containing: - * - element: An associative array containing the properties of the element. - * Properties used: #title, #value, #options, #description, #required, - * #attributes, #id, #name, #type, #min, #max, #step, #value, #size. + * @param array $element + * An associative array containing the properties of the element. + * Properties used: #title, #value, #options, #description, #required, + * #attributes, #id, #name, #type, #min, #max, #step, #value, #size. * - * @ingroup themeable + * Note: The input "name" attribute needs to be sanitized before output, which + * is currently done by initializing Drupal\Core\Template\Attribute with + * all the attributes. + * + * @return array + * The $element with prepared variables ready for theme_input(). */ -function theme_date($variables) { - $element = $variables['element']; - if (empty($element['attribute']['type'])) { - $element['attribute']['type'] = 'date'; - } - element_set_attributes($element, array('id', 'name', 'type', 'min', 'max', 'step', 'value', 'size')); - _form_set_attributes($element, array('form-' . $element['attribute']['type'])); +function form_pre_render_date($element) { + $element['#attributes']['type'] = 'date'; + element_set_attributes($element, array('id', 'name', 'min', 'max', 'step', 'value', 'size')); + _form_set_attributes($element, array('form-date')); - return ''; + return $element; } /** @@ -3150,7 +3131,7 @@ function form_pre_render_checkbox($element) { } /** - * Returns HTML for a set of checkbox form elements. + * Preprocesses variables for a set of checkbox form elements. * * @param $variables * An associative array containing: @@ -3159,20 +3140,28 @@ function form_pre_render_checkbox($element) { * * @ingroup themeable */ -function theme_checkboxes($variables) { +function template_preprocess_checkboxes(&$variables) { $element = $variables['element']; - $attributes = array(); + if (isset($element['#id'])) { - $attributes['id'] = $element['#id']; + $variables['attributes']['id'] = $element['#id']; } - $attributes['class'][] = 'form-checkboxes'; + $variables['attributes']['class'] = array(); + $variables['attributes']['class'][] = 'form-checkboxes'; if (!empty($element['#attributes']['class'])) { - $attributes['class'] = array_merge($attributes['class'], $element['#attributes']['class']); + if (is_array($element['#attributes']['class'])) { + foreach ($element['#attributes']['class'] as $class) { + $variables['attributes']['class'][] = $class; + } + } + else { + $variables['attributes']['class'][] = $element['#attributes']['class']; + } } if (isset($element['#attributes']['title'])) { - $attributes['title'] = $element['#attributes']['title']; + $variables['attributes']['title'] = $element['#attributes']['title']; } - return '' . (!empty($element['#children']) ? $element['#children'] : '') . ''; + $variables['children'] = !empty($element['#children']) ? $element['#children'] : ''; } /** @@ -3410,11 +3399,9 @@ function form_process_container($element, &$form_state) { } /** - * Returns HTML to wrap child elements in a container. + * Prepares variables for container templates. * - * Used for grouped form items. Can also be used as a #theme_wrapper for any - * renderable element, to surround it with a
and add attributes such as - * classes or an HTML id. + * Default template: container.html.twig. * * @param $variables * An associative array containing: @@ -3423,7 +3410,7 @@ function form_process_container($element, &$form_state) { * * @ingroup themeable */ -function theme_container($variables) { +function template_preprocess_container(&$variables) { $element = $variables['element']; // Special handling for form elements. @@ -3436,11 +3423,12 @@ function theme_container($variables) { $element['#attributes']['class'][] = 'form-wrapper'; } - return '' . $element['#children'] . '
'; + $variables['children'] = $element['#children']; + $variables['attributes'] = new Attribute($element['#attributes']); } /** - * Returns HTML for a table with radio buttons or checkboxes. + * Prepares variables for a table with radio buttons or checkboxes. * * @param $variables * An associative array containing: @@ -3478,11 +3466,8 @@ function theme_container($variables) { * '#empty' => t('No content available.'), * ); * @endcode - * - * @ingroup themeable */ -function theme_tableselect($variables) { - $element = $variables['element']; +function form_pre_render_tableselect(array $element) { $rows = array(); $header = $element['#header']; if (!empty($element['#options'])) { @@ -3522,7 +3507,7 @@ function theme_tableselect($variables) { // checkboxes/radios in the first table column. if ($element['#js_select']) { // Add a "Select all" checkbox. - drupal_add_library('system', 'drupal.tableselect'); + $element['#attached']['library'][] = array('system', 'drupal.tableselect'); array_unshift($header, array('class' => array('select-all'))); } else { @@ -3531,7 +3516,11 @@ function theme_tableselect($variables) { array_unshift($header, ''); } } - return theme('table', array('header' => $header, 'rows' => $rows, 'empty' => $element['#empty'], 'attributes' => $element['#attributes'])); + // This is all we really change. + $element['#header'] = $header; + $element['#rows'] = $rows; + + return $element; } /** @@ -3922,11 +3911,13 @@ function form_process_group(&$element, &$form_state) { * The modified element. */ function form_pre_render_details($element) { - // The .form-wrapper class is required for #states to treat details like - // containers. + element_set_attributes($element, array('id')); if (!isset($element['#attributes']['class'])) { $element['#attributes']['class'] = array(); } + // The .form-wrapper class is required for #states to treat details like + // containers. + _form_set_attributes($element, array('form-wrapper')); // Collapsible details. $element['#attached']['library'][] = array('system', 'drupal.collapse'); @@ -4060,18 +4051,17 @@ function form_pre_render_vertical_tabs($element) { } /** - * Returns HTML for an element's children details as vertical tabs. + * Preapres an element's children details for vertical tabs templates. + * + * Default template: vertical-tabs.html.twig. * * @param $variables * An associative array containing: * - element: An associative array containing the properties and children of * the details element. Properties used: #children. - * - * @ingroup themeable */ -function theme_vertical_tabs($variables) { - $element = $variables['element']; - return '
' . $element['#children'] . '
'; +function template_preprocess_vertical_tabs(&$variables) { + $variables['children'] = $variables['element']['#children']; } /** @@ -4113,33 +4103,17 @@ function form_process_autocomplete($element, &$form_state) { } /** - * Preprocesses variables for theme_input(). - * - * @param array $variables - * An associative array containing: - * - element: An associative array containing the properties of the element. + * Prepares variables for input templates. * - * @ingroup themeable - */ -function template_preprocess_input(&$variables) { - $element = $variables['element']; - $variables['attributes'] = new Attribute($element['#attributes']); -} - -/** - * Returns HTML for an input form element. + * Default template: input.html.twig. * * @param array $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * Properties used: #attributes. - * - * @ingroup themeable */ -function theme_input($variables) { - $element = $variables['element']; - $attributes = $variables['attributes']; - return '' . drupal_render_children($element); +function template_preprocess_input(&$variables) { + $variables['attributes'] = new Attribute($variables['element']['#attributes']); + $variables['children'] = drupal_render_children($variables['element']); } /** @@ -4499,7 +4473,9 @@ function form_pre_render_color($element) { } /** - * Returns HTML for a form. + * Prepares variables for form templates. + * + * Default template: form.html.twig. * * @param $variables * An associative array containing: @@ -4508,48 +4484,40 @@ function form_pre_render_color($element) { * * @ingroup themeable */ -function theme_form($variables) { +function template_preprocess_form(&$variables) { $element = $variables['element']; + element_set_attributes($element, array('method', 'id')); if (isset($element['#action'])) { $element['#attributes']['action'] = drupal_strip_dangerous_protocols($element['#action']); } - element_set_attributes($element, array('method', 'id')); if (empty($element['#attributes']['accept-charset'])) { $element['#attributes']['accept-charset'] = "UTF-8"; } - // Anonymous DIV to satisfy XHTML compliance. - return '
' . $element['#children'] . '
'; + $variables['attributes'] = new Attribute($element['#attributes']); + $variables['children'] = $element['#children']; } /** - * Returns HTML for a textarea form element. + * Prepares variables for textarea form element templates. + * + * Default template: textarea.html.twig. * * @param $variables * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #title, #value, #description, #rows, #cols, * #placeholder, #required, #attributes, #resizable - * - * @ingroup themeable */ -function theme_textarea($variables) { +function template_preprocess_textarea(&$variables) { $element = $variables['element']; element_set_attributes($element, array('id', 'name', 'rows', 'cols', 'placeholder')); _form_set_attributes($element, array('form-textarea')); - - $wrapper_attributes = array( - 'class' => array('form-textarea-wrapper'), - ); - - // Add resizable behavior. if (!empty($element['#resizable'])) { $element['#attributes']['class'][] = 'resize-' . $element['#resizable']; } - $output = ''; - $output .= '' . check_plain($element['#value']) . ''; - $output .= ''; - return $output; + $variables['attributes'] = new Attribute($element['#attributes']); + $variables['value'] = check_plain($element['#value']); } /** @@ -4621,7 +4589,9 @@ function form_pre_render_file($element) { } /** - * Returns HTML for a form element. + * Prepares variables for form element templates. + * + * Default template: form-element.html.twig. * * Each form element is wrapped in a DIV container having the following CSS * classes: @@ -4663,102 +4633,77 @@ function form_pre_render_file($element) { * - element: An associative array containing the properties of the element. * Properties used: #title, #title_display, #description, #id, #required, * #children, #type, #name. - * - * @ingroup themeable */ -function theme_form_element($variables) { - $element = &$variables['element']; +function template_preprocess_form_element(&$variables) { + $element = $variables['element']; // This function is invoked as theme wrapper, but the rendered form element // may not necessarily have been processed by form_builder(). $element += array( '#title_display' => 'before', ); - + // If #title is not set, we don't display any label or required marker. + if (!isset($element['#title'])) { + $element['#title_display'] = 'none'; + } + // We call it a label, though. + $variables['label_display'] = $element['#title_display']; + // Label returns empty tring in some cases. + $variables['label'] = theme('form_element_label', $variables); // Take over any #wrapper_attributes defined by the element. // @todo Temporary hack for #type 'item'. // @see http://drupal.org/node/1829202 - if (isset($element['#wrapper_attributes'])) { - $attributes = $element['#wrapper_attributes']; - } - // Add element #id for #type 'item'. - if (isset($element['#markup']) && !empty($element['#id'])) { - $attributes['id'] = $element['#id']; - } + $variables['wrapper_attributes'] = new Attribute((isset($element['#wrapper_attributes'])) ? $element['#wrapper_attributes'] : array('class' => array())); // Add element's #type and #name as class to aid with JS/CSS selectors. - $attributes['class'][] = 'form-item'; + $variables['wrapper_attributes']['class'][] = 'form-item'; if (!empty($element['#type'])) { - $attributes['class'][] = 'form-type-' . strtr($element['#type'], '_', '-'); + $variables['wrapper_attributes']['class'][] = 'form-type-' . strtr($element['#type'], '_', '-'); } if (!empty($element['#name'])) { - $attributes['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => '')); + $variables['wrapper_attributes']['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => '')); } // Add a class for disabled elements to facilitate cross-browser styling. if (!empty($element['#attributes']['disabled'])) { - $attributes['class'][] = 'form-disabled'; - } - $output = '' . "\n"; - - // If #title is not set, we don't display any label or required marker. - if (!isset($element['#title'])) { - $element['#title_display'] = 'none'; + $variables['wrapper_attributes']['class'][] = 'form-disabled'; } - $prefix = isset($element['#field_prefix']) ? '' . $element['#field_prefix'] . ' ' : ''; - $suffix = isset($element['#field_suffix']) ? ' ' . $element['#field_suffix'] . '' : ''; - - switch ($element['#title_display']) { - case 'before': - case 'invisible': - $output .= ' ' . theme('form_element_label', $variables); - $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n"; - break; - - case 'after': - $output .= ' ' . $prefix . $element['#children'] . $suffix; - $output .= ' ' . theme('form_element_label', $variables) . "\n"; - break; - - case 'none': - case 'attribute': - // Output no label and no required marker, only the children. - $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n"; - break; - } - - if (!empty($element['#description'])) { - $attributes = array('class' => 'description'); + // Add element #id for #type 'item'. + if (isset($element['#markup']) && !empty($element['#id'])) { + $variables['wrapper_attributes']['id'] = $element['#id']; + } + $variables['prefix'] = isset($element['#field_prefix']) ? $element['#field_prefix'] : NULL; + $variables['suffix'] = isset($element['#field_suffix']) ? $element['#field_suffix'] : NULL; + $variables['children'] = isset($element['#children']) ? $element['#children'] : NULL; + $variables['description'] = !empty($element['#description']) ? $element['#description'] : NULL; + if ($variables['description']) { + $variables['description_attributes'] = new Attribute(array('class' => 'description')); if (!empty($element['#id'])) { - $attributes['id'] = $element['#id'] . '--description'; + $variables['description_attributes']['id'] = $element['#id'] . '--description'; } - $output .= '' . $element['#description'] . "\n"; } - - $output .= "\n"; - - return $output; } /** - * Returns HTML for a marker for required form elements. + * Prepares variables for form element required marker templates. + * + * Default template: form-element-required.html.twig. * * @param $variables * An associative array containing: * - element: An associative array containing the properties of the element. - * - * @ingroup themeable */ -function theme_form_required_marker($variables) { +function template_preprocess_form_required_marker(&$variables) { // This is also used in the installer, pre-database setup. $t = get_t(); - $attributes = array( + $variables['attributes'] = new Attribute(array( 'class' => 'form-required', 'title' => $t('This field is required.'), - ); - return '*'; + )); } /** - * Returns HTML for a form element label and required marker. + * Prepares variables for form element label templates. + * + * Default template: form-label.html.twig. * * Form element labels include the #title and a #required marker. The label is * associated with the element itself by the element #id. Labels may appear @@ -4777,39 +4722,40 @@ function theme_form_required_marker($variables) { * An associative array containing: * - element: An associative array containing the properties of the element. * Properties used: #required, #title, #id, #value, #description. - * - * @ingroup themeable */ -function theme_form_element_label($variables) { +function template_preprocess_form_element_label(&$variables) { $element = $variables['element']; // This is also used in the installer, pre-database setup. $t = get_t(); - // If title and required marker are both empty, output no label. - if ((!isset($element['#title']) || $element['#title'] === '') && empty($element['#required'])) { - return ''; - } - - // If the element is required, a required marker is appended to the label. - $required = !empty($element['#required']) ? theme('form_required_marker', array('element' => $element)) : ''; - - $title = filter_xss_admin($element['#title']); - - $attributes = array(); - // Style the label as class option to display inline with the element. - if ($element['#title_display'] == 'after') { - $attributes['class'] = 'option'; - } - // Show label only to screen readers to avoid disruption in visual flows. - elseif ($element['#title_display'] == 'invisible') { - $attributes['class'] = 'element-invisible'; + // If title and required marker are both empty, prepare no label. + if (empty($element['#required']) && (!isset($element['#title']) || $element['#title'] === '')) { + $variables['label'] = FALSE; + $variables['required'] = FALSE; + return; } - - if (!empty($element['#id'])) { - $attributes['for'] = $element['#id']; + else { + // If the element is required, a required marker is appended to the label. + $variables['label'] = (isset($element['#title'])) ? $t(filter_xss_admin($element['#title'])) : NULL; + $variables['required'] = (!empty($element['#required'])) ? array('#theme' => 'form_required_marker', '#element' => $element) : ''; + $variables['attributes'] = new Attribute(array('class' => array())); + // Associate the label with the field it is for. + if (!empty($element['#id'])) { + $variables['attributes']['for'] = $element['#id']; + } + // Add label positioning classes. + if (!empty($element['#title_display'])) { + // Style the label as class 'option' to display inline with the element. + // @todo: Use a more semantic class name like 'layout-inline-after'? + if ($element['#title_display'] == 'after') { + $variables['attributes']['class'][] = 'option'; + } + // Show label only to screen readers to avoid disruption in visual flows. + elseif ($element['#title_display'] == 'invisible') { + $variables['attributes']['class'][] = 'element-invisible'; + } + } } - - return '' . $t('!title!required', array('!title' => $title, '!required' => $required)) . ''; } /** diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc index d2e461e..05c9f69 100644 --- a/core/includes/install.core.inc +++ b/core/includes/install.core.inc @@ -7,6 +7,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -374,6 +375,31 @@ function install_begin_request(&$install_state) { )) ->addMethodCall('setUserAgent', array('Drupal (+http://drupal.org/)')); + // Register the Twig theme engine. + $container->register('twig.loader.filesystem', 'Twig_Loader_Filesystem') + ->addArgument(DRUPAL_ROOT); + $container->register('twig', 'Drupal\Core\Template\TwigEnvironment') + ->addArgument(new Reference('twig.loader.filesystem')) + ->addArgument(array( + // Twig templates are saved / loaded via drupal_php_storage(). + // All files can be refreshed by clearing caches. + // @todo ensure garbage collection of expired files. + 'cache' => TRUE, + 'base_template_class' => 'Drupal\Core\Template\TwigTemplate', + // @todo Implement Twig autoescape. + // @see http://drupal.org/node/1712444. + 'autoescape' => FALSE, + // @todo Decide on strict variables option. + // @see http://drupal.org/node/1806538. + 'strict_variables' => FALSE, + 'debug' => FALSE, + 'auto_reload' => FALSE, + )) + ->addMethodCall('addExtension', array(new Definition('Drupal\Core\Template\TwigExtension'))) + // @todo Figure out what to do about debugging functions. + // @see http://drupal.org/node/1804998 + ->addMethodCall('addExtension', array(new Definition('Twig_Extension_Debug'))); + Drupal::setContainer($container); } diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 1ed2caa..2d18766 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -3271,51 +3271,58 @@ function drupal_common_theme() { // From form.inc. 'input' => array( 'render element' => 'element', + 'template' => 'input', ), 'select' => array( 'render element' => 'element', + 'template' => 'select', ), 'fieldset' => array( 'render element' => 'element', + 'template' => 'fieldset', ), 'details' => array( 'render element' => 'element', + 'template' => 'details', ), 'radios' => array( 'render element' => 'element', - ), - 'date' => array( - 'render element' => 'element', + 'template' => 'radios', ), 'exposed_filters' => array( 'render element' => 'form', ), 'checkboxes' => array( 'render element' => 'element', + 'template' => 'checkboxes', ), 'form' => array( 'render element' => 'element', + 'template' => 'form', ), 'textarea' => array( 'render element' => 'element', - ), - 'tableselect' => array( - 'render element' => 'element', + 'template' => 'textarea', ), 'form_element' => array( 'render element' => 'element', + 'template' => 'form-element', ), 'form_required_marker' => array( 'render element' => 'element', + 'template' => 'form-required-marker', ), 'form_element_label' => array( 'render element' => 'element', + 'template' => 'form-element-label', ), 'vertical_tabs' => array( 'render element' => 'element', + 'template' => 'vertical-tabs', ), 'container' => array( 'render element' => 'element', + 'template' => 'container', ), ); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php index 07591f5..2a727fb 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Form/FormTest.php @@ -94,7 +94,7 @@ function testRequiredFields() { $elements['file']['empty_values'] = $empty_strings; // Regular expression to find the expected marker on required elements. - $required_marker_preg = '@\*@'; + $required_marker_preg = '@\*\s*?@'; // Go through all the elements and all the empty values for them. foreach ($elements as $type => $data) { diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 2c51ae0..e6e7bc7 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -299,7 +299,7 @@ function system_element_info() { '#limit_validation_errors' => FALSE, '#process' => array('form_process_button', 'ajax_process_form'), '#pre_render' => array('form_pre_render_button'), - '#theme_wrappers' => array('input__submit'), + '#theme' => 'input__submit', ); $types['button'] = array( '#input' => TRUE, @@ -309,7 +309,7 @@ function system_element_info() { '#limit_validation_errors' => FALSE, '#process' => array('form_process_button', 'ajax_process_form'), '#pre_render' => array('form_pre_render_button'), - '#theme_wrappers' => array('input__button'), + '#theme' => 'input__button', ); $types['image_button'] = array( '#input' => TRUE, @@ -321,7 +321,7 @@ function system_element_info() { '#has_garbage_value' => TRUE, '#src' => NULL, '#pre_render' => array('form_pre_render_image_button'), - '#theme_wrappers' => array('input__image_button'), + '#theme' => 'input__image_button', ); $types['textfield'] = array( '#input' => TRUE, @@ -490,7 +490,8 @@ function system_element_info() { ); $types['date'] = array( '#input' => TRUE, - '#theme' => 'date', + '#theme' => 'input__date', + '#pre_render' => array('form_pre_render_date'), '#theme_wrappers' => array('form_element'), ); $types['file'] = array( @@ -504,10 +505,11 @@ function system_element_info() { '#input' => TRUE, '#js_select' => TRUE, '#multiple' => TRUE, + '#pre_render' => array('form_pre_render_tableselect'), '#process' => array('form_process_tableselect'), '#options' => array(), '#empty' => '', - '#theme' => 'tableselect', + '#theme' => 'table__tableselect', ); // Form structure. diff --git a/core/modules/system/templates/checkboxes.html.twig b/core/modules/system/templates/checkboxes.html.twig new file mode 100644 index 0000000..eda7291 --- /dev/null +++ b/core/modules/system/templates/checkboxes.html.twig @@ -0,0 +1,18 @@ +{# +/** + * @file + * Default theme implementation for a 'checkboxes' #type form element. + * + * Available variables + * - attributes: HTML attributes for the checkboxes wrapper element. + * - children: HTML markup for the child checkboxes. + * + * @see template_preprocess() + * @see template_preprocess_checkboxes() + * + * @ingroup themeable + */ + @todo: remove this file once http://drupal.org/node/1819284 is resolved. + This is identical to core/themes/stark/templates/form.inc/container.html.twig +#} +{{ children }} diff --git a/core/modules/system/templates/container.html.twig b/core/modules/system/templates/container.html.twig new file mode 100644 index 0000000..9d4446e --- /dev/null +++ b/core/modules/system/templates/container.html.twig @@ -0,0 +1,16 @@ +{# +/** + * @file + * Default theme implementation of a container used to wrap child elements. + * + * Available variables: + * - attributes: Remaining html attributes for the containing element. + * - children: The rendered child elements of the container. + * + * @see template_preprocess() + * @see template_preprocess_container() + * + * @ingroup themeable + */ +#} +{{ children }} diff --git a/core/modules/system/templates/datetime.html.twig b/core/modules/system/templates/datetime.html.twig index 5ea386e..f811f56 100644 --- a/core/modules/system/templates/datetime.html.twig +++ b/core/modules/system/templates/datetime.html.twig @@ -1,6 +1,7 @@ {# /** - * Returns HTML for a date / time. + * @file + * Default theme implementation for a date / time element. * * Available variables * - timestamp: (optional) A UNIX timestamp for the datetime attribute. If the @@ -25,4 +26,4 @@ */ #} {# @todo Revisit once http://drupal.org/node/1825952 is resolved. #} - + diff --git a/core/modules/system/templates/details.html.twig b/core/modules/system/templates/details.html.twig new file mode 100644 index 0000000..2aa10b8 --- /dev/null +++ b/core/modules/system/templates/details.html.twig @@ -0,0 +1,34 @@ +{# +/** + * @file + * Default theme implementation for a details element. + * + * Available variables + * - attributes: An array of HTML attributes for the details element. + * - title: The title of the element, or NULL if not set. + * - description: The description of the element, or NULL if not set. + * - children: The children of the element, or NULL if not set. + * - value: The value of the element, or NULL if not set. + * + * @see template_preprocess() + * @see template_preprocess_details() + * + * @ingroup themeable + */ +#} + + {% if title %} + {{ title }} + {% endif %} +
+ {% if description %} +
{{ description }}
+ {% endif %} + {% if children %} + {{ children }} + {% endif %} + {% if value %} + {{ value }} + {% endif %} +
+ diff --git a/core/modules/system/templates/fieldset.html.twig b/core/modules/system/templates/fieldset.html.twig new file mode 100644 index 0000000..0a3f895 --- /dev/null +++ b/core/modules/system/templates/fieldset.html.twig @@ -0,0 +1,36 @@ +{# +/** + * @file + * Default theme implementation for a fieldset element and its children. + * + * Available variables: + * - attributes: An array of HTML attributes for the fieldset element. + * - title: Title of the fieldset, intended for use as the text of the legend. + * - title_attributes: An array of HTML attributes to apply to the legend. + * - description: The description of the fieldset. + * - description_attributes: An array of HTML attributes to apply to the + * description container. + * - children: The rendered child elements of the fieldset. + * - value: The value of the fieldset. + * + * @see template_preprocess() + * @see template_preprocess_fieldset() + * + * @ingroup themeable + */ +#} + + {% if title is defined %} + {# Always wrap fieldset legends in a SPAN for CSS positioning. #} + {{ title }} + {% endif %} +
+ {% if description is defined %} + {{ description }}
+ {% endif %} + {{ children }} + {% if value %} + {{ value }} + {% endif %} + + diff --git a/core/modules/system/templates/form-element-label.html.twig b/core/modules/system/templates/form-element-label.html.twig new file mode 100644 index 0000000..9acee29 --- /dev/null +++ b/core/modules/system/templates/form-element-label.html.twig @@ -0,0 +1,29 @@ +{# +/** + * @file + * Default theme implementation for a form element label. + * + * Available variables: + * - label: The text of the label, or FALSE if there is no title and the element + * is not required. + * - required: A rendered marker indicating the field is required, or + * an empty string if the field is not required. + * - attributes: An array of HTML attributes to apply to the label. + * + * @see template_preprocess() + * @see template_preprocess_form_label() + * @see form-required-marker.html.twig + * + * @ingroup themeable + */ +#} +{% if (label is not empty) or (required is not empty) %} + + {%- if label is not empty -%} + {{ label }} + {%- endif -%} + {%- if required is not empty -%} + {{ required }} + {%- endif -%} + +{% endif %} diff --git a/core/modules/system/templates/form-element.html.twig b/core/modules/system/templates/form-element.html.twig new file mode 100644 index 0000000..bb07a5e --- /dev/null +++ b/core/modules/system/templates/form-element.html.twig @@ -0,0 +1,58 @@ +{# +/** + * @file + * Default theme implementation for a form element. + * + * Available variables: + * - wrapper_attributes: An array of HTML attributes to apply to the wrapper. + * - prefix: The form element prefix, or NULL. + * - suffix: The form element suffix, or NULL. + * - label: The rendered label. @see form-element-label.html.twig. + * - label_display: Label display setting. It can have these values: + * - before: The label is output before the element. This is the default. The + * label includes the #title and the required marker, if #required. + * - after: The label is output after the element. For example, this is used + * for radio and checkbox #type elements as set in system_element_info(). + * If the #title is empty but the field is #required, the label will + * contain only the required marker. + * - invisible: Labels are critical for screen readers to enable them to + * properly navigate through forms but can be visually distracting. This + * property hides the label for everyone except screen readers. + * - attribute: Set the title attribute on the element to create a tooltip + * but output no label element. This is supported only for checkboxes and + * radios in form_pre_render_conditional_form_element(). It is used where + * a visual label is not needed, such as a table of checkboxes where the + * row and column provide the context. The tooltip will include the title + * and required marker. + * - description: A description of the form element, or NULL if not set. + * - description_attributes: An array of HTML attributes to apply to the wrapper + * of the description. Will only be set when description is not NULL. + * + * @see template_preprocess() + * @see template_preprocess_form_element() + * + * @ingroup themeable + */ +#} + + {% if (label is not empty) and (label_display in ['before', 'invisible']) %} + {{ label }} + {% endif %} + {% if prefix is not empty %} + {{ prefix }} + {% endif %} + {% if children is not empty %} + {{ children }} + {% endif %} + {% if suffix is not empty %} + {{ suffix }} + {% endif %} + {% if (label is not empty) and (label_display == 'after') %} + {{ label }} + {% endif %} + {% if description is not empty %} + + {{ description }} + + {% endif %} + diff --git a/core/modules/system/templates/form-required-marker.html.twig b/core/modules/system/templates/form-required-marker.html.twig new file mode 100644 index 0000000..2c26446 --- /dev/null +++ b/core/modules/system/templates/form-required-marker.html.twig @@ -0,0 +1,15 @@ +{# +/** + * @file + * Default theme implementation for a form element required marker. + * + * Available variables: + * - attributes: An array of HTML attributes for the label. + * + * @see template_preprocess() + * @see template_preprocess_form_required_marker() + * + * @ingroup themeable + */ +#} +* diff --git a/core/modules/system/templates/form.html.twig b/core/modules/system/templates/form.html.twig new file mode 100644 index 0000000..71fb632 --- /dev/null +++ b/core/modules/system/templates/form.html.twig @@ -0,0 +1,19 @@ +{# +/** + * @file + * Default theme implementation for a form. + * + * Available variables: + * - attributes: An array of HTML attributes for the form element. + * - children: Rendered child form elements. + * + * @see template_preprocess() + * @see template_preprocess_form() + * + * @ingroup themeable + */ + @todo: remove the inner div once http://drupal.org/node/1822210 is resolved. +#} + +
{{ children }}
+ diff --git a/core/modules/system/templates/input.html.twig b/core/modules/system/templates/input.html.twig new file mode 100644 index 0000000..7e3b5a8 --- /dev/null +++ b/core/modules/system/templates/input.html.twig @@ -0,0 +1,34 @@ +{# +/** + * @file + * Default theme implementation for an input element. + * + * This covers input types: + * - button + * - checkbox + * - date + * - email + * - file + * - hidden + * - image_button + * - number + * - radio + * - range + * - password + * - tel + * - textfield + * + * Available variables: + * - attributes: An array of HTML attributes for the input element. + * - children: An array of child elements. + * + * @see template_preprocess() + * @see template_preprocess_input() + * + * @ingroup themeable + */ +#} + +{% if children is not empty %} + {{ children }} +{% endif %} diff --git a/core/modules/system/templates/radios.html.twig b/core/modules/system/templates/radios.html.twig new file mode 100644 index 0000000..4e44796 --- /dev/null +++ b/core/modules/system/templates/radios.html.twig @@ -0,0 +1,18 @@ +{# +/** + * @file + * Default theme implementation for a #type 'radios' form element. + * + * Available variables: + * - attributes: An array of HTML attributes for the container element. + * - children: An array of rendered child radio elements. + * + * @see template_preprocess() + * @see template_preprocess_radios() + * + * @ingroup themeable + */ + @todo: remove this file once http://drupal.org/node/1819284 is resolved. + This is identical to core/themes/stark/templates/form.inc/container.html.twig +#} +
{{ children }}
diff --git a/core/modules/system/templates/select.html.twig b/core/modules/system/templates/select.html.twig new file mode 100644 index 0000000..e8c6920 --- /dev/null +++ b/core/modules/system/templates/select.html.twig @@ -0,0 +1,16 @@ +{# +/** + * @file + * Default theme implementation for a select element. + * + * Available variables: + * - attributes: An array of HTML attributes for the select element. + * - options: The rendered list of select options. + * + * @see template_preprocess() + * @see template_preprocess_select() + * + * @ingroup themeable + */ +#} + diff --git a/core/modules/system/templates/textarea.html.twig b/core/modules/system/templates/textarea.html.twig new file mode 100644 index 0000000..96f6aac --- /dev/null +++ b/core/modules/system/templates/textarea.html.twig @@ -0,0 +1,16 @@ +{# +/** + * @file + * Default theme implementation for a textarea element. + * + * Available variables: + * - attributes: An array of HTML attributes for the textarea element. + * - value: Plain text value of the textarea. + * + * @see template_preprocess() + * @see template_preprocess_textarea() + * + * @ingroup themeable + */ +#} +{{ value }} diff --git a/core/modules/system/templates/vertical-tabs.html.twig b/core/modules/system/templates/vertical-tabs.html.twig new file mode 100644 index 0000000..206081b --- /dev/null +++ b/core/modules/system/templates/vertical-tabs.html.twig @@ -0,0 +1,15 @@ +{# +/** + * @file + * Default theme implementation for a set of vertical tabs. + * + * Available variables + * - children: The rendered child fieldsets elements. + * + * @see template_preprocess() + * @see template_preprocess_vertical_tabs() + * + * @ingroup themeable + */ +#} +
{{ children }}