Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
88.46% covered (warning)
88.46%
46 / 52
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
SettingsController
88.46% covered (warning)
88.46%
46 / 52
50.00% covered (danger)
50.00%
1 / 2
11.19
0.00% covered (danger)
0.00%
0 / 1
 index
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
2
 saveSettings
80.65% covered (warning)
80.65%
25 / 31
0.00% covered (danger)
0.00%
0 / 1
9.59
1<?php
2declare(strict_types=1);
3
4namespace App\Controller\Admin;
5
6use App\Controller\AppController;
7use App\Utility\SettingsManager;
8use Cake\Http\Response;
9
10/**
11 * Settings Controller
12 *
13 * This controller handles the management of application settings.
14 * It provides functionality to view and save settings, which are organized
15 * by category and key name.
16 *
17 * @property \App\Model\Table\SettingsTable $Settings The settings table instance.
18 */
19class SettingsController extends AppController
20{
21    /**
22     * Index method
23     *
24     * Retrieves all settings from the database, orders them by category
25     * and key name, and groups them into an array structure.
26     * The grouped settings are then passed to the view for rendering.
27     *
28     * @return \Cake\Http\Response|null Returns null, allowing the view to be rendered
29     */
30    public function index(): ?Response
31    {
32        $articlesTable = $this->fetchTable('Articles');
33        $sitePages = $articlesTable->find('treeList')
34            ->where(['kind' => 'page'])
35            ->toArray();
36
37        $noneItem = ['None' => 'None'];
38        $sitePages = $noneItem + $sitePages;
39
40        $settings = $this->Settings->find('all')
41            ->orderBy(['category' => 'ASC', 'ordering' => 'ASC'])
42            ->toArray();
43
44        $groupedSettings = [];
45        foreach ($settings as $setting) {
46            $groupedSettings[$setting->category][$setting->key_name] = [
47                'value' => $setting->value,
48                'value_type' => $setting->value_type,
49                'value_obscure' => $setting->value_obscure,
50                'data' => $setting->data,
51                'description' => $setting->description,
52                'column_width' => $setting->column_width,
53            ];
54        }
55
56        $this->set(compact('groupedSettings', 'sitePages'));
57
58        return null;
59    }
60
61    /**
62     * Save Settings method
63     *
64     * Processes the incoming request to update settings. It iterates over
65     * the submitted data, finds the corresponding setting in the database, and updates
66     * its value. If all updates are successful, a success message is displayed and the
67     * cache is cleared. Otherwise, an error message is shown with details of the failed updates.
68     *
69     * @return \Cake\Http\Response|null Redirects to the index action after processing
70     */
71    public function saveSettings(): ?Response
72    {
73        if ($this->request->is(['patch', 'post', 'put'])) {
74            $data = $this->request->getData();
75            $success = true;
76            $errorMessages = [];
77
78            foreach ($data as $category => $settings) {
79                foreach ($settings as $key => $value) {
80                    $setting = $this->Settings->find()
81                        ->where([
82                            'category' => $category,
83                            'key_name' => $key,
84                        ])
85                        ->first();
86
87                    if ($setting) {
88                        $setting = $this->Settings->patchEntity($setting, ['value' => $value]);
89                    } else {
90                        $errorMessages[] = __('Setting not found: {0}.{1}', $category, $key);
91                        $success = false;
92                        continue;
93                    }
94
95                    if (!$this->Settings->save($setting)) {
96                        $success = false;
97                        $errors = $setting->getErrors();
98                        foreach ($errors as $fieldErrors) {
99                            foreach ($fieldErrors as $error) {
100                                $errorMessages[] = __('Error saving {0}.{1}: {2}', $category, $key, $error);
101                            }
102                        }
103                    }
104                }
105            }
106
107            if ($success) {
108                $this->Flash->success(__('The settings have been saved.'));
109                // Clear the cache if saved successfully
110                SettingsManager::clearCache();
111            } else {
112                $this->Flash->error(__('Some settings could not be saved. Please, try again.'), [
113                    'params' => ['errors' => $errorMessages],
114                ]);
115            }
116
117            return $this->redirect(['action' => 'index']);
118        }
119
120        return null;
121    }
122}