Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
Merger
0.00% covered (danger)
0.00%
0 / 40
0.00% covered (danger)
0.00%
0 / 2
342
0.00% covered (danger)
0.00%
0 / 1
 merge
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
56
 mergeMulti
0.00% covered (danger)
0.00%
0 / 23
0.00% covered (danger)
0.00%
0 / 1
132
1<?php
2
3namespace Flow\Data\Utils;
4
5/**
6 * This assists in performing client-side 1-to-1 joins. It collects the foreign key
7 * from a multi-dimensional array, queries a callable for the foreign key values and
8 * then returns the source data with related data merged in.
9 */
10class Merger {
11
12    /**
13     * @param array[] $source input two dimensional array
14     * @param string $fromKey Key in nested arrays of $source containing foreign key
15     * @param callable $callable Callable receiving array of foreign keys returning map
16     *  from foreign key to its value
17     * @param string|null $name Name to merge loaded foreign data as. If null uses $fromKey.
18     * @param string $default Value to use when no matching foreign value can be located
19     * @return array $source array with all found foreign key values merged
20     */
21    public static function merge( array $source, $fromKey, $callable, $name = null, $default = '' ) {
22        $name ??= $fromKey;
23        $ids = [];
24        foreach ( $source as $row ) {
25            $id = $row[$fromKey];
26            if ( $id !== null ) {
27                $ids[] = $id;
28            }
29        }
30        if ( !$ids ) {
31            return $source;
32        }
33        $res = $callable( $ids );
34        if ( $res === false ) {
35            return [];
36        }
37        foreach ( $source as $idx => $row ) {
38            $id = $row[$fromKey];
39            if ( $id === null ) {
40                continue;
41            }
42            $source[$idx][$name] = $res[$id] ?? $default;
43        }
44        return $source;
45    }
46
47    /**
48     * Same as self::merge, but for 3-dimensional source arrays
49     *
50     * @param array $multiSource input three dimensonal array
51     * @param string $fromKey
52     * @param callable $callable Callable receiving array of foreign keys returning map
53     *  from foreign key to its value
54     * @param string|null $name Name to merge loaded foreign data as. If null uses $fromKey.
55     * @param string $default Value to use when no matching foreign value can be located
56     * @return array $multiSource array with all found foreign key values merged
57     */
58    public static function mergeMulti( array $multiSource, $fromKey, $callable, $name = null, $default = '' ) {
59        $name ??= $fromKey;
60        $ids = [];
61        foreach ( $multiSource as $source ) {
62            if ( $source === null ) {
63                continue;
64            }
65            foreach ( $source as $row ) {
66                $id = $row[$fromKey];
67                if ( $id !== null ) {
68                    $ids[] = $id;
69                }
70            }
71        }
72        if ( !$ids ) {
73            return $multiSource;
74        }
75        $res = $callable( array_unique( $ids ) );
76        if ( $res === false ) {
77            return [];
78        }
79        foreach ( $multiSource as $i => $source ) {
80            if ( $source === null ) {
81                continue;
82            }
83            foreach ( $source as $j => $row ) {
84                $id = $row[$fromKey];
85                if ( $id === null ) {
86                    continue;
87                }
88                $multiSource[$i][$j][$name] = $res[$id] ?? $default;
89            }
90        }
91        return $multiSource;
92    }
93}