public function render(Curry_Backend $backend, array $params) { $view = $this->view ? $this->view : $this->parentView; if (!$view instanceof Curry_ModelView_List) { throw new Exception('Expected view to be of type Curry_ModelView_List, got ' . get_class($view)); } $view = clone $view; // Send response headers to the browser $filename = $this->filename ? $this->filename : $view->getOption('title') . ".csv"; header('Content-Type: text/csv'); header('Content-Disposition: attachment; filename=' . Curry_String::escapeQuotedString($filename)); $fp = fopen('php://output', 'w'); // Print column headers $headers = array(); foreach ($view->getOption('columns') as $name => $opts) { // TODO: should we really ignore display/escape option? $view->addColumn($name, array('display' => null, 'escape' => false)); $headers[] = $opts['label']; } if ($this->includeHeaders) { Curry_Util::fputcsv($fp, $headers); } // Print rows $page = 0; $maxPerPage = 100; $view->setOptions(array('maxPerPage' => $maxPerPage)); do { $results = $view->getJson(array('p' => ++$page)); foreach ($results['rows'] as $row) { Curry_Util::fputcsv($fp, $row); } } while (count($results['rows']) == $maxPerPage); fclose($fp); exit; }