PageRenderTime 34ms CodeModel.GetById 11ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/wp-lister-for-ebay/classes/table/ListingsTable.php

https://bitbucket.org/sanders_nick/my-maxi-skirt
PHP | 658 lines | 374 code | 110 blank | 174 comment | 72 complexity | 45d2b80014cb425ce8184f38668af1ba MD5 | raw file
  1<?php
  2
  3/*************************** LOAD THE BASE CLASS *******************************
  4 *******************************************************************************
  5 * The WP_List_Table class isn't automatically available to plugins, so we need
  6 * to check if it's available and load it if necessary.
  7 */
  8if(!class_exists('WP_List_Table')){
  9    require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
 10}
 11
 12
 13
 14
 15/************************** CREATE A PACKAGE CLASS *****************************
 16 *******************************************************************************
 17 * Create a new list table package that extends the core WP_List_Table class.
 18 * WP_List_Table contains most of the framework for generating the table, but we
 19 * need to define and override some methods so that our data can be displayed
 20 * exactly the way we need it to be.
 21 * 
 22 * To display this example on a page, you will first need to instantiate the class,
 23 * then call $yourInstance->prepare_items() to handle any data manipulation, then
 24 * finally call $yourInstance->display() to render the table to the page.
 25 * 
 26 * Our theme for this list table is going to be profiles.
 27 */
 28class ListingsTable extends WP_List_Table {
 29
 30    /** ************************************************************************
 31     * REQUIRED. Set up a constructor that references the parent constructor. We 
 32     * use the parent reference to set some default configs.
 33     ***************************************************************************/
 34    function __construct(){
 35        global $status, $page;
 36                
 37        //Set parent defaults
 38        parent::__construct( array(
 39            'singular'  => 'auction',     //singular name of the listed records
 40            'plural'    => 'auctions',    //plural name of the listed records
 41            'ajax'      => false        //does this table support ajax?
 42        ) );
 43        
 44        // get array of profile names
 45        $profilesModel = new ProfilesModel();
 46        $this->profiles = $profilesModel->getAllNames();
 47    }
 48    
 49    
 50    /** ************************************************************************
 51     * Recommended. This method is called when the parent class can't find a method
 52     * specifically build for a given column. Generally, it's recommended to include
 53     * one method for each column you want to render, keeping your package class
 54     * neat and organized. For example, if the class needs to process a column
 55     * named 'title', it would first see if a method named $this->column_title() 
 56     * exists - if it does, that method will be used. If it doesn't, this one will
 57     * be used. Generally, you should try to use custom column methods as much as 
 58     * possible. 
 59     * 
 60     * Since we have defined a column_title() method later on, this method doesn't
 61     * need to concern itself with any column with a name of 'title'. Instead, it
 62     * needs to handle everything else.
 63     * 
 64     * For more detailed insight into how columns are handled, take a look at 
 65     * WP_List_Table::single_row_columns()
 66     * 
 67     * @param array $item A singular item (one full row's worth of data)
 68     * @param array $column_name The name/slug of the column to be processed
 69     * @return string Text or HTML to be placed inside the column <td>
 70     **************************************************************************/
 71    function column_default($item, $column_name){
 72        switch($column_name){
 73            case 'type':
 74            case 'quantity_sold':
 75            case 'ebay_id':
 76            case 'status':
 77                return $item[$column_name];
 78            case 'fees':
 79            case 'price':
 80                return $this->number_format( $item[$column_name], 2 );
 81            case 'end_date':
 82            case 'date_published':
 83            	// use date format from wp
 84                return mysql2date( get_option('date_format'), $item[$column_name] );
 85            case 'template':
 86                return basename( $item['template'] );
 87            case 'profile':
 88                return isset($item['profile_id']) ? $this->profiles[ $item['profile_id'] ] : '';
 89            default:
 90                return print_r($item,true); //Show the whole array for troubleshooting purposes
 91        }
 92    }
 93    
 94        
 95    /** ************************************************************************
 96     * Recommended. This is a custom column method and is responsible for what
 97     * is rendered in any column with a name/slug of 'title'. Every time the class
 98     * needs to render a column, it first looks for a method named 
 99     * column_{$column_title} - if it exists, that method is run. If it doesn't
100     * exist, column_default() is called instead.
101     * 
102     * This example also illustrates how to implement rollover actions. Actions
103     * should be an associative array formatted as 'slug'=>'link html' - and you
104     * will need to generate the URLs yourself. You could even ensure the links
105     * 
106     * 
107     * @see WP_List_Table::::single_row_columns()
108     * @param array $item A singular item (one full row's worth of data)
109     * @return string Text to be placed inside the column <td> (profile title only)
110     **************************************************************************/
111    function column_auction_title($item){
112        
113        // get current page with paging as url param
114        $page = $_REQUEST['page'];
115        if ( isset( $_REQUEST['paged'] )) $page .= '&paged='.$_REQUEST['paged'];
116
117        //Build row actions
118        $actions = array(
119            'preview_auction' => sprintf('<a href="?page=%s&action=%s&auction=%s&width=820&height=550" class="thickbox">%s</a>',$page,'preview_auction',$item['id'],__('Preview','wplister')),
120            'edit'           => sprintf('<a href="?page=%s&action=%s&auction=%s">%s</a>',$page,'edit',$item['id'],__('Edit','wplister')),
121            'verify'          => sprintf('<a href="?page=%s&action=%s&auction=%s">%s</a>',$page,'verify',$item['id'],__('Verify','wplister')),
122            'publish2e'       => sprintf('<a href="?page=%s&action=%s&auction=%s">%s</a>',$page,'publish2e',$item['id'],__('Publish','wplister')),
123            'open'            => sprintf('<a href="%s" target="_blank">%s</a>',$item['ViewItemURL'],__('View on eBay','wplister')),
124            'revise'          => sprintf('<a href="?page=%s&action=%s&auction=%s">%s</a>',$page,'revise',$item['id'],__('Revise','wplister')),
125            'end_item'        => sprintf('<a href="?page=%s&action=%s&auction=%s">%s</a>',$page,'end_item',$item['id'],__('End Listing','wplister')),
126            #'update'         => sprintf('<a href="?page=%s&action=%s&auction=%s">%s</a>',$page,'update',$item['id'],__('Update','wplister')),
127            #'open'           => sprintf('<a href="%s" target="_blank">%s</a>',$item['ViewItemURL'],__('Open in new tab','wplister')),
128            'relist'         => sprintf('<a href="?page=%s&action=%s&auction=%s">%s</a>',$page,'relist',$item['id'],__('Relist','wplister')),
129            'delete'         => sprintf('<a href="?page=%s&action=%s&auction=%s">%s</a>',$page,'delete',$item['id'],__('Delete','wplister')),
130        );
131
132        $profile_data = maybe_unserialize( $item['profile_data'] );
133        $listing_title = $item['auction_title'];
134
135        // make title link to products edit page
136        if ( ProductWrapper::plugin == 'woo' ) {
137            $listing_title = '<a class="product_title_link" href="post.php?post='.$item['post_id'].'&action=edit">'.$listing_title.'</a>';
138        } elseif ( ProductWrapper::plugin == 'shopp' ) {
139            $listing_title = '<a class="product_title_link" href="admin.php?page=shopp-products&id='.$item['post_id'].'">'.$listing_title.'</a>';
140        }
141
142        // show variations
143        if ( ProductWrapper::hasVariations( $item['post_id'] ) ) {
144            $listing_title .= ' (<a href="#" onClick="jQuery(\'#pvars_'.$item['id'].'\').toggle();return false;">&raquo;Variations</a>)<br>';
145            // $listing_title .= '<pre>'.print_r( ProductWrapper::getVariations( $item['post_id'] ), 1 )."</pre>";
146            $variations = ProductWrapper::getVariations( $item['post_id'] );
147
148            $listingsModel = new ListingsModel();
149
150            $variations_html = '<div id="pvars_'.$item['id'].'" class="variations_list" style="display:none;margin-bottom:10px;">';
151
152            // show variation mode message
153            if ( isset( $profile_data['details']['variations_mode'] ) && ( $profile_data['details']['variations_mode'] == 'flat' ) ) {
154                $variations_html .= '<p><b>' . __('These variations will be listed as a single item.','wplister') . '</b></p>';
155            }
156
157            $variations_html .= '<table style="margin-bottom: 8px;">';
158
159            // header
160            $variations_html .= '<tr><th>';
161            $variations_html .= '&nbsp;';
162            $variations_html .= '</th><th>';
163            foreach ($variations[0]['variation_attributes'] as $name => $value) {
164                $variations_html .= $name;
165                $variations_html .= '</th><th>';
166            }
167            $variations_html .= __('Price','wplister');
168            $variations_html .= '</th></tr>';
169
170            foreach ($variations as $var) {
171
172                // first column: quantity
173                $variations_html .= '<tr><td align="right">';
174                $variations_html .= intval( $var['stock'] ) . '&nbsp;x';
175                $variations_html .= '</td>';
176
177                foreach ($var['variation_attributes'] as $name => $value) {
178                    // $variations_html .= $name.': '.$value ;
179                    $variations_html .= '<td>';
180                    $variations_html .= $value ;
181                    $variations_html .= '</td>';
182                }
183                // $variations_html .= '('.$var['sku'].') ';
184                // $variations_html .= '('.$var['image'].') ';
185                
186                // last column: price
187                $variations_html .= '<td align="right">';
188                $price = $listingsModel->applyProfilePrice( $var['price'], $profile_data['details']['start_price'] );
189                $variations_html .= $this->number_format( $price, 2 );
190
191                $variations_html .= '</td></tr>';
192
193            }
194            $variations_html .= '</table>';
195
196            // show variation mode message
197            if ( isset( $profile_data['details']['variations_mode'] ) && ( $profile_data['details']['variations_mode'] == 'flat' ) ) {
198                // $variations_html .= '<p><b>' . __('These variations will be listed as a single item.','wplister') . '</b></p>';
199            } else {
200    
201
202            }
203
204            // list shopp addons
205            if ( ProductWrapper::plugin == 'shopp' ) {
206                $addons = ProductWrapper::getAddons( $item['post_id'] );
207                $variations_html .= '<table style="margin-bottom: 8px;">';
208                foreach ($addons as $addonGroup) {
209
210                    // first column: quantity
211                    $variations_html .= '<tr><td colspan="2" align="left"><b>';
212                    $variations_html .= $addonGroup->name;
213                    $variations_html .= '</b></td></tr>';
214
215                    foreach ($addonGroup->options as $addon) {
216                        $variations_html .= '<tr><td align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
217                        $variations_html .= $addon->name;
218                        $variations_html .= '</td><td align="right">';
219                        $variations_html .= $this->number_format( $addon->price, 2 );
220                        $variations_html .= '</td></tr>';
221                    }
222                    
223                }
224                $variations_html .= '</table>';
225            }
226
227
228            $variations_html .= '</div>';
229            $listing_title .= $variations_html;
230        }
231
232        // disable some actions depending on status
233        if ( $item['status'] != 'published' ) unset( $actions['end_item'] );
234        if ( $item['status'] != 'prepared' ) unset( $actions['verify'] );
235        if ( $item['status'] != 'changed' ) unset( $actions['revise'] );
236        if (($item['status'] != 'prepared' ) &&
237            ($item['status'] != 'verified')) unset( $actions['publish2e'] );
238        if (($item['status'] != 'published' ) &&
239            ($item['status'] != 'changed') &&
240            ($item['status'] != 'ended')) unset( $actions['open'] );
241        if ( $item['status'] == 'ended' ) unset( $actions['edit'] );
242        if ( $item['status'] == 'ended' ) unset( $actions['preview_auction'] );
243        if ( $item['status'] != 'ended' ) unset( $actions['delete'] );
244        if ( $item['status'] != 'ended' ) unset( $actions['relist'] );
245
246        //Return the title contents
247        //return sprintf('%1$s <span style="color:silver">%2$s</span>%3$s',
248        return sprintf('%1$s %2$s',
249            /*$1%s*/ $listing_title,
250            /*$2%s*/ //$item['profile_id'],
251            /*$3%s*/ $this->row_actions($actions)
252        );
253    }
254
255    function column_ebay_id_DISABLED($item){
256
257        //Build row actions
258        #if ( intval($item['ebay_id']) > 0)
259        if ( trim($item['ViewItemURL']) != '')
260        $actions = array(
261            'open' 		=> sprintf('<a href="%s" target="_blank">%s</a>',$item['ViewItemURL'],__('View on eBay','wplister')),
262        );
263        
264        //Return the title contents
265        return sprintf('%1$s %2$s',
266            /*$1%s*/ $item['ebay_id'],
267            /*$2%s*/ $this->row_actions($actions)
268        );
269	}
270	  
271    function column_quantity($item){
272        
273        // use profile quantity for flattened variations
274        $profile_data = maybe_unserialize( $item['profile_data'] );
275        if ( isset( $profile_data['details']['variations_mode'] ) && ( $profile_data['details']['variations_mode'] == 'flat' ) ) {
276
277            if ( $item['quantity_sold'] > 0 ) {
278                $qty_available = $item['quantity'] - $item['quantity_sold'];
279                return $qty_available . ' / ' . $item['quantity'];
280            }
281
282            return $item['quantity']; 
283        }
284
285
286        // if item has variations count them...
287        if ( ProductWrapper::hasVariations( $item['post_id'] ) ) {
288
289            $variations = ProductWrapper::getVariations( $item['post_id'] );
290
291            $quantity = 0;
292            foreach ($variations as $var) {
293                $quantity += intval( $var['stock'] );
294            }
295            return $quantity;
296        }
297
298        if ( $item['quantity_sold'] > 0 ) {
299            $qty_available = $item['quantity'] - $item['quantity_sold'];
300            return $qty_available . ' / ' . $item['quantity'];
301        }
302
303        return $item['quantity'];
304    }
305    
306    function column_price($item){
307        
308        // if item has variations check each price...
309        if ( ProductWrapper::hasVariations( $item['post_id'] ) ) {
310
311            $variations = ProductWrapper::getVariations( $item['post_id'] );
312
313            $price_min = 1000000; // one million should be a high enough ceiling
314            $price_max = 0;
315            foreach ($variations as $var) {
316                $price = $var['price'];
317                if ( $price > $price_max ) $price_max = $price;
318                if ( $price < $price_min ) $price_min = $price;
319            }
320
321            // apply price modifiers
322            $listingsModel = new ListingsModel();
323            $profile_data = maybe_unserialize( $item['profile_data'] );
324            $price_min = $listingsModel->applyProfilePrice( $price_min, $profile_data['details']['start_price'] );
325            $price_max = $listingsModel->applyProfilePrice( $price_max, $profile_data['details']['start_price'] );
326
327            // use lowest price for flattened variations
328            $profile_data = maybe_unserialize( $item['profile_data'] );
329            if ( isset( $profile_data['details']['variations_mode'] ) && ( $profile_data['details']['variations_mode'] == 'flat' ) ) {
330                return $this->number_format( $price_min, 2 );
331            }
332
333
334            if ( $price_min == $price_max ) {
335                return $this->number_format( $price_min, 2 );
336            } else {
337                return $this->number_format( $price_min, 2 ) . ' - ' . $this->number_format( $price_max, 2 );
338            }
339        }
340
341        return $this->number_format( $item['price'], 2 );
342    }
343    
344    function column_end_date($item) {
345
346        $profile_data = maybe_unserialize( $item['profile_data'] );
347        
348        if ( $item['date_finished'] ) {
349            $date = $item['date_finished'];
350            $value = mysql2date( get_option('date_format'), $date );
351            return '<span style="color:darkgreen">'.$value.'</span>';
352        } elseif ( ( is_array($profile_data['details']) ) && ( 'GTC' == $profile_data['details']['listing_duration'] ) ) {
353            $value = 'GTC';
354            return '<span style="color:silver">'.$value.'</span>';
355    	} else {
356			$date = $item['end_date'];
357	    	$value = mysql2date( get_option('date_format'), $date );
358			return '<span>'.$value.'</span>';
359    	}
360
361	}
362	  
363	
364    function column_status($item){
365
366        switch( $item['status'] ){
367            case 'prepared':
368                $color = 'orange';
369                $value = __('prepared','wplister');
370				break;
371            case 'verified':
372                $color = '#21759B';
373                $value = __('verified','wplister');
374				break;
375            case 'published':
376                $color = 'darkgreen';
377                $value = __('published','wplister');
378				break;
379            case 'sold':
380                $color = 'black';
381                $value = __('sold','wplister');
382                break;
383            case 'ended':
384                $color = '#777';
385                $value = __('ended','wplister');
386                break;
387            case 'imported':
388                $color = 'orange';
389                $value = __('imported','wplister');
390				break;
391            case 'selected':
392                $color = 'orange';
393                $value = __('selected','wplister');
394                break;
395            case 'changed':
396                $color = 'purple';
397                $value = __('changed','wplister');
398                break;
399            default:
400                $color = 'black';
401                $value = $item['status'];
402        }
403
404        //Return the title contents
405        return sprintf('<mark style="background-color:%1$s">%2$s</mark>',
406            /*$1%s*/ $color,
407            /*$2%s*/ $value
408        );
409	}
410	  
411    function column_profile($item){
412
413        $profile_name = @$this->profiles[ $item['profile_id'] ];
414
415        return sprintf(
416            '<a href="admin.php?page=wplister-profiles&action=edit&profile=%1$s&return_to=listings" title="%2$s">%3$s</a>',
417            /*$1%s*/ $item['profile_id'],  
418            /*$2%s*/ __('Edit','wplister'),  
419            /*$3%s*/ $profile_name        
420        );
421    }
422    
423    function column_template($item){
424
425        $template_id = basename( $item['template'] );
426        $template_name = TemplatesModel::getNameFromCache( $template_id );
427
428        return sprintf(
429            '<a href="admin.php?page=wplister-templates&action=edit&template=%1$s&return_to=listings" title="%2$s">%3$s</a>',
430            /*$1%s*/ $template_id,  
431            /*$2%s*/ __('Edit','wplister'),  
432            /*$3%s*/ $template_name        
433        );
434    }
435    
436    /** ************************************************************************
437     * REQUIRED if displaying checkboxes or using bulk actions! The 'cb' column
438     * is given special treatment when columns are processed. It ALWAYS needs to
439     * have it's own method.
440     * 
441     * @see WP_List_Table::::single_row_columns()
442     * @param array $item A singular item (one full row's worth of data)
443     * @return string Text to be placed inside the column <td> (profile title only)
444     **************************************************************************/
445    function column_cb($item){
446        return sprintf(
447            '<input type="checkbox" name="%1$s[]" value="%2$s" />',
448            /*$1%s*/ $this->_args['singular'],  //Let's simply repurpose the table's singular label ("listing")
449            /*$2%s*/ $item['id']       			//The value of the checkbox should be the record's id
450        );
451    }
452    
453    
454    /** ************************************************************************
455     * REQUIRED! This method dictates the table's columns and titles. This should
456     * return an array where the key is the column slug (and class) and the value 
457     * is the column's title text. If you need a checkbox for bulk actions, refer
458     * to the $columns array below.
459     * 
460     * The 'cb' column is treated differently than the rest. If including a checkbox
461     * column in your table you must create a column_cb() method. If you don't need
462     * bulk actions or checkboxes, simply leave the 'cb' entry out of your array.
463     * 
464     * @see WP_List_Table::::single_row_columns()
465     * @return array An associative array containing column information: 'slugs'=>'Visible Titles'
466     **************************************************************************/
467    function get_columns(){
468        $columns = array(
469            'cb'        		=> '<input type="checkbox" />', //Render a checkbox instead of text
470            'ebay_id'  			=> __('eBay ID','wplister'),
471            'auction_title' 	=> __('Title','wplister'),
472            'quantity'			=> __('Quantity','wplister'),
473            'quantity_sold'		=> __('Sold','wplister'),
474            'price'				=> __('Price','wplister'),
475            'fees'				=> __('Fees','wplister'),
476            'date_published'	=> __('Created at','wplister'),
477            'end_date'          => __('Ends at','wplister'),
478            'profile'           => __('Profile','wplister'),
479            'template'          => __('Template','wplister'),
480            'status'		 	=> __('Status','wplister')
481        );
482        return $columns;
483    }
484    
485    /** ************************************************************************
486     * Optional. If you want one or more columns to be sortable (ASC/DESC toggle), 
487     * you will need to register it here. This should return an array where the 
488     * key is the column that needs to be sortable, and the value is db column to 
489     * sort by. Often, the key and value will be the same, but this is not always
490     * the case (as the value is a column name from the database, not the list table).
491     * 
492     * @return array An associative array containing all the columns that should be sortable: 'slugs'=>array('data_values',bool)
493     **************************************************************************/
494    function get_sortable_columns() {
495        $sortable_columns = array(
496            'date_published'  	=> array('date_published',false),     //true means its already sorted
497            'end_date'  		=> array('end_date',false),
498            'auction_title'     => array('auction_title',false),
499            'status'            => array('status',false)
500        );
501        return $sortable_columns;
502    }
503    
504    
505    /** ************************************************************************
506     * Optional. If you need to include bulk actions in your list table, this is
507     * the place to define them. Bulk actions are an associative array in the format
508     * 'slug'=>'Visible Title'
509     * 
510     * Also note that list tables are not automatically wrapped in <form> elements,
511     * so you will need to create those manually in order for bulk actions to function.
512     * 
513     * @return array An associative array containing all the bulk actions: 'slugs'=>'Visible Titles'
514     **************************************************************************/
515    function get_bulk_actions() {
516        $actions = array(
517            'verify'    => __('Verify with eBay','wplister'),
518            'publish2e' => __('Publish to eBay','wplister'),
519            'update' 	=> __('Update details from eBay','wplister'),
520            'reselect'  => __('Select another profile','wplister'),
521            'reapply'   => __('Re-apply profile','wplister'),
522            'revise'    => __('Revise items','wplister'),
523            'end_item'  => __('End listings','wplister'),
524            'relist'    => __('Re-list ended items','wplister'),
525            'delete'    => __('Delete listings','wplister')
526        );
527        return $actions;
528    }
529    
530    
531    /** ************************************************************************
532     * Optional. You can handle your bulk actions anywhere or anyhow you prefer.
533     * For this example package, we will handle it in the class to keep things
534     * clean and organized.
535     * 
536     * @see $this->prepare_items()
537     **************************************************************************/
538    function process_bulk_action() {
539        global $wbdb;
540        
541        //Detect when a bulk action is being triggered...
542        if( 'delete'===$this->current_action() ) {
543            #wp_die('Items deleted (or they would be if we had items to delete)!');
544            #$wpdb->query("DELETE FROM {$wpdb->prefix}ebay_auctions WHERE id = ''",)
545        }
546
547        if( 'verify'===$this->current_action() ) {
548			#echo "<br>verify handler<br>";			
549        }
550        
551    }
552
553    // status filter links
554    // http://wordpress.stackexchange.com/questions/56883/how-do-i-create-links-at-the-top-of-wp-list-table
555    function get_views(){
556       $views = array();
557       $current = ( !empty($_REQUEST['listing_status']) ? $_REQUEST['listing_status'] : 'all');
558
559       // get listing status summary
560       $lm = new ListingsModel();
561       $summary = $lm->getStatusSummary();
562
563       // All link
564       $class = ($current == 'all' ? ' class="current"' :'');
565       $all_url = remove_query_arg('listing_status');
566       $views['all']  = "<a href='{$all_url }' {$class} >".__('All','wplister')."</a>";
567       $views['all'] .= '<span class="count">('.$this->total_items.')</span>';
568
569       // prepared link
570       $prepared_url = add_query_arg('listing_status','prepared');
571       $class = ($current == 'prepared' ? ' class="current"' :'');
572       $views['prepared'] = "<a href='{$prepared_url}' {$class} >".__('Prepared','wplister')."</a>";
573       if ( isset($summary->prepared) ) $views['prepared'] .= '<span class="count">('.$summary->prepared.')</span>';
574
575       // verified link
576       $verified_url = add_query_arg('listing_status','verified');
577       $class = ($current == 'verified' ? ' class="current"' :'');
578       $views['verified'] = "<a href='{$verified_url}' {$class} >".__('Verified','wplister')."</a>";
579       if ( isset($summary->verified) ) $views['verified'] .= '<span class="count">('.$summary->verified.')</span>';
580
581       // published link
582       $published_url = add_query_arg('listing_status','published');
583       $class = ($current == 'published' ? ' class="current"' :'');
584       $views['published'] = "<a href='{$published_url}' {$class} >".__('Published','wplister')."</a>";
585       if ( isset($summary->published) ) $views['published'] .= '<span class="count">('.$summary->published.')</span>';
586
587       // changed link
588       $changed_url = add_query_arg('listing_status','changed');
589       $class = ($current == 'changed' ? ' class="current"' :'');
590       $views['changed'] = "<a href='{$changed_url}' {$class} >".__('Changed','wplister')."</a>";
591       if ( isset($summary->changed) ) $views['changed'] .= '<span class="count">('.$summary->changed.')</span>';
592
593       // ended link
594       $ended_url = add_query_arg('listing_status','ended');
595       $class = ($current == 'ended' ? ' class="current"' :'');
596       $views['ended'] = "<a href='{$ended_url}' {$class} >".__('Ended','wplister')."</a>";
597       if ( isset($summary->ended) ) $views['ended'] .= '<span class="count">('.$summary->ended.')</span>';
598
599       return $views;
600    }    
601    
602    /** ************************************************************************
603     * REQUIRED! This is where you prepare your data for display. This method will
604     * usually be used to query the database, sort and filter the data, and generally
605     * get it ready to be displayed. At a minimum, we should set $this->items and
606     * $this->set_pagination_args(), although the following properties and methods
607     * are frequently interacted with here...
608     * 
609     * @uses $this->_column_headers
610     * @uses $this->items
611     * @uses $this->get_columns()
612     * @uses $this->get_sortable_columns()
613     * @uses $this->get_pagenum()
614     * @uses $this->set_pagination_args()
615     **************************************************************************/
616    function prepare_items( $items = false ) {
617        
618        // process bulk actions
619        $this->process_bulk_action();
620                        
621        // get pagination state
622        $current_page = $this->get_pagenum();
623        $per_page = $this->get_items_per_page('listings_per_page', 20);
624        
625        // define columns
626        $this->_column_headers = $this->get_column_info();
627        
628        // fetch listings from model - if no parameter passed
629        if ( ! $items ) {
630
631            $listingsModel = new ListingsModel();
632            $this->items = $listingsModel->getPageItems( $current_page, $per_page );
633            $this->total_items = $listingsModel->total_items;
634
635        } else {
636
637            $this->items = $items;
638            $this->total_items = count($items);
639
640        }
641
642        // register our pagination options & calculations.
643        $this->set_pagination_args( array(
644            'total_items' => $this->total_items,
645            'per_page'    => $per_page,
646            'total_pages' => ceil($this->total_items/$per_page)
647        ) );
648
649    }
650
651    // small helper to make sure $price is not a string    
652    function number_format( $price, $decimals = 2 ) {
653        return number_format_i18n( floatval($price), $decimals );
654    }
655    
656    
657}
658