mirror of
https://github.com/php-win-ext/php-sdk-binary-tools.git
synced 2026-03-24 09:02:12 +01:00
240 lines
5.4 KiB
PHP
240 lines
5.4 KiB
PHP
<?php
|
|
|
|
namespace SDK;
|
|
|
|
trait FileOps
|
|
{
|
|
protected function md(string $name = "", bool $tmp = false) : string
|
|
{/*{{{*/
|
|
$ret = $name;
|
|
|
|
if (!$name) {
|
|
if ($tmp) {
|
|
$pre = Config::getTmpDir();
|
|
$ret = $pre . DIRECTORY_SEPARATOR . md5(uniqid());
|
|
} else {
|
|
throw new Exception("Dir name is empty");
|
|
}
|
|
}
|
|
|
|
|
|
if (!is_dir($ret)) {
|
|
if (!mkdir($ret, 0755, true)) {
|
|
throw new Exception("Unable to create '$ret'");
|
|
}
|
|
}
|
|
|
|
return $ret;
|
|
}/*}}}*/
|
|
|
|
/* TODO is link and more checks. */
|
|
protected function rm(string $path) : bool
|
|
{/*{{{*/
|
|
if (!file_exists($path)) {
|
|
return false;
|
|
} else if (is_file($path)) {
|
|
return unlink($path);
|
|
}
|
|
|
|
$ret = true;
|
|
|
|
$iterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator(
|
|
$path,
|
|
\FilesystemIterator::SKIP_DOTS
|
|
),
|
|
\RecursiveIteratorIterator::CHILD_FIRST
|
|
);
|
|
foreach ($iterator as $item) {
|
|
if ($item->isDir()) {
|
|
$ret = $ret && rmdir($item->getPathname());
|
|
} else {
|
|
$ret = $ret && unlink($item->getPathname());
|
|
}
|
|
}
|
|
return $ret && rmdir($path);
|
|
}/*}}}*/
|
|
|
|
/* TODO islink and more checks */
|
|
protected function cp_or_mv(string $src, string $dst, callable $cb) : bool
|
|
{/*{{{*/
|
|
if (!file_exists($src)) {
|
|
return false;
|
|
} else if (is_file($src)) {
|
|
return call_user_func($cb, $src, $dst);
|
|
}
|
|
|
|
if (!file_exists($dst)) {
|
|
$this->md($dst);
|
|
}
|
|
|
|
$iterator = new \RecursiveIteratorIterator(
|
|
new \RecursiveDirectoryIterator(
|
|
$src,
|
|
\FilesystemIterator::SKIP_DOTS
|
|
),
|
|
\RecursiveIteratorIterator::CHILD_FIRST
|
|
);
|
|
$cut_len = strlen($src)+1;
|
|
foreach ($iterator as $item) {
|
|
$src_path = $item->getPathname();
|
|
$sub = substr($src_path, $cut_len);
|
|
$dst_path = $dst . DIRECTORY_SEPARATOR . $sub;
|
|
$dst_parent = dirname($dst_path);
|
|
|
|
if (!is_dir($dst_parent)) {
|
|
if (!$this->md($dst_parent)) {
|
|
throw new Exception("Unable to create '$dst_parent'");
|
|
}
|
|
}
|
|
|
|
if ($item->isFile()) {
|
|
if (!call_user_func($cb, $src_path, $dst_path)) {
|
|
assert(is_string($cb));
|
|
throw new Exception("Unable to $cb '$src_path' to '$dst_path'");
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
}/*}}}*/
|
|
|
|
protected function cp(string $src, string $dst) : bool
|
|
{/*{{{*/
|
|
return $this->cp_or_mv($src, $dst, "copy");
|
|
}/*}}}*/
|
|
|
|
protected function mv(string $src, string $dst) : bool
|
|
{/*{{{*/
|
|
$ret = $this->cp_or_mv($src, $dst, "rename");
|
|
|
|
$ret = $ret && $this->rm($src);
|
|
|
|
return $ret;
|
|
}/*}}}*/
|
|
|
|
protected function download(string $url, string $dest_fn = NULL) : ?string
|
|
{/*{{{*/
|
|
$fd = NULL;
|
|
$retry = 0;
|
|
|
|
retry:
|
|
$ch = curl_init();
|
|
|
|
echo "CALL $url \n";
|
|
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
|
|
if ($dest_fn) {
|
|
$fd = fopen($dest_fn, "w+");
|
|
curl_setopt($ch, CURLOPT_FILE, $fd);
|
|
} else {
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
}
|
|
|
|
//curl_setopt($ch, CURLOPT_HEADER, false);
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
curl_setopt($ch, CURLOPT_USERAGENT, Config::getSdkUserAgentName());
|
|
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
|
|
|
$token = getenv('API_TOKEN');
|
|
if (!empty($token)) {
|
|
echo "**** define authorization header ! ****\n";
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-custom-header: top1','Authorization: Bearer '.$token]);
|
|
}
|
|
|
|
// workaround for <https://github.com/microsoft/php-sdk-binary-tools/issues/69>
|
|
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
|
|
|
$ret = curl_exec($ch);
|
|
|
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
if (false === $ret || 200 !== $code) {
|
|
$err = curl_error($ch);
|
|
curl_close($ch);
|
|
if ($dest_fn) {
|
|
fclose($fd);
|
|
}
|
|
if ($retry++ < 3) {
|
|
goto retry;
|
|
}
|
|
throw new Exception($err);
|
|
}
|
|
|
|
curl_close($ch);
|
|
|
|
if ($dest_fn) {
|
|
fclose($fd);
|
|
return NULL;
|
|
}
|
|
|
|
return $ret;
|
|
}/*}}}*/
|
|
|
|
/* TODO More detailed zip errors. */
|
|
protected function unzip(string $zip_fn, string $dest_fn, string $dest_dn = NULL) : void
|
|
{/*{{{*/
|
|
$zip = new \ZipArchive;
|
|
|
|
$res = $zip->open($zip_fn);
|
|
if (true !== $res) {
|
|
throw new Exception("Failed to open '$zip_fn'.");
|
|
}
|
|
|
|
$res = $zip->extractTo($dest_fn);
|
|
if (true !== $res) {
|
|
$zip->close();
|
|
throw new Exception("Failed to unzip '$zip_fn'.");
|
|
}
|
|
|
|
/* Not robust, useful for zips containing one dir sibling only in the root. */
|
|
if ($dest_dn) {
|
|
$stat = $zip->statIndex(0);
|
|
if (false === $stat) {
|
|
$zip->close();
|
|
throw new Exception("Failed to stat first index in '$zip_fn'.");
|
|
}
|
|
|
|
$zip->close();
|
|
|
|
/* Index of zero might be not the zipped folder, unusual but true. */
|
|
/*$name = $stat["name"];
|
|
if ("/" != substr($name, -1)) {
|
|
throw new Exception("'$name' is not a directory.");
|
|
}
|
|
$name = substr($name, 0, -1);*/
|
|
|
|
$name = rtrim($stat["name"], "/");
|
|
while (strstr($name, '/') !== false) {
|
|
$name = dirname($name);
|
|
}
|
|
|
|
$old_dir = $dest_fn . DIRECTORY_SEPARATOR . $name;
|
|
$new_dir = $dest_fn . DIRECTORY_SEPARATOR . $dest_dn;
|
|
if (file_exists($new_dir)) {
|
|
if (!$this->rm($new_dir)) {
|
|
throw new Exception("Failed to remove '$new_dir'.");
|
|
}
|
|
}
|
|
/* if (!$this->mv($old_dir, $new_dir)) { */
|
|
if (!rename($old_dir, $new_dir)) {
|
|
throw new Exception("Failed to rename '$old_dir' to '$new_dir'.");
|
|
}
|
|
} else {
|
|
$zip->close();
|
|
}
|
|
}/*}}}*/
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* tab-width: 4
|
|
* c-basic-offset: 4
|
|
* End:
|
|
* vim600: sw=4 ts=4 fdm=marker
|
|
* vim<600: sw=4 ts=4
|
|
*/
|