maj grav
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Filesystem;
|
||||
|
||||
use Grav\Common\Utils;
|
||||
|
||||
abstract class Archiver
|
||||
{
|
||||
protected $options = [
|
||||
'exclude_files' => ['.DS_Store'],
|
||||
'exclude_paths' => []
|
||||
];
|
||||
|
||||
protected $archive_file;
|
||||
|
||||
public static function create($compression)
|
||||
{
|
||||
if ($compression === 'zip') {
|
||||
return new ZipArchiver();
|
||||
}
|
||||
|
||||
return new ZipArchiver();
|
||||
}
|
||||
|
||||
public function setArchive($archive_file)
|
||||
{
|
||||
$this->archive_file = $archive_file;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setOptions($options)
|
||||
{
|
||||
// Set infinite PHP execution time if possible.
|
||||
if (function_exists('set_time_limit') && !Utils::isFunctionDisabled('set_time_limit')) {
|
||||
set_time_limit(0);
|
||||
}
|
||||
|
||||
$this->options = $options + $this->options;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public abstract function compress($folder, callable $status = null);
|
||||
|
||||
public abstract function extract($destination, callable $status = null);
|
||||
|
||||
public abstract function addEmptyFolders($folders, callable $status = null);
|
||||
|
||||
protected function getArchiveFiles($rootPath)
|
||||
{
|
||||
$exclude_paths = $this->options['exclude_paths'];
|
||||
$exclude_files = $this->options['exclude_files'];
|
||||
$dirItr = new \RecursiveDirectoryIterator($rootPath, \RecursiveDirectoryIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS | \FilesystemIterator::UNIX_PATHS);
|
||||
$filterItr = new RecursiveDirectoryFilterIterator($dirItr, $rootPath, $exclude_paths, $exclude_files);
|
||||
$files = new \RecursiveIteratorIterator($filterItr, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
return $files;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav.Common.FileSystem
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -48,7 +49,7 @@ abstract class Folder
|
||||
/**
|
||||
* Recursively find the last modified time under given path by file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $path
|
||||
* @param string $extensions which files to search for specifically
|
||||
*
|
||||
* @return int
|
||||
@@ -86,7 +87,7 @@ abstract class Folder
|
||||
/**
|
||||
* Recursively md5 hash all files in a path
|
||||
*
|
||||
* @param $path
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public static function hashAllFiles($path)
|
||||
@@ -141,6 +142,7 @@ abstract class Folder
|
||||
*/
|
||||
public static function getRelativePathDotDot($path, $base)
|
||||
{
|
||||
// Normalize paths.
|
||||
$base = preg_replace('![\\\/]+!', '/', $base);
|
||||
$path = preg_replace('![\\\/]+!', '/', $path);
|
||||
|
||||
@@ -148,8 +150,8 @@ abstract class Folder
|
||||
return '';
|
||||
}
|
||||
|
||||
$baseParts = explode('/', isset($base[0]) && '/' === $base[0] ? substr($base, 1) : $base);
|
||||
$pathParts = explode('/', isset($path[0]) && '/' === $path[0] ? substr($path, 1) : $path);
|
||||
$baseParts = explode('/', ltrim($base, '/'));
|
||||
$pathParts = explode('/', ltrim($path, '/'));
|
||||
|
||||
array_pop($baseParts);
|
||||
$lastPart = array_pop($pathParts);
|
||||
@@ -164,7 +166,7 @@ abstract class Folder
|
||||
$path = str_repeat('../', count($baseParts)) . implode('/', $pathParts);
|
||||
|
||||
return '' === $path
|
||||
|| '/' === $path[0]
|
||||
|| strpos($path, '/') === 0
|
||||
|| false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos)
|
||||
? "./$path" : $path;
|
||||
}
|
||||
@@ -199,14 +201,14 @@ abstract class Folder
|
||||
}
|
||||
|
||||
$compare = isset($params['compare']) ? 'get' . $params['compare'] : null;
|
||||
$pattern = isset($params['pattern']) ? $params['pattern'] : null;
|
||||
$filters = isset($params['filters']) ? $params['filters'] : null;
|
||||
$recursive = isset($params['recursive']) ? $params['recursive'] : true;
|
||||
$levels = isset($params['levels']) ? $params['levels'] : -1;
|
||||
$pattern = $params['pattern'] ?? null;
|
||||
$filters = $params['filters'] ?? null;
|
||||
$recursive = $params['recursive'] ?? true;
|
||||
$levels = $params['levels'] ?? -1;
|
||||
$key = isset($params['key']) ? 'get' . $params['key'] : null;
|
||||
$value = isset($params['value']) ? 'get' . $params['value'] : ($recursive ? 'getSubPathname' : 'getFilename');
|
||||
$folders = isset($params['folders']) ? $params['folders'] : true;
|
||||
$files = isset($params['files']) ? $params['files'] : true;
|
||||
$value = 'get' . ($params['value'] ?? ($recursive ? 'SubPathname' : 'Filename'));
|
||||
$folders = $params['folders'] ?? true;
|
||||
$files = $params['files'] ?? true;
|
||||
|
||||
/** @var UniformResourceLocator $locator */
|
||||
$locator = Grav::instance()['locator'];
|
||||
@@ -233,7 +235,7 @@ abstract class Folder
|
||||
/** @var \RecursiveDirectoryIterator $file */
|
||||
foreach ($iterator as $file) {
|
||||
// Ignore hidden files.
|
||||
if ($file->getFilename()[0] === '.') {
|
||||
if (strpos($file->getFilename(), '.') === 0) {
|
||||
continue;
|
||||
}
|
||||
if (!$folders && $file->isDir()) {
|
||||
@@ -255,7 +257,7 @@ abstract class Folder
|
||||
if (isset($filters['value'])) {
|
||||
$filter = $filters['value'];
|
||||
if (is_callable($filter)) {
|
||||
$filePath = call_user_func($filter, $file);
|
||||
$filePath = $filter($file);
|
||||
} else {
|
||||
$filePath = preg_replace($filter, '', $filePath);
|
||||
}
|
||||
@@ -316,7 +318,7 @@ abstract class Folder
|
||||
|
||||
if (!$success) {
|
||||
$error = error_get_last();
|
||||
throw new \RuntimeException($error['message']);
|
||||
throw new \RuntimeException($error['message'] ?? 'Unknown error');
|
||||
}
|
||||
|
||||
// Make sure that the change will be detected when caching.
|
||||
@@ -416,23 +418,27 @@ abstract class Folder
|
||||
*/
|
||||
public static function create($folder)
|
||||
{
|
||||
if (is_dir($folder)) {
|
||||
// Silence error for open_basedir; should fail in mkdir instead.
|
||||
if (@is_dir($folder)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$success = @mkdir($folder, 0777, true);
|
||||
|
||||
if (!$success) {
|
||||
$error = error_get_last();
|
||||
throw new \RuntimeException($error['message']);
|
||||
// Take yet another look, make sure that the folder doesn't exist.
|
||||
clearstatcache(true, $folder);
|
||||
if (!@is_dir($folder)) {
|
||||
throw new \RuntimeException(sprintf('Unable to create directory: %s', $folder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive copy of one directory to another
|
||||
*
|
||||
* @param $src
|
||||
* @param $dest
|
||||
* @param string $src
|
||||
* @param string $dest
|
||||
*
|
||||
* @return bool
|
||||
* @throws \RuntimeException
|
||||
@@ -448,7 +454,7 @@ abstract class Folder
|
||||
|
||||
// If the destination directory does not exist create it
|
||||
if (!is_dir($dest)) {
|
||||
static::mkdir($dest);
|
||||
static::create($dest);
|
||||
}
|
||||
|
||||
// Open the source directory to read in files
|
||||
@@ -475,7 +481,7 @@ abstract class Folder
|
||||
protected static function doDelete($folder, $include_target = true)
|
||||
{
|
||||
// Special case for symbolic links.
|
||||
if (is_link($folder)) {
|
||||
if ($include_target && is_link($folder)) {
|
||||
return @unlink($folder);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Filesystem;
|
||||
|
||||
class RecursiveDirectoryFilterIterator extends \RecursiveFilterIterator
|
||||
{
|
||||
protected static $root;
|
||||
protected static $ignore_folders;
|
||||
protected static $ignore_files;
|
||||
|
||||
/**
|
||||
* Create a RecursiveFilterIterator from a RecursiveIterator
|
||||
*
|
||||
* @param \RecursiveIterator $iterator
|
||||
* @param string $root
|
||||
* @param array $ignore_folders
|
||||
* @param array $ignore_files
|
||||
*/
|
||||
public function __construct(\RecursiveIterator $iterator, $root, $ignore_folders, $ignore_files)
|
||||
{
|
||||
parent::__construct($iterator);
|
||||
|
||||
$this::$root = $root;
|
||||
$this::$ignore_folders = $ignore_folders;
|
||||
$this::$ignore_files = $ignore_files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the current element of the iterator is acceptable
|
||||
*
|
||||
* @return bool true if the current element is acceptable, otherwise false.
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
/** @var \SplFileInfo $file */
|
||||
$file = $this->current();
|
||||
$filename = $file->getFilename();
|
||||
$relative_filename = str_replace($this::$root . '/', '', $file->getPathname());
|
||||
|
||||
if ($file->isDir()) {
|
||||
if (in_array($relative_filename, $this::$ignore_folders, true)) {
|
||||
return false;
|
||||
}
|
||||
if (!in_array($filename, $this::$ignore_files, true)) {
|
||||
return true;
|
||||
}
|
||||
} elseif ($file->isFile() && !in_array($filename, $this::$ignore_files, true)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getChildren()
|
||||
{
|
||||
/** @var RecursiveDirectoryFilterIterator $iterator */
|
||||
$iterator = $this->getInnerIterator();
|
||||
|
||||
return new self($iterator->getChildren(), $this::$root, $this::$ignore_folders, $this::$ignore_files);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav.Common.FileSystem
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
@@ -12,19 +13,23 @@ use Grav\Common\Grav;
|
||||
|
||||
class RecursiveFolderFilterIterator extends \RecursiveFilterIterator
|
||||
{
|
||||
protected static $folder_ignores;
|
||||
protected static $ignore_folders;
|
||||
|
||||
/**
|
||||
* Create a RecursiveFilterIterator from a RecursiveIterator
|
||||
*
|
||||
* @param \RecursiveIterator $iterator
|
||||
* @param array $ignore_folders
|
||||
*/
|
||||
public function __construct(\RecursiveIterator $iterator)
|
||||
public function __construct(\RecursiveIterator $iterator, $ignore_folders = [])
|
||||
{
|
||||
parent::__construct($iterator);
|
||||
if (empty($this::$folder_ignores)) {
|
||||
$this::$folder_ignores = Grav::instance()['config']->get('system.pages.ignore_folders');
|
||||
|
||||
if (empty($ignore_folders)) {
|
||||
$ignore_folders = Grav::instance()['config']->get('system.pages.ignore_folders');
|
||||
}
|
||||
|
||||
$this::$ignore_folders = $ignore_folders;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -34,12 +39,9 @@ class RecursiveFolderFilterIterator extends \RecursiveFilterIterator
|
||||
*/
|
||||
public function accept()
|
||||
{
|
||||
/** @var $current \SplFileInfo */
|
||||
/** @var \SplFileInfo $current */
|
||||
$current = $this->current();
|
||||
|
||||
if ($current->isDir() && !in_array($current->getFilename(), $this::$folder_ignores, true)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return $current->isDir() && !in_array($current->getFilename(), $this::$ignore_folders, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package Grav\Common\Filesystem
|
||||
*
|
||||
* @copyright Copyright (C) 2015 - 2019 Trilby Media, LLC. All rights reserved.
|
||||
* @license MIT License; see LICENSE file for details.
|
||||
*/
|
||||
|
||||
namespace Grav\Common\Filesystem;
|
||||
|
||||
class ZipArchiver extends Archiver
|
||||
{
|
||||
|
||||
public function extract($destination, callable $status = null)
|
||||
{
|
||||
$zip = new \ZipArchive();
|
||||
$archive = $zip->open($this->archive_file);
|
||||
|
||||
if ($archive === true) {
|
||||
Folder::create($destination);
|
||||
|
||||
if (!$zip->extractTo($destination)) {
|
||||
throw new \RuntimeException('ZipArchiver: ZIP failed to extract ' . $this->archive_file . ' to ' . $destination);
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
return $this;
|
||||
}
|
||||
|
||||
throw new \RuntimeException('ZipArchiver: Failed to open ' . $this->archive_file);
|
||||
}
|
||||
|
||||
public function compress($source, callable $status = null)
|
||||
{
|
||||
if (!extension_loaded('zip')) {
|
||||
throw new \InvalidArgumentException('ZipArchiver: Zip PHP module not installed...');
|
||||
}
|
||||
|
||||
if (!file_exists($source)) {
|
||||
throw new \InvalidArgumentException('ZipArchiver: ' . $source . ' cannot be found...');
|
||||
}
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
if (!$zip->open($this->archive_file, \ZipArchive::CREATE)) {
|
||||
throw new \InvalidArgumentException('ZipArchiver:' . $this->archive_file . ' cannot be created...');
|
||||
}
|
||||
|
||||
// Get real path for our folder
|
||||
$rootPath = realpath($source);
|
||||
|
||||
$files = $this->getArchiveFiles($rootPath);
|
||||
|
||||
$status && $status([
|
||||
'type' => 'count',
|
||||
'steps' => iterator_count($files),
|
||||
]);
|
||||
|
||||
foreach ($files as $file) {
|
||||
$filePath = $file->getPathname();
|
||||
$relativePath = ltrim(substr($filePath, strlen($rootPath)), '/');
|
||||
|
||||
if ($file->isDir()) {
|
||||
$zip->addEmptyDir($relativePath);
|
||||
} else {
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
|
||||
$status && $status([
|
||||
'type' => 'progress',
|
||||
]);
|
||||
}
|
||||
|
||||
$status && $status([
|
||||
'type' => 'message',
|
||||
'message' => 'Compressing...'
|
||||
]);
|
||||
|
||||
$zip->close();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addEmptyFolders($folders, callable $status = null)
|
||||
{
|
||||
if (!extension_loaded('zip')) {
|
||||
throw new \InvalidArgumentException('ZipArchiver: Zip PHP module not installed...');
|
||||
}
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
if (!$zip->open($this->archive_file)) {
|
||||
throw new \InvalidArgumentException('ZipArchiver: ' . $this->archive_file . ' cannot be opened...');
|
||||
}
|
||||
|
||||
$status && $status([
|
||||
'type' => 'message',
|
||||
'message' => 'Adding empty folders...'
|
||||
]);
|
||||
|
||||
foreach($folders as $folder) {
|
||||
$zip->addEmptyDir($folder);
|
||||
$status && $status([
|
||||
'type' => 'progress',
|
||||
]);
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user