03 października 2014

Event Calendar Pro – Widget minionych wydarzeń

Past Events Widget for Event Calendar Pro

Events Calendar Pro jest znakomitym systemem wydarzeń dla WordPress jednak developer nie przemyślał do końca naszych oczekiwań.
Tworząc stronę dla Gorlickiego Centrum Kultury zabrakło funkcjonalności widgetu minionych wydarzeń. W wersji PRO otrzymujemy rozbudowany widget wydarzeń nadchodzących i ten właśnie widget wykorzystaliśmy do stworzenia widgetu wydarzeń minonych.

 

 

1. Tworzymy kopię widgetu

W pliku function.php naszego motywu wklejamy kod dodający nowy widget o nazwie Wydarzenia Minione:

[php]
class TribeEventsAdvancedListWidgetPast extends TribeEventsListWidget {
/**
* @var array
*/
public $instance = array();

public function __construct() {
$widget_ops = array(
‘classname’ => ‘tribe-events-adv-list-widget-past’,
‘description’ => __( ‘A widget that displays past or upcoming x events.’, ‘tribe-events-calendar-pro’ ) );

$control_ops = array( ‘id_base’ => ‘tribe-events-adv-list-widget-past’ );

parent::__construct( ‘tribe-events-adv-list-widget-past’, __( ‘Past events’, ‘tribe-events-calendar-pro’ ), $widget_ops, $control_ops );
add_filter( ‘tribe_events_list_widget_query_args’, array( $this, ‘taxonomy_filters’ ) );
}

public function taxonomy_filters( $query ) {
if ( empty( $this->instance ) ) return $query;
$tax_query = TribeEventsPro_Widgets::form_tax_query( json_decode( $this->instance[‘filters’] ), $this->instance[‘operand’] );

if ( isset( $query[‘tax_query’] ) ) $query[‘tax_query’] = array_merge( $query[‘tax_query’], $tax_query );
else $query[‘tax_query’] = $tax_query;

return $query;
}

public function widget( $args, $instance ) {
$ecp = TribeEventsPro::instance();
$tooltip_status = $ecp->recurring_info_tooltip_status();
$ecp->disable_recurring_info_tooltip();
$this->instance_defaults( $instance );

// @todo remove after 3.7 (continuity helper for upgrading users)
if ( isset( $this->instance[‘category’] ) ) $this->include_cat_id( $this->instance[‘filters’], $this->instance[‘category’] );

if ( $tooltip_status ) $ecp->enable_recurring_info_tooltip();
parent::widget_output( $args, $this->instance, ‘pro/widgets/past-widget’ );
}

public function update( $new_instance, $old_instance ) {
$instance = parent::update( $new_instance, $old_instance );

$instance[‘venue’] = $new_instance[‘venue’];
$instance[‘country’] = $new_instance[‘country’];
$instance[‘address’] = $new_instance[‘address’];
$instance[‘city’] = $new_instance[‘city’];
$instance[‘region’] = $new_instance[‘region’];
$instance[‘zip’] = $new_instance[‘zip’];
$instance[‘phone’] = $new_instance[‘phone’];
$instance[‘cost’] = $new_instance[‘cost’];
$instance[‘organizer’] = $new_instance[‘organizer’];
$instance[‘operand’] = strip_tags( $new_instance[‘operand’] );
$instance[‘filters’] = maybe_unserialize( $new_instance[‘filters’] );
$instance[‘featured_image’] = $new_instance[‘featured_image’];
$instance[‘past_or_next’] = $new_instance[‘past_or_next’];

// @todo remove after 3.7 (added for continuity when users transition from 3.5.x or earlier to this release)
if ( isset( $old_instance[‘category’] ) ) {
$this->include_cat_id($instance[‘filters’], $old_instance[‘category’]);
unset( $instance[‘category’] );
}

return $instance;
}

public function form( $instance ) {
$this->instance_defaults( $instance );
$this->include_cat_id( $this->instance[‘filters’], $this->instance[‘category’] ); // @todo remove after 3.7

$taxonomies = get_object_taxonomies( TribeEvents::POSTTYPE, ‘objects’ );
$taxonomies = array_reverse( $taxonomies );

$instance = $this->instance;
include( TribeEventsPro::instance()->pluginPath . ‘admin-views/widget-admin-advanced-list-past.php’ );
}

protected function instance_defaults( $instance ) {
$this->instance = wp_parse_args( (array) $instance, array(
‘title’ => __( ‘Past Events’, ‘tribe-events-calendar-pro’ ),
‘limit’ => ‘5’,
‘no_upcoming_events’ => false,
‘featured_image’ => false,
‘past_or_next’ => false,
‘venue’ => false,
‘country’ => true,
‘address’ => false,
‘city’ => true,
‘region’ => true,
‘zip’ => false,
‘phone’ => false,
‘cost’ => false,
‘category’ => false, // @todo remove this element after 3.7
‘organizer’ => false,
‘operand’ => ‘OR’,
‘filters’ => ”
) );
}

/**
* Adds the provided category ID to the list of filters.
*
* In 3.6 taxonomy filters were added to this widget (as already existed for the calendar
* widget): this helper exists to provide some continuity for users upgrading from a 3.5.x
* release or earlier, transitioning any existing category setting to the new filters
* list.
*
* @todo remove after 3.7
* @param mixed &$filters
* @param int $id
*/
protected function include_cat_id( &$filters, $id ) {
$id = (string) absint( $id ); // An absint for sanity but a string for comparison purposes
$tax = TribeEvents::TAXONOMY;
if ( ‘0’ === $id || ! is_string( $filters ) ) return;

$filters = (array) json_decode( $filters, true );

if ( isset( $filters[$tax] ) && ! in_array( $id, $filters[$tax] ) ) $filters[$tax][] = $id;
elseif ( ! isset( $filters[$tax] ) ) $filters[$tax] = array( $id );

$filters = json_encode( $filters );
}
}add_action( ‘widgets_init’, function(){
register_widget( ‘TribeEventsAdvancedListWidgetPast’ );
});
[/php]

 2. Kopiujemy widok widgetu – list-widget.php

