déplacer yaml dans nur/ser74
This commit is contained in:
parent
2d4801e135
commit
9a6acf912b
|
@ -9,7 +9,6 @@
|
|||
}
|
||||
],
|
||||
"require": {
|
||||
"symfony/yaml": "^5.0",
|
||||
"php": ">=7.4"
|
||||
},
|
||||
"require-dev": {
|
||||
|
@ -59,15 +58,8 @@
|
|||
"bin": [
|
||||
"nur_bin/compctl.php",
|
||||
"nur_bin/compdep.php",
|
||||
"nur_bin/cachectl.php",
|
||||
"nur_bin/dumpser.php",
|
||||
"nur_bin/datectl.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"
|
||||
"nur_bin/fsvdiff.php"
|
||||
],
|
||||
"scripts": {
|
||||
"uc": "@php sbin/update_classes.php"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
});
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue