Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
KeyValueDependencyStore
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 5
210
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
 retrieveMulti
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
20
 storeMulti
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
30
 remove
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getStoreKey
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 */
20
21namespace Wikimedia\DependencyStore;
22
23use BagOStuff;
24use InvalidArgumentException;
25
26/**
27 * Track per-module file dependencies in object cache via BagOStuff.
28 *
29 * @see $wgResourceLoaderUseObjectCacheForDeps
30 * @internal For use by ResourceLoader\Module only
31 * @since 1.35
32 */
33class KeyValueDependencyStore extends DependencyStore {
34    /** @var BagOStuff */
35    private $stash;
36
37    /**
38     * @param BagOStuff $stash Storage backend
39     */
40    public function __construct( BagOStuff $stash ) {
41        $this->stash = $stash;
42    }
43
44    public function retrieveMulti( $type, array $entities ) {
45        $entitiesByKey = [];
46        foreach ( $entities as $entity ) {
47            $entitiesByKey[$this->getStoreKey( $type, $entity )] = $entity;
48        }
49
50        $blobsByKey = $this->stash->getMulti( array_keys( $entitiesByKey ) );
51
52        $results = [];
53        foreach ( $entitiesByKey as $key => $entity ) {
54            $blob = $blobsByKey[$key] ?? null;
55            $data = is_string( $blob ) ? json_decode( $blob, true ) : null;
56            $results[$entity] = $this->newEntityDependencies(
57                $data[self::KEY_PATHS] ?? [],
58                $data[self::KEY_AS_OF] ?? null
59            );
60        }
61
62        return $results;
63    }
64
65    public function storeMulti( $type, array $dataByEntity, $ttl ) {
66        $blobsByKey = [];
67        foreach ( $dataByEntity as $entity => $data ) {
68            if ( !is_array( $data[self::KEY_PATHS] ) || !is_int( $data[self::KEY_AS_OF] ) ) {
69                throw new InvalidArgumentException( "Invalid entry for '$entity'" );
70            }
71
72            // Normalize the list by removing duplicates and sorting
73            $data[self::KEY_PATHS] = array_values( array_unique( $data[self::KEY_PATHS] ) );
74            sort( $data[self::KEY_PATHS], SORT_STRING );
75
76            $blob = json_encode( $data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
77            $blobsByKey[$this->getStoreKey( $type, $entity )] = $blob;
78        }
79
80        if ( $blobsByKey ) {
81            $this->stash->setMulti( $blobsByKey, $ttl, BagOStuff::WRITE_BACKGROUND );
82        }
83    }
84
85    public function remove( $type, $entities ) {
86        $keys = [];
87        foreach ( (array)$entities as $entity ) {
88            $keys[] = $this->getStoreKey( $type, $entity );
89        }
90
91        if ( $keys ) {
92            $this->stash->deleteMulti( $keys, BagOStuff::WRITE_BACKGROUND );
93        }
94    }
95
96    /**
97     * @param string $type
98     * @param string $entity
99     * @return string
100     */
101    private function getStoreKey( $type, $entity ) {
102        return $this->stash->makeKey( "{$type}-dependencies", $entity );
103    }
104}