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