abstract class FileSystemBase in Forena Reports 8
Hierarchy
- class \Drupal\forena\File\FileSystemBase implements FileInterface
Expanded class hierarchy of FileSystemBase
File
- src/
File/ FileSystemBase.php, line 9 - FileSystemBase.inc File toolbox for manipulating files contained tn the report directory.
Namespace
Drupal\forena\FileView source
abstract class FileSystemBase implements FileInterface {
const CACHE_KEY = 'filesystem';
// Location to write files to.
public $write_dir;
// Locations to search for files.
public $includes = [];
//Other places to look for a directory.
// Index of fields organized by extension then base name
public $type_index = [];
// Index of fields organized by base name then extension.
public $name_index = [];
// Indicates whether the directory needs scanning.
public $needScan = TRUE;
// Indicates whether state needs saving
public $needSave = FALSE;
// Cache of all infomration about files.
public $cache;
// The base directory where reports can be written to.
public $dir = '';
// Indicates whether the cache has been validated once or not
public $validated = FALSE;
public $cacheKey;
public function __construct() {
$this->cacheKey = static::CACHE_KEY;
}
/**
* Recursive function which scans the directory and loads the base indexes.
* @param $directory
* Scans a directory ignoring hidden files.
* @param $files
*/
private function scanDirectory(&$directory, &$files) {
// Scan the directory for files.
$d = @dir($directory);
if ($d) {
while (false !== ($file = $d
->read())) {
$file_path = rtrim($d->path, '/') . '/' . trim($file, '/');
// Determine extension
if (is_file($file_path)) {
@(list($base_file, $ext) = explode('.', $file, 2));
$files[$ext][$file_path] = filemtime($file_path);
}
elseif (is_dir($file_path)) {
if (strpos($file, '.') !== 0) {
$this
->scanDirectory($file_path, $files);
}
}
}
}
if ($d) {
$d
->close();
}
}
/**
* Parse a drectory
* @param string $directory
*/
protected function scanInclude($directory) {
$is_include = strpos($directory, $this->dir) !== 0;
$files = array();
$this
->scanDirectory($directory, $files);
foreach ($files as $ext => $files_of_type) {
foreach ($files_of_type as $file => $mtime) {
// Determine file name without extension.
$base_name = substr($file, strlen($directory) + 1, -1 * (strlen($ext) + 1));
// NO Cache entry exists.
if (!isset($this->cache[$ext][$base_name])) {
$obj = new \stdClass();
$obj->file = $file;
$obj->ext = $ext;
$obj->base = $base_name;
$obj->mtime = $mtime;
$obj->include = $is_include;
$obj->override = FALSE;
$this
->extractMetaData($obj);
$this->cache[$ext][$base_name] = $obj;
}
else {
// If its our first pass on this replace the entry
$entry = $this->cache[$ext][$base_name];
// Find out if we are replacing an include
if (!$is_include && $entry->include) {
$entry->file = $file;
$entry->mtime = $mtime;
$entry->include = $is_include;
$entry->override = TRUE;
$this
->extractMetaData($entry);
$this->needSave = TRUE;
}
// Find out it is the same file and it needs to be changed.
if ($entry->file == $file && $entry->mtime != $mtime) {
$entry->mtime = $mtime;
$this
->extractMetaData($entry);
$this->needSave = TRUE;
}
// If its a different file make sure its override is set
if ($entry->file != $file && !$entry->override) {
$entry->override = TRUE;
$this->needSave = TRUE;
}
unset($this->filesToDelete[$ext][$base_name]);
}
}
}
}
private function setFilesToDelete() {
$this->filesToDelete = array();
//Quickly make a list of files in the cache right now.
if ($this->cache) {
foreach ($this->cache as $ext => $files_of_type) {
$this->filesToDelete[$ext] = array_fill_keys(array_keys($files_of_type), 1);
}
}
}
private function deleteMissingEntries() {
foreach ($this->filesToDelete as $ext => $files_of_type) {
foreach ($files_of_type as $base_name => $val) {
unset($this->cache[$ext][$base_name]);
$this->needSave = TRUE;
}
}
}
public function scan() {
// Add the base report files.
if ($this->needScan) {
$this
->scanInclude($this->dir);
// Now add the module provided ones.
if ($this->includes) {
foreach ($this->includes as $directory) {
$this
->scanInclude($directory);
}
}
if ($this->needSave) {
$this
->setDirectoryState();
}
}
}
public function getDirectoryState() {
return \Drupal::state()
->get($this->cacheKey);
}
public function setDirectoryState() {
if ($this->cacheKey) {
return \Drupal::state()
->set($this->cacheKey, $this->cache);
}
}
/**
* Revert an individual report
* @param $file
* @return int
* Number of files reverted.
*/
public function revert($file) {
$i = 0;
if ($this
->includeExists($file)) {
$file_to_delete = $this->dir . '/' . $file;
if (file_exists($file_to_delete)) {
if (is_writeable(dirname($file_to_delete))) {
drupal_set_message(t('Removing customization %s', array(
'%s' => $file_to_delete,
)));
unlink($file_to_delete);
$i++;
}
else {
drupal_set_message(t('Unable to revert %s', array(
'%s' => $file_to_delete,
)), 'error');
}
}
}
return $i;
}
/**
* Determine if the file exists in the include path.
* @param $file
* @return bool
* TRUE indicates that a base file exists on include path.
*/
public function includeExists($file) {
$found = false;
$i = 0;
while (isset($this->includes[$i]) && !$found) {
$filename = $this->includes[$i] . '/' . $file;
if (file_exists($this->includes[$i] . '/' . $file)) {
$found = TRUE;
}
$i++;
}
return $found;
}
/**
* Return the full path to the filename
*
* @param $filename
* @return string
* Fully qualified fiel name.
*/
public function path($filename, $use_include = TRUE) {
$path = $this->dir . '/' . $filename;
if ($use_include && !file_exists($path)) {
foreach ($this->includes as $dir) {
if (file_exists($dir . '/' . $filename)) {
$path = $dir . '/' . $filename;
}
}
}
return $path;
}
/**
* Return the directory portion of a report filename.
* @param string $filename
* relative path to file
* @return string
* Name of directory containing the file.
*/
public function directory($filename) {
@(list($dir, $name_part) = explode('/', $filename, -1));
return $this->dir . '/' . $dir;
}
/**
* Return whether the file exists.
* @param string $filename
* Relative path to file
*/
public function exists($filename, $use_include = TRUE) {
$path = $this
->path($filename, $use_include);
return file_exists($path);
}
/**
* Return the contents of a file located in the report directory
* @param string $filename
* filename and extension for report file.
* @return
* Contents of file
*/
public function contents($filename) {
$path = $this
->path($filename);
if (file_exists($path)) {
return file_get_contents($path);
}
else {
return '';
}
}
/**
* Get all metadata for files of a specific extension.
* @param $ext
* File extension being retrieved
* @return array
* Array of metadata entries keyed by base filename.
*/
protected function allMetadataForExt($ext) {
if (isset($this->cache[$ext])) {
return $this->cache[$ext];
}
else {
return [];
}
}
function verifyDirectory($fullpath, $recursive = FALSE) {
static $path = '';
$success = TRUE;
if (!$recursive) {
$path = $this->dir;
if (!is_writable($path)) {
drupal_set_message(t('Directory %s is not modifiable', array(
'%s' => $path,
)), 'error');
return FALSE;
}
}
@(list($dir, $file) = explode('/', $fullpath, 2));
$path .= '/' . $dir;
// Path
if (!file_exists($path) && $file) {
@mkdir($path);
if (!is_writable($path)) {
drupal_set_message(t('Error creating directory %path', array(
'%path' => $path,
)), 'error');
return FALSE;
}
}
// Recurse to next file.
if ($file && strpos($file, '/')) {
$this
->verifyDirectory($file, TRUE);
}
return TRUE;
}
/**
* Save a file into the report directory.
* @param string $filename
* @param string $data
* @return void
*/
public function save($filename, $data) {
$path = $this->dir . '/' . $filename;
$this
->verifyDirectory($filename);
if (is_writable($path) || !file_exists($path) && is_writable(dirname($path))) {
file_put_contents($path, $data);
}
else {
Frx::error(t('Insufficient privileges to write file.'));
}
}
/**
* Delete a file from the directory.
* @param string $filename
* @return bool
*/
public function delete($filename) {
$path = $this->dir . '/' . $filename;
$dir = getcwd();
$do = TRUE;
if (file_exists($path) && is_writeable($path) && is_writable(dirname($path))) {
$info = pathinfo($path);
chdir(dirname($path));
$do = unlink($info['basename']);
chdir($dir);
}
return $do;
}
/**
* Retrieve path info
* @param string $filename filename used for data
* @param bool $use_include boolean value determining whether to search
* include path.
* @return mixed
*/
public function pathinfo($filename, $use_include = TRUE) {
return pathinfo($this
->path($filename, $use_include));
}
/**
* Return an indicator as to whether the file is savable.
* New files can be saved if the directory is writabel.
* @param string $filename
* @return bool
*/
public function isWritable($filename) {
return is_writeable($this->dir . "/{$filename}") || !file_exists($this->dir . "/{$filename}");
}
/**
* Returns the cache entry based on a filename.
* @param string $filename
* @return object
*/
public function getMetaData($filename) {
list($base_name, $ext) = explode('.', $filename, 2);
$cache = isset($this->cache[$ext][$base_name]) ? $this->cache[$ext][$base_name] : null;
return $cache;
}
/**
* Test whether file is overriding code provided files.
* @param $filename
* @return mixed
*/
public function isOverriden($filename) {
$cache = $this
->getMetaData($filename);
return $cache->override;
}
/**
* Determine whether the file is a cusomt implmentation.
* @param $filename
* @return bool
*/
public function isCustom($filename) {
$cache = $this
->getMetaData($filename);
return !$cache->include;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
FileInterface:: |
public | function | Loads metadata into object based on file type. | 2 |
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
public | property | ||
FileSystemBase:: |
protected | function | Get all metadata for files of a specific extension. | |
FileSystemBase:: |
constant | 1 | ||
FileSystemBase:: |
public | function |
Return the contents of a file located in the report directory Overrides FileInterface:: |
|
FileSystemBase:: |
public | function |
Delete a file from the directory. Overrides FileInterface:: |
1 |
FileSystemBase:: |
private | function | ||
FileSystemBase:: |
public | function | Return the directory portion of a report filename. | |
FileSystemBase:: |
public | function |
Return whether the file exists. Overrides FileInterface:: |
|
FileSystemBase:: |
public | function | 1 | |
FileSystemBase:: |
public | function |
Returns the cache entry based on a filename. Overrides FileInterface:: |
|
FileSystemBase:: |
public | function | Determine if the file exists in the include path. | |
FileSystemBase:: |
public | function |
Determine whether the file is a cusomt implmentation. Overrides FileInterface:: |
|
FileSystemBase:: |
public | function |
Test whether file is overriding code provided files. Overrides FileInterface:: |
|
FileSystemBase:: |
public | function |
Return an indicator as to whether the file is savable.
New files can be saved if the directory is writabel. Overrides FileInterface:: |
|
FileSystemBase:: |
public | function | Return the full path to the filename | |
FileSystemBase:: |
public | function | Retrieve path info | |
FileSystemBase:: |
public | function | Revert an individual report | |
FileSystemBase:: |
public | function |
Save a file into the report directory. Overrides FileInterface:: |
1 |
FileSystemBase:: |
public | function | ||
FileSystemBase:: |
private | function | Recursive function which scans the directory and loads the base indexes. | |
FileSystemBase:: |
protected | function | Parse a drectory | |
FileSystemBase:: |
public | function | 1 | |
FileSystemBase:: |
private | function | ||
FileSystemBase:: |
function | |||
FileSystemBase:: |
public | function | 2 |