class EntityLinksTest

Tests the behavior of generating entity URLs when using entity links in CKEditor.

Attributes

#[Group('filter')] #[CoversClass(EntityLinks::class)] #[RunTestsInSeparateProcesses]

Hierarchy

Expanded class hierarchy of EntityLinksTest

File

core/modules/filter/tests/src/Kernel/EntityLinksTest.php, line 33

Namespace

Drupal\Tests\filter\Kernel
View source
class EntityLinksTest extends KernelTestBase {
  use PathAliasTestTrait;
  
  /**
   * The entity_links filter.
   *
   * @var \Drupal\filter\Plugin\Filter\EntityLinks
   */
  protected EntityLinks $filter;
  
  /**
   * The test logger.
   *
   * @var \ColinODell\PsrTestLogger\TestLogger
   */
  protected TestLogger $logger;
  
  /**
   * {@inheritdoc}
   */
  protected static $modules = [
    'filter',
    'entity_test',
    'path',
    'path_alias',
    'language',
    'file',
    'user',
    // @see ::testMediaEntity
'system',
    'field',
    'image',
    'media',
    'media_test_source',
    // @see ::testMenuLinkContentEntity
'link',
    'menu_link_content',
    // @see ::testShortcutEntity
'shortcut',
  ];
  
  /**
   * {@inheritdoc}
   */
  protected function setUp() : void {
    parent::setUp();
    $this->installConfig('system');
    // @see ::test
    $this->installEntitySchema('entity_test');
    $this->installEntitySchema('entity_test_mul');
    $this->installEntitySchema('path_alias');
    // @see ::testFileEntity
    // @see ::testMediaEntity
    $this->installEntitySchema('file');
    // @see ::testMediaEntity
    $this->installEntitySchema('media');
    $this->installEntitySchema('media_type');
    $this->installEntitySchema('field_storage_config');
    $this->installEntitySchema('field_config');
    $this->installEntitySchema('user');
    $this->installSchema('file', [
      'file_usage',
    ]);
    $this->installConfig([
      'media',
    ]);
    // @see ::testMenuLinkContentEntity
    $this->installEntitySchema('menu_link_content');
    // @see ::testShortcutEntity
    $this->installEntitySchema('shortcut');
    $this->installConfig([
      'shortcut',
    ]);
    // Add Swedish, Danish and Finnish.
    ConfigurableLanguage::createFromLangcode('sv')->save();
    ConfigurableLanguage::createFromLangcode('da')->save();
    ConfigurableLanguage::createFromLangcode('fi')->save();
    /** @var \Drupal\Component\Plugin\PluginManagerInterface $manager */
    $manager = $this->container
      ->get('plugin.manager.filter');
    $bag = new FilterPluginCollection($manager, []);
    $this->filter = $bag->get('entity_links');
    // Add test logger to the 'filter' channel to assert no exceptions occurred.
    $this->logger = new TestLogger();
    $this->container
      ->get('logger.factory')
      ->get('filter')
      ->addLogger($this->logger);
  }
  
  /**
   * {@inheritdoc}
   */
  public function register(ContainerBuilder $container) : void {
    parent::register($container);
    // Undo what the parent did, to allow testing path aliases in kernel tests.
    $container->getDefinition('path_alias.path_processor')
      ->addTag('path_processor_inbound')
      ->addTag('path_processor_outbound');
  }
  
