sterzycom/kirby/toolkit/lib/folder.php

406 lines
No EOL
8.3 KiB
PHP

<?php
/**
* Folder
*
* @package Kirby Toolkit
* @author Bastian Allgeier <bastian@getkirby.com>
* @link http://getkirby.com
* @copyright Bastian Allgeier
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
class Folder {
// the root for the directory
protected $root = null;
// a cache for the scanned inventory
protected $inventory = null;
/**
* Constructor
*/
public function __construct($root) {
if(file_exists($root) && is_file($root)) throw new Exception('Invalid folder: ' . $root);
$this->root = $root;
}
/**
* Returns the root of the directory
*/
public function root() {
return $this->root;
}
/**
* Returns a md5 hash of the root
*/
public function hash() {
return md5($this->root);
}
/**
* Returns the name of the directory without the full path
*
* @return string
*/
public function name() {
return basename($this->root);
}
/**
* Returns the parent directory object
*
* @return Directory
*/
public function parent() {
return new static(dirname($this->root));
}
/**
* Checks if the dir exists
*
* @return boolean
*/
public function exists() {
return is_dir($this->root);
}
/**
* Creates the directory if it does not exist yet
*
* @param boolean $recursive
* @return boolean
*/
public function make($recursive = true) {
return dir::make($this->root, $recursive);
}
/**
* Alternative for make
*
* @param boolean $recursive
* @return boolean
*/
public function create($recursive = true) {
return $this->make($recursive);
}
/**
* Returns the entire content of the directory
*
* @return array
*/
public function inventory() {
if(!is_dir($this->root)) return array();
return $this->inventory = is_null($this->inventory) ? scandir($this->root) : $this->inventory;
}
/**
* Reads the directory content and returns an array with file objects
*
* @param array $ignore
* @return array
*/
public function scan($ignore = null) {
$skip = is_array($ignore) ? $ignore : a::get(dir::$defaults, 'ignore', array());
return empty($skip) ? $this->inventory() : (array)array_diff($this->inventory(), $skip);
}
/**
* Alternative for scan
*
* @param array $ignore
* @return array
*/
public function read($ignore = null) {
return $this->scan($ignore);
}
/**
* Returns a collection with full File and Directory objects
* for each item in the directory
*
* @param array $ignore
* @return Collection
*/
public function content($ignore = null) {
$raw = $this->scan($ignore);
$root = $this->root;
$content = new Collection();
foreach($raw as $file) {
if(is_dir($root . DS . $file)) {
$content->append($file, new static($root . DS . $file));
} else {
$content->append($file, new Media($root . DS . $file));
}
}
return $content;
}
/**
* Return a collection of all files within the directory
*
* @param array $ignore
* @param boolean $plain
* @return mixed When $plain is true an array will be returned. Otherwise a Collection
*/
public function files($ignore = null, $plain = false) {
$raw = $this->scan($ignore);
if($plain) {
$content = array();
foreach($raw as $file) {
if(is_file($this->root . DS . $file)) $content[] = $file;
}
} else {
$content = new Collection();
foreach($raw as $file) {
if(is_file($this->root . DS . $file)) {
$content->append($file, new Media($this->root . DS . $file));
}
}
}
return $content;
}
/**
* Return a collection of subfolders
*
* @param array $ignore
* @param boolean $plain
* @return mixed If $plain is true an array will be returned. Otherwise a Collection
*/
public function children($ignore = null, $plain = false) {
$raw = $this->scan($ignore);
if($plain) {
$content = array();
foreach($raw as $file) {
if(is_dir($this->root . DS . $file)) $content[] = $file;
}
} else {
$content = new Collection();
foreach($raw as $file) {
if(is_dir($this->root . DS . $file)) {
$content->append($file, new static($this->root . DS . $file));
}
}
}
return $content;
}
/**
* Returns a subfolder object by path
*
* @return mixed Directory
*/
public function child($path) {
$root = $this->root . DS . str_replace('/', DS, $path);
if(!is_dir($root)) return false;
return new static($root);
}
/**
* Corresponding method to File::type()
* which makes it possible to filter a collection
* of files and directories by type.
*
* @return string
*/
public function type() {
return 'directory';
}
/**
* Moves the directory to a new location
*
* @param string $to
* @return boolean
*/
public function move($to) {
if(!dir::move($this->root, $to)) {
return false;
} else {
$this->root = true;
return true;
}
}
/**
* Copies the directory to a new location
*
* @param string $to
* @return boolean
*/
public function copy($to) {
// Make destination directory
$copy = new static($to);
if(!$copy->make()) return false;
// Loop through all subfiles and folders
foreach($this->content() as $item) {
if(is_a($item, 'Folder')) {
$dest = $to . DS . $item->name();
} else {
$dest = $to . DS . $item->filename();
}
if(!$item->copy($dest)) return false;
}
return $copy;
}
/**
* Deletes the directory
*
* @param boolean $keep Set this to true to keep the directory but delete all its content
* @return boolean
*/
public function delete($keep = false) {
$items = $this->content(array('.', '..'));
foreach($items as $item) $item->delete();
return $keep ? true : @rmdir($this->root);
}
/**
* Alternative for delete
*
* @param boolean $keep Set this to true to keep the directory but delete all its content
* @return boolean
*/
public function remove($keep = false) {
return $this->delete($keep);
}
/**
* Deletes all contents of the directory
*
* @return boolean
*/
public function flush() {
return $this->delete(true);
}
/**
* Alternative for flush
*
* @return boolean
*/
public function clean() {
return $this->delete(true);
}
/**
* Returns the entire size of the directory and all its contents
*
* @return int
*/
public function size() {
$size = 0;
$items = $this->content(array('.', '..'));
foreach($items AS $item) $size += $item->size();
return $size;
}
/**
* Returns the size as a human-readable string
*
* @return string
*/
public function niceSize() {
return f::niceSize($this->size());
}
/**
* Recursively check when the dir and all
* subfolders have been modified for the last time.
*
* @return int
*/
public function modified($format = null, $handler = 'date') {
$modified = filemtime($this->root);
$items = $this->scan(array('.', '..'));
foreach($items AS $item) {
if(is_file($this->root . DS . $item)) {
$newModified = filemtime($this->root . DS . $item);
} else {
$object = new static($this->root . DS . $item);
$newModified = $object->modified();
}
$modified = ($newModified > $modified) ? $newModified : $modified;
}
return !is_null($format) ? $handler($format, $modified) : $modified;
}
/**
* Checks if the directory is writable
*
* @param boolean $recursive
* @return boolean
*/
public function isWritable($recursive = false) {
if($recursive) {
if(!$this->isWritable()) return false;
foreach($this->content() as $f) {
if(!$f->isWritable(true)) return false;
}
return true;
}
return is_writable($this->root);
}
/**
* Checks if the directory is readable
*
* @return boolean
*/
public function isReadable() {
return is_readable($this->root);
}
/**
* Makes it possible to echo the entire object
*
* @return string
*/
public function __toString() {
return $this->root;
}
}