Compare commits
	
		
			24 Commits
		
	
	
		
			4037bf2042
			...
			8094346358
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8094346358 | |||
| c2b1d23d36 | |||
| 23358180ac | |||
| d274a6528a | |||
| 2e026daeda | |||
| 8e7e59cc42 | |||
| dd3006e05d | |||
| bbbe101918 | |||
| b8a3d7ae77 | |||
| c78196450e | |||
| a587f99e42 | |||
| 00effe4ee8 | |||
| 50aedea0e6 | |||
| cc56dc9834 | |||
| a418a87ac9 | |||
| 0a73ba371f | |||
| 24ecb913dc | |||
| aef0533d9b | |||
| 87e262cfe2 | |||
| aabdb3f765 | |||
| a371a68ee2 | |||
| d70612261d | |||
| 1671354fd8 | |||
| 714baef2fe | 
							
								
								
									
										15
									
								
								CHANGES.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								CHANGES.md
									
									
									
									
									
								
							@ -1,3 +1,18 @@
 | 
			
		||||
## Release 0.5.1p74 du 12/05/2025-15:28
 | 
			
		||||
 | 
			
		||||
* `d274a65` améliorer status
 | 
			
		||||
* `2e026da` l'option -ww affiche la différence
 | 
			
		||||
* `8e7e59c` intégrer les méthodes de Cursor et KeyAccess
 | 
			
		||||
* `a587f99` installer completion pour pman
 | 
			
		||||
* `cc56dc9` renommer pdev en pmer
 | 
			
		||||
* `0a73ba3` améliorer ergonomie de p
 | 
			
		||||
* `aef0533` ajout str::split
 | 
			
		||||
* `87e262c` ajout cl::delv
 | 
			
		||||
* `a371a68` maj doc
 | 
			
		||||
* `d706122` ajout infos release
 | 
			
		||||
 | 
			
		||||
## Release 0.5.0p82 du 30/04/2025-04:33
 | 
			
		||||
 | 
			
		||||
## Release 0.5.0p74 du 30/04/2025-04:31
 | 
			
		||||
 | 
			
		||||
* `3ee92ef` ajout str::replace
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
# nulib
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Release
 | 
			
		||||
 | 
			
		||||
Exemple: release de la version 0.6.0
 | 
			
		||||
~~~sh
 | 
			
		||||
version=0.6.0
 | 
			
		||||
 | 
			
		||||
## branche dev74
 | 
			
		||||
git checkout dev74
 | 
			
		||||
 | 
			
		||||
prel -v$version
 | 
			
		||||
 | 
			
		||||
_merge82
 | 
			
		||||
 | 
			
		||||
## branche dev82
 | 
			
		||||
git checkout dev82
 | 
			
		||||
 | 
			
		||||
prel -C
 | 
			
		||||
 | 
			
		||||
commit="$(git log --grep="Init changelog . version ${version}p82" --format=%H)"
 | 
			
		||||
git checkout dev74
 | 
			
		||||
git cherry-pick "$commit"
 | 
			
		||||
pp -a
 | 
			
		||||
~~~
 | 
			
		||||
 | 
			
		||||
-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary
 | 
			
		||||
@ -1 +1 @@
 | 
			
		||||
0.5.0
 | 
			
		||||
0.5.1
 | 
			
		||||
 | 
			
		||||
@ -84,6 +84,12 @@ function _list_commits() {
 | 
			
		||||
        _filter_rel
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _show_diff() {
 | 
			
		||||
    local source="${1:-$SrcBranch}" dest="${2:-$DestBranch}" mergebase
 | 
			
		||||
    setx mergebase=git merge-base "$dest" "$source"
 | 
			
		||||
    git diff ${_sd_COLOR:+--color=$_sd_COLOR} "$mergebase..$source"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function _scripte() {
 | 
			
		||||
    echo >>"$script"
 | 
			
		||||
    echo "$comment$(qvals "$@")" >>"$script"
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | 
			
		||||
 | 
			
		||||
exec "$(dirname -- "$0")/pdev" --tech-merge -Bdev82 dev74 -a "git checkout dev74" "$@"
 | 
			
		||||
exec "$(dirname -- "$0")/pmer" --tech-merge -Bdev82 dev74 -a "git checkout dev74" "$@"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								bin/p
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								bin/p
									
									
									
									
									
								
							@ -29,6 +29,9 @@ function git_statuses() {
 | 
			
		||||
    done
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# sans arguments, il y a un comportement spécial
 | 
			
		||||
[ $# -eq 0 ] && NoArgs=1 || NoArgs=
 | 
			
		||||
 | 
			
		||||
chdir=
 | 
			
		||||
all=
 | 
			
		||||
composer=
 | 
			
		||||
@ -43,6 +46,13 @@ Si l'option -a est utilisée, ce script accepte comme arguments une liste de pat
 | 
			
		||||
)
 | 
			
		||||
parse_args "$@"; set -- "${args[@]}"
 | 
			
		||||
 | 
			
		||||
if [ -n "$NoArgs" ]; then
 | 
			
		||||
    # si aucun argument n'est spécifié et si on n'est pas dans un projet git,
 | 
			
		||||
    # afficher le status de tous les sous répertoires
 | 
			
		||||
    setx toplevel=git_get_toplevel
 | 
			
		||||
    [ -z "$toplevel" ] && all=1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
setx OrigCwd=pwd
 | 
			
		||||
if [ -n "$chdir" ]; then
 | 
			
		||||
    cd "$chdir" || die
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								bin/pman
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								bin/pman
									
									
									
									
									
								
							@ -78,7 +78,7 @@ function init_repo_action() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function init_config_action() {
 | 
			
		||||
    local -a push_branches; config
 | 
			
		||||
    local -a push_branches; local config
 | 
			
		||||
 | 
			
		||||
    [ -f .pman.conf -a -z "$ForceCreate" ] && die "La configuration pman a déjà été initialisée"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,8 +11,19 @@ function show_action() {
 | 
			
		||||
    local commits
 | 
			
		||||
    setx commits=_list_commits
 | 
			
		||||
    if [ -n "$commits" ]; then
 | 
			
		||||
        einfo "Commits à fusionner $SrcBranch --> $DestBranch"
 | 
			
		||||
        eecho "$commits"
 | 
			
		||||
        if [ $ShowLevel -ge 2 ]; then
 | 
			
		||||
            {
 | 
			
		||||
                echo "\
 | 
			
		||||
# Commits à fusionner $SrcBranch --> $DestBranch
 | 
			
		||||
 | 
			
		||||
$commits
 | 
			
		||||
"
 | 
			
		||||
                _sd_COLOR=always _show_diff
 | 
			
		||||
            } | less -eRF
 | 
			
		||||
        else
 | 
			
		||||
            einfo "Commits à fusionner $SrcBranch --> $DestBranch"
 | 
			
		||||
            eecho "$commits"
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -148,6 +159,7 @@ ConfigFile=
 | 
			
		||||
_Fake=
 | 
			
		||||
_KeepScript=
 | 
			
		||||
action=merge
 | 
			
		||||
ShowLevel=0
 | 
			
		||||
TechMerge=
 | 
			
		||||
SquashMsg=
 | 
			
		||||
[ -z "$PMAN_NO_PUSH" ] && Push=1 || Push=
 | 
			
		||||
@ -158,6 +170,7 @@ args=(
 | 
			
		||||
    " [source]
 | 
			
		||||
 | 
			
		||||
CONFIGURATION
 | 
			
		||||
 | 
			
		||||
Le fichier .pman.conf contient la configuration des branches. Les variables
 | 
			
		||||
supplémentaires suivantes peuvent être définies:
 | 
			
		||||
    BEFORE_MERGE_<srcType>
 | 
			
		||||
@ -176,7 +189,7 @@ fichier de configuration des branches. cette option est prioritaire sur --config
 | 
			
		||||
par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe"
 | 
			
		||||
    --fake _Fake=1 "++option non documentée"
 | 
			
		||||
    --keep-script _KeepScript=1 "++option non documentée"
 | 
			
		||||
    -w,--show action=show "\
 | 
			
		||||
    -w,--show '$action=show; inc@ ShowLevel' "\
 | 
			
		||||
lister les modifications qui seraient fusionnées dans la branche destination"
 | 
			
		||||
    -b,--rebase action=rebase "\
 | 
			
		||||
lancer git rebase -i sur la branche source. cela permet de réordonner les
 | 
			
		||||
							
								
								
									
										18
									
								
								bin/prel
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								bin/prel
									
									
									
									
									
								
							@ -11,8 +11,19 @@ function show_action() {
 | 
			
		||||
    local commits
 | 
			
		||||
    setx commits=_list_commits
 | 
			
		||||
    if [ -n "$commits" ]; then
 | 
			
		||||
        einfo "Commits à fusionner $SrcBranch --> $DestBranch"
 | 
			
		||||
        eecho "$commits"
 | 
			
		||||
        if [ $ShowLevel -ge 2 ]; then
 | 
			
		||||
            {
 | 
			
		||||
                echo "\
 | 
			
		||||
# Commits à fusionner $SrcBranch --> $DestBranch
 | 
			
		||||
 | 
			
		||||
$commits
 | 
			
		||||
"
 | 
			
		||||
                _sd_COLOR=always _show_diff
 | 
			
		||||
            } | less -eRF
 | 
			
		||||
        else
 | 
			
		||||
            einfo "Commits à fusionner $SrcBranch --> $DestBranch"
 | 
			
		||||
            eecho "$commits"
 | 
			
		||||
        fi
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -194,6 +205,7 @@ ConfigFile=
 | 
			
		||||
_Fake=
 | 
			
		||||
_KeepScript=
 | 
			
		||||
action=release
 | 
			
		||||
ShowLevel=0
 | 
			
		||||
[ -z "$PMAN_NO_MERGE" ] && Merge=1 || Merge=
 | 
			
		||||
[ -z "$PMAN_NO_PUSH" ] && Push=1 || Push=
 | 
			
		||||
Version=
 | 
			
		||||
@ -222,7 +234,7 @@ fichier de configuration des branches. cette option est prioritaire sur --config
 | 
			
		||||
par défaut, utiliser le fichier .pman.conf dans le répertoire du dépôt s'il existe"
 | 
			
		||||
    --fake _Fake=1 "++option non documentée"
 | 
			
		||||
    --keep-script _KeepScript=1 "++option non documentée"
 | 
			
		||||
    -w,--show action=show "\
 | 
			
		||||
    -w,--show '$action=show; inc@ ShowLevel' "\
 | 
			
		||||
lister les modifications qui seraient intégrées dans la release"
 | 
			
		||||
    --release action=release "++\
 | 
			
		||||
créer la release.
 | 
			
		||||
 | 
			
		||||
@ -29,7 +29,7 @@ for file in "$@"; do
 | 
			
		||||
    estep "Création de $file"
 | 
			
		||||
 | 
			
		||||
    cat >"$file" <<EOF
 | 
			
		||||
-- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=$encoding
 | 
			
		||||
-- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | 
			
		||||
-- @database xxx
 | 
			
		||||
 | 
			
		||||
start transaction;
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | 
			
		||||
 | 
			
		||||
function __pman_pdev_branches() {
 | 
			
		||||
function __pman_pmer_branches() {
 | 
			
		||||
    local toplevel="$(git rev-parse --show-toplevel 2>/dev/null)"
 | 
			
		||||
    [ -n "$toplevel" ] || return 0
 | 
			
		||||
 | 
			
		||||
@ -29,9 +29,9 @@ function __pman_pdev_branches() {
 | 
			
		||||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function __pdev_completion() {
 | 
			
		||||
function __pmer_completion() {
 | 
			
		||||
    local cur
 | 
			
		||||
    _get_comp_words_by_ref cur
 | 
			
		||||
    COMPREPLY=($(compgen -W "$(__pman_pdev_branches)" "$cur"))
 | 
			
		||||
    COMPREPLY=($(compgen -W "$(__pman_pmer_branches)" "$cur"))
 | 
			
		||||
}
 | 
			
		||||
complete -F __pdev_completion pdev
 | 
			
		||||
complete -F __pmer_completion pmer
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,20 @@
 | 
			
		||||
# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | 
			
		||||
 | 
			
		||||
source "$@" || exit 1
 | 
			
		||||
cd "$srcdir"
 | 
			
		||||
 | 
			
		||||
# supprimer les fichiers de VCS
 | 
			
		||||
rm -rf "$srcdir/.git"
 | 
			
		||||
rm -rf .git
 | 
			
		||||
 | 
			
		||||
# completion
 | 
			
		||||
fromdir=lib/completion.d
 | 
			
		||||
todir="$HOME/etc/completion.d"
 | 
			
		||||
mkdir -p "$todir"
 | 
			
		||||
for file in pman; do
 | 
			
		||||
    from="$fromdir/$file"
 | 
			
		||||
    to="$todir/$file"
 | 
			
		||||
    if [ -f "$to" ]; then
 | 
			
		||||
        diff -q "$from" "$to" && continue
 | 
			
		||||
    fi
 | 
			
		||||
    cp "$from" "$to"
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										112
									
								
								php/src/A.php
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								php/src/A.php
									
									
									
									
									
								
							@ -1,13 +1,14 @@
 | 
			
		||||
<?php
 | 
			
		||||
namespace nulib;
 | 
			
		||||
 | 
			
		||||
use nulib\php\func;
 | 
			
		||||
use Traversable;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Class A: gestion de tableaux ou d'instances de {@link IArrayWrapper}
 | 
			
		||||
 *
 | 
			
		||||
 * contrairement à {@link cl}, les méthodes de cette classes sont plutôt conçues
 | 
			
		||||
 * pour modifier le tableau en place
 | 
			
		||||
 * cette classe reprend les méthodes de {@link cl} avec la différence que la
 | 
			
		||||
 * modification est faite en place
 | 
			
		||||
 */
 | 
			
		||||
class A {
 | 
			
		||||
  /**
 | 
			
		||||
@ -232,4 +233,111 @@ class A {
 | 
			
		||||
    if ($assoc) uasort($array, cl::compare($keys));
 | 
			
		||||
    else usort($array, cl::compare($keys));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #############################################################################
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * s'assurer que $array est un tableau associatif, en remplaçant toutes les
 | 
			
		||||
   * clés numériques par la clé correspondante dans $key
 | 
			
		||||
   * <code>
 | 
			
		||||
   * $array = ["first", "second"]
 | 
			
		||||
   * A::ensure_assoc($array, ["a", "b"]);
 | 
			
		||||
   * // returns ["a" => "first", "b" => "second"]
 | 
			
		||||
   * </code>
 | 
			
		||||
   */
 | 
			
		||||
  static final function ensure_assoc(?array &$array, array $keys, ?array $params=null): void {
 | 
			
		||||
    $prefix = $params["key_prefix"] ?? null;
 | 
			
		||||
    $suffix = $params["key_suffix"] ?? null;
 | 
			
		||||
    $index = 0;
 | 
			
		||||
    foreach ($keys as $key) {
 | 
			
		||||
      if ($prefix !== null || $suffix !== null) {
 | 
			
		||||
        $destKey = "$prefix$key$suffix";
 | 
			
		||||
      } else {
 | 
			
		||||
        # préserver les clés numériques
 | 
			
		||||
        $destKey = $key;
 | 
			
		||||
      }
 | 
			
		||||
      if ($array !== null && array_key_exists($destKey, $array)) continue;
 | 
			
		||||
      while (in_array($index, $keys, true)) {
 | 
			
		||||
        $index++;
 | 
			
		||||
      }
 | 
			
		||||
      if ($array !== null && array_key_exists($index, $array)) {
 | 
			
		||||
        $array[$destKey] = $array[$index];
 | 
			
		||||
        unset($array[$index]);
 | 
			
		||||
        $index++;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * s'assurer que $array contient toutes les clés de $defaults, avec la valeur
 | 
			
		||||
   * par défaut le cas échéant
 | 
			
		||||
   *
 | 
			
		||||
   * $missings est un tableau indiquant des valeurs qui si elles sont dans
 | 
			
		||||
   * $array, signifie que la clé correspondante doit être considérée comme
 | 
			
		||||
   * inexistante (et donc remplacée par la valeur de $defaults)
 | 
			
		||||
   */
 | 
			
		||||
  static final function ensure_keys(?array &$array, array $defaults, ?array $missings=null, ?array $params=null): void {
 | 
			
		||||
    $keys = array_keys($defaults);
 | 
			
		||||
    $prefix = $params["key_prefix"] ?? null;
 | 
			
		||||
    $suffix = $params["key_suffix"] ?? null;
 | 
			
		||||
    foreach ($keys as $key) {
 | 
			
		||||
      $destKey = "$prefix$key$suffix";
 | 
			
		||||
      $haveMissing = $missings !== null && array_key_exists($key, $missings);
 | 
			
		||||
      if ($array === null || !array_key_exists($destKey, $array)) {
 | 
			
		||||
        $array[$destKey] = $defaults[$key];
 | 
			
		||||
      } elseif ($haveMissing && $array[$destKey] === $missings[$key]) {
 | 
			
		||||
        $array[$destKey] = $defaults[$key];
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * supprimer dans $array les clés dont les valeurs correspondent au tableau
 | 
			
		||||
   * $missings
 | 
			
		||||
   */
 | 
			
		||||
  static final function delete_missings(?array &$array, array $missings, ?array $params=null): void {
 | 
			
		||||
    $prefix = $params["key_prefix"] ?? null;
 | 
			
		||||
    $suffix = $params["key_suffix"] ?? null;
 | 
			
		||||
    foreach ($missings as $key => $missing) {
 | 
			
		||||
      $destKey = "$prefix$key$suffix";
 | 
			
		||||
      if (array_key_exists($destKey, $array) && $array[$destKey] === $missing) {
 | 
			
		||||
        unset($array[$destKey]);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * s'assurer que les clés dans $array sont dans le même ordre que dans $keys
 | 
			
		||||
   *
 | 
			
		||||
   * les clés supplémentaires sont poussées à la fin du tableau
 | 
			
		||||
   */
 | 
			
		||||
  static final function ensure_order(?array &$array, array $keys, ?array $params=null): void {
 | 
			
		||||
    if ($array === null) return;
 | 
			
		||||
 | 
			
		||||
    $prefix = $params["key_prefix"] ?? null;
 | 
			
		||||
    $suffix = $params["key_suffix"] ?? null;
 | 
			
		||||
    if ($prefix !== null || $suffix !== null) {
 | 
			
		||||
      foreach ($keys as &$key) {
 | 
			
		||||
        $key = "$prefix$key$suffix";
 | 
			
		||||
      }; unset($key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $destKeys = array_keys($array);
 | 
			
		||||
    $keyCount = count($keys);
 | 
			
		||||
    if (array_slice($destKeys, 0, $keyCount) === $keys) {
 | 
			
		||||
      # si le tableau a déjà les bonnes clés dans le bon ordre, rien à faire
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    $ordered = [];
 | 
			
		||||
    foreach ($keys as $key) {
 | 
			
		||||
      if (array_key_exists($key, $array)) {
 | 
			
		||||
        $ordered[$key] = $array[$key];
 | 
			
		||||
        unset($array[$key]);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $preserveKeys = $params["preserve_keys"] ?? false;
 | 
			
		||||
    if ($preserveKeys) $array = cl::merge2($ordered, $array);
 | 
			
		||||
    else $array = array_merge($ordered, $array);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -460,7 +460,7 @@ class RunFile {
 | 
			
		||||
      $exitcode = null;
 | 
			
		||||
      $message = [
 | 
			
		||||
        "status" => "$desc: EN COURS pid $data[pid]",
 | 
			
		||||
        "started" => "Démarrée depuis $dateStart ($sinceStart)",
 | 
			
		||||
        "started" => "Démarrée $sinceStart le $dateStart",
 | 
			
		||||
        "action" => $action,
 | 
			
		||||
      ];
 | 
			
		||||
    } elseif ($this->isStopped($data)) {
 | 
			
		||||
@ -471,8 +471,9 @@ class RunFile {
 | 
			
		||||
      elseif ($exitcode === 0) $type = "success";
 | 
			
		||||
      else $type = "danger";
 | 
			
		||||
      $message = [
 | 
			
		||||
        "status" => "$desc: TERMINEE$duration",
 | 
			
		||||
        "status" => "$desc: TERMINEE",
 | 
			
		||||
        "stopped" => "Arrêtée $sinceStop le $dateStop",
 | 
			
		||||
        "duration" => $duration,
 | 
			
		||||
        "result" => $result,
 | 
			
		||||
      ];
 | 
			
		||||
    } else {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										139
									
								
								php/src/cl.php
									
									
									
									
									
								
							
							
						
						
									
										139
									
								
								php/src/cl.php
									
									
									
									
									
								
							@ -60,6 +60,35 @@ class cl {
 | 
			
		||||
    return $default;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * retourner la valeur à l'index $index, ou $default si le tableau est null
 | 
			
		||||
   * ou vide, ou si l'index n'existe pas
 | 
			
		||||
   *
 | 
			
		||||
   * ici, l'index est le rang de la clé: 0 pour la première clé du tableau, 1
 | 
			
		||||
   * pour la deuxième, etc.
 | 
			
		||||
   *
 | 
			
		||||
   * si $index est négatif, il est compté à partir de la fin du tableau
 | 
			
		||||
   */
 | 
			
		||||
  static final function nth(?iterable $iterable, int $index, $default=null) {
 | 
			
		||||
    if ($iterable === null) return $default;
 | 
			
		||||
    if ($index < 0 && !is_array($iterable)) {
 | 
			
		||||
      $iterable = iterator_to_array($iterable, false);
 | 
			
		||||
    }
 | 
			
		||||
    if (is_array($iterable)) {
 | 
			
		||||
      $keys = array_keys($iterable);
 | 
			
		||||
      $count = count($keys);
 | 
			
		||||
      while ($index < 0) $index += $count;
 | 
			
		||||
      $key = $keys[$index] ?? null;
 | 
			
		||||
      if ($key === null) return $default;
 | 
			
		||||
      return $iterable[$key];
 | 
			
		||||
    }
 | 
			
		||||
    foreach ($iterable as $value) {
 | 
			
		||||
      if ($index === 0) return $value;
 | 
			
		||||
      $index--;
 | 
			
		||||
    }
 | 
			
		||||
    return $default;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * retourner la dernière valeur de $array ou $default si le tableau est null
 | 
			
		||||
   * ou vide
 | 
			
		||||
@ -212,7 +241,7 @@ class cl {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * obtenir la liste des clés finalement obtenues après l'appel à
 | 
			
		||||
   * obtenir la liste des clés qui seraient finalement obtenues après l'appel à
 | 
			
		||||
   * {@link self::select()} avec le mapping spécifié
 | 
			
		||||
   */
 | 
			
		||||
  static final function selected_keys(?array $mappings): array {
 | 
			
		||||
@ -255,7 +284,7 @@ class cl {
 | 
			
		||||
   * $includes qui ne sont pas mentionnées dans $excludes.
 | 
			
		||||
   *
 | 
			
		||||
   * - si $includes===null && $excludes===null, retourner le tableau inchangé
 | 
			
		||||
   * - si $includes vaut null, prendre toutes les clés
 | 
			
		||||
   * - si $includes vaut null, c'est comme si toutes les clés étaient incluses
 | 
			
		||||
   *
 | 
			
		||||
   */
 | 
			
		||||
  static final function xselect($array, ?array $includes, ?array $excludes=null): ?array {
 | 
			
		||||
@ -302,6 +331,27 @@ class cl {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * si $array est un array ou une instance de ArrayAccess&Traversable,
 | 
			
		||||
   * supprimer le premier élément dont la valeur est $value
 | 
			
		||||
   *
 | 
			
		||||
   * @param array|ArrayAccess $array
 | 
			
		||||
   */
 | 
			
		||||
  static final function delv(&$array, $value, bool $strict=false): void {
 | 
			
		||||
    if (is_array($array)) {
 | 
			
		||||
      $key = array_search($value, $array, $strict);
 | 
			
		||||
      if ($key !== false) unset($array[$key]);
 | 
			
		||||
    } elseif ($array instanceof ArrayAccess && $array instanceof Traversable) {
 | 
			
		||||
      $found = false;
 | 
			
		||||
      foreach ($array as $key => $val) {
 | 
			
		||||
        if ($strict) $found = $val === $value;
 | 
			
		||||
        else $found = $val == $value;
 | 
			
		||||
        if ($found) break;
 | 
			
		||||
      }
 | 
			
		||||
      if ($found) $array->offsetUnset($key);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** retourner le nombre d'éléments de $array */
 | 
			
		||||
  static final function count(?array $array): int {
 | 
			
		||||
    return $array !== null? count($array): 0;
 | 
			
		||||
@ -348,15 +398,86 @@ class cl {
 | 
			
		||||
 | 
			
		||||
  #############################################################################
 | 
			
		||||
 | 
			
		||||
  static final function map($func, ?iterable $array): array {
 | 
			
		||||
    $result = [];
 | 
			
		||||
    if ($array !== null) {
 | 
			
		||||
      $func = func::with($func);
 | 
			
		||||
      foreach ($array as $key => $value) {
 | 
			
		||||
        $result[$key] = $func->invoke([$value, $key]);
 | 
			
		||||
  /**
 | 
			
		||||
   * tester si $array 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
 | 
			
		||||
   */
 | 
			
		||||
  static final function filter(?array $array, $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 === null) return false;
 | 
			
		||||
        if (!array_key_exists($value, $array)) return false;
 | 
			
		||||
      } elseif (is_bool($value)) {
 | 
			
		||||
        if ($value) {
 | 
			
		||||
          if ($array === null || !array_key_exists($key, $array)) return false;
 | 
			
		||||
        } else {
 | 
			
		||||
          if ($array !== null && array_key_exists($key, $array)) return false;
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        if ($array === null) return false;
 | 
			
		||||
        if (!array_key_exists($key, $array)) return false;
 | 
			
		||||
        if ($array[$key] !== $value) return false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $result;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * mapper le tableau source $array 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" => $array["a"], "b" => $array["x"], "c" => "y", "d" => null]
 | 
			
		||||
   *
 | 
			
		||||
   * si une fonction est utilisée, sa signature est
 | 
			
		||||
   * <code>function(mixed $value, string|int $key, ?array $array)</code>
 | 
			
		||||
   */
 | 
			
		||||
  static function map(?array $array, ?array $map): ?array {
 | 
			
		||||
    if ($map === null) return $array;
 | 
			
		||||
    $index = 0;
 | 
			
		||||
    $mapped = [];
 | 
			
		||||
    foreach ($map as $key => $value) {
 | 
			
		||||
      if ($key === $index) {
 | 
			
		||||
        $index++;
 | 
			
		||||
        if ($value === null) $mapped[] = null;
 | 
			
		||||
        else $mapped[$value] = cl::get($array, $value);
 | 
			
		||||
      } elseif (is_callable($value)) {
 | 
			
		||||
        $func = func::with($value);
 | 
			
		||||
        $value = cl::get($array, $key);
 | 
			
		||||
        $mapped[$key] = $func->invoke([$value, $key, $array]);
 | 
			
		||||
      } else {
 | 
			
		||||
        if ($value === null) $mapped[$key] = null;
 | 
			
		||||
        else $mapped[$key] = cl::get($array, $value);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $mapped;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static final function mapf(?iterable $items, $func): array {
 | 
			
		||||
    $mapped = [];
 | 
			
		||||
    if ($items !== null) {
 | 
			
		||||
      $func = func::with($func);
 | 
			
		||||
      foreach ($items as $key => $item) {
 | 
			
		||||
        $mapped[$key] = $func->invoke([$item, $key, $items]);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return $mapped;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #############################################################################
 | 
			
		||||
 | 
			
		||||
@ -677,7 +677,7 @@ abstract class CapacitorStorage {
 | 
			
		||||
  function _delete(CapacitorChannel $channel, $filter, $func, ?array $args): int {
 | 
			
		||||
    $this->_create($channel);
 | 
			
		||||
    if ($func === null) $func = CapacitorChannel::onDelete;
 | 
			
		||||
    $onEach = func::with($func)->bind($channel);
 | 
			
		||||
    $onDelete = func::with($func)->bind($channel);
 | 
			
		||||
    $db = $this->db();
 | 
			
		||||
    # si on est déjà dans une transaction, désactiver la gestion des transactions
 | 
			
		||||
    $manageTransactions = $channel->isManageTransactions() && !$db->inTransaction();
 | 
			
		||||
@ -693,8 +693,8 @@ abstract class CapacitorStorage {
 | 
			
		||||
      $all = $this->_allCached("delete", $channel, $filter);
 | 
			
		||||
      foreach ($all as $values) {
 | 
			
		||||
        $rowIds = $this->getRowIds($channel, $values);
 | 
			
		||||
        $delete = boolval($onEach->invoke([$values["item"], $values, ...$args]));
 | 
			
		||||
        if ($delete) {
 | 
			
		||||
        $shouldDelete = boolval($onDelete->invoke([$values["item"], $values, ...$args]));
 | 
			
		||||
        if ($shouldDelete) {
 | 
			
		||||
          $db->exec([
 | 
			
		||||
            "delete",
 | 
			
		||||
            "from" => $tableName,
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,8 @@ class _select extends _common {
 | 
			
		||||
    return preg_match("/^select\b/i", $sql);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static function add_prefix(string $col, ?string $prefix): string {
 | 
			
		||||
  private static function add_prefix(?string $col, ?string $prefix): string {
 | 
			
		||||
    $col ??= "null";
 | 
			
		||||
    if ($prefix === null) return $col;
 | 
			
		||||
    if (strpos($col, ".") !== false) return $col;
 | 
			
		||||
    return "$prefix$col";
 | 
			
		||||
 | 
			
		||||
@ -81,6 +81,12 @@ class Pgsql implements IDatabase {
 | 
			
		||||
        #if ($tmp !== null) $dbconn = $tmp;
 | 
			
		||||
        #else $dbconn = ["" => $dbconn];
 | 
			
		||||
      }
 | 
			
		||||
      unset($dbconn["type"]);
 | 
			
		||||
      $name = $dbconn["name"] ?? null;
 | 
			
		||||
      if ($name !== null) {
 | 
			
		||||
        $dbconn[""] = $name;
 | 
			
		||||
        unset($dbconn["name"]);
 | 
			
		||||
      }
 | 
			
		||||
      $params["dbconn"] = $dbconn;
 | 
			
		||||
    }
 | 
			
		||||
    # dbconn
 | 
			
		||||
 | 
			
		||||
@ -40,12 +40,20 @@ class SqliteStorage extends CapacitorStorage {
 | 
			
		||||
    return new _sqliteMigration($migrations, $channel->getName());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function channelExists(string $name): bool {
 | 
			
		||||
    return null !== $this->db->get([
 | 
			
		||||
      "select name",
 | 
			
		||||
  function channelExists(string $name, ?array &$row=null): bool {
 | 
			
		||||
    $row = $this->db->one([
 | 
			
		||||
      "select",
 | 
			
		||||
      "from" => static::CHANNELS_TABLE,
 | 
			
		||||
      "where" => ["name" => $name],
 | 
			
		||||
    ]);
 | 
			
		||||
    return $row !== null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function getChannels(): iterable {
 | 
			
		||||
    return $this->db->all([
 | 
			
		||||
      "select",
 | 
			
		||||
      "from" => static::CHANNELS_TABLE,
 | 
			
		||||
    ]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  protected function _addToChannelsSql(CapacitorChannel $channel): array {
 | 
			
		||||
 | 
			
		||||
@ -59,9 +59,10 @@ class func {
 | 
			
		||||
   * @param bool $strict vérifier l'inexistence de la classe et l'existence de
 | 
			
		||||
   * la fonction (ne pas uniquement faire une vérification syntaxique)
 | 
			
		||||
   */
 | 
			
		||||
  static function verifix_function(&$func, bool $strict=true, ?string &$reason=null): bool {
 | 
			
		||||
  static function verifix_function(&$func, ?array &$args=null, bool $strict=true, ?string &$reason=null): bool {
 | 
			
		||||
    if ($strict) $reason = null;
 | 
			
		||||
    if ($func instanceof ReflectionFunction) return true;
 | 
			
		||||
    $rargs = null;
 | 
			
		||||
    if (is_string($func)) {
 | 
			
		||||
      $c = false;
 | 
			
		||||
      $f = $func;
 | 
			
		||||
@ -70,6 +71,7 @@ class func {
 | 
			
		||||
      $c = $func[0];
 | 
			
		||||
      if (!array_key_exists(1, $func)) return false;
 | 
			
		||||
      $f = $func[1];
 | 
			
		||||
      $rargs = array_slice($func, 2);
 | 
			
		||||
    } else {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
@ -90,6 +92,7 @@ class func {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $func = [false, $f];
 | 
			
		||||
    if ($rargs) $args = cl::merge($rargs, $args);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -98,7 +101,7 @@ class func {
 | 
			
		||||
   * {@link self::verifix_function()}
 | 
			
		||||
   */
 | 
			
		||||
  static function is_function($func, bool $strict=true, ?string &$reason=null): bool {
 | 
			
		||||
    return self::verifix_function($func, $strict, $reason);
 | 
			
		||||
    return self::verifix_function($func, $args, $strict, $reason);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #############################################################################
 | 
			
		||||
@ -115,9 +118,10 @@ class func {
 | 
			
		||||
   * @param bool $strict vérifier l'existence de la classe (ne pas uniquement
 | 
			
		||||
   * faire une vérification syntaxique)
 | 
			
		||||
   */
 | 
			
		||||
  static function verifix_class(&$func, bool $strict=true, ?string &$reason=null): bool {
 | 
			
		||||
  static function verifix_class(&$func, ?array &$args=null, bool $strict=true, ?string &$reason=null): bool {
 | 
			
		||||
    if ($strict) $reason = null;
 | 
			
		||||
    if ($func instanceof ReflectionClass) return true;
 | 
			
		||||
    $rargs = null;
 | 
			
		||||
    if (is_string($func)) {
 | 
			
		||||
      $c = $func;
 | 
			
		||||
      $f = false;
 | 
			
		||||
@ -126,6 +130,7 @@ class func {
 | 
			
		||||
      $c = $func[0];
 | 
			
		||||
      if (!array_key_exists(1, $func)) return false;
 | 
			
		||||
      $f = $func[1];
 | 
			
		||||
      $rargs = array_slice($func, 2);
 | 
			
		||||
    } else {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
@ -139,6 +144,7 @@ class func {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    $func = [$c, false];
 | 
			
		||||
    if ($rargs) $args = cl::merge($rargs, $args);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -147,7 +153,7 @@ class func {
 | 
			
		||||
   * {@link self::verifix_class()}
 | 
			
		||||
   */
 | 
			
		||||
  static function is_class($func, bool $strict=true, ?string &$reason=null): bool {
 | 
			
		||||
    return self::verifix_class($func, $strict, $reason);
 | 
			
		||||
    return self::verifix_class($func, $args, $strict, $reason);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #############################################################################
 | 
			
		||||
@ -198,14 +204,16 @@ class func {
 | 
			
		||||
   * liée à une classe avant d'être utilisée
 | 
			
		||||
   *
 | 
			
		||||
   * @param bool $strict vérifier l'existence de la classe et de la méthode si
 | 
			
		||||
   * @param array|null &$args
 | 
			
		||||
   * la méthode est liée (ne pas uniquement faire une vérification syntaxique)
 | 
			
		||||
   */
 | 
			
		||||
  static function verifix_static(&$func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool {
 | 
			
		||||
  static function verifix_static(&$func, ?array &$args = null, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool {
 | 
			
		||||
    if ($strict) $reason = null;
 | 
			
		||||
    if ($func instanceof ReflectionMethod) {
 | 
			
		||||
      $bound = false;
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    $rargs = null;
 | 
			
		||||
    if (is_string($func)) {
 | 
			
		||||
      if (!self::_parse_c_static($func, $c, $f, $bound)) return false;
 | 
			
		||||
      $cf = [$c, $f];
 | 
			
		||||
@ -252,6 +260,7 @@ class func {
 | 
			
		||||
        self::_parse_static($f);
 | 
			
		||||
      }
 | 
			
		||||
      $cf[1] = $f;
 | 
			
		||||
      $rargs = array_slice($func, 2);
 | 
			
		||||
    } else {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
@ -274,6 +283,7 @@ class func {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $func = $cf;
 | 
			
		||||
    if ($rargs) $args = cl::merge($rargs, $args);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -282,7 +292,7 @@ class func {
 | 
			
		||||
   * {@link self::verifix_static()}
 | 
			
		||||
   */
 | 
			
		||||
  static function is_static($func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool {
 | 
			
		||||
    return self::verifix_static($func, $strict, $bound, $reason);
 | 
			
		||||
    return self::verifix_static($func, $args, $strict, $bound, $reason);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #############################################################################
 | 
			
		||||
@ -335,12 +345,13 @@ class func {
 | 
			
		||||
   * @param bool $strict vérifier l'existence de la classe et de la méthode si
 | 
			
		||||
   * la méthode est liée (ne pas uniquement faire une vérification syntaxique)
 | 
			
		||||
   */
 | 
			
		||||
  static function verifix_method(&$func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool {
 | 
			
		||||
  static function verifix_method(&$func, ?array &$args=null, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool {
 | 
			
		||||
    if ($strict) $reason = null;
 | 
			
		||||
    if ($func instanceof ReflectionMethod) {
 | 
			
		||||
      $bound = false;
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    $rargs = null;
 | 
			
		||||
    if (is_string($func)) {
 | 
			
		||||
      if (!self::_parse_c_method($func, $c, $f, $bound)) return false;
 | 
			
		||||
      $cf = [$c, $f];
 | 
			
		||||
@ -388,6 +399,7 @@ class func {
 | 
			
		||||
        self::_parse_method($f);
 | 
			
		||||
      }
 | 
			
		||||
      $cf[1] = $f;
 | 
			
		||||
      $rargs = array_slice($func, 2);
 | 
			
		||||
    } else {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
@ -410,6 +422,7 @@ class func {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    $func = $cf;
 | 
			
		||||
    if ($rargs) $args = cl::merge($rargs, $args);
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -418,7 +431,7 @@ class func {
 | 
			
		||||
   * {@link self::verifix_method()}
 | 
			
		||||
   */
 | 
			
		||||
  static function is_method($func, bool $strict=true, ?bool &$bound=null, ?string &$reason=null): bool {
 | 
			
		||||
    return self::verifix_method($func, $strict, $bound, $reason);
 | 
			
		||||
    return self::verifix_method($func, $args, $strict, $bound, $reason);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #############################################################################
 | 
			
		||||
@ -452,13 +465,13 @@ class func {
 | 
			
		||||
        return new self(self::TYPE_METHOD, $func, $args, false);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (self::verifix_function($func, $strict, $reason)) {
 | 
			
		||||
    if (self::verifix_function($func, $args, $strict, $reason)) {
 | 
			
		||||
      return new self(self::TYPE_FUNCTION, $func, $args, false, $reason);
 | 
			
		||||
    } elseif (self::verifix_class($func, $strict, $reason)) {
 | 
			
		||||
    } elseif (self::verifix_class($func, $args, $strict, $reason)) {
 | 
			
		||||
      return new self(self::TYPE_CLASS, $func, $args, false, $reason);
 | 
			
		||||
    } elseif (self::verifix_method($func, $strict, $bound, $reason)) {
 | 
			
		||||
    } elseif (self::verifix_method($func, $args, $strict, $bound, $reason)) {
 | 
			
		||||
      return new self(self::TYPE_METHOD, $func, $args, $bound, $reason);
 | 
			
		||||
    } elseif (self::verifix_static($func, $strict, $bound, $reason)) {
 | 
			
		||||
    } elseif (self::verifix_static($func, $args, $strict, $bound, $reason)) {
 | 
			
		||||
      return new self(self::TYPE_STATIC, $func, $args, $bound, $reason);
 | 
			
		||||
    }
 | 
			
		||||
    return null;
 | 
			
		||||
 | 
			
		||||
@ -328,6 +328,22 @@ class str {
 | 
			
		||||
    else return preg_split('/\s+/', $s);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * découper la chaine:
 | 
			
		||||
   * - avec preg_split si $sep est une expression régulière /re/
 | 
			
		||||
   * - avec explode sinon
 | 
			
		||||
   */
 | 
			
		||||
  static final function split(string $sep, ?string $s): ?array {
 | 
			
		||||
    if ($s === null) return null;
 | 
			
		||||
    if ($sep === "") {
 | 
			
		||||
      return [$s];
 | 
			
		||||
    } elseif (substr($sep, 0, 1) === "/") {
 | 
			
		||||
      return preg_split($sep, $s);
 | 
			
		||||
    } else {
 | 
			
		||||
      return explode($sep, $s);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * joindre les éléments de $parts comme avec implode(), mais en ignorant les
 | 
			
		||||
   * valeurs fausses (cela n'inclue pas la chaine "0")
 | 
			
		||||
 | 
			
		||||
@ -12,10 +12,10 @@ class clTest extends TestCase {
 | 
			
		||||
  }
 | 
			
		||||
  function test_same_keys() {
 | 
			
		||||
    $array = ["a" => 42, "b" => "tesxt"]; $arrayKeys = array_keys($array);
 | 
			
		||||
    $xarray = ["parasite0", "a" => 42, "parasite1", "b" => "tesxt"]; $xarrayKeys = array_keys($array);
 | 
			
		||||
    $missingArray = ["c" => true]; $missingArrayKeys = array_keys($missingArray);
 | 
			
		||||
    $ref = ["a" => "int", "b" => "text"]; $refKeys = array_keys($ref);
 | 
			
		||||
    $missingArray = ["c" => true]; $missingKeys = array_keys($missingArray);
 | 
			
		||||
    $missingRef = ["c" => "bool"]; $missingKeys = array_keys($missingRef);
 | 
			
		||||
    $missingRef = ["c" => "bool"]; $missingRefKeys = array_keys($missingRef);
 | 
			
		||||
    $xarray = ["parasite0", "a" => 42, "parasite1", "b" => "tesxt"];
 | 
			
		||||
 | 
			
		||||
    $this->checkKeys(null, null, true, [], [], []);
 | 
			
		||||
    $this->checkKeys(null, [], true, [], [], []);
 | 
			
		||||
@ -29,8 +29,8 @@ class clTest extends TestCase {
 | 
			
		||||
    $this->checkKeys($array, [], true, [], $arrayKeys, []);
 | 
			
		||||
 | 
			
		||||
    $this->checkKeys($array, $ref, true, $arrayKeys, [], []);
 | 
			
		||||
    $this->checkKeys(cl::merge($array, $missingArray), $ref, true, $arrayKeys, $missingKeys, []);
 | 
			
		||||
    $this->checkKeys($array, cl::merge($ref, $missingRef), false, $arrayKeys, [], $missingKeys);
 | 
			
		||||
    $this->checkKeys(cl::merge($array, $missingArray), $ref, true, $arrayKeys, $missingArrayKeys, []);
 | 
			
		||||
    $this->checkKeys($array, cl::merge($ref, $missingRef), false, $arrayKeys, [], $missingRefKeys);
 | 
			
		||||
 | 
			
		||||
    $this->checkKeys($xarray, $ref, false, $arrayKeys, [0, 1], []);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -295,14 +295,14 @@ namespace nulib\php {
 | 
			
		||||
 | 
			
		||||
        $workf = $func;
 | 
			
		||||
        $msg = var_export($func, true)." (strict)";
 | 
			
		||||
        self::assertSame($verifix1, func::verifix_function($workf, true), "$msg --> verifix");
 | 
			
		||||
        self::assertSame($verifix1, func::verifix_function($workf, $args, true), "$msg --> verifix");
 | 
			
		||||
        if ($verifix1) {
 | 
			
		||||
          self::assertSame($func1, $workf, "$msg --> func");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $workf = $func;
 | 
			
		||||
        $msg = var_export($func, true)." (lenient)";
 | 
			
		||||
        self::assertSame($verifix2, func::verifix_function($workf, false), "$msg --> verifix");
 | 
			
		||||
        self::assertSame($verifix2, func::verifix_function($workf, $args, false), "$msg --> verifix");
 | 
			
		||||
        if ($verifix2) {
 | 
			
		||||
          self::assertSame($func2, $workf, "$msg --> func");
 | 
			
		||||
        }
 | 
			
		||||
@ -595,7 +595,7 @@ namespace nulib\php {
 | 
			
		||||
 | 
			
		||||
        $workf = $func;
 | 
			
		||||
        $msg = var_export($func, true)." (strict)";
 | 
			
		||||
        self::assertSame($verifix1, func::verifix_static($workf, true, $bound), "$msg --> verifix");
 | 
			
		||||
        self::assertSame($verifix1, func::verifix_static($workf, $args, true, $bound), "$msg --> verifix");
 | 
			
		||||
        if ($verifix1) {
 | 
			
		||||
          self::assertSame($bound1, $bound, "$msg --> bound");
 | 
			
		||||
          self::assertSame($func1, $workf, "$msg --> func");
 | 
			
		||||
@ -603,7 +603,7 @@ namespace nulib\php {
 | 
			
		||||
 | 
			
		||||
        $workf = $func;
 | 
			
		||||
        $msg = var_export($func, true)." (lenient)";
 | 
			
		||||
        self::assertSame($verifix2, func::verifix_static($workf, false, $bound), "$msg --> verifix");
 | 
			
		||||
        self::assertSame($verifix2, func::verifix_static($workf, $args, false, $bound), "$msg --> verifix");
 | 
			
		||||
        if ($verifix2) {
 | 
			
		||||
          self::assertSame($bound2, $bound, "$msg --> bound");
 | 
			
		||||
          self::assertSame($func2, $workf, "$msg --> func");
 | 
			
		||||
@ -894,7 +894,7 @@ namespace nulib\php {
 | 
			
		||||
 | 
			
		||||
        $workf = $func;
 | 
			
		||||
        $msg = var_export($func, true)." (strict)";
 | 
			
		||||
        self::assertSame($verifix1, func::verifix_method($workf, true, $bound), "$msg --> verifix");
 | 
			
		||||
        self::assertSame($verifix1, func::verifix_method($workf, $args, true, $bound), "$msg --> verifix");
 | 
			
		||||
        if ($verifix1) {
 | 
			
		||||
          self::assertSame($bound1, $bound, "$msg --> bound");
 | 
			
		||||
          self::assertSame($func1, $workf, "$msg --> func");
 | 
			
		||||
@ -902,7 +902,7 @@ namespace nulib\php {
 | 
			
		||||
 | 
			
		||||
        $workf = $func;
 | 
			
		||||
        $msg = var_export($func, true)." (lenient)";
 | 
			
		||||
        self::assertSame($verifix2, func::verifix_method($workf, false, $bound), "$msg --> verifix");
 | 
			
		||||
        self::assertSame($verifix2, func::verifix_method($workf, $args, false, $bound), "$msg --> verifix");
 | 
			
		||||
        if ($verifix2) {
 | 
			
		||||
          self::assertSame($bound2, $bound, "$msg --> bound");
 | 
			
		||||
          self::assertSame($func2, $workf, "$msg --> func");
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ outil pour gérer les projets PHP
 | 
			
		||||
  projets dépendants du projet courant
 | 
			
		||||
* pver: gestion des versions.
 | 
			
		||||
  calculer la prochaine version en respectant semver
 | 
			
		||||
* pdev: gérer les branches de features et hotfixes.
 | 
			
		||||
* pmer: gérer les branches de features et hotfixes.
 | 
			
		||||
* prel: faire une release.
 | 
			
		||||
  ces outils peuvent agir sur les projets dépendants: faire une release sur un
 | 
			
		||||
  projet downstream, ou synchroniser la version depuis un projet upstream
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user