  /**
   * @legacy-covers ::process
   */
  public function test() : void {
    $expected_aliases = [
      'da' => '/foo-da',
      'en' => '/foo-en',
      'fi' => '/foo-fi',
      'sv' => '/foo-sv',
    ];
    $expected_hrefs = $expected_aliases + [
      LanguageInterface::LANGCODE_DEFAULT => '/foo-en',
      LanguageInterface::LANGCODE_NOT_APPLICABLE => '/foo-en',
      LanguageInterface::LANGCODE_NOT_SPECIFIED => '/foo-en',
      LanguageInterface::LANGCODE_SITE_DEFAULT => '/foo-en',
    ];
    // Create an entity and add translations to that.
    /** @var \Drupal\entity_test\Entity\EntityTestMul $entity */
    $entity = EntityTestMul::create([
      'name' => $this->randomMachineName(),
    ]);
    $entity->addTranslation('sv', [
      'name' => $this->randomMachineName(),
      'langcode' => 'sv',
    ]);
    $entity->addTranslation('da', [
      'name' => $this->randomMachineName(),
      'langcode' => 'da',
    ]);
    $entity->addTranslation('fi', [
      'name' => $this->randomMachineName(),
      'langcode' => 'fi',
    ]);
    $entity->save();
    // Assert the entity has a translation for every expected language.
    $this->assertSame(array_keys($expected_aliases), array_keys($entity->getTranslationLanguages()));
    // Create per-translation URL aliases.
    $canonical_url = $entity->toUrl()
      ->toString(TRUE)
      ->getGeneratedUrl();
    foreach ($expected_aliases as $langcode => $alias) {
      $this->createPathAlias($canonical_url, $alias, $langcode);
    }
    foreach ($expected_hrefs as $langcode => $expected_alias) {
      $expected_result = (new FilterProcessResult())->setProcessedText(sprintf('<a href="%s">Link text</a>', $expected_alias))
        ->setCacheTags([
        'entity_test_mul:1',
      ])
        ->setCacheContexts([])
        ->setCacheMaxAge(Cache::PERMANENT);
      // The expected href is generated.
      $this->assertFilterProcessResult(sprintf('<a data-entity-type="entity_test_mul" data-entity-uuid="%s">Link text</a>', $entity->uuid()), $langcode, $expected_result);
      // The existing href is overwritten with the expected value.
      $this->assertFilterProcessResult(sprintf('<a data-entity-type="entity_test_mul" data-entity-uuid="%s" href="something">Link text</a>', $entity->uuid()), $langcode, $expected_result);
      // The existing href is overwritten, but its customized query string and
      // fragment remain unchanged.
      $this->assertFilterProcessResult(sprintf('<a data-entity-type="entity_test_mul" data-entity-uuid="%s" href="something?query=string#fragment">Link text</a>', $entity->uuid()), $langcode, (new FilterProcessResult())->setProcessedText(sprintf('<a href="%s?query=string#fragment">Link text</a>', $expected_alias))
        ->setCacheTags([
        'entity_test_mul:1',
      ])
        ->setCacheContexts([])
        ->setCacheMaxAge(Cache::PERMANENT));
    }
  }
  
  /**
   * @legacy-covers ::getUrl
   * @legacy-covers \Drupal\file\Entity\FileLinkTarget
   */
  public function testFileEntity() : void {
    $file = File::create([
      'uid' => 1,
      'filename' => 'druplicon.txt',
      'uri' => 'public://druplicon.txt',
      'filemime' => 'text/plain',
      'status' => FileInterface::STATUS_PERMANENT,
    ]);
    $file->save();
    $this->assertFilterProcessResult(sprintf('<a data-entity-type="file" data-entity-uuid="%s" href="something?query=string#fragment">Link text</a>', $file->uuid()), 'en', (new FilterProcessResult())->setProcessedText(sprintf('<a href="%s?query=string#fragment">Link text</a>', $file->createFileUrl(TRUE)))
      ->setCacheTags([
      'file:1',
    ])
      ->setCacheContexts([])
      ->setCacheMaxAge(Cache::PERMANENT));
  }
  
