Related   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 25
dl 0
loc 96
rs 10
c 0
b 0
f 0
wmc 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A relation() 0 9 1
A relations() 0 10 1
B rsRender() 0 47 8
1
<?php
2
/**
3
 * Related data merging
4
 * User: moyo
5
 * Date: 26/12/2017
6
 * Time: 10:33 AM
7
 */
8
9
namespace Carno\Database\SQL\Merging;
10
11
use Carno\Database\SQL\Builder;
12
use Carno\Database\SQL\Exception\RelatedMergingFailedException;
13
use Closure;
14
15
trait Related
16
{
17
    /**
18
     * similar with "relations" but merge single-data in source
19
     * @param string $table
20
     * @param string $bindKey
21
     * @param string $srcKey
22
     * @param Closure $userExe
23
     * @return Builder
24
     */
25
    public function relation(
26
        string $table,
27
        string $bindKey,
28
        string $srcKey = 'id',
29
        Closure $userExe = null
30
    ) : Builder {
31
        $this->rsRender($table, $bindKey, $srcKey, null, $userExe);
32
33
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Carno\Database\SQL\Merging\Related which includes types incompatible with the type-hinted return Carno\Database\SQL\Builder.
Loading history...
34
    }
35
36
    /**
37
     * similar with "relation" but attach listed-data in source
38
     * @param string $table
39
     * @param string $bindKey
40
     * @param string $listKey
41
     * @param string $srcKey
42
     * @param Closure $userExe
43
     * @return Builder
44
     */
45
    public function relations(
46
        string $table,
47
        string $bindKey,
48
        string $listKey,
49
        string $srcKey = 'id',
50
        Closure $userExe = null
51
    ) : Builder {
52
        $this->rsRender($table, $bindKey, $srcKey, $listKey, $userExe);
53
54
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type Carno\Database\SQL\Merging\Related which includes types incompatible with the type-hinted return Carno\Database\SQL\Builder.
Loading history...
55
    }
56
57
    /**
58
     * @param string $table
59
     * @param string $bindKey
60
     * @param string $srcKey
61
     * @param string $listedAs
62
     * @param Closure $userExe
63
     */
64
    private function rsRender(
65
        string $table,
66
        string $bindKey,
67
        string $srcKey,
68
        string $listedAs = null,
69
        Closure $userExe = null
70
    ) : void {
71
        $this->rsWatching(function (array $rows) use ($table, $bindKey, $srcKey, $listedAs, $userExe) {
0 ignored issues
show
Bug introduced by
It seems like rsWatching() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

71
        $this->/** @scrutinizer ignore-call */ 
72
               rsWatching(function (array $rows) use ($table, $bindKey, $srcKey, $listedAs, $userExe) {
Loading history...
72
73
            $srcIds = [];
74
75
            array_walk($rows, function (array $row) use ($srcKey, &$srcIds) {
76
                if (isset($row[$srcKey])) {
77
                    $srcIds[] = $row[$srcKey];
78
                }
79
            });
80
81
            if (empty($srcIds)) {
82
                throw new RelatedMergingFailedException('Empty source identifies');
83
            }
84
85
            /**
86
             * @var Builder $builder
87
             */
88
            $builder = $this->new($table);
0 ignored issues
show
Bug introduced by
It seems like new() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

88
            /** @scrutinizer ignore-call */ 
89
            $builder = $this->new($table);
Loading history...
89
90
            if ($userExe) {
91
                $userExe($builder);
92
            }
93
94
            $related = yield $builder->where($bindKey, 'in', $srcIds)->list();
95
96
            $stack = [];
97
            foreach ($related as $row) {
98
                $stack[$row[$bindKey]][] = $row;
99
            }
100
101
            // merge single-data or attach listed-data
102
            foreach ($rows as $i => $row) {
103
                if ($listedAs) {
104
                    $rows[$i][$listedAs] = $stack[$row[$srcKey]] ?? [];
105
                } else {
106
                    $rows[$i] = array_merge(current($stack[$row[$srcKey]] ?? []) ?: [], $row);
107
                }
108
            }
109
110
            return $rows;
111
        });
112
    }
113
}
114