déplacer yaml dans nur/ser74

This commit is contained in:
Jephté Clain 2024-11-14 19:42:33 +04:00
parent 2d4801e135
commit 9a6acf912b
8 changed files with 12 additions and 1533 deletions

View File

@ -9,7 +9,6 @@
} }
], ],
"require": { "require": {
"symfony/yaml": "^5.0",
"php": ">=7.4" "php": ">=7.4"
}, },
"require-dev": { "require-dev": {
@ -59,15 +58,8 @@
"bin": [ "bin": [
"nur_bin/compctl.php", "nur_bin/compctl.php",
"nur_bin/compdep.php", "nur_bin/compdep.php",
"nur_bin/cachectl.php",
"nur_bin/dumpser.php",
"nur_bin/datectl.php", "nur_bin/datectl.php",
"nur_bin/fsvdiff.php", "nur_bin/fsvdiff.php"
"nur_bin/ldap-delete.php",
"nur_bin/ldap-get-infos.php",
"nur_bin/ldap-search.php",
"nur_bin/sqlite-storage.php",
"nur_bin/mysql-storage.php"
], ],
"scripts": { "scripts": {
"uc": "@php sbin/update_classes.php" "uc": "@php sbin/update_classes.php"

1025
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,119 +0,0 @@
#!/usr/bin/php
<?php
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
use nur\b\io\CacheFile;
use nur\cli\Application;
use nur\msg;
use nur\path;
use nur\yaml;
Application::run(new class extends Application {
const ACTION_READ = 10, ACTION_INFOS = 20, ACTION_CLEAN = 30;
const ACTION_UPDATE = 40, ACTION_UPDATE_ADD = 41, ACTION_UPDATE_SUB = 42, ACTION_UPDATE_SET = 43;
const ARGS = [
"merge" => parent::ARGS,
"purpose" => "gestion de fichiers cache",
["-r", "--read", "name" => "action", "value" => self::ACTION_READ,
"help" => "Afficher le contenu d'un fichier cache",
],
["-i", "--infos", "name" => "action", "value" => self::ACTION_INFOS,
"help" => "Afficher des informations sur le fichier cache",
],
["-k", "--clean", "name" => "action", "value" => self::ACTION_CLEAN,
"help" => "Supprimer le fichier cache s'il a expiré",
],
["-a", "--add-duration", "args" => 1,
"action" => [null, "->setActionUpdate", self::ACTION_UPDATE_ADD],
"help" => "Ajouter le nombre de secondes spécifié à la durée du cache",
],
["-b", "--sub-duration", "args" => 1,
"action" => [null, "->setActionUpdate", self::ACTION_UPDATE_SUB],
"help" => "Enlever le nombre de secondes spécifié à la durée du cache",
],
["-s", "--set-duration", "args" => 1,
"action" => [null, "->setActionUpdate", self::ACTION_UPDATE_SET],
"help" => "Mettre à jour la durée du cache à la valeur spécifiée",
],
];
protected $action = self::ACTION_READ;
protected $updateAction, $updateDuration;
protected $args;
function setActionUpdate(int $action, $updateDuration): void {
$this->action = self::ACTION_UPDATE;
switch ($action) {
case self::ACTION_UPDATE_SUB: $this->updateAction = -1; break;
case self::ACTION_UPDATE_SET: $this->updateAction = 0; break;
case self::ACTION_UPDATE_ADD: $this->updateAction = 1; break;
}
$this->updateDuration = $updateDuration;
}
protected function findCaches(string $dir, ?array &$files): void {
foreach (glob("$dir/*") as $file) {
if (is_dir($file)) {
$this->findCaches($file, $files);
} elseif (is_file($file) && fnmatch("*.cache", $file)) {
$files[] = $file;
}
}
}
function main() {
$files = [];
foreach ($this->args as $arg) {
if (is_dir($arg)) {
$this->findCaches($arg, $files);
} elseif (is_file($arg)) {
$files[] = $arg;
} else {
msg::warning("$arg: fichier invalide ou introuvable");
}
}
$showSection = count($files) > 1;
foreach ($files as $file) {
switch ($this->action) {
case self::ACTION_READ:
if ($showSection) msg::section($file);
$cache = new CacheFile($file, [
"duration" => "INF",
"override_duration" => true,
]);
yaml::dump($cache->get());
break;
case self::ACTION_INFOS:
if ($showSection) msg::section($file);
$cache = new CacheFile($file);
yaml::dump($cache->getInfos());
break;
case self::ACTION_CLEAN:
msg::action(path::ppath($file));
$cache = new CacheFile($file);
try {
if ($cache->deleteExpired()) msg::asuccess("fichier supprimé");
else msg::astep("fichier non expiré");
} catch (Exception $e) {
msg::afailure(null, $e);
}
break;
case self::ACTION_UPDATE:
msg::action(path::ppath($file));
$cache = new CacheFile($file);
try {
$cache->updateDuration($this->updateDuration, $this->updateAction);
msg::asuccess("fichier mis à jour");
} catch (Exception $e) {
msg::afailure(null, $e);
}
break;
default:
self::die("$this->action: action non implémentée");
}
}
}
});

View File

@ -1,36 +0,0 @@
#!/usr/bin/php
<?php
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
use nur\b\io\CacheFile;
use nur\b\io\SharedFile;
use nur\cli\Application;
use nur\msg;
use nur\path;
use nur\yaml;
Application::run(new class extends Application {
const ARGS = [
"merge" => parent::ARGS,
"purpose" => "afficher des données sérialisées",
];
protected $args;
function main() {
$files = [];
foreach ($this->args as $arg) {
if (is_file($arg)) {
$files[] = $arg;
} else {
msg::warning("$arg: fichier invalide ou introuvable");
}
}
$showSection = count($files) > 1;
foreach ($files as $file) {
if ($showSection) msg::section($file);
$sfile = new SharedFile($file);
yaml::dump($sfile->unserialize());
}
}
});

View File

@ -1,127 +0,0 @@
#!/usr/bin/php
<?php
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
use nur\b\io\CacheFile;
use nur\cli\Application;
use nur\config;
use nur\msg;
use nur\path;
use nur\sery\db\Capacitor;
use nur\sery\db\CapacitorChannel;
use nur\sery\db\mysql\MysqlStorage;
use nur\sery\db\sqlite\SqliteStorage;
use nur\sery\file\Stream;
use nur\yaml;
Application::run(new class extends Application {
const ACTION_QUERY = 0, ACTION_SQL = 1;
const ARGS = [
"merge" => parent::ARGS,
"purpose" => "gestion d'un capacitor mysql",
"usage" => [
"-d DBCONN -c CHANNEL [--query] key=value...",
"-d DBCONN -c CHANNEL --sql-create",
],
["-d", "--dbconn", "args" => 1,
"help" => "nom de la connexion à la base de données",
],
["-t", "--table-name", "args" => 1,
"help" => "nom de la table porteuse du canal de données",
],
["-c", "--channel-class", "args" => 1,
"help" => "nom de la classe dérivée de CapacitorChannel",
],
["--query", "name" => "action", "value" => self::ACTION_QUERY,
"help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut",
],
["-s", "--sql-create", "name" => "action", "value" => self::ACTION_SQL,
"help" => "afficher la requête pour créer la table",
],
];
protected ?string $dbconn = null;
protected ?string $tableName = null;
protected ?string $channelClass = null;
protected int $action = self::ACTION_QUERY;
protected ?array $args = null;
protected static function isa_cond(string $arg, ?array &$ms=null): bool {
return preg_match('/^(.+?)\s*(=|<>|<|>|<=|>=|(?:is\s+)?null|(?:is\s+)?not\s+null)\s*(.*)$/', $arg, $ms);
}
function main() {
$dbconn = $this->dbconn;
if ($dbconn === null) self::die("Vous devez spécifier la base de données");
$tmp = config::db($dbconn);
if ($tmp === null) self::die("$dbconn: base de données invalide");
$dbconn = $tmp;
if ($this->channelClass !== null) {
$channelClass = str_replace("/", "\\", $this->channelClass);
$channel = new $channelClass;
} elseif ($this->tableName !== null) {
$channel = new class($this->tableName) extends CapacitorChannel {
function __construct(?string $name=null) {
parent::__construct($name);
$this->tableName = $name;
}
};
} else {
self::die("Vous devez spécifier le canal de données");
}
$storage = new MysqlStorage($dbconn);
$capacitor = new Capacitor($storage, $channel);
switch ($this->action) {
case self::ACTION_QUERY:
$args = $this->args;
if (!$args) {
# lister les id
$out = new Stream(STDOUT);
$primaryKeys = $storage->getPrimaryKeys($channel);
$rows = $storage->db()->all([
"select",
"cols" => $primaryKeys,
"from" => $channel->getTableName(),
]);
$out->fputcsv($primaryKeys);
foreach ($rows as $row) {
$rowIds = $storage->getRowIds($channel, $row);
$out->fputcsv($rowIds);
}
} else {
# afficher les lignes correspondantes
if (count($args) == 1 && !self::isa_cond($args[0])) {
$filter = $args[0];
} else {
$filter = [];
$ms = null;
foreach ($args as $arg) {
if (self::isa_cond($arg, $ms)) {
$filter[$ms[1]] = [$ms[2], $ms[3]];
} else {
$filter[$arg] = ["not null"];
}
}
}
$first = true;
$capacitor->each($filter, function ($item, $row) use (&$first) {
if ($first) $first = false;
else echo "---\n";
yaml::dump($row);
});
}
break;
case self::ACTION_SQL:
echo $capacitor->getCreateSql()."\n";
break;
}
}
});

View File

@ -1,156 +0,0 @@
#!/usr/bin/php
<?php
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
use nur\b\io\CacheFile;
use nur\cli\Application;
use nur\msg;
use nur\path;
use nur\sery\db\Capacitor;
use nur\sery\db\CapacitorChannel;
use nur\sery\db\sqlite\SqliteStorage;
use nur\sery\file\Stream;
use nur\yaml;
Application::run(new class extends Application {
const ACTION_QUERY = 0, ACTION_SQL = 1;
const ARGS = [
"merge" => parent::ARGS,
"purpose" => "gestion d'un capacitor sqlite",
"usage" => [
"-f DBFILE -n CHANNEL [--query] key=value...",
"-f DBFILE -n CHANNEL --sql-create",
],
["-f", "--dbfile", "args" => 1,
"help" => "chemin vers la base de données",
],
["-n", "--name", "args" => 1,
"help" => "nom du canal de données. table-name et channel-class sont chargés depuis la base de données",
],
["-t", "--table-name", "args" => 1,
"help" => "nom de la table porteuse du canal de données",
],
["-c", "--channel-class", "args" => 1,
"help" => "nom de la classe dérivée de CapacitorChannel",
],
["--query", "name" => "action", "value" => self::ACTION_QUERY,
"help" => "lister les lignes correspondant aux valeurs spécifiées. c'est l'action par défaut",
],
["-s", "--sql-create", "name" => "action", "value" => self::ACTION_SQL,
"help" => "afficher la requête pour créer la table",
],
];
protected ?string $dbfile = null;
protected ?string $name = null;
protected ?string $tableName = null;
protected ?string $channelClass = null;
protected int $action = self::ACTION_QUERY;
protected ?array $args = null;
protected static function isa_cond(string $arg, ?array &$ms=null): bool {
return preg_match('/^(.+?)\s*(=|<>|<|>|<=|>=|(?:is\s+)?null|(?:is\s+)?not\s+null)\s*(.*)$/', $arg, $ms);
}
function main() {
$dbfile = $this->dbfile;
if ($dbfile === null) self::die("Vous devez spécifier la base de données");
if (!file_exists($dbfile)) self::die("$dbfile: fichier introuvable");
$storage = new SqliteStorage($dbfile);
$db = $storage->db();
$haveChannels = $storage->tableExists("_channels");
$name = $this->name;
$channelClass = $this->channelClass;
$tableName = $this->tableName;
if ($name !== null) {
$row = null;
if ($haveChannels) {
$row = $db->one([
"select from _channels",
"where" => ["name" => $name],
]);
}
if ($row === null) self::die("$name: nom de canal de données introuvable");
if ($row["class"] !== "class@anonymous") $channelClass = $row["class"];
else $tableName = $row["table_name"];
}
if ($channelClass !== null) {
$channelClass = str_replace("/", "\\", $channelClass);
$channel = new $channelClass;
} elseif ($tableName !== null) {
$channel = new class($tableName) extends CapacitorChannel {
function __construct(?string $name=null) {
parent::__construct($name);
$this->tableName = $name;
}
};
} else {
$found = false;
if ($haveChannels) {
$rows = $db->all([
"select from _channels",
]);
foreach ($rows as $row) {
msg::print($row["name"]);
$found = true;
}
}
if (!$found) self::die("Vous devez spécifier le canal de données");
else self::exit();
}
$capacitor = new Capacitor($storage, $channel);
switch ($this->action) {
case self::ACTION_QUERY:
$args = $this->args;
if (!$args) {
# lister les id
$out = new Stream(STDOUT);
$primaryKeys = $storage->getPrimaryKeys($channel);
$rows = $db->all([
"select",
"cols" => $primaryKeys,
"from" => $channel->getTableName(),
]);
$out->fputcsv($primaryKeys);
foreach ($rows as $row) {
$rowIds = $storage->getRowIds($channel, $row);
$out->fputcsv($rowIds);
}
} else {
# afficher les lignes correspondantes
if (count($args) == 1 && !self::isa_cond($args[0])) {
$filter = $args[0];
} else {
$filter = [];
$ms = null;
foreach ($args as $arg) {
if (self::isa_cond($arg, $ms)) {
$filter[$ms[1]] = [$ms[2], $ms[3]];
} else {
$filter[$arg] = ["not null"];
}
}
}
$first = true;
$capacitor->each($filter, function ($item, $row) use (&$first) {
if ($first) $first = false;
else echo "---\n";
yaml::dump($row);
});
}
break;
case self::ACTION_SQL:
echo $capacitor->getCreateSql()."\n";
break;
}
}
});

View File

@ -1,37 +0,0 @@
<?php
namespace nur;
use nur\b\io\IOException;
use nur\b\io\IReader;
use nur\b\ValueException;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml as SymfonyYaml;
/**
* Class yaml: lecture de données yaml
*/
class yaml {
/**
* @throws ValueException si $input n'est pas un string ni une instance de
* {@link IReader}
* @throws IOException si une erreur de lecture s'est produite
*/
static final function load($input): array {
$contents = reader::get_contents($input);
try {
return A::with(SymfonyYaml::parse($contents));
} catch (ParseException $e) {
$message = "parse error";
if (is_string($input)) $message .= " while loading $input";
throw new IOException($message, 0, $e);
}
}
static final function with($data, int $indent=2, int $flags=0): string {
return SymfonyYaml::dump($data, PHP_INT_MAX, $indent, $flags);
}
static final function dump($data, $output=null, int $indent=2, int $flags=0): void {
writer::with($output)->write(self::with($data, $indent, $flags))->close();
}
}

View File

@ -1,35 +0,0 @@
<?php
namespace nur\sery\ext;
use nur\sery\cl;
use nur\sery\file;
use nur\sery\os\IOException;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml as SymfonyYaml;
/**
* Class yaml: lecture de données yaml
*/
class yaml {
/**
* @throws IOException si une erreur de lecture s'est produite
*/
static final function load($input): array {
$contents = file::reader($input)->getContents();
try {
return cl::with(SymfonyYaml::parse($contents));
} catch (ParseException $e) {
$message = "parse error";
if (is_string($input)) $message .= " while loading $input";
throw new IOException($message, 0, $e);
}
}
static final function with($data, int $indent=2, int $flags=0): string {
return SymfonyYaml::dump($data, PHP_INT_MAX, $indent, $flags);
}
static final function dump($data, $output=null, int $indent=2, int $flags=0): void {
file::writer($output)->putContents(self::with($data, $indent, $flags));
}
}