Kolejnym krokiem jest wykonanie kopi widoku pliku renderującego widget do naszego motywu.
Oryginalny plik znajduje się w katalogu wp-content/plugins/event-calendar-pro/views/pro/widgets/list-widget.php

W katalogu naszego motywu tworzymy nowy plik i wklejamy niżej załączony kod.
Plik tworzymy zachowując strukturę katalogów: wp-content/themes/nasz_motyw/tribe-events/pro/widgets/past-widget.php

 

Plik zmodyfikowaliśmy dając użytkownikowi wybór aby mógł wyświetlić nadchodzące lub minione wydarzenia (linia 47-49) oraz wyświetlić lub ukryć obrazek wydarzenia (linia 57-58).

[php]
<?php
/**
* Events Pro List Widget Template
* This is the template for the output of the events list widget.
* All the items are turned on and off through the widget admin.
* There is currently no default styling, which is highly needed.
*
* Override this template in your own theme by creating a file at [your-theme]/tribe-events/widgets/list-widget.php
*
* When the template is loaded, the following vars are set: $start, $end, $venue,
* $address, $city, $state, $province’], $zip, $country, $phone, $cost
*
* @package TribeEventsCalendarPro
*
*/

if ( !defined(‘ABSPATH’) ) die(‘-1’);

// Have taxonomy filters been applied?
$filters = json_decode( $filters, true );

// Is the filter restricted to a single taxonomy?
$single_taxonomy = ( is_array( $filters ) && 1 === count( $filters ) );
$single_term = false;

// Pull the actual taxonomy and list of terms into scope
if ( $single_taxonomy ) foreach ( $filters as $taxonomy => $terms );

// If we have a single taxonomy and a single term, the View All link should point to the relevant archive page
if ( $single_taxonomy && 1 === count( $terms ) ) {
$link_to_archive = true;
$link_to_all = get_term_link( absint( $terms[0] ), $taxonomy );
}

// Otherwise link to the main events page
else {
$link_to_archive = false;
$link_to_all = tribe_get_events_link();
}

// Check if any posts were found
if ( $posts ):
?>
<ol class="hfeed vcalendar">

<?php
if ( $past_or_next != ” ) {
$posts = tribe_get_events( array(
‘eventDisplay’=>’past’) );}

foreach( $posts as $post ) :
setup_postdata( $post );
?>
<li class="<?php tribe_events_event_classes() ?>">

<?php do_action( ‘tribe_events_list_widget_before_the_event_title’ );
if ( $featured_image != ” ) {
echo tribe_event_featured_image(null, ‘thumbnail’); }?>
<h4 class="entry-title summary">
<a href="<?php echo tribe_get_event_link(); ?>" rel="bookmark"><?php the_title(); ?></a>
</h4>

<?php do_action( ‘tribe_events_list_widget_after_the_event_title’ ); ?>

<?php do_action( ‘tribe_events_list_widget_before_the_meta’ ) ?>

<div class="duration">
<?php echo tribe_events_event_schedule_details(); ?>
</div>
<?php if ( $cost && tribe_get_cost() != ” ) { ?>
<span class="tribe-events-divider">|</span>
<div class="tribe-events-event-cost">
<?php echo tribe_get_cost( null, true ); ?>
</div>
<?php } ?>
<div class="vcard adr location">

<?php if ( $venue && tribe_get_venue() != ”) { ?>
<span class="fn org tribe-venue"><?php echo tribe_get_venue_link(); ?></span>
<?php } ?>

<?php if ( $address && tribe_get_address() != ” ) { ?>
<span class="street-address"><?php echo tribe_get_address(); ?></span>
<?php } ?>

<?php if ( $city && tribe_get_city() != ” ) { ?>
<span class="locality"><?php echo tribe_get_city(); ?></span>
<?php } ?>

<?php if ( $region && tribe_get_region() !=” ) { ?>
<span class="region"><?php echo tribe_get_region(); ?></span>
<?php } ?>

<?php if ( $zip && tribe_get_zip() != ” ) { ?>
<span class="postal-code"><?php echo tribe_get_zip(); ?></span>
<?php } ?>

<?php if ( $country && tribe_get_country() != ”) { ?>
<span class="country-name"><?php echo tribe_get_country(); ?></span>
<?php } ?>

<?php if ( $organizer && tribe_get_organizer() != ” ) { ?>
<?php _e( ‘Organizer:’, ‘tribe-events-calendar-pro’ ); ?>
<span class="tribe-organizer"><?php echo tribe_get_organizer_link(); ?></span>
<?php } ?>

<?php if ( $phone && tribe_get_phone() != ” ) { ?>
<span class="tel"><?php echo tribe_get_phone(); ?></span>
<?php } ?>
</div>

<?php do_action( ‘tribe_events_list_widget_after_the_meta’ ) ?>

</li>
<?php
endforeach;
?>
</ol><!– .hfeed –>

<p class="tribe-events-widget-link">
<a href="<?php esc_attr_e( esc_url( $link_to_all ) ) ?>" rel="bookmark">
<?php _e( ‘View More…’, ‘tribe-events-calendar-pro’ ) ?>
</a>
</p>
<?php
// No Events were Found
else:
?>
<p><?php _e( ‘There are no upcoming events at this time.’, ‘tribe-events-calendar’ ) ?></p>
<?php
endif;
[/php]

3. Stworzenie widoku administratora dla nowego widgetu.

Aby wyświetlić na stronie administracyjnej widgetu dodatkowe opcje zmodyfikowaliśmy a w zasadzie stworzyliśmy nowy widok kopiując i modyfikując plik:
wp-content/plugins/event-calendar-pro/admin-views/widget-admin-advanced-list.php

Nowy plik zapisujemy w tym samym katalogu i zmieniamy nazwę na widget-admin-advanced-list-past.php
wp-content/plugins/event-calendar-pro/admin-views/widget-admin-advanced-list-past.php

Nie musimy się obawiać nadpisania pliku przy aktualizacji pluginu – chyba, że developer wdroży opisaną w poście funkcjonalność.

[php]<?php
/**
* Widget admin for the event list widget.
*/

// Don’t load directly
if ( !defined(‘ABSPATH’) ) { die(‘-1’); }

?>
<p>Test></p>
<p>
<label for="<?php echo $this->get_field_id( ‘title’ ); ?>"><?php _e(‘Title:’,’tribe-events-calendar-pro’);?></label>
<input class="widefat" id="<?php echo $this->get_field_id( ‘title’ ); ?>" name="<?php echo $this->get_field_name( ‘title’ ); ?>" type="text" value="<?php echo esc_attr( $instance[‘title’] ); ?>" />
</p>

<p>
<label for="<?php echo $this->get_field_id( ‘limit’ ); ?>"><?php _e(‘Number of events to show:’,’tribe-events-calendar-pro’);?></label>
<select id="<?php echo $this->get_field_id( ‘limit’ ); ?>" name="<?php echo $this->get_field_name( ‘limit’ ); ?>" class="widefat">
<?php for ($i=1; $i<=10; $i++)
{?>
<option <?php if ( $i == $instance[‘limit’] ) {echo ‘selected="selected"’;}?> > <?php echo $i;?> </option>
<?php } ?>
</select>
</p>

<p><?php _e( ‘Display:’, ‘tribe-events-calendar-pro’ ); ?><br />

<?php $displayoptions = array (
"venue" => __("Venue", ‘tribe-events-calendar-pro’),
"organizer" => __("Organizer", ‘tribe-events-calendar-pro’),
"address" => __("Address", ‘tribe-events-calendar-pro’),
"city" => __("City", ‘tribe-events-calendar-pro’),
"region" => __("State (US) Or Province (Int)", ‘tribe-events-calendar-pro’),
"zip" => __("Postal Code", ‘tribe-events-calendar-pro’),
"country" => __("Country", ‘tribe-events-calendar-pro’),
"phone" => __("Phone", ‘tribe-events-calendar-pro’),
"cost" => __("Price", ‘tribe-events-calendar-pro’),
);
foreach ($displayoptions as $option => $label) { ?>
<input class="checkbox" type="checkbox" value="1" <?php checked( $instance[$option], true ); ?> id="<?php echo $this->get_field_id( $option ); ?>" name="<?php echo $this->get_field_name( $option ); ?>" style="margin-left:5px"/>
<label for="<?php echo $this->get_field_id( $option ); ?>"><?php echo $label ?></label>
<br/>
<?php } ?>
</p>

<?php
/**
* Filters
*/

$class = "";
if ( empty( $instance[‘filters’] ) ) {
$class = "display:none;";
}
?>

<div class="calendar-widget-filters-container" style="<?php echo $class;?>">

<h3 class="calendar-widget-filters-title"><?php _e(‘Filters’, ‘tribe-events-calendar-pro’); ?>:</h3>

<input type="hidden" name="<?php echo $this->get_field_name( ‘filters’ ); ?>"
id="<?php echo $this->get_field_id( ‘filters’ ); ?>" class="calendar-widget-added-filters"
value=’<?php echo maybe_serialize( $instance[‘filters’] ); ?>’/>
<style>
.customizer-select2 {
z-index:500001
}
</style>
<div class="calendar-widget-filter-list">
<?php
if ( ! empty( $instance[‘filters’] ) ) {

echo ‘<ul>’;

foreach ( json_decode( $instance[‘filters’] ) as $tax => $terms ) {
$tax_obj = get_taxonomy( $tax );

foreach ( $terms as $term ) {
if ( empty( $term ) ) {
continue;
}
$term_obj = get_term( $term, $tax );
if ( empty( $term_obj ) || is_wp_error( $term_obj ) ) {
continue;
}
echo sprintf( "<li><p>%s: %s  <span><a href=’#’ class=’calendar-widget-remove-filter’ data-tax=’%s’ data-term=’%s’>(".__(‘remove’, ‘tribe-events-calendar-pro’).")</a></span></p></li>", $tax_obj->labels->name, $term_obj->name, $tax, $term_obj->term_id );
}
}

echo ‘</ul>’;
}
?>

</div>

<p class="calendar-widget-filters-operand">
<label for="<?php echo $this->get_field_name( ‘operand’ ); ?>">
<input <?php checked( $instance[‘operand’], ‘AND’ ); ?> type="radio" name="<?php echo $this->get_field_name( ‘operand’ ); ?>" value="AND">
<?php _e(‘Match all’, ‘tribe-events-calendar-pro’); ?></label><br/>
<label for="<?php echo $this->get_field_name( ‘operand’ ); ?>">
<input <?php checked( $instance[‘operand’], ‘OR’ ); ?> type="radio" name="<?php echo $this->get_field_name( ‘operand’ ); ?>" value="OR">
<?php _e(‘Match any’, ‘tribe-events-calendar-pro’); ?></label>
</p>
</div>
<p>
<label><?php _e(‘Add a filter’, ‘tribe-events-calendar-pro’); ?>:
<select class="widefat calendar-widget-add-filter" id="<?php echo $this->get_field_id( ‘selector’ ); ?>" data-storage="<?php echo $this->get_field_id( ‘filters’ ); ?>">
<?php
echo "<option value=’0’>" . __( ‘Select one…’, ‘tribe-events-calendar-pro’ ) . "</option>";
foreach ( $taxonomies as $tax ) {
echo sprintf( "<optgroup id=’%s’ label=’%s’>", $tax->name, $tax->labels->name );
$terms = get_terms( $tax->name, array( ‘hide_empty’ => false ) );
foreach ( $terms as $term ) {
echo sprintf( "<option value=’%d’>%s</option>", $term->term_id, $term->name );
}
echo "</optgroup>";
}
?>
</select>
</label>
</p>

<script type="text/javascript">

jQuery( document ).ready( function ( $ ) {
if ( $( ‘div.widgets-sortables’ ).find( ‘select.calendar-widget-add-filter:not(#widget-tribe-mini-calendar-__i__-selector)’ ).length && !$(‘#customize-controls’ ).length) {

$( ".select2-container.calendar-widget-add-filter" ).remove();
setTimeout( function () {
$( "select.calendar-widget-add-filter:not(#widget-tribe-mini-calendar-__i__-selector)" ).select2();
calendar_toggle_all();
}, 600 );
}
} );
</script>
<p><label for="<?php echo $this->get_field_id( ‘past_or_next’ ); ?>"><?php _e(‘Show past events:’,’tribe-events-calendar-pro’);?></label>
<input id="<?php echo $this->get_field_id( ‘past_or_next’ ); ?>" name="<?php echo $this->get_field_name( ‘past_or_next’ ); ?>" type="checkbox" <?php checked( $instance[‘past_or_next’], 1 ); ?> value="1" /></p>

<p><label for="<?php echo $this->get_field_id( ‘featured_image’ ); ?>"><?php _e(‘Show featured image:’,’tribe-events-calendar-pro’);?></label>
<input id="<?php echo $this->get_field_id( ‘featured_image’ ); ?>" name="<?php echo $this->get_field_name( ‘featured_image’ ); ?>" type="checkbox" <?php checked( $instance[‘featured_image’], 1 ); ?> value="1" /></p>

<p><label for="<?php echo $this->get_field_id( ‘no_upcoming_events’ ); ?>"><?php _e(‘Hide this widget if there are no upcoming events:’,’tribe-events-calendar-pro’);?></label>
<input id="<?php echo $this->get_field_id( ‘no_upcoming_events’ ); ?>" name="<?php echo $this->get_field_name( ‘no_upcoming_events’ ); ?>" type="checkbox" <?php checked( $instance[‘no_upcoming_events’], 1 ); ?> value="1" /></p>
[/php]

Jeśli nie rozumiesz modyfikacji w plikach php postępuj dokładnie z nasza instrukcją i zapisuj pliki pod nazwami, które podaliśmy.

Dzięki naszej modyfikacji zachowaliśmy pierwotny widget nadchodzących wydarzeń i dodaliśmy zupełnie nowy widget, którego szukaj pod nazwą Past Events.

Powodzenia!