/** * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::preview(). */ public function preview() { $output = $this->view->render(); if (!empty($this->view->live_preview)) { $output = array('#prefix' => '<pre>', '#markup' => SafeMarkup::checkPlain(drupal_render_root($output)), '#suffix' => '</pre>'); } return $output; }
/** * {@inheritdoc} */ public function preview() { $output = $this->view->render(); if (!empty($this->view->live_preview)) { $output = array('#prefix' => '<pre>', '#plain_text' => drupal_render_root($output), '#suffix' => '</pre>'); } return $output; }
/** * Tests that elements are rendered properly. */ protected function assertRenderedElement(array $element, $xpath, array $xpath_args = array()) { $original_element = $element; $this->setRawContent(drupal_render_root($element)); $this->verbose('<hr />' . $this->getRawContent()); // @see \Drupal\simpletest\WebTestBase::xpath() $xpath = $this->buildXPathQuery($xpath, $xpath_args); $element += array('#value' => NULL); $this->assertFieldByXPath($xpath, $element['#value'], format_string('#type @type was properly rendered.', array('@type' => var_export($element['#type'], TRUE)))); }
/** * {@inheritdoc} */ public function render($row) { $entity = $row->_entity; $item = new \stdClass(); foreach ($entity as $name => $field) { // views_view_row_rss takes care about the escaping. $item->{$name} = $field->value; } $item->elements = array(array('key' => 'pubDate', 'value' => gmdate('r', $entity->timestamp->value)), array('key' => 'dc:creator', 'value' => $entity->author->value), array('key' => 'guid', 'value' => $entity->guid->value, 'attributes' => array('isPermaLink' => 'false'))); $build = array('#theme' => $this->themeFunctions(), '#view' => $this->view, '#options' => $this->options, '#row' => $item); return drupal_render_root($build); }
/** * Checks the behavior of the Serializer callback paths and row plugins. */ public function testSerializerResponses() { // Test the serialize callback. $view = Views::getView('test_serializer_display_field'); $view->initDisplay(); $this->executeView($view); $actual_json = $this->drupalGet('test/serialize/field', array(), array('Accept: application/json')); $this->assertResponse(200); // Test the http Content-type. $headers = $this->drupalGetHeaders(); $this->assertEqual($headers['content-type'], 'application/json', 'The header Content-type is correct.'); $expected = array(); foreach ($view->result as $row) { $expected_row = array(); foreach ($view->field as $id => $field) { $expected_row[$id] = $field->render($row); } $expected[] = $expected_row; } $this->assertIdentical($actual_json, json_encode($expected), 'The expected JSON output was found.'); // Test that the rendered output and the preview output are the same. $view->destroy(); $view->setDisplay('rest_export_1'); // Mock the request content type by setting it on the display handler. $view->display_handler->setContentType('json'); $output = $view->preview(); $this->assertIdentical($actual_json, drupal_render_root($output), 'The expected JSON preview output was found.'); // Test a 403 callback. $this->drupalGet('test/serialize/denied'); $this->assertResponse(403); // Test the entity rows. $view = Views::getView('test_serializer_display_entity'); $view->initDisplay(); $this->executeView($view); // Get the serializer service. $serializer = $this->container->get('serializer'); $entities = array(); foreach ($view->result as $row) { $entities[] = $row->_entity; } $expected = $serializer->serialize($entities, 'json'); $actual_json = $this->drupalGet('test/serialize/entity', array(), array('Accept: application/json')); $this->assertResponse(200); $this->assertIdentical($actual_json, $expected, 'The expected JSON output was found.'); $expected = $serializer->serialize($entities, 'hal_json'); $actual_json = $this->drupalGet('test/serialize/entity', array(), array('Accept: application/hal+json')); $this->assertIdentical($actual_json, $expected, 'The expected HAL output was found.'); }
/** * {@inheritdoc} */ public function renderResponse(array $main_content, Request $request, RouteMatchInterface $route_match) { $response = new AjaxResponse(); // First render the main content, because it might provide a title. $content = drupal_render_root($main_content); // Attach the library necessary for using the OpenModalDialogCommand and set // the attachments for this Ajax response. $main_content['#attached']['library'][] = 'core/drupal.dialog.ajax'; $response->setAttachments($main_content['#attached']); // If the main content doesn't provide a title, use the title resolver. $title = isset($main_content['#title']) ? $main_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject()); // Determine the title: use the title provided by the main content if any, // otherwise get it from the routing information. $options = $request->request->get('dialogOptions', array()); $response->addCommand(new OpenModalDialogCommand($title, $content, $options)); return $response; }
/** * {@inheritdoc} */ public function render(HtmlFragmentInterface $fragment, $status_code = 200) { // Converts the given HTML fragment which represents the main content region // of the page into a render array. $page_content['main'] = array('#markup' => $fragment->getContent()); $page_content['#title'] = $fragment->getTitle(); if ($fragment instanceof CacheableInterface) { $page_content['main']['#cache']['tags'] = $fragment->getCacheTags(); } // Build the full page array by calling drupal_prepare_page(), which invokes // hook_page_build(). This adds the other regions to the page. $page_array = drupal_prepare_page($page_content); // Build the HtmlPage object. $page = new HtmlPage('', array(), $fragment->getTitle()); $page = $this->preparePage($page, $page_array); $page->setBodyTop(drupal_render_root($page_array['page_top'])); $page->setBodyBottom(drupal_render_root($page_array['page_bottom'])); $page->setContent(drupal_render_root($page_array)); $page->setStatusCode($status_code); drupal_process_attached($page_array); if (isset($page_array['page_top'])) { drupal_process_attached($page_array['page_top']); } if (isset($page_array['page_bottom'])) { drupal_process_attached($page_array['page_bottom']); } if ($fragment instanceof CacheableInterface) { // Persist cache tags associated with this page. Also associate the // "rendered" cache tag. This allows us to invalidate the entire render // cache, regardless of the cache bin. $cache_tags = Cache::mergeTags(isset($page_array['page_top']) ? $page_array['page_top']['#cache']['tags'] : [], $page_array['#cache']['tags'], isset($page_array['page_bottom']) ? $page_array['page_bottom']['#cache']['tags'] : [], ['rendered']); // Only keep unique cache tags. We need to prevent duplicates here already // rather than only in the cache layer, because they are also used by // reverse proxies (like Varnish), not only by Drupal's page cache. $page->setCacheTags(array_unique($cache_tags)); } return $page; }
/** * Tests various code snippets. */ function testSnippets() { $container = \Drupal::getContainer(); // Cache snippets from section "The Drupal Cache" in Chapter 1. // Make up some test data. $bin = 'default'; $cid = 'my_cid'; $data = 'my_data'; $nid = 5; $tags = array('node:' . $nid); // Cache the data. Get the class in two different ways. $cache_class = \Drupal::cache($bin); $this->assertTrue($cache_class, 'Cache class is not null'); $cache_class = $container->get('cache.' . $bin); $cache_class->set($cid, $data, CacheBackendInterface::CACHE_PERMANENT, $tags); // Check that we can retrieve data from the cache. $out = $cache_class->get($cid); $this->outputVariable($out, 'Cache get method output'); $this->assertEqual($data, $out->data, 'Cached data could be retrieved'); // Invalidate the data and check that it cannot be retrieved. Cache::invalidateTags($tags); $out = $cache_class->get($cid); $this->assertFalse($out, 'After invalidating tags, cached data cannot be retrieved'); // Theme snippets from section "Making Your Output Themeable" in Chapter 2. $build['hello'] = array('#input1' => t('Hello World!'), '#theme' => 'mymodule_hookname'); $output = drupal_render_root($build); $expected = '<div>Hello World!</div>'; $this->outputHTML($output, 'Theme template output'); $this->assertEqual(trim($output), $expected, 'Theme template worked in render array'); // Config API snippets from "Configuration API in Drupal 8" section in // chapter 2. // Test reading the settings several different ways. $config = \Drupal::config('mymodule.settings'); $this->assertTrue($config, 'Config class is not null'); $config = $container->get('config.factory')->getEditable('mymodule.settings'); $all = $config->get(); $this->outputVariable($all, 'Full configuration output'); $button_label = $all['submit_button_label']; $this->assertEqual($button_label, 'Submit', 'Read correct button label from overall get'); $button_label = $config->get('submit_button_label'); $this->assertEqual($button_label, 'Submit', 'Read correct button label with specific get'); $name_field_info = $all['name_field_settings']; $name_label = $name_field_info['field_label']; $this->assertEqual($name_label, 'Your name', 'Read correct name field label from overall get'); $name_field_info = $config->get('name_field_settings'); $this->outputVariable($name_field_info, 'Name field configuration output'); $name_label = $name_field_info['field_label']; $this->assertEqual($name_label, 'Your name', 'Read correct name field label from field settings get'); $name_label = $config->get('name_field_settings.field_label'); $this->assertEqual($name_label, 'Your name', 'Read correct name field label from specific get'); // Change the submit label. $new_label = "Save"; $config->set('submit_button_label', $new_label); $config->save(); // Get a new config object, to make sure it was really saved. $new_config = \Drupal::config('mymodule.settings'); $button_label = $new_config->get('submit_button_label'); $this->assertEqual($button_label, 'Save', 'Read correct button label after save'); // State API snippets from "State API in Drupal 8" section in chapter 2. // Get $state in two ways. $state = \Drupal::state(); $this->assertTrue($state, 'State is not null'); $state = $container->get('state'); $value = 'Some test data'; $state->set('mymodule.my_state_variable_name', $value); $new_value = $state->get('mymodule.my_state_variable_name'); $this->assertEqual($value, $new_value, 'State get worked correctly'); $state->delete('mymodule.my_state_variable_name'); $new_value = $state->get('mymodule.my_state_variable_name'); $this->assertNull($new_value, 'After delete, could not retrieve state value'); // Snippets from "Internationalizing User Interface Text" section in // chapter 2. Good code only; bad code examples are omitted. $button_text = t('Save'); $this->assertEqual($button_text, 'Save', 't() worked OK on simple string'); $user_name = 'foo'; $message_string = t('Hello @user_name', array('@user_name' => $user_name)); $this->outputHTML($message_string, 't() with variables output'); $this->assertEqual($message_string, 'Hello foo', 't() worked OK on string with variable'); $test = (object) array(); $foo = $test instanceof MyClass; // Database snippets from "Querying the Database with the Database API" // section in Chapter 2. // Make a blocked user for querying purposes. $account = $this->drupalCreateUser(array()); $account->status = 0; $account->save(); // Query by status 0 (blocked). $desired_status = 0; $found = FALSE; $result = db_query('SELECT * FROM {users_field_data} u WHERE u.status = :status', array(':status' => $desired_status)); foreach ($result as $record) { $this->outputVariable($record, 'User database record'); if ($record->uid == $account->id()) { $found = TRUE; } } $this->assertTrue($found, 'Created user was found by status query'); // Test the ability to query by user name. $found = FALSE; $result = db_query('SELECT * FROM {users_field_data} u WHERE u.name = :name', array(':name' => $account->getUsername())); foreach ($result as $record) { if ($record->uid == $account->id()) { $found = TRUE; } } $this->assertTrue($found, 'Created user was found by name query'); // Create a node, for query purposes. $newnode = $this->drupalCreateNode(); // Log in as user who can access content. $account = $this->drupalCreateUser(array('access content')); $this->drupalLogin($account); $query = db_select('node', 'n'); $query->innerJoin('node_field_data', 'nd', 'n.nid = nd.nid AND n.vid = nd.vid'); $query->innerJoin('users_field_data', 'u', 'u.uid = nd.uid'); $query->addField('nd', 'changed', 'last_updated'); $query->extend('Drupal\\Core\\Database\\Query\\PagerSelectExtender')->limit(20)->fields('nd', array('title', 'nid'))->fields('u', array('name'))->addTag('node_access')->condition('nd.status', 1); $result = $query->execute(); $found = FALSE; foreach ($result as $node) { $title = $node->title; if ($node->nid == $newnode->id()) { $found = TRUE; $this->verbose("Found node with title {$title}"); } } $this->assertTrue($found, "Found node in query"); // Snippets from the "Cleansing and Checking User-Provided Input" // section in Chapter 2. Only "good" code is included. $text = '<h2>Text with HTML</h2>'; $plain_text = htmlentities($text); $url = 'http://example.com'; $url_object = Url::fromUri($url); $output = Drupal::l($text, $url_object); $this->outputHTML($output, 'l() output'); $this->assertEqual($output, '<a href="' . $url . '">' . $plain_text . '</a>', 'l output is as expected'); // Form builder snippet from "Basic Form Generation and Processing in // Drupal 8", chapter 4. $my_render_array['personal_data_form'] = \Drupal::formBuilder()->getForm('Drupal\\mymodule\\Form\\PersonalDataForm'); $this->outputVariable($my_render_array, 'Personal data form array'); $this->assertTrue(isset($my_render_array['personal_data_form']['first_name']), 'First name field is present in form array'); $builder = $container->get('form_builder'); $my_render_array['personal_data_form'] = $builder->getForm('Drupal\\mymodule\\Form\\PersonalDataForm'); $this->assertTrue(isset($my_render_array['personal_data_form']['first_name']), 'First name field is present in form array'); // Entity query snippets from "Querying and Loading Entities in Drupal 8", // chapter 4. // Try various methods for retrieving the query. $query = \Drupal::entityQuery('node'); $this->assertTrue($query, 'Query is not null'); $query = \Drupal::entityQueryAggregate('node'); $this->assertTrue($query, 'Query is not null'); $query_service = $container->get('entity.query'); $query = $query_service->getAggregate('node'); $this->assertTrue($query, 'Query is not null'); // Try an actual query. $query = $query_service->get('node'); $query->condition('type', $newnode->getType()); $ids = $query->execute(); // Try different methods of getting storage manager. $storage = \Drupal::entityManager()->getStorage('node'); $this->assertTrue($storage, 'Storage is not null'); // Load the entities and verify. $storage = $container->get('entity.manager')->getStorage('node'); $entities = $storage->loadMultiple($ids); $this->assertEqual(count($entities), 1, 'One node was found'); $first = reset($entities); $this->assertEqual($first->getTitle(), $newnode->getTitle(), 'Correct node was found'); }
/** * Processes a successful controller into an HTTP 200 response. * * Some controllers may not return a response object but simply the body of * one. The VIEW event is called in that case, to allow us to mutate that * body into a Response object. In particular we assume that the return * from an JSON-type response is a JSON string, so just wrap it into a * Response object. * * @param Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event * The Event to process. */ public function onView(GetResponseForControllerResultEvent $event) { $request = $event->getRequest(); // For a master request, we process the result and wrap it as needed. // For a subrequest, all we want is the string value. We assume that // is just an HTML string from a controller, so wrap that into a response // object. The subrequest's response will get dissected and placed into // the larger page as needed. if ($event->getRequestType() == HttpKernelInterface::MASTER_REQUEST) { $method = 'on' . $this->negotiation->getContentType($request); if (method_exists($this, $method)) { $event->setResponse($this->{$method}($event)); } else { $event->setResponse(new Response('Not Acceptable', 406)); } } else { // This is a new-style Symfony-esque subrequest, which means we assume // the body is not supposed to be a complete page but just a page // fragment. $page_result = $event->getControllerResult(); if ($page_result instanceof HtmlPage || $page_result instanceof Response) { return $page_result; } if (!is_array($page_result)) { $page_result = array('#markup' => $page_result); } // If no title was returned fall back to one defined in the route. if (!isset($page_result['#title'])) { $page_result['#title'] = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT)); } $event->setResponse(new Response(drupal_render_root($page_result))); } }
public function render($row) { global $base_url; $nid = $row->{$this->field_alias}; if (!is_numeric($nid)) { return; } $display_mode = $this->options['view_mode']; if ($display_mode == 'default') { $display_mode = \Drupal::config('system.rss')->get('items.view_mode'); } // Load the specified node: /** @var \Drupal\node\NodeInterface $node */ $node = $this->nodes[$nid]; if (empty($node)) { return; } $item_text = ''; $node->link = $node->url('canonical', array('absolute' => TRUE)); $node->rss_namespaces = array(); $node->rss_elements = array(array('key' => 'pubDate', 'value' => gmdate('r', $node->getCreatedTime())), array('key' => 'dc:creator', 'value' => $node->getOwner()->getUsername()), array('key' => 'guid', 'value' => $node->id() . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false'))); // The node gets built and modules add to or modify $node->rss_elements // and $node->rss_namespaces. $build_mode = $display_mode; $build = node_view($node, $build_mode); unset($build['#theme']); if (!empty($node->rss_namespaces)) { $this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, $node->rss_namespaces); } elseif (function_exists('rdf_get_namespaces')) { // Merge RDF namespaces in the XML namespaces in case they are used // further in the RSS content. $xml_rdf_namespaces = array(); foreach (rdf_get_namespaces() as $prefix => $uri) { $xml_rdf_namespaces['xmlns:' . $prefix] = $uri; } $this->view->style_plugin->namespaces += $xml_rdf_namespaces; } if ($display_mode != 'title') { // We render node contents. $item_text .= drupal_render_root($build); } $item = new \stdClass(); $item->description = SafeMarkup::set($item_text); $item->title = $node->label(); $item->link = $node->link; $item->elements = $node->rss_elements; $item->nid = $node->id(); $theme_function = array('#theme' => $this->themeFunctions(), '#view' => $this->view, '#options' => $this->options, '#row' => $item); return drupal_render_root($theme_function); }
/** * Displays content in a dialog. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object. * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The route match. * @param mixed $_content * A controller definition string, or a callable object/closure. * @param bool $modal * (optional) TRUE to render a modal dialog. Defaults to FALSE. * * @return \Drupal\Core\Ajax\AjaxResponse * AjaxResponse to return the content wrapper in a dialog. */ public function dialog(Request $request, RouteMatchInterface $route_match, $_content, $modal = FALSE) { $page_content = $this->getContentResult($request, $_content); // Allow controllers to return a HtmlPage or a Response object directly. if ($page_content instanceof HtmlPage) { $page_content = $page_content->getContent(); } if ($page_content instanceof Response) { $page_content = $page_content->getContent(); } // Most controllers return a render array, but some return a string. if (!is_array($page_content)) { $page_content = array('#markup' => $page_content); } $content = drupal_render_root($page_content); drupal_process_attached($page_content); $title = isset($page_content['#title']) ? $page_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject()); $response = new AjaxResponse(); // Fetch any modal options passed in from data-dialog-options. $options = $request->request->get('dialogOptions', array()); // Set modal flag and re-use the modal ID. if ($modal) { $options['modal'] = TRUE; $target = '#drupal-modal'; } else { // Generate the target wrapper for the dialog. if (isset($options['target'])) { // If the target was nominated in the incoming options, use that. $target = $options['target']; // Ensure the target includes the #. if (substr($target, 0, 1) != '#') { $target = '#' . $target; } // This shouldn't be passed on to jQuery.ui.dialog. unset($options['target']); } else { // Generate a target based on the route id. $route_name = $route_match->getRouteName(); $target = '#' . drupal_html_id("drupal-dialog-{$route_name}"); } } $response->addCommand(new OpenDialogCommand($target, $title, $content, $options)); return $response; }
/** * Wraps drupal_render_root(). * * @todo: Remove as part of https://drupal.org/node/2182149 */ protected function drupalRenderRoot(&$elements) { $output = drupal_render_root($elements); drupal_process_attached($elements); return $output; }
public function render($row) { static $row_index; if (!isset($row_index)) { $row_index = 0; } if (function_exists('rdf_get_namespaces')) { // Merge RDF namespaces in the XML namespaces in case they are used // further in the RSS content. $xml_rdf_namespaces = array(); foreach (rdf_get_namespaces() as $prefix => $uri) { $xml_rdf_namespaces['xmlns:' . $prefix] = $uri; } $this->view->style_plugin->namespaces += $xml_rdf_namespaces; } // Create the RSS item object. $item = new \stdClass(); $item->title = $this->getField($row_index, $this->options['title_field']); $item->link = _url($this->getField($row_index, $this->options['link_field']), array('absolute' => TRUE)); $item->description = $this->getField($row_index, $this->options['description_field']); $item->elements = array(array('key' => 'pubDate', 'value' => $this->getField($row_index, $this->options['date_field'])), array('key' => 'dc:creator', 'value' => $this->getField($row_index, $this->options['creator_field']), 'namespace' => array('xmlns:dc' => 'http://purl.org/dc/elements/1.1/'))); $guid_is_permalink_string = 'false'; $item_guid = $this->getField($row_index, $this->options['guid_field_options']['guid_field']); if ($this->options['guid_field_options']['guid_field_is_permalink']) { $guid_is_permalink_string = 'true'; $item_guid = _url($item_guid, array('absolute' => TRUE)); } $item->elements[] = array('key' => 'guid', 'value' => $item_guid, 'attributes' => array('isPermaLink' => $guid_is_permalink_string)); $row_index++; foreach ($item->elements as $element) { if (isset($element['namespace'])) { $this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, $element['namespace']); } } $build = array('#theme' => $this->themeFunctions(), '#view' => $this->view, '#options' => $this->options, '#row' => $item, '#field_alias' => isset($this->field_alias) ? $this->field_alias : ''); return drupal_render_root($build); }
public function render($row) { global $base_url; $cid = $row->{$this->field_alias}; if (!is_numeric($cid)) { return; } $view_mode = $this->options['view_mode']; if ($view_mode == 'default') { $view_mode = \Drupal::config('system.rss')->get('items.view_mode'); } // Load the specified comment and its associated node: /** @var $comment \Drupal\comment\CommentInterface */ $comment = $this->comments[$cid]; if (empty($comment)) { return; } $item_text = ''; $comment->link = $comment->url('canonical', array('absolute' => TRUE)); $comment->rss_namespaces = array(); $comment->rss_elements = array(array('key' => 'pubDate', 'value' => gmdate('r', $comment->getCreatedTime())), array('key' => 'dc:creator', 'value' => $comment->getAuthorName()), array('key' => 'guid', 'value' => 'comment ' . $comment->id() . ' at ' . $base_url, 'attributes' => array('isPermaLink' => 'false'))); // The comment gets built and modules add to or modify // $comment->rss_elements and $comment->rss_namespaces. $build = comment_view($comment, 'rss'); unset($build['#theme']); if (!empty($comment->rss_namespaces)) { $this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, $comment->rss_namespaces); } if ($view_mode != 'title') { // We render comment contents. $item_text .= drupal_render_root($build); } $item = new \stdClass(); $item->description = $item_text; $item->title = $comment->label(); $item->link = $comment->link; $item->elements = $comment->rss_elements; $item->cid = $comment->id(); $build = array('#theme' => $this->themeFunctions(), '#view' => $this->view, '#options' => $this->options, '#row' => $item); return drupal_render_root($build); }
/** * {@inheritdoc} */ public function execute() { parent::execute(); $output = $this->view->render(); return new Response(drupal_render_root($output), 200, array('Content-type' => $this->getMimeType())); }
public function render($row) { static $row_index; if (!isset($row_index)) { $row_index = 0; } if (function_exists('rdf_get_namespaces')) { // Merge RDF namespaces in the XML namespaces in case they are used // further in the RSS content. $xml_rdf_namespaces = array(); foreach (rdf_get_namespaces() as $prefix => $uri) { $xml_rdf_namespaces['xmlns:' . $prefix] = $uri; } $this->view->style_plugin->namespaces += $xml_rdf_namespaces; } // Create the RSS item object. $item = new \stdClass(); $item->title = $this->getField($row_index, $this->options['title_field']); // @todo Views should expect and store a leading /. See: // https://www.drupal.org/node/2423913 $item->link = Url::fromUserInput('/' . $this->getField($row_index, $this->options['link_field']))->setAbsolute()->toString(); $item->description = $this->getField($row_index, $this->options['description_field']); $item->elements = array(array('key' => 'pubDate', 'value' => $this->getField($row_index, $this->options['date_field'])), array('key' => 'dc:creator', 'value' => $this->getField($row_index, $this->options['creator_field']), 'namespace' => array('xmlns:dc' => 'http://purl.org/dc/elements/1.1/'))); $guid_is_permalink_string = 'false'; $item_guid = $this->getField($row_index, $this->options['guid_field_options']['guid_field']); if ($this->options['guid_field_options']['guid_field_is_permalink']) { $guid_is_permalink_string = 'true'; // @todo Enforce GUIDs as system-generated rather than user input? See // https://www.drupal.org/node/2430589. $item_guid = Url::fromUserInput('/' . $item_guid)->setAbsolute()->toString(); } $item->elements[] = array('key' => 'guid', 'value' => $item_guid, 'attributes' => array('isPermaLink' => $guid_is_permalink_string)); $row_index++; foreach ($item->elements as $element) { if (isset($element['namespace'])) { $this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, $element['namespace']); } } $build = array('#theme' => $this->themeFunctions(), '#view' => $this->view, '#options' => $this->options, '#row' => $item, '#field_alias' => isset($this->field_alias) ? $this->field_alias : ''); return drupal_render_root($build); }
if (is_array($results['tasks'])) { $links += $results['tasks']; } else { $links = array_merge($links, array(\Drupal::l(t('Administration pages'), new Url('system.admin')), \Drupal::l(t('Front page'), new Url('<front>')))); } $item_list = array('#theme' => 'item_list', '#items' => $links, '#title' => t('Next steps')); $output .= drupal_render_root($item_list); } elseif ($request->query->has('batch')) { $output = _batch_page($request); } else { if (empty($_SESSION['authorize_operation']) || empty($_SESSION['authorize_filetransfer_info'])) { $output = t('It appears you have reached this page in error.'); } elseif (!($batch = batch_get())) { // We have a batch to process, show the filetransfer form. $elements = \Drupal::formBuilder()->getForm('Drupal\\Core\\FileTransfer\\Form\\FileTransferAuthorizeForm'); $output = drupal_render_root($elements); } } // We defer the display of messages until all operations are done. $show_messages = !(($batch = batch_get()) && isset($batch['running'])); } else { $response->setStatusCode(403); \Drupal::logger('access denied')->warning('authorize.php'); $page_title = t('Access denied'); $output = t('You are not allowed to access this page.'); } if (!empty($output)) { $response->headers->set('Content-Type', 'text/html; charset=utf-8'); $response->setContent(DefaultHtmlPageRenderer::renderPage($output, $page_title, 'maintenance', array('#show_messages' => $show_messages))); $response->send(); }
/** * Checks the behavior of the Serializer callback paths and row plugins. */ public function testSerializerResponses() { // Test the serialize callback. $view = Views::getView('test_serializer_display_field'); $view->initDisplay(); $this->executeView($view); $actual_json = $this->drupalGetWithFormat('test/serialize/field', 'json'); $this->assertResponse(200); $this->assertCacheTags($view->getCacheTags()); $this->assertCacheContexts(['languages:language_interface', 'theme', 'request_format']); // @todo Due to https://www.drupal.org/node/2352009 we can't yet test the // propagation of cache max-age. // Test the http Content-type. $headers = $this->drupalGetHeaders(); $this->assertEqual($headers['content-type'], 'application/json', 'The header Content-type is correct.'); $expected = array(); foreach ($view->result as $row) { $expected_row = array(); foreach ($view->field as $id => $field) { $expected_row[$id] = $field->render($row); } $expected[] = $expected_row; } $this->assertIdentical($actual_json, json_encode($expected), 'The expected JSON output was found.'); // Test that the rendered output and the preview output are the same. $view->destroy(); $view->setDisplay('rest_export_1'); // Mock the request content type by setting it on the display handler. $view->display_handler->setContentType('json'); $output = $view->preview(); $this->assertIdentical($actual_json, (string) drupal_render_root($output), 'The expected JSON preview output was found.'); // Test a 403 callback. $this->drupalGet('test/serialize/denied'); $this->assertResponse(403); // Test the entity rows. $view = Views::getView('test_serializer_display_entity'); $view->initDisplay(); $this->executeView($view); // Get the serializer service. $serializer = $this->container->get('serializer'); $entities = array(); foreach ($view->result as $row) { $entities[] = $row->_entity; } $expected = $serializer->serialize($entities, 'json'); $actual_json = $this->drupalGetWithFormat('test/serialize/entity', 'json'); $this->assertResponse(200); $this->assertIdentical($actual_json, $expected, 'The expected JSON output was found.'); $expected_cache_tags = $view->getCacheTags(); $expected_cache_tags[] = 'entity_test_list'; /** @var \Drupal\Core\Entity\EntityInterface $entity */ foreach ($entities as $entity) { $expected_cache_tags = Cache::mergeTags($expected_cache_tags, $entity->getCacheTags()); } $this->assertCacheTags($expected_cache_tags); $this->assertCacheContexts(['languages:language_interface', 'theme', 'entity_test_view_grants', 'request_format']); $expected = $serializer->serialize($entities, 'hal_json'); $actual_json = $this->drupalGetWithFormat('test/serialize/entity', 'hal_json'); $this->assertIdentical($actual_json, $expected, 'The expected HAL output was found.'); $this->assertCacheTags($expected_cache_tags); // Change the default format to xml. $view->setDisplay('rest_export_1'); $view->getDisplay()->setOption('style', array('type' => 'serializer', 'options' => array('uses_fields' => FALSE, 'formats' => array('xml' => 'xml')))); $view->save(); $expected = $serializer->serialize($entities, 'xml'); $actual_xml = $this->drupalGet('test/serialize/entity'); $this->assertIdentical($actual_xml, $expected, 'The expected XML output was found.'); $this->assertCacheContexts(['languages:language_interface', 'theme', 'entity_test_view_grants', 'request_format']); // Allow multiple formats. $view->setDisplay('rest_export_1'); $view->getDisplay()->setOption('style', array('type' => 'serializer', 'options' => array('uses_fields' => FALSE, 'formats' => array('xml' => 'xml', 'json' => 'json')))); $view->save(); $expected = $serializer->serialize($entities, 'json'); $actual_json = $this->drupalGetWithFormat('test/serialize/entity', 'json'); $this->assertIdentical($actual_json, $expected, 'The expected JSON output was found.'); $expected = $serializer->serialize($entities, 'xml'); $actual_xml = $this->drupalGetWithFormat('test/serialize/entity', 'xml'); $this->assertIdentical($actual_xml, $expected, 'The expected XML output was found.'); }
/** * Renders a page using a custom page theme hook and optional region content. * * Temporary shim to facilitate modernization progress for special front * controllers (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_root($page_array['page_top'])); $page->setBodyBottom(drupal_render_root($page_array['page_bottom'])); $page->setContent(drupal_render_root($page_array)); drupal_process_attached($page_array); if (isset($page_array['page_top'])) { drupal_process_attached($page_array['page_top']); } if (isset($page_array['page_bottom'])) { drupal_process_attached($page_array['page_bottom']); } return \Drupal::service('html_page_renderer')->render($page); }
/** * Tests the 'processed_text' element. * * check_markup() is a wrapper for the 'processed_text' element, for use in * simple scenarios; the 'processed_text' element has more advanced features: * it lets filters attach assets, associate cache tags and define * #post_render_cache callbacks. * This test focuses solely on those advanced features. */ function testProcessedTextElement() { entity_create('filter_format', array('format' => 'element_test', 'name' => 'processed_text element test format', 'filters' => array('filter_test_assets' => array('weight' => -1, 'status' => TRUE), 'filter_test_cache_tags' => array('weight' => 0, 'status' => TRUE), 'filter_test_post_render_cache' => array('weight' => 1, 'status' => TRUE), 'filter_htmlcorrector' => array('weight' => 10, 'status' => TRUE))))->save(); $build = array('#type' => 'processed_text', '#text' => '<p>Hello, world!</p>', '#format' => 'element_test'); drupal_render_root($build); // Verify the assets, cache tags and #post_render_cache callbacks. $expected_assets = array('library' => array('filter/caption')); $this->assertEqual($expected_assets, $build['#attached'], 'Expected assets present'); $expected_cache_tags = array('filter_format:element_test', 'foo:bar', 'foo:baz'); $this->assertEqual($expected_cache_tags, $build['#cache']['tags'], 'Expected cache tags present.'); $expected_markup = '<p>Hello, world!</p><p>This is a dynamic llama.</p>'; $this->assertEqual($expected_markup, $build['#markup'], 'Expected #post_render_cache callback has been applied.'); }
/** * Wraps drupal_render_root(). * * @todo Remove as part of https://www.drupal.org/node/2182149. */ protected function drupalRenderRoot(&$elements) { return drupal_render_root($elements); }
/** * Tests bubbling of assets, cache tags and post-render cache callbacks when * they are added by #pre_render callbacks. */ function testDrupalRenderBubbling() { $verify_result = function ($test_element) { \Drupal::state()->set('bubbling_nested_pre_render_uncached', FALSE); \Drupal::state()->set('bubbling_nested_pre_render_cached', FALSE); \Drupal::cache('render')->set('cached_nested', array('#markup' => 'Cached nested!', '#attached' => array(), '#cache' => array('tags' => array()), '#post_render_cache' => array())); \Drupal::cache('render')->delete('uncached_nested'); $output = drupal_render_root($test_element); // Assert top-level. $this->assertEqual('Cache tag!Asset!Post-render cache!barquxNested!Cached nested!', trim($output), 'Expected HTML generated.'); $this->assertEqual(array('child:cache_tag'), $test_element['#cache']['tags'], 'Expected cache tags found.'); $expected_attached = array('js' => array(0 => array('type' => 'setting', 'data' => array('foo' => 'bar')))); $this->assertEqual($expected_attached, $test_element['#attached'], 'Expected assets found.'); $expected_post_render_cache = array('Drupal\\system\\Tests\\Common\\RenderTest::bubblingPostRenderCache' => array(0 => array('foo' => 'bar', 'baz' => 'qux'))); $post_render_cache = $test_element['#post_render_cache']; // We don't care about the exact token. unset($post_render_cache['Drupal\\system\\Tests\\Common\\RenderTest::bubblingPostRenderCache'][0]['token']); $this->assertEqual($expected_post_render_cache, $post_render_cache, 'Expected post-render cache data found.'); // Ensure that #pre_render callbacks are only executed if they don't have // a render cache hit. $this->assertTrue(\Drupal::state()->get('bubbling_nested_pre_render_uncached')); $this->assertFalse(\Drupal::state()->get('bubbling_nested_pre_render_cached')); }; $this->pass('Test <strong>without</strong> theming/Twig.'); $test_element_without_theme = array('foo' => array('#pre_render' => array(array(get_class($this), 'bubblingPreRender')))); $verify_result($test_element_without_theme); $this->pass('Test <strong>with</strong> theming/Twig.'); $test_element_with_theme = array('#theme' => 'common_test_render_element', 'foo' => array('#pre_render' => array(array(get_class($this), 'bubblingPreRender')))); $verify_result($test_element_with_theme); }
/** * Tests the 'processed_text' element. * * check_markup() is a wrapper for the 'processed_text' element, for use in * simple scenarios; the 'processed_text' element has more advanced features: * it lets filters attach assets, associate cache tags and define * #lazy_builder callbacks. * This test focuses solely on those advanced features. */ function testProcessedTextElement() { entity_create('filter_format', array('format' => 'element_test', 'name' => 'processed_text element test format', 'filters' => array('filter_test_assets' => array('weight' => -1, 'status' => TRUE), 'filter_test_cache_tags' => array('weight' => 0, 'status' => TRUE), 'filter_test_cache_contexts' => array('weight' => 0, 'status' => TRUE), 'filter_test_cache_merge' => array('weight' => 0, 'status' => TRUE), 'filter_test_placeholders' => array('weight' => 1, 'status' => TRUE), 'filter_htmlcorrector' => array('weight' => 10, 'status' => TRUE))))->save(); $build = array('#type' => 'processed_text', '#text' => '<p>Hello, world!</p>', '#format' => 'element_test'); drupal_render_root($build); // Verify the attachments and cacheability metadata. $expected_attachments = array('library' => array('filter/caption'), 'placeholders' => []); $this->assertEqual($expected_attachments, $build['#attached'], 'Expected attachments present'); $expected_cache_tags = array('config:filter.format.element_test', 'foo:bar', 'foo:baz', 'merge:tag'); $this->assertEqual($expected_cache_tags, $build['#cache']['tags'], 'Expected cache tags present.'); $expected_cache_contexts = ['languages:' . LanguageInterface::TYPE_CONTENT, 'languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']; $this->assertEqual($expected_cache_contexts, $build['#cache']['contexts'], 'Expected cache contexts present.'); $expected_markup = '<p>Hello, world!</p><p>This is a dynamic llama.</p>'; $this->assertEqual($expected_markup, $build['#markup'], 'Expected #lazy_builder callback has been applied.'); }
/** * {@inheritdoc} */ public function render(array $output, $status_code = 200) { if (!isset($output['#title'])) { $output['#title'] = $this->titleResolver->getTitle(\Drupal::request(), \Drupal::routeMatch()->getRouteObject()); } $page = new HtmlPage('', isset($output['#cache']) ? $output['#cache'] : array(), $output['#title']); $page_array = drupal_prepare_page($output); $page = $this->fragmentRenderer->preparePage($page, $page_array); $page->setBodyTop(drupal_render_root($page_array['page_top'])); $page->setBodyBottom(drupal_render_root($page_array['page_bottom'])); $page->setContent(drupal_render_root($page_array)); drupal_process_attached($page_array); if (isset($page_array['page_top'])) { drupal_process_attached($page_array['page_top']); } if (isset($page_array['page_bottom'])) { drupal_process_attached($page_array['page_bottom']); } $page->setStatusCode($status_code); return $page; }