Completed
Push — master ( e5fd41...bf061c )
by Askupa
01:42
created

SettingsPage.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Amarkal\Settings;
4
5
/**
6
 * Implements a settings page.
7
 */
8
class SettingsPage
9
{   
10
    /**
11
     * Configuration array 
12
     * 
13
     * @var array 
14
     */
15
    private $config;
16
    
17
    /**
18
     * The UI form instance
19
     * 
20
     * @var Amarkal\UI\Form 
21
     */
22
    private $form;
23
24
    /**
25
     * The list of arguments for each section 
26
     *
27
     * @var array
28
     */
29
    private $sections;
30
31
    /**
32
     * The list of fields for the entire settings page
33
     *
34
     * @var Amarkal\UI\ComponentList
35
     */
36
    private $fields;
37
    
38
    /**
39
     * Set the config, create a form instance and add actions.
40
     * 
41
     * @param array $config
42
     */
43
    public function __construct( array $config = array() ) 
44
    {
45
        $this->config   = array_merge($this->default_args(), $config);
46
        $this->fields   = new \Amarkal\UI\ComponentList();
47
        $this->sections = array();
48
        $this->form     = new \Amarkal\UI\Form($this->fields);
49
        
50
        \add_action('admin_menu', array($this,'add_submenu_page'));
51
        \add_action('admin_enqueue_scripts', array($this,'enqueue_scripts'));
52
    }
53
54
    /**
55
     * Add a section to this settings page
56
     *
57
     * @param array $args
58
     * @return void
59
     */
60
    public function add_section( array $args )
61
    {
62
        $args = \array_merge($this->default_section_args(), $args);
63
        $slug = $args['slug'];
64
        if(array_key_exists($slug, $this->sections))
65
        {
66
            throw new \RuntimeException("A section with '$slug' has already been created for this page.");  
67
        }
68
        $this->sections[$slug] = $args;
69
    }
70
71
    /**
72
     * Add a settings field to this settings page
73
     *
74
     * @param array $args
75
     * @return void
76
     */
77
    public function add_field( array $args )
78
    {
79
        $this->fields->add_component($args);
80
    }
81
82
    /**
83
     * Get the value of the given field from the database, or the default value if none exists
84
     *
85
     * @param string $name
86
     * @return void
87
     */
88
    public function get_field_value( $name )
89
    {
90
        $old_instance = $this->get_old_instance();
91
92
        if(\array_key_exists($name, $old_instance))
93
        {
94
            return $old_instance[$name];
95
        }
96
        
97
        $component = $this->get_component($name);
0 ignored issues
show
Are you sure the assignment to $component is correct as $this->get_component($name) (which targets Amarkal\Settings\SettingsPage::get_component()) seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
98
        return $component->default;
99
    }
100
    
101
    /**
102
     * Internally used to add a submenu page for this settings page
103
     */
104
    public function add_submenu_page()
105
    {
106
        \add_submenu_page(
107
            $this->config['parent_slug'], 
108
            $this->config['title'], 
109
            $this->config['menu_title'], 
110
            $this->config['capability'],
111
            $this->config['slug'],
112
            array($this, 'render')
113
        );
114
    }
115
    
116
    /**
117
     * Conditionally enqueue settings scripts and styles if the calling page is
118
     * a settings page.
119
     */
120
    public function enqueue_scripts()
121
    {
122
        // Only enqueue styles & scripts if this is a settings page
123
        if($this->config['slug'] === filter_input(INPUT_GET, 'page'))
124
        {
125
            \wp_enqueue_style('amarkal-settings');
126
            \wp_enqueue_script('amarkal-settings');
127
        }
128
    }
129
    
130
    /**
131
     * Render the settings page
132
     */
133
    public function render()
134
    {
135
        $this->form->update($this->get_old_instance());
136
        include __DIR__.'/SettingsPage.phtml';
137
        \add_filter('admin_footer_text', array($this, 'footer_credits'));
138
    }
139
    
140
    /**
141
     * Ajax callback internally used to update options values for the given 
142
     * settings page.
143
     * 
144
     * @param array $new_instance
145
     * @return array
146
     */
147 View Code Duplication
    public function update( $new_instance )
148
    {
149
        if($this->can_update())
150
        {
151
            $old_instance = $this->get_old_instance();
152
            $final_instance = $this->form->update($new_instance, $old_instance);
153
            
154
            \update_option($this->config['slug'],$final_instance);
155
156
            return $this->results_array(
157
                $this->get_errors(),
158
                $final_instance
159
            );
160
        }
161
        return $this->results_array(
162
            array("You don't have permission to manage options on this site")
163
        );
164
    }
165
    
166
    /**
167
     * Ajax callback internally used to reset all component values to their 
168
     * defaults for the given settings page.
169
     * 
170
     * @return type
171
     */
172
    public function reset()
173
    {
174
        if($this->can_update())
175
        {
176
            \delete_option($this->config['slug']);
177
178
            return $this->results_array(
179
                array(),
180
                $this->form->reset()
181
            );
182
        }
183
        return $this->results_array(
184
            array("You don't have permission to manage options on this site")
185
        );
186
    }
187
188
    /**
189
     * Ajax callback internally used to reset all component values to their 
190
     * defaults for the given settings section.
191
     *
192
     * @param string $slug
193
     * @return void
194
     */
195 View Code Duplication
    public function reset_section( $slug ) 
196
    {
197
        if($this->can_update())
198
        {
199
            $old_instance = $this->get_old_instance();
200
            $final_instance = $this->form->reset_components($this->get_section_fields($slug));
201
            
202
            \update_option($this->config['slug'], 
203
                // Array merge is needed in order not to delete fields from other sections
204
                // since the $final_instance only contains the fields that were reset
205
                array_merge($old_instance, $final_instance)
206
            );
207
208
            return $this->results_array(
209
                array(),
210
                $final_instance
211
            );
212
        }
213
        return $this->results_array(
214
            array("You don't have permission to manage options on this site")
215
        );
216
    }
217
    
218
    /**
219
     * Renders Amarkal's credits on the page's footer.
220
     */
221
    public function footer_credits()
222
    {
223
        echo '<span id="footer-thankyou">Created with <a href="https://github.com/askupasoftware/amarkal-settings">amarkal-settings</a>, a module within the <a href="https://github.com/askupasoftware/amarkal">Amarkal Framework</a></span>';
224
    }
225
226
    /**
227
     * Get the component corresponding to the given name
228
     *
229
     * @param [string] $name
230
     * @throws RuntimeException when the component cannot be found
231
     * @return void
232
     */
233
    public function get_component($name)
234
    {
235
        return $this->form->get_component_list()->get_by_name($name);
236
    }
237
238
    /**
239
     * Get all the fields for the given section
240
     *
241
     * @param string $slug
242
     * @return array
243
     */
244
    private function get_section_fields($slug)
245
    {
246
        $fields = array();
247
        foreach($this->fields->get_all() as $c)
248
        {
249
            if($c->section === $slug)
250
            {
251
                $fields[] = $c;
252
            }
253
        }
254
        return $fields;
255
    }
256
    
257
    /**
258
     * Get all errors from the form instance.
259
     * 
260
     * @return array
261
     */
262
    private function get_errors()
263
    {
264
        $errors = array();
265
        foreach($this->form->get_errors() as $name => $error)
266
        {
267
            $errors[$name] = $error;
268
        }
269
        return $errors;
270
    }
271
    
272
    /**
273
     * Generates a results array to be returned when an Ajax request is made.
274
     * 
275
     * @param array $errors The list of errors
276
     * @param array $values The list of values
277
     * @return array
278
     */
279
    private function results_array( $errors = array(), $values = '' )
280
    {
281
        return array(
282
            'values' => $values,
283
            'errors' => $errors
284
        );
285
    }
286
    
287
    /**
288
     * Check if the current user has the required privileges to update the 
289
     * settings values.
290
     * 
291
     * @return boolean
292
     */
293
    private function can_update()
294
    {
295
        return \current_user_can($this->config['capability']);
296
    }
297
    
298
    /**
299
     * Get the old instance from the database.
300
     * 
301
     * @return array
302
     */
303
    private function get_old_instance()
304
    {
305
        return \get_option($this->config['slug'], array());
306
    }
307
    
308
    /**
309
     * The default config arguments array for a page.
310
     * 
311
     * @return array
312
     */
313
    private function default_args()
314
    {
315
        return array(
316
            'parent_slug'    => '',
317
            'slug'           => '',
318
            'title'          => '',
319
            'subtitle'       => '',
320
            'menu_title'     => '',
321
            'capability'     => 'manage_options',
322
            'footer_html'    => '',
323
            'subfooter_html' => ''
324
        );
325
    }
326
327
    /**
328
     * The default config arguments array for a section.
329
     *
330
     * @return void
331
     */
332
    private function default_section_args()
333
    {
334
        return array(
335
            'slug'           => '',
336
            'title'          => '',
337
            'subtitle'       => ''
338
        );
339
    }
340
}