directiveArgValue('ability'); $model = $this->directiveArgValue('modelForPolicy') ?? $this->directiveArgValue('models')[0]; Gate::authorize($ability, [$model, ...$this->modelsToCheck($root, $args, $context, $resolveInfo)]); return null; } /** * @param array $args * @return iterable> */ protected function modelsToCheck(mixed $root, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): iterable { $findList = $this->directiveArgValue('find'); $findValues = []; foreach ($findList as $find) { $findValues[] = Arr::get($args, $find) ?? throw self::missingKeyToFindModel($find); } $models = []; foreach ($this->getModelClasses() as $modelClass) { $queryBuilder = $modelClass::query(); $argumentSetDirectives = $resolveInfo->argumentSet->directives; $directivesContainsForceDelete = $argumentSetDirectives->contains( Utils::instanceofMatcher(ForceDeleteDirective::class), ); if ($directivesContainsForceDelete) { /** @see \Illuminate\Database\Eloquent\SoftDeletes */ // @phpstan-ignore-next-line because it involves mixins $queryBuilder->withTrashed(); } $directivesContainsRestore = $argumentSetDirectives->contains( Utils::instanceofMatcher(RestoreDirective::class), ); if ($directivesContainsRestore) { /** @see \Illuminate\Database\Eloquent\SoftDeletes */ // @phpstan-ignore-next-line because it involves mixins $queryBuilder->onlyTrashed(); } try { $enhancedBuilder = $resolveInfo->enhanceBuilder( $queryBuilder, $this->directiveArgValue('scopes', []), $root, $args, $context, $resolveInfo, Utils::instanceofMatcher(TrashedDirective::class), ); assert($enhancedBuilder instanceof EloquentBuilder); foreach ($findValues as $index => $findValue) { if ($findValue instanceof Model) { $models[] = $findValue; } else { $models[] = $this->directiveArgValue('findOrFail', false) ? $enhancedBuilder->where($this->directiveArgValue('columns')[$index], $findValue)->firstOrFail() : $enhancedBuilder->where($this->directiveArgValue('columns')[$index], $findValue)->first(); } } } catch (ModelNotFoundException $modelNotFoundException) { throw ClientSafeModelNotFoundException::fromLaravel($modelNotFoundException); } } return $models; } /** * Get the model class from the `model` argument of the field. * * @api * * @param string $argumentName The default argument name "model" may be overwritten * @return class-string[] */ protected function getModelClasses(string $argumentName = 'models'): array { $models = $this->directiveArgValue($argumentName, ASTHelper::modelName($this->definitionNode)) ?? throw new DefinitionException("Could not determine a model name for the '@{$this->name()}' directive on '{$this->nodeName()}'."); $namespaces = []; foreach ($models as $model) { $namespaces[] = $this->namespaceModelClass($model); } return $namespaces; } public static function missingKeyToFindModel(string $find): Error { return new Error("Got no key to find a model at the expected input path: {$find}."); } }