/** * Tests the integration. */ public function testIntegration() { // Remove the watchdog entries added by the potential batch process. $this->container->get('database')->truncate('watchdog')->execute(); $entries = array(); // Setup a watchdog entry without tokens. $entries[] = array('message' => $this->randomMachineName(), 'variables' => array('link' => \Drupal::l('Link', new Url('<front>')))); // Setup a watchdog entry with one token. $entries[] = array('message' => '@token1', 'variables' => array('@token1' => $this->randomMachineName(), 'link' => \Drupal::l('Link', new Url('<front>')))); // Setup a watchdog entry with two tokens. $entries[] = array('message' => '@token1 !token2', 'variables' => array('@token1' => $this->randomMachineName(), '!token2' => $this->randomMachineName(), 'link' => \Drupal::l(SafeMarkup::set('<object>Link</object>'), new Url('<front>')))); $logger_factory = $this->container->get('logger.factory'); foreach ($entries as $entry) { $entry += array('type' => 'test-views', 'severity' => RfcLogLevel::NOTICE); $logger_factory->get($entry['type'])->log($entry['severity'], $entry['message'], $entry['variables']); } $view = Views::getView('test_dblog'); $this->executeView($view); $view->initStyle(); foreach ($entries as $index => $entry) { $this->assertEqual($view->style_plugin->getField($index, 'message'), SafeMarkup::format($entry['message'], $entry['variables'])); $this->assertEqual($view->style_plugin->getField($index, 'link'), Xss::filterAdmin($entry['variables']['link'])); } // Disable replacing variables and check that the tokens aren't replaced. $view->destroy(); $view->storage->invalidateCaches(); $view->initHandlers(); $this->executeView($view); $view->initStyle(); $view->field['message']->options['replace_variables'] = FALSE; foreach ($entries as $index => $entry) { $this->assertEqual($view->style_plugin->getField($index, 'message'), $entry['message']); } }
/** * Tests the generation of all system site information tokens. */ public function testSystemSiteTokenReplacement() { $url_options = array('absolute' => TRUE, 'language' => $this->interfaceLanguage); $slogan = '<blink>Slogan</blink>'; $safe_slogan = Xss::filterAdmin($slogan); // Set a few site variables. $config = $this->config('system.site'); $config->set('name', '<strong>Drupal<strong>')->set('slogan', $slogan)->set('mail', '*****@*****.**')->save(); // Generate and test tokens. $tests = array(); $tests['[site:name]'] = Html::escape($config->get('name')); $tests['[site:slogan]'] = $safe_slogan; $tests['[site:mail]'] = $config->get('mail'); $tests['[site:url]'] = \Drupal::url('<front>', [], $url_options); $tests['[site:url-brief]'] = preg_replace(array('!^https?://!', '!/$!'), '', \Drupal::url('<front>', [], $url_options)); $tests['[site:login-url]'] = \Drupal::url('user.page', [], $url_options); $base_bubbleable_metadata = new BubbleableMetadata(); $metadata_tests = []; $metadata_tests['[site:name]'] = BubbleableMetadata::createFromObject(\Drupal::config('system.site')); $metadata_tests['[site:slogan]'] = BubbleableMetadata::createFromObject(\Drupal::config('system.site')); $metadata_tests['[site:mail]'] = BubbleableMetadata::createFromObject(\Drupal::config('system.site')); $bubbleable_metadata = clone $base_bubbleable_metadata; $metadata_tests['[site:url]'] = $bubbleable_metadata->addCacheContexts(['url.site']); $metadata_tests['[site:url-brief]'] = $bubbleable_metadata; $metadata_tests['[site:login-url]'] = $bubbleable_metadata; // Test to make sure that we generated something for each token. $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.'); foreach ($tests as $input => $expected) { $bubbleable_metadata = new BubbleableMetadata(); $output = $this->tokenService->replace($input, array(), array('langcode' => $this->interfaceLanguage->getId()), $bubbleable_metadata); $this->assertEqual($output, $expected, new FormattableMarkup('System site information token %token replaced.', ['%token' => $input])); $this->assertEqual($bubbleable_metadata, $metadata_tests[$input]); } }
/** * {@inheritdoc} */ public function buildRow(EntityInterface $entity) { $row = array(); $row['title'] = array('data' => $this->getLabel($entity), 'class' => array('menu-label')); $row['description'] = Xss::filterAdmin($entity->description); return $row + parent::buildRow($entity); }
/** * Redirects on 403 Access Denied kernel exceptions. * * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $event * The Event to process. */ public function onKernelException(GetResponseEvent $event) { $exception = $event->getException(); if (!$exception instanceof AccessDeniedHttpException) { return; } $config = $this->configFactory->get('r4032login.settings'); $options = array(); $options['query'] = $this->redirectDestination->getAsArray(); $options['absolute'] = TRUE; $code = $config->get('default_redirect_code'); if ($this->currentUser->isAnonymous()) { // Show custom access denied message if set. if ($config->get('display_denied_message')) { $message = $config->get('access_denied_message'); $message_type = $config->get('access_denied_message_type'); drupal_set_message(Xss::filterAdmin($message), $message_type); } // Handle redirection to the login form. $login_route = $config->get('user_login_route'); $url = Url::fromRoute($login_route, array(), $options)->toString(); $response = new RedirectResponse($url, $code); $event->setResponse($response); } else { // Check to see if we are to redirect the user. $redirect = $config->get('redirect_authenticated_users_to'); if ($redirect) { // Custom access denied page for logged in users. $url = Url::fromUserInput($redirect, $options)->toString(); $response = new RedirectResponse($url, $code); $event->setResponse($response); } } }
/** * Overrides \Drupal\views\Plugin\views\style\StylePluginBase\StylePluginBase::render(). */ public function render() { if (!empty($this->view->live_preview)) { return parent::render(); } // Group the rows according to the grouping field, if specified. $sets = $this->renderGrouping($this->view->result, $this->options['grouping']); // Grab the alias of the 'id' field added by // entity_reference_plugin_display. $id_field_alias = $this->view->storage->get('base_field'); // @todo We don't display grouping info for now. Could be useful for select // widget, though. $results = array(); $this->view->row_index = 0; foreach ($sets as $records) { foreach ($records as $values) { // Sanitize HTML, remove line breaks and extra whitespace. $output = $this->view->rowPlugin->render($values); $output = drupal_render($output); $results[$values->{$id_field_alias}] = Xss::filterAdmin(preg_replace('/\\s\\s+/', ' ', str_replace("\n", '', $output))); $this->view->row_index++; } } unset($this->view->row_index); return $results; }
/** * {@inheritdoc} */ public function completeSale($order, $login = FALSE) { // Empty that cart... $this->emptyCart(); // Force the order to load from the DB instead of the entity cache. // @todo Remove this once uc_payment_enter() can modify order objects? // @todo Should we be overwriting $order with this newly-loaded db_order? $db_order = $this->entityManager()->getStorage('uc_order')->loadUnchanged($order->id()); $order->data = $db_order->data; // Ensure that user creation and triggers are only run once. if (empty($order->data->complete_sale)) { $this->completeSaleAccount($order); // Move an order's status from "In checkout" to "Pending". if ($order->getStateId() == 'in_checkout') { $order->setStatusId(uc_order_state_default('post_checkout')); } $order->save(); // Invoke the checkout complete trigger and hook. $account = $order->getUser(); $this->moduleHandler()->invokeAll('uc_checkout_complete', array($order, $account)); // rules_invoke_event('uc_checkout_complete', $order); } $type = $order->data->complete_sale; // Log in new users, if requested. if ($type == 'new_user' && $login && $this->currentUser()->isAnonymous()) { $type = 'new_user_logged_in'; user_login_finalize($order->getUser()); } $message = $this->config('uc_cart.messages')->get($type); $message = \Drupal::token()->replace($message, array('uc_order' => $order)); $variables['!new_username'] = isset($order->data->new_user_name) ? $order->data->new_user_name : ''; $variables['!new_password'] = isset($order->password) ? $order->password : t('Your password'); $message = strtr($message, $variables); return array('#theme' => 'uc_cart_complete_sale', '#message' => Xss::filterAdmin($message), '#order' => $order); }
/** * Tests the integration. */ public function testIntegration() { // Remove the watchdog entries added by the potential batch process. $this->container->get('database')->truncate('watchdog')->execute(); $entries = array(); // Setup a watchdog entry without tokens. $entries[] = array('message' => $this->randomMachineName(), 'variables' => array(), 'link' => l('Link', 'node/1')); // Setup a watchdog entry with one token. $entries[] = array('message' => '@token1', 'variables' => array('@token1' => $this->randomMachineName()), 'link' => l('Link', 'node/2')); // Setup a watchdog entry with two tokens. $entries[] = array('message' => '@token1 !token2', 'variables' => array('@token1' => $this->randomMachineName(), '!token2' => $this->randomMachineName()), 'link' => l('<object>Link</object>', 'node/2', array('html' => TRUE))); foreach ($entries as $entry) { $entry += array('type' => 'test-views', 'severity' => WATCHDOG_NOTICE); watchdog($entry['type'], $entry['message'], $entry['variables'], $entry['severity'], $entry['link']); } $view = Views::getView('test_dblog'); $this->executeView($view); $view->initStyle(); foreach ($entries as $index => $entry) { $this->assertEqual($view->style_plugin->getField($index, 'message'), String::format($entry['message'], $entry['variables'])); $this->assertEqual($view->style_plugin->getField($index, 'link'), Xss::filterAdmin($entry['link'])); } // Disable replacing variables and check that the tokens aren't replaced. $view->destroy(); $view->initHandlers(); $this->executeView($view); $view->initStyle(); $view->field['message']->options['replace_variables'] = FALSE; foreach ($entries as $index => $entry) { $this->assertEqual($view->style_plugin->getField($index, 'message'), $entry['message']); } }
/** * {@inheritdoc} */ public function execute($entity = NULL) { if (empty($this->configuration['node'])) { $this->configuration['node'] = $entity; } $message = $this->token->replace(Xss::filterAdmin($this->configuration['message']), $this->configuration); drupal_set_message($message); }
/** * {@inheritdoc} */ public function view(OrderInterface $order, array $form, FormStateInterface $form_state) { $contents['#description'] = Xss::filterAdmin(\Drupal::config('uc_quote.settings')->get('pane_description')); $contents['#attached']['library'][] = 'uc_quote/uc_quote.styles'; $contents['uid'] = array('#type' => 'hidden', '#value' => \Drupal::currentUser()->id()); $contents['quote_button'] = array('#type' => 'submit', '#value' => t('Click to calculate shipping'), '#submit' => [[$this, 'paneSubmit']], '#weight' => 0, '#ajax' => array('effect' => 'slide', 'progress' => array('type' => 'bar', 'message' => t('Receiving quotes...'))), '#limit_validation_errors' => array()); $contents['quotes'] = array('#tree' => TRUE, '#prefix' => '<div id="quote">', '#suffix' => '</div>', '#weight' => 1); $contents['quotes'] += $order->quote_form; $form_state->set(['uc_ajax', 'uc_quote', 'panes][quotes][quote_button'], array('payment-pane' => 'uc_ajax_replace_checkout_pane', 'quotes-pane' => 'uc_ajax_replace_checkout_pane')); $form_state->set(['uc_ajax', 'uc_quote', 'panes][quotes][quotes][quote_option'], array('payment-pane' => 'uc_ajax_replace_checkout_pane')); return $contents; }
/** * Pre-processes variables for the "bootstrap_panel" theme hook. * * See template for list of available variables. * * @see bootstrap-panel.html.twig * * @ingroup theme_preprocess */ function bootstrap_preprocess_bootstrap_panel(&$variables) { $element = $variables['element']; Element::setAttributes($element, array('id')); Element\RenderElement::setAttributes($element); $variables['attributes'] = $element['#attributes']; $variables['prefix'] = isset($element['#field_prefix']) ? $element['#field_prefix'] : NULL; $variables['suffix'] = isset($element['#field_suffix']) ? $element['#field_suffix'] : NULL; $variables['title_display'] = isset($element['#title_display']) ? $element['#title_display'] : NULL; $variables['children'] = $element['#children']; $variables['required'] = !empty($element['#required']) ? $element['#required'] : NULL; $variables['legend']['title'] = !empty($element['#title']) ? Xss::filterAdmin($element['#title']) : ''; $variables['legend']['attributes'] = new Attribute(); $variables['legend_span']['attributes'] = new Attribute(); if (!empty($element['#description'])) { $description_id = $element['#attributes']['id'] . '--description'; $description_attributes['id'] = $description_id; $variables['description']['attributes'] = new Attribute($description_attributes); $variables['description']['content'] = $element['#description']; // Add the description's id to the fieldset aria attributes. $variables['attributes']['aria-describedby'] = $description_id; } $variables['collapsible'] = FALSE; if (isset($element['#collapsible'])) { $variables['collapsible'] = $element['#collapsible']; $variables['attributes']['class'][] = 'collapsible'; } $variables['collapsed'] = FALSE; if (isset($element['#collapsed'])) { $variables['collapsed'] = $element['#collapsed']; } // Force grouped fieldsets to not be collapsible (for vertical tabs). if (!empty($element['#group'])) { $variables['collapsible'] = FALSE; $variables['collapsed'] = FALSE; } if (!isset($element['#id']) && $variables['collapsible']) { $element['#id'] = \Drupal\Component\Utility\Html::getUniqueId('bootstrap-panel'); } $variables['target'] = NULL; if (isset($element['#id'])) { if (!isset($variables['attributes']['id'])) { $variables['attributes']['id'] = $element['#id']; } $variables['target'] = '#' . $element['#id'] . ' > .collapse'; } // Iterate over optional variables. $keys = array('description', 'prefix', 'suffix', 'title', 'value'); foreach ($keys as $key) { $variables[$key] = !empty($element["#{$key}"]) ? $element["#{$key}"] : FALSE; } }
/** * Tests the generation of all system site information tokens. */ public function testSystemSiteTokenReplacement() { // The use of the \Drupal::url() method requires the url_alias table to exist. $this->installSchema('system', 'url_alias'); $url_options = array('absolute' => TRUE, 'language' => $this->interfaceLanguage); $slogan = '<blink>Slogan</blink>'; $safe_slogan = Xss::filterAdmin($slogan); // Set a few site variables. $config = $this->config('system.site'); $config->set('name', '<strong>Drupal<strong>')->set('slogan', $slogan)->set('mail', '*****@*****.**')->save(); // Generate and test sanitized tokens. $tests = array(); $tests['[site:name]'] = SafeMarkup::checkPlain($config->get('name')); $tests['[site:slogan]'] = $safe_slogan; $tests['[site:mail]'] = $config->get('mail'); $tests['[site:url]'] = \Drupal::url('<front>', [], $url_options); $tests['[site:url-brief]'] = preg_replace(array('!^https?://!', '!/$!'), '', \Drupal::url('<front>', [], $url_options)); $tests['[site:login-url]'] = \Drupal::url('user.page', [], $url_options); $base_bubbleable_metadata = new BubbleableMetadata(); $metadata_tests = []; $metadata_tests['[site:name]'] = BubbleableMetadata::createFromObject(\Drupal::config('system.site')); $metadata_tests['[site:slogan]'] = BubbleableMetadata::createFromObject(\Drupal::config('system.site')); $metadata_tests['[site:mail]'] = BubbleableMetadata::createFromObject(\Drupal::config('system.site')); $bubbleable_metadata = clone $base_bubbleable_metadata; $metadata_tests['[site:url]'] = $bubbleable_metadata->addCacheContexts(['url.site']); $metadata_tests['[site:url-brief]'] = $bubbleable_metadata; $metadata_tests['[site:login-url]'] = $bubbleable_metadata; // Test to make sure that we generated something for each token. $this->assertFalse(in_array(0, array_map('strlen', $tests)), 'No empty tokens generated.'); foreach ($tests as $input => $expected) { $bubbleable_metadata = new BubbleableMetadata(); $output = $this->tokenService->replace($input, array(), array('langcode' => $this->interfaceLanguage->getId()), $bubbleable_metadata); $this->assertEqual($output, $expected, format_string('Sanitized system site information token %token replaced.', array('%token' => $input))); $this->assertEqual($bubbleable_metadata, $metadata_tests[$input]); } // Generate and test unsanitized tokens. $tests['[site:name]'] = $config->get('name'); $tests['[site:slogan]'] = $config->get('slogan'); foreach ($tests as $input => $expected) { $output = $this->tokenService->replace($input, array(), array('langcode' => $this->interfaceLanguage->getId(), 'sanitize' => FALSE), $bubbleable_metadata); $this->assertEqual($output, $expected, format_string('Unsanitized system site information token %token replaced.', array('%token' => $input))); } // Check that the results of Token::generate are sanitized properly. This // does NOT test the cleanliness of every token -- just that the $sanitize // flag is being passed properly through the call stack and being handled // correctly by a 'known' token, [site:slogan]. $raw_tokens = array('slogan' => '[site:slogan]'); $generated = $this->tokenService->generate('site', $raw_tokens, [], [], $bubbleable_metadata); $this->assertEqual($generated['[site:slogan]'], $safe_slogan, 'Token sanitized.'); $generated = $this->tokenService->generate('site', $raw_tokens, array(), array('sanitize' => FALSE), $bubbleable_metadata); $this->assertEqual($generated['[site:slogan]'], $slogan, 'Unsanitized token generated properly.'); }
/** * {@inheritdoc} */ public function render(ResultRow $values) { $value = $this->getValue($values); if (!empty($this->options['not'])) { $value = !$value; } if ($this->options['type'] == 'custom') { return $value ? UtilityXss::filterAdmin($this->options['type_custom_true']) : UtilityXss::filterAdmin($this->options['type_custom_false']); } elseif (isset($this->formats[$this->options['type']])) { return $value ? $this->formats[$this->options['type']][0] : $this->formats[$this->options['type']][1]; } else { return $value ? $this->formats['yes-no'][0] : $this->formats['yes-no'][1]; } }
/** * Displays a list of product classes. */ public function classOverview() { $classes = \Drupal::entityManager()->getStorage('node_type')->loadByProperties(array('third_party_settings.uc_product.product' => TRUE)); $header = array($this->t('Class ID'), $this->t('Name'), $this->t('Description'), $this->t('Operations')); $rows = []; foreach ($classes as $class) { $links = []; $links['edit'] = array('title' => $this->t('Edit'), 'url' => Url::fromRoute('entity.node_type.edit_form', ['node_type' => $class->id()]), 'query' => array('destination' => 'admin/store/products/classes')); if (!$class->isLocked()) { $links['delete'] = array('title' => $this->t('Delete'), 'url' => Url::fromRoute('entity.node_type.delete_form', ['node_type' => $class->id()]), 'query' => array('destination' => 'admin/store/products/classes')); } $rows[] = array(SafeMarkup::checkPlain($class->id()), SafeMarkup::checkPlain($class->label()), Xss::filterAdmin($class->getDescription()), array('data' => array('#type' => 'operations', '#links' => $links))); } return array('#theme' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => $this->t('No product classes have been defined yet.')); }
/** * {@inheritdoc} */ public function build() { $this->view->display_handler->preBlockBuild($this); if ($output = $this->view->executeDisplay($this->displayID)) { // Override the label to the dynamic title configured in the view. if (empty($this->configuration['views_label']) && $this->view->getTitle()) { $output['#title'] = Xss::filterAdmin($this->view->getTitle()); } // Before returning the block output, convert it to a renderable array // with contextual links. $this->addContextualLinks($output); return $output; } return array(); }
/** * {@inheritdoc} */ public function render(ResultRow $values) { $value = $this->getValue($values); if (!empty($this->options['not'])) { $value = !$value; } if ($this->options['type'] == 'custom') { $custom_value = $value ? $this->options['type_custom_true'] : $this->options['type_custom_false']; return ViewsRenderPipelineMarkup::create(UtilityXss::filterAdmin($custom_value)); } elseif (isset($this->formats[$this->options['type']])) { return $value ? $this->formats[$this->options['type']][0] : $this->formats[$this->options['type']][1]; } else { return $value ? $this->formats['yes-no'][0] : $this->formats['yes-no'][1]; } }
/** * {@inheritdoc} */ public function buildRow(EntityInterface $entity) { /** @var \Drupal\eform\Entity\EFormType $entity */ $row['title'] = array( 'data' => $entity->getSubmitLink(), 'class' => array('menu-label'), ); // @todo add getDescription to eform_type $row['description'] = Xss::filterAdmin($entity->getDescription()); $url = Url::fromRoute('entity.eform_type.submissions', ['eform_type' => $entity->id()]); $row += parent::buildRow($entity); // @todo Is there a better way to get the l function here? $row['submissions'] = \Drupal::l('Submissions', $url); return $row; }
/** * Overrides \Drupal\views\Plugin\views\display\PathPluginBase::execute(). */ public function execute() { parent::execute(); // Let the world know that this is the page view we're using. views_set_page_view($this->view); // 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' => Xss::filterAdmin($this->view->getTitle())); } return $render; }
/** * Shows the status of all required packages. * * @return array * Returns a render array as expected by drupal_render(). */ public function page() { if (!composer_manager_initialized()) { $message = t("Composer Manager needs to be initialized before usage. Run the module's <code>init.sh</code> script or <code>drush composer-manager-init</code> on the command line."); drupal_set_message($message, 'warning'); return array(); } try { $packages = $this->packageManager->getRequiredPackages(); } catch (\RuntimeException $e) { drupal_set_message(Xss::filterAdmin($e->getMessage()), 'error'); $packages = array(); } $rows = array(); foreach ($packages as $package_name => $package) { // Prepare the package name and description. if (!empty($package['homepage'])) { $options = array('attributes' => array('target' => '_blank')); $name = $this->l($package_name, Url::fromUri($package['homepage']), $options); } else { $name = SafeMarkup::checkPlain($package_name); } if (!empty($package['description'])) { $name .= '<div class="description">' . SafeMarkup::checkPlain($package['description']) . '</div>'; } // Prepare the installed and required versions. $installed_version = $package['version'] ? $package['version'] : $this->t('Not installed'); $required_version = $this->buildRequiredVersion($package['constraint'], $package['required_by']); // Prepare the row classes. $class = array(); if (empty($package['version'])) { $class[] = 'error'; } elseif (empty($package['required_by'])) { $class[] = 'warning'; } $rows[$package_name] = array('class' => $class, 'data' => array('package' => SafeMarkup::set($name), 'installed_version' => $installed_version, 'required_version' => SafeMarkup::set($required_version))); } $build = array(); $build['packages'] = array('#theme' => 'table', '#header' => array('package' => $this->t('Package'), 'installed_version' => $this->t('Installed Version'), 'required_version' => $this->t('Required Version')), '#rows' => $rows, '#caption' => $this->t('Status of Packages Managed by Composer'), '#attributes' => array('class' => array('system-status-report'))); // Display any errors returned by hook_requirements(). $this->moduleHandler->loadInclude('composer_manager', 'install'); $requirements = composer_manager_requirements('runtime'); if ($requirements['composer_manager']['severity'] == REQUIREMENT_ERROR) { drupal_set_message($requirements['composer_manager']['description'], 'warning'); } return $build; }
/** * Shows the status of all required packages. * * @return array * Returns a render array as expected by drupal_render(). */ public function page() { if (!composer_manager_initialized()) { $message = t("Composer Manager needs to be initialized before usage. Run the module's <code>init.php</code> script on the command line."); drupal_set_message($message, 'warning'); return []; } try { $packages = $this->packageManager->getRequiredPackages(); } catch (\RuntimeException $e) { drupal_set_message(Xss::filterAdmin($e->getMessage()), 'error'); return []; } $rows = []; foreach ($packages as $package_name => $package) { $package_column = []; if (!empty($package['homepage'])) { $package_column[] = ['#type' => 'link', '#title' => $package_name, '#url' => Url::fromUri($package['homepage']), '#options' => ['attributes' => ['target' => '_blank']]]; } else { $package_column[] = ['#plain_text' => $package_name]; } if (!empty($package['description'])) { $package_column[] = ['#prefix' => '<div class="description">', '#plain_text' => $package['description'], '#suffix' => '</div>']; } // Prepare the installed and required versions. $installed_version = $package['version'] ? $package['version'] : $this->t('Not installed'); $required_version = $this->buildRequiredVersion($package['constraint'], $package['required_by']); // Prepare the row classes. $class = []; if (empty($package['version'])) { $class[] = 'error'; } elseif (empty($package['required_by'])) { $class[] = 'warning'; } $rows[$package_name] = ['class' => $class, 'data' => ['package' => ['data' => $package_column], 'installed_version' => $installed_version, 'required_version' => ['data' => $required_version]]]; } $build = []; $build['packages'] = ['#theme' => 'table', '#header' => ['package' => $this->t('Package'), 'installed_version' => $this->t('Installed Version'), 'required_version' => $this->t('Required Version')], '#rows' => $rows, '#caption' => $this->t('Status of Packages Managed by Composer'), '#attributes' => ['class' => ['system-status-report']]]; // Display any errors returned by hook_requirements(). $this->moduleHandler->loadInclude('composer_manager', 'install'); $requirements = composer_manager_requirements('runtime'); if ($requirements['composer_manager']['severity'] == REQUIREMENT_ERROR) { drupal_set_message($requirements['composer_manager']['description'], 'warning'); } return $build; }
/** * Tests the integration. */ public function testIntegration() { // Remove the watchdog entries added by the potential batch process. $this->container->get('database')->truncate('watchdog')->execute(); $entries = array(); // Setup a watchdog entry without tokens. $entries[] = array('message' => $this->randomMachineName(), 'variables' => array('link' => \Drupal::l('Link', new Url('<front>')))); // Setup a watchdog entry with one token. $entries[] = array('message' => '@token1', 'variables' => array('@token1' => $this->randomMachineName(), 'link' => \Drupal::l('Link', new Url('<front>')))); // Setup a watchdog entry with two tokens. $entries[] = array('message' => '@token1 @token2', 'variables' => array('@token1' => $this->randomMachineName(), '@token2' => $this->randomMachineName(), 'link' => '<a href="' . \Drupal::url('<front>') . '"><object>Link</object></a>')); $logger_factory = $this->container->get('logger.factory'); foreach ($entries as $entry) { $entry += array('type' => 'test-views', 'severity' => RfcLogLevel::NOTICE); $logger_factory->get($entry['type'])->log($entry['severity'], $entry['message'], $entry['variables']); } $view = Views::getView('test_dblog'); $this->executeView($view); $view->initStyle(); foreach ($entries as $index => $entry) { $this->assertEqual($view->style_plugin->getField($index, 'message'), SafeMarkup::format($entry['message'], $entry['variables'])); $link_field = $view->style_plugin->getField($index, 'link'); // The 3rd entry contains some unsafe markup that needs to get filtered. if ($index == 2) { // Make sure that unsafe link differs from the rendered link, so we know // that some filtering actually happened. $this->assertNotEqual($link_field, $entry['variables']['link']); } $this->assertEqual($link_field, Xss::filterAdmin($entry['variables']['link'])); } // Disable replacing variables and check that the tokens aren't replaced. $view->destroy(); $view->storage->invalidateCaches(); $view->initHandlers(); $this->executeView($view); $view->initStyle(); $view->field['message']->options['replace_variables'] = FALSE; foreach ($entries as $index => $entry) { $this->assertEqual($view->style_plugin->getField($index, 'message'), $entry['message']); } }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, OrderInterface $uc_order = NULL) { $this->order = $uc_order; $form['#attached']['library'][] = 'uc_payment/uc_payment.styles'; $total = $this->order->getTotal(); $payments = uc_payment_load_payments($this->order->id()); $form['order_total'] = array('#type' => 'item', '#title' => $this->t('Order total'), '#theme' => 'uc_price', '#price' => $total); $form['payments'] = array('#type' => 'table', '#tree' => TRUE, '#header' => array($this->t('Received'), $this->t('User'), $this->t('Method'), $this->t('Amount'), $this->t('Balance'), $this->t('Comment'), $this->t('Action')), '#weight' => 10); $account = \Drupal::currentUser(); if ($payments !== FALSE) { foreach ($payments as $payment) { $form['payments'][$payment->receipt_id]['received'] = array('#markup' => \Drupal::service('date.formatter')->format($payment->received, 'short')); $markup = array('#theme' => 'uc_uid', '#uid' => $payment->uid); $form['payments'][$payment->receipt_id]['user'] = array('#markup' => drupal_render($markup)); $form['payments'][$payment->receipt_id]['method'] = array('#markup' => $payment->method == '' ? $this->t('Unknown') : $payment->method); $form['payments'][$payment->receipt_id]['amount'] = array('#theme' => 'uc_price', '#price' => $payment->amount); $total -= $payment->amount; $form['payments'][$payment->receipt_id]['balance'] = array('#theme' => 'uc_price', '#price' => $total); $form['payments'][$payment->receipt_id]['comment'] = array('#markup' => $payment->comment == '' ? '-' : Xss::filterAdmin($payment->comment)); if ($account->hasPermission('delete payments')) { $action_value = $this->l($this->t('Delete'), new Url('uc_payments.delete', ['uc_order' => $this->order->id(), 'payment' => $payment->receipt_id])); } else { $action_value = '-'; } $form['payments'][$payment->receipt_id]['action'] = array('#markup' => $action_value); } } $form['balance'] = array('#type' => 'item', '#title' => t('Current balance'), '#theme' => 'uc_price', '#price' => $total); if ($account->hasPermission('manual payments')) { $form['payments']['new']['received'] = array('#type' => 'date', '#default_value' => array('month' => \Drupal::service('date.formatter')->format(REQUEST_TIME, 'custom', 'n'), 'day' => \Drupal::service('date.formatter')->format(REQUEST_TIME, 'custom', 'j'), 'year' => \Drupal::service('date.formatter')->format(REQUEST_TIME, 'custom', 'Y'))); $form['payments']['new']['user'] = array('#markup' => '-'); $form['payments']['new']['method'] = array('#type' => 'select', '#title' => t('Method'), '#title_display' => 'invisible', '#options' => $this->paymentMethodManager->listOptions()); $form['payments']['new']['amount'] = array('#type' => 'textfield', '#title' => t('Amount'), '#title_display' => 'invisible', '#size' => 6); $form['payments']['new']['balance'] = array('#markup' => '-'); $form['payments']['new']['comment'] = array('#type' => 'textfield', '#title' => $this->t('Comment'), '#title_display' => 'invisible', '#size' => 32, '#maxlength' => 256); $form['payments']['new']['action'] = array('#type' => 'actions'); $form['payments']['new']['action']['action'] = array('#type' => 'submit', '#value' => $this->t('Enter')); } return $form; }
/** * Test if the title of the site is XSS proof. */ function testTitleXSS() { // Set some title with JavaScript and HTML chars to escape. $title = '</title><script type="text/javascript">alert("Title XSS!");</script> & < > " \' '; $title_filtered = Html::escape($title); $slogan = '<script type="text/javascript">alert("Slogan XSS!");</script>'; $slogan_filtered = Xss::filterAdmin($slogan); // Set title and slogan. $edit = array('site_name' => $title, 'site_slogan' => $slogan); $this->drupalPostForm('admin/config/system/site-information', $edit, t('Save configuration')); // Place branding block with site name and slogan into header region. $this->drupalPlaceBlock('system_branding_block', ['region' => 'header']); // Load frontpage. $this->drupalGet(''); // Test the title. $this->assertNoRaw($title, 'Check for the lack of the unfiltered version of the title.'); // Add </title> to make sure we're checking the title tag, rather than the // first 'heading' on the page. $this->assertRaw($title_filtered . '</title>', 'Check for the filtered version of the title in a <title> tag.'); // Test the slogan. $this->assertNoRaw($slogan, 'Check for the unfiltered version of the slogan.'); $this->assertRaw($slogan_filtered, 'Check for the filtered version of the slogan.'); }
/** * Test if the title of the site is XSS proof. */ function testTitleXSS() { // Set some title with JavaScript and HTML chars to escape. $title = '</title><script type="text/javascript">alert("Title XSS!");</script> & < > " \' '; $title_filtered = String::checkPlain($title); $slogan = '<script type="text/javascript">alert("Slogan XSS!");</script>'; $slogan_filtered = Xss::filterAdmin($slogan); // Activate needed appearance settings. $edit = array('toggle_name' => TRUE, 'toggle_slogan' => TRUE); $this->drupalPostForm('admin/appearance/settings', $edit, t('Save configuration')); // Set title and slogan. $edit = array('site_name' => $title, 'site_slogan' => $slogan); $this->drupalPostForm('admin/config/system/site-information', $edit, t('Save configuration')); // Load frontpage. $this->drupalGet(''); // Test the title. $this->assertNoRaw($title, 'Check for the lack of the unfiltered version of the title.'); // Add </title> to make sure we're checking the title tag, rather than the // first 'heading' on the page. $this->assertRaw($title_filtered . '</title>', 'Check for the filtered version of the title in a <title> tag.'); // Test the slogan. $this->assertNoRaw($slogan, 'Check for the unfiltered version of the slogan.'); $this->assertRaw($slogan_filtered, 'Check for the filtered version of the slogan.'); }
/** * Take a value and apply token replacement logic to it. */ public function tokenizeValue($value, $row_index) { if (strpos($value, '{{') !== FALSE) { // Row tokens might be empty, for example for node row style. $tokens = isset($this->rowTokens[$row_index]) ? $this->rowTokens[$row_index] : array(); if (!empty($this->view->build_info['substitutions'])) { $tokens += $this->view->build_info['substitutions']; } $value = $this->viewsTokenReplace($value, $tokens); } else { // ::viewsTokenReplace() will run Xss::filterAdmin on the // resulting string. We do the same here for consistency. $value = Xss::filterAdmin($value); } return $value; }
/** * Pre-render callback: Renders #browsers into #prefix and #suffix. * * @param array $element * A render array with a '#browsers' property. The '#browsers' property can * contain any or all of the following keys: * - 'IE': If FALSE, the element is not rendered by Internet Explorer. If * TRUE, the element is rendered by Internet Explorer. Can also be a string * containing an expression for Internet Explorer to evaluate as part of a * conditional comment. For example, this can be set to 'lt IE 7' for the * element to be rendered in Internet Explorer 6, but not in Internet * Explorer 7 or higher. Defaults to TRUE. * - '!IE': If FALSE, the element is not rendered by browsers other than * Internet Explorer. If TRUE, the element is rendered by those browsers. * Defaults to TRUE. * Examples: * - To render an element in all browsers, '#browsers' can be left out or set * to array('IE' => TRUE, '!IE' => TRUE). * - To render an element in Internet Explorer only, '#browsers' can be set * to array('!IE' => FALSE). * - To render an element in Internet Explorer 6 only, '#browsers' can be set * to array('IE' => 'lt IE 7', '!IE' => FALSE). * - To render an element in Internet Explorer 8 and higher and in all other * browsers, '#browsers' can be set to array('IE' => 'gte IE 8'). * * @return array * The passed-in element with markup for conditional comments potentially * added to '#prefix' and '#suffix'. */ public static function preRenderConditionalComments($element) { $browsers = isset($element['#browsers']) ? $element['#browsers'] : array(); $browsers += array('IE' => TRUE, '!IE' => TRUE); // If rendering in all browsers, no need for conditional comments. if ($browsers['IE'] === TRUE && $browsers['!IE']) { return $element; } // Determine the conditional comment expression for Internet Explorer to // evaluate. if ($browsers['IE'] === TRUE) { $expression = 'IE'; } elseif ($browsers['IE'] === FALSE) { $expression = '!IE'; } else { // The IE expression might contain some user input data. $expression = Xss::filterAdmin($browsers['IE']); } // If the #prefix and #suffix properties are used, wrap them with // conditional comment markup. The conditional comment expression is // evaluated by Internet Explorer only. To control the rendering by other // browsers, use either the "downlevel-hidden" or "downlevel-revealed" // technique. See http://en.wikipedia.org/wiki/Conditional_comment // for details. // Ensure what we are dealing with is safe. // This would be done later anyway in drupal_render(). $prefix = isset($element['#prefix']) ? $element['#prefix'] : ''; if ($prefix && !SafeMarkup::isSafe($prefix)) { $prefix = Xss::filterAdmin($prefix); } $suffix = isset($element['#suffix']) ? $element['#suffix'] : ''; if ($suffix && !SafeMarkup::isSafe($suffix)) { $suffix = Xss::filterAdmin($suffix); } // We ensured above that $expression is either a string we created or is // admin XSS filtered, and that $prefix and $suffix are also admin XSS // filtered if they are unsafe. Thus, all these strings are safe. if (!$browsers['!IE']) { // "downlevel-hidden". $element['#prefix'] = Markup::create("\n<!--[if {$expression}]>\n" . $prefix); $element['#suffix'] = Markup::create($suffix . "<![endif]-->\n"); } else { // "downlevel-revealed". $element['#prefix'] = Markup::create("\n<!--[if {$expression}]><!-->\n" . $prefix); $element['#suffix'] = Markup::create($suffix . "<!--<![endif]-->\n"); } return $element; }
/** * Render this field as a link, with the info from a fieldset set by * the user. */ protected function renderAsLink($alter, $text, $tokens) { $value = ''; if (!empty($alter['prefix'])) { $value .= Xss::filterAdmin(strtr($alter['prefix'], $tokens)); } $options = array('html' => TRUE, 'absolute' => !empty($alter['absolute']) ? TRUE : FALSE); // $path will be run through check_url() by l() so we do not need to // sanitize it ourselves. $path = $alter['path']; // strip_tags() removes <front>, so check whether its different to front. if ($path != '<front>') { // Use strip tags as there should never be HTML in the path. // However, we need to preserve special characters like " that // were removed by String::checkPlain(). $path = strip_tags(decode_entities(strtr($path, $tokens))); if (!empty($alter['path_case']) && $alter['path_case'] != 'none') { $path = $this->caseTransform($path, $this->options['alter']['path_case']); } if (!empty($alter['replace_spaces'])) { $path = str_replace(' ', '-', $path); } } // Parse the URL and move any query and fragment parameters out of the path. $url = parse_url($path); // Seriously malformed URLs may return FALSE or empty arrays. if (empty($url)) { return $text; } // If the path is empty do not build a link around the given text and return // it as is. // http://www.example.com URLs will not have a $url['path'], so check host as well. if (empty($url['path']) && empty($url['host']) && empty($url['fragment'])) { return $text; } // If no scheme is provided in the $path, assign the default 'http://'. // This allows a url of 'www.example.com' to be converted to 'http://www.example.com'. // Only do this on for external URLs. if ($alter['external']) { if (!isset($url['scheme'])) { // There is no scheme, add the default 'http://' to the $path. $path = "http://{$path}"; // Reset the $url array to include the new scheme. $url = parse_url($path); } } if (isset($url['query'])) { $path = strtr($path, array('?' . $url['query'] => '')); $query = array(); parse_str($url['query'], $query); // Remove query parameters that were assigned a query string replacement // token for which there is no value available. foreach ($query as $param => $val) { if ($val == '%' . $param) { unset($query[$param]); } } $options['query'] = $query; } if (isset($url['fragment'])) { $path = strtr($path, array('#' . $url['fragment'] => '')); // If the path is empty we want to have a fragment for the current site. if ($path == '') { $options['external'] = TRUE; } $options['fragment'] = $url['fragment']; } $alt = strtr($alter['alt'], $tokens); // Set the title attribute of the link only if it improves accessibility if ($alt && $alt != $text) { $options['attributes']['title'] = decode_entities($alt); } $class = strtr($alter['link_class'], $tokens); if ($class) { $options['attributes']['class'] = array($class); } if (!empty($alter['rel']) && ($rel = strtr($alter['rel'], $tokens))) { $options['attributes']['rel'] = $rel; } $target = String::checkPlain(trim(strtr($alter['target'], $tokens))); if (!empty($target)) { $options['attributes']['target'] = $target; } // Allow the addition of arbitrary attributes to links. Additional attributes // currently can only be altered in preprocessors and not within the UI. if (isset($alter['link_attributes']) && is_array($alter['link_attributes'])) { foreach ($alter['link_attributes'] as $key => $attribute) { if (!isset($options['attributes'][$key])) { $options['attributes'][$key] = strtr($attribute, $tokens); } } } // If the query and fragment were programatically assigned overwrite any // parsed values. if (isset($alter['query'])) { // Convert the query to a string, perform token replacement, and then // convert back to an array form for l(). $options['query'] = UrlHelper::buildQuery($alter['query']); $options['query'] = strtr($options['query'], $tokens); $query = array(); parse_str($options['query'], $query); $options['query'] = $query; } if (isset($alter['alias'])) { // Alias is a boolean field, so no token. $options['alias'] = $alter['alias']; } if (isset($alter['fragment'])) { $options['fragment'] = strtr($alter['fragment'], $tokens); } if (isset($alter['language'])) { $options['language'] = $alter['language']; } // If the url came from entity_uri(), pass along the required options. if (isset($alter['entity'])) { $options['entity'] = $alter['entity']; } if (isset($alter['entity_type'])) { $options['entity_type'] = $alter['entity_type']; } $value .= l($text, $path, $options); if (!empty($alter['suffix'])) { $value .= Xss::filterAdmin(strtr($alter['suffix'], $tokens)); } return $value; }
/** * Add information about a section to a display. */ public function getFormBucket(ViewUI $view, $type, $display) { $executable = $view->getExecutable(); $executable->setDisplay($display['id']); $executable->initStyle(); $types = $executable->getHandlerTypes(); $build = array('#theme_wrappers' => array('views_ui_display_tab_bucket')); $build['#overridden'] = FALSE; $build['#defaulted'] = FALSE; $build['#name'] = $type; $build['#title'] = $types[$type]['title']; $rearrange_url = Url::fromRoute('views_ui.form_rearrange', ['js' => 'nojs', 'view' => $view->id(), 'display_id' => $display['id'], 'type' => $type]); $class = 'icon compact rearrange'; // Different types now have different rearrange forms, so we use this switch // to get the right one. switch ($type) { case 'filter': // The rearrange form for filters contains the and/or UI, so override // the used path. $rearrange_url = Url::fromRoute('views_ui.form_rearrange_filter', ['js' => 'nojs', 'view' => $view->id(), 'display_id' => $display['id']]); // TODO: Add another class to have another symbol for filter rearrange. $class = 'icon compact rearrange'; break; case 'field': // Fetch the style plugin info so we know whether to list fields or not. $style_plugin = $executable->style_plugin; $uses_fields = $style_plugin && $style_plugin->usesFields(); if (!$uses_fields) { $build['fields'][] = array('#markup' => $this->t('The selected style or row format does not use fields.'), '#theme_wrappers' => array('views_ui_container'), '#attributes' => array('class' => array('views-display-setting'))); return $build; } break; case 'header': case 'footer': case 'empty': if (!$executable->display_handler->usesAreas()) { $build[$type][] = array('#markup' => $this->t('The selected display type does not use @type plugins', array('@type' => $type)), '#theme_wrappers' => array('views_ui_container'), '#attributes' => array('class' => array('views-display-setting'))); return $build; } break; } // Create an array of actions to pass to links template. $actions = array(); $count_handlers = count($executable->display_handler->getHandlers($type)); // Create the add text variable for the add action. $add_text = $this->t('Add <span class="visually-hidden">@type</span>', array('@type' => $types[$type]['ltitle'])); $actions['add'] = array('title' => $add_text, 'url' => Url::fromRoute('views_ui.form_add_handler', ['js' => 'nojs', 'view' => $view->id(), 'display_id' => $display['id'], 'type' => $type]), 'attributes' => array('class' => array('icon compact add', 'views-ajax-link'), 'id' => 'views-add-' . $type)); if ($count_handlers > 0) { // Create the rearrange text variable for the rearrange action. $rearrange_text = $type == 'filter' ? $this->t('And/Or Rearrange <span class="visually-hidden">filter criteria</span>') : $this->t('Rearrange <span class="visually-hidden">@type</span>', array('@type' => $types[$type]['ltitle'])); $actions['rearrange'] = array('title' => $rearrange_text, 'url' => $rearrange_url, 'attributes' => array('class' => array($class, 'views-ajax-link'), 'id' => 'views-rearrange-' . $type)); } // Render the array of links $build['#actions'] = array('#type' => 'dropbutton', '#links' => $actions, '#attributes' => array('class' => array('views-ui-settings-bucket-operations'))); if (!$executable->display_handler->isDefaultDisplay()) { if (!$executable->display_handler->isDefaulted($types[$type]['plural'])) { $build['#overridden'] = TRUE; } else { $build['#defaulted'] = TRUE; } } static $relationships = NULL; if (!isset($relationships)) { // Get relationship labels. $relationships = array(); foreach ($executable->display_handler->getHandlers('relationship') as $id => $handler) { $relationships[$id] = $handler->adminLabel(); } } // Filters can now be grouped so we do a little bit extra: $groups = array(); $grouping = FALSE; if ($type == 'filter') { $group_info = $executable->display_handler->getOption('filter_groups'); // If there is only one group but it is using the "OR" filter, we still // treat it as a group for display purposes, since we want to display the // "OR" label next to items within the group. if (!empty($group_info['groups']) && (count($group_info['groups']) > 1 || current($group_info['groups']) == 'OR')) { $grouping = TRUE; $groups = array(0 => array()); } } $build['fields'] = array(); foreach ($executable->display_handler->getOption($types[$type]['plural']) as $id => $field) { // Build the option link for this handler ("Node: ID = article"). $build['fields'][$id] = array(); $build['fields'][$id]['#theme'] = 'views_ui_display_tab_setting'; $handler = $executable->display_handler->getHandler($type, $id); if ($handler->broken()) { $build['fields'][$id]['#class'][] = 'broken'; $field_name = $handler->adminLabel(); $build['fields'][$id]['#link'] = $this->l($field_name, new Url('views_ui.form_handler', array('js' => 'nojs', 'view' => $view->id(), 'display_id' => $display['id'], 'type' => $type, 'id' => $id), array('attributes' => array('class' => array('views-ajax-link'))))); continue; } $field_name = $handler->adminLabel(TRUE); if (!empty($field['relationship']) && !empty($relationships[$field['relationship']])) { $field_name = '(' . $relationships[$field['relationship']] . ') ' . $field_name; } $description = Xss::filterAdmin($handler->adminSummary()); $link_text = $field_name . (empty($description) ? '' : " ({$description})"); $link_attributes = array('class' => array('views-ajax-link')); if (!empty($field['exclude'])) { $link_attributes['class'][] = 'views-field-excluded'; // Add a [hidden] marker, if the field is excluded. $link_text .= ' [' . $this->t('hidden') . ']'; } $build['fields'][$id]['#link'] = $this->l($link_text, new Url('views_ui.form_handler', array('js' => 'nojs', 'view' => $view->id(), 'display_id' => $display['id'], 'type' => $type, 'id' => $id), array('attributes' => $link_attributes))); $build['fields'][$id]['#class'][] = Html::cleanCssIdentifier($display['id'] . '-' . $type . '-' . $id); if ($executable->display_handler->useGroupBy() && $handler->usesGroupBy()) { $build['fields'][$id]['#settings_links'][] = $this->l(SafeMarkup::format('<span class="label">@text</span>', array('@text' => $this->t('Aggregation settings'))), new Url('views_ui.form_handler_group', array('js' => 'nojs', 'view' => $view->id(), 'display_id' => $display['id'], 'type' => $type, 'id' => $id), array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => $this->t('Aggregation settings'))))); } if ($handler->hasExtraOptions()) { $build['fields'][$id]['#settings_links'][] = $this->l(SafeMarkup::format('<span class="label">@text</span>', array('@text' => $this->t('Settings'))), new Url('views_ui.form_handler_extra', array('js' => 'nojs', 'view' => $view->id(), 'display_id' => $display['id'], 'type' => $type, 'id' => $id), array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => $this->t('Settings'))))); } if ($grouping) { $gid = $handler->options['group']; // Show in default group if the group does not exist. if (empty($group_info['groups'][$gid])) { $gid = 0; } $groups[$gid][] = $id; } } // If using grouping, re-order fields so that they show up properly in the list. if ($type == 'filter' && $grouping) { $store = $build['fields']; $build['fields'] = array(); foreach ($groups as $gid => $contents) { // Display an operator between each group. if (!empty($build['fields'])) { $build['fields'][] = array('#theme' => 'views_ui_display_tab_setting', '#class' => array('views-group-text'), '#link' => $group_info['operator'] == 'OR' ? $this->t('OR') : $this->t('AND')); } // Display an operator between each pair of filters within the group. $keys = array_keys($contents); $last = end($keys); foreach ($contents as $key => $pid) { if ($key != $last) { $operator = $group_info['groups'][$gid] == 'OR' ? $this->t('OR') : $this->t('AND'); $store[$pid]['#link'] = SafeMarkup::format('@link <span>@operator</span>', ['@link' => $store[$pid]['#link'], '@operator' => $operator]); } $build['fields'][$pid] = $store[$pid]; } } } return $build; }
/** * Tests the rendering of an area. */ public function testRenderArea() { $view = Views::getView('test_example_area'); $view->initHandlers(); // Insert a random string with XSS injection in the test area plugin. // Ensure that the string is rendered for the header, footer, and empty // text with the markup properly escaped. $header_string = '<script type="text/javascript">alert("boo");</script><p>' . $this->randomMachineName() . '</p>'; $footer_string = '<script type="text/javascript">alert("boo");</script><p>' . $this->randomMachineName() . '</p>'; $empty_string = '<script type="text/javascript">alert("boo");</script><p>' . $this->randomMachineName() . '</p>'; $view->header['test_example']->options['string'] = $header_string; $view->header['test_example']->options['empty'] = TRUE; $view->footer['test_example']->options['string'] = $footer_string; $view->footer['test_example']->options['empty'] = TRUE; $view->empty['test_example']->options['string'] = $empty_string; // Check whether the strings exist in the output and are sanitized. $output = $view->preview(); $output = $this->container->get('renderer')->renderRoot($output); $this->assertTrue(strpos($output, Xss::filterAdmin($header_string)) !== FALSE, 'Views header exists in the output and is sanitized'); $this->assertTrue(strpos($output, Xss::filterAdmin($footer_string)) !== FALSE, 'Views footer exists in the output and is sanitized'); $this->assertTrue(strpos($output, Xss::filterAdmin($empty_string)) !== FALSE, 'Views empty exists in the output and is sanitized'); $this->assertTrue(strpos($output, '<script') === FALSE, 'Script tags were escaped'); }
/** * Render the taxonomy tree. * * @param string $vid * Vocabulary id. * @param string $name * An optional name for the tree. (Default: NULL). * @param string $description * $description An optional description of the tree. (Default: NULL). * * @return string * A string representing a rendered tree. */ public function getTaxonomyTree($vid, $name = NULL, $description = NULL) { $output = ''; $options = array(); $attributes = new Attribute(); $config = \Drupal::config('sitemap.settings'); if (\Drupal::service('module_handler')->moduleExists('forum') && $vid == \Drupal::config('forum.settings')->get('vocabulary')) { $title = \Drupal::l($name, Url::fromRoute('forum.index')); $threshold = $config->get('forum_threshold'); $forum_link = TRUE; } else { $title = $name; $threshold = $config->get('term_threshold'); $forum_link = FALSE; } $last_depth = -1; $output .= !empty($description) && $config->get('show_description') ? '<div class="description">' . Xss::filterAdmin($description) . "</div>\n" : ''; $depth = $config->get('vocabulary_depth'); if ($depth <= -1) { $depth = NULL; } $tree = \Drupal::entityManager()->getStorage('taxonomy_term')->loadTree($vid, 0, $depth); foreach ($tree as $term) { $term->count = sitemap_taxonomy_term_count_nodes($term->tid); if ($term->count <= $threshold) { continue; } // Adjust the depth of the <ul> based on the change // in $term->depth since the $last_depth. if ($term->depth > $last_depth) { for ($i = 0; $i < $term->depth - $last_depth; $i++) { $output .= "\n<ul>"; } } elseif ($term->depth == $last_depth) { $output .= '</li>'; } elseif ($term->depth < $last_depth) { for ($i = 0; $i < $last_depth - $term->depth; $i++) { $output .= "</li>\n</ul>\n</li>"; } } // Display the $term. $output .= "\n<li>"; $term_item = ''; if ($forum_link) { $term_item .= \Drupal::l($term->name, Url::fromRoute('forum.page', array('taxonomy_term' => $term->tid), array('attributes' => array('title' => $term->description__value)))); } elseif ($term->count) { $term_item .= \Drupal::l($term->name, Url::fromRoute('entity.taxonomy_term.canonical', array('taxonomy_term' => $term->tid), array('attributes' => array('title' => $term->description__value)))); } else { $term_item .= $term->name; } if ($config->get('show_count')) { $span_title = \Drupal::translation()->formatPlural($term->count, '1 item has this term', '@count items have this term'); $term_item .= " <span title=\"" . $span_title . "\">(" . $term->count . ")</span>"; } // RSS depth. $rss_depth = $config->get('rss_taxonomy'); if ($config->get('show_rss_links') != 0 && ($rss_depth == -1 || $term->depth < $rss_depth)) { $feed_icon = array('#theme' => 'sitemap_feed_icon', '#url' => 'taxonomy/term/' . $term->tid . '/feed', '#name' => $term->name); $rss_link = drupal_render($feed_icon); if ($config->get('show_rss_links') == 1) { $term_item .= ' ' . $rss_link; } else { $attributes->addClass('sitemap-rss-left'); $term_item = $rss_link . ' ' . $term_item; } } // Add an alter hook for modules to manipulate the taxonomy term output. \Drupal::moduleHandler()->alter(array('sitemap_taxonomy_term', 'sitemap_taxonomy_term_' . $term->tid), $term_item, $term); $output .= $term_item; // Reset $last_depth in preparation for the next $term. $last_depth = $term->depth; } // Bring the depth back to where it began, -1. if ($last_depth > -1) { for ($i = 0; $i < $last_depth + 1; $i++) { $output .= "</li>\n</ul>\n"; } } $this->setOption($options, 'show_titles', 1, 'show_titles', TRUE); $attributes->addClass('sitemap-box-terms', 'sitemap-box-terms-' . $vid); $sitemap_box = array('title' => $title, 'content' => array('#markup' => $output), 'attributes' => $attributes, 'options' => $options); return $sitemap_box; }
/** * {@inheritdoc} */ public function execute() { $this->view->build(); $render = $this->view->render(); // Render the test option as the title before the view output. $render['#prefix'] = '<h1>' . Xss::filterAdmin($this->options['test_option']) . '</h1>'; return $render; }