ToggleCheckbox.php
3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<?php
namespace YahnisElsts\AdminMenuEditor\Customizable\Controls;
use YahnisElsts\AdminMenuEditor\Customizable\HtmlHelper;
use YahnisElsts\AdminMenuEditor\Customizable\Rendering\Renderer;
/**
* A special "checkbox" that sends one value when it's checked and another value
* when it's unchecked.
*
* Usually, the browser only sends the checkbox value when the checkbox is
* checked. This class uses a hidden input and some JS to send a different
* value when the checkbox is unchecked.
*
* It can also work without JS, but only if the server handles multiple fields
* with the same name by taking the value of the last field and discarding
* the rest (which PHP does).
*/
class ToggleCheckbox extends ClassicControl {
protected $type = 'binCheckbox';
protected $koComponentName = 'ame-toggle-checkbox';
protected $onValue = '1';
protected $offValue = '0';
public function __construct($settings = [], $params = []) {
$this->hasPrimaryInput = true;
parent::__construct($settings, $params);
if ( array_key_exists('onValue', $params) ) {
$this->onValue = $params['onValue'];
}
if ( array_key_exists('offValue', $params) ) {
$this->offValue = $params['offValue'];
}
}
public function renderContent(Renderer $renderer) {
$isChecked = ($this->getMainSettingValue() === $this->onValue);
//Encode non-scalar values as JSON. To simplify things for the script that
//receives this data, we'll either encode both values or none of them.
$useJson = !is_scalar($this->onValue) || !is_scalar($this->offValue);
if ( $useJson ) {
$onString = wp_json_encode($this->onValue);
$offString = wp_json_encode($this->offValue);
} else {
$onString = self::boxValueToString($this->onValue);
$offString = self::boxValueToString($this->offValue);
}
echo HtmlHelper::tag(
'input',
[
'type' => 'hidden',
'name' => $this->getFieldName(),
'value' => $offString,
'class' => 'ame-toggle-checkbox-alternative',
]
);
echo HtmlHelper::tag(
'label',
['class' => array_merge(['ame-toggle-checkbox-control'], $this->classes)]
);
$jsonOnValue = wp_json_encode($this->onValue);
$jsonOffValue = wp_json_encode($this->offValue);
//phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped -- Method is safe, and label is allowed to have HTML.
echo $this->buildInputElement(
[
'type' => 'checkbox',
'name' => $this->getFieldName(),
'value' => $onString,
'checked' => $isChecked,
'data-ame-on-value' => $jsonOnValue,
'data-ame-off-value' => $jsonOffValue,
'data-bind' => 'ameToggleCheckbox: {
checked: ' . $this->getKoObservableExpression($isChecked ? $this->onValue : $this->offValue)
. ', onValue: ' . $jsonOnValue
. ', offValue: ' . $jsonOffValue . ' }',
]
);
echo ' ', $this->label;
//phpcs:enable
$this->outputNestedDescription();
echo '</label>';
self::enqueueDependencies();
}
/**
* Convert one of the checkbox values to a string that can be used in a "value" attribute.
*
* @param scalar $stateValue
* @return string
*/
protected static function boxValueToString($stateValue) {
if ( is_bool($stateValue) ) {
return $stateValue ? '1' : '0';
} else {
return (string)$stateValue;
}
}
public function includesOwnLabel() {
return true;
}
protected function getKoComponentParams() {
return array_merge(
parent::getKoComponentParams(),
[
'onValue' => $this->onValue,
'offValue' => $this->offValue,
]
);
}
}