-
Notifications
You must be signed in to change notification settings - Fork 73
/
jw_custom_posts.php
333 lines (271 loc) · 12.8 KB
/
jw_custom_posts.php
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
<?php
session_start();
/**
* JW Post Types
* @author Jeffrey Way
* @link http://jeffrey-way.com
*/
class JW_Post_Type
{
/**
* The name of the post type.
* @var string
*/
public $post_type_name;
/**
* A list of user-specific options for the post type.
* @var array
*/
public $post_type_args;
/**
* Sets default values, registers the passed post type, and
* listens for when the post is saved.
*
* @param string $name The name of the desired post type.
* @param array @post_type_args Override the options.
*/
function __construct($name, $post_type_args = array())
{
if (!isset($_SESSION["taxonomy_data"])) {
$_SESSION['taxonomy_data'] = array();
}
$this->post_type_name = strtolower($name);
$this->post_type_args = (array)$post_type_args;
// First step, register that new post type
$this->init(array(&$this, "register_post_type"));
$this->save_post();
}
/**
* Helper method, that attaches a passed function to the 'init' WP action
* @param function $cb Passed callback function.
*/
function init($cb)
{
add_action("init", $cb);
}
/**
* Helper method, that attaches a passed function to the 'admin_init' WP action
* @param function $cb Passed callback function.
*/
function admin_init($cb)
{
add_action("admin_init", $cb);
}
/**
* Registers a new post type in the WP db.
*/
function register_post_type()
{
$n = ucwords($this->post_type_name);
$args = array(
"label" => $n . 's',
'singular_name' => $n,
"public" => true,
"publicly_queryable" => true,
"query_var" => true,
#"menu_icon" => get_stylesheet_directory_uri() . "/article16.png",
"rewrite" => true,
"capability_type" => "post",
"hierarchical" => false,
"menu_position" => null,
"supports" => array("title", "editor", "thumbnail"),
'has_archive' => true
);
// Take user provided options, and override the defaults.
$args = array_merge($args, $this->post_type_args);
register_post_type($this->post_type_name, $args);
}
/**
* Registers a new taxonomy, associated with the instantiated post type.
*
* @param string $taxonomy_name The name of the desired taxonomy
* @param string $plural The plural form of the taxonomy name. (Optional)
* @param array $options A list of overrides
*/
function add_taxonomy($taxonomy_name, $plural = '', $options = array())
{
// Create local reference so we can pass it to the init cb.
$post_type_name = $this->post_type_name;
// If no plural form of the taxonomy was provided, do a crappy fix. :)
if (empty($plural)) {
$plural = $taxonomy_name . 's';
}
// Taxonomies need to be lowercase, but displaying them will look better this way...
$taxonomy_name = ucwords($taxonomy_name);
// At WordPress' init, register the taxonomy
$this->init(
function() use($taxonomy_name, $plural, $post_type_name, $options)
{
// Override defaults with user provided options
$options = array_merge(
array(
"hierarchical" => false,
"label" => $taxonomy_name,
"singular_label" => $plural,
"show_ui" => true,
"query_var" => true,
"rewrite" => array("slug" => strtolower($taxonomy_name))
),
$options
);
// name of taxonomy, associated post type, options
register_taxonomy(strtolower($taxonomy_name), $post_type_name, $options);
});
}
/**
* Creates a new custom meta box in the New 'post_type' page.
*
* @param string $title
* @param array $form_fields Associated array that contains the label of the input, and the desired input type. 'Title' => 'text'
*/
function add_meta_box($title, $form_fields = array())
{
$post_type_name = $this->post_type_name;
// end update_edit_form
add_action('post_edit_form_tag', function()
{
echo ' enctype="multipart/form-data"';
});
// At WordPress' admin_init action, add any applicable metaboxes.
$this->admin_init(function() use($title, $form_fields, $post_type_name)
{
add_meta_box(
strtolower(str_replace(' ', '_', $title)), // id
$title, // title
function($post, $data)
{ // function that displays the form fields
global $post;
wp_nonce_field(plugin_basename(__FILE__), 'jw_nonce');
// List of all the specified form fields
$inputs = $data['args'][0];
// Get the saved field values
$meta = get_post_custom($post->ID);
// For each form field specified, we need to create the necessary markup
// $name = Label, $type = the type of input to create
foreach ($inputs as $name => $type) {
#'Happiness Info' in 'Snippet Info' box becomes
# snippet_info_happiness_level
$id_name = $data['id'] . '_' . strtolower(str_replace(' ', '_', $name));
if (is_array($inputs[$name])) {
// then it must be a select or file upload
// $inputs[$name][0] = type of input
if (strtolower($inputs[$name][0]) === 'select') {
// filter through them, and create options
$select = "<select name='$id_name' class='widefat'>";
foreach ($inputs[$name][1] as $option) {
// if what's stored in the db is equal to the
// current value in the foreach, that should
// be the selected one
if (isset($meta[$id_name]) && $meta[$id_name][0] == $option) {
$set_selected = "selected='selected'";
} else $set_selected = '';
$select .= "<option value='$option' $set_selected> $option </option>";
}
$select .= "</select>";
array_push($_SESSION['taxonomy_data'], $id_name);
}
}
// Attempt to set the value of the input, based on what's saved in the db.
$value = isset($meta[$id_name][0]) ? $meta[$id_name][0] : '';
$checked = ($type == 'checkbox' && !empty($value) ? 'checked' : '');
// Sorta sloppy. I need a way to access all these form fields later on.
// I had trouble finding an easy way to pass these values around, so I'm
// storing it in a session. Fix eventually.
array_push($_SESSION['taxonomy_data'], $id_name);
// TODO - Add the other input types.
$lookup = array(
"text" => "<input type='text' name='$id_name' value='$value' class='widefat' />",
"textarea" => "<textarea name='$id_name' class='widefat' rows='10'>$value</textarea>",
"checkbox" => "<input type='checkbox' name='$id_name' value='$name' $checked />",
"select" => isset($select) ? $select : '',
"file" => "<input type='file' name='$id_name' id='$id_name' />"
);
?>
<p>
<label><?php echo ucwords($name) . ':'; ?></label>
<?php echo $lookup[is_array($type) ? $type[0] : $type]; ?>
</p>
<p>
<?php
// If a file was uploaded, display it below the input.
$file = get_post_meta($post->ID, $id_name, true);
if ( $type === 'file' ) {
// display the image
$file = get_post_meta($post->ID, $id_name, true);
$file_type = wp_check_filetype($file);
$image_types = array('jpeg', 'jpg', 'bmp', 'gif', 'png');
if ( isset($file) ) {
if ( in_array($file_type['ext'], $image_types) ) {
echo "<img src='$file' alt='' style='max-width: 400px;' />";
} else {
echo "<a href='$file'>$file</a>";
}
}
}
?>
</p>
<?php
}
},
$post_type_name, // associated post type
'normal', // location/context. normal, side, etc.
'default', // priority level
array($form_fields) // optional passed arguments.
); // end add_meta_box
});
}
/**
* When a post saved/updated in the database, this methods updates the meta box params in the db as well.
*/
function save_post()
{
add_action('save_post', function()
{
// Only do the following if we physically submit the form,
// and now when autosave occurs.
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
global $post;
if ($_POST && !wp_verify_nonce($_POST['jw_nonce'], plugin_basename(__FILE__))) {
return;
}
// Get all the form fields that were saved in the session,
// and update their values in the db.
if (isset($_SESSION['taxonomy_data'])) {
foreach ($_SESSION['taxonomy_data'] as $form_name) {
if (!empty($_FILES[$form_name]) ) {
if ( !empty($_FILES[$form_name]['tmp_name']) ) {
$upload = wp_upload_bits($_FILES[$form_name]['name'], null, file_get_contents($_FILES[$form_name]['tmp_name']));
if (isset($upload['error']) && $upload['error'] != 0) {
wp_die('There was an error uploading your file. The error is: ' . $upload['error']);
} else {
update_post_meta($post->ID, $form_name, $upload['url']);
}
}
} else {
// Make better. Have to do this, because I can't figure
// out a better way to deal with checkboxes. If deselected,
// they won't be represented here, but I still need to
// update the value to false to blank in the table. Hmm...
if (!isset($_POST[$form_name])) $_POST[$form_name] = '';
if (isset($post->ID) ) {
update_post_meta($post->ID, $form_name, $_POST[$form_name]);
}
}
}
$_SESSION['taxonomy_data'] = array();
}
});
}
}
/*********/
/* USAGE */
/*********/
// $product = new PostType("movie");
// $product->add_taxonomy('Actor');
// $product->add_taxonomy('Director');
// $product->add_meta_box('Movie Info', array(
// 'name' => 'text',
// 'rating' => 'text',
// 'review' => 'textarea',
// 'Profile Image' => 'file'
// ));