/**
     * @param $message - an array holding a result from the shub_message row
     * @param array $existing_rows - optional array passed in from the individual extension already having data for this row.
     * @return array
     */
    public function output_row($message, $existing_rows = array())
    {
        $extension_message = $this->get_message(false, false, $message['shub_message_id']);
        $messages = $extension_message->get_comments();
        $return = array();
        ob_start();
        echo $this->get_friendly_icon();
        ?>
        <a href="<?php 
        echo $extension_message->get_link();
        ?>
"
           target="_blank"><?php 
        echo htmlspecialchars($extension_message->get('account') ? $extension_message->get('account')->get('account_name') : 'Item');
        ?>
</a> <br/>
        <?php 
        echo htmlspecialchars($extension_message->get_type_pretty());
        ?>
        <?php 
        $return['shub_column_account'] = ob_get_clean();
        ob_start();
        $shub_product_id = $extension_message->get_product_id();
        $product_data = array();
        $item_data = array();
        $item = $extension_message->get('item');
        if (!$shub_product_id && $item) {
            $shub_product_id = $item->get('shub_product_id');
            $item_data = $item->get('item_data');
            if (!is_array($item_data)) {
                $item_data = array();
            }
        }
        if ($shub_product_id) {
            $shub_product = new SupportHubProduct();
            $shub_product->load($shub_product_id);
            $product_data = $shub_product->get('product_data');
            if (!empty($product_data['image'])) {
                ?>
                <img src="<?php 
                echo esc_attr($product_data['image']);
                ?>
" class="shub_friendly_icon">
            <?php 
            }
            ?>
            <?php 
            if (!empty($product_data['url'])) {
                ?>
                <a href="<?php 
                echo esc_url($product_data['url']);
                ?>
" target="_blank"><?php 
                echo htmlspecialchars($shub_product->get('product_name'));
                ?>
</a>
                <?php 
            } else {
                ?>
 <?php 
                echo htmlspecialchars($shub_product->get('product_name'));
                ?>
 <?php 
            }
        }
        $return['shub_column_product'] = ob_get_clean();
        $return['shub_column_time'] = '<span class="shub_time" data-time="' . esc_attr($extension_message->get('last_active')) . '" data-date="' . esc_attr(shub_print_date($extension_message->get('last_active'), true)) . '">' . shub_pretty_date($extension_message->get('last_active')) . '</span>';
        ob_start();
        // work out who this is from.
        $from = $extension_message->get_from();
        ?>
        <div class="shub_from_holder">
            <div class="shub_from_full">
                <?php 
        foreach ($from as $id => $from_data) {
            ?>
                    <div>
                        <a href="<?php 
            echo esc_url($from_data->get_link());
            ?>
" target="_blank"><img src="<?php 
            echo esc_attr($from_data->get_image());
            ?>
" class="shub_from_picture"></a> <?php 
            echo htmlspecialchars($from_data->get_name());
            ?>
                    </div>
                    <?php 
        }
        ?>
            </div>
            <?php 
        reset($from);
        if (isset($from_data)) {
            echo '<a href="' . $from_data->get_link() . '" target="_blank">' . '<img src="' . esc_attr($from_data->get_image()) . '" class="shub_from_picture"></a> ';
            echo '<span class="shub_from_count">';
            if (count($from) > 1) {
                echo '+' . (count($from) - 1);
            }
            echo '</span>';
        }
        ?>
        </div>
        <?php 
        $return['shub_column_from'] = ob_get_clean();
        ob_start();
        ?>
        <span style="float:right;">
		    <?php 
        echo count($messages) > 0 ? '(' . count($messages) . ')' : '';
        ?>
	    </span>
        <div class="shub_message_summary<?php 
        echo !isset($message['read_time']) || !$message['read_time'] ? ' unread' : '';
        ?>
"> <?php 
        // todo - pull in comments here, not just title/summary
        // todo - style customer and admin replies differently (eg <em> so we can easily see)
        $title = strip_tags($extension_message->get('title'));
        $summary = strip_tags($extension_message->get('summary'));
        echo htmlspecialchars(strlen($title) > 80 ? substr($title, 0, 80) . '...' : $title) . ($summary != $title ? '<br/>' . htmlspecialchars(strlen($summary) > 80 ? substr($summary, 0, 80) . '...' : $summary) : '');
        ?>
        </div>
        <?php 
        $return['shub_column_summary'] = ob_get_clean();
        ob_start();
        ?>
        <a href="<?php 
        echo $extension_message->link_open();
        ?>
" class="socialmessage_open shub_modal button" data-modaltitle="<?php 
        echo esc_attr($title);
        ?>
" data-network="<?php 
        echo esc_attr($this->id);
        ?>
" data-message_id="<?php 
        echo (int) $extension_message->get('shub_message_id');
        ?>
"><?php 
        _e('Open');
        ?>
</a>
        <?php 
        if ($extension_message->get('shub_status') == _shub_MESSAGE_STATUS_ANSWERED) {
            ?>
            <a href="#" class="socialmessage_action shub_message_action button"
               data-action="set-unanswered" data-post="<?php 
            echo esc_attr(json_encode(array('network' => $this->id, 'shub_message_id' => $extension_message->get('shub_message_id'))));
            ?>
"><?php 
            _e('Inbox');
            ?>
</a>
        <?php 
        } else {
            ?>
            <a href="#" class="socialmessage_action shub_message_action button"
               data-action="set-answered" data-post="<?php 
            echo esc_attr(json_encode(array('network' => $this->id, 'shub_message_id' => $extension_message->get('shub_message_id'))));
            ?>
"><?php 
            _e('Archive');
            ?>
</a>
        <?php 
        }
        ?>
        <?php 
        $return['shub_column_action'] = ob_get_clean();
        return $return;
    }
 public function update_author_sale_history($debug = false, $do_all = false)
 {
     return;
     // todo: save sale history in db with no username/api key just for stats
     $api = $this->get_api();
     // how many days do we want to go back? maybe 60 days to start with?
     $last_sale = get_option('supporthub_envato_author_sales_last', false);
     if (!$last_sale) {
         $last_sale = strtotime('-360 days');
     }
     $last_sale_in_this_batch = 0;
     $page = 1;
     while (true) {
         $recent_sales = $api->api('v2/market/author/sales?page=' . $page, array(), true);
         //            echo "Recent sales are: ";print_r($recent_sales);exit;
         if ($debug) {
             echo "Page {$page} of sales data contained " . count($recent_sales) . " results.<br>\n";
         }
         $page++;
         if (!$recent_sales || !is_array($recent_sales)) {
             break;
         }
         foreach ($recent_sales as $recent_sale) {
             if ($recent_sale && !empty($recent_sale['sold_at']) && !empty($recent_sale['code']) && !empty($recent_sale['item']['id'])) {
                 //                    echo $recent_sale['sold_at']."<br>";
                 // add this to the database, or break if we already have this one in the db.
                 $sale_time = strtotime($recent_sale['sold_at']);
                 // we might already have this one in our database
                 // unless we are doing the intial seed
                 $existing_purchase = shub_get_single('shub_envato_purchase', array('purchase_code'), array($recent_sale['code']));
                 if ($existing_purchase) {
                     if (!$do_all) {
                         break 2;
                         // stop processing once we reach one we've already saved
                     }
                     continue;
                     // exists already in the db, skip to next one.
                 }
                 $last_sale_in_this_batch = max($last_sale_in_this_batch, $sale_time);
                 // todo: check if they add username to the system, for now we use a 0 shub_user_id because we're unsure which user this purchase is related to (without doing another separate purchase call)
                 if ($debug) {
                     echo " - adding new sale to database ( " . shub_print_date($sale_time, true) . " - " . $recent_sale['item']['name'] . " )...<br>\n";
                 }
                 // for now we do all processing based on this purchase code. SLOW. but until we get usernames in the buyer result there is no other way.
                 //                    echo "Query this code: ".$recent_sale['code'];exit;
                 SupportHub::getInstance()->message_managers['envato']->pull_purchase_code($api, $recent_sale['code'], $recent_sale);
                 update_option('supporthub_envato_author_sales_last', $last_sale_in_this_batch);
                 continue;
                 // save this purchase code into the db
                 // find the product this purchase is related to
                 $existing_products = SupportHub::getInstance()->get_products();
                 // check if this item exists already
                 $exists = false;
                 foreach ($existing_products as $existing_product) {
                     if (isset($existing_product['product_data']['envato_item_id']) && $existing_product['product_data']['envato_item_id'] == $recent_sale['item']['id']) {
                         $exists = $existing_product['shub_product_id'];
                     }
                 }
                 $newproduct = new SupportHubProduct();
                 if (!$exists) {
                     $newproduct->create_new();
                     if (!$newproduct->get('product_name')) {
                         $newproduct->update('product_name', $recent_sale['item']['name']);
                     }
                     $existing_product_data = $newproduct->get('product_data');
                     if (!is_array($existing_product_data)) {
                         $existing_product_data = array();
                     }
                     if (empty($existing_product_data['envato_item_id'])) {
                         $existing_product_data['envato_item_id'] = $recent_sale['item']['id'];
                     }
                     if (empty($existing_product_data['envato_item_data'])) {
                         $existing_product_data['envato_item_data'] = $recent_sale['item'];
                     }
                     if (empty($existing_product_data['image'])) {
                         $existing_product_data['image'] = $recent_sale['item']['thumbnail_url'];
                     }
                     if (empty($existing_product_data['url'])) {
                         $existing_product_data['url'] = $recent_sale['item']['url'];
                     }
                     $newproduct->update('product_data', $existing_product_data);
                 } else {
                     $newproduct->load($exists);
                 }
                 if ($newproduct->get('shub_product_id')) {
                     // product has been added
                     // time to add it to the purchase db
                     // check if this already exists in the db
                     $existing_purchase = shub_get_single('shub_envato_purchase', array('purchase_code'), array($recent_sale['code']));
                     if (!$existing_purchase) {
                         $shub_envato_purchase_id = shub_update_insert('shub_envato_purchase_id', false, 'shub_envato_purchase', array('shub_user_id' => 0, 'shub_product_id' => $newproduct->get('shub_product_id'), 'purchase_time' => $sale_time, 'envato_user_id' => 0, 'purchase_code' => $recent_sale['code'], 'api_type' => 'author/sales', 'purchase_data' => json_encode($recent_sale)));
                     } else {
                         $shub_envato_purchase_id = $existing_purchase['shub_envato_purchase_id'];
                     }
                     if ($shub_envato_purchase_id) {
                         // we have a purchase in the db
                         // add or update the support expiry based on this purchase history.
                         // work out when this purchase support expires
                         // this is the expiry date returned in the api or just 6 months from the original purchase date.
                         $support_expiry_time = strtotime("+6 months", $sale_time);
                         // todo - check for this expiry time in the new api results.
                         $existing_support = shub_get_single('shub_envato_support', array('shub_envato_purchase_id'), array($shub_envato_purchase_id));
                         if ($existing_support && $existing_support['shub_envato_support_id'] && $existing_support['start_time'] == $sale_time) {
                             // check the existing support expiry matches the one we have in the database.
                             if ($existing_support['end_time'] < $support_expiry_time) {
                                 // we have a support extension!
                                 $shub_envato_support_id = shub_update_insert('shub_envato_support_id', $existing_support['shub_envato_support_id'], 'shub_envato_support', array('end_time' => $support_expiry_time, 'api_type' => 'buyer/purchases', 'support_data' => json_encode($recent_sale)));
                             }
                         } else {
                             // we are adding a new support entry
                             $shub_envato_support_id = shub_update_insert('shub_envato_support_id', false, 'shub_envato_support', array('shub_user_id' => 0, 'shub_product_id' => $newproduct->get('shub_product_id'), 'shub_envato_purchase_id' => $shub_envato_purchase_id, 'start_time' => $sale_time, 'end_time' => $support_expiry_time, 'api_type' => 'author/sales', 'support_data' => json_encode($recent_sale)));
                         }
                     }
                 }
             }
         }
     }
 }
 public function filter_message_user_sidebar($user_bits, $shub_user_ids)
 {
     // find purchases for these user ids and if they are in a valid support term.
     if (!empty($shub_user_ids) && is_array($shub_user_ids)) {
         foreach ($shub_user_ids as $shub_user_id) {
             if ((int) $shub_user_id > 0) {
                 // find purchases.
                 $total = 0;
                 $purchases = shub_get_multiple('shub_envato_purchase', array('shub_user_id' => $shub_user_id));
                 foreach ($purchases as $purchase) {
                     if ($purchase['shub_product_id']) {
                         $purchase_product = new SupportHubProduct($purchase['shub_product_id']);
                         $data = $purchase_product->get('product_data');
                         if (!empty($data['envato_item_data']['item'])) {
                             $support_text = '<span class="buyer_status_badges">';
                             $support = shub_get_single('shub_envato_support', 'shub_envato_purchase_id', $purchase['shub_envato_purchase_id']);
                             if ($support && !empty($support['end_time']) && $support['end_time'] <= time()) {
                                 // WHOPPS. I got this wrong in the DB initially. Hack to double check purchase happened before new support terms
                                 if (strtotime($purchase['purchase_time']) < strtotime("2015-09-01")) {
                                     $support['end_time'] = strtotime("+6 months", strtotime("2015-09-01"));
                                 }
                             }
                             if ($support && !empty($support['end_time']) && $support['end_time'] > time()) {
                                 $support_text .= '<span class="buyer_badge supported">' . shub_print_date($support['end_time']) . '</span>';
                             } else {
                                 if ($support && !empty($support['end_time'])) {
                                     $support_text .= '<span class="buyer_badge unsupported">' . shub_print_date($support['end_time']) . '</span>';
                                 } else {
                                     $support_text .= '<span class="buyer_badge unsupported">Unknown</span>';
                                 }
                             }
                             $support_text .= '</span>';
                             $user_bits[] = array('Purchase', esc_html($data['envato_item_data']['item']) . ' on ' . shub_print_date($purchase['purchase_time']) . ' support until ' . $support_text);
                             $sale_data = @json_decode($purchase['purchase_data'], true);
                             if ($sale_data && !empty($sale_data['amount'])) {
                                 $total += $sale_data['amount'];
                             }
                             if ($sale_data && !empty($sale_data['support_amount'])) {
                                 $total += $sale_data['support_amount'];
                             }
                             if (!$sale_data) {
                                 print_r($purchase);
                             }
                         }
                     } else {
                         // failed API lookup, show purchase code instead.
                         // todo: a re-lookup button.
                         $user_bits[] = array('Failed Purchase Code', $purchase['purchase_code']);
                     }
                 }
                 if ($total) {
                     $user_bits[] = array('Total', '$' . number_format($total, 2, ".", ","));
                 }
             }
         }
     }
     return $user_bits;
 }
 public function get_buyer_status($shub_user_id)
 {
     $return = array();
     if ($shub_product_id = $this->get_product_id()) {
         // thid is a duplicate of the code in class.shub_envato.php to determine if a user has purchased a product
         // todo: try to make them both use the same cached data.
         $purchases = shub_get_multiple('shub_envato_purchase', array('shub_user_id' => $shub_user_id, 'shub_product_id' => $shub_product_id));
         foreach ($purchases as $purchase) {
             if ($purchase['shub_product_id']) {
                 $purchase_product = new SupportHubProduct($purchase['shub_product_id']);
                 $data = $purchase_product->get('product_data');
                 if (!empty($data['envato_item_data']['item'])) {
                     $return['purchased'] = true;
                     $support = shub_get_single('shub_envato_support', 'shub_envato_purchase_id', $purchase['shub_envato_purchase_id']);
                     if ($support && !empty($support['end_time']) && $support['end_time'] <= time()) {
                         // WHOPPS. I got this wrong in the DB initially. Hack to double check purchase happened before new support terms
                         if (strtotime($purchase['purchase_time']) < strtotime("2015-09-01")) {
                             $support['end_time'] = strtotime("+6 months", strtotime("2015-09-01"));
                         }
                     }
                     if ($support && !empty($support['end_time']) && $support['end_time'] > time()) {
                         $return['supported'] = true;
                     }
                 }
             }
         }
         if (empty($return['purchased'])) {
             $return['presale'] = true;
         }
         if (empty($return['supported']) && empty($return['presale'])) {
             $return['unsupported'] = true;
         }
     } else {
         $return['unknown'] = true;
     }
     return $return;
 }
 public function init()
 {
     if (isset($_REQUEST['_process'])) {
         // fix up WordPress bork:
         // todo: don't overwrite default superglobals, run stripslashes every time before we use the content, because another plugin might be stripslashing already
         $_POST = stripslashes_deep($_POST);
         $_GET = stripslashes_deep($_GET);
         $_REQUEST = stripslashes_deep($_REQUEST);
         $process_action = $_REQUEST['_process'];
         $process_options = array();
         $shub_message_id = false;
         if ($process_action == 'send_shub_message' && check_admin_referer('shub_send-message')) {
             // we are sending a social message! yay!
             $send_time = time();
             // default: now
             if (isset($_POST['schedule_date']) && isset($_POST['schedule_time']) && !empty($_POST['schedule_date']) && !empty($_POST['schedule_time'])) {
                 $date = $_POST['schedule_date'];
                 $time_hack = $_POST['schedule_time'];
                 $time_hack = str_ireplace('am', '', $time_hack);
                 $time_hack = str_ireplace('pm', '', $time_hack);
                 $bits = explode(':', $time_hack);
                 if (strpos($_POST['schedule_time'], 'pm')) {
                     $bits[0] += 12;
                 }
                 // add the time if it exists
                 $date .= ' ' . implode(':', $bits) . ':00';
                 $send_time = strtotime($date);
                 //echo $date."<br>".$send_time."<br>".shub_print_date($send_time,true);exit;
             } else {
                 if (isset($_POST['schedule_date']) && !empty($_POST['schedule_date'])) {
                     $send_time = strtotime($_POST['schedule_date']);
                 }
             }
             // wack a new entry into the shub_message database table and pass that onto our message_managers below
             $shub_message_id = shub_update_insert('shub_message_id', false, 'shub_message', array('post_id' => isset($_POST['post_id']) ? $_POST['post_id'] : 0, 'sent_time' => $send_time));
             if ($shub_message_id) {
                 $process_options['shub_message_id'] = $shub_message_id;
                 $process_options['send_time'] = $send_time;
             } else {
                 die('Failed to create social message');
             }
             /* @var $message_manager shub_facebook */
             $message_count = 0;
             foreach ($this->message_managers as $name => $message_manager) {
                 $message_count += $message_manager->handle_process($process_action, $process_options);
             }
             if ($shub_message_id && !$message_count) {
                 // remove the gobal social message as nothing worked.
                 shub_delete_from_db('shub_message', 'shub_message_id', $shub_message_id);
             } else {
                 if ($shub_message_id) {
                     shub_update_insert('shub_message_id', $shub_message_id, 'shub_message', array('message_count' => $message_count));
                 }
             }
             if (isset($_POST['debug']) && $_POST['debug']) {
                 echo "<br><hr> Successfully sent {$message_count} messages <hr><br><pre>";
                 print_r($_POST);
                 print_r($process_options);
                 echo "</pre><hr><br>Completed";
                 exit;
             }
             header("Location: admin.php?page=support_hub_sent");
             exit;
         } else {
             if ($process_action == 'save_general_settings') {
                 if (check_admin_referer('save-general-settings')) {
                     if (isset($_POST['possible_shub_manager_enabled'])) {
                         foreach ($_POST['possible_shub_manager_enabled'] as $id => $tf) {
                             if (isset($_POST['shub_manager_enabled'][$id]) && $_POST['shub_manager_enabled'][$id]) {
                                 update_option('shub_manager_enabled_' . $id, 1);
                             } else {
                                 update_option('shub_manager_enabled_' . $id, 0);
                             }
                         }
                         header("Location: admin.php?page=support_hub_settings");
                         exit;
                     }
                 }
             } else {
                 if ($process_action == 'save_log_settings') {
                     if (check_admin_referer('save-log-settings')) {
                         if (!empty($_POST['enable_logging'])) {
                             update_option('shub_logging_enabled', time() + 3600 * 24);
                         }
                         if (!empty($_POST['remove_logs'])) {
                             global $wpdb;
                             $wpdb->query($wpdb->prepare("DELETE FROM `" . _support_hub_DB_PREFIX . "shub_log` WHERE log_time <= %d", $_POST['remove_logs']));
                         }
                         header("Location: admin.php?page=support_hub_settings&tab=logs");
                         exit;
                     }
                 } else {
                     if ($process_action == 'save_encrypted_vault') {
                         if (check_admin_referer('save-encrypted-vault') && !empty($_POST['public_key']) && !empty($_POST['private_key'])) {
                             update_option('shub_encrypt_public_key', $_POST['public_key']);
                             update_option('shub_encrypt_private_key', $_POST['private_key']);
                             header("Location: admin.php?page=support_hub_settings&tab=extra");
                             exit;
                         }
                     } else {
                         if ($process_action == 'save_extra_details') {
                             $shub_extra_id = !empty($_REQUEST['shub_extra_id']) ? (int) $_REQUEST['shub_extra_id'] : 0;
                             if (check_admin_referer('save-extra' . $shub_extra_id)) {
                                 $shub_extra = new SupportHubExtra($shub_extra_id);
                                 if (isset($_REQUEST['butt_delete'])) {
                                     $shub_extra->delete();
                                     header("Location: admin.php?page=support_hub_settings&tab=extra");
                                     exit;
                                 }
                                 if (!$shub_extra->get('shub_extra_id')) {
                                     $shub_extra->create_new();
                                 }
                                 $shub_extra->update($_POST);
                                 $shub_extra_id = $shub_extra->get('shub_extra_id');
                                 header("Location: admin.php?page=support_hub_settings&tab=extra");
                                 //&shub_extra_id=" . $shub_extra_id );
                                 exit;
                             }
                         } else {
                             if ($process_action == 'save_product_details') {
                                 $shub_product_id = !empty($_REQUEST['shub_product_id']) ? (int) $_REQUEST['shub_product_id'] : 0;
                                 if (check_admin_referer('save-product' . $shub_product_id)) {
                                     $shub_product = new SupportHubProduct($shub_product_id);
                                     if (isset($_REQUEST['butt_delete'])) {
                                         $shub_product->delete();
                                         header("Location: admin.php?page=support_hub_settings&tab=products");
                                         exit;
                                     }
                                     if (!$shub_product->get('shub_product_id')) {
                                         $shub_product->create_new();
                                     }
                                     $shub_product->update($_POST);
                                     $shub_product_id = $shub_product->get('shub_product_id');
                                     header("Location: admin.php?page=support_hub_settings&tab=products");
                                     //&shub_product_id=" . $shub_product_id );
                                     exit;
                                 }
                             } else {
                                 // just process each request normally:
                                 /* @var $message_manager shub_facebook */
                                 foreach ($this->message_managers as $name => $message_manager) {
                                     $message_manager->handle_process($process_action, $process_options);
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
 }
 public function update_purchase_history()
 {
     $tokens = shub_get_multiple('shub_envato_oauth', array('shub_user_id' => $this->shub_user_id));
     // find the latest token for this user, per account.
     $account_tokens = array();
     // if any of them have expired, refresh the token from the api
     foreach ($tokens as $token) {
         if (!$token['shub_account_id']) {
             continue;
         }
         if (!isset($account_tokens[$token['shub_account_id']]) || $token['expire_time'] > $account_tokens[$token['shub_account_id']]['expire_time']) {
             $account_tokens[$token['shub_account_id']] = $token;
         }
     }
     foreach ($account_tokens as $account_token) {
         $shub_envato_account = new shub_envato_account($account_token['shub_account_id']);
         // found the account, pull in the API and build the url
         $api = $shub_envato_account->get_api();
         $api->set_manual_token($account_token);
         if ($account_token['expire_time'] <= time()) {
             // renew this token!
             $new_access_token = $api->refresh_token();
             if ($new_access_token) {
                 shub_update_insert('shub_envato_oauth_id', $account_token['shub_envato_oauth_id'], 'shub_envato_oauth', array('access_token' => $new_access_token, 'expire_time' => time() + 3600));
             } else {
                 echo 'Token refresh failed';
                 return false;
             }
         }
         $api_result = $api->api('v1/market/private/user/username.json', array(), false);
         $api_result_email = $api->api('v1/market/private/user/email.json', array(), false);
         if ($api_result && !empty($api_result['username'])) {
             $this->add_unique_meta('envato_username', $api_result['username']);
         }
         if ($api_result_email && !empty($api_result_email['email'])) {
             $email = trim(strtolower($api_result_email['email']));
             // todo: not sure if best to update users eamail , if they change email accounts and stuff
             $this->update('user_email', $email);
         }
         $api_result_purchase_history = $api->api('v2/market/buyer/purchases', array(), false);
         // store this purchase history in our db for later use.
         if ($api_result_purchase_history && !empty($api_result_purchase_history['buyer']['id']) && !empty($api_result_purchase_history['buyer']['username']) && $api_result_purchase_history['buyer']['username'] == $api_result['username']) {
             // we have the buyer ID! yay! this is better than a username.
             $this->add_unique_meta('envato_user_id', $api_result_purchase_history['buyer']['id']);
             if (!empty($api_result_purchase_history['purchases']) && is_array($api_result_purchase_history['purchases'])) {
                 foreach ($api_result_purchase_history['purchases'] as $purchase) {
                     if (!empty($purchase['item']['id'])) {
                         // todo: beg envato to add the purchase code to this output so we can link it together correctly.
                         // find out which shub product this is for
                         // if we cannot find one then we create one. this helps when new items are made.
                         $existing_products = SupportHub::getInstance()->get_products();
                         // check if this item exists already
                         $exists = false;
                         foreach ($existing_products as $existing_product) {
                             if (isset($existing_product['product_data']['envato_item_id']) && $existing_product['product_data']['envato_item_id'] == $purchase['item']['id']) {
                                 $exists = $existing_product['shub_product_id'];
                             }
                         }
                         $newproduct = new SupportHubProduct();
                         if (!$exists) {
                             $newproduct->create_new();
                         } else {
                             $newproduct->load($exists);
                         }
                         if (!$newproduct->get('product_name')) {
                             $newproduct->update('product_name', $purchase['item']['name']);
                         }
                         $existing_product_data = $newproduct->get('product_data');
                         if (!is_array($existing_product_data)) {
                             $existing_product_data = array();
                         }
                         if (empty($existing_product_data['envato_item_id'])) {
                             $existing_product_data['envato_item_id'] = $purchase['item']['id'];
                         }
                         if (empty($existing_product_data['envato_item_data'])) {
                             $existing_product_data['envato_item_data'] = $purchase['item'];
                         }
                         if (empty($existing_product_data['image'])) {
                             $existing_product_data['image'] = $purchase['item']['thumbnail_url'];
                         }
                         if (empty($existing_product_data['url'])) {
                             $existing_product_data['url'] = $purchase['item']['url'];
                         }
                         $newproduct->update('product_data', $existing_product_data);
                         if ($newproduct->get('shub_product_id')) {
                             // product has been added
                             // time to add it to the purchase db
                             // check if this already exists in the db
                             $existing_purchase = shub_get_single('shub_envato_purchase', array('purchase_code'), array($purchase['code']));
                             if (!$existing_purchase) {
                                 $shub_envato_purchase_id = shub_update_insert('shub_envato_purchase_id', false, 'shub_envato_purchase', array('shub_user_id' => $this->get('shub_user_id'), 'shub_product_id' => $newproduct->get('shub_product_id'), 'purchase_time' => strtotime($purchase['sold_at']), 'envato_user_id' => $api_result_purchase_history['buyer']['id'], 'purchase_code' => $purchase['code'], 'api_type' => 'buyer/purchases', 'purchase_data' => json_encode($purchase)));
                             } else {
                                 if (!$existing_purchase['shub_user_id']) {
                                     shub_update_insert('shub_envato_purchase_id', $existing_purchase['shub_envato_purchase_id'], 'shub_envato_purchase', array('shub_user_id' => $this->get('shub_user_id')));
                                 }
                                 $shub_envato_purchase_id = $existing_purchase['shub_envato_purchase_id'];
                             }
                             if ($shub_envato_purchase_id) {
                                 // we have a purchase in the db
                                 // add or update the support expiry based on this purchase history.
                                 // work out when this purchase support expires
                                 // this is the expiry date returned in the api or just 6 months from the original purchase date.
                                 $support_expiry_time = strtotime("+6 months", strtotime($purchase['sold_at']));
                                 // todo - check for this expiry time in the new api results.
                                 $existing_support = shub_get_single('shub_envato_support', array('shub_envato_purchase_id'), array($shub_envato_purchase_id));
                                 if ($existing_support && empty($existing_support['shub_user_id'])) {
                                     shub_update_insert('shub_envato_support_id', $existing_support['shub_envato_support_id'], 'shub_envato_support', array('shub_user_id' => $this->get('shub_user_id')));
                                 }
                                 if ($existing_support && $existing_support['shub_envato_support_id'] && $existing_support['start_time'] == strtotime($purchase['sold_at'])) {
                                     // check the existing support expiry matches the one we have in the database.
                                     if ($existing_support['end_time'] < $support_expiry_time) {
                                         // we have a support extension!
                                         $shub_envato_support_id = shub_update_insert('shub_envato_support_id', $existing_support['shub_envato_support_id'], 'shub_envato_support', array('end_time' => $support_expiry_time, 'api_type' => 'buyer/purchases', 'support_data' => json_encode($purchase)));
                                     }
                                 } else {
                                     // we are adding a new support entry
                                     $shub_envato_support_id = shub_update_insert('shub_envato_support_id', false, 'shub_envato_support', array('shub_user_id' => $this->get('shub_user_id'), 'shub_product_id' => $newproduct->get('shub_product_id'), 'shub_envato_purchase_id' => $shub_envato_purchase_id, 'start_time' => strtotime($purchase['sold_at']), 'end_time' => $support_expiry_time, 'api_type' => 'buyer/purchases', 'support_data' => json_encode($purchase)));
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     return true;
 }