Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
77.78% covered (warning)
77.78%
21 / 27
60.00% covered (warning)
60.00%
3 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
AutoloadsOtherRelations
77.78% covered (warning)
77.78%
21 / 27
60.00% covered (warning)
60.00%
3 / 5
7.54
0.00% covered (danger)
0.00%
0 / 1
 autoloads
50.00% covered (danger)
50.00%
2 / 4
0.00% covered (danger)
0.00%
0 / 1
1.12
 getResults
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 match
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 matchOtherRelations
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 matchOtherRelation
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3namespace Baril\Bonsai\Relations\Concerns;
4
5use Illuminate\Database\Eloquent\Collection as EloquentCollection;
6use Illuminate\Database\Eloquent\Relations\Relation;
7
8/**
9 * @mixin \Illuminate\Database\Eloquent\Relations\Relation
10 */
11trait AutoloadsOtherRelations
12{
13    protected $otherRelationsAutoloads;
14
15    public function autoloads($relation, $callback = null)
16    {
17        $this->otherRelationsAutoloads[$relation] = $callback ?? function ($models, $results) {
18            return [$models, $results];
19        };
20
21        return $this;
22    }
23
24    /**
25     * @see \Illuminate\Database\Eloquent\Relations\BelongsToMany::getResults()
26     *
27     * @return \Illuminate\Database\Eloquent\Collection
28     */
29    public function getResults()
30    {
31        $results = parent::getResults();
32
33        $this->matchOtherRelations([$this->parent], $results);
34        $this->matchOtherRelations($results->all(), $results);
35
36        return $results;
37    }
38
39    /**
40     * Match the eagerly loaded results to their parents.
41     *
42     * @see \Illuminate\Database\Eloquent\Relations\BelongsToMany::match()
43     *
44     * @param  array<int, TDeclaringModel>  $models
45     * @param  \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>  $results
46     * @param  string  $relation
47     * @return array<int, TDeclaringModel>
48     */
49    public function match(array $models, EloquentCollection $results, $relation)
50    {
51        parent::match($models, $results, $relation);
52
53        $this->matchOtherRelations($models, $results);
54        $this->matchOtherRelations($results->all(), $results);
55
56        return $models;
57    }
58
59    protected function matchOtherRelations(array $models, EloquentCollection $results)
60    {
61        foreach ($this->otherRelationsAutoloads as $relation => $callback) {
62            list($models, $results) = $callback($models, $results);
63            $this->matchOtherRelation($models, $results, $relation);
64        }
65    }
66
67    /**
68     * On $this, and on each of the related models that were loaded by
69     * a "through-closures" relation (eg. "ancestors"), load the corresponding
70     * "closed" relation (eg. "parent").
71     *
72     * @param  array<int, TDeclaringModel>  $models
73     * @param  \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>  $results
74     * @param  string  $relation
75     * @return array
76     */
77    protected function matchOtherRelation(array $models, EloquentCollection $results, $relation)
78    {
79        $model = $models[0] ?? null;
80        if (!$model) {
81            return $models;
82        }
83
84        /**
85         * @var \Illuminate\Database\Eloquent\Relations\Relation
86         */
87        $relationObject = Relation::noConstraints(function () use ($model, $relation) {
88            return $model->$relation();
89        });
90
91        // Prevents an unneeded query in case we try to access the relation on a leaf/root:
92        $relationObject->initRelation($models, $relation);
93
94        // Set relation for all related models and parent model:
95        return $relationObject->match(
96            $models,
97            $results,
98            $relation
99        );
100    }
101}