Skip to content

Commit

Permalink
Add WP_In_Memory_Filesystem and use more consistent methods names
Browse files Browse the repository at this point in the history
  • Loading branch information
adamziel committed Dec 31, 2024
1 parent 6bf961f commit e8b7a07
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 281 deletions.
21 changes: 14 additions & 7 deletions src/WordPress/Filesystem/WP_Abstract_Filesystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ abstract public function is_file($path);
*
* @example
*
* $fs->start_streaming_file($path);
* $fs->open_file_stream($path);
* while($fs->next_file_chunk()) {
* $chunk = $fs->get_file_chunk();
* // process $chunk
* }
* $fs->close_file_reader();
* $fs->close_file_stream();
*
* @param string $path The path to the file.
*/
abstract public function start_streaming_file($path);
abstract public function open_file_stream($path);

/**
* Get the next chunk of a file.
Expand All @@ -65,6 +65,13 @@ abstract public function next_file_chunk();
*/
abstract public function get_file_chunk();

/**
* Get the length of the streamed file.
*
* @return int|false The length of the file or false if the file is not streamed.
*/
abstract public function get_streamed_file_length();

/**
* Get the error message of the filesystem.
*
Expand All @@ -75,7 +82,7 @@ abstract public function get_error_message();
/**
* Close the file reader.
*/
abstract public function close_file_reader();
abstract public function close_file_stream();

// @TODO: Support for write methods, perhaps in a separate interface?
// abstract public function append_to($path, $data);
Expand All @@ -93,8 +100,8 @@ abstract public function close_file_reader();
* @param string $path The path to the file.
* @return string|false The contents of the file or false if the file does not exist.
*/
public function read_file($path) {
$this->start_streaming_file($path);
public function get_contents($path) {
$this->open_file_stream($path);
$body = '';
while($this->next_file_chunk()) {
$chunk = $this->get_file_chunk();
Expand All @@ -103,7 +110,7 @@ public function read_file($path) {
}
$body .= $chunk;
}
$this->close_file_reader();
$this->close_file_stream();
return $body;
}

Expand Down
164 changes: 164 additions & 0 deletions src/WordPress/Filesystem/WP_In_Memory_Filesystem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
<?php

namespace WordPress\Filesystem;

/**
* Represents an in-memory filesystem.
*/
class WP_In_Memory_Filesystem extends WP_Abstract_Filesystem {

private $files = [];
private $last_file_reader = null;

public function __construct() {
$this->files['/'] = [
'type' => 'dir',
'contents' => []
];
}

public function ls($parent = '/') {
$parent = rtrim($parent, '/');
if (!isset($this->files[$parent]) || $this->files[$parent]['type'] !== 'dir') {
return false;
}
return array_keys($this->files[$parent]['contents']);
}

public function is_dir($path) {
return isset($this->files[$path]) && $this->files[$path]['type'] === 'dir';
}

public function is_file($path) {
return isset($this->files[$path]) && $this->files[$path]['type'] === 'file';
}

public function exists($path) {
return isset($this->files[$path]);
}

private function get_parent_dir($path) {
$path = rtrim($path, '/');
$parent = dirname($path);
if($parent === '.') {
return '/';
}
return $parent;
}

public function open_file_stream($path) {
if($this->last_file_reader) {
$this->last_file_reader->close();
}
if (!$this->is_file($path)) {
return false;
}
$this->last_file_reader = \WordPress\ByteReader\WP_String_Reader::create($this->files[$path]['contents']);
return true;
}

public function next_file_chunk() {
return $this->last_file_reader->next_bytes();
}

public function get_file_chunk() {
return $this->last_file_reader->get_bytes();
}

public function get_streamed_file_length() {
return $this->last_file_reader->length();
}

public function get_error_message() {
return $this->last_file_reader->get_last_error();
}

public function close_file_stream() {
if($this->last_file_reader) {
$this->last_file_reader->close();
$this->last_file_reader = null;
}
}

public function rename($old_path, $new_path) {
if (!$this->exists($old_path)) {
return false;
}

$parent = $this->get_parent_dir($new_path);
if (!$this->is_dir($parent)) {
return false;
}

$this->files[$new_path] = $this->files[$old_path];
unset($this->files[$old_path]);
return true;
}

public function mkdir($path) {
if ($this->exists($path)) {
return false;
}

$parent = $this->get_parent_dir($path);
if (!$this->is_dir($parent)) {
return false;
}

$this->files[$path] = [
'type' => 'dir',
'contents' => []
];
$this->files[$parent]['contents'][basename($path)] = true;
return true;
}

public function rm($path) {
if (!$this->is_file($path)) {
return false;
}

$parent = $this->get_parent_dir($path);
unset($this->files[$parent]['contents'][basename($path)]);
unset($this->files[$path]);
return true;
}

public function rmdir($path, $options = []) {
$recursive = $options['recursive'] ?? false;
if (!$this->is_dir($path)) {
return false;
}

if ($recursive) {
$path = rtrim($path, '/');
foreach($this->ls($path) as $child) {
if($this->is_dir($path . '/' . $child)) {
$this->rmdir($path . '/' . $child, $options);
} else {
$this->rm($path . '/' . $child);
}
}
}

$parent = $this->get_parent_dir($path);
unset($this->files[$parent]['contents'][basename($path)]);
unset($this->files[$path]);
return true;
}

public function put_contents($path, $data) {
$parent = $this->get_parent_dir($path);
if (!$this->is_dir($parent)) {
return false;
}

$this->files[$path] = [
'type' => 'file',
'contents' => $data
];
$this->files[$parent]['contents'][basename($path)] = true;
return true;
}

}
8 changes: 6 additions & 2 deletions src/WordPress/Filesystem/WP_Local_Filesystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public function exists($path) {
// but that could suggest that the reader is a separate object
// and that we can have multiple readers open at the same time.
private $last_file_reader = null;
public function start_streaming_file($path) {
public function open_file_stream($path) {
if($this->last_file_reader) {
$this->last_file_reader->close();
}
Expand All @@ -73,11 +73,15 @@ public function get_file_chunk() {
return $this->last_file_reader->get_bytes();
}

public function get_streamed_file_length() {
return $this->last_file_reader->length();
}

public function get_error_message() {
return $this->last_file_reader->get_last_error();
}

public function close_file_reader() {
public function close_file_stream() {
if($this->last_file_reader) {
$this->last_file_reader->close();
$this->last_file_reader = null;
Expand Down
Loading

0 comments on commit e8b7a07

Please sign in to comment.