#!/bin/php isDot()) { // do nothing } elseif ($fileinfo->isDir()) { process_candidate_dir($fileinfo->getPathname()); } } } /** * Recursively scans a directory for Drupal extensions, and runs * process_extension() for each one that it finds. * * @param string $dir * A directory that could be a Drupal extension directory. */ function process_candidate_dir($dir) { /** * @var \DirectoryIterator $fileinfo */ foreach (new \DirectoryIterator($dir) as $fileinfo) { if ($fileinfo->isDot()) { // Ignore "." and "..". } elseif ($fileinfo->isDir()) { // It's a directory. switch ($fileinfo->getFilename()) { case 'lib': case 'src': // Ignore these directory names. continue; default: // Look for more extensions in subdirectories. process_candidate_dir($fileinfo->getPathname()); } } else { // It's a file. if (preg_match('/^(.+).info.yml$/', $fileinfo->getFilename(), $m)) { // It's a *.info.yml file, so we found an extension directory. $extension_name = $m[1]; } } } if (isset($extension_name)) { process_extension($extension_name, $dir); process_extension_phpunit($extension_name, $dir); } } /** * Process a Drupal extension (module, theme) in a directory. * * This will move all class files in this extension from * lib/Drupal/$extension_name/$path to src/$path. * * @param string $name * Name of the extension. * @param string $dir * Directory of the extension. * @throws \Exception */ function process_extension($name, $dir) { if (!is_dir($source = "$dir/lib/Drupal/$name")) { // Nothing to do in this module. return; } if (!is_dir($destination = "$dir/src")) { mkdir($destination); } // Move class files two levels up. move_directory_contents($source, $destination); // Clean up. require_dir_empty("$dir/lib/Drupal"); rmdir("$dir/lib/Drupal"); } /** * Process a Drupal extension (module, theme) in a directory. * * This will move all PHPUnit class files in this extension from * tests/Drupal/$name/Tests/ to tests/src/. * * @param string $name * Name of the extension. * @param string $dir * Directory of the extension. */ function process_extension_phpunit($name, $dir) { if (!is_dir($source = "$dir/tests/Drupal/$name/Tests")) { // Nothing to do in this module. return; } if (!is_dir($dest = "$dir/tests/src")) { mkdir($dest); } // Move class files two levels up. move_directory_contents($source, $dest); // Clean up. require_dir_empty("$dir/tests/Drupal/$name"); rmdir("$dir/tests/Drupal/$name"); require_dir_empty("$dir/tests/Drupal"); rmdir("$dir/tests/Drupal"); } /** * Move directory contents from an existing source directory to an existing * destination directory. * * @param string $source * An existing source directory. * @param string $destination * An existing destination directory. * * @throws \Exception */ function move_directory_contents($source, $destination) { if (!is_dir($source)) { throw new \Exception("The source '$source' is not a directory."); } if (!is_dir($destination)) { throw new \Exception("The destination '$destination' is not a directory."); } /** * @var \DirectoryIterator $fileinfo */ foreach (new \DirectoryIterator($source) as $fileinfo) { if ($fileinfo->isDot()) { continue; } $dest_path = $destination . '/' . $fileinfo->getFilename(); if (!file_exists($dest_path)) { rename($fileinfo->getPathname(), $dest_path); } elseif ($fileinfo->isFile()) { throw new \Exception("Destination '$dest_path' already exists, cannot overwrite."); } elseif ($fileinfo->isDir()) { if (!is_dir($dest_path)) { throw new \Exception("Destination '$dest_path' is not a directory."); } move_directory_contents($fileinfo->getPathname(), $dest_path); } } require_dir_empty($source); rmdir($source); } /** * Throws an exception if a directory is not empty. * * @param string $dir * Directory to check. * * @throws \Exception */ function require_dir_empty($dir) { if (is_file($dir)) { throw new \Exception("The path '$dir' is a file, when it should be a directory."); } if (!is_dir($dir)) { throw new \Exception("The directory '$dir' does not exist."); } if (!is_readable($dir)) { throw new \Exception("The directory '$dir' is not readable."); } /** * @var \DirectoryIterator $fileinfo */ foreach (new \DirectoryIterator($dir) as $fileinfo) { if ($fileinfo->isDot()) { continue; } $path = $fileinfo->getPathname(); if ($fileinfo->isFile()) { throw new \Exception("File '$path' found in a directory that should be empty."); } elseif ($fileinfo->isDir()) { throw new \Exception("Subdirectory '$path' found in a directory that should be empty."); } } }