diff --git a/src/Components/Container.php b/src/Components/Container.php
index 2d7198b4..45058622 100644
--- a/src/Components/Container.php
+++ b/src/Components/Container.php
@@ -11,6 +11,8 @@
namespace Grido\Components;
+use Grido\Components\Exports\BaseExport;
+use Grido\Components\Exports\CsvExport;
use Grido\Grid;
use Grido\Helpers;
use Grido\Components\Actions\Action;
@@ -94,12 +96,37 @@ public function getOperation($need = TRUE)
/**
* Returns export component.
+ * @param string $name
* @param bool $need
- * @return Export
+ * @return CsvExport
+ */
+ public function getExport($name = NULL, $need = TRUE)
+ {
+ if (is_bool($name) || $name === NULL) { // deprecated
+ trigger_error('This usage of ' . __METHOD__ . '() is deprecated,
+ please write name of export to first parameter.', E_USER_DEPRECATED);
+ $export = $this->getComponent(BaseExport::ID, $name);
+ if ($export) {
+ $export = $export->getComponent(CsvExport::CSV_ID, is_bool($name) ? $name : TRUE);
+ }
+ return $export;
+ }
+ return $this->hasExport()
+ ? $this->getComponent(BaseExport::ID)->getComponent(Helpers::formatColumnName($name), $need)
+ : NULL;
+ }
+
+ /**
+ * @param bool $need
+ * @return BaseExport[]
*/
- public function getExport($need = TRUE)
+ public function getExports($need = TRUE)
{
- return $this->getComponent(Export::ID, $need);
+ $export = $this->getComponent(BaseExport::ID, $need);
+ if ($export) {
+ $export = $export->getComponents();
+ }
+ return $export;
}
/**********************************************************************************************/
@@ -185,7 +212,7 @@ public function hasExport($useCache = TRUE)
$hasExport = $this->hasExport;
if ($hasExport === NULL || $useCache === FALSE) {
- $hasExport = (bool) $this->getComponent(Export::ID, FALSE);
+ $hasExport = (bool) $this->getExports(FALSE);
$this->hasExport = $useCache ? $hasExport : NULL;
}
@@ -361,10 +388,29 @@ public function setOperation(array $operations, $onSubmit)
/**
* @param string $label of exporting file
* @return Export
+ *
+ * @deprecated
*/
public function setExport($label = NULL)
{
- return new Export($this, $label);
+ trigger_error(__METHOD__ . '() is deprecated; use addExport instead.', E_USER_DEPRECATED);
+ return $this->addExport(new CsvExport($label), CsvExport::CSV_ID);
+ }
+
+ /**
+ * @param BaseExport $export
+ * @param string $name Component name
+ * @return BaseExport
+ */
+ public function addExport(BaseExport $export, $name)
+ {
+ $container = $this->getComponent(BaseExport::ID, FALSE);
+ if (!$container) {
+ $container = new \Nette\ComponentModel\Container();
+ $this->addComponent($container, BaseExport::ID);
+ }
+ $container->addComponent($export, $name);
+ return $export;
}
/**
diff --git a/src/Components/Export.php b/src/Components/Export.php
deleted file mode 100644
index ca4fb713..00000000
--- a/src/Components/Export.php
+++ /dev/null
@@ -1,180 +0,0 @@
-grid = $grid;
- $this->label = $label;
-
- $grid->addComponent($this, self::ID);
- }
-
- /**
- * @return void
- */
- protected function printCsv()
- {
- $escape = function($value) {
- return preg_match("~[\"\n,;\t]~", $value) || $value === ""
- ? '"' . str_replace('"', '""', $value) . '"'
- : $value;
- };
-
- $print = function(array $row) {
- print implode(',', $row) . "\n";
- };
-
- $columns = $this->grid[Column::ID]->getComponents();
-
- $header = [];
- $headerItems = $this->header ? $this->header : $columns;
- foreach ($headerItems as $column) {
- $header[] = $this->header
- ? $escape($column)
- : $escape($column->getLabel());
- }
-
- $print($header);
-
- $datasource = $this->grid->getData(FALSE, FALSE, FALSE);
- $iterations = ceil($datasource->getCount() / $this->fetchLimit);
- for ($i = 0; $i < $iterations; $i++) {
- $datasource->limit($i * $this->fetchLimit, $this->fetchLimit);
- $data = $this->customData
- ? call_user_func_array($this->customData, [$datasource])
- : $datasource->getData();
-
- foreach ($data as $items) {
- $row = [];
-
- $columns = $this->customData
- ? $items
- : $columns;
-
- foreach ($columns as $column) {
- $row[] = $this->customData
- ? $escape($column)
- : $escape($column->renderExport($items));
- }
-
- $print($row);
- }
- }
- }
-
- /**
- * Sets a limit which will be used in order to retrieve data from datasource.
- * @param int $limit
- * @return \Grido\Components\Export
- */
- public function setFetchLimit($limit)
- {
- $this->fetchLimit = (int) $limit;
- return $this;
- }
-
- /**
- * @return int
- */
- public function getFetchLimit()
- {
- return $this->fetchLimit;
- }
-
- /**
- * Sets a custom header of result CSV file (list of field names).
- * @param array $header
- * @return \Grido\Components\Export
- */
- public function setHeader(array $header)
- {
- $this->header = $header;
- return $this;
- }
-
- /**
- * Sets a callback to modify output data. This callback must return a list of items. (array) function($datasource)
- * DEBUG? You probably need to comment lines started with $httpResponse->setHeader in Grido\Components\Export.php
- * @param callable $callback
- * @return \Grido\Components\Export
- */
- public function setCustomData($callback)
- {
- $this->customData = $callback;
- return $this;
- }
-
- /**
- * @internal
- */
- public function handleExport()
- {
- !empty($this->grid->onRegistered) && $this->grid->onRegistered($this->grid);
- $this->grid->presenter->sendResponse($this);
- }
-
- /*************************** interface \Nette\Application\IResponse ***************************/
-
- /**
- * Sends response to output.
- * @param \Nette\Http\IRequest $httpRequest
- * @param \Nette\Http\IResponse $httpResponse
- * @return void
- */
- public function send(\Nette\Http\IRequest $httpRequest, \Nette\Http\IResponse $httpResponse)
- {
- $encoding = 'utf-8';
- $label = $this->label
- ? ucfirst(Strings::webalize($this->label))
- : ucfirst($this->grid->getName());
-
- $httpResponse->setHeader('Content-Encoding', $encoding);
- $httpResponse->setHeader('Content-Type', "text/csv; charset=$encoding");
- $httpResponse->setHeader('Content-Disposition', "attachment; filename=\"$label.csv\"");
-
- print chr(0xEF) . chr(0xBB) . chr(0xBF); //UTF-8 BOM
- $this->printCsv();
- }
-}
diff --git a/src/Components/Exports/BaseExport.php b/src/Components/Exports/BaseExport.php
new file mode 100644
index 00000000..a516d4bd
--- /dev/null
+++ b/src/Components/Exports/BaseExport.php
@@ -0,0 +1,154 @@
+label = $label;
+ $this->monitor('Grido\Grid');
+ }
+
+ protected function attached($presenter)
+ {
+ parent::attached($presenter);
+ if ($presenter instanceof Grid) {
+ $this->grid = $presenter;
+ }
+ }
+
+ /**
+ * @return void
+ */
+ abstract protected function printData();
+
+ /**
+ * @param \Nette\Http\IResponse $httpResponse
+ * @param string $label
+ * @return void
+ */
+ abstract protected function setHttpHeaders(\Nette\Http\IResponse $httpResponse, $label);
+
+ /**
+ * @param string $title
+ * @return self
+ */
+ public function setTitle($title)
+ {
+ $this->title = $title;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTitle()
+ {
+ return $this->title;
+ }
+
+ /**
+ * Sets a limit which will be used in order to retrieve data from datasource.
+ * @param int $limit
+ * @return \Grido\Components\Export
+ */
+ public function setFetchLimit($limit)
+ {
+ $this->fetchLimit = (int) $limit;
+ return $this;
+ }
+
+ /**
+ * @return int
+ */
+ public function getFetchLimit()
+ {
+ return $this->fetchLimit;
+ }
+
+ /**
+ * Sets a custom header of result CSV file (list of field names).
+ * @param array $header
+ * @return \Grido\Components\Export
+ */
+ public function setHeader(array $header)
+ {
+ $this->header = $header;
+ return $this;
+ }
+
+ /**
+ * Sets a callback to modify output data. This callback must return a list of items. (array) function($datasource)
+ * DEBUG? You probably need to comment lines started with $httpResponse->setHeader in Grido\Components\Export.php
+ * @param callable $callback
+ * @return \Grido\Components\Export
+ */
+ public function setCustomData($callback)
+ {
+ $this->customData = $callback;
+ return $this;
+ }
+
+ /**
+ * @internal
+ */
+ public function handleExport()
+ {
+ !empty($this->grid->onRegistered) && $this->grid->onRegistered($this->grid);
+ $this->grid->presenter->sendResponse($this);
+ }
+
+ /*************************** interface \Nette\Application\IResponse ***************************/
+
+ /**
+ * Sends response to output.
+ * @param \Nette\Http\IRequest $httpRequest
+ * @param \Nette\Http\IResponse $httpResponse
+ * @return void
+ */
+ public function send(\Nette\Http\IRequest $httpRequest, \Nette\Http\IResponse $httpResponse)
+ {
+ $label = $this->label
+ ? ucfirst(Strings::webalize($this->label))
+ : ucfirst($this->grid->name);
+
+ $this->setHttpHeaders($httpResponse, $label);
+
+ print chr(0xEF) . chr(0xBB) . chr(0xBF); //UTF-8 BOM
+ $this->printData();
+ }
+}
diff --git a/src/Components/Exports/CsvExport.php b/src/Components/Exports/CsvExport.php
new file mode 100644
index 00000000..8d8fc50f
--- /dev/null
+++ b/src/Components/Exports/CsvExport.php
@@ -0,0 +1,78 @@
+grid[Column::ID]->getComponents();
+
+ $header = [];
+ $headerItems = $this->header ? $this->header : $columns;
+ foreach ($headerItems as $column) {
+ $header[] = $this->header
+ ? $escape($column)
+ : $escape($column->getLabel());
+ }
+
+ $print($header);
+
+ $datasource = $this->grid->getData(FALSE, FALSE, FALSE);
+ $iterations = ceil($datasource->getCount() / $this->fetchLimit);
+ for ($i = 0; $i < $iterations; $i++) {
+ $datasource->limit($i * $this->fetchLimit, $this->fetchLimit);
+ $data = $this->customData
+ ? call_user_func_array($this->customData, [$datasource])
+ : $datasource->getData();
+
+ foreach ($data as $items) {
+ $row = [];
+
+ $columns = $this->customData
+ ? $items
+ : $columns;
+
+ foreach ($columns as $column) {
+ $row[] = $this->customData
+ ? $escape($column)
+ : $escape($column->renderExport($items));
+ }
+
+ $print($row);
+ }
+ }
+ }
+
+ /**
+ * @param IResponse $httpResponse
+ * @param string $label
+ */
+ protected function setHttpHeaders(IResponse $httpResponse, $label)
+ {
+ $encoding = 'utf-8';
+ $httpResponse->setHeader('Content-Encoding', $encoding);
+ $httpResponse->setHeader('Content-Type', "text/csv; charset=$encoding");
+ $httpResponse->setHeader('Content-Disposition', "attachment; filename=\"$label.csv\"");
+ }
+}
diff --git a/src/templates/default.latte b/src/templates/default.latte
old mode 100755
new mode 100644
index 86109cc6..891fed08
--- a/src/templates/default.latte
+++ b/src/templates/default.latte
@@ -144,9 +144,12 @@
{/block}
{input $form[buttons][perPage], class => 'hide'}
-
- {_'Grido.Export'}
+ {if $control->hasExport()}
+
+ {var $title = $export->title ? : $template->translate('Grido.ExportAllItems')}
+ {_'Grido.Export'}
+ {/if}
{input $form[buttons][reset]}
diff --git a/tests/Components/Export.phpt b/tests/Components/Export.phpt
index 9a33aec6..5c1cd92d 100644
--- a/tests/Components/Export.phpt
+++ b/tests/Components/Export.phpt
@@ -9,6 +9,8 @@
namespace Grido\Tests;
+use Grido\Components\Exports\BaseExport;
+use Grido\Components\Exports\CsvExport;
use Tester\Assert,
Grido\Grid,
Grido\Tests\Helper,
@@ -47,7 +49,7 @@ class ExportTest extends \Tester\TestCase
$grid = new Grid;
Assert::false($grid->hasExport());
- $grid->setExport();
+ $grid->addExport(new CsvExport(), 'csv');
Assert::false($grid->hasExport());
Assert::true($grid->hasExport(FALSE));
}
@@ -57,15 +59,15 @@ class ExportTest extends \Tester\TestCase
$grid = new Grid;
$label = 'export';
- $grid->setExport($label);
- $component = $grid->getExport();
- Assert::type('\Grido\Components\Export', $component);
+ $grid->addExport(new CsvExport($label), 'csv');
+ $component = $grid->getExport('csv');
+ Assert::type('\Grido\Components\Exports\BaseExport', $component);
Assert::same($label, $component->label);
- unset($grid[Export::ID]);
+ $grid[BaseExport::ID]->removeComponent($grid->getExport('csv'));
// getter
Assert::exception(function() use ($grid) {
- $grid->getExport();
+ $grid->getExport('csv');
}, 'Nette\InvalidArgumentException');
}
@@ -95,11 +97,11 @@ class ExportTest extends \Tester\TestCase
->setSortable();
$grid->addColumnText('country', 'Country')
->setFilterText();
- $grid->setExport($label);
+ $grid->addExport(new CsvExport($label), 'csv');
});
$params = [
- 'do' => 'grid-export-export',
+ 'do' => 'grid-export-csv-export',
'grid-sort' => ['name' => \Grido\Components\Columns\Column::ORDER_DESC],
'grid-filter' => ['country' => 'Switzerland'],
'grid-page' => 2
@@ -134,7 +136,7 @@ class ExportTest extends \Tester\TestCase
$grid->addColumnText('firstname', 'Name')
->setSortable();
- $grid->setExport()
+ $grid->addExport(new CsvExport(), 'csv')
->setHeader(['"Jméno"', "Příjmení\t", "Karta\n", 'Jméno,Příjmení'])
->setCustomData(function(ArraySource $source) {
$data = $source->getData();
@@ -151,7 +153,7 @@ class ExportTest extends \Tester\TestCase
});
});
- $params = ['do' => 'grid-export-export'];
+ $params = ['do' => 'grid-export-csv-export'];
ob_start();
Helper::request($params)->send(mock('\Nette\Http\IRequest'), new Response);
diff --git a/tests/DataSources/ArraySource.phpt b/tests/DataSources/ArraySource.phpt
index 48fcb762..16565308 100644
--- a/tests/DataSources/ArraySource.phpt
+++ b/tests/DataSources/ArraySource.phpt
@@ -9,6 +9,7 @@
namespace Grido\Tests;
+use Grido\Components\Exports\CsvExport;
use Tester\Assert,
Grido\Grid,
Grido\Components\Filters\Condition;
@@ -58,7 +59,7 @@ class ArraySourceTest extends DataSourceTestCase
return $row['centimeters'] >= 180;
});
- $grid->setExport();
+ $grid->addExport(new CsvExport(), 'csv');
})->run();
}
diff --git a/tests/DataSources/DibiFluent.phpt b/tests/DataSources/DibiFluent.phpt
index 93642f65..58437c05 100644
--- a/tests/DataSources/DibiFluent.phpt
+++ b/tests/DataSources/DibiFluent.phpt
@@ -9,6 +9,7 @@
namespace Grido\Tests;
+use Grido\Components\Exports\CsvExport;
use Tester\Assert,
Grido\Grid,
Grido\Components\Filters\Condition;
@@ -60,7 +61,7 @@ class DibiFluentTest extends DataSourceTestCase
});
$limit = 100;
- $export = $grid->setExport()->setFetchLimit($limit);
+ $export = $grid->addExport(new CsvExport(), 'csv')->setFetchLimit($limit);
Assert::same($limit, $export->getFetchLimit());
})->run();
diff --git a/tests/DataSources/Doctrine.phpt b/tests/DataSources/Doctrine.phpt
index 7bfbeb1a..715583d1 100644
--- a/tests/DataSources/Doctrine.phpt
+++ b/tests/DataSources/Doctrine.phpt
@@ -9,6 +9,7 @@
namespace Grido\Tests;
+use Grido\Components\Exports\CsvExport;
use Tester\Assert;
use Grido\Grid;
use Grido\Components\Filters\Condition;
@@ -65,7 +66,7 @@ class DoctrineTest extends DataSourceTestCase
$qb->andWhere("a.centimeters >= :height")->setParameter('height', 180);
});
- $grid->setExport();
+ $grid->addExport(new CsvExport(), 'csv');
})->run();
}
diff --git a/tests/DataSources/NetteDatabase.phpt b/tests/DataSources/NetteDatabase.phpt
index 3dbb4dc3..ed5c3123 100644
--- a/tests/DataSources/NetteDatabase.phpt
+++ b/tests/DataSources/NetteDatabase.phpt
@@ -9,6 +9,7 @@
namespace Grido\Tests;
+use Grido\Components\Exports\CsvExport;
use Tester\Assert,
Grido\Grid,
Grido\Components\Filters\Condition;
@@ -55,7 +56,7 @@ class NetteDatabaseTest extends DataSourceTestCase
$fluent->where('[centimeters] >= ?', 180);
});
- $grid->setExport();
+ $grid->addExport(new CsvExport(), 'csv');
})->run();
}
diff --git a/tests/DataSources/TestCase.php b/tests/DataSources/TestCase.php
index 43677dd0..ec87d0c9 100644
--- a/tests/DataSources/TestCase.php
+++ b/tests/DataSources/TestCase.php
@@ -105,7 +105,7 @@ function testNullableForeignKey()
function testExport()
{
Helper::$presenter->forceAjaxMode = FALSE;
- $params = $this->params + ['do' => 'grid-export-export'];
+ $params = $this->params + ['do' => 'grid-export-csv-export'];
ob_start();
Helper::request($params)->send(mock('\Nette\Http\IRequest'), new \Nette\Http\Response);
diff --git a/tests/DataSources/files/doctrine/proxies/.htaccess b/tests/DataSources/files/doctrine/proxies/.htaccess
index 74e020d6..22b9ed25 100644
--- a/tests/DataSources/files/doctrine/proxies/.htaccess
+++ b/tests/DataSources/files/doctrine/proxies/.htaccess
@@ -1,2 +1,2 @@
-Order Allow,Deny
+Order Allow,Deny
Deny from all
\ No newline at end of file
diff --git a/tests/DataSources/files/export.expect b/tests/DataSources/files/export.expect
index 4b6e8acd..964d97eb 100644
--- a/tests/DataSources/files/export.expect
+++ b/tests/DataSources/files/export.expect
@@ -1,5 +1,5 @@
Firstname,Surname,Gender,Phone,Country
-Marij,"Rašpolić Příliš, žluťoučký ""kůň"" úpěl 'ďábelské' ódy.
+Marij,"Rašpolić Příliš, žluťoučký ""kůň"" úpěl 'ďábelské' ódy.
and newline ""test"";",male,905-895-1107,Australia
James,Vallace,male,04774 25 83 51,Australia
Juhana,Uusipaikka,male,519-896-1068,Australia
diff --git a/tests/DataSources/files/render.expect b/tests/DataSources/files/render.expect
index 3a1bdb8a..628c3dfd 100644
--- a/tests/DataSources/files/render.expect
+++ b/tests/DataSources/files/render.expect
@@ -68,7 +68,7 @@
- Export
+ Export
diff --git a/tests/DataSources/files/users.s3db b/tests/DataSources/files/users.s3db
old mode 100755
new mode 100644
diff --git a/tests/DataSources/files/users.s3db.editable b/tests/DataSources/files/users.s3db.editable
new file mode 100644
index 00000000..c68d0d12
Binary files /dev/null and b/tests/DataSources/files/users.s3db.editable differ
diff --git a/tests/Grid/files/render.editable.expect b/tests/Grid/files/render.editable.expect
index 68e46c1d..21759899 100644
--- a/tests/Grid/files/render.editable.expect
+++ b/tests/Grid/files/render.editable.expect
@@ -72,7 +72,7 @@
- Export
+ Export
diff --git a/tests/Grid/files/render.expect b/tests/Grid/files/render.expect
index e16cf7cf..4f1781de 100644
--- a/tests/Grid/files/render.expect
+++ b/tests/Grid/files/render.expect
@@ -72,7 +72,10 @@
- Export
+ Export
+
+
+ Export
diff --git a/tests/Grid/render.editable.phpt b/tests/Grid/render.editable.phpt
index a4932d58..1b2afefd 100644
--- a/tests/Grid/render.editable.phpt
+++ b/tests/Grid/render.editable.phpt
@@ -9,6 +9,7 @@
namespace Grido\Tests;
+use Grido\Components\Exports\CsvExport;
use Tester\Assert,
Grido\Grid;
@@ -58,7 +59,7 @@ test(function()
->elementPrototype = \Nette\Utils\Html::el('button');
$grid->setOperation(['print' => 'Print'], function(){});
- $grid->setExport();
+ $grid->addExport(new CsvExport(), 'csv');
})->run();
diff --git a/tests/Grid/render.phpt b/tests/Grid/render.phpt
index 5c48c57d..604601c8 100644
--- a/tests/Grid/render.phpt
+++ b/tests/Grid/render.phpt
@@ -9,6 +9,7 @@
namespace Grido\Tests;
+use Grido\Components\Exports\CsvExport;
use Tester\Assert,
Grido\Grid;
@@ -55,7 +56,8 @@ test(function()
->elementPrototype = \Nette\Utils\Html::el('button');
$grid->setOperation(['print' => 'Print'], function(){});
- $grid->setExport();
+ $grid->addExport(new CsvExport('myLabel'), 'csv');
+ $grid->addExport(new CsvExport('myLabel'), 'csv2');
})->run();