/** * Autocomplete the label of an entity. * * @param \Symfony\Component\HttpFoundation\Request $request * The request object that contains the typed tags. * @param string $target_type * The ID of the target entity type. * @param string $selection_handler * The plugin ID of the entity reference selection handler. * @param string $selection_settings_key * The hashed key of the key/value entry that holds the selection handler * settings. * * @return \Symfony\Component\HttpFoundation\JsonResponse * The matched entity labels as a JSON response. * * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException * Thrown if the selection settings key is not found in the key/value store * or if it does not match the stored data. */ public function handleAutocomplete(Request $request, $target_type, $selection_handler, $selection_settings_key) { $matches = array(); // Get the typed string from the URL, if it exists. if ($input = $request->query->get('q')) { $typed_string = Tags::explode($input); $typed_string = Unicode::strtolower(array_pop($typed_string)); // Selection settings are passed in as a hashed key of a serialized array // stored in the key/value store. $selection_settings = $this->keyValue->get($selection_settings_key, FALSE); if ($selection_settings !== FALSE) { $selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt()); if ($selection_settings_hash !== $selection_settings_key) { // Disallow access when the selection settings hash does not match the // passed-in key. throw new AccessDeniedHttpException('Invalid selection settings key.'); } } else { // Disallow access when the selection settings key is not found in the // key/value store. throw new AccessDeniedHttpException(); } $matches = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string); } return new JsonResponse($matches); }
protected function getSystemData() { $systemManager = $this->getSystemManager(); $requirements = $systemManager->listRequirements(); $systemData = []; foreach ($requirements as $key => $requirement) { if ($requirement['title'] instanceof \Drupal\Core\StringTranslation\TranslatableMarkup) { $title = $requirement['title']->render(); } else { $title = $requirement['title']; } $systemData['system'][$title] = $requirement['value']; } $kernelHelper = $this->getKernelHelper(); $drupal = $this->getDrupalHelper(); Settings::initialize($drupal->getRoot(), 'sites/default', $kernelHelper->getClassLoader()); try { $hashSalt = Settings::getHashSalt(); } catch (\Exception $e) { $hashSalt = ''; } $systemData['system'][$this->trans('commands.site.status.messages.hash_salt')] = $hashSalt; $systemData['system'][$this->trans('commands.site.status.messages.console')] = $this->getApplication()->getVersion(); return $systemData; }
protected function getSystemData() { if (!$this->systemManager) { return []; } $requirements = $this->systemManager->listRequirements(); $systemData = []; foreach ($requirements as $key => $requirement) { if ($requirement['title'] instanceof \Drupal\Core\StringTranslation\TranslatableMarkup) { $title = $requirement['title']->render(); } else { $title = $requirement['title']; } $systemData['system'][$title] = $requirement['value']; } if ($this->settings) { try { $hashSalt = $this->settings->getHashSalt(); } catch (\Exception $e) { $hashSalt = ''; } $systemData['system'][$this->trans('commands.site.status.messages.hash_salt')] = $hashSalt; $systemData['system'][$this->trans('commands.site.status.messages.console')] = $this->getApplication()->getVersion(); } return $systemData; }
protected function setUp() { // DrupalKernel relies on global $config_directories and requires those // directories to exist. Therefore, create the directories, but do not // invoke KernelTestBase::setUp(), since that would set up further // environment aspects, which would distort this test, because it tests // the DrupalKernel (re-)building itself. $this->prepareConfigDirectories(); $this->settingsSet('php_storage', array('service_container' => array('bin' => 'service_container', 'class' => 'Drupal\\Component\\PhpStorage\\MTimeProtectedFileStorage', 'directory' => DRUPAL_ROOT . '/' . $this->publicFilesDirectory . '/php', 'secret' => Settings::getHashSalt()))); }
/** * Generates a hash that uniquely identifies the user's permissions. * * @param \Drupal\user\Entity\Role[] $roles * The user's roles. * * @return string * The permissions hash. */ protected function doGenerate(array $roles) { // @todo Once Drupal gets rid of user_role_permissions(), we should be able // to inject the user role controller and call a method on that instead. $permissions_by_role = user_role_permissions($roles); foreach ($permissions_by_role as $role => $permissions) { sort($permissions); $permissions_by_role[$role] = $permissions; } return hash('sha256', $this->privateKey->get() . Settings::getHashSalt() . serialize($permissions_by_role)); }
protected function getSystemData() { $systemManager = $this->getSystemManager(); $requirements = $systemManager->listRequirements(); $systemData = []; foreach ($requirements as $key => $requirement) { $systemData['system'][$requirement['title']] = $requirement['value']; } $kernelHelper = $this->getHelper('kernel'); $drupalAutoLoad = $this->getHelperSet()->get('drupal-autoload'); Settings::initialize($drupalAutoLoad->getDrupalRoot(), 'sites/default', $kernelHelper->getClassLoader()); $systemData['system'][$this->trans('commands.site.status.messages.hash_salt')] = Settings::getHashSalt(); $systemData['system'][$this->trans('commands.site.status.messages.console')] = $this->getApplication()->getVersion(); return $systemData; }
/** * #pre_render callback to generate a placeholder. * * Ensures the same token is used for all instances, hence resulting in the * same placeholder for all places rendering the status messages for this * request (e.g. in multiple blocks). This ensures we can put the rendered * messages in all placeholders in one go. * Also ensures the same context key is used for the #post_render_cache * property, this ensures that if status messages are rendered multiple times, * their individual (but identical!) #post_render_cache properties are merged, * ensuring the callback is only invoked once. * * @see ::renderMessages() * @param array $element * A renderable array. * * @return array * The updated renderable array containing the placeholder. */ public static function generatePlaceholder(array $element) { $plugin_id = 'status_messages'; $callback = get_class() . '::renderMessages'; try { $hash_salt = Settings::getHashSalt(); } catch (\RuntimeException $e) { // Status messages are also shown during the installer, at which time no // hash salt is defined yet. $hash_salt = Crypt::randomBytes(8); } $key = $plugin_id . $element['#display']; $context = ['display' => $element['#display'], 'token' => Crypt::hmacBase64($key, $hash_salt)]; $placeholder = static::renderer()->generateCachePlaceholder($callback, $context); $element['#post_render_cache'] = [$callback => [$key => $context]]; $element['#markup'] = $placeholder; return $element; }
/** * Instantiates a storage for generated PHP code. * * By default, this returns an instance of the * \Drupal\Component\PhpStorage\MTimeProtectedFileStorage class. * * Classes implementing * \Drupal\Component\PhpStorage\PhpStorageInterface can be registered for a * specific bin or as a default implementation. * * @param string $name * The name for which the storage should be returned. Defaults to 'default' * The name is also used as the storage bin if one is not specified in the * configuration. * * @return \Drupal\Component\PhpStorage\PhpStorageInterface * An instantiated storage for the specified name. */ static function get($name) { $overrides = Settings::get('php_storage'); if (isset($overrides[$name])) { $configuration = $overrides[$name]; } elseif (isset($overrides['default'])) { $configuration = $overrides['default']; } else { $configuration = array('class' => 'Drupal\\Component\\PhpStorage\\MTimeProtectedFileStorage', 'secret' => Settings::getHashSalt()); } $class = isset($configuration['class']) ? $configuration['class'] : 'Drupal\\Component\\PhpStorage\\MTimeProtectedFileStorage'; if (!isset($configuration['bin'])) { $configuration['bin'] = $name; } if (!isset($configuration['directory'])) { $configuration['directory'] = DRUPAL_ROOT . '/' . PublicStream::basePath() . '/php'; } return new $class($configuration); }
/** * Instantiates a storage for generated PHP code. * * By default, this returns an instance of the * \Drupal\Component\PhpStorage\MTimeProtectedFileStorage class. * * Classes implementing * \Drupal\Component\PhpStorage\PhpStorageInterface can be registered for a * specific bin or as a default implementation. * * @param string $name * The name for which the storage should be returned. Defaults to 'default' * The name is also used as the storage bin if one is not specified in the * configuration. * * @return \Drupal\Component\PhpStorage\PhpStorageInterface * An instantiated storage for the specified name. */ static function get($name) { $configuration = array(); $overrides = Settings::get('php_storage'); if (isset($overrides[$name])) { $configuration = $overrides[$name]; } elseif (isset($overrides['default'])) { $configuration = $overrides['default']; } // Make sure all the necessary configuration values are set. $class = isset($configuration['class']) ? $configuration['class'] : 'Drupal\\Component\\PhpStorage\\MTimeProtectedFileStorage'; if (!isset($configuration['secret'])) { $configuration['secret'] = Settings::getHashSalt(); } if (!isset($configuration['bin'])) { $configuration['bin'] = $name; } if (!isset($configuration['directory'])) { $configuration['directory'] = PublicStream::basePath() . '/php'; } return new $class($configuration); }
/** * {@inheritdoc} */ public function getPathToken($uri) { // Return the first 8 characters. return substr(Crypt::hmacBase64($this->id() . ':' . $uri, \Drupal::service('private_key')->get() . Settings::getHashSalt()), 0, 8); }
/** * Tests Settings::getHashSalt() with no hash salt value. * * @covers ::getHashSalt * * @dataProvider providerTestGetHashSaltEmpty * * @expectedException \RuntimeException */ public function testGetHashSaltEmpty(array $config) { // Re-create settings with no 'hash_salt' key. $settings = new Settings($config); $settings->getHashSalt(); }
/** * Generates a token based on $value, the token seed, and the private key. * * @param string $seed * The per-session token seed. * @param string $value * (optional) An additional value to base the token on. * * @return string * A 43-character URL-safe token for validation, based on the token seed, * the hash salt provided by Settings::getHashSalt(), and the * 'drupal_private_key' configuration variable. * * @see \Drupal\Core\Site\Settings::getHashSalt() */ protected function computeToken($seed, $value = '') { return Crypt::hmacBase64($value, $seed . $this->privateKey->get() . Settings::getHashSalt()); }
/** * Gets a salt useful for hardening against SQL injection. * * @return string * A salt based on information in settings.php, not in the database. * * @throws \RuntimeException */ protected function getHashSalt() { return Settings::getHashSalt(); }
/** * Stop-gap fix. * * @see http://drupal.org/node/1555862 */ protected function drupalGetToken($value = '') { // Use the same code as \Drupal\Core\Access\CsrfTokenGenerator::get(). $private_key = $this->container->get('private_key')->get(); /** @var \Drupal\Core\Session\MetadataBag $session_metadata */ $session_metadata = $this->container->get('session_manager.metadata_bag'); // @TODO Try to get seed from testing site, broken now. $seed = $session_metadata->getCsrfTokenSeed(); return Crypt::hmacBase64($value, $seed . $private_key . Settings::getHashSalt()); }
/** * Generates a key from job item data that can be used in the URL. * * @param \Drupal\tmgmt\JobItemInterface $tmgmt_job_item * Job item. * * @return string * Returns hashed key that is safe to use in the URL. */ public function getKey(JobItemInterface $tmgmt_job_item) { return Crypt::hmacBase64($tmgmt_job_item->id(), Settings::getHashSalt()); }
/** * Adds entity autocomplete functionality to a form element. * * @param array $element * The form element to process. Properties used: * - #target_type: The ID of the target entity type. * - #selection_handler: The plugin ID of the entity reference selection * handler. * - #selection_settings: An array of settings that will be passed to the * selection handler. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * @param array $complete_form * The complete form structure. * * @return array * The form element. * * @throws \InvalidArgumentException * Exception thrown when the #target_type or #autocreate['bundle'] are * missing. */ public static function processEntityAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) { // Nothing to do if there is no target entity type. if (empty($element['#target_type'])) { throw new \InvalidArgumentException('Missing required #target_type parameter.'); } // Provide default values and sanity checks for the #autocreate parameter. if ($element['#autocreate']) { if (!isset($element['#autocreate']['bundle'])) { throw new \InvalidArgumentException("Missing required #autocreate['bundle'] parameter."); } // Default the autocreate user ID to the current user. $element['#autocreate']['uid'] = isset($element['#autocreate']['uid']) ? $element['#autocreate']['uid'] : \Drupal::currentUser()->id(); } // Store the selection settings in the key/value store and pass a hashed key // in the route parameters. $selection_settings = isset($element['#selection_settings']) ? $element['#selection_settings'] : []; $data = serialize($selection_settings) . $element['#target_type'] . $element['#selection_handler']; $selection_settings_key = Crypt::hmacBase64($data, Settings::getHashSalt()); $key_value_storage = \Drupal::keyValue('entity_autocomplete'); if (!$key_value_storage->has($selection_settings_key)) { $key_value_storage->set($selection_settings_key, $selection_settings); } $element['#autocomplete_route_name'] = 'system.entity_autocomplete'; $element['#autocomplete_route_parameters'] = array('target_type' => $element['#target_type'], 'selection_handler' => $element['#selection_handler'], 'selection_settings_key' => $selection_settings_key); return $element; }
/** * Render API callback: Expands the managed_file element type. * * Expands the file type to include Upload and Remove buttons, as well as * support for a default value. */ public static function processManagedFile(&$element, FormStateInterface $form_state, &$complete_form) { // This is used sometimes so let's implode it just once. $parents_prefix = implode('_', $element['#parents']); $fids = isset($element['#value']['fids']) ? $element['#value']['fids'] : []; // Set some default element properties. $element['#progress_indicator'] = empty($element['#progress_indicator']) ? 'none' : $element['#progress_indicator']; $element['#files'] = !empty($fids) ? File::loadMultiple($fids) : FALSE; $element['#tree'] = TRUE; // Generate a unique wrapper HTML ID. $ajax_wrapper_id = Html::getUniqueId('ajax-wrapper'); $ajax_settings = ['callback' => [get_called_class(), 'uploadAjaxCallback'], 'options' => ['query' => ['element_parents' => implode('/', $element['#array_parents'])]], 'wrapper' => $ajax_wrapper_id, 'effect' => 'fade', 'progress' => ['type' => $element['#progress_indicator'], 'message' => $element['#progress_message']]]; // Set up the buttons first since we need to check if they were clicked. $element['upload_button'] = ['#name' => $parents_prefix . '_upload_button', '#type' => 'submit', '#value' => t('Upload'), '#attributes' => ['class' => ['js-hide']], '#validate' => [], '#submit' => ['file_managed_file_submit'], '#limit_validation_errors' => [$element['#parents']], '#ajax' => $ajax_settings, '#weight' => -5]; // Force the progress indicator for the remove button to be either 'none' or // 'throbber', even if the upload button is using something else. $ajax_settings['progress']['type'] = $element['#progress_indicator'] == 'none' ? 'none' : 'throbber'; $ajax_settings['progress']['message'] = NULL; $ajax_settings['effect'] = 'none'; $element['remove_button'] = ['#name' => $parents_prefix . '_remove_button', '#type' => 'submit', '#value' => $element['#multiple'] ? t('Remove selected') : t('Remove'), '#validate' => [], '#submit' => ['file_managed_file_submit'], '#limit_validation_errors' => [$element['#parents']], '#ajax' => $ajax_settings, '#weight' => 1]; $element['fids'] = ['#type' => 'hidden', '#value' => $fids]; // Add progress bar support to the upload if possible. if ($element['#progress_indicator'] == 'bar' && ($implementation = file_progress_implementation())) { $upload_progress_key = mt_rand(); if ($implementation == 'uploadprogress') { $element['UPLOAD_IDENTIFIER'] = ['#type' => 'hidden', '#value' => $upload_progress_key, '#attributes' => ['class' => ['file-progress']], '#weight' => -20]; } elseif ($implementation == 'apc') { $element['APC_UPLOAD_PROGRESS'] = ['#type' => 'hidden', '#value' => $upload_progress_key, '#attributes' => ['class' => ['file-progress']], '#weight' => -20]; } // Add the upload progress callback. $element['upload_button']['#ajax']['progress']['url'] = Url::fromRoute('file.ajax_progress', ['key' => $upload_progress_key]); } // The file upload field itself. $element['upload'] = ['#name' => 'files[' . $parents_prefix . ']', '#type' => 'file', '#title' => t('Choose a file'), '#title_display' => 'invisible', '#size' => $element['#size'], '#multiple' => $element['#multiple'], '#theme_wrappers' => [], '#weight' => -10, '#error_no_message' => TRUE]; if (!empty($fids) && $element['#files']) { foreach ($element['#files'] as $delta => $file) { $file_link = ['#theme' => 'file_link', '#file' => $file]; if ($element['#multiple']) { $element['file_' . $delta]['selected'] = ['#type' => 'checkbox', '#title' => \Drupal::service('renderer')->renderPlain($file_link)]; } else { $element['file_' . $delta]['filename'] = $file_link + ['#weight' => -10]; } // Anonymous users who have uploaded a temporary file need a // non-session-based token added so $this->valueCallback() can check // that they have permission to use this file on subsequent submissions // of the same form (for example, after an Ajax upload or form // validation error). if ($file->isTemporary() && \Drupal::currentUser()->isAnonymous()) { $element['file_' . $delta]['fid_token'] = array('#type' => 'hidden', '#value' => Crypt::hmacBase64('file-' . $delta, \Drupal::service('private_key')->get() . Settings::getHashSalt())); } } } // Add the extension list to the page as JavaScript settings. if (isset($element['#upload_validators']['file_validate_extensions'][0])) { $extension_list = implode(',', array_filter(explode(' ', $element['#upload_validators']['file_validate_extensions'][0]))); $element['upload']['#attached']['drupalSettings']['file']['elements']['#' . $element['#id']] = $extension_list; } // Let #id point to the file element, so the field label's 'for' corresponds // with it. $element['#id'] =& $element['upload']['#id']; // Prefix and suffix used for Ajax replacement. $element['#prefix'] = '<div id="' . $ajax_wrapper_id . '">'; $element['#suffix'] = '</div>'; return $element; }
/** * {@inheritdoc} */ public function digest() { return Crypt::hmacBase64(Json::encode($this->getValues()), Settings::getHashSalt()); }
/** * {@inheritdoc} */ protected function setUp() { $this->keyValueFactory = new KeyValueMemoryFactory(); // Back up settings from TestBase::prepareEnvironment(). $settings = Settings::getAll(); // Allow for test-specific overrides. $directory = DRUPAL_ROOT . '/' . $this->siteDirectory; $settings_services_file = DRUPAL_ROOT . '/' . $this->originalSite . '/testing.services.yml'; $container_yamls = []; if (file_exists($settings_services_file)) { // Copy the testing-specific service overrides in place. $testing_services_file = $directory . '/services.yml'; copy($settings_services_file, $testing_services_file); $container_yamls[] = $testing_services_file; } $settings_testing_file = DRUPAL_ROOT . '/' . $this->originalSite . '/settings.testing.php'; if (file_exists($settings_testing_file)) { // Copy the testing-specific settings.php overrides in place. copy($settings_testing_file, $directory . '/settings.testing.php'); } if (file_exists($directory . '/settings.testing.php')) { // Add the name of the testing class to settings.php and include the // testing specific overrides $hash_salt = Settings::getHashSalt(); $test_class = get_class($this); $container_yamls_export = Variable::export($container_yamls); $php = <<<EOD <?php \$settings['hash_salt'] = '{$hash_salt}'; \$settings['container_yamls'] = {$container_yamls_export}; \$test_class = '{$test_class}'; include DRUPAL_ROOT . '/' . \$site_path . '/settings.testing.php'; EOD; file_put_contents($directory . '/settings.php', $php); } // Add this test class as a service provider. // @todo Remove the indirection; implement ServiceProviderInterface instead. $GLOBALS['conf']['container_service_providers']['TestServiceProvider'] = 'Drupal\\simpletest\\TestServiceProvider'; // Bootstrap a new kernel. $class_loader = (require DRUPAL_ROOT . '/autoload.php'); $this->kernel = new DrupalKernel('testing', $class_loader, FALSE); $request = Request::create('/'); $site_path = DrupalKernel::findSitePath($request); $this->kernel->setSitePath($site_path); if (file_exists($directory . '/settings.testing.php')) { Settings::initialize(DRUPAL_ROOT, $site_path, $class_loader); } $this->kernel->boot(); // Ensure database install tasks have been run. require_once __DIR__ . '/../../../includes/install.inc'; $connection = Database::getConnection(); $errors = db_installer_object($connection->driver())->runTasks(); if (!empty($errors)) { $this->fail('Failed to run installer database tasks: ' . implode(', ', $errors)); } // Reboot the kernel because the container might contain a connection to the // database that has been closed during the database install tasks. This // prevents any services created during the first boot from having stale // database connections, for example, \Drupal\Core\Config\DatabaseStorage. $this->kernel->shutdown(); $this->kernel->boot(); // Save the original site directory path, so that extensions in the // site-specific directory can still be discovered in the test site // environment. // @see \Drupal\Core\Extension\ExtensionDiscovery::scan() $settings['test_parent_site'] = $this->originalSite; // Restore and merge settings. // DrupalKernel::boot() initializes new Settings, and the containerBuild() // method sets additional settings. new Settings($settings + Settings::getAll()); // Create and set new configuration directories. $this->prepareConfigDirectories(); // Set the request scope. $this->container = $this->kernel->getContainer(); $this->container->get('request_stack')->push($request); // Re-inject extension file listings into state, unless the key/value // service was overridden (in which case its storage does not exist yet). if ($this->container->get('keyvalue') instanceof KeyValueMemoryFactory) { $this->container->get('state')->set('system.module.files', $this->moduleFiles); $this->container->get('state')->set('system.theme.files', $this->themeFiles); } // Create a minimal core.extension configuration object so that the list of // enabled modules can be maintained allowing // \Drupal\Core\Config\ConfigInstaller::installDefaultConfig() to work. // Write directly to active storage to avoid early instantiation of // the event dispatcher which can prevent modules from registering events. \Drupal::service('config.storage')->write('core.extension', array('module' => array(), 'theme' => array())); // Collect and set a fixed module list. $class = get_class($this); $modules = array(); while ($class) { if (property_exists($class, 'modules')) { // Only add the modules, if the $modules property was not inherited. $rp = new \ReflectionProperty($class, 'modules'); if ($rp->class == $class) { $modules[$class] = $class::$modules; } } $class = get_parent_class($class); } // Modules have been collected in reverse class hierarchy order; modules // defined by base classes should be sorted first. Then, merge the results // together. $modules = array_reverse($modules); $modules = call_user_func_array('array_merge_recursive', $modules); if ($modules) { $this->enableModules($modules); } // Tests based on this class are entitled to use Drupal's File and // StreamWrapper APIs. // @todo Move StreamWrapper management into DrupalKernel. // @see https://www.drupal.org/node/2028109 file_prepare_directory($this->publicFilesDirectory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS); $this->settingsSet('file_public_path', $this->publicFilesDirectory); $this->streamWrappers = array(); $this->registerStreamWrapper('public', 'Drupal\\Core\\StreamWrapper\\PublicStream'); // The temporary stream wrapper is able to operate both with and without // configuration. $this->registerStreamWrapper('temporary', 'Drupal\\Core\\StreamWrapper\\TemporaryStream'); }
/** * Hashes the given string. * * @param string $identifier * The string to be hashed. * * @return string * The hash. */ protected function hash($identifier) { return hash('sha256', $this->privateKey->get() . Settings::getHashSalt() . $identifier); }
/** * Returns the result of an Entity reference autocomplete request. * * @param string $input * The label of the entity to query by. * * @return mixed * The JSON value encoded in its appropriate PHP type. */ protected function getAutocompleteResult($input) { $request = Request::create('entity_reference_autocomplete/' . $this->entityType . '/default'); $request->query->set('q', $input); $selection_settings = []; $selection_settings_key = Crypt::hmacBase64(serialize($selection_settings) . $this->entityType . 'default', Settings::getHashSalt()); \Drupal::keyValue('entity_autocomplete')->set($selection_settings_key, $selection_settings); $entity_reference_controller = EntityAutocompleteController::create($this->container); $result = $entity_reference_controller->handleAutocomplete($request, $this->entityType, 'default', $selection_settings_key)->getContent(); return Json::decode($result); }
/** * Create a DrupalKernel object from a request. * * @param \Symfony\Component\HttpFoundation\Request $request * The request. * @param $class_loader * The class loader. Normally Composer's ClassLoader, as included by the * front controller, but may also be decorated; e.g., * \Symfony\Component\ClassLoader\ApcClassLoader. * @param string $environment * String indicating the environment, e.g. 'prod' or 'dev'. * @param bool $allow_dumping * (optional) FALSE to stop the container from being written to or read * from disk. Defaults to TRUE. * * @return static * * @throws \Symfony\Component\HttpKernel\Exception\BadRequestHttpException * In case the host name in the request is not trusted. */ public static function createFromRequest(Request $request, $class_loader, $environment, $allow_dumping = TRUE) { // Include our bootstrap file. $core_root = dirname(dirname(dirname(__DIR__))); require_once $core_root . '/includes/bootstrap.inc'; $class_loader_class = get_class($class_loader); $kernel = new static($environment, $class_loader, $allow_dumping); // Ensure sane php environment variables.. static::bootEnvironment(); // Get our most basic settings setup. $site_path = static::findSitePath($request); $kernel->setSitePath($site_path); Settings::initialize(dirname($core_root), $site_path, $class_loader); // Initialize our list of trusted HTTP Host headers to protect against // header attacks. $host_patterns = Settings::get('trusted_host_patterns', array()); if (PHP_SAPI !== 'cli' && !empty($host_patterns)) { if (static::setupTrustedHosts($request, $host_patterns) === FALSE) { throw new BadRequestHttpException('The provided host name is not valid for this server.'); } } // Redirect the user to the installation script if Drupal has not been // installed yet (i.e., if no $databases array has been defined in the // settings.php file) and we are not already installing. if (!Database::getConnectionInfo() && !drupal_installation_attempted() && PHP_SAPI !== 'cli') { $response = new RedirectResponse($request->getBasePath() . '/core/install.php'); $response->prepare($request)->send(); } // If the class loader is still the same, possibly upgrade to the APC class // loader. if ($class_loader_class == get_class($class_loader) && Settings::get('class_loader_auto_detect', TRUE) && Settings::get('hash_salt', FALSE) && function_exists('apc_fetch')) { $prefix = 'drupal.' . hash('sha256', 'drupal.' . Settings::getHashSalt()); $apc_loader = new \Symfony\Component\ClassLoader\ApcClassLoader($prefix, $class_loader); $class_loader->unregister(); $apc_loader->register(); $class_loader = $apc_loader; } // Ensure that the class loader reference is up-to-date. $kernel->classLoader = $class_loader; return $kernel; }