taskman_config/scan.inc.php

228 lines
4.8 KiB
PHP

<?php
namespace taskman;
use Exception;
class ConfigDirFiles implements \ArrayAccess, \Countable, \Iterator
{
private array $base_dirs;
/*var array<string, string[]>*/
private array $base_dir2files = array();
private $iter_pos = 0;
function __construct(array $base_dir2files = array(), ?array $base_dirs = null)
{
foreach($base_dir2files as $dir => $files)
$this->base_dir2files[$dir] = $files;
if($base_dirs === null)
$this->base_dirs = array_keys($base_dir2files);
else
$this->base_dirs = $base_dirs;
}
static function makeFor(ConfigManager $mgr) : ConfigDirFiles
{
return new ConfigDirFiles([], $mgr->getGlobals()->base_dirs);
}
function clear()
{
$this->base_dir2files = array();
}
function isEmpty() : bool
{
return empty($this->base_dir2files);
}
function count() : int
{
$total = 0;
foreach($this->base_dir2files as $base_dir => $files)
$total += count($files);
return $total;
}
function apply(callable $fn)
{
foreach($this->base_dir2files as $base_dir => $files)
$this->base_dir2files[$base_dir] = $fn($base_dir, $files);
}
function filter(callable $filter)
{
foreach($this->base_dir2files as $base_dir => $files)
{
$filtered = array_filter($files, $filter);
//NOTE: don't want any index gaps
$this->base_dir2files[$base_dir] = array_values($filtered);
}
}
function forEachFile(callable $fn)
{
foreach($this->base_dir2files as $base_dir => $files)
{
foreach($files as $file)
$fn($base_dir, $file);
}
}
function addFile(string $file, bool $unique = false)
{
$this->add(config_map_base_dir($this->base_dirs, $file, normalized: true), $file, $unique);
}
function add(string $base_dir, string $file, bool $unique = false)
{
if(!isset($this->base_dir2files[$base_dir]))
$this->base_dir2files[$base_dir] = array();
if(!$unique || !in_array($file, $this->base_dir2files[$base_dir]))
$this->base_dir2files[$base_dir][] = $file;
}
function getMap() : array
{
return $this->base_dir2files;
}
//returns [[base_dir, file1], [base_dir, file2], ...]
function getFlatArray() : array
{
$flat = [];
foreach($this->base_dir2files as $base_dir => $files)
{
foreach($files as $file)
$flat[] = [$base_dir, $file];
}
return $flat;
}
function getAllFiles() : array
{
$all_files = [];
foreach($this->base_dir2files as $base_dir => $files)
$all_files = array_merge($all_files, $files);
return $all_files;
}
//ArrayAccess interface
function offsetExists(mixed $offset) : bool
{
if(!is_int($offset))
throw new Exception("Invalid offset");
return $this->count() > $offset;
}
function offsetGet(mixed $offset) : mixed
{
if(!is_int($offset))
throw new Exception("Invalid offset");
foreach($this->base_dir2files as $base_dir => $files)
{
$n = count($files);
if($offset - $n < 0)
return $files[$offset];
$offset -= $n;
}
return null;
}
function offsetSet(mixed $offset, mixed $value) : void
{
if(!is_int($offset))
throw new Exception("Invalid offset");
foreach($this->base_dir2files as $base_dir => &$files)
{
$n = count($files);
if($offset - $n < 0)
{
$files[$offset] = $value;
return;
}
$offset -= $n;
}
}
function offsetUnset(mixed $offset) : void
{
if(!is_int($offset))
throw new Exception("Invalid offset");
foreach($this->base_dir2files as $base_dir => $files)
{
$n = count($files);
if($offset - $n < 0)
{
unset($files[$offset]);
return;
}
$offset -= $n;
}
}
//Iterator interface
function rewind() : void
{
$this->iter_pos = 0;
}
function current() : mixed
{
return $this->offsetGet($this->iter_pos);
}
function key() : mixed
{
return $this->iter_pos;
}
function next() : void
{
++$this->iter_pos;
}
function valid() : bool
{
return $this->offsetExists($this->iter_pos);
}
}
function config_scan_files(
iterable $base_dirs,
string $ext_filter = '.conf.js',
bool $verbose = false
) : ConfigDirFiles
{
$t = microtime(true);
$base_dir2files = [];
foreach($base_dirs as $base_dir)
{
$base_dir2files[$base_dir] =
scan_files_rec([$base_dir], [$ext_filter]);
}
$result = new ConfigDirFiles($base_dir2files);
if($verbose)
config_log("File scan: {$result->count()}, done " . round(microtime(true) - $t,2) . " sec.");
return $result;
}
//NOTE: this one is obsolete
function config_hash_changed(ConfigGlobals $globals, iterable $all_files)
{
$all_crc_file = $globals->build_dir . "/configs.crc";
return names_hash_changed($all_crc_file, $all_files);
}