/** * Lists the feed items belonging to a feed. */ public function listItems(FeedInterface $feeds_feed, Request $request) { $processor = $feeds_feed->getType()->getProcessor(); $header = ['title' => $this->t('Label'), 'imported' => $this->t('Imported'), 'guid' => ['data' => $this->t('GUID'), 'class' => [RESPONSIVE_PRIORITY_LOW]], 'url' => ['data' => $this->t('URL'), 'class' => [RESPONSIVE_PRIORITY_LOW]]]; $build = []; $build['table'] = ['#type' => 'table', '#header' => $header, '#rows' => [], '#empty' => $this->t('There are no items yet.')]; // @todo Allow processors to create their own entity listings. if (!$processor instanceof EntityProcessorInterface) { return $build; } $entity_ids = \Drupal::entityQuery($processor->entityType())->condition('feeds_item.target_id', $feeds_feed->id())->pager(50)->sort('feeds_item.imported', 'DESC')->execute(); $storage = $this->entityManager()->getStorage($processor->entityType()); foreach ($storage->loadMultiple($entity_ids) as $entity) { $ago = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $entity->get('feeds_item')->imported); $row = []; // Entity link. $row[] = ['data' => $entity->link(Unicode::truncate($entity->label(), 75, TRUE, TRUE)), 'title' => $entity->label()]; // Imported ago. $row[] = $this->t('@time ago', ['@time' => $ago]); // Item GUID. $row[] = ['data' => SafeMarkup::checkPlain(Unicode::truncate($entity->get('feeds_item')->guid, 30, FALSE, TRUE)), 'title' => $entity->get('feeds_item')->guid]; // Item URL. $row[] = ['data' => SafeMarkup::checkPlain(Unicode::truncate($entity->get('feeds_item')->url, 30, FALSE, TRUE)), 'title' => $entity->get('feeds_item')->url]; $build['table']['#rows'][] = $row; } $build['pager'] = ['#type' => 'pager']; $build['#title'] = $this->t('%title items', ['%title' => $feeds_feed->label()]); return $build; }
/** * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { $OriginalValue = ''; if (($node = \Drupal::routeMatch()->getParameter('node')) && $node instanceof \Drupal\node\NodeInterface) { $FiledsView = $items->view(); $LangCode = $items->getLangcode(); $FieldName = $FiledsView['#field_name']; $node = (array) $node; $arrayValues = array_values($node); if (isset($arrayValues[0]['langcode']['x-default']) && $arrayValues[0]['langcode']['x-default'] != $LangCode) { if ($FieldName != 'title') { if (isset($arrayValues[0][$FieldName]['x-default'][0]['value'])) { $OriginalValue = $arrayValues[0][$FieldName]['x-default'][0]['value']; } } else { if (isset($arrayValues[0][$FieldName]['x-default'])) { $OriginalValue = $arrayValues[0][$FieldName]['x-default']; } } $Title = $OriginalValue; $OriginalValue = Unicode::truncate($OriginalValue, 200, TRUE); $OriginalValue = '<div class="original_text" title="' . $Title . '"><span class="original">ORIGINAL: </span>' . $OriginalValue . '</div>'; } } $element['value'] = $element + array('#type' => 'textfield', '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL, '#size' => $this->getSetting('size'), '#placeholder' => $this->getSetting('placeholder'), '#maxlength' => $this->getFieldSetting('max_length'), '#attributes' => array('class' => array('text-full')), '#suffix' => $OriginalValue); return $element; }
/** * {@inheritdoc} */ public function prepareRow(Row $row) { $row->setSourceProperty('options', unserialize($row->getSourceProperty('options'))); $row->setSourceProperty('enabled', !$row->getSourceProperty('hidden')); $row->setSourceProperty('description', Unicode::truncate($row->getSourceProperty('options/attributes/title'), 255)); return parent::prepareRow($row); }
/** * {@inheritdoc} */ protected function setUp() { $this->databaseContents['menu_links'] = $this->expectedResults; // Add long link title attributes. $title = $this->getRandomGenerator()->string('500'); $this->databaseContents['menu_links'][0]['options']['attributes']['title'] = $title; $this->expectedResults[0]['description'] = Unicode::truncate($title, 255); // D6 menu link to a custom menu, provided by menu module. $this->databaseContents['menu_links'][] = ['menu_name' => 'menu-user', 'mlid' => 143, 'plid' => 0, 'link_path' => 'admin/build/menu-customize/navigation', 'router_path' => 'admin/build/menu-customize/%', 'link_title' => 'Navigation', 'options' => array(), 'module' => 'menu', 'hidden' => 0, 'external' => 0, 'has_children' => 0, 'expanded' => 0, 'weight' => 0, 'depth' => 0, 'customized' => 0, 'p1' => '0', 'p2' => '0', 'p3' => '0', 'p4' => '0', 'p5' => '0', 'p6' => '0', 'p7' => '0', 'p8' => '0', 'p9' => '0', 'updated' => '0', 'description' => '']; array_walk($this->databaseContents['menu_links'], function (&$row) { $row['options'] = serialize($row['options']); }); parent::setUp(); }
/** * {@inheritdoc} */ public function uniquify(&$alias, $source, $langcode) { $config = $this->configFactory->get('pathauto.settings'); if (!$this->isReserved($alias, $source, $langcode)) { return; } // If the alias already exists, generate a new, hopefully unique, variant. $maxlength = min($config->get('max_length'), $this->aliasStorageHelper->getAliasSchemaMaxlength()); $separator = $config->get('separator'); $original_alias = $alias; $i = 0; do { // Append an incrementing numeric suffix until we find a unique alias. $unique_suffix = $separator . $i; $alias = Unicode::truncate($original_alias, $maxlength - Unicode::strlen($unique_suffix, TRUE)) . $unique_suffix; $i++; } while ($this->isReserved($alias, $source, $langcode)); }
/** * {@inheritdoc} */ public function cleanAlias($alias) { if (!isset($this->aliasMaxLength)) { $config = $this->configFactory->get('pathauto.settings'); $this->aliasMaxLength = min($config->get('max_length'), $this->aliasStorageHelper->getAliasSchemaMaxLength()); } $output = $alias; // Trim duplicate, leading, and trailing separators. Do this before cleaning // backslashes since a pattern like "[token1]/[token2]-[token3]/[token4]" // could end up like "value1/-/value2" and if backslashes were cleaned first // this would result in a duplicate blackslash. $output = $this->getCleanSeparators($output); // Trim duplicate, leading, and trailing backslashes. $output = $this->getCleanSeparators($output, '/'); // Shorten to a logical place based on word boundaries. $output = Unicode::truncate($output, $this->aliasMaxLength, TRUE); return $output; }
/** * {@inheritdoc} */ public function providerSource() { $tests = []; // The source data. $tests[0]['source_data']['menu_links'] = [['menu_name' => 'menu-test-menu', 'mlid' => 140, 'plid' => 0, 'link_path' => 'admin/config/system/cron', 'router_path' => 'admin/config/system/cron', 'link_title' => 'Cron', 'options' => array(), 'module' => 'system', 'hidden' => 0, 'external' => 0, 'has_children' => 0, 'expanded' => 0, 'weight' => 0, 'depth' => 0, 'customized' => 1, 'p1' => '0', 'p2' => '0', 'p3' => '0', 'p4' => '0', 'p5' => '0', 'p6' => '0', 'p7' => '0', 'p8' => '0', 'p9' => '0', 'updated' => '0', 'description' => ''], ['menu_name' => 'menu-test-menu', 'mlid' => 141, 'plid' => 0, 'link_path' => 'node/141', 'router_path' => 'node/%', 'link_title' => 'Node 141', 'options' => array(), 'module' => 'menu', 'hidden' => 0, 'external' => 0, 'has_children' => 0, 'expanded' => 0, 'weight' => 0, 'depth' => 0, 'customized' => 1, 'p1' => '0', 'p2' => '0', 'p3' => '0', 'p4' => '0', 'p5' => '0', 'p6' => '0', 'p7' => '0', 'p8' => '0', 'p9' => '0', 'updated' => '0', 'description' => ''], ['menu_name' => 'menu-test-menu', 'mlid' => 142, 'plid' => 0, 'link_path' => 'node/142', 'router_path' => 'node/%', 'link_title' => 'Node 142', 'options' => array(), 'module' => 'menu', 'hidden' => 0, 'external' => 0, 'has_children' => 0, 'expanded' => 0, 'weight' => 0, 'depth' => 0, 'customized' => 0, 'p1' => '0', 'p2' => '0', 'p3' => '0', 'p4' => '0', 'p5' => '0', 'p6' => '0', 'p7' => '0', 'p8' => '0', 'p9' => '0', 'updated' => '0', 'description' => ''], ['menu_name' => 'menu-test-menu', 'mlid' => 138, 'plid' => 0, 'link_path' => 'admin', 'router_path' => 'admin', 'link_title' => 'Test 1', 'options' => array('attributes' => array('title' => 'Test menu link 1')), 'module' => 'menu', 'hidden' => 0, 'external' => 0, 'has_children' => 1, 'expanded' => 0, 'weight' => 15, 'depth' => 1, 'customized' => 1, 'p1' => '138', 'p2' => '0', 'p3' => '0', 'p4' => '0', 'p5' => '0', 'p6' => '0', 'p7' => '0', 'p8' => '0', 'p9' => '0', 'updated' => '0', 'description' => 'Test menu link 1'], ['menu_name' => 'menu-test-menu', 'mlid' => 139, 'plid' => 138, 'link_path' => 'admin/modules', 'router_path' => 'admin/modules', 'link_title' => 'Test 2', 'options' => array('attributes' => array('title' => 'Test menu link 2')), 'module' => 'menu', 'hidden' => 0, 'external' => 0, 'has_children' => 0, 'expanded' => 0, 'weight' => 12, 'depth' => 2, 'customized' => 1, 'p1' => '138', 'p2' => '139', 'p3' => '0', 'p4' => '0', 'p5' => '0', 'p6' => '0', 'p7' => '0', 'p8' => '0', 'p9' => '0', 'updated' => '0', 'description' => 'Test menu link 2'], ['menu_name' => 'menu-user', 'mlid' => 143, 'plid' => 0, 'link_path' => 'admin/build/menu-customize/navigation', 'router_path' => 'admin/build/menu-customize/%', 'link_title' => 'Navigation', 'options' => array(), 'module' => 'menu', 'hidden' => 0, 'external' => 0, 'has_children' => 0, 'expanded' => 0, 'weight' => 0, 'depth' => 0, 'customized' => 0, 'p1' => '0', 'p2' => '0', 'p3' => '0', 'p4' => '0', 'p5' => '0', 'p6' => '0', 'p7' => '0', 'p8' => '0', 'p9' => '0', 'updated' => '0', 'description' => '']]; // Add long link title attributes to source data. $title = $this->getRandomGenerator()->string('500'); $tests[0]['source_data']['menu_links'][0]['options']['attributes']['title'] = $title; // Build the expected results. $expected = $tests[0]['source_data']['menu_links']; // Add long link title attributes to expected results. $expected[0]['description'] = Unicode::truncate($title, 255); // Don't expect D6 menu link to a custom menu, provided by menu module. unset($expected[5]); array_walk($tests[0]['source_data']['menu_links'], function (&$row) { $row['options'] = serialize($row['options']); }); $tests[0]['expected_data'] = $expected; return $tests; }
/** * Displays the path administration overview page. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object. * * @return array * A render array as expected by drupal_render(). */ public function adminOverview(Request $request) { $keys = $request->query->get('search'); // Add the filter form above the overview table. $build['path_admin_filter_form'] = $this->formBuilder()->getForm('Drupal\\path\\Form\\PathFilterForm', $keys); // Enable language column if language.module is enabled or if we have any // alias with a language. $multilanguage = $this->moduleHandler()->moduleExists('language') || $this->aliasStorage->languageAliasExists(); $header = array(); $header[] = array('data' => $this->t('Alias'), 'field' => 'alias', 'sort' => 'asc'); $header[] = array('data' => $this->t('System'), 'field' => 'source'); if ($multilanguage) { $header[] = array('data' => $this->t('Language'), 'field' => 'langcode'); } $header[] = $this->t('Operations'); $rows = array(); $destination = $this->getDestinationArray(); foreach ($this->aliasStorage->getAliasesForAdminListing($header, $keys) as $data) { $row = array(); // @todo Should Path module store leading slashes? See // https://www.drupal.org/node/2430593. $row['data']['alias'] = $this->l(Unicode::truncate($data->alias, 50, FALSE, TRUE), Url::fromUserInput($data->source, array('attributes' => array('title' => $data->alias)))); $row['data']['source'] = $this->l(Unicode::truncate($data->source, 50, FALSE, TRUE), Url::fromUserInput($data->source, array('alias' => TRUE, 'attributes' => array('title' => $data->source)))); if ($multilanguage) { $row['data']['language_name'] = $this->languageManager()->getLanguageName($data->langcode); } $operations = array(); $operations['edit'] = array('title' => $this->t('Edit'), 'url' => Url::fromRoute('path.admin_edit', ['pid' => $data->pid], ['query' => $destination])); $operations['delete'] = array('title' => $this->t('Delete'), 'url' => Url::fromRoute('path.delete', ['pid' => $data->pid], ['query' => $destination])); $row['data']['operations'] = array('data' => array('#type' => 'operations', '#links' => $operations)); // If the system path maps to a different URL alias, highlight this table // row to let the user know of old aliases. if ($data->alias != $this->aliasManager->getAliasByPath($data->source, $data->langcode)) { $row['class'] = array('warning'); } $rows[] = $row; } $build['path_table'] = array('#type' => 'table', '#header' => $header, '#rows' => $rows, '#empty' => $this->t('No URL aliases available. <a href=":link">Add URL alias</a>.', array(':link' => $this->url('path.admin_add')))); $build['path_pager'] = array('#type' => 'pager'); return $build; }
/** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode) { $element = array(); $entity = $items->getEntity(); $settings = $this->getSettings(); foreach ($items as $delta => $item) { // By default use the full URL as the link text. $url = $this->buildUrl($item); $link_title = $url->toString(); // If the link text field value is available, use it for the text. if (empty($settings['url_only']) && !empty($item->title)) { // Unsanitized token replacement here because the entire link title // gets auto-escaped during link generation in // \Drupal\Core\Utility\LinkGenerator::generate(). $link_title = \Drupal::token()->replace($item->title, [$entity->getEntityTypeId() => $entity], ['clear' => TRUE]); } // The link_separate formatter has two titles; the link text (as in the // field values) and the URL itself. If there is no link text value, // $link_title defaults to the URL, so it needs to be unset. // The URL version may need to be trimmed as well. if (empty($item->title)) { $link_title = NULL; } $url_title = $url->toString(); if (!empty($settings['trim_length'])) { $link_title = Unicode::truncate($link_title, $settings['trim_length'], FALSE, TRUE); $url_title = Unicode::truncate($url_title, $settings['trim_length'], FALSE, TRUE); } $element[$delta] = array('#theme' => 'link_formatter_link_separate', '#title' => $link_title, '#url_title' => $url_title, '#url' => $url); if (!empty($item->_attributes)) { // Set our RDFa attributes on the <a> element that is being built. $url->setOption('attributes', $item->_attributes); // Unset field item attributes since they have been included in the // formatter output and should not be rendered in the field template. unset($item->_attributes); } } return $element; }
/** * Tests multibyte truncate. * * @dataProvider providerTruncate * @covers ::truncate */ public function testTruncate($text, $max_length, $expected, $wordsafe = FALSE, $add_ellipsis = FALSE) { $this->assertEquals($expected, Unicode::truncate($text, $max_length, $wordsafe, $add_ellipsis)); }
/** * {@inheritdoc} */ public function process(FeedInterface $feed) { if (!is_array($feed->items)) { return; } foreach ($feed->items as $item) { // @todo: The default entity view builder always returns an empty // array, which is ignored in aggregator_save_item() currently. Should // probably be fixed. if (empty($item['title'])) { continue; } // Save this item. Try to avoid duplicate entries as much as possible. If // we find a duplicate entry, we resolve it and pass along its ID is such // that we can update it if needed. if (!empty($item['guid'])) { $values = array('fid' => $feed->id(), 'guid' => $item['guid']); } elseif ($item['link'] && $item['link'] != $feed->link && $item['link'] != $feed->url) { $values = array('fid' => $feed->id(), 'link' => $item['link']); } else { $values = array('fid' => $feed->id(), 'title' => $item['title']); } // Try to load an existing entry. if ($entry = entity_load_multiple_by_properties('aggregator_item', $values)) { $entry = reset($entry); } else { $entry = entity_create('aggregator_item', array('langcode' => $feed->language()->getId())); } if ($item['timestamp']) { $entry->setPostedTime($item['timestamp']); } // Make sure the item title and author fit in the 255 varchar column. $entry->setTitle(Unicode::truncate($item['title'], 255, TRUE, TRUE)); $entry->setAuthor(Unicode::truncate($item['author'], 255, TRUE, TRUE)); $entry->setFeedId($feed->id()); $entry->setLink($item['link']); $entry->setGuid($item['guid']); $description = ''; if (!empty($item['description'])) { $description = $item['description']; } $entry->setDescription($description); $entry->save(); } }
/** * Confirms that a log message appears on the database log overview screen. * * This function should only be used for the admin/reports/dblog page, because * it checks for the message link text truncated to 56 characters. Other log * pages have no detail links so they contain the full message text. * * @param string $log_message * The database log message to check. * @param string $message * The message to pass to simpletest. */ protected function assertLogMessage($log_message, $message) { $message_text = Unicode::truncate(Html::decodeEntities(strip_tags($log_message)), 56, TRUE, TRUE); $this->assertLink($message_text, 0, $message); }
/** * Recursively processes and formats book links for getTableOfContents(). * * This helper function recursively modifies the table of contents array for * each item in the book tree, ignoring items in the exclude array or at a * depth greater than the limit. Truncates titles over thirty characters and * appends an indentation string incremented by depth. * * @param array $tree * The data structure of the book's outline tree. Includes hidden links. * @param string $indent * A string appended to each node title. Increments by '--' per depth * level. * @param array $toc * Reference to the table of contents array. This is modified in place, so * the function does not have a return value. * @param array $exclude * Optional array of Node ID values. Any link whose node ID is in this * array will be excluded (along with its children). * @param int $depth_limit * Any link deeper than this value will be excluded (along with its * children). */ protected function recurseTableOfContents(array $tree, $indent, array &$toc, array $exclude, $depth_limit) { $nids = array(); foreach ($tree as $data) { if ($data['link']['depth'] > $depth_limit) { // Don't iterate through any links on this level. return; } if (!in_array($data['link']['nid'], $exclude)) { $nids[] = $data['link']['nid']; } } $nodes = $this->entityManager->getStorage('node')->loadMultiple($nids); foreach ($tree as $data) { $nid = $data['link']['nid']; // Check for excluded or missing node. if (empty($nodes[$nid])) { continue; } $toc[$nid] = $indent . ' ' . Unicode::truncate($nodes[$nid]->label(), 30, TRUE, TRUE); if ($data['below']) { $this->recurseTableOfContents($data['below'], $indent . '--', $toc, $exclude, $depth_limit); } } }
/** * 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' => 'u.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')); 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. $log_text = Unicode::truncate(Xss::filter($message, array()), 56, TRUE, TRUE); $message = $this->l($log_text, 'dblog.event', array('event_id' => $dblog->wid), array('html' => TRUE)); } $username = array('#theme' => 'username', '#account' => user_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), Xss::filter($dblog->link)), 'class' => array(drupal_html_class('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('#theme' => 'pager'); return $build; }
protected function getAllEvents(DrupalStyle $io, $eventType, $eventSeverity, $userId, $asc, $offset, $limit) { $connection = $this->getDrupalService('database'); $dateFormatter = $this->getDrupalService('date.formatter'); $userStorage = $this->getDrupalService('entity_type.manager')->getStorage('user'); $severity = RfcLogLevel::getLevels(); $query = $connection->select('watchdog', 'w'); $query->fields('w', ['wid', 'uid', 'severity', 'type', 'timestamp', 'message', 'variables']); if ($eventType) { $query->condition('type', $eventType); } if ($eventSeverity) { if (!in_array($eventSeverity, $severity)) { $io->error(sprintf($this->trans('commands.database.log.debug.messages.invalid-severity'), $eventSeverity)); return false; } $query->condition('severity', array_search($eventSeverity, $severity)); } if ($userId) { $query->condition('uid', $userId); } if ($asc) { $query->orderBy('wid', 'ASC'); } else { $query->orderBy('wid', 'DESC'); } if ($limit) { $query->range($offset, $limit); } $result = $query->execute(); $tableHeader = [$this->trans('commands.database.log.debug.messages.event-id'), $this->trans('commands.database.log.debug.messages.type'), $this->trans('commands.database.log.debug.messages.date'), $this->trans('commands.database.log.debug.messages.message'), $this->trans('commands.database.log.debug.messages.user'), $this->trans('commands.database.log.debug.messages.severity')]; $tableRows = []; foreach ($result as $dblog) { $user = $userStorage->load($dblog->uid); $tableRows[] = [$dblog->wid, $dblog->type, $dateFormatter->format($dblog->timestamp, 'short'), Unicode::truncate(Html::decodeEntities(strip_tags($this->formatMessage($dblog))), 56, true, true), $user->getUsername() . ' (' . $user->id() . ')', $severity[$dblog->severity]]; } $io->table($tableHeader, $tableRows); return true; }
/** * Tests the failed search text, and various other text on the search page. */ function testSearchText() { $this->drupalLogin($this->searchingUser); $this->drupalGet('search/node'); $this->assertText(t('Enter your keywords')); $this->assertText(t('Search')); $this->assertTitle(t('Search') . ' | Drupal', 'Search page title is correct'); $edit = array(); $search_terms = 'bike shed ' . $this->randomMachineName(); $edit['keys'] = $search_terms; $this->drupalPostForm('search/node', $edit, t('Search')); $this->assertText('search yielded no results'); $this->assertText(t('Search')); $title_source = 'Search for @keywords | Drupal'; $this->assertTitle(t($title_source, array('@keywords' => Unicode::truncate($search_terms, 60, TRUE, TRUE))), 'Search page title is correct'); $this->assertNoText('Node', 'Erroneous tab and breadcrumb text is not present'); $this->assertNoText(t('Node'), 'Erroneous translated tab and breadcrumb text is not present'); $this->assertText(t('Content'), 'Tab and breadcrumb text is present'); $this->clickLink('Search help'); $this->assertText('Search help', 'Correct title is on search help page'); $this->assertText('Use upper-case OR to get more results', 'Correct text is on content search help page'); // Search for a longer text, and see that it is in the title, truncated. $edit = array(); $search_terms = 'Every word is like an unnecessary stain on silence and nothingness.'; $edit['keys'] = $search_terms; $this->drupalPostForm('search/node', $edit, t('Search')); $this->assertTitle(t($title_source, array('@keywords' => 'Every word is like an unnecessary stain on silence and…')), 'Search page title is correct'); // Search for a string with a lot of special characters. $search_terms = 'Hear nothing > "see nothing" `feel' . " '1982."; $edit['keys'] = $search_terms; $this->drupalPostForm('search/node', $edit, t('Search')); $actual_title = (string) current($this->xpath('//title')); $this->assertEqual($actual_title, String::decodeEntities(t($title_source, array('@keywords' => Unicode::truncate($search_terms, 60, TRUE, TRUE)))), 'Search page title is correct'); $edit['keys'] = $this->searchingUser->getUsername(); $this->drupalPostForm('search/user', $edit, t('Search')); $this->assertText(t('Search')); $this->assertTitle(t($title_source, array('@keywords' => Unicode::truncate($this->searchingUser->getUsername(), 60, TRUE, TRUE)))); $this->clickLink('Search help'); $this->assertText('Search help', 'Correct title is on search help page'); $this->assertText('user names and partial user names', 'Correct text is on user search help page'); // Test that search keywords containing slashes are correctly loaded // from the GET params and displayed in the search form. $arg = $this->randomMachineName() . '/' . $this->randomMachineName(); $this->drupalGet('search/node', array('query' => array('keys' => $arg))); $input = $this->xpath("//input[@id='edit-keys' and @value='{$arg}']"); $this->assertFalse(empty($input), 'Search keys with a / are correctly set as the default value in the search box.'); // Test a search input exceeding the limit of AND/OR combinations to test // the Denial-of-Service protection. $limit = $this->config('search.settings')->get('and_or_limit'); $keys = array(); for ($i = 0; $i < $limit + 1; $i++) { // Use a key of 4 characters to ensure we never generate 'AND' or 'OR'. $keys[] = $this->randomMachineName(4); if ($i % 2 == 0) { $keys[] = 'OR'; } } $edit['keys'] = implode(' ', $keys); $this->drupalPostForm('search/node', $edit, t('Search')); $this->assertRaw(t('Your search used too many AND/OR expressions. Only the first @count terms were included in this search.', array('@count' => $limit))); // Test that a search on Node or User with no keywords entered generates // the "Please enter some keywords" message. $this->drupalPostForm('search/node', array(), t('Search')); $this->assertText(t('Please enter some keywords'), 'With no keywords entered, message is displayed on node page'); $this->drupalPostForm('search/user', array(), t('Search')); $this->assertText(t('Please enter some keywords'), 'With no keywords entered, message is displayed on user page'); // Make sure the "Please enter some keywords" message is NOT displayed if // you use "or" words or phrases in Advanced Search. $this->drupalPostForm('search/node', array('or' => $this->randomMachineName() . ' ' . $this->randomMachineName()), t('Advanced search')); $this->assertNoText(t('Please enter some keywords'), 'With advanced OR keywords entered, no keywords message is not displayed on node page'); $this->drupalPostForm('search/node', array('phrase' => '"' . $this->randomMachineName() . '" "' . $this->randomMachineName() . '"'), t('Advanced search')); $this->assertNoText(t('Please enter some keywords'), 'With advanced phrase entered, no keywords message is not displayed on node page'); // Verify that if you search for a too-short keyword, you get the right // message, and that if after that you search for a longer keyword, you // do not still see the message. $this->drupalPostForm('search/node', array('keys' => $this->randomMachineName(1)), t('Search')); $this->assertText('You must include at least one positive keyword', 'Keyword message is displayed when searching for short word'); $this->assertNoText(t('Please enter some keywords'), 'With short word entered, no keywords message is not displayed'); $this->drupalPostForm(NULL, array('keys' => $this->randomMachineName()), t('Search')); $this->assertNoText('You must include at least one positive keyword', 'Keyword message is not displayed when searching for long word after short word search'); // Test that if you search for a URL with .. in it, you still end up at // the search page. See issue https://drupal.org/node/890058. $this->drupalPostForm('search/node', array('keys' => '../../admin'), t('Search')); $this->assertResponse(200, 'Searching for ../../admin with non-admin user does not lead to a 403 error'); $this->assertText('no results', 'Searching for ../../admin with non-admin user gives you a no search results page'); // Test that if you search for a URL starting with "./", you still end up // at the search page. See issue https://drupal.org/node/1421560. $this->drupalPostForm('search/node', array('keys' => '.something'), t('Search')); $this->assertResponse(200, 'Searching for .something does not lead to a 403 error'); $this->assertText('no results', 'Searching for .something gives you a no search results page'); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { parent::submitForm($form, $form_state); /** @var \Drupal\comment\CommentInterface $comment */ $comment = $this->entity; // If the comment was posted by a registered user, assign the author's ID. // @todo Too fragile. Should be prepared and stored in comment_form() // already. $author_name = $comment->getAuthorName(); if (!$comment->is_anonymous && !empty($author_name) && ($account = user_load_by_name($author_name))) { $comment->setOwner($account); } // If the comment was posted by an anonymous user and no author name was // required, use "Anonymous" by default. if ($comment->is_anonymous && (!isset($author_name) || $author_name === '')) { $comment->setAuthorName($this->config('user.settings')->get('anonymous')); } // Validate the comment's subject. If not specified, extract from comment // body. if (trim($comment->getSubject()) == '') { // The body may be in any format, so: // 1) Filter it into HTML // 2) Strip out all HTML tags // 3) Convert entities back to plain-text. $comment_text = $comment->comment_body->processed; $comment->setSubject(Unicode::truncate(trim(String::decodeEntities(strip_tags($comment_text))), 29, TRUE)); // Edge cases where the comment body is populated only by HTML tags will // require a default subject. if ($comment->getSubject() == '') { $comment->setSubject($this->t('(No subject)')); } } return $comment; }
public function adminSummary() { if ($this->isAGroup()) { return $this->t('grouped'); } if (!empty($this->options['exposed'])) { return $this->t('exposed'); } $info = $this->operators(); $this->getValueOptions(); // Some filter_in_operator usage uses optgroups forms, so flatten it. $flat_options = OptGroup::flattenOptions($this->valueOptions); if (!is_array($this->value)) { return; } $operator = $info[$this->operator]['short']; $values = ''; if (in_array($this->operator, $this->operatorValues(1))) { // Remove every element which is not known. foreach ($this->value as $value) { if (!isset($flat_options[$value])) { unset($this->value[$value]); } } // Choose different kind of output for 0, a single and multiple values. if (count($this->value) == 0) { $values = $this->t('Unknown'); } elseif (count($this->value) == 1) { // If any, use the 'single' short name of the operator instead. if (isset($info[$this->operator]['short_single'])) { $operator = $info[$this->operator]['short_single']; } $keys = $this->value; $value = array_shift($keys); if (isset($flat_options[$value])) { $values = $flat_options[$value]; } else { $values = ''; } } else { foreach ($this->value as $value) { if ($values !== '') { $values .= ', '; } if (Unicode::strlen($values) > 8) { $values = Unicode::truncate($values, 8, FALSE, TRUE); break; } if (isset($flat_options[$value])) { $values .= $flat_options[$value]; } } } } return $operator . ($values !== '' ? ' ' . $values : ''); }
/** * Tests the 'link_separate' formatter. * * This test is mostly the same as testLinkFormatter(), but they cannot be * merged, since they involve different configuration and output. */ function testLinkSeparateFormatter() { $field_name = Unicode::strtolower($this->randomMachineName()); // Create a field with settings to validate. $this->fieldStorage = entity_create('field_storage_config', array('field_name' => $field_name, 'entity_type' => 'entity_test', 'type' => 'link', 'cardinality' => 2)); $this->fieldStorage->save(); entity_create('field_config', array('field_storage' => $this->fieldStorage, 'bundle' => 'entity_test', 'settings' => array('title' => DRUPAL_OPTIONAL, 'link_type' => LinkItemInterface::LINK_GENERIC)))->save(); $display_options = array('type' => 'link_separate', 'label' => 'hidden'); entity_get_form_display('entity_test', 'entity_test', 'default')->setComponent($field_name, array('type' => 'link_default'))->save(); entity_get_display('entity_test', 'entity_test', 'full')->setComponent($field_name, $display_options)->save(); // Create an entity with two link field values: // - The first field item uses a URL only. // - The second field item uses a URL and link text. // For consistency in assertion code below, the URL is assigned to the title // variable for the first field. $this->drupalGet('entity_test/add'); $url1 = 'http://www.example.com/content/articles/archive?author=John&year=2012#com'; $url2 = 'http://www.example.org/content/articles/archive?author=John&year=2012#org'; // Intentionally contains an ampersand that needs sanitization on output. $title2 = 'A very long & strange example title that could break the nice layout of the site'; $edit = array("{$field_name}[0][uri]" => $url1, "{$field_name}[1][uri]" => $url2, "{$field_name}[1][title]" => $title2); $this->drupalPostForm(NULL, $edit, t('Save')); preg_match('|entity_test/manage/(\\d+)|', $this->url, $match); $id = $match[1]; $this->assertText(t('entity_test @id has been created.', array('@id' => $id))); // Verify that the link is output according to the formatter settings. $options = array('trim_length' => array(NULL, 6), 'rel' => array(NULL, 'nofollow'), 'target' => array(NULL, '_blank')); foreach ($options as $setting => $values) { foreach ($values as $new_value) { // Update the field formatter settings. $display_options['settings'] = array($setting => $new_value); entity_get_display('entity_test', 'entity_test', 'full')->setComponent($field_name, $display_options)->save(); $this->renderTestEntity($id); switch ($setting) { case 'trim_length': $url = $url1; $url_title = isset($new_value) ? Unicode::truncate($url, $new_value, FALSE, TRUE) : $url; $expected = '<div class="link-item">'; $expected .= '<div class="link-url"><a href="' . Html::escape($url) . '">' . Html::escape($url_title) . '</a></div>'; $expected .= '</div>'; $this->assertRaw($expected); $url = $url2; $url_title = isset($new_value) ? Unicode::truncate($url, $new_value, FALSE, TRUE) : $url; $title = isset($new_value) ? Unicode::truncate($title2, $new_value, FALSE, TRUE) : $title2; $expected = '<div class="link-item">'; $expected .= '<div class="link-title">' . Html::escape($title) . '</div>'; $expected .= '<div class="link-url"><a href="' . Html::escape($url) . '">' . Html::escape($url_title) . '</a></div>'; $expected .= '</div>'; $this->assertRaw($expected); break; case 'rel': $rel = isset($new_value) ? ' rel="' . $new_value . '"' : ''; $this->assertRaw('<div class="link-url"><a href="' . Html::escape($url1) . '"' . $rel . '>' . Html::escape($url1) . '</a></div>'); $this->assertRaw('<div class="link-url"><a href="' . Html::escape($url2) . '"' . $rel . '>' . Html::escape($url2) . '</a></div>'); break; case 'target': $target = isset($new_value) ? ' target="' . $new_value . '"' : ''; $this->assertRaw('<div class="link-url"><a href="' . Html::escape($url1) . '"' . $target . '>' . Html::escape($url1) . '</a></div>'); $this->assertRaw('<div class="link-url"><a href="' . Html::escape($url2) . '"' . $target . '>' . Html::escape($url2) . '</a></div>'); break; } } } }
/** * {@inheritdoc} */ public function viewElements(FieldItemListInterface $items, $langcode) { $element = array(); $entity = $items->getEntity(); $settings = $this->getSettings(); foreach ($items as $delta => $item) { // By default use the full URL as the link text. $url = $this->buildUrl($item); $link_title = $url->toString(); // If the title field value is available, use it for the link text. if (empty($settings['url_only']) && !empty($item->title)) { // Unsanitized token replacement here because the entire link title // gets auto-escaped during link generation in // \Drupal\Core\Utility\LinkGenerator::generate(). $link_title = \Drupal::token()->replace($item->title, [$entity->getEntityTypeId() => $entity], ['clear' => TRUE]); } // Trim the link text to the desired length. if (!empty($settings['trim_length'])) { $link_title = Unicode::truncate($link_title, $settings['trim_length'], FALSE, TRUE); } if (!empty($settings['url_only']) && !empty($settings['url_plain'])) { $element[$delta] = array('#plain_text' => $link_title); if (!empty($item->_attributes)) { // Piggyback on the metadata attributes, which will be placed in the // field template wrapper, and set the URL value in a content // attribute. // @todo Does RDF need a URL rather than an internal URI here? // @see \Drupal\Tests\rdf\Kernel\Field\LinkFieldRdfaTest. $content = str_replace('internal:/', '', $item->uri); $item->_attributes += array('content' => $content); } } else { $element[$delta] = array('#type' => 'link', '#title' => $link_title, '#options' => $url->getOptions()); $element[$delta]['#url'] = $url; if (!empty($item->_attributes)) { $element[$delta]['#options'] += array('attributes' => array()); $element[$delta]['#options']['attributes'] += $item->_attributes; // Unset field item attributes since they have been included in the // formatter output and should not be rendered in the field template. unset($item->_attributes); } } } return $element; }
/** * Form constructor for the comment overview administration form. * * @param array $form * An associative array containing the structure of the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * @param string $type * The type of the overview form ('approval' or 'new'). * * @return array * The form structure. */ public function buildForm(array $form, FormStateInterface $form_state, $type = 'new') { // Build an 'Update options' form. $form['options'] = array('#type' => 'details', '#title' => $this->t('Update options'), '#open' => TRUE, '#attributes' => array('class' => array('container-inline'))); if ($type == 'approval') { $options['publish'] = $this->t('Publish the selected comments'); } else { $options['unpublish'] = $this->t('Unpublish the selected comments'); } $options['delete'] = $this->t('Delete the selected comments'); $form['options']['operation'] = array('#type' => 'select', '#title' => $this->t('Action'), '#title_display' => 'invisible', '#options' => $options, '#default_value' => 'publish'); $form['options']['submit'] = array('#type' => 'submit', '#value' => $this->t('Update')); // Load the comments that need to be displayed. $status = $type == 'approval' ? CommentInterface::NOT_PUBLISHED : CommentInterface::PUBLISHED; $header = array('subject' => array('data' => $this->t('Subject'), 'specifier' => 'subject'), 'author' => array('data' => $this->t('Author'), 'specifier' => 'name', 'class' => array(RESPONSIVE_PRIORITY_MEDIUM)), 'posted_in' => array('data' => $this->t('Posted in'), 'class' => array(RESPONSIVE_PRIORITY_LOW)), 'changed' => array('data' => $this->t('Updated'), 'specifier' => 'changed', 'sort' => 'desc', 'class' => array(RESPONSIVE_PRIORITY_LOW)), 'operations' => $this->t('Operations')); $cids = $this->commentStorage->getQuery()->condition('status', $status)->tableSort($header)->pager(50)->execute(); /** @var $comments \Drupal\comment\CommentInterface[] */ $comments = $this->commentStorage->loadMultiple($cids); // Build a table listing the appropriate comments. $options = array(); $destination = $this->getDestinationArray(); $commented_entity_ids = array(); $commented_entities = array(); foreach ($comments as $comment) { $commented_entity_ids[$comment->getCommentedEntityTypeId()][] = $comment->getCommentedEntityId(); } foreach ($commented_entity_ids as $entity_type => $ids) { $commented_entities[$entity_type] = $this->entityManager->getStorage($entity_type)->loadMultiple($ids); } foreach ($comments as $comment) { /** @var $commented_entity \Drupal\Core\Entity\EntityInterface */ $commented_entity = $commented_entities[$comment->getCommentedEntityTypeId()][$comment->getCommentedEntityId()]; $comment_permalink = $comment->permalink(); if ($comment->hasField('comment_body') && ($body = $comment->get('comment_body')->value)) { $attributes = $comment_permalink->getOption('attributes') ?: array(); $attributes += array('title' => Unicode::truncate($body, 128)); $comment_permalink->setOption('attributes', $attributes); } $options[$comment->id()] = array('title' => array('data' => array('#title' => $comment->getSubject() ?: $comment->id())), 'subject' => array('data' => array('#type' => 'link', '#title' => $comment->getSubject(), '#url' => $comment_permalink)), 'author' => array('data' => array('#theme' => 'username', '#account' => $comment->getOwner())), 'posted_in' => array('data' => array('#type' => 'link', '#title' => $commented_entity->label(), '#access' => $commented_entity->access('view'), '#url' => $commented_entity->urlInfo())), 'changed' => $this->dateFormatter->format($comment->getChangedTimeAcrossTranslations(), 'short')); $comment_uri_options = $comment->urlInfo()->getOptions() + ['query' => $destination]; $links = array(); $links['edit'] = array('title' => $this->t('Edit'), 'url' => $comment->urlInfo('edit-form', $comment_uri_options)); if ($this->moduleHandler->moduleExists('content_translation') && $this->moduleHandler->invoke('content_translation', 'translate_access', array($comment))->isAllowed()) { $links['translate'] = array('title' => $this->t('Translate'), 'url' => $comment->urlInfo('drupal:content-translation-overview', $comment_uri_options)); } $options[$comment->id()]['operations']['data'] = array('#type' => 'operations', '#links' => $links); } $form['comments'] = array('#type' => 'tableselect', '#header' => $header, '#options' => $options, '#empty' => $this->t('No comments available.')); $form['pager'] = array('#type' => 'pager'); return $form; }
public function prepareComment($comment, $length = NULL) { // Truncate comment to maximum comment length. if (isset($length)) { // Add table prefixes before truncating. $comment = Unicode::truncate($this->connection->prefixTables($comment), $length, TRUE, TRUE); } // Remove semicolons to avoid triggering multi-statement check. $comment = strtr($comment, array(';' => '.')); return $this->connection->quote($comment); }
/** * Form validation handler to perform textual analysis on submitted form values. */ public static function validateAnalysis(&$form, FormState $form_state) { if (!static::shouldValidate($form, $form_state)) { return; } /** @var \Drupal\mollom\Entity\Form $mollom_form */ $mollom = $form_state->getValue('mollom'); if (!$mollom['require_analysis']) { return FALSE; } // Perform textual analysis. $all_data = self::extractMollomValues($form_state->cleanValues(), $mollom['enabled_fields'], $mollom['mapping']); // Cancel processing upon invalid UTF-8 data. if ($all_data === FALSE) { return FALSE; } $data = $all_data; // Remove postId property; only used by submitForm(). if (isset($data['postId'])) { unset($data['postId']); } $contentId = isset($mollom['contentId']) ? $mollom['contentId'] : NULL; if (!empty($contentId)) { $data['id'] = $contentId; } if (is_array($mollom['checks'])) { $data['checks'] = $mollom['checks']; } $data['strictness'] = $mollom['strictness']; if (isset($mollom['type'])) { $data['type'] = $mollom['type']; } if (in_array('spam', $data['checks']) && $mollom['unsure'] == 'binary') { $data['unsure'] = 0; } // Allow modules to alter data sent. \Drupal::moduleHandler()->alter('mollom_content', $data); /** @var \Drupal\mollom\API\DrupalClient $mollom */ $mollom_service = \Drupal::service('mollom.client'); $result = $mollom_service->checkContent($data); // Use all available data properties for log messages below. $data += $all_data; // Trigger global fallback behavior if there is a unexpected result. if (!is_array($result) || !isset($result['id'])) { return MollomUtilities::handleFallback(); } // Set form values accordingly. Do not overwrite the entity ID. // @todo Rename 'id' to 'entity_id'. $result['contentId'] = $result['id']; unset($result['id']); // Store the response returned by Mollom. $form_state->setValue(array('mollom', 'response', 'content'), $result); $form_state->setValue('mollom', array_merge($mollom, $result)); // Ensure the latest content ID is output as value. // form_set_value() is effectless, as this is not a element-level but a // form-level validation handler. $form['mollom']['contentId']['#value'] = $result['contentId']; // Prepare watchdog message teaser text. $teaser = '--'; if (isset($data['postTitle'])) { $teaser = Unicode::truncate(strip_tags($data['postTitle']), 40); } elseif (isset($data['postBody'])) { $teaser = Unicode::truncate(strip_tags($data['postBody']), 40); } // Handle the profanity check result. if (isset($result['profanityScore']) && $result['profanityScore'] >= 0.5) { if ($mollom['discard']) { $form_state->setError($form, t('Your submission has triggered the profanity filter and will not be accepted until the inappropriate language is removed.')); } else { $form_state->setValue(['mollom', 'require_moderation'], TRUE); } Logger::addMessage(array('message' => 'Profanity: %teaser', 'arguments' => array('%teaser' => $teaser))); } // Handle the spam check result. // The Mollom API takes over state tracking for each content ID/session. The // spamClassification will usually turn into 'ham' after solving a CAPTCHA. // It may also change to 'spam', if the user replaced the values with very // spammy content. In any case, we always do what we are told to do. $form_state->setValue(['mollom', 'require_captcha'], FALSE); $form['mollom']['captcha']['#access'] = FALSE; if (isset($result['spamClassification'])) { switch ($result['spamClassification']) { case 'ham': $message = SafeMarkup::format('Ham: %teaser', array('%teaser' => $teaser)); \Drupal::logger('mollom')->notice($message); break; case 'spam': if ($mollom['discard']) { $form_state->setError($form, t('Your submission has triggered the spam filter and will not be accepted. @fp_message', array('@fp_message' => MollomUtilities::formatFalsePositiveMessage($form_state, $data)))); } else { $form_state->setValue(array('mollom', 'require_moderation'), TRUE); } $message = SafeMarkup::format('Spam: %teaser', array('%teaser' => $teaser)); \Drupal::logger('mollom')->notice($message); break; case 'unsure': if ($mollom['unsure'] == 'moderate') { $form_state->setValue(array('mollom', 'require_moderation'), TRUE); } else { $form_state->setValue(['mollom', 'captcha_response_id'], NULL); $form['mollom']['captcha_response_id']['#value'] = NULL; $form_state->setValue(array('mollom', 'require_captcha'), TRUE); // Require a new CAPTCHA and throw an error. $had_captcha = $form_state->get('mollom_had_captcha'); $form_state->setCached(FALSE); // Set the CAPTCHA type required indicator. $form_state->setValue(array('mollom', 'captcha_required'), $mollom['captcha_type']); $form['mollom']['captcha_required']['#value'] = $mollom['captcha_type']; $form['mollom']['captcha']['#access'] = TRUE; if (!empty($had_captcha)) { $form_state->setErrorByName('mollom][captcha', t('The word verification was not completed correctly. Please complete this new word verification and try again. @fp_message', array('@fp_message' => MollomUtilities::formatFalsePositiveMessage($form_state, $data)))); } else { $form_state->setErrorByName('mollom][captcha', t('To complete this form, please complete the word verification.')); } } $message = SafeMarkup::format('Unsure: %teaser', array('%teaser' => $teaser)); \Drupal::logger('mollom')->notice($message); break; case 'unknown': default: // If we end up here, Mollom responded with a unknown spamClassification. // Normally, this should not happen, but if it does, log it. As there // could be multiple reasons for this, it is not safe to trigger the // fallback mode. $message = SafeMarkup::format('Unknown: %teaser', array('%teaser' => $teaser)); \Drupal::logger('mollom')->notice($message); break; } } }
/** * {@inheritdoc} */ public function getLabel(JobItemInterface $job_item) { if ($locale_object = $this->getLocaleObject($job_item)) { if ($locale_object->origin == 'source') { $label = $locale_object->source; } else { $label = $locale_object->translation; } return Unicode::truncate(strip_tags($label), 30, FALSE, TRUE); } }
/** * {@inheritdoc} */ public function buildEntity(array $form, FormStateInterface $form_state) { /** @var \Drupal\comment\CommentInterface $comment */ $comment = parent::buildEntity($form, $form_state); if (!$form_state->isValueEmpty('date') && $form_state->getValue('date') instanceof DrupalDateTime) { $comment->setCreatedTime($form_state->getValue('date')->getTimestamp()); } else { $comment->setCreatedTime(REQUEST_TIME); } // Empty author ID should revert to anonymous. $author_id = $form_state->getValue('uid'); if ($comment->id() && $this->currentUser->hasPermission('administer comments')) { // Admin can leave the author ID blank to revert to anonymous. $author_id = $author_id ?: 0; } if (!is_null($author_id)) { if ($author_id === 0 && $form['author']['name']['#access']) { // Use the author name value when the form has access to the element and // the author ID is anonymous. $comment->setAuthorName($form_state->getValue('name')); } else { // Ensure the author name is not set. $comment->setAuthorName(NULL); } } else { $author_id = $this->currentUser->id(); } $comment->setOwnerId($author_id); // Validate the comment's subject. If not specified, extract from comment // body. if (trim($comment->getSubject()) == '') { if ($comment->hasField('comment_body')) { // The body may be in any format, so: // 1) Filter it into HTML // 2) Strip out all HTML tags // 3) Convert entities back to plain-text. $comment_text = $comment->comment_body->processed; $comment->setSubject(Unicode::truncate(trim(Html::decodeEntities(strip_tags($comment_text))), 29, TRUE, TRUE)); } // Edge cases where the comment body is populated only by HTML tags will // require a default subject. if ($comment->getSubject() == '') { $comment->setSubject($this->t('(No subject)')); } } return $comment; }
/** * {@inheritdoc} */ public function cleanString($string, array $options = array()) { if (empty($this->cleanStringCache)) { // Generate and cache variables used in this method. $config = $this->configFactory->get('pathauto.settings'); $this->cleanStringCache = array('separator' => $config->get('separator'), 'strings' => array(), 'transliterate' => $config->get('transliterate'), 'punctuation' => array(), 'reduce_ascii' => (bool) $config->get('reduce_ascii'), 'ignore_words_regex' => FALSE, 'lowercase' => (bool) $config->get('case'), 'maxlength' => min($config->get('max_component_length'), $this->aliasStorageHelper->getAliasSchemaMaxLength())); // Generate and cache the punctuation replacements for strtr(). $punctuation = $this->getPunctuationCharacters(); foreach ($punctuation as $name => $details) { $action = $config->get('punctuation.' . $name); switch ($action) { case PathautoManagerInterface::PUNCTUATION_REMOVE: $cache['punctuation'][$details['value']] = ''; $this->cleanStringCache; case PathautoManagerInterface::PUNCTUATION_REPLACE: $this->cleanStringCache['punctuation'][$details['value']] = $this->cleanStringCache['separator']; break; case PathautoManagerInterface::PUNCTUATION_DO_NOTHING: // Literally do nothing. break; } } // Generate and cache the ignored words regular expression. $ignore_words = $config->get('ignore_words'); $ignore_words_regex = preg_replace(array('/^[,\\s]+|[,\\s]+$/', '/[,\\s]+/'), array('', '\\b|\\b'), $ignore_words); if ($ignore_words_regex) { $this->cleanStringCache['ignore_words_regex'] = '\\b' . $ignore_words_regex . '\\b'; if (function_exists('mb_eregi_replace')) { mb_regex_encoding('UTF-8'); $this->cleanStringCache['ignore_words_callback'] = 'mb_eregi_replace'; } else { $this->cleanStringCache['ignore_words_callback'] = 'preg_replace'; $this->cleanStringCache['ignore_words_regex'] = '/' . $this->cleanStringCache['ignore_words_regex'] . '/i'; } } } // Empty strings do not need any processing. if ($string === '' || $string === NULL) { return ''; } $langcode = NULL; if (!empty($options['language'])) { $langcode = $options['language']->getId(); } elseif (!empty($options['langcode'])) { $langcode = $options['langcode']; } // Check if the string has already been processed, and if so return the // cached result. if (isset($this->cleanStringCache['strings'][$langcode][(string) $string])) { return $this->cleanStringCache['strings'][$langcode][(string) $string]; } // Remove all HTML tags from the string. $output = Html::decodeEntities($string); $output = PlainTextOutput::renderFromHtml($output); // Optionally transliterate. if ($this->cleanStringCache['transliterate']) { // If the reduce strings to letters and numbers is enabled, don't bother // replacing unknown characters with a question mark. Use an empty string // instead. $output = $this->transliteration->transliterate($output, $langcode, $this->cleanStringCache['reduce_ascii'] ? '' : '?'); } // Replace or drop punctuation based on user settings. $output = strtr($output, $this->cleanStringCache['punctuation']); // Reduce strings to letters and numbers. if ($this->cleanStringCache['reduce_ascii']) { $output = preg_replace('/[^a-zA-Z0-9\\/]+/', $this->cleanStringCache['separator'], $output); } // Get rid of words that are on the ignore list. if ($this->cleanStringCache['ignore_words_regex']) { $words_removed = $this->cleanStringCache['ignore_words_callback']($this->cleanStringCache['ignore_words_regex'], '', $output); if (Unicode::strlen(trim($words_removed)) > 0) { $output = $words_removed; } } // Always replace whitespace with the separator. $output = preg_replace('/\\s+/', $this->cleanStringCache['separator'], $output); // Trim duplicates and remove trailing and leading separators. $output = $this->getCleanSeparators($this->getCleanSeparators($output, $this->cleanStringCache['separator'])); // Optionally convert to lower case. if ($this->cleanStringCache['lowercase']) { $output = Unicode::strtolower($output); } // Shorten to a logical place based on word boundaries. $output = Unicode::truncate($output, $this->cleanStringCache['maxlength'], TRUE); // Cache this result in the static array. $this->cleanStringCache['strings'][$langcode][(string) $string] = $output; return $output; }
/** * {@inheritdoc} */ public function suggestedTitle() { // If the user entered a search string, truncate it and append it to the // title. if (!empty($this->keywords)) { return $this->t('Search for @keywords', array('@keywords' => Unicode::truncate($this->keywords, 60, TRUE, TRUE))); } // Use the default 'Search' title. return $this->t('Search'); }
protected function setDefaultSubjectIfNeeded(&$comment) { // Extract subject from comment body. if (!isset($comment['subject'])) { $comment['subject'] = ''; } if (trim($comment['subject']) == '') { if (isset($comment['comment_body'])) { // The body may be in any format, so: // 1) Filter it into HTML // 2) Strip out all HTML tags // 3) Convert entities back to plain-text. $comment_text = $comment['comment_body']['value']; $comment['subject'] = Unicode::truncate(trim(Html::decodeEntities(strip_tags($comment_text))), 29, TRUE, TRUE); } // Edge cases where the comment body is populated only by HTML tags will // require a default subject. if ($comment['subject'] == '') { $comment['subject'] = t('(No subject)'); } } }
/** * Checks that a table or column comment matches a given description. * * @param $description * The asserted description. * @param $table * The table to test. * @param $column * Optional column to test. */ function checkSchemaComment($description, $table, $column = NULL) { if (method_exists(Database::getConnection()->schema(), 'getComment')) { $comment = Database::getConnection()->schema()->getComment($table, $column); // The schema comment truncation for mysql is different. if (Database::getConnection()->databaseType() == 'mysql') { $max_length = $column ? 255 : 60; $description = Unicode::truncate($description, $max_length, TRUE, TRUE); } $this->assertEqual($comment, $description, 'The comment matches the schema description.'); } }
/** * Confirms that a log message appears on the database log overview screen. * * This function should only be used for the admin/reports/dblog page, because * it checks for the message link text truncated to 56 characters. Other log * pages have no detail links so they contain the full message text. * * @param string $log_message * The database log message to check. * @param string $message * The message to pass to simpletest. */ protected function assertLogMessage($log_message, $message) { $message_text = Unicode::truncate(Xss::filter($log_message, array()), 56, TRUE, TRUE); // After \Drupal\Component\Utility\Xss::filter(), HTML entities should be // converted to their character equivalents because assertLink() uses this // string in xpath() to query the Document Object Model (DOM). $this->assertLink(html_entity_decode($message_text), 0, $message); }