PHP Classes

File: Grid/Deploy/Csv.php

Recommend this page to a friend!
  Classes of Filipe Sá   Zend Framework Data Grid   Grid/Deploy/Csv.php   Download  
File: Grid/Deploy/Csv.php
Role: Class source
Content type: text/plain
Description: Class source
Class: Zend Framework Data Grid
Display and edit data from a database in a grid
Author: By
Last change:
Date: 13 years ago
Size: 8,864 bytes
 

Contents

Class file image Download
<?php

/**
 * LICENSE
 *
 * This source file is subject to the new BSD license
 * It is available through the world-wide-web at this URL:
 * http://www.petala-azul.com/bsd.txt
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to geral@petala-azul.com so we can send you a copy immediately.
 *
 * @package Bvb_Grid
 * @author Bento Vilas Boas <geral@petala-azul.com>
 * @copyright 2010 ZFDatagrid
 * @license http://www.petala-azul.com/bsd.txt New BSD License
 * @version $Id$
 * @link http://zfdatagrid.com
 */

class Bvb_Grid_Deploy_Csv extends Bvb_Grid implements Bvb_Grid_Deploy_DeployInterface
{
   
/**
     * Storing file
     */
   
protected $_outFile = null;

   
/**
     * We don't want to display hidden fields
     *
     * @var $_removeHiddenFields boolean
     */
   
protected $_removeHiddenFields = true;

   
/**
     * Set to true if setForceRecordsPerPage was called with number
     *
     * @var boolean
     */
   
protected $_isRecordsPerPageForced = false;

   
/**
     * Optimize performance by setting best value for $this->setPagination(?);
     *
     * Options (deploy.csv.<option>):
     * set_time_limit - time out for php script
     * memory_limit - PHP memory limit
     * download - send data directly to user
     * save - save data to file
     * fileName - filename used as suggestion when downloading and to save data
     * dir - directory where to store data
     *
     * @param array $options options
     * @see _prepareOptions
     * @return void
     */
   
public function __construct (array $options = array())
    {
       
$this->_setRemoveHiddenFields(true);

       
parent::__construct($options);

       
// default pagination, should be adjusted based on data processed to improve speed
       
$this->setForceRecordsPerPage(5000);

       
// fix configuration options
       
$deploy = $this->getDeployOption($this->_deployName, array());
       
$defaults = array(
           
'dir' => '',
           
'store' => false,
           
'download' => (!isset($deploy['download']) && !isset($deploy['store'])),
        );
       
$deploy = array_merge($defaults, $deploy);

        if (!empty(
$deploy['dir'])) {
           
$deploy['dir'] = rtrim($deploy['dir'], "/") . "/";
        }

       
// set the changed options
       
$this->setDeployOption($this->_deployName, $deploy);

       
// TODO I don't understand why parent::__constructor will not set this automaticaly,
        // what if it would be loaded from config ?
       
$this->_deploy = $this->getDeployOption($this->_deployName);
       
$this->checkExportRights();
    }
   
/**
     * Force to use given value as records per page
     *
     * Csv should work with as high number of rows as possible to deliver good export speed. On the otherside high number could reach PHP memory limit.
     *
     * @param int|boolean $number will not accept any other changes made by setRecordsPerPage if not FALSE
     *
     * @return Bvb_Grid
     */
   
public function setForceRecordsPerPage($number)
    {
        if (
false===$number) {
           
$this->_isRecordsPerPageForced = false;
        } else {
           
$this->_isRecordsPerPageForced = true;
           
$this->_recordsPerPage = (int) $number;
        }

        return
$this;
    }
   
/**
     * Number of records to show per page
     *
     * @param int $number Records to show
     *
     * @return Bvb_Grid
     */
   
public function setRecordsPerPage($number = 15)
    {
        if (!
$this->_isRecordsPerPageForced) {
           
// will be ignore if setForceRecordsPerPage was used to set value
           
return parent::setRecordsPerPage($number);
        }
        return
$this;
    }
   
/**
     * Return name of file
     *
     * @return string
     */
   
public function getFileName()
    {
       
$fileName = $this->getInfo('fileName');
        if (!
$fileName) {
           
$fileName = $this->getInfo('title');
        }
        if (!
$fileName) {
           
$fileName = Zend_Controller_Front::getInstance()->getRequest()->getParam('controller') . '-' . date("Ymd");
        }
        return
$fileName . '.csv';
    }

   
/**
     * Build list of column names for header row
     *
     * @return string
     */
   
public function buildTitles()
    {
        return
$this->formatLine($this->_buildTitles());
    }

   
/**
     * Create line with values build based on sql expressions
     *
     * @return string
     */
   
public function buildSqlexp()
    {
        return
$this->formatLine($this->_buildSqlExp());
    }

   
/**
     * Build data rows
     *
     * @return string
     */
   
public function buildGrid()
    {
        return
implode("\n", array_map(array($this, 'formatLine'), $this->_buildGrid()));
    }

   
/**
     * Escape/format an array of row data as a single line of CSV
     * @param array $row
     * @return string
     */
   
protected function formatLine($row)
    {
       
// TODO: _buildGrid should be refactored so we don't have to call arrayPluck here
       
$s = implode(',', array_map(array($this, 'formatCell'), $this->arrayPluck($row)));
        return
$s;
    }

   
/**
     * Format CSV cell
     * @param string $value
     * @return string
     */
   
protected function formatCell($value)
    {
        return
'"' . strip_tags($value) . '"';
    }

   
/**
     * Add row to results
     *
     * Depending on settings store to file and/or directly upload
     *
     * @param array $data data
     * @return void
     */
   
protected function csvAddData($data)
    {
        if (
0==strlen($data)) {
            return;
        }
        if (
$this->getDeployOption('download')) {
           
// send first headers
           
echo $data."\n";
           
flush();
           
ob_flush();
        }
        if (
$this->getDeployOption('store')) {
           
// open file handler
           
fwrite($this->_outFile, $data."\n");
        }
    }

   
/**
     * Deploy method
     *
     * @return boolean FALSE if error
     */
   
public function deploy()
    {
       
// prepare data
       
$this->_prepareOptions();
       
parent::deploy();

        if (
$this->getDeployOption('download')) {
           
// send first headers
           
ob_end_clean();

           
header('Content-Description: File Transfer');
           
header('Cache-Control: public, must-revalidate, max-age=0'); // HTTP/1.1
           
header('Pragma: public');
           
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
           
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
           
header("Content-Type: application/csv");
           
header('Content-Disposition: attachment; filename="' . $this->getFileName() . '"');
           
header('Content-Transfer-Encoding: binary');
        }
        if (
$this->getDeployOption('store')) {
           
// open file handler
           
$this->_outFile = fopen($this->_deploy['dir'] . $this->getFileName(), "w");
        }

       
// export header
       
if (!$this->getDeployOption('skipHeaders')) {
           
$this->csvAddData($this->buildTitles());
        }
       
$i = 0;
        do {
           
$i += $this->_recordsPerPage;
           
$this->csvAddData($this->buildGrid());
           
$this->csvAddData($this->buildSqlexp());

           
// get next page
           
$this->getSource()->buildQueryLimit($this->_recordsPerPage, $i);
           
$this->_result = $this->getSource()->execute();
        } while (
count($this->_result));

        if (
$this->getDeployOption('store')) {
           
// close file handler
           
fclose($this->_outFile);
        }
        if (
$this->getDeployOption('download')) {
           
// we set special headers and uploaded data, there is nothing more we could do
           
die();
        }

        return
true;
    }

   
/**
     * Set some deploy settings
     *
     * @return void
     */
   
protected function _prepareOptions()
    {
       
// apply options
       
if (isset($this->_deploy['set_time_limit'])) {
           
// script needs time to proces huge amount of data (important)
           
set_time_limit($this->_deploy['set_time_limit']);
        }
        if (isset(
$this->_deploy['memory_limit'])) {
           
// adjust memory_limit if needed (not very important)
           
ini_set('memory_limit', $this->_deploy['memory_limit']);
        }
    }

   
/**
     * Return file if download requested without the need to continue up to deploy() method
     *
     * @return Bvb_Grid_Deploy_Csv
     */
   
public function setAjax()
    {
        if (
$this->getDeployOption('download')) {
           
// if we want to upload data then we should do it now, deploy will die if needed
           
$this->deploy();
        }
        return
$this;
    }
}