root > WikiSense-trunk > common > CSV.php

CSV.php

application/x-php, 6322 bytes (load raw)
<?php

/**
* Utility class for creating CSV-Formated output.
*/

class CSV {
        var $urlEncode;
       
        var $separator;

        var $mime;
       
        var $trim;
       
        /**
        * @param $urlEncode if true, URL-encode all values, so lines can be split
        *             reliably at the separator. If false, use CSV quotes.
        *             Defaults to true.
        * @param $separator the field separator, defaults to ',' (comma)
        */
     
        function CSV( $urlEncode = true, $separator = ',', $mime = NULL ) {
                $this->urlEncode = $urlEncode;
                $this->separator = $separator;
                $this->trim = true;
               
                if ($mime) $this->mime= $mime;
                else {
                    #NOTE: url-encoding applies, so the charset is always us-ascii
                    #NOTE: text/csv is the correct mime type, but text/plain does not force
                    #      download / external app in web browsers, so it's more convenient.
                    #$this->mime = "text/csv; charset=us-ascii; header=present; escape=url;";
                    $this->mime = "text/plain; charset=us-ascii;";
                }
        }

        /**
        * creates a CSV formatted line from the given values, without
        * the trailing linebreak.
        *
        * @param $values the values to use
        * @param $fields restrict values to the keys in this array. If NULL (default),
        *                all values will be used.
        */

        function csvLine( $values, $fields = NULL ) {
                if ( $fields ) {
                        #build a new value array,
                        #using only the keys from $fields
                       
                        $v = array();
                        foreach ( $fields as $f ) {
                                $v[$f] = $values[$f];
                        }
                       
                        $values = $v;
                }
       
                #escape quotes and separators
                foreach ( $values as $i => $f ) {
                        if ( $this->trim ) {
                                $f = trim($f);
                        }
                       
                        if ( $this->urlEncode ) {
                                $values[$i] = urlencode($f);
                        } else if ( strpos( $f, '"' ) !== false
                                 || strpos( $f, "\r" ) !== false
                                 || strpos( $f, "\n" ) !== false
                                 || strpos( $f, $this->separator ) !== false ) {
                                $values[$i] = '"' . str_replace('"', '""', $f) . '"';
                        }
                }
               
                return implode( $this->separator, $values );
        }
       
        /**
         * Creates a page containing a CSV formatted table from
         * a DB result set. Note that the caller is responsible
         * for calling $dbr->freeResult( $res ) after this
         * function.
         *
         * This function will set the Content-Type header to an
         * appropriate value, and disable HTML output by calling
         * $wgOut->disable();
         *
         * @param $dbr a database object
         * @param $res the result set
         * @param $fields columns to use. If null, all columns will be used.
         * @param $mogrify an expression to evaluate to mogrify each line (array) before
         *              output. NULL per default. Inside the expression, the current
         *              row is available as $row.
         */

        function csvFromDB( &$dbr, &$res, $fields = NULL, $mogrify = NULL ) {
                header( "Content-Type: " . $this->mime );
               
                $first = true;
               
                while( true ) {
                        #if no fields are defined, look at the first record to
                        #find all column names.
                        if ( !$fields ) {
                                $obj = $dbr->fetchObject( $res );
                                if ( !$obj ) break;
                               
                                $row = get_object_vars( $obj );
                               
                                if ( $mogrify && $row) {
                                        $row= eval( $mogrify );
                                }
                               
                                $fields = array_keys( $row );
                        } else {
                                $row = $dbr->fetchRow( $res );
                       
                                if ( $mogrify && $row) {
                                        $row= eval( $mogrify );
                                }
                        }
                       
                        # write header before first row.
                        # do inside loop becuase fields may not be known earlier
                        if ($first) {
                                $first= false;
                               
                                $line = $this->csvLine( $fields, NULL );
                               
                                print $line;
                                print "\r\n";
                      }
                       
                        if ( !$row ) break;
                       
                        $line = $this->csvLine( $row, $fields );
                       
                        print $line;
                        print "\r\n";
                }
               
                #no more output
                global $wgOut;
                if (!is_null($wgOut)) $wgOut->disable();
        }
       
        /**
         * Creates a page containing a CSV formatted table from
         * an array. Each value in the array must be an object or an array.
         *
         * This function will set the Content-Type header to an
         * appropriate value, and disable HTML output by calling
         * $wgOut->disable();
         *
         * @param $data an array of objects or arrays. All rows should have the same fields.
         * @param $fields columns to use. If null, all columns defined for the first record will be used.
         * @param $mogrify an expression to evaluate to mogrify each line (array) before
         *              output. NULL per default. Inside the expression, the current
         *              row is available as $row.
         */

        function csvFromArray( &$data, $fields = NULL, $mogrify = NULL ) {
                header( "Content-Type: " . $this->mime );
               
                $first = true;
               
                foreach ( $data as $row ) {
                        if ( is_object( $row ) ) $row = get_object_vars( $row );
               
                        if ( $mogrify ) {
                                $row= eval( $mogrify );
                        }
                       
                        #if no fields are defined, look at the first record to
                        #find all column names.
                        if ( !$fields ) {
                                $fields = array_keys( $row );
                        }
                       
                        # write header before first row.
                        # do inside loop becuase fields may not be known earlier
                        if ($first) {
                                $first= false;
                               
                                $line = $this->csvLine( $fields, NULL );
                               
                                print $line;
                                print "\r\n";
                      }
                       
                        $line = $this->csvLine( $row, $fields );
                       
                        print $line;
                        print "\r\n";
                }
               
                #no more output
                global $wgOut;
                $wgOut->disable();
        }
       
        /**
         * Creates a page containing a CSV formatted two-column table
         * from an associative array (aka map).
         *
         * This function will set the Content-Type header to an
         * appropriate value, and disable HTML output by calling
         * $wgOut->disable();
         *
         * @param $map an associative array, assigning values to keys.
         * @param $keycol the name of the column that is to contain the key of each entry.
         *        Default is 'key'.
         * @param $valuecol the name of the column that is to contain the value of each entry.
         *        Default is 'value'.
         * @param $mogrify an expression to evaluate to mogrify each line (array) before
         *              output. NULL per default. Inside the expression, the current
         *              row is available as $row.
         */

        function csvFromMap( &$map, $keycol='key', $valucol='value', $mogrify = NULL ) {
                $data= array();
                foreach ($map as $k => $v) {
                        $data[]= array( $keycol => $k, $valucol => $v );
                }
               
                $this->csvFromArray( $data, $mogrify );
        }
}

?>