Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
MultiGetList
0.00% covered (danger)
0.00%
0 / 41
0.00% covered (danger)
0.00%
0 / 3
240
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 get
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
 getByKey
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
90
1<?php
2
3namespace Flow\Repository;
4
5use Flow\Data\FlowObjectCache;
6use Flow\Exception\InvalidParameterException;
7use Flow\Model\UUID;
8
9class MultiGetList {
10
11    /**
12     * @var FlowObjectCache
13     */
14    protected $cache;
15
16    /**
17     * @param FlowObjectCache $cache
18     */
19    public function __construct( FlowObjectCache $cache ) {
20        $this->cache = $cache;
21    }
22
23    /**
24     * @param string $treeType
25     * @param array $ids
26     * @param callable $loadCallback
27     * @return array
28     * @throws InvalidParameterException
29     */
30    public function get( $treeType, array $ids, $loadCallback ) {
31        $cacheKeys = [];
32        foreach ( $ids as $id ) {
33            if ( $id instanceof UUID ) {
34                $cacheId = $id;
35            } elseif ( is_scalar( $id ) ) {
36                $cacheId = UUID::create( $id );
37            } else {
38                $type = is_object( $id ) ? get_class( $id ) : gettype( $id );
39                throw new InvalidParameterException( "Not scalar: $type" );
40            }
41            // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
42            $cacheKeys[ TreeCacheKey::build( $treeType, $cacheId ) ] = $id;
43        }
44        return $this->getByKey( $cacheKeys, $loadCallback );
45    }
46
47    /**
48     * @param array $cacheKeys
49     * @param callable $loadCallback
50     * @return array
51     */
52    public function getByKey( array $cacheKeys, $loadCallback ) {
53        if ( !$cacheKeys ) {
54            return [];
55        }
56        $result = [];
57        $multiRes = $this->cache->getMulti( array_keys( $cacheKeys ) );
58        // Memcached BagOStuff only returns found keys, but the redis bag
59        // returns false for not found keys.
60        $multiRes = array_filter(
61            $multiRes,
62            static function ( $val ) {
63                return $val !== false;
64            }
65        );
66        foreach ( $multiRes as $key => $value ) {
67            $idx = $cacheKeys[$key];
68            if ( $idx instanceof UUID ) {
69                $idx = $idx->getAlphadecimal();
70            }
71            $result[$idx] = $value;
72            unset( $cacheKeys[$key] );
73        }
74
75        if ( count( $cacheKeys ) === 0 ) {
76            return $result;
77        }
78        $res = $loadCallback( array_values( $cacheKeys ) );
79        if ( !$res ) {
80            // storage failure of some sort
81            return $result;
82        }
83        $invCacheKeys = [];
84        foreach ( $cacheKeys as $cacheKey => $id ) {
85            if ( $id instanceof UUID ) {
86                $id = $id->getAlphadecimal();
87            }
88            $invCacheKeys[$id] = $cacheKey;
89        }
90        foreach ( $res as $id => $row ) {
91            $this->cache->set( $invCacheKeys[$id], $row );
92            $result[$id] = $row;
93        }
94
95        return $result;
96    }
97}