AbstractExporter.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. <?php
  2. namespace Dcat\Admin\Grid\Exporters;
  3. use Dcat\Admin\Grid;
  4. use Illuminate\Support\Str;
  5. /**
  6. * @method $this disableExportAll(bool $value = true)
  7. * @method $this disableExportCurrentPage(bool $value = true)
  8. * @method $this disableExportSelectedRow(bool $value = true)
  9. */
  10. abstract class AbstractExporter implements ExporterInterface
  11. {
  12. /**
  13. * @var \Dcat\Admin\Grid
  14. */
  15. protected $grid;
  16. /**
  17. * @var Grid\Exporter
  18. */
  19. protected $parent;
  20. /**
  21. * @var \Closure
  22. */
  23. protected $builder;
  24. /**
  25. * @var array
  26. */
  27. protected $titles = [];
  28. /**
  29. * @var string
  30. */
  31. protected $filename;
  32. /**
  33. * @var string
  34. */
  35. protected $scope;
  36. /**
  37. * @var string
  38. */
  39. protected $extension = 'xlsx';
  40. /**
  41. * Create a new exporter instance.
  42. *
  43. * @param array $titles
  44. */
  45. public function __construct($titles = [])
  46. {
  47. $this->titles($titles);
  48. }
  49. /**
  50. * Set the headings of excel sheet.
  51. *
  52. * @param array|false $titles
  53. *
  54. * @return $this
  55. */
  56. public function titles($titles)
  57. {
  58. if (is_array($titles) || $titles === false) {
  59. $this->titles = $titles;
  60. }
  61. return $this;
  62. }
  63. /**
  64. * Set filename.
  65. *
  66. * @param string|\Closure $filename
  67. *
  68. * @return $this
  69. */
  70. public function filename($filename)
  71. {
  72. $this->filename = value($filename);
  73. return $this;
  74. }
  75. /**
  76. * Set export data callback function.
  77. *
  78. * @param \Closure $builder
  79. *
  80. * @return $this
  81. */
  82. public function rows(\Closure $builder)
  83. {
  84. $this->builder = $builder;
  85. return $this;
  86. }
  87. /**
  88. * @return $this
  89. */
  90. public function xlsx()
  91. {
  92. return $this->extension('xlsx');
  93. }
  94. /**
  95. * @return $this
  96. */
  97. public function csv()
  98. {
  99. return $this->extension('csv');
  100. }
  101. /**
  102. * @return $this
  103. */
  104. public function ods()
  105. {
  106. return $this->extension('ods');
  107. }
  108. /**
  109. * @param string $ext e.g. csv/xlsx/ods
  110. *
  111. * @return $this
  112. */
  113. public function extension(string $ext)
  114. {
  115. $this->extension = $ext;
  116. return $this;
  117. }
  118. /**
  119. * Set grid for exporter.
  120. *
  121. * @param Grid $grid
  122. *
  123. * @return $this
  124. */
  125. public function setGrid(Grid $grid)
  126. {
  127. $this->grid = $grid;
  128. $this->parent = $grid->exporter();
  129. return $this;
  130. }
  131. /**
  132. * @return string
  133. */
  134. public function getFilename()
  135. {
  136. return $this->filename ?: (admin_trans_label().'-'.date('Ymd-His').'-'.Str::random(6));
  137. }
  138. /**
  139. * Get data with export query.
  140. *
  141. * @param int $page
  142. * @param int $perPage
  143. *
  144. * @return array|\Illuminate\Support\Collection|mixed
  145. */
  146. public function buildData(?int $page = null, ?int $perPage = null)
  147. {
  148. $model = $this->grid->model();
  149. // current page
  150. if ($this->scope === Grid\Exporter::SCOPE_CURRENT_PAGE) {
  151. $page = $model->getCurrentPage();
  152. $perPage = $model->getPerPage();
  153. }
  154. $model->usePaginate(false);
  155. if ($page && $this->scope !== Grid\Exporter::SCOPE_SELECTED_ROWS) {
  156. $perPage = $perPage ?: $this->getChunkSize();
  157. $model->forPage($page, $perPage);
  158. }
  159. $array = $this->grid->processFilter(true);
  160. $model->reset();
  161. return $this->callBuilder($array);
  162. }
  163. /**
  164. * @param array $data
  165. *
  166. * @return array
  167. */
  168. protected function callBuilder(array &$data)
  169. {
  170. if ($data && $this->builder) {
  171. return ($this->builder)($data);
  172. }
  173. return $data;
  174. }
  175. /**
  176. * @return int
  177. */
  178. protected function getChunkSize()
  179. {
  180. return $this->parent->option('chunk_size') ?: 5000;
  181. }
  182. /**
  183. * Export data with scope.
  184. *
  185. * @param string $scope
  186. *
  187. * @return $this
  188. */
  189. public function withScope($scope)
  190. {
  191. $data = explode(':', $scope);
  192. $scope = $data[0] ?? '';
  193. $args = $data[1] ?? '';
  194. $this->scope = $scope;
  195. if ($scope == Grid\Exporter::SCOPE_SELECTED_ROWS) {
  196. $selected = explode(',', $args);
  197. $this->grid->model()->whereIn($this->grid->getKeyName(), $selected);
  198. }
  199. return $this;
  200. }
  201. /**
  202. * {@inheritdoc}
  203. */
  204. abstract public function export();
  205. /**
  206. * @param $method
  207. * @param $arguments
  208. *
  209. * @return mixed
  210. */
  211. public function __call($method, $arguments)
  212. {
  213. $this->parent->{$method}(...$arguments);
  214. return $this;
  215. }
  216. /**
  217. * Create a new exporter instance.
  218. *
  219. * @param \Closure|array $closure
  220. */
  221. public static function make($builder = null)
  222. {
  223. return new static($builder);
  224. }
  225. }