From 4993696bcd746e72608cef090f92c2f035644973 Mon Sep 17 00:00:00 2001 From: Eric Lippmann Date: Thu, 2 Jul 2026 09:28:03 +0200 Subject: [PATCH] Release version 0.16.0 --- CHANGELOG.md | 78 +++++++++++++++++++++++++++++----------------------- README.md | 34 +++++++++++++++++++---- 2 files changed, 71 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a71158..57aa03e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,22 +4,29 @@ All notable changes to this library are documented in this file. ## [Unreleased] -## [v0.15.1] — 2026-04-21 +## [0.16.0] - 2026-07-02 + +- Add `Seq::map()` and `Filter\Chain::yieldRules()` (#75) +- Add `Seq::unique()` (#76, #80) +- Add `Str::isEmpty()` (#77) +- Fix `Seq::find()` to return `[null, null]` instead of `false` when no value is found (#79) + +## [0.15.1] - 2026-04-21 - Fix `Events::on()` return type to restore compatibility with `EventEmitterTrait` (#73) -## [v0.15.0] — 2026-03-24 +## [0.15.0] - 2026-03-24 - **Breaking** Raise minimum PHP version to 8.2 (#63) - Add strict type declarations (#63) - Support PHP 8.5 (#61) -## [v0.14.0] — 2024-07-15 +## [0.14.0] - 2024-07-15 - **Breaking** Restrict `Str::symmetricSplit()`'s `$default` parameter to `?string` (#55) - Support PHP 8.3 -## [v0.13.0] — 2023-09-21 +## [0.13.0] - 2023-09-21 - **Breaking** `Seq` no longer treats function names as needles (#42) - Add `iterable_value_first()` (#49) @@ -28,11 +35,11 @@ All notable changes to this library are documented in this file. - Support PHP 8.2 (#39) -## [v0.12.1] — 2022-12-13 +## [0.12.1] - 2022-12-13 - Refine `Str` method signatures and `null` handling to improve PHP 8.1 compatibility (#37) -## [v0.12.0] — 2022-06-15 +## [0.12.0] - 2022-06-15 - **Breaking** Raise the minimum supported PHP version to 7.2 (#29) - **Breaking** `Filter::equal()` and `Filter::unequal()` no longer perform wildcard matching; @@ -41,19 +48,19 @@ All notable changes to this library are documented in this file. - Add iteration support to `Properties` via `IteratorAggregate` (#32) - Support PHP 8.1 (#29) -## [v0.11.0] — 2022-03-23 +## [0.11.0] - 2022-03-23 - **Breaking** Drop PHP 5.6 support; require PHP ≥ 7.0 (#28) - Introduce `BaseFilter` trait for simple filter-aware classes (#28) -## [v0.10.0] — 2021-11-10 +## [0.10.0] - 2021-11-10 - Add the `Seq` utility for searching iterables by key or value (#26) - Fix `Properties` to not mutate values on set (#23); resolve closures before mutation (#24) - Support PHP 8 (#21) -## [v0.9.0] — 2021-03-19 +## [0.9.0] - 2021-03-19 - **Breaking** `Filter\Chain` and `Filter\Condition` no longer tolerate dynamic properties; use dedicated metadata instead (#20) @@ -63,22 +70,22 @@ All notable changes to this library are documented in this file. - Introduce `MetaDataProvider` interface for filter rule metadata (#20) - Extend `Filter\Chain` with `insertBefore()` and `insertAfter()` (#20) -## [v0.8.0] — 2021-01-14 +## [0.8.0] - 2021-01-14 - Introduce filter system: `Filter` facade and `Filter\Rule`, `Filter\Chain` (`All`, `Any`, `None`), and `Filter\Condition` (`Equal`, `Unequal`, `GreaterThan`, `GreaterThanOrEqual`, `LessThan`, `LessThanOrEqual`) (#15) - Add `random_bytes()` polyfill for PHP < 7.0 (#18) -## [v0.7.0] — 2020-10-19 +## [0.7.0] - 2020-10-19 - Introduce `Properties` trait for dynamic typed property storage (#16) -## [v0.6.0] — 2020-10-12 +## [0.6.0] - 2020-10-12 - Introduce `Translator` contract interface (#14) -## [v0.5.0] — 2020-03-12 +## [0.5.0] - 2020-03-12 - **Breaking** Raise the minimum supported PHP version to 5.6 (#12) - **Breaking** Refactor contracts and traits: rename `EventEmitter` → `Events`, @@ -88,42 +95,43 @@ All notable changes to this library are documented in this file. - Introduce `PriorityQueue` class wrapping `SplPriorityQueue` with stable ordering (#13) -## [v0.4.0] — 2020-03-10 +## [0.4.0] - 2020-03-10 - Add `iterable_key_first()` for retrieving the first key from any iterable (#10) - Add `Str::symmetricSplit()`, `Str::trimSplit()`, and `Str::startsWith()` -## [v0.3.0] — 2019-10-16 +## [0.3.0] - 2019-10-16 - Introduce `PaginationInterface` (#5) - Introduce `Str` class with `camel()` case conversion - Add `is_iterable()` polyfill for PHP < 7.1 -## [v0.2.0] — 2019-05-16 +## [0.2.0] - 2019-05-16 - Introduce `EventEmitter` trait, wrapping [Evenement](https://github.com/igorw/evenement) (#8) -## [v0.1.0] — 2019-03-26 +## [0.1.0] - 2019-03-26 Initial release providing `AutoloadingPluginLoader`, `MessageContainer` trait, `ValidatorInterface`, and type/iterable utility functions. -[Unreleased]: https://github.com/Icinga/ipl-stdlib/compare/v0.15.1...HEAD -[v0.15.1]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.15.1 -[v0.15.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.15.0 -[v0.14.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.14.0 -[v0.13.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.13.0 -[v0.12.1]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.12.1 -[v0.12.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.12.0 -[v0.11.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.11.0 -[v0.10.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.10.0 -[v0.9.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.9.0 -[v0.8.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.8.0 -[v0.7.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.7.0 -[v0.6.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.6.0 -[v0.5.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.5.0 -[v0.4.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.4.0 -[v0.3.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.3.0 -[v0.2.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.2.0 -[v0.1.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.1.0 +[Unreleased]: https://github.com/Icinga/ipl-stdlib/compare/v0.16.0...HEAD +[0.16.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.16.0 +[0.15.1]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.15.1 +[0.15.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.15.0 +[0.14.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.14.0 +[0.13.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.13.0 +[0.12.1]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.12.1 +[0.12.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.12.0 +[0.11.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.11.0 +[0.10.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.10.0 +[0.9.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.9.0 +[0.8.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.8.0 +[0.7.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.7.0 +[0.6.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.6.0 +[0.5.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.5.0 +[0.4.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.4.0 +[0.3.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.3.0 +[0.2.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.2.0 +[0.1.0]: https://github.com/Icinga/ipl-stdlib/releases/tag/v0.1.0 diff --git a/README.md b/README.md index ac94294..5d70090 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,14 @@ Available condition factories: `equal`, `unequal`, `like`, `unlike`, `greaterThan`, `greaterThanOrEqual`, `lessThan`, `lessThanOrEqual`. Available logical factories: `all`, `any`, `none`, `not`. +Flatten nested chains when you need to inspect individual rules: + +```php +foreach ($filter->yieldRules() as $rule) { + // Inspect each leaf rule. +} +``` + ### Build Filters Incrementally When an object needs to collect filter conditions over time, use the `Filters` @@ -145,6 +153,11 @@ Str::trimSplit('root:secret', ':'); // ['root', 'secret'] // Case-insensitive prefix check: Str::startsWith('Foobar', 'foo', caseSensitive: false); // true Str::startsWith('foobar', 'foo'); // true + +// Empty-string check: +Str::isEmpty(null); // true +Str::isEmpty(' '); // true +Str::isEmpty('0'); // false ``` ### Seq @@ -166,8 +179,17 @@ Seq::contains($users, 'viewer'); // true [$key, $value] = Seq::find($users, 'admin'); // ['alice', 'admin'] -// Match by predicate — returns as soon as a result is found: -[$key, $value] = Seq::find($users, fn(string $role): bool => $role !== 'admin'); // ['bob', 'viewer'] +// Match by predicate. Returns as soon as a result is found: +[$key, $value] = Seq::find( + $users, + fn(string $role): bool => $role !== 'admin' +); // ['bob', 'viewer'] + +// Transform values while preserving keys: +$roles = Seq::map($users, fn(string $role): string => strtoupper($role)); + +// Yield unique values while preserving their first keys: +$roles = Seq::unique(['first' => 'admin', 'second' => 'admin', 'third' => 1]); ``` ### Iterable Helpers @@ -184,7 +206,7 @@ $map = [ iterable_key_first($map); // 'id' iterable_value_first($map); // 42 -// Works with generators and iterators — does not require an array: +// Works with generators and iterators. Does not require an array: iterable_key_first(new ArrayIterator(['a' => 1])); // 'a' iterable_key_first([]); // null ``` @@ -207,10 +229,10 @@ foreach (yield_groups($rows, fn(object $row): string => $row->category) as $cate ### Other Utility Classes -- `Data` — mutable key/value store -- `Messages` — collects user-facing messages and supports `sprintf`-style +- `Data`: mutable key/value store +- `Messages`: collects user-facing messages and supports `sprintf`-style placeholders -- `PriorityQueue` — extends `SplPriorityQueue` with stable insertion-order for +- `PriorityQueue`: extends `SplPriorityQueue` with stable insertion-order for items at equal priority; iterate non-destructively with `yieldAll()` ## Changelog