/** * Tests that mails for contact messages are correctly sent. */ function testSendPersonalContactMessage() { // Ensure that the web user's email needs escaping. $mail = $this->webUser->getUsername() . '&escaped@example.com'; $this->webUser->setEmail($mail)->save(); $this->drupalLogin($this->webUser); $this->drupalGet('user/' . $this->contactUser->id() . '/contact'); $this->assertEscaped($mail); $message = $this->submitPersonalContact($this->contactUser); $mails = $this->drupalGetMails(); $this->assertEqual(1, count($mails)); $mail = $mails[0]; $this->assertEqual($mail['to'], $this->contactUser->getEmail()); $this->assertEqual($mail['from'], $this->config('system.site')->get('mail')); $this->assertEqual($mail['reply-to'], $this->webUser->getEmail()); $this->assertEqual($mail['key'], 'user_mail'); $variables = array('@site-name' => $this->config('system.site')->get('name'), '@subject' => $message['subject[0][value]'], '@recipient-name' => $this->contactUser->getDisplayName()); $subject = PlainTextOutput::renderFromHtml(t('[@site-name] @subject', $variables)); $this->assertEqual($mail['subject'], $subject, 'Subject is in sent message.'); $this->assertTrue(strpos($mail['body'], 'Hello ' . $variables['@recipient-name']) !== FALSE, 'Recipient name is in sent message.'); $this->assertTrue(strpos($mail['body'], $this->webUser->getDisplayName()) !== FALSE, 'Sender name is in sent message.'); $this->assertTrue(strpos($mail['body'], $message['message[0][value]']) !== FALSE, 'Message body is in sent message.'); // Check there was no problems raised during sending. $this->drupalLogout(); $this->drupalLogin($this->adminUser); // Verify that the correct watchdog message has been logged. $this->drupalGet('/admin/reports/dblog'); $placeholders = array('@sender_name' => $this->webUser->username, '@sender_email' => $this->webUser->getEmail(), '@recipient_name' => $this->contactUser->getUsername()); $this->assertRaw(SafeMarkup::format('@sender_name (@sender_email) sent @recipient_name an email.', $placeholders)); // Ensure an unescaped version of the email does not exist anywhere. $this->assertNoRaw($this->webUser->getEmail()); }
/** * Constructs an OpenDialogCommand object. * * @param string $selector * The selector of the dialog. * @param string $title * The title of the dialog. * @param string|array $content * The content that will be placed in the dialog, either a render array * or an HTML string. * @param array $dialog_options * (optional) Options to be passed to the dialog implementation. Any * jQuery UI option can be used. See http://api.jqueryui.com/dialog. * @param array|null $settings * (optional) Custom settings that will be passed to the Drupal behaviors * on the content of the dialog. If left empty, the settings will be * populated automatically from the current request. */ public function __construct($selector, $title, $content, array $dialog_options = array(), $settings = NULL) { $title = PlainTextOutput::renderFromHtml($title); $dialog_options += array('title' => $title); $this->selector = $selector; $this->content = $content; $this->dialogOptions = $dialog_options; $this->settings = $settings; }
/** * Determines the URI for a file field. * * @param array $settings * The array of field settings. * @param array $data * An array of token objects to pass to token_replace(). * * @return string * An unsanitized file directory URI with tokens replaced. The result of * the token replacement is then converted to plain text and returned. */ protected static function doGetUploadLocation(array $settings, $data = []) { $destination = trim($settings['file_directory'], '/'); // Replace tokens. As the tokens might contain HTML we convert it to plain // text. $destination = PlainTextOutput::renderFromHtml(\Drupal::token()->replace($destination, $data)); return $settings['uri_scheme'] . '://' . $destination; }
/** * {@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 execute($entity = NULL) { if (empty($this->configuration['node'])) { $this->configuration['node'] = $entity; } $recipient = PlainTextOutput::renderFromHtml($this->token->replace($this->configuration['recipient'], $this->configuration)); // If the recipient is a registered user with a language preference, use // the recipient's preferred language. Otherwise, use the system default // language. $recipient_accounts = $this->storage->loadByProperties(array('mail' => $recipient)); $recipient_account = reset($recipient_accounts); if ($recipient_account) { $langcode = $recipient_account->getPreferredLangcode(); } else { $langcode = $this->languageManager->getDefaultLanguage()->getId(); } $params = array('context' => $this->configuration); if ($this->mailManager->mail('system', 'action_send_email', $recipient, $langcode, $params)) { $this->logger->notice('Sent email to %recipient', array('%recipient' => $recipient)); } else { $this->logger->error('Unable to send email to %recipient', array('%recipient' => $recipient)); } }
/** * Tests ::renderFromHtml(). * * @param $expected * The expected formatted value. * @param $string * A string to be formatted. * @param array $args * (optional) An associative array of replacements to make. Defaults to * none. * * @covers ::renderFromHtml * @dataProvider providerRenderFromHtml */ public function testRenderFromHtml($expected, $string, $args = []) { $markup = SafeMarkup::format($string, $args); $output = PlainTextOutput::renderFromHtml($markup); $this->assertSame($expected, $output); }
/** * Generate the elements that go in the attached array in * hook_page_attachments. * * @param array $tags * The array of tags as plugin_id => value. * @param object $entity * Optional entity object to use for token replacements. * @return array * Render array with tag elements. */ public function generateElements($tags, $entity = NULL) { $metatag_tags = $this->tagPluginManager->getDefinitions(); $elements = []; // Each element of the $values array is a tag with the tag plugin name // as the key. foreach ($tags as $tag_name => $value) { // Check to ensure there is a matching plugin. if (isset($metatag_tags[$tag_name])) { // Get an instance of the plugin. $tag = $this->tagPluginManager->createInstance($tag_name); // Render any tokens in the value. $token_replacements = []; if ($entity) { $token_replacements = [$entity->getEntityTypeId() => $entity]; } // Set the value as sometimes the data needs massaging, such as when // field defaults are used for the Robots field, which come as an array // that needs to be filtered and converted to a string. // @see @Robots::setValue(). $tag->setValue($value); $langcode = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId(); if ($tag->type() === 'image') { $processed_value = $this->tokenService->replace($tag->value(), $token_replacements, ['langcode' => $langcode]); } else { $processed_value = PlainTextOutput::renderFromHtml(htmlspecialchars_decode($this->tokenService->replace($tag->value(), $token_replacements, ['langcode' => $langcode]))); } // Now store the value with processed tokens back into the plugin. $tag->setValue($processed_value); // Have the tag generate the output based on the value we gave it. $output = $tag->output(); if (!empty($output)) { $elements['#attached']['html_head'][] = [$output, $tag_name]; } } } return $elements; }
/** * Creates the different types of attribute values. * * @param string $name * The attribute name. * @param mixed $value * The attribute value. * * @return \Drupal\Core\Template\AttributeValueBase * An AttributeValueBase representation of the attribute's value. */ protected function createAttributeValue($name, $value) { // If the value is already an AttributeValueBase object, // return a new instance of the same class, but with the new name. if ($value instanceof AttributeValueBase) { $class = get_class($value); return new $class($name, $value->value()); } // An array value or 'class' attribute name are forced to always be an // AttributeArray value for consistency. if ($name == 'class' && !is_array($value)) { // Cast the value to string in case it implements MarkupInterface. $value = [(string) $value]; } if (is_array($value)) { // Cast the value to an array if the value was passed in as a string. // @todo Decide to fix all the broken instances of class as a string // in core or cast them. $value = new AttributeArray($name, $value); } elseif (is_bool($value)) { $value = new AttributeBoolean($name, $value); } elseif ($value instanceof MarkupInterface) { // Attributes are not supposed to display HTML markup, so we just convert // the value to plain text. $value = PlainTextOutput::renderFromHtml($value); $value = new AttributeString($name, $value); } elseif (!is_object($value)) { $value = new AttributeString($name, $value); } return $value; }
/** * Determines the URI for a video field. * * @param array $settings * The array of field settings. * @param array $data * An array of token objects to pass to token_replace(). * * @return string * An unsanitized file directory URI with tokens replaced. The result of * the token replacement is then converted to plain text and returned. */ protected function getUploadLocation($data = []) { $settings = $this->getVideoSettings(); $destination = trim($settings['file_directory'], '/'); $destination = PlainTextOutput::renderFromHtml(\Drupal::token()->replace($destination, $data)); return $settings['uri_scheme'] . '://' . $destination; }
/** * {@inheritdoc} */ public function mail($module, $key, $to, $langcode, $params = array(), $reply = NULL, $send = TRUE) { $site_config = $this->configFactory->get('system.site'); $site_mail = $site_config->get('mail'); if (empty($site_mail)) { $site_mail = ini_get('sendmail_from'); } // Bundle up the variables into a structured array for altering. $message = array('id' => $module . '_' . $key, 'module' => $module, 'key' => $key, 'to' => $to, 'from' => $site_mail, 'reply-to' => $reply, 'langcode' => $langcode, 'params' => $params, 'send' => TRUE, 'subject' => '', 'body' => array()); // Build the default headers. $headers = array('MIME-Version' => '1.0', 'Content-Type' => 'text/plain; charset=UTF-8; format=flowed; delsp=yes', 'Content-Transfer-Encoding' => '8Bit', 'X-Mailer' => 'Drupal'); // To prevent email from looking like spam, the addresses in the Sender and // Return-Path headers should have a domain authorized to use the // originating SMTP server. $headers['Sender'] = $headers['Return-Path'] = $site_mail; $headers['From'] = $site_config->get('name') . ' <' . $site_mail . '>'; if ($reply) { $headers['Reply-to'] = $reply; } $message['headers'] = $headers; // Build the email (get subject and body, allow additional headers) by // invoking hook_mail() on this module. We cannot use // moduleHandler()->invoke() as we need to have $message by reference in // hook_mail(). if (function_exists($function = $module . '_mail')) { $function($key, $message, $params); } // Invoke hook_mail_alter() to allow all modules to alter the resulting // email. $this->moduleHandler->alter('mail', $message); // Retrieve the responsible implementation for this message. $system = $this->getInstance(array('module' => $module, 'key' => $key)); // Format the message body. $message = $system->format($message); // Optionally send email. if ($send) { // The original caller requested sending. Sending was canceled by one or // more hook_mail_alter() implementations. We set 'result' to NULL, // because FALSE indicates an error in sending. if (empty($message['send'])) { $message['result'] = NULL; } else { // Ensure that subject is plain text. By default translated and // formatted strings are prepared for the HTML context and email // subjects are plain strings. if ($message['subject']) { $message['subject'] = PlainTextOutput::renderFromHtml($message['subject']); } $message['result'] = $system->mail($message); // Log errors. if (!$message['result']) { $this->loggerFactory->get('mail')->error('Error sending email (from %from to %to with reply-to %reply).', array('%from' => $message['from'], '%to' => $message['to'], '%reply' => $message['reply-to'] ? $message['reply-to'] : $this->t('not set'))); drupal_set_message($this->t('Unable to send email. Contact the site administrator if the problem persists.'), 'error'); } } } return $message; }
/** * Determines the URI for a file field. * * @param array $data * An array of token objects to pass to token_replace(). * * @return string * An unsanitized file directory URI with tokens replaced. The result of * the token replacement is then converted to plain text and returned. * * @see token_replace() */ public function getUploadLocation($data = array()) { $settings = $this->getSettings(); $destination = trim($settings['file_directory'], '/'); // Replace tokens. As the tokens might contain HTML we convert it to plain // text. $destination = PlainTextOutput::renderFromHtml(\Drupal::token()->replace($destination, $data)); return $settings['uri_scheme'] . '://' . $destination; }
/** * {@inheritdoc} */ public function saveFile($uri, $destination, $extensions, AccountProxyInterface $user, $validators = []) { // Create the file entity. $file = $this->fileEntityFromUri($uri, $user); // Replace tokens. As the tokens might contain HTML we convert it to plain // text. $destination = PlainTextOutput::renderFromHtml($this->token->replace($destination)); // Handle potentialy dangerous extensions. $renamed = $this->renameExecutableExtensions($file); // The .txt extension may not be in the allowed list of extensions. We have // to add it here or else the file upload will fail. if ($renamed && !empty($extensions)) { $extensions .= ' txt'; drupal_set_message(t('For security reasons, your upload has been renamed to %filename.', ['%filename' => $file->getFilename()])); } // Validate the file. $errors = $this->validateFile($file, $extensions, $validators); if (!empty($errors)) { $message = ['error' => ['#markup' => t('The specified file %name could not be uploaded.', ['%name' => $file->getFilename()])], 'item_list' => ['#theme' => 'item_list', '#items' => $errors]]; drupal_set_message($this->renderer->renderPlain($message), 'error'); return FALSE; } // Prepare destination. if (!$this->prepareDestination($file, $destination)) { drupal_set_message(t('The file could not be uploaded because the destination %destination is invalid.', ['%destination' => $destination]), 'error'); return FALSE; } // Move uploaded files from PHP's upload_tmp_dir to destination. $move_result = file_unmanaged_move($uri, $file->getFileUri()); if (!$move_result) { drupal_set_message(t('File upload error. Could not move uploaded file.'), 'error'); $this->logger->notice('Upload error. Could not move uploaded file %file to destination %destination.', ['%file' => $file->getFilename(), '%destination' => $file->getFileUri()]); return FALSE; } // Set the permissions on the new file. $this->fileSystem->chmod($file->getFileUri()); // If we made it this far it's safe to record this file in the database. $file->save(); return $file; }