getVisitFn() public static method

public static getVisitFn ( $visitor, $kind, $isLeaving ) : null
$visitor
$kind
$isLeaving
return null
 /**
  * This uses a specialized visitor which runs multiple visitors in parallel,
  * while maintaining the visitor skip and break API.
  *
  * @param Schema $schema
  * @param Document $documentAST
  * @param array $rules
  * @return array
  */
 public static function visitUsingRules(Schema $schema, Document $documentAST, array $rules)
 {
     $typeInfo = new TypeInfo($schema);
     $context = new ValidationContext($schema, $documentAST, $typeInfo);
     $errors = [];
     // TODO: convert to class
     $visitInstances = function ($ast, $instances) use($typeInfo, $context, &$errors, &$visitInstances) {
         $skipUntil = new \SplFixedArray(count($instances));
         $skipCount = 0;
         Visitor::visit($ast, ['enter' => function ($node, $key) use($typeInfo, $instances, $skipUntil, &$skipCount, &$errors, $context, $visitInstances) {
             $typeInfo->enter($node);
             for ($i = 0; $i < count($instances); $i++) {
                 // Do not visit this instance if it returned false for a previous node
                 if ($skipUntil[$i]) {
                     continue;
                 }
                 $result = null;
                 // Do not visit top level fragment definitions if this instance will
                 // visit those fragments inline because it
                 // provided `visitSpreadFragments`.
                 if ($node->kind === Node::FRAGMENT_DEFINITION && $key !== null && !empty($instances[$i]['visitSpreadFragments'])) {
                     $result = Visitor::skipNode();
                 } else {
                     $enter = Visitor::getVisitFn($instances[$i], false, $node->kind);
                     if ($enter instanceof \Closure) {
                         // $enter = $enter->bindTo($instances[$i]);
                         $result = call_user_func_array($enter, func_get_args());
                     } else {
                         $result = null;
                     }
                 }
                 if ($result instanceof VisitorOperation) {
                     if ($result->doContinue) {
                         $skipUntil[$i] = $node;
                         $skipCount++;
                         // If all instances are being skipped over, skip deeper traversal
                         if ($skipCount === count($instances)) {
                             for ($k = 0; $k < count($instances); $k++) {
                                 if ($skipUntil[$k] === $node) {
                                     $skipUntil[$k] = null;
                                     $skipCount--;
                                 }
                             }
                             return Visitor::skipNode();
                         }
                     } else {
                         if ($result->doBreak) {
                             $instances[$i] = null;
                         }
                     }
                 } else {
                     if ($result && self::isError($result)) {
                         self::append($errors, $result);
                         for ($j = $i - 1; $j >= 0; $j--) {
                             $leaveFn = Visitor::getVisitFn($instances[$j], true, $node->kind);
                             if ($leaveFn) {
                                 // $leaveFn = $leaveFn->bindTo($instances[$j])
                                 $result = call_user_func_array($leaveFn, func_get_args());
                                 if ($result instanceof VisitorOperation) {
                                     if ($result->doBreak) {
                                         $instances[$j] = null;
                                     }
                                 } else {
                                     if (self::isError($result)) {
                                         self::append($errors, $result);
                                     } else {
                                         if ($result !== null) {
                                             throw new \Exception("Config cannot edit document.");
                                         }
                                     }
                                 }
                             }
                         }
                         $typeInfo->leave($node);
                         return Visitor::skipNode();
                     } else {
                         if ($result !== null) {
                             throw new \Exception("Config cannot edit document.");
                         }
                     }
                 }
             }
             // If any validation instances provide the flag `visitSpreadFragments`
             // and this node is a fragment spread, validate the fragment from
             // this point.
             if ($node instanceof FragmentSpread) {
                 $fragment = $context->getFragment($node->name->value);
                 if ($fragment) {
                     $fragVisitingInstances = [];
                     foreach ($instances as $idx => $inst) {
                         if (!empty($inst['visitSpreadFragments']) && !$skipUntil[$idx]) {
                             $fragVisitingInstances[] = $inst;
                         }
                     }
                     if (!empty($fragVisitingInstances)) {
                         $visitInstances($fragment, $fragVisitingInstances);
                     }
                 }
             }
         }, 'leave' => function ($node) use($instances, $typeInfo, $skipUntil, &$skipCount, &$errors) {
             for ($i = count($instances) - 1; $i >= 0; $i--) {
                 if ($skipUntil[$i]) {
                     if ($skipUntil[$i] === $node) {
                         $skipUntil[$i] = null;
                         $skipCount--;
                     }
                     continue;
                 }
                 $leaveFn = Visitor::getVisitFn($instances[$i], true, $node->kind);
                 if ($leaveFn) {
                     // $leaveFn = $leaveFn.bindTo($instances[$i]);
                     $result = call_user_func_array($leaveFn, func_get_args());
                     if ($result instanceof VisitorOperation) {
                         if ($result->doBreak) {
                             $instances[$i] = null;
                         }
                     } else {
                         if (self::isError($result)) {
                             self::append($errors, $result);
                         } else {
                             if ($result !== null) {
                                 throw new \Exception("Config cannot edit document.");
                             }
                         }
                     }
                 }
             }
             $typeInfo->leave($node);
         }]);
     };
     // Visit the whole document with instances of all provided rules.
     $allRuleInstances = [];
     foreach ($rules as $rule) {
         $allRuleInstances[] = $rule($context);
     }
     $visitInstances($documentAST, $allRuleInstances);
     return $errors;
 }