1. <?php
  2.  
  3. class CP_Calendar_Event_Handler extends CP_Custom_Content_Handler_Base
  4. {
  5.     /**
  6.      * Registers the Calendar Event PostType
  7.      *
  8.      */
  9.     public function on_setup_custom_content()
  10.     {
  11.         CP_Custom_Content_Core::GetInstance()->register_custom_content_type($this);
  12.         add_filter('posts_where_request', array($this, 'filter_events_where'), 10, 1);
  13.         add_filter('posts_join_request', array($this, 'filter_events_join'), 10, 1);
  14.  
  15.         $this->metadata = array(
  16.             'misc' => array(
  17.                 new URL_Metadata('clickthru_url', 'Click-Thru URL'),
  18.                 new URL_Metadata('ticket_purchase_url', 'Ticket Purchase URL'),
  19.                 new Checkbox_Metadata('livenation_link', 'LiveNation Ticket Link'),
  20.                 new Text_Metadata('ticket_price', 'Ticket Price'),
  21.                 new Checkbox_Metadata('sold_out', 'Sold Out'),
  22.             )
  23.         );
  24.     }
  25.  
  26.     public function get_content_type()
  27.     {
  28.         return 'calendar_event';
  29.     }
  30.     public function get_type_label()
  31.     {
  32.         return 'Event';
  33.     }
  34.     public function get_type_label_plural()
  35.     {
  36.         return 'Events';
  37.     }
  38.     public function get_type_publicly_queryable() {return true; }
  39.     public function get_type_icon_url()
  40.     {
  41.         return CP_BASE_URL.'/child-plugins/cp-calendar-events/menu-events.png';
  42.     }
  43.     public function get_type_permastructure()
  44.     {
  45.         return array('identifier' => 'events', 'structure' => '%identifier%/%year%/%monthnum%/%day%/%postname%/');
  46.     }
  47.  
  48.     /**
  49.      * Returns an array of features the content type supports
  50.      *
  51.      * @return array
  52.      */
  53.     public function get_type_supports()
  54.     {
  55.         //leaving out thumbnail until we can migrate featured images to use that instead.
  56.         return array('title', 'editor', 'excerpt', 'comments');
  57.     }
  58.  
  59.     /**
  60.      * First fired on 'request' filter
  61.      * Sets order to 'asc' by default
  62.      * Sets month and year to current if not set and not a search
  63.      *
  64.      * @param array $query_vars
  65.      * @return array
  66.      */
  67.     public function filter_request_query_vars($query_vars)
  68.     {
  69.         if(!is_admin() && (isset($query_vars['taxonomy']) && in_array( $query_vars['taxonomy'], get_object_taxonomies($this->get_content_type())) && $query_vars['post_type'] == $this->get_content_type()))
  70.         {
  71.             $query_vars['order'] = 'asc';
  72.         }
  73.         if(!is_admin() && isset($query_vars['post_type']) && $this->get_content_type() == $query_vars['post_type'])
  74.         {
  75.             if(!isset($query_vars['order']))
  76.             {
  77.                 $query_vars['order'] = 'asc';
  78.             }
  79.             if(!isset($query_vars['monthnum']) && empty($query_vars['s']))
  80.             {
  81.                 //set month to current
  82.                 $query_vars['year'] = date('Y');
  83.                 $query_vars['monthnum'] = date('m');
  84.             }
  85.         }
  86.         return $query_vars;
  87.     }
  88.  
  89.     /**
  90.      * Replaces the submitdiv meta box with a custom one for events
  91.      * Adds metabox for remaining event data
  92.      *
  93.      * @param object $post
  94.      */
  95.     public function add_meta_boxes($post)
  96.     {
  97.         global $wp_meta_boxes;
  98.  
  99.         //replace the default submit metabox with the special one for events
  100.         $wp_meta_boxes[$this->get_content_type()]['side']['core']['submitdiv'] = array('id' => 'submitdiv', 'title' => 'Publish', 'callback' => array($this, 'submit_meta_box'), 'args' => null);
  101.         add_meta_box('eventmeta', "Misc Event Meta", array($this, 'misc_event_metabox'), $this->get_content_type(), 'normal', 'core');
  102.     }
  103.  
  104.     /**
  105.      * Meta boxes for ticket price, ticket purchase url, clickthru url, etc
  106.      *
  107.      * @param unknown_type $post
  108.      */
  109.     public function misc_event_metabox($post)
  110.     {
  111.         CP_Custom_Metadata_Base::display_all($this->metadata['misc'], $post->ID);
  112.     }
  113.  
  114.     /**
  115.      * Save event for the data from the Misc Event Metabox
  116.      *
  117.      * @param int $post_id
  118.      */
  119.     public function on_save_event($post_id, $post)
  120.     {
  121.         if(!((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || (defined('DOING_CRON') && DOING_CRON)))
  122.         {
  123.             if ( wp_is_post_revision($post_id) || wp_is_post_autosave($post_id))
  124.             {
  125.                 return $post_id;
  126.             }
  127.             CP_Custom_Metadata_Base::save_all($this->metadata['misc'], $post_id);
  128.         }
  129.     }
  130.  
  131.     /**
  132.      * Runs on 'wp_insert_post_data' filter to change the status from 'future' to 'publish'
  133.      * and validates and saves the end date in meta.
  134.      *
  135.      * @param array $data
  136.      * @param array $posted_data
  137.      * @return array
  138.      */
  139.     public function filter_wp_insert_post_data($data, $posted_data)
  140.     {
  141.         if($data['post_type'] == $this->get_content_type())
  142.         {
  143.             if($posted_data['post_status'] == 'publish' || $data['post_status'] == 'future')
  144.             {
  145.                 $data['post_status'] = 'publish';
  146.             }
  147.  
  148.             if(isset($posted_data['update_event_nonce']) && wp_verify_nonce($posted_data['update_event_nonce'], 'update_event'))
  149.             {
  150.  
  151.                 //update the dates
  152.                 $defaults = array(
  153.                     'start_aa' => '',
  154.                     'start_mm' => '',
  155.                     'start_jj' => '',
  156.                     'start_hh' => '',
  157.                     'start_mn' => '',
  158.                     'start_ss' => '',
  159.                     'start_mr' => '',
  160.                     'end_aa' => '',
  161.                     'end_mm' => '',
  162.                     'end_jj' => '',
  163.                     'end_hh' => '',
  164.                     'end_mn' => '',
  165.                     'end_ss' => '',
  166.                     'end_mr' => '',
  167.                 );
  168.  
  169.                 $posted_data = array_merge($defaults, $posted_data);
  170.  
  171.                 $is_allday = isset($posted_data['event_is_allday']);
  172.  
  173.                 $start_aa = $posted_data['start_aa'];
  174.                 $start_mm = $posted_data['start_mm'];
  175.                 $start_jj = $posted_data['start_jj'];
  176.                 $start_hh = $posted_data['start_hh'];
  177.                 $start_mn = $posted_data['start_mn'];
  178.                 $start_ss = $posted_data['start_ss'];
  179.                 $start_mr = $posted_data['start_mr'];
  180.                 $start_mr = ($start_mr == 'AM') ? 'AM' : 'PM';
  181.                 $start_hh = (($start_mr == 'PM' && $start_hh != 12) || ($start_mr != 'PM' && $start_hh = 12)) ? $start_hh + 12 : $start_hh;
  182.                 $start_aa = ($start_aa <= 0 ) ? date('Y') : $start_aa;
  183.                 $start_mm = ($start_mm <= 0 ) ? date('n') : $start_mm;
  184.                 $start_jj = ($start_jj > 31 ) ? 31 : $start_jj;
  185.                 $start_jj = ($start_jj <= 0 ) ? date('j') : $start_jj;
  186.                 if($is_allday)
  187.                 {
  188.                     $start_mn = $start_hh = '00';
  189.                 }
  190.                 else
  191.                 {
  192.                     $start_hh = ($start_hh > 23 ) ? $start_hh -24 : $start_hh;
  193.                     $start_mn = ($start_mn > 59 ) ? $start_mn -60 : $start_mn;
  194.                 }
  195.                 $data['post_date'] = sprintf( "%04d-%02d-%02d %02d:%02d:00", $start_aa, $start_mm, $start_jj, $start_hh, $start_mn);
  196.  
  197.                 $end_aa = $posted_data['end_aa'];
  198.                 $end_mm = $posted_data['end_mm'];
  199.                 $end_jj = $posted_data['end_jj'];
  200.                 $end_hh = $posted_data['end_hh'];
  201.                 $end_mn = $posted_data['end_mn'];
  202.                 $end_ss = $posted_data['end_ss'];
  203.                 $end_mr = $posted_data['end_mr'];
  204.                 $end_mr = ($end_mr == 'AM') ? 'AM' : 'PM';
  205.                 $end_hh = (($end_mr == 'PM' && $end_hh != 12) || ($end_mr != 'PM' && $end_hh = 12)) ? $end_hh + 12 : $end_hh;
  206.                 $end_aa = ($end_aa <= 0 ) ? date('Y') : $end_aa;
  207.                 $end_mm = ($end_mm <= 0 ) ? date('n') : $end_mm;
  208.                 $end_jj = ($end_jj > 31 ) ? 31 : $end_jj;
  209.                 $end_jj = ($end_jj <= 0 ) ? date('j') : $end_jj;
  210.                 if($is_allday)
  211.                 {
  212.                     $end_mn = $end_hh = '00';
  213.                 }
  214.                 else
  215.                 {
  216.                     $end_hh = ($end_hh > 23 ) ? $end_hh -24 : $end_hh;
  217.                     $end_mn = ($end_mn > 59 ) ? $end_mn -60 : $end_mn;
  218.                 }
  219.                 $end_datetime = sprintf( "%04d-%02d-%02d %02d:%02d:00", $end_aa, $end_mm, $end_jj, $end_hh, $end_mn);
  220.                 update_post_meta($posted_data['post_ID'], 'event_is_allday', $is_allday ? '1' : '0');
  221.                 update_post_meta($posted_data['post_ID'], 'event_end_datetime', $end_datetime);
  222.             }
  223.         }
  224.         return $data;
  225.     }
  226.  
  227.     /**
  228.      * Submit box for Events, replaces default submit box to add end date and all day option
  229.      *
  230.      * @param object $post
  231.      */
  232.     public function submit_meta_box($post)
  233.     {
  234.         global $action, $wp_locale;
  235.         $post_type_obj = get_post_type_object($post->post_type);
  236.         $can_publish = current_user_can($post_type_obj->cap->publish_posts);
  237.         ?>
  238.         <div class="submitbox" id="submitpost">
  239.             <?php wp_nonce_field('update_event', 'update_event_nonce');?>
  240.             <div id="minor-publishing">
  241.                 <?php // Hidden submit button early on so that the browser chooses the right button when form is submitted with Return key ?>
  242.                 <div style="display:none;">
  243.                     <input type="submit" name="save" value="<?php esc_attr_e('Save'); ?>" />
  244.                 </div>
  245.                 <div id="minor-publishing-actions">
  246.                     <div id="save-action">
  247.                         <?php if ( 'publish' != $post->post_status && 'future' != $post->post_status && 'pending' != $post->post_status ) : ?>
  248.                             <input <?php if ( 'private' == $post->post_status ) { ?>style="display:none"<?php } ?> type="submit" name="save" id="save-post" value="<?php esc_attr_e('Save Draft'); ?>" tabindex="4" class="button button-highlighted" />
  249.                         <?php elseif ( 'pending' == $post->post_status && $can_publish ) : ?>
  250.                             <input type="submit" name="save" id="save-post" value="<?php esc_attr_e('Save as Pending'); ?>" tabindex="4" class="button button-highlighted" />
  251.                         <?php endif; ?>
  252.                     </div>
  253.                     <div id="preview-action">
  254.                         <?php
  255.                         if ( 'publish' == $post->post_status ) {
  256.                             $preview_link = esc_url(get_permalink($post->ID));
  257.                             $preview_button = __('Preview Changes');
  258.                         } else {
  259.                             $preview_link = esc_url(apply_filters('preview_post_link', add_query_arg('preview', 'true', get_permalink($post->ID))));
  260.                             $preview_button = __('Preview');
  261.                         }
  262.                         ?>
  263.                         <a class="preview button" href="<?php echo $preview_link; ?>" target="wp-preview" id="post-preview" tabindex="4"><?php echo $preview_button; ?></a>
  264.                         <input type="hidden" name="wp-preview" id="wp-preview" value="" />
  265.                     </div>
  266.                     <div class="clear"></div>
  267.                 </div><?php // /minor-publishing-actions ?>
  268.                 <div id="misc-publishing-actions">
  269.                     <div class="misc-pub-section<?php if ( !$can_publish ) { echo ' misc-pub-section-last'; } ?>">
  270.                         <label for="post_status"><?php _e('Status:') ?></label>
  271.                         <span id="post-status-display">
  272.                             <?php
  273.                             switch ( $post->post_status ) {
  274.                                 case 'private':
  275.                                     _e('Privately Published');
  276.                                     break;
  277.                                 case 'publish':
  278.                                     _e('Published');
  279.                                     break;
  280.                                 case 'future':
  281.                                     _e('Scheduled');
  282.                                     break;
  283.                                 case 'pending':
  284.                                     _e('Pending Review');
  285.                                     break;
  286.                                 case 'draft':
  287.                                     _e('Draft');
  288.                                     break;
  289.                             }
  290.                             ?>
  291.                         </span>
  292.                         <?php if ( 'publish' == $post->post_status || 'private' == $post->post_status || $can_publish ) : ?>
  293.                             <a href="#post_status" <?php if ( 'private' == $post->post_status ) { ?>style="display:none;" <?php } ?>class="edit-post-status hide-if-no-js" tabindex='4'><?php _e('Edit') ?></a>
  294.                             <div id="post-status-select" class="hide-if-js">
  295.                                 <input type="hidden" name="hidden_post_status" id="hidden_post_status" value="<?php echo esc_attr($post->post_status); ?>" />
  296.                                 <select name='post_status' id='post_status' tabindex='4'>
  297.                                     <?php if ( $can_publish ) : ?>
  298.                                         <option<?php selected( $post->post_status, 'publish' ); ?> value='publish'><?php _e('Published') ?></option>
  299.                                         <option<?php selected( $post->post_status, 'private' ); ?> value='publish'><?php _e('Privately Published') ?></option>
  300.                                         <option<?php selected( $post->post_status, 'future' ); ?> value='future'><?php _e('Scheduled') ?></option>
  301.                                     <?php endif; ?>
  302.                                     <option<?php selected( $post->post_status, 'pending' ); ?> value='pending'><?php _e('Pending Review') ?></option>
  303.                                     <option<?php selected( $post->post_status, 'draft' ); ?> value='draft'><?php _e('Draft') ?></option>
  304.                                 </select>
  305.                                 <a href="#post_status" class="save-post-status hide-if-no-js button"><?php _e('OK'); ?></a>
  306.                                 <a href="#post_status" class="cancel-post-status hide-if-no-js"><?php _e('Cancel'); ?></a>
  307.                             </div>
  308.                         <?php endif; ?>
  309.                     </div><?php // /misc-pub-section ?>
  310.                     <div class="misc-pub-section " id="visibility">
  311.                         <?php _e('Visibility:'); ?>
  312.                         <span id="post-visibility-display">
  313.                             <?php
  314.                             if ( 'private' == $post->post_status )
  315.                             {
  316.                                 $post->post_password = '';
  317.                                 $visibility = 'private';
  318.                                 $visibility_trans = __('Private');
  319.                             }
  320.                             elseif ( !empty( $post->post_password ) )
  321.                             {
  322.                                 $visibility = 'password';
  323.                                 $visibility_trans = __('Password protected');
  324.                             }
  325.                             else
  326.                             {
  327.                                 $visibility = 'public';
  328.                                 $visibility_trans = __('Public');
  329.                             }
  330.                             echo esc_html( $visibility_trans );
  331.                             ?>
  332.                         </span>
  333.                         <?php if ( $can_publish ) : ?>
  334.                             <a href="#visibility" class="edit-visibility hide-if-no-js"><?php _e('Edit'); ?></a>
  335.                             <div id="post-visibility-select" class="hide-if-js">
  336.                                 <input type="hidden" name="hidden_post_password" id="hidden-post-password" value="<?php echo esc_attr($post->post_password); ?>" />
  337.                                 <input type="hidden" name="hidden_post_visibility" id="hidden-post-visibility" value="<?php echo esc_attr( $visibility ); ?>" />
  338.                                 <input type="radio" name="visibility" id="visibility-radio-public" value="public" <?php checked( $visibility, 'public' ); ?> /> <label for="visibility-radio-public" class="selectit"><?php _e('Public'); ?></label><br />
  339.                                 <input type="radio" name="visibility" id="visibility-radio-password" value="password" <?php checked( $visibility, 'password' ); ?> /> <label for="visibility-radio-password" class="selectit"><?php _e('Password protected'); ?></label><br />
  340.                                 <span id="password-span"><label for="post_password"><?php _e('Password:'); ?></label> <input type="text" name="post_password" id="post_password" value="<?php echo esc_attr($post->post_password); ?>" /><br /></span>
  341.                                 <input type="radio" name="visibility" id="visibility-radio-private" value="private" <?php checked( $visibility, 'private' ); ?> /> <label for="visibility-radio-private" class="selectit"><?php _e('Private'); ?></label><br />
  342.                                 <p>
  343.                                     <a href="#visibility" class="save-post-visibility hide-if-no-js button"><?php _e('OK'); ?></a>
  344.                                     <a href="#visibility" class="cancel-post-visibility hide-if-no-js"><?php _e('Cancel'); ?></a>
  345.                                 </p>
  346.                             </div>
  347.                         <?php endif; ?>
  348.                     </div><?php // /misc-pub-section ?>
  349.  
  350.                     <?php
  351.                     $tab_index_attribute = ' tabindex="4"';
  352.  
  353.                     if ( 0 != $post->ID )
  354.                     {
  355.                         $start_datetime = strtotime($post->post_date);
  356.                         if(!$end_date_sql = get_post_meta($post->ID, 'event_end_datetime', true))
  357.                         {
  358.                             $end_datetime = $start_datetime;
  359.                         }
  360.                         else
  361.                         {
  362.                             $end_datetime = strtotime($end_date_sql);
  363.                         }
  364.                         $is_allday = (bool)get_post_meta($post->ID, 'event_is_allday', true);
  365.                     }
  366.                     else
  367.                     {
  368.                         $start_datetime = current_time('timestamp');
  369.                         $end_datetime = current_time('timestamp');
  370.                         $is_allday = false;
  371.                     }
  372.  
  373.                     $start_jj = date( 'd', $start_datetime);
  374.                     $start_mm = date( 'm', $start_datetime);
  375.                     $start_aa = date( 'Y', $start_datetime);
  376.                     $start_hh = date( 'g', $start_datetime);
  377.                     $start_mn = date( 'i', $start_datetime);
  378.                     $start_ss = date( 's', $start_datetime);
  379.                     $start_mr = date( 'A', $start_datetime);
  380.  
  381.                     $end_jj = date( 'd', $end_datetime);
  382.                     $end_mm = date( 'm', $end_datetime);
  383.                     $end_aa = date( 'Y', $end_datetime);
  384.                     $end_hh = date( 'g', $end_datetime);
  385.                     $end_mn = date( 'i', $end_datetime);
  386.                     $end_ss = date( 's', $end_datetime);
  387.                     $end_mr = date( 'A', $end_datetime);
  388.  
  389.  
  390.                     $start_month = "<select id=\"start_mm\" name=\"start_mm\"$tab_index_attribute>\n";
  391.                     for ( $i = 1; $i < 13; $i = $i +1 ) {
  392.                         $start_month .= "\t\t\t" . '<option value="' . zeroise($i, 2) . '"';
  393.                         if ( $i == $start_mm )
  394.                         $start_month .= ' selected="selected"';
  395.                         $start_month .= '>' . $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) ) . "</option>\n";
  396.                     }
  397.                     $start_month .= '</select>';
  398.  
  399.                     $end_month = "<select id=\"end_mm\" name=\"end_mm\"$tab_index_attribute>\n";
  400.                     for ( $i = 1; $i < 13; $i = $i +1 ) {
  401.                         $end_month .= "\t\t\t" . '<option value="' . zeroise($i, 2) . '"';
  402.                         if ( $i == $end_mm )
  403.                         $end_month .= ' selected="selected"';
  404.                         $end_month .= '>' . $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) ) . "</option>\n";
  405.                     }
  406.                     $end_month .= '</select>';
  407.  
  408.                     $start_day = '<input type="text" id="start_jj" name="start_jj" value="' . $start_jj . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />';
  409.                     $start_year = '<input type="text" id="start_aa" name="start_aa" value="' . $start_aa . '" size="4" maxlength="4"' . $tab_index_attribute . ' autocomplete="off" />';
  410.                     $start_hour = '<input type="text" id="start_hh" name="start_hh" value="' . $start_hh . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />';
  411.                     $start_minute = '<input type="text" id="start_mn" name="start_mn" value="' . $start_mn . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />';
  412.                     $start_meridian = '<select id="start_mr" name="start_mr" '.$tab_index_attribute.'>';
  413.                     $start_meridian.= '<option value="AM" '.('AM' == $start_mr ? 'selected="selected"' : '').'>AM</option>';
  414.                     $start_meridian.= '<option value="PM" '.('PM' == $start_mr ? 'selected="selected"' : '').'>PM</option>';
  415.                     $start_meridian.=   '</select>';
  416.  
  417.                     $end_day = '<input type="text" id="end_jj" name="end_jj" value="'. $end_jj . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />';
  418.                     $end_year = '<input type="text" id="end_aa" name="end_aa" value="' . $end_aa . '" size="4" maxlength="4"' . $tab_index_attribute . ' autocomplete="off" />';
  419.                     $end_hour = '<input type="text" id="end_hh" name="end_hh" value="' . $end_hh . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />';
  420.                     $end_minute = '<input type="text" id="end_mn" name="end_mn" value="' . $end_mn . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />';
  421.                     $end_meridian = '<select id="end_mr" name="end_mr" '.$tab_index_attribute.'>';
  422.                     $end_meridian.= '<option value="AM" '.('AM' == $end_mr ? 'selected="selected"' : '').'>AM</option>';
  423.                     $end_meridian.= '<option value="PM" '.('PM' == $end_mr ? 'selected="selected"' : '').'>PM</option>';
  424.                     $end_meridian.= '</select>';
  425.  
  426.                     ?>
  427.                     <div class="misc-pub-section curtime misc-pub-section-last">
  428.                         <div id="div_allday">
  429.                             <label for="event_is_allday">Is All Day Event?</label>
  430.                             <input type="checkbox" id="event_is_allday" name="event_is_allday"<?php echo $is_allday ? 'checked="checked"' : ''?> />
  431.                         </div>
  432.                         <div>
  433.                             <span>Start Date: </span>
  434.                             <?php echo "$start_month $start_day, $start_year"?>
  435.                         </div>
  436.                         <div id="div_start_time">
  437.                             <span>Start Time: </span>
  438.                             <?php echo "$start_hour : $start_minute $start_meridian"?>
  439.                         </div>
  440.                         <div>
  441.                             <span>End Date: </span>
  442.                             <?php echo "$end_month $end_day, $end_year"?>
  443.                         </div>
  444.                         <div id="div_end_time">
  445.                             <span>End Time: </span>
  446.                             <?php echo "$end_hour : $end_minute $end_meridian"?>
  447.                         </div>
  448.                     </div>
  449.  
  450.                 </div>
  451.                 <div class="clear"></div>
  452.             </div>
  453.             <div id="major-publishing-actions">
  454.                 <?php do_action('post_submitbox_start'); ?>
  455.                 <div id="delete-action">
  456.                     <?php if ( ( 'edit' == $action ) && current_user_can('delete_page', $post->ID) ) : ?>
  457.                         <a class="submitdelete deletion" href="<?php echo wp_nonce_url("page.php?action=trash&amp;post=$post->ID", 'trash-page_' . $post->ID); ?>"><?php _e('Move to Trash'); ?></a>
  458.                     <?php endif; ?>
  459.                 </div>
  460.                 <div id="publishing-action">
  461.                     <?php if ( !in_array( $post->post_status, array('publish', 'future', 'private') ) || 0 == $post->ID ) : ?>
  462.                         <?php   if ( $can_publish ) : ?>
  463.                             <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Publish') ?>" />
  464.                             <input name="publish" type="submit" class="button-primary" id="publish" tabindex="5" accesskey="p" value="<?php esc_attr_e('Publish') ?>" />
  465.                         <?php else : ?>
  466.                             <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Submit for Review') ?>" />
  467.                             <input name="publish" type="submit" class="button-primary" id="publish" tabindex="5" accesskey="p" value="<?php esc_attr_e('Submit for Review') ?>" />
  468.                         <?php endif; ?>
  469.                     <?php else: ?>
  470.                         <input name="original_publish" type="hidden" id="original_publish" value="<?php esc_attr_e('Update Page') ?>" />
  471.                         <input name="save" type="submit" class="button-primary" id="publish" tabindex="5" accesskey="p" value="<?php esc_attr_e('Update Page') ?>" />
  472.                     <?php endif; ?>
  473.                 </div>
  474.                 <div class="clear"></div>
  475.             </div>
  476.         </div>
  477.         <?php
  478.     }
  479.  
  480.     /**
  481.      * Filter for 'get_previous_posts_where'
  482.      *
  483.      * @todo check that this is still needed in 3.0
  484.      *
  485.      * @param string $where
  486.      * @return string
  487.      */
  488.     public function filter_get_previous_next_post_where($where)
  489.     {
  490.         global $post;
  491.         if($post->post_type == $this->get_content_type())
  492.         {
  493.             $where = str_replace("post_type = 'post'", "post_type = '".$this->get_content_type()."'", $where);
  494.         }
  495.         return $where;
  496.     }
  497.  
  498.     /**
  499.      * Filters for handle_404 to allow months with no events not to 404
  500.      *
  501.      * @todo This is dependent on http://core.trac.wordpress.org/ticket/10722
  502.      *
  503.      * @param bool $handle_404
  504.      * @return bool
  505.      */
  506.     public function should_handle_404($handle_404)
  507.     {
  508.         global $wp_query;
  509.         if($handle_404 && get_query_var('post_type') == $this->get_content_type())
  510.         {
  511.             $handle_404 = false;
  512.         }
  513.         return $handle_404;
  514.     }
  515.  
  516.     /**
  517.      * The following 2 functions are a work around to keep empty months from 404ing
  518.      * until http://core.trac.wordpress.org/ticket/10722 is available.
  519.      *
  520.      */
  521.     public function handle_404_workaround()
  522.     {
  523.         if(get_query_var('post_type') == $this->get_content_type() && is_date())
  524.         {
  525.             global $wp_query;
  526.             $wp_query->is_category = true;
  527.             $wp_query->queried_object = true;
  528.         }
  529.     }
  530.     public function reset_handle_404_workaround()
  531.     {
  532.         if(get_query_var('post_type') == $this->get_content_type() && is_date())
  533.         {
  534.             global $wp_query;
  535.             $wp_query->is_category = false;
  536.             unset($wp_query->queried_object);
  537.         }
  538.     }
  539.  
  540.     /**
  541.      * Runs on 'posts_where_request' to exclude events that ended previous to today.
  542.      *
  543.      * @param string $where
  544.      * @return string
  545.      */
  546.     public function filter_events_where($where)
  547.     {
  548.         global $wpdb;
  549.         if(!is_admin() && ($this->get_content_type() == get_query_var('post_type') || get_query_var('taxonomy') == 'venue'))
  550.         {
  551.             $gmt_time = current_time('timestamp');
  552.             $gmt_bod = mktime(0, 0, 0, date('m', $gmt_time), date('j', $gmt_time), date('Y', $gmt_time));
  553.  
  554.             $where.= $wpdb->prepare(" AND (($wpdb->posts.post_date >= %s AND EndDate.meta_value is null) OR EndDate.meta_value >= %s)", gmdate('Y-m-d H:i:s', $gmt_bod), gmdate('Y-m-d H:i:s', $gmt_bod));
  555.         }
  556.         return $where;
  557.  
  558.     }
  559.  
  560.     /**
  561.      * Runs on 'posts_join_request' filter to add joins needed for filter_events_where method.
  562.      *
  563.      * @param string $join
  564.      * @return string
  565.      */
  566.     public function filter_events_join($join)
  567.     {
  568.         global $wpdb;
  569.         if(!is_admin() && ($this->get_content_type() == get_query_var('post_type') || get_query_var('taxonomy') == 'venue'))
  570.         {
  571.             $join.= "LEFT JOIN $wpdb->postmeta EndDate ON EndDate.post_id = $wpdb->posts.ID AND EndDate.meta_key = 'event_end_datetime' ";
  572.         }
  573.         return $join;
  574.     }
  575.  
  576.     /**
  577.      * Redirects the events home to the current month.
  578.      *
  579.      */
  580.     public function redirect_event_landing()
  581.     {
  582.         if(in_array($_SERVER['REQUEST_URI'], array('/events', '/events/')))
  583.         {
  584.             wp_redirect(site_url('events'.date('/Y/m/')));
  585.             die();
  586.         }
  587.         if(function_exists('wpcom_is_vip') && (strpos($_SERVER['REQUEST_URI'], '/events?s=') !== false || strpos($_SERVER['REQUEST_URI'], '/events/?s=') !== false))
  588.         {
  589.             wp_redirect(site_url('events/search/'.urlencode($_REQUEST['s']).'/'));
  590.             die();
  591.         }
  592.     }
  593.  
  594.     /**
  595.      * Adds a date based template for events
  596.      *
  597.      * @param string $template
  598.      * @return string
  599.      */
  600.     public function filter_date_template($template)
  601.     {
  602.         if($this->get_content_type() == get_query_var('post_type'))
  603.         {
  604.             $date_template = locate_template(array('date-calendar_event.php'));
  605.             if($date_template) $template = $date_template;
  606.         }
  607.         return $date_template;
  608.     }
  609. }
  610. $cal_handler = new CP_Calendar_Event_Handler();
  611. add_action('setup_custom_content', array($cal_handler, 'on_setup_custom_content'));
  612. add_action('save_post', array($cal_handler, 'on_save_event'), 10, 2);
  613.  
  614. add_filter('request', array($cal_handler, 'filter_request_query_vars'));
  615. //add_filter('posts_request', array($cal_handler, 'fix_request'), 10, 1); //added for debugging
  616. add_action('init', array($cal_handler, 'redirect_event_landing'));
  617. /**
  618.  * @todo the handle_404 filter requires ticket http://core.trac.wordpress.org/ticket/10722 to be available.
  619.  * the other two functions are a work around until then.
  620.  */
  621. //add_filter('handle_404', array($cal_handler, 'should_handle_404'), 10, 1);
  622. add_action('posts_selection', array($cal_handler, 'handle_404_workaround'), 10, 1);
  623. add_action('template_redirect', array($cal_handler, 'reset_handle_404_workaround'));
  624. add_filter('date_template', array($cal_handler, 'filter_date_template'), 10, 1);
  625. add_action('add_meta_boxes_'.$cal_handler->get_content_type(), array($cal_handler, 'add_meta_boxes'), 10, 1);
  626. add_filter('wp_insert_post_data', array($cal_handler, 'filter_wp_insert_post_data'), 10, 2);