/** * Renders a page using a custom page theme hook and optional region content. * * Temporary shim to facilitate modernization progress for special front * contollers (install.php, update.php, authorize.php), maintenance mode, and * the exception handler. * * Do NOT use this method in your code. This method will be removed as soon * as architecturally possible. * * This is functionally very similar to DefaultHtmlFragmentRenderer::render() * but with the following important differences: * * - drupal_prepare_page() and hook_page_build() cannot be invoked on the * maintenance and install pages, since possibly enabled page layout/block * modules would replace the main page content with configured region * content. * - This function composes a complete page render array including a page * template theme suggestion (as opposed to the main page content only). * - The render cache and cache tags is skipped. * * @param array|string $main * A render array or string containing the main page content. * @param string $title * (optional) The page title. * @param string $theme * (optional) The theme hook to use for rendering the page. Defaults to * 'maintenance'. The given value will be appended with '_page' to compose * the #theme property for #type 'page' currently; e.g., 'maintenance' * becomes 'maintenance_page'. Ultimately this parameter will be converted * into a page template theme suggestion; i.e., 'page__$theme'. * @param array $regions * (optional) Additional region content to add to the page. The given array * is added to the page render array, so this parameter may also be used to * pass e.g. the #show_messages property for #type 'page'. * * @return string * The rendered HTML page. * * @internal */ public static function renderPage($main, $title = '', $theme = 'maintenance', array $regions = array()) { // Automatically convert the main page content into a render array. if (!is_array($main)) { $main = array('#markup' => $main); } $page = new HtmlPage('', array(), $title); $page_array = array('#type' => 'page', '#theme' => $theme . '_page', '#title' => $title, 'content' => array('system_main' => $main)); // Append region content. $page_array += $regions; // Add default properties. $page_array += element_info('page'); // hook_page_build() cannot be invoked on the maintenance and install pages, // because the application is in an unknown or special state. // In particular on the install page, invoking hook_page_build() directly // after e.g. Block module has been installed would *replace* the installer // output with the configured blocks of the installer theme (loaded from // default configuration of the installation profile). // Allow modules and themes to alter the page render array. // This allows e.g. themes to attach custom libraries. \Drupal::moduleHandler()->alter('page', $page_array); // @todo Move preparePage() before alter() above, so $page_array['#page'] is // available in hook_page_alter(), so that HTML attributes can be altered. $page = \Drupal::service('html_fragment_renderer')->preparePage($page, $page_array); $page->setBodyTop(drupal_render($page_array['page_top'])); $page->setBodyBottom(drupal_render($page_array['page_bottom'])); $page->setContent(drupal_render($page_array)); return \Drupal::service('html_page_renderer')->render($page); }
/** * Returns a system batch page. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return mixed * A \Symfony\Component\HttpFoundation\Response object or page element or * NULL. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException */ public function batchPage(Request $request) { require_once DRUPAL_ROOT . '/core/includes/batch.inc'; $output = _batch_page($request); if ($output === FALSE) { throw new AccessDeniedHttpException(); } elseif ($output instanceof Response) { return $output; } elseif (isset($output)) { // Force a page without blocks or messages to // display a list of collected messages later. drupal_set_page_content($output); $page = element_info('page'); $page['#show_messages'] = FALSE; $page = $this->render($page); return $page; } }
function page_content($js, $input, $entity, $view_mode) { $panelizer = $entity->panelizer[$view_mode]; if (empty($panelizer)) { return MENU_NOT_FOUND; } list($entity_id, $revision_id, $bundle) = entity_extract_ids($this->entity_type, $entity); $form_state = array('entity' => $entity, 'revision info' => $this->entity_allows_revisions($entity), 'display cache' => panels_edit_cache_get(implode(':', array_filter(array('panelizer', $this->entity_type, $entity_id, $view_mode, $revision_id)))), 'no_redirect' => TRUE); ctools_include('common', 'panelizer'); $output = drupal_build_form('panelizer_edit_content_form', $form_state); if (!empty($form_state['executed'])) { if (!empty($form_state['clicked_button']['#save-display'])) { drupal_set_message(t('The settings have been updated.')); $entity->panelizer[$view_mode]->display = $form_state['display']; $entity->panelizer[$view_mode]->display_is_modified = TRUE; $this->entity_save($entity); } else { drupal_set_message(t('Changes have been discarded.')); } panels_edit_cache_clear($form_state['display cache']); drupal_goto($_GET['q']); } $output = $this->wrap_entity_panelizer_pages($entity, $view_mode, $output); ctools_set_no_blocks(FALSE); drupal_set_page_content($output); $page = element_info('page'); return $page; }
/** * Wraps element_info(). * * @return array */ protected function getElementInfo($type) { return element_info($type); }
/** * Implements hook_js_alter(). */ function omega_js_alter(&$js) { // If the AJAX.js isn't included... we don't need the ajaxPageState settings! if (!isset($js['misc/ajax.js']) && isset($js['settings']['data'])) { foreach ($js['settings']['data'] as $delta => $setting) { if (array_key_exists('ajaxPageState', $setting)) { if (count($setting) == 1) { unset($js['settings']['data'][$delta]); } else { unset($js['settings']['data'][$delta]['ajaxPageState']); } } } } // In some cases the element info array might get built before the theme // system is fully bootstrapped. In this case, omega_element_info_alter() will // never get called causing custom Omega pre-rendering of scripts to be // skipped which results in no JavaScript being output. if (!element_info('scripts')) { drupal_static_reset('element_info'); } if (!omega_extension_enabled('assets')) { return; } omega_css_js_alter($js, 'js'); // Move the specified JavaScript files to the footer. if (($footer = omega_theme_get_setting('omega_js_footer')) && is_array($footer)) { require_once drupal_get_path('theme', 'omega') . '/includes/assets.inc'; if (!($cache = cache_get("omega:{$GLOBALS['theme_key']}:footer"))) { // Explode and trim the values for the footer rules. $steps = omega_assets_regex_steps($footer); cache_set("omega:{$GLOBALS['theme_key']}:footer", $steps, 'cache', CACHE_TEMPORARY); } else { $steps = $cache->data; } $mapping = omega_assets_generate_mapping($js); foreach (omega_assets_regex_execute($mapping, $steps) as $key => $match) { $js[$key]['scope'] = 'footer'; } } }
/** * Builds the renderable view of an entity. * * Entities postpone the composition of their renderable arrays to #pre_render * functions in order to maximize cache efficacy. This means that the full * rendable array for an entity is constructed in drupal_render(). Some tests * require the complete renderable array for an entity outside of the * drupal_render process in order to verify the presence of specific values. * This method isolates the steps in the render process that produce an * entity's renderable array. * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity to prepare a renderable array for. * @param string $view_mode * (optional) The view mode that should be used to build the entity. * @param null $langcode * (optional) For which language the entity should be prepared, defaults to * the current content language. * @param bool $reset * (optional) Whether to clear the cache for this entity. * @return array * * @see drupal_render() */ protected function drupalBuildEntityView(EntityInterface $entity, $view_mode = 'full', $langcode = NULL, $reset = FALSE) { $ensure_fully_built = function (&$elements) use(&$ensure_fully_built) { // If the default values for this element have not been loaded yet, populate // them. if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) { $elements += element_info($elements['#type']); } // Make any final changes to the element before it is rendered. This means // that the $element or the children can be altered or corrected before the // element is rendered into the final text. if (isset($elements['#pre_render'])) { foreach ($elements['#pre_render'] as $callable) { $elements = call_user_func($callable, $elements); } } // And recurse. $children = Element::children($elements, TRUE); foreach ($children as $key) { $ensure_fully_built($elements[$key]); } }; $render_controller = $this->container->get('entity.manager')->getViewBuilder($entity->getEntityTypeId()); if ($reset) { $render_controller->resetCache(array($entity->id())); } $build = $render_controller->view($entity, $view_mode, $langcode); $ensure_fully_built($build); return $build; }
/** * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { $field_settings = $this->getFieldSettings(); // The field settings include defaults for the field type. However, this // widget is a base class for other widgets (e.g., ImageWidget) that may act // on field types without these expected settings. $field_settings += array('display_default' => NULL, 'display_field' => NULL, 'description_field' => NULL); $cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality(); $defaults = array('fids' => array(), 'display' => (bool) $field_settings['display_default'], 'description' => ''); // Essentially we use the managed_file type, extended with some // enhancements. $element_info = element_info('managed_file'); $element += array('#type' => 'managed_file', '#upload_location' => $items[$delta]->getUploadLocation(), '#upload_validators' => $items[$delta]->getUploadValidators(), '#value_callback' => array(get_class($this), 'value'), '#process' => array_merge($element_info['#process'], array(array(get_class($this), 'process'))), '#progress_indicator' => $this->getSetting('progress_indicator'), '#extended' => TRUE, '#field_name' => $this->fieldDefinition->getName(), '#entity_type' => $items->getEntity()->getEntityTypeId(), '#display_field' => (bool) $field_settings['display_field'], '#display_default' => $field_settings['display_default'], '#description_field' => $field_settings['description_field'], '#cardinality' => $cardinality); $element['#weight'] = $delta; // Field stores FID value in a single mode, so we need to transform it for // form element to recognize it correctly. if (!isset($items[$delta]->fids) && isset($items[$delta]->target_id)) { $items[$delta]->fids = array($items[$delta]->target_id); } $element['#default_value'] = $items[$delta]->getValue() + $defaults; $default_fids = $element['#extended'] ? $element['#default_value']['fids'] : $element['#default_value']; if (empty($default_fids)) { $file_upload_help = array('#theme' => 'file_upload_help', '#description' => $element['#description'], '#upload_validators' => $element['#upload_validators'], '#cardinality' => $cardinality); $element['#description'] = drupal_render($file_upload_help); $element['#multiple'] = $cardinality != 1 ? TRUE : FALSE; if ($cardinality != 1 && $cardinality != -1) { $element['#element_validate'] = array(array(get_class($this), 'validateMultipleCount')); } } return $element; }
/** * {@inheritdoc} * * The entire HTML: takes a #type 'page' and wraps it in a #type 'html'. */ public function renderResponse(array $main_content, Request $request, RouteMatchInterface $route_match) { list($page, $title) = $this->prepare($main_content, $request, $route_match); if (!isset($page['#type']) || $page['#type'] !== 'page') { throw new \LogicException('Must be #type page'); } $page['#title'] = $title; // Now render the rendered page.html.twig template inside the html.html.twig // template, and use the bubbled #attached metadata from $page to ensure we // load all attached assets. $html = ['#type' => 'html', 'page' => $page]; $html += element_info('html'); // The special page regions will appear directly in html.html.twig, not in // page.html.twig, hence add them here, just before rendering html.html.twig. $this->buildPageTopAndBottom($html); // The three parts of rendered markup in html.html.twig (page_top, page and // page_bottom) must be rendered with drupal_render_root(), so that their // #post_render_cache callbacks are executed (which may attach additional // assets). // html.html.twig must be able to render the final list of attached assets, // and hence may not execute any #post_render_cache_callbacks (because they // might add yet more assets to be attached), and therefore it must be // rendered with drupal_render(), not drupal_render_root(). $this->renderer->render($html['page'], TRUE); if (isset($html['page_top'])) { $this->renderer->render($html['page_top'], TRUE); } if (isset($html['page_bottom'])) { $this->renderer->render($html['page_bottom'], TRUE); } $content = $this->renderer->render($html); // Expose the cache contexts and cache tags associated with this page in a // X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags header respectively. Also // associate the "rendered" cache tag. This allows us to invalidate the // entire render cache, regardless of the cache bin. $cache_contexts = []; $cache_tags = ['rendered']; $cache_max_age = Cache::PERMANENT; foreach (['page_top', 'page', 'page_bottom'] as $region) { if (isset($html[$region])) { $cache_contexts = Cache::mergeContexts($cache_contexts, $html[$region]['#cache']['contexts']); $cache_tags = Cache::mergeTags($cache_tags, $html[$region]['#cache']['tags']); $cache_max_age = Cache::mergeMaxAges($cache_max_age, $html[$region]['#cache']['max-age']); } } // Set the generator in the HTTP header. list($version) = explode('.', \Drupal::VERSION, 2); $response = new Response($content, 200, ['X-Drupal-Cache-Tags' => implode(' ', $cache_tags), 'X-Drupal-Cache-Contexts' => implode(' ', $this->cacheContexts->optimizeTokens($cache_contexts)), 'X-Generator' => 'Drupal ' . $version . ' (https://www.drupal.org)']); // If an explicit non-infinite max-age is specified by a part of the page, // respect that by applying it to the response's headers. if ($cache_max_age !== Cache::PERMANENT) { $response->setMaxAge($cache_max_age); } return $response; }