/** * {@inheritdoc} */ public function build() { $this->view->display_handler->preBlockBuild($this); if ($output = $this->view->buildRenderable($this->displayID, [], FALSE)) { // Override the label to the dynamic title configured in the view. if (empty($this->configuration['views_label']) && $this->view->getTitle()) { // @todo https://www.drupal.org/node/2527360 remove call to SafeMarkup. $output['#title'] = SafeMarkup::xssFilter($this->view->getTitle(), Xss::getAdminTagList()); } // Before returning the block output, convert it to a renderable array // with contextual links. $this->addContextualLinks($output); return $output; } return array(); }
/** * {@inheritdoc} */ public function process($text, $langcode) { $result = new FilterProcessResult($text); if (stristr($text, 'data-caption') !== FALSE) { $dom = Html::load($text); $xpath = new \DOMXPath($dom); foreach ($xpath->query('//*[@data-caption]') as $node) { // Read the data-caption attribute's value, then delete it. $caption = SafeMarkup::checkPlain($node->getAttribute('data-caption')); $node->removeAttribute('data-caption'); // Sanitize caption: decode HTML encoding, limit allowed HTML tags; only // allow inline tags that are allowed by default, plus <br>. $caption = Html::decodeEntities($caption); $caption = SafeMarkup::xssFilter($caption, array('a', 'em', 'strong', 'cite', 'code', 'br')); // The caption must be non-empty. if (Unicode::strlen($caption) === 0) { continue; } // Given the updated node and caption: re-render it with a caption, but // bubble up the value of the class attribute of the captioned element, // this allows it to collaborate with e.g. the filter_align filter. $classes = $node->getAttribute('class'); $node->removeAttribute('class'); $filter_caption = array('#theme' => 'filter_caption', '#node' => SafeMarkup::set($node->C14N()), '#tag' => $node->tagName, '#caption' => $caption, '#classes' => $classes); $altered_html = drupal_render($filter_caption); // Load the altered HTML into a new DOMDocument and retrieve the element. $updated_node = Html::load($altered_html)->getElementsByTagName('body')->item(0)->childNodes->item(0); // Import the updated node from the new DOMDocument into the original // one, importing also the child nodes of the updated node. $updated_node = $dom->importNode($updated_node, TRUE); // Finally, replace the original image node with the new image node! $node->parentNode->replaceChild($updated_node, $node); } $result->setProcessedText(Html::serialize($dom))->addAttachments(array('library' => array('filter/caption'))); } return $result; }
/** * Route title callback. * * @param \Drupal\taxonomy\TermInterface $taxonomy_term * The taxonomy term. * * @return string * The term label. */ public function termTitle(TermInterface $taxonomy_term) { return SafeMarkup::xssFilter($taxonomy_term->getName()); }
/** * Displays a listing of database log messages. * * Messages are truncated at 56 chars. * Full-length messages can be viewed on the message details page. * * @return array * A render array as expected by drupal_render(). * * @see dblog_clear_log_form() * @see dblog_event() */ public function overview() { $filter = $this->buildFilterQuery(); $rows = array(); $classes = static::getLogLevelClassMap(); $this->moduleHandler->loadInclude('dblog', 'admin.inc'); $build['dblog_filter_form'] = $this->formBuilder->getForm('Drupal\\dblog\\Form\\DblogFilterForm'); $build['dblog_clear_log_form'] = $this->formBuilder->getForm('Drupal\\dblog\\Form\\DblogClearLogForm'); $header = array('', array('data' => $this->t('Type'), 'field' => 'w.type', 'class' => array(RESPONSIVE_PRIORITY_MEDIUM)), array('data' => $this->t('Date'), 'field' => 'w.wid', 'sort' => 'desc', 'class' => array(RESPONSIVE_PRIORITY_LOW)), $this->t('Message'), array('data' => $this->t('User'), 'field' => 'ufd.name', 'class' => array(RESPONSIVE_PRIORITY_MEDIUM)), array('data' => $this->t('Operations'), 'class' => array(RESPONSIVE_PRIORITY_LOW))); $query = $this->database->select('watchdog', 'w')->extend('\\Drupal\\Core\\Database\\Query\\PagerSelectExtender')->extend('\\Drupal\\Core\\Database\\Query\\TableSortExtender'); $query->fields('w', array('wid', 'uid', 'severity', 'type', 'timestamp', 'message', 'variables', 'link')); $query->leftJoin('users_field_data', 'ufd', 'w.uid = ufd.uid'); if (!empty($filter['where'])) { $query->where($filter['where'], $filter['args']); } $result = $query->limit(50)->orderByHeader($header)->execute(); foreach ($result as $dblog) { $message = $this->formatMessage($dblog); if ($message && isset($dblog->wid)) { // Truncate link_text to 56 chars of message. // @todo Reevaluate the SafeMarkup::set() in // https://www.drupal.org/node/2399261. $log_text = SafeMarkup::set(Unicode::truncate(Xss::filter($message, array()), 56, TRUE, TRUE)); $message = $this->l($log_text, new Url('dblog.event', array('event_id' => $dblog->wid), array('attributes' => array('title' => Unicode::truncate(strip_tags($message), 256, TRUE, TRUE))))); } $username = array('#theme' => 'username', '#account' => $this->userStorage->load($dblog->uid)); $rows[] = array('data' => array(array('class' => array('icon')), $this->t($dblog->type), $this->dateFormatter->format($dblog->timestamp, 'short'), $message, array('data' => $username), SafeMarkup::xssFilter($dblog->link)), 'class' => array(Html::getClass('dblog-' . $dblog->type), $classes[$dblog->severity])); } $build['dblog_table'] = array('#type' => 'table', '#header' => $header, '#rows' => $rows, '#attributes' => array('id' => 'admin-dblog', 'class' => array('admin-dblog')), '#empty' => $this->t('No log messages available.'), '#attached' => array('library' => array('dblog/drupal.dblog'))); $build['dblog_pager'] = array('#type' => 'pager'); return $build; }
/** * Route title callback. * * @param \Drupal\system\MenuInterface $menu * The menu entity. * * @return string * The menu label. */ public function menuTitle(MenuInterface $menu) { return SafeMarkup::xssFilter($menu->label()); }
/** * Route title callback. * * @param \Drupal\user\UserInterface $user * The user account. * * @return string * The user account name. */ public function userTitle(UserInterface $user = NULL) { return $user ? SafeMarkup::xssFilter($user->getUsername()) : ''; }
/** * Route title callback. * * @param \Drupal\aggregator\FeedInterface $aggregator_feed * The aggregator feed. * * @return string * The feed label. */ public function feedTitle(FeedInterface $aggregator_feed) { return SafeMarkup::xssFilter($aggregator_feed->label()); }
/** * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::execute(). */ public function execute() { parent::execute(); // And now render the view. $render = $this->view->render(); // First execute the view so it's possible to get tokens for the title. // And the title, which is much easier. // @todo Figure out how to support custom response objects. Maybe for pages // it should be dropped. if (is_array($render)) { $render += array('#title' => SafeMarkup::xssFilter($this->view->getTitle(), Xss::getAdminTagList())); } return $render; }
/** * Generates an overview table of older revisions of a node. * * @param \Drupal\node\NodeInterface $node * A node object. * * @return array * An array as expected by drupal_render(). */ public function revisionOverview(NodeInterface $node) { $account = $this->currentUser(); $node_storage = $this->entityManager()->getStorage('node'); $type = $node->getType(); $build = array(); $build['#title'] = $this->t('Revisions for %title', array('%title' => $node->label())); $header = array($this->t('Revision'), $this->t('Operations')); $revert_permission = ($account->hasPermission("revert {$type} revisions") || $account->hasPermission('revert all revisions') || $account->hasPermission('administer nodes')) && $node->access('update'); $delete_permission = ($account->hasPermission("delete {$type} revisions") || $account->hasPermission('delete all revisions') || $account->hasPermission('administer nodes')) && $node->access('delete'); $rows = array(); $vids = $node_storage->revisionIds($node); foreach (array_reverse($vids) as $vid) { $revision = $node_storage->loadRevision($vid); $username = ['#theme' => 'username', '#account' => $revision->uid->entity]; // Use revision link to link to revisions that are not active. $date = $this->dateFormatter->format($revision->revision_timestamp->value, 'short'); if ($vid != $node->getRevisionId()) { $link = $this->l($date, new Url('entity.node.revision', ['node' => $node->id(), 'node_revision' => $vid])); } else { $link = $node->link($date); } $row = []; $column = ['data' => ['#type' => 'inline_template', '#template' => '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}', '#context' => ['date' => $link, 'username' => $this->renderer->renderPlain($username), 'message' => SafeMarkup::xssFilter($revision->revision_log->value)]]]; // @todo Simplify once https://www.drupal.org/node/2334319 lands. $this->renderer->addCacheableDependency($column['data'], $username); $row[] = $column; if ($vid == $node->getRevisionId()) { $row[0]['class'] = ['revision-current']; $row[] = ['data' => SafeMarkup::placeholder($this->t('current revision')), 'class' => ['revision-current']]; } else { $links = []; if ($revert_permission) { $links['revert'] = ['title' => $this->t('Revert'), 'url' => Url::fromRoute('node.revision_revert_confirm', ['node' => $node->id(), 'node_revision' => $vid])]; } if ($delete_permission) { $links['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('node.revision_delete_confirm', ['node' => $node->id(), 'node_revision' => $vid])]; } $row[] = ['data' => ['#type' => 'operations', '#links' => $links]]; } $rows[] = $row; } $build['node_revisions_table'] = array('#theme' => 'table', '#rows' => $rows, '#header' => $header, '#attached' => array('library' => array('node/drupal.node.admin'))); return $build; }