Browse Source

implement local directory browser

PHP-GTK3
yggverse 2 months ago
parent
commit
c66dd6b94c
  1. 72
      src/Entity/Browser/Container/Page/Content.php
  2. 132
      src/Model/Filesystem.php

72
src/Entity/Browser/Container/Page/Content.php

@ -103,17 +103,51 @@ class Content
{ {
case 'file': case 'file':
if (file_exists($address->getPath()) && is_readable($address->getPath())) switch (true)
{ {
switch ($address->getPath()) // Try directory
case (
$list = \Yggverse\Yoda\Model\Filesystem::getList(
$address->getPath()
)
):
$map = [];
foreach ($list as $item)
{ {
case is_dir($address->getPath()): $map[] = trim(
sprintf(
'=> file://%s %s',
$item['path'],
$item['name'] . (
$item['file'] ? null : '/'
)
)
);
}
// @TODO build fs listing $this->data->setGemtext(
implode(
PHP_EOL,
$map
) . PHP_EOL
);
$this->page->title->set(
basename(
$address->getPath()
),
'localhost'
);
break; break;
case str_ends_with($address->getPath(), '.gmi'): // Try open file by extension supported
case str_ends_with(
$address->getPath(),
'.gmi'
):
$title = null; $title = null;
@ -127,34 +161,32 @@ class Content
if ($title) // detect title by document h1 if ($title) // detect title by document h1
{ {
$this->page->title->set( $this->page->title->set(
$title $title,
'localhost'
); );
} }
break; else
{
default:
$this->page->title->set( $this->page->title->set(
'Oops!', basename(
'file extension not supported' $address->getPath()
); ),
'localhost'
$this->data->setPlain(
'File extension not supported'
); );
} }
}
else break;
{
default:
$this->page->title->set( $this->page->title->set(
'Failure', 'Failure',
'resource not found or not readable' 'resource not found or not readable'
); );
$this->data->setPlain( $this->data->setPlain(
'Could not open file' 'Could not open location'
); );
} }

132
src/Model/Filesystem.php

@ -81,6 +81,112 @@ class Filesystem
return $this->_base . $filename; return $this->_base . $filename;
} }
public static function getList(
?string $dirname,
string $sort = 'name',
int $order = SORT_ASC,
int $method = SORT_STRING | SORT_NATURAL | SORT_FLAG_CASE
): ?array
{
// Convert to realpath with ending slash
if (!$realpath = self::_getRealpath($dirname))
{
return null;
}
// Make sure requested path is directory
if (!is_dir($realpath))
{
return null;
}
// Begin list builder
$directories = [];
$files = [];
foreach ((array) scandir($realpath) as $name)
{
// Skip system locations
if (empty($name) || $name == '.')
{
continue;
}
// Try to build destination path
if (!$path = self::_getRealpath($realpath . $name))
{
continue;
}
// Context
switch (true)
{
case is_dir($path):
$directories[] =
[
'file' => false,
'path' => $path,
'name' => $name,
'link' => urlencode(
$name
),
'time' => filemtime(
$path
)
];
break;
case is_file($path):
$files[] =
[
'file' => true,
'path' => $path,
'name' => $name,
'link' => urlencode(
$name
),
'time' => filemtime(
$path
)
];
break;
}
}
// Sort order
array_multisort(
array_column(
$directories,
$sort
),
$order,
$method,
$directories
);
// Sort files by name ASC
array_multisort(
array_column(
$directories,
$sort
),
$order,
$method,
$directories
);
// Merge list
return array_merge(
$directories,
$files
);
}
private static function _fixDirectorySeparators( private static function _fixDirectorySeparators(
string $path, string $path,
string $separator = DIRECTORY_SEPARATOR string $separator = DIRECTORY_SEPARATOR
@ -95,4 +201,30 @@ class Filesystem
$path $path
); );
} }
// PHP::realpath extension appending slash to dir paths
private static function _getRealpath(
?string $path
): ?string
{
if (empty($path))
{
return null;
}
if (!$realpath = realpath($path))
{
return null;
}
if (is_dir($realpath))
{
$realpath = rtrim(
$realpath,
DIRECTORY_SEPARATOR
) . DIRECTORY_SEPARATOR;
}
return $realpath;
}
} }
Loading…
Cancel
Save