wir
6/9/2014 - 9:17 PM

a class to read and write CSV

a class to read and write CSV

Array
(
    [0] => Array
        (
            [name] => Lorem
            [number] => 11
        )

    [1] => Array
        (
            [name] => ipsum
            [number] => 22
        )

)
"name", "number"
"Lorem", 11
"ipsum", 22
<?php

/**
 * This class is used in Orbisius Price Changer for WooCommerce
 * This premium WooCommerce extension allows you to change product prices (up/down) for all products or for a selected category and its subcategories.
 * You can review them before actually making the changes.
 * 
 * @see http://club.orbisius.com/products/wordpress-plugins/woocommerce-extensions/orbisius-woocommerce-ext-price-changer/
 * @author jaywilliams | myd3.com | https://gist.github.com/jaywilliams
 * @author Svetoslav Marinov (SLAVI) | http://orbisius.com
 */
Class orbisius_woocommerce_ext_price_changer_csv {
    protected $buff_size = 1024;
    protected $delimiter = ',';

    public function delimiter($delimiter = '') {
        if (!empty($delimiter)) {
            $this->delimiter = $delimiter;
        }

        return $this->delimiter;
    }

    /**
    * Reads a CSV file and returns array of arrays.
    * The header rows are not returned. We can extract them by getting the keys of the first array element.
    * @link http://gist.github.com/385876
    * @return array / false on error
    */
   public function read($filename = '') {
       if (!file_exists($filename) || !is_readable($filename)) {
           trigger_error(sprintf("File [%s] doesn't exist or not readable.", esc_attr($filename)), E_USER_WARNING);
           return false;
       }

       $data = array();
       $header = array();

       if (($handle = fopen($filename, 'rb')) !== false) {
           // we just need a read lock
           flock($handle, LOCK_SH);

           while (($row = fgetcsv($handle, $this->buff_size, $this->delimiter)) !== false) {
               // No header row OR if the data contains header row somewhere instead of data
               if (empty($header) || count(array_diff($header, $row)) == 0) {
                   $header = $row;
               } else {
                   $data[] = array_combine($header, $row);
               }
           }

           flock($handle, LOCK_UN);
           fclose($handle);
       }
       
       return $data;

       /*
        * Return value
        array (
        0 =>
        array (
          'product_title' => 'Bottle',
          'parent_product_id' => '0',
          'product_id' => '308',
          'old_regular_price' => '1.00',
          'new_regular_price' => '5',
          'old_sale_price' => '1.00',
          'new_sale_price' => '2.00',
          'currency' => 'GBP',
          'cur_user_id' => '20',
          'cur_user_email' => 'user@email.com',
          'cur_date' => '2014-06-09 10:59:37',
        ),
        1 =>
        array (
          'product_title' => 'Bottles (Case)',
          'parent_product_id' => '0',
          'product_id' => '309',
          'old_regular_price' => '100.00',
          'new_regular_price' => '50.00',
          'old_sale_price' => '10.00',
          'new_sale_price' => '10.00',
          'currency' => 'GBP',
          'cur_user_id' => '20',
          'cur_user_email' => 'user@email.com',
          'cur_date' => '2014-06-09 10:59:37',
        ),
      )
        */
   }

    /**
     * This outputs data in a file or in the browser (if file param is passed).
     * If the browser option is used it will output the data and will exit.
     *
     * @param array $data array of arrays
     * @param array $title_row (optional) title/header row of the CSV file
     * @param str $file target file to save the output to
     * @return bool true/false depending on success
     */
    public function write($data, $title_row = array(), $file = '', $append = 1) {
        $output_in_browser = empty($file);

        if ($output_in_browser) { // browser
            $handle = fopen('php://output', 'w');
        } else {
            $handle = fopen($file, $append ? 'ab' : 'wb');
        }

        if (empty($handle)) {
            return false;
        }

        // for some reason filesize would not update if the script accesses this file quickly
        // this resulted in header column being written multiple times.
        // that's why we clear the cache every time we write.
        clearstatcache();
        flock($handle, LOCK_EX);

        // add the title row only if we're not appending or if the file size is minimal (fewer than 10 bytes).
        // no need to add header rows all the time.
        if ( !empty($title_row) && (!$append || filesize($file) < 10) ) {
            fputcsv($handle, $title_row);
        }

        foreach ($data as $csv_data) {
            fputcsv($handle, $csv_data);
        }

        flock($handle, LOCK_UN);
        fclose($handle);

        if ($output_in_browser) {
            die;
        }
        
        return true;
    }
}