Compare commits

..

1 Commits
php74 ... php82

Author SHA1 Message Date
Jephté Clain e71693fae3 maj deps php8.2 2025-01-24 16:17:26 +04:00
11 changed files with 29 additions and 703 deletions

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PhpTestFrameworkVersionCache">
<tools_cache>
<tool tool_name="PHPUnit">
<cache>
<versions>
<info id="Local/vendor/autoload.php" version="9.6.22" />
</versions>
</cache>
</tool>
</tools_cache>
</component>
</project>

View File

@ -4,5 +4,5 @@
RUNPHP=
# Si RUNPHP n'est pas défini, les variables suivantes peuvent être définies
DIST=d11
DIST=d12
#REGISTRY=pubdocker.univ-reunion.fr

View File

@ -1,7 +0,0 @@
#!/usr/bin/php
<?php
require $_composer_autoload_path?? __DIR__.'/../vendor/autoload.php';
use nulib\tools\DumpserApp;
DumpserApp::run();

View File

@ -27,13 +27,13 @@
}
},
"require": {
"php": "^7.4"
"php": "^8.2"
},
"require-dev": {
"nulib/php": "^7.4-dev",
"nulib/spout": "^7.4-dev",
"nulib/phpss": "^7.4-dev",
"nulib/tests": "^7.4",
"nulib/php": "^8.2-dev",
"nulib/spout": "^8.2-dev",
"nulib/phpss": "^8.2-dev",
"nulib/tests": "^8.2",
"ext-posix": "*",
"ext-pcntl": "*",
"ext-fileinfo": "*",
@ -80,13 +80,12 @@
}
},
"bin": [
"bin/dumpser.php",
"bin/csv2xlsx.php",
"nur_bin/compctl.php",
"nur_bin/compdep.php",
"nur_bin/datectl.php",
"nur_bin/fsvdiff.php",
"nur_bin/cachectl.php",
"nur_bin/dumpser.php",
"nur_bin/ldap-delete.php",
"nur_bin/ldap-get-infos.php",
"nur_bin/ldap-search.php",

120
composer.lock generated
View File

@ -4,88 +4,9 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "75bc483e6daffdf3e962197c49841ce9",
"content-hash": "90b972256fe0b784ba158cecdff7edaf",
"packages": [],
"packages-dev": [
{
"name": "composer/pcre",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<1.11.10"
},
"require-dev": {
"phpstan/phpstan": "^1.12 || ^2",
"phpstan/phpstan-strict-rules": "^1 || ^2",
"phpunit/phpunit": "^8 || ^9"
},
"type": "library",
"extra": {
"phpstan": {
"includes": [
"extension.neon"
]
},
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Pcre\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
"PCRE",
"preg",
"regex",
"regular expression"
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.3.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2024-11-12T16:29:46+00:00"
},
{
"name": "doctrine/instantiator",
"version": "1.5.0",
@ -585,11 +506,11 @@
},
{
"name": "nulib/php",
"version": "dev-php74",
"version": "dev-master",
"dist": {
"type": "path",
"url": "../nulib",
"reference": "de3b84441d2b588475b4d6d74bffdc487e333034"
"reference": "0dfb30d395c0516ba14ef3d9eb22e408bfd93d80"
},
"require": {
"ext-json": "*",
@ -600,12 +521,12 @@
"ext-curl": "*",
"ext-pcntl": "*",
"ext-posix": "*",
"nulib/tests": "^7.4"
"nulib/tests": "7.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-php74": "7.4.x-dev",
"dev-master": "7.4.x-dev",
"dev-php82": "8.2.x-dev"
}
},
@ -632,11 +553,11 @@
},
{
"name": "nulib/phpss",
"version": "dev-php74",
"version": "dev-master",
"dist": {
"type": "path",
"url": "../nulib-phpss",
"reference": "b950bb7718fa0fe48850fd6b2d71f7015e144bf1"
"reference": "df05afda07f5973e55db4568fac5a9659ab38e76"
},
"require": {
"nulib/php": "^7.4-dev",
@ -649,7 +570,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-php74": "7.4.x-dev",
"dev-master": "7.4.x-dev",
"dev-php82": "8.2.x-dev"
}
},
@ -676,11 +597,11 @@
},
{
"name": "nulib/spout",
"version": "dev-php74",
"version": "dev-master",
"dist": {
"type": "path",
"url": "../nulib-spout",
"reference": "967319ff0b29b370f4345e748a5df7a63a66cea6"
"reference": "a9df7e7c30805ea9a138ea6d07a5b4aff5793ce6"
},
"require": {
"ext-dom": "*",
@ -704,13 +625,13 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-php74": "7.4.x-dev",
"dev-master": "7.4.x-dev",
"dev-php82": "8.2.x-dev"
}
},
"autoload": {
"psr-4": {
"nulib\\": "src",
"nulib\\ext\\": "src",
"OpenSpout\\": "upstream-3.x/src"
}
},
@ -736,7 +657,7 @@
"source": {
"type": "git",
"url": "https://git.univ-reunion.fr/sda-php/nulib-tests.git",
"reference": "a8541304eeddf696040e65792f45308d1d292aed"
"reference": "6ce8257560b42e8fb3eea03eba84d3877c9648ca"
},
"require": {
"php": ">=7.3",
@ -760,7 +681,7 @@
}
],
"description": "fonctions et classes pour les tests",
"time": "2025-01-30T14:12:43+00:00"
"time": "2024-03-26T10:56:17+00:00"
},
{
"name": "phar-io/manifest",
@ -882,20 +803,19 @@
},
{
"name": "phpoffice/phpspreadsheet",
"version": "1.29.9",
"version": "1.29.8",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "ffb47b639649fc9c8a6fa67977a27b756592ed85"
"reference": "089ffdfc04b5fcf25a3503d81a4e589f247e20e3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/ffb47b639649fc9c8a6fa67977a27b756592ed85",
"reference": "ffb47b639649fc9c8a6fa67977a27b756592ed85",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/089ffdfc04b5fcf25a3503d81a4e589f247e20e3",
"reference": "089ffdfc04b5fcf25a3503d81a4e589f247e20e3",
"shasum": ""
},
"require": {
"composer/pcre": "^3.3",
"ext-ctype": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
@ -982,9 +902,9 @@
],
"support": {
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.9"
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.8"
},
"time": "2025-01-26T04:55:00+00:00"
"time": "2025-01-12T03:16:27+00:00"
},
{
"name": "phpunit/php-code-coverage",

View File

@ -1,2 +1,2 @@
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
__uaddpath "@@dest@@/bin:@@dest@@/nur_bin" PATH
__uaddpath "@@dest@@/nur_bin" PATH

View File

@ -5,7 +5,6 @@ use ArrayAccess;
use Countable;
use Exception;
use Generator;
use nulib\file\Stream;
use nur\A;
use nur\b\coll\TBaseArray;
use nur\b\IllegalAccessException;
@ -105,7 +104,6 @@ abstract class FileCachedValue extends Parametrable implements ArrayAccess, Coun
/** désérialiser la données depuis le contenu spécifié */
protected function unserialize(string $contents) {
$contents = Stream::nursery_compat_verifix($contents);
return unserialize($contents);
}
@ -150,7 +148,7 @@ abstract class FileCachedValue extends Parametrable implements ArrayAccess, Coun
}
protected function loadInfos(): array {
[$tstart, $duration] = $this->unserialize(fgets($this->fp));
[$tstart, $duration] = unserialize(fgets($this->fp));
if (is_int($tstart)) {
$tstart = new DateTime($tstart);
$duration = new Delay($duration, $tstart);

View File

@ -1,255 +0,0 @@
<?php
namespace nur\sery\wip\php\coll;
use Iterator;
use nulib\cl;
use nulib\php\func;
use nur\sery\wip\php\iter;
use Traversable;
/**
* Class Cursor: parcours des lignes itérable
*
* @property-read array|null $value alias pour $row
* @property-read iterable|null $rows la source des lignes
*/
class Cursor implements Iterator {
const PARAMS_SCHEMA = [
"rows" => ["?iterable"],
"rows_func" => ["?callable"],
"cols" => ["?array"],
"cols_func" => ["?callable"],
"map" => ["?array"],
"map_func" => ["?callable"],
"filter" => ["?array"],
"filter_func" => ["?callable"],
];
/**
* mapper le tableau source $row selon les règles suivantes illustrées dans
* l'exemple suivant:
* si
* $map = ["a", "b" => "x", "c" => function() { return "y"; }, "d" => null]
* alors retourner le tableau
* ["a" => $row["a"], "b" => $row["x"], "c" => "y", "d" => null]
*/
private static function map_row(array $row, ?array $map): array {
if ($map === null) return $row;
$index = 0;
$mapped = [];
foreach ($map as $key => $value) {
if ($key === $index) {
$index++;
if ($value === null) $mapped[] = null;
else $mapped[$value] = cl::get($row, $value);
} elseif (is_callable($value)) {
$func = func::with($value);
$value = cl::get($row, $key);
$mapped[$key] = $func->invoke([$value, $key, $row]);
} else {
if ($value === null) $mapped[$key] = null;
else $mapped[$key] = cl::get($row, $key);
}
}
return $mapped;
}
/**
* tester si $row satisfait les conditions de $filter
* - $filter est un scalaire, le transformer en [$filter]
* - sinon $filter doit être un tableau de scalaires
*
* les règles des conditions sont les suivantes:
* - une valeur séquentielle $key est équivalente à la valeur associative
* $key => true
* - une valeur associative $key => bool indique que la clé correspondante ne
* doit pas (resp. doit) exister selon que bool vaut false (resp. true)
* - une valeur associative $key => $value indique que la clé correspondante
* doit exiter avec la valeur spécifiée
*/
private static function filter_row(array $row, $filter): bool {
if ($filter === null) return false;
if (!is_array($filter)) $filter = [$filter];
if (!$filter) return false;
$index = 0;
foreach ($filter as $key => $value) {
if ($key === $index) {
$index++;
if (!array_key_exists($value, $row)) return false;
} elseif (is_bool($value)) {
if ($value) {
if (!array_key_exists($value, $row)) return false;
} else {
if (array_key_exists($value, $row)) return false;
}
} else {
if (!array_key_exists($value, $row)) return false;
if ($row[$key] !== $value) return false;
}
}
return true;
}
function __construct(?iterable $rows=null, ?array $params=null) {
if ($rows !== null) $params["rows"] = $rows;
$rows = $params["rows"] ?? null;
$rowsGenerator = null;
$rowsFunc = $params["rows_func"] ?? null;
if ($rowsFunc !== null) {
if ($rowsFunc instanceof Traversable) {
$rowsGenerator = $rowsFunc;
$rowsFunc = null;
} else {
$rowsFunc = func::with($rowsFunc, [$rows]);
}
} elseif ($rows instanceof Traversable) {
$rowsGenerator = $rows;
} else {
$rowsFunc = func::with(function() use ($rows) {
return $rows;
});
}
$this->rowsGenerator = $rowsGenerator;
$this->rowsFunc = $rowsFunc;
$map = $params["map"] ?? null;
$mapFunc = $params["map_func"] ?? null;
if ($mapFunc !== null) {
$mapFunc = func::with($mapFunc);
} elseif ($map !== null) {
$mapFunc = func::with(function(array $row) use ($map) {
return self::map_row($row, $map);
});
}
$this->mapFunc = $mapFunc;
$filter = $params["filter"] ?? null;
$filterFunc = $params["filter_func"] ?? null;
if ($filterFunc !== null) {
$filterFunc = func::with($filterFunc);
} elseif ($filter !== null) {
$filterFunc = func::with(function(array $row) use ($filter) {
return self::filter_row($row, $filter);
});
}
$this->filterFunc = $filterFunc;
}
/** un générateur de lignes */
private ?Traversable $rowsGenerator;
/** une fonction de signature <code>function(Cursor):?iterable</code> */
private ?func $rowsFunc;
/** une fonction de signature <code>function(Cursor):?array</code> */
private ?func $colsFunc;
/** une fonction de signature <code>function(Cursor):?array</code> */
private ?func $mapFunc;
/** une fonction de signature <code>function(Cursor):bool</code> */
private ?func $filterFunc;
protected ?iterable $rows;
public ?array $cols;
public int $index;
public int $origIndex;
public $key;
public $raw;
public ?array $row;
function __get($name) {
if ($name === "value") return $this->row;
elseif ($name == "rows") return $this->rows;
trigger_error("Undefined property $name");
return null;
}
protected function filter(): bool {
return false;
}
protected function map(): ?array {
return $this->row;
}
#############################################################################
# Iterator
function rewind() {
$this->index = 0;
$this->origIndex = 0;
$this->key = null;
$this->raw = null;
$this->row = null;
if ($this->rowsGenerator !== null) {
$this->rows = $this->rowsGenerator;
$this->rows->rewind();
} else {
$this->rows = $this->rowsFunc->invoke();
}
}
function valid() {
$filter = $this->filterFunc;
$map = $this->mapFunc;
while ($valid = iter::valid($this->rows)) {
$this->raw = iter::current($this->rows, $this->key);
$this->key ??= $this->origIndex;
$this->row = cl::withn($this->raw);
if ($filter === null) $filtered = $this->filter();
else $filtered = $filter->invoke([$this]);
if (!$filtered) {
if ($map === null) $this->row = $this->map();
else $this->row = $map->invoke([$this]);
break;
} else {
iter::next($this->rows);
$this->origIndex++;
}
}
if (!$valid) {
iter::close($this->rows);
$this->rows = null;
$this->index = -1;
$this->origIndex = -1;
$this->key = null;
$this->raw = null;
$this->row = null;
}
return $valid;
}
function current() {
return $this->row;
}
function key() {
return $this->key;
}
function next() {
iter::next($this->rows);
$this->index++;
$this->origIndex++;
}
#############################################################################
function each(callable $func): void {
$func = func::with($func);
$this->rewind();
while ($this->valid()) {
$func->invoke([$this]);
$this->next();
}
}
}

View File

@ -1,169 +0,0 @@
<?php # -*- coding: utf-8 mode: php -*- vim:sw=2:sts=2:et:ai:si:sta:fenc=utf-8
namespace nur\sery\wip\php;
use Exception;
use Generator;
use Iterator;
use IteratorAggregate;
use nulib\php\ICloseable;
use nulib\StopException;
use nulib\ValueException;
use Traversable;
/**
* Class iter: gestion des itérateurs
*/
class iter {
private static function unexpected_type($object): ValueException {
return ValueException::invalid_type($object, "iterable");
}
/**
* fermer "proprement" un itérateur ou un générateur. retourner true en cas de
* succès, ou false si c'est un générateur et qu'il ne supporte pas l'arrêt
* avec StopException (la valeur de retour n'est alors pas disponible)
*/
static function close($it): bool {
if ($it instanceof ICloseable) {
$it->close();
return true;
} elseif ($it instanceof Generator) {
try {
$it->throw(new StopException());
return true;
} catch (StopException $e) {
}
}
return false;
}
/**
* retourner la première valeur du tableau, de l'itérateur ou de l'instance
* de Traversable, ou $default si aucun élément n'est trouvé.
*/
static final function first($values, $default=null) {
if ($values instanceof IteratorAggregate) $values = $values->getIterator();
if ($values instanceof Iterator) {
try {
$values->rewind();
$value = $values->valid()? $values->current(): $default;
} finally {
self::close($values);
}
} elseif (is_array($values) || $values instanceof Traversable) {
$value = $default;
foreach ($values as $value) {
break;
}
} else {
throw self::unexpected_type($values);
}
return $value;
}
/**
* retourner la première clé du tableau, de l'itérateur ou de l'instance
* de Traversable, ou $default si aucun élément n'est trouvé.
*/
static final function first_key($values, $default=null) {
if ($values instanceof IteratorAggregate) $values = $values->getIterator();
if ($values instanceof Iterator) {
try {
$values->rewind();
$key = $values->valid()? $values->key(): $default;
} finally {
self::close($values);
}
} elseif (is_array($values) || $values instanceof Traversable) {
$key = $default;
foreach ($values as $key => $ignored) {
break;
}
} else {
throw self::unexpected_type($values);
}
return $key;
}
#############################################################################
# outils pour gérer de façon générique des instances de {@link Iterator} ou
# des arrays
/**
* @param $it ?iterable|array
* @return bool true si l'itérateur ou le tableau ont pu être réinitialisés
*/
static function rewind(&$it, ?Exception &$exception=null): bool {
if ($it instanceof Iterator) {
try {
$exception = null;
$it->rewind();
return true;
} catch (Exception $e) {
$exception = $e;
}
} elseif ($it !== null) {
reset($it);
return true;
}
return false;
}
/**
* @param $it ?iterable|array
*/
static function valid($it): bool {
if ($it instanceof Iterator) {
return $it->valid();
} elseif ($it !== null) {
return key($it) !== null;
} else {
return false;
}
}
/**
* @param $it ?iterable|array
*/
static function current($it, &$key=null) {
if ($it instanceof Iterator) {
$key = $it->key();
return $it->current();
} elseif ($it !== null) {
$key = key($it);
return current($it);
} else {
$key = null;
return null;
}
}
/**
* @param $it ?iterable|array
*/
static function next(&$it, ?Exception &$exception=null): void {
if ($it instanceof Iterator) {
try {
$exception = null;
$it->next();
} catch (Exception $e) {
$exception = $e;
}
} elseif ($it !== null) {
next($it);
}
}
/**
* obtenir la valeur de retour si $it est un générateur terminé, ou null sinon
*/
static function get_return($it) {
if ($it instanceof Generator) {
try {
return $it->getReturn();
} catch (Exception $e) {
}
}
return null;
}
}

View File

@ -1,34 +0,0 @@
<?php
namespace nulib\tools;
use nulib\app\cli\Application;
use nulib\ext\yaml;
use nulib\file\SharedFile;
use nulib\output\msg;
class DumpserApp 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,112 +0,0 @@
<?php
namespace nur\sery\wip\php\coll;
use Exception;
use nulib\cl;
use nulib\output\msg;
use nulib\output\std\StdMessenger;
use nulib\tests\TestCase;
use TypeError;
class CursorTest extends TestCase {
protected function setUp(): void {
msg::set_messenger(new StdMessenger());
}
const SCALARS = [0, 1, 2, 3, 4];
function generator() {
yield from self::SCALARS;
}
function testVanilla() {
$c = new Cursor(self::SCALARS);
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
$c = new Cursor($this->generator());
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
self::assertException(Exception::class, function() use ($c) {
// pas possible de rewind un générateur
return cl::all($c);
});
$c = new Cursor(null, [
"rows" => function() {
return self::SCALARS;
},
]);
self::assertError(TypeError::class, function() use ($c) {
// rows doit être un iterable, pas une fonction
return cl::all($c);
});
$c = new Cursor(null, [
"rows_func" => function() {
return self::SCALARS;
},
]);
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
$c = new Cursor(null, [
"rows_func" => $this->generator(),
]);
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
self::assertException(Exception::class, function() use ($c) {
// pas possible de rewind un générateur
return cl::all($c);
});
$c = new Cursor(null, [
"rows_func" => function() {
yield from self::SCALARS;
},
]);
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
self::assertSame([[0], [1], [2], [3], [4]], cl::all($c));
}
function testMap() {
$c = new Cursor(self::SCALARS, [
"map_func" => function(Cursor $c) {
return [$c->raw + 1];
},
]);
self::assertSame([[1], [2], [3], [4], [5]], cl::all($c));
}
function testFilter() {
$c = new Cursor(self::SCALARS, [
"filter_func" => function(Cursor $c) {
return $c->raw % 2 == 0;
},
]);
self::assertSame([[1], [3]], cl::all($c));
}
function testEach() {
$c = new Cursor(self::SCALARS, [
"filter_func" => function(Cursor $c) {
return $c->raw % 2 == 0;
},
"map_func" => function(Cursor $c) {
return [$c->raw + 1];
},
]);
$xs = [];
$xitems = [];
$oxs = [];
$kitems = [];
$c->each(function(Cursor $c) use (&$xs, &$xitems, &$oxs, &$kitems) {
$xs[] = $c->index;
$oxs[] = $c->origIndex;
$xitems[$c->index] = $c->row[0];
$kitems[$c->key] = $c->row[0];
});
self::assertSame([0, 1], $xs);
self::assertSame([2, 4], $xitems);
self::assertSame([1, 3], $oxs);
self::assertSame([1 => 2, 3 => 4], $kitems);
}
}