131 lines
No EOL
5.2 KiB
PHP
131 lines
No EOL
5.2 KiB
PHP
<?php
|
|
/*
|
|
* Copyright (c) Nosial 2022-2023, all rights reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
* associated documentation files (the "Software"), to deal in the Software without restriction, including without
|
|
* limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
* Software, and to permit persons to whom the Software is furnished to do so, subject to the following
|
|
* conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
|
* of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
* PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
*/
|
|
|
|
namespace ncc\Classes;
|
|
|
|
use Exception;
|
|
use finfo;
|
|
use ncc\Exceptions\IOException;
|
|
use ncc\Exceptions\NotSupportedException;
|
|
use ncc\Utilities\Console;
|
|
use PharData;
|
|
use RuntimeException;
|
|
use ZipArchive;
|
|
|
|
class ArchiveExtractor
|
|
{
|
|
/**
|
|
* Extracts a given archive to a directory path
|
|
*
|
|
* @param string $archive_path
|
|
* @param string $directory_path
|
|
* @return void
|
|
* @throws IOException
|
|
* @throws NotSupportedException
|
|
*/
|
|
public static function extract(string $archive_path, string $directory_path): void
|
|
{
|
|
if(!is_file($archive_path))
|
|
{
|
|
throw new IOException(sprintf('Archive file "%s" does not exist', $archive_path));
|
|
}
|
|
|
|
$file_info = new finfo(FILEINFO_MIME);
|
|
|
|
$mime = strtolower($file_info->file($archive_path));
|
|
if(($pos = strpos($mime, ';')) !== false)
|
|
{
|
|
$mime = substr($mime, 0, $pos);
|
|
}
|
|
|
|
switch($mime)
|
|
{
|
|
case 'application/zip':
|
|
Console::outDebug(sprintf('Extracting zip archive "%s" to "%s"', $archive_path, $directory_path));
|
|
self::extractZip($archive_path, $directory_path);
|
|
break;
|
|
|
|
case 'application/x-tar':
|
|
case 'application/x-gzip':
|
|
Console::outDebug(sprintf('Extracting tar archive "%s" to "%s"', $archive_path, $directory_path));
|
|
$phar = new PharData($archive_path);
|
|
$phar->extractTo($directory_path);
|
|
break;
|
|
|
|
default:
|
|
throw new NotSupportedException(sprintf('Unable to extract archive "%s" of type "%s"', $archive_path, $file_info->file($archive_path)));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Extracts a zip archive to a directory
|
|
*
|
|
* @param string $archive_path
|
|
* @param string $directory_path
|
|
* @return void
|
|
* @throws IOException
|
|
*/
|
|
private static function extractZip(string $archive_path, string $directory_path): void
|
|
{
|
|
$zip_archive = new ZipArchive();
|
|
Console::outDebug(sprintf('Opening zip archive "%s"', $archive_path));
|
|
|
|
if(!$zip_archive->open($archive_path))
|
|
{
|
|
throw new IOException(sprintf('Unable to open zip archive "%s"', $archive_path));
|
|
}
|
|
|
|
if(!is_dir($directory_path) && !mkdir($directory_path, 0777, true) && !is_dir($directory_path))
|
|
{
|
|
throw new IOException(sprintf('Unable to create directory "%s"', $directory_path));
|
|
}
|
|
|
|
for($i=0; $i < $zip_archive->numFiles; $i++)
|
|
{
|
|
$entry_name = $zip_archive->statIndex($i)['name'];
|
|
|
|
if(str_ends_with($entry_name, '/'))
|
|
{
|
|
$concurrent_directory = $directory_path . DIRECTORY_SEPARATOR . $entry_name;
|
|
Console::outDebug(sprintf('Creating directory "%s"', $concurrent_directory));
|
|
if(!is_dir($concurrent_directory) && !mkdir($concurrent_directory, 0777, true) && !is_dir($concurrent_directory))
|
|
{
|
|
throw new RuntimeException(sprintf('Directory "%s" was not created', $concurrent_directory));
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
try
|
|
{
|
|
Console::outDebug(sprintf('Extracting file "%s" from archive "%s"', $entry_name, $archive_path));
|
|
$zip_archive->extractTo($directory_path, $entry_name);
|
|
}
|
|
catch(Exception $e)
|
|
{
|
|
throw new IOException(sprintf('Unable to extract file "%s" from archive "%s"', $entry_name, $archive_path), $e);
|
|
}
|
|
}
|
|
|
|
$zip_archive->close();
|
|
}
|
|
} |