Passed
Pull Request — master (#45)
by Stefano
02:34
created

ApiCacheComponent::readIndex()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 2
eloc 3
c 1
b 1
f 0
nc 2
nop 0
dl 0
loc 6
rs 10
1
<?php
2
declare(strict_types=1);
3
4
/**
5
 * BEdita, API-first content management framework
6
 * Copyright 2021 Atlas Srl, ChannelWeb Srl, Chialab Srl
7
 *
8
 * This file is part of BEdita: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published
10
 * by the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
14
 */
15
16
namespace BEdita\WebTools\Controller\Component;
17
18
use BEdita\WebTools\ApiClientProvider;
19
use Cake\Cache\Cache;
20
use Cake\Controller\Component;
21
22
/**
23
 * Component to cache some GET API calls.
24
 *
25
 * An index is used in order to refresh this cache with an external script.
26
 */
27
class ApiCacheComponent extends Component
28
{
29
    /**
30
     * Default config for this component.
31
     *
32
     * @var array
33
     */
34
    protected $_defaultConfig = [
35
        'cache' => '_apicache_',
36
    ];
37
38
    /**
39
     * Cache index
40
     *
41
     * @var array
42
     */
43
    protected $cacheIndex = [];
44
45
    /**
46
     * Use 'default' as fallback if no cache configuration is found.
47
     *
48
     * @param array $config The configuration settings provided to this helper.
49
     * @return void
50
     */
51
    public function initialize(array $config): void
52
    {
53
        if (Cache::getConfig($this->getConfig('cache')) === null) {
54
            $this->setConfig('cache', 'default');
55
        }
56
    }
57
58
    /**
59
     * Cache key using type and query string
60
     *
61
     * @param string $path API path
62
     * @param array|null $query Optional query string
63
     * @return string
64
     */
65
    protected function cacheKey(string $path, ?array $query = null): string
66
    {
67
        $hash = md5(json_encode($query));
68
        $path = str_replace('/', '_', $path);
69
70
        return sprintf('%s_%s', $path, $hash);
71
    }
72
73
    /**
74
     * Update cache index
75
     *
76
     * @param string $key Cache Key
77
     * @param array $params Cache params
78
     * @return void
79
     */
80
    protected function updateCacheIndex(string $key, array $params): void
81
    {
82
        if (!empty($this->cacheIndex[$key])) {
83
            return;
84
        }
85
        $this->cacheIndex[$key] = $params;
86
        Cache::write('index', $this->cacheIndex, $this->getConfig('cache'));
87
    }
88
89
    /**
90
     * Read current cache index
91
     *
92
     * @return void
93
     */
94
    protected function readIndex(): void
95
    {
96
        if (!empty($this->cacheIndex)) {
97
            return;
98
        }
99
        $this->cacheIndex = array_filter((array)Cache::read('index', $this->getConfig('cache')));
100
    }
101
102
    /**
103
     * Cached GET API call
104
     *
105
     * @param string $path Path invoked
106
     * @param array|null $query Optional query string
107
     * @return array
108
     */
109
    public function get(string $path, ?array $query = null): array
110
    {
111
        $this->readIndex();
112
        $key = $this->cacheKey($path, $query);
113
114
        $response = (array)Cache::remember(
115
            $key,
116
            function () use ($key, $path, $query) {
117
                return (array)ApiClientProvider::getApiClient()->get($path, $query);
118
            },
119
            $this->getConfig('cache')
120
        );
121
        $this->updateCacheIndex($key, compact('path', 'query'));
122
123
        return $response;
124
    }
125
}
126