/** * {@inheritdoc} */ public function log($level, $message, array $context = array()) { // Remove any backtraces since they may contain an unserializable variable. unset($context['backtrace']); // Convert PSR3-style messages to SafeMarkup::format() style, so they can be // translated too in runtime. $message_placeholders = $this->parser->parseMessagePlaceholders($message, $context); try { $this->connection->insert('watchdog')->fields(array('uid' => $context['uid'], 'type' => Unicode::substr($context['channel'], 0, 64), 'message' => $message, 'variables' => serialize($message_placeholders), 'severity' => $level, 'link' => $context['link'], 'location' => $context['request_uri'], 'referer' => $context['referer'], 'hostname' => Unicode::substr($context['ip'], 0, 128), 'timestamp' => $context['timestamp']))->execute(); } catch (\Exception $e) { // When running Drupal on MySQL or MariaDB you can run into several errors // that corrupt the database connection. Some examples for these kind of // errors on the database layer are "1100 - Table 'xyz' was not locked // with LOCK TABLES" and "1153 - Got a packet bigger than // 'max_allowed_packet' bytes". If such an error happens, the MySQL server // invalidates the connection and answers all further requests in this // connection with "2006 - MySQL server had gone away". In that case the // insert statement above results in a database exception. To ensure that // the causal error is written to the log we try once to open a dedicated // connection and write again. if (($e instanceof DatabaseException || $e instanceof \PDOException) && $this->connection->getTarget() != self::DEDICATED_DBLOG_CONNECTION_TARGET) { // Open a dedicated connection for logging. $key = $this->connection->getKey(); $info = Database::getConnectionInfo($key); Database::addConnectionInfo($key, self::DEDICATED_DBLOG_CONNECTION_TARGET, $info['default']); $this->connection = Database::getConnection(self::DEDICATED_DBLOG_CONNECTION_TARGET, $key); // Now try once to log the error again. $this->log($level, $message, $context); } else { throw $e; } } }
/** * {@inheritdoc} */ protected function prepareValue($delta, array &$values) { // Trim the value if it's too long. if (!empty($this->settings['max_length'])) { $values['value'] = Unicode::substr($values['value'], 0, $this->settings['max_length']); } }
/** * Form submit handler for the theme settings form. */ function at_core_submit_layouts(&$form, &$form_state) { $build_info = $form_state->getBuildInfo(); $values = $form_state->getValues(); $theme = $build_info['args'][0]; // Generate and save a new layout. if (isset($values['settings_layouts_enable']) && $values['settings_layouts_enable'] == 1) { $generateLayout = new LayoutSubmit($theme, $values); // Update the themes info file with new regions. $generateLayout->saveLayoutRegions(); // Build and save the suggestions layout css files. $generateLayout->saveLayoutSuggestionsCSS(); // Build and save the suggestions twig templates. $generateLayout->saveLayoutSuggestionsMarkup(); // Add a new suggestion to the page suggestions array in config. if (!empty($values['ts_name'])) { $suggestion = trim($values['ts_name']); $clean_suggestion = str_replace('-', '_', $suggestion); $values["settings_suggestion_page__$clean_suggestion"] = $clean_suggestion; } // Delete suggestion files $templates_directory = drupal_get_path('theme', $theme) . '/templates/page'; $css_directory = $values['settings_generated_files_path']; foreach ($values as $values_key => $values_value) { if (substr($values_key, 0, 18) === 'delete_suggestion_') { if ($values_value === 1) { $delete_suggestion_keys[] = Unicode::substr($values_key, 18); } } } if (isset($delete_suggestion_keys)) { foreach ($delete_suggestion_keys as $suggestion_to_remove) { $formatted_suggestion = str_replace('_', '-', $suggestion_to_remove); $template_file_path = $templates_directory . '/' . $formatted_suggestion . '.html.twig'; $css_file_path = $css_directory . '/' . $theme . '--layout__' . $formatted_suggestion . '.css'; if (file_exists($template_file_path)) {unlink($template_file_path);} if (file_exists($css_file_path)) {unlink($css_file_path);} } } } // Flush all caches. This is the only realy reliable way I have found to ensure // new templates and layouts work correctly. drupal_flush_all_caches(); // Manage settings and configuration. // Must get mutable config otherwise bad things happen. $config = \Drupal::configFactory()->getEditable($theme . '.settings'); $convertToConfig = new ThemeSettingsConfig(); $convertToConfig->settingsConvertToConfig($values, $config); }
/** * {@inheritdoc} */ public static function generateSampleValue(FieldDefinitionInterface $field_definition) { $values = parent::generateSampleValue($field_definition); $suffix_length = $field_definition->getSetting('max_length') - 7; foreach ($values as $key => $value) { $values[$key] = 'http://' . Unicode::substr($value, 0, $suffix_length); } return $values; }
/** * {@inheritdoc} */ public function log($level, $message, array $context = array()) { // Remove any backtraces since they may contain an unserializable variable. unset($context['backtrace']); // Convert PSR3-style messages to SafeMarkup::format() style, so they can be // translated too in runtime. $message_placeholders = $this->parser->parseMessagePlaceholders($message, $context); $this->database->insert('watchdog')->fields(array('uid' => $context['uid'], 'type' => Unicode::substr($context['channel'], 0, 64), 'message' => $message, 'variables' => serialize($message_placeholders), 'severity' => $level, 'link' => $context['link'], 'location' => $context['request_uri'], 'referer' => $context['referer'], 'hostname' => Unicode::substr($context['ip'], 0, 128), 'timestamp' => $context['timestamp']))->execute(); }
/** * Convert a RGBA hex to its RGBA integer GD components. * * GD expects a value between 0 and 127 for alpha, where 0 indicates * completely opaque while 127 indicates completely transparent. * RGBA hexadecimal notation has #00 for transparent and #FF for * fully opaque. * * @param string $rgba_hex * A string specifing an RGBA color in the format '#RRGGBBAA'. * * @return array * An array with four elements for red, green, blue, and alpha. */ protected function hexToRgba($rgba_hex) { $rgbHex = Unicode::substr($rgba_hex, 0, 7); try { $rgb = Color::hexToRgb($rgbHex); $opacity = ColorUtility::rgbaToOpacity($rgba_hex); $alpha = 127 - floor($opacity / 100 * 127); $rgb['alpha'] = $alpha; return $rgb; } catch (\InvalidArgumentException $e) { return FALSE; } }
/** * @return mixed */ public function decrypt($text, $key, $options = array()) { $processed_text = ''; // Key cannot be too long for this encryption. $key = \Drupal\Component\Utility\Unicode::substr($key, 0, 32); // Define iv cipher. $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB); $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $disable_base64 = array_key_exists('base64', $options) && $options['base64'] == FALSE; // Check if we are disabling base64 encoding if (!$disable_base64) { $text = base64_decode($text); } // Decrypt text. return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, $iv)); }
/** * Tests entity based deduplication based on providerTestDedupe() values. * * @dataProvider providerTestDedupe */ public function testDedupe($count, $postfix = '', $start = NULL, $length = NULL) { $configuration = array('entity_type' => 'test_entity_type', 'field' => 'test_field'); if ($postfix) { $configuration['postfix'] = $postfix; } $configuration['start'] = isset($start) ? $start : NULL; $configuration['length'] = isset($length) ? $length : NULL; $plugin = new DedupeEntity($configuration, 'dedupe_entity', array(), $this->getMigration(), $this->entityQueryFactory); $this->entityQueryExpects($count); $value = $this->randomMachineName(32); $actual = $plugin->transform($value, $this->migrateExecutable, $this->row, 'testproperty'); $expected = Unicode::substr($value, $start, $length); $expected .= $count ? $postfix . $count : ''; $this->assertSame($expected, $actual); }
/** * Tests that all Unicode characters simplify correctly. */ function testSearchSimplifyUnicode() { // This test uses a file that was constructed so that the even lines are // boundary characters, and the odd lines are valid word characters. (It // was generated as a sequence of all the Unicode characters, and then the // boundary characters (punctuation, spaces, etc.) were split off into // their own lines). So the even-numbered lines should simplify to nothing, // and the odd-numbered lines we need to split into shorter chunks and // verify that simplification doesn't lose any characters. $input = file_get_contents(\Drupal::root() . '/core/modules/search/tests/UnicodeTest.txt'); $basestrings = explode(chr(10), $input); $strings = array(); foreach ($basestrings as $key => $string) { if ($key % 2) { // Even line - should simplify down to a space. $simplified = search_simplify($string); $this->assertIdentical($simplified, ' ', "Line {$key} is excluded from the index"); } else { // Odd line, should be word characters. // Split this into 30-character chunks, so we don't run into limits // of truncation in search_simplify(). $start = 0; while ($start < Unicode::strlen($string)) { $newstr = Unicode::substr($string, $start, 30); // Special case: leading zeros are removed from numeric strings, // and there's one string in this file that is numbers starting with // zero, so prepend a 1 on that string. if (preg_match('/^[0-9]+$/', $newstr)) { $newstr = '1' . $newstr; } $strings[] = $newstr; $start += 30; } } } foreach ($strings as $key => $string) { $simplified = search_simplify($string); $this->assertTrue(Unicode::strlen($simplified) >= Unicode::strlen($string), "Nothing is removed from string {$key}."); } // Test the low-numbered ASCII control characters separately. They are not // in the text file because they are problematic for diff, especially \0. $string = ''; for ($i = 0; $i < 32; $i++) { $string .= chr($i); } $this->assertIdentical(' ', search_simplify($string), 'Search simplify works for ASCII control characters.'); }
/** * {@inheritdoc} */ protected function prepareValue($delta, array &$values) { $values['value'] = (string) $values['value']; // At todo. Maybe break these up into separate classes. if (!empty($this->settings['settings']['allowed_values'])) { if ($key = array_search($values['value'], $this->settings['settings']['allowed_values']) !== FALSE) { $values['value'] = $key; } else { $values['value'] = ''; } } // Trim the value if it's too long. if (!empty($this->settings['settings']['max_length'])) { $values['value'] = Unicode::substr($values['value'], 0, $this->settings['settings']['max_length']); } $values['format'] = $this->configuration['format']; }
/** * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { $start = isset($this->configuration['start']) ? $this->configuration['start'] : 0; if (!is_int($start)) { throw new MigrateException('The start position configuration value should be an integer. Omit this key to capture from the beginning of the string.'); } $length = isset($this->configuration['length']) ? $this->configuration['length'] : NULL; if (!is_null($length) && !is_int($length)) { throw new MigrateException('The character length configuration value should be an integer. Omit this key to capture from the start position to the end of the string.'); } if (!is_string($value)) { throw new MigrateException('The input value must be a string.'); } // Use optional start or length to return a portion of $value. $new_value = Unicode::substr($value, $start, $length); return $new_value; }
/** * {@inheritdoc} */ protected function prepareValue($delta, array &$values) { $values['value'] = (string) $values['value']; // @todo We need to generalize this big time. We might be able to get rid of // some target classes if property_constraints get used across the board. if (!empty($this->settings['property_constraints'])) { foreach ($this->settings['property_constraints'] as $key => $constraint) { foreach ($constraint as $name => $condition) { switch ($name) { case 'Length': $values[$key] = Unicode::substr($values[$key], 0, $condition['max']); break; } } } } }
/** * Set config for theme settings, core seems to have forgotten themes can * have custom settings that you probably very much need in config. */ public function settingsConvertToConfig(array $values, Config $config) { foreach ($values as $key => $value) { // Save settings as config if (substr($key, 0, 9) == 'settings_') { $config_key = Unicode::substr($key, 9); $config->set('settings.' . $config_key, $value)->save(); } // Delete suggestions config settings. We do not remove all the suggestions settings // because later on if the suggestion is recreated there will be settings for it already, // which is kind of nice for the user should they accidentally delete a suggestion. if (substr($key, 0, 18) == 'delete_suggestion_') { $delete_suggestion_key = 'settings.suggestion_' . Unicode::substr($key, 18); if ($value == 1) { $config->clear($delete_suggestion_key, $value)->save(); } } } }
public function addWords($words, $tag = '') { if ($tag != $this->tag) { $this->_flushGroup($tag); } foreach ($words as $word) { // new-line should only come as first char of word. if ($word == '') { continue; } if ($word[0] == "\n") { $this->_flushLine($tag); $word = Unicode::substr($word, 1); } assert(!strstr($word, "\n")); $this->group .= $word; } }
/** * {@inheritdoc} */ public function optimize(array $js_asset) { if ($js_asset['type'] !== 'file') { throw new \Exception('Only file JavaScript assets can be optimized.'); } if ($js_asset['type'] === 'file' && !$js_asset['preprocess']) { throw new \Exception('Only file JavaScript assets with preprocessing enabled can be optimized.'); } // If a BOM is found, convert the file to UTF-8, then use substr() to // remove the BOM from the result. $data = file_get_contents($js_asset['data']); if ($encoding = Unicode::encodingFromBOM($data)) { $data = Unicode::substr(Unicode::convertToUtf8($data, $encoding), 1); } elseif (isset($js_asset['attributes']['charset'])) { $data = Unicode::convertToUtf8($data, $js_asset['attributes']['charset']); } // No-op optimizer: no optimizations are applied to JavaScript assets. return $data; }
/** * {@inheritdoc} */ public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { $i = 1; $postfix = isset($this->configuration['postfix']) ? $this->configuration['postfix'] : ''; $start = isset($this->configuration['start']) ? $this->configuration['start'] : 0; if (!is_int($start)) { throw new MigrateException('The start position configuration key should be an integer. Omit this key to capture from the beginning of the string.'); } $length = isset($this->configuration['length']) ? $this->configuration['length'] : NULL; if (!is_null($length) && !is_int($length)) { throw new MigrateException('The character length configuration key should be an integer. Omit this key to capture the entire string.'); } // Use optional start or length to return a portion of deduplicated value. $value = Unicode::substr($value, $start, $length); $new_value = $value; while ($this->exists($new_value)) { $new_value = $value . $postfix . $i++; } return $new_value; }
/** * {@inheritdoc} */ protected function processStubRow(Row $row) { // We stub the uri value ourselves so we can create a real stub file for it. if (!$row->getDestinationProperty('uri')) { $field_definitions = $this->entityManager->getFieldDefinitions($this->storage->getEntityTypeId(), $this->getKey('bundle')); $value = UriItem::generateSampleValue($field_definitions['uri']); if (empty($value)) { throw new MigrateException('Stubbing failed, unable to generate value for field uri'); } // generateSampleValue() wraps the value in an array. $value = reset($value); // Make it into a proper public file uri, stripping off the existing // scheme if present. $value = 'public://' . preg_replace('|^[a-z]+://|i', '', $value); $value = Unicode::substr($value, 0, $field_definitions['uri']->getSetting('max_length')); // Create a real file, so File::preSave() can do filesize() on it. touch($value); $row->setDestinationProperty('uri', $value); } parent::processStubRow($row); }
public function getOptions(FieldDefinitionInterface $field, $component) { $fs = $field->getFieldStorageDefinition()->getSettings(); $options = $fs[$component . '_options']; foreach ($options as $index => $opt) { if (preg_match('/^\\[vocabulary:([0-9a-z\\_]{1,})\\]/', trim($opt), $matches)) { unset($options[$index]); if ($this->termStorage && $this->vocabularyStorage) { $vocabulary = $this->vocabularyStorage->load($matches[1]); if ($vocabulary) { $max_length = isset($fs['max_length'][$component]) ? $fs['max_length'][$component] : 255; foreach ($this->termStorage->loadTree($vocabulary->id()) as $term) { if (Unicode::strlen($term->name) <= $max_length) { $options[] = $term->name; } } } } } } // Options could come from multiple sources, filter duplicates. $options = array_unique($options); if (isset($fs['sort_options']) && !empty($fs['sort_options'][$component])) { natcasesort($options); } $default = FALSE; foreach ($options as $index => $opt) { if (strpos($opt, '--') === 0) { unset($options[$index]); $default = trim(Unicode::substr($opt, 2)); } } $options = array_map('trim', $options); $options = array_combine($options, $options); if ($default !== FALSE) { $options = array('' => $default) + $options; } return $options; }
/** * Formats the weekday information into a table header format. * * @return array * An array with weekday table header data. */ public static function weekHeader($view) { $nameSize = $view->styleInfo->getNameSize(); $len = isset($nameSize) ? $view->styleInfo->getNameSize() : (!empty($view->styleInfo->isMini()) ? 1 : 3); $with_week = !empty($view->styleInfo->isShowWeekNumbers()); // create week header $untranslated_days = self::untranslatedDays(); $full_translated_days = self::weekDaysOrdered(self::weekDays(TRUE)); if ($len == 99) { $translated_days = $full_translated_days; } else { $translated_days = self::weekDaysOrdered(self::weekDaysAbbr(TRUE)); } if ($with_week) { $row[] = ['header' => TRUE, 'class' => 'days week', 'data' => '', 'header_id' => 'Week']; } foreach ($untranslated_days as $delta => $day) { $label = $len < 3 ? Unicode::substr($translated_days[$delta], 0, $len) : $translated_days[$delta]; $row[] = ['header' => TRUE, 'class' => "days " . $day, 'data' => $label, 'header_id' => $full_translated_days[$delta]]; } return $row; }
/** * Replaces URLs with absolute URLs. */ public static function absoluteMailUrls($match) { global $base_url, $base_path; $regexp =& drupal_static(__FUNCTION__); $url = $label = ''; if ($match) { if (empty($regexp)) { $regexp = '@^' . preg_quote($base_path, '@') . '@'; } list(, $url, $label) = $match; $url = strpos($url, '://') ? $url : preg_replace($regexp, $base_url . '/', $url); // If the link is formed by Drupal's URL filter, we only return the URL. // The URL filter generates a label out of the original URL. if (strpos($label, '...') === Unicode::strlen($label) - 3) { // Remove ellipsis from end of label. $label = Unicode::substr($label, 0, Unicode::strlen($label) - 3); } if (strpos($url, $label) !== FALSE) { return $url; } return $label . ' ' . $url; } }
/** * Tests access to user autocompletion and verify the correct results. */ function testUserAutocomplete() { // Check access from unprivileged user, should be denied. $this->drupalLogin($this->unprivileged_user); $username = $this->unprivileged_user->getUsername(); $this->drupalGet('user/autocomplete', array('query' => array('q' => $username[0]))); $this->assertResponse(403, 'Autocompletion access denied to user without permission.'); // Check access from privileged user. $this->drupalLogout(); $this->drupalLogin($this->privileged_user); $this->drupalGet('user/autocomplete', array('query' => array('q' => $username[0]))); $this->assertResponse(200, 'Autocompletion access allowed.'); // Using first letter of the user's name, make sure the user's full name is in the results. $this->assertRaw($this->unprivileged_user->getUsername(), 'User name found in autocompletion results.'); $anonymous_name = $this->randomString() . '<script>alert();</script>'; \Drupal::config('user.settings')->set('anonymous', $anonymous_name)->save(); // Test that anonymous username is in the result when requested and escaped // with \Drupal\Component\Utility\String::checkPlain(). $users = $this->drupalGetJSON('user/autocomplete/anonymous', array('query' => array('q' => Unicode::substr($anonymous_name, 0, 4)))); $this->assertEqual(String::checkPlain($anonymous_name), $users[0]['label'], 'The anonymous name found in autocompletion results.'); $users = $this->drupalGetJSON('user/autocomplete', array('query' => array('q' => Unicode::substr($anonymous_name, 0, 4)))); $this->assertTrue(empty($users), 'The anonymous name not found in autocompletion results without enabling anonymous username.'); }
/** * Processes a 'image_effects_color' form element. * * @param array $element * The form element to process. Properties used: * '#allow_null' - if set to TRUE, a checkbox is displayed to set the * color as a full transparency, In this case, color hex and opacity are * hidden, and the value returned is NULL. * '#allow_opacity' - if set to TRUE, a textfield is displayed to capture the * 'opacity' value, as a percentage. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * @param array $complete_form * The complete form structure. * * @return array * The processed element. */ public static function processImageEffectsColor(&$element, FormStateInterface $form_state, &$complete_form) { // Make sure element properties are set. $element += ['#allow_null' => FALSE, '#allow_opacity' => FALSE, '#description' => NULL, '#states' => NULL, '#title' => t('Color'), '#checkbox_title' => t('Transparent')]; // In case default value is transparent, set hex and opacity to default // values (white, fully opaque) so that if transparency is unchecked, // we have a starting value. $transparent = empty($element['#default_value']) ? TRUE : FALSE; $hex = $transparent ? '#FFFFFF' : Unicode::substr($element['#default_value'], 0, 7); $opacity = $transparent ? 100 : ColorUtility::rgbaToOpacity($element['#default_value']); $colorPlugin = \Drupal::service('plugin.manager.image_effects.color_selector')->getPlugin(); if ($element['#allow_null'] || $element['#allow_opacity']) { // More sub-fields are needed to define the color, wrap them in a // container fieldset. $element['container'] = array('#type' => 'fieldset', '#description' => $element['#description'], '#title' => $element['#title'], '#states' => $element['#states']); // Checkbox for transparency. if ($element['#allow_null']) { $element['container']['transparent'] = array('#type' => 'checkbox', '#title' => $element['#checkbox_title'], '#default_value' => $transparent); } // Color field. $element['container']['hex'] = $colorPlugin->selectionElement(array('#default_value' => $hex)); // States management for color field. $element['container']['hex']['#states'] = array('visible' => array(':input[name="' . $element['#name'] . '[container][transparent]"]' => array('checked' => FALSE))); // Textfield for opacity. if ($element['#allow_opacity']) { $element['container']['opacity'] = array('#type' => 'number', '#title' => t('Opacity'), '#default_value' => $opacity, '#maxlength' => 3, '#size' => 2, '#field_suffix' => '%', '#min' => 0, '#max' => 100, '#states' => array('visible' => array(':input[name="' . $element['#name'] . '[container][transparent]"]' => array('checked' => FALSE)))); } } else { // No transparency or opacity, straight color field. $options = $element; $options['#default_value'] = $hex; $element['hex'] = $colorPlugin->selectionElement($options); } unset($element['#description'], $element['#title']); return $element; }
/** * {@inheritdoc} */ public function encrypt($key, $source, $sourcelen = 0) { $this->errors = array(); // Convert key into sequence of numbers $fudgefactor = $this->convertKey($key); if ($this->errors) { return; } if (empty($source)) { // Commented out to prevent errors getting logged for use cases that may // have variable encryption/decryption requirements. -RS // $this->errors[] = t('No value has been supplied for encryption'); return; } while (strlen($source) < $sourcelen) { $source .= ' '; } $target = NULL; $factor2 = 0; for ($i = 0; $i < Unicode::strlen($source); $i++) { $char1 = Unicode::substr($source, $i, 1); $num1 = strpos(self::$scramble1, $char1); if ($num1 === FALSE) { $this->errors[] = t('Source string contains an invalid character (@char)', ['@char' => $char1]); return; } $adj = $this->applyFudgeFactor($fudgefactor); $factor1 = $factor2 + $adj; $num2 = round($factor1) + $num1; $num2 = $this->checkRange($num2); $factor2 = $factor1 + $num2; $char2 = substr(self::$scramble2, $num2, 1); $target .= $char2; } return $target; }
/** * Determines what the most important (or only) info file is in a directory. * * Since there is no enforcement of which info file is the project's "main" * info file, this will get one with the same name as the directory, or the * first one it finds. Not ideal, but needs a larger solution. * * @param string $directory * Directory to search in. * * @return string * Path to the info file. */ public static function findInfoFile($directory) { $info_files = file_scan_directory($directory, '/.*\\.info.yml$/'); if (!$info_files) { return FALSE; } foreach ($info_files as $info_file) { if (Unicode::substr($info_file->filename, 0, -9) == drupal_basename($directory)) { // Info file Has the same name as the directory, return it. return $info_file->uri; } } // Otherwise, return the first one. $info_file = array_shift($info_files); return $info_file->uri; }
/** * {@inheritdoc} */ public function installCollectionDefaultConfig($collection) { $storage = new ExtensionInstallStorage($this->getActiveStorages(StorageInterface::DEFAULT_COLLECTION), InstallStorage::CONFIG_INSTALL_DIRECTORY, $collection, $this->drupalInstallationAttempted()); // Only install configuration for enabled extensions. $enabled_extensions = $this->getEnabledExtensions(); $config_to_install = array_filter($storage->listAll(), function ($config_name) use($enabled_extensions) { $provider = Unicode::substr($config_name, 0, strpos($config_name, '.')); return in_array($provider, $enabled_extensions); }); if (!empty($config_to_install)) { $this->createConfiguration($collection, $storage->readMultiple($config_to_install)); // Reset all the static caches and list caches. $this->configFactory->reset(); } }
/** * Tests JavaScript settings. */ function testSettings() { $build = array(); $build['#attached']['library'][] = 'core/drupalSettings'; // Nonsensical value to verify if it's possible to override path settings. $build['#attached']['drupalSettings']['path']['pathPrefix'] = 'yarhar'; $assets = AttachedAssets::createFromRenderArray($build); $js = $this->assetResolver->getJsAssets($assets, FALSE)[1]; $js_render_array = \Drupal::service('asset.js.collection_renderer')->render($js); $rendered_js = $this->renderer->renderPlain($js_render_array); // Parse the generated drupalSettings <script> back to a PHP representation. $startToken = '{'; $endToken = '}'; $start = strpos($rendered_js, $startToken); $end = strrpos($rendered_js, $endToken); $json = Unicode::substr($rendered_js, $start, $end - $start + 1); $parsed_settings = Json::decode($json); // Test whether the settings for core/drupalSettings are available. $this->assertTrue(isset($parsed_settings['path']['baseUrl']), 'drupalSettings.path.baseUrl is present.'); $this->assertIdentical($parsed_settings['path']['pathPrefix'], 'yarhar', 'drupalSettings.path.pathPrefix is present and has the correct (overridden) value.'); $this->assertIdentical($parsed_settings['path']['currentPath'], '', 'drupalSettings.path.currentPath is present and has the correct value.'); $this->assertIdentical($parsed_settings['path']['currentPathIsAdmin'], FALSE, 'drupalSettings.path.currentPathIsAdmin is present and has the correct value.'); $this->assertIdentical($parsed_settings['path']['isFront'], FALSE, 'drupalSettings.path.isFront is present and has the correct value.'); $this->assertIdentical($parsed_settings['path']['currentLanguage'], 'en', 'drupalSettings.path.currentLanguage is present and has the correct value.'); // Tests whether altering JavaScript settings via hook_js_settings_alter() // is working as expected. // @see common_test_js_settings_alter() $this->assertIdentical($parsed_settings['pluralDelimiter'], '☃'); $this->assertIdentical($parsed_settings['foo'], 'bar'); }
/** * {@inheritdoc} */ public function renderSpans($data_options, $mtitle, $mpath) { foreach ($data_options['option_extras'] as $service) { $data_options['services'] .= ',"' . $service . '"'; } // The share buttons are simply spans of the form class='st_SERVICE_BUTTONTYPE' -- "st" stands for ShareThis. $type = Unicode::substr($data_options['buttons'], 4); $type = $type == "_" ? "" : Html::escape($type); $service_array = explode(",", $data_options['services']); $st_spans = ""; foreach ($service_array as $service_full) { // Strip the quotes from the element in the array (They are there for javascript). $service = explode(":", $service_full); // Service names are expected to be parsed by Name:machine_name. If only one // element in the array is given, it's an invalid service. if (count($service) < 2) { continue; } // Find the service code name. $service_code_name = Unicode::substr($service[1], 0, -1); // Switch the title on a per-service basis if required. // $mtitle = $mtitle;. switch ($service_code_name) { case 'twitter': $mtitle = empty($data_options['twitter_suffix']) ? $mtitle : Html::escape($mtitle) . ' ' . Html::escape($data_options['twitter_suffix']); break; } // Sanitize the service code for display. $display = Html::escape($service_code_name); // Put together the span attributes. $attributes = array('st_url' => $mpath, 'st_title' => $mtitle, 'class' => 'st_' . $display . $type); if ($service_code_name == 'twitter') { if (!empty($data_options['twitter_handle'])) { $attributes['st_via'] = $data_options['twitter_handle']; $attributes['st_username'] = $data_options['twitter_recommends']; } } // Only show the display text if the type is set. if (!empty($type)) { $attributes['displayText'] = Html::escape($display); } $meta_generator = array('#type' => 'html_tag', '#tag' => 'span', '#attributes' => $attributes, '#value' => ''); // Render the span tag. $st_spans .= drupal_render($meta_generator); } return ['data_options' => $data_options, 'm_path' => $mpath, 'm_title' => $mtitle, 'st_spans' => $st_spans]; }
/** * Generates and then verifies some user events. */ private function doUser() { // Set user variables. $name = $this->randomMachineName(); $pass = user_password(); // Add a user using the form to generate an add user event (which is not // triggered by drupalCreateUser). $edit = array(); $edit['name'] = $name; $edit['mail'] = $name . '@example.com'; $edit['pass[pass1]'] = $pass; $edit['pass[pass2]'] = $pass; $edit['status'] = 1; $this->drupalPostForm('admin/people/create', $edit, t('Create new account')); $this->assertResponse(200); // Retrieve the user object. $user = user_load_by_name($name); $this->assertTrue($user != NULL, format_string('User @name was loaded', array('@name' => $name))); // pass_raw property is needed by drupalLogin. $user->pass_raw = $pass; // Log in user. $this->drupalLogin($user); // Log out user. $this->drupalLogout(); // Fetch the row IDs in watchdog that relate to the user. $result = db_query('SELECT wid FROM {watchdog} WHERE uid = :uid', array(':uid' => $user->id())); foreach ($result as $row) { $ids[] = $row->wid; } $count_before = isset($ids) ? count($ids) : 0; $this->assertTrue($count_before > 0, format_string('DBLog contains @count records for @name', array('@count' => $count_before, '@name' => $user->getUsername()))); // Log in the admin user. $this->drupalLogin($this->adminUser); // Delete the user created at the start of this test. // We need to POST here to invoke batch_process() in the internal browser. $this->drupalPostForm('user/' . $user->id() . '/cancel', array('user_cancel_method' => 'user_cancel_reassign'), t('Cancel account')); // View the database log report. $this->drupalGet('admin/reports/dblog'); $this->assertResponse(200); // Verify that the expected events were recorded. // Add user. // Default display includes name and email address; if too long, the email // address is replaced by three periods. $this->assertLogMessage(t('New user: %name %email.', array('%name' => $name, '%email' => '<' . $user->getEmail() . '>')), 'DBLog event was recorded: [add user]'); // Log in user. $this->assertLogMessage(t('Session opened for %name.', array('%name' => $name)), 'DBLog event was recorded: [login user]'); // Log out user. $this->assertLogMessage(t('Session closed for %name.', array('%name' => $name)), 'DBLog event was recorded: [logout user]'); // Delete user. $message = t('Deleted user: %name %email.', array('%name' => $name, '%email' => '<' . $user->getEmail() . '>')); $message_text = Unicode::truncate(Html::decodeEntities(strip_tags($message)), 56, TRUE, TRUE); // Verify that the full message displays on the details page. $link = FALSE; if ($links = $this->xpath('//a[text()="' . $message_text . '"]')) { // Found link with the message text. $links = array_shift($links); foreach ($links->attributes() as $attr => $value) { if ($attr == 'href') { // Extract link to details page. $link = Unicode::substr($value, strpos($value, 'admin/reports/dblog/event/')); $this->drupalGet($link); // Check for full message text on the details page. $this->assertRaw($message, 'DBLog event details was found: [delete user]'); break; } } } $this->assertTrue($link, 'DBLog event was recorded: [delete user]'); // Visit random URL (to generate page not found event). $not_found_url = $this->randomMachineName(60); $this->drupalGet($not_found_url); $this->assertResponse(404); // View the database log page-not-found report page. $this->drupalGet('admin/reports/page-not-found'); $this->assertResponse(200); // Check that full-length URL displayed. $this->assertText($not_found_url, 'DBLog event was recorded: [page not found]'); }
/** * Initialize the plugin. */ protected function init() { if (!$this->initialized) { $this->initialized = TRUE; // Default generated table names, limited to 63 characters. $machine_name = str_replace(':', '__', $this->migration->id()); $prefix_length = strlen($this->getDatabase()->tablePrefix()); $this->mapTableName = 'migrate_map_' . Unicode::strtolower($machine_name); $this->mapTableName = Unicode::substr($this->mapTableName, 0, 63 - $prefix_length); $this->messageTableName = 'migrate_message_' . Unicode::strtolower($machine_name); $this->messageTableName = Unicode::substr($this->messageTableName, 0, 63 - $prefix_length); $this->ensureTables(); } }
/** * Trims the field down to the specified length. * * @param array $alter * The alter array of options to use. * - max_length: Maximum length of the string, the rest gets truncated. * - word_boundary: Trim only on a word boundary. * - ellipsis: Show an ellipsis (…) at the end of the trimmed string. * - html: Make sure that the html is correct. * * @param string $value * The string which should be trimmed. * * @return string * The trimmed string. */ public static function trimText($alter, $value) { if (Unicode::strlen($value) > $alter['max_length']) { $value = Unicode::substr($value, 0, $alter['max_length']); if (!empty($alter['word_boundary'])) { $regex = "(.*)\\b.+"; if (function_exists('mb_ereg')) { mb_regex_encoding('UTF-8'); $found = mb_ereg($regex, $value, $matches); } else { $found = preg_match("/{$regex}/us", $value, $matches); } if ($found) { $value = $matches[1]; } } // Remove scraps of HTML entities from the end of a strings $value = rtrim(preg_replace('/(?:<(?!.+>)|&(?!.+;)).*$/us', '', $value)); if (!empty($alter['ellipsis'])) { $value .= t('…'); } } if (!empty($alter['html'])) { $value = Html::normalize($value); } return $value; }