/** * {@inheritdoc} */ public function getDescription() { $locked = $this->tempStore->getMetadata($this->entity->id()); $account = $this->entityTypeManager->getStorage('user')->load($locked->owner); $username = array('#theme' => 'username', '#account' => $account); return $this->t('By breaking this lock, any unsaved changes made by @user will be lost.', array('@user' => $this->renderer->render($username))); }
/** * {@inheritdoc} */ public function getDescription() { $locked = $this->rulesUiHandler->getLockMetaData(); $account = $this->entityTypeManager->getStorage('user')->load($locked->owner); $username = ['#theme' => 'username', '#account' => $account]; return $this->t('By breaking this lock, any unsaved changes made by @user will be lost.', ['@user' => $this->renderer->render($username)]); }
/** * {@inheritdoc} * * For anonymous users, the "active" class will be calculated on the server, * because most sites serve each anonymous user the same cached page anyway. * For authenticated users, the "active" class will be calculated on the * client (through JavaScript), only data- attributes are added to links to * prevent breaking the render cache. The JavaScript is added in * system_page_attachments(). * * @see system_page_attachments() */ public function generate($text, Url $url, $collect_cacheability_metadata = FALSE) { // Performance: avoid Url::toString() needing to retrieve the URL generator // service from the container. $url->setUrlGenerator($this->urlGenerator); // Start building a structured representation of our link to be altered later. $variables = array('text' => is_array($text) ? $this->renderer->render($text) : $text, 'url' => $url, 'options' => $url->getOptions()); // Merge in default options. $variables['options'] += array('attributes' => array(), 'query' => array(), 'language' => NULL, 'set_active_class' => FALSE, 'absolute' => FALSE); // Add a hreflang attribute if we know the language of this link's url and // hreflang has not already been set. if (!empty($variables['options']['language']) && !isset($variables['options']['attributes']['hreflang'])) { $variables['options']['attributes']['hreflang'] = $variables['options']['language']->getId(); } // Set the "active" class if the 'set_active_class' option is not empty. if (!empty($variables['options']['set_active_class']) && !$url->isExternal()) { // Add a "data-drupal-link-query" attribute to let the // drupal.active-link library know the query in a standardized manner. if (!empty($variables['options']['query'])) { $query = $variables['options']['query']; ksort($query); $variables['options']['attributes']['data-drupal-link-query'] = Json::encode($query); } // Add a "data-drupal-link-system-path" attribute to let the // drupal.active-link library know the path in a standardized manner. if ($url->isRouted() && !isset($variables['options']['attributes']['data-drupal-link-system-path'])) { // @todo System path is deprecated - use the route name and parameters. $system_path = $url->getInternalPath(); // Special case for the front page. $variables['options']['attributes']['data-drupal-link-system-path'] = $system_path == '' ? '<front>' : $system_path; } } // Remove all HTML and PHP tags from a tooltip, calling expensive strip_tags() // only when a quick strpos() gives suspicion tags are present. if (isset($variables['options']['attributes']['title']) && strpos($variables['options']['attributes']['title'], '<') !== FALSE) { $variables['options']['attributes']['title'] = strip_tags($variables['options']['attributes']['title']); } // Allow other modules to modify the structure of the link. $this->moduleHandler->alter('link', $variables); // Move attributes out of options since generateFromRoute() doesn't need // them. Include a placeholder for the href. $attributes = array('href' => '') + $variables['options']['attributes']; unset($variables['options']['attributes']); $url->setOptions($variables['options']); if (!$collect_cacheability_metadata) { $url_string = $url->toString($collect_cacheability_metadata); } else { $generated_url = $url->toString($collect_cacheability_metadata); $url_string = $generated_url->getGeneratedUrl(); $generated_link = GeneratedLink::createFromObject($generated_url); } // The result of the URL generator is a plain-text URL to use as the href // attribute, and it is escaped by \Drupal\Core\Template\Attribute. $attributes['href'] = $url_string; $result = SafeMarkup::format('<a@attributes>@text</a>', array('@attributes' => new Attribute($attributes), '@text' => $variables['text'])); return $collect_cacheability_metadata ? $generated_link->setGeneratedLink($result) : $result; }
/** * Generates the toolbar. * * @param Profile $profile * * @return array */ public function toolbarAction(Profile $profile) { $this->profiler->disable(); $templates = $this->templateManager->getTemplates($profile); $rendered = ''; foreach ($templates as $name => $template) { $rendered .= $template->renderBlock('toolbar', ['collector' => $profile->getcollector($name), 'token' => $profile->getToken(), 'name' => $name]); } $toolbar = ['#theme' => 'webprofiler_toolbar', '#toolbar' => $rendered, '#token' => $profile->getToken()]; return new Response($this->renderer->render($toolbar)); }
/** * Helper function for self::listing() to build table rows. * * @param array[] $hierarchy * Keys are plugin IDs, and values are arrays of the same structure as this * parameter. The depth is unlimited. * @param integer $depth * The depth of $hierarchy's top-level items as seen from the original * hierarchy's root (this function is recursive), starting with 0. * * @return array * A render array. */ protected function buildListingLevel(array $hierarchy, $depth) { $rows = []; foreach ($hierarchy as $plugin_id => $children) { $definition = $this->paymentStatusManager->getDefinition($plugin_id); $operations_provider = $this->paymentStatusManager->getOperationsProvider($plugin_id); $indentation = ['#theme' => 'indentation', '#size' => $depth]; $rows[$plugin_id] = ['label' => ['#markup' => $this->renderer->render($indentation) . $definition['label']], 'description' => ['#markup' => $definition['description']], 'operations' => ['#type' => 'operations', '#links' => $operations_provider ? $operations_provider->getOperations($plugin_id) : []]]; $rows = array_merge($rows, $this->buildListingLevel($children, $depth + 1)); } return $rows; }
/** * Bubbles the bubbleable metadata to the current render context. * * @param \Drupal\Core\GeneratedUrl $generated_url * The generated URL whose bubbleable metadata to bubble. * @param array $options * (optional) The URL options. Defaults to none. */ protected function bubble(GeneratedUrl $generated_url, array $options = []) { // Bubbling metadata makes sense only if the code is executed inside a // render context. All code running outside controllers has no render // context by default, so URLs used there are not supposed to affect the // response cacheability. if ($this->renderer->hasRenderContext()) { $build = []; $generated_url->applyTo($build); $this->renderer->render($build); } }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $block_instance = $this->getBlockInstance($form_state); // Submit the block configuration form. $block_form_state = (new FormState())->setValues($form_state->getValue('settings')); $block_instance->submitConfigurationForm($form, $block_form_state); // Update the original form values. $form_state->setValue('settings', $block_form_state->getValues()); // If a temporary configuration for this variant exists, use it. $temp_store_key = $this->panelsDisplay->id(); if ($variant_config = $this->tempStore->get($temp_store_key)) { $this->panelsDisplay->setConfiguration($variant_config); } // Set the block region appropriately. $block_config = $block_instance->getConfiguration(); $block_config['region'] = $form_state->getValue(array('settings', 'region')); // Determine if we need to update or add this block. if ($uuid = $form_state->getValue('uuid')) { $this->panelsDisplay->updateBlock($uuid, $block_config); } else { $uuid = $this->panelsDisplay->addBlock($block_config); } // Set the tempstore value. $this->tempStore->set($this->panelsDisplay->id(), $this->panelsDisplay->getConfiguration()); // Assemble data required for our App. $build = $this->buildBlockInstance($block_instance); $form['build'] = $build; // Add our data attribute for the Backbone app. $build['#attributes']['data-block-id'] = $uuid; $block_model = ['uuid' => $uuid, 'label' => $block_instance->label(), 'id' => $block_instance->getPluginId(), 'region' => $block_config['region'], 'html' => $this->renderer->render($build)]; // Add Block metadata and HTML as a drupalSetting. $form['#attached']['drupalSettings']['panels_ipe']['updated_block'] = $block_model; return $form; }
/** * Pre-render callback to build the page title. * * @param array $page * A page render array. * * @return array * The changed page render array. */ public function buildTitle(array $page) { $entity_type = $page['#entity_type']; $entity = $page['#' . $entity_type]; // If the entity's label is rendered using a field formatter, set the // rendered title field formatter as the page title instead of the default // plain text title. This allows attributes set on the field to propagate // correctly (e.g. RDFa, in-place editing). if ($entity instanceof FieldableEntityInterface) { $label_field = $entity->getEntityType()->getKey('label'); if (isset($page[$label_field])) { $page['#title'] = $this->renderer->render($page[$label_field]); } } return $page; }
/** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode) { $element = []; $thumbnails = $this->thumbnailFormatter->viewElements($items, $langcode); $videos = $this->videoFormatter->viewElements($items, $langcode); foreach ($items as $delta => $item) { // Support responsive videos within the colorbox modal. if ($this->getSetting('responsive')) { $videos[$delta]['#attributes']['class'][] = 'video-embed-field-responsive-modal'; $videos[$delta]['#attributes']['style'] = sprintf('width:%dpx;', $this->getSetting('modal_max_width')); } $element[$delta] = ['#type' => 'container', '#attributes' => ['data-video-embed-field-modal' => (string) $this->renderer->render($videos[$delta]), 'class' => ['video-embed-field-launch-modal']], '#attached' => ['library' => ['video_embed_field/colorbox', 'video_embed_field/responsive-video']], '#cache' => ['contexts' => ['user.permissions']], 'children' => $thumbnails[$delta]]; } $this->colorboxAttachment->attach($element); return $element; }
/** * {@inheritdoc} */ protected function getRevisionDescription(ContentEntityInterface $revision, $is_default = FALSE) { /** @var \Drupal\Core\Entity\ContentEntityInterface|\Drupal\user\EntityOwnerInterface|\Drupal\Core\Entity\RevisionLogInterface $revision */ if ($revision instanceof RevisionLogInterface) { // Use revision link to link to revisions that are not active. $date = $this->dateFormatter->format($revision->getRevisionCreationTime(), 'short'); $link = $revision->toLink($date, 'revision'); // @todo: Simplify this when https://www.drupal.org/node/2334319 lands. $username = ['#theme' => 'username', '#account' => $revision->getRevisionUser()]; $username = $this->renderer->render($username); } else { $link = $revision->toLink($revision->label(), 'revision'); $username = ''; } $markup = ''; if ($revision instanceof RevisionLogInterface) { $markup = $revision->getRevisionLogMessage(); } if ($username) { $template = '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}'; } else { $template = '{% trans %} {{ date }} {% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}'; } $column = ['data' => ['#type' => 'inline_template', '#template' => $template, '#context' => ['date' => $link->toString(), 'username' => $username, 'message' => ['#markup' => $markup, '#allowed_tags' => Xss::getHtmlTagList()]]]]; return $column; }
/** * Save data to the cache. * * A plugin should override this to provide specialized caching behavior. */ public function cacheSet($type) { switch ($type) { case 'query': // Not supported currently, but this is certainly where we'd put it. break; case 'results': $data = array('result' => $this->prepareViewResult($this->view->result), 'total_rows' => isset($this->view->total_rows) ? $this->view->total_rows : 0, 'current_page' => $this->view->getCurrentPage()); \Drupal::cache($this->resultsBin)->set($this->generateResultsKey(), $data, $this->cacheSetExpire($type), $this->getCacheTags()); break; case 'output': // Make a copy of the output so it is not modified. If we render the // display output directly an empty string will be returned when the // view is actually rendered. If we try to set '#printed' to FALSE there // are problems with asset bubbling. $output = $this->view->display_handler->output; $this->renderer->render($output); // Also assign the cacheable render array back to the display handler so // that is used to render the view for this request and rendering does // not happen twice. $this->storage = $this->view->display_handler->output = $this->renderer->getCacheableRenderArray($output); \Drupal::cache($this->outputBin)->set($this->generateOutputKey(), $this->storage, $this->cacheSetExpire($type), Cache::mergeTags($this->storage['#cache']['tags'], ['rendered'])); break; } }
/** * Gets a given layout with empty regions and relevant metadata. * * @param \Drupal\page_manager\PageVariantInterface $page_variant * The page variant entity. * @param string $layout_id * The machine name of the requested layout. * * @return \Symfony\Component\HttpFoundation\JsonResponse */ public function getLayout(PageVariantInterface $page_variant, $layout_id) { /** @var \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $variant_plugin */ $variant_plugin = $page_variant->getVariantPlugin(); // Build the requested layout. $configuration = $variant_plugin->getConfiguration(); $configuration['layout'] = $layout_id; $variant_plugin->setConfiguration($configuration); // Inherit our PageVariant's contexts before rendering. $variant_plugin->setContexts($page_variant->getContexts()); $regions = $variant_plugin->getRegionNames(); $region_data = []; $region_content = []; // Compile region content and metadata. foreach ($regions as $id => $label) { // Wrap the region with a class/data attribute that our app can use. $region_name = Html::getClass("block-region-{$id}"); $region_content[$id] = ['#prefix' => '<div class="' . $region_name . '" data-region-name="' . $id . '">', '#suffix' => '</div>']; // Format region metadata. $region_data[] = ['name' => $id, 'label' => $label]; } $build = $variant_plugin->getLayout()->build($region_content); // Get the current layout. $current_layout = $variant_plugin->getLayout()->getPluginId(); // Get a list of all available layouts. $layouts = $this->layoutPluginManager->getLayoutOptions(); $data = ['id' => $layout_id, 'label' => $layouts[$layout_id], 'current' => $current_layout == $layout_id, 'html' => $this->renderer->render($build), 'regions' => $region_data]; // Update temp store. $this->savePageVariant($page_variant); // Return a structured JSON response for our Backbone App. return new JsonResponse($data); }
/** * Wrapper around render() for twig printed output. * * If an object is passed which does not implement __toString(), * RenderableInterface or toString() then an exception is thrown; * Other objects are casted to string. However in the case that the * object is an instance of a Twig_Markup object it is returned directly * to support auto escaping. * * If an array is passed it is rendered via render() and scalar values are * returned directly. * * @param mixed $arg * String, Object or Render Array. * * @throws \Exception * When $arg is passed as an object which does not implement __toString(), * RenderableInterface or toString(). * * @return mixed * The rendered output or an Twig_Markup object. * * @see render * @see TwigNodeVisitor */ public function renderVar($arg) { // Check for a numeric zero int or float. if ($arg === 0 || $arg === 0.0) { return 0; } // Return early for NULL and empty arrays. if ($arg == NULL) { return NULL; } // Optimize for scalars as it is likely they come from the escape filter. if (is_scalar($arg)) { return $arg; } if (is_object($arg)) { $this->bubbleArgMetadata($arg); if ($arg instanceof RenderableInterface) { $arg = $arg->toRenderable(); } elseif (method_exists($arg, '__toString')) { return (string) $arg; } elseif (method_exists($arg, 'toString')) { return $arg->toString(); } else { throw new \Exception('Object of type ' . get_class($arg) . ' cannot be printed.'); } } // This is a render array, with special simple cases already handled. // Early return if this element was pre-rendered (no need to re-render). if (isset($arg['#printed']) && $arg['#printed'] == TRUE && isset($arg['#markup']) && strlen($arg['#markup']) > 0) { return $arg['#markup']; } $arg['#printed'] = FALSE; return $this->renderer->render($arg); }
/** * Prepares the HTML body: wraps the main content in #type 'page'. * * @param array $main_content * The render array representing the main content. * @param \Symfony\Component\HttpFoundation\Request $request * The request object, for context. * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The route match, for context. * * @return array * An array with two values: * 0. A #type 'page' render array. * 1. The page title. * * @throws \LogicException * If the selected display variant does not implement PageVariantInterface. */ protected function prepare(array $main_content, Request $request, RouteMatchInterface $route_match) { // If the _controller result already is #type => page, // we have no work to do: The "main content" already is an entire "page" // (see html.html.twig). if (isset($main_content['#type']) && $main_content['#type'] === 'page') { $page = $main_content; } else { // Select the page display variant to be used to render this main content, // default to the built-in "simple page". $event = new PageDisplayVariantSelectionEvent('simple_page', $route_match); $this->eventDispatcher->dispatch(RenderEvents::SELECT_PAGE_DISPLAY_VARIANT, $event); $variant_id = $event->getPluginId(); // We must render the main content now already, because it might provide a // title. We set its $is_root_call parameter to FALSE, to ensure // placeholders are not yet replaced. This is essentially "pre-rendering" // the main content, the "full rendering" will happen in // ::renderResponse(). // @todo Remove this once https://www.drupal.org/node/2359901 lands. if (!empty($main_content)) { $this->renderer->executeInRenderContext(new RenderContext(), function () use(&$main_content) { if (isset($main_content['#cache']['keys'])) { // Retain #title, otherwise, dynamically generated titles would be // missing for controllers whose entire returned render array is // render cached. $main_content['#cache_properties'][] = '#title'; } return $this->renderer->render($main_content, FALSE); }); $main_content = $this->renderCache->getCacheableRenderArray($main_content) + ['#title' => isset($main_content['#title']) ? $main_content['#title'] : NULL]; } // Instantiate the page display, and give it the main content. $page_display = $this->displayVariantManager->createInstance($variant_id); if (!$page_display instanceof PageVariantInterface) { throw new \LogicException('Cannot render the main content for this page because the provided display variant does not implement PageVariantInterface.'); } $page_display->setMainContent($main_content)->setConfiguration($event->getPluginConfiguration()); // Generate a #type => page render array using the page display variant, // the page display will build the content for the various page regions. $page = array('#type' => 'page'); $page += $page_display->build(); } // $page is now fully built. Find all non-empty page regions, and add a // theme wrapper function that allows them to be consistently themed. $regions = \Drupal::theme()->getActiveTheme()->getRegions(); foreach ($regions as $region) { if (!empty($page[$region])) { $page[$region]['#theme_wrappers'][] = 'region'; $page[$region]['#region'] = $region; } } // Allow hooks to add attachments to $page['#attached']. $this->invokePageAttachmentHooks($page); // Determine the title: use the title provided by the main content if any, // otherwise get it from the routing information. $title = isset($main_content['#title']) ? $main_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject()); return [$page, $title]; }
/** * Implements form AJAX callback. */ public function ajaxAddMoreSubmit(array &$form, FormStateInterface $form_state) { $triggering_element = $form_state->getTriggeringElement(); $parents = array_slice($triggering_element['#array_parents'], 0, -2); $root_element = NestedArray::getValue($form, $parents); $response = new AjaxResponse(); $response->addCommand(new ReplaceCommand('#' . $root_element['#id'], $this->renderer->render($root_element))); return $response; }
/** * Provides a page to render a single entity. * * @param \Drupal\Core\Entity\EntityInterface $_entity * The Entity to be rendered. Note this variable is named $_entity rather * than $entity to prevent collisions with other named placeholders in the * route. * @param string $view_mode * (optional) The view mode that should be used to display the entity. * Defaults to 'full'. * @param string $langcode * (optional) For which language the entity should be rendered, defaults to * the current content language. * * @return array * A render array as expected by drupal_render(). */ public function view(EntityInterface $_entity, $view_mode = 'full', $langcode = NULL) { $page = $this->entityManager->getViewBuilder($_entity->getEntityTypeId())->view($_entity, $view_mode, $langcode); // If the entity's label is rendered using a field formatter, set the // rendered title field formatter as the page title instead of the default // plain text title. This allows attributes set on the field to propagate // correctly (e.g. RDFa, in-place editing). if ($_entity instanceof FieldableEntityInterface) { $label_field = $_entity->getEntityType()->getKey('label'); if ($label_field && $_entity->getFieldDefinition($label_field)->getDisplayOptions('view')) { // We must render the label field, because rendering the entity may be // a cache hit, in which case we can't extract the rendered label field // from the $page renderable array. $build = $this->entityManager->getTranslationFromContext($_entity)->get($label_field)->view($view_mode); $page['#title'] = $this->renderer->render($build); } } return $page; }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { // Return early if there are any errors. if ($form_state->hasAnyErrors()) { return $form; } $panels_display = $this->panelsDisplay; // Submit the layout form. $layout_form_state = (new FormState())->setValues($form_state->getValue('settings', [])); $this->layout->submitConfigurationForm($form, $layout_form_state); $layout_config = $this->layout->getConfiguration(); // Shift our blocks to the first available region. The IPE can control // re-assigning blocks in a smarter way. $region_definitions = $this->layout->getRegionDefinitions(); $first_region = reset(array_keys($region_definitions)); // For each block, set the region to match the new layout. foreach ($panels_display->getRegionAssignments() as $region => $region_assignment) { /** @var \Drupal\Core\Block\BlockPluginInterface $block */ foreach ($region_assignment as $block_id => $block) { $block_config = $block->getConfiguration(); // If the new layout does not have a region with the same name, use the // first available region. if (!isset($region_definitions[$block_config['region']])) { $block_config['region'] = $first_region; $panels_display->updateBlock($block_id, $block_config); } } } // Have our panels display use the new layout. $this->panelsDisplay->setLayout($this->layout, $layout_config); // Update tempstore. $this->tempStore->set($panels_display->id(), $panels_display->getConfiguration()); $region_data = []; $region_content = []; // Compile region content and metadata. $regions = $panels_display->getRegionAssignments(); foreach ($regions as $id => $label) { // Wrap the region with a class/data attribute that our app can use. $region_name = Html::getClass("block-region-{$id}"); $region_content[$id] = ['#prefix' => '<div class="' . $region_name . '" data-region-name="' . $id . '">', '#suffix' => '</div>']; // Format region metadata. $region_data[] = ['name' => $id, 'label' => $label]; } $build = $panels_display->getLayout()->build($region_content); $form['build'] = $build; $data = ['id' => $this->layout->getPluginId(), 'label' => $layout_config['label'], 'current' => TRUE, 'html' => $this->renderer->render($build), 'regions' => $region_data]; // Add Block metadata and HTML as a drupalSetting. $form['#attached']['drupalSettings']['panels_ipe']['updated_layout'] = $data; return $form; }
/** * {@inheritdoc} */ public function buildRow(EntityInterface $entity) { /** @var \Drupal\profile\Entity\ProfileInterface $entity */ $mark = ['#theme' => 'mark', '#mark_type' => node_mark($entity->id(), $entity->getChangedTime())]; $langcode = $entity->language()->id; $uri = $entity->toUrl(); $options = $uri->getOptions(); $options += $langcode != LanguageInterface::LANGCODE_NOT_SPECIFIED && isset($languages[$langcode]) ? ['language' => $languages[$langcode]] : []; $uri->setOptions($options); $row['label']['data'] = ['#type' => 'link', '#title' => $entity->label(), '#suffix' => ' ' . $this->renderer->render($mark)] + $uri->toRenderArray(); $row['type'] = $entity->getType()->id(); $row['owner']['data'] = ['#theme' => 'username', '#account' => $entity->getOwner()]; $row['status'] = $entity->isActive() ? $this->t('active') : $this->t('not active'); $row['changed'] = $this->dateFormatter->format($entity->getChangedTime(), 'short'); $language_manager = \Drupal::languageManager(); if ($language_manager->isMultilingual()) { $row['language_name'] = $language_manager->getLanguageName($langcode); } $route_params = ['user' => $entity->getOwnerId(), 'type' => $entity->bundle(), 'profile' => $entity->id()]; $links['edit'] = ['title' => t('Edit'), 'route_name' => 'entity.profile.edit_form', 'route_parameters' => $route_params]; $links['delete'] = ['title' => t('Delete'), 'route_name' => 'entity.profile.delete_form', 'route_parameters' => $route_params]; $row[] = ['data' => ['#type' => 'operations', '#links' => $links]]; return $row + parent::buildRow($entity); }
/** * {@inheritdoc} */ public function process($text, $langcode) { $response = new FilterProcessResult($text); // Use a look ahead to match the capture groups in any order. if (preg_match_all('/(<p>)?(?<json>{(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})(<\\/p>)?/', $text, $matches)) { foreach ($matches['json'] as $delta => $match) { // Ensure the JSON string is valid. $embed_data = json_decode($match, TRUE); if (!is_array($embed_data)) { continue; } // If the URL can't matched to a provider or the settings are invalid, // ignore it. $provider = $this->providerManager->loadProviderFromInput($embed_data['video_url']); if (!$provider || !$this->validSettings($embed_data['settings'])) { continue; } $autoplay = $this->currentUser->hasPermission('never autoplay videos') ? FALSE : $embed_data['settings']['autoplay']; $embed_code = $provider->renderEmbedCode($embed_data['settings']['width'], $embed_data['settings']['height'], $autoplay); // Add the container to make the video responsive if it's been // configured as such. This usually is attached to field output in the // case of a formatter, but a custom container must be used where one is // not present. if ($embed_data['settings']['responsive']) { $embed_code = ['#type' => 'container', '#attributes' => ['class' => ['video-embed-field-responsive-video']], 'children' => $embed_code]; } // Replace the JSON settings with a video. $text = str_replace($matches[0][$delta], $this->renderer->render($embed_code), $text); } } // Add the required responsive video library and update the response text. $response->setProcessedText($text); $response->addAttachments(['library' => ['video_embed_field/responsive-video']]); $response->setCacheContexts(['user.permissions']); return $response; }
/** * Tests JavaScript files that have querystrings attached get added right. */ function testAddJsFileWithQueryString() { $build['#attached']['library'][] = 'common_test/querystring'; $assets = AttachedAssets::createFromRenderArray($build); $css = $this->assetResolver->getCssAssets($assets, FALSE); $js = $this->assetResolver->getJsAssets($assets, FALSE)[1]; $this->assertTrue(array_key_exists('core/modules/system/tests/modules/common_test/querystring.css?arg1=value1&arg2=value2', $css), 'CSS file with query string is correctly added.'); $this->assertTrue(array_key_exists('core/modules/system/tests/modules/common_test/querystring.js?arg1=value1&arg2=value2', $js), 'JavaScript file with query string is correctly added.'); $css_render_array = \Drupal::service('asset.css.collection_renderer')->render($css); $rendered_css = $this->renderer->render($css_render_array); $js_render_array = \Drupal::service('asset.js.collection_renderer')->render($js); $rendered_js = $this->renderer->render($js_render_array); $query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0'; $this->assertNotIdentical(strpos($rendered_css, '<link rel="stylesheet" href="' . str_replace('&', '&', file_create_url('core/modules/system/tests/modules/common_test/querystring.css?arg1=value1&arg2=value2')) . '&' . $query_string . '" media="all" />'), FALSE, 'CSS file with query string gets version query string correctly appended..'); $this->assertNotIdentical(strpos($rendered_js, '<script src="' . str_replace('&', '&', file_create_url('core/modules/system/tests/modules/common_test/querystring.js?arg1=value1&arg2=value2')) . '&' . $query_string . '"></script>'), FALSE, 'JavaScript file with query string gets version query string correctly appended.'); }
/** * Generate the HTML for our entity. * * @param \Drupal\Core\Entity\ContentEntityInterface $entity * The entity we're rendering. * @param bool $use_default_css * TRUE if we should inject our default CSS otherwise FALSE. * @param bool $optimize_css * TRUE if we should compress the CSS otherwise FALSE. * * @return string * The generated HTML. * * @throws \Exception */ protected function getHtml(ContentEntityInterface $entity, $use_default_css, $optimize_css) { $render_controller = $this->entityTypeManager->getViewBuilder($entity->getEntityTypeId()); $render = ['#theme' => 'entity_print__' . $entity->getEntityTypeId() . '__' . $entity->id(), '#entity' => $entity, '#entity_array' => $render_controller->view($entity, 'pdf'), '#attached' => []]; // Inject some generic CSS across all templates. if ($use_default_css) { $render['#attached']['library'][] = 'entity_print/default'; } // Allow other modules to add their own CSS. $this->moduleHandler->alter('entity_print_css', $render, $entity); // Inject CSS from the theme info files and then render the CSS. $render = $this->addCss($render, $entity); $css_assets = $this->assetResolver->getCssAssets(AttachedAssets::createFromRenderArray($render), $optimize_css); $rendered_css = $this->cssRenderer->render($css_assets); $render['#entity_print_css'] = $this->renderer->render($rendered_css); return $this->renderer->render($render); }
/** * Indexes a single node. * * @param \Drupal\node\NodeInterface $node * The node to index. */ protected function indexNode(NodeInterface $node) { $languages = $node->getTranslationLanguages(); $node_render = $this->entityManager->getViewBuilder('node'); foreach ($languages as $language) { $node = $node->getTranslation($language->getId()); // Render the node. $build = $node_render->view($node, 'search_index', $language->getId()); unset($build['#theme']); $rendered = $this->renderer->render($build); $text = '<h1>' . SafeMarkup::checkPlain($node->label($language->getId())) . '</h1>' . $rendered; // Fetch extra data normally not visible. $extra = $this->moduleHandler->invokeAll('node_update_index', array($node, $language->getId())); foreach ($extra as $t) { $text .= $t; } // Update index, using search index "type" equal to the plugin ID. search_index($this->getPluginId(), $node->id(), $language->getId(), $text); } }
private function queryBenzinarii($lat_ne, $lon_ne, $lat_sw, $lon_sw) { $data = new \stdClass(); $data->pins = []; $data->listing = ''; $query = $this->entity_query->get('node')->condition('field_coordonate.lat', (double) $lat_ne, '<')->condition('field_coordonate.lon', (double) $lon_ne, '<')->condition('field_coordonate.lat', (double) $lat_sw, '>')->condition('field_coordonate.lon', (double) $lon_sw, '>'); $ids = $query->execute(); if (!count($ids)) { return $data; } $entities = $this->entity_type_manager->getStorage('node')->loadMultiple($ids); foreach ($entities as $entity) { $pin = new \stdClass(); $pin->lat = $entity->field_coordonate->lat; $pin->lon = $entity->field_coordonate->lon; $pin->pret = PretCarburant::getPretCarburantCurent($entity); $pin->id = $entity->id(); if ($pin->pret) { $entity->pret = $pin->pret; $data->pins[$pin->id] = $pin; $render_entities[] = $entity; } } if (!count($render_entities)) { return $data; } uasort($render_entities, function ($a, $b) { if ($a->pret == $b->pret) { return 0; } else { if ($a->pret < $b->pret) { return -1; } else { return 1; } } }); $render = $this->entity_type_manager->getViewBuilder('node')->viewMultiple($render_entities, 'small_teaser'); $data->listing = '<div class="listing-benzinarii">' . $this->renderer->render($render) . '</div>'; return $data; }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $block_instance = $this->getBlockInstance($form_state); // Submit the block form. $block_instance->submitConfigurationForm($form, $form_state); // Save the block instance to our temporary configuration. /** @var \Drupal\page_manager\PageVariantInterface $page_variant */ $page_variant = PageVariant::load($form_state->getValue('variant_id')); /** @var \Drupal\panels\Plugin\DisplayVariant\PanelsDisplayVariant $variant_plugin */ $variant_plugin = $page_variant->getVariantPlugin(); // If a temporary configuration for this variant exists, use it. $temp_store_key = 'variant.' . $page_variant->id(); if ($variant_config = $this->tempStore->get($temp_store_key)) { $variant_plugin->setConfiguration($variant_config); } // Set the block region appropriately. $block_config = $block_instance->getConfiguration(); $block_config['region'] = $form_state->getValue('region'); // Determine if we need to update or add this block. if ($uuid = $form_state->getValue('uuid')) { $variant_plugin->updateBlock($uuid, $block_config); } else { $uuid = $variant_plugin->addBlock($block_config); } // Set the tempstore value. $variant_config = $variant_plugin->getConfiguration(); $this->tempStore->set('variant.' . $page_variant->id(), $variant_config); // Assemble data required for our App. $build = $this->buildBlockInstance($block_instance); // Add our data attribute for the Backbone app. $build['#attributes']['data-block-id'] = $uuid; $settings = ['uuid' => $uuid, 'label' => $block_instance->label(), 'id' => $block_instance->getPluginId(), 'region' => $form_state->getValue('region'), 'html' => $this->renderer->render($build)]; // Add Block metadata and HTML as a drupalSetting. // @todo How do we handle #attachments in the $build this way? $form['#attached']['drupalSettings']['panels_ipe']['updated_block'] = $settings; return $form; }
/** * Loads and renders a view via AJAX. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * * @return \Drupal\views\Ajax\ViewAjaxResponse * The view response as ajax response. * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * Thrown when the view was not found. */ public function ajaxView(Request $request) { $name = $request->request->get('view_name'); $display_id = $request->request->get('view_display_id'); if (isset($name) && isset($display_id)) { $args = $request->request->get('view_args'); $args = isset($args) && $args !== '' ? explode('/', $args) : array(); // Arguments can be empty, make sure they are passed on as NULL so that // argument validation is not triggered. $args = array_map(function ($arg) { return $arg == '' ? NULL : $arg; }, $args); $path = $request->request->get('view_path'); $dom_id = $request->request->get('view_dom_id'); $dom_id = isset($dom_id) ? preg_replace('/[^a-zA-Z0-9_-]+/', '-', $dom_id) : NULL; $pager_element = $request->request->get('pager_element'); $pager_element = isset($pager_element) ? intval($pager_element) : NULL; $response = new ViewAjaxResponse(); // Remove all of this stuff from the query of the request so it doesn't // end up in pagers and tablesort URLs. foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids') as $key) { $request->query->remove($key); $request->request->remove($key); } // Load the view. if (!($entity = $this->storage->load($name))) { throw new NotFoundHttpException(); } $view = $this->executableFactory->get($entity); if ($view && $view->access($display_id)) { $response->setView($view); // Fix the current path for paging. if (!empty($path)) { $this->currentPath->setPath('/' . $path, $request); } // Add all POST data, because AJAX is always a post and many things, // such as tablesorts, exposed filters and paging assume GET. $request_all = $request->request->all(); $query_all = $request->query->all(); $request->query->replace($request_all + $query_all); // Overwrite the destination. // @see the redirect.destination service. $origin_destination = $path; $query = UrlHelper::buildQuery($request->query->all()); if ($query != '') { $origin_destination .= '?' . $query; } $this->redirectDestination->set($origin_destination); // Override the display's pager_element with the one actually used. if (isset($pager_element)) { $response->addCommand(new ScrollTopCommand(".view-dom-id-{$dom_id}")); $view->displayHandlers->get($display_id)->setOption('pager_element', $pager_element); } // Reuse the same DOM id so it matches that in drupalSettings. $view->dom_id = $dom_id; if ($preview = $view->preview($display_id, $args)) { $response->addCommand(new ReplaceCommand(".view-dom-id-{$dom_id}", $this->renderer->render($preview))); $response->setAttachments($preview['#attached']); } return $response; } else { throw new AccessDeniedHttpException(); } } else { throw new NotFoundHttpException(); } }
/** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { // The confirmation step needs no additional validation. if ($this->data) { return; } // Decode the submitted import. $data = Yaml::decode($form_state->getValue('import')); // Validate for config entities. if ($form_state->getValue('config_type') !== 'system.simple') { $definition = $this->entityManager->getDefinition($form_state->getValue('config_type')); $id_key = $definition->getKey('id'); // If a custom entity ID is specified, override the value in the // configuration data being imported. if (!$form_state->isValueEmpty('custom_entity_id')) { $data[$id_key] = $form_state->getValue('custom_entity_id'); } $entity_storage = $this->entityManager->getStorage($form_state->getValue('config_type')); // If an entity ID was not specified, set an error. if (!isset($data[$id_key])) { $form_state->setErrorByName('import', $this->t('Missing ID key "@id_key" for this @entity_type import.', array('@id_key' => $id_key, '@entity_type' => $definition->getLabel()))); return; } $config_name = $definition->getConfigPrefix() . '.' . $data[$id_key]; // If there is an existing entity, ensure matching ID and UUID. if ($entity = $entity_storage->load($data[$id_key])) { $this->configExists = $entity; if (!isset($data['uuid'])) { $form_state->setErrorByName('import', $this->t('An entity with this machine name already exists but the import did not specify a UUID.')); return; } if ($data['uuid'] !== $entity->uuid()) { $form_state->setErrorByName('import', $this->t('An entity with this machine name already exists but the UUID does not match.')); return; } } elseif (isset($data['uuid']) && $entity_storage->loadByProperties(array('uuid' => $data['uuid']))) { $form_state->setErrorByName('import', $this->t('An entity with this UUID already exists but the machine name does not match.')); } } else { $config_name = $form_state->getValue('config_name'); $config = $this->config($config_name); $this->configExists = !$config->isNew() ? $config : FALSE; } // Use ConfigImporter validation. if (!$form_state->getErrors()) { $source_storage = new StorageReplaceDataWrapper($this->configStorage); $source_storage->replaceData($config_name, $data); $storage_comparer = new StorageComparer($source_storage, $this->configStorage, $this->configManager); if (!$storage_comparer->createChangelist()->hasChanges()) { $form_state->setErrorByName('import', $this->t('There are no changes to import.')); } else { $config_importer = new ConfigImporter($storage_comparer, $this->eventDispatcher, $this->configManager, $this->lock, $this->typedConfigManager, $this->moduleHandler, $this->moduleInstaller, $this->themeHandler, $this->getStringTranslation()); try { $config_importer->validate(); $form_state->set('config_importer', $config_importer); } catch (ConfigImporterException $e) { // There are validation errors. $item_list = ['#theme' => 'item_list', '#items' => $config_importer->getErrors(), '#title' => $this->t('The configuration cannot be imported because it failed validation for the following reasons:')]; $form_state->setErrorByName('import', $this->renderer->render($item_list)); } } } // Store the decoded version of the submitted import. $form_state->setValueForElement($form['import'], $data); }
public function cacheableDomainObjectEarly() { $render_array = $this->earlyRenderContent(); $this->renderer->render($render_array); return new CacheableTestDomainObject(); }
/** * Gets an array of items for the field. * * @param \Drupal\views\ResultRow $values * The result row object containing the values. * * @return array * An array of items for the field. */ public function getItems(ResultRow $values) { $original_entity = $this->getEntity($values); if (!$original_entity) { return array(); } $entity = $this->process_entity($values, $original_entity); if (!$entity) { return array(); } $display = array('type' => $this->options['type'], 'settings' => $this->options['settings'], 'label' => 'hidden'); $render_array = $entity->get($this->definition['field_name'])->view($display); if ($this->options['field_api_classes']) { return array(array('rendered' => $this->renderer->render($render_array))); } $items = array(); foreach (Element::children($render_array) as $delta) { $items[$delta]['rendered'] = $render_array[$delta]; // Merge the cacheability metadata of the top-level render array into // each child because they will most likely be rendered individually. if (isset($render_array['#cache'])) { CacheableMetadata::createFromRenderArray($render_array)->merge(CacheableMetadata::createFromRenderArray($items[$delta]['rendered']))->applyTo($items[$delta]['rendered']); } // Add the raw field items (for use in tokens). $items[$delta]['raw'] = $render_array['#items'][$delta]; } return $items; }
/** * Gets an array of items for the field. * * @param \Drupal\views\ResultRow $values * The result row object containing the values. * * @return array * An array of items for the field. */ public function getItems(ResultRow $values) { if (!$this->displayHandler->useGroupBy()) { $build_list = $this->getEntityFieldRenderer()->render($values, $this); } else { // For grouped results we need to retrieve a massaged entity having // grouped field values to ensure that "grouped by" values, especially // those with multiple cardinality work properly. See // \Drupal\Tests\views\Kernel\QueryGroupByTest::testGroupByFieldWithCardinality. $display = ['type' => $this->options['type'], 'settings' => $this->options['settings'], 'label' => 'hidden']; // Some bundles might not have a specific field, in which case the faked // entity doesn't have it either. $entity = $this->createEntityForGroupBy($this->getEntity($values), $values); $build_list = isset($entity->{$this->definition['field_name']}) ? $entity->{$this->definition['field_name']}->view($display) : NULL; } if (!$build_list) { return []; } if ($this->options['field_api_classes']) { return [['rendered' => $this->renderer->render($build_list)]]; } // Render using the formatted data itself. $items = []; // Each item is extracted and rendered separately, the top-level formatter // render array itself is never rendered, so we extract its bubbleable // metadata and add it to each child individually. $bubbleable = BubbleableMetadata::createFromRenderArray($build_list); foreach (Element::children($build_list) as $delta) { BubbleableMetadata::createFromRenderArray($build_list[$delta])->merge($bubbleable)->applyTo($build_list[$delta]); $items[$delta] = ['rendered' => $build_list[$delta], 'raw' => $build_list['#items'][$delta]]; } return $items; }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { // Return early if there are any errors. if ($form_state->hasAnyErrors()) { return $form; } $block_instance = $this->getBlockInstance($form_state); // Submit the block configuration form. $this->submitBlock($block_instance, $form, $form_state); // If a temporary configuration for this variant exists, use it. $temp_store_key = $this->panelsDisplay->id(); if ($variant_config = $this->tempStore->get($temp_store_key)) { $this->panelsDisplay->setConfiguration($variant_config); } // Set the block region appropriately. $block_config = $block_instance->getConfiguration(); $block_config['region'] = $form_state->getValue(array('settings', 'region')); // Determine if we need to update or add this block. if ($uuid = $form_state->getValue('uuid')) { $this->panelsDisplay->updateBlock($uuid, $block_config); } else { $uuid = $this->panelsDisplay->addBlock($block_config); } // Set the tempstore value. $this->tempStore->set($this->panelsDisplay->id(), $this->panelsDisplay->getConfiguration()); // Assemble data required for our App. $build = $this->buildBlockInstance($block_instance); // Bubble block attributes up if possible. This allows modules like // Quickedit to function. // See \Drupal\block\BlockViewBuilder::preRender() for reference. if ($build['content'] !== NULL && !Element::isEmpty($build['content'])) { foreach (['#attributes', '#contextual_links'] as $property) { if (isset($build['content'][$property])) { $build[$property] += $build['content'][$property]; unset($build['content'][$property]); } } } // Add our data attribute for the Backbone app. $build['#attributes']['data-block-id'] = $uuid; $block_model = ['uuid' => $uuid, 'label' => $block_instance->label(), 'id' => $block_instance->getPluginId(), 'region' => $block_config['region'], 'html' => $this->renderer->render($build)]; $form['build'] = $build; // Add Block metadata and HTML as a drupalSetting. $form['#attached']['drupalSettings']['panels_ipe']['updated_block'] = $block_model; return $form; }