Completed
Push — master ( 335325...39f8a6 )
by Stefano
01:18 queued 01:16
created

ConfigComponent::fetchConfig()   A

Complexity

Conditions 5
Paths 1

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 12
rs 9.6111
cc 5
nc 1
nop 1
1
<?php
2
declare(strict_types=1);
3
/**
4
 * BEdita, API-first content management framework
5
 * Copyright 2022 Atlas Srl, Chialab Srl
6
 *
7
 * This file is part of BEdita: you can redistribute it and/or modify
8
 * it under the terms of the GNU Lesser General Public License as published
9
 * by the Free Software Foundation, either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
13
 */
14
15
namespace App\Controller\Component;
16
17
use App\Utility\CacheTools;
18
use BEdita\SDK\BEditaClientException;
19
use BEdita\WebTools\ApiClientProvider;
20
use Cake\Cache\Cache;
21
use Cake\Collection\Collection;
22
use Cake\Controller\Component;
23
use Cake\Core\Configure;
24
use Cake\Utility\Hash;
25
26
/**
27
 * Config component
28
 */
29
class ConfigComponent extends Component
30
{
31
    /**
32
     * BEdita Api client
33
     *
34
     * @var \BEdita\SDK\BEditaClient
35
     */
36
    protected $apiClient = null;
37
38
    /**
39
     * {@inheritDoc}
40
     * {@codeCoverageIgnore}
41
     */
42
    public function startup(): void
43
    {
44
        // API config may not be set in `login` for a multi-project setup
45
        if (Configure::check('API.apiBaseUrl')) {
46
            $this->apiClient = ApiClientProvider::getApiClient();
47
        }
48
    }
49
50
    /**
51
     * Get a cached configuration key from API.
52
     * Get standard config [from config/app.php etc.] if no configuration from API was found.
53
     *
54
     * @param string $key Configuration key
55
     * @return array
56
     */
57
    public function read(string $key): array
58
    {
59
        try {
60
            $config = Cache::remember(
61
                CacheTools::cacheKey(sprintf('config.%s', $key)),
62
                function () use ($key) {
63
                    return $this->fetchConfig($key);
64
                }
65
            );
66
        } catch (BEditaClientException $e) {
67
            $this->log($e->getMessage(), 'error');
68
            $this->getController()->Flash->error($e->getMessage(), ['params' => $e]);
69
        }
70
71
        if (!empty($config)) {
72
            return (array)json_decode((string)Hash::get($config, 'attributes.content'), true);
73
        }
74
75
        return (array)Configure::read($key);
76
    }
77
78
    /**
79
     * Fetch configuration from API
80
     *
81
     * @param string $key Configuration key
82
     * @return array
83
     */
84
    protected function fetchConfig(string $key): array
85
    {
86
        $response = (array)$this->apiClient->get('/config');
87
        $collection = new Collection((array)Hash::get($response, 'data'));
88
89
        return (array)$collection->reject(function ($item) use ($key) {
90
            $attr = (array)Hash::get((array)$item, 'attributes');
91
92
            return empty($attr['application_id']) ||
93
                empty($attr['context']) || $attr['context'] !== 'app' ||
94
                empty($attr['name']) || $attr['name'] !== $key;
95
        })->first();
96
    }
97
98
    /**
99
     * Get BEdita Manager application ID
100
     *
101
     * @return int
102
     */
103
    public function managerApplicationId(): int
104
    {
105
        $name = (string)Configure::read('ManagerAppName', 'manager');
106
        $filter = compact('name');
107
        $response = (array)$this->apiClient->get('/admin/applications', compact('filter'));
108
109
        return (int)Hash::get($response, 'data.0.id');
110
    }
111
112
    /**
113
     * Save configuration to API
114
     *
115
     * @param string $key Configuration key
116
     * @param array $data Configuration data
117
     * @return void
118
     */
119
    public function save(string $key, array $data): void
120
    {
121
        $config = $this->fetchConfig($key);
122
        $configId = Hash::get($config, 'id');
123
        $managerAppId = Hash::get($config, 'attributes.application_id');
124
        if (empty($managerAppId)) {
125
            $managerAppId = $this->managerApplicationId();
126
        }
127
        $endpoint = '/admin/config';
128
        $body = [
129
            'data' => [
130
                'type' => 'config',
131
                'attributes' => [
132
                    'name' => $key,
133
                    'context' => 'app',
134
                    'content' => json_encode($data),
135
                    'application_id' => $managerAppId,
136
                ],
137
            ],
138
        ];
139
140
        if (empty($configId)) {
141
            $this->apiClient->post($endpoint, json_encode($body));
142
        } else {
143
            $body['data']['id'] = (string)$configId;
144
            $this->apiClient->patch(sprintf('%s/%s', $endpoint, $configId), json_encode($body));
145
        }
146
        Cache::delete(CacheTools::cacheKey(sprintf('config.%s', $key)));
147
    }
148
}
149