/**
  * Tests the get() method with overridden settings.
  */
 public function testGetOverride()
 {
     $this->setSettings('test');
     $php = PhpStorageFactory::get('test');
     // The FileReadOnlyStorage should be used from settings.
     $this->assertTrue($php instanceof MockPhpStorage, 'A MockPhpStorage instance was returned from overridden settings.');
     // Test that the name is used for the bin when it is NULL.
     $this->setSettings('test', array('bin' => NULL));
     $php = PhpStorageFactory::get('test');
     $this->assertTrue($php instanceof MockPhpStorage, 'An MockPhpStorage instance was returned from overridden settings.');
     $this->assertSame('test', $php->getConfigurationValue('bin'), 'Name value was used for bin.');
     // Test that a default directory is set if it's empty.
     $this->setSettings('test', array('directory' => NULL));
     $php = PhpStorageFactory::get('test');
     $this->assertTrue($php instanceof MockPhpStorage, 'An MockPhpStorage instance was returned from overridden settings.');
     $this->assertSame(PublicStream::basePath() . '/php', $php->getConfigurationValue('directory'), 'Default file directory was used.');
     // Test that a default storage class is set if it's empty.
     $this->setSettings('test', array('class' => NULL));
     $php = PhpStorageFactory::get('test');
     $this->assertTrue($php instanceof MTimeProtectedFileStorage, 'An MTimeProtectedFileStorage instance was returned from overridden settings with no class.');
     // Test that a default secret is not returned if it's set in the override.
     $this->setSettings('test');
     $php = PhpStorageFactory::get('test');
     $this->assertNotEquals('mock hash salt', $php->getConfigurationValue('secret'), 'The default secret is not used if a secret is set in the overridden settings.');
     // Test that a default secret is set if it's empty.
     $this->setSettings('test', array('secret' => NULL));
     $php = PhpStorageFactory::get('test');
     $this->assertSame('mock hash salt', $php->getConfigurationValue('secret'), 'The default secret is used if one is not set in the overridden settings.');
 }
Example #2
0
 /**
  * Test the getViaUri() and getViaScheme() methods and target functions.
  */
 function testUriFunctions()
 {
     $config = $this->config('system.file');
     $instance = \Drupal::service('stream_wrapper_manager')->getViaUri($this->scheme . '://foo');
     $this->assertEqual($this->classname, get_class($instance), 'Got correct class type for dummy URI.');
     $instance = \Drupal::service('stream_wrapper_manager')->getViaUri('public://foo');
     $this->assertEqual('Drupal\\Core\\StreamWrapper\\PublicStream', get_class($instance), 'Got correct class type for public URI.');
     // Test file_uri_target().
     $this->assertEqual(file_uri_target('public://foo/bar.txt'), 'foo/bar.txt', 'Got a valid stream target from public://foo/bar.txt.');
     $this->assertEqual(file_uri_target('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', t('Got a valid stream target from a data URI.'));
     $this->assertFalse(file_uri_target('foo/bar.txt'), 'foo/bar.txt is not a valid stream.');
     $this->assertFalse(file_uri_target('public://'), 'public:// has no target.');
     $this->assertFalse(file_uri_target('data:'), 'data: has no target.');
     // Test file_build_uri() and
     // Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath().
     $this->assertEqual(file_build_uri('foo/bar.txt'), 'public://foo/bar.txt', 'Expected scheme was added.');
     $this->assertEqual(\Drupal::service('stream_wrapper_manager')->getViaScheme('public')->getDirectoryPath(), PublicStream::basePath(), 'Expected default directory path was returned.');
     $this->assertEqual(\Drupal::service('stream_wrapper_manager')->getViaScheme('temporary')->getDirectoryPath(), $config->get('path.temporary'), 'Expected temporary directory path was returned.');
     $config->set('default_scheme', 'private')->save();
     $this->assertEqual(file_build_uri('foo/bar.txt'), 'private://foo/bar.txt', 'Got a valid URI from foo/bar.txt.');
     // Test file_create_url()
     // TemporaryStream::getExternalUrl() uses Url::fromRoute(), which needs
     // route information to work.
     $this->container->get('router.builder')->rebuild();
     $this->assertTrue(strpos(file_create_url('temporary://test.txt'), 'system/temporary?file=test.txt'), 'Temporary external URL correctly built.');
     $this->assertTrue(strpos(file_create_url('public://test.txt'), Settings::get('file_public_path') . '/test.txt'), 'Public external URL correctly built.');
     $this->assertTrue(strpos(file_create_url('private://test.txt'), 'system/files/test.txt'), 'Private external URL correctly built.');
 }
Example #3
0
 /**
  * @param \Symfony\Component\DependencyInjection\ContainerBuilder $container
  *
  * @throws \InvalidArgumentException
  */
 public function process(ContainerBuilder $container)
 {
     // configure the profiler service
     if (FALSE === $container->hasDefinition('profiler')) {
         return;
     }
     $definition = $container->getDefinition('profiler');
     $collectors = new \SplPriorityQueue();
     $order = PHP_INT_MAX;
     foreach ($container->findTaggedServiceIds('data_collector') as $id => $attributes) {
         $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
         $template = NULL;
         if (isset($attributes[0]['template'])) {
             if (!isset($attributes[0]['id'])) {
                 throw new \InvalidArgumentException(sprintf('Data collector service "%s" must have an id attribute in order to specify a template', $id));
             }
             if (!isset($attributes[0]['title'])) {
                 throw new \InvalidArgumentException(sprintf('Data collector service "%s" must have a title attribute', $id));
             }
             $template = [$attributes[0]['id'], $attributes[0]['template'], $attributes[0]['title']];
         }
         $collectors->insert([$id, $template], [-$priority, --$order]);
     }
     $templates = [];
     foreach ($collectors as $collector) {
         $definition->addMethodCall('add', [new Reference($collector[0])]);
         $templates[$collector[0]] = $collector[1];
     }
     $container->setParameter('data_collector.templates', $templates);
     // set parameter to store the public folder path
     $path = 'file:' . DRUPAL_ROOT . '/' . PublicStream::basePath() . '/profiler';
     $container->setParameter('data_collector.storage', $path);
 }
Example #4
0
 /**
  * Test the theme settings form.
  */
 function testThemeSettings()
 {
     // Ensure invalid theme settings form URLs return a proper 404.
     $this->drupalGet('admin/appearance/settings/bartik');
     $this->assertResponse(404, 'The theme settings form URL for a uninstalled theme could not be found.');
     $this->drupalGet('admin/appearance/settings/' . $this->randomMachineName());
     $this->assertResponse(404, 'The theme settings form URL for a non-existent theme could not be found.');
     // Specify a filesystem path to be used for the logo.
     $file = current($this->drupalGetTestFiles('image'));
     $file_relative = strtr($file->uri, array('public:/' => PublicStream::basePath()));
     $default_theme_path = 'core/themes/classy';
     $supported_paths = array($file->uri => array('form' => file_uri_target($file->uri), 'src' => file_create_url($file->uri)), file_uri_target($file->uri) => array('form' => file_uri_target($file->uri), 'src' => file_create_url($file->uri)), $file_relative => array('form' => $file_relative, 'src' => file_create_url($file->uri)), 'core/misc/druplicon.png' => array('form' => 'core/misc/druplicon.png', 'src' => $GLOBALS['base_url'] . '/' . 'core/misc/druplicon.png'), $default_theme_path . '/logo.svg' => array('form' => $default_theme_path . '/logo.svg', 'src' => $GLOBALS['base_url'] . '/' . $default_theme_path . '/logo.svg'));
     foreach ($supported_paths as $input => $expected) {
         $edit = array('default_logo' => FALSE, 'logo_path' => $input);
         $this->drupalPostForm('admin/appearance/settings', $edit, t('Save configuration'));
         $this->assertNoText('The custom logo path is invalid.');
         $this->assertFieldByName('logo_path', $expected['form']);
         // Verify logo path examples.
         $elements = $this->xpath('//div[contains(@class, :item)]/div[@class=:description]/code', array(':item' => 'form-item-logo-path', ':description' => 'description'));
         // Expected default values (if all else fails).
         $implicit_public_file = 'logo.svg';
         $explicit_file = 'public://logo.svg';
         $local_file = $default_theme_path . '/logo.svg';
         // Adjust for fully qualified stream wrapper URI in public filesystem.
         if (file_uri_scheme($input) == 'public') {
             $implicit_public_file = file_uri_target($input);
             $explicit_file = $input;
             $local_file = strtr($input, array('public:/' => PublicStream::basePath()));
         } elseif (file_uri_scheme($input) !== FALSE) {
             $explicit_file = $input;
         } elseif ($input == file_uri_target($file->uri)) {
             $implicit_public_file = $input;
             $explicit_file = 'public://' . $input;
             $local_file = PublicStream::basePath() . '/' . $input;
         }
         $this->assertEqual((string) $elements[0], $implicit_public_file);
         $this->assertEqual((string) $elements[1], $explicit_file);
         $this->assertEqual((string) $elements[2], $local_file);
         // Verify the actual 'src' attribute of the logo being output.
         $this->drupalGet('');
         $elements = $this->xpath('//header/a[@rel=:rel]/img', array(':rel' => 'home'));
         $this->assertEqual((string) $elements[0]['src'], $expected['src']);
     }
     $unsupported_paths = array('public://whatever.png', 'private://whatever.png', 'temporary://whatever.png', 'public:/whatever.png', '://whatever.png', ':whatever.png', 'public://', 'whatever.png', PublicStream::basePath() . '/whatever.png', '/' . PublicStream::basePath() . '/whatever.png', 'core/misc/whatever.png', '/core/misc/whatever.png', drupal_realpath($file->uri));
     $this->drupalGet('admin/appearance/settings');
     foreach ($unsupported_paths as $path) {
         $edit = array('default_logo' => FALSE, 'logo_path' => $path);
         $this->drupalPostForm(NULL, $edit, t('Save configuration'));
         $this->assertText('The custom logo path is invalid.');
     }
     // Upload a file to use for the logo.
     $edit = array('default_logo' => FALSE, 'logo_path' => '', 'files[logo_upload]' => drupal_realpath($file->uri));
     $this->drupalPostForm('admin/appearance/settings', $edit, t('Save configuration'));
     $fields = $this->xpath($this->constructFieldXpath('name', 'logo_path'));
     $uploaded_filename = 'public://' . $fields[0]['value'];
     $this->drupalGet('');
     $elements = $this->xpath('//header/a[@rel=:rel]/img', array(':rel' => 'home'));
     $this->assertEqual($elements[0]['src'], file_create_url($uploaded_filename));
 }
Example #5
0
 protected function setUp()
 {
     parent::setUp();
     // Create a directory.
     $dir = PublicStream::basePath() . '/config';
     $this->fileStorage = new FileStorage($dir);
     $this->storage = new CachedStorage($this->fileStorage, \Drupal::service('cache.config'));
     $this->cache = \Drupal::service('cache_factory')->get('config');
     // ::listAll() verifications require other configuration data to exist.
     $this->storage->write('system.performance', array());
 }
Example #6
0
 /**
  * {@inheritdoc}
  */
 protected function setUp()
 {
     parent::setUp();
     // Create a directory.
     $this->directory = PublicStream::basePath() . '/config';
     $this->storage = new FileStorage($this->directory);
     $this->invalidStorage = new FileStorage($this->directory . '/nonexisting');
     // FileStorage::listAll() requires other configuration data to exist.
     $this->storage->write('system.performance', $this->config('system.performance')->get());
     $this->storage->write('core.extension', array('module' => array()));
 }
 /**
  * Tests removal of images having a non-local source.
  */
 function testImageSource()
 {
     global $base_url;
     $public_files_path = PublicStream::basePath();
     $http_base_url = preg_replace('/^https?/', 'http', $base_url);
     $https_base_url = preg_replace('/^https?/', 'https', $base_url);
     $files_path = base_path() . $public_files_path;
     $csrf_path = $public_files_path . '/' . implode('/', array_fill(0, substr_count($public_files_path, '/') + 1, '..'));
     $druplicon = 'core/misc/druplicon.png';
     $red_x_image = base_path() . 'core/misc/icons/e32700/error.svg';
     $alt_text = t('Image removed.');
     $title_text = t('This image has been removed. For security reasons, only images from the local domain are allowed.');
     // Put a test image in the files directory.
     $test_images = $this->drupalGetTestFiles('image');
     $test_image = $test_images[0]->filename;
     // Put a test image in the files directory with special filename.
     $special_filename = 'tést fïle nàme.png';
     $special_image = rawurlencode($special_filename);
     $special_uri = str_replace($test_images[0]->filename, $special_filename, $test_images[0]->uri);
     file_unmanaged_copy($test_images[0]->uri, $special_uri);
     // Create a list of test image sources.
     // The keys become the value of the IMG 'src' attribute, the values are the
     // expected filter conversions.
     $host = \Drupal::request()->getHost();
     $host_pattern = '|^http\\://' . $host . '(\\:[0-9]{0,5})|';
     $images = array($http_base_url . '/' . $druplicon => base_path() . $druplicon, $https_base_url . '/' . $druplicon => base_path() . $druplicon, preg_replace($host_pattern, 'http://' . $host . ':', $http_base_url . '/' . $druplicon) => base_path() . $druplicon, preg_replace($host_pattern, 'http://' . $host . ':80', $http_base_url . '/' . $druplicon) => base_path() . $druplicon, preg_replace($host_pattern, 'http://' . $host . ':443', $http_base_url . '/' . $druplicon) => base_path() . $druplicon, preg_replace($host_pattern, 'http://' . $host . ':8080', $http_base_url . '/' . $druplicon) => base_path() . $druplicon, base_path() . $druplicon => base_path() . $druplicon, $files_path . '/' . $test_image => $files_path . '/' . $test_image, $http_base_url . '/' . $public_files_path . '/' . $test_image => $files_path . '/' . $test_image, $https_base_url . '/' . $public_files_path . '/' . $test_image => $files_path . '/' . $test_image, $http_base_url . '/' . $public_files_path . '/' . $special_image => $files_path . '/' . $special_image, $https_base_url . '/' . $public_files_path . '/' . $special_image => $files_path . '/' . $special_image, $files_path . '/example.png' => $red_x_image, 'http://example.com/' . $druplicon => $red_x_image, 'https://example.com/' . $druplicon => $red_x_image, 'javascript:druplicon.png' => $red_x_image, $csrf_path . '/logout' => $red_x_image);
     $comment = array();
     foreach ($images as $image => $converted) {
         // Output the image source as plain text for debugging.
         $comment[] = $image . ':';
         // Hash the image source in a custom test attribute, because it might
         // contain characters that confuse XPath.
         $comment[] = '<img src="' . $image . '" testattribute="' . hash('sha256', $image) . '" />';
     }
     $edit = array('comment_body[0][value]' => implode("\n", $comment));
     $this->drupalPostForm('node/' . $this->node->id(), $edit, t('Save'));
     foreach ($images as $image => $converted) {
         $found = FALSE;
         foreach ($this->xpath('//img[@testattribute="' . hash('sha256', $image) . '"]') as $element) {
             $found = TRUE;
             if ($converted == $red_x_image) {
                 $this->assertEqual((string) $element['src'], $red_x_image);
                 $this->assertEqual((string) $element['alt'], $alt_text);
                 $this->assertEqual((string) $element['title'], $title_text);
                 $this->assertEqual((string) $element['height'], '16');
                 $this->assertEqual((string) $element['width'], '16');
             } else {
                 $this->assertEqual((string) $element['src'], $converted);
             }
         }
         $this->assertTrue($found, format_string('@image was found.', array('@image' => $image)));
     }
 }
 /**
  * Test for transliteration of file name.
  */
 public function testFileTransliteration()
 {
     $account = $this->drupalCreateUser(array('access site reports'));
     $this->drupalLogin($account);
     $original = drupal_get_path('module', 'simpletest') . '/files';
     file_unmanaged_copy($original . '/image-1.png', PublicStream::basePath() . '/foo°.png');
     // Upload with replace to guarantee there's something there.
     $edit = array('file_test_replace' => FILE_EXISTS_RENAME, 'files[file_test_upload]' => drupal_realpath('public://foo°.png'));
     $this->drupalPostForm('file-test/upload', $edit, t('Submit'));
     $this->assertResponse(200, 'Received a 200 response for posted test file.');
     $this->assertRaw(t('You WIN!'), 'Found the success message.');
     $this->assertTrue(file_exists('temporary://foodeg.png'));
     $max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {file_managed}')->fetchField();
     $file = file_load($max_fid_after);
     $this->assertIdentical('foodeg.png', $file->getFilename());
     $this->assertIdentical('temporary://foodeg.png', $file->getFileUri());
 }
Example #9
0
 /**
  * {@inheritdoc}
  */
 public function buildForm(array $form, FormStateInterface $form_state)
 {
     $config = $this->config('system.file');
     $form['file_public_path'] = array('#type' => 'item', '#title' => t('Public file system path'), '#markup' => PublicStream::basePath(), '#description' => t('A local file system path where public files will be stored. This directory must exist and be writable by Drupal. This directory must be relative to the Drupal installation directory and be accessible over the web. This must be changed in settings.php'));
     $form['file_private_path'] = array('#type' => 'item', '#title' => t('Private file system path'), '#markup' => PrivateStream::basePath() ? PrivateStream::basePath() : t('Not set'), '#description' => t('An existing local file system path for storing private files. It should be writable by Drupal and not accessible over the web. This must be changed in settings.php'));
     $form['file_temporary_path'] = array('#type' => 'textfield', '#title' => t('Temporary directory'), '#default_value' => $config->get('path.temporary'), '#maxlength' => 255, '#description' => t('A local file system path where temporary files will be stored. This directory should not be accessible over the web.'), '#after_build' => array('system_check_directory'));
     // Any visible, writeable wrapper can potentially be used for the files
     // directory, including a remote file system that integrates with a CDN.
     $options = $this->streamWrapperManager->getDescriptions(StreamWrapperInterface::WRITE_VISIBLE);
     if (!empty($options)) {
         $form['file_default_scheme'] = array('#type' => 'radios', '#title' => t('Default download method'), '#default_value' => $config->get('default_scheme'), '#options' => $options, '#description' => t('This setting is used as the preferred download method. The use of public files is more efficient, but does not provide any access control.'));
     }
     $intervals = array(0, 21600, 43200, 86400, 604800, 2419200, 7776000);
     $period = array_combine($intervals, array_map(array($this->dateFormatter, 'formatInterval'), $intervals));
     $period[0] = t('Never');
     $form['temporary_maximum_age'] = array('#type' => 'select', '#title' => t('Delete orphaned files after'), '#default_value' => $config->get('temporary_maximum_age'), '#options' => $period, '#description' => t('Orphaned files are not referenced from any content but remain in the file system and may appear in administrative listings. <strong>Warning:</strong> If enabled, orphaned files will be permanently deleted and may not be recoverable.'));
     return parent::buildForm($form, $form_state);
 }
 /**
  * Test the URI and target functions.
  */
 function testUriFunctions()
 {
     $config = \Drupal::config('system.file');
     $instance = file_stream_wrapper_get_instance_by_uri($this->scheme . '://foo');
     $this->assertEqual($this->classname, get_class($instance), 'Got correct class type for dummy URI.');
     $instance = file_stream_wrapper_get_instance_by_uri('public://foo');
     $this->assertEqual('Drupal\\Core\\StreamWrapper\\PublicStream', get_class($instance), 'Got correct class type for public URI.');
     // Test file_uri_target().
     $this->assertEqual(file_uri_target('public://foo/bar.txt'), 'foo/bar.txt', 'Got a valid stream target from public://foo/bar.txt.');
     $this->assertFalse(file_uri_target('foo/bar.txt'), 'foo/bar.txt is not a valid stream.');
     // Test file_build_uri() and
     // Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath().
     $this->assertEqual(file_build_uri('foo/bar.txt'), 'public://foo/bar.txt', 'Expected scheme was added.');
     $this->assertEqual(file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath(), PublicStream::basePath(), 'Expected default directory path was returned.');
     $this->assertEqual(file_stream_wrapper_get_instance_by_scheme('temporary')->getDirectoryPath(), $config->get('path.temporary'), 'Expected temporary directory path was returned.');
     $config->set('default_scheme', 'private')->save();
     $this->assertEqual(file_build_uri('foo/bar.txt'), 'private://foo/bar.txt', 'Got a valid URI from foo/bar.txt.');
 }
 /**
  * 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);
 }
Example #12
0
 /**
  * {@inheritdoc}
  */
 public function buildForm(array $form, array &$form_state)
 {
     $config = $this->config('system.file');
     $form['file_public_path'] = array('#type' => 'item', '#title' => t('Public file system path'), '#default_value' => PublicStream::basePath(), '#markup' => PublicStream::basePath(), '#description' => t('A local file system path where public files will be stored. This directory must exist and be writable by Drupal. This directory must be relative to the Drupal installation directory and be accessible over the web. This must be changed in settings.php'));
     $form['file_private_path'] = array('#type' => 'textfield', '#title' => t('Private file system path'), '#default_value' => $config->get('path.private'), '#maxlength' => 255, '#description' => t('An existing local file system path for storing private files. It should be writable by Drupal and not accessible over the web. See the online handbook for <a href="@handbook">more information about securing private files</a>.', array('@handbook' => 'http://drupal.org/documentation/modules/file')), '#after_build' => array('system_check_directory'));
     $form['file_temporary_path'] = array('#type' => 'textfield', '#title' => t('Temporary directory'), '#default_value' => $config->get('path.temporary'), '#maxlength' => 255, '#description' => t('A local file system path where temporary files will be stored. This directory should not be accessible over the web.'), '#after_build' => array('system_check_directory'));
     // Any visible, writeable wrapper can potentially be used for the files
     // directory, including a remote file system that integrates with a CDN.
     foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $info) {
         $options[$scheme] = String::checkPlain($info['description']);
     }
     if (!empty($options)) {
         $form['file_default_scheme'] = array('#type' => 'radios', '#title' => t('Default download method'), '#default_value' => $config->get('default_scheme'), '#options' => $options, '#description' => t('This setting is used as the preferred download method. The use of public files is more efficient, but does not provide any access control.'));
     }
     $intervals = array(0, 21600, 43200, 86400, 604800, 2419200, 7776000);
     $period = array_combine($intervals, array_map('format_interval', $intervals));
     $period[0] = t('Never');
     $form['temporary_maximum_age'] = array('#type' => 'select', '#title' => t('Delete orphaned files after'), '#default_value' => $config->get('temporary_maximum_age'), '#options' => $period, '#description' => t('Orphaned files are not referenced from any content but remain in the file system and may appear in administrative listings. <strong>Warning:</strong> If enabled, orphaned files will be permanently deleted and may not be recoverable.'));
     return parent::buildForm($form, $form_state);
 }
Example #13
0
 function testJail()
 {
     $source = $this->_buildFakeModule();
     // This convoluted piece of code is here because our testing framework does
     // not support expecting exceptions.
     $gotit = FALSE;
     try {
         $this->testConnection->copyDirectory($source, sys_get_temp_dir());
     } catch (FileTransferException $e) {
         $gotit = TRUE;
     }
     $this->assertTrue($gotit, 'Was not able to copy a directory outside of the jailed area.');
     $gotit = TRUE;
     try {
         $this->testConnection->copyDirectory($source, \Drupal::root() . '/' . PublicStream::basePath());
     } catch (FileTransferException $e) {
         $gotit = FALSE;
     }
     $this->assertTrue($gotit, 'Was able to copy a directory inside of the jailed area');
 }
 /**
  * Test the URI and target functions.
  */
 function testUriFunctions()
 {
     $config = \Drupal::config('system.file');
     $instance = file_stream_wrapper_get_instance_by_uri($this->scheme . '://foo');
     $this->assertEqual($this->classname, get_class($instance), 'Got correct class type for dummy URI.');
     $instance = file_stream_wrapper_get_instance_by_uri('public://foo');
     $this->assertEqual('Drupal\\Core\\StreamWrapper\\PublicStream', get_class($instance), 'Got correct class type for public URI.');
     // Test file_uri_target().
     $this->assertEqual(file_uri_target('public://foo/bar.txt'), 'foo/bar.txt', 'Got a valid stream target from public://foo/bar.txt.');
     $this->assertEqual(file_uri_target('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', t('Got a valid stream target from a data URI.'));
     $this->assertFalse(file_uri_target('foo/bar.txt'), 'foo/bar.txt is not a valid stream.');
     $this->assertFalse(file_uri_target('public://'), 'public:// has no target.');
     $this->assertFalse(file_uri_target('data:'), 'data: has no target.');
     // Test file_build_uri() and
     // Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath().
     $this->assertEqual(file_build_uri('foo/bar.txt'), 'public://foo/bar.txt', 'Expected scheme was added.');
     $this->assertEqual(file_stream_wrapper_get_instance_by_scheme('public')->getDirectoryPath(), PublicStream::basePath(), 'Expected default directory path was returned.');
     $this->assertEqual(file_stream_wrapper_get_instance_by_scheme('temporary')->getDirectoryPath(), $config->get('path.temporary'), 'Expected temporary directory path was returned.');
     $config->set('default_scheme', 'private')->save();
     $this->assertEqual(file_build_uri('foo/bar.txt'), 'private://foo/bar.txt', 'Got a valid URI from foo/bar.txt.');
 }
 /**
  * Gets a list of files that can be used in tests.
  *
  * The first time this method is called, it will call
  * $this->generateFile() to generate binary and ASCII text files in the
  * public:// directory. It will also copy all files in
  * core/modules/simpletest/files to public://. These contain image, SQL, PHP,
  * JavaScript, and HTML files.
  *
  * All filenames are prefixed with their type and have appropriate extensions:
  * - text-*.txt
  * - binary-*.txt
  * - html-*.html and html-*.txt
  * - image-*.png, image-*.jpg, and image-*.gif
  * - javascript-*.txt and javascript-*.script
  * - php-*.txt and php-*.php
  * - sql-*.txt and sql-*.sql
  *
  * Any subsequent calls will not generate any new files, or copy the files
  * over again. However, if a test class adds a new file to public:// that
  * is prefixed with one of the above types, it will get returned as well, even
  * on subsequent calls.
  *
  * @param $type
  *   File type, possible values: 'binary', 'html', 'image', 'javascript',
  *   'php', 'sql', 'text'.
  * @param $size
  *   (optional) File size in bytes to match. Defaults to NULL, which will not
  *   filter the returned list by size.
  *
  * @return array[]
  *   List of files in public:// that match the filter(s).
  */
 protected function getTestFiles($type, $size = NULL)
 {
     if (empty($this->generatedTestFiles)) {
         // Generate binary test files.
         $lines = [64, 1024];
         $count = 0;
         foreach ($lines as $line) {
             $this->generateFile('binary-' . $count++, 64, $line, 'binary');
         }
         // Generate ASCII text test files.
         $lines = [16, 256, 1024, 2048, 20480];
         $count = 0;
         foreach ($lines as $line) {
             $this->generateFile('text-' . $count++, 64, $line, 'text');
         }
         // Copy other test files from simpletest.
         $original = drupal_get_path('module', 'simpletest') . '/files';
         $files = file_scan_directory($original, '/(html|image|javascript|php|sql)-.*/');
         foreach ($files as $file) {
             file_unmanaged_copy($file->uri, PublicStream::basePath());
         }
         $this->generatedTestFiles = TRUE;
     }
     $files = [];
     // Make sure type is valid.
     if (in_array($type, ['binary', 'html', 'image', 'javascript', 'php', 'sql', 'text'])) {
         $files = file_scan_directory('public://', '/' . $type . '\\-.*/');
         // If size is set then remove any files that are not of that size.
         if ($size !== NULL) {
             foreach ($files as $file) {
                 $stats = stat($file->uri);
                 if ($stats['size'] != $size) {
                     unset($files[$file->uri]);
                 }
             }
         }
     }
     usort($files, [$this, 'compareFiles']);
     return $files;
 }
Example #16
0
 /**
  * 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);
 }
Example #17
0
 /**
  * Setup the environment containing local and remote translation files.
  *
  * Update tests require a simulated environment for local and remote files.
  * Normally remote files are located at a remote server (e.g. ftp.drupal.org).
  * For testing we can not rely on this. A directory in the file system of the
  * test site is designated for remote files and is addressed using an absolute
  * URL. Because Drupal does not allow files with a po extension to be accessed
  * (denied in .htaccess) the translation files get a _po extension. Another
  * directory is designated for local translation files.
  *
  * The environment is set up with the following files. File creation times are
  * set to create different variations in test conditions.
  *   contrib_module_one
  *    - remote file: timestamp new
  *    - local file:  timestamp old
  *   contrib_module_two
  *    - remote file: timestamp old
  *    - local file:  timestamp new
  *   contrib_module_three
  *    - remote file: timestamp old
  *    - local file:  timestamp old
  *   custom_module_one
  *    - local file:  timestamp new
  * Time stamp of current translation set by setCurrentTranslations() is always
  * timestamp medium. This makes it easy to predict which translation will be
  * imported.
  */
 protected function setTranslationFiles()
 {
     $config = $this->config('locale.settings');
     // A flag is set to let the locale_test module replace the project data with
     // a set of test projects which match the below project files.
     \Drupal::state()->set('locale.test_projects_alter', TRUE);
     \Drupal::state()->set('locale.remove_core_project', FALSE);
     // Setup the environment.
     $public_path = PublicStream::basePath();
     $this->setTranslationsDirectory($public_path . '/local');
     $config->set('translation.default_filename', '%project-%version.%language._po')->save();
     // Setting up sets of translations for the translation files.
     $translations_one = array('January' => 'Januar_1', 'February' => 'Februar_1', 'March' => 'Marz_1');
     $translations_two = array('February' => 'Februar_2', 'March' => 'Marz_2', 'April' => 'April_2');
     $translations_three = array('April' => 'April_3', 'May' => 'Mai_3', 'June' => 'Juni_3');
     // Add a number of files to the local file system to serve as remote
     // translation server and match the project definitions set in
     // locale_test_locale_translation_projects_alter().
     $this->makePoFile('remote/8.x/contrib_module_one', 'contrib_module_one-8.x-1.1.de._po', $this->timestampNew, $translations_one);
     $this->makePoFile('remote/8.x/contrib_module_two', 'contrib_module_two-8.x-2.0-beta4.de._po', $this->timestampOld, $translations_two);
     $this->makePoFile('remote/8.x/contrib_module_three', 'contrib_module_three-8.x-1.0.de._po', $this->timestampOld, $translations_three);
     // Add a number of files to the local file system to serve as local
     // translation files and match the project definitions set in
     // locale_test_locale_translation_projects_alter().
     $this->makePoFile('local', 'contrib_module_one-8.x-1.1.de._po', $this->timestampOld, $translations_one);
     $this->makePoFile('local', 'contrib_module_two-8.x-2.0-beta4.de._po', $this->timestampNew, $translations_two);
     $this->makePoFile('local', 'contrib_module_three-8.x-1.0.de._po', $this->timestampOld, $translations_three);
     $this->makePoFile('local', 'custom_module_one.de.po', $this->timestampNew);
 }
 /**
  * Overrides \Drupal\block\BlockBase::blockForm().
  */
 public function blockForm($form, FormStateInterface $form_state)
 {
     // Labels & default text.
     $form['search_box'] = array('#type' => 'details', '#title' => t('Search box'), '#open' => TRUE);
     $form['search_box']['label_visibility'] = array('#type' => 'checkbox', '#title' => t('Display label'), '#default_value' => $this->configuration['search_box']['label_visibility']);
     $form['search_box']['label'] = array('#type' => 'textfield', '#title' => t('Label'), '#default_value' => $this->configuration['search_box']['label'], '#description' => t('Enter the label text for the search box. The default value is "Search this site".'), '#states' => array('visible' => array(':input[name="settings[search_box][label_visibility]"]' => array('checked' => TRUE))));
     $form['search_box']['placeholder'] = array('#type' => 'textfield', '#title' => t('Placeholder text'), '#default_value' => $this->configuration['search_box']['placeholder'], '#description' => t('This will change the default text inside the search form. This is the <a href="http://www.w3schools.com/tags/att_input_placeholder.asp" target="_blank">placeholder</a> attribute for the TextField. Leave blank for no text. This field is blank by default.'));
     $form['search_box']['title'] = array('#type' => 'textfield', '#title' => t('Hint text'), '#default_value' => $this->configuration['search_box']['title'], '#description' => t('Enter the text that will be displayed when hovering the input field (HTML <em>title</em> attritube).'));
     $form['search_box']['size'] = array('#type' => 'textfield', '#title' => t('Size'), '#size' => 3, '#default_value' => $this->configuration['search_box']['size'], '#description' => t('The default value is "!default".', array('!default' => 15)));
     $form['search_box']['max_length'] = array('#type' => 'textfield', '#title' => t('Maximum length'), '#size' => 3, '#default_value' => $this->configuration['search_box']['max_length'], '#description' => t('The default value is "!default".', array('!default' => 128)), '#required' => TRUE);
     // Submit button.
     $form['submit'] = array('#type' => 'details', '#title' => t('Submit button'), '#open' => TRUE);
     $form['submit']['text'] = array('#type' => 'textfield', '#title' => t('Text'), '#default_value' => $this->configuration['submit']['text'], '#description' => t('Enter the text for the submit button. Leave blank to hide it. The default value is "Search".'));
     if ($this->moduleHandler->moduleExists('file')) {
         $form['submit']['image_path'] = array('#type' => 'textfield', '#title' => t('Image path'), '#description' => t('The path to the file you would like to use as submit button instead of the default text button.'), '#default_value' => $this->configuration['submit']['image_path']);
         $friendly_path = NULL;
         $default_image = 'search.png';
         if (\Drupal::service('file_system')->uriScheme($this->configuration['submit']['image_path']) == 'public') {
             $friendly_path = file_uri_target($this->configuration['submit']['image_path']);
         }
         if ($this->configuration['submit']['image_path'] && isset($friendly_path)) {
             $local_file = strtr($this->configuration['submit']['image_path'], array('public:/' => PublicStream::basePath()));
         } else {
             $local_file = \Drupal::theme()->getActiveTheme()->getPath() . '/' . $default_image;
         }
         $form['submit']['image_path']['#description'] = t('Examples: <code>@implicit-public-file</code> (for a file in the public filesystem), <code>@explicit-file</code>, or <code>@local-file</code>.', array('@implicit-public-file' => isset($friendly_path) ? $friendly_path : $default_image, '@explicit-file' => \Drupal::service('file_system')->uriScheme($this->configuration['submit']['image_path']) !== FALSE ? $this->configuration['submit']['image_path'] : 'public://' . $default_image, '@local-file' => $local_file));
         $form['submit']['image'] = array('#type' => 'file', '#title' => t('Image'), '#description' => t("If you don't have direct file access to the server, use this field to upload your image."));
     }
     // Content.
     $form['content'] = array('#type' => 'details', '#title' => t('Content'), '#description' => t("Select the search types to present as search options in the search block. If none is selected, no selector will be displayed. <strong>Note</strong>: if there's only one type checked, the selector won't be displayed BUT only this type will be searched."), '#open' => count(array_filter($this->configuration['content']['types'])) + count(array_filter($this->configuration['content']['excluded'])));
     $search_pages = entity_load_multiple('search_page');
     $pages_options = array();
     foreach ($search_pages as $page) {
         if ($page->getPlugin()->getPluginId() == 'node_search') {
             $pages_options[$page->id()] = $page->label();
         }
     }
     if (count($pages_options)) {
         $form['content']['page'] = array('#type' => 'select', '#title' => t('Search page'), '#description' => t('Select which page to use when searching content with this block. Pages are defined <a href="!link">here</a>.', array('!link' => Url::fromRoute('entity.search_page.collection', array(), array('fragment' => 'edit-search-pages'))->toString())), '#default_value' => $this->configuration['content']['page'], '#options' => $pages_options);
     }
     $form['content']['types'] = array('#type' => 'checkboxes', '#title' => t('Content types'), '#default_value' => $this->configuration['content']['types'], '#options' => node_type_get_names());
     $other_pages_options = array();
     foreach ($search_pages as $page) {
         if ($page->getPlugin()->getPluginId() != 'node_search') {
             $other_pages_options[$page->id()] = $page->label();
         }
     }
     if (count($other_pages_options)) {
         $form['content']['other'] = array('#type' => 'checkboxes', '#title' => t('Other search pages'), '#default_value' => $this->configuration['content']['other'], '#options' => $other_pages_options);
     }
     $form['content']['selector']['type'] = array('#type' => 'select', '#title' => t('Selector type'), '#options' => array('select' => t('Drop-down list'), 'selectmultiple' => t('Drop-down list with multiple choices'), 'radios' => t('Radio buttons'), 'checkboxes' => t('Checkboxes')), '#description' => t('Choose which selector type to use. Note: content types and other searches cannot be combined in a single search.'), '#default_value' => $this->configuration['content']['selector']['type']);
     $form['content']['selector']['label_visibility'] = array('#type' => 'checkbox', '#title' => t('Display label'), '#default_value' => $this->configuration['content']['selector']['label_visibility']);
     $form['content']['selector']['label'] = array('#type' => 'textfield', '#title' => t('Label text'), '#default_value' => $this->configuration['content']['selector']['label'], '#description' => t('Enter the label text for the selector. The default value is "Search for".'), '#states' => array('visible' => array(':input[name="settings[content][selector][label_visibility]"]' => array('checked' => TRUE))));
     $form['content']['any'] = array('#type' => 'details', '#title' => t('- Any -'));
     $form['content']['any']['text'] = array('#type' => 'textfield', '#title' => t('- Any content type - text'), '#default_value' => $this->configuration['content']['any']['text'], '#required' => TRUE, '#description' => t('Enter the text for "any content type" choice. The default value is "- Any -".'));
     $form['content']['any']['restricts'] = array('#type' => 'checkbox', '#title' => t('Choosing - Any - restricts the search to the selected content types.'), '#default_value' => $this->configuration['content']['any']['restricts'], '#description' => t('If not checked, choosing - Any - will search in all content types.'));
     $form['content']['any']['force'] = array('#type' => 'checkbox', '#title' => t('Force - Any - to be displayed.'), '#default_value' => $this->configuration['content']['any']['force'], '#description' => t('When only one content type is selected, the default behaviour is to hide the selector. If you need the - Any - option to be displayed, check this.'));
     $form['content']['excluded'] = array('#type' => 'checkboxes', '#title' => t('Content exclusion'), '#description' => t("Select the content types you don't want to be displayed as results."), '#default_value' => $this->configuration['content']['excluded'], '#options' => node_type_get_names());
     // Taxonomy.
     $vocabularies = entity_load_multiple('taxonomy_vocabulary');
     if (count($vocabularies)) {
         $open = FALSE;
         foreach ($vocabularies as $voc) {
             $vocId = $voc->id();
             if ($this->configuration['taxonomy'][$vocId]['type'] != 'disabled') {
                 $open = TRUE;
                 break;
             }
         }
         $form['taxonomy'] = array('#type' => 'details', '#title' => t('Taxonomy'), '#description' => t('Select the vocabularies to present as search options in the search block. If none is selected, no selector will be displayed.'), '#open' => $open);
         // Get vocabularies forms.
         foreach ($vocabularies as $voc) {
             $vocId = $voc->id();
             $form['taxonomy'][$vocId] = array('#type' => 'details', '#title' => $voc->label(), '#open' => $this->configuration['taxonomy'][$vocId]['type'] != 'disabled');
             $form['taxonomy'][$vocId]['type'] = array('#type' => 'select', '#title' => t('Selector type'), '#options' => array('disabled' => t('Disabled'), 'select' => t('Drop-down list'), 'selectmultiple' => t('Drop-down list with multiple choices'), 'radios' => t('Radio buttons'), 'checkboxes' => t('Checkboxes')), '#description' => t('Choose which selector type to use.'), '#default_value' => $this->configuration['taxonomy'][$vocId]['type']);
             $form['taxonomy'][$vocId]['depth'] = array('#type' => 'textfield', '#title' => t('Depth'), '#size' => 2, '#default_value' => $this->configuration['taxonomy'][$vocId]['depth'], '#description' => t('Define the maximum depth of terms being displayed. The default value is "0" which disables the limit.'));
             $form['taxonomy'][$vocId]['label_visibility'] = array('#type' => 'checkbox', '#title' => t('Display label'), '#default_value' => $this->configuration['taxonomy'][$vocId]['label_visibility']);
             $form['taxonomy'][$vocId]['label'] = array('#type' => 'textfield', '#title' => t('Label text'), '#default_value' => $this->configuration['taxonomy'][$vocId]['label'], '#description' => t('Enter the label text for the selector. The default value is "!default".', array('!default' => $voc->label())), '#states' => array('visible' => array(':input[name="settings[taxonomy][' . $vocId . '][label_visibility]"]' => array('checked' => TRUE))));
             $form['taxonomy'][$vocId]['all_text'] = array('#type' => 'textfield', '#title' => t('-Any- text'), '#default_value' => $this->configuration['taxonomy'][$vocId]['all_text'], '#required' => TRUE, '#description' => t('Enter the text for "any term" choice. The default value is "- Any -".'));
         }
     }
     // Criteria.
     $form['criteria'] = array('#type' => 'details', '#title' => t('Advanced search criteria'), '#open' => $this->configuration['criteria']['or']['display'] || $this->configuration['criteria']['phrase']['display'] || $this->configuration['criteria']['negative']['display']);
     $form['criteria']['or'] = array('#type' => 'details', '#title' => t('Or'), '#open' => $this->configuration['criteria']['or']['display']);
     $form['criteria']['or']['display'] = array('#type' => 'checkbox', '#title' => t('Display'), '#default_value' => $this->configuration['criteria']['or']['display']);
     $form['criteria']['or']['label'] = array('#type' => 'textfield', '#title' => t('Label'), '#default_value' => $this->configuration['criteria']['or']['label'], '#description' => t('Enter the label text for this field. The default value is "Containing any of the words".'), '#states' => array('visible' => array(':input[name="settings[criteria][or][display]"]' => array('checked' => TRUE))));
     $form['criteria']['phrase'] = array('#type' => 'details', '#title' => t('Phrase'), '#open' => $this->configuration['criteria']['phrase']['display']);
     $form['criteria']['phrase']['display'] = array('#type' => 'checkbox', '#title' => t('Display'), '#default_value' => $this->configuration['criteria']['phrase']['display']);
     $form['criteria']['phrase']['label'] = array('#type' => 'textfield', '#title' => t('Label'), '#default_value' => $this->configuration['criteria']['phrase']['label'], '#description' => t('Enter the label text for this field. The default value is "Containing the phrase".'), '#states' => array('visible' => array(':input[name="settings[criteria][phrase][display]"]' => array('checked' => TRUE))));
     $form['criteria']['negative'] = array('#type' => 'details', '#title' => t('Negative'), '#open' => $this->configuration['criteria']['negative']['display']);
     $form['criteria']['negative']['display'] = array('#type' => 'checkbox', '#title' => t('Display'), '#default_value' => $this->configuration['criteria']['negative']['display']);
     $form['criteria']['negative']['label'] = array('#type' => 'textfield', '#title' => t('Label'), '#default_value' => $this->configuration['criteria']['negative']['label'], '#description' => t('Enter the label text for this field. The default value is "Containing none of the words".'), '#states' => array('visible' => array(':input[name="settings[criteria][negative][display]"]' => array('checked' => TRUE))));
     // Search API support.
     if ($this->moduleHandler->moduleExists('search_api_page')) {
         $search_api_pages = search_api_page_load_multiple();
         $options[0] = t('None');
         foreach ($search_api_pages as $page) {
             $options[$page->id()] = $page->label();
         }
         $form['searchapi'] = array('#type' => 'details', '#title' => t('Search API'), '#collapsible' => TRUE, '#collapsed' => TRUE);
         $form['searchapi']['page'] = array('#type' => 'select', '#title' => t('Search API Page to use'), '#options' => $options, '#default_value' => $this->configuration['searchapi']['page']);
     }
     // Languages.
     $form['languages'] = array('#type' => 'details', '#title' => t('Languages'), '#description' => t("Select the languages to present as search options in the search block. If none is selected, no selector will be displayed. <strong>Note</strong>: if there's only one language checked, the selector won't be displayed BUT only this language will be searched."), '#open' => count(array_filter($this->configuration['languages']['languages'])));
     $languages = \Drupal::languageManager()->getLanguages();
     $languages_options = array('current' => t('- Current language -'));
     foreach ($languages as $id => $language) {
         $languages_options[$id] = $language->getName();
     }
     $languages_options[Language::LANGCODE_NOT_SPECIFIED] = t('- Not specified -');
     $languages_options[Language::LANGCODE_NOT_APPLICABLE] = t('- Not applicable -');
     $form['languages']['languages'] = array('#type' => 'checkboxes', '#title' => t('Languages'), '#description' => t('Note: if <em>- Current language -</em> is selected, this current language won\'t be displayed twice.'), '#default_value' => $this->configuration['languages']['languages'], '#options' => $languages_options);
     $form['languages']['selector']['type'] = array('#type' => 'select', '#title' => t('Selector type'), '#options' => array('select' => t('Drop-down list'), 'selectmultiple' => t('Drop-down list with multiple choices'), 'radios' => t('Radio buttons'), 'checkboxes' => t('Checkboxes')), '#description' => t('Choose which selector type to use.'), '#default_value' => $this->configuration['languages']['selector']['type']);
     $form['languages']['selector']['label_visibility'] = array('#type' => 'checkbox', '#title' => t('Display label'), '#default_value' => $this->configuration['languages']['selector']['label_visibility']);
     $form['languages']['selector']['label'] = array('#type' => 'textfield', '#title' => t('Label text'), '#default_value' => $this->configuration['languages']['selector']['label'], '#description' => t('Enter the label text for the selector. The default value is "Languages".'), '#states' => array('visible' => array(':input[name="settings[languages][selector][label_visibility]"]' => array('checked' => TRUE))));
     $form['languages']['any'] = array('#type' => 'details', '#title' => t('- Any -'));
     $form['languages']['any']['text'] = array('#type' => 'textfield', '#title' => t('- Any language - text'), '#default_value' => $this->configuration['languages']['any']['text'], '#required' => TRUE, '#description' => t('Enter the text for "any language" choice. The default value is "- Any -".'));
     $form['languages']['any']['restricts'] = array('#type' => 'checkbox', '#title' => t('Choosing - Any - restricts the search to the selected languages.'), '#default_value' => $this->configuration['languages']['any']['restricts'], '#description' => t('If not checked, choosing - Any - will search in all languages.'));
     $form['languages']['any']['force'] = array('#type' => 'checkbox', '#title' => t('Force - Any - to be displayed.'), '#default_value' => $this->configuration['languages']['any']['force'], '#description' => t('When only one language is selected, the default behaviour is to hide the selector. If you need the - Any - option to be displayed, check this.'));
     // Custom Paths.
     $form['paths'] = array('#type' => 'details', '#title' => t('Custom search paths'), '#open' => $this->configuration['paths']['list'] != '');
     $form['paths']['selector']['type'] = array('#type' => 'select', '#title' => t('Selector type'), '#options' => array('select' => t('Drop-down list'), 'radios' => t('Radio buttons')), '#description' => t('Choose which selector type to use.'), '#default_value' => $this->configuration['paths']['selector']['type']);
     $form['paths']['selector']['label_visibility'] = array('#type' => 'checkbox', '#title' => t('Display label'), '#default_value' => $this->configuration['paths']['selector']['label_visibility']);
     $form['paths']['selector']['label'] = array('#type' => 'textfield', '#title' => t('Label text'), '#default_value' => $this->configuration['paths']['selector']['label'], '#description' => t('Enter the label text for the selector. The default value is "Customize your search".'), '#states' => array('visible' => array(':input[name="settings[paths][selector][label_visibility]"]' => array('checked' => TRUE))));
     $form['paths']['list'] = array('#type' => 'textarea', '#title' => t('Paths'), '#default_value' => $this->configuration['paths']['list'], '#rows' => 3, '#description' => t('If you want to use custom search paths, enter them here in the form <em>path</em>|<em>label</em>, one per line (if only one path is specified, the selector will be hidden). The [key] token will be replaced by what is entered in the search box, the [types] token will be replaced by the selected content types machine name(s) and the [terms] token will be replaced by the selected taxonomy term id(s). Ie: mysearch/[key]|My custom search label. The [current_path] token can also be used to use the current URL path of the page being viewed.'));
     $form['paths']['separator'] = array('#type' => 'textfield', '#title' => t('Arguments separator'), '#description' => t('Enter a separator that will be used when multiple content types or taxonomy terms are selected and [types] and/or [terms] tokens are used.'), '#default_value' => $this->configuration['paths']['separator'], '#size' => 2);
     // Ordering.
     $form['#attached']['library'][] = 'core/drupal.tableheader';
     $form['#attached']['library'][] = 'custom_search/custom_search.ordering';
     $form['order'] = array('#type' => 'details', '#title' => t('Elements layout'), '#description' => t('Order the form elements as you want them to be displayed. If you put elements in the Popup region, they will only appear when the search field is clicked.'), '#open' => TRUE);
     $form['order']['table'] = array('#type' => 'table', '#header' => array(t('Element'), t('Region'), t('Weight')), '#attributes' => array('id' => 'elements'));
     $elements = array('search_box' => array('label' => t('Search box'), 'config' => $this->configuration['search_box']), 'submit' => array('label' => t('Submit button'), 'config' => $this->configuration['submit']), 'content' => array('label' => t('Content types'), 'config' => $this->configuration['content']), 'or' => array('label' => t('Criteria: Containing any of the words'), 'config' => $this->configuration['criteria']['or']), 'phrase' => array('label' => t('Criteria: Containing the phrase'), 'config' => $this->configuration['criteria']['phrase']), 'negative' => array('label' => t('Criteria: Containing none of the words'), 'config' => $this->configuration['criteria']['negative']), 'languages' => array('label' => t('Languages'), 'config' => $this->configuration['languages']), 'paths' => array('label' => t('Custom Path'), 'config' => $this->configuration['paths']));
     if (count($vocabularies)) {
         foreach ($vocabularies as $voc) {
             $vocId = $voc->id();
             $elements['voc-' . $vocId] = array('label' => t('Taxonomy: !name', array('!name' => $voc->label())), 'config' => $this->configuration['taxonomy'][$vocId]);
         }
     }
     uasort($elements, array($this, 'weightsSort'));
     $regions = array('block' => t('Block'), 'popup' => t('Popup'));
     foreach ($elements as $id => $element) {
         $element_config = $element['config'];
         $regionsElements[$element_config['region']][$id] = $element;
     }
     foreach ($regions as $region => $title) {
         $form['order']['table']['#tabledrag'][] = array('action' => 'match', 'relationship' => 'sibling', 'group' => 'order-region', 'subgroup' => 'order-region-' . $region, 'hidden' => FALSE);
         $form['order']['table']['#tabledrag'][] = array('action' => 'order', 'relationship' => 'sibling', 'group' => 'order-weight', 'subgroup' => 'order-weight-' . $region);
         $form['order']['table'][$region] = array('#attributes' => array('class' => array('region-title', 'region-title-' . $region), 'no_striping' => TRUE));
         $form['order']['table'][$region]['title'] = array('#markup' => $title, '#wrapper_attributes' => array('colspan' => 5));
         $form['order']['table'][$region . '-message'] = array('#attributes' => array('class' => array('region-message', 'region-' . $region . '-message', empty($regionsElements[$region]) ? 'region-empty' : 'region-populated')));
         $form['order']['table'][$region . '-message']['message'] = array('#markup' => '<em>' . t('No elements in this region') . '</em>', '#wrapper_attributes' => array('colspan' => 5));
         if (isset($regionsElements[$region])) {
             foreach ($regionsElements[$region] as $id => $element) {
                 $element_config = $element['config'];
                 $form['order']['table'][$id]['#attributes']['class'][] = 'draggable';
                 $form['order']['table'][$id]['#weight'] = $element_config['weight'];
                 $form['order']['table'][$id]['element'] = array('#markup' => $element['label']);
                 $form['order']['table'][$id]['region'] = array('#type' => 'select', '#title' => t('Region for @title', array('@title' => $element['label'])), '#title_display' => 'invisible', '#options' => array('block' => t('Block'), 'popup' => t('Popup')), '#default_value' => $region, '#attributes' => array('class' => array('order-region', 'order-region-' . $region)));
                 $form['order']['table'][$id]['weight'] = array('#type' => 'weight', '#title' => t('Weight for @title', array('@title' => $element['label'])), '#title_display' => 'invisible', '#default_value' => $element_config['weight'], '#attributes' => array('class' => array('order-weight', 'order-weight-' . $element_config['region'])));
             }
         }
     }
     return $form;
 }
  /**
   * Override getExternalUrl().
   *
   * Return the HTML URI of a public file.
   */
  public function getExternalUrl() {
    $path = str_replace('\\', '/', $this->getTarget());

    return PublicStream::baseUrl() . '/' . UrlHelper::encodePath($path);
  }
Example #20
0
 /**
  * Creates and gets test image file.
  *
  * @return \Drupal\file\FileInterface
  *   File object.
  */
 protected function getTestFile() {
   file_unmanaged_copy(drupal_get_path('module', 'crop') . '/tests/files/sarajevo.png', PublicStream::basePath());
   return $this->fileStorage->create([
     'uri' => 'public://sarajevo.png',
     'status' => FILE_STATUS_PERMANENT,
   ]);
 }
Example #21
0
 /**
  * Run all tests in this class.
  *
  * Regardless of whether $methods are passed or not, only method names
  * starting with "test" are executed.
  *
  * @param $methods
  *   (optional) A list of method names in the test case class to run; e.g.,
  *   array('testFoo', 'testBar'). By default, all methods of the class are
  *   taken into account, but it can be useful to only run a few selected test
  *   methods during debugging.
  */
 public function run(array $methods = array())
 {
     $class = get_class($this);
     if ($missing_requirements = $this->checkRequirements()) {
         $object_info = new \ReflectionObject($this);
         $caller = array('file' => $object_info->getFileName());
         foreach ($missing_requirements as $missing_requirement) {
             TestBase::insertAssert($this->testId, $class, FALSE, $missing_requirement, 'Requirements check', $caller);
         }
         return;
     }
     TestServiceProvider::$currentTest = $this;
     $simpletest_config = $this->config('simpletest.settings');
     // Unless preset from run-tests.sh, retrieve the current verbose setting.
     if (!isset($this->verbose)) {
         $this->verbose = $simpletest_config->get('verbose');
     }
     if ($this->verbose) {
         // Initialize verbose debugging.
         $this->verbose = TRUE;
         $this->verboseDirectory = PublicStream::basePath() . '/simpletest/verbose';
         $this->verboseDirectoryUrl = file_create_url($this->verboseDirectory);
         if (file_prepare_directory($this->verboseDirectory, FILE_CREATE_DIRECTORY) && !file_exists($this->verboseDirectory . '/.htaccess')) {
             file_put_contents($this->verboseDirectory . '/.htaccess', "<IfModule mod_expires.c>\nExpiresActive Off\n</IfModule>\n");
         }
         $this->verboseClassName = str_replace("\\", "_", $class);
     }
     // HTTP auth settings (<username>:<password>) for the simpletest browser
     // when sending requests to the test site.
     $this->httpAuthMethod = (int) $simpletest_config->get('httpauth.method');
     $username = $simpletest_config->get('httpauth.username');
     $password = $simpletest_config->get('httpauth.password');
     if (!empty($username) && !empty($password)) {
         $this->httpAuthCredentials = $username . ':' . $password;
     }
     set_error_handler(array($this, 'errorHandler'));
     // Iterate through all the methods in this class, unless a specific list of
     // methods to run was passed.
     $test_methods = array_filter(get_class_methods($class), function ($method) {
         return strpos($method, 'test') === 0;
     });
     if (empty($test_methods)) {
         // Call $this->assert() here because we need to pass along custom caller
         // information, lest the wrong originating code file/line be identified.
         $this->assert(FALSE, 'No test methods found.', 'Requirements', array('function' => __METHOD__ . '()', 'file' => __FILE__, 'line' => __LINE__));
     }
     if ($methods) {
         $test_methods = array_intersect($test_methods, $methods);
     }
     foreach ($test_methods as $method) {
         // Insert a fail record. This will be deleted on completion to ensure
         // that testing completed.
         $method_info = new \ReflectionMethod($class, $method);
         $caller = array('file' => $method_info->getFileName(), 'line' => $method_info->getStartLine(), 'function' => $class . '->' . $method . '()');
         $test_completion_check_id = TestBase::insertAssert($this->testId, $class, FALSE, 'The test did not complete due to a fatal error.', 'Completion check', $caller);
         try {
             $this->prepareEnvironment();
         } catch (\Exception $e) {
             $this->exceptionHandler($e);
             // The prepareEnvironment() method isolates the test from the parent
             // Drupal site by creating a random database prefix and test site
             // directory. If this fails, a test would possibly operate in the
             // parent site. Therefore, the entire test run for this test class
             // has to be aborted.
             // restoreEnvironment() cannot be called, because we do not know
             // where exactly the environment setup failed.
             break;
         }
         try {
             $this->setUp();
         } catch (\Exception $e) {
             $this->exceptionHandler($e);
             // Abort if setUp() fails, since all test methods will fail.
             // But ensure to clean up and restore the environment, since
             // prepareEnvironment() succeeded.
             $this->restoreEnvironment();
             break;
         }
         try {
             $this->{$method}();
         } catch (\Exception $e) {
             $this->exceptionHandler($e);
         }
         try {
             $this->tearDown();
         } catch (\Exception $e) {
             $this->exceptionHandler($e);
             // If a test fails to tear down, abort the entire test class, since
             // it is likely that all tests will fail in the same way and a
             // failure here only results in additional test artifacts that have
             // to be manually deleted.
             $this->restoreEnvironment();
             break;
         }
         $this->restoreEnvironment();
         // Remove the test method completion check record.
         TestBase::deleteAssert($test_completion_check_id);
     }
     TestServiceProvider::$currentTest = NULL;
     // Clear out the error messages and restore error handler.
     drupal_get_messages();
     restore_error_handler();
 }
Example #22
0
 /**
  * {@inheritdoc}
  *
  * @param string $theme
  *   The theme name.
  */
 public function buildForm(array $form, FormStateInterface $form_state, $theme = '')
 {
     $form = parent::buildForm($form, $form_state);
     $themes = $this->themeHandler->listInfo();
     // Default settings are defined in theme_get_setting() in includes/theme.inc
     if ($theme) {
         if (!$this->themeHandler->hasUi($theme)) {
             throw new NotFoundHttpException();
         }
         $var = 'theme_' . $theme . '_settings';
         $config_key = $theme . '.settings';
         $themes = $this->themeHandler->listInfo();
         $features = $themes[$theme]->info['features'];
     } else {
         $var = 'theme_settings';
         $config_key = 'system.theme.global';
     }
     // @todo this is pretty meaningless since we're using theme_get_settings
     //   which means overrides can bleed into active config here. Will be fixed
     //   by https://www.drupal.org/node/2402467.
     $this->editableConfig = [$config_key];
     $form['var'] = array('#type' => 'hidden', '#value' => $var);
     $form['config_key'] = array('#type' => 'hidden', '#value' => $config_key);
     // Toggle settings
     $toggles = array('node_user_picture' => t('User pictures in posts'), 'comment_user_picture' => t('User pictures in comments'), 'comment_user_verification' => t('User verification status in comments'), 'favicon' => t('Shortcut icon'));
     // Some features are not always available
     $disabled = array();
     if (!user_picture_enabled()) {
         $disabled['toggle_node_user_picture'] = TRUE;
         $disabled['toggle_comment_user_picture'] = TRUE;
     }
     if (!$this->moduleHandler->moduleExists('comment')) {
         $disabled['toggle_comment_user_picture'] = TRUE;
         $disabled['toggle_comment_user_verification'] = TRUE;
     }
     $form['theme_settings'] = array('#type' => 'details', '#title' => t('Toggle display'), '#open' => TRUE, '#description' => t('Enable or disable the display of certain page elements.'));
     foreach ($toggles as $name => $title) {
         if (!$theme || in_array($name, $features)) {
             $form['theme_settings']['toggle_' . $name] = array('#type' => 'checkbox', '#title' => $title, '#default_value' => theme_get_setting('features.' . $name, $theme));
             // Disable checkboxes for features not supported in the current configuration.
             if (isset($disabled['toggle_' . $name])) {
                 $form['theme_settings']['toggle_' . $name]['#disabled'] = TRUE;
             }
         }
     }
     if (!Element::children($form['theme_settings'])) {
         // If there is no element in the theme settings details then do not show
         // it -- but keep it in the form if another module wants to alter.
         $form['theme_settings']['#access'] = FALSE;
     }
     // Logo settings, only available when file.module is enabled.
     if (!$theme || in_array('logo', $features) && $this->moduleHandler->moduleExists('file')) {
         $form['logo'] = array('#type' => 'details', '#title' => t('Logo image settings'), '#open' => TRUE, '#states' => array('invisible' => array('input[name="toggle_logo"]' => array('checked' => FALSE))));
         $form['logo']['default_logo'] = array('#type' => 'checkbox', '#title' => t('Use the default logo supplied by the theme'), '#default_value' => theme_get_setting('logo.use_default', $theme), '#tree' => FALSE);
         $form['logo']['settings'] = array('#type' => 'container', '#states' => array('invisible' => array('input[name="default_logo"]' => array('checked' => TRUE))));
         $form['logo']['settings']['logo_path'] = array('#type' => 'textfield', '#title' => t('Path to custom logo'), '#default_value' => theme_get_setting('logo.path', $theme));
         $form['logo']['settings']['logo_upload'] = array('#type' => 'file', '#title' => t('Upload logo image'), '#maxlength' => 40, '#description' => t("If you don't have direct file access to the server, use this field to upload your logo."));
     }
     if ((!$theme || in_array('favicon', $features)) && $this->moduleHandler->moduleExists('file')) {
         $form['favicon'] = array('#type' => 'details', '#title' => t('Shortcut icon settings'), '#open' => TRUE, '#description' => t("Your shortcut icon, or 'favicon', is displayed in the address bar and bookmarks of most browsers."), '#states' => array('invisible' => array('input[name="toggle_favicon"]' => array('checked' => FALSE))));
         $form['favicon']['default_favicon'] = array('#type' => 'checkbox', '#title' => t('Use the default shortcut icon supplied by the theme'), '#default_value' => theme_get_setting('favicon.use_default', $theme));
         $form['favicon']['settings'] = array('#type' => 'container', '#states' => array('invisible' => array('input[name="default_favicon"]' => array('checked' => TRUE))));
         $form['favicon']['settings']['favicon_path'] = array('#type' => 'textfield', '#title' => t('Path to custom icon'), '#default_value' => theme_get_setting('favicon.path', $theme));
         $form['favicon']['settings']['favicon_upload'] = array('#type' => 'file', '#title' => t('Upload icon image'), '#description' => t("If you don't have direct file access to the server, use this field to upload your shortcut icon."));
     }
     // Inject human-friendly values and form element descriptions for logo and
     // favicon.
     foreach (array('logo' => 'logo.svg', 'favicon' => 'favicon.ico') as $type => $default) {
         if (isset($form[$type]['settings'][$type . '_path'])) {
             $element =& $form[$type]['settings'][$type . '_path'];
             // If path is a public:// URI, display the path relative to the files
             // directory; stream wrappers are not end-user friendly.
             $original_path = $element['#default_value'];
             $friendly_path = NULL;
             if (file_uri_scheme($original_path) == 'public') {
                 $friendly_path = file_uri_target($original_path);
                 $element['#default_value'] = $friendly_path;
             }
             // Prepare local file path for description.
             if ($original_path && isset($friendly_path)) {
                 $local_file = strtr($original_path, array('public:/' => PublicStream::basePath()));
             } elseif ($theme) {
                 $local_file = drupal_get_path('theme', $theme) . '/' . $default;
             } else {
                 $local_file = \Drupal::theme()->getActiveTheme()->getPath() . '/' . $default;
             }
             $element['#description'] = t('Examples: <code>@implicit-public-file</code> (for a file in the public filesystem), <code>@explicit-file</code>, or <code>@local-file</code>.', array('@implicit-public-file' => isset($friendly_path) ? $friendly_path : $default, '@explicit-file' => file_uri_scheme($original_path) !== FALSE ? $original_path : 'public://' . $default, '@local-file' => $local_file));
         }
     }
     if ($theme) {
         // Call engine-specific settings.
         $function = $themes[$theme]->prefix . '_engine_settings';
         if (function_exists($function)) {
             $form['engine_specific'] = array('#type' => 'details', '#title' => t('Theme-engine-specific settings'), '#open' => TRUE, '#description' => t('These settings only exist for the themes based on the %engine theme engine.', array('%engine' => $themes[$theme]->prefix)));
             $function($form, $form_state);
         }
         // Create a list which includes the current theme and all its base themes.
         if (isset($themes[$theme]->base_themes)) {
             $theme_keys = array_keys($themes[$theme]->base_themes);
             $theme_keys[] = $theme;
         } else {
             $theme_keys = array($theme);
         }
         // Save the name of the current theme (if any), so that we can temporarily
         // override the current theme and allow theme_get_setting() to work
         // without having to pass the theme name to it.
         $default_active_theme = \Drupal::theme()->getActiveTheme();
         $default_theme = $default_active_theme->getName();
         /** @var \Drupal\Core\Theme\ThemeInitialization $theme_initialization */
         $theme_initialization = \Drupal::service('theme.initialization');
         \Drupal::theme()->setActiveTheme($theme_initialization->getActiveThemeByName($theme));
         // Process the theme and all its base themes.
         foreach ($theme_keys as $theme) {
             // Include the theme-settings.php file.
             $filename = DRUPAL_ROOT . '/' . $themes[$theme]->getPath() . '/theme-settings.php';
             if (file_exists($filename)) {
                 require_once $filename;
             }
             // Call theme-specific settings.
             $function = $theme . '_form_system_theme_settings_alter';
             if (function_exists($function)) {
                 $function($form, $form_state);
             }
         }
         // Restore the original current theme.
         if (isset($default_theme)) {
             \Drupal::theme()->setActiveTheme($default_active_theme);
         } else {
             \Drupal::theme()->resetActiveTheme();
         }
     }
     return $form;
 }
Example #23
0
 /**
  * Test the theme settings form.
  */
 function testThemeSettings()
 {
     // Ensure invalid theme settings form URLs return a proper 404.
     $this->drupalGet('admin/appearance/settings/bartik');
     $this->assertResponse(404, 'The theme settings form URL for a uninstalled theme could not be found.');
     $this->drupalGet('admin/appearance/settings/' . $this->randomMachineName());
     $this->assertResponse(404, 'The theme settings form URL for a non-existent theme could not be found.');
     $this->assertTrue(\Drupal::service('theme_installer')->install(['stable']));
     $this->drupalGet('admin/appearance/settings/stable');
     $this->assertResponse(404, 'The theme settings form URL for a hidden theme is unavailable.');
     // Specify a filesystem path to be used for the logo.
     $file = current($this->drupalGetTestFiles('image'));
     $file_relative = strtr($file->uri, array('public:/' => PublicStream::basePath()));
     $default_theme_path = 'core/themes/classy';
     $supported_paths = array($file->uri => array('form' => file_uri_target($file->uri), 'src' => file_url_transform_relative(file_create_url($file->uri))), file_uri_target($file->uri) => array('form' => file_uri_target($file->uri), 'src' => file_url_transform_relative(file_create_url($file->uri))), $file_relative => array('form' => $file_relative, 'src' => file_url_transform_relative(file_create_url($file->uri))), 'core/misc/druplicon.png' => array('form' => 'core/misc/druplicon.png', 'src' => base_path() . 'core/misc/druplicon.png'), $default_theme_path . '/logo.svg' => array('form' => $default_theme_path . '/logo.svg', 'src' => base_path() . $default_theme_path . '/logo.svg'));
     foreach ($supported_paths as $input => $expected) {
         $edit = array('default_logo' => FALSE, 'logo_path' => $input);
         $this->drupalPostForm('admin/appearance/settings', $edit, t('Save configuration'));
         $this->assertNoText('The custom logo path is invalid.');
         $this->assertFieldByName('logo_path', $expected['form']);
         // Verify logo path examples.
         $elements = $this->xpath('//div[contains(@class, :item)]/div[@class=:description]/code', array(':item' => 'js-form-item-logo-path', ':description' => 'description'));
         // Expected default values (if all else fails).
         $implicit_public_file = 'logo.svg';
         $explicit_file = 'public://logo.svg';
         $local_file = $default_theme_path . '/logo.svg';
         // Adjust for fully qualified stream wrapper URI in public filesystem.
         if (file_uri_scheme($input) == 'public') {
             $implicit_public_file = file_uri_target($input);
             $explicit_file = $input;
             $local_file = strtr($input, array('public:/' => PublicStream::basePath()));
         } elseif (file_uri_scheme($input) !== FALSE) {
             $explicit_file = $input;
         } elseif ($input == file_uri_target($file->uri)) {
             $implicit_public_file = $input;
             $explicit_file = 'public://' . $input;
             $local_file = PublicStream::basePath() . '/' . $input;
         }
         $this->assertEqual((string) $elements[0], $implicit_public_file);
         $this->assertEqual((string) $elements[1], $explicit_file);
         $this->assertEqual((string) $elements[2], $local_file);
         // Verify the actual 'src' attribute of the logo being output in a site
         // branding block.
         $this->drupalPlaceBlock('system_branding_block', ['region' => 'header']);
         $this->drupalGet('');
         $elements = $this->xpath('//header//a[@rel=:rel]/img', array(':rel' => 'home'));
         $this->assertEqual((string) $elements[0]['src'], $expected['src']);
     }
     $unsupported_paths = array('public://whatever.png', 'private://whatever.png', 'temporary://whatever.png', 'public:/whatever.png', '://whatever.png', ':whatever.png', 'public://', 'whatever.png', PublicStream::basePath() . '/whatever.png', '/' . PublicStream::basePath() . '/whatever.png', 'core/misc/whatever.png', '/core/misc/whatever.png', drupal_realpath($file->uri));
     $this->drupalGet('admin/appearance/settings');
     foreach ($unsupported_paths as $path) {
         $edit = array('default_logo' => FALSE, 'logo_path' => $path);
         $this->drupalPostForm(NULL, $edit, t('Save configuration'));
         $this->assertText('The custom logo path is invalid.');
     }
     // Upload a file to use for the logo.
     $edit = array('default_logo' => FALSE, 'logo_path' => '', 'files[logo_upload]' => drupal_realpath($file->uri));
     $this->drupalPostForm('admin/appearance/settings', $edit, t('Save configuration'));
     $fields = $this->xpath($this->constructFieldXpath('name', 'logo_path'));
     $uploaded_filename = 'public://' . $fields[0]['value'];
     $this->drupalPlaceBlock('system_branding_block', ['region' => 'header']);
     $this->drupalGet('');
     $elements = $this->xpath('//header//a[@rel=:rel]/img', array(':rel' => 'home'));
     $this->assertEqual($elements[0]['src'], file_url_transform_relative(file_create_url($uploaded_filename)));
     $this->container->get('theme_handler')->install(array('bartik'));
     // Ensure only valid themes are listed in the local tasks.
     $this->drupalPlaceBlock('local_tasks_block', ['region' => 'header']);
     $this->drupalGet('admin/appearance/settings');
     $theme_handler = \Drupal::service('theme_handler');
     $this->assertLink($theme_handler->getName('classy'));
     $this->assertLink($theme_handler->getName('bartik'));
     $this->assertNoLink($theme_handler->getName('stable'));
     // If a hidden theme is an admin theme it should be viewable.
     \Drupal::configFactory()->getEditable('system.theme')->set('admin', 'stable')->save();
     \Drupal::service('router.builder')->rebuildIfNeeded();
     $this->drupalPlaceBlock('local_tasks_block', ['region' => 'header', 'theme' => 'stable']);
     $this->drupalGet('admin/appearance/settings');
     $this->assertLink($theme_handler->getName('stable'));
     $this->drupalGet('admin/appearance/settings/stable');
     $this->assertResponse(200, 'The theme settings form URL for a hidden theme that is the admin theme is available.');
 }