Repository navigation
v0.16.0 — Internal refactor, namespace re-shape, test/doc round-3/4/5
⚠️ Breaking change — namespace re-shape (#141)The flat
Vusys\NestedSet\Aggregates\*andVusys\NestedSet\Events\*namespaces are split by responsibility, and two user-implementable interfaces are promoted toContracts\(Laravel convention). Noclass_aliasshims —usestatements andEvent::listen(::class)calls must be updated. Pre-1.0 polish-phase window.Aggregates — most-likely-imported renames (full mapping in the PR #141 body):
Before After Aggregates\AggregateDefinitionAggregates\Definitions\AggregateDefinitionAggregates\ListenerAggregateDefinitionAggregates\Definitions\ListenerAggregateDefinitionAggregates\CompanionSpecAggregates\Definitions\CompanionSpecAggregates\CompanionSourceOrigin/CompanionSourceTransformAggregates\Definitions\…Aggregates\FilterPredicate/FilterPredicateKind/FilterValueQuoterAggregates\Filters\…Aggregates\AggregateRegistryAggregates\Registry\AggregateRegistryAggregates\AggregateSqlEmitter/DerivedAggregateFragments/VarianceSqlFragments/SqliteBitwiseAggregatesAggregates\Sql\…Aggregates\TreeAggregateListenerContracts\TreeAggregateListenerAggregates\AggregateDefinitionContractContracts\AggregateDefinitionContractPublic API roots —
Aggregate,ListenerAggregate,AggregateFunction,AggregateFixResult— stay atVusys\NestedSet\Aggregates\.Events — by lifecycle phase:
Sub-namespace Events Events\Mutation\NodeMoved,NodePromotedToRoot,NodesSwappedEvents\Subtree\SubtreeMoving,SubtreeMoved,SubtreeForceDeleting,SubtreeForceDeletedEvents\SoftDelete\SubtreeSoftDeleting,SubtreeSoftDeleted,SubtreeRestoring,SubtreeRestored,SoftDeleteMarkerCapturedEvents\BulkInsert\BulkInsertTreeStarting,BulkInsertTreePlanned,BulkInsertNodeSaved,BulkInsertTreeSaved,BulkInsertTreeCompletedEvents\Aggregates\NodeAggregatesRecomputed,AggregateDriftDetected,AggregateMaintenanceFailed,DeferredMaintenanceStarting,DeferredAggregateMaintenanceCompleted,FixAggregatesChunkCompleted,FixAggregatesCompleted,FixAggregatesJobDispatchedEvents\Repair\FixTreeCompleted,TreeIntegrityCheckedEvents\Diagnostics\ScopeViolationDetected
Events\EventDispatcherstays at the namespace root.Upgrade: ripgrep
use Vusys\\NestedSet\\Aggregates\\anduse Vusys\\NestedSet\\Events\\across your app and rewrite to the new FQCNs. The new locations are searchable in the docs site under §6.1 and §6.2.
v0.16.0 — Internal refactor, namespace re-shape, test/doc round-3/4/5
Pre-1.0 polish release: the round-3/4/5 sweeps. One BC-affecting namespace reshape (callout above), three internal-only refactors that split large files into focused classes by responsibility, a doc-coherence pass covering the M3–M5 features and the NodeTrait surface, and a test-reshuffle that mirrors tests/ to src/ and fills genuinely-reachable coverage gaps.
Refactor
- Split
AggregatesandEventsinto sub-namespaces (§6.1, §6.2) (#141). BC — see callout above. - Round-5 §7 code-smell consolidations (#142):
AggregateRegistry*CompanionsFor()dedupe → sharedfindFirstCompanion();TreeAggregateBuilderchain-fold tower →ChainFoldAccumulatorvalue object;HasNestedSetAggregatesnumeric helpers →Vusys\NestedSet\Aggregates\Numeric;HasTreeRelations::requireTreeBuilder()helper. - Split
TreeAggregateBuilder(2 710 LoC) into four focused classes underQuery\Aggregates\(§6.5) (#143) —AggregateValueComparator,AggregateSqlFragments,AggregateDiffer,FreshAggregateProjector. Pure motion; the original class is deleted (internal-only). - Extract listener PHP fix path to
Vusys\NestedSet\Aggregates\Listeners\ListenerMaintenance(§6.4) (#144) —HasNestedSetAggregatestrait drops 341 LoC; mutation hooks, public maintenance API, anchor/scope plumbing stay in the trait and delegate.
Tests
- Round-4 coverage gaps + broken-assertion fixes + marathon-test splits (#140). Replaces bare
addToAssertionCount(1)placeholders with real before/after snapshots; pins the documentedcountErrors()cycle-detection gap so it fails loudly if ever fixed. New coverage for cross-scopeparent_idcorruption (ScopedCorruptionRecoveryTest), Median/Percentile ×fixAggregatesinteraction, MeanArea structural moves, WeightedAvg edge cases (weight→0, negative weight, zero-total NULL),FixAggregatesJobserialisation + failure,bulkInsertTree × withDeferredAggregateMaintenancenesting, and parallelappendToNodeon the same parent (AppendToNodeConcurrencyTest, multi-writer-CI only). Three marathon scripted-scenario suites broken into focused regression-class names sharing seed helpers. - Namespace
tests/to mirrorsrc/(#145). 100+ files reorganised across three independently-green commits:Unit/re-nested intoAggregates/{Definitions,Filters,Registry,Sql},Attributes/,Events/,Query/;Feature/gainsMutation/,SoftDelete/,BulkInsert/,Events/,Scoping/,Fuzzers/;Feature/Aggregates/further split intoMaintenance/,Integrity/,Functions/,Listeners/,Repair/,Collections/. TheEdgeCasesTestcatch-all decomposed so each concern owns its edge cases. PSR-4 path→namespace rewrite verified as a no-op on the pre-refactor tree before any moves landed. ChainFoldAccumulator+Aggregatecoverage + data-provider adoption (#146). SQLite line coverage86.55% → 90.01%(1 321 → 1 454 tests). NewChainFoldAccumulatorTestcovers the PHP chain-fold fast path for every reachable kind (Sum/Count/Min/Max/Bit*/Avg/Variance/Stddev/WeightedAvg/BoolOr/BoolAnd/geometric+harmonic mean) plus companion source-transforms;Aggregatefactory coverage76% → 99.7%;DerivedAggregateFragments62% → 100%via snapshot tests;NestedSetAggregateattribute validation paths driven by a DataProvider; newScopedAreafixture (the only one combining partitioned trees with maintained aggregates) lifts theNestedSetScopeResolver+ scope-predicate paths.
Documentation
-
Cover M3–M5 + rewrite setup / maintenance / deferred sections (#138). New
docs/aggregates/means.md(geometric / harmonic, positivity & non-zero constraints,allowNonPositive(), theEXP(Σ LN(x) / n)precision caveat). Newdocs/aggregates/quantiles.md(median / percentile /percentiles([...])/quartiles()— fresh-read-only constraint, linear-interpolation semantics, per-backend SQL shape table). Replaces the previous SUM/COUNT-only caption insetup.mdwith a complete 14-rowtype:reference (display column shape, null/default convention, auto-allocated companions,dropNestedSetAggregate('col', type: …)requirement).maintenance.mdcost matrix replaced with families table covering delta-maintainable / companion-derived / extremum-recompute / chain-recompute / bitwise mixed / fresh-read-only.fix-aggregates.mdexpandswithDeferredAggregateMaintenancewith the explicit signature, scoped-model anchor requirement, re-entrancy counter, failure-safety, and observability events. -
Round-3 coherence pass — pitfalls callout, soft-deletes rewrite, exception taxonomy (#139). 15 docs-only fixes folded into one PR.
NodeTraitsurface inmodel-setup.mdupdated to includebulkInsertTree,moveTo/moveBefore/moveAfter,isSiblingOf,prevSibling/nextSibling, and theHasTreeExportconcern. New "Refresh after mutating a child" callout — the package only refreshes the target of a mutation, the parent reference you held goes stale (the #1 footgun). Exception taxonomy split into LogicException (programmer error) vs RuntimeException (data-state);CorruptTreeExceptionandAggregateSourceConstraintViolationExceptionadded (were missing).soft-deletes.mdrewritten from a 15-line stub to cover cascade lifecycles, microsecond timestamp matching (DATETIME(6)caveat), aggregate semantics on cascade, and scope interaction. Listener AVG companion migration example now shows the float-returning case as adecimalcolumn (bigint default silently truncated).queries.mdordered-output examples now calldefaultOrder().bulk-insertion.mdnotes the silent scope-column override.