Initial Drupal 11 with DDEV setup
This commit is contained in:
295
vendor/consolidation/robo/src/Task/Archive/Extract.php
vendored
Normal file
295
vendor/consolidation/robo/src/Task/Archive/Extract.php
vendored
Normal file
@ -0,0 +1,295 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Task\Archive;
|
||||
|
||||
use Robo\Result;
|
||||
use Robo\Task\BaseTask;
|
||||
use Robo\Task\Filesystem\Tasks as FilesystemTaskLoader;
|
||||
use Robo\Contract\BuilderAwareInterface;
|
||||
use Robo\TaskAccessor;
|
||||
|
||||
/**
|
||||
* Extracts an archive.
|
||||
*
|
||||
* Note that often, distributions are packaged in tar or zip archives
|
||||
* where the topmost folder may contain variable information, such as
|
||||
* the release date, or the version of the package. This information
|
||||
* is very useful when unpacking by hand, but arbitrarily-named directories
|
||||
* are much less useful to scripts. Therefore, by default, Extract will
|
||||
* remove the top-level directory, and instead store all extracted files
|
||||
* into the directory specified by $archivePath.
|
||||
*
|
||||
* To keep the top-level directory when extracting, use
|
||||
* `preserveTopDirectory(true)`.
|
||||
*
|
||||
* ``` php
|
||||
* <?php
|
||||
* $this->taskExtract($archivePath)
|
||||
* ->to($destination)
|
||||
* ->preserveTopDirectory(false) // the default
|
||||
* ->run();
|
||||
* ?>
|
||||
* ```
|
||||
*/
|
||||
class Extract extends BaseTask implements BuilderAwareInterface
|
||||
{
|
||||
use TaskAccessor;
|
||||
use FilesystemTaskLoader;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $filename;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $to;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $preserveTopDirectory = false;
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
*/
|
||||
public function __construct($filename)
|
||||
{
|
||||
$this->filename = $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location to store extracted files.
|
||||
*
|
||||
* @param string $to
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function to($to)
|
||||
{
|
||||
$this->to = $to;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $preserve
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function preserveTopDirectory($preserve = true)
|
||||
{
|
||||
$this->preserveTopDirectory = $preserve;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
if (!file_exists($this->filename)) {
|
||||
$this->printTaskError("File {filename} does not exist", ['filename' => $this->filename]);
|
||||
|
||||
return false;
|
||||
}
|
||||
if (!($mimetype = static::archiveType($this->filename))) {
|
||||
$this->printTaskError("Could not determine type of archive for {filename}", ['filename' => $this->filename]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$umask = 0777 - umask();
|
||||
|
||||
// We will first extract to $extractLocation and then move to $this->to
|
||||
$extractLocation = $this->getTempDir();
|
||||
@mkdir($extractLocation, $umask, true);
|
||||
|
||||
$destinationParentDir = dirname($this->to);
|
||||
if (!file_exists($destinationParentDir)) {
|
||||
@mkdir($destinationParentDir, $umask, true);
|
||||
}
|
||||
|
||||
$this->startTimer();
|
||||
|
||||
$this->printTaskInfo("Extracting {filename}", ['filename' => $this->filename]);
|
||||
|
||||
$result = $this->extractAppropriateType($mimetype, $extractLocation);
|
||||
if ($result->wasSuccessful()) {
|
||||
$this->printTaskInfo("{filename} extracted", ['filename' => $this->filename]);
|
||||
// Now, we want to move the extracted files to $this->to. There
|
||||
// are two possibilities that we must consider:
|
||||
//
|
||||
// (1) Archived files were encapsulated in a folder with an arbitrary name
|
||||
// (2) There was no encapsulating folder, and all the files in the archive
|
||||
// were extracted into $extractLocation
|
||||
//
|
||||
// In the case of (1), we want to move and rename the encapsulating folder
|
||||
// to $this->to.
|
||||
//
|
||||
// In the case of (2), we will just move and rename $extractLocation.
|
||||
$filesInExtractLocation = glob("$extractLocation/*");
|
||||
$hasEncapsulatingFolder = ((count($filesInExtractLocation) == 1) && is_dir($filesInExtractLocation[0]));
|
||||
if ($hasEncapsulatingFolder && !$this->preserveTopDirectory) {
|
||||
$this
|
||||
->taskFilesystemStack()
|
||||
->rename($filesInExtractLocation[0], $this->to)
|
||||
->remove($extractLocation)
|
||||
->run();
|
||||
} else {
|
||||
$this
|
||||
->taskFilesystemStack()
|
||||
->rename($extractLocation, $this->to)
|
||||
->run();
|
||||
}
|
||||
}
|
||||
$this->stopTimer();
|
||||
$result['time'] = $this->getExecutionTime();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $mimetype
|
||||
* @param string $extractLocation
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
protected function extractAppropriateType($mimetype, $extractLocation)
|
||||
{
|
||||
// Perform the extraction of a zip file.
|
||||
if (($mimetype == 'application/zip') || ($mimetype == 'application/x-zip')) {
|
||||
return $this->extractZip($extractLocation);
|
||||
}
|
||||
return $this->extractTar($extractLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $extractLocation
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
protected function extractZip($extractLocation)
|
||||
{
|
||||
if (!extension_loaded('zlib')) {
|
||||
return Result::errorMissingExtension($this, 'zlib', 'zip extracting');
|
||||
}
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
if (($status = $zip->open($this->filename)) !== true) {
|
||||
return Result::error($this, "Could not open zip archive {$this->filename}");
|
||||
}
|
||||
if (!$zip->extractTo($extractLocation)) {
|
||||
return Result::error($this, "Could not extract zip archive {$this->filename}");
|
||||
}
|
||||
$zip->close();
|
||||
|
||||
return Result::success($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $extractLocation
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
protected function extractTar($extractLocation)
|
||||
{
|
||||
if (!class_exists('Archive_Tar')) {
|
||||
return Result::errorMissingPackage($this, 'Archive_Tar', 'pear/archive_tar');
|
||||
}
|
||||
$tar_object = new \Archive_Tar($this->filename);
|
||||
if (!$tar_object->extract($extractLocation)) {
|
||||
return Result::error($this, "Could not extract tar archive {$this->filename}");
|
||||
}
|
||||
|
||||
return Result::success($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
protected static function archiveType($filename)
|
||||
{
|
||||
$content_type = false;
|
||||
if (class_exists('finfo')) {
|
||||
$finfo = new \finfo(FILEINFO_MIME_TYPE);
|
||||
$content_type = $finfo->file($filename);
|
||||
// If finfo cannot determine the content type, then we will try other methods
|
||||
if ($content_type == 'application/octet-stream') {
|
||||
$content_type = false;
|
||||
}
|
||||
}
|
||||
// Examing the file's magic header bytes.
|
||||
if (!$content_type) {
|
||||
if ($file = fopen($filename, 'rb')) {
|
||||
$first = fread($file, 2);
|
||||
fclose($file);
|
||||
if ($first !== false) {
|
||||
// Interpret the two bytes as a little endian 16-bit unsigned int.
|
||||
$data = unpack('v', $first);
|
||||
switch ($data[1]) {
|
||||
case 0x8b1f:
|
||||
// First two bytes of gzip files are 0x1f, 0x8b (little-endian).
|
||||
// See https://www.gzip.org/zlib/rfc-gzip.html#header-trailer
|
||||
$content_type = 'application/x-gzip';
|
||||
break;
|
||||
|
||||
case 0x4b50:
|
||||
// First two bytes of zip files are 0x50, 0x4b ('PK') (little-endian).
|
||||
// See https://en.wikipedia.org/wiki/Zip_(file_format)#File_headers
|
||||
$content_type = 'application/zip';
|
||||
break;
|
||||
|
||||
case 0x5a42:
|
||||
// First two bytes of bzip2 files are 0x5a, 0x42 ('BZ') (big-endian).
|
||||
// See https://en.wikipedia.org/wiki/Bzip2#File_format
|
||||
$content_type = 'application/x-bzip2';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 3. Lastly if above methods didn't work, try to guess the mime type from
|
||||
// the file extension. This is useful if the file has no identificable magic
|
||||
// header bytes (for example tarballs).
|
||||
if (!$content_type) {
|
||||
// Remove querystring from the filename, if present.
|
||||
$filename = basename(current(explode('?', $filename, 2)));
|
||||
$extension_mimetype = array(
|
||||
'.tar.gz' => 'application/x-gzip',
|
||||
'.tgz' => 'application/x-gzip',
|
||||
'.tar' => 'application/x-tar',
|
||||
);
|
||||
foreach ($extension_mimetype as $extension => $ct) {
|
||||
if (substr($filename, -strlen($extension)) === $extension) {
|
||||
$content_type = $ct;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $content_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function getTempDir()
|
||||
{
|
||||
return $this->to . '-tmp' . rand() . time();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use $this->getTempDir() instead.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @see getTempDir
|
||||
*/
|
||||
protected static function getTmpDir()
|
||||
{
|
||||
return getcwd() . '/tmp' . rand() . time();
|
||||
}
|
||||
}
|
||||
291
vendor/consolidation/robo/src/Task/Archive/Pack.php
vendored
Normal file
291
vendor/consolidation/robo/src/Task/Archive/Pack.php
vendored
Normal file
@ -0,0 +1,291 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Task\Archive;
|
||||
|
||||
use Robo\Contract\PrintedInterface;
|
||||
use Robo\Result;
|
||||
use Robo\Task\BaseTask;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
/**
|
||||
* Creates a zip or tar archive.
|
||||
*
|
||||
* ``` php
|
||||
* <?php
|
||||
* $this->taskPack(
|
||||
* <archiveFile>)
|
||||
* ->add('README') // Puts file 'README' in archive at the root
|
||||
* ->add('project') // Puts entire contents of directory 'project' in archinve inside 'project'
|
||||
* ->addFile('dir/file.txt', 'file.txt') // Takes 'file.txt' from cwd and puts it in archive inside 'dir'.
|
||||
* ->exclude(['dir\/.*.zip', '.*.md']) // Add regex (or array of regex) to the excluded patterns list.
|
||||
* ->run();
|
||||
* ?>
|
||||
* ```
|
||||
*/
|
||||
class Pack extends BaseTask implements PrintedInterface
|
||||
{
|
||||
/**
|
||||
* The list of items to be packed into the archive.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $items = [];
|
||||
|
||||
/**
|
||||
* The full path to the archive to be created.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $archiveFile;
|
||||
|
||||
/**
|
||||
* A list of regex patterns to exclude from the archive.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $ignoreList;
|
||||
/**
|
||||
* Construct the class.
|
||||
*
|
||||
* @param string $archiveFile
|
||||
* The full path and name of the archive file to create.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function __construct($archiveFile)
|
||||
{
|
||||
$this->archiveFile = $archiveFile;
|
||||
$this->ignoreList = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Satisfy the parent requirement.
|
||||
*
|
||||
* @return bool
|
||||
* Always returns true.
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function getPrinted()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $archiveFile
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function archiveFile($archiveFile)
|
||||
{
|
||||
$this->archiveFile = $archiveFile;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the archive. Like file_exists(), the parameter
|
||||
* may be a file or a directory.
|
||||
*
|
||||
* @param string $placementLocation
|
||||
* Relative path and name of item to store in archive.
|
||||
* @param string $filesystemLocation
|
||||
* Absolute or relative path to file or directory's location in filesystem.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addFile($placementLocation, $filesystemLocation)
|
||||
{
|
||||
$this->items[$placementLocation] = $filesystemLocation;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for addFile, in case anyone has angst about using
|
||||
* addFile with a directory.
|
||||
*
|
||||
* @param string $placementLocation
|
||||
* Relative path and name of directory to store in archive.
|
||||
* @param string $filesystemLocation
|
||||
* Absolute or relative path to directory or directory's location in filesystem.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addDir($placementLocation, $filesystemLocation)
|
||||
{
|
||||
$this->addFile($placementLocation, $filesystemLocation);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a file or directory, or list of same to the archive.
|
||||
*
|
||||
* @param string|array $item
|
||||
* If given a string, should contain the relative filesystem path to the
|
||||
* the item to store in archive; this will also be used as the item's
|
||||
* path in the archive, so absolute paths should not be used here.
|
||||
* If given an array, the key of each item should be the path to store
|
||||
* in the archive, and the value should be the filesystem path to the
|
||||
* item to store.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function add($item)
|
||||
{
|
||||
if (is_array($item)) {
|
||||
$this->items = array_merge($this->items, $item);
|
||||
} else {
|
||||
$this->addFile($item, $item);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow files or folder to be excluded from the archive. Use regex, without enclosing slashes.
|
||||
*
|
||||
* @param string|string[]
|
||||
* A regex (or array of) to be excluded.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function exclude($ignoreList)
|
||||
{
|
||||
$this->ignoreList = array_merge($this->ignoreList, (array) $ignoreList);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a zip archive for distribution.
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*
|
||||
* @since 1.0
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$this->startTimer();
|
||||
|
||||
// Use the file extension to determine what kind of archive to create.
|
||||
$fileInfo = new \SplFileInfo($this->archiveFile);
|
||||
$extension = strtolower($fileInfo->getExtension());
|
||||
if (empty($extension)) {
|
||||
return Result::error($this, "Archive filename must use an extension (e.g. '.zip') to specify the kind of archive to create.");
|
||||
}
|
||||
|
||||
try {
|
||||
// Inform the user which archive we are creating
|
||||
$this->printTaskInfo("Creating archive {filename}", ['filename' => $this->archiveFile]);
|
||||
if ($extension == 'zip') {
|
||||
$result = $this->archiveZip($this->archiveFile, $this->items);
|
||||
} else {
|
||||
$result = $this->archiveTar($this->archiveFile, $this->items);
|
||||
}
|
||||
$this->printTaskSuccess("{filename} created.", ['filename' => $this->archiveFile]);
|
||||
} catch (\Exception $e) {
|
||||
$this->printTaskError("Could not create {filename}. {exception}", ['filename' => $this->archiveFile, 'exception' => $e->getMessage(), '_style' => ['exception' => '']]);
|
||||
$result = Result::error($this, sprintf('Could not create %s. %s', $this->archiveFile, $e->getMessage()));
|
||||
}
|
||||
$this->stopTimer();
|
||||
$result['time'] = $this->getExecutionTime();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $archiveFile
|
||||
* @param array $items
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
protected function archiveTar($archiveFile, $items)
|
||||
{
|
||||
if (!class_exists('Archive_Tar')) {
|
||||
return Result::errorMissingPackage($this, 'Archive_Tar', 'pear/archive_tar');
|
||||
}
|
||||
|
||||
$tar_object = new \Archive_Tar($archiveFile);
|
||||
if (!empty($this->ignoreList)) {
|
||||
$regexp = '#/' . join('$|/', $this->ignoreList) . '#';
|
||||
$tar_object->setIgnoreRegexp($regexp);
|
||||
}
|
||||
foreach ($items as $placementLocation => $filesystemLocation) {
|
||||
$p_remove_dir = $filesystemLocation;
|
||||
$p_add_dir = $placementLocation;
|
||||
if (is_file($filesystemLocation)) {
|
||||
$p_remove_dir = dirname($filesystemLocation);
|
||||
$p_add_dir = dirname($placementLocation);
|
||||
if (basename($filesystemLocation) != basename($placementLocation)) {
|
||||
return Result::error($this, "Tar archiver does not support renaming files during extraction; could not add $filesystemLocation as $placementLocation.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!$tar_object->addModify([$filesystemLocation], $p_add_dir, $p_remove_dir)) {
|
||||
return Result::error($this, "Could not add $filesystemLocation to the archive.");
|
||||
}
|
||||
}
|
||||
|
||||
return Result::success($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $archiveFile
|
||||
* @param array $items
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
protected function archiveZip($archiveFile, $items)
|
||||
{
|
||||
if (!extension_loaded('zlib') || !class_exists(\ZipArchive::class)) {
|
||||
return Result::errorMissingExtension($this, 'zlib', 'zip packing');
|
||||
}
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
if (!$zip->open($archiveFile, \ZipArchive::CREATE)) {
|
||||
return Result::error($this, "Could not create zip archive {$archiveFile}");
|
||||
}
|
||||
$result = $this->addItemsToZip($zip, $items);
|
||||
$zip->close();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \ZipArchive $zip
|
||||
* @param array $items
|
||||
*
|
||||
* @return \Robo\Result
|
||||
*/
|
||||
protected function addItemsToZip($zip, $items)
|
||||
{
|
||||
foreach ($items as $placementLocation => $filesystemLocation) {
|
||||
if (is_dir($filesystemLocation)) {
|
||||
$finder = new Finder();
|
||||
$finder->files()->in($filesystemLocation)->ignoreDotFiles(false);
|
||||
if (!empty($this->ignoreList)) {
|
||||
// Add slashes so Symfony Finder patterns work like Archive_Tar ones.
|
||||
$zipIgnoreList = preg_filter('/^|$/', '/', $this->ignoreList);
|
||||
$finder->notName($zipIgnoreList)->notPath($zipIgnoreList);
|
||||
}
|
||||
|
||||
foreach ($finder as $file) {
|
||||
// Replace Windows slashes or resulting zip will have issues on *nixes.
|
||||
$relativePathname = str_replace('\\', '/', $file->getRelativePathname());
|
||||
|
||||
if (!$zip->addFile($file->getRealpath(), "{$placementLocation}/{$relativePathname}")) {
|
||||
return Result::error($this, "Could not add directory $filesystemLocation to the archive; error adding {$file->getRealpath()}.");
|
||||
}
|
||||
}
|
||||
} elseif (is_file($filesystemLocation)) {
|
||||
if (!$zip->addFile($filesystemLocation, $placementLocation)) {
|
||||
return Result::error($this, "Could not add file $filesystemLocation to the archive.");
|
||||
}
|
||||
} else {
|
||||
return Result::error($this, "Could not find $filesystemLocation for the archive.");
|
||||
}
|
||||
}
|
||||
|
||||
return Result::success($this);
|
||||
}
|
||||
}
|
||||
26
vendor/consolidation/robo/src/Task/Archive/Tasks.php
vendored
Normal file
26
vendor/consolidation/robo/src/Task/Archive/Tasks.php
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Robo\Task\Archive;
|
||||
|
||||
trait Tasks
|
||||
{
|
||||
/**
|
||||
* @param string $filename
|
||||
*
|
||||
* @return \Robo\Task\Archive\Pack|\Robo\Collection\CollectionBuilder
|
||||
*/
|
||||
protected function taskPack($filename)
|
||||
{
|
||||
return $this->task(Pack::class, $filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filename
|
||||
*
|
||||
* @return \Robo\Task\Archive\Extract|\Robo\Collection\CollectionBuilder
|
||||
*/
|
||||
protected function taskExtract($filename)
|
||||
{
|
||||
return $this->task(Extract::class, $filename);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user