@@ -316,6 +316,44 @@ public function testWithClosureRules():void
316316 self ::assertContains ('[1]b Fail condition from closure ' , $ model ->getErrors ('indexed ' ));
317317 }
318318
319+ public function testWithCallableRules ():void
320+ {
321+ $ data = [
322+ 'hash ' => ['a ' => 1 , 'b ' => 'foo ' ],
323+ 'indexed ' => [
324+ ['a ' => 1 , 'b ' => 'foo ' ],
325+ ['a ' => 12 , 'b ' => 'bar ' ],
326+ ],
327+ ];
328+
329+ $ structure = [
330+ 'a ' => [
331+ ['integer ' ],
332+ [Closure::fromCallable ([$ this , 'callableValidator ' ])],
333+ ],
334+ 'b ' => [
335+ [Closure::fromCallable ([$ this , 'callableValidator ' ])]
336+ ],
337+ ];
338+ $ rules = [
339+ ['hash ' , ArrayStructureValidator::class, ['rules ' => $ structure ]],
340+ [
341+ 'indexed ' ,
342+ ArrayStructureValidator::class,
343+ ['rules ' => $ structure , 'compactErrors ' => false , 'each ' => true ],
344+ ],
345+ ];
346+ $ model = new DynamicModel ($ data );
347+ foreach ($ rules as $ rule ) {
348+ $ model ->addRule (...$ rule );
349+ }
350+ //VarDumper::dump($model->errors);
351+ self ::assertFalse ($ model ->validate ());
352+ self ::assertFalse ($ model ->hasErrors ('hash ' ));
353+ self ::assertContains ('[1]a Fail condition from callable ' , $ model ->getErrors ('indexed ' ));
354+ self ::assertContains ('[1]b Fail condition from callable ' , $ model ->getErrors ('indexed ' ));
355+ }
356+
319357 public function testNestedArray ():void
320358 {
321359 $ data = [
@@ -773,4 +811,23 @@ public function rules()
773811 $ model ->validate ();
774812 self ::assertNull ($ model ->value ['z ' ]);
775813 }
814+
815+ public function callableValidator ($ attribute , $ model , $ index , $ baseModel , $ baseAttribute ) {
816+ if ($ baseAttribute === 'hash ' ) {
817+ self ::assertNull ($ index );
818+ } else {
819+ self ::assertTrue (in_array ($ index , [0 , 1 ], true ));
820+ }
821+ self ::assertInstanceOf (DynamicModel::class, $ model );
822+ self ::assertInstanceOf (DynamicModel::class, $ baseModel );
823+ self ::assertTrue ($ model ->hasAttribute ('a ' ));
824+ self ::assertTrue ($ model ->hasAttribute ('b ' ));
825+ self ::assertFalse ($ model ->hasAttribute ('hash ' ));
826+ self ::assertFalse ($ baseModel ->hasAttribute ('a ' ));
827+ self ::assertTrue ($ baseModel ->hasAttribute ('hash ' ));
828+ self ::assertTrue ($ baseModel ->hasAttribute ('indexed ' ));
829+ if ($ model ->b !== 'foo ' ) {
830+ $ model ->addError ($ attribute , $ attribute . ' Fail condition from callable ' );
831+ }
832+ }
776833}
0 commit comments