  /**
   * @legacy-covers ::getUrl
   * @legacy-covers \Drupal\media\Entity\MediaLinkTarget
   *
   * @param bool $standalone_url_setting
   *   Whether the standalone_url setting is off (Drupal's default) or on.
   * @param string $media_source
   *   Which media source to use.
   * @param array $media_entity_values
   *   Which values to assign to the media entity.
   * @param string $expected_url
   *   The expected URL.
   * @param string[] $expected_cache_tags
   *   The expected cache tags.
   */
  public function testMediaEntity(bool $standalone_url_setting, string $media_source, array $media_entity_values, string $expected_url, array $expected_cache_tags) : void {
    \Drupal::configFactory()->getEditable('media.settings')
      ->set('standalone_url', $standalone_url_setting)
      ->save();
    // Create media type using the given source plugin.
    $media_type = MediaType::create([
      'label' => 'test',
      'id' => 'test',
      'description' => 'Test type.',
      'source' => $media_source,
    ]);
    $media_type->save();
    $source_field = $media_type->getSource()
      ->createSourceField($media_type);
    $source_field->getFieldStorageDefinition()
      ->save();
    $source_field->save();
    $media_type->set('source_configuration', [
      'source_field' => $source_field->getName(),
    ])
      ->save();
    // @see \Drupal\media\Plugin\media\Source\File
    if ($media_source === 'file') {
      $file = File::create([
        'uid' => 1,
        'filename' => 'druplicon.txt',
        'uri' => 'public://druplicon.txt',
        'filemime' => 'text/plain',
        'status' => FileInterface::STATUS_PERMANENT,
      ]);
      $file->save();
    }
    $media = Media::create([
      'bundle' => 'test',
      $source_field->getName() => $media_entity_values,
    ]);
    $media->save();
    $expected_url = str_replace('<SITE_DIRECTORY>', $this->siteDirectory, $expected_url);
    $this->assertFilterProcessResult(sprintf('<a data-entity-type="media" data-entity-uuid="%s" href="something?query=string#fragment">Link text</a>', $media->uuid()), 'en', (new FilterProcessResult())->setProcessedText(sprintf('<a href="%s?query=string#fragment">Link text</a>', $expected_url))
      ->setCacheTags($expected_cache_tags)
      ->setCacheContexts([])
      ->setCacheMaxAge(Cache::PERMANENT));
  }
  
  /**
   * Data provider for testMediaEntity.
   */
  public static function providerTestMediaEntity() : array {
    return [
      [
        TRUE,
        'file',
        [
          'target_id' => 1,
        ],
        '/media/1',
        [
          'media:1',
        ],
      ],
      [
        FALSE,
        'file',
        [
          'target_id' => 1,
        ],
        '/<SITE_DIRECTORY>/files/druplicon.txt',
        [
          'file:1',
          'media:1',
        ],
      ],
      [
        TRUE,
        'oembed:video',
        [
          'value' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
        ],
        '/media/1',
        [
          'media:1',
        ],
      ],
      [
        FALSE,
        'oembed:video',
        [
          'value' => 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
        ],
        'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
        [
          'media:1',
        ],
      ],
      [
        TRUE,
        'test',
        [
          'value' => 'foobar',
        ],
        '/media/1',
        [
          'media:1',
        ],
      ],
      [
        FALSE,
        'test',
        [
          'value' => 'foobar',
        ],
        '',
        [
          'media:1',
        ],
      ],
    ];
  }
  
  /**
   * @legacy-covers ::getUrl
   * @legacy-covers \Drupal\menu_link_content\Entity\MenuLinkContentLinkTarget
   */
  public function testMenuLinkContentEntity() : void {
    $link = 'https://nl.wikipedia.org/wiki/Llama';
    $menu_link_content = MenuLinkContent::create([
      'id' => 'llama',
      'title' => 'Llama Gabilondo',
      'description' => 'Llama Gabilondo',
      'link' => $link,
      'weight' => 0,
      'menu_name' => 'main',
    ]);
    $menu_link_content->save();
    $this->assertFilterProcessResult(sprintf('<a data-entity-type="menu_link_content" data-entity-uuid="%s" href="something?query=string#fragment">Link text</a>', $menu_link_content->uuid()), 'en', (new FilterProcessResult())->setProcessedText(sprintf('<a href="%s?query=string#fragment">Link text</a>', $link))
      ->setCacheTags([
      'menu_link_content:1',
    ])
      ->setCacheContexts([])
      ->setCacheMaxAge(Cache::PERMANENT));
  }
  
  /**
   * @legacy-covers ::getUrl
   * @legacy-covers \Drupal\shortcut\Entity\ShortcutLinkTarget
   */
  public function testShortcutEntity() : void {
    // cspell:disable-next-line
    $path = '/user/logout?token=fzL0Ox4jS6qafdt6gzGzjWGb_hsR6kJ8L8E0D4hC5Mo';
    $shortcut = Shortcut::create([
      'shortcut_set' => 'default',
      'title' => 'Comments',
      'weight' => -20,
      'link' => [
        'uri' => "internal:{$path}",
      ],
    ]);
    $shortcut->save();
    $this->assertFilterProcessResult(sprintf('<a data-entity-type="shortcut" data-entity-uuid="%s" href="something?query=string#fragment">Link text</a>', $shortcut->uuid()), 'en', (new FilterProcessResult())->setProcessedText(sprintf('<a href="%s?query=string#fragment">Link text</a>', $path))
      ->setCacheTags([
      'config:shortcut.set.default',
    ])
      ->setCacheContexts([])
      ->setCacheMaxAge(Cache::PERMANENT));
  }
  
  /**
   * Asserts an input string + langcode yield the expected FilterProcessResult.
   *
   * @param string $input
   *   The text string to be filtered.
   * @param string $langcode
   *   The language code of the text to be filtered.
   * @param \Drupal\filter\FilterProcessResult $expected_result
   *   The expected filtered result.
   */
  private function assertFilterProcessResult(string $input, string $langcode, FilterProcessResult $expected_result) : void {
    $result = $this->filter
      ->process($input, $langcode);
    // No exceptions should have occurred.
    $this->assertSame([], $this->logger->records);
    // Assert both the processed text and the associated cacheability.
    $this->assertSame($expected_result->getProcessedText(), $result->getProcessedText());
    $this->assertEquals(CacheableMetadata::createFromObject($expected_result), CacheableMetadata::createFromObject($result));
  }

}

Members

Title Sort descending Deprecated Modifiers Object type Summary Overriden Title Overrides
AssertContentTrait::$content protected property The current raw content.
AssertContentTrait::$drupalSettings protected property The drupalSettings value from the current raw $content.
AssertContentTrait::$elements protected property The XML structure parsed from the current raw $content. 1
AssertContentTrait::$plainTextContent protected property The plain-text content of raw $content (text nodes).
AssertContentTrait::assertEscaped protected function Passes if the raw text IS found escaped on the loaded page, fail otherwise.
AssertContentTrait::assertField protected function Asserts that a field exists with the given name or ID.
AssertContentTrait::assertFieldById Deprecated protected function Asserts that a field exists with the given ID and value.
AssertContentTrait::assertFieldByName protected function Asserts that a field exists with the given name and value.
AssertContentTrait::assertFieldByXPath protected function Asserts that a field exists in the current page by the given XPath.
AssertContentTrait::assertFieldChecked Deprecated protected function Asserts that a checkbox field in the current page is checked.
AssertContentTrait::assertFieldsByValue protected function Asserts that a field exists in the current page with a given Xpath result.
AssertContentTrait::assertLink protected function Passes if a link with the specified label is found.
AssertContentTrait::assertLinkByHref protected function Passes if a link containing a given href (part) is found.
AssertContentTrait::assertNoDuplicateIds Deprecated protected function Asserts that each HTML ID is used for just a single element.
AssertContentTrait::assertNoEscaped protected function Passes if raw text IS NOT found escaped on loaded page, fail otherwise.
AssertContentTrait::assertNoField Deprecated protected function Asserts that a field does not exist with the given name or ID.
AssertContentTrait::assertNoFieldById Deprecated protected function Asserts that a field does not exist with the given ID and value.
AssertContentTrait::assertNoFieldByName Deprecated protected function Asserts that a field does not exist with the given name and value.
AssertContentTrait::assertNoFieldByXPath Deprecated protected function Asserts that a field does not exist or its value does not match, by XPath.
AssertContentTrait::assertNoFieldChecked Deprecated protected function Asserts that a checkbox field in the current page is not checked.
AssertContentTrait::assertNoLink protected function Passes if a link with the specified label is not found.
AssertContentTrait::assertNoLinkByHref Deprecated protected function Passes if a link containing a given href (part) is not found.
AssertContentTrait::assertNoLinkByHrefInMainRegion Deprecated protected function Passes if a link containing a given href is not found in the main region.
AssertContentTrait::assertNoOption Deprecated protected function Asserts that a select option in the current page does not exist.
AssertContentTrait::assertNoOptionSelected Deprecated protected function Asserts that a select option in the current page is not checked.
AssertContentTrait::assertNoPattern protected function Triggers a pass if the perl regex pattern is not found in raw content.
AssertContentTrait::assertNoRaw protected function Passes if the raw text is NOT found on the loaded page, fail otherwise.
AssertContentTrait::assertNoText protected function Passes if the page (with HTML stripped) does not contains the text.
AssertContentTrait::assertNoTitle protected function Pass if the page title is not the given string.
AssertContentTrait::assertNoUniqueText Deprecated protected function Passes if the text is found MORE THAN ONCE on the text version of the page.
AssertContentTrait::assertOption protected function Asserts that a select option in the current page exists.
AssertContentTrait::assertOptionByText Deprecated protected function Asserts that a select option with the visible text exists.
AssertContentTrait::assertOptionSelected Deprecated protected function Asserts that a select option in the current page is checked.
AssertContentTrait::assertOptionSelectedWithDrupalSelector Deprecated protected function Asserts that a select option in the current page is checked.
AssertContentTrait::assertOptionWithDrupalSelector protected function Asserts that a select option in the current page exists.
AssertContentTrait::assertPattern protected function Triggers a pass if the Perl regex pattern is found in the raw content.
AssertContentTrait::assertRaw protected function Passes if the raw text IS found on the loaded page, fail otherwise.
AssertContentTrait::assertText protected function Passes if the page (with HTML stripped) contains the text.
AssertContentTrait::assertTextHelper protected function Helper for assertText and assertNoText.
AssertContentTrait::assertTextPattern Deprecated protected function Asserts that a Perl regex pattern is found in the plain-text content.
AssertContentTrait::assertThemeOutput protected function Asserts themed output.
AssertContentTrait::assertTitle protected function Pass if the page title is the given string.
AssertContentTrait::assertUniqueText Deprecated protected function Passes if the text is found ONLY ONCE on the text version of the page.
AssertContentTrait::assertUniqueTextHelper Deprecated protected function Helper for assertUniqueText and assertNoUniqueText.
AssertContentTrait::buildXPathQuery protected function Builds an XPath query.
AssertContentTrait::constructFieldXpath protected function Helper: Constructs an XPath for the given set of attributes and value.
AssertContentTrait::cssSelect protected function Searches elements using a CSS selector in the raw content.
AssertContentTrait::getAllOptions protected function Get all option elements, including nested options, in a select.
AssertContentTrait::getDrupalSettings protected function Gets the value of drupalSettings for the currently-loaded page.
AssertContentTrait::getRawContent protected function Gets the current raw content.
AssertContentTrait::getSelectedItem protected function Get the selected value from a select field.
AssertContentTrait::getTextContent protected function Retrieves the plain-text content from the current raw content.
AssertContentTrait::parse protected function Parse content returned from curlExec using DOM and SimpleXML.
AssertContentTrait::removeWhiteSpace protected function Removes all white-space between HTML tags from the raw content.
AssertContentTrait::setDrupalSettings protected function Sets the value of drupalSettings for the currently-loaded page.
AssertContentTrait::setRawContent protected function Sets the raw content (e.g. HTML).
AssertContentTrait::xpath protected function Performs an xpath search on the contents of the internal browser.
ConfigTestTrait::configImporter protected function Returns a ConfigImporter object to import test configuration.
ConfigTestTrait::copyConfig protected function Copies configuration objects from source storage to target storage.
EntityLinksTest::$filter protected property The entity_links filter.
EntityLinksTest::$logger protected property The test logger.
EntityLinksTest::$modules protected static property Modules to install. Overrides KernelTestBase::$modules
EntityLinksTest::assertFilterProcessResult private function Asserts an input string + langcode yield the expected FilterProcessResult.
EntityLinksTest::providerTestMediaEntity public static function Data provider for testMediaEntity.
EntityLinksTest::register public function Registers test-specific services. Overrides KernelTestBase::register
EntityLinksTest::setUp protected function Overrides KernelTestBase::setUp
EntityLinksTest::test public function @legacy-covers ::process
EntityLinksTest::testFileEntity public function @legacy-covers ::getUrl
@legacy-covers \Drupal\file\Entity\FileLinkTarget
EntityLinksTest::testMediaEntity public function @legacy-covers ::getUrl
@legacy-covers \Drupal\media\Entity\MediaLinkTarget
EntityLinksTest::testMenuLinkContentEntity public function @legacy-covers ::getUrl
@legacy-covers \Drupal\menu_link_content\Entity\MenuLinkContentLinkTarget
EntityLinksTest::testShortcutEntity public function @legacy-covers ::getUrl
@legacy-covers \Drupal\shortcut\Entity\ShortcutLinkTarget
ExpectDeprecationTrait::expectDeprecation public function Adds an expected deprecation.
ExpectDeprecationTrait::setUpErrorHandler public function Sets up the test error handler.
ExpectDeprecationTrait::tearDownErrorHandler public function Tears down the test error handler.
ExtensionListTestTrait::getModulePath protected function Gets the path for the specified module.
ExtensionListTestTrait::getThemePath protected function Gets the path for the specified theme.
KernelTestBase::$classLoader protected property The class loader.
KernelTestBase::$configImporter protected property The configuration importer. 6
KernelTestBase::$configSchemaCheckerExclusions protected static property An array of config object names that are excluded from schema checking. 4
KernelTestBase::$container protected property The test container.
KernelTestBase::$databasePrefix protected property The test database prefix.
KernelTestBase::$keyValue protected property The key_value service that must persist between container rebuilds.
KernelTestBase::$root protected property The app root.
KernelTestBase::$siteDirectory protected property The relative path to the test site directory.
KernelTestBase::$strictConfigSchema protected property Set to TRUE to strict check all configuration saved. 10
KernelTestBase::$usesSuperUserAccessPolicy protected property Set to TRUE to make user 1 a super user. 1
KernelTestBase::$vfsRoot protected property The virtual filesystem root directory.
KernelTestBase::assertPostConditions protected function 1
KernelTestBase::bootEnvironment protected function Bootstraps a basic test environment.
KernelTestBase::bootKernel protected function Bootstraps a kernel for a test. 1
KernelTestBase::config protected function Configuration accessor for tests. Returns non-overridden configuration.
KernelTestBase::disableModules protected function Disables modules for this test.
KernelTestBase::enableModules protected function Enables modules for this test. 2
KernelTestBase::getConfigSchemaExclusions protected function Gets the config schema exclusions for this test.
KernelTestBase::getDatabaseConnectionInfo protected function Returns the Database connection info to be used for this test. 3
KernelTestBase::getDatabasePrefix public function Gets the database prefix used for test isolation.
KernelTestBase::getExtensionsForModules private function Returns Extension objects for $modules to install.
KernelTestBase::getModulesToEnable protected static function Returns the modules to install for this test.
KernelTestBase::initFileCache protected function Initializes the FileCache component.
KernelTestBase::installConfig protected function Installs default configuration for a given list of modules.
KernelTestBase::installEntitySchema protected function Installs the storage schema for a specific entity type.
KernelTestBase::installSchema protected function Installs database tables from a module schema definition.
KernelTestBase::render protected function Renders a render array. 1
KernelTestBase::setDebugDumpHandler public static function Registers the dumper CLI handler when the DebugDump extension is enabled.
KernelTestBase::setInstallProfile protected function Sets the install profile and rebuilds the container to update it.
KernelTestBase::setSetting protected function Sets an in-memory Settings variable.
KernelTestBase::setUpFilesystem protected function Sets up the filesystem, so things like the file directory. 3
KernelTestBase::tearDown protected function 9
KernelTestBase::tearDownCloseDatabaseConnection public function Additional tear down method to close the connection at the end.
KernelTestBase::vfsDump protected function Dumps the current state of the virtual filesystem to STDOUT.
KernelTestBase::__construct public function
KernelTestBase::__sleep public function Prevents serializing any properties.
PathAliasTestTrait::assertPathAliasExists protected function Asserts that a path alias exists in the storage.
PathAliasTestTrait::assertPathAliasNotExists protected function Asserts that a path alias does not exist in the storage.
PathAliasTestTrait::createPathAlias protected function Creates a new path alias.
PathAliasTestTrait::loadPathAliasByConditions protected function Gets the first result from a &#039;load by properties&#039; storage call.
RandomGeneratorTrait::getRandomGenerator protected function Gets the random generator for the utility methods.
RandomGeneratorTrait::randomMachineName protected function Generates a unique random string containing letters and numbers.
RandomGeneratorTrait::randomObject public function Generates a random PHP object.
RandomGeneratorTrait::randomString public function Generates a pseudo-random string of ASCII characters of codes 32 to 126.
StorageCopyTrait::replaceStorageContents protected static function Copy the configuration from one storage to another and remove stale items.
TestRequirementsTrait::getDrupalRoot protected static function Returns the Drupal root directory.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.