├── .gitignore
├── .travis.yml
├── LICENSE.md
├── README.md
├── composer.json
├── jqGrid.png
├── phpunit.xml
├── public
└── .gitkeep
├── src
├── Mgallegos
│ └── LaravelJqgrid
│ │ ├── Encoders
│ │ ├── JqGridJsonEncoder.php
│ │ └── RequestedDataInterface.php
│ │ ├── Exceptions
│ │ ├── JsonEncodingMaxDepthException.php
│ │ ├── JsonEncodingStateMismatchException.php
│ │ ├── JsonEncodingSyntaxErrorException.php
│ │ ├── JsonEncodingUnexpectedControlCharException.php
│ │ └── JsonEncodingUnknownException.php
│ │ ├── Facades
│ │ ├── GridEncoder.php
│ │ └── GridRender.php
│ │ ├── LaravelJqgridServiceProvider.php
│ │ ├── Renders
│ │ ├── JqGridRender.php
│ │ ├── RenderInterface.php
│ │ └── Validations
│ │ │ ├── ColModel
│ │ │ └── NameValidation.php
│ │ │ ├── FilterToolbar
│ │ │ └── .gitkeep
│ │ │ ├── GridOptions
│ │ │ └── .gitkeep
│ │ │ ├── Navigator
│ │ │ └── .gitkeep
│ │ │ └── PropertyValidatorInterface.php
│ │ └── Repositories
│ │ ├── EloquentRepositoryAbstract.php
│ │ └── RepositoryInterface.php
├── config
│ ├── .gitkeep
│ └── config.php
├── lang
│ └── .gitkeep
├── migrations
│ └── .gitkeep
└── views
│ └── .gitkeep
└── tests
└── .gitkeep
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | .project
3 | .buildpath
4 | .settings
5 | composer.phar
6 | composer.lock
7 | .DS_Store
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.3
5 | - 5.4
6 | - 5.5
7 |
8 | before_script:
9 | - curl -s http://getcomposer.org/installer | php
10 | - php composer.phar install --dev
11 |
12 | script: phpunit
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | All LaravelJqGrid code is Copyright (c) 2013 by the original authors.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel jqGrid package
2 |
3 | [](https://packagist.org/packages/mgallegos/laravel-jqgrid) [](https://packagist.org/packages/mgallegos/laravel-jqgrid)
4 |
5 | Laravel jqGrid package allows you to easily integrate the popular jQuery Grid Plugin (jqGrid) into your Laravel application.
6 |
7 | 
8 |
9 | ## Requirements
10 |
11 | * [Laravel 4, 5, 6, 7 or 8 Framework](http://laravel.com/docs/installation)
12 | * [jQuery v2.0.0 or later](http://jquery.com/)
13 | * [Your choice of a jQuery UI theme](http://jqueryui.com/themeroller/#themeGallery)
14 | * [Free JGrid Plugin](https://github.com/free-jqgrid/jqGrid) or [jQuery Grid Plugin](http://www.trirand.com/blog/)
15 |
16 | ## Features
17 |
18 | * Spreadsheet Exporter.
19 | * CSV Exporter.
20 | * Config file with global properties to use in all grids of your application.
21 | * PHP Render to handle the jqGrid HTML and Javascript code.
22 | * JSON Data Enconder to send the data to the grid in the correct format.
23 | * Datasource independent (you are able to create your own datasource implementation).
24 |
25 | ## Documentation
26 |
27 | The complete documentation can be found at: [mariogallegos.com](http://goo.gl/Krn7o7)
28 |
29 | ## Live Demos
30 |
31 | There are three demos available:
32 |
33 | * Pivot Grid(Not available)
34 | * CRUD Web App with jqGrid forms(Not available)
35 | * [CRUD Web App with a custom form](http://www.mariogallegos.com/cms/open-source-development/laravel-jqgrid/demo3)
36 |
37 | ## Tutorials
38 |
39 | There are three tutorials available:
40 |
41 | * Building a Pivot Grid and handling jqGrid events using Laravel jqGrid package(Not available)
42 | * Building a CRUD Web App with jqGrid forms using Laravel jqGrid package(Not available)
43 | * [Building a CRUD Web App with a custom form using Laravel jqGrid package](http://www.mariogallegos.com/cms/tutorials)
44 |
45 | ## Aditional information
46 |
47 | Any questions, problems or feature request feel free to open an [issue](https://github.com/mgallegos/laravel-jqgrid/issues).
48 |
49 |
50 | ## License
51 |
52 | Laravel jqGrid package is open source software licensed under the MIT License.
53 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mgallegos/laravel-jqgrid",
3 | "description": "Laravel jqGrid package allows you to easily integrate the popular jQuery Grid Plugin (jqGrid) into your Laravel application.",
4 | "keywords": ["laravel", "jquery", "jqgrid", "grid"],
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Mario Gallegos",
9 | "email": "freelance@mariogallegos.com"
10 | }
11 | ],
12 | "require": {
13 | "php": ">=5.3.0",
14 | "illuminate/support": "4.*|5.*|6.*|7.*|8.*|9.*|10.*|11.*|12.*",
15 | "phpoffice/phpspreadsheet": "^1.8"
16 | },
17 | "autoload": {
18 | "classmap": [
19 | "src/migrations"
20 | ],
21 | "psr-0": {
22 | "Mgallegos\\LaravelJqgrid": "src/"
23 | }
24 | },
25 | "minimum-stability": "dev"
26 | }
27 |
--------------------------------------------------------------------------------
/jqGrid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgallegos/laravel-jqgrid/afcb0331512926a22fdc4308a9d3b242d193c807/jqGrid.png
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | ./tests/
16 |
17 |
18 |
--------------------------------------------------------------------------------
/public/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgallegos/laravel-jqgrid/afcb0331512926a22fdc4308a9d3b242d193c807/public/.gitkeep
--------------------------------------------------------------------------------
/src/Mgallegos/LaravelJqgrid/Encoders/JqGridJsonEncoder.php:
--------------------------------------------------------------------------------
1 | ';
175 | break;
176 | case 'ge': //greater or equal
177 | $filter['op'] = '>=';
178 | break;
179 | case 'bw': //begins with
180 | $filter['op'] = 'like';
181 | $filter['data'] = $filter['data'] . '%';
182 | break;
183 | case 'bn': //does not begin with
184 | $filter['op'] = 'not like';
185 | $filter['data'] = $filter['data'] . '%';
186 | break;
187 | case 'in': //is in
188 | $filter['op'] = 'is in';
189 | break;
190 | case 'ni': //is not in
191 | $filter['op'] = 'is not in';
192 | break;
193 | case 'ew': //ends with
194 | $filter['op'] = 'like';
195 | $filter['data'] = '%' . $filter['data'];
196 | break;
197 | case 'en': //does not end with
198 | $filter['op'] = 'not like';
199 | $filter['data'] = '%' . $filter['data'];
200 | break;
201 | case 'cn': //contains
202 | $filter['op'] = 'like';
203 | $filter['data'] = '%' . str_replace(' ', '%', $filter['data']) . '%';
204 | break;
205 | case 'cnpg': //contains PostgreSQL
206 | $filter['op'] = 'ilike';
207 | $filter['data'] = '%' . str_replace(' ', '%', $filter['data']) . '%';
208 | break;
209 | case 'nc': //does not contains
210 | $filter['op'] = 'not like';
211 | $filter['data'] = '%' . $filter['data'] . '%';
212 | break;
213 | case 'nu': //is null
214 | $filter['op'] = 'is null';
215 | $filter['data'] = '';
216 | break;
217 | case 'nn': //is not null
218 | $filter['op'] = 'is not null';
219 | $filter['data'] = '';
220 | break;
221 | case 'btw': //between
222 | $filter['op'] = 'between';
223 | break;
224 | }
225 | }
226 | }
227 | else
228 | {
229 | $filters['rules'] = array();
230 | }
231 |
232 | $Repository->beforeProcessing();
233 |
234 | $count = $Repository->getTotalNumberOfRows($filters['rules']);
235 |
236 | if(empty($limit))
237 | {
238 | $limit = $count;
239 | }
240 |
241 | if(!is_int($count))
242 | {
243 | throw new Exception('The method getTotalNumberOfRows must return an integer');
244 | }
245 |
246 | if( $count > 0 )
247 | {
248 | $totalPages = ceil($count/$limit);
249 | }
250 | else
251 | {
252 | $totalPages = 0;
253 | }
254 |
255 | if ($page > $totalPages)
256 | {
257 | $page = $totalPages;
258 | }
259 |
260 | if ($limit < 0 )
261 | {
262 | $limit = 0;
263 | }
264 |
265 | $start = $limit * $page - $limit;
266 |
267 | if ($start < 0)
268 | {
269 | $start = 0;
270 | }
271 |
272 | $limit = $limit * $page;
273 |
274 | if(empty($postedData['pivotRows']))
275 | {
276 | $rows = $Repository->getRows($limit, $start, $sidx, $sord, $filters['rules'], $nodeId, $nodeLevel, $exporting);
277 |
278 | if($encodeRowsToUtf8)
279 | {
280 | $rows = $this->utf8ize($rows);
281 | }
282 |
283 | if($count < count($rows))
284 | {
285 | $count = count($rows);
286 | }
287 | }
288 | else
289 | {
290 | $rows = json_decode($postedData['pivotRows'], true);
291 | }
292 |
293 | if(!is_array($rows) || (isset($rows[0]) && !is_array($rows[0])))
294 | {
295 | throw new Exception('The method getRows must return an array of arrays, example: array(array("column1" => "1-1", "column2" => "1-2"), array("column1" => "2-1", "column2" => "2-2"))');
296 | }
297 |
298 | if($exporting)
299 | {
300 | $method_name = 'export_to_'.$postedData['exportFormat'];
301 |
302 | if(method_exists($Repository, $method_name) )
303 | {
304 | return $Repository->$method_name(
305 | array_merge(
306 | ['rows'=> $rows],
307 | ['postedData'=> $postedData]
308 | )
309 | );
310 | }
311 |
312 | $this->setSpreadsheetStyles();
313 |
314 | $StreamedResponse = new StreamedResponse();
315 | $StreamedResponse->setCallback(function () use (&$rows, $postedData)
316 | {
317 |
318 | // foreach (json_decode($postedData['fileProperties'], true) as $key => $value)
319 | // {
320 | // $method = 'set' . ucfirst($key);
321 |
322 | // $Excel->$method($value);
323 | // }
324 |
325 | $groupingView = json_decode($postedData['groupingView'], true);
326 | $groupHeaders = json_decode($postedData['groupHeaders'], true);
327 | $columnsPositions = $summaryTypes = $modelLabels = $modelSelectFormattersValues = $modelNumberFormatters = $modelDateFormatters = $numericColumns = $textColumns = array();
328 | $groupFieldName = '';
329 | $columnCounter = 0;
330 | $Spreadsheet = new Spreadsheet();
331 | $Worksheet = $Spreadsheet->getActiveSheet();
332 |
333 | foreach (json_decode($postedData['model'], true) as $a => $model)
334 | {
335 | $styles = array();
336 | $formatCode = '';
337 | $isVisible = false;
338 |
339 | if(!empty($groupingView) && $groupingView['groupField'][0] == $model['name'])
340 | {
341 | if(isset($model['hidden']) && $model['hidden'] === true)
342 | {
343 | $groupFieldHidden = true;
344 | }
345 | else
346 | {
347 | $groupFieldHidden = false;
348 | }
349 |
350 | $groupFieldName = $model['name'];
351 |
352 | if(isset($model['label']))
353 | {
354 | $groupFieldLabel = $model['label'];
355 | }
356 | else
357 | {
358 | $groupFieldLabel = $model['name'];
359 | }
360 | }
361 |
362 | if(isset($model['hidden']) && $model['hidden'] !== true)
363 | {
364 | $columnCounter++;
365 |
366 | $isVisible = true;
367 | $columnsPositions[$model['name']] = $columnCounter;
368 | }
369 |
370 | if(isset($model['hidedlg']) && $model['hidedlg'] === true)
371 | {
372 | continue;
373 | }
374 |
375 | if(isset($model['summaryType']))
376 | {
377 | $summaryTypes[isset($model['label']) ? $model['label'] : $model['name']] = $model['summaryType'];
378 | }
379 |
380 | if($model['hidden'] === false || $model['name'] == $groupFieldName)
381 | {
382 | if(isset($model['label']))
383 | {
384 | $modelLabels[$model['name']] = $model['label'];
385 | }
386 | else
387 | {
388 | $modelLabels[$model['name']] = $model['name'];
389 | }
390 | }
391 |
392 | if(isset($model['formatter']))
393 | {
394 | switch ($model['formatter'])
395 | {
396 | case 'select':
397 | if(isset($model['editoptions']['value']))
398 | {
399 | foreach (explode(';', $model['editoptions']['value']) as $index => $value)
400 | {
401 | $temp = explode(':', $value);
402 |
403 | $modelSelectFormattersValues[isset($model['label']) ? $model['label'] : $model['name']][$temp[0]] = $temp[1];
404 | }
405 | }
406 |
407 | break;
408 | case 'integer':
409 | $formatCode = '0';
410 | // $modelNumberFormatters[$model['name']] = '0';
411 |
412 | array_push($numericColumns, isset($model['label']) ? $model['label'] : $model['name']);
413 |
414 | break;
415 | case 'number':
416 | case 'currency':
417 | if(isset($model['formatoptions']['prefix']))
418 | {
419 | // $prefix = $model['formatoptions']['prefix'];
420 |
421 | $formatCode = '"' . $model['formatoptions']['prefix'] . '"#,##0.00';
422 | }
423 | else
424 | {
425 | // $prefix = '';
426 | $formatCode = '#,##0.00';
427 | }
428 |
429 | // $formatCode = '"' . $prefix . '"#,##0.00';
430 | // $modelNumberFormatters[$model['name']] = '"' . $prefix . '"#,##0.00';
431 |
432 | array_push($numericColumns, isset($model['label']) ? $model['label'] : $model['name']);
433 |
434 | break;
435 | case 'date':
436 | if((isset($model['formatoptions']['srcformat']) || $postedData['srcDateFormat']) && (isset($model['formatoptions']['newformat']) || $postedData['newDateFormat']))
437 | {
438 | if(isset($model['formatoptions']['srcformat']))
439 | {
440 | $srcformat = $model['formatoptions']['srcformat'];
441 | }
442 | else
443 | {
444 | $srcformat = $postedData['srcDateFormat'];
445 | }
446 |
447 | if(isset($model['formatoptions']['newformat']))
448 | {
449 | $newformat = $model['formatoptions']['newformat'];
450 | }
451 | else
452 | {
453 | $newformat = $postedData['newDateFormat'];
454 | }
455 |
456 | // $modelDateFormatters[$model['name']] = array('srcformat' => $srcformat, 'newformat' => $newformat);
457 | $modelDateFormatters[isset($model['label']) ? $model['label'] : $model['name']] = array('srcformat' => $srcformat, 'newformat' => $newformat);
458 | }
459 |
460 | break;
461 | }
462 | }
463 |
464 | if (isset($model['align']) && isset($model['hidden']) && $model['hidden'] !== true)
465 | {
466 | switch ($model['align']) {
467 | case 'left':
468 | $styles = array_merge($styles, $this->styleAlignmentLeft);
469 | break;
470 | case 'right':
471 | $styles = array_merge($styles, $this->styleAlignmentRight);
472 | break;
473 | case 'center':
474 | $styles = array_merge($styles, $this->styleAlignmentCenter);
475 | break;
476 | default:
477 | # code...
478 | break;
479 | }
480 | }
481 |
482 | if($isVisible)
483 | {
484 | $letter = $this->numToLetter($columnCounter, true);
485 |
486 | if(!empty($styles))
487 | {
488 | $Worksheet->getStyle($letter . ':' . $letter)->applyFromArray($styles);
489 | }
490 |
491 | if(!empty($formatCode))
492 | {
493 | $Worksheet->getStyle($letter . ':' . $letter)
494 | ->getNumberFormat()
495 | ->applyFromArray(
496 | [
497 | 'formatCode' => $formatCode
498 | ]
499 | );
500 | }
501 | else
502 | {
503 | $Worksheet->getStyle($letter . ':' . $letter)
504 | ->getNumberFormat()
505 | ->setFormatCode( \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_TEXT );
506 |
507 | array_push($textColumns, isset($model['label']) ? $model['label'] : $model['name']);
508 | }
509 |
510 |
511 | if(!empty($model['width']))
512 | {
513 | // $Worksheet->getColumnDimension($letter)->setAutoSize(true);
514 | // $Worksheet->getColumnDimension($letter)->setWidth($model['width'], 'px');
515 | }
516 | }
517 | }
518 |
519 | $copyRows = $rows;
520 | $rows = array();
521 |
522 | if(empty($postedData['pivot']))
523 | {
524 | foreach ($copyRows as $index => $row)
525 | {
526 | $currentRow = array();
527 |
528 | foreach ($modelLabels as $columnName => $value)
529 | {
530 | $currentRow[$value] = isset($row[$columnName]) ? $row[$columnName] : '';
531 | }
532 |
533 | foreach ($modelSelectFormattersValues as $label => $modelSelectFormatterValue)
534 | {
535 | if(isset($currentRow[$label]))
536 | {
537 | $currentRow[$label] = isset($modelSelectFormatterValue[$currentRow[$label]])?$modelSelectFormatterValue[$currentRow[$label]]:$currentRow[$label];
538 | }
539 | }
540 |
541 | foreach ($modelDateFormatters as $label => $modelDateFormatter)
542 | {
543 | if(isset($currentRow[$label]) && !empty($currentRow[$label]))
544 | {
545 | $currentRow[$label] = Carbon::createFromFormat($modelDateFormatter['srcformat'], $currentRow[$label])->format($modelDateFormatter['newformat']);
546 | }
547 | }
548 |
549 | foreach ($numericColumns as $index => $label)
550 | {
551 | if(isset($currentRow[$label]))
552 | {
553 | $currentRow[$label] = (float) $currentRow[$label];
554 | }
555 | }
556 |
557 | $rows[] = $currentRow;
558 | // $row = $currentRow;
559 | }
560 | }
561 |
562 | // foreach (json_decode($postedData['sheetProperties'], true) as $key => $value)
563 | // {
564 | // $method = 'set' . ucfirst($key);
565 |
566 | // $Sheet->$method($value);
567 | // }
568 |
569 | $subTotalGroupedRowsNumber = array();
570 |
571 | if(!empty($groupingView))
572 | {
573 | $groupedRows = $groupedRowsNumbers = $subTotalGroupedRow = $currentSubTotalGroupedRow = array();
574 | $rowCounter = 0;
575 |
576 | foreach ($rows as $index => $row)
577 | {
578 | if($rowCounter == 0)
579 | {
580 | $currentgroupFieldValue = $row[$groupFieldLabel];
581 |
582 | if($groupFieldHidden)
583 | {
584 | unset($row[$groupFieldLabel]);
585 | }
586 |
587 | $firstColumnName = key($row);
588 |
589 | $groupedRow = $row;
590 |
591 | foreach ($groupedRow as $label => &$cell)
592 | {
593 | if($firstColumnName == $label)
594 | {
595 | $cell = $currentgroupFieldValue;
596 | }
597 | else
598 | {
599 | $cell = '';
600 | }
601 |
602 | $subTotalGroupedRow[$label] = '';
603 | }
604 |
605 | $currentSubTotalGroupedRow = $subTotalGroupedRow;
606 |
607 | $rowCounter = 2;
608 |
609 | if(!empty($groupHeaders))
610 | {
611 | $rowCounter++;
612 | }
613 |
614 | array_push($groupedRows, $groupedRow);
615 | array_push($groupedRowsNumbers, $rowCounter);
616 | }
617 | else
618 | {
619 | if($row[$groupFieldLabel] != $currentgroupFieldValue)
620 | {
621 | $currentgroupFieldValue = $groupedRow[$firstColumnName] = $row[$groupFieldLabel];
622 |
623 | $rowCounter++;
624 |
625 | if(!empty($summaryTypes))
626 | {
627 | foreach ($summaryTypes as $column => $summaryType)
628 | {
629 | switch ($summaryType) {
630 | case 'count':
631 | $currentSubTotalGroupedRow[$column] = "($currentSubTotalGroupedRow[$column]) total";
632 | break;
633 | }
634 | }
635 |
636 | array_push($groupedRows, $currentSubTotalGroupedRow);
637 | array_push($subTotalGroupedRowsNumber, $rowCounter);
638 |
639 | $currentSubTotalGroupedRow = $subTotalGroupedRow;
640 |
641 | $rowCounter++;
642 | }
643 |
644 | array_push($groupedRows, $groupedRow);
645 | array_push($groupedRowsNumbers, $rowCounter);
646 | }
647 |
648 | if($groupFieldHidden)
649 | {
650 | unset($row[$groupFieldLabel]);
651 | }
652 | }
653 |
654 | if(!empty($summaryTypes))
655 | {
656 | foreach ($summaryTypes as $label => $summaryType)
657 | {
658 | switch ($summaryType) {
659 | case 'sum':
660 | if(empty($currentSubTotalGroupedRow[$label]))
661 | {
662 | $currentSubTotalGroupedRow[$label] = $row[$label] + 0;
663 | }
664 | else
665 | {
666 | $currentSubTotalGroupedRow[$label] += $row[$label];
667 | }
668 |
669 | break;
670 | case 'count':
671 | if($currentSubTotalGroupedRow[$label] != 0 && empty($currentSubTotalGroupedRow[$label]))
672 | {
673 | $currentSubTotalGroupedRow[$label] = 0;
674 | }
675 | else
676 | {
677 | $currentSubTotalGroupedRow[$label] ++;
678 | }
679 |
680 | break;
681 | }
682 | }
683 | }
684 |
685 | array_push($groupedRows, $row);
686 |
687 | $rowCounter++;
688 | }
689 |
690 | if(!empty($summaryTypes))
691 | {
692 | foreach ($summaryTypes as $column => $summaryType)
693 | {
694 | switch ($summaryType) {
695 | case 'count':
696 | $currentSubTotalGroupedRow[$column] = "($currentSubTotalGroupedRow[$column]) total";
697 | break;
698 | }
699 | }
700 |
701 | array_push($groupedRows, $currentSubTotalGroupedRow);
702 | array_push($subTotalGroupedRowsNumber, ++$rowCounter);
703 | }
704 |
705 | $lastCellLetter = $this->numToLetter($columnCounter, true);
706 |
707 | foreach ($groupedRowsNumbers as $index => $groupedRowsNumber)
708 | {
709 | $Worksheet->mergeCells("A$groupedRowsNumber:$lastCellLetter$groupedRowsNumber");
710 | }
711 |
712 | $rows = $groupedRows;
713 | }
714 |
715 | // $columnFormats = array();
716 |
717 | // foreach ($modelNumberFormatters as $columnName => $format)
718 | // {
719 | // if(isset($columnsPositions[$columnName]))
720 | // {
721 | // $columnFormats[$this->numToLetter($columnsPositions[$columnName], true)] = $format;
722 | // }
723 | // }
724 |
725 | // $Sheet->setColumnFormat($columnFormats);
726 |
727 | $footerRow = json_decode($postedData['fotterRow'], true);
728 |
729 | if(!empty($footerRow))
730 | {
731 | array_push($rows, $footerRow);
732 | }
733 |
734 | $headers = $firstHeader = array();
735 |
736 | if(!empty($groupHeaders))
737 | {
738 | foreach ($groupHeaders as $index => $groupHeader)
739 | {
740 | $firstHeader[$columnsPositions[$groupHeader['startColumnName']] - 1] = $groupHeader['titleText'];
741 |
742 | $Worksheet->mergeCells(
743 | $this->numToLetter(
744 | $columnsPositions[$groupHeader['startColumnName']],
745 | true
746 | ) .
747 | '1:' .
748 | $this->numToLetter(
749 | // $columnsPositions[$groupHeader['startColumnName']] + $groupHeader['numberOfColumns'] - 1,
750 | $columnsPositions[$groupHeader['startColumnName']] + $groupHeader['numberOfColumns'],
751 | true
752 | ) .
753 | '1'
754 | );
755 | }
756 |
757 | array_push($headers, $firstHeader);
758 | array_push($headers, array_keys($rows[0]));
759 |
760 | $Worksheet->fromArray($headers, null, 'A1');
761 | $Worksheet->getStyle('A1:' . $this->numToLetter($columnCounter, true) . '1')
762 | ->applyFromArray($this->styleBold);
763 | $Worksheet->getStyle('A1:' . $this->numToLetter($columnCounter, true) . '1')
764 | ->getAlignment()
765 | ->setWrapText(true);
766 | $Worksheet->getStyle('A2:' . $this->numToLetter($columnCounter, true) . '2')
767 | ->applyFromArray($this->styleBold);
768 |
769 | $counterRow = 3;
770 | }
771 | else
772 | {
773 | array_push($headers, array_keys($rows[0]));
774 |
775 | $Worksheet->fromArray($headers, null, 'A1');
776 |
777 | $Worksheet->getStyle('A1:' . $this->numToLetter($columnCounter, true) . '1')
778 | ->applyFromArray($this->styleBold);
779 | $Worksheet->getStyle('A1:' . $this->numToLetter($columnCounter, true) . '1')
780 | ->getAlignment()
781 | ->setWrapText(true);
782 |
783 | $counterRow = 2;
784 | }
785 |
786 | $columns = array_keys($rows[0]);
787 |
788 | foreach ($rows as $key => $row)
789 | {
790 | $counterColumn = 'A';
791 |
792 | foreach ($columns as $column)
793 | {
794 | if(in_array($column, $textColumns))
795 | {
796 | $Worksheet->setCellValueExplicit(
797 | "$counterColumn$counterRow", $row[$column],
798 | \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING
799 | );
800 | }
801 | else
802 | {
803 | $Worksheet->setCellValue("$counterColumn$counterRow", $row[$column]);
804 | }
805 |
806 | $counterColumn++;
807 | }
808 |
809 | $counterRow++;
810 | }
811 |
812 | foreach ($subTotalGroupedRowsNumber as $index => $number)
813 | {
814 | $Worksheet->getStyle('A' . $number . ':' . $this->numToLetter($columnCounter, true) . $number)
815 | ->applyFromArray($this->styleBold);
816 | }
817 |
818 | if(!empty($footerRow))
819 | {
820 | if(!empty($headers))
821 | {
822 | $footerRowNumber = count($rows) + count($headers);
823 | }
824 | else
825 | {
826 | $footerRowNumber = count($rows) + 1;
827 | }
828 |
829 | $Worksheet->getStyle('A' . $footerRowNumber . ':' . $this->numToLetter($columnCounter, true) . $footerRowNumber)
830 | ->applyFromArray($this->styleBold);
831 |
832 | // $Worksheet->row($footerRowNumber, function($Row)
833 | // {
834 | // $Row->setFontWeight('bold');
835 | // });
836 | }
837 |
838 | $Writer = new Xlsx($Spreadsheet);
839 | $Writer->save('php://output');
840 | });
841 |
842 | $contentDisposition = 'attachment; filename=' . $postedData['name'] . '.xlsx';
843 | $StreamedResponse->setStatusCode(Response::HTTP_OK);
844 | $StreamedResponse->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
845 | $StreamedResponse->headers->set('Content-Disposition', $contentDisposition);
846 |
847 | return $StreamedResponse->send();
848 | }
849 | else
850 | {
851 | echo $this->safe_json_encode(
852 | array(
853 | 'page' => $page,
854 | 'total' => $totalPages,
855 | 'records' => $count,
856 | 'rows' => $rows
857 | )
858 | );
859 | }
860 | }
861 |
862 | /**
863 | * Takes a number and converts it to a-z,aa-zz,aaa-zzz, etc with uppercase option
864 | *
865 | * @access protected
866 | * @param int number to convert
867 | * @param bool upper case the letter on return?
868 | * @return string letters from number input
869 | */
870 | protected function numToLetter($c, $uppercase = FALSE)
871 | {
872 | $c = intval($c);
873 | if ($c <= 0) return '';
874 |
875 | $letter = '';
876 |
877 | while($c != 0){
878 | $p = ($c - 1) % 26;
879 | $c = intval(($c - $p) / 26);
880 | $letter = chr(65 + $p) . $letter;
881 | }
882 |
883 | return ($uppercase ? strtoupper($letter) : $letter);
884 | }
885 |
886 | /**
887 | * Safe JSON_ENCODE function that tries to deal with UTF8 chars or throws a valid exception.
888 | *
889 | * Lifted from http://stackoverflow.com/questions/10199017/how-to-solve-json-error-utf8-error-in-php-json-decode
890 | * Based on: http://php.net/manual/en/function.json-last-error.php#115980
891 | * @param $value
892 | * @return string
893 | */
894 | protected function safe_json_encode($value)
895 | {
896 | if (version_compare(PHP_VERSION, '5.4.0') >= 0)
897 | {
898 | $encoded = json_encode($value, JSON_PRETTY_PRINT);
899 | }
900 | else
901 | {
902 | $encoded = json_encode($value);
903 | }
904 | switch (json_last_error())
905 | {
906 | case JSON_ERROR_NONE:
907 | return $encoded;
908 | case JSON_ERROR_DEPTH:
909 | throw new JsonEncodingMaxDepthException('Maximum stack depth exceeded.');
910 | case JSON_ERROR_STATE_MISMATCH:
911 | throw new JsonEncodingStateMismatchException('Underflow or the modes mismatch.');
912 | case JSON_ERROR_CTRL_CHAR:
913 | throw new JsonEncodingUnexpectedControlCharException('Unexpected control character found.');
914 | case JSON_ERROR_SYNTAX:
915 | throw new JsonEncodingSyntaxErrorException('Syntax , malformed JSON.');
916 | case JSON_ERROR_UTF8:
917 | $clean = $this->utf8ize($value);
918 | return $this->safe_json_encode($clean);
919 | default:
920 | throw new JsonEncodingUnknownException('Unknown error');
921 | }
922 | }
923 |
924 | /**
925 | * Clean the array passed in from UTF8 chars.
926 | *
927 | * Lifted from http://stackoverflow.com/questions/10199017/how-to-solve-json-error-utf8-error-in-php-json-decode
928 | * Based on: http://php.net/manual/en/function.json-last-error.php#115980
929 | *
930 | * @param $mixed
931 | * @return array|string
932 | */
933 | protected function utf8ize($mixed)
934 | {
935 | if (is_array($mixed))
936 | {
937 | foreach ($mixed as $key => $value)
938 | {
939 | $mixed[$key] = $this->utf8ize($value);
940 | }
941 | } else if (is_string ($mixed))
942 | {
943 | return utf8_encode($mixed);
944 | }
945 |
946 | return $mixed;
947 | }
948 |
949 | /**
950 | * Set Spreadsheet styles
951 | *
952 | * @return void
953 | */
954 | protected function setSpreadsheetStyles()
955 | {
956 | $this->styleBold = [
957 | 'font' => [
958 | 'bold' => 'true'
959 | ]
960 | ];
961 |
962 | $this->styleAlignmentLeft = [
963 | 'alignment' => [
964 | 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT,
965 | ]
966 | ];
967 |
968 | $this->styleAlignmentRight = [
969 | 'alignment' => [
970 | 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_RIGHT,
971 | ]
972 | ];
973 |
974 | $this->styleAlignmentCenter = [
975 | 'alignment' => [
976 | 'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
977 | ]
978 | ];
979 | }
980 | }
981 |
--------------------------------------------------------------------------------
/src/Mgallegos/LaravelJqgrid/Encoders/RequestedDataInterface.php:
--------------------------------------------------------------------------------
1 | isLaravelVersion('4'))
34 | {
35 | $this->package('mgallegos/laravel-jqgrid');
36 | }
37 | // elseif ($this->isLaravelVersion('5'))
38 | else
39 | {
40 | $this->publishes([
41 | __DIR__ . '/../../config/config.php' => config_path('laravel-jqgrid.php'),
42 | ]);
43 |
44 | $this->mergeConfigFrom(
45 | __DIR__ . '/../../config/config.php', 'laravel-jqgrid'
46 | );
47 | }
48 | }
49 |
50 | /**
51 | * Register the service provider.
52 | *
53 | * @return void
54 | */
55 | public function register()
56 | {
57 | if ($this->isLaravelVersion('5'))
58 | {
59 | $this->app->register('Maatwebsite\Excel\ExcelServiceProvider');
60 | }
61 | $this->registerRender();
62 | $this->registerEncoder();
63 | }
64 |
65 | /**
66 | * Register render service provider.
67 | *
68 | * @return void
69 | */
70 | public function registerRender()
71 | {
72 | if ($this->isLaravelVersion('4'))
73 | {
74 | $prefix = 'laravel-jqgrid::';
75 | }
76 | // elseif ($this->isLaravelVersion('5'))
77 | else
78 | {
79 | $prefix = 'laravel-jqgrid.';
80 | }
81 |
82 | $this->app->bind('gridrender', function($app) use ($prefix)
83 | {
84 | return new Renders\JqGridRender(
85 | array(),
86 | array(new NameValidation()),
87 | array(),
88 | array(),
89 | $app['config']->get($prefix . 'default_grid_options'),
90 | $app['config']->get($prefix . 'default_pivot_grid_options'),
91 | $app['config']->get($prefix . 'default_group_header_options'),
92 | $app['config']->get($prefix . 'default_col_model_properties'),
93 | $app['config']->get($prefix . 'default_navigator_options'),
94 | $app['config']->get($prefix . 'default_filter_toolbar_options'),
95 | $app['config']->get($prefix . 'default_filter_toolbar_buttons_options'),
96 | $app['config']->get($prefix . 'default_export_buttons_options'),
97 | $app['config']->get($prefix . 'default_file_properties'),
98 | $app['config']->get($prefix . 'default_sheet_properties'),
99 | $app['config']->get($prefix . 'function_type_properties'),
100 | $app['config']->get($prefix . 'pivot_options'),
101 | $app['config']->get($prefix . 'group_header_options'),
102 | $app['session']->token()
103 | );
104 | });
105 | }
106 |
107 | /**
108 | * Register encoder service provider.
109 | *
110 | * @return void
111 | */
112 | public function registerEncoder()
113 | {
114 | $this->app->bind('Mgallegos\LaravelJqgrid\Encoders\RequestedDataInterface', function($app)
115 | {
116 | return new Encoders\JqGridJsonEncoder();
117 | });
118 | }
119 |
120 | /**
121 | * Determine if laravel starts with any of the given version strings
122 | *
123 | * @param string|array $startsWith
124 | * @return boolean
125 | */
126 | protected function isLaravelVersion($startsWith)
127 | {
128 | return Str::startsWith(Application::VERSION, $startsWith);
129 | }
130 |
131 |
132 | /**
133 | * Get the services provided by the provider.
134 | *
135 | * @return array
136 | */
137 | public function provides()
138 | {
139 | return array('gridrender', 'Mgallegos\LaravelJqgrid\Encoders\RequestedDataInterface');
140 | }
141 |
142 | }
143 |
--------------------------------------------------------------------------------
/src/Mgallegos/LaravelJqgrid/Renders/JqGridRender.php:
--------------------------------------------------------------------------------
1 | gridId = str_random(10);
350 | $this->jqPivot = false;
351 | $this->frozenColumn = false;
352 | $this->colModelValidators = $colModelValidators;
353 | $this->optionValidators = $optionValidators;
354 | $this->navigatorValidators = $navigatorValidators;
355 | $this->filterToolbarValidators = $filterToolbarValidators;
356 | $this->colModel = array();
357 | $this->options = $defaultGridOptions;
358 | $this->pivotOptions = $defaultPivotGridOptions;
359 | $this->pivotOptionsNames = $pivotOptionsNames;
360 | $this->groupHeaderOptions = $defaultGroupHeaderOptions;
361 | $this->groupHeaderOptionsNames = $groupHeaderOptionsNames;
362 | $this->navigatorOptions = $defaultNavigatorOptions;
363 | $this->navigatorEditOptions = array();
364 | $this->navigatorAddOptions = array();
365 | $this->navigatorDeleteOptions = array();
366 | $this->navigatorSearchOptions = array();
367 | $this->navigatorViewOptions = array();
368 | $this->filterToolbarOptions = $defaultfilterToolbarOptions;
369 | $this->filterToolbarButtonsOptions = $defaultFilterToolbarButtonsOptions;
370 | $this->exportButtonsOptions = $defaultExportButtonsOptions;
371 | $this->fileProperties = $defaultFileProperties;
372 | $this->sheetProperties = $defaultSheetProperties;
373 | $this->defaultColModelProperties = $defaultColModelProperties;
374 | $this->defaultGridOptions = $defaultGridOptions;
375 | $this->defaultPivotGridOptions = $defaultPivotGridOptions;
376 | $this->defaultGroupHeaderOptions = $defaultGroupHeaderOptions;
377 | $this->defaultNavigatorOptions = $defaultNavigatorOptions;
378 | $this->defaultfilterToolbarOptions = $defaultfilterToolbarOptions;
379 | $this->defaultFilterToolbarButtonsOptions = $defaultFilterToolbarButtonsOptions;
380 | $this->defaultExportButtonsOptions = $defaultExportButtonsOptions;
381 | $this->defaultFileProperties = $defaultFileProperties;
382 | $this->defaultSheetProperties = $defaultSheetProperties;
383 | $this->functionTypeProperties = $functionTypeProperties;
384 | $this->token = $token;
385 | }
386 |
387 | /**
388 | * Add a column at the last position in the columns model.
389 | *
390 | * @param string $id
391 | *
392 | * @return $this
393 | * Returns an object, allowing the calls to be chained together in a single statement
394 | */
395 | public function setGridId($id=null)
396 | {
397 | $this->gridId = $id;
398 |
399 | return $this;
400 | }
401 |
402 | /**
403 | * Add a column at the last position in the columns model.
404 | *
405 | * @param array $properties
406 | * An array of valid jqGrid column model property, the index key of the array must correspond to a column model property.
407 | * Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options
408 | * @return $this
409 | * Returns an object, allowing the calls to be chained together in a single statement
410 | */
411 | public function addColumn(array $properties = array())
412 | {
413 | foreach ($this->colModelValidators as $validator)
414 | {
415 | $validator->validate($properties);
416 | }
417 |
418 | if (in_array('frozen', $properties))
419 | {
420 | $this->frozenColumn = true;
421 | }
422 |
423 | if (!isset($properties['name']) && !isset($properties['index']))
424 | {
425 | $properties = array_add($properties, 'name', 'Col. ' . (count($this->colModel) + 1));
426 | $properties = array_add($properties, 'index', 'Col. ' . (count($this->colModel) + 1));
427 | }
428 |
429 | if (!isset($properties['name']) && isset($properties['index']))
430 | {
431 | $properties = array_add($properties, 'name', $properties['index']);
432 | }
433 |
434 | if (isset($properties['name']) && !isset($properties['index']))
435 | {
436 | $properties = array_add($properties, 'index', $properties['name']);
437 | }
438 |
439 | $this->markFunctionTypeProperty($properties);
440 |
441 | array_push($this->colModel, array_merge($this->defaultColModelProperties, $properties));
442 |
443 | return $this;
444 | }
445 |
446 | /**
447 | * Add a group header. This are columns that can be added above the normal grid columns.
448 | * This method has no effect when working with pivot grid.
449 | *
450 | * @param array $properties
451 | * An array of valid group header options.
452 | * Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:groupingheadar
453 | * @return $this
454 | * Returns an object, allowing the calls to be chained together in a single statement
455 | */
456 | public function addGroupHeader(array $properties = array())
457 | {
458 | foreach ($this->optionValidators as $validator)
459 | {
460 | $validator->validate(array_add(array(), $option, $value));
461 | }
462 |
463 | $this->markFunctionTypeProperty($properties);
464 |
465 | if(!isset($this->groupHeaderOptions['groupHeaders']))
466 | {
467 | $this->groupHeaderOptions['groupHeaders'] = array();
468 | }
469 |
470 | array_push($this->groupHeaderOptions['groupHeaders'], $properties);
471 |
472 | return $this;
473 | }
474 |
475 | /**
476 | * Add a X dimension. Use this method only when working with pivot grids.
477 | *
478 | * @param array $properties
479 | * An array of valid xDimension options.
480 | * Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:pivotsettings
481 | * @return $this
482 | * Returns an object, allowing the calls to be chained together in a single statement
483 | */
484 | public function addXDimension(array $properties = array())
485 | {
486 | foreach ($this->colModelValidators as $validator)
487 | {
488 | $validator->validate($properties);
489 | }
490 |
491 | $this->markFunctionTypeProperty($properties);
492 |
493 | if(!isset($this->pivotOptions['xDimension']))
494 | {
495 | $this->pivotOptions['xDimension'] = array();
496 | }
497 |
498 | array_push($this->pivotOptions['xDimension'], array_merge($this->defaultColModelProperties, $properties));
499 |
500 | return $this;
501 | }
502 |
503 | /**
504 | * Add a Y dimension. Use this method only when working with pivot grids.
505 | *
506 | * @param array $properties
507 | * An array of valid yDimension options.
508 | * Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:pivotsettings
509 | * @return $this
510 | * Returns an object, allowing the calls to be chained together in a single statement
511 | */
512 | public function addYDimension(array $properties = array())
513 | {
514 | foreach ($this->colModelValidators as $validator)
515 | {
516 | $validator->validate($properties);
517 | }
518 |
519 | $this->markFunctionTypeProperty($properties);
520 |
521 | if(!isset($this->pivotOptions['yDimension']))
522 | {
523 | $this->pivotOptions['yDimension'] = array();
524 | }
525 |
526 | array_push($this->pivotOptions['yDimension'], array_merge($this->defaultColModelProperties, $properties));
527 |
528 | return $this;
529 | }
530 |
531 | /**
532 | * Add an aggregate. Use this method only when working with pivot grids.
533 | *
534 | * @param array $properties
535 | * An array of valid aggregate options (all jqGrid column model property can be used).
536 | * Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:pivotsettings
537 | * @return $this
538 | * Returns an object, allowing the calls to be chained together in a single statement
539 | */
540 | public function addAggregate(array $properties = array())
541 | {
542 | foreach ($this->colModelValidators as $validator)
543 | {
544 | $validator->validate($properties);
545 | }
546 |
547 | $this->markFunctionTypeProperty($properties);
548 |
549 | if(!isset($this->pivotOptions['aggregates']))
550 | {
551 | $this->pivotOptions['aggregates'] = array();
552 | }
553 |
554 | array_push($this->pivotOptions['aggregates'], array_merge($this->defaultColModelProperties, $properties));
555 |
556 | return $this;
557 | }
558 |
559 | /**
560 | * Set a jqGrid option.
561 | *
562 | * @param string $option
563 | * A valid jqGrid option, online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:options or
564 | * a valid pivot grid option, online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:pivotsettings
565 | * a valid group header option, online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:groupingheadar
566 | * @param mixed $option
567 | * A value of an option can be a string, boolean or array.
568 | * @return $this
569 | * Returns an object, allowing the calls to be chained together in a single statement
570 | */
571 | public function setGridOption($option, $value)
572 | {
573 | foreach ($this->optionValidators as $validator)
574 | {
575 | $validator->validate(array_add(array(), $option, $value));
576 | }
577 |
578 | if (in_array($option, array('xDimension', 'yDimension', 'aggregates')))
579 | {
580 | foreach ($value as &$v)
581 | {
582 | $v = array_merge($this->defaultColModelProperties, $v);
583 | $this->markFunctionTypeProperty($v);
584 | }
585 | }
586 |
587 | $property = array_add(array(), $option, $value);
588 |
589 | $this->markFunctionTypeProperty($property);
590 |
591 | if (in_array($option, $this->pivotOptionsNames))
592 | {
593 | if(isset($this->pivotOptions[$option]))
594 | {
595 | $this->pivotOptions[$option] = $property[$option];
596 | }
597 | else
598 | {
599 | $this->pivotOptions = array_add($this->pivotOptions, $option, $property[$option]);
600 | }
601 | }
602 | else if (in_array($option, $this->groupHeaderOptionsNames))
603 | {
604 | if(isset($this->groupHeaderOptions[$option]))
605 | {
606 | $this->groupHeaderOptions[$option] = $property[$option];
607 | }
608 | else
609 | {
610 | $this->groupHeaderOptions = array_add($this->groupHeaderOptions, $option, $property[$option]);
611 | }
612 | }
613 | else
614 | {
615 | if(isset($this->options[$option]))
616 | {
617 | $this->options[$option] = $property[$option];
618 | }
619 | else
620 | {
621 | $this->options = array_add($this->options, $option, $property[$option]);
622 | }
623 | }
624 |
625 | return $this;
626 | }
627 |
628 | /**
629 | * Set a jqGrid event.
630 | *
631 | * @param string $event
632 | * Valid grid event, online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:events&s[]=event
633 | * @param string $code
634 | * Javascript code which will be executed when the event raises
635 | * @return $this
636 | * Returns an object, allowing the calls to be chained together in a single statement
637 | */
638 | public function setGridEvent($event, $code)
639 | {
640 | foreach ($this->optionValidators as $validator)
641 | {
642 | $validator->validate(array_add(array(), $event, $code));
643 | }
644 |
645 | $this->options = array_add($this->options, $event, '###' . $code . '###');
646 |
647 | return $this;
648 | }
649 |
650 | /**
651 | * Set options in the navigator or in any of the following modules add,edit,del,view, search. Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:navigator
652 | *
653 | * @param string $module
654 | * Can be navigator, add, edit, del, view, search.
655 | * @param array $options
656 | * Options that are applicable to this module The key correspond to the options in jqGrid
657 | * @return $this
658 | * Returns an object, allowing the calls to be chained together in a single statement
659 | */
660 | public function setNavigatorOptions($module, array $options)
661 | {
662 | foreach ($this->navigatorValidators as $validator)
663 | {
664 | $validator->validate(array_add(array(), $module, $options));
665 | }
666 |
667 | $this->markFunctionTypeProperty($options);
668 |
669 | switch ($module)
670 | {
671 | case 'navigator':
672 | $this->navigatorOptions = array_merge($this->navigatorOptions, $options);
673 | break;
674 | case 'edit':
675 | $this->navigatorEditOptions = $options;
676 | break;
677 | case 'add':
678 | $this->navigatorAddOptions = $options;
679 | break;
680 | case 'del':
681 | $this->navigatorDeleteOptions = $options;
682 | break;
683 | case 'search':
684 | $this->navigatorSearchOptions = $options;
685 | break;
686 | case 'view':
687 | $this->navigatorViewOptions = $options;
688 | break;
689 | }
690 |
691 | return $this;
692 | }
693 |
694 | /**
695 | * Set an event in the navigator or in the diffrent modules add,edit,del,view, search. Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:navigator
696 | *
697 | * @param string $module
698 | * Can be navigator, edit, add, del, search, view.
699 | * @param string $event
700 | * Valid event for the particular module
701 | * @param string $code
702 | * Javascript code which will be executed when the event raises
703 | * @return $this
704 | * Returns an object, allowing the calls to be chained together in a single statement
705 | */
706 | public function setNavigatorEvent($module, $event, $code)
707 | {
708 | foreach ($this->navigatorValidators as $validator)
709 | {
710 | //$validator->validate(array_add(array(), $module, $options));
711 | }
712 |
713 | switch ($module)
714 | {
715 | case 'navigator':
716 | $this->navigatorOptions = array_add($this->navigatorOptions, $event, '###' . $code . '###');
717 | break;
718 | case 'edit':
719 | $this->navigatorEditOptions = array_add($this->navigatorEditOptions, $event, '###' . $code . '###');
720 | break;
721 | case 'add':
722 | $this->navigatorAddOptions = array_add($this->navigatorAddOptions, $event, '###' . $code . '###');
723 | break;
724 | case 'del':
725 | $this->navigatorDeleteOptions = array_add($this->navigatorDeleteOptions, $event, '###' . $code . '###');
726 | break;
727 | case 'search':
728 | $this->navigatorSearchOptions = array_add($this->navigatorSearchOptions, $event, '###' . $code . '###');
729 | break;
730 | case 'view':
731 | $this->navigatorViewOptions = array_add($this->navigatorViewOptions, $event, '###' . $code . '###');
732 | break;
733 | }
734 |
735 | return $this;
736 | }
737 |
738 | /**
739 | * Set options for the toolbar filter when enabled. Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:toolbar_searching
740 | *
741 | * @param array $options
742 | * Options that are applicable to the filter toolbar
743 | * @return $this
744 | * Returns an object, allowing the calls to be chained together in a single statement
745 | */
746 | public function setFilterToolbarOptions(array $options)
747 | {
748 | foreach ($this->filterToolbarValidators as $validator)
749 | {
750 | $validator->validate($options);
751 | }
752 |
753 | $this->markFunctionTypeProperty($options);
754 |
755 | $this->filterToolbarOptions = array_merge($this->filterToolbarOptions, $options);
756 |
757 | return $this;
758 | }
759 |
760 | /**
761 | * Set a export button option
762 | *
763 | * @param string $option
764 | * A valid export button option: xlsButtonVisible, xlsButtonText, xlsIcon, csvButtonVisible, csvButtonText, csvIcon, srcDateFormat, newDateFormat
765 | * @param mixed $option
766 | * A value of an option can be a string or boolean.
767 | * @return $this
768 | * Returns an object, allowing the calls to be chained together in a single statement
769 | */
770 | public function setExportButtonsOption($option, $value)
771 | {
772 | if(isset($this->exportButtonsOptions[$option]))
773 | {
774 | $this->exportButtonsOptions[$option] = $value;
775 | }
776 | else
777 | {
778 | $this->exportButtonsOptions = array_add($this->exportButtonsOptions, $option, $value);
779 | }
780 |
781 | return $this;
782 | }
783 |
784 | /**
785 | * Set a Spreadsheet file property.
786 | *
787 | * @param string $option
788 | * A valid Spreadsheet file property, online documentation available at https://phpspreadsheet.readthedocs.io/
789 | * @param mixed $option
790 | * A value of an option can be a string, boolean or array.
791 | * @return $this
792 | * Returns an object, allowing the calls to be chained together in a single statement
793 | */
794 | public function setFileProperty($option, $value)
795 | {
796 | if(isset($this->fileProperties[$option]))
797 | {
798 | $this->fileProperties[$option] = $value;
799 | }
800 | else
801 | {
802 | $this->fileProperties = array_add($this->fileProperties, $option, $value);
803 | }
804 |
805 | return $this;
806 | }
807 |
808 | /**
809 | * Set a toolbar event.
810 | *
811 | * @param string $event
812 | * Valid toolbar grid event, online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:toolbar_searching
813 | * @param string $code
814 | * Javascript code which will be executed when the event raises
815 | * @return $this
816 | * Returns an object, allowing the calls to be chained together in a single statement
817 | */
818 | public function setFilterToolbarEvent($event, $code)
819 | {
820 | foreach ($this->filterToolbarValidators as $validator)
821 | {
822 | $validator->validate(array_add(array(), $event, $code));
823 | }
824 |
825 | $this->filterToolbarOptions = array_merge($this->filterToolbarOptions, array_add(array(), $event, '###' . $code . '###'));
826 |
827 | return $this;
828 | }
829 |
830 | /**
831 | * When this method is called the grid will be treated as Pivot Grid (differents javascript methods are used to generate the grid) according to the official documentation. Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:pivotdescription.
832 | *
833 | * @return $this
834 | * Returns an object, allowing the calls to be chained together in a single statement
835 | */
836 | public function setGridAsPivot()
837 | {
838 | $this->jqPivot = true;
839 |
840 | return $this;
841 | }
842 |
843 | /**
844 | * Hide XLS Navigator button.
845 | *
846 | * @return $this
847 | * Returns an object, allowing the calls to be chained together in a single statement
848 | */
849 | public function hideXlsExporter()
850 | {
851 | $this->exportButtonsOptions['xlsButtonVisible'] = false;
852 |
853 | return $this;
854 | }
855 |
856 | /**
857 | * Hide csv Navigator button.
858 | *
859 | * @return $this
860 | * Returns an object, allowing the calls to be chained together in a single statement
861 | */
862 | public function hideCsvExporter()
863 | {
864 | $this->exportButtonsOptions['csvButtonVisible'] = false;
865 |
866 | return $this;
867 | }
868 |
869 | /**
870 | * Set a Spreadsheet sheet property.
871 | *
872 | * @param string $option
873 | * A valid Spreadsheet sheet property, online documentation available at https://phpspreadsheet.readthedocs.io/
874 | * @param mixed $option
875 | * A value of an option can be a string, boolean or array.
876 | * @return $this
877 | * Returns an object, allowing the calls to be chained together in a single statement
878 | */
879 | public function setSheetProperty($option, $value)
880 | {
881 | if(isset($this->sheetProperties[$option]))
882 | {
883 | $this->sheetProperties[$option] = $value;
884 | }
885 | else
886 | {
887 | $this->sheetProperties = array_add($this->sheetProperties, $option, $value);
888 | }
889 |
890 | return $this;
891 | }
892 |
893 | /**
894 | * Enable filter toolbar.
895 | *
896 | * @param boolean $createToggleButton
897 | * If true a toggle button will be created in the navigator. Default is null
898 | * @param boolean $createClearButton
899 | * If true a clear button will be created in the navigator. Default is null
900 | * @return $this
901 | * Returns an object, allowing the calls to be chained together in a single statement
902 | */
903 | public function enableFilterToolbar($createToggleButton = null, $createClearButton = null)
904 | {
905 | $this->filterToolbarButtonsOptions['filterToolbar'] = true;
906 |
907 | if(!is_null($createToggleButton))
908 | {
909 | $this->filterToolbarButtonsOptions['toggleButton'] = $createToggleButton;
910 | }
911 |
912 | if(!is_null($createClearButton))
913 | {
914 | $this->filterToolbarButtonsOptions['clearButton'] = $createClearButton;
915 | }
916 |
917 | return $this;
918 | }
919 |
920 | /**
921 | * Main method that construct the html and javascript code of the grid.
922 | *
923 | * @param boolean $script
924 | * If true javascript tags will be included within the output. Default is true
925 | * @param boolean $createTableElement
926 | * If true the table element is created automatically from this method. Default is true
927 | * @param boolean $createPagerElement
928 | * If true the pager element is created automatically from this method. Default is true
929 | * @param boolean $echo
930 | * If false the function return the string representing the grid. Default is true
931 | * @return mixed
932 | * String if $echo is set to false, void in any other case
933 | */
934 | public function renderGrid($script = true, $createTableElement = true, $createPagerElement = true, $echo = true)
935 | {
936 | $this->options = array_add($this->options, 'colModel', $this->colModel);
937 |
938 | if (!isset($this->options['pager']))
939 | {
940 | $this->options = array_add($this->options, 'pager', $this->gridId . 'Pager');
941 | }
942 |
943 | if(isset($this->options['filename']))
944 | {
945 | $fileName = mb_substr($this->options['filename'],0,31);
946 | }
947 | else
948 | {
949 | $fileName = $this->gridId;
950 | }
951 |
952 | if(isset($this->options['groupingView']))
953 | {
954 | $groupingView = $this->options['groupingView'];
955 | }
956 | else
957 | {
958 | $groupingView = array();
959 | }
960 |
961 | if(isset($this->groupHeaderOptions['groupHeaders']))
962 | {
963 | $groupHeaders = $this->groupHeaderOptions['groupHeaders'];
964 | }
965 | else
966 | {
967 | $groupHeaders = array();
968 | }
969 |
970 | $html = '';
971 | $html .= '
972 |
';
990 |
991 | if($createTableElement)
992 | {
993 | $html .= '';
994 | }
995 |
996 | if($createTableElement)
997 | {
998 | $html .= '';
999 | }
1000 |
1001 | if($this->jqPivot)
1002 | {
1003 | $mtype = $this->options['mtype'];
1004 | unset($this->options['colModel'], $this->options['mtype'], $this->options['datatype']);
1005 | $script = 'jQuery("#' . $this->gridId . '").jqGrid("jqPivot", "'. $this->options['url'] . '", ' . json_encode($this->pivotOptions) . ', ' . json_encode($this->options) . ', {async : false, type: "' . $mtype .'"});';
1006 | $script .= 'jQuery("#' . $this->gridId . '").navGrid("#'. $this->options['pager'] .'", '. json_encode($this->navigatorOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorEditOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorAddOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorDeleteOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorSearchOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorViewOptions, JSON_FORCE_OBJECT) .' );';
1007 | }
1008 | else
1009 | {
1010 | $script = 'jQuery("#' . $this->gridId . '").jqGrid(' . json_encode($this->options) . ')';
1011 | $script .= '.navGrid("#'. $this->options['pager'] .'", '. json_encode($this->navigatorOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorEditOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorAddOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorDeleteOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorSearchOptions, JSON_FORCE_OBJECT) .', '. json_encode($this->navigatorViewOptions, JSON_FORCE_OBJECT) .' );';
1012 | }
1013 | /*
1014 | $script .= 'jQuery("#' . $this->gridId . '").jqGrid("navButtonAdd", "#' . $this->options['pager'] . '",{"id": "' . $this->gridId . 'XlsButton", "caption":"' . $this->exportButtonsOptions['xlsButtonText'] . '", "buttonicon":"' . $this->exportButtonsOptions['xlsIcon'] . '", "onClickButton":function(){ ' . $this->getJavascriptExportFunctionCode() . ' jQuery("#' . $this->gridId . 'ExportFormat").val("xls"); jQuery("#' . $this->gridId . 'ExportForm").submit();} });';
1015 | $script .= 'jQuery("#' . $this->gridId . '").jqGrid("navButtonAdd", "#' . $this->options['pager'] . '",{"id": "' . $this->gridId . 'CsvButton", "caption":"' . $this->exportButtonsOptions['csvButtonText'] . '", "buttonicon":"' . $this->exportButtonsOptions['csvIcon'] . '", "onClickButton":function(){ ' . $this->getJavascriptExportFunctionCode() . ' jQuery("#' . $this->gridId . 'ExportFormat").val("csv"); jQuery("#' . $this->gridId . 'ExportForm").submit();} });';
1016 |
1017 | if($this->exportButtonsOptions['xlsButtonVisible'] || $this->exportButtonsOptions['csvButtonVisible'])
1018 | {
1019 | $script .= 'jQuery("#' . $this->gridId . '").jqGrid("navSeparatorAdd", "#' . $this->options['pager'] . '");';
1020 | }
1021 |
1022 | if(!$this->exportButtonsOptions['xlsButtonVisible'])
1023 | {
1024 | $script .= 'jQuery("#' . $this->gridId . 'XlsButton").hide();';
1025 | }
1026 |
1027 | if(!$this->exportButtonsOptions['csvButtonVisible'])
1028 | {
1029 | $script .= 'jQuery("#' . $this->gridId . 'CsvButton").hide();';
1030 | }
1031 | */
1032 | foreach ($this->exportButtonsOptions as $key => $value)
1033 | {
1034 | if( preg_match('/ButtonVisible$/', $key) && gettype($value) == 'boolean' )
1035 | {
1036 | $script .= "\n\n\t// Add button and hendler for ". strtoupper(substr($key, 0, -1*strlen('ButtonVisible'))) . "-export : \n";
1037 | $script .= $this->getJavascriptExportFunctionCode( substr($key, 0, -1*strlen('ButtonVisible') ) );
1038 | }
1039 | }
1040 |
1041 | if($this->exportButtonsVisible)
1042 | {
1043 | $script .= 'jQuery("#' . $this->gridId . '").jqGrid("navSeparatorAdd", "#' . $this->options['pager'] . '");';
1044 | }
1045 |
1046 | if($this->filterToolbarButtonsOptions['filterToolbar'])
1047 | {
1048 | $script .= 'jQuery("#' . $this->gridId . '").jqGrid("filterToolbar", ' . json_encode($this->filterToolbarOptions, JSON_FORCE_OBJECT) . ');';
1049 |
1050 | if($this->filterToolbarButtonsOptions['toggleButton'])
1051 | {
1052 | $script .= 'jQuery("#' . $this->gridId . '").jqGrid("navButtonAdd", "#' . $this->options['pager'] . '",{"caption":"'. $this->filterToolbarButtonsOptions['toggleButtonText'] .'", "buttonicon":"ui-icon-pin-s", "onClickButton":function(){ jQuery("#' . $this->gridId . '")[0].toggleToolbar();} });';
1053 | }
1054 |
1055 | if($this->filterToolbarButtonsOptions['clearButton'])
1056 | {
1057 | $script .= 'jQuery("#' . $this->gridId . '").jqGrid("navButtonAdd", "#' . $this->options['pager'] . '",{"caption":"'. $this->filterToolbarButtonsOptions['clearButtonText'] .'", "buttonicon":"ui-icon-refresh", "onClickButton":function(){ jQuery("#' . $this->gridId . '")[0].clearToolbar();} });';
1058 | }
1059 |
1060 | $script .= 'jQuery("#' . $this->gridId . '").jqGrid("navSeparatorAdd", "#' . $this->options['pager'] . '");';
1061 | }
1062 |
1063 | if(!empty($this->groupHeaderOptions))
1064 | {
1065 | $script .= 'setTimeout(function () {jQuery("#' . $this->gridId . '").jqGrid("setGroupHeaders", ' . json_encode($this->groupHeaderOptions) . ');}, 500);';
1066 | }
1067 |
1068 | if($this->frozenColumn)
1069 | {
1070 | $script .= 'jQuery("#' . $this->gridId . '").jqGrid("setFrozenColumns");';
1071 | }
1072 |
1073 | $script = str_replace(array('"###','###"','\"', '"JS>>>', '<<reset();
1076 |
1077 | if($script)
1078 | {
1079 | $script = '';
1080 | }
1081 |
1082 | if($echo)
1083 | {
1084 | echo $html . $script;
1085 | }
1086 | else
1087 | {
1088 | return $html.$script;
1089 | }
1090 | }
1091 |
1092 | /**
1093 | * Reset variables to their original state.
1094 | *
1095 | * @return void
1096 | */
1097 | protected function reset()
1098 | {
1099 | $this->gridId = str_random(10);
1100 | $this->jqPivot = false;
1101 | $this->frozenColumn = false;
1102 | $this->options = $this->defaultGridOptions;
1103 | $this->pivotOptions = $this->defaultPivotGridOptions;
1104 | $this->groupHeaderOptions = $this->defaultGroupHeaderOptions;
1105 | $this->colModel = array();
1106 | $this->navigatorOptions = $this->defaultNavigatorOptions;
1107 | $this->navigatorEditOptions = array();
1108 | $this->navigatorAddOptions = array();
1109 | $this->navigatorDeleteOptions = array();
1110 | $this->navigatorSearchOptions = array();
1111 | $this->navigatorViewOptions = array();
1112 | $this->filterToolbarOptions = $this->defaultfilterToolbarOptions;
1113 | $this->filterToolbarButtonsOptions = $this->defaultFilterToolbarButtonsOptions;
1114 | $this->exportButtonsOptions = $this->defaultExportButtonsOptions;
1115 | $this->fileProperties = $this->defaultFileProperties;
1116 | $this->sheetProperties = $this->defaultSheetProperties;
1117 | }
1118 |
1119 | /**
1120 | * Mark function type properties.
1121 | * First and last quotes will be removed from the javascript code to all properties marked by this method
1122 | *
1123 | * @param array $properties
1124 | * An array of valid jqGrid column model property, the key of the array must correspond to a column model property.
1125 | *
1126 | * @return void
1127 | */
1128 | protected function markFunctionTypeProperty(array &$properties)
1129 | {
1130 | foreach ($properties as $key => &$value)
1131 | {
1132 | if (in_array($key, array_keys($this->functionTypeProperties)))
1133 | {
1134 | if (!in_array($value, $this->functionTypeProperties[$key]))
1135 | {
1136 | $value = '###' . $value . '###';
1137 | }
1138 | }
1139 | else
1140 | {
1141 | if(is_array($value) && array_values($value) != $value)
1142 | {
1143 | $this->markFunctionTypeProperty($value);
1144 | }
1145 | }
1146 |
1147 | }
1148 | }
1149 |
1150 | /**
1151 | * Get exporter's javascript code.
1152 | *
1153 | * @param string $exportFormat
1154 | * @return void
1155 | */
1156 | protected function getJavascriptExportFunctionCode($exportFormat)
1157 | {
1158 | $code = 'jQuery("#' . $this->gridId . '").jqGrid("navButtonAdd", "#' . $this->options['pager'];
1159 | $code .= '",{"id": "' . $this->gridId . ucfirst($exportFormat) . 'Button", "caption":"' . $this->exportButtonsOptions[$exportFormat . 'ButtonText'];
1160 | $code .= '", "buttonicon":"' . $this->exportButtonsOptions[$exportFormat . 'Icon'];
1161 | $code .= '", "onClickButton":function(){ ';
1162 |
1163 | $code .= '
1164 | var headers = [], rows = [], row, cellCounter, postData, groupingView, sidx, sord;
1165 | jQuery("#' . $this->gridId . 'Model").val(JSON.stringify(jQuery("#' . $this->gridId . '").getGridParam("colModel")));
1166 | postData = jQuery("#' . $this->gridId . '").getGridParam("postData");
1167 | if(postData["filters"] != undefined)
1168 | {
1169 | jQuery("#' . $this->gridId . 'Filters").val(postData["filters"]);
1170 | }
1171 | ';
1172 |
1173 | $code .= '
1174 | groupingView = jQuery("#' . $this->gridId . '").getGridParam("groupingView");
1175 | sidx = jQuery("#' . $this->gridId . '").getGridParam("sortname");
1176 | if(sidx == null) sidx = "";
1177 | sord = jQuery("#' . $this->gridId . '").getGridParam("sortorder");
1178 | if(sord == null) sord = "";
1179 | if(groupingView.groupField.length > 0)
1180 | {
1181 | jQuery("#' . $this->gridId . 'Sidx").val(groupingView.groupField[0] + " " + groupingView.groupOrder[0] + "," + " " + sidx);
1182 | }
1183 | else
1184 | {
1185 | jQuery("#' . $this->gridId . 'Sidx").val(sidx);
1186 | }
1187 | jQuery("#' . $this->gridId . 'Sord").val(sord);
1188 | ';
1189 |
1190 | if($this->jqPivot)
1191 | {
1192 | $code .= '
1193 | jQuery.each($("#gbox_' . $this->gridId . '").find(".ui-jqgrid-sortable"), function( index, header )
1194 | {
1195 | headers.push(jQuery(header).text());
1196 | });
1197 | jQuery.each($("#gview_' . $this->gridId . '").find(".ui-widget-content"), function( index, gridRows )
1198 | {
1199 | row = {}, cellCounter = 0;
1200 | jQuery.each($(gridRows).find("td"), function( index, cell)
1201 | {
1202 | row[headers[cellCounter++]] = $(cell).text();
1203 | });
1204 | for (i = cellCounter; i < headers.length; i++) {
1205 | row[headers[i]] = "";
1206 | }
1207 | rows.push(row);
1208 | });
1209 | jQuery("#' . $this->gridId . 'Rows").val(JSON.stringify(rows));
1210 | ';
1211 | }
1212 | else
1213 | {
1214 | //Include footer row if exists
1215 | $code .= '
1216 | jQuery.each($("#gbox_' . $this->gridId . '").find(".ui-jqgrid-sortable").filter(":visible"), function( index, header )
1217 | {
1218 | headers.push(jQuery(header).text());
1219 | });
1220 | row = {}, cellCounter = 0;
1221 | jQuery.each($("#gview_' . $this->gridId . '").find(".footrow").find("td").filter(":visible"), function( index, cell)
1222 | {
1223 | row[headers[cellCounter++]] = $(cell).text();
1224 | });
1225 | jQuery("#' . $this->gridId . 'FotterRow").val(JSON.stringify(row));
1226 | ';
1227 | }
1228 |
1229 | if(isset($this->exportButtonsOptions['srcDateFormat']))
1230 | {
1231 | $code .= ' jQuery("#' . $this->gridId . 'SrcDateFormat").val("' . $this->exportButtonsOptions['srcDateFormat'] . '");';
1232 | }
1233 |
1234 | if(isset($this->exportButtonsOptions['newDateFormat']))
1235 | {
1236 | $code .= ' jQuery("#' . $this->gridId . 'NewDateFormat").val("' . $this->exportButtonsOptions['newDateFormat'] . '");';
1237 | }
1238 |
1239 | $code .= ' jQuery("#' . $this->gridId . 'ExportFormat").val("' . $exportFormat . '");';
1240 | $code .= 'jQuery("#' . $this->gridId . 'ExportForm").submit();} });';
1241 |
1242 | if(!$this->exportButtonsOptions[$exportFormat . 'ButtonVisible'])
1243 | {
1244 | $code .= 'jQuery("#' . $this->gridId . ucfirst($exportFormat) . 'Button").hide();';
1245 | }else
1246 | {
1247 | $this->exportButtonsVisible = TRUE;
1248 | }
1249 |
1250 | return $code;
1251 | }
1252 |
1253 |
1254 | public function addExport(array $properties = array())
1255 | {
1256 | $export_type = '';
1257 | foreach ($properties as $key => $value)
1258 | {
1259 | if( preg_match('/ButtonVisible$/', $key) && gettype($value) == 'boolean' )
1260 | {
1261 | $export_type = substr($key, 0, -1*strlen('ButtonVisible') );
1262 | }
1263 | }
1264 | if ( $export_type == '' )
1265 | {
1266 | throw new \Exception('addExport-method does not set the required parameter ...ButtonVisible or can not determine the type of the method by prefix of this parameter');
1267 | }
1268 |
1269 | $notFoundKeys = array_diff( [$export_type.'ButtonVisible', $export_type.'ButtonText', $export_type.'Icon'], array_keys($properties));
1270 | if ( count($notFoundKeys) > 0 )
1271 | {
1272 | throw new \Exception('addExport-method does not set the required parameters: '.implode(', ', $notFoundKeys));
1273 | }
1274 |
1275 | $this->exportButtonsOptions = array_merge($this->exportButtonsOptions, $properties);
1276 |
1277 | return $this;
1278 | }
1279 | }
1280 |
--------------------------------------------------------------------------------
/src/Mgallegos/LaravelJqgrid/Renders/RenderInterface.php:
--------------------------------------------------------------------------------
1 | 'column index/name 1','op'=>'operator','data'=>'searched string column 1'), array('field'=>'column index/name 2','op'=>'operator','data'=>'searched string column 2'))
80 | * The 'field' key will contain the 'index' column property if is set, otherwise the 'name' column property.
81 | * The 'op' key will contain one of the following operators: '=', '<', '>', '<=', '>=', '<>', '!=','like', 'not like', 'is in', 'is not in'.
82 | * when the 'operator' is 'like' the 'data' already contains the '%' character in the appropiate position.
83 | * The 'data' key will contain the string searched by the user.
84 | * @return integer
85 | * Total number of rows
86 | */
87 | public function getTotalNumberOfRows(array $filters = array())
88 | {
89 | return intval($this->Database->whereNested(function($query) use ($filters)
90 | {
91 | foreach ($filters as $filter)
92 | {
93 | if($filter['op'] == 'is in')
94 | {
95 | $query->whereIn($filter['field'], explode(',',$filter['data']));
96 | continue;
97 | }
98 |
99 | if($filter['op'] == 'is not in')
100 | {
101 | $query->whereNotIn($filter['field'], explode(',',$filter['data']));
102 | continue;
103 | }
104 |
105 | if($filter['op'] == 'is null')
106 | {
107 | $query->whereNull($filter['field']);
108 | continue;
109 | }
110 |
111 | if($filter['op'] == 'is not null')
112 | {
113 | $query->whereNotNull($filter['field']);
114 | continue;
115 | }
116 |
117 | if($filter['op'] == 'between')
118 | {
119 | if(strpos($filter['data'], ' - ') !== false)
120 | {
121 | list($from, $to) = explode(' - ', $filter['data'], 2);
122 |
123 | if(!$from or !$to)
124 | {
125 | throw new \Exception('Invalid between format');
126 | }
127 | }
128 | else
129 | {
130 | throw new \Exception('Invalid between format');
131 | }
132 |
133 | if( $from == $to)
134 | {
135 | $query->where($filter['field'], $from);
136 | }else
137 | {
138 | //$query->whereBetween($filter['field'], array($from, $to));
139 | $query->where($filter['field'], '>=', $from);
140 | $query->where($filter['field'], '<=', $to);
141 | }
142 |
143 | continue;
144 | }
145 |
146 | $query->where($filter['field'], $filter['op'], $filter['data']);
147 | }
148 | })
149 | ->count());
150 | }
151 |
152 |
153 | /**
154 | * Get the rows data to be shown in the grid.
155 | *
156 | * @param integer $limit
157 | * Number of rows to be shown into the grid
158 | * @param integer $offset
159 | * Start position
160 | * @param string $orderBy
161 | * Column name to order by.
162 | * @param string $sord
163 | * Sorting order
164 | * @param array $filters
165 | * An array of filters, example: array(array('field'=>'column index/name 1','op'=>'operator','data'=>'searched string column 1'), array('field'=>'column index/name 2','op'=>'operator','data'=>'searched string column 2'))
166 | * The 'field' key will contain the 'index' column property if is set, otherwise the 'name' column property.
167 | * The 'op' key will contain one of the following operators: '=', '<', '>', '<=', '>=', '<>', '!=','like', 'not like', 'is in', 'is not in'.
168 | * when the 'operator' is 'like' the 'data' already contains the '%' character in the appropiate position.
169 | * The 'data' key will contain the string searched by the user.
170 | * @param string $nodeId
171 | * Node id (used only when the treeGrid option is set to true)
172 | * @param string $nodeLevel
173 | * Node level (used only when the treeGrid option is set to true)
174 | * @param boolean $exporting
175 | * Flag that determines if the data will be exported (used only when the treeGrid option is set to true)
176 | * @return array
177 | * An array of array, each array will have the data of a row.
178 | * Example: array(array("column1" => "1-1", "column2" => "1-2"), array("column1" => "2-1", "column2" => "2-2"))
179 | */
180 | public function getRows($limit, $offset, $orderBy = null, $sord = null, array $filters = array(), $nodeId = null, $nodeLevel = null, $exporting = false)
181 | {
182 | $orderByRaw = null;
183 |
184 | if(!is_null($orderBy) || !is_null($sord))
185 | {
186 | $found = false;
187 | $pos = strpos($orderBy, 'desc');
188 |
189 | if ($pos !== false)
190 | {
191 | $found = true;
192 | }
193 | else
194 | {
195 | $pos = strpos($orderBy, 'asc');
196 |
197 | if ($pos !== false)
198 | {
199 | $found = true;
200 | }
201 | }
202 |
203 | if($found)
204 | {
205 | $orderBy = rtrim($orderBy);
206 |
207 | if(substr($orderBy, -1) == ',')
208 | {
209 | $orderBy = substr($orderBy, 0, -1);
210 | }
211 | else
212 | {
213 | $orderBy .= " $sord";
214 | }
215 |
216 | $orderByRaw = $orderBy;
217 | }
218 | else
219 | {
220 | $this->orderBy = array(array($orderBy, $sord));
221 | }
222 | }
223 |
224 | if($limit == 0)
225 | {
226 | $limit = 1;
227 | }
228 |
229 | if(empty($orderByRaw))
230 | {
231 | $orderByRaw = array();
232 |
233 | foreach ($this->orderBy as $orderBy)
234 | {
235 | array_push($orderByRaw, implode(' ',$orderBy));
236 | }
237 |
238 | $orderByRaw = implode(',',$orderByRaw);
239 | }
240 |
241 | $rows = $this->Database->whereNested(function($query) use ($filters, $nodeId, $exporting)
242 | {
243 | foreach ($filters as $filter)
244 | {
245 | if($filter['op'] == 'is in')
246 | {
247 | $query->whereIn($filter['field'], explode(',',$filter['data']));
248 | continue;
249 | }
250 |
251 | if($filter['op'] == 'is not in')
252 | {
253 | $query->whereNotIn($filter['field'], explode(',',$filter['data']));
254 | continue;
255 | }
256 |
257 | if($filter['op'] == 'is null')
258 | {
259 | $query->whereNull($filter['field']);
260 | continue;
261 | }
262 |
263 | if($filter['op'] == 'is not null')
264 | {
265 | $query->whereNotNull($filter['field']);
266 | continue;
267 | }
268 |
269 | if($filter['op'] == 'between')
270 | {
271 | if(strpos($filter['data'], ' - ') !== false)
272 | {
273 | list($from, $to) = explode(' - ', $filter['data'], 2);
274 |
275 | if(!$from or !$to)
276 | {
277 | throw new \Exception('Invalid between format');
278 | }
279 | }
280 | else
281 | {
282 | throw new \Exception('Invalid between format');
283 | }
284 |
285 | if( $from == $to)
286 | {
287 | $query->where($filter['field'], $from);
288 | }else
289 | {
290 | //$query->whereBetween($filter['field'], array($from, $to));
291 | $query->where($filter['field'], '>=', $from);
292 | $query->where($filter['field'], '<=', $to);
293 | }
294 | continue;
295 | }
296 |
297 | $query->where($filter['field'], $filter['op'], $filter['data']);
298 | }
299 |
300 | if($this->treeGrid && !$exporting)
301 | {
302 | if(empty($nodeId))
303 | {
304 | $query->whereNull($this->parentColumn);
305 | }
306 | else
307 | {
308 | $query->where($this->parentColumn, '=', $nodeId);
309 | }
310 | }
311 | })
312 | ->take($limit)
313 | ->skip($offset)
314 | ->orderByRaw($orderByRaw)
315 | ->get($this->visibleColumns);
316 |
317 | if(!is_array($rows))
318 | {
319 | $rows = $rows->toArray();
320 | }
321 |
322 | foreach ($rows as &$row)
323 | {
324 | $row = (array) $row;
325 |
326 | if($this->treeGrid && !$exporting)
327 | {
328 | if(is_null($nodeLevel))
329 | {
330 | $row['level'] = 0;
331 | }
332 | else
333 | {
334 | $row['level'] = (int)$nodeLevel + 1;
335 | }
336 |
337 | if($row[$this->leafColumn] == 0)
338 | {
339 | $row[$this->leafColumn] = false;
340 | }
341 | else
342 | {
343 | $row[$this->leafColumn] = true;
344 | }
345 | }
346 | }
347 |
348 | return $rows;
349 | }
350 |
351 | }
352 |
--------------------------------------------------------------------------------
/src/Mgallegos/LaravelJqgrid/Repositories/RepositoryInterface.php:
--------------------------------------------------------------------------------
1 | 'column index/name 1','op'=>'operator','data'=>'searched string column 1'), array('field'=>'column index/name 2','op'=>'operator','data'=>'searched string column 2'))
28 | * The 'field' key will contain the 'index' column property if is set, otherwise the 'name' column property.
29 | * The 'op' key will contain one of the following operators: '=', '<', '>', '<=', '>=', '<>', '!=','like', 'not like', 'is in', 'is not in'.
30 | * when the 'operator' is 'like' the 'data' already contains the '%' character in the appropiate position.
31 | * The 'data' key will contain the string searched by the user.
32 | * @return integer
33 | * Total number of rows
34 | */
35 | public function getTotalNumberOfRows(array $filters = array());
36 |
37 |
38 | /**
39 | * Get the rows data to be shown in the grid.
40 | *
41 | * @param integer $limit
42 | * Number of rows to be shown into the grid
43 | * @param integer $offset
44 | * Start position
45 | * @param string $orderBy
46 | * Column name to order by.
47 | * @param string $sord
48 | * Sorting order
49 | * @param array $filters
50 | * An array of filters, example: array(array('field'=>'column index/name 1','op'=>'operator','data'=>'searched string column 1'), array('field'=>'column index/name 2','op'=>'operator','data'=>'searched string column 2'))
51 | * The 'field' key will contain the 'index' column property if is set, otherwise the 'name' column property.
52 | * The 'op' key will contain one of the following operators: '=', '<', '>', '<=', '>=', '<>', '!=','like', 'not like', 'is in', 'is not in'.
53 | * when the 'operator' is 'like' the 'data' already contains the '%' character in the appropiate position.
54 | * The 'data' key will contain the string searched by the user.
55 | * @param string $nodeId
56 | * Node id (used only when the treeGrid option is set to true)
57 | * @param string $nodeLevel
58 | * Node level (used only when the treeGrid option is set to true)
59 | * @param boolean $exporting
60 | * Flag that determines if the data will be exported (used only when the treeGrid option is set to true)
61 | * @return array
62 | * An array of array, each array will have the data of a row.
63 | * Example: array(array("column1" => "1-1", "column2" => "1-2"), array("column1" => "2-1", "column2" => "2-2"))
64 | */
65 | public function getRows($limit, $offset, $orderBy = null, $sord = null, array $filters = array(), $nodeId = null, $nodeLevel = null, $exporting);
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/config/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgallegos/laravel-jqgrid/afcb0331512926a22fdc4308a9d3b242d193c807/src/config/.gitkeep
--------------------------------------------------------------------------------
/src/config/config.php:
--------------------------------------------------------------------------------
1 | array('datatype' => 'json', 'mtype' => 'POST', 'treeGridModel' => 'adjacency'),
25 |
26 | /*
27 | |--------------------------------------------------------------------------
28 | | Default Pivot Grid Options
29 | |--------------------------------------------------------------------------
30 | |
31 | | An array of pivot grid options that will be set to all grids of your applications,
32 | | the key of the array must correspond to a valid pivot grid option.
33 | | These options can override by setting a different value in a specific grid.
34 | | Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:pivotsettings
35 | |
36 | */
37 |
38 | 'default_pivot_grid_options' => array('yDimension' => array()),
39 |
40 | /*
41 | |--------------------------------------------------------------------------
42 | | Default Group Header Options
43 | |--------------------------------------------------------------------------
44 | |
45 | | An array of group header options that will be set to all grids of your applications,
46 | | the key of the array must correspond to a valid pivot grid option.
47 | | These options can override by setting a different value in a specific grid.
48 | | Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:groupingheadar
49 | |
50 | */
51 |
52 | 'default_group_header_options' => array('useColSpanStyle' => true),
53 |
54 | /*
55 | |--------------------------------------------------------------------------
56 | | Default column model properties
57 | |--------------------------------------------------------------------------
58 | |
59 | | An array of column model properties that will be set to all columns grid of your applications,
60 | | the key of the array must correspond to a valid column model property.
61 | | These column model properties can override by setting a different value in a specific grid.
62 | | Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options
63 | |
64 | */
65 |
66 | 'default_col_model_properties' => array('searchoptions' => array('sopt'=>array('cn'))),
67 |
68 | /*
69 | |--------------------------------------------------------------------------
70 | | Default navigator options
71 | |--------------------------------------------------------------------------
72 | |
73 | | Default navigators options that will be set to all grid of your applications,
74 | | the key of the array must correspond to a valid navigator option.
75 | | These options can override by setting a different value in a specific grid.
76 | | Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:navigator
77 | |
78 | */
79 |
80 | 'default_navigator_options' => array('add' => false, 'edit' => false, 'del' => false, 'search' => false, 'view' => true, 'refresh' => false),
81 |
82 | /*
83 | |--------------------------------------------------------------------------
84 | | Default filter toolbar options
85 | |--------------------------------------------------------------------------
86 | |
87 | | Default navigators options that will be set to all grid of your applications,
88 | | the key of the array must correspond to a valid filter toolbar option.
89 | | These options can override by setting a different value in a specific grid.
90 | | Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:toolbar_searching
91 | |
92 | */
93 |
94 | 'default_filter_toolbar_options' => array('stringResult' => true),
95 |
96 | /*
97 | |--------------------------------------------------------------------------
98 | | Default Filter Toolbar Buttons Options
99 | |--------------------------------------------------------------------------
100 | |
101 | | An array of toolbar button options that will be set to all grids of your applications.
102 | | filterToolbar: enable o disabled the filter toolbar
103 | | toggleButton: add a button to toggle the filter toolbar
104 | | clearButton: add a button to clear the filter toolbar
105 | | toggleButtonText: text of the toggle button
106 | | clearButtonText: text of the clear button
107 | |
108 | */
109 |
110 | 'default_filter_toolbar_buttons_options' => array('filterToolbar' => false, 'toggleButton' => true, 'clearButton' => true, 'toggleButtonText' => '', 'clearButtonText' => ''),
111 |
112 | /*
113 | |--------------------------------------------------------------------------
114 | | Default Export Buttons Options
115 | |--------------------------------------------------------------------------
116 | |
117 | | An array of toolbar button options that will be set to all grids of your applications.
118 | | xlsButtonVisible: show or hide the xls export button
119 | | xlsButtonText: text of the xls export button
120 | | xlsIcon: xls icon (jquery ui icon)
121 | | csvButtonVisible: show or hide the csv export button
122 | | csvButtonText: text of the csv export button
123 | | csvIcon: csv icon (jquery ui icon)
124 | | srcDateFormat: source (database) date format (php available formats: http://php.net/manual/en/datetime.formats.date.php)
125 | | newDateFormat: new date format (php available formats: http://php.net/manual/en/datetime.formats.date.php)
126 | |
127 | */
128 |
129 | 'default_export_buttons_options' => array('xlsButtonVisible' => true, 'xlsButtonText' => 'xls', 'xlsIcon' => 'ui-icon-arrowthickstop-1-s', 'csvButtonVisible' => true, 'csvButtonText' => 'csv', 'csvIcon' => 'ui-icon-arrowthickstop-1-s', 'srcDateFormat' => 'Y-m-d', 'newDateFormat' => 'm/d/Y'),
130 |
131 | /*
132 | |--------------------------------------------------------------------------
133 | | Default Spreadsheet File Properties
134 | |--------------------------------------------------------------------------
135 | |
136 | | Default Spreadsheet File Properties that will be set to all grid of your applications,
137 | | the key of the array must correspond to a Spreadsheet File Property.
138 | | These properties can override by setting a different value in a specific grid.
139 | | Online documentation available at https://phpspreadsheet.readthedocs.io/
140 | |
141 | */
142 |
143 | 'default_file_properties' => array(),
144 |
145 | /*
146 | |--------------------------------------------------------------------------
147 | | Default Spreadsheet Sheet Properties
148 | |--------------------------------------------------------------------------
149 | |
150 | | Default Spreadsheet Sheet Properties that will be set to all grid of your applications,
151 | | the key of the array must correspond to a Spreadsheet Sheet Property.
152 | | These properties can override by setting a different value in a specific grid.
153 | | Online documentation available at https://phpspreadsheet.readthedocs.io/
154 | |
155 | */
156 |
157 | 'default_sheet_properties' => array(),
158 |
159 | /*
160 | |--------------------------------------------------------------------------
161 | | Pivot options
162 | |--------------------------------------------------------------------------
163 | |
164 | | Pivots options defined by the jqGrid documentation.
165 | | Warning: This options are vital when using the grid as a pivot grid, do not modify them unless you know what you are doing.
166 | | Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:pivotsettings
167 | |
168 | */
169 |
170 | 'pivot_options' => array('aggregates', 'colTotals', 'frozenStaticCols', 'groupSummary', 'groupSummaryPos', 'rowTotals', 'rowTotalsText', 'xDimension', 'yDimension'),
171 |
172 | /*
173 | |--------------------------------------------------------------------------
174 | | Group header options
175 | |--------------------------------------------------------------------------
176 | |
177 | | Group header options options defined by the jqGrid documentation.
178 | | Warning: This options are vital when grouping header columns, do not modify them unless you know what you are doing.
179 | | Online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:groupingheadar
180 | |
181 | */
182 |
183 | 'group_header_options' => array('useColSpanStyle', 'groupHeaders'),
184 |
185 | /*
186 | |--------------------------------------------------------------------------
187 | | Function type Grid options and column properties
188 | |--------------------------------------------------------------------------
189 | |
190 | | These options and properties can be set as a string by the programmer, but first and last quotes will be removed from the javascript code.
191 | | In some cases there are predefined values that are exceptions, these can be included as an array.
192 | | "JqGrid options" online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options
193 | | "JqGrid column properties" online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:colmodel_options
194 | | "JqGrid predefined format types" online documentation available at http://www.trirand.com/jqgridwiki/doku.php?id=wiki:predefined_formatter
195 | | Warning: This options are vital for the functionaty of the package, do not modify them unless you know what you are doing.
196 | |
197 | */
198 |
199 | 'function_type_properties' => array(
200 | 'datatype' => array('xml', 'xmlstring', 'json', 'jsonstring', 'local', 'javascript', 'clientSide'),
201 | 'cellattr' => array(),
202 | 'formatter' => array('integer', 'number', 'currency', 'date', 'email', 'link', 'showlink', 'checkbox', 'select', 'actions'),
203 | 'unformat' => array(),
204 | 'sorttype' => array('int','integer', 'float','number', 'currency', 'date', 'text'),
205 | 'dataInit' => array(),
206 | 'fn' => array(),
207 | 'custom_element' => array(),
208 | 'custom_value' => array(),
209 | 'custom_func' => array(),
210 | 'buildSelect' => array(),
211 | 'summaryType' => array('sum','count','avg','min','max'),
212 | 'rowattr' => array(),
213 | 'converter' => array(),
214 | ),
215 | );
216 |
--------------------------------------------------------------------------------
/src/lang/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgallegos/laravel-jqgrid/afcb0331512926a22fdc4308a9d3b242d193c807/src/lang/.gitkeep
--------------------------------------------------------------------------------
/src/migrations/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgallegos/laravel-jqgrid/afcb0331512926a22fdc4308a9d3b242d193c807/src/migrations/.gitkeep
--------------------------------------------------------------------------------
/src/views/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgallegos/laravel-jqgrid/afcb0331512926a22fdc4308a9d3b242d193c807/src/views/.gitkeep
--------------------------------------------------------------------------------
/tests/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mgallegos/laravel-jqgrid/afcb0331512926a22fdc4308a9d3b242d193c807/tests/.gitkeep
--------------------------------------------------------------------------------