Advertisement
Guest User

priceupdate

a guest
Jun 30th, 2012
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 15.71 KB | None | 0 0
  1.  
  2. <?php
  3. /*
  4. Plugin Name: Price Update
  5. Plugin URI: http://mtekk.us/code/
  6. Description: Updates product prices from a xml file
  7. Version: 0.0.1
  8. Author: John Havlik
  9. Author URI: http://mtekk.us
  10. */
  11. /*
  12.     Copyright 2011 John Havlik
  13.     This program is free software; you can redistribute it and/or modify
  14.     it under the terms of the GNU General Public License as published by
  15.     the Free Software Foundation; either version 2 of the License, or
  16.     (at your option) any later version.
  17.     This program is distributed in the hope that it will be useful,
  18.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20.     GNU General Public License for more details.
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  24. */
  25. //Do a PHP version check, require 5.2 or newer
  26. if(version_compare(phpversion(), '5.2.0', '<'))
  27. {
  28.     //Only purpose of this function is to echo out the PHP version error
  29.     function bcn_phpold()
  30.     {
  31.         printf('<div class="error"><p>' . __('Your PHP version is too old, please upgrade to a newer version. Your version is %s, Price Update requires %s', 'pr_upate') . '</p></div>', phpversion(), '5.2.0');
  32.     }
  33.     //If we are in the admin, let's print a warning then return
  34.     if(is_admin())
  35.     {
  36.         add_action('admin_notices', 'bcn_phpold');
  37.     }
  38.     return;
  39. }
  40. //Include admin base class
  41. if(!class_exists('mtekk_admin'))
  42. {
  43.     require_once(dirname(__FILE__) . '/includes/mtekk_admin_class.php');
  44. }
  45. /**
  46.  * The administrative interface class
  47.  */
  48. class PriceUpdate extends mtekk_admin
  49. {
  50.     protected $version = '0.0.1';
  51.     protected $full_name = 'Price Update';
  52.     protected $short_name = 'Price Update';
  53.     protected $access_level = 'manage_options';
  54.     protected $identifier = 'pr_upate';
  55.     protected $unique_prefix = 'prud';
  56.     protected $plugin_basename = 'price-update/price-update.php';
  57.     protected $opt = array();
  58.     /**
  59.      * __construct()
  60.      *
  61.      * Class default constructor
  62.      */
  63.     function __construct()
  64.     {
  65.         //We set the plugin basename here, could manually set it, but this is for demonstration purposes
  66.         $this->plugin_basename = plugin_dir_path(__FILE__);
  67.         register_deactivation_hook(__FILE__, array($this, 'deactivate'));
  68.         add_action($this->unique_prefix . '_cron_hook', array($this,'cron_handle'));
  69.         //Register some of our custom taxonomies
  70.         add_action('init', array($this, 'wp_init'), 0);
  71.         add_action('wp_footer', array($this, 'footer'));
  72.         //We're going to make sure we load the parent's constructor
  73.         parent::__construct();
  74.     }
  75.     /**
  76.      * admin initialisation callback function
  77.      *
  78.      * is bound to wpordpress action 'admin_init' on instantiation
  79.      *
  80.      * @return void
  81.      */
  82.     function init()
  83.     {
  84.         //We're going to make sure we run the parent's version of this function as well
  85.         parent::init();
  86.         //We can not synchronize our database options untill after the parent init runs (the reset routine must run first if it needs to)
  87.         $this->opt = get_option($this->unique_prefix . '_options');
  88.         //Admin Options update hook
  89.         if(isset($_POST[$this->unique_prefix . '_update_prices']))
  90.         {
  91.             //Do some security related things as we are not using the normal WP settings API
  92.             $this->security();
  93.             // Save Quote Form Options
  94.             $options = $this->get_config();
  95.             $options['quote_enabled'] = ((isset($_POST['quote_enabled']) && $_POST['quote_enabled'] == 'yes') ? true : false);
  96.             $options['quote_form'] = $_POST['quote_form'];
  97.             $options['quote_field'] = $_POST['quote_field'];
  98.             $options['quote_tb_title'] = $_POST['quote_tb_title'];
  99.             $options['quote_tb_width'] = (((int) $_POST['quote_tb_width'] > 0) ? $_POST['quote_tb_width'] : 640);
  100.             $options['quote_tb_height'] = (((int) $_POST['quote_tb_height'] > 0) ? $_POST['quote_tb_height'] : 440);
  101.             update_option('price-update', $options);
  102.             //Do a nonce check, prevent malicious link/form problems
  103.             check_admin_referer($this->unique_prefix . '_update_prices');
  104.             //File opening code
  105.             $file = dirname(__FILE__) . '/' . $_POST[$this->unique_prefix . '_update_prices_file'];
  106.             //Temporarily add update function on init if form has been submitted
  107.             if (file_exists($file) && !is_dir($file))
  108.                 $this->update_prices($file);
  109.         }
  110.         if(!wp_next_scheduled($this->unique_prefix . '_cron_hook'))
  111.         {
  112.             wp_schedule_event(time(), 'daily', $this->unique_prefix . '_cron_hook');
  113.         }
  114.     }
  115.     function wp_init()
  116.     {
  117.         register_taxonomy('rsci_id', array('post'), array(
  118.             'public' => false,
  119.             'hierarchical' => false,
  120.             'label' => 'RSCI ID',
  121.             'query_var' => 'rsci_id',
  122.             'rewrite' => array('slug' => 'rsci_id')
  123.         ));
  124.         $this->get_config();
  125.     }
  126.     function get_config()
  127.     {
  128.         $options = get_option('price-update');
  129.         if ($options == null)
  130.             $options = array('quote_enabled' => false, 'quote_form' => null, 'quote_field' => 'rscno',
  131.                              'quote_tb_title' => 'Contact for Quote', 'quote_tb_width' => 640, 'quote_tb_height' => 440);
  132.         return $options;
  133.     }
  134.     function footer()
  135.     {
  136.         global  $wpdb;
  137.         $options = $this->get_config();
  138.         if ($options['quote_enabled'] != true || (int) $options['quote_form'] <= 0) return false;
  139.         $container = $field = $options['quote_field'];
  140.         $tb_title = htmlspecialchars($options['quote_tb_title'], ENT_QUOTES);
  141.         $tb_width = (int) $options['quote_tb_width'];
  142.         $tb_height = (int) $options['quote_tb_height'];
  143.         $_form = $wpdb->get_var( $wpdb->prepare( "SELECT `display_meta` FROM {$wpdb->prefix}rg_form_meta WHERE `form_id`=%d", $options['quote_form']) );
  144.         if (!empty($_form))
  145.         {
  146.             $_form = @unserialize($_form);
  147.             foreach ($_form['fields'] as $_field)
  148.             {
  149.                 if ($_field['inputName'] == $field)
  150.                 {
  151.                     $field = 'input_'.$_field['id'];
  152.                     $container = 'field_'.$options['quote_form'].'_'.$_field['id'];
  153.                     break;
  154.                 }
  155.             }
  156.         }
  157.         echo <<<HTML
  158. <script type='text/javascript'>
  159. function showQuoteForm(value)
  160. {
  161.     tb_remove();
  162.     jQuery("input[name='{$field}']", "li#{$container}").val(value);
  163.     jQuery("input[name='{$field}']", "li#{$container}").attr('readonly', true);
  164.     tb_show('{$tb_title}', '#TB_inline?width={$tb_width}&height={$tb_height}&modal=false&inlineId=pu_QuoteForm', false);
  165.     return false;
  166. }
  167. </script>
  168. HTML;
  169.         echo '<div id="pu_QuoteForm" style="display: none;">';
  170.         gravity_form($options['quote_form'], true, true, false, null, true);
  171.         echo '</div>';
  172.         gravity_form_enqueue_scripts($options['quote_form'], true);
  173.     }
  174.     function add_page()
  175.     {
  176.         //Add the submenu page to "tools" menu
  177.         $hookname = add_submenu_page('tools.php', __($this->full_name, $this->identifier), $this->short_name, $this->access_level, $this->identifier, array($this, 'admin_page'));
  178.     }
  179.     /**
  180.      * security
  181.      *
  182.      * Makes sure the current user can manage options to proceed
  183.      */
  184.     function security()
  185.     {
  186.         //If the user can not manage options we will die on them
  187.         if(!current_user_can($this->access_level))
  188.         {
  189.             wp_die(__('Insufficient privileges to proceed.', $this->identifier));
  190.         }
  191.     }
  192.     function deactivate()
  193.     {
  194.         wp_clear_scheduled_hook($this->unique_prefix . '_cron_hook');
  195.     }
  196.     //Wrapper to call update_prices
  197.     function cron_handle()
  198.     {
  199.         $file = dirname(__FILE__) . '/cup8100.xml';
  200.         //Generate a file checksum, used to determine if the file was updated
  201.         $file_hash = sha1_file($file);
  202.         //See if we do not have a stored checksum or the hashes do not match
  203.         if(get_transient($this->unique_prefix . '_file_hash') === false || get_transient($this->unique_prefix . '_file_hash') !== $file_hash)
  204.         {
  205.             //Update our transient with the new hash, lasts 10 days
  206.             set_transient($this->unique_prefix . '_file_hash', $file_hash, 60*60*24*10);
  207.             //Parse the file
  208.             $this->update_prices($file);
  209.         }
  210.     }
  211.     /**
  212.      * Upgrades input options array, sets to $this->opt
  213.      *
  214.      * @param array $opts
  215.      * @param string $version the version of the passed in options
  216.      */
  217.     function opts_upgrade($opts, $version)
  218.     {
  219.     }
  220.     function update_prices($file)
  221.     {
  222.         global $wpdb;
  223.         set_time_limit(0);
  224.         remove_action('save_post','yarpp_save_cache');
  225.         if(0 == validate_file($file))
  226.         {
  227.             $start = microtime(true);
  228.             //We want to handle erros
  229.             libxml_use_internal_errors(true);
  230.             $data = implode("", file($file));
  231.             $ItemPriceList = new SimpleXMLElement($data);
  232.             if(!$ItemPriceList)
  233.             {
  234.                 $this->message['error'][] = __('Error with XML file.', 'pr_upate');
  235.                 foreach(libxml_get_errors() as $error)
  236.                 {
  237.                     $this->message['error'][] = $error;
  238.                 }
  239.             }
  240.             else
  241.             {
  242.                 $tobequoted = 0;
  243.                 $performed = 0;
  244.                 $total = 0;
  245.                 $inpost = 0;
  246.                 $post_cache = null;
  247.                 $prev_id = 0;
  248.                 $updated = 0;
  249.                 foreach($ItemPriceList->Item as $item)
  250.                 {
  251.                     $total++;
  252.                     $sprice = (string) $item->ItemPrice[0];
  253.                     //If we already have a post in the cache, let's see if it has the data we need to modify
  254.                     if($post_cache !== null && stripos($post_cache->post_content, 'id="sp'. $item->ItemCode . '"') !== false)
  255.                     {
  256.                         $query->post = $post_cache;
  257.                     }
  258.                     //We need to find the post this time
  259.                     else
  260.                     {
  261.                         $args = array(
  262.                             'tax_query' => array(
  263.                                 array('taxonomy' => 'rsci_id',
  264.                                 'terms' => sanitize_title($item->ItemCode),
  265.                                 'field' => 'slug')
  266.                             ),
  267.                             'posts_per_page' => 1);
  268.                         $query = new WP_query;
  269.                         $query->query($args);
  270.                     }
  271.                     if(isset($query->post))
  272.                     {
  273.                         //If we haven't grabed a post yet, do it
  274.                         if($post_cache == null)
  275.                         {
  276.                             $post_cache = $query->post;
  277.                         }
  278.                         //If the cache is "stale", store and refresh
  279.                         else if($query->post->ID != $post_cache->ID)
  280.                         {
  281.                             $sstart = microtime(true);
  282.                             //Update the post, from cache
  283.                             //wp_update_post($post_cache);
  284.                             //Yes, I am using a direct query, yes I know it is bad
  285.                             $query_str = $wpdb->prepare("UPDATE $wpdb->posts SET post_content = %s WHERE ID = %u AND post_status = 'publish'", array($post_cache->post_content, $post_cache->ID));
  286.                             $wpdb->query($query_str);
  287.                             $sstop = microtime(true);
  288.                             //Replace the cache
  289.                             $post_cache = $query->post;
  290.                             $updated++;
  291.         if(isset($_POST[$this->unique_prefix . '_update_prices']))
  292.         {
  293.             echo "Updated Post ID: " . $post_cache->ID . " took: " . ($sstop - $sstart) . "sec<br />\n";
  294.             ob_flush();
  295.         }
  296.                         }
  297.                         $performed++;
  298.                         //Assemble our search pattern
  299.                         $pattern = '~<td id="sp'. $item->ItemCode . '" class="sale_price">\s*<a ([^>]*)>([^<]*)</a>\s*</td>~i';
  300.                         if($item->ItemPrice == 0.0 || $sprice[0] == 'C' || $sprice[0] == 'c')
  301.                         {
  302.                             $sprice = '<a class="ptb" href="#" onclick="return showQuoteForm(\''.$item->ItemCode.'\');" rel="nofollow">Quote</a>';
  303.                             $tobequoted++;
  304.                         }
  305.                         else
  306.                         {
  307.                             if($sprice[0] !== 'C' && $sprice[0] !== 'c')
  308.                                 $sprice = sprintf('\$%.2f', $item->ItemPrice);
  309.                             $sprice = '<a href="'.htmlentities('http://shop.rsci.com/industrial_supplies_description.asp?ItemCode='.$item->ItemCode).'" rel="nofollow">'.$sprice.'</a>';
  310.                         }
  311.                         //Now update the post content
  312.                         $post_cache->post_content = preg_replace($pattern, sprintf('<td id="sp%s" class="sale_price">%s</td>', $item->ItemCode, $sprice), $post_cache->post_content);
  313.                         if(defined('WP_DEBUG') && WP_DEBUG)
  314.                         {
  315.                             $this->message['updated fade'][] = sprintf(__('Item %s price updated to %s','pr_upate'), $item->ItemCode, $sprice);
  316.                         }
  317.                     }
  318.                 }
  319.                 //Update the post, from cache, must do outside of the loop to capture last changes
  320.                 wp_update_post($post_cache);
  321.                 $end = microtime(true);
  322.                 $this->message['updated fade'][] = 'Processed in: ' . ($end - $start) . 'sec<br />Performed: ' . $performed . ' / To Be Quoted: ' . $tobequoted . ' / Total: ' . $total . '<br />Products Updated: ' . $updated;
  323.             }
  324.             add_action('admin_notices', array($this, 'message'));
  325.         }
  326.     }
  327.     /**
  328.      * admin_page
  329.      *
  330.      * The administrative page for Relatively Perfect
  331.      *
  332.      */
  333.     function admin_page()
  334.     {
  335.         $options = $this->get_config();
  336.         $this->security();
  337.         ?>
  338.         <div class="wrap"><h2><?php _e('Price Update', 'pr_upate'); ?></h2>
  339.         <p<?php if($this->_has_contextual_help): ?> class="hide-if-js"<?php endif; ?>><?php
  340.             print $this->_get_help_text();
  341.         ?></p>
  342.         <form action="tools.php?page=pr_upate" method="post" id="<?php echo $this->unique_prefix;?>_update_prices">
  343.             <?php wp_nonce_field($this->unique_prefix . '_update_prices');?>
  344.             <div id="hasadmintabs">
  345.             <fieldset id="general" class="<?php echo $this->unique_prefix;?>_options">
  346.                 <table class="form-table">
  347.                 <?php
  348.                 //If we don't have titles passed in, we'll use option names as values
  349.                 $optid = $this->get_valid_id($this->unique_prefix . '_update_prices_file');?>
  350.                 <tr valign="top">
  351.                     <th scope="row">
  352.                         <label for="<?php echo $optid;?>"><?php _e('Prices File', 'pr_upate');?></label>
  353.                     </th>
  354.                     <td>
  355.                         <select name="<?php echo $this->unique_prefix;?>_update_prices_file" id="<?php echo $optid;?>">
  356.                         <option value="">-</option>
  357.                             <?php
  358.                                 //Make sure a directory was passed
  359.                                 $dir = dirname(__FILE__);
  360.                                 if(is_dir($dir))
  361.                                 {
  362.                                     $contents = array();
  363.                                     if($dirh = opendir($dir))
  364.                                     {
  365.                                         //Makesure the filename isread
  366.                                         while(false !== ($file = readdir($dirh)))
  367.                                         {
  368.                                             //We don't want . or ..'
  369.                                             if($file != '..' && $file != '.')
  370.                                             {
  371.                                                 $name = explode('.', $file);
  372.                                                 if(isset($name[1]) && strtolower($name[1]) == 'xml')
  373.                                                 {
  374.                                                     printf('<option value="%s" %s>%s</option>', $file, '', $file);
  375.                                                 }
  376.                                             }
  377.                                         }
  378.                                         //Be good and release some memory
  379.                                         closedir($dirh);
  380.                                     }
  381.                                 }?>
  382.                         </select><br />
  383.                         <span class="setting-description"><?php printf(__('Select the prices file to process for price updates. Note that the file must be located in the directory "%s" to show up in the dropdown.', 'pr_upate'), $dir);?></span>
  384.                     </td>
  385.                 </tr>
  386.                 </table>
  387.                 <h2>Quote Form Options</h2>
  388.                 <div><input type="checkbox" name="quote_enabled" value="yes"<?= (($options['quote_enabled'] !== false) ? ' checked="checked"' : null) ?> /> Enabled</div>
  389.                 <div>Gravity Form:</div>
  390.                 <div>&nbsp; <select name="quote_form"><option value="">-</option><?php
  391.                     global $wpdb;
  392.                     $_forms = $wpdb->get_results( $wpdb->prepare( "SELECT `id`, `title` FROM {$wpdb->prefix}rg_form WHERE `is_active`=1 ORDER BY `title` ASC") );
  393.                     foreach ($_forms as $form)
  394.                         echo '<option value="'.$form->id.'"'.(($form->id == $options['quote_form']) ? ' selected' : null).'>'.htmlspecialchars($form->title).'</option>'
  395.                 ?></select></div>
  396.                 <div>RSC# Field<small> (name of the field with the RSC#)</small>:</div>
  397.                 <div>&nbsp; <input type="text" size="80" name="quote_field" value="<?php $str = $options['quote_field']; echo stripslashes($str); ?>" /></div>
  398.                 <div>ThickBox Title<small>:</div>
  399.                 <div>&nbsp; <input type="text" size="80" name="quote_tb_title" value="<?php $str = $options['quote_tb_title']; echo stripslashes($str); ?>" /></div>
  400.                 <div>ThickBox Width<small>:</div>
  401.                 <div>&nbsp; <input type="text" size="80" name="quote_tb_width" value="<?php $str = $options['quote_tb_width']; echo stripslashes($str); ?>" /></div>
  402.                 <div>ThickBox Height<small>:</div>
  403.                 <div>&nbsp; <input type="text" size="80" name="quote_tb_height" value="<?php $str = $options['quote_tb_height']; echo stripslashes($str); ?>" /></div>
  404.             </fieldset>
  405.             </div>
  406.             <p class="submit"><input type="submit" class="button-primary" name="<?php echo $this->unique_prefix;?>_update_prices" value="<?php esc_attr_e('Update'); ?>" /></p>
  407.         </form>
  408.         </div>
  409.         <?php
  410.     }
  411. }
  412. //Let's make an instance of our object takes care of everything
  413. $PriceUpdate = new PriceUpdate;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement