|
1
|
|
|
<?php |
|
|
|
|
|
|
2
|
|
|
|
|
3
|
|
|
require_once( 'WL_Metabox_Field.php' ); |
|
4
|
|
|
require_once( 'WL_Metabox_Field_date.php' ); |
|
5
|
|
|
require_once( 'WL_Metabox_Field_uri.php' ); |
|
6
|
|
|
require_once( 'WL_Metabox_Field_coordinates.php' ); |
|
7
|
|
|
require_once( 'WL_Metabox_Field_sameas.php' ); |
|
8
|
|
|
require_once( 'WL_Metabox_Field_address.php' ); |
|
9
|
|
|
|
|
10
|
|
|
/** |
|
11
|
|
|
* Class WL_Metabox |
|
12
|
|
|
* |
|
13
|
|
|
* @since 3.1.0 |
|
14
|
|
|
*/ |
|
15
|
|
|
class WL_Metabox { |
|
16
|
|
|
|
|
17
|
|
|
public $fields; |
|
18
|
|
|
|
|
19
|
|
|
/** |
|
20
|
|
|
* WL_Metabox constructor. |
|
21
|
|
|
* |
|
22
|
|
|
* @since 3.1.0 |
|
23
|
|
|
*/ |
|
24
|
|
|
public function __construct() { |
|
25
|
|
|
|
|
26
|
|
|
// Add hooks to print metaboxes and save submitted data. |
|
27
|
|
|
add_action( 'add_meta_boxes', array( &$this, 'add_main_metabox' ) ); |
|
28
|
|
|
add_action( 'wl_linked_data_save_post', array( |
|
29
|
|
|
&$this, |
|
30
|
|
|
'save_form_data', |
|
31
|
|
|
) ); |
|
32
|
|
|
|
|
33
|
|
|
// Enqueue js and css. |
|
34
|
|
|
$this->enqueue_scripts_and_styles(); |
|
35
|
|
|
|
|
36
|
|
|
} |
|
37
|
|
|
|
|
38
|
|
|
/** |
|
39
|
|
|
* Add a callback to print the metabox in page. |
|
40
|
|
|
* Wordpress will fire the $this->html() callback at the right time. |
|
41
|
|
|
*/ |
|
42
|
|
|
public function add_main_metabox() { |
|
43
|
|
|
|
|
44
|
|
|
// Add main metabox (will print also the inner fields). |
|
45
|
|
|
$id = uniqid( 'wl-metabox-' ); |
|
46
|
|
|
$title = get_the_title() . ' ' . __( 'properties', 'wordlift' ); |
|
47
|
|
|
add_meta_box( $id, $title, array( |
|
48
|
|
|
$this, |
|
49
|
|
|
'html', |
|
50
|
|
|
), Wordlift_Entity_Service::TYPE_NAME, 'normal', 'high' ); |
|
51
|
|
|
|
|
52
|
|
|
// Add filter to change the metabox CSS class. |
|
53
|
|
|
add_filter( "postbox_classes_entity_$id", 'wl_admin_metaboxes_add_css_class' ); |
|
54
|
|
|
} |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* Called from WP to print the metabox content in page. |
|
58
|
|
|
* |
|
59
|
|
|
* @since 3.1.0 |
|
60
|
|
|
* |
|
61
|
|
|
* @param WP_Post $post The post. |
|
62
|
|
|
*/ |
|
63
|
|
|
public function html( $post ) { |
|
64
|
|
|
|
|
65
|
|
|
// Build the fields we need to print. |
|
66
|
|
|
$this->instantiate_fields( $post->ID ); |
|
67
|
|
|
|
|
68
|
|
|
// Loop over the fields. |
|
69
|
|
|
foreach ( $this->fields as $field ) { |
|
70
|
|
|
|
|
71
|
|
|
// load data from DB (values will be available in $field->data). |
|
72
|
|
|
$field->get_data(); |
|
73
|
|
|
|
|
74
|
|
|
// print field HTML (nonce included). |
|
75
|
|
|
echo $field->html(); |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
} |
|
79
|
|
|
|
|
80
|
|
|
/** |
|
81
|
|
|
* Read the WL <-> Schema mapping and build the Fields for the entity being edited. |
|
82
|
|
|
* |
|
83
|
|
|
* Note: the first function that calls this method will instantiate the fields. |
|
84
|
|
|
* Why it isn't called from the constructor? Because we need to hook this process as late as possible. |
|
85
|
|
|
* |
|
86
|
|
|
* @since 3.1.0 |
|
87
|
|
|
* |
|
88
|
|
|
* @param int $post_id The post id. |
|
89
|
|
|
*/ |
|
90
|
|
|
public function instantiate_fields( $post_id ) { |
|
91
|
|
|
|
|
92
|
|
|
// This function must be called only once. Not called from the constructor because WP hooks have a rococo ordering. |
|
93
|
|
|
if ( isset( $this->fields ) ) { |
|
94
|
|
|
return; |
|
95
|
|
|
} |
|
96
|
|
|
|
|
97
|
|
|
$entity_type = wl_entity_taxonomy_get_custom_fields( $post_id ); |
|
98
|
|
|
|
|
99
|
|
|
if ( isset( $entity_type ) ) { |
|
100
|
|
|
|
|
101
|
|
|
/** |
|
102
|
|
|
* In some special case, properties must be grouped in one field (e.g. coordinates) or dealed with custom methods. |
|
103
|
|
|
* We must divide fields in two groups: |
|
104
|
|
|
* - simple: accept values for one property |
|
105
|
|
|
* - grouped: accept values for more properties, or for one property that needs a specific metabox. |
|
106
|
|
|
*/ |
|
107
|
|
|
$metaboxes = $this->group_properties_by_input_field( $entity_type ); |
|
108
|
|
|
$simple_metaboxes = $metaboxes[0]; |
|
109
|
|
|
$grouped_metaboxes = $metaboxes[1]; |
|
110
|
|
|
|
|
111
|
|
|
// Loop over simple entity properties. |
|
112
|
|
|
foreach ( $simple_metaboxes as $key => $property ) { |
|
113
|
|
|
|
|
114
|
|
|
// Info passed to the metabox. |
|
115
|
|
|
$info = array(); |
|
116
|
|
|
$info[ $key ] = $property; |
|
117
|
|
|
|
|
118
|
|
|
// Build the requested field as WL_Metabox_Field_ object. |
|
119
|
|
|
$this->add_field( $info ); |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
// Loop over grouped properties. |
|
123
|
|
|
foreach ( $grouped_metaboxes as $key => $property ) { |
|
124
|
|
|
|
|
125
|
|
|
// Info passed to the metabox. |
|
126
|
|
|
$info = array(); |
|
127
|
|
|
$info[ $key ] = $property; |
|
128
|
|
|
|
|
129
|
|
|
// Build the requested field group as WL_Metabox_Field_ object. |
|
130
|
|
|
$this->add_field( $info, true ); |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
} |
|
134
|
|
|
} |
|
135
|
|
|
|
|
136
|
|
|
/** |
|
137
|
|
|
* Separes metaboxes in simple and grouped. |
|
138
|
|
|
* |
|
139
|
|
|
* @param array $custom_fields Information on the entity type. |
|
140
|
|
|
*/ |
|
141
|
|
|
public function group_properties_by_input_field( $custom_fields ) { |
|
142
|
|
|
|
|
143
|
|
|
$simple_properties = array(); |
|
144
|
|
|
$grouped_properties = array(); |
|
145
|
|
|
|
|
146
|
|
|
// Loop over possible entity properties. |
|
147
|
|
|
foreach ( $custom_fields as $key => $property ) { |
|
148
|
|
|
|
|
149
|
|
|
// Check presence of predicate and type. |
|
150
|
|
|
if ( isset( $property['predicate'] ) && isset( $property['type'] ) ) { |
|
151
|
|
|
|
|
152
|
|
|
// Check if input_field is defined. |
|
153
|
|
|
if ( isset( $property['input_field'] ) && $property['input_field'] !== '' ) { |
|
154
|
|
|
|
|
155
|
|
|
$grouped_key = $property['input_field']; |
|
156
|
|
|
|
|
157
|
|
|
// Update list of grouped properties. |
|
158
|
|
|
$grouped_properties[ $grouped_key ][ $key ] = $property; |
|
159
|
|
|
|
|
160
|
|
|
} else { |
|
161
|
|
|
|
|
162
|
|
|
// input_field not defined, add simple metabox. |
|
163
|
|
|
$simple_properties[ $key ] = $property; |
|
164
|
|
|
} |
|
165
|
|
|
} |
|
166
|
|
|
} |
|
167
|
|
|
|
|
168
|
|
|
return array( $simple_properties, $grouped_properties ); |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
/** |
|
172
|
|
|
* Add a Field to the current Metabox, based on the description of the Field. |
|
173
|
|
|
* This method is a rude factory for Field objects. |
|
174
|
|
|
* |
|
175
|
|
|
* @param array $args |
|
176
|
|
|
* @param bool $grouped Flag to distinguish between simple and grouped Fields |
|
177
|
|
|
*/ |
|
178
|
|
|
public function add_field( $args, $grouped = false ) { |
|
179
|
|
|
|
|
180
|
|
|
if ( $grouped ) { |
|
181
|
|
|
// Special fields (sameas, coordinates, etc.). |
|
182
|
|
|
|
|
183
|
|
|
// Build Field with a custom class (e.g. WL_Metabox_Field_date). |
|
184
|
|
|
$field_class = 'WL_Metabox_Field_' . key( $args ); |
|
185
|
|
|
|
|
186
|
|
|
} else { |
|
187
|
|
|
// Simple fields (string, uri, boolean, etc.). |
|
188
|
|
|
|
|
189
|
|
|
// Which field? We want to use the class that is specific for the field. |
|
190
|
|
|
$meta = key( $args ); |
|
191
|
|
|
$this_meta = $args[ $meta ]; |
|
192
|
|
|
|
|
193
|
|
|
// If the field declares what metabox it wants, use that one. |
|
194
|
|
|
if ( isset( $this_meta['metabox']['class'] ) ) { |
|
195
|
|
|
|
|
196
|
|
|
$field_class = $this_meta['metabox']['class']; |
|
197
|
|
|
|
|
198
|
|
|
} elseif ( ! isset( $this_meta['type'] ) || ( $this_meta['type'] == Wordlift_Schema_Service::DATA_TYPE_STRING ) ) { |
|
199
|
|
|
|
|
200
|
|
|
// TODO: all fields should explicitly declare the required WL_Metabox. |
|
201
|
|
|
// When they will remove this. |
|
202
|
|
|
|
|
203
|
|
|
// Use default WL_Metabox_Field (manages strings). |
|
204
|
|
|
$field_class = 'WL_Metabox_Field'; |
|
205
|
|
|
|
|
206
|
|
|
} else { |
|
207
|
|
|
|
|
208
|
|
|
// TODO: all fields should explicitly declare the required WL_Metabox. |
|
209
|
|
|
// When they will remove this. |
|
210
|
|
|
|
|
211
|
|
|
// Build Field with a custom class (e.g. WL_Metabox_Field_date). |
|
212
|
|
|
$field_class = 'WL_Metabox_Field_' . $this_meta['type']; |
|
213
|
|
|
|
|
214
|
|
|
} |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
// Call apropriate constructor (e.g. WL_Metabox_Field_... ). |
|
218
|
|
|
$this->fields[] = new $field_class( $args ); |
|
219
|
|
|
} |
|
220
|
|
|
|
|
221
|
|
|
public function save_form_data( $entity_id ) { |
|
|
|
|
|
|
222
|
|
|
|
|
223
|
|
|
// Build Field objects. |
|
224
|
|
|
$this->instantiate_fields( $entity_id ); |
|
225
|
|
|
|
|
226
|
|
|
// Check if WL metabox form was posted. |
|
227
|
|
|
if ( ! isset( $_POST['wl_metaboxes'] ) ) { |
|
228
|
|
|
return; |
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
foreach ( $this->fields as $field ) { |
|
232
|
|
|
|
|
233
|
|
|
// Verify nonce. |
|
234
|
|
|
$valid_nonce = $field->verify_nonce(); |
|
235
|
|
|
if ( $valid_nonce ) { |
|
236
|
|
|
|
|
237
|
|
|
$posted_data = $_POST['wl_metaboxes']; |
|
238
|
|
|
$field_name = $field->meta_name; |
|
239
|
|
|
|
|
240
|
|
|
// Each Filed only deals with its values. |
|
241
|
|
|
if ( isset( $posted_data[ $field_name ] ) ) { |
|
242
|
|
|
|
|
243
|
|
|
$values = $posted_data[ $field_name ]; |
|
244
|
|
|
if ( ! is_array( $values ) ) { |
|
245
|
|
|
$values = array( $values ); |
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
|
// Save data permanently |
|
249
|
|
|
$field->save_data( $values ); |
|
250
|
|
|
} |
|
251
|
|
|
} |
|
252
|
|
|
} |
|
253
|
|
|
|
|
254
|
|
|
wl_linked_data_push_to_redlink( $entity_id ); |
|
255
|
|
|
} |
|
256
|
|
|
|
|
257
|
|
|
/** |
|
258
|
|
|
* Enqueue scripts and styles. |
|
259
|
|
|
* |
|
260
|
|
|
* @since 3.0.0 |
|
261
|
|
|
*/ |
|
262
|
|
|
public function enqueue_scripts_and_styles() { |
|
263
|
|
|
|
|
264
|
|
|
// Load the jquery-ui-timepicker-addon library. |
|
265
|
|
|
wp_enqueue_style( 'jquery-ui-timepicker-addon', dirname( plugin_dir_url( __FILE__ ) ) . '/js/jquery-ui-timepicker-addon/jquery-ui-timepicker-addon.min.css' ); |
|
266
|
|
|
wp_enqueue_script( 'jquery-ui-timepicker-addon', dirname( plugin_dir_url( __FILE__ ) ) . '/js/jquery-ui-timepicker-addon/jquery-ui-timepicker-addon.min.js', array( 'jquery-ui-datepicker' ), '1.6.3', true ); |
|
267
|
|
|
|
|
268
|
|
|
wp_enqueue_script( 'jquery-ui-timepicker-no-conflict', dirname( plugin_dir_url( __FILE__ ) ) . '/js/jquery.datetimepicker.no-conflict.js', array( |
|
269
|
|
|
'jquery-ui-datepicker', |
|
270
|
|
|
'jquery-ui-timepicker-addon', |
|
271
|
|
|
) ); |
|
272
|
|
|
|
|
273
|
|
|
// Leaflet. |
|
274
|
|
|
wp_enqueue_style( 'leaflet', dirname( dirname( plugin_dir_url( __FILE__ ) ) ) . '/bower_components/leaflet/dist/leaflet.css' ); |
|
275
|
|
|
wp_enqueue_script( 'leaflet', dirname( dirname( plugin_dir_url( __FILE__ ) ) ) . '/bower_components/leaflet/dist/leaflet.js', __FILE__ ); |
|
276
|
|
|
|
|
277
|
|
|
// Add AJAX autocomplete to facilitate metabox editing. |
|
278
|
|
|
wp_enqueue_script( 'wl-entity-metabox-utility', dirname( plugin_dir_url( __FILE__ ) ) . '/js/wl_entity_metabox_utilities.js' ); |
|
279
|
|
|
wp_localize_script( 'wl-entity-metabox-utility', 'wlEntityMetaboxParams', array( |
|
280
|
|
|
'ajax_url' => admin_url( 'admin-ajax.php' ), |
|
281
|
|
|
'action' => 'entity_by_title', |
|
282
|
|
|
) |
|
283
|
|
|
); |
|
284
|
|
|
|
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
} |
|
288
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.