Editorial Calendar - Version 1.4

Version Description

  • We now have a new look and feel for the quick edit dialog and a few other elements to match WordPress 3.2.

  • We've refactored the Editorial Calendar into a PHP class for easier maintainability and better scoping.

Download this release

Release Info

Developer zgrossbart
Plugin Icon wp plugin Editorial Calendar
Version 1.4
Comparing to
See all releases

Code changes from version 1.3.4 to 1.4

Files changed (3) hide show
  1. edcal.css +78 -22
  2. edcal.php +1031 -1024
  3. readme.txt +9 -7
edcal.css CHANGED
@@ -47,16 +47,17 @@
47
  }
48
 
49
  .day {
50
- border: 1px solid rgb(164, 164, 164); /* this will add to total height in IE. So, 100% + 2px */
51
- -moz-border-radius-topright:3px;
52
- -moz-border-radius-topleft:3px;
53
- -webkit-border-top-left-radius:3px;
54
- -webkit-border-top-right-radius:3px;
55
  background: white;
56
  }
57
 
58
  .day.beforeToday {
59
- background: #f1f1f1;
 
60
  }
61
 
62
  .day.todayAndAfter {
@@ -83,6 +84,10 @@
83
 
84
  .firstOfMonth .dayobj {
85
  background-color: #eaf2fb;
 
 
 
 
86
  }
87
 
88
  .daylabel {
@@ -93,6 +98,20 @@
93
  font-weight:bold;
94
  text-align: right;
95
  padding-right: 10px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  }
97
 
98
  .daynewlink {
@@ -109,7 +128,7 @@
109
  height: 1.5em;
110
  }
111
 
112
- .today .daylabel {
113
  color: white;
114
  }
115
 
@@ -149,7 +168,6 @@
149
  }
150
 
151
  .dayhead {
152
- font-weight: bold;
153
  text-align: left;
154
  text-indent: 5px;
155
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8);
@@ -160,8 +178,22 @@
160
 
161
  .dayheadcont {
162
  position: relative;
163
- height: 28px;
164
  top: 0px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  }
166
 
167
  .dayhead.firstday {
@@ -176,6 +208,8 @@
176
  padding-bottom:1px;
177
  -moz-border-radius:4px;
178
  -webkit-border-radius:4px;
 
 
179
  }
180
 
181
  #topbar {
@@ -252,29 +286,47 @@
252
  /* Quick Add/Edit Tooltip */
253
 
254
  #tooltip {
255
- background: #f9f9f9;
256
  width:500px;
257
- border:1px solid #D3D3D3;
258
- -moz-border-radius:6px;
259
- -webkit-border-radius:6px;
260
- -moz-box-shadow:0 4px 8px #C8C8C8;
 
 
 
 
 
261
  position: relative;
262
  z-index: 25;
263
  }
264
 
265
  .tooltip {
266
- padding: 1em;
267
  position: relative;
 
 
 
 
 
 
 
 
 
 
268
  }
269
 
270
  #tooltiptitle {
271
- font-weight:bold;
272
- padding-left:1em;
273
- padding-right:1em;
274
- height:30px;
275
- line-height:30px;
 
276
  position:relative;
277
  text-shadow: #fff 0px 1px 0px;
 
 
278
  }
279
 
280
  #tipclose {
@@ -282,7 +334,7 @@
282
  height: 15px;
283
  position: absolute;
284
  top:8px;
285
- right:1em;
286
  }
287
 
288
  #tooltip .inline-edit-row fieldset {
@@ -326,6 +378,9 @@ TinyMCE Rich Editor and Media buttons are not currently used
326
  padding:0 0 0.5em 0;
327
  }
328
 
 
 
 
329
  #newPostScheduleButton {
330
  position: absolute;
331
  right: 0;
@@ -333,7 +388,8 @@ TinyMCE Rich Editor and Media buttons are not currently used
333
  }
334
 
335
  #newPostScheduleButton.disabled {
336
- color: #AAAAAA;
 
337
  }
338
 
339
  /* End Add/Edit Tooltip */
47
  }
48
 
49
  .day {
50
+ border: 1px solid #ccc; /* this will add to total height in IE. So, 100% + 2px */
51
+ -moz-border-radius:3px;
52
+ -webkit-border-radius:3px;
53
+ -o-border-radius:3px;
54
+ border-radius:3px;
55
  background: white;
56
  }
57
 
58
  .day.beforeToday {
59
+ background: #ececec;
60
+ /* background: #f9f9f9;*/
61
  }
62
 
63
  .day.todayAndAfter {
84
 
85
  .firstOfMonth .dayobj {
86
  background-color: #eaf2fb;
87
+ -moz-border-radius:2px;
88
+ -webkit-border-radius:2px;
89
+ -o-border-radius:2px;
90
+ border-radius:2px;
91
  }
92
 
93
  .daylabel {
98
  font-weight:bold;
99
  text-align: right;
100
  padding-right: 10px;
101
+ -moz-border-radius:2px 2px 0 0;
102
+ -webkit-border-radius:2px 2px 0 0;
103
+ -o-border-radius:2px 2px 0 0;
104
+ border-radius:2px 2px 0 0;
105
+ }
106
+
107
+ .day.month-present .daylabel {
108
+ border-bottom:1px solid #dfdfdf;
109
+ background:#e9e9e9;
110
+ background-image:-moz-linear-gradient(top,#f4f4f4,#e9e9e9);
111
+ background-image:-o-linear-gradient(top,#f4f4f4,#e9e9e9);
112
+ background-image:-webkit-gradient(linear,left top,left bottom,from(#f4f4f4),to(#e9e9e9));
113
+ background-image:-webkit-linear-gradient(top,#f4f4f4,#e9e9e9);
114
+ background-image:linear-gradient(top,#f4f4f4,#e9e9e9);
115
  }
116
 
117
  .daynewlink {
128
  height: 1.5em;
129
  }
130
 
131
+ .day.today .daylabel {
132
  color: white;
133
  }
134
 
168
  }
169
 
170
  .dayhead {
 
171
  text-align: left;
172
  text-indent: 5px;
173
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.8);
178
 
179
  .dayheadcont {
180
  position: relative;
181
+ height: 34px;
182
  top: 0px;
183
+ background:#e9e9e9;
184
+ background-image:-moz-linear-gradient(top,#f4f4f4,#e9e9e9);
185
+ background-image:-o-linear-gradient(top,#f4f4f4,#e9e9e9);
186
+ background-image:-webkit-gradient(linear,left top,left bottom,from(#f4f4f4),to(#e9e9e9));
187
+ background-image:-webkit-linear-gradient(top,#f4f4f4,#e9e9e9);
188
+ background-image:linear-gradient(top,#f4f4f4,#e9e9e9);
189
+ font-family:Georgia,"Times New Roman","Bitstream Charter",Times,serif;
190
+ font-size:14px;
191
+ border-top:1px solid #fff;
192
+ border-bottom:1px solid #dfdfdf;
193
+ -moz-border-radius:3px 3px 0 0;
194
+ -webkit-border-radius:3px 3px 0 0
195
+ -o-border-radius:3px 3px 0 0
196
+ border-radius:3px 3px 0 0
197
  }
198
 
199
  .dayhead.firstday {
208
  padding-bottom:1px;
209
  -moz-border-radius:4px;
210
  -webkit-border-radius:4px;
211
+ -o-border-radius:4px;
212
+ border-radius:4px;
213
  }
214
 
215
  #topbar {
286
  /* Quick Add/Edit Tooltip */
287
 
288
  #tooltip {
289
+ background: #f4f4f4;
290
  width:500px;
291
+ border:1px solid #dfdfdf;
292
+ -moz-border-radius:3px;
293
+ -webkit-border-radius:3px;
294
+ -o-border-radius:3px;
295
+ border-radius:3px;
296
+ -moz-box-shadow:0 4px 8px #c8c8c8, 0 1px 0 #FFFFFF inset;
297
+ -webkit-box-shadow:0 4px 8px #c8c8c8, 0 1px 0 #FFFFFF inset;
298
+ -o-box-shadow:0 4px 8px #c8c8c8, 0 1px 0 #FFFFFF inset;
299
+ box-shadow:0 4px 8px #c8c8c8, 0 1px 0 #FFFFFF inset;
300
  position: relative;
301
  z-index: 25;
302
  }
303
 
304
  .tooltip {
305
+ padding: 10px;
306
  position: relative;
307
+ border-top:1px solid #fff;
308
+ }
309
+
310
+ #tooltiphead {
311
+ background: #e9e9e9;
312
+ background-image:-moz-linear-gradient(top,#f4f4f4,#e9e9e9);
313
+ background-image:-o-linear-gradient(top,#f4f4f4,#e9e9e9);
314
+ background-image:-webkit-gradient(linear,left top,left bottom,from(#f4f4f4),to(#e9e9e9));
315
+ background-image:-webkit-linear-gradient(top,#f4f4f4,#e9e9e9);
316
+ background-image:linear-gradient(top,#f4f4f4,#e9e9e9);
317
  }
318
 
319
  #tooltiptitle {
320
+ border-bottom:1px solid #dfdfdf;
321
+ color:#464646;
322
+ font-family:Georgia,"Times New Roman","Bitstream Charter",Times,serif;
323
+ font-size:15px;
324
+ font-weight:normal;
325
+ line-height:1;
326
  position:relative;
327
  text-shadow: #fff 0px 1px 0px;
328
+ padding:7px 10px;
329
+ margin:1px 0 0;
330
  }
331
 
332
  #tipclose {
334
  height: 15px;
335
  position: absolute;
336
  top:8px;
337
+ right:10px;
338
  }
339
 
340
  #tooltip .inline-edit-row fieldset {
378
  padding:0 0 0.5em 0;
379
  }
380
 
381
+ #edit-slug-buttons a {
382
+ }
383
+
384
  #newPostScheduleButton {
385
  position: absolute;
386
  right: 0;
388
  }
389
 
390
  #newPostScheduleButton.disabled {
391
+ color:#9FD0D5!important;
392
+ background:#298CBA!important;
393
  }
394
 
395
  /* End Add/Edit Tooltip */
edcal.php CHANGED
@@ -18,1168 +18,1175 @@
18
  /*
19
  Plugin Name: WordPress Editorial Calendar
20
  Description: The Editorial Calendar makes it possible to see all your posts and drag and drop them to manage your blog.
21
- Version: 1.3.4
22
  Author: Colin Vernon, Justin Evans, Mary Vogt, and Zack Grossbart
23
  Author URI: http://www.zackgrossbart.com
24
  Plugin URI: http://stresslimitdesign.com/editorial-calendar-plugin
25
  */
26
 
27
- add_action('wp_ajax_edcal_saveoptions', 'edcal_saveoptions' );
28
- add_action('wp_ajax_edcal_changedate', 'edcal_changedate' );
29
- //add_action('wp_ajax_edcal_newdraft', 'edcal_newdraft' );
30
- add_action('wp_ajax_edcal_savepost', 'edcal_savepost' );
31
- add_action('wp_ajax_edcal_changetitle', 'edcal_changetitle' );
32
- add_action('admin_menu', 'edcal_list_add_management_page');
33
- add_action('wp_ajax_edcal_posts', 'edcal_posts' );
34
- add_action('wp_ajax_edcal_getpost', 'edcal_getpost' );
35
- add_action('wp_ajax_edcal_deletepost', 'edcal_deletepost' );
36
- //add_action("admin_print_scripts", 'edcal_scripts');
37
- add_action("init", 'edcal_load_language');
38
 
39
  /*
40
  * This error code matches CONCURRENCY_ERROR from edcal.js
41
  */
42
- $EDCAL_CONCURRENCY_ERROR = "4";
43
 
44
  /*
45
  * This error code matches PERMISSION_ERROR from edcal.js
46
  */
47
- $EDCAL_PERMISSION_ERROR = "5";
48
 
49
  /*
50
  * This error code matches NONCE_ERROR from edcal.js
51
  */
52
- $EDCAL_NONCE_ERROR = "6";
53
-
54
- /*
55
- * This boolean variable will be used to check whether this
56
- * installation of WordPress supports custom post types.
57
- */
58
- $edcal_supports_custom_types = function_exists('get_post_types') && function_exists('get_post_type_object');
59
-
60
- function edcal_load_language() {
61
- $plugin_dir = basename(dirname(__FILE__));
62
- load_plugin_textdomain( 'editorial-calendar', 'wp-content/plugins/' . $plugin_dir . '/languages/', $plugin_dir . '/languages/' );
63
- }
64
 
65
- /*
66
- * This function adds our calendar page to the admin UI
67
- */
68
- function edcal_list_add_management_page( ) {
69
- global $edcal_supports_custom_types;
70
- if ( function_exists('add_management_page') ) {
71
- $page = add_posts_page( __('Calendar', 'editorial-calendar'), __('Calendar', 'editorial-calendar'), 'edit_posts', 'cal', 'edcal_list_admin' );
72
- add_action( "admin_print_scripts-$page", 'edcal_scripts' );
 
 
 
 
 
 
 
73
 
74
- if($edcal_supports_custom_types) {
75
-
76
- /*
77
- * We add one calendar for Posts and then we add a separate calendar for each
78
- * custom post type. This calendar will have an URL like this:
79
- * /wp-admin/edit.php?post_type=podcasts&page=cal_podcasts
80
- *
81
- * We can then use the post_type parameter to show the posts of just that custom
82
- * type and update the labels for each post type.
83
- */
84
- $args = array(
85
- 'public' => true,
86
- '_builtin' => false
87
- );
88
- $output = 'names'; // names or objects
89
- $operator = 'and'; // 'and' or 'or'
90
- $post_types = get_post_types($args,$output,$operator);
91
-
92
- foreach ($post_types as $post_type) {
93
- $page = add_submenu_page('edit.php?post_type=' . $post_type, __('Calendar', 'editorial-calendar'), __('Calendar', 'editorial-calendar'), 'edit_posts', 'cal_' . $post_type, 'edcal_list_admin');
94
- add_action( "admin_print_scripts-$page", 'edcal_scripts' );
95
- }
96
-
97
- }
98
- }
99
- }
100
-
101
- /*
102
- * This is a utility function to open a file add it to our
103
- * output stream. We use this to embed JavaScript and CSS
104
- * files and cut down on the number of HTTP requests.
105
- */
106
- function echoEdCalFile($myFile) {
107
- $fh = fopen($myFile, 'r');
108
- $theData = fread($fh, filesize($myFile));
109
- fclose($fh);
110
- echo $theData;
111
- }
112
-
113
- /*
114
- * This is the function that generates our admin page. It adds the CSS files and
115
- * generates the divs that we need for the JavaScript to work.
116
- */
117
- function edcal_list_admin() {
118
- include_once('edcal.php');
119
-
120
- /*
121
- * We want to count the number of times they load the calendar
122
- * so we only show the feedback after they have been using it
123
- * for a little while.
124
- */
125
- $edcal_count = get_option("edcal_count");
126
- if ($edcal_count == '') {
127
- $edcal_count = 0;
128
- add_option("edcal_count", $edcal_count, "", "yes");
129
- }
130
 
131
- if (get_option("edcal_do_feedback") != "done") {
132
- $edcal_count++;
133
- update_option("edcal_count", $edcal_count);
 
 
 
134
  }
135
 
 
 
 
 
136
 
137
  /*
138
- * This section of code embeds certain CSS and
139
- * JavaScript files into the HTML. This has the
140
- * advantage of fewer HTTP requests, but the
141
- * disadvantage that the browser can't cache the
142
- * results. We only do this for files that will
143
- * be used on this page and nowhere else.
144
  */
145
-
146
- echo '<!-- This is the styles from time picker.css -->';
147
- echo '<style type="text/css">';
148
- echoEdCalFile(dirname( __FILE__ ) . "/lib/timePicker.css");
149
- echo '</style>';
150
-
151
- echo '<!-- This is the styles from humanmsg.css -->';
152
- echo '<style type="text/css">';
153
- echoEdCalFile(dirname( __FILE__ ) . "/lib/humanmsg.css");
154
- echo '</style>';
155
-
156
- echo '<!-- This is the styles from edcal.css -->';
157
- echo '<style type="text/css">';
158
- echoEdCalFile(dirname( __FILE__ ) . "/edcal.css");
159
- echo '</style>';
160
-
161
- ?>
162
-
163
- <!-- This is just a little script so we can pass the AJAX URL and some localized strings -->
164
- <script type="text/javascript">
165
- jQuery(document).ready(function(){
166
- edcal.wp_nonce = '<?php echo wp_create_nonce("edit-calendar"); ?>';
167
- <?php
168
- if (get_option("edcal_weeks_pref") != "") {
169
- ?>
170
- edcal.weeksPref = <?php echo(get_option("edcal_weeks_pref")); ?>;
171
- <?php
172
- }
173
- ?>
174
-
175
- <?php
176
- if (get_option("edcal_author_pref") != "") {
177
- ?>
178
- edcal.authorPref = <?php echo(get_option("edcal_author_pref")); ?>;
179
- <?php
180
- }
181
- ?>
182
-
183
- <?php
184
- if (get_option("edcal_time_pref") != "") {
185
- ?>
186
- edcal.timePref = <?php echo(get_option("edcal_time_pref")); ?>;
187
- <?php
188
- }
189
- ?>
190
-
191
- <?php
192
- if (get_option("edcal_status_pref") != "") {
193
- ?>
194
- edcal.statusPref = <?php echo(get_option("edcal_status_pref")); ?>;
195
- <?php
196
- }
197
- ?>
198
-
199
- <?php
200
- if (get_option("edcal_do_feedback") != "done") {
201
- ?>
202
- edcal.doFeedbackPref = true;
203
- edcal.visitCount = <?php echo(get_option("edcal_count")); ?>;
204
- <?php
205
- }
206
- ?>
207
-
208
- edcal.startOfWeek = <?php echo(get_option("start_of_week")); ?>;
209
- edcal.timeFormat = "<?php echo(get_option("time_format")); ?>";
210
- edcal.previewDateFormat = "MMMM d";
211
-
212
- /*
213
- * We want to show the day of the first day of the week to match the user's
214
- * country code. The problem is that we can't just use the WordPress locale.
215
- * If the locale was fr-FR so we started the week on Monday it would still
216
- * say Sunday was the first day if we didn't have a proper language bundle
217
- * for French. Therefore we must depend on the language bundle writers to
218
- * specify the locale for the language they are adding.
219
- *
220
- */
221
- edcal.locale = '<?php echo(__('en-US', 'editorial-calendar')) ?>';
222
-
223
- /*
224
- * These strings are all localized values. The WordPress localization mechanism
225
- * doesn't really extend to JavaScript so we localize the strings in PHP and then
226
- * pass the values to JavaScript.
227
- */
228
 
229
- edcal.str_by = <?php echo(edcal_json_encode(__('%1$s by %2$s', 'editorial-calendar'))) ?>;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
 
231
- edcal.str_addPostLink = <?php echo(edcal_json_encode(__('New Post', 'editorial-calendar'))) ?>;
232
-
233
- edcal.str_draft = <?php echo(edcal_json_encode(__(' [DRAFT]', 'editorial-calendar'))) ?>;
234
- edcal.str_pending = <?php echo(edcal_json_encode(__(' [PENDING]', 'editorial-calendar'))) ?>;
235
- edcal.str_sticky = <?php echo(edcal_json_encode(__(' [STICKY]', 'editorial-calendar'))) ?>;
236
- edcal.str_draft_sticky = <?php echo(edcal_json_encode(__(' [DRAFT, STICKY]', 'editorial-calendar'))) ?>;
237
- edcal.str_pending_sticky = <?php echo(edcal_json_encode(__(' [PENDING, STICKY]', 'editorial-calendar'))) ?>;
238
- edcal.str_edit = <?php echo(edcal_json_encode(__('Edit', 'editorial-calendar'))) ?>;
239
- edcal.str_quick_edit = <?php echo(edcal_json_encode(__('Quick Edit', 'editorial-calendar'))) ?>;
240
- edcal.str_del = <?php echo(edcal_json_encode(__('Delete', 'editorial-calendar'))) ?>;
241
- edcal.str_view = <?php echo(edcal_json_encode(__('View', 'editorial-calendar'))) ?>;
242
- edcal.str_republish = <?php echo(edcal_json_encode(__('Edit', 'editorial-calendar'))) ?>;
243
- edcal.str_status = <?php echo(edcal_json_encode(__('Status:', 'editorial-calendar'))) ?>;
244
- edcal.str_cancel = <?php echo(edcal_json_encode(__('Cancel', 'editorial-calendar'))) ?>;
245
- edcal.str_posttitle = <?php echo(edcal_json_encode(__('Title', 'editorial-calendar'))) ?>;
246
- edcal.str_postcontent = <?php echo(edcal_json_encode(__('Content', 'editorial-calendar'))) ?>;
247
- edcal.str_newpost = <?php echo(edcal_json_encode(__('Add a new post on %s', 'editorial-calendar'))) ?>;
248
- edcal.str_newpost_title = <?php echo(edcal_json_encode(sprintf(__('New %s - ', 'editorial-calendar'), edcal_get_posttype_singlename()))) ?> ;
249
- edcal.str_update = <?php echo(edcal_json_encode(__('Update', 'editorial-calendar'))) ?>;
250
- edcal.str_publish = <?php echo(edcal_json_encode(__('Schedule', 'editorial-calendar'))) ?>;
251
- edcal.str_review = <?php echo(edcal_json_encode(__('Submit for Review', 'editorial-calendar'))) ?>;
252
- edcal.str_save = <?php echo(edcal_json_encode(__('Save', 'editorial-calendar'))) ?>;
253
- edcal.str_edit_post_title = <?php echo(edcal_json_encode(__('Edit %1$s - %2$s', 'editorial-calendar'))) ?>;
254
- edcal.str_scheduled = <?php echo(edcal_json_encode(__('Scheduled', 'editorial-calendar'))) ?>;
255
-
256
- edcal.str_del_msg1 = <?php echo(edcal_json_encode(__('You are about to delete the post "', 'editorial-calendar'))) ?>;
257
- edcal.str_del_msg2 = <?php echo(edcal_json_encode(__('". Press Cancel to stop, OK to delete.', 'editorial-calendar'))) ?>;
258
-
259
- edcal.concurrency_error = <?php echo(edcal_json_encode(__('Looks like someone else already moved this post.', 'editorial-calendar'))) ?>;
260
- edcal.permission_error = <?php echo(edcal_json_encode(__('You do not have permission to edit posts.', 'editorial-calendar'))) ?>;
261
- edcal.checksum_error = <?php echo(edcal_json_encode(__('Invalid checksum for post. This is commonly a cross-site scripting error.', 'editorial-calendar'))) ?>;
262
- edcal.general_error = <?php echo(edcal_json_encode(__('There was an error contacting your blog.', 'editorial-calendar'))) ?>;
263
-
264
- edcal.str_screenoptions = <?php echo(edcal_json_encode(__('Screen Options', 'editorial-calendar'))) ?>;
265
- edcal.str_optionscolors = <?php echo(edcal_json_encode(__('Colors', 'editorial-calendar'))) ?>;
266
- edcal.str_optionsdraftcolor = <?php echo(edcal_json_encode(__('Drafts: ', 'editorial-calendar'))) ?>;
267
- edcal.str_apply = <?php echo(edcal_json_encode(__('Apply', 'editorial-calendar'))) ?>;
268
- edcal.str_show_title = <?php echo(edcal_json_encode(__('Show on screen', 'editorial-calendar'))) ?>;
269
- edcal.str_opt_weeks = <?php echo(edcal_json_encode(__(' weeks at a time', 'editorial-calendar'))) ?>;
270
- edcal.str_show_opts = <?php echo(edcal_json_encode(__('Show in Calendar Cell', 'editorial-calendar'))) ?>;
271
- edcal.str_opt_author = <?php echo(edcal_json_encode(__('Author', 'editorial-calendar'))) ?>;
272
- edcal.str_opt_status = <?php echo(edcal_json_encode(__('Status', 'editorial-calendar'))) ?>;
273
- edcal.str_opt_time = <?php echo(edcal_json_encode(__('Time of day', 'editorial-calendar'))) ?>;
274
- edcal.str_fatal_error = <?php echo(edcal_json_encode(__('An error occurred while loading the calendar: ', 'editorial-calendar'))) ?>;
275
-
276
- edcal.str_weekserror = <?php echo(edcal_json_encode(__('The calendar can only show between 1 and 5 weeks at a time.', 'editorial-calendar'))) ?>;
277
- edcal.str_weekstt = <?php echo(edcal_json_encode(__('Select the number of weeks for the calendar to show.', 'editorial-calendar'))) ?>;
278
-
279
- edcal.str_feedbackmsg = <?php echo(edcal_json_encode(__('<div id="feedbacksection">' .
280
- '<h2>Help us Make the Editorial Calendar Better</h2>' .
281
- 'We are always trying to improve the Editorial Calendar and you can help. May we collect some data about your blog and browser settings to help us improve this plugin? We\'ll only do it once and your blog will show up on our <a target="_blank" href="http://www.zackgrossbart.com/edcal/mint/">Editorial Calendar Statistics page</a>.<br /><br />' .
282
- '<button class="button-secondary" onclick="edcal.doFeedback();">Collect Anonymous Data</button> ' .
283
- '<a href="#" id="nofeedbacklink" onclick="edcal.noFeedback(); return false;">No thank you</a></div>', 'editorial-calendar'))) ?>;
284
-
285
- edcal.str_feedbackdone = <?php echo(edcal_json_encode(__('<h2>We\'re done</h2>We\'ve finished collecting data. Thank you for helping us make the calendar better.', 'editorial-calendar'))) ?>;
286
- });
287
- </script>
288
-
289
- <style type="text/css">
290
- .loadingclass > .postlink, .loadingclass:hover > .postlink, .tiploading {
291
- background-image: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/../../../wp-admin/images/loading.gif")); ?>');
292
- }
293
-
294
- #loading {
295
- background-image: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/../../../wp-admin/images/loading.gif")); ?>');
296
- }
297
-
298
- #tipclose {
299
- background-image: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/images/tip_close.png")); ?>');
300
- }
301
-
302
- #tooltip {
303
- background: white url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/../../../wp-admin/images/gray-grad.png")); ?>') repeat-x left top;
304
- }
305
-
306
- .month-present .daylabel, .firstOfMonth .daylabel, .dayheadcont {
307
- background: #6D6D6D url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/../../../wp-admin/images/gray-grad.png")); ?>') repeat-x scroll left top;
308
- }
309
-
310
- .today .daylabel {
311
- background: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/../../../wp-admin/images/button-grad.png")); ?>') repeat-x left top;
312
- }
313
-
314
- </style>
315
 
316
- <?php
317
- echo '<!-- This is the code from edcal.js -->';
318
- echo '<script type="text/javascript">';
319
- echoEdCalFile(dirname( __FILE__ ) . "/edcal.js");
320
- echo '</script>';
321
-
322
- ?>
323
-
324
- <div class="wrap">
325
- <div class="icon32" id="icon-edit"><br/></div>
326
- <h2 id="edcal_main_title"><?php echo(edcal_get_posttype_multiplename()); ?><?php echo(__(' Calendar', 'editorial-calendar')); ?></h2>
327
-
328
- <div id="loadingcont">
329
- <div id="loading"> </div>
330
- </div>
331
-
332
- <div id="topbar" class="tablenav">
333
- <div id="topleft" class="tablenav-pages">
334
- <h3>
335
- <a href="#" title="<?php echo(__('Jump back', 'editorial-calendar')) ?>" class="prev page-numbers" id="prevmonth">&laquo;</a>
336
- <span id="currentRange"></span>
337
- <a href="#" title="<?php echo(__('Skip ahead', 'editorial-calendar')) ?>" class="next page-numbers" id="nextmonth">&raquo;</a>
338
- </h3>
339
- </div>
340
-
341
- <div id="topright">
342
- <button class="save button" title="<?php echo(__('Scroll the calendar and make the today visible', 'editorial-calendar')) ?>" id="moveToToday"><?php echo(__('Show Today', 'editorial-calendar')) ?></button>
343
- </div>
344
- </div>
345
-
346
- <div id="cal_cont">
347
- <div id="edcal_scrollable" class="edcal_scrollable vertical">
348
- <div id="cal"></div>
349
- </div>
350
- </div>
351
-
352
- <div id="tooltip" style="display:none;">
353
- <div id="tooltiphead">
354
- <div id="tooltiptitle"><?php _e('Edit Post', 'editorial-calendar') ?></div>
355
- <a href="#" id="tipclose" onclick="edcal.hideForm(); return false;" title="close"> </a>
356
- </div>
357
-
358
- <div class="tooltip inline-edit-row">
359
-
360
- <fieldset>
361
-
362
- <label>
363
- <span class="title"><?php _e('Title', 'editorial-calendar') ?></span>
364
- <span class="input-text-wrap"><input type="text" class="ptitle" id="edcal-title-new-field" name="title" /></span>
365
- </label>
366
-
367
- <label>
368
- <span class="title"><?php _e('Content', 'editorial-calendar') ?></span>
369
- <?php /*
370
- <div id="cal_mediabar">
371
- <?php if ( current_user_can( 'upload_files' ) ) : ?>
372
- <div id="media-buttons" class="hide-if-no-js">
373
- <?php do_action( 'media_buttons' ); ?>
374
- </div>
375
- <?php endif; ?>
376
- </div>
377
- /*/ ?>
378
- <span class="input-text-wrap"><textarea cols="15" rows="7" id="content" name="content"></textarea></span>
379
- </label>
380
-
381
-
382
- <label>
383
- <span class="title"><?php _e('Time', 'editorial-calendar') ?></span>
384
- <span class="input-text-wrap"><input type="text" class="ptitle" id="edcal-time" name="time" value="" size="8" readonly="true" maxlength="8" autocomplete="off" /></span>
385
- </label>
386
-
387
- <label>
388
- <span class="title"><?php _e('Status', 'editorial-calendar') ?></span>
389
- <span class="input-text-wrap">
390
- <select name="status" id="edcal-status">
391
- <option value="draft"><?php _e('Draft', 'editorial-calendar') ?></option>
392
- <option value="pending"><?php _e('Pending Review', 'editorial-calendar') ?></option>
393
- <?php if ( current_user_can('publish_posts') ) {?>
394
- <option id="futureoption" value="future"><?php _e('Scheduled', 'editorial-calendar') ?></option>
395
- <?php } ?>
396
- </select>
397
- </span>
398
- </label>
399
-
400
- <?php /* <label>
401
- <span class="title"><?php _e('Author', 'editorial-calendar') ?></span>
402
- <span id="edcal-author-p"><!-- Placeholder for the author's name, added dynamically --></span>
403
- </label>
404
- */ ?>
405
- </fieldset>
406
-
407
- <p class="submit inline-edit-save" id="edit-slug-buttons">
408
- <a class="button-primary disabled" id="newPostScheduleButton" href="#"><?php _e('Schedule', 'editorial-calendar') ?></a>
409
- <a href="#" onclick="edcal.hideForm(); return false;" class="button-secondary cancel"><?php _e('Cancel', 'editorial-calendar') ?></a>
410
- </p>
411
-
412
- <input type="hidden" id="edcal-date" name="date" value="" />
413
- <input type="hidden" id="edcal-id" name="id" value="" />
414
-
415
- </div><?php // end .tooltip ?>
416
- </div><?php // end #tooltip ?>
417
-
418
- </div><?php // end .wrap ?>
419
-
420
- <?php
421
- }
422
-
423
- /*
424
- * We use these variables to hold the post dates for the filter when
425
- * we do our post query.
426
- */
427
- $edcal_startDate;
428
- $edcal_endDate;
429
-
430
- /*
431
- * When we get a set of posts to populate the calendar we don't want
432
- * to get all of the posts. This filter allows us to specify the dates
433
- * we want.
434
- */
435
- function edcal_filter_where($where = '') {
436
- global $edcal_startDate, $edcal_endDate;
437
- //posts in the last 30 days
438
- //$where .= " AND post_date > '" . date('Y-m-d', strtotime('-30 days')) . "'";
439
- //posts 30 to 60 days old
440
- //$where .= " AND post_date >= '" . date('Y-m-d', strtotime('-60 days')) . "'" . " AND post_date <= '" . date('Y-m-d', strtotime('-30 days')) . "'";
441
- //posts for March 1 to March 15, 2009
442
- $where .= " AND post_date >= '" . $edcal_startDate . "' AND post_date < '" . $edcal_endDate . "'";
443
- return $where;
444
- }
445
-
446
- /*
447
- * This function adds all of the JavaScript files we need.
448
- *
449
- */
450
- function edcal_scripts() {
451
- /*
452
- * To get proper localization for dates we need to include the correct JavaScript file for the current
453
- * locale. We can do this based on the locale in the localized bundle to make sure the date locale matches
454
- * the locale for the other strings.
455
- */
456
- wp_enqueue_script( "date", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/languages/date-".__('en-US', 'editorial-calendar').".js"), array( 'jquery' ) );
457
- wp_enqueue_script( 'jquery' );
458
- wp_enqueue_script( 'jquery-ui-draggable' );
459
- wp_enqueue_script( 'jquery-ui-droppable' );
460
-
461
- //wp_enqueue_script( "date-extras", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/date.extras.js"), array( 'jquery' ) );
462
-
463
- wp_enqueue_script( "edcal-lib", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/edcallib.min.js"), array( 'jquery' ) );
464
-
465
- if ($_GET['qunit']) {
466
- wp_enqueue_script( "qunit", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/qunit.js"), array( 'jquery' ) );
467
- wp_enqueue_script( "edcal-test", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/edcal_test.js"), array( 'jquery' ) );
468
  }
469
 
470
- return;
471
-
472
  /*
473
- * If you're using one of the specific libraries you should comment out the two lines
474
- * above this comment.
 
475
  */
476
- wp_enqueue_script( "bgiframe", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/jquery.bgiframe.js"), array( 'jquery' ) );
477
- wp_enqueue_script( "humanMsg", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/humanmsg.js"), array( 'jquery' ) );
478
- wp_enqueue_script( "jquery-timepicker", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/jquery.timepicker.js"), array( 'jquery' ) );
479
-
480
- wp_enqueue_script( "scrollable", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/tools.scrollable-1.1.2.js"), array( 'jquery' ) );
481
- wp_enqueue_script( "mouse-wheel", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/tools.scrollable.mousewheel-1.0.1.js"), array( 'jquery' ) );
482
-
483
- wp_enqueue_script( "json-parse2", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/json2.js"), array( 'jquery' ) );
484
- }
485
-
486
- /*
487
- * This is an AJAX call that gets the posts between the from date
488
- * and the to date.
489
- */
490
- function edcal_posts() {
491
- header("Content-Type: application/json");
492
- edcal_addNoCacheHeaders();
493
- if (!edcal_checknonce()) {
494
- die();
495
  }
496
-
497
- global $edcal_startDate, $edcal_endDate;
498
- $edcal_startDate = isset($_GET['from'])?$_GET['from']:null;
499
- $edcal_endDate = isset($_GET['to'])?$_GET['to']:null;
500
- global $post;
501
- $args = array(
502
- 'posts_per_page' => -1,
503
- 'post_status' => "publish&future&draft",
504
- 'post_parent' => null // any parent
505
- );
506
-
507
- /*
508
- * If we're in the specific post type case we need to add
509
- * the post type to our query.
510
  */
511
- $post_type = $_GET['post_type'];
512
- if ($post_type) {
513
- $args['post_type'] = $post_type;
514
- }
515
-
516
- add_filter('posts_where', 'edcal_filter_where');
517
- $myposts = query_posts($args);
518
- remove_filter('posts_where', 'edcal_filter_where');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
519
 
520
- ?>[
521
- <?php
522
- $size = sizeof($myposts);
 
523
 
524
- for($i = 0; $i < $size; $i++) {
525
- $post = $myposts[$i];
526
- edcal_postJSON($post, $i < $size - 1);
527
- }
528
 
529
- ?> ]
530
- <?php
 
531
 
532
- die();
533
- }
534
-
535
- /*
536
- * This is for an AJAX call that returns a post with the specified ID
537
- */
538
- function edcal_getpost() {
539
-
540
- header("Content-Type: application/json");
541
- edcal_addNoCacheHeaders();
542
-
543
- // If nonce fails, return
544
- if (!edcal_checknonce()) die();
545
-
546
- $post_id = intval($_GET['postid']);
547
-
548
- // If a proper post_id wasn't passed, return
549
- if(!$post_id) die();
550
 
551
- $args = array(
552
- 'post__in' => array($post_id)
553
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
554
 
555
- /*
556
- * If we're in the specific post type case we need to add
557
- * the post type to our query.
558
- */
559
- $post_type = $_GET['post_type'];
560
- if ($post_type) {
561
- $args['post_type'] = $post_type;
562
  }
563
-
564
- $post = query_posts($args);
565
-
566
- // get_post and setup_postdata don't get along, so we're doing a mini-loop
567
- if(have_posts()) :
568
- while(have_posts()) : the_post();
569
- ?>
570
- {
571
- "post" :
572
- <?php
573
- edcal_postJSON($post[0], false, true);
574
- ?>
575
- }
576
- <?php
577
- endwhile;
578
- endif;
579
- die();
580
- }
581
-
582
- function edcal_json_encode($string) {
583
  /*
584
- * WordPress escapes apostrophe's when they show up in post titles as &#039;
585
- * This is the HTML ASCII code for a straight apostrophe. This works well
586
- * with Firefox, but IE complains with a very unhelpful error message. We
587
- * can replace them with a right curly apostrophe since that works in IE
588
- * and Firefox. It is also a little nicer typographically.
589
  */
590
- return json_encode(str_replace("&#039;", "&#146;", $string));
591
- }
592
-
593
- /*
594
- * This helper functions gets the plural name of the post
595
- * type specified by the post_type parameter.
596
- */
597
- function edcal_get_posttype_multiplename() {
598
-
599
- $post_type = $_GET['post_type'];
600
- if (!$post_type) {
601
- return 'Posts';
602
- }
603
-
604
- $postTypeObj = get_post_type_object($post_type);
605
- return $postTypeObj->labels->name;
606
- }
607
-
608
- /*
609
- * This helper functions gets the singular name of the post
610
- * type specified by the post_type parameter.
611
- */
612
-
613
- function edcal_get_posttype_singlename() {
614
-
615
- $post_type = $_GET['post_type'];
616
- if (!$post_type) {
617
- return 'Post';
618
- }
619
-
620
- $postTypeObj = get_post_type_object($post_type);
621
- return $postTypeObj->labels->singular_name;
622
- }
623
-
624
- /*
625
- * This function sets up the post data and prints out the values we
626
- * care about in a JSON data structure. This prints out just the
627
- * value part. If $fullPost is set to true, post_content is also returned.
628
- */
629
- function edcal_postJSON($post, $addComma = true, $fullPost = false) {
630
- global $edcal_supports_custom_types;
631
- $timeFormat = get_option("time_format");
632
- if ($timeFormat == "g:i a") {
633
- $timeFormat = "ga";
634
- } else if ($timeFormat == "g:i A") {
635
- $timeFormat = "gA";
636
- } else if ($timeFormat == "H:i") {
637
- $timeFormat = "H";
638
- }
639
-
640
- setup_postdata($post);
641
 
642
- if (get_post_status() == 'auto-draft') {
643
- /*
644
- * WordPress 3 added a new post status of auto-draft so
645
- * we want to hide them from the calendar
646
- */
647
- return;
648
- }
649
-
650
- /*
651
- * We want to return the type of each post as part of the
652
- * JSON data about that post. Right now this will always
653
- * match the post_type parameter for the calendar, but in
654
- * the future we might support a mixed post type calendar
655
- * and this extra data will become useful. Right now we
656
- * are using this data for the title on the quick edit form.
657
- */
658
- if($edcal_supports_custom_types) {
659
- $postTypeObj = get_post_type_object(get_post_type( $post ));
660
- $postTypeTitle = $postTypeObj->labels->singular_name;
661
- } else {
662
- $postTypeTitle = 'post';
663
- }
664
  ?>
665
- {
666
- "date" : "<?php the_time('d') ?><?php the_time('m') ?><?php the_time('Y') ?>",
667
- "time" : "<?php the_time() ?>",
668
- "formattedtime" : "<?php edcal_json_encode(the_time($timeFormat)); ?>",
669
- "sticky" : "<?php echo(is_sticky($post->ID)); ?>",
670
- "url" : "<?php edcal_json_encode(the_permalink()); ?>",
671
- "status" : "<?php echo(get_post_status()); ?>",
672
- "title" : <?php echo(edcal_json_encode(get_the_title())); ?>,
673
- "author" : <?php echo(edcal_json_encode(get_the_author())); ?>,
674
- "type" : "<?php echo(get_post_type( $post )); ?>",
675
- "typeTitle" : "<?php echo($postTypeTitle); ?>",
676
-
677
- <?php if ( current_user_can('edit_post', $post->ID) ) {?>
678
- "editlink" : "<?php echo(get_edit_post_link($id)); ?>",
679
- <?php } ?>
680
-
681
- <?php if ( current_user_can('delete_post', $post->ID) ) {?>
682
- "dellink" : "javascript:edcal.deletePost(<?php echo $post->ID ?>)",
683
- <?php } ?>
684
-
685
- "permalink" : "<?php echo(get_permalink($id)); ?>",
686
- "id" : "<?php the_ID(); ?>"
687
-
688
- <?php if($fullPost) : ?>
689
- , "content" : <?php echo edcal_json_encode($post->post_content) ?>
690
-
691
- <?php endif; ?>
692
- }
693
- <?php
694
- if ($addComma) {
695
- ?>,<?php
696
- }
697
- }
698
-
699
- /*
700
- * This is a helper AJAX function to delete a post. It gets called
701
- * when a user clicks the delete button, and allows the user to
702
- * retain their position within the calendar without a page refresh.
703
- * It is not called unless the user has permission to delete the post
704
- */
705
- function edcal_deletepost() {
706
- if (!edcal_checknonce()) {
707
- die();
708
- }
709
-
710
- header("Content-Type: application/json");
711
- edcal_addNoCacheHeaders();
712
 
713
- $edcal_postid = isset($_GET['postid'])?$_GET['postid']:null;
714
- $post = get_post($edcal_postid, ARRAY_A);
715
- $title = $post['post_title'];
716
- $date = date('dmY', strtotime($post['post_date'])); // [TODO] : is there a better way to generate the date string ... ??
717
-
718
-
719
- $force = !EMPTY_TRASH_DAYS; // wordpress 2.9 thing. deleted post hangs around (ie in a recycle bin) after deleted for this # of days
720
- if ( $post->post_type == 'attachment' ) {
721
- $force = ( $force || !MEDIA_TRASH );
722
- if ( ! wp_delete_attachment($edcal_postid, $force) )
723
- wp_die( __('Error in deleting...') );
724
- } else {
725
- if ( !wp_delete_post($edcal_postid, $force) )
726
- wp_die( __('Error in deleting...') );
727
- }
728
-
729
- // return the following info so that jQuery can then remove post from edcal display :
730
- ?>
731
- {
732
- "post" :
733
- {
734
- "date" : "<?php echo $date ?>",
735
- "title" : "<?php echo $title ?>",
736
- "id" : "<?php echo $edcal_postid ?>"
737
- }
738
- }
739
- <?php
740
-
741
- die();
742
- }
743
-
744
-
745
-
746
-
747
- /*
748
- * This is a helper AJAX function to change the title of a post. It
749
- * gets called from the save button in the tooltip when you change a
750
- * post title in a calendar.
751
- */
752
- function edcal_changetitle() {
753
- if (!edcal_checknonce()) {
754
- die();
 
 
 
 
 
 
 
 
755
  }
756
-
757
- header("Content-Type: application/json");
758
- edcal_addNoCacheHeaders();
759
-
760
- $edcal_postid = isset($_GET['postid'])?$_GET['postid']:null;
761
- $edcal_newTitle = isset($_GET['title'])?$_GET['title']:null;
762
-
763
- $post = get_post($edcal_postid, ARRAY_A);
764
- setup_postdata($post);
765
-
766
- $post['post_title'] = $edcal_newTitle;
767
 
768
  /*
769
- * Now we finally update the post into the database
 
 
770
  */
771
- wp_update_post( $post );
 
 
 
 
772
 
773
  /*
774
- * We finish by returning the latest data for the post in the JSON
 
775
  */
776
- global $post;
777
- $args = array(
778
- 'posts_id' => $edcal_postid,
779
- );
 
 
 
 
 
 
780
 
781
- $post = get_post($edcal_postid);
782
 
783
- ?>{
784
- "post" :
785
- <?php
786
-
787
- edcal_postJSON($post);
788
 
789
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
790
  }
791
- <?php
792
-
793
 
794
- die();
795
- }
796
-
797
- /*
798
- * This is a helper function to create a new blank draft
799
- * post on a specified date.
800
- */
801
- function edcal_newdraft() {
802
- if (!edcal_checknonce()) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
803
  die();
804
  }
805
-
806
- header("Content-Type: application/json");
807
- edcal_addNoCacheHeaders();
808
-
809
- $edcal_date = isset($_POST["date"])?$_POST["date"]:null;
810
-
811
- $my_post = array();
812
- $my_post['post_title'] = isset($_POST["title"])?$_POST["title"]:null;
813
- $my_post['post_content'] = isset($_POST["content"])?$_POST["content"]:null;
814
- $my_post['post_status'] = 'draft';
815
-
816
- $my_post['post_date'] = $edcal_date;
817
- $my_post['post_date_gmt'] = get_gmt_from_date($edcal_date);
818
- $my_post['post_modified'] = $edcal_date;
819
- $my_post['post_modified_gmt'] = get_gmt_from_date($edcal_date);
820
-
821
- // Insert the post into the database
822
- $my_post_id = wp_insert_post( $my_post );
823
 
824
  /*
825
- * We finish by returning the latest data for the post in the JSON
826
  */
827
- global $post;
828
- $post = get_post($my_post_id);
829
-
830
- ?>{
831
- "post" :
832
- <?php
833
-
834
- edcal_postJSON($post, false);
835
-
836
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
837
  }
838
- <?php
839
 
840
- die();
841
- }
842
-
843
- /*
844
- * This is a helper function to create a new draft post on a specified date
845
- * or update an existing post
846
- */
847
- function edcal_savepost() {
848
-
849
- if (!edcal_checknonce()) {
850
- die();
 
851
  }
852
-
853
- header("Content-Type: application/json");
854
- edcal_addNoCacheHeaders();
855
 
856
- $edcal_date = isset($_POST["date"])?$_POST["date"]:null;
 
 
 
 
857
 
858
- $my_post = array();
859
-
860
- // If the post id is not specified, we're creating a new post
861
- if($_POST['id']) {
862
- $my_post['ID'] = intval($_POST['id']);
863
- } else {
864
- $my_post['post_status'] = 'draft'; // if new post, set the status to draft
865
- }
866
-
867
- $my_post['post_title'] = isset($_POST["title"])?$_POST["title"]:null;
868
- $my_post['post_content'] = isset($_POST["content"])?$_POST["content"]:null;
869
 
870
- $my_post['post_date'] = $edcal_date;
871
- $my_post['post_date_gmt'] = get_gmt_from_date($edcal_date);
872
- $my_post['post_modified'] = $edcal_date;
873
- $my_post['post_modified_gmt'] = get_gmt_from_date($edcal_date);
874
 
875
  /*
876
- * When we create a new post we need to specify the post type
877
- * passed in from the JavaScript.
878
  */
879
- $post_type = isset($_POST["post_type"])?$_POST["post_type"]:null;
880
- if ($post_type) {
881
- $my_post['post_type'] = $post_type;
882
- }
883
 
884
- if($_POST['status']) {
885
- wp_transition_post_status($_POST['status'], $my_post['post_status'], $my_post);
886
- $my_post['post_status'] = $_POST['status'];
887
- }
888
 
 
 
 
 
889
 
890
- // Insert the post into the database
891
- if($my_post['ID']) {
892
- $my_post_id = wp_update_post( $my_post );
893
- } else {
894
- $my_post_id = wp_insert_post( $my_post );
895
  }
896
-
897
- // TODO: throw error if update/insert or getsinglepost fails
898
- /*
899
- * We finish by returning the latest data for the post in the JSON
900
- */
901
- $args = array(
902
- 'p' => $my_post_id
903
- );
904
 
905
- if ($post_type) {
906
- $args['post_type'] = $post_type;
907
- }
908
- $post = query_posts($args);
909
-
910
- // get_post and setup_postdata don't get along, so we're doing a mini-loop
911
- if(have_posts()) :
912
- while(have_posts()) : the_post();
913
- ?>
914
- {
915
- "post" :
916
- <?php
917
- edcal_postJSON($post[0], false);
918
- ?>
919
- }
920
- <?php
921
- endwhile;
922
- endif;
923
- die();
924
- }
925
-
926
- /*
927
- * This function checks the nonce for the URL. It returns
928
- * true if the nonce checks out and outputs a JSON error
929
- * and returns false otherwise.
930
- */
931
- function edcal_checknonce() {
932
- header("Content-Type: application/json");
933
- edcal_addNoCacheHeaders();
934
-
935
- global $EDCAL_NONCE_ERROR;
936
- if (!wp_verify_nonce($_REQUEST['_wpnonce'], 'edit-calendar')) {
937
- /*
938
- * This is just a sanity check to make sure
939
- * this isn't a CSRF attack. Most of the time this
940
- * will never be run because you can't see the calendar unless
941
- * you are at least an editor
942
  */
 
 
 
 
 
 
943
  ?>
944
- {
945
- "error": <?php echo($EDCAL_NONCE_ERROR); ?>
946
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
947
  <?php
948
- return false;
 
 
949
  }
950
- return true;
951
- }
952
-
953
- /*
954
- * This function changes the date on a post. It does optimistic
955
- * concurrency checking by comparing the original post date from
956
- * the browser with the one from the database. If they don't match
957
- * then it returns an error code and the updated post data.
958
- *
959
- * If the call is successful then it returns the updated post data.
960
- */
961
- function edcal_changedate() {
962
- if (!edcal_checknonce()) {
963
- die();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
964
  }
965
- header("Content-Type: application/json");
966
- edcal_addNoCacheHeaders();
967
 
968
- global $edcal_startDate, $edcal_endDate;
969
- $edcal_postid = isset($_GET['postid'])?$_GET['postid']:null;
970
- $edcal_newDate = isset($_GET['newdate'])?$_GET['newdate']:null;
971
- $edcal_oldDate = isset($_GET['olddate'])?$_GET['olddate']:null;
972
- $edcal_postStatus = isset($_GET['postStatus'])?$_GET['postStatus']:null;
 
 
 
 
973
 
974
- if (!current_user_can('edit_post', $edcal_postid)) {
975
- global $EDCAL_PERMISSION_ERROR;
 
 
 
 
 
 
 
 
 
976
  /*
977
- * This is just a sanity check to make sure that the current
978
- * user has permission to edit posts. Most of the time this
979
- * will never be run because you can't see the calendar unless
980
- * you are at least an editor
981
  */
982
- ?>
983
- {
984
- "error": <?php echo($EDCAL_PERMISSION_ERROR); ?>,
985
- <?php
986
 
 
 
 
987
  global $post;
988
  $args = array(
989
  'posts_id' => $edcal_postid,
990
  );
991
 
992
  $post = get_post($edcal_postid);
993
- ?>
 
994
  "post" :
995
  <?php
996
- edcal_postJSON($post, false, true);
997
- ?> }
998
 
 
 
 
 
999
  <?php
 
 
1000
  die();
1001
  }
1002
 
1003
- $post = get_post($edcal_postid, ARRAY_A);
1004
- setup_postdata($post);
1005
-
1006
  /*
1007
- * We are doing optimistic concurrency checking on the dates. If
1008
- * the user tries to move a post we want to make sure nobody else
1009
- * has moved that post since the page was last updated. If the
1010
- * old date in the database doesn't match the old date from the
1011
- * browser then we return an error to the browser along with the
1012
- * updated post data.
1013
  */
1014
- if (date('Y-m-d', strtotime($post['post_date'])) != date('Y-m-d', strtotime($edcal_oldDate))) {
1015
- global $EDCAL_CONCURRENCY_ERROR;
1016
- ?> {
1017
- "error": <?php echo($EDCAL_CONCURRENCY_ERROR); ?>,
1018
- <?php
 
 
1019
 
1020
- global $post;
1021
- $args = array(
1022
- 'posts_id' => $edcal_postid,
1023
- );
1024
 
1025
- $post = get_post($edcal_postid);
1026
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1027
  "post" :
1028
  <?php
1029
- edcal_postJSON($post, false, true);
1030
- ?> }
1031
 
 
 
 
 
1032
  <?php
 
1033
  die();
1034
  }
1035
 
1036
  /*
1037
- * Posts in WordPress have more than one date. There is the GMT date,
1038
- * the date in the local time zone, the modified date in GMT and the
1039
- * modified date in the local time zone. We update all of them.
1040
- */
1041
- $post['post_date_gmt'] = $post['post_date'];
1042
-
1043
- /*
1044
- * When a user creates a draft and never sets a date or publishes it
1045
- * then the GMT date will have a timestamp of 00:00:00 to indicate
1046
- * that the date hasn't been set. In that case we need to specify
1047
- * an edit date or the wp_update_post function will strip our new
1048
- * date out and leave the post as publish immediately.
1049
- */
1050
- $needsEditDate = strpos($post['post_date_gmt'], "0000-00-00 00:00:00") === 0;
1051
-
1052
- $updated_post = array();
1053
- $updated_post['ID'] = $edcal_postid;
1054
- $updated_post['post_date'] = $edcal_newDate . substr($post['post_date'], strlen($edcal_newDate));
1055
- if ($needsEditDate != -1) {
1056
- $updated_post['edit_date'] = $edcal_newDate . substr($post['post_date'], strlen($edcal_newDate));
1057
- }
1058
-
1059
- /*
1060
- * We need to make sure to use the GMT formatting for the date.
1061
  */
1062
- $updated_post['post_date_gmt'] = get_gmt_from_date($updated_post['post_date']);
1063
- $updated_post['post_modified'] = $edcal_newDate . substr($post['post_modified'], strlen($edcal_newDate));
1064
- $updated_post['post_modified_gmt'] = get_gmt_from_date($updated_post['post_date']);
 
 
1065
 
1066
- if ( $edcal_postStatus != $post['post_status'] ) {
1067
- /*
1068
- * We only want to update the post status if it has changed.
1069
- * If the post status has changed that takes a few more steps
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1070
  */
1071
- wp_transition_post_status($edcal_postStatus, $post['post_status'], $post);
1072
- $updated_post['post_status'] = $edcal_postStatus;
 
 
1073
 
1074
- // Update counts for the post's terms.
1075
- foreach ( (array) get_object_taxonomies('post') as $taxonomy ) {
1076
- $tt_ids = wp_get_object_terms($post_id, $taxonomy, 'fields=tt_ids');
1077
- wp_update_term_count($tt_ids, $taxonomy);
1078
  }
1079
 
1080
- do_action('edit_post', $edcal_postid, $post);
1081
- do_action('save_post', $edcal_postid, $post);
1082
- do_action('wp_insert_post', $edcal_postid, $post);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1083
  }
1084
 
1085
  /*
1086
- * Now we finally update the post into the database
 
 
1087
  */
1088
- wp_update_post( $updated_post );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1089
 
1090
  /*
1091
- * We finish by returning the latest data for the post in the JSON
 
 
 
 
 
1092
  */
1093
- global $post;
1094
- $args = array(
1095
- 'posts_id' => $edcal_postid,
1096
- );
1097
-
1098
- $post = get_post($edcal_postid);
1099
- ?>{
1100
- "post" :
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1101
 
1102
- <?php
1103
- edcal_postJSON($post, false, true);
1104
- ?>}
1105
- <?php
1106
-
1107
- die();
1108
- }
1109
-
1110
- /*
1111
- * This function saves the preferences
1112
- */
1113
- function edcal_saveoptions() {
1114
- if (!edcal_checknonce()) {
1115
  die();
1116
  }
1117
-
1118
- header("Content-Type: application/json");
1119
- edcal_addNoCacheHeaders();
1120
 
1121
  /*
1122
- * The number of weeks preference
1123
  */
1124
- $edcal_weeks = isset($_GET['weeks'])?$_GET['weeks']:null;
1125
- if ($edcal_weeks != null) {
1126
- add_option("edcal_weeks_pref", $edcal_weeks, "", "yes");
1127
- update_option("edcal_weeks_pref", $edcal_weeks);
1128
- }
1129
 
1130
- /*
1131
- * The show author preference
1132
- */
1133
- $edcal_author = isset($_GET['author-hide'])?$_GET['author-hide']:null;
1134
- if ($edcal_author != null) {
1135
- add_option("edcal_author_pref", $edcal_author, "", "yes");
1136
- update_option("edcal_author_pref", $edcal_author);
1137
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1138
 
1139
- /*
1140
- * The show status preference
1141
- */
1142
- $edcal_status = isset($_GET['status-hide'])?$_GET['status-hide']:null;
1143
- if ($edcal_status != null) {
1144
- add_option("edcal_status_pref", $edcal_status, "", "yes");
1145
- update_option("edcal_status_pref", $edcal_status);
 
 
 
 
 
 
 
 
 
 
 
1146
  }
1147
 
1148
  /*
1149
- * The show time preference
 
1150
  */
1151
- $edcal_time = isset($_GET['time-hide'])?$_GET['time-hide']:null;
1152
- if ($edcal_time != null) {
1153
- add_option("edcal_time_pref", $edcal_time, "", "yes");
1154
- update_option("edcal_time_pref", $edcal_time);
1155
  }
1156
 
1157
- /*
1158
- * The edcal feedback preference
1159
- */
1160
- $edcal_feedback = isset($_GET['dofeedback'])?$_GET['dofeedback']:null;
1161
- if ($edcal_feedback != null) {
1162
- add_option("edcal_do_feedback", $edcal_feedback, "", "yes");
1163
- update_option("edcal_do_feedback", $edcal_feedback);
1164
- }
1165
-
1166
-
1167
- /*
1168
- * We finish by returning the latest data for the post in the JSON
1169
- */
1170
- ?>{
1171
- "update" : "success"
1172
- }
1173
- <?php
1174
-
1175
- die();
1176
  }
1177
 
1178
- /*
1179
- * Add the no cache headers to make sure that our responses aren't
1180
- * cached by the browser.
1181
- */
1182
- function edcal_addNoCacheHeaders() {
1183
- header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
1184
- header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
1185
- }
18
  /*
19
  Plugin Name: WordPress Editorial Calendar
20
  Description: The Editorial Calendar makes it possible to see all your posts and drag and drop them to manage your blog.
21
+ Version: 1.4
22
  Author: Colin Vernon, Justin Evans, Mary Vogt, and Zack Grossbart
23
  Author URI: http://www.zackgrossbart.com
24
  Plugin URI: http://stresslimitdesign.com/editorial-calendar-plugin
25
  */
26
 
27
+
28
+
29
+ global $edcal;
30
+ if( empty($edcal) )
31
+ $edcal = new EdCal();
32
+
33
+
 
 
 
 
34
 
35
  /*
36
  * This error code matches CONCURRENCY_ERROR from edcal.js
37
  */
38
+ define( 'EDCAL_CONCURRENCY_ERROR', 4 );
39
 
40
  /*
41
  * This error code matches PERMISSION_ERROR from edcal.js
42
  */
43
+ define( 'EDCAL_PERMISSION_ERROR', 5 );
44
 
45
  /*
46
  * This error code matches NONCE_ERROR from edcal.js
47
  */
48
+ define( 'EDCAL_NONCE_ERROR', 6 );
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ class EdCal {
51
+
52
+ protected $supports_custom_types;
53
+
54
+ function __construct() {
55
+
56
+ add_action('wp_ajax_edcal_saveoptions', array(&$this, 'edcal_saveoptions'));
57
+ add_action('wp_ajax_edcal_changedate', array(&$this, 'edcal_changedate'));
58
+ add_action('wp_ajax_edcal_savepost', array(&$this, 'edcal_savepost'));
59
+ add_action('wp_ajax_edcal_changetitle', array(&$this, 'edcal_changetitle'));
60
+ add_action('admin_menu', array(&$this, 'edcal_list_add_management_page'));
61
+ add_action('wp_ajax_edcal_posts', array(&$this, 'edcal_posts'));
62
+ add_action('wp_ajax_edcal_getpost', array(&$this, 'edcal_getpost'));
63
+ add_action('wp_ajax_edcal_deletepost', array(&$this, 'edcal_deletepost'));
64
+ add_action("init", array(&$this, 'edcal_load_language'));
65
 
66
+ /*
67
+ * This boolean variable will be used to check whether this
68
+ * installation of WordPress supports custom post types.
69
+ */
70
+ $this->supports_custom_types = function_exists('get_post_types') && function_exists('get_post_type_object');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
+ /*
73
+ * We use these variables to hold the post dates for the filter when
74
+ * we do our post query.
75
+ */
76
+ //$edcal_startDate;
77
+ //$edcal_endDate;
78
  }
79
 
80
+ function edcal_load_language() {
81
+ $plugin_dir = basename(dirname(__FILE__));
82
+ load_plugin_textdomain( 'editorial-calendar', 'wp-content/plugins/' . $plugin_dir . '/languages/', $plugin_dir . '/languages/' );
83
+ }
84
 
85
  /*
86
+ * This function adds our calendar page to the admin UI
 
 
 
 
 
87
  */
88
+ function edcal_list_add_management_page() {
89
+ if (function_exists('add_management_page') ) {
90
+ $page = add_posts_page( __('Calendar', 'editorial-calendar'), __('Calendar', 'editorial-calendar'), 'edit_posts', 'cal', array(&$this, 'edcal_list_admin'));
91
+ add_action( "admin_print_scripts-$page", array(&$this, 'edcal_scripts'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
+ if( $this->supports_custom_types ) {
94
+
95
+ /*
96
+ * We add one calendar for Posts and then we add a separate calendar for each
97
+ * custom post type. This calendar will have an URL like this:
98
+ * /wp-admin/edit.php?post_type=podcasts&page=cal_podcasts
99
+ *
100
+ * We can then use the post_type parameter to show the posts of just that custom
101
+ * type and update the labels for each post type.
102
+ */
103
+ $args = array(
104
+ 'public' => true,
105
+ '_builtin' => false
106
+ );
107
+ $output = 'names'; // names or objects
108
+ $operator = 'and'; // 'and' or 'or'
109
+ $post_types = get_post_types($args,$output,$operator);
110
 
111
+ foreach ($post_types as $post_type) {
112
+ $page = add_submenu_page('edit.php?post_type=' . $post_type, __('Calendar', 'editorial-calendar'), __('Calendar', 'editorial-calendar'), 'edit_posts', 'cal_' . $post_type, array(&$this, 'edcal_list_admin'));
113
+ add_action( "admin_print_scripts-$page", array(&$this, 'edcal_scripts'));
114
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
+ }
117
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  }
119
 
 
 
120
  /*
121
+ * This is a utility function to open a file add it to our
122
+ * output stream. We use this to embed JavaScript and CSS
123
+ * files and cut down on the number of HTTP requests.
124
  */
125
+ function edcal_echoFile($myFile) {
126
+ $fh = fopen($myFile, 'r');
127
+ $theData = fread($fh, filesize($myFile));
128
+ fclose($fh);
129
+ echo $theData;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  }
131
+
132
+ /*
133
+ * This is the function that generates our admin page. It adds the CSS files and
134
+ * generates the divs that we need for the JavaScript to work.
 
 
 
 
 
 
 
 
 
 
135
  */
136
+ function edcal_list_admin() {
137
+ include_once('edcal.php');
138
+
139
+ /*
140
+ * We want to count the number of times they load the calendar
141
+ * so we only show the feedback after they have been using it
142
+ * for a little while.
143
+ */
144
+ $edcal_count = get_option("edcal_count");
145
+ if ($edcal_count == '') {
146
+ $edcal_count = 0;
147
+ add_option("edcal_count", $edcal_count, "", "yes");
148
+ }
149
+
150
+ if (get_option("edcal_do_feedback") != "done") {
151
+ $edcal_count++;
152
+ update_option("edcal_count", $edcal_count);
153
+ }
154
+
155
+
156
+ /*
157
+ * This section of code embeds certain CSS and
158
+ * JavaScript files into the HTML. This has the
159
+ * advantage of fewer HTTP requests, but the
160
+ * disadvantage that the browser can't cache the
161
+ * results. We only do this for files that will
162
+ * be used on this page and nowhere else.
163
+ */
164
+
165
+ echo '<!-- This is the styles from time picker.css -->';
166
+ echo '<style type="text/css">';
167
+ $this->edcal_echoFile(dirname( __FILE__ ) . "/lib/timePicker.css");
168
+ echo '</style>';
169
+
170
+ echo '<!-- This is the styles from humanmsg.css -->';
171
+ echo '<style type="text/css">';
172
+ $this->edcal_echoFile(dirname( __FILE__ ) . "/lib/humanmsg.css");
173
+ echo '</style>';
174
+
175
+ echo '<!-- This is the styles from edcal.css -->';
176
+ echo '<style type="text/css">';
177
+ $this->edcal_echoFile(dirname( __FILE__ ) . "/edcal.css");
178
+ echo '</style>';
179
+
180
+ ?>
181
+
182
+ <!-- This is just a little script so we can pass the AJAX URL and some localized strings -->
183
+ <script type="text/javascript">
184
+ jQuery(document).ready(function(){
185
+ edcal.wp_nonce = '<?php echo wp_create_nonce("edit-calendar"); ?>';
186
+ <?php
187
+ if (get_option("edcal_weeks_pref") != "") {
188
+ ?>
189
+ edcal.weeksPref = <?php echo(get_option("edcal_weeks_pref")); ?>;
190
+ <?php
191
+ }
192
+ ?>
193
+
194
+ <?php
195
+ if (get_option("edcal_author_pref") != "") {
196
+ ?>
197
+ edcal.authorPref = <?php echo(get_option("edcal_author_pref")); ?>;
198
+ <?php
199
+ }
200
+ ?>
201
+
202
+ <?php
203
+ if (get_option("edcal_time_pref") != "") {
204
+ ?>
205
+ edcal.timePref = <?php echo(get_option("edcal_time_pref")); ?>;
206
+ <?php
207
+ }
208
+ ?>
209
+
210
+ <?php
211
+ if (get_option("edcal_status_pref") != "") {
212
+ ?>
213
+ edcal.statusPref = <?php echo(get_option("edcal_status_pref")); ?>;
214
+ <?php
215
+ }
216
+ ?>
217
+
218
+ <?php
219
+ if (get_option("edcal_do_feedback") != "done") {
220
+ ?>
221
+ edcal.doFeedbackPref = true;
222
+ edcal.visitCount = <?php echo(get_option("edcal_count")); ?>;
223
+ <?php
224
+ }
225
+ ?>
226
+
227
+ edcal.startOfWeek = <?php echo(get_option("start_of_week")); ?>;
228
+ edcal.timeFormat = "<?php echo(get_option("time_format")); ?>";
229
+ edcal.previewDateFormat = "MMMM d";
230
+
231
+ /*
232
+ * We want to show the day of the first day of the week to match the user's
233
+ * country code. The problem is that we can't just use the WordPress locale.
234
+ * If the locale was fr-FR so we started the week on Monday it would still
235
+ * say Sunday was the first day if we didn't have a proper language bundle
236
+ * for French. Therefore we must depend on the language bundle writers to
237
+ * specify the locale for the language they are adding.
238
+ *
239
+ */
240
+ edcal.locale = '<?php echo(__('en-US', 'editorial-calendar')) ?>';
241
+
242
+ /*
243
+ * These strings are all localized values. The WordPress localization mechanism
244
+ * doesn't really extend to JavaScript so we localize the strings in PHP and then
245
+ * pass the values to JavaScript.
246
+ */
247
+
248
+ edcal.str_by = <?php echo($this->edcal_json_encode(__('%1$s by %2$s', 'editorial-calendar'))) ?>;
249
+
250
+ edcal.str_addPostLink = <?php echo($this->edcal_json_encode(__('New Post', 'editorial-calendar'))) ?>;
251
+
252
+ edcal.str_draft = <?php echo($this->edcal_json_encode(__(' [DRAFT]', 'editorial-calendar'))) ?>;
253
+ edcal.str_pending = <?php echo($this->edcal_json_encode(__(' [PENDING]', 'editorial-calendar'))) ?>;
254
+ edcal.str_sticky = <?php echo($this->edcal_json_encode(__(' [STICKY]', 'editorial-calendar'))) ?>;
255
+ edcal.str_draft_sticky = <?php echo($this->edcal_json_encode(__(' [DRAFT, STICKY]', 'editorial-calendar'))) ?>;
256
+ edcal.str_pending_sticky = <?php echo($this->edcal_json_encode(__(' [PENDING, STICKY]', 'editorial-calendar'))) ?>;
257
+ edcal.str_edit = <?php echo($this->edcal_json_encode(__('Edit', 'editorial-calendar'))) ?>;
258
+ edcal.str_quick_edit = <?php echo($this->edcal_json_encode(__('Quick Edit', 'editorial-calendar'))) ?>;
259
+ edcal.str_del = <?php echo($this->edcal_json_encode(__('Delete', 'editorial-calendar'))) ?>;
260
+ edcal.str_view = <?php echo($this->edcal_json_encode(__('View', 'editorial-calendar'))) ?>;
261
+ edcal.str_republish = <?php echo($this->edcal_json_encode(__('Edit', 'editorial-calendar'))) ?>;
262
+ edcal.str_status = <?php echo($this->edcal_json_encode(__('Status:', 'editorial-calendar'))) ?>;
263
+ edcal.str_cancel = <?php echo($this->edcal_json_encode(__('Cancel', 'editorial-calendar'))) ?>;
264
+ edcal.str_posttitle = <?php echo($this->edcal_json_encode(__('Title', 'editorial-calendar'))) ?>;
265
+ edcal.str_postcontent = <?php echo($this->edcal_json_encode(__('Content', 'editorial-calendar'))) ?>;
266
+ edcal.str_newpost = <?php echo($this->edcal_json_encode(__('Add a new post on %s', 'editorial-calendar'))) ?>;
267
+ edcal.str_newpost_title = <?php echo($this->edcal_json_encode(sprintf(__('New %s - ', 'editorial-calendar'), $this->edcal_get_posttype_singlename()))) ?> ;
268
+ edcal.str_update = <?php echo($this->edcal_json_encode(__('Update', 'editorial-calendar'))) ?>;
269
+ edcal.str_publish = <?php echo($this->edcal_json_encode(__('Schedule', 'editorial-calendar'))) ?>;
270
+ edcal.str_review = <?php echo($this->edcal_json_encode(__('Submit for Review', 'editorial-calendar'))) ?>;
271
+ edcal.str_save = <?php echo($this->edcal_json_encode(__('Save', 'editorial-calendar'))) ?>;
272
+ edcal.str_edit_post_title = <?php echo($this->edcal_json_encode(__('Edit %1$s - %2$s', 'editorial-calendar'))) ?>;
273
+ edcal.str_scheduled = <?php echo($this->edcal_json_encode(__('Scheduled', 'editorial-calendar'))) ?>;
274
+
275
+ edcal.str_del_msg1 = <?php echo($this->edcal_json_encode(__('You are about to delete the post "', 'editorial-calendar'))) ?>;
276
+ edcal.str_del_msg2 = <?php echo($this->edcal_json_encode(__('". Press Cancel to stop, OK to delete.', 'editorial-calendar'))) ?>;
277
+
278
+ edcal.concurrency_error = <?php echo($this->edcal_json_encode(__('Looks like someone else already moved this post.', 'editorial-calendar'))) ?>;
279
+ edcal.permission_error = <?php echo($this->edcal_json_encode(__('You do not have permission to edit posts.', 'editorial-calendar'))) ?>;
280
+ edcal.checksum_error = <?php echo($this->edcal_json_encode(__('Invalid checksum for post. This is commonly a cross-site scripting error.', 'editorial-calendar'))) ?>;
281
+ edcal.general_error = <?php echo($this->edcal_json_encode(__('There was an error contacting your blog.', 'editorial-calendar'))) ?>;
282
+
283
+ edcal.str_screenoptions = <?php echo($this->edcal_json_encode(__('Screen Options', 'editorial-calendar'))) ?>;
284
+ edcal.str_optionscolors = <?php echo($this->edcal_json_encode(__('Colors', 'editorial-calendar'))) ?>;
285
+ edcal.str_optionsdraftcolor = <?php echo($this->edcal_json_encode(__('Drafts: ', 'editorial-calendar'))) ?>;
286
+ edcal.str_apply = <?php echo($this->edcal_json_encode(__('Apply', 'editorial-calendar'))) ?>;
287
+ edcal.str_show_title = <?php echo($this->edcal_json_encode(__('Show on screen', 'editorial-calendar'))) ?>;
288
+ edcal.str_opt_weeks = <?php echo($this->edcal_json_encode(__(' weeks at a time', 'editorial-calendar'))) ?>;
289
+ edcal.str_show_opts = <?php echo($this->edcal_json_encode(__('Show in Calendar Cell', 'editorial-calendar'))) ?>;
290
+ edcal.str_opt_author = <?php echo($this->edcal_json_encode(__('Author', 'editorial-calendar'))) ?>;
291
+ edcal.str_opt_status = <?php echo($this->edcal_json_encode(__('Status', 'editorial-calendar'))) ?>;
292
+ edcal.str_opt_time = <?php echo($this->edcal_json_encode(__('Time of day', 'editorial-calendar'))) ?>;
293
+ edcal.str_fatal_error = <?php echo($this->edcal_json_encode(__('An error occurred while loading the calendar: ', 'editorial-calendar'))) ?>;
294
+
295
+ edcal.str_weekserror = <?php echo($this->edcal_json_encode(__('The calendar can only show between 1 and 5 weeks at a time.', 'editorial-calendar'))) ?>;
296
+ edcal.str_weekstt = <?php echo($this->edcal_json_encode(__('Select the number of weeks for the calendar to show.', 'editorial-calendar'))) ?>;
297
+
298
+ edcal.str_feedbackmsg = <?php echo($this->edcal_json_encode(__('<div id="feedbacksection">' .
299
+ '<h2>Help us Make the Editorial Calendar Better</h2>' .
300
+ 'We are always trying to improve the Editorial Calendar and you can help. May we collect some data about your blog and browser settings to help us improve this plugin? We\'ll only do it once and your blog will show up on our <a target="_blank" href="http://www.zackgrossbart.com/edcal/mint/">Editorial Calendar Statistics page</a>.<br /><br />' .
301
+ '<button class="button-secondary" onclick="edcal.doFeedback();">Collect Anonymous Data</button> ' .
302
+ '<a href="#" id="nofeedbacklink" onclick="edcal.noFeedback(); return false;">No thank you</a></div>', 'editorial-calendar'))) ?>;
303
+
304
+ edcal.str_feedbackdone = <?php echo($this->edcal_json_encode(__('<h2>We\'re done</h2>We\'ve finished collecting data. Thank you for helping us make the calendar better.', 'editorial-calendar'))) ?>;
305
+ });
306
+ </script>
307
+
308
+ <?php
309
+ /*
310
+ * There are a few images we want to reference where we need the full path to the image
311
+ * since we don't want to make assumptions about the plugin file structure. We need to
312
+ * set those here since we need PHP to get the full path.
313
+ */
314
+ ?>
315
 
316
+ <style type="text/css">
317
+ .loadingclass > .postlink, .loadingclass:hover > .postlink, .tiploading {
318
+ background-image: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/../../../wp-admin/images/loading.gif")); ?>');
319
+ }
320
 
321
+ #loading {
322
+ background-image: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/../../../wp-admin/images/loading.gif")); ?>');
323
+ }
 
324
 
325
+ #tipclose {
326
+ background-image: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/images/tip_close.png")); ?>');
327
+ }
328
 
329
+ .day.today .daylabel {
330
+ background: url('<?php echo(path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/../../../wp-admin/images/button-grad.png")); ?>') repeat-x left top;
331
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
332
 
333
+ </style>
334
+
335
+ <?php
336
+ echo '<!-- This is the code from edcal.js -->';
337
+ echo '<script type="text/javascript">';
338
+ $this->edcal_echoFile(dirname( __FILE__ ) . "/edcal.js");
339
+ echo '</script>';
340
+
341
+ ?>
342
+
343
+ <div class="wrap">
344
+ <div class="icon32" id="icon-edit"><br/></div>
345
+ <h2 id="edcal_main_title"><?php echo($this->edcal_get_posttype_multiplename()); ?><?php echo(__(' Calendar', 'editorial-calendar')); ?></h2>
346
+
347
+ <div id="loadingcont">
348
+ <div id="loading"> </div>
349
+ </div>
350
+
351
+ <div id="topbar" class="tablenav">
352
+ <div id="topleft" class="tablenav-pages">
353
+ <h3>
354
+ <a href="#" title="<?php echo(__('Jump back', 'editorial-calendar')) ?>" class="prev page-numbers" id="prevmonth">&laquo;</a>
355
+ <span id="currentRange"></span>
356
+ <a href="#" title="<?php echo(__('Skip ahead', 'editorial-calendar')) ?>" class="next page-numbers" id="nextmonth">&raquo;</a>
357
+ </h3>
358
+ </div>
359
+
360
+ <div id="topright">
361
+ <button class="save button" title="<?php echo(__('Scroll the calendar and make the today visible', 'editorial-calendar')) ?>" id="moveToToday"><?php echo(__('Show Today', 'editorial-calendar')) ?></button>
362
+ </div>
363
+ </div>
364
+
365
+ <div id="cal_cont">
366
+ <div id="edcal_scrollable" class="edcal_scrollable vertical">
367
+ <div id="cal"></div>
368
+ </div>
369
+ </div>
370
+
371
+ <?php $this->edcal_edit_popup(); ?>
372
+
373
+ </div><?php // end .wrap ?>
374
 
375
+ <?php
 
 
 
 
 
 
376
  }
377
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378
  /*
379
+ * Generate the DOM elements for the quick edit popup from
380
+ * within the calendar.
 
 
 
381
  */
382
+ function edcal_edit_popup() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
384
  ?>
385
+ <div id="tooltip" style="display:none;">
386
+ <div id="tooltiphead">
387
+ <h3 id="tooltiptitle"><?php _e('Edit Post', 'editorial-calendar') ?></h3>
388
+ <a href="#" id="tipclose" onclick="edcal.hideForm(); return false;" title="close"> </a>
389
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
 
391
+ <div class="tooltip inline-edit-row">
392
+
393
+ <fieldset>
394
+
395
+ <label>
396
+ <span class="title"><?php _e('Title', 'editorial-calendar') ?></span>
397
+ <span class="input-text-wrap"><input type="text" class="ptitle" id="edcal-title-new-field" name="title" /></span>
398
+ </label>
399
+
400
+ <label>
401
+ <span class="title"><?php _e('Content', 'editorial-calendar') ?></span>
402
+ <span class="input-text-wrap"><textarea cols="15" rows="7" id="content" name="content"></textarea></span>
403
+ </label>
404
+
405
+
406
+ <label>
407
+ <span class="title"><?php _e('Time', 'editorial-calendar') ?></span>
408
+ <span class="input-text-wrap"><input type="text" class="ptitle" id="edcal-time" name="time" value="" size="8" readonly="true" maxlength="8" autocomplete="off" /></span>
409
+ </label>
410
+
411
+ <label>
412
+ <span class="title"><?php _e('Status', 'editorial-calendar') ?></span>
413
+ <span class="input-text-wrap">
414
+ <select name="status" id="edcal-status">
415
+ <option value="draft"><?php _e('Draft', 'editorial-calendar') ?></option>
416
+ <option value="pending"><?php _e('Pending Review', 'editorial-calendar') ?></option>
417
+ <?php if ( current_user_can('publish_posts') ) {?>
418
+ <option id="futureoption" value="future"><?php _e('Scheduled', 'editorial-calendar') ?></option>
419
+ <?php } ?>
420
+ </select>
421
+ </span>
422
+ </label>
423
+
424
+ <?php /* <label>
425
+ <span class="title"><?php _e('Author', 'editorial-calendar') ?></span>
426
+ <span id="edcal-author-p"><!-- Placeholder for the author's name, added dynamically --></span>
427
+ </label>
428
+ */ ?>
429
+ </fieldset>
430
+
431
+ <p class="submit inline-edit-save" id="edit-slug-buttons">
432
+ <a class="button-primary disabled" id="newPostScheduleButton" href="#"><?php _e('Schedule', 'editorial-calendar') ?></a>
433
+ <a href="#" onclick="edcal.hideForm(); return false;" class="button-secondary cancel"><?php _e('Cancel', 'editorial-calendar') ?></a>
434
+ </p>
435
+
436
+ <input type="hidden" id="edcal-date" name="date" value="" />
437
+ <input type="hidden" id="edcal-id" name="id" value="" />
438
+
439
+ </div><?php // end .tooltip ?>
440
+ </div><?php // end #tooltip
441
  }
 
 
 
 
 
 
 
 
 
 
 
442
 
443
  /*
444
+ * When we get a set of posts to populate the calendar we don't want
445
+ * to get all of the posts. This filter allows us to specify the dates
446
+ * we want.
447
  */
448
+ function edcal_filter_where($where = '') {
449
+ global $edcal_startDate, $edcal_endDate;
450
+ $where .= " AND post_date >= '" . $edcal_startDate . "' AND post_date < '" . $edcal_endDate . "'";
451
+ return $where;
452
+ }
453
 
454
  /*
455
+ * This function adds all of the JavaScript files we need.
456
+ *
457
  */
458
+ function edcal_scripts() {
459
+ /*
460
+ * To get proper localization for dates we need to include the correct JavaScript file for the current
461
+ * locale. We can do this based on the locale in the localized bundle to make sure the date locale matches
462
+ * the locale for the other strings.
463
+ */
464
+ wp_enqueue_script( "date", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/languages/date-".__('en-US', 'editorial-calendar').".js"), array( 'jquery' ) );
465
+ wp_enqueue_script( 'jquery' );
466
+ wp_enqueue_script( 'jquery-ui-draggable' );
467
+ wp_enqueue_script( 'jquery-ui-droppable' );
468
 
469
+ //wp_enqueue_script( "date-extras", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/date.extras.js"), array( 'jquery' ) );
470
 
471
+ wp_enqueue_script( "edcal-lib", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/edcallib.min.js"), array( 'jquery' ) );
 
 
 
 
472
 
473
+ if ($_GET['qunit']) {
474
+ wp_enqueue_script( "qunit", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/qunit.js"), array( 'jquery' ) );
475
+ wp_enqueue_script( "edcal-test", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/edcal_test.js"), array( 'jquery' ) );
476
+ }
477
+
478
+ return;
479
+
480
+ /*
481
+ * If you're using one of the specific libraries you should comment out the two lines
482
+ * above this comment.
483
+ */
484
+ wp_enqueue_script( "bgiframe", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/jquery.bgiframe.js"), array( 'jquery' ) );
485
+ wp_enqueue_script( "humanMsg", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/humanmsg.js"), array( 'jquery' ) );
486
+ wp_enqueue_script( "jquery-timepicker", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/jquery.timepicker.js"), array( 'jquery' ) );
487
+
488
+ wp_enqueue_script( "scrollable", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/tools.scrollable-1.1.2.js"), array( 'jquery' ) );
489
+ wp_enqueue_script( "mouse-wheel", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/tools.scrollable.mousewheel-1.0.1.js"), array( 'jquery' ) );
490
+
491
+ wp_enqueue_script( "json-parse2", path_join(WP_PLUGIN_URL, basename( dirname( __FILE__ ) )."/lib/json2.js"), array( 'jquery' ) );
492
  }
 
 
493
 
494
+ /*
495
+ * This is an AJAX call that gets the posts between the from date
496
+ * and the to date.
497
+ */
498
+ function edcal_posts() {
499
+ header("Content-Type: application/json");
500
+ $this->edcal_addNoCacheHeaders();
501
+ if (!$this->edcal_checknonce()) {
502
+ die();
503
+ }
504
+
505
+ global $edcal_startDate, $edcal_endDate;
506
+
507
+ $edcal_startDate = isset($_GET['from'])?$_GET['from']:null;
508
+ $edcal_endDate = isset($_GET['to'])?$_GET['to']:null;
509
+ global $post;
510
+ $args = array(
511
+ 'posts_per_page' => -1,
512
+ 'post_status' => "publish&future&draft",
513
+ 'post_parent' => null // any parent
514
+ );
515
+
516
+ /*
517
+ * If we're in the specific post type case we need to add
518
+ * the post type to our query.
519
+ */
520
+ $post_type = $_GET['post_type'];
521
+ if ($post_type) {
522
+ $args['post_type'] = $post_type;
523
+ }
524
+
525
+ add_filter('posts_where', array(&$this, 'edcal_filter_where'));
526
+ $myposts = query_posts($args);
527
+ remove_filter('posts_where', array(&$this, 'edcal_filter_where'));
528
+
529
+ ?>[
530
+ <?php
531
+ $size = sizeof($myposts);
532
+
533
+ for($i = 0; $i < $size; $i++) {
534
+ $post = $myposts[$i];
535
+ $this->edcal_postJSON($post, $i < $size - 1);
536
+ }
537
+
538
+ ?> ]
539
+ <?php
540
+
541
  die();
542
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
543
 
544
  /*
545
+ * This is for an AJAX call that returns a post with the specified ID
546
  */
547
+ function edcal_getpost() {
548
+
549
+ header("Content-Type: application/json");
550
+ $this->edcal_addNoCacheHeaders();
551
+
552
+ // If nonce fails, return
553
+ if (!$this->edcal_checknonce()) {
554
+ die();
555
+ }
556
+
557
+ $post_id = intval($_GET['postid']);
558
+
559
+ // If a proper post_id wasn't passed, return
560
+ if(!$post_id) die();
561
+
562
+ $args = array(
563
+ 'post__in' => array($post_id)
564
+ );
565
+
566
+ /*
567
+ * If we're in the specific post type case we need to add
568
+ * the post type to our query.
569
+ */
570
+ $post_type = $_GET['post_type'];
571
+ if ($post_type) {
572
+ $args['post_type'] = $post_type;
573
+ }
574
+
575
+ $post = query_posts($args);
576
+
577
+ // get_post and setup_postdata don't get along, so we're doing a mini-loop
578
+ if(have_posts()) :
579
+ while(have_posts()) : the_post();
580
+ ?>
581
+ {
582
+ "post" :
583
+ <?php
584
+ $this->edcal_postJSON($post[0], false, true);
585
+ ?>
586
+ }
587
+ <?php
588
+ endwhile;
589
+ endif;
590
+ die();
591
  }
 
592
 
593
+ /*
594
+ * Wrap php's json_encode() for a WP-specific apostrophe bug
595
+ */
596
+ function edcal_json_encode($string) {
597
+ /*
598
+ * WordPress escapes apostrophe's when they show up in post titles as &#039;
599
+ * This is the HTML ASCII code for a straight apostrophe. This works well
600
+ * with Firefox, but IE complains with a very unhelpful error message. We
601
+ * can replace them with a right curly apostrophe since that works in IE
602
+ * and Firefox. It is also a little nicer typographically.
603
+ */
604
+ return json_encode(str_replace("&#039;", "&#146;", $string));
605
  }
 
 
 
606
 
607
+ /*
608
+ * This helper functions gets the plural name of the post
609
+ * type specified by the post_type parameter.
610
+ */
611
+ function edcal_get_posttype_multiplename() {
612
 
613
+ $post_type = $_GET['post_type'];
614
+ if (!$post_type) {
615
+ return 'Posts';
616
+ }
 
 
 
 
 
 
 
617
 
618
+ $postTypeObj = get_post_type_object($post_type);
619
+ return $postTypeObj->labels->name;
620
+ }
 
621
 
622
  /*
623
+ * This helper functions gets the singular name of the post
624
+ * type specified by the post_type parameter.
625
  */
 
 
 
 
626
 
627
+ function edcal_get_posttype_singlename() {
 
 
 
628
 
629
+ $post_type = $_GET['post_type'];
630
+ if (!$post_type) {
631
+ return 'Post';
632
+ }
633
 
634
+ $postTypeObj = get_post_type_object($post_type);
635
+ return $postTypeObj->labels->singular_name;
 
 
 
636
  }
 
 
 
 
 
 
 
 
637
 
638
+ /*
639
+ * This function sets up the post data and prints out the values we
640
+ * care about in a JSON data structure. This prints out just the
641
+ * value part. If $fullPost is set to true, post_content is also returned.
642
+ */
643
+ function edcal_postJSON($post, $addComma = true, $fullPost = false) {
644
+ $timeFormat = get_option("time_format");
645
+ if ($timeFormat == "g:i a") {
646
+ $timeFormat = "ga";
647
+ } else if ($timeFormat == "g:i A") {
648
+ $timeFormat = "gA";
649
+ } else if ($timeFormat == "H:i") {
650
+ $timeFormat = "H";
651
+ }
652
+
653
+ setup_postdata($post);
654
+
655
+ if (get_post_status() == 'auto-draft') {
656
+ /*
657
+ * WordPress 3 added a new post status of auto-draft so
658
+ * we want to hide them from the calendar
659
+ */
660
+ return;
661
+ }
662
+
663
+ /*
664
+ * We want to return the type of each post as part of the
665
+ * JSON data about that post. Right now this will always
666
+ * match the post_type parameter for the calendar, but in
667
+ * the future we might support a mixed post type calendar
668
+ * and this extra data will become useful. Right now we
669
+ * are using this data for the title on the quick edit form.
 
 
 
 
 
670
  */
671
+ if( $this->supports_custom_types ) {
672
+ $postTypeObj = get_post_type_object(get_post_type( $post ));
673
+ $postTypeTitle = $postTypeObj->labels->singular_name;
674
+ } else {
675
+ $postTypeTitle = 'post';
676
+ }
677
  ?>
678
+ {
679
+ "date" : "<?php the_time('d') ?><?php the_time('m') ?><?php the_time('Y') ?>",
680
+ "time" : "<?php the_time() ?>",
681
+ "formattedtime" : "<?php $this->edcal_json_encode(the_time($timeFormat)); ?>",
682
+ "sticky" : "<?php echo(is_sticky($post->ID)); ?>",
683
+ "url" : "<?php $this->edcal_json_encode(the_permalink()); ?>",
684
+ "status" : "<?php echo(get_post_status()); ?>",
685
+ "title" : <?php echo($this->edcal_json_encode(get_the_title())); ?>,
686
+ "author" : <?php echo($this->edcal_json_encode(get_the_author())); ?>,
687
+ "type" : "<?php echo(get_post_type( $post )); ?>",
688
+ "typeTitle" : "<?php echo($postTypeTitle); ?>",
689
+
690
+ <?php if ( current_user_can('edit_post', $post->ID) ) {?>
691
+ "editlink" : "<?php echo(get_edit_post_link($id)); ?>",
692
+ <?php } ?>
693
+
694
+ <?php if ( current_user_can('delete_post', $post->ID) ) {?>
695
+ "dellink" : "javascript:edcal.deletePost(<?php echo $post->ID ?>)",
696
+ <?php } ?>
697
+
698
+ "permalink" : "<?php echo(get_permalink($id)); ?>",
699
+ "id" : "<?php the_ID(); ?>"
700
+
701
+ <?php if($fullPost) : ?>
702
+ , "content" : <?php echo $this->edcal_json_encode($post->post_content) ?>
703
+
704
+ <?php endif; ?>
705
+ }
706
  <?php
707
+ if ($addComma) {
708
+ ?>,<?php
709
+ }
710
  }
711
+
712
+ /*
713
+ * This is a helper AJAX function to delete a post. It gets called
714
+ * when a user clicks the delete button, and allows the user to
715
+ * retain their position within the calendar without a page refresh.
716
+ * It is not called unless the user has permission to delete the post
717
+ */
718
+ function edcal_deletepost() {
719
+ if (!$this->edcal_checknonce()) {
720
+ die();
721
+ }
722
+
723
+ header("Content-Type: application/json");
724
+ $this->edcal_addNoCacheHeaders();
725
+
726
+ $edcal_postid = isset($_GET['postid'])?$_GET['postid']:null;
727
+ $post = get_post($edcal_postid, ARRAY_A);
728
+ $title = $post['post_title'];
729
+ $date = date('dmY', strtotime($post['post_date'])); // [TODO] : is there a better way to generate the date string ... ??
730
+
731
+ $force = !EMPTY_TRASH_DAYS; // wordpress 2.9 thing. deleted post hangs around (ie in a recycle bin) after deleted for this # of days
732
+ if ( $post->post_type == 'attachment' ) {
733
+ $force = ( $force || !MEDIA_TRASH );
734
+ if ( ! wp_delete_attachment($edcal_postid, $force) )
735
+ wp_die( __('Error in deleting...') );
736
+ } else {
737
+ if ( !wp_delete_post($edcal_postid, $force) )
738
+ wp_die( __('Error in deleting...') );
739
+ }
740
+
741
+ // return the following info so that jQuery can then remove post from edcal display :
742
+ ?>
743
+ {
744
+ "post" :
745
+ {
746
+ "date" : "<?php echo $date ?>",
747
+ "title" : "<?php echo $title ?>",
748
+ "id" : "<?php echo $edcal_postid ?>"
749
+ }
750
+ }
751
+ <?php
752
+
753
+ die();
754
  }
 
 
755
 
756
+ /*
757
+ * This is a helper AJAX function to change the title of a post. It
758
+ * gets called from the save button in the tooltip when you change a
759
+ * post title in a calendar.
760
+ */
761
+ function edcal_changetitle() {
762
+ if (!$this->edcal_checknonce()) {
763
+ die();
764
+ }
765
 
766
+ header("Content-Type: application/json");
767
+ $this->edcal_addNoCacheHeaders();
768
+
769
+ $edcal_postid = isset($_GET['postid'])?$_GET['postid']:null;
770
+ $edcal_newTitle = isset($_GET['title'])?$_GET['title']:null;
771
+
772
+ $post = get_post($edcal_postid, ARRAY_A);
773
+ setup_postdata($post);
774
+
775
+ $post['post_title'] = $edcal_newTitle;
776
+
777
  /*
778
+ * Now we finally update the post into the database
 
 
 
779
  */
780
+ wp_update_post( $post );
 
 
 
781
 
782
+ /*
783
+ * We finish by returning the latest data for the post in the JSON
784
+ */
785
  global $post;
786
  $args = array(
787
  'posts_id' => $edcal_postid,
788
  );
789
 
790
  $post = get_post($edcal_postid);
791
+
792
+ ?>{
793
  "post" :
794
  <?php
 
 
795
 
796
+ $this->edcal_postJSON($post);
797
+
798
+ ?>
799
+ }
800
  <?php
801
+
802
+
803
  die();
804
  }
805
 
 
 
 
806
  /*
807
+ * This is a helper function to create a new blank draft
808
+ * post on a specified date.
 
 
 
 
809
  */
810
+ function edcal_newdraft() {
811
+ if (!$this->edcal_checknonce()) {
812
+ die();
813
+ }
814
+
815
+ header("Content-Type: application/json");
816
+ $this->edcal_addNoCacheHeaders();
817
 
818
+ $edcal_date = isset($_POST["date"])?$_POST["date"]:null;
 
 
 
819
 
820
+ $my_post = array();
821
+ $my_post['post_title'] = isset($_POST["title"])?$_POST["title"]:null;
822
+ $my_post['post_content'] = isset($_POST["content"])?$_POST["content"]:null;
823
+ $my_post['post_status'] = 'draft';
824
+
825
+ $my_post['post_date'] = $edcal_date;
826
+ $my_post['post_date_gmt'] = get_gmt_from_date($edcal_date);
827
+ $my_post['post_modified'] = $edcal_date;
828
+ $my_post['post_modified_gmt'] = get_gmt_from_date($edcal_date);
829
+
830
+ // Insert the post into the database
831
+ $my_post_id = wp_insert_post( $my_post );
832
+
833
+ /*
834
+ * We finish by returning the latest data for the post in the JSON
835
+ */
836
+ global $post;
837
+ $post = get_post($my_post_id);
838
+
839
+ ?>{
840
  "post" :
841
  <?php
 
 
842
 
843
+ $this->edcal_postJSON($post, false);
844
+
845
+ ?>
846
+ }
847
  <?php
848
+
849
  die();
850
  }
851
 
852
  /*
853
+ * This is a helper function to create a new draft post on a specified date
854
+ * or update an existing post
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
855
  */
856
+ function edcal_savepost() {
857
+
858
+ if (!$this->edcal_checknonce()) {
859
+ die();
860
+ }
861
 
862
+ header("Content-Type: application/json");
863
+ $this->edcal_addNoCacheHeaders();
864
+
865
+ $edcal_date = isset($_POST["date"])?$_POST["date"]:null;
866
+
867
+ $my_post = array();
868
+
869
+ // If the post id is not specified, we're creating a new post
870
+ if($_POST['id']) {
871
+ $my_post['ID'] = intval($_POST['id']);
872
+ } else {
873
+ $my_post['post_status'] = 'draft'; // if new post, set the status to draft
874
+ }
875
+
876
+ $my_post['post_title'] = isset($_POST["title"])?$_POST["title"]:null;
877
+ $my_post['post_content'] = isset($_POST["content"])?$_POST["content"]:null;
878
+
879
+ $my_post['post_date'] = $edcal_date;
880
+ $my_post['post_date_gmt'] = get_gmt_from_date($edcal_date);
881
+ $my_post['post_modified'] = $edcal_date;
882
+ $my_post['post_modified_gmt'] = get_gmt_from_date($edcal_date);
883
+
884
+ /*
885
+ * When we create a new post we need to specify the post type
886
+ * passed in from the JavaScript.
887
  */
888
+ $post_type = isset($_POST["post_type"])?$_POST["post_type"]:null;
889
+ if ($post_type) {
890
+ $my_post['post_type'] = $post_type;
891
+ }
892
 
893
+ if($_POST['status']) {
894
+ wp_transition_post_status($_POST['status'], $my_post['post_status'], $my_post);
895
+ $my_post['post_status'] = $_POST['status'];
 
896
  }
897
 
898
+
899
+ // Insert the post into the database
900
+ if($my_post['ID']) {
901
+ $my_post_id = wp_update_post( $my_post );
902
+ } else {
903
+ $my_post_id = wp_insert_post( $my_post );
904
+ }
905
+
906
+ // TODO: throw error if update/insert or getsinglepost fails
907
+ /*
908
+ * We finish by returning the latest data for the post in the JSON
909
+ */
910
+ $args = array(
911
+ 'p' => $my_post_id
912
+ );
913
+
914
+ if ($post_type) {
915
+ $args['post_type'] = $post_type;
916
+ }
917
+ $post = query_posts($args);
918
+
919
+ // get_post and setup_postdata don't get along, so we're doing a mini-loop
920
+ if(have_posts()) :
921
+ while(have_posts()) : the_post();
922
+ ?>
923
+ {
924
+ "post" :
925
+ <?php
926
+ $this->edcal_postJSON($post[0], false);
927
+ ?>
928
+ }
929
+ <?php
930
+ endwhile;
931
+ endif;
932
+ die();
933
  }
934
 
935
  /*
936
+ * This function checks the nonce for the URL. It returns
937
+ * true if the nonce checks out and outputs a JSON error
938
+ * and returns false otherwise.
939
  */
940
+ function edcal_checknonce() {
941
+ header("Content-Type: application/json");
942
+ $this->edcal_addNoCacheHeaders();
943
+
944
+ if (!wp_verify_nonce($_REQUEST['_wpnonce'], 'edit-calendar')) {
945
+ /*
946
+ * This is just a sanity check to make sure
947
+ * this isn't a CSRF attack. Most of the time this
948
+ * will never be run because you can't see the calendar unless
949
+ * you are at least an editor
950
+ */
951
+ ?>
952
+ {
953
+ "error": <?php echo(EDCAL_NONCE_ERROR); ?>
954
+ }
955
+ <?php
956
+ return false;
957
+ }
958
+ return true;
959
+ }
960
 
961
  /*
962
+ * This function changes the date on a post. It does optimistic
963
+ * concurrency checking by comparing the original post date from
964
+ * the browser with the one from the database. If they don't match
965
+ * then it returns an error code and the updated post data.
966
+ *
967
+ * If the call is successful then it returns the updated post data.
968
  */
969
+ function edcal_changedate() {
970
+ if (!$this->edcal_checknonce()) {
971
+ die();
972
+ }
973
+ header("Content-Type: application/json");
974
+ $this->edcal_addNoCacheHeaders();
975
+
976
+ $edcal_postid = isset($_GET['postid'])?$_GET['postid']:null;
977
+ $edcal_newDate = isset($_GET['newdate'])?$_GET['newdate']:null;
978
+ $edcal_oldDate = isset($_GET['olddate'])?$_GET['olddate']:null;
979
+ $edcal_postStatus = isset($_GET['postStatus'])?$_GET['postStatus']:null;
980
+
981
+ if (!current_user_can('edit_post', $edcal_postid)) {
982
+ /*
983
+ * This is just a sanity check to make sure that the current
984
+ * user has permission to edit posts. Most of the time this
985
+ * will never be run because you can't see the calendar unless
986
+ * you are at least an editor
987
+ */
988
+ ?>
989
+ {
990
+ "error": <?php echo(EDCAL_PERMISSION_ERROR); ?>,
991
+ <?php
992
+
993
+ global $post;
994
+ $args = array(
995
+ 'posts_id' => $edcal_postid,
996
+ );
997
+
998
+ $post = get_post($edcal_postid);
999
+ ?>
1000
+ "post" :
1001
+ <?php
1002
+ $this->edcal_postJSON($post, false, true);
1003
+ ?> }
1004
+
1005
+ <?php
1006
+ die();
1007
+ }
1008
+
1009
+ $post = get_post($edcal_postid, ARRAY_A);
1010
+ setup_postdata($post);
1011
+
1012
+ /*
1013
+ * We are doing optimistic concurrency checking on the dates. If
1014
+ * the user tries to move a post we want to make sure nobody else
1015
+ * has moved that post since the page was last updated. If the
1016
+ * old date in the database doesn't match the old date from the
1017
+ * browser then we return an error to the browser along with the
1018
+ * updated post data.
1019
+ */
1020
+ if (date('Y-m-d', strtotime($post['post_date'])) != date('Y-m-d', strtotime($edcal_oldDate))) {
1021
+ ?> {
1022
+ "error": <?php echo(EDCAL_CONCURRENCY_ERROR); ?>,
1023
+ <?php
1024
+
1025
+ global $post;
1026
+ $args = array(
1027
+ 'posts_id' => $edcal_postid,
1028
+ );
1029
+
1030
+ $post = get_post($edcal_postid);
1031
+ ?>
1032
+ "post" :
1033
+ <?php
1034
+ $this->edcal_postJSON($post, false, true);
1035
+ ?> }
1036
+
1037
+ <?php
1038
+ die();
1039
+ }
1040
+
1041
+ /*
1042
+ * Posts in WordPress have more than one date. There is the GMT date,
1043
+ * the date in the local time zone, the modified date in GMT and the
1044
+ * modified date in the local time zone. We update all of them.
1045
+ */
1046
+ $post['post_date_gmt'] = $post['post_date'];
1047
+
1048
+ /*
1049
+ * When a user creates a draft and never sets a date or publishes it
1050
+ * then the GMT date will have a timestamp of 00:00:00 to indicate
1051
+ * that the date hasn't been set. In that case we need to specify
1052
+ * an edit date or the wp_update_post function will strip our new
1053
+ * date out and leave the post as publish immediately.
1054
+ */
1055
+ $needsEditDate = strpos($post['post_date_gmt'], "0000-00-00 00:00:00") === 0;
1056
+
1057
+ $updated_post = array();
1058
+ $updated_post['ID'] = $edcal_postid;
1059
+ $updated_post['post_date'] = $edcal_newDate . substr($post['post_date'], strlen($edcal_newDate));
1060
+ if ($needsEditDate != -1) {
1061
+ $updated_post['edit_date'] = $edcal_newDate . substr($post['post_date'], strlen($edcal_newDate));
1062
+ }
1063
+
1064
+ /*
1065
+ * We need to make sure to use the GMT formatting for the date.
1066
+ */
1067
+ $updated_post['post_date_gmt'] = get_gmt_from_date($updated_post['post_date']);
1068
+ $updated_post['post_modified'] = $edcal_newDate . substr($post['post_modified'], strlen($edcal_newDate));
1069
+ $updated_post['post_modified_gmt'] = get_gmt_from_date($updated_post['post_date']);
1070
+
1071
+ if ($edcal_postStatus != $post['post_status']) {
1072
+ /*
1073
+ * We only want to update the post status if it has changed.
1074
+ * If the post status has changed that takes a few more steps
1075
+ */
1076
+ wp_transition_post_status($edcal_postStatus, $post['post_status'], $post);
1077
+ $updated_post['post_status'] = $edcal_postStatus;
1078
+
1079
+ // Update counts for the post's terms.
1080
+ foreach ( (array) get_object_taxonomies('post') as $taxonomy ) {
1081
+ $tt_ids = wp_get_object_terms($post_id, $taxonomy, 'fields=tt_ids');
1082
+ wp_update_term_count($tt_ids, $taxonomy);
1083
+ }
1084
+
1085
+ do_action('edit_post', $edcal_postid, $post);
1086
+ do_action('save_post', $edcal_postid, $post);
1087
+ do_action('wp_insert_post', $edcal_postid, $post);
1088
+ }
1089
+
1090
+ /*
1091
+ * Now we finally update the post into the database
1092
+ */
1093
+ wp_update_post( $updated_post );
1094
+
1095
+ /*
1096
+ * We finish by returning the latest data for the post in the JSON
1097
+ */
1098
+ global $post;
1099
+ $args = array(
1100
+ 'posts_id' => $edcal_postid,
1101
+ );
1102
+
1103
+ $post = get_post($edcal_postid);
1104
+ ?>{
1105
+ "post" :
1106
+
1107
+ <?php
1108
+ $this->edcal_postJSON($post, false, true);
1109
+ ?>}
1110
+ <?php
1111
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1112
  die();
1113
  }
 
 
 
1114
 
1115
  /*
1116
+ * This function saves the preferences
1117
  */
1118
+ function edcal_saveoptions() {
1119
+ if (!$this->edcal_checknonce()) {
1120
+ die();
1121
+ }
 
1122
 
1123
+ header("Content-Type: application/json");
1124
+ $this->edcal_addNoCacheHeaders();
1125
+
1126
+ /*
1127
+ * The number of weeks preference
1128
+ */
1129
+ $edcal_weeks = isset($_GET['weeks'])?$_GET['weeks']:null;
1130
+ if ($edcal_weeks != null) {
1131
+ add_option("edcal_weeks_pref", $edcal_weeks, "", "yes");
1132
+ update_option("edcal_weeks_pref", $edcal_weeks);
1133
+ }
1134
+
1135
+ /*
1136
+ * The show author preference
1137
+ */
1138
+ $edcal_author = isset($_GET['author-hide'])?$_GET['author-hide']:null;
1139
+ if ($edcal_author != null) {
1140
+ add_option("edcal_author_pref", $edcal_author, "", "yes");
1141
+ update_option("edcal_author_pref", $edcal_author);
1142
+ }
1143
+
1144
+ /*
1145
+ * The show status preference
1146
+ */
1147
+ $edcal_status = isset($_GET['status-hide'])?$_GET['status-hide']:null;
1148
+ if ($edcal_status != null) {
1149
+ add_option("edcal_status_pref", $edcal_status, "", "yes");
1150
+ update_option("edcal_status_pref", $edcal_status);
1151
+ }
1152
+
1153
+ /*
1154
+ * The show time preference
1155
+ */
1156
+ $edcal_time = isset($_GET['time-hide'])?$_GET['time-hide']:null;
1157
+ if ($edcal_time != null) {
1158
+ add_option("edcal_time_pref", $edcal_time, "", "yes");
1159
+ update_option("edcal_time_pref", $edcal_time);
1160
+ }
1161
 
1162
+ /*
1163
+ * The edcal feedback preference
1164
+ */
1165
+ $edcal_feedback = isset($_GET['dofeedback'])?$_GET['dofeedback']:null;
1166
+ if ($edcal_feedback != null) {
1167
+ add_option("edcal_do_feedback", $edcal_feedback, "", "yes");
1168
+ update_option("edcal_do_feedback", $edcal_feedback);
1169
+ }
1170
+
1171
+ /*
1172
+ * We finish by returning the latest data for the post in the JSON
1173
+ */
1174
+ ?>{
1175
+ "update" : "success"
1176
+ }
1177
+ <?php
1178
+
1179
+ die();
1180
  }
1181
 
1182
  /*
1183
+ * Add the no cache headers to make sure that our responses aren't
1184
+ * cached by the browser.
1185
  */
1186
+ function edcal_addNoCacheHeaders() {
1187
+ header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
1188
+ header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
 
1189
  }
1190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1191
  }
1192
 
 
 
 
 
 
 
 
 
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: cvernon, justinstresslimit, MaryVogt, zgrossbart
3
  Tags: posts, post, calendar, AJAX, admin, administration
4
  Requires at least: 2.8.5
5
- Tested up to: 3.1
6
- Stable tag: 1.3.4
7
 
8
  The Editorial Calendar makes it possible to see all your posts and drag and drop them to manage your blog.
9
 
@@ -13,8 +13,7 @@ Did you remember to write a post for next Tuesday? What about the Tuesday after
13
 
14
  <h4>Watch the video</h4>
15
 
16
- Get a quick overview of what the calendar can do for you with the <a href="http://vimeo.com/13196017" target="_blank">The WordPress Editorial Calendar Screen Cast</a>.
17
-
18
 
19
  <h4>Try it out</h4>
20
  Try the calendar before you install it. Check out the demo installation at <a href="http://www.zackgrossbart.com/extras/sandbox/wp-admin/edit.php?page=cal">Zack's WordPress Sandbox</a>.
@@ -152,6 +151,12 @@ Moving published posts can cause problems with some RSS feeds and is generally n
152
 
153
  == Changelog ==
154
 
 
 
 
 
 
 
155
  = 1.3.4 =
156
  * The calendar now shows authors properly when they have double quotes in their names
157
 
@@ -260,6 +265,3 @@ so we don't overwrite the post without the full post content.
260
 
261
  = 0.1 =
262
  * This version is just for beta testers
263
-
264
-
265
- `<?php code(); // goes in backticks ?>`
2
  Contributors: cvernon, justinstresslimit, MaryVogt, zgrossbart
3
  Tags: posts, post, calendar, AJAX, admin, administration
4
  Requires at least: 2.8.5
5
+ Tested up to: 3.2
6
+ Stable tag: 1.4
7
 
8
  The Editorial Calendar makes it possible to see all your posts and drag and drop them to manage your blog.
9
 
13
 
14
  <h4>Watch the video</h4>
15
 
16
+ [vimeo http://vimeo.com/13196017]
 
17
 
18
  <h4>Try it out</h4>
19
  Try the calendar before you install it. Check out the demo installation at <a href="http://www.zackgrossbart.com/extras/sandbox/wp-admin/edit.php?page=cal">Zack's WordPress Sandbox</a>.
151
 
152
  == Changelog ==
153
 
154
+ = 1.4 =
155
+
156
+ * We now have a new look and feel for the quick edit dialog and a few other elements to match WordPress 3.2.
157
+
158
+ * We've refactored the Editorial Calendar into a PHP class for easier maintainability and better scoping.
159
+
160
  = 1.3.4 =
161
  * The calendar now shows authors properly when they have double quotes in their names
162
 
265
 
266
  = 0.1 =
267
  * This version is just for beta testers