/** * Overrides WebTestBase::setUp(). */ protected function setUp() { $this->isInstalled = FALSE; // Define information about the user 1 account. $this->root_user = new UserSession(array('uid' => 1, 'name' => 'admin', 'mail' => '*****@*****.**', 'pass_raw' => $this->randomMachineName())); // If any $settings are defined for this test, copy and prepare an actual // settings.php, so as to resemble a regular installation. if (!empty($this->settings)) { // Not using File API; a potential error must trigger a PHP warning. copy(DRUPAL_ROOT . '/sites/default/default.settings.php', DRUPAL_ROOT . '/' . $this->siteDirectory . '/settings.php'); $this->writeSettings($this->settings); } // Note that WebTestBase::installParameters() returns form input values // suitable for a programmed drupal_form_submit(). // @see WebTestBase::translatePostValues() $this->parameters = $this->installParameters(); // Set up a minimal container (required by WebTestBase). // @see install_begin_request() $request = Request::create($GLOBALS['base_url'] . '/core/install.php'); $this->container = new ContainerBuilder(); $request_stack = new RequestStack(); $request_stack->push($request); $this->container->set('request_stack', $request_stack); $this->container->setParameter('language.default_values', Language::$defaultValues); $this->container->register('language.default', 'Drupal\\Core\\Language\\LanguageDefault')->addArgument('%language.default_values%'); $this->container->register('language_manager', 'Drupal\\Core\\Language\\LanguageManager')->addArgument(new Reference('language.default')); $this->container->register('string_translation', 'Drupal\\Core\\StringTranslation\\TranslationManager')->addArgument(new Reference('language_manager')); \Drupal::setContainer($this->container); $this->drupalGet($GLOBALS['base_url'] . '/core/install.php'); // Select language. $this->setUpLanguage(); // Select profile. $this->setUpProfile(); // Configure settings. $this->setUpSettings(); // @todo Allow test classes based on this class to act on further installer // screens. // Configure site. $this->setUpSite(); // Import new settings.php written by the installer. $request = Request::createFromGlobals(); $class_loader = (require DRUPAL_ROOT . '/core/vendor/autoload.php'); Settings::initialize(DrupalKernel::findSitePath($request), $class_loader); foreach ($GLOBALS['config_directories'] as $type => $path) { $this->configDirectories[$type] = $path; } // After writing settings.php, the installer removes write permissions // from the site directory. To allow drupal_generate_test_ua() to write // a file containing the private key for drupal_valid_test_ua(), the site // directory has to be writable. // WebTestBase::tearDown() will delete the entire test site directory. // Not using File API; a potential error must trigger a PHP warning. chmod(DRUPAL_ROOT . '/' . $this->siteDirectory, 0777); $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', FALSE); $this->kernel->prepareLegacyRequest($request); $this->container = $this->kernel->getContainer(); $config = $this->container->get('config.factory'); // Manually configure the test mail collector implementation to prevent // tests from sending out e-mails and collect them in state instead. $config->get('system.mail')->set('interface.default', 'test_mail_collector')->save(); // When running from run-tests.sh we don't get an empty current path which // would indicate we're on the home page. $path = current_path(); if (empty($path)) { _current_path('run-tests'); } $this->isInstalled = TRUE; }
public function renderPreview($display_id, $args = array()) { // Save the current path so it can be restored before returning from this function. $old_q = current_path(); // Determine where the query and performance statistics should be output. $config = \Drupal::config('views.settings'); $show_query = $config->get('ui.show.sql_query.enabled'); $show_info = $config->get('ui.show.preview_information'); $show_location = $config->get('ui.show.sql_query.where'); $show_stats = $config->get('ui.show.performance_statistics'); if ($show_stats) { $show_stats = $config->get('ui.show.sql_query.where'); } $combined = $show_query && $show_stats; $rows = array('query' => array(), 'statistics' => array()); $output = ''; $errors = $this->executable->validate(); $this->executable->destroy(); if (empty($errors)) { $this->ajax = TRUE; $this->executable->live_preview = TRUE; // AJAX happens via HTTP POST but everything expects exposed data to // be in GET. Copy stuff but remove ajax-framework specific keys. // If we're clicking on links in a preview, though, we could actually // have some input in the query parameters, so we merge request() and // query() to ensure we get it all. $exposed_input = array_merge(\Drupal::request()->request->all(), \Drupal::request()->query->all()); foreach (array('view_name', 'view_display_id', 'view_args', 'view_path', 'view_dom_id', 'pager_element', 'view_base_path', 'ajax_html_ids', 'ajax_page_state', 'form_id', 'form_build_id', 'form_token') as $key) { if (isset($exposed_input[$key])) { unset($exposed_input[$key]); } } $this->executable->setExposedInput($exposed_input); if (!$this->executable->setDisplay($display_id)) { return t('Invalid display id @display', array('@display' => $display_id)); } $this->executable->setArguments($args); // Store the current view URL for later use: if ($this->executable->display_handler->getOption('path')) { $path = $this->executable->getUrl(); } // Make view links come back to preview. $this->override_path = 'admin/structure/views/view/' . $this->id() . '/preview/' . $display_id; // Also override the current path so we get the pager. $original_path = current_path(); $q = _current_path($this->override_path); if ($args) { $q .= '/' . implode('/', $args); _current_path($q); } // Suppress contextual links of entities within the result set during a // Preview. // @todo We'll want to add contextual links specific to editing the View, so // the suppression may need to be moved deeper into the Preview pipeline. views_ui_contextual_links_suppress_push(); $show_additional_queries = $config->get('ui.show.additional_queries'); Timer::start('entity.view.preview_form'); if ($show_additional_queries) { $this->startQueryCapture(); } // Execute/get the view preview. $preview = $this->executable->preview($display_id, $args); $preview = drupal_render($preview); if ($show_additional_queries) { $this->endQueryCapture(); } $this->render_time = Timer::stop('entity.view.preview_form'); views_ui_contextual_links_suppress_pop(); // Reset variables. unset($this->override_path); _current_path($original_path); // Prepare the query information and statistics to show either above or // below the view preview. if ($show_info || $show_query || $show_stats) { // Get information from the preview for display. if (!empty($this->executable->build_info['query'])) { if ($show_query) { $query_string = $this->executable->build_info['query']; // Only the sql default class has a method getArguments. $quoted = array(); if ($this->executable->query instanceof Sql) { $quoted = $query_string->getArguments(); $connection = Database::getConnection(); foreach ($quoted as $key => $val) { if (is_array($val)) { $quoted[$key] = implode(', ', array_map(array($connection, 'quote'), $val)); } else { $quoted[$key] = $connection->quote($val); } } } $rows['query'][] = array(array('data' => array('#type' => 'inline_template', '#template' => "<strong>{% trans 'Query' %}</strong>")), array('data' => array('#type' => 'inline_template', '#template' => '<pre>{{ query }}</pre>', '#context' => array('query' => strtr($query_string, $quoted))))); if (!empty($this->additionalQueries)) { $queries = '<strong>' . t('These queries were run during view rendering:') . '</strong>'; foreach ($this->additionalQueries as $query) { if ($queries) { $queries .= "\n"; } $query_string = strtr($query['query'], $query['args']); $queries .= t('[@time ms] @query', array('@time' => round($query['time'] * 100000, 1) / 100000.0, '@query' => $query_string)); } $rows['query'][] = array(array('data' => array('#type' => 'inline_template', '#template' => "<strong>{% trans 'Other queries' %}</strong>")), SafeMarkup::set('<pre>' . $queries . '</pre>')); } } if ($show_info) { $rows['query'][] = array(array('data' => array('#type' => 'inline_template', '#template' => "<strong>{% trans 'Title' %}</strong>")), Xss::filterAdmin($this->executable->getTitle())); if (isset($path)) { $path = _l($path, $path); } else { $path = t('This display has no path.'); } $rows['query'][] = array(SafeMarkup::set('<strong>' . t('Path') . '</strong>'), $path); } if ($show_stats) { $rows['statistics'][] = array('<strong>' . t('Query build time') . '</strong>', t('@time ms', array('@time' => intval($this->executable->build_time * 100000) / 100))); $rows['statistics'][] = array('<strong>' . t('Query execute time') . '</strong>', t('@time ms', array('@time' => intval($this->executable->execute_time * 100000) / 100))); $rows['statistics'][] = array('<strong>' . t('View render time') . '</strong>', t('@time ms', array('@time' => intval($this->executable->render_time * 100000) / 100))); } \Drupal::moduleHandler()->alter('views_preview_info', $rows, $this->executable); } else { // No query was run. Display that information in place of either the // query or the performance statistics, whichever comes first. if ($combined || $show_location === 'above') { $rows['query'] = array(array(SafeMarkup::set('<strong>' . t('Query') . '</strong>'), t('No query was run'))); } else { $rows['statistics'] = array(array(SafeMarkup::set('<strong>' . t('Query') . '</strong>'), t('No query was run'))); } } } } else { foreach ($errors as $display_errors) { foreach ($display_errors as $error) { drupal_set_message($error, 'error'); } } $preview = t('Unable to preview due to validation errors.'); } // Assemble the preview, the query info, and the query statistics in the // requested order. $table = array('#type' => 'table', '#prefix' => '<div class="views-query-info">', '#suffix' => '</div>'); if ($show_location === 'above' || $show_location === 'below') { if ($combined) { $table['#rows'] = array_merge($rows['query'], $rows['statistics']); } else { $table['#rows'] = $rows['query']; } } elseif ($show_stats === 'above' || $show_stats === 'below') { $table['#rows'] = $rows['statistics']; } if ($show_location === 'above' || $show_stats === 'above') { $output .= drupal_render($table) . $preview; } elseif ($show_location === 'below' || $show_stats === 'below') { $output .= $preview . drupal_render($table); } _current_path($old_q); return $output; }
/** * Sets up a Drupal site for running functional and integration tests. * * Installs Drupal with the installation profile specified in * \Drupal\simpletest\WebTestBase::$profile into the prefixed database. * * Afterwards, installs any additional modules specified in the static * \Drupal\simpletest\WebTestBase::$modules property of each class in the * class hierarchy. * * After installation all caches are flushed and several configuration values * are reset to the values of the parent site executing the test, since the * default values may be incompatible with the environment in which tests are * being executed. */ protected function setUp() { // When running tests through the Simpletest UI (vs. on the command line), // Simpletest's batch conflicts with the installer's batch. Batch API does // not support the concept of nested batches (in which the nested is not // progressive), so we need to temporarily pretend there was no batch. // Backup the currently running Simpletest batch. $this->originalBatch = batch_get(); // Define information about the user 1 account. $this->root_user = new UserSession(array('uid' => 1, 'name' => 'admin', 'mail' => '*****@*****.**', 'pass_raw' => $this->randomMachineName())); // Some tests (SessionTest and SessionHttpsTest) need to examine whether the // proper session cookies were set on a response. Because the child site // uses the same session name as the test runner, it is necessary to make // that available to test-methods. $this->session_name = $this->originalSessionName; // Reset the static batch to remove Simpletest's batch operations. $batch =& batch_get(); $batch = array(); // Get parameters for install_drupal() before removing global variables. $parameters = $this->installParameters(); // Prepare installer settings that are not install_drupal() parameters. // Copy and prepare an actual settings.php, so as to resemble a regular // installation. // Not using File API; a potential error must trigger a PHP warning. $directory = DRUPAL_ROOT . '/' . $this->siteDirectory; copy(DRUPAL_ROOT . '/sites/default/default.settings.php', $directory . '/settings.php'); copy(DRUPAL_ROOT . '/sites/default/default.services.yml', $directory . '/services.yml'); // All file system paths are created by System module during installation. // @see system_requirements() // @see TestBase::prepareEnvironment() $settings['settings']['file_public_path'] = (object) array('value' => $this->public_files_directory, 'required' => TRUE); // 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\SystemListing::scan() $settings['settings']['test_parent_site'] = (object) array('value' => $this->originalSite, 'required' => TRUE); // Add the parent profile's search path to the child site's search paths. // @see \Drupal\Core\Extension\ExtensionDiscovery::getProfileDirectories() $settings['conf']['simpletest.settings']['parent_profile'] = (object) array('value' => $this->originalProfile, 'required' => TRUE); $this->writeSettings($settings); // Allow for test-specific overrides. $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'); // Add the name of the testing class to settings.php and include the // testing specific overrides file_put_contents($directory . '/settings.php', "\n\$test_class = '" . get_class($this) . "';\n" . 'include DRUPAL_ROOT . \'/\' . $site_path . \'/settings.testing.php\';' . "\n", FILE_APPEND); } $settings_services_file = DRUPAL_ROOT . '/' . $this->originalSite . '/testing.services.yml'; if (file_exists($settings_services_file)) { // Copy the testing-specific service overrides in place. copy($settings_services_file, $directory . '/services.yml'); } // Since Drupal is bootstrapped already, install_begin_request() will not // bootstrap into DRUPAL_BOOTSTRAP_CONFIGURATION (again). Hence, we have to // reload the newly written custom settings.php manually. $class_loader = (require DRUPAL_ROOT . '/core/vendor/autoload.php'); Settings::initialize($directory, $class_loader); // Execute the non-interactive installer. require_once DRUPAL_ROOT . '/core/includes/install.core.inc'; install_drupal($parameters); // Import new settings.php written by the installer. Settings::initialize($directory, $class_loader); foreach ($GLOBALS['config_directories'] as $type => $path) { $this->configDirectories[$type] = $path; } // After writing settings.php, the installer removes write permissions // from the site directory. To allow drupal_generate_test_ua() to write // a file containing the private key for drupal_valid_test_ua(), the site // directory has to be writable. // TestBase::restoreEnvironment() will delete the entire site directory. // Not using File API; a potential error must trigger a PHP warning. chmod($directory, 0777); $request = \Drupal::request(); $this->kernel = DrupalKernel::createFromRequest($request, $class_loader, 'prod', TRUE); $this->kernel->prepareLegacyRequest($request); // Force the container to be built from scratch instead of loaded from the // disk. This forces us to not accidently load the parent site. $container = $this->kernel->rebuildContainer(); $config = $container->get('config.factory'); // Manually create and configure private and temporary files directories. // While these could be preset/enforced in settings.php like the public // files directory above, some tests expect them to be configurable in the // UI. If declared in settings.php, they would no longer be configurable. file_prepare_directory($this->private_files_directory, FILE_CREATE_DIRECTORY); file_prepare_directory($this->temp_files_directory, FILE_CREATE_DIRECTORY); $config->get('system.file')->set('path.private', $this->private_files_directory)->set('path.temporary', $this->temp_files_directory)->save(); // Manually configure the test mail collector implementation to prevent // tests from sending out emails and collect them in state instead. // While this should be enforced via settings.php prior to installation, // some tests expect to be able to test mail system implementations. $config->get('system.mail')->set('interface.default', 'test_mail_collector')->save(); // By default, verbosely display all errors and disable all production // environment optimizations for all tests to avoid needless overhead and // ensure a sane default experience for test authors. // @see https://drupal.org/node/2259167 $config->get('system.logging')->set('error_level', 'verbose')->save(); $config->get('system.performance')->set('css.preprocess', FALSE)->set('js.preprocess', FALSE)->save(); // Restore the original Simpletest batch. $batch =& batch_get(); $batch = $this->originalBatch; // Collect modules to install. $class = get_class($this); $modules = array(); while ($class) { if (property_exists($class, 'modules')) { $modules = array_merge($modules, $class::$modules); } $class = get_parent_class($class); } if ($modules) { $modules = array_unique($modules); $success = $container->get('module_handler')->install($modules, TRUE); $this->assertTrue($success, String::format('Enabled modules: %modules', array('%modules' => implode(', ', $modules)))); $this->rebuildContainer(); } // Reset/rebuild all data structures after enabling the modules, primarily // to synchronize all data structures and caches between the test runner and // the child site. // @see \Drupal\Core\DrupalKernel::bootCode() // @todo Test-specific setUp() methods may set up further fixtures; find a // way to execute this after setUp() is done, or to eliminate it entirely. $this->resetAll(); $this->kernel->prepareLegacyRequest($request); // Explicitly call register() again on the container registered in \Drupal. // @todo This should already be called through // DrupalKernel::prepareLegacyRequest() -> DrupalKernel::boot() but that // appears to be calling a different container. $this->container->get('stream_wrapper_manager')->register(); // Temporary fix so that when running from run-tests.sh we don't get an // empty current path which would indicate we're on the home page. $path = current_path(); if (empty($path)) { _current_path('run-tests'); } }
/** * Ensure page-front template suggestion is added when on front page. */ function testFrontPageThemeSuggestion() { $original_path = _current_path(); // Set the current path to node because theme_get_suggestions() will query // it to see if we are on the front page. \Drupal::config('system.site')->set('page.front', 'node')->save(); _current_path('node'); $suggestions = theme_get_suggestions(array('node'), 'page'); // Set it back to not annoy the batch runner. _current_path($original_path); $this->assertTrue(in_array('page__front', $suggestions), 'Front page template was suggested.'); }
/** * Bootstraps the legacy global request variables. * * @param \Symfony\Component\HttpFoundation\Request $request * The current request. * * @todo D8: Eliminate this entirely in favor of Request object. */ protected function initializeRequestGlobals(Request $request) { // Provided by settings.php. global $base_url; // Set and derived from $base_url by this function. global $base_path, $base_root, $script_path; global $base_secure_url, $base_insecure_url; // @todo Refactor with the Symfony Request object. _current_path(request_path()); if (isset($base_url)) { // Parse fixed base URL from settings.php. $parts = parse_url($base_url); if (!isset($parts['path'])) { $parts['path'] = ''; } $base_path = $parts['path'] . '/'; // Build $base_root (everything until first slash after "scheme://"). $base_root = substr($base_url, 0, strlen($base_url) - strlen($parts['path'])); } else { // Create base URL. $http_protocol = $request->isSecure() ? 'https' : 'http'; $base_root = $http_protocol . '://' . $request->server->get('HTTP_HOST'); $base_url = $base_root; // For a request URI of '/index.php/foo', $_SERVER['SCRIPT_NAME'] is // '/index.php', whereas $_SERVER['PHP_SELF'] is '/index.php/foo'. if ($dir = rtrim(dirname($request->server->get('SCRIPT_NAME')), '\\/')) { // Remove "core" directory if present, allowing install.php, // authorize.php, and others to auto-detect a base path. $core_position = strrpos($dir, '/core'); if ($core_position !== FALSE && strlen($dir) - 5 == $core_position) { $base_path = substr($dir, 0, $core_position); } else { $base_path = $dir; } $base_url .= $base_path; $base_path .= '/'; } else { $base_path = '/'; } } $base_secure_url = str_replace('http://', 'https://', $base_url); $base_insecure_url = str_replace('https://', 'http://', $base_url); // Determine the path of the script relative to the base path, and add a // trailing slash. This is needed for creating URLs to Drupal pages. if (!isset($script_path)) { $script_path = ''; // We don't expect scripts outside of the base path, but sanity check // anyway. if (strpos($request->server->get('SCRIPT_NAME'), $base_path) === 0) { $script_path = substr($request->server->get('SCRIPT_NAME'), strlen($base_path)) . '/'; // If the request URI does not contain the script name, then clean URLs // are in effect and the script path can be similarly dropped from URL // generation. For servers that don't provide $_SERVER['REQUEST_URI'], // we do not know the actual URI requested by the client, and // request_uri() returns a URI with the script name, resulting in // non-clean URLs unless // there's other code that intervenes. if (strpos(request_uri(TRUE) . '/', $base_path . $script_path) !== 0) { $script_path = ''; } // @todo Temporary BC for install.php, authorize.php, and other scripts. // - http://drupal.org/node/1547184 // - http://drupal.org/node/1546082 if ($script_path !== 'index.php/') { $script_path = ''; } } } }