150 lines
4.0 KiB
PHP
150 lines
4.0 KiB
PHP
<?php
|
|
namespace nur\b\values;
|
|
|
|
use nur\A;
|
|
|
|
/**
|
|
* Class Breaker: aide pour construire des listes multi-niveaux.
|
|
*
|
|
* Dans une liste, certaines valeurs sont des clés. L'idée est de pouvoir
|
|
* visuellement représenter les valeurs associées à ces clés. La méthode
|
|
* should_break_on() indique quand la clé change, ce qui indique qu'il faut
|
|
* passer à la section suivante.
|
|
*
|
|
* Par exemple, avec la liste suivante:
|
|
* clé valeur
|
|
* A 1.1
|
|
* A 1.2
|
|
* A 1.3
|
|
* B 2.1
|
|
* B 2.2
|
|
* C 3.1
|
|
* should_break_on($row["clé"]) retourne true pour les valeurs 1.1, 2.1 et 3.1
|
|
* et donc on peut facilement construire cette liste pour affichage:
|
|
* clé valeur
|
|
* A 1.1
|
|
* 1.2
|
|
* 1.3
|
|
* B 2.1
|
|
* 2.2
|
|
* C 3.1
|
|
*/
|
|
class Breaker {
|
|
function __construct() {
|
|
$this->reset();
|
|
}
|
|
|
|
private $values;
|
|
|
|
private $changedKeys;
|
|
|
|
private function computeShouldBreak(array $values): bool {
|
|
$should_break = false;
|
|
foreach ($values as $key => $value) {
|
|
if (!$should_break) {
|
|
if ($value === A::get($this->values, $key)) {
|
|
$this->changedKeys[$key] = false;
|
|
continue;
|
|
} else {
|
|
$should_break = true;
|
|
}
|
|
}
|
|
$this->changedKeys[$key] = $should_break;
|
|
}
|
|
$this->values = $values;
|
|
return $should_break;
|
|
}
|
|
|
|
function reset() {
|
|
$this->values = [];
|
|
$this->changedKeys = [];
|
|
}
|
|
|
|
/**
|
|
* Retourner true si $values est différent par rapport au précédent appel
|
|
*
|
|
* $value peut contenir des instances de Breaker à condition que leur
|
|
* méthodes {@link shouldBreakOn()} aient déjà été appelées.
|
|
*/
|
|
function shouldBreakOn(...$values): bool {
|
|
# résoudre les éventuelles instances de Breaker
|
|
$actual_values = [];
|
|
foreach ($values as $value) {
|
|
if ($value instanceof Breaker) {
|
|
$actual_values = array_merge($actual_values, $value->values);
|
|
} else {
|
|
$actual_values[] = $value;
|
|
}
|
|
}
|
|
return $this->computeShouldBreak($actual_values);
|
|
}
|
|
|
|
/**
|
|
* Retourner true si les valeurs de $array correspondant aux clés $keys sont
|
|
* différentes par rapport au précédent appel
|
|
*
|
|
* $keys peut contenir des instances de Breaker à condition que leur méthodes
|
|
* {@link shouldBreakOnKeys()} aient déjà été appelées.
|
|
*/
|
|
function shouldBreakOnKeys($array, ...$keys): bool {
|
|
# résoudre les éventuelles instances de Breaker
|
|
$values = [];
|
|
foreach ($keys as $key) {
|
|
if ($key instanceof Breaker) {
|
|
$values[] = $key;
|
|
} else {
|
|
$values[$key] = A::get($array, $key);
|
|
}
|
|
}
|
|
$actual_values = [];
|
|
foreach ($values as $key => $value) {
|
|
if ($value instanceof Breaker) {
|
|
$actual_values = array_merge($actual_values, $value->values);
|
|
} else {
|
|
$actual_values[$key] = $value;
|
|
}
|
|
}
|
|
return $this->computeShouldBreak($actual_values);
|
|
}
|
|
|
|
/**
|
|
* Tester si la clé spécifiée a été changée.
|
|
*
|
|
* Il faut d'abord avoir appelé l'une des méthodes {@link shouldBreakOn()}
|
|
* ou {@link shouldBreakOnKeys()}
|
|
*/
|
|
function isChanged($key=null): bool {
|
|
if ($key !== null) return $this->changedKeys[$key];
|
|
foreach ($this->changedKeys as $changed) {
|
|
if ($changed) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Appeler {@link shouldBreakOn()}(...$values) puis retourner un tableau avec
|
|
* les valeurs non modifiées à false.
|
|
*/
|
|
function getChanged(...$values): array {
|
|
$this->shouldBreakOn(...$values);
|
|
$values = [];
|
|
foreach ($this->values as $key => $value) {
|
|
$values[$key] = $this->changedKeys[$key]? $value: false;
|
|
}
|
|
return $values;
|
|
}
|
|
|
|
/**
|
|
* Appeler {@link shouldBreakOnKeys()}($array, ...$keys) puis retourner un
|
|
* tableau avec les valeurs non modifiées à false.
|
|
*/
|
|
function getChangedKeys($array, ...$keys): array {
|
|
$this->shouldBreakOnKeys($array, ...$keys);
|
|
$values = [];
|
|
foreach ($this->values as $key => $value) {
|
|
$values[$key] = $this->changedKeys[$key]? $value: false;
|
|
}
|
|
return $values;
|
|
}
|
|
}
|