From 86128332829d6fc36e506e10589ee12e97b25fd3 Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Sat, 11 Nov 2023 16:16:24 -0500 Subject: [PATCH 01/11] Drastically simplify using Composer Runtime API --- .gitignore | 1 + composer.json | 34 +++- src/DrupalFinder.php | 267 +------------------------ tests/Drupal7FinderTest.php | 169 ---------------- tests/Drupal8FinderTest.php | 343 --------------------------------- tests/DrupalFinderTest.php | 15 ++ tests/DrupalFinderTestBase.php | 184 ------------------ 7 files changed, 49 insertions(+), 964 deletions(-) delete mode 100644 tests/Drupal7FinderTest.php delete mode 100644 tests/Drupal8FinderTest.php create mode 100644 tests/DrupalFinderTest.php delete mode 100644 tests/DrupalFinderTestBase.php diff --git a/.gitignore b/.gitignore index 8f7045c..3b5b6d9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /composer.lock /vendor/ /.phpunit.result.cache +/web diff --git a/composer.json b/composer.json index 703c2a8..4920316 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "webflo/drupal-finder", - "description": "Helper class to locate a Drupal installation from a given path.", + "description": "Helper class to locate a Drupal installation.", "license": "GPL-2.0-or-later", "type": "library", "authors": [ @@ -10,20 +10,34 @@ } ], "require": { - "ext-json": "*" - }, - "autoload": { - "classmap": [ - "src/DrupalFinder.php" - ] + "composer-runtime-api": "^2.2" }, "autoload-dev": { "psr-4": { - "DrupalFinder\\Tests\\": "tests/" + "DrupalFinder\\Tests\\": "tests/", + "DrupalFinder\\": "src/" } }, "require-dev": { - "phpunit/phpunit": "^8.5.14", - "mikey179/vfsstream": "^1.6" + "composer/installers": "^2", + "drupal/core-recommended": "^10", + "phpunit/phpunit": "^9" + }, + "config": { + "allow-plugins": { + "composer/installers": true + }, + "optimize-autoloader": true, + "preferred-install": "dist", + "sort-packages": true, + "process-timeout": 9600, + "platform": { + "php": "8.1" + } + }, + "extra": { + "installer-paths": { + "web/core": ["type:drupal-core"] + } } } diff --git a/src/DrupalFinder.php b/src/DrupalFinder.php index ffbcecd..4ad8065 100644 --- a/src/DrupalFinder.php +++ b/src/DrupalFinder.php @@ -7,92 +7,10 @@ namespace DrupalFinder; +use Composer\InstalledVersions; + class DrupalFinder { - /** - * Drupal root environment variable. - */ - const ENV_DRUPAL_ROOT = 'DRUPAL_FINDER_DRUPAL_ROOT'; - - /** - * Composer root environment variable. - */ - const ENV_COMPOSER_ROOT = 'DRUPAL_FINDER_COMPOSER_ROOT'; - - /** - * Vendor directory environment variable. - */ - const ENV_VENDOR_DIR = 'DRUPAL_FINDER_VENDOR_DIR'; - - /** - * Drupal web public directory. - * - * @var string - */ - private $drupalRoot; - - /** - * Drupal package composer directory. - * - * @var bool - */ - private $composerRoot; - - /** - * Composer vendor directory. - * - * @var string - * - * @see https://getcomposer.org/doc/06-config.md#vendor-dir - */ - private $vendorDir; - - /** - * Initialize finder. - * - * Optionally pass the starting path. - * - * @param string|null $start_path - * The path to begin the search from. - * - * @throws \Exception - * @todo Make $start_path mandatory in v2. - */ - public function __construct($start_path = null) { - // Initialize path variables to false, indicating their locations are - // not yet known. - $this->drupalRoot = false; - $this->composerRoot = false; - $this->vendorDir = false; - - // If a starting path was provided, attempt to locate and set path - // variables. - if (!empty($start_path)) { - $this->discoverRoots($start_path); - } - } - - /** - * Locate Drupal, Composer, and vendor directory paths. - * - * @param string $start_path - * The path to begin the search from. - * - * @return bool - * True if the Drupal root was identified, false otherwise. - * - * @throws \Exception - * - * @deprecated Will be removed in v2. Future usage should instantiate - * a new DrupalFinder object by passing the starting path to its - * constructor. - */ - public function locateRoot($start_path) - { - $this->discoverRoots($start_path); - return !empty($this->getDrupalRoot()); - } - /** * Get the Drupal root. * @@ -101,9 +19,8 @@ public function locateRoot($start_path) */ public function getDrupalRoot() { - $environment_path = $this->getValidEnvironmentVariablePath(self::ENV_DRUPAL_ROOT); - - return !empty($environment_path) ? $environment_path : $this->drupalRoot; + $core = InstalledVersions::getInstallPath('drupal/core'); + return $core ? realpath(dirname($core)) : false; } /** @@ -114,8 +31,7 @@ public function getDrupalRoot() */ public function getComposerRoot() { - $environment_path = $this->getValidEnvironmentVariablePath(self::ENV_COMPOSER_ROOT); - return !empty($environment_path) ? $environment_path : $this->composerRoot; + return realpath(dirname($this->getVendorDir())); } /** @@ -126,175 +42,10 @@ public function getComposerRoot() */ public function getVendorDir() { - $environment_path = $this->getValidEnvironmentVariablePath(self::ENV_VENDOR_DIR); - return !empty($environment_path) ? $environment_path : $this->vendorDir; - } - - /** - * Discover all valid paths. - * - * @param $start_path - * The path to start the search from. - * - * @throws \Exception - */ - protected function discoverRoots($start_path) { - // Since we are discovering, reset all path variables. - $this->drupalRoot = false; - $this->composerRoot = false; - $this->vendorDir = false; - - foreach (array(true, false) as $follow_symlinks) { - $path = $start_path; - if ($follow_symlinks && is_link($path)) { - $path = realpath($path); - } - - // Check the start path. - if ($this->findAndValidateRoots($path)) { - return; - } else { - // Move up dir by dir and check each. - while ($path = $this->shiftPathUp($path)) { - if ($follow_symlinks && is_link($path)) { - $path = realpath($path); - } - if ($this->findAndValidateRoots($path)) { - return; - } - } - } - } - } - - /** - * Determine if a valid Drupal root exists. - * - * In addition, set any valid path properties if they are found. - * - * @param $path - * The starting path to search from. - * - * @return bool - * True if all roots were discovered and validated. False otherwise. - */ - protected function findAndValidateRoots($path) - { - - if (!empty($path) && is_dir($path) && file_exists($path . '/autoload.php') && file_exists($path . '/' . $this->getComposerFileName())) { - // Additional check for the presence of core/composer.json to - // grant it is not a Drupal 7 site with a base folder named "core". - $candidate = 'core/includes/common.inc'; - if (file_exists($path . '/' . $candidate) && file_exists($path . '/core/core.services.yml')) { - if (file_exists($path . '/core/misc/drupal.js') || file_exists($path . '/core/assets/js/drupal.js')) { - $this->composerRoot = $path; - $this->drupalRoot = $path; - $this->vendorDir = $this->composerRoot . '/vendor'; - } - } - } - if (!empty($path) && is_dir($path) && file_exists($path . '/' . $this->getComposerFileName())) { - $json = json_decode( - file_get_contents($path . '/' . $this->getComposerFileName()), - true - ); - - if (is_null($json)) { - throw new \Exception('Unable to decode ' . $path . '/' . $this->getComposerFileName()); - } - - if (is_array($json)) { - if (isset($json['extra']['installer-paths']) && is_array($json['extra']['installer-paths'])) { - foreach ($json['extra']['installer-paths'] as $install_path => $items) { - if (in_array('type:drupal-core', $items) || - in_array('drupal/core', $items) || - in_array('drupal/drupal', $items)) { - $this->composerRoot = $path; - // @todo: Remove this magic and detect the major version instead. - if (($install_path == 'core') || ((isset($json['name'])) && ($json['name'] == 'drupal/drupal'))) { - $install_path = ''; - } elseif (substr($install_path, -5) == '/core') { - $install_path = substr($install_path, 0, -5); - } - $this->drupalRoot = rtrim($path . '/' . $install_path, '/'); - $this->vendorDir = $this->composerRoot . '/vendor'; - } - } - } - } - } - if ($this->composerRoot && file_exists($this->composerRoot . '/' . $this->getComposerFileName())) { - $json = json_decode( - file_get_contents($path . '/' . $this->getComposerFileName()), - true - ); - if (is_array($json) && isset($json['config']['vendor-dir'])) { - $this->vendorDir = $this->composerRoot . '/' . $json['config']['vendor-dir']; - } - } - - return $this->allPathsDiscovered(); - } - - /** - * @return string - */ - protected function getComposerFileName() - { - return trim(getenv('COMPOSER')) ?: 'composer.json'; - } - - /** - * Helper function to quickly determine whether or not all paths were discovered. - * - * @return bool - * True if all paths have been discovered, false if one or more haven't been found. - */ - protected function allPathsDiscovered() { - return !empty($this->drupalRoot) && !empty($this->composerRoot) && !empty($this->vendorDir); - } - - /** - * Helper function to quickly determine whether or not all paths are known. - * - * @return bool - * True if all paths are known, false if one or more paths are unknown. - */ - protected function allPathsKnown() { - return !empty($this->getDrupalRoot()) && !empty($this->getComposerRoot()) && !empty($this->getVendorDir()); - } - - /** - * Get path stored in environment variable. - * - * @param string $variable - * The name of the environment variable to retrieve the path from. - * - * @return false|string - * A path if it is valid. False otherwise. - */ - protected function getValidEnvironmentVariablePath($variable) { - $path = getenv($variable); - if (is_string($path) && is_dir($path)) { - return $path; - } - return false; - } - - /** - * Returns parent directory. - * - * @param string - * Path to start from - * - * @return string|false - * Parent path of given path or false when $path is filesystem root - */ - private function shiftPathUp($path) - { - $parent = dirname($path); - - return in_array($parent, ['.', $path]) ? false : $parent; + // See https://getcomposer.org/doc/07-runtime.md#autoloader-path-in-binaries + // PHPUnit replaces $_composer_autoload_path with its constant in vendor/phpunit/phpunit/phpunit + $autoload_path = $GLOBALS['_composer_autoload_path'] ?? PHPUNIT_COMPOSER_INSTALL; + return isset($autoload_path) ? realpath(dirname($autoload_path)) : false; } } diff --git a/tests/Drupal7FinderTest.php b/tests/Drupal7FinderTest.php deleted file mode 100644 index 9d84d61..0000000 --- a/tests/Drupal7FinderTest.php +++ /dev/null @@ -1,169 +0,0 @@ - [ - 'common.inc' => '', - ], - 'misc' => [ - 'drupal.js' => '', - ], - 'sites' => [ - 'all' => [ - 'modules' => [] - ] - ] - ]; - - /** - * @return array - */ - protected function getDrupalComposerStructure() - { - $fileStructure = [ - 'web' => static::$fileStructure, - 'composer.json' => [ - 'require' => [ - 'drupal/drupal' => '*', - ], - 'extra' => [ - 'installer-paths' => [ - 'web/' => [ - 'type:drupal-core', - ], - ], - ], - ], - 'vendor' => [], - ]; - return $fileStructure; - } - - public function testDrupalComposerStructure() - { - $fileStructure = $this->getDrupalComposerStructure(); - $this->assertComposerStructure($fileStructure); - } - - public function testDrupalComposerStructureWithoutRequire() - { - $fileStructure = [ - 'web' => static::$fileStructure, - 'composer.json' => [ - 'extra' => [ - 'installer-paths' => [ - 'web' => [ - 'drupal/drupal', - ], - ], - ], - ], - ]; - $this->assertComposerStructure($fileStructure); - } - - public function testNoDrupalRootWithRealFilesystem() - { - $finder = new DrupalFinder(); - $root = $this->tempdir(sys_get_temp_dir()); - - $this->assertFalse($finder->locateRoot($root)); - $this->assertFalse($finder->getDrupalRoot()); - $this->assertFalse($finder->getComposerRoot()); - $this->assertFalse($finder->getVendorDir()); - } - - public function testDrupalComposerStructureWithRealFilesystem() - { - $finder = new DrupalFinder(); - $root = $this->tempdir(sys_get_temp_dir()); - $this->dumpToFileSystem($this->getDrupalComposerStructure(), $root); - - $this->assertTrue($finder->locateRoot($root)); - $this->assertSame($root . '/web', $finder->getDrupalRoot()); - $this->assertSame($root, $finder->getComposerRoot()); - $this->assertSame($root . '/vendor', $finder->getVendorDir()); - - // Test symlink implementation - $symlink = $this->tempdir(sys_get_temp_dir()); - $this->symlink($root, $symlink . '/foo'); - - $this->assertTrue($finder->locateRoot($symlink . '/foo')); - $this->assertSame($root . '/web', $finder->getDrupalRoot()); - $this->assertSame($root, $finder->getComposerRoot()); - $this->assertSame($root . '/vendor', $finder->getVendorDir()); - } - - public function testDrupalWithLinkedModule() - { - $finder = new DrupalFinder(); - $root = $this->tempdir(sys_get_temp_dir()); - $this->dumpToFileSystem($this->getDrupalComposerStructure(), $root); - - $module = $this->tempdir(sys_get_temp_dir()); - $module_link = $root . '/web/sites/all/modules/foo'; - $this->symlink($module, $module_link); - - $this->assertTrue($finder->locateRoot($module_link)); - $this->assertSame($root . '/web', realpath($finder->getDrupalRoot())); - $this->assertSame($root, realpath($finder->getComposerRoot())); - $this->assertSame($root . '/vendor', realpath($finder->getVendorDir())); - } - - public function testDrupalWithCustomVendor() - { - $finder = new DrupalFinder(); - $root = $this->tempdir(sys_get_temp_dir()); - $fileStructure = $this->getDrupalComposerStructure(); - $composerJson = $fileStructure['composer.json']; - $composerJson['config']['vendor-dir'] = 'vendor-foo'; - $fileStructure['composer.json'] = $composerJson; - $fileStructure['vendor-foo'] = []; - $this->dumpToFileSystem($fileStructure, $root); - - $this->assertTrue($finder->locateRoot($root)); - $this->assertSame($root . '/web', realpath($finder->getDrupalRoot())); - $this->assertSame($root, realpath($finder->getComposerRoot())); - $this->assertSame($root . '/vendor-foo', realpath($finder->getVendorDir())); - } - - /** - * @param $fileStructure - */ - protected function assertComposerStructure($fileStructure) - { - $finder = new DrupalFinder(); - $fileStructure = $this->prepareFileStructure($fileStructure); - $root = vfsStream::setup('root', null, $fileStructure); - $this->assertTrue($finder->locateRoot($root->url() . '/web')); - $this->assertSame('vfs://root/web', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $this->assertTrue($finder->locateRoot($root->url() . '/web/misc')); - $this->assertSame('vfs://root/web', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $this->assertTrue($finder->locateRoot($root->url())); - $this->assertSame('vfs://root/web', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $root = vfsStream::setup( - 'root', - null, - ['nested_folder' => $fileStructure] - ); - $this->assertFalse($finder->locateRoot($root->url())); - $this->assertFalse($finder->getDrupalRoot()); - $this->assertFalse($finder->getComposerRoot()); - $this->assertFalse($finder->getVendorDir()); - } -} diff --git a/tests/Drupal8FinderTest.php b/tests/Drupal8FinderTest.php deleted file mode 100644 index 2d00e44..0000000 --- a/tests/Drupal8FinderTest.php +++ /dev/null @@ -1,343 +0,0 @@ - '', - 'composer.json' => [ - 'extra' => [ - 'installer-paths' => [ - 'core' => [ - 'type:drupal-core' - ] - ] - ] - ], - 'core' => [ - 'includes' => [ - 'common.inc' => '', - ], - 'misc' => [ - 'drupal.js' => '', - ], - 'core.services.yml' => '', - ], - 'modules' => [], - 'vendor' => [], - ]; - - protected static $fileStructureDrupal_8_8_x = [ - 'autoload.php' => '', - 'composer.json' => [ - 'name' => 'drupal/drupal', - 'require' => [ - 'drupal/core' => 'self.version', - ], - 'extra' => [ - 'installer-paths' => [ - 'vendor/drupal/core' => [ - 'type:drupal-core', - ], - ], - ], - ], - 'core' => [ - 'includes' => [ - 'common.inc' => '', - ], - 'misc' => [ - 'drupal.js' => '', - ], - 'core.services.yml' => '', - ], - 'modules' => [], - 'vendor' => [], - ]; - - /** - * @return array - */ - protected function getDrupalComposerStructure() - { - $fileStructure = [ - 'web' => static::$fileStructure, - 'composer.json' => [ - 'require' => [ - 'drupal/core' => '*', - ], - 'extra' => [ - 'installer-paths' => [ - 'web/core' => [ - 'type:drupal-core', - ], - ], - ], - ], - 'vendor' => [], - ]; - unset($fileStructure['web']['composer.json']); - unset($fileStructure['web']['vendor']); - - return $fileStructure; - } - - public function testDrupalDefaultStructure() - { - $finder = new DrupalFinder(); - $root = vfsStream::setup('root', null, $this->prepareFileStructure(static::$fileStructure)); - - $this->assertTrue($finder->locateRoot($root->url())); - $this->assertSame('vfs://root', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $this->assertTrue($finder->locateRoot($root->url() . '/misc')); - $this->assertSame('vfs://root', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $root = vfsStream::setup( - 'root', - null, - ['project' => $this->prepareFileStructure(static::$fileStructure)] - ); - $this->assertFalse( - $finder->locateRoot($root->url()), - 'Not in the scope of the project' - ); - $this->assertFalse($finder->getDrupalRoot()); - $this->assertFalse($finder->getComposerRoot()); - $this->assertFalse($finder->getVendorDir()); - } - - public function testDrupalDefaultStructure_8_8_x() - { - $finder = new DrupalFinder(); - $root = vfsStream::setup('root', null, $this->prepareFileStructure(static::$fileStructureDrupal_8_8_x)); - - $this->assertTrue($finder->locateRoot($root->url())); - $this->assertSame('vfs://root', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $this->assertTrue($finder->locateRoot($root->url() . '/misc')); - $this->assertSame('vfs://root', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $root = vfsStream::setup( - 'root', - null, - ['project' => $this->prepareFileStructure(static::$fileStructure)] - ); - $this->assertFalse( - $finder->locateRoot($root->url()), - 'Not in the scope of the project' - ); - $this->assertFalse($finder->getDrupalRoot()); - $this->assertFalse($finder->getComposerRoot()); - $this->assertFalse($finder->getVendorDir()); - } - - public function testDrupalComposerStructure() - { - $fileStructure = $this->getDrupalComposerStructure(); - $this->assertComposerStructure($fileStructure); - } - - public function testDrupalComposerStructureWithCustomRoot() - { - $finder = new DrupalFinder(); - $fileStructure = [ - 'src' => static::$fileStructure, - 'composer.json' => [ - 'require' => [ - 'drupal/core' => '*', - ], - 'extra' => [ - 'installer-paths' => [ - 'src/core' => [ - 'type:drupal-core', - ], - ], - ], - ], - 'vendor' => [], - ]; - unset($fileStructure['src']['composer.json']); - unset($fileStructure['src']['vendor']); - - $fileStructure = $this->prepareFileStructure($fileStructure); - $root = vfsStream::setup('root', null, $fileStructure); - $this->assertTrue($finder->locateRoot($root->url() . '/src')); - $this->assertSame('vfs://root/src', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $this->assertTrue($finder->locateRoot($root->url() . '/src/misc')); - $this->assertSame('vfs://root/src', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $this->assertTrue($finder->locateRoot($root->url())); - $this->assertSame('vfs://root/src', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $root = vfsStream::setup( - 'root', - null, - ['nested_folder' => $fileStructure] - ); - $this->assertFalse($finder->locateRoot($root->url())); - $this->assertFalse($finder->getDrupalRoot()); - $this->assertFalse($finder->getComposerRoot()); - $this->assertFalse($finder->getVendorDir()); - } - - public function testDrupalComposerStructureWithoutRequire() - { - $fileStructure = [ - 'web' => static::$fileStructure, - 'composer.json' => [ - 'extra' => [ - 'installer-paths' => [ - 'web/core' => [ - 'drupal/core', - ], - ], - ], - ], - ]; - unset($fileStructure['web']['composer.json']); - $this->assertComposerStructure($fileStructure); - } - - public function testNoDrupalRootWithRealFilesystem() - { - $finder = new DrupalFinder(); - $root = $this->tempdir(sys_get_temp_dir()); - - $this->assertFalse($finder->locateRoot($root)); - $this->assertFalse($finder->getDrupalRoot()); - $this->assertFalse($finder->getComposerRoot()); - $this->assertFalse($finder->getVendorDir()); - } - - public function testDrupalDefaultStructureWithRealFilesystem() - { - $finder = new DrupalFinder(); - $root = $this->tempdir(sys_get_temp_dir()); - $this->dumpToFileSystem(static::$fileStructure, $root); - - $this->assertTrue($finder->locateRoot($root)); - $this->assertSame($root, $finder->getDrupalRoot()); - $this->assertSame($root, $finder->getComposerRoot()); - $this->assertSame($root . '/vendor', $finder->getVendorDir()); - - // Test symlink implementation - $symlink = $this->tempdir(sys_get_temp_dir()); - $this->symlink($root, $symlink . '/foo'); - - $this->assertTrue($finder->locateRoot($symlink . '/foo')); - $this->assertSame($root, $finder->getDrupalRoot()); - $this->assertSame($root, $finder->getComposerRoot()); - $this->assertSame($root . '/vendor', $finder->getVendorDir()); - } - - public function testDrupalComposerStructureWithRealFilesystem() - { - $finder = new DrupalFinder(); - $root = $this->tempdir(sys_get_temp_dir()); - $this->dumpToFileSystem($this->getDrupalComposerStructure(), $root); - - $this->assertTrue($finder->locateRoot($root)); - $this->assertSame($root . '/web', $finder->getDrupalRoot()); - $this->assertSame($root, $finder->getComposerRoot()); - $this->assertSame($root . '/vendor', $finder->getVendorDir()); - - // Test symlink implementation - $symlink = $this->tempdir(sys_get_temp_dir()); - $this->symlink($root, $symlink . '/foo'); - - $this->assertTrue($finder->locateRoot($symlink . '/foo')); - $this->assertSame($root . '/web', $finder->getDrupalRoot()); - $this->assertSame($root, $finder->getComposerRoot()); - $this->assertSame($root . '/vendor', $finder->getVendorDir()); - } - - public function testDrupalWithLinkedModule() - { - $finder = new DrupalFinder(); - $root = $this->tempdir(sys_get_temp_dir()); - $this->dumpToFileSystem(static::$fileStructure, $root); - - $module = $this->tempdir(sys_get_temp_dir()); - $module_link = $root . '/modules/foo'; - $this->symlink($module, $module_link); - - $this->assertTrue($finder->locateRoot($module_link)); - $this->assertSame($root, realpath($finder->getDrupalRoot())); - $this->assertSame($root, realpath($finder->getComposerRoot())); - $this->assertSame($root . '/vendor', realpath($finder->getVendorDir())); - } - - public function testDrupalWithCustomVendor() - { - $finder = new DrupalFinder(); - $root = $this->tempdir(sys_get_temp_dir()); - $fileStructure = static::$fileStructure; - $fileStructure['composer.json'] = [ - 'config' => [ - 'vendor-dir' => 'vendor-foo' - ] - ]; - $fileStructure['vendor-foo'] = []; - $this->dumpToFileSystem($fileStructure, $root); - - $this->assertTrue($finder->locateRoot($root)); - $this->assertSame($root, realpath($finder->getDrupalRoot())); - $this->assertSame($root, realpath($finder->getComposerRoot())); - $this->assertSame($root . '/vendor-foo', realpath($finder->getVendorDir())); - } - - /** - * @param $fileStructure - */ - protected function assertComposerStructure($fileStructure) - { - $finder = new DrupalFinder(); - $fileStructure = $this->prepareFileStructure($fileStructure); - $root = vfsStream::setup('root', null, $fileStructure); - $this->assertTrue($finder->locateRoot($root->url() . '/web')); - $this->assertSame('vfs://root/web', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $this->assertTrue($finder->locateRoot($root->url() . '/web/misc')); - $this->assertSame('vfs://root/web', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $this->assertTrue($finder->locateRoot($root->url())); - $this->assertSame('vfs://root/web', $finder->getDrupalRoot()); - $this->assertSame('vfs://root', $finder->getComposerRoot()); - $this->assertSame('vfs://root/vendor', $finder->getVendorDir()); - - $root = vfsStream::setup( - 'root', - null, - ['nested_folder' => $fileStructure] - ); - $this->assertFalse($finder->locateRoot($root->url())); - $this->assertFalse($finder->getDrupalRoot()); - $this->assertFalse($finder->getComposerRoot()); - $this->assertFalse($finder->getVendorDir()); - } - -} diff --git a/tests/DrupalFinderTest.php b/tests/DrupalFinderTest.php new file mode 100644 index 0000000..9f0e574 --- /dev/null +++ b/tests/DrupalFinderTest.php @@ -0,0 +1,15 @@ +assertSame(dirname(__DIR__) . '/web', $finder->getDrupalRoot()); + $this->assertSame(dirname(__DIR__) . '/vendor', $finder->getVendorDir()); + $this->assertSame(dirname(__DIR__), $finder->getComposerRoot()); + } +} \ No newline at end of file diff --git a/tests/DrupalFinderTestBase.php b/tests/DrupalFinderTestBase.php deleted file mode 100644 index d8c99a3..0000000 --- a/tests/DrupalFinderTestBase.php +++ /dev/null @@ -1,184 +0,0 @@ -envNameDrupal = DrupalFinder::ENV_DRUPAL_ROOT; - $this->envNameComposer = DrupalFinder::ENV_COMPOSER_ROOT; - $this->envNameVendor = DrupalFinder::ENV_VENDOR_DIR; - } - - protected function tearDown(): void - { - parent::tearDown(); - // Unset variables to ensure their values don't carry over into other - // tests that are going to run. - putenv('DRUPAL_FINDER_DRUPAL_ROOT'); - putenv('DRUPAL_FINDER_COMPOSER_ROOT'); - putenv('DRUPAL_FINDER_VENDOR_DIR'); - } - - public function testOnlyDrupalEnvironmentVariable() { - $finder = new DrupalFinder(); - $fileStructure = [ - 'web' => [], - ]; - - $root = $this->tempdir(sys_get_temp_dir()); - $this->dumpToFileSystem($fileStructure, $root); - - $drupal_root = $root . '/web'; - - putenv("{$this->envNameDrupal}=$drupal_root"); - - // DrupalFinder::locateRoot should be true if the Drupal root is known. - $this->assertTrue($finder->locateRoot($root)); - $this->assertSame($finder->getDrupalRoot(), $drupal_root); - } - - public function testOnlyVendorEnvironmentVariable() { - $finder = new DrupalFinder(); - $fileStructure = [ - 'vendor' => [], - ]; - - $root = $this->tempdir(sys_get_temp_dir()); - $this->dumpToFileSystem($fileStructure, $root); - - $vendor_dir = $root . '/vendor'; - - putenv("{$this->envNameVendor}=$vendor_dir"); - - // DrupalFinder::locateRoot should be false since Drupal root is unknown. - $this->assertFalse($finder->locateRoot($root)); - $this->assertSame($finder->getVendorDir(), $vendor_dir); - } - - public function testOnlyComposerEnvironmentVariable() { - $finder = new DrupalFinder(); - $fileStructure = []; - - $root = $this->tempdir(sys_get_temp_dir()); - $this->dumpToFileSystem($fileStructure, $root); - - $composer_dir = $root; - - putenv("{$this->envNameComposer}=$composer_dir"); - - // DrupalFinder::locateRoot should be false since Drupal root is unknown. - $this->assertFalse($finder->locateRoot($root)); - $this->assertSame($finder->getComposerRoot(), $composer_dir); - } - - protected function dumpToFileSystem($fileStructure, $root) - { - $fileStructure = $this->prepareFileStructure($fileStructure); - foreach ($fileStructure as $name => $content) { - if (is_array($content)) { - mkdir($root . '/' . $name); - $this->dumpToFileSystem($content, $root . '/' . $name); - } else { - file_put_contents($root . '/' . $name, $content); - } - } - } - - protected function prepareFileStructure($fileStructure) - { - foreach ($fileStructure as $name => $content) { - if (($name === 'composer.json' || $name === 'composer.lock') && is_array($content)) { - $fileStructure[$name] = json_encode($content, JSON_UNESCAPED_SLASHES); - } elseif (is_array($content)) { - $fileStructure[$name] = $this->prepareFileStructure($content); - } - } - return $fileStructure; - } - - protected function tempdir($dir, $prefix = '', $mode = 0700) - { - if (substr($dir, -1) != '/') { - $dir .= '/'; - } - do { - $path = $dir . $prefix . mt_rand(0, 9999999); - } while (!mkdir($path, $mode)); - register_shutdown_function( - [static::class, 'tempdir_remove'], - $path - ); - - return realpath($path); - } - - public static function tempdir_remove($path) - { - if (is_link($path)) { - if (defined('PHP_WINDOWS_VERSION_BUILD')) { - rmdir($path); - } else { - unlink($path); - } - - return; - } - - foreach (scandir($path) as $child) { - if (in_array($child, ['.', '..'])) { - continue; - } - $child = "$path/$child"; - is_dir($child) ? static::tempdir_remove($child) : unlink($child); - } - rmdir($path); - } - - /** - * @param $target - * @param $link - * - * @throws SkippedTestError - */ - protected function symlink($target, $link) - { - try { - return symlink($target, $link); - } catch (Exception $e) { - if (defined('PHP_WINDOWS_VERSION_BUILD') - && strstr($e->getMessage(), WIN_ERROR_PRIVILEGE_NOT_HELD) - ) { - $this->markTestSkipped(<<<'MESSAGE' -No privilege to create symlinks. Run test as Administrator (elevated process). -MESSAGE - ); - } - throw $e; - } - } -} - -define('WIN_ERROR_PRIVILEGE_NOT_HELD', '1314'); From b1d130500a82971575e13b401d9b090a85e5fe0f Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Sat, 11 Nov 2023 16:18:39 -0500 Subject: [PATCH 02/11] 8.1 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d94f8a..58bee2d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: operating-system: ['ubuntu-latest'] - php-versions: ['7.2', '7.3', '7.4', '8.0'] + php-versions: ['8.1'] steps: - name: Checkout uses: actions/checkout@v2 From 6c92c1ad744287ca987a18d144c3d1586172e5f7 Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Sat, 11 Nov 2023 22:56:55 -0500 Subject: [PATCH 03/11] More robust getVendorDir(). And update README --- README.md | 25 +------------------------ src/DrupalFinder.php | 9 +++++++-- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index c68c09a..90e0188 100644 --- a/README.md +++ b/README.md @@ -8,36 +8,13 @@ Drupal Finder provides a class to locate a Drupal installation in a given path. ## Usage ```PHP -$drupalFinder = new \DrupalFinder\DrupalFinder(getcwd()); +$drupalFinder = new \DrupalFinder\DrupalFinder(); $drupalRoot = $drupalFinder->getDrupalRoot(); $composerRoot = $drupalFinder->getComposerRoot(); $vendorDir = $drupalFinder->getVendorDir(); ``` -### Environment variables - -If a set of environment variables is specified, then Drupal Finder uses those -values to determine the paths of the pertinent directories: - -- `DRUPAL_FINDER_DRUPAL_ROOT` -- `DRUPAL_FINDER_COMPOSER_ROOT` -- `DRUPAL_FINDER_VENDOR_DIR` - -For example: - -- `DRUPAL_FINDER_DRUPAL_ROOT=/var/www/web` -- `DRUPAL_FINDER_COMPOSER_ROOT=/var/www` -- `DRUPAL_FINDER_VENDOR_DIR=/var/www/vendor` - -This is useful for situations where you are containerizing an application, -directories may be in odd places, or a composer.json might be missing since it -is unneeded in a final build artifact. - -You are not required to set all the environment variables to use this -feature. If you set an environment variable, then its associated getter -function will return the value assigned to the environment variable. - ## Examples - [Drupal Console Launcher](https://github.com/hechoendrupal/drupal-console-launcher) diff --git a/src/DrupalFinder.php b/src/DrupalFinder.php index 4ad8065..e418c86 100644 --- a/src/DrupalFinder.php +++ b/src/DrupalFinder.php @@ -44,8 +44,13 @@ public function getVendorDir() { // See https://getcomposer.org/doc/07-runtime.md#autoloader-path-in-binaries // PHPUnit replaces $_composer_autoload_path with its constant in vendor/phpunit/phpunit/phpunit - $autoload_path = $GLOBALS['_composer_autoload_path'] ?? PHPUNIT_COMPOSER_INSTALL; - return isset($autoload_path) ? realpath(dirname($autoload_path)) : false; + $return = false; + if (isset($GLOBALS['_composer_autoload_path'])) { + $return = realpath(dirname($GLOBALS['_composer_autoload_path'])); + } elseif (defined(PHPUNIT_COMPOSER_INSTALL)) { + $return = realpath(dirname(PHPUNIT_COMPOSER_INSTALL)); + } + return $return; } } From f7e8bde62b373e8b73b30565cc25efd29f25bdad Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Sun, 12 Nov 2023 08:04:06 -0500 Subject: [PATCH 04/11] Quotes in test --- src/DrupalFinder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DrupalFinder.php b/src/DrupalFinder.php index e418c86..40bbd42 100644 --- a/src/DrupalFinder.php +++ b/src/DrupalFinder.php @@ -47,7 +47,7 @@ public function getVendorDir() $return = false; if (isset($GLOBALS['_composer_autoload_path'])) { $return = realpath(dirname($GLOBALS['_composer_autoload_path'])); - } elseif (defined(PHPUNIT_COMPOSER_INSTALL)) { + } elseif (defined('PHPUNIT_COMPOSER_INSTALL')) { $return = realpath(dirname(PHPUNIT_COMPOSER_INSTALL)); } return $return; From 6504ac31e1a72ba41c45e2697dc5b6e2836e31b6 Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Sun, 12 Nov 2023 08:09:33 -0500 Subject: [PATCH 05/11] Specify return types --- composer.json | 3 ++- src/DrupalFinder.php | 15 +++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index 4920316..7ae9e48 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,8 @@ } ], "require": { - "composer-runtime-api": "^2.2" + "composer-runtime-api": "^2.2", + "php": ">=8.1" }, "autoload-dev": { "psr-4": { diff --git a/src/DrupalFinder.php b/src/DrupalFinder.php index 40bbd42..3d76828 100644 --- a/src/DrupalFinder.php +++ b/src/DrupalFinder.php @@ -14,10 +14,9 @@ class DrupalFinder /** * Get the Drupal root. * - * @return string|bool * The path to the Drupal root, if it was discovered. False otherwise. */ - public function getDrupalRoot() + public function getDrupalRoot(): string|bool { $core = InstalledVersions::getInstallPath('drupal/core'); return $core ? realpath(dirname($core)) : false; @@ -26,10 +25,10 @@ public function getDrupalRoot() /** * Get the Composer root. * - * @return string|bool + * @return * The path to the Composer root, if it was discovered. False otherwise. */ - public function getComposerRoot() + public function getComposerRoot(): string|bool { return realpath(dirname($this->getVendorDir())); } @@ -37,17 +36,17 @@ public function getComposerRoot() /** * Get the vendor path. * - * @return string|bool + * @return * The path to the vendor directory, if it was found. False otherwise. */ - public function getVendorDir() + public function getVendorDir(): string|bool { - // See https://getcomposer.org/doc/07-runtime.md#autoloader-path-in-binaries - // PHPUnit replaces $_composer_autoload_path with its constant in vendor/phpunit/phpunit/phpunit $return = false; if (isset($GLOBALS['_composer_autoload_path'])) { + // See https://getcomposer.org/doc/07-runtime.md#autoloader-path-in-binaries $return = realpath(dirname($GLOBALS['_composer_autoload_path'])); } elseif (defined('PHPUNIT_COMPOSER_INSTALL')) { + // PHPUnit replaces $_composer_autoload_path with its constant in vendor/phpunit/phpunit/phpunit $return = realpath(dirname(PHPUNIT_COMPOSER_INSTALL)); } return $return; From 487d1d39852178ba153bd33347d3fb2781d98078 Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Sun, 12 Nov 2023 08:10:50 -0500 Subject: [PATCH 06/11] Slim composer.json --- composer.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/composer.json b/composer.json index 7ae9e48..e28bd36 100644 --- a/composer.json +++ b/composer.json @@ -28,10 +28,6 @@ "allow-plugins": { "composer/installers": true }, - "optimize-autoloader": true, - "preferred-install": "dist", - "sort-packages": true, - "process-timeout": 9600, "platform": { "php": "8.1" } From f43614797aba60b27b69ee9c21144fc3f926d85e Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Wed, 15 Nov 2023 17:07:56 -0500 Subject: [PATCH 07/11] PR feedback --- composer.json | 6 ++++-- src/DrupalFinder.php | 25 +++++++++---------------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/composer.json b/composer.json index e28bd36..d1470cc 100644 --- a/composer.json +++ b/composer.json @@ -13,10 +13,12 @@ "composer-runtime-api": "^2.2", "php": ">=8.1" }, + "autoload": { + "DrupalFinder\\": "src/" + }, "autoload-dev": { "psr-4": { - "DrupalFinder\\Tests\\": "tests/", - "DrupalFinder\\": "src/" + "DrupalFinder\\Tests\\": "tests/" } }, "require-dev": { diff --git a/src/DrupalFinder.php b/src/DrupalFinder.php index 3d76828..6cdd8ee 100644 --- a/src/DrupalFinder.php +++ b/src/DrupalFinder.php @@ -12,36 +12,29 @@ class DrupalFinder { /** - * Get the Drupal root. - * - * The path to the Drupal root, if it was discovered. False otherwise. + * Get the Drupal root path. */ - public function getDrupalRoot(): string|bool + public function getDrupalRoot(): ?string { $core = InstalledVersions::getInstallPath('drupal/core'); - return $core ? realpath(dirname($core)) : false; + return $core ? realpath(dirname($core)) : null; } /** - * Get the Composer root. - * - * @return - * The path to the Composer root, if it was discovered. False otherwise. + * Get the path to the Composer root directory. */ - public function getComposerRoot(): string|bool + public function getComposerRoot(): ?string { - return realpath(dirname($this->getVendorDir())); + $vendor = $this->getVendorDir(); + return $vendor ? realpath(dirname($vendor)) : null; } /** * Get the vendor path. - * - * @return - * The path to the vendor directory, if it was found. False otherwise. */ - public function getVendorDir(): string|bool + public function getVendorDir(): ?string { - $return = false; + $return = null; if (isset($GLOBALS['_composer_autoload_path'])) { // See https://getcomposer.org/doc/07-runtime.md#autoloader-path-in-binaries $return = realpath(dirname($GLOBALS['_composer_autoload_path'])); From b3e2fb917d3439eebadbebe100eb4e57f021c289 Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Wed, 15 Nov 2023 17:10:22 -0500 Subject: [PATCH 08/11] Fix composer.json --- composer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d1470cc..fcf414e 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,9 @@ "php": ">=8.1" }, "autoload": { - "DrupalFinder\\": "src/" + "psr-4": { + "DrupalFinder\\": "src/" + } }, "autoload-dev": { "psr-4": { From 4caedbabe1d465717c971c804ea72056fa88b75c Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Thu, 16 Nov 2023 00:13:18 +0100 Subject: [PATCH 09/11] Implement test-cases for custom vendor-dir --- .github/workflows/ci.yml | 3 ++ .gitignore | 4 ++ composer.json | 26 ++++++++----- phpunit.xml.dist | 1 + src/DrupalFinder.php | 15 ++------ tests/DrupalFinderTest.php | 38 +++++++++++++++---- tests/fixtures/custom-vendor/composer.json | 17 +++++++++ .../fixtures/custom-vendor/drupal-finder.php | 14 +++++++ tests/fixtures/default/composer.json | 27 +++++++++++++ tests/fixtures/default/drupal-finder.php | 14 +++++++ 10 files changed, 131 insertions(+), 28 deletions(-) create mode 100644 tests/fixtures/custom-vendor/composer.json create mode 100644 tests/fixtures/custom-vendor/drupal-finder.php create mode 100644 tests/fixtures/default/composer.json create mode 100644 tests/fixtures/default/drupal-finder.php diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58bee2d..32b89a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,5 +21,8 @@ jobs: - name: Install dependencies run: composer install + - name: Install fixtures + run: composer install-fixtures + - name: Run unit tests run: ./vendor/bin/phpunit diff --git a/.gitignore b/.gitignore index 3b5b6d9..6c4b09f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,7 @@ /vendor/ /.phpunit.result.cache /web +/tests/fixtures/custom-vendor/foo +/tests/fixtures/default/web +/tests/fixtures/default/vendor +/tests/fixtures/*/composer.lock diff --git a/composer.json b/composer.json index fcf414e..cd72939 100644 --- a/composer.json +++ b/composer.json @@ -24,21 +24,27 @@ } }, "require-dev": { - "composer/installers": "^2", - "drupal/core-recommended": "^10", - "phpunit/phpunit": "^9" + "phpunit/phpunit": "^10.4" }, "config": { - "allow-plugins": { - "composer/installers": true - }, "platform": { "php": "8.1" } }, - "extra": { - "installer-paths": { - "web/core": ["type:drupal-core"] - } + "scripts": { + "install-fixtures": [ + "cd tests/fixtures/custom-vendor && composer install", + "cd tests/fixtures/default && composer install" + ], + "uninstall-fixtures": [ + "rm -rf tests/fixtures/*/composer.lock", + "rm -rf tests/fixtures/custom-vendor/foo", + "rm -rf tests/fixtures/default/web", + "rm -rf tests/fixtures/default/vendor" + ], + "reinstall-fixtures": [ + "@uninstall-fixtures", + "@install-fixtures" + ] } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 92f27db..34265ab 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -3,6 +3,7 @@ ./tests + ./tests/fixtures diff --git a/src/DrupalFinder.php b/src/DrupalFinder.php index 6cdd8ee..cbeae74 100644 --- a/src/DrupalFinder.php +++ b/src/DrupalFinder.php @@ -25,8 +25,8 @@ public function getDrupalRoot(): ?string */ public function getComposerRoot(): ?string { - $vendor = $this->getVendorDir(); - return $vendor ? realpath(dirname($vendor)) : null; + $root = InstalledVersions::getRootPackage(); + return realpath($root['install_path']); } /** @@ -34,15 +34,8 @@ public function getComposerRoot(): ?string */ public function getVendorDir(): ?string { - $return = null; - if (isset($GLOBALS['_composer_autoload_path'])) { - // See https://getcomposer.org/doc/07-runtime.md#autoloader-path-in-binaries - $return = realpath(dirname($GLOBALS['_composer_autoload_path'])); - } elseif (defined('PHPUNIT_COMPOSER_INSTALL')) { - // PHPUnit replaces $_composer_autoload_path with its constant in vendor/phpunit/phpunit/phpunit - $return = realpath(dirname(PHPUNIT_COMPOSER_INSTALL)); - } - return $return; + $reflection = new \ReflectionClass(InstalledVersions::class); + return realpath(dirname(dirname($reflection->getFileName()))); } } diff --git a/tests/DrupalFinderTest.php b/tests/DrupalFinderTest.php index 9f0e574..c525a90 100644 --- a/tests/DrupalFinderTest.php +++ b/tests/DrupalFinderTest.php @@ -2,14 +2,38 @@ namespace DrupalFinder\Tests; -use DrupalFinder\DrupalFinder; use PHPUnit\Framework\TestCase; class DrupalFinderTest extends TestCase { - public function testPaths() { - $finder = new DrupalFinder(); - $this->assertSame(dirname(__DIR__) . '/web', $finder->getDrupalRoot()); - $this->assertSame(dirname(__DIR__) . '/vendor', $finder->getVendorDir()); - $this->assertSame(dirname(__DIR__), $finder->getComposerRoot()); + + protected const installFixtures = 'Execute "composer install-fixtures" first.'; + + /** + * @runInSeparateProcess + */ + public function testDefault() { + $basePath = realpath( __DIR__ . '/fixtures/default'); + $this->assertDirectoryExists($basePath . '/vendor', static::installFixtures); + $this->assertDirectoryExists($basePath . '/web', static::installFixtures); + + $result = json_decode(require $basePath . '/drupal-finder.php', TRUE); + $this->assertSame($result['getComposerRoot'], $basePath); + $this->assertSame($result['getVendorDir'], $basePath . '/vendor'); + $this->assertSame($result['getDrupalRoot'], $basePath . '/web'); } -} \ No newline at end of file + + /** + * @runInSeparateProcess + */ + public function testCustomVendor() { + $basePath = realpath( __DIR__ . '/fixtures/custom-vendor'); + $this->assertDirectoryExists($basePath . '/foo/bar', static::installFixtures); + $this->assertDirectoryExists($basePath . '/foo/bar/drupal', static::installFixtures); + + $result = json_decode(require $basePath . '/drupal-finder.php', TRUE); + $this->assertSame($result['getComposerRoot'], $basePath); + $this->assertSame($result['getVendorDir'], $basePath . '/foo/bar'); + $this->assertSame($result['getDrupalRoot'], $basePath . '/foo/bar/drupal'); + } + +} diff --git a/tests/fixtures/custom-vendor/composer.json b/tests/fixtures/custom-vendor/composer.json new file mode 100644 index 0000000..0d1a7f3 --- /dev/null +++ b/tests/fixtures/custom-vendor/composer.json @@ -0,0 +1,17 @@ +{ + "repositories": { + "drupal-finder": { + "type": "path", + "url": "../../../" + } + }, + "require": { + "webflo/drupal-finder": "*", + "drupal/core": "^10" + }, + "config": { + "vendor-dir": "foo/bar" + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/tests/fixtures/custom-vendor/drupal-finder.php b/tests/fixtures/custom-vendor/drupal-finder.php new file mode 100644 index 0000000..89e6dd5 --- /dev/null +++ b/tests/fixtures/custom-vendor/drupal-finder.php @@ -0,0 +1,14 @@ + $finder->getComposerRoot(), + 'getVendorDir' => $finder->getVendorDir(), + 'getDrupalRoot' => $finder->getDrupalRoot(), + ] +); diff --git a/tests/fixtures/default/composer.json b/tests/fixtures/default/composer.json new file mode 100644 index 0000000..7741bd3 --- /dev/null +++ b/tests/fixtures/default/composer.json @@ -0,0 +1,27 @@ +{ + "repositories": { + "drupal-finder": { + "type": "path", + "url": "../../../" + } + }, + "require": { + "composer/installers": "^2.2", + "drupal/core": "^10", + "webflo/drupal-finder": "*" + }, + "config": { + "allow-plugins": { + "composer/installers": true + } + }, + "extra": { + "installer-paths": { + "web/core": [ + "type:drupal-core" + ] + } + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/tests/fixtures/default/drupal-finder.php b/tests/fixtures/default/drupal-finder.php new file mode 100644 index 0000000..2669234 --- /dev/null +++ b/tests/fixtures/default/drupal-finder.php @@ -0,0 +1,14 @@ + $finder->getComposerRoot(), + 'getVendorDir' => $finder->getVendorDir(), + 'getDrupalRoot' => $finder->getDrupalRoot(), + ] +); From de29c185610898a23cf51e2c2f273e9b29dad256 Mon Sep 17 00:00:00 2001 From: Florian Weber Date: Thu, 16 Nov 2023 00:23:38 +0100 Subject: [PATCH 10/11] Remove /web from .gitignore everything lives in texts/fixtures --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 6c4b09f..4ece3d5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ /composer.lock /vendor/ /.phpunit.result.cache -/web /tests/fixtures/custom-vendor/foo /tests/fixtures/default/web /tests/fixtures/default/vendor From 8998aecdda29123bfa6544c0bcd93364c3e96306 Mon Sep 17 00:00:00 2001 From: Moshe Weitzman Date: Sat, 23 Dec 2023 07:48:33 -0500 Subject: [PATCH 11/11] Update readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 90e0188..768140d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/webflo/drupal-finder/CI)](https://github.com/webflo/drupal-finder/actions/workflows/ci.yml) [![Packagist](https://img.shields.io/packagist/v/webflo/drupal-finder.svg)](https://packagist.org/packages/webflo/drupal-finder) -Drupal Finder provides a class to locate a Drupal installation in a given path. +Drupal Finder provides a class to locate a Drupal installation based on Composer metadata. ## Usage @@ -18,7 +18,7 @@ $vendorDir = $drupalFinder->getVendorDir(); ## Examples - [Drupal Console Launcher](https://github.com/hechoendrupal/drupal-console-launcher) -- [Drush Launcher](https://github.com/drush-ops/drush-launcher) +- [Drush](https://github.com/drush-ops/drush) ## License