Completed
Push — master ( a5a9b4...e8fd61 )
by Stefano
15s queued 13s
created

CategoriesComponent::names()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 13
rs 10
cc 2
nc 2
nop 1
1
<?php
2
/**
3
 * BEdita, API-first content management framework
4
 * Copyright 2022 Atlas Srl, Chialab Srl
5
 *
6
 * This file is part of BEdita: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
12
 */
13
namespace App\Controller\Component;
14
15
use App\Utility\CacheTools;
16
use BEdita\WebTools\ApiClientProvider;
17
use Cake\Cache\Cache;
18
use Cake\Controller\Component;
19
use Cake\Utility\Hash;
20
21
/**
22
 * Categories component
23
 */
24
class CategoriesComponent extends Component
25
{
26
    /**
27
     * Fetch categories list.
28
     *
29
     * @param string|null $objectType The object type filter for categories.
30
     * @param array|null $options Query options.
31
     * @return array The BEdita API response for the categories list.
32
     */
33
    public function index(?string $objectType = null, ?array $options = []): array
34
    {
35
        $apiClient = ApiClientProvider::getApiClient();
36
37
        $options = $options + [
38
            'page_size' => 100,
39
        ];
40
        if (!empty($objectType)) {
41
            $options['filter'] = $options['filter'] ?? [];
42
            $options['filter']['type'] = $objectType;
43
        }
44
45
        return $apiClient->get('/model/categories', $options);
46
    }
47
48
    /**
49
     * Fetch categories names
50
     *
51
     * @param string|null $objectType The object type
52
     * @return array
53
     */
54
    public function names(?string $objectType = null): array
55
    {
56
        $apiClient = ApiClientProvider::getApiClient();
57
        $query = [
58
            'fields' => 'name',
59
            'page_size' => 500, // BE4 API MAX_LIMIT
60
        ];
61
        if (!empty($objectType)) {
62
            $query['filter']['type'] = $objectType;
63
        }
64
        $response = $apiClient->get('/model/categories', $query);
65
66
        return (array)Hash::extract($response, 'data.{n}.attributes.name');
67
    }
68
69
    /**
70
     * Create a key/value map of categories from the BEdita categories list response.
71
     *
72
     * @param array $response The BEdita API response for the categories list.
73
     * @return array A map with the category ids as keys and the category attributes as values.
74
     */
75
    public function map(?array $response): array
76
    {
77
        return (array)Hash::combine((array)Hash::get($response, 'data'), '{n}.id', '{n}');
78
    }
79
80
    /**
81
     * Create an id-based categories tree.
82
     *
83
     * @param array $map The categories map returned by the map function.
84
     * @return array The categories tree.
85
     */
86
    public function tree(?array $map): array
87
    {
88
        $tree = [
89
            '_' => [],
90
        ];
91
        foreach ($map as $category) {
92
            if (empty($category['attributes']['parent_id'])) {
93
                $tree['_'][] = $category['id'];
94
            } else {
95
                $tree[$category['attributes']['parent_id']][] = $category['id'];
96
            }
97
        }
98
99
        return $tree;
100
    }
101
102
    /**
103
     * Get an id/label map of available category roots.
104
     *
105
     * @param array $map The categories map returned by the map function.
106
     * @return array The list of available roots.
107
     */
108
    public function getAvailableRoots(?array $map): array
109
    {
110
        $roots = ['' => '-'];
111
        foreach ($map as $category) {
112
            if (empty($category['attributes']['parent_id'])) {
113
                $roots[$category['id']] = empty($category['attributes']['label']) ? $category['attributes']['name'] : $category['attributes']['label'];
114
            }
115
        }
116
117
        return $roots;
118
    }
119
120
    /**
121
     * Save a category using the `/model/` API.
122
     *
123
     * @param array $data Data to save.
124
     * @return array|null The BEdita API response for the saved category.
125
     */
126
    public function save(array $data): ?array
127
    {
128
        $id = Hash::get($data, 'id');
129
        $type = Hash::get($data, 'object_type_name');
130
        unset($data['id']);
131
        $body = [
132
            'data' => [
133
                'type' => 'categories',
134
                'attributes' => $data,
135
            ],
136
        ];
137
138
        $apiClient = ApiClientProvider::getApiClient();
139
        $endpoint = '/model/categories';
140
        $response = null;
141
        if (empty($id)) {
142
            $response = $apiClient->post($endpoint, json_encode($body));
143
        } else {
144
            $body['data']['id'] = $id;
145
146
            $response = $apiClient->patch(sprintf('%s/%s', $endpoint, $id), json_encode($body));
147
        }
148
149
        if (!empty($type)) {
150
            $this->invalidateSchemaCache($type);
151
        }
152
153
        return $response;
154
    }
155
156
    /**
157
     * Delete a category using the `/model/` API.
158
     *
159
     * @param string $id The category id to delete.
160
     * @param string $type The object type name of the category.
161
     * @return array|null The BEdita API response for the deleted category.
162
     */
163
    public function delete(string $id, $type = null): ?array
164
    {
165
        $apiClient = ApiClientProvider::getApiClient();
166
167
        $response = $apiClient->delete(sprintf('/model/%s/%s', 'categories', $id));
168
        if (!empty($type)) {
169
            $this->invalidateSchemaCache($type);
170
        }
171
172
        return $response;
173
    }
174
175
    /**
176
     * Invalidate schema cache for forms.
177
     *
178
     * @param string $type The object type name of the category.
179
     * @return void
180
     */
181
    private function invalidateSchemaCache(string $type): void
182
    {
183
        $key = CacheTools::cacheKey($type);
184
        Cache::delete($key, SchemaComponent::CACHE_CONFIG);
185
    }
186
}
187