Файловый менеджер - Редактировать - /home/easybachat/hisabat365.com/4a7891/yajra.tar
Ðазад
laravel-datatables-export/phpstan.neon.dist 0000644 00000000526 15060167532 0015123 0 ustar 00 includes: - ./vendor/larastan/larastan/extension.neon parameters: paths: - src level: max ignoreErrors: - '#Parameter \#1 \$callback of method Illuminate\\Container\\Container::call\(\) expects \(callable\(\): mixed\)\|string*#' excludePaths: - tests checkMissingIterableValueType: false laravel-datatables-export/src/WithExportQueue.php 0000644 00000002345 15060167532 0016246 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Bus; use Yajra\DataTables\Jobs\DataTableExportJob; /** * @mixin \Yajra\DataTables\Services\DataTable */ trait WithExportQueue { /** * Process dataTables needed render output. * * @return mixed * * @throws \Throwable */ public function render(?string $view = null, array $data = [], array $mergeData = []) { if (request()->ajax() && request('action') == 'exportQueue') { return $this->exportQueue(); } return parent::render($view, $data, $mergeData); } /** * Create and run batch job. * * * @throws \Throwable */ public function exportQueue(): string { $job = new DataTableExportJob( [self::class, $this->attributes], request()->all(), Auth::id() ?? 0, $this->sheetName(), ); $batch = Bus::batch([$job])->name('datatables-export')->dispatch(); return $batch->id; } /** * Default sheet name. * Character limit 31. */ protected function sheetName(): string { return request('sheetName', 'Sheet1'); } } laravel-datatables-export/src/Livewire/ExportButtonComponent.php 0000644 00000006153 15060167532 0021253 0 ustar 00 <?php namespace Yajra\DataTables\Livewire; use Illuminate\Bus\Batch; use Illuminate\Contracts\Support\Renderable; use Illuminate\Support\Facades\Bus; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use Livewire\Component; use Symfony\Component\HttpFoundation\StreamedResponse; /** * @property Batch $exportBatch */ class ExportButtonComponent extends Component { public string $class = 'btn btn-primary'; public ?string $tableId = null; public ?string $emailTo = ''; public string $type = 'xlsx'; public string $filename = ''; public string $buttonName = 'Export'; public string $sheetName = 'Sheet1'; public bool $autoDownload = false; public bool $downloaded = false; public bool $exporting = false; public bool $exportFinished = false; public bool $exportFailed = false; public ?string $batchJobId = null; public function export(string $batchJobId): void { $this->batchJobId = $batchJobId; $this->exportFinished = false; $this->exportFailed = false; $this->exporting = true; $this->downloaded = false; } public function getExportBatchProperty(): ?Batch { if (! $this->batchJobId) { return null; } return Bus::findBatch($this->batchJobId); } public function updateExportProgress(): ?StreamedResponse { $this->exportFinished = $this->exportBatch->finished(); $this->exportFailed = $this->exportBatch->hasFailures(); if ($this->exportFinished) { $this->exporting = false; if ($this->autoDownload and ! $this->downloaded) { $this->downloaded = true; return $this->downloadExport(); } } return null; } public function downloadExport(): StreamedResponse { if ($this->getS3Disk()) { return Storage::disk($this->getS3Disk()) ->download($this->batchJobId.'.'.$this->getType(), $this->getFilename()); } return Storage::disk($this->getDisk())->download($this->batchJobId.'.'.$this->getType(), $this->getFilename()); } protected function getType(): string { if (Str::endsWith($this->filename, ['csv', 'xlsx'])) { return pathinfo($this->filename, PATHINFO_EXTENSION); } return $this->type == 'csv' ? 'csv' : 'xlsx'; } protected function getFilename(): string { if (Str::endsWith(Str::lower($this->filename), ['csv', 'xlsx'])) { return $this->filename; } return Str::random().'.'.$this->getType(); } public function render(): Renderable { return view('datatables-export::export-button', [ 'fileType' => $this->getType(), ]); } protected function getDisk(): string { /** @var string $disk */ $disk = config('datatables-export.disk', 'local'); return $disk; } protected function getS3Disk(): string { /** @var string $disk */ $disk = config('datatables-export.s3_disk', ''); return $disk; } } laravel-datatables-export/src/Commands/DataTablesPurgeExportCommand.php 0000644 00000002531 15060167532 0022372 0 ustar 00 <?php namespace Yajra\DataTables\Commands; use Illuminate\Console\Command; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; class DataTablesPurgeExportCommand extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'datatables:purge-export'; /** * The console command description. * * @var string */ protected $description = 'Remove exported files that datatables-export generate.'; /** * Execute the console command. * * @return void */ public function handle() { /** @var string $disk */ $disk = config('datatables-export.disk', 'local'); /** @var int $daysOld */ $daysOld = config('datatables-export.purge.days', 1); $timestamp = now()->subDays($daysOld)->getTimestamp(); collect(Storage::disk($disk)->files()) ->each(function ($file) use ($timestamp, $disk) { $path = Storage::disk($disk)->path($file); if (File::lastModified($path) < $timestamp && Str::endsWith(strtolower($file), ['xlsx', 'csv'])) { File::delete($path); } }); $this->info('The command was successful. Export files are cleared!'); } } laravel-datatables-export/src/Jobs/DataTableExportJob.php 0000644 00000022427 15060167532 0017502 0 ustar 00 <?php namespace Yajra\DataTables\Jobs; use Carbon\Carbon; use DateTimeInterface; use Illuminate\Auth\Events\Login; use Illuminate\Bus\Batchable; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Http\File; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use OpenSpout\Common\Entity\Cell; use OpenSpout\Common\Entity\Row; use OpenSpout\Common\Entity\Style\Style; use OpenSpout\Writer\Common\Creator\WriterFactory; use OpenSpout\Writer\XLSX\Helper\DateHelper; use OpenSpout\Writer\XLSX\Writer as XLSXWriter; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; use Yajra\DataTables\Html\Column; use Yajra\DataTables\Services\DataTable; class DataTableExportJob implements ShouldBeUnique, ShouldQueue { use Batchable; use Dispatchable; use InteractsWithQueue; use Queueable; use SerializesModels; /** * @var class-string<DataTable> */ public string $dataTable; public array $attributes = []; /** * @param array{class-string<DataTable>, array} $instance */ public function __construct( array $instance, public array $request, public int|string|null $user, public string $sheetName = 'Sheet1' ) { $this->dataTable = $instance[0]; $this->attributes = $instance[1]; } /** * Execute the job. * * @throws \OpenSpout\Common\Exception\IOException * @throws \OpenSpout\Common\Exception\UnsupportedTypeException * @throws \OpenSpout\Writer\Exception\WriterNotOpenedException * @throws \OpenSpout\Writer\Exception\InvalidSheetNameException */ public function handle(): void { if ($this->user) { Event::forget(Login::class); Auth::loginUsingId($this->user); } /** @var DataTable $oTable */ $oTable = resolve($this->dataTable); request()->merge($this->request); $query = app()->call([$oTable->with($this->attributes), 'query']); /** @var \Yajra\DataTables\QueryDataTable $dataTable */ $dataTable = app()->call([$oTable, 'dataTable'], compact('query')); $dataTable->skipPaging(); $type = 'xlsx'; $exportType = request('export_type', 'xlsx'); if (is_string($exportType)) { $type = Str::of($exportType)->startsWith('csv') ? 'csv' : 'xlsx'; } $filename = $this->batchId.'.'.$type; $path = Storage::disk($this->getDisk())->path($filename); $writer = WriterFactory::createFromFile($filename); $writer->openToFile($path); if ($writer instanceof XLSXWriter) { $sheet = $writer->getCurrentSheet(); $sheet->setName(substr($this->sheetName, 0, 31)); } $columns = $this->getExportableColumns($oTable); $headers = []; $columns->each(function (Column $column) use (&$headers) { $headers[] = strip_tags($column->title); }); $writer->addRow(Row::fromValues($headers)); if ($this->usesLazyMethod()) { $chunkSize = 1_000; if (is_int(config('datatables-export.chunk'))) { $chunkSize = config('datatables-export.chunk'); } $query = $dataTable->getFilteredQuery()->lazy($chunkSize); } else { $query = $dataTable->getFilteredQuery()->cursor(); } foreach ($query as $row) { $cells = []; $row = $row instanceof Arrayable ? $row->toArray() : (array) $row; if ($this->usesLazyMethod() && is_array($row)) { $row = Arr::dot($row); } $defaultDateFormat = 'yyyy-mm-dd'; if (config('datatables-export.default_date_format') && is_string(config('datatables-export.default_date_format')) ) { $defaultDateFormat = config('datatables-export.default_date_format'); } $columns->map(function (Column $column) use ($row, &$cells, $defaultDateFormat) { $property = $column->data; /* Handles orthogonal data */ if (is_array($property)) { $property = $property['_'] ?? $column->name; } /** @var array|bool|int|string|null|DateTimeInterface $value */ $value = $row[$property] ?? ''; if (is_array($value)) { $value = json_encode($value); } switch (true) { case $this->wantsText($column): if ($value instanceof DateTimeInterface) { $cellValue = $value->format($defaultDateFormat); } else { $cellValue = strval($value); } $format = $column->exportFormat ?? '@'; break; case $this->wantsDateFormat($column): if ($value instanceof DateTimeInterface) { $cellValue = DateHelper::toExcel($value); } else { $cellValue = $value ? DateHelper::toExcel(Carbon::parse(strval($value))) : ''; } $format = $column->exportFormat ?? $defaultDateFormat; break; case $this->wantsNumeric($column): if ($value instanceof DateTimeInterface) { $cellValue = 0.0; } else { $cellValue = floatval($value); } $format = $column->exportFormat; break; case $value instanceof DateTimeInterface: $cellValue = $value; $format = $column->exportFormat ?? $defaultDateFormat; break; default: $cellValue = $this->isNumeric($value) ? floatval($value) : $value; $format = $column->exportFormat ?? NumberFormat::FORMAT_GENERAL; } $cells[] = Cell::fromValue($cellValue, (new Style)->setFormat($format)); }); $writer->addRow(new Row($cells)); } $writer->close(); if ($this->getS3Disk()) { Storage::disk($this->getS3Disk())->putFileAs('', (new File($path)), $filename); } $emailTo = request('emailTo'); if ($emailTo && is_string($emailTo)) { $data = ['email' => urldecode($emailTo), 'path' => $path]; $this->sendResults($data); } } protected function getDisk(): string { $disk = 'local'; if (is_string(config('datatables-export.disk'))) { $disk = config('datatables-export.disk'); } return $disk; } /** * @return \Illuminate\Support\Collection<array-key, Column> */ protected function getExportableColumns(DataTable $dataTable): Collection { $columns = $dataTable->html()->getColumns(); return $columns->filter(fn (Column $column) => $column->exportable); } protected function usesLazyMethod(): bool { return config('datatables-export.method', 'lazy') === 'lazy'; } protected function wantsText(Column $column): bool { if (! isset($column['exportFormat'])) { return false; } return in_array($column['exportFormat'], (array) config('datatables-export.text_formats', ['@'])); } protected function wantsDateFormat(Column $column): bool { if (! isset($column['exportFormat'])) { return false; } /** @var array $formats */ $formats = config('datatables-export.date_formats', []); return in_array($column['exportFormat'], $formats); } protected function wantsNumeric(Column $column): bool { return Str::contains($column->exportFormat, ['0', '#']); } /** * @param int|bool|string|null $value */ protected function isNumeric($value): bool { // Skip numeric style if value has leading zeroes. if (Str::startsWith(strval($value), '0')) { return false; } return is_numeric($value); } protected function getS3Disk(): string { $disk = ''; if (config('datatables-export.s3_disk') && is_string(config('datatables-export.s3_disk'))) { $disk = config('datatables-export.s3_disk'); } return $disk; } public function sendResults(array $data): void { Mail::send('datatables-export::export-email', $data, function ($message) use ($data) { $message->attach($data['path']); $message->to($data['email']) ->subject('Export Report'); $message->from(config('datatables-export.mail_from')); }); } } laravel-datatables-export/src/resources/views/export-email.blade.php 0000644 00000000051 15060167532 0021737 0 ustar 00 Attached you will find requested report. laravel-datatables-export/src/resources/views/export-button.blade.php 0000644 00000004535 15060167532 0022176 0 ustar 00 <div class="d-flex align-items-center" x-data> <form class="mr-2" x-on:submit.prevent=" $refs.exportBtn.disabled = true; var oTable = LaravelDataTables['{{ $tableId }}']; var baseUrl = oTable.ajax.url() === '' ? window.location.toString() : oTable.ajax.url(); var url = new URL(baseUrl); var searchParams = new URLSearchParams(url.search); searchParams.set('action', 'exportQueue'); searchParams.set('exportType', '{{$fileType}}'); searchParams.set('sheetName', '{{$sheetName}}'); searchParams.set('buttonName', '{{$buttonName}}'); searchParams.set('emailTo', '{{urlencode($emailTo)}}'); var tableParams = $.param(oTable.ajax.params()); if (tableParams) { var tableSearchParams = new URLSearchParams(tableParams); tableSearchParams.forEach((value, key) => { searchParams.append(key, value); }); } url.search = searchParams.toString(); $.get(url.toString()).then(function(exportId) { $wire.export(exportId); }).catch(function(error) { $wire.exportFinished = true; $wire.exporting = false; $wire.exportFailed = true; }); " > <button type="submit" x-ref="exportBtn" :disabled="$wire.exporting" class="{{ $class }}" >{{$buttonName}} </button> </form> @if($exporting && $emailTo) <div class="d-inline">Export will be emailed to {{ $emailTo }}.</div> @endif @if($exporting && !$exportFinished) <div class="d-inline" wire:poll="updateExportProgress">Exporting...please wait.</div> @endif @if($exportFinished && !$exportFailed && !$autoDownload) <span>Done. Download file <a href="#" class="text-primary" wire:click.prevent="downloadExport">here</a></span> @endif @if($exportFinished && !$exportFailed && $autoDownload && $downloaded) <span>Done. File has been downloaded.</span> @endif @if($exportFailed) <span>Export failed, please try again later.</span> @endif </div> laravel-datatables-export/src/ExportServiceProvider.php 0000644 00000002237 15060167532 0017441 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Support\ServiceProvider; use Livewire\Livewire; use Livewire\LivewireServiceProvider; use Yajra\DataTables\Commands\DataTablesPurgeExportCommand; use Yajra\DataTables\Livewire\ExportButtonComponent; class ExportServiceProvider extends ServiceProvider { public function boot(): void { $this->loadViewsFrom(__DIR__.'/resources/views', 'datatables-export'); $this->publishAssets(); Livewire::component('export-button', ExportButtonComponent::class); } protected function publishAssets(): void { $this->publishes([ __DIR__.'/config/datatables-export.php' => config_path('datatables-export.php'), ], 'datatables-export'); $this->publishes([ __DIR__.'/resources/views' => base_path('/resources/views/vendor/datatables-export'), ], 'datatables-export'); } public function register(): void { $this->mergeConfigFrom(__DIR__.'/config/datatables-export.php', 'datatables-export'); $this->commands([DataTablesPurgeExportCommand::class]); $this->app->register(LivewireServiceProvider::class); } } laravel-datatables-export/src/config/datatables-export.php 0000644 00000007522 15060167532 0020016 0 ustar 00 <?php use PhpOffice\PhpSpreadsheet\Style\NumberFormat; return [ /* |-------------------------------------------------------------------------- | Method |-------------------------------------------------------------------------- | | Method to use to iterate with the query results. | Options: lazy, cursor | | @link https://laravel.com/docs/eloquent#cursors | @link https://laravel.com/docs/eloquent#chunking-using-lazy-collections | */ 'method' => 'lazy', /* |-------------------------------------------------------------------------- | Chunk Size |-------------------------------------------------------------------------- | | Chunk size to be used when using lazy method. | */ 'chunk' => 1000, /* |-------------------------------------------------------------------------- | Export filesystem disk |-------------------------------------------------------------------------- | | Export filesystem disk where generated files will be stored. | */ 'disk' => 'local', /* |-------------------------------------------------------------------------- | Use S3 for final file destination |-------------------------------------------------------------------------- | | After generating the file locally, it can be uploaded to s3. | */ 's3_disk' => '', /* |-------------------------------------------------------------------------- | Mail from address |-------------------------------------------------------------------------- | | Will be used to email report from this address. | */ 'mail_from' => env('MAIL_FROM_ADDRESS', ''), /* |-------------------------------------------------------------------------- | Default Date Format |-------------------------------------------------------------------------- | | Default export format for date. | */ 'default_date_format' => 'yyyy-mm-dd', /* |-------------------------------------------------------------------------- | Valid Date Formats |-------------------------------------------------------------------------- | | List of valid date formats to be used for auto-detection. | */ 'date_formats' => [ 'mm/dd/yyyy', NumberFormat::FORMAT_DATE_DATETIME, NumberFormat::FORMAT_DATE_YYYYMMDD, NumberFormat::FORMAT_DATE_XLSX22, NumberFormat::FORMAT_DATE_DDMMYYYY, NumberFormat::FORMAT_DATE_DMMINUS, NumberFormat::FORMAT_DATE_DMYMINUS, NumberFormat::FORMAT_DATE_DMYSLASH, NumberFormat::FORMAT_DATE_MYMINUS, NumberFormat::FORMAT_DATE_TIME1, NumberFormat::FORMAT_DATE_TIME2, NumberFormat::FORMAT_DATE_TIME3, NumberFormat::FORMAT_DATE_TIME4, NumberFormat::FORMAT_DATE_TIME5, NumberFormat::FORMAT_DATE_TIME6, NumberFormat::FORMAT_DATE_TIME7, NumberFormat::FORMAT_DATE_XLSX14, NumberFormat::FORMAT_DATE_XLSX15, NumberFormat::FORMAT_DATE_XLSX16, NumberFormat::FORMAT_DATE_XLSX17, NumberFormat::FORMAT_DATE_YYYYMMDD2, NumberFormat::FORMAT_DATE_YYYYMMDDSLASH, ], /* |-------------------------------------------------------------------------- | Valid Text Formats |-------------------------------------------------------------------------- | | List of valid text formats to be used. | */ 'text_formats' => [ '@', NumberFormat::FORMAT_GENERAL, NumberFormat::FORMAT_TEXT, ], /* |-------------------------------------------------------------------------- | Purge Options |-------------------------------------------------------------------------- | | Purge all exported by purge.days old files. | */ 'purge' => [ 'days' => 1, ], ]; laravel-datatables-export/CONTRIBUTING.md 0000644 00000001651 15060167532 0014054 0 ustar 00 # Contributing Contributions are **welcome** and will be fully **credited**. We accept contributions via Pull Requests on [Github](https://github.com/yajra/laravel-datatables-export). ## Pull Requests - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. **Happy coding**! laravel-datatables-export/LICENSE.md 0000644 00000002117 15060167532 0013225 0 ustar 00 (The MIT License) Copyright (c) 2013-2022 Arjay Angeles <aqangeles@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. laravel-datatables-export/phpunit.xml.dist 0000644 00000001001 15060167532 0014763 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false"> <testsuites> <testsuite name="Package Test Suite"> <directory suffix="Test.php">./tests/</directory> </testsuite> </testsuites> </phpunit> laravel-datatables-export/rector.php 0000644 00000001032 15060167532 0013623 0 ustar 00 <?php declare(strict_types=1); use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; use Rector\Config\RectorConfig; use Rector\Set\ValueObject\LevelSetList; return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths([ __DIR__.'/src', __DIR__.'/tests', ]); // register a single rule $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); // define sets of rules $rectorConfig->sets([ LevelSetList::UP_TO_PHP_82, ]); }; laravel-datatables-export/UPGRADE.md 0000644 00000000376 15060167532 0013237 0 ustar 00 # UPGRADE GUIDE ## Upgrade from 10.x to 11.x 1. Update the composer.json file and change the version of the package to `^11.0`: ```json "require": { "yajra/laravel-datatables-export": "^11.0" } ``` 2. Run `composer update` to update the package. laravel-datatables-export/CHANGELOG.md 0000644 00000001067 15060167532 0013435 0 ustar 00 # Laravel DataTables Export Plugin CHANGELOG. ## UNRELEASED ## v11.1.1 - 2024-04-29 - fix: pestphp require-dev #61 - bump deps - fix: yajra/laravel-datatables#3136 ## v11.1.0 - 2024-04-29 - feat: add button name option #59 ## v11.0.1 - 2024-04-16 - fix: Export button URL: Merge new with existing query params #58 - fix #57 - Handle new params with existing query params in the export button URL ## v11.0.0 - 2023-03-14 - Laravel 11.x support - Use Pest for testing - Add Pint and Rector for code quality - Add GitHub Actions for CI/CD - Fix PhpStan issues laravel-datatables-export/composer.json 0000644 00000004126 15060167532 0014345 0 ustar 00 { "name": "yajra/laravel-datatables-export", "description": "Laravel DataTables Queued Export Plugin.", "keywords": [ "laravel", "datatables", "export", "excel", "livewire", "queue" ], "license": "MIT", "authors": [ { "name": "Arjay Angeles", "email": "aqangeles@gmail.com" } ], "require": { "php": "^8.2", "ext-json": "*", "livewire/livewire": "^2.11.2|^3.4.12", "openspout/openspout": "^4.24.1", "phpoffice/phpspreadsheet": "^1.29", "yajra/laravel-datatables-buttons": "^11.0" }, "require-dev": { "larastan/larastan": "^2.9.6", "orchestra/testbench": "^9.0.4", "pestphp/pest": "^2.34.7", "pestphp/pest-plugin-laravel": "^2.4", "laravel/pint": "^1.15.3", "rector/rector": "^1.1" }, "autoload": { "psr-4": { "Yajra\\DataTables\\": "src/" } }, "autoload-dev": { "psr-4": { "Yajra\\DataTables\\Exports\\Tests\\": "tests/" } }, "scripts": { "test": "./vendor/bin/pest", "pint": "./vendor/bin/pint", "rector": "./vendor/bin/rector", "stan": "./vendor/bin/phpstan analyse --memory-limit=2G --ansi --no-progress --no-interaction --configuration=phpstan.neon.dist", "pr": [ "@rector", "@pint", "@stan", "@test" ] }, "config": { "preferred-install": "dist", "sort-packages": true, "optimize-autoloader": true, "allow-plugins": { "pestphp/pest-plugin": true } }, "extra": { "branch-alias": { "dev-master": "11.x-dev" }, "laravel": { "providers": [ "Yajra\\DataTables\\ExportServiceProvider" ] } }, "minimum-stability": "dev", "prefer-stable": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/yajra" } ] } laravel-datatables-export/.styleci.yml 0000644 00000000020 15060167532 0014065 0 ustar 00 preset: laravel laravel-datatables-export/README.md 0000644 00000016054 15060167532 0013105 0 ustar 00 # Laravel DataTables Export Plugin [](http://laravel.com) [](https://packagist.org/packages/yajra/laravel-datatables-export) [](https://github.com/yajra/laravel-datatables-export/actions/workflows/continuous-integration.yml) [](https://github.com/yajra/laravel-datatables-export/actions/workflows/static-analysis.yml) [](https://packagist.org/packages/yajra/laravel-datatables-export) [](https://packagist.org/packages/yajra/laravel-datatables-export) This package is a plugin of [Laravel DataTables](https://github.com/yajra/laravel-datatables) for handling server-side exporting using Queue, OpenSpout and Livewire. ## Requirements - [PHP >=8.2](http://php.net/) - [Laravel 11](https://github.com/laravel/framework) - [Laravel Livewire](https://laravel-livewire.com/) - [OpenSpout](https://github.com/openspout/openspout/) - [Laravel DataTables 11.x](https://github.com/yajra/laravel-datatables) - [jQuery DataTables v1.10.x](http://datatables.net/) ## Documentations - [Laravel DataTables Documentation](http://yajrabox.com/docs/laravel-datatables) ## Laravel Version Compatibility | Laravel | Package | |:--------|:--------| | 8.x | 0.x | | 9.x | 1.x | | 10.x | 10.x | | 11.x | 11.x | ## Quick Installation `composer require yajra/laravel-datatables-export:^11.0` The package also requires batch job: ```shell php artisan queue:batches-table php artisan migrate ``` #### Service Provider (Optional since Laravel 5.5+) `Yajra\DataTables\ExportServiceProvider::class` #### Configuration and Assets (Optional) `$ php artisan vendor:publish --tag=datatables-export --force` ## Usage 1. Add the export-button livewire component on your view file that uses dataTable class. ```html <livewire:export-button :table-id="$dataTable->getTableId()"/> ``` 2. On your `DataTable` class, use `WithExportQueue` ```php use Yajra\DataTables\WithExportQueue; class PermissionsDataTable extends DataTable { use WithExportQueue; ... } ``` 3. Run your queue worker. Ex: `php artisan queue:work` ## Purging exported files On `app\Console\Kernel.php`, register the purge command ```php $schedule->command('datatables:purge-export')->weekly(); ``` ## Export Filename You can set the export filename by setting the property. ```html <livewire:export-button :table-id="$dataTable->getTableId()" filename="my-table.xlsx"/> <livewire:export-button :table-id="$dataTable->getTableId()" filename="my-table.csv"/> <livewire:export-button :table-id="$dataTable->getTableId()" :filename="$filename"/> ``` ## Export Button Name You can set the export button name by setting the `buttonName` property. ```html <!-- Examples demonstrating how to customize the button name for different scenarios --> <livewire:export-button :table-id="$dataTable->getTableId()" type="xlsx" buttonName="Export Excel"/> <livewire:export-button :table-id="$dataTable->getTableId()" type="csv" buttonName="Export CSV"/> ``` ## Export Type You can set the export type by setting the property to `csv` or `xlsx`. Default value is `xlsx`. ```html <livewire:export-button :table-id="$dataTable->getTableId()" type="xlsx"/> <livewire:export-button :table-id="$dataTable->getTableId()" type="csv"/> ``` ## Set Excel Sheet Name Option 1: You can set the Excel sheet name by setting the property. ```html <livewire:export-button :table-id="$dataTable->getTableId()" sheet-name="Monthly Report"/> ``` Option 2: You can also set the Excel sheet name by overwriting the method. ```php protected function sheetName() : string { return "Yearly Report"; } ``` ## Formatting Columns You can format the column by setting it via Column definition on you DataTable service class. ```php Column::make('mobile')->exportFormat('00000000000'), ``` The format above will treat mobile numbers as text with leading zeroes. ## Numeric Fields Formatting The package will auto-detect numeric fields and can be used with custom formats. ```php Column::make('total')->exportFormat('0.00'), Column::make('count')->exportFormat('#,##0'), Column::make('average')->exportFormat('#,##0.00'), ``` ## Date Fields Formatting The package will auto-detect date fields when used with a valid format or is a DateTime instance. ```php Column::make('report_date')->exportFormat('mm/dd/yyyy'), Column::make('created_at'), Column::make('updated_at')->exportFormat(NumberFormat::FORMAT_DATE_DATETIME), ``` ## Valid Date Formats Valid date formats can be adjusted on `datatables-export.php` config file. ```php 'date_formats' => [ 'mm/dd/yyyy', NumberFormat::FORMAT_DATE_DATETIME, NumberFormat::FORMAT_DATE_YYYYMMDD, NumberFormat::FORMAT_DATE_XLSX22, NumberFormat::FORMAT_DATE_DDMMYYYY, NumberFormat::FORMAT_DATE_DMMINUS, NumberFormat::FORMAT_DATE_DMYMINUS, NumberFormat::FORMAT_DATE_DMYSLASH, NumberFormat::FORMAT_DATE_MYMINUS, NumberFormat::FORMAT_DATE_TIME1, NumberFormat::FORMAT_DATE_TIME2, NumberFormat::FORMAT_DATE_TIME3, NumberFormat::FORMAT_DATE_TIME4, NumberFormat::FORMAT_DATE_TIME5, NumberFormat::FORMAT_DATE_TIME6, NumberFormat::FORMAT_DATE_TIME7, NumberFormat::FORMAT_DATE_XLSX14, NumberFormat::FORMAT_DATE_XLSX15, NumberFormat::FORMAT_DATE_XLSX16, NumberFormat::FORMAT_DATE_XLSX17, NumberFormat::FORMAT_DATE_YYYYMMDD2, NumberFormat::FORMAT_DATE_YYYYMMDDSLASH, ] ``` ## Force Numeric Field As Text Format Option to force auto-detected numeric value as text format. ```php Column::make('id')->exportFormat('@'), Column::make('id')->exportFormat(NumberFormat::FORMAT_GENERAL), Column::make('id')->exportFormat(NumberFormat::FORMAT_TEXT), ``` ## Auto Download Option to automatically download the exported file. ```html <livewire:export-button :table-id="$dataTable->getTableId()" filename="my-table.xlsx" auto-download="true"/> ``` ## Contributing Please see [CONTRIBUTING](https://github.com/yajra/laravel-datatables-export/blob/master/.github/CONTRIBUTING.md) for details. ## Security If you discover any security related issues, please email [aqangeles@gmail.com](mailto:aqangeles@gmail.com) instead of using the issue tracker. ## Credits - [Arjay Angeles](https://github.com/yajra) - [All Contributors](https://github.com/yajra/laravel-datatables-export/graphs/contributors) - [Laravel Daily](https://github.com/LaravelDaily/Laravel-Excel-Export-Import-Large-Files) ## License The MIT License (MIT). Please see [License File](https://github.com/yajra/laravel-datatables-export/blob/master/LICENSE.md) for more information. laravel-datatables-export/CONDUCT.md 0000644 00000012243 15060167532 0013243 0 ustar 00 # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others’ private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning Community Impact: A violation through a single incident or series of actions. Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban Community Impact: A serious violation of community standards, including sustained inappropriate behavior. Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. Consequence: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. Community Impact Guidelines were inspired by Mozilla’s code of conduct enforcement ladder. For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. laravel-datatables-buttons/src/Services/DataTablesExportHandler.php 0000644 00000000254 15060167532 0021565 0 ustar 00 <?php namespace Yajra\DataTables\Services; use Yajra\DataTables\Exports\DataTablesCollectionExport; class DataTablesExportHandler extends DataTablesCollectionExport { } laravel-datatables-buttons/src/Services/DataTable.php 0000644 00000044721 15060167532 0016711 0 ustar 00 <?php namespace Yajra\DataTables\Services; use Barryvdh\Snappy\PdfWrapper; use Closure; use Generator; use Illuminate\Contracts\Support\Renderable; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Relations\Relation as EloquentRelation; use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Http\JsonResponse; use Illuminate\Http\Resources\Json\AnonymousResourceCollection; use Illuminate\Http\Response; use Illuminate\Support\Collection; use Illuminate\Support\LazyCollection; use Maatwebsite\Excel\ExcelServiceProvider; use Rap2hpoutre\FastExcel\FastExcel; use Yajra\DataTables\Contracts\DataTableButtons; use Yajra\DataTables\Contracts\DataTableScope; use Yajra\DataTables\Exceptions\Exception; use Yajra\DataTables\Html\Builder; use Yajra\DataTables\Html\Column; use Yajra\DataTables\QueryDataTable; use Yajra\DataTables\Transformers\DataArrayTransformer; use Yajra\DataTables\Utilities\Request; abstract class DataTable implements DataTableButtons { /** * DataTables print preview view. * * @phpstan-var view-string */ protected string $printPreview = 'datatables::print'; /** * Name of the dataTable variable. */ protected string $dataTableVariable = 'dataTable'; /** * List of columns to be excluded from export. */ protected array $excludeFromExport = []; /** * List of columns to be excluded from printing. */ protected array $excludeFromPrint = []; /** * List of columns to be exported. */ protected string|array $exportColumns = '*'; /** * List of columns to be printed. */ protected string|array $printColumns = '*'; /** * Query scopes. * * @var \Yajra\DataTables\Contracts\DataTableScope[] */ protected array $scopes = []; /** * Html builder. */ protected ?Builder $htmlBuilder = null; /** * Html builder extension callback. * * @var callable|null */ protected $htmlCallback; /** * Export filename. */ protected string $filename = ''; /** * Custom attributes set on the class. */ protected array $attributes = []; /** * Callback before sending the response. * * @var callable|null */ protected $beforeCallback; /** * Callback after processing the response. * * @var callable|null */ protected $responseCallback; /** * Available button actions. When calling an action, the value will be used * as the function name (so it should be available) * If you want to add or disable an action, overload and modify this property. */ protected array $actions = ['print', 'csv', 'excel', 'pdf']; protected ?Request $request = null; /** * Flag to use fast-excel package for export. */ protected bool $fastExcel = false; /** * Flag to enable/disable fast-excel callback. * Note: Disabling this flag can improve you export time. * Enabled by default to emulate the same output * with laravel-excel. */ protected bool $fastExcelCallback = true; /** * Export class handler. * * @var class-string */ protected string $exportClass = DataTablesExportHandler::class; /** * CSV export typewriter. */ protected string $csvWriter = 'Csv'; /** * Excel export typewriter. */ protected string $excelWriter = 'Xlsx'; /** * PDF export typewriter. */ protected string $pdfWriter = 'Dompdf'; public function __construct() { /** @var Request $request */ $request = app('datatables.request'); /** @var Builder $builder */ $builder = app('datatables.html'); $this->request = $request; $this->htmlBuilder = $builder; } /** * Process dataTables needed render output. * * @phpstan-param view-string|null $view * * @return mixed */ public function render(?string $view = null, array $data = [], array $mergeData = []) { if ($this->request()->ajax() && $this->request()->wantsJson()) { return app()->call($this->ajax(...)); } /** @var string $action */ $action = $this->request()->get('action'); $actionMethod = $action === 'print' ? 'printPreview' : $action; if (in_array($action, $this->actions) && method_exists($this, $actionMethod)) { /** @var callable $callback */ $callback = [$this, $actionMethod]; return app()->call($callback); } /** @phpstan-ignore-next-line */ return view($view, $data, $mergeData)->with($this->dataTableVariable, $this->getHtmlBuilder()); } /** * Get DataTables Request instance. */ public function request(): Request { if (! $this->request) { $this->request = app(Request::class); } return $this->request; } /** * Display ajax response. */ public function ajax(): JsonResponse { $query = null; if (method_exists($this, 'query')) { /** @var EloquentBuilder|QueryBuilder|EloquentRelation $query */ $query = app()->call([$this, 'query']); $query = $this->applyScopes($query); } /** @var \Yajra\DataTables\DataTableAbstract $dataTable */ // @phpstan-ignore-next-line $dataTable = app()->call([$this, 'dataTable'], compact('query')); if (is_callable($this->beforeCallback)) { app()->call($this->beforeCallback, compact('dataTable')); } if (is_callable($this->responseCallback)) { $data = new Collection($dataTable->toArray()); $response = app()->call($this->responseCallback, compact('data')); return new JsonResponse($response); } return $dataTable->toJson(); } /** * Display printable view of datatables. * * @return \Illuminate\Contracts\View\View */ public function printPreview(): Renderable { $data = $this->getDataForPrint(); return view($this->printPreview, compact('data')); } /** * Get mapped columns versus final decorated output. */ protected function getDataForPrint(): array { $columns = $this->printColumns(); return $this->mapResponseToColumns($columns, 'printable'); } /** * Get printable columns. */ protected function printColumns(): array|Collection { return is_array($this->printColumns) ? $this->toColumnsCollection($this->printColumns) : $this->getPrintColumnsFromBuilder(); } /** * Get filtered print columns definition from html builder. */ protected function getPrintColumnsFromBuilder(): Collection { return $this->html()->removeColumn(...$this->excludeFromPrint)->getColumns(); } /** * Get filtered export columns definition from html builder. */ protected function getExportColumnsFromBuilder(): Collection { return $this->html()->removeColumn(...$this->excludeFromExport)->getColumns(); } /** * Get columns definition from html builder. */ protected function getColumnsFromBuilder(): Collection { return $this->html()->getColumns(); } /** * Optional method if you want to use html builder. * * @return \Yajra\DataTables\Html\Builder */ public function html() { return $this->builder(); } /** * Get DataTables Html Builder instance. */ public function builder(): Builder { if (method_exists($this, 'htmlBuilder')) { return $this->htmlBuilder = $this->htmlBuilder(); } if (! $this->htmlBuilder) { $this->htmlBuilder = app(Builder::class); } return $this->htmlBuilder; } /** * Map ajax response to columns definition. */ protected function mapResponseToColumns(array|\Illuminate\Support\Collection $columns, string $type): array { $transformer = new DataArrayTransformer; return array_map(fn ($row) => $transformer->transform($row, $columns, $type), $this->getAjaxResponseData()); } /** * Get decorated data as defined in datatables ajax response. */ protected function getAjaxResponseData(): array { $this->request()->merge([ 'start' => 0, 'length' => -1, ]); /** @var JsonResponse $response */ $response = app()->call($this->ajax(...)); /** @var array{data: array} $data */ $data = $response->getData(true); return $data['data']; } protected function getHtmlBuilder(): Builder { $builder = $this->html(); if (is_callable($this->htmlCallback)) { app()->call($this->htmlCallback, compact('builder')); } return $builder; } /** * Add html builder callback hook. * * @return $this */ public function withHtml(callable $callback): static { $this->htmlCallback = $callback; return $this; } /** * Add callback before sending the response. * * @return $this */ public function before(callable $callback): static { $this->beforeCallback = $callback; return $this; } /** * Add callback after the response was processed. * * @return $this */ public function response(callable $callback): static { $this->responseCallback = $callback; return $this; } /** * Export results to Excel file. * * @return string|\Symfony\Component\HttpFoundation\BinaryFileResponse|\Symfony\Component\HttpFoundation\StreamedResponse * * @throws \Exception */ public function excel() { set_time_limit(3600); $path = $this->getFilename().'.'.strtolower($this->excelWriter); $excelFile = $this->buildExcelFile(); if ($excelFile instanceof FastExcel) { $callback = $this->fastExcelCallback ? $this->fastExcelCallback() : null; return $excelFile->download($path, $callback); } // @phpstan-ignore-next-line return $excelFile->download($path, $this->excelWriter); } /** * Build Excel file and prepare for export. * * @return mixed|FastExcel * * @throws \Exception */ protected function buildExcelFile() { if ($this->fastExcel) { return $this->buildFastExcelFile(); } if (! class_exists(ExcelServiceProvider::class)) { throw new Exception('Please `composer require maatwebsite/excel` to be able to use this function.'); } if (! new $this->exportClass instanceof DataTablesExportHandler) { $collection = $this->getAjaxResponseData(); return new $this->exportClass($this->convertToLazyCollection($collection)); } $collection = $this->getDataForExport(); return new $this->exportClass($this->convertToLazyCollection($collection)); } /** * Get export filename. */ public function getFilename(): string { return $this->filename ?: $this->filename(); } /** * Set export filename. * * @return $this */ public function setFilename(string $filename): static { $this->filename = $filename; return $this; } /** * Get filename for export. */ protected function filename(): string { return class_basename($this).'_'.date('YmdHis'); } /** * Get mapped columns versus final decorated output. */ protected function getDataForExport(): array { $columns = $this->exportColumns(); return $this->mapResponseToColumns($columns, 'exportable'); } /** * Get export columns definition. * * @return Collection<int, Column> */ protected function exportColumns(): Collection { return is_array($this->exportColumns) ? $this->toColumnsCollection($this->exportColumns) : $this->getExportColumnsFromBuilder(); } /** * Convert array to collection of Column class. */ private function toColumnsCollection(array $columns): Collection { $collection = new Collection; foreach ($columns as $column) { if (isset($column['data'])) { $column['title'] ??= $column['data']; $collection->push(new Column($column)); } else { $data = []; $data['data'] = $column; $data['title'] = $column; $collection->push(new Column($data)); } } return $collection; } /** * Export results to CSV file. * * @return string|\Symfony\Component\HttpFoundation\StreamedResponse * * @throws \Exception */ public function csv() { set_time_limit(3600); $path = $this->getFilename().'.'.strtolower($this->csvWriter); $excelFile = $this->buildExcelFile(); if ($excelFile instanceof FastExcel) { $callback = $this->fastExcelCallback ? $this->fastExcelCallback() : null; return $excelFile->download($path, $callback); } // @phpstan-ignore-next-line return $this->buildExcelFile()->download($path, $this->csvWriter); } /** * Export results to PDF file. * * @return \Illuminate\Http\Response|string|\Symfony\Component\HttpFoundation\StreamedResponse * * @throws \Exception */ public function pdf() { if (config('datatables-buttons.pdf_generator', 'snappy') == 'snappy') { return $this->snappyPdf(); } // @phpstan-ignore-next-line return $this->buildExcelFile()->download($this->getFilename().'.pdf', $this->pdfWriter); } /** * PDF version of the table using print preview blade template. * * * @throws \Yajra\DataTables\Exceptions\Exception */ public function snappyPdf(): Response { if (! class_exists(PdfWrapper::class)) { throw new Exception('Please `composer require barryvdh/laravel-snappy` to be able to use this feature.'); } /** @var \Barryvdh\Snappy\PdfWrapper $snappy */ $snappy = app('snappy.pdf.wrapper'); $options = (array) config('datatables-buttons.snappy.options'); /** @var string $orientation */ $orientation = config('datatables-buttons.snappy.orientation'); $snappy->setOptions($options)->setOrientation($orientation); return $snappy->loadHTML($this->printPreview())->download($this->getFilename().'.pdf'); } /** * Add basic array query scopes. * * @return $this */ public function addScope(DataTableScope $scope): static { $this->scopes[] = $scope; return $this; } /** * Push multiples scopes to array query scopes. * * @return $this */ public function addScopes(array $scopes): static { $this->scopes = array_merge($this->scopes, $scopes); return $this; } /** * Set a custom class attribute. * * @return $this */ public function with(array|string $key, mixed $value = null): static { if (is_array($key)) { $this->attributes = array_merge($this->attributes, $key); } else { $this->attributes[$key] = $value; } return $this; } /** * Dynamically retrieve the value of an attribute. * * @return mixed|null */ public function __get(string $key) { if (array_key_exists($key, $this->attributes)) { return $this->attributes[$key]; } return null; } /** * Apply query scopes. */ protected function applyScopes( EloquentBuilder|QueryBuilder|EloquentRelation|Collection|AnonymousResourceCollection $query ): EloquentBuilder|QueryBuilder|EloquentRelation|Collection|AnonymousResourceCollection { foreach ($this->scopes as $scope) { $scope->apply($query); } return $query; } /** * Determine if the DataTable has scopes. */ protected function hasScopes(array $scopes, bool $validateAll = false): bool { $filteredScopes = array_filter($this->scopes, fn ($scope) => in_array($scope::class, $scopes)); return $validateAll ? count($filteredScopes) === count($scopes) : ! empty($filteredScopes); } /** * Get default builder parameters. */ protected function getBuilderParameters(): array { /** @var array $defaults */ $defaults = config('datatables-buttons.parameters', []); return $defaults; } protected function convertToLazyCollection(array|Collection $collection): LazyCollection { if (is_array($collection)) { $collection = collect($collection); } return $collection->lazy(); } public function fastExcelCallback(): Closure { return function ($row) { $mapped = []; $this->exportColumns()->each(function (Column $column) use (&$mapped, $row) { if ($column['exportable']) { $mapped[$column['title']] = $row[$column['data']]; } }); return $mapped; }; } /** * @throws \Yajra\DataTables\Exceptions\Exception */ protected function buildFastExcelFile(): FastExcel { if (! class_exists(FastExcel::class)) { throw new Exception('Please `composer require rap2hpoutre/fast-excel` to be able to use this function.'); } $query = null; if (method_exists($this, 'query')) { /** @var EloquentBuilder|QueryBuilder $query */ $query = app()->call([$this, 'query']); $query = $this->applyScopes($query); } /** @var \Yajra\DataTables\DataTableAbstract $dataTable */ // @phpstan-ignore-next-line $dataTable = app()->call([$this, 'dataTable'], compact('query')); $dataTable->skipPaging(); if ($dataTable instanceof QueryDataTable) { $queryGenerator = function ($dataTable): Generator { foreach ($dataTable->getFilteredQuery()->cursor() as $row) { yield $row; } }; return new FastExcel($queryGenerator($dataTable)); } return new FastExcel($dataTable->toArray()['data']); } } laravel-datatables-buttons/src/Transformers/DataArrayTransformer.php 0000644 00000004374 15060167532 0022065 0 ustar 00 <?php namespace Yajra\DataTables\Transformers; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Yajra\DataTables\Html\Column; class DataArrayTransformer { /** * Transform row data by column's definition. * * @param array|Collection<array-key, Column> $columns */ public function transform(array $row, array|Collection $columns, string $type = 'printable'): array { if ($columns instanceof Collection) { return $this->buildColumnByCollection($row, $columns, $type); } return Arr::only($row, $columns); } /** * Transform row column by collection. * * @param Collection<array-key, Column> $columns */ protected function buildColumnByCollection(array $row, Collection $columns, string $type = 'printable'): array { $results = []; $columns->each(function (Column $column) use ($row, $type, &$results) { if ($column[$type]) { $title = $column->title; if (is_array($column->data)) { $key = $column->data['filter'] ?? $column->name ?? ''; } else { $key = $column->data ?? $column->name; } $data = Arr::get($row, $key) ?? ''; if ($type == 'exportable') { $title = $this->decodeContent($title); $data = is_array($data) ? json_encode($data, JSON_THROW_ON_ERROR) : $this->decodeContent($data); } if (isset($column->exportRender)) { $callback = $column->exportRender; $results[$title] = $callback($row, $data); } else { $results[$title] = $data; } } }); return $results; } /** * Decode content to a readable text value. */ protected function decodeContent(mixed $data): mixed { if (is_bool($data)) { return $data ? 'True' : 'False'; } if (is_string($data)) { $decoded = html_entity_decode(trim(strip_tags($data)), ENT_QUOTES, 'UTF-8'); return (string) str_replace("\xc2\xa0", ' ', $decoded); } return $data; } } laravel-datatables-buttons/src/Exports/DataTablesCollectionExport.php 0000644 00000001600 15060167532 0022160 0 ustar 00 <?php namespace Yajra\DataTables\Exports; use Illuminate\Support\Collection; use Illuminate\Support\LazyCollection; use Maatwebsite\Excel\Concerns\Exportable; use Maatwebsite\Excel\Concerns\FromCollection; use Maatwebsite\Excel\Concerns\WithHeadings; abstract class DataTablesCollectionExport implements FromCollection, WithHeadings { use Exportable; protected LazyCollection|Collection $collection; public function __construct(Collection|LazyCollection|null $collection = null) { $this->collection = $collection ?? new Collection; } public function collection(): Collection|LazyCollection { return $this->collection; } public function headings(): array { /** @var array $first */ $first = $this->collection->first(); if ($first) { return array_keys($first); } return []; } } laravel-datatables-buttons/src/ButtonsServiceProvider.php 0000644 00000003453 15060167532 0017774 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Support\ServiceProvider; use Maatwebsite\Excel\ExcelServiceProvider; use Yajra\DataTables\Generators\DataTablesHtmlCommand; use Yajra\DataTables\Generators\DataTablesMakeCommand; use Yajra\DataTables\Generators\DataTablesScopeCommand; class ButtonsServiceProvider extends ServiceProvider { /** * Bootstrap the application events. */ public function boot(): void { $this->loadViewsFrom(__DIR__.'/resources/views', 'datatables'); $this->publishAssets(); $this->registerCommands(); } /** * Publish datatables assets. */ protected function publishAssets(): void { $this->publishes([ __DIR__.'/config/config.php' => config_path('datatables-buttons.php'), ], 'datatables-buttons'); $this->publishes([ __DIR__.'/resources/assets/buttons.server-side.js' => public_path('vendor/datatables/buttons.server-side.js'), ], 'datatables-buttons'); $this->publishes([ __DIR__.'/resources/views' => base_path('/resources/views/vendor/datatables'), ], 'datatables-buttons'); } /** * Register datatables commands. */ protected function registerCommands(): void { $this->commands(DataTablesMakeCommand::class); $this->commands(DataTablesScopeCommand::class); $this->commands(DataTablesHtmlCommand::class); } /** * Register the service provider. */ public function register(): void { $this->mergeConfigFrom(__DIR__.'/config/config.php', 'datatables-buttons'); $this->app->register(HtmlServiceProvider::class); if (class_exists(ExcelServiceProvider::class)) { $this->app->register(ExcelServiceProvider::class); } } } laravel-datatables-buttons/src/Generators/DataTablesScopeCommand.php 0000644 00000002061 15060167532 0021702 0 ustar 00 <?php namespace Yajra\DataTables\Generators; use Illuminate\Console\GeneratorCommand; class DataTablesScopeCommand extends GeneratorCommand { /** * The console command name. * * @var string */ protected $name = 'datatables:scope'; /** * The console command description. * * @var string */ protected $description = 'Create a new DataTable Scope class.'; /** * The type of class being generated. * * @var string */ protected $type = 'DataTable Scope'; /** * Get the default namespace for the class. * * @param string $rootNamespace */ protected function getDefaultNamespace($rootNamespace): string { return $rootNamespace.'\DataTables\Scopes'; } /** * Get the stub file for the generator. */ protected function getStub(): string { if ($stubFolder = config('datatables-buttons.stub')) { return base_path($stubFolder.'/scopes.stub'); } return __DIR__.'/stubs/scopes.stub'; } } laravel-datatables-buttons/src/Generators/stubs/builder.stub 0000644 00000002106 15060167532 0020361 0 ustar 00 <?php namespace DummyNamespace; use DummyModel; use Illuminate\Database\Eloquent\Builder as QueryBuilder; use Yajra\DataTables\EloquentDataTable; use Yajra\DataTables\Html\Builder as HtmlBuilder; use Yajra\DataTables\Services\DataTable; class DummyClass extends DataTable { /** * Build the DataTable class. * * @param QueryBuilder $query Results from query() method. */ public function dataTable(QueryBuilder $query): EloquentDataTable { return (new EloquentDataTable($query)) ->addColumn('action', 'DummyAction') ->setRowId('id'); } /** * Get the query source of dataTable. */ public function query(ModelName $model): QueryBuilder { return $model->newQuery(); } /** * Optional method if you want to use the html builder. */ public function html(): HtmlBuilder { return DummyBuilder::make(); } /** * Get the filename for export. */ protected function filename(): string { return 'DummyFilename_' . date('YmdHis'); } } laravel-datatables-buttons/src/Generators/stubs/datatables.stub 0000644 00000003624 15060167532 0021045 0 ustar 00 <?php namespace DummyNamespace; use DummyModel; use Yajra\DataTables\Html\Button; use Yajra\DataTables\Html\Column; use Yajra\DataTables\Services\DataTable; use Yajra\DataTables\Html\Editor\Fields; use Yajra\DataTables\Html\Editor\Editor; use Illuminate\Database\Eloquent\Builder as QueryBuilder; use Yajra\DataTables\EloquentDataTable; use Yajra\DataTables\Html\Builder as HtmlBuilder; class DummyClass extends DataTable { /** * Build the DataTable class. * * @param QueryBuilder $query Results from query() method. */ public function dataTable(QueryBuilder $query): EloquentDataTable { return (new EloquentDataTable($query)) ->addColumn('action', 'DummyAction') ->setRowId('id'); } /** * Get the query source of dataTable. */ public function query(ModelName $model): QueryBuilder { return $model->newQuery(); } /** * Optional method if you want to use the html builder. */ public function html(): HtmlBuilder { return $this->builder() ->setTableId('DummyTableId') ->columns($this->getColumns()) ->minifiedAjax() //->dom('DummyDOM') ->orderBy(1) ->selectStyleSingle() ->buttons([ DummyButtons ]); } /** * Get the dataTable columns definition. */ public function getColumns(): array { return [ Column::computed('action') ->exportable(false) ->printable(false) ->width(60) ->addClass('text-center'), DummyColumns ]; } /** * Get the filename for export. */ protected function filename(): string { return 'DummyFilename_' . date('YmdHis'); } } laravel-datatables-buttons/src/Generators/stubs/html.stub 0000644 00000002114 15060167532 0017676 0 ustar 00 <?php namespace DummyNamespace; use Yajra\DataTables\Html\Button; use Yajra\DataTables\Html\Column; use Yajra\DataTables\Html\DataTableHtml; use Yajra\DataTables\Html\Editor\Fields; use Yajra\DataTables\Html\Editor\Editor; class DummyClass extends DataTableHtml { /** * Build the html builder. * * @throws \Exception */ public function handle(): Builder { return $this->setTableId('DummyTableId') ->columns($this->getColumns()) ->minifiedAjax() //->dom('DummyDOM') ->orderBy(1) ->selectStyleSingle() ->buttons([ DummyButtons ]); } /** * Get the dataTable columns definition. */ public function getColumns(): array { return [ Column::computed('action') ->exportable(false) ->printable(false) ->width(60) ->addClass('text-center'), DummyColumns ]; } } laravel-datatables-buttons/src/Generators/stubs/scopes.stub 0000644 00000000577 15060167532 0020241 0 ustar 00 <?php namespace DummyNamespace; use Yajra\DataTables\Contracts\DataTableScope; class DummyClass implements DataTableScope { /** * Apply a query scope. * * @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder $query * @return mixed */ public function apply($query) { // return $query->where('id', 1); } } laravel-datatables-buttons/src/Generators/DataTablesMakeCommand.php 0000644 00000024101 15060167532 0021505 0 ustar 00 <?php namespace Yajra\DataTables\Generators; use Illuminate\Console\GeneratorCommand; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Str; class DataTablesMakeCommand extends GeneratorCommand { /** * The name and signature of the console command. * * @var string */ protected $signature = 'datatables:make {name : The name of the DataTable.} {--model= : The name of the model to be used.} {--model-namespace= : The namespace of the model to be used.} {--action= : The path of the action view.} {--table= : Scaffold columns from the table.} {--builder : Extract html() to a Builder class.} {--dom= : The dom of the DataTable.} {--buttons= : The buttons of the DataTable.} {--columns= : The columns of the DataTable.}'; /** * The console command description. * * @var string */ protected $description = 'Create a new DataTable service class.'; /** * The type of class being generated. * * @var string */ protected $type = 'DataTable'; public function handle() { parent::handle(); if ($this->option('builder')) { $columns = config('datatables-buttons.generator.columns', 'id,add your columns,created_at,updated_at'); $buttons = config('datatables-buttons.generator.buttons', 'create,export,print,reset,reload'); $dom = config('datatables-buttons.generator.dom', 'Bfrtip'); $this->call('datatables:html', [ 'name' => $this->getDataTableBaseName(), '--columns' => $this->option('columns') ?: $columns, '--buttons' => $this->option('buttons') ?: $buttons, '--dom' => $this->option('dom') ?: $dom, '--table' => $this->option('table'), ]); } } /** * Build the class with the given name. * * @param string $name * * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException */ protected function buildClass($name): string { $stub = parent::buildClass($name); $this->replaceModelImport($stub) ->replaceModel($stub) ->replaceBuilder($stub) ->replaceColumns($stub) ->replaceButtons($stub) ->replaceDOM($stub) ->replaceTableId($stub) ->replaceAction($stub) ->replaceFilename($stub); return $stub; } /** * Get DataTable class base name without the suffix. */ protected function getDataTableBaseName(): string { return (string) preg_replace('#datatable$#i', '', (string) $this->getNameInput()); } /** * Prepare model name from input. */ protected function prepareModelName(): string { return basename($this->getDataTableBaseName()); } /** * Replace the filename. * * @return $this */ protected function replaceFilename(string &$stub): static { $stub = str_replace('DummyFilename', $this->prepareModelName(), $stub); return $this; } /** * Replace the action. */ protected function replaceAction(string &$stub): static { $stub = str_replace('DummyAction', $this->getAction(), $stub); return $this; } /** * Set the action view to be used. */ protected function getAction(): string { /** @var string $action */ $action = $this->option('action'); if ($action) { return $action; } return Str::lower($this->prepareModelName()).'.action'; } /** * Replace columns. * * @return $this */ protected function replaceTableId(string &$stub): static { $stub = str_replace('DummyTableId', Str::lower($this->prepareModelName()).'-table', $stub); return $this; } /** * Replace dom. * * @return $this */ protected function replaceDOM(string &$stub): static { /** @var string $dom */ $dom = $this->option('dom') ?: config('datatables-buttons.generator.dom', 'Bfrtip'); $stub = str_replace('DummyDOM', $dom, $stub); return $this; } /** * Replace buttons. * * @return $this */ protected function replaceButtons(string &$stub): static { $stub = str_replace('DummyButtons', $this->getButtons(), $stub); return $this; } /** * Get the columns to be used. */ protected function getButtons(): string { /** @var string $buttons */ $buttons = $this->option('buttons'); if ($buttons) { return $this->parseButtons($buttons); } /** @var string $buttons */ $buttons = config('datatables-buttons.generator.buttons', 'create,export,print,reset,reload'); return $this->parseButtons($buttons); } /** * Parse array from definition. */ protected function parseButtons(string $definition, int $indentation = 24): string { $columns = explode(',', $definition); $stub = ''; foreach ($columns as $key => $column) { $indent = ''; $separator = ','; if ($key < count($columns) - 1) { $indent = PHP_EOL.str_repeat(' ', $indentation); } if ($key == count($columns) - 1) { $separator = ''; } $stub .= "Button::make('{$column}')".$separator.$indent; } return $stub; } /** * Replace columns. * * @return $this */ protected function replaceColumns(string &$stub): static { $stub = str_replace('DummyColumns', $this->getColumns(), $stub); return $this; } /** * Get the columns to be used. */ protected function getColumns(): string { /** @var string $table */ $table = $this->option('table'); if ($table) { return $this->parseColumns(Schema::getColumnListing($table)); } /** @var string $columns */ $columns = $this->option('columns'); if ($columns) { return $this->parseColumns($columns); } /** @var string $columns */ $columns = config('datatables-buttons.generator.columns', 'id,add your columns,created_at,updated_at'); return $this->parseColumns($columns); } /** * Parse array from definition. */ protected function parseColumns(array|string $definition, int $indentation = 12): string { $columns = is_array($definition) ? $definition : explode(',', $definition); $stub = ''; foreach ($columns as $key => $column) { $stub .= "Column::make('{$column}'),"; if ($key < count($columns) - 1) { $stub .= PHP_EOL.str_repeat(' ', $indentation); } } return $stub; } /** * Replace builder name. * * @param string $stub * @return \Yajra\DataTables\Generators\DataTablesMakeCommand */ protected function replaceBuilder(&$stub) { $name = $this->qualifyClass($this->getNameInput()); $class = str_replace($this->getNamespace($name).'\\', '', $name); $stub = str_replace('DummyBuilder', $class.'Html', $stub); return $this; } /** * Parse the name and format according to the root namespace. * * @param string $name * @return string */ protected function qualifyClass($name) { $rootNamespace = $this->laravel->getNamespace(); if (Str::startsWith($name, $rootNamespace)) { return $name; } if (Str::contains($name, '/')) { $name = str_replace('/', '\\', $name); } if (! Str::contains(Str::lower($name), 'datatable')) { $name .= 'DataTable'; } else { $name = preg_replace('#datatable$#i', 'DataTable', $name); } return $this->getDefaultNamespace(trim((string) $rootNamespace, '\\')).'\\'.$name; } /** * Get the default namespace for the class. * * @param string $rootNamespace */ protected function getDefaultNamespace($rootNamespace): string { return $rootNamespace.'\\'.config('datatables-buttons.namespace.base', 'DataTables'); } /** * Replace model name. */ protected function replaceModel(string &$stub): static { $model = explode('\\', $this->getModel()); $model = array_pop($model); $stub = str_replace('ModelName', $model, $stub); return $this; } /** * Get model name to use. */ protected function getModel(): string { /** @var string $modelFromOption */ $modelFromOption = $this->option('model'); $modelNamespaceFromOption = $this->option('model-namespace') ?: config('datatables-buttons.namespace.model'); $name = $modelFromOption ?: $this->prepareModelName(); $modelNamespace = $modelNamespaceFromOption ?: $this->laravel->getNamespace(); if (empty($modelNamespaceFromOption) && is_dir(app_path('Models'))) { $modelNamespace = $modelNamespace.'\\Models\\'; } return $modelNamespace.'\\'.Str::singular($name); } /** * Replace model import. * * @return $this */ protected function replaceModelImport(string &$stub): static { $stub = str_replace('DummyModel', str_replace('\\\\', '\\', $this->getModel()), $stub); return $this; } /** * Get the stub file for the generator. */ protected function getStub(): string { $stub = 'datatables.stub'; if ($this->option('builder')) { $stub = 'builder.stub'; } return config('datatables-buttons.stub') ? base_path().config('datatables-buttons.stub')."/$stub" : __DIR__."/stubs/{$stub}"; } } laravel-datatables-buttons/src/Generators/DataTablesHtmlCommand.php 0000644 00000005030 15060167532 0021534 0 ustar 00 <?php namespace Yajra\DataTables\Generators; use Illuminate\Support\Str; class DataTablesHtmlCommand extends DataTablesMakeCommand { /** * The name and signature of the console command. * * @var string */ protected $signature = 'datatables:html {name : The name of the DataTable html.} {--dom= : The dom of the DataTable.} {--buttons= : The buttons of the DataTable.} {--table= : Scaffold columns from the table.} {--builder : Ignore, added to work with parent generator.} {--columns= : The columns of the DataTable.}'; /** * The console command description. * * @var string */ protected $description = 'Create a new DataTable html class.'; /** * The type of class being generated. * * @var string */ protected $type = 'DataTableHtml'; /** * Build the class with the given name. * * @param string $name * * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException */ protected function buildClass($name): string { $stub = $this->files->get($this->getStub()); $stub = $this->replaceNamespace($stub, $name)->replaceClass($stub, $name); $this->replaceBuilder($stub) ->replaceColumns($stub) ->replaceButtons($stub) ->replaceDOM($stub) ->replaceTableId($stub); return $stub; } /** * Get the stub file for the generator. */ protected function getStub(): string { return config('datatables-buttons.stub') ? base_path().config('datatables-buttons.stub').'/html.stub' : __DIR__.'/stubs/html.stub'; } /** * Parse the name and format according to the root namespace. * * @param string $name */ protected function qualifyClass($name): string { $rootNamespace = $this->laravel->getNamespace(); if (Str::startsWith($name, $rootNamespace)) { return $name; } if (Str::contains($name, '/')) { $name = str_replace('/', '\\', $name); } if (! Str::contains(Str::lower($name), 'datatablehtml')) { $name .= 'DataTableHtml'; } else { $name = preg_replace('#datatablehtml$#i', 'DataTableHtml', $name); } return $this->getDefaultNamespace(trim((string) $rootNamespace, '\\')).'\\'.$name; } } laravel-datatables-buttons/src/resources/views/print.blade.php 0000644 00000002503 15060167532 0020646 0 ustar 00 <!DOCTYPE html> <html lang="en"> <head> <title>Print Table</title> <meta charset="UTF-8"> <meta name=description content=""> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Bootstrap CSS --> <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> <style> body {margin: 20px} </style> </head> <body> <table class="table table-bordered table-condensed table-striped"> @foreach($data as $row) @if ($loop->first) <tr> @foreach($row as $key => $value) <th>{!! $key !!}</th> @endforeach </tr> @endif <tr> @foreach($row as $key => $value) @if(is_string($value) || is_numeric($value)) <td>{!! $value !!}</td> @else <td></td> @endif @endforeach </tr> @endforeach </table> </body> </html> laravel-datatables-buttons/src/resources/assets/buttons.server-side.js 0000644 00000021560 15060167532 0022367 0 ustar 00 (function ($, DataTable) { "use strict"; var _buildParams = function (dt, action, onlyVisibles) { var params = dt.ajax.params(); params.action = action; params._token = $('meta[name="csrf-token"]').attr('content'); if (onlyVisibles) { params.visible_columns = _getVisibleColumns(); } else { params.visible_columns = null; } return params; }; var _getVisibleColumns = function () { var visible_columns = []; $.each(DataTable.settings[0].aoColumns, function (key, col) { if (col.bVisible) { visible_columns.push(col.name); } }); return visible_columns; }; var _downloadFromUrl = function (url, params) { var postUrl = url + '/export'; var xhr = new XMLHttpRequest(); xhr.open('POST', postUrl, true); xhr.responseType = 'arraybuffer'; xhr.onload = function () { if (this.status === 200) { var filename = ""; var disposition = xhr.getResponseHeader('Content-Disposition'); if (disposition && disposition.indexOf('attachment') !== -1) { var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; var matches = filenameRegex.exec(disposition); if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, ''); } var type = xhr.getResponseHeader('Content-Type'); var blob = new Blob([this.response], {type: type}); if (typeof window.navigator.msSaveBlob !== 'undefined') { // IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed." window.navigator.msSaveBlob(blob, filename); } else { var URL = window.URL || window.webkitURL; var downloadUrl = URL.createObjectURL(blob); if (filename) { // use HTML5 a[download] attribute to specify filename var a = document.createElement("a"); // safari doesn't support this yet if (typeof a.download === 'undefined') { window.location = downloadUrl; } else { a.href = downloadUrl; a.download = filename; document.body.appendChild(a); a.click(); } } else { window.location = downloadUrl; } setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup } } }; xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send($.param(params)); }; var _buildUrl = function(dt, action) { var url = dt.ajax.url() || ''; var params = dt.ajax.params(); params.action = action; if (url.indexOf('?') > -1) { return url + '&' + $.param(params); } return url + '?' + $.param(params); }; DataTable.ext.buttons.excel = { className: 'buttons-excel', text: function (dt) { return '<i class="fa fa-file-excel-o"></i> ' + dt.i18n('buttons.excel', 'Excel'); }, action: function (e, dt, button, config) { var url = _buildUrl(dt, 'excel'); window.location = url; } }; DataTable.ext.buttons.postExcel = { className: 'buttons-excel', text: function (dt) { return '<i class="fa fa-file-excel-o"></i> ' + dt.i18n('buttons.excel', 'Excel'); }, action: function (e, dt, button, config) { var url = dt.ajax.url() || window.location.href; var params = _buildParams(dt, 'excel'); _downloadFromUrl(url, params); } }; DataTable.ext.buttons.postExcelVisibleColumns = { className: 'buttons-excel', text: function (dt) { return '<i class="fa fa-file-excel-o"></i> ' + dt.i18n('buttons.excel', 'Excel (only visible columns)'); }, action: function (e, dt, button, config) { var url = dt.ajax.url() || window.location.href; var params = _buildParams(dt, 'excel', true); _downloadFromUrl(url, params); } }; DataTable.ext.buttons.export = { extend: 'collection', className: 'buttons-export', text: function (dt) { return '<i class="fa fa-download"></i> ' + dt.i18n('buttons.export', 'Export') + ' <span class="caret"/>'; }, buttons: ['csv', 'excel', 'pdf'] }; DataTable.ext.buttons.csv = { className: 'buttons-csv', text: function (dt) { return '<i class="fa fa-file-excel-o"></i> ' + dt.i18n('buttons.csv', 'CSV'); }, action: function (e, dt, button, config) { var url = _buildUrl(dt, 'csv'); window.location = url; } }; DataTable.ext.buttons.postCsvVisibleColumns = { className: 'buttons-csv', text: function (dt) { return '<i class="fa fa-file-excel-o"></i> ' + dt.i18n('buttons.csv', 'CSV (only visible columns)'); }, action: function (e, dt, button, config) { var url = dt.ajax.url() || window.location.href; var params = _buildParams(dt, 'csv', true); _downloadFromUrl(url, params); } }; DataTable.ext.buttons.postCsv = { className: 'buttons-csv', text: function (dt) { return '<i class="fa fa-file-excel-o"></i> ' + dt.i18n('buttons.csv', 'CSV'); }, action: function (e, dt, button, config) { var url = dt.ajax.url() || window.location.href; var params = _buildParams(dt, 'csv'); _downloadFromUrl(url, params); } }; DataTable.ext.buttons.pdf = { className: 'buttons-pdf', text: function (dt) { return '<i class="fa fa-file-pdf-o"></i> ' + dt.i18n('buttons.pdf', 'PDF'); }, action: function (e, dt, button, config) { var url = _buildUrl(dt, 'pdf'); window.location = url; } }; DataTable.ext.buttons.postPdf = { className: 'buttons-pdf', text: function (dt) { return '<i class="fa fa-file-pdf-o"></i> ' + dt.i18n('buttons.pdf', 'PDF'); }, action: function (e, dt, button, config) { var url = dt.ajax.url() || window.location.href; var params = _buildParams(dt, 'pdf'); _downloadFromUrl(url, params); } }; DataTable.ext.buttons.print = { className: 'buttons-print', text: function (dt) { return '<i class="fa fa-print"></i> ' + dt.i18n('buttons.print', 'Print'); }, action: function (e, dt, button, config) { var url = _buildUrl(dt, 'print'); window.location = url; } }; DataTable.ext.buttons.reset = { className: 'buttons-reset', text: function (dt) { return '<i class="fa fa-undo"></i> ' + dt.i18n('buttons.reset', 'Reset'); }, action: function (e, dt, button, config) { dt.search(''); dt.columns().search(''); dt.draw(); } }; DataTable.ext.buttons.reload = { className: 'buttons-reload', text: function (dt) { return '<i class="fa fa-refresh"></i> ' + dt.i18n('buttons.reload', 'Reload'); }, action: function (e, dt, button, config) { dt.draw(false); } }; DataTable.ext.buttons.create = { className: 'buttons-create', text: function (dt) { return '<i class="fa fa-plus"></i> ' + dt.i18n('buttons.create', 'Create'); }, action: function (e, dt, button, config) { window.location = window.location.href.replace(/\/+$/, "") + '/create'; } }; if (typeof DataTable.ext.buttons.copyHtml5 !== 'undefined') { $.extend(DataTable.ext.buttons.copyHtml5, { text: function (dt) { return '<i class="fa fa-copy"></i> ' + dt.i18n('buttons.copy', 'Copy'); } }); } if (typeof DataTable.ext.buttons.colvis !== 'undefined') { $.extend(DataTable.ext.buttons.colvis, { text: function (dt) { return '<i class="fa fa-eye"></i> ' + dt.i18n('buttons.colvis', 'Column visibility'); } }); } })(jQuery, jQuery.fn.dataTable); laravel-datatables-buttons/src/Html/DataTableHtml.php 0000644 00000002345 15060167532 0016653 0 ustar 00 <?php namespace Yajra\DataTables\Html; use BadMethodCallException; use Yajra\DataTables\Contracts\DataTableHtmlBuilder; /** * @mixin Builder */ abstract class DataTableHtml implements DataTableHtmlBuilder { protected ?Builder $htmlBuilder = null; public static function make(): Builder { if (func_get_args()) { return (new static(...func_get_args()))->handle(); } /** @var static $html */ $html = app(static::class); return $html->handle(); } /** * @return \Yajra\DataTables\Html\Builder * * @throws \Exception */ public function __call(string $method, mixed $parameters) { if (method_exists($this->getHtmlBuilder(), $method)) { return $this->getHtmlBuilder()->{$method}(...$parameters); } throw new BadMethodCallException("Method {$method} does not exists"); } protected function getHtmlBuilder(): Builder { if ($this->htmlBuilder) { return $this->htmlBuilder; } return $this->htmlBuilder = app(Builder::class); } public function setHtmlBuilder(Builder $builder): static { $this->htmlBuilder = $builder; return $this; } } laravel-datatables-buttons/src/Contracts/DataTableHtmlBuilder.php 0000644 00000000337 15060167532 0021215 0 ustar 00 <?php namespace Yajra\DataTables\Contracts; interface DataTableHtmlBuilder { /** * Handle building of dataTables html. * * @return \Yajra\DataTables\Html\Builder */ public function handle(); } laravel-datatables-buttons/src/Contracts/DataTableScope.php 0000644 00000000642 15060167532 0020052 0 ustar 00 <?php namespace Yajra\DataTables\Contracts; interface DataTableScope { /** * Apply a query scope. * * @param \Illuminate\Database\Query\Builder|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Relations\Relation|\Illuminate\Support\Collection|\Illuminate\Http\Resources\Json\AnonymousResourceCollection $query * @return mixed */ public function apply($query); } laravel-datatables-buttons/src/Contracts/DataTableButtons.php 0000644 00000000760 15060167532 0020440 0 ustar 00 <?php namespace Yajra\DataTables\Contracts; interface DataTableButtons { /** * Export to excel file. * * @return mixed */ public function excel(); /** * Export to CSV file. * * @return mixed */ public function csv(); /** * Export to PDF file. * * @return mixed */ public function pdf(); /** * Display printer friendly view. * * @return mixed */ public function printPreview(); } laravel-datatables-buttons/src/config/config.php 0000644 00000004320 15060167532 0016006 0 ustar 00 <?php return [ /* * Namespaces used by the generator. */ 'namespace' => [ /* * Base namespace/directory to create the new file. * This is appended on default Laravel namespace. * Usage: php artisan datatables:make User * Output: App\DataTables\UserDataTable * With Model: App\User (default model) * Export filename: users_timestamp */ 'base' => 'DataTables', /* * Base namespace/directory where your model's are located. * This is appended on default Laravel namespace. * Usage: php artisan datatables:make Post --model * Output: App\DataTables\PostDataTable * With Model: App\Post * Export filename: posts_timestamp */ 'model' => 'App\\Models', ], /* * Set Custom stub folder */ //'stub' => '/resources/custom_stub', /* * PDF generator to be used when converting the table to pdf. * Available generators: excel, snappy * Snappy package: barryvdh/laravel-snappy * Excel package: maatwebsite/excel */ 'pdf_generator' => 'snappy', /* * Snappy PDF options. */ 'snappy' => [ 'options' => [ 'no-outline' => true, 'margin-left' => '0', 'margin-right' => '0', 'margin-top' => '10mm', 'margin-bottom' => '10mm', ], 'orientation' => 'landscape', ], /* * Default html builder parameters. */ 'parameters' => [ 'dom' => 'Bfrtip', 'order' => [[0, 'desc']], 'buttons' => [ 'excel', 'csv', 'pdf', 'print', 'reset', 'reload', ], ], /* * Generator command default options value. */ 'generator' => [ /* * Default columns to generate when not set. */ 'columns' => 'id,add your columns,created_at,updated_at', /* * Default buttons to generate when not set. */ 'buttons' => 'excel,csv,pdf,print,reset,reload', /* * Default DOM to generate when not set. */ 'dom' => 'Bfrtip', ], ]; laravel-datatables-buttons/CONTRIBUTING.md 0000644 00000001652 15060167532 0014232 0 ustar 00 # Contributing Contributions are **welcome** and will be fully **credited**. We accept contributions via Pull Requests on [Github](https://github.com/yajra/laravel-datatables-buttons). ## Pull Requests - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. **Happy coding**! laravel-datatables-buttons/LICENSE.md 0000644 00000002117 15060167532 0013402 0 ustar 00 (The MIT License) Copyright (c) 2013-2018 Arjay Angeles <aqangeles@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. laravel-datatables-buttons/rector.php 0000644 00000001032 15060167532 0014000 0 ustar 00 <?php declare(strict_types=1); use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; use Rector\Config\RectorConfig; use Rector\Set\ValueObject\LevelSetList; return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths([ __DIR__.'/src', __DIR__.'/tests', ]); // register a single rule $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); // define sets of rules $rectorConfig->sets([ LevelSetList::UP_TO_PHP_82, ]); }; laravel-datatables-buttons/CHANGELOG.md 0000644 00000000140 15060167532 0013601 0 ustar 00 # Laravel DataTables Buttons Plugin CHANGELOG. ## v11.0.0 - 2024-03-14 - Laravel 11.x support laravel-datatables-buttons/composer.json 0000644 00000004436 15060167532 0014526 0 ustar 00 { "name": "yajra/laravel-datatables-buttons", "description": "Laravel DataTables Buttons Plugin.", "keywords": [ "laravel", "datatables", "buttons", "jquery" ], "license": "MIT", "authors": [ { "name": "Arjay Angeles", "email": "aqangeles@gmail.com" } ], "require": { "php": "^8.2", "yajra/laravel-datatables-oracle": "^11", "yajra/laravel-datatables-html": "^11", "illuminate/console": "^11" }, "require-dev": { "larastan/larastan": "^2.9.2", "orchestra/testbench": "^9", "laravel/pint": "^1.14", "rector/rector": "^1.0.2", "maatwebsite/excel": "^3.1.55", "rap2hpoutre/fast-excel": "^5.4" }, "autoload": { "psr-4": { "Yajra\\DataTables\\": "src/" } }, "autoload-dev": { "psr-4": { "Yajra\\DataTables\\Buttons\\Tests\\": "tests/" } }, "extra": { "branch-alias": { "dev-master": "11.0-dev" }, "laravel": { "providers": [ "Yajra\\DataTables\\ButtonsServiceProvider" ] } }, "suggest": { "yajra/laravel-datatables-export": "Exporting of dataTables (excel, csv and PDF) via livewire and queue worker.", "maatwebsite/excel": "Exporting of dataTables (excel, csv and PDF) using maatwebsite package.", "rap2hpoutre/fast-excel": "Faster exporting of dataTables using fast-excel package.", "dompdf/dompdf": "Allows exporting of dataTable to PDF using the DomPDF.", "barryvdh/laravel-snappy": "Allows exporting of dataTable to PDF using the print view." }, "scripts": { "test": "./vendor/bin/phpunit", "pint": "./vendor/bin/pint", "rector": "./vendor/bin/rector", "stan": "./vendor/bin/phpstan analyse --memory-limit=2G --ansi --no-progress --no-interaction --configuration=phpstan.neon.dist", "pr": [ "@pint", "@rector", "@stan", "@test" ] }, "minimum-stability": "dev", "prefer-stable": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/yajra" } ] } laravel-datatables-buttons/README.md 0000644 00000005675 15060167532 0013271 0 ustar 00 # Laravel DataTables Buttons Plugin [](http://laravel.com) [](https://packagist.org/packages/yajra/laravel-datatables-buttons) [](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/continuous-integration.yml) [](https://github.com/yajra/laravel-datatables-buttons/actions/workflows/static-analysis.yml) [](https://scrutinizer-ci.com/g/yajra/laravel-datatables-buttons/?branch=master) [](https://packagist.org/packages/yajra/laravel-datatables-buttons) [](https://packagist.org/packages/yajra/laravel-datatables-buttons) This package is a plugin of [Laravel DataTables](https://github.com/yajra/laravel-datatables) for handling server-side function of exporting the table as csv, excel, pdf and printing. ## Requirements - [PHP >= 8.2](http://php.net/) - [Laravel 11.x](https://github.com/laravel/framework) - [Laravel DataTables](https://github.com/yajra/laravel-datatables) - [jQuery DataTables v1.10.x](http://datatables.net/) - [jQuery DataTables Buttons Extension](https://datatables.net/reference/button/) ## Documentations - [Laravel DataTables Documentation](http://yajrabox.com/docs/laravel-datatables) ## Laravel Version Compatibility | Laravel | Package | |:--------------|:--------| | 8.x and below | 4.x | | 9.x | 9.x | | 10.x | 10.x | | 11.x | 11.x | ## Quick Installation `composer require yajra/laravel-datatables-buttons:^11` #### Service Provider (Optional on Laravel 5.5) `Yajra\DataTables\ButtonsServiceProvider::class` #### Configuration and Assets (Optional) `$ php artisan vendor:publish --tag=datatables-buttons --force` And that's it! Start building out some awesome DataTables! ## Contributing Please see [CONTRIBUTING](https://github.com/yajra/laravel-datatables-buttons/blob/master/.github/CONTRIBUTING.md) for details. ## Security If you discover any security related issues, please email [aqangeles@gmail.com](mailto:aqangeles@gmail.com) instead of using the issue tracker. ## Credits - [Arjay Angeles](https://github.com/yajra) - [All Contributors](https://github.com/yajra/laravel-datatables-buttons/graphs/contributors) ## License The MIT License (MIT). Please see [License File](https://github.com/yajra/laravel-datatables-buttons/blob/master/LICENSE.md) for more information. laravel-datatables-buttons/UPGADE.md 0000644 00000001050 15060167532 0013260 0 ustar 00 # UPGRADE GUIDE ## Upgrade from 10.x to 11.x 1. Update the composer.json file and change the version of the package to `^11.0`: ```json "require": { "yajra/laravel-datatables-buttons": "^11.0" } ``` 2. Run `composer update` to update the package. 3. If you are using a custom class of laravel-excel to export the data, you need to update the collection method and include the return type `Collection|LazyCollection` in the method signature. ```php public function collection(): Collection|LazyCollection { return $this->collection; } ``` laravel-datatables/tests/Unit/ExampleTest.php 0000644 00000000107 15060167532 0015324 0 ustar 00 <?php test('example', function () { expect(true)->toBeTrue(); }); laravel-datatables/tests/Feature/PackageTest.php 0000644 00000000755 15060167532 0015751 0 ustar 00 <?php test('it loads all the packages', function () { expect(class_exists(\Yajra\DataTables\DataTablesServiceProvider::class))->toBeTrue(); expect(class_exists(\Yajra\DataTables\HtmlServiceProvider::class))->toBeTrue(); expect(class_exists(\Yajra\DataTables\FractalServiceProvider::class))->toBeTrue(); expect(class_exists(\Yajra\DataTables\ButtonsServiceProvider::class))->toBeTrue(); expect(class_exists(\Yajra\DataTables\ExportServiceProvider::class))->toBeTrue(); }); laravel-datatables/tests/Pest.php 0000644 00000003013 15060167532 0013064 0 ustar 00 <?php /* |-------------------------------------------------------------------------- | Test Case |-------------------------------------------------------------------------- | | The closure you provide to your test functions is always bound to a specific PHPUnit test | case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may | need to change it using the "uses()" function to bind a different classes or traits. | */ use Yajra\DataTables\Installer\Tests\TestCase; uses(TestCase::class)->in('Feature'); /* |-------------------------------------------------------------------------- | Expectations |-------------------------------------------------------------------------- | | When you're writing tests, you often need to check that values meet certain conditions. The | "expect()" function gives you access to a set of "expectations" methods that you can use | to assert different things. Of course, you may extend the Expectation API at any time. | */ expect()->extend('toBeOne', function () { return $this->toBe(1); }); /* |-------------------------------------------------------------------------- | Functions |-------------------------------------------------------------------------- | | While Pest is very powerful out-of-the-box, you may have some testing code specific to your | project that you don't want to repeat in every file. Here you can also expose helpers as | global functions to help you to reduce the number of lines of code in your test files. | */ function something() { // .. } laravel-datatables/tests/TestCase.php 0000644 00000000651 15060167532 0013671 0 ustar 00 <?php namespace Yajra\DataTables\Installer\Tests; use Illuminate\Foundation\Testing\LazilyRefreshDatabase; use Orchestra\Testbench\TestCase as BaseTestCase; use Yajra\DataTables\ButtonsServiceProvider; abstract class TestCase extends BaseTestCase { use LazilyRefreshDatabase; protected function getPackageProviders($app): array { return [ ButtonsServiceProvider::class, ]; } } laravel-datatables/phpstan.neon.dist 0000644 00000000410 15060167532 0013574 0 ustar 00 includes: - ./vendor/larastan/larastan/extension.neon parameters: paths: - src level: max ignoreErrors: - '#Unsafe usage of new static\(\).#' excludePaths: - src/helper.php checkMissingIterableValueType: false laravel-datatables/src/.gitkeep 0000644 00000000000 15060167532 0012507 0 ustar 00 laravel-datatables/LICENSE.md 0000644 00000002117 15060167532 0011706 0 ustar 00 (The MIT License) Copyright (c) 2013-2017 Arjay Angeles <aqangeles@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. laravel-datatables/phpunit.xml.dist 0000644 00000001001 15060167532 0013444 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false"> <testsuites> <testsuite name="Package Test Suite"> <directory suffix="Test.php">./tests/</directory> </testsuite> </testsuites> </phpunit> laravel-datatables/rector.php 0000644 00000001070 15060167532 0012306 0 ustar 00 <?php declare(strict_types=1); use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; use Rector\Config\RectorConfig; use Rector\Set\ValueObject\LevelSetList; return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths([ __DIR__.'/config', __DIR__.'/database', __DIR__.'/src', ]); // register a single rule $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); // define sets of rules $rectorConfig->sets([ LevelSetList::UP_TO_PHP_80, ]); }; laravel-datatables/CHANGELOG.md 0000644 00000000522 15060167532 0012111 0 ustar 00 # Laravel DataTables Complete Package ## Change Log ### v11.0.0 - 2024-03-16 - Add Laravel 11 support ### v10.1.0 - 2023-02-20 - Install export package by default. ### v10.0.0 - 2023-02-07 - Add Laravel 10 specific support ### v9.0.0 - 2022-05-08 - Add Laravel 9 specific support - Match package major version with the framework laravel-datatables/composer.json 0000644 00000002776 15060167532 0013037 0 ustar 00 { "name": "yajra/laravel-datatables", "description": "Laravel DataTables Complete Package.", "keywords": [ "laravel", "datatables", "jquery" ], "license": "MIT", "authors": [ { "name": "Arjay Angeles", "email": "aqangeles@gmail.com" } ], "require": { "php": "^8.2", "yajra/laravel-datatables-buttons": "^11", "yajra/laravel-datatables-editor": "^11", "yajra/laravel-datatables-export": "^11", "yajra/laravel-datatables-fractal": "^11", "yajra/laravel-datatables-html": "^11", "yajra/laravel-datatables-oracle": "^11" }, "require-dev": { "larastan/larastan": "^2.9.1", "orchestra/testbench": "^9", "laravel/pint": "^1.14", "rector/rector": "^1.0" }, "autoload-dev": { "psr-4": { "Yajra\\DataTables\\Installer\\Tests\\": "tests" } }, "extra": { "branch-alias": { "dev-master": "11.x-dev" } }, "config": { "sort-packages": true, "allow-plugins": { "pestphp/pest-plugin": true } }, "scripts": { "test": "./vendor/bin/phpunit", "pint": "./vendor/bin/pint", "rector": "./vendor/bin/rector", "stan": "./vendor/bin/phpstan analyse --memory-limit=2G --ansi --no-progress --no-interaction --configuration=phpstan.neon.dist", "pr": [ "@pint", "@rector", "@stan", "@test" ] }, "minimum-stability": "dev", "prefer-stable": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/yajra" } ] } laravel-datatables/README.md 0000644 00000006202 15060167532 0011560 0 ustar 00 # Laravel DataTables Complete Package [](https://gitter.im/yajra/laravel-datatables?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://www.paypal.me/yajra) [](https://www.patreon.com/bePatron?u=4521203) [](http://laravel.com) [](https://packagist.org/packages/yajra/laravel-datatables-oracle) [](https://github.com/yajra/laravel-datatables/actions/workflows/continuous-integration.yml) [](https://github.com/yajra/laravel-datatables/actions/workflows/static-analysis.yml) [](https://packagist.org/packages/yajra/laravel-datatables-oracle) [](https://packagist.org/packages/yajra/laravel-datatables-oracle) This package is a complete installer of [Laravel DataTables](https://github.com/yajra/laravel-datatables) core & plugins. ## Requirements - [PHP >= 8.2](http://php.net/) - [Laravel 11.x](https://github.com/laravel/framework) - [jQuery DataTables v1.10.x](http://datatables.net/) - [jQuery DataTables Buttons Extension](https://datatables.net/reference/button/) ## Documentations - [Laravel DataTables Documentation](http://yajrabox.com/docs/laravel-datatables) ## Laravel Version Compatibility | Laravel | Package | |:--------------|:--------| | 8.x and below | 1.x | | 9.x | 9.x | | 10.x | 10.x | | 11.x | 11.x | ## Installation `composer require yajra/laravel-datatables:^11` #### Service Providers Update `config/app.php` and register the following providers. > This step is optional if you are using Laravel 5.5. ```php Yajra\DataTables\DataTablesServiceProvider::class, Yajra\DataTables\ButtonsServiceProvider::class, Yajra\DataTables\FractalServiceProvider::class ``` #### Configuration and Assets (Optional) `$ php artisan vendor:publish` And that's it! Start building out some awesome DataTables! ## Contributing Please see [CONTRIBUTING](https://github.com/yajra/laravel-datatables/blob/master/.github/CONTRIBUTING.md) for details. ## Security If you discover any security related issues, please email [aqangeles@gmail.com](mailto:aqangeles@gmail.com) instead of using the issue tracker. ## Credits - [Arjay Angeles](https://github.com/yajra) - [All Contributors](https://github.com/yajra/laravel-datatables/graphs/contributors) ## License The MIT License (MIT). Please see [License File](https://github.com/yajra/laravel-datatables/blob/master/LICENSE.md) for more information. laravel-datatables-html/src/resources/views/script.blade.php 0000644 00000000507 15060167532 0020266 0 ustar 00 $(function(){window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}=window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}||{};window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}["%1$s"]=$("#%1$s").DataTable(%2$s);}); @foreach ($scripts as $script) @include($script) @endforeach laravel-datatables-html/src/resources/views/editor.blade.php 0000644 00000001523 15060167532 0020247 0 ustar 00 $(function(){ window.{{ config('datatables-html.namespace', 'LaravelDataTables') }} = window.{{ config('datatables-html.namespace', 'LaravelDataTables') }} || {}; $.ajaxSetup({headers: {'X-CSRF-TOKEN': '{{csrf_token()}}'}}); @foreach($editors as $editor) var {{$editor->instance}} = window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}["%1$s-{{$editor->instance}}"] = new $.fn.dataTable.Editor({!! $editor->toJson() !!}); {!! $editor->scripts !!} @foreach ((array) $editor->events as $event) {{$editor->instance}}.on('{!! $event['event'] !!}', {!! $event['script'] !!}); @endforeach @endforeach window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}["%1$s"] = $("#%1$s").DataTable(%2$s); }); @foreach ($scripts as $script) @include($script) @endforeach laravel-datatables-html/src/resources/views/function.blade.php 0000644 00000001504 15060167532 0020605 0 ustar 00 window.dtx = window.dtx || {}; window.dtx["%1$s"] = function(opts) { window.{{ config('datatables-html.namespace', 'LaravelDataTables') }} = window.{{ config('datatables-html.namespace', 'LaravelDataTables') }} || {}; @if(isset($editors)) @foreach($editors as $editor) var {{$editor->instance}} = window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}["%1$s-{{$editor->instance}}"] = new $.fn.dataTable.Editor({!! $editor->toJson() !!}); {!! $editor->scripts !!} @foreach ((array) $editor->events as $event) {{$editor->instance}}.on('{!! $event['event'] !!}', {!! $event['script'] !!}); @endforeach @endforeach @endif return window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}["%1$s"] = $("#%1$s").DataTable($.extend(%2$s, opts)); } laravel-datatables-html/src/resources/views/options.blade.php 0000644 00000000754 15060167532 0020461 0 ustar 00 window.{{ config('datatables-html.namespace', 'LaravelDataTables') }} = window.{{ config('datatables-html.namespace', 'LaravelDataTables') }} || {}; window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}.options = %2$s window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}.editors = []; @foreach($editors as $editor) window.{{ config('datatables-html.namespace', 'LaravelDataTables') }}.editors["{{$editor->instance}}"] = {!! $editor->toJson() !!} @endforeach laravel-datatables-html/src/resources/views/functions/batch_remove.blade.php 0000644 00000000724 15060167532 0023431 0 ustar 00 $(function(){ @foreach($editors as $editor) {{ config('datatables-html.namespace', 'LaravelDataTables') }}["%1$s-{{$editor->instance}}"].on('preSubmit', function(e, data, action) { if (action !== 'remove') return; for (let row_id of Object.keys(data.data)) { data.data[row_id] = { DT_RowId: data.data[row_id].DT_RowId }; } }); @endforeach }); laravel-datatables-html/src/resources/views/scout.blade.php 0000644 00000001543 15060167532 0020120 0 ustar 00 $(function(){ $('#%1$s').on('xhr.dt', function (e, settings, json, xhr) { if (json == null || !('disableOrdering' in json)) return; let table = {{ config('datatables-html.namespace', 'LaravelDataTables') }}[$(this).attr('id')]; if (json.disableOrdering) { table.settings()[0].aoColumns.forEach(function(column) { column.bSortable = false; $(column.nTh).removeClass('sorting_asc sorting_desc sorting').addClass('sorting_disabled'); }); } else { let changed = false; table.settings()[0].aoColumns.forEach(function(column) { if (column.bSortable) return; column.bSortable = true; changed = true; }); if (changed) { table.draw(); } } }); }); laravel-datatables-html/src/resources/config/config.php 0000644 00000000765 15060167532 0017277 0 ustar 00 <?php return [ /* * DataTables JavaScript global namespace. */ 'namespace' => 'LaravelDataTables', /* * Default table attributes when generating the table. */ 'table' => [ 'class' => 'table', 'id' => 'dataTableBuilder', ], /* * Html builder script template. */ 'script' => 'datatables::script', /* * Html builder script template for DataTables Editor integration. */ 'editor' => 'datatables::editor', ]; laravel-datatables-html/src/Html/ColumnDefinitions.php 0000644 00000000174 15060167532 0017102 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Illuminate\Support\Collection; class ColumnDefinitions extends Collection { } laravel-datatables-html/src/Html/Editor/Editor.php 0000644 00000015734 15060167532 0016135 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor; use Illuminate\Support\Arr; use Illuminate\Support\Fluent; use Yajra\DataTables\Html\Editor\Fields\Field; use Yajra\DataTables\Html\HasAuthorizations; use Yajra\DataTables\Utilities\Helper; /** * @property string $instance * @property string|null $table * @property string|array|null $ajax * @property array $fields * @property string|null $template * @property string $idSrc * @property string $display * @property string $scripts * @property array $formOptions */ class Editor extends Fluent { use HasAuthorizations; use HasEvents; final public const DISPLAY_LIGHTBOX = 'lightbox'; final public const DISPLAY_ENVELOPE = 'envelope'; final public const DISPLAY_BOOTSTRAP = 'bootstrap'; final public const DISPLAY_FOUNDATION = 'foundation'; final public const DISPLAY_JQUERYUI = 'jqueryui'; public array $events = []; /** * Editor constructor. * * @param string|array $instance */ public function __construct($instance = 'editor') { $attributes = []; $attributes['instance'] = $instance; parent::__construct($attributes); } /** * Make new Editor instance. */ public static function make(array|string $instance = 'editor'): static { if (is_array($instance)) { $instance = $instance['editor'] ?? 'editor'; } return new static($instance); } /** * Append raw scripts. * * @return $this */ public function scripts(string $scripts): static { $this->attributes['scripts'] = $scripts; return $this; } /** * Set Editor's variable name / instance. * * @return $this */ public function instance(string $instance): static { $this->attributes['instance'] = $instance; return $this; } /** * Set Editor's ajax parameter. * * @return $this * * @see https://editor.datatables.net/reference/option/ajax */ public function ajax(array|string $ajax): static { $this->attributes['ajax'] = $ajax; return $this; } /** * Set Editor's table source. * * @return $this * * @see https://editor.datatables.net/reference/option/table */ public function table(string $table): static { $this->attributes['table'] = $table; return $this; } /** * Set Editor's idSrc option. * * @return $this * * @see https://editor.datatables.net/reference/option/idSrc */ public function idSrc(string $idSrc = 'DT_RowId'): static { $this->attributes['idSrc'] = $idSrc; return $this; } /** * Set Editor's display option. * * @return $this * * @see https://editor.datatables.net/reference/option/display */ public function display(string $display): static { $this->attributes['display'] = $display; return $this; } /** * Set Editor's fields. * * @return $this * * @see https://editor.datatables.net/reference/option/fields */ public function fields(array $fields): static { $this->attributes['fields'] = $fields; return $this; } /** * Set Editor's bubble formOptions. * * @return $this * * @see https://editor.datatables.net/reference/option/formOptions.bubble */ public function formOptionsBubble(array|FormOptions $formOptions): static { return $this->formOptions(['bubble' => Helper::castToArray($formOptions)]); } /** * Set Editor's formOptions. * * @return $this * * @see https://editor.datatables.net/reference/option/formOptions * @see https://editor.datatables.net/reference/type/form-options */ public function formOptions(array $formOptions): static { $this->attributes['formOptions'] = $formOptions; return $this; } /** * Set Editor's inline formOptions. * * @return $this * * @see https://editor.datatables.net/reference/option/formOptions.inline */ public function formOptionsInline(array|FormOptions $formOptions): static { return $this->formOptions(['inline' => Helper::castToArray($formOptions)]); } /** * Set Editor's main formOptions. * * @return $this * * @see https://editor.datatables.net/reference/option/formOptions.main */ public function formOptionsMain(array|FormOptions $formOptions): static { return $this->formOptions(['main' => Helper::castToArray($formOptions)]); } /** * Set Editor's language. * * @return $this * * @see https://editor.datatables.net/reference/option/i18n */ public function language(array $language): static { $this->attributes['i18n'] = $language; return $this; } /** * Set Editor's template. * * @return $this * * @see https://editor.datatables.net/reference/option/template */ public function template(string $template): static { $this->attributes['template'] = $template; return $this; } /** * Convert the fluent instance to an array. */ public function toArray(): array { if (! $this->isAuthorized()) { return []; } $array = parent::toArray(); unset($array['events']); foreach ((array) Arr::get($array, 'fields', []) as $key => &$field) { if ($field instanceof Field) { Arr::set($array['fields'], $key, $field->toArray()); } } return $array; } /** * Convert the fluent instance to JSON. * * @param int $options */ public function toJson($options = 0): string { $parameters = $this->jsonSerialize(); unset($parameters['events']); return Helper::toJsonScript($parameters, $options); } /** * Hide fields on create action. * * @return $this */ public function hiddenOnCreate(array $fields): static { return $this->hiddenOn('create', $fields); } /** * Hide fields on specific action. * * @return $this */ public function hiddenOn(string $action, array $fields): static { $script = 'function(e, mode, action) {'; $script .= "if (action === '$action') {"; foreach ($fields as $field) { $script .= "this.hide('$field');"; } $script .= '} else {'; foreach ($fields as $field) { $script .= "this.show('$field');"; } $script .= '}'; $script .= 'return true;'; $script .= '}'; $this->onPreOpen($script); return $this; } /** * Hide fields on edit action. * * @return $this */ public function hiddenOnEdit(array $fields): static { return $this->hiddenOn('edit', $fields); } } laravel-datatables-html/src/Html/Editor/Fields/Select.php 0000644 00000003047 15060167532 0017326 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; /** * @see https://editor.datatables.net/reference/field/select */ class Select extends Field { protected string $type = 'select'; /** * Set field multiple value. * * @return $this */ public function multiple(bool $value = true): static { $this->attributes['multiple'] = $value; return $this; } /** * Set field optionsPair value. * * @return $this */ public function optionsPair(array|string $label = 'label', string $value = 'value'): static { if (is_array($label)) { $this->attributes['optionsPair'] = $label; } else { $this->attributes['optionsPair'] = [ 'label' => $label, 'value' => $value, ]; } return $this; } /** * Set field placeholder value. * * @return $this */ public function placeholder(string $value): static { $this->attributes['placeholder'] = $value; return $this; } /** * Set field placeholderDisabled value. * * @return $this */ public function placeholderDisabled(bool $value): static { $this->attributes['placeholderDisabled'] = $value; return $this; } /** * Set field placeholderValue value. * * @return $this */ public function placeholderValue(string $value): static { $this->attributes['placeholderValue'] = $value; return $this; } } laravel-datatables-html/src/Html/Editor/Fields/BelongsTo.php 0000644 00000001345 15060167532 0020002 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Str; class BelongsTo extends Select { /** * @param class-string<\Illuminate\Database\Eloquent\Model>|Builder $class */ public static function model(Builder|string $class, string $text, string $id = 'id', ?string $foreign = null): static { if ($class instanceof Builder) { $table = $class->getModel()->getTable(); } else { $table = (new $class)->getTable(); } $table = Str::singular($table); $foreign ??= $table.'_id'; return self::make($foreign, Str::title($table)) ->modelOptions($class, $text, $id); } } laravel-datatables-html/src/Html/Editor/Fields/Password.php 0000644 00000000201 15060167532 0017676 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class Password extends Field { protected string $type = 'password'; } laravel-datatables-html/src/Html/Editor/Fields/Radio.php 0000644 00000000173 15060167532 0017142 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class Radio extends Field { protected string $type = 'radio'; } laravel-datatables-html/src/Html/Editor/Fields/Boolean.php 0000644 00000000550 15060167532 0017462 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class Boolean extends Checkbox { /** * Make a new instance of a field. */ public static function make(array|string $name, string $label = ''): static { return parent::make($name, $label)->separator(',')->options( Options::make()->append('', 1) ); } } laravel-datatables-html/src/Html/Editor/Fields/Checkbox.php 0000644 00000000201 15060167532 0017622 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class Checkbox extends Field { protected string $type = 'checkbox'; } laravel-datatables-html/src/Html/Editor/Fields/Text.php 0000644 00000000124 15060167532 0017024 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class Text extends Field { } laravel-datatables-html/src/Html/Editor/Fields/Select2.php 0000644 00000006047 15060167532 0017413 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; /** * @see https://editor.datatables.net/plug-ins/field-type/editor.select2 */ class Select2 extends Select { protected string $type = 'select2'; /** * @return $this */ public function allowClear(bool $state = true): static { return $this->opts(['allowClear' => $state]); } /** * @return $this */ public function placeholder(string $value): static { return $this->optsPlaceholder($value); } /** * @return $this */ public function optsPlaceholder(string $text = '', string $id = ''): static { return $this->opts([ 'placeholder' => [ 'id' => $id, 'text' => $text, ], ]); } public function multiple(bool $value = true): static { return $this->opts(['multiple' => $value]); } /** * Set select2 ajax option. * * @return $this */ public function ajax(array|string $value): static { $ajax = $this->opts['ajax'] ?? []; if (is_array($value)) { return $this->opts(['ajax' => array_merge($ajax, $value)]); } return $this->opts(['ajax' => array_merge($ajax, ['url' => $value])]); } /** * Set select2 ajax url option. * * @return $this */ public function ajaxUrl(string $value): static { return $this->ajax(['url' => $value]); } /** * Set select2 ajaxDelay option. * * @return $this */ public function ajaxDelay(int $value = 250): static { return $this->ajax(['delay' => $value]); } /** * Set select2 ajax data option. * * @return $this */ public function ajaxData(array|string $data): static { if (is_array($data)) { $script = 'function(params) {'; foreach ($data as $key => $value) { $value = json_encode($value, JSON_THROW_ON_ERROR); $script .= " params.$key = $value; "; } $script .= 'return params; }'; $data = $script; } return $this->ajax(['data' => $data]); } /** * Set select2 ajax processResults option to process a paginated results. * * @return $this */ public function processPaginatedResults(string $display = 'text', string $id = 'id', string $wrap = 'results'): static { $script = 'function(data, params) { '; $script .= 'params.page = params.page || 1; '; $script .= "data.$wrap.map(function(e) { e.text = e.$display; e.id = e.$id; return e; }); "; $script .= "return { results: data.$wrap, pagination: { more: data.meta.current_page < data.meta.last_page } };"; $script .= '}'; return $this->processResults($script); } /** * Set select2 ajax processResults option. * * @return $this */ public function processResults(string $value): static { return $this->ajax(['processResults' => $value]); } } laravel-datatables-html/src/Html/Editor/Fields/Hidden.php 0000644 00000000175 15060167532 0017301 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class Hidden extends Field { protected string $type = 'hidden'; } laravel-datatables-html/src/Html/Editor/Fields/Options.php 0000644 00000004675 15060167532 0017552 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; use Closure; use Illuminate\Contracts\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Query\Builder; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; /** * @template TKey of array-key * @template TValue */ class Options extends Collection { /** * Return a Yes/No options. */ public static function yesNo(): static { $data = [ ['label' => __('Yes'), 'value' => 1], ['label' => __('No'), 'value' => 0], ]; return new static($data); } /** * Get options from a model. * * @param class-string<Model>|\Illuminate\Database\Eloquent\Builder $model */ public static function model(string|EloquentBuilder $model, string $value, string $key = 'id'): Collection { if (! $model instanceof EloquentBuilder) { $model = $model::query(); } return $model->get()->map(fn ($model) => [ 'value' => $model->{$key}, 'label' => $model->{$value}, ]); } /** * Get options from a table. */ public static function table( Closure|Builder|string $table, string $value, string $key = 'id', ?Closure $callback = null, ?string $connection = null ): Collection { $query = DB::connection($connection) ->table($table) ->select("$value as label", "$key as value"); if (is_callable($callback)) { $callback($query); } return $query->get()->map(fn ($row) => (array) $row); } /** * Return a True/False options. */ public static function trueFalse(): static { $data = [ ['label' => __('True'), 'value' => 1], ['label' => __('False'), 'value' => 0], ]; return new static($data); } /** * Push an item onto the end of the collection. */ public function append(string $value, int|string $key): static { return $this->push(['label' => $value, 'value' => $key]); } /** * Push an item onto the beginning of the collection. * * @param TValue $value * @param TKey $key */ public function prepend($value, $key = null): static { $data = ['label' => $value, 'value' => $key]; return parent::prepend($data); } } laravel-datatables-html/src/Html/Editor/Fields/Field.php 0000644 00000020604 15060167532 0017130 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; use Closure; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Support\Fluent; use Illuminate\Support\Str; use Illuminate\Support\Traits\Macroable; use Yajra\DataTables\Html\HasAuthorizations; /** * @see https://editor.datatables.net/reference/option/ */ class Field extends Fluent { use HasAuthorizations; use Macroable; /** * Field type. */ protected string $type = 'text'; /** * Password constructor. * * @param array $attributes */ public function __construct($attributes = []) { $attributes['type'] ??= $this->type; parent::__construct($attributes); } /** * Make a new instance of a field. */ public static function make(array|string $name, string $label = ''): static { if (is_array($name)) { return new static($name); } $data = [ 'name' => $name, 'label' => $label ?: Str::title(str_replace('_', ' ', $name)), ]; return new static($data); } /** * @return $this * * @see https://editor.datatables.net/reference/option/fields.label */ public function label(string $label): static { $this->attributes['label'] = $label; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/option/fields.name */ public function name(string $name): static { $this->attributes['name'] = $name; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/option/fields.data */ public function data(string $data): static { $this->attributes['data'] = $data; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/option/fields.type */ public function type(string $type): static { $this->attributes['type'] = $type; $this->type = $type; return $this; } /** * Get options from a model. * * @param \Illuminate\Database\Eloquent\Builder|class-string<\Illuminate\Database\Eloquent\Model> $model * @return $this */ public function modelOptions(Builder|string $model, string $value, string $key = 'id'): static { return $this->options( Options::model($model, $value, $key) ); } /** * Get options from a Enum::cases(). * * @return $this */ public function enumOptions(array $cases): static { $options = []; foreach ($cases as $case) { $options[] = [ 'value' => $case->value, 'label' => $case->value, ]; } return $this->options($options); } /** * Set select options. * * @return $this */ public function options(array|Arrayable $options): static { if ($options instanceof Arrayable) { $options = $options->toArray(); } $this->attributes['options'] = $options; return $this; } /** * Get options from a table. * * @return $this */ public function tableOptions( QueryBuilder|Closure|string $table, string $value, string $key = 'id', ?Closure $whereCallback = null, ?string $connection = null ): static { return $this->options( Options::table($table, $value, $key, $whereCallback, $connection) ); } /** * Set checkbox separator. * * @return $this */ public function separator(string $separator = ','): static { $this->attributes['separator'] = $separator; return $this; } /** * Set dateTime format. * * @return $this * * @see https://editor.datatables.net/reference/field/datetime */ public function format(string $format): static { $this->attributes['format'] = $format; return $this; } /** * Set field default value. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.def */ public function default(float|bool|int|string|array $value): static { $this->attributes['def'] = $value; return $this; } /** * Set field message value. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.message */ public function message(string $value): static { $this->attributes['message'] = $value; return $this; } /** * Set field fieldInfo value. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.fieldInfo */ public function fieldInfo(string $value): static { $this->attributes['fieldInfo'] = $value; return $this; } /** * Set field labelInfo value. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.labelInfo */ public function labelInfo(string $value): static { $this->attributes['labelInfo'] = $value; return $this; } /** * Set field entityDecode value. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.entityDecode */ public function entityDecode(bool $value): static { $this->attributes['entityDecode'] = $value; return $this; } /** * Set field multiEditable value. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.multiEditable */ public function multiEditable(bool $value): static { $this->attributes['multiEditable'] = $value; return $this; } /** * Set field id value. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.id */ public function id(string $value): static { $this->attributes['id'] = $value; return $this; } /** * Set field submit value. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.submit */ public function submit(bool $value): static { $this->attributes['submit'] = $value; return $this; } /** * Set field compare value. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.compare */ public function compare(bool $value): static { $this->attributes['compare'] = $value; return $this; } /** * Set field opts value. * * @return $this * * @see https://datatables.net/forums/discussion/comment/156581/#Comment_156581 */ public function opts(array $value): static { if (! isset($this->attributes['opts'])) { $this->attributes['opts'] = $value; } else { $this->attributes['opts'] = array_merge((array) $this->attributes['opts'], $value); } return $this; } /** * Set field element html attributes. * * @return $this * * @see https://datatables.net/forums/discussion/comment/156581/#Comment_156581 */ public function attr(string $attribute, int|bool|string $value): static { if (! isset($this->attributes['attr'])) { $this->attributes['attr'] = []; } $attributes = (array) $this->attributes['attr']; $attributes[$attribute] = $value; $this->attributes['attr'] = $attributes; return $this; } public function getType(): string { return $this->type; } /** * Replace null values with the field's default on edit. * * @return $this * * @see https://editor.datatables.net/reference/option/fields.nullDefault */ public function nullDefault(bool $value = true): static { $this->attributes['nullDefault'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/option/fields.className */ public function className(string $className): static { $this->attributes['className'] = $className; return $this; } } laravel-datatables-html/src/Html/Editor/Fields/Number.php 0000644 00000000366 15060167532 0017340 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class Number extends Field { public static function make(array|string $name, string $label = ''): static { return parent::make($name, $label)->attr('type', 'number'); } } laravel-datatables-html/src/Html/Editor/Fields/TextArea.php 0000644 00000000515 15060167532 0017621 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class TextArea extends Field { protected string $type = 'textarea'; public function rows(int $value): static { return $this->attr('rows', $value); } public function cols(int $value): static { return $this->attr('cols', $value); } } laravel-datatables-html/src/Html/Editor/Fields/Image.php 0000644 00000000746 15060167532 0017134 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; /** * @see https://editor.datatables.net/reference/field/upload * @see https://editor.datatables.net/examples/advanced/upload.html * @see https://editor.datatables.net/examples/advanced/upload-many.html */ class Image extends File { protected string $type = 'upload'; public static function make(array|string $name, string $label = ''): static { return parent::make($name, $label)->displayImage(); } } laravel-datatables-html/src/Html/Editor/Fields/Date.php 0000644 00000000454 15060167532 0016763 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class Date extends DateTime { /** * Make a new instance of a field. */ public static function make(array|string $name, string $label = ''): static { return parent::make($name, $label)->format('YYYY-MM-DD'); } } laravel-datatables-html/src/Html/Editor/Fields/ReadOnlyField.php 0000644 00000000206 15060167532 0020562 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class ReadOnlyField extends Field { protected string $type = 'readonly'; } laravel-datatables-html/src/Html/Editor/Fields/Time.php 0000644 00000000767 15060167532 0017013 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class Time extends DateTime { /** * Make a new instance of a field. */ public static function make(array|string $name, string $label = ''): static { $field = parent::make($name, $label); return $field->format('hh:mm a'); } /** * Set format to military time (24 hrs). * * @return $this */ public function military(): static { return $this->format('HH:mm'); } } laravel-datatables-html/src/Html/Editor/Fields/DateTime.php 0000644 00000010763 15060167532 0017606 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; class DateTime extends Field { protected string $type = 'datetime'; /** * Make a new instance of a field. */ public static function make(array|string $name, string $label = ''): static { return parent::make($name, $label)->format('YYYY-MM-DD hh:mm a'); } /** * Set format to military time (24 hrs). * * @return $this */ public function military(): static { return $this->format('YYYY-MM-DD HH:mm'); } /** * @return $this * * @see https://editor.datatables.net/examples/dates/options-min-max.html */ public function minDate(\DateTime $dateTime, string $format = 'Y-m-d'): static { return $this->opts(['minDate' => "new Date('".$dateTime->format($format)."')"]); } /** * @return $this * * @see https://editor.datatables.net/examples/dates/options-min-max.html */ public function maxDate(\DateTime $dateTime, string $format = 'Y-m-d'): static { return $this->opts(['maxDate' => "new Date('".$dateTime->format($format)."')"]); } /** * @return $this * * @see https://editor.datatables.net/examples/dates/options-week-numbers.html */ public function showWeekNumber(bool $state = true): static { return $this->opts(['showWeekNumber' => $state]); } /** * @return $this * * @see https://editor.datatables.net/examples/dates/options-disable-days.html */ public function disableDays(array $days): static { return $this->opts(['disableDays' => $days]); } /** * @return $this * * @see https://editor.datatables.net/examples/dates/time-increment.html */ public function minutesIncrement(int $minutes): static { return $this->opts(['minutesIncrement' => $minutes]); } /** * @return $this * * @see https://editor.datatables.net/examples/dates/time-increment.html */ public function secondsIncrement(int $seconds): static { return $this->opts(['secondsIncrement' => $seconds]); } /** * @return $this * * @see https://editor.datatables.net/examples/dates/datetime.html */ public function hoursAvailable(array $hours): static { return $this->opts(['hoursAvailable' => $hours]); } /** * @return $this * * @see https://editor.datatables.net/examples/dates/datetime.html */ public function minutesAvailable(array $minutes): static { return $this->opts(['minutesAvailable' => $minutes]); } /** * The format of the date string loaded from the server for the field's * value and also for sending to the server on form submission. * The formatting options are defined by Moment.js. * * @return $this * * @see https://editor.datatables.net/reference/field/datetime#Options * @see https://momentjs.com/docs/#/displaying/format/ */ public function wireFormat(string $format = 'YYYY-MM-DDTHH:mm:ss.000000Z'): static { $this->attributes['wireFormat'] = $format; return $this; } /** * Allow (default), or disallow, the end user to type into the date / time input element. * If disallowed, they must use the calendar picker to enter data. This can be useful * if you are using a more complex date format and wish to disallow the user from * potentially making typing mistakes, although note that it does also disallow * pasting of data. * * @return $this * * @see https://editor.datatables.net/reference/field/datetime#Options */ public function keyInput(bool $state = true): static { $this->attributes['keyInput'] = $state; return $this; } /** * The format of the date string that will be shown to the end user in the input element. * The formatting options are defined by Moment.js. If a format is used that is not * ISO8061 (i.e. YYYY-MM-DD) and Moment.js has not been included, Editor will * throw an error stating that Moment.js must be included for custom * formatting to be used. * * @return $this * * @see https://editor.datatables.net/reference/field/datetime#Options * @see https://momentjs.com/docs/#/displaying/format/ */ public function displayFormat(string $format = 'YYYY-MM-DD hh:mm a'): static { $this->attributes['displayFormat'] = $format; return $this; } } laravel-datatables-html/src/Html/Editor/Fields/File.php 0000644 00000007040 15060167532 0016763 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor\Fields; /** * @see https://editor.datatables.net/reference/field/upload * @see https://editor.datatables.net/examples/advanced/upload.html * @see https://editor.datatables.net/examples/advanced/upload-many.html */ class File extends Field { protected string $type = 'upload'; /** * Editor instance variable name. */ protected string $editor = 'editor'; public static function make(array|string $name, string $label = ''): static { $field = parent::make($name, $label); return $field->displayFile()->clearText()->noImageText(); } /** * @return $this */ public function ajax(string $value): static { $this->attributes['ajax'] = $value; return $this; } /** * @return $this */ public function ajaxData(string $value): static { $this->attributes['ajaxData'] = $value; return $this; } /** * @return $this */ public function dragDrop(bool $value = true): static { $this->attributes['dragDrop'] = $value; return $this; } /** * @return $this */ public function dragDropText(string $value): static { $this->attributes['dragDropText'] = $value; return $this; } /** * @return $this */ public function fileReadText(string $value): static { $this->attributes['fileReadText'] = $value; return $this; } /** * @return $this */ public function noFileText(string $value): static { $this->attributes['noFileText'] = $value; return $this; } /** * @return $this */ public function processingText(string $value): static { $this->attributes['processingText'] = $value; return $this; } /** * @return $this */ public function uploadText(string $value): static { $this->attributes['uploadText'] = $value; return $this; } /** * Set editor instance for file upload. * * @return $this */ public function editor(string $editor): static { $this->editor = $editor; return $this; } /** * Display image upon upload. * * @return $this */ public function displayImage(): static { // TODO: Use Laravel filesystem instead of hard coded storage path return $this->display(<<<'SCRIPT' function (file_id) { return file_id ? '<img src="storage/' + file_id + '" alt=""/>' : null; } SCRIPT ); } /** * @return $this */ public function display(string $value): static { $this->attributes['display'] = $value; return $this; } /** * Display the file path. * * @return $this */ public function displayFile(): static { return $this->display('function (file_id) { return file_id; }'); } /** * @return $this */ public function clearText(string $value = 'Clear'): static { $this->attributes['clearText'] = $value; return $this; } /** * @return $this */ public function noImageText(string $value = 'No image'): static { $this->attributes['noImageText'] = $value; return $this; } /** * @return $this */ public function multiple(bool $state = true): static { if ($state) { $this->type('uploadMany'); } return $this; } } laravel-datatables-html/src/Html/Editor/HasEvents.php 0000644 00000004555 15060167532 0016606 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor; use Illuminate\Support\Str; /** * @method $this onClose($script) * @method $this onClosed($script) * @method $this onCreate($script) * @method $this onDisplayOrder($script) * @method $this onEdit($script) * @method $this onInitCreate($script) * @method $this onInitEdit($script) * @method $this onInitEditor($script) * @method $this onInitRemove($script) * @method $this onInitSubmit($script) * @method $this onOpen($script) * @method $this onOpened($script) * @method $this onPostCreate($script) * @method $this onPostEdit($script) * @method $this onPostRemove($script) * @method $this onPostSubmit($script) * @method $this onPostUpload($script) * @method $this onPreBlur($script) * @method $this onPreBlurCancelled($script) * @method $this onPreClose($script) * @method $this onPreCreate($script) * @method $this onPreEdit($script) * @method $this onPreOpen($script) * @method $this onPreOpenCancelled($script) * @method $this onPreRemove($script) * @method $this onPreSubmit($script) * @method $this onPreSubmitCancelled($script) * @method $this onPreUpload($script) * @method $this onPreUploadCancelled($script) * @method $this onProcessing($script) * @method $this onRemove($script) * @method $this onSetData($script) * @method $this onSubmitComplete($script) * @method $this onSubmitError($script) * @method $this onSubmitSuccess($script) * @method $this onSubmitUnsuccessful($script) * @method $this onUploadXhrError($script) * @method $this onUploadXhrSuccess($script) */ trait HasEvents { /** * Magic method handler for editor events. * * @param string $method * @param array{0: string} $parameters * @return $this */ public function __call($method, $parameters) { if (Str::startsWith($method, 'on')) { $event = Str::camel(substr($method, 2, strlen($method) - 2)); return $this->on($event, $parameters[0]); } return parent::__call($method, $parameters); } /** * Add Editor event listener scripts. * * @return $this * * @see https://editor.datatables.net/reference/event */ public function on(string $event, mixed $script): static { $this->events[] = [ 'event' => $event, 'script' => value($script), ]; return $this; } } laravel-datatables-html/src/Html/Editor/FormOptions.php 0000644 00000010724 15060167532 0017160 0 ustar 00 <?php namespace Yajra\DataTables\Html\Editor; use Illuminate\Support\Fluent; /** * @see https://editor.datatables.net/reference/type/form-options */ class FormOptions extends Fluent { public static function make(array $attributes = []): static { return new static($attributes); } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#focus */ public function focus(int|string|null $value = null): static { $this->attributes['focus'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#nest */ public function nest(bool $value): static { $this->attributes['nest'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#onBackground */ public function onBackground(string $value = 'blur'): static { $this->attributes['onBackground'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#onBlur */ public function onBlur(string $value = 'close'): static { $this->attributes['onBlur'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#onComplete */ public function onComplete(string $value = 'close'): static { $this->attributes['onComplete'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#onEsc */ public function onEsc(string $value = 'close'): static { $this->attributes['onEsc'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#onFieldError */ public function onFieldError(string $value = 'focus'): static { $this->attributes['onFieldError'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#onReturn */ public function onReturn(string $value = 'submit'): static { $this->attributes['onReturn'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#submit */ public function submit(string $value = 'changed'): static { $this->attributes['submit'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#scope */ public function formScope(string $value = 'row'): static { $this->attributes['scope'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#buttons */ public function buttons(array|string $value): static { $this->attributes['buttons'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#drawType */ public function drawType(string $value = ''): static { $this->attributes['drawType'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#message */ public function message(bool|string $value = ''): static { $this->attributes['message'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#submitTrigger */ public function submitTrigger(int|string $value): static { $this->attributes['submitTrigger'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#submitHtml */ public function submitHtml(string $value): static { $this->attributes['submitHtml'] = $value; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/type/form-options#title */ public function title(bool|string $value): static { $this->attributes['title'] = $value; return $this; } } laravel-datatables-html/src/Html/SearchPane.php 0000644 00000016566 15060167532 0015476 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Closure; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Support\Fluent; use Yajra\DataTables\Html\Editor\Fields\Options; class SearchPane extends Fluent { public function __construct($attributes = []) { parent::__construct(['show' => true] + $attributes); } public static function make(array $options = []): static { return new static($options); } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.cascadePanes */ public function cascadePanes(bool $value = true): static { $this->attributes['cascadePanes'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.clear */ public function clear(bool $value = true): static { $this->attributes['clear'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.columns */ public function columns(array $value = []): static { $this->attributes['columns'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.controls */ public function controls(bool $value = true): static { $this->attributes['controls'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.dtOpts * @see https://datatables.net/reference/option/columns.searchPanes.dtOpts */ public function dtOpts(array $value = []): static { $this->attributes['dtOpts'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.emptyMessage */ public function emptyMessage(string $value): static { $this->attributes['emptyMessage'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.filterChanged */ public function filterChanged(string $value): static { $this->attributes['filterChanged'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.hideCount */ public function hideCount(bool $value = true): static { $this->attributes['hideCount'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.layout */ public function layout(string $value): static { $this->attributes['layout'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.order */ public function order(array $value): static { $this->attributes['order'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.orderable */ public function orderable(bool $value = true): static { $this->attributes['orderable'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.panes */ public function panes(array $value): static { $panes = collect($value)->map(function ($pane) { if ($pane instanceof Arrayable) { return $pane->toArray(); } return $pane; })->toArray(); $this->attributes['panes'] = $panes; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.threshold */ public function threshold(float $value): static { $this->attributes['threshold'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.viewTotal */ public function viewTotal(bool $value = true): static { $this->attributes['viewTotal'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.viewTotal */ public function hideTotal(bool $value = true): static { $this->attributes['viewTotal'] = ! $value; return $this; } /** * Get options from a model. * * @param class-string<\Illuminate\Database\Eloquent\Model>|EloquentBuilder $model */ public function modelOptions(EloquentBuilder|string $model, string $value, string $key = 'id'): SearchPane { return $this->options(Options::model($model, $value, $key)); } /** * @return $this * * @see https://datatables.net/reference/option/columns.searchPanes.options */ public function options(array|Arrayable $value): static { if ($value instanceof Arrayable) { $value = $value->toArray(); } $this->attributes['options'] = $value; return $this; } /** * Get options from a table. * * @return $this */ public function tableOptions( string $table, string $value, string $key = 'id', ?Closure $callback = null, ?string $connection = null ): static { return $this->options(Options::table($table, $value, $key, $callback, $connection)); } /** * @return $this * * @see https://datatables.net/reference/option/columns.searchPanes.className */ public function className(string $value): static { $this->attributes['className'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.panes.header */ public function header(string $value): static { $this->attributes['header'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/columns.searchPanes.show */ public function show(bool $value = true): static { $this->attributes['show'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/columns.searchPanes.name */ public function name(string $value): static { $this->attributes['name'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/columns.searchPanes.orthogonal */ public function orthogonal(array|string $value): static { $this->attributes['orthogonal'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.collapse */ public function collapse(bool $value = true): static { $this->attributes['collapse'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/searchPanes.initCollapsed */ public function initCollapsed(bool $value = false): static { $this->attributes['initCollapsed'] = $value; return $this; } } laravel-datatables-html/src/Html/Column.php 0000644 00000032757 15060167532 0014722 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Illuminate\Support\Arr; use Illuminate\Support\Fluent; use Illuminate\Support\Str; use Yajra\DataTables\Html\Options\Plugins\SearchPanes; /** * @property array|string $data * @property string $name * @property string $title * @property string $titleAttr * @property bool $orderable * @property bool $searchable * @property bool $printable * @property bool $exportable * @property array|string $footer * @property array $attributes * @property string $render * @property string $className * @property string $editField * @property int|array $orderData * @property string $orderDataType * @property string $orderSequence * @property string $cellType * @property string $type * @property string $contentPadding * @property string $createdCell * @property string $exportFormat * * @see https://datatables.net/reference/option/#columns */ class Column extends Fluent { use HasAuthorizations; use SearchPanes; /** * @param array $attributes */ public function __construct($attributes = []) { $attributes['title'] ??= self::titleFormat($attributes['data'] ?? ''); $attributes['orderable'] ??= true; $attributes['searchable'] ??= true; $attributes['exportable'] ??= true; $attributes['printable'] ??= true; $attributes['footer'] ??= ''; $attributes['attributes'] ??= []; // Allow methods override attribute value foreach ($attributes as $attribute => $value) { $method = 'parse'.ucfirst(strtolower($attribute)); if (! is_null($value) && method_exists($this, $method)) { $attributes[$attribute] = $this->$method($value); } } if (! isset($attributes['name']) && isset($attributes['data'])) { $attributes['name'] = $attributes['data']; } parent::__construct($attributes); } /** * Format string to title case. */ public static function titleFormat(string $value): string { return Str::title(str_replace(['.', '_'], ' ', Str::snake($value))); } /** * Set column title. * * @return $this * * @see https://datatables.net/reference/option/columns.title */ public function title(string $value): static { $this->attributes['title'] = $value; return $this; } /** * Create a computed column that is not searchable/orderable. */ public static function computed(string $data, ?string $title = null): Column { if (is_null($title)) { $title = self::titleFormat($data); } return static::make($data)->title($title)->orderable(false)->searchable(false); } /** * Set column searchable flag. * * @return $this * * @see https://datatables.net/reference/option/columns.searchable */ public function searchable(bool $flag = true): static { $this->attributes['searchable'] = $flag; return $this; } /** * Set column orderable flag. * * @return $this * * @see https://datatables.net/reference/option/columns.orderable */ public function orderable(bool $flag = true): static { $this->attributes['orderable'] = $flag; return $this; } /** * Make a new column instance. */ public static function make(array|string $data = [], string $name = ''): static { $attr = $data; if (is_string($data)) { $attr = [ 'data' => $data, 'name' => $name ?: $data, ]; } return new static($attr); } /** * Make a new formatted column instance. */ public static function formatted(string $name): static { $attr = [ 'data' => $name, 'name' => $name, 'title' => self::titleFormat($name), 'render' => 'full.'.$name.'_formatted', ]; return new static($attr); } /** * Create a checkbox column. */ public static function checkbox(string $title = ''): static { return static::make('') ->content('') ->title($title) ->className('select-checkbox') ->orderable(false) ->exportable(false) ->searchable(false); } /** * Set column exportable flag. * * @return $this */ public function exportable(bool $flag = true): static { $this->attributes['exportable'] = $flag; return $this; } /** * Set column class name. * * @return $this * * @see https://datatables.net/reference/option/columns.className */ public function className(string $class): static { $this->attributes['className'] = $class; return $this; } /** * Set column default content. * * @return $this * * @see https://datatables.net/reference/option/columns.defaultContent */ public function content(string $value): static { $this->attributes['defaultContent'] = $value; return $this; } /** * Set column responsive priority. * * @return $this * * @see https://datatables.net/reference/option/columns.responsivePriority */ public function responsivePriority(int|string $value): static { $this->attributes['responsivePriority'] = $value; return $this; } /** * Set column hidden state. * * @return $this * * @see https://datatables.net/reference/option/columns.visible */ public function hidden(): static { return $this->visible(false); } /** * Set column visible flag. * * @return $this * * @see https://datatables.net/reference/option/columns.visible */ public function visible(bool $flag = true): static { $this->attributes['visible'] = $flag; return $this; } /** * Append a class name to field. * * @return $this */ public function addClass(string $class): static { if (! isset($this->attributes['className'])) { $this->attributes['className'] = $class; } else { $this->attributes['className'] .= " $class"; } return $this; } /** * Set column printable flag. * * @return $this */ public function printable(bool $flag = true): static { $this->attributes['printable'] = $flag; return $this; } /** * Set column width value. * * @return $this * * @see https://datatables.net/reference/option/columns.width */ public function width(int|string $value): static { $this->attributes['width'] = $value; return $this; } /** * Set column data option value. * * @return $this * * @see https://datatables.net/reference/option/columns.data * @see https://datatables.net/manual/data/orthogonal-data */ public function data(array|string $value): static { $this->attributes['data'] = $value; return $this; } /** * Set column name option value. * * @return $this * * @see https://datatables.net/reference/option/columns.name */ public function name(string $value): static { $this->attributes['name'] = $value; return $this; } /** * Set column edit field option value. * * @return $this * * @see https://datatables.net/reference/option/columns.editField */ public function editField(array|string $value): static { $this->attributes['editField'] = $value; return $this; } /** * Set column orderData option value. * * @return $this * * @see https://datatables.net/reference/option/columns.orderData */ public function orderData(array|int $value): static { $this->attributes['orderData'] = $value; return $this; } /** * Set column orderDataType option value. * * @return $this * * @see https://datatables.net/reference/option/columns.orderDataType */ public function orderDataType(string $value): static { $this->attributes['orderDataType'] = $value; return $this; } /** * Set column orderSequence option value. * * @return $this * * @see https://datatables.net/reference/option/columns.orderSequence */ public function orderSequence(array $value): static { $this->attributes['orderSequence'] = $value; return $this; } /** * Set column cellType option value. * * @return $this * * @see https://datatables.net/reference/option/columns.cellType */ public function cellType(string $value = 'th'): static { $this->attributes['cellType'] = $value; return $this; } /** * Set column type option value. * * @return $this * * @see https://datatables.net/reference/option/columns.type */ public function type(string $value): static { $this->attributes['type'] = $value; return $this; } /** * Set column contentPadding option value. * * @return $this * * @see https://datatables.net/reference/option/columns.contentPadding */ public function contentPadding(string $value): static { $this->attributes['contentPadding'] = $value; return $this; } /** * Set column createdCell option value. * * @return $this * * @see https://datatables.net/reference/option/columns.createdCell */ public function createdCell(string $value): static { $this->attributes['createdCell'] = $value; return $this; } /** * Use the js renderer "$.fn.dataTable.render.". * * @param int|string|null ...$params * @return $this * * @see https://datatables.net/reference/option/columns.render */ public function renderJs(string $value, ...$params): static { if ($params) { $value .= '('; foreach ($params as $param) { $value .= sprintf("'%s',", $param); } $value = mb_substr($value, 0, -1); $value .= ')'; } $renderer = '$.fn.dataTable.render.'.$value; return $this->render($renderer); } /** * Set column renderer. * * @return $this * * @see https://datatables.net/reference/option/columns.render */ public function render(mixed $value): static { $this->attributes['render'] = $this->parseRender($value); return $this; } /** * Set Callback function to render column for Print + Export * * @return $this */ public function exportRender(callable $callback): static { $this->attributes['exportRender'] = $callback; return $this; } /** * Parse render attribute. */ public function parseRender(mixed $value): ?string { /** @var \Illuminate\Contracts\View\Factory $view */ $view = app('view'); $parameters = []; if (is_array($value)) { $parameters = Arr::except($value, 0); $value = $value[0]; } if (is_callable($value)) { return $value($parameters); } elseif ($this->isBuiltInRenderFunction($value)) { return $value; } elseif (strlen((string) $value) < 256 && $view->exists($value)) { return $view->make($value)->with($parameters)->render(); } return $value ? $this->parseRenderAsString($value) : null; } /** * Check if given key & value is a valid datatables built-in renderer function. */ private function isBuiltInRenderFunction(string $value): bool { if (empty($value)) { return false; } return Str::startsWith(trim($value), ['$.fn.dataTable.render', '[']); } /** * Display render value as is. */ private function parseRenderAsString(string $value): string { return "function(data,type,full,meta){return $value;}"; } /** * Set column renderer with give raw value. * * @return $this * * @see https://datatables.net/reference/option/columns.render */ public function renderRaw(mixed $value): static { $this->attributes['render'] = $value; return $this; } /** * Set column footer. * * @return $this */ public function footer(mixed $value): static { $this->attributes['footer'] = $value; return $this; } /** * Set custom html title instead default label. * * @return $this */ public function titleAttr(mixed $value): static { $this->attributes['titleAttr'] = $value; return $this; } /** * Set excel column format when exporting. * * @return $this * * @see https://github.com/yajra/laravel-datatables-export */ public function exportFormat(string|callable $format): static { $this->attributes['exportFormat'] = $format; return $this; } public function toArray(): array { if (! $this->isAuthorized()) { return []; } return Arr::except($this->attributes, [ 'printable', 'exportable', 'footer', ]); } } laravel-datatables-html/src/Html/Builder.php 0000644 00000015076 15060167532 0015046 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Illuminate\Contracts\Config\Repository; use Illuminate\Contracts\View\Factory; use Illuminate\Support\Collection; use Illuminate\Support\HtmlString; use Illuminate\Support\Traits\Macroable; use Yajra\DataTables\Utilities\Helper; class Builder { use Columns\Action; use Columns\Checkbox; use Columns\Index; use HasEditor; use HasOptions; use HasTable; use Macroable; // Select plugin constants. final public const SELECT_STYLE_API = 'api'; final public const SELECT_STYLE_SINGLE = 'single'; final public const SELECT_STYLE_MULTI = 'multi'; final public const SELECT_STYLE_OS = 'os'; final public const SELECT_STYLE_MULTI_SHIFT = 'multi+shift'; final public const SELECT_ITEMS_ROW = 'row'; final public const SELECT_ITEMS_COLUMN = 'column'; final public const SELECT_ITEMS_CELL = 'cell'; /** * The default type to use for the DataTables javascript. */ protected static string $jsType = 'text/javascript'; /** * @var Collection<int, \Yajra\DataTables\Html\Column> */ public Collection $collection; /** * @var array<string, string|null> */ protected array $tableAttributes = []; protected string $template = ''; protected array $attributes = [ 'serverSide' => true, 'processing' => true, ]; protected string|array $ajax = ''; protected array $additionalScripts = []; public function __construct(public Repository $config, public Factory $view, public HtmlBuilder $html) { /** @var array $defaults */ $defaults = $this->config->get('datatables-html.table', []); $this->collection = new Collection; $this->tableAttributes = $defaults; } /** * Set the default type to module for the DataTables javascript. */ public static function useVite(): void { static::$jsType = 'module'; } /** * Set the default type to text/javascript for the DataTables javascript. */ public static function useWebpack(): void { static::$jsType = 'text/javascript'; } /** * Generate DataTable javascript. */ public function scripts(?string $script = null, array $attributes = []): HtmlString { $script = $script ?: $this->generateScripts(); $attributes = $this->html->attributes( array_merge($attributes, ['type' => $attributes['type'] ?? static::$jsType]) ); return new HtmlString("<script{$attributes}>$script</script>"); } /** * Get generated raw scripts. */ public function generateScripts(): HtmlString { $parameters = $this->generateJson(); return new HtmlString( trim(sprintf($this->template(), $this->getTableAttribute('id'), $parameters)) ); } /** * Get generated json configuration. */ public function generateJson(): string { return $this->parameterize($this->getOptions()); } /** * Generate DataTables js parameters. */ public function parameterize(array $attributes = []): string { $parameters = (new Parameters($attributes))->toArray(); return Helper::toJsonScript($parameters); } /** * Get DataTable options array. */ public function getOptions(): array { return array_merge( $this->attributes, [ 'ajax' => $this->ajax, 'columns' => $this->collection->map(function (Column $column) { $column = $column->toArray(); unset($column['attributes']); return $column; })->toArray(), ] ); } /** * Get javascript template to use. */ protected function template(): string { /** @var view-string $configTemplate */ $configTemplate = $this->config->get('datatables-html.script', 'datatables::script'); $template = $this->template ?: $configTemplate; return $this->view->make($template, ['editors' => $this->editors, 'scripts' => $this->additionalScripts])->render(); } /** * Generate DataTable's table html. */ public function table(array $attributes = [], bool $drawFooter = false, bool $drawSearch = false): HtmlString { $this->setTableAttributes($attributes); $th = $this->compileTableHeaders(); $htmlAttr = $this->html->attributes($this->tableAttributes); $tableHtml = '<table'.$htmlAttr.'>'; $searchHtml = $drawSearch ? '<tr class="search-filter">'.implode('', $this->compileTableSearchHeaders()).'</tr>' : ''; $tableHtml .= '<thead'.($this->theadClass ?? '').'>'; $tableHtml .= '<tr>'.implode('', $th).'</tr>'.$searchHtml.'</thead>'; if ($drawFooter) { $tf = $this->compileTableFooter(); $tableHtml .= '<tfoot><tr>'.implode('', $tf).'</tr></tfoot>'; } $tableHtml .= '</table>'; return new HtmlString($tableHtml); } /** * Configure DataTable's parameters. * * @return $this */ public function parameters(array $attributes = []): static { $this->attributes = array_merge($this->attributes, $attributes); return $this; } /** * Generate scripts that set the dataTables options into a variable. * * @return $this */ public function asOptions(): static { return $this->setTemplate('datatables::options'); } /** * Set custom javascript template. * * @return $this */ public function setTemplate(string $template): static { $this->template = $template; return $this; } /** * Wrap dataTable scripts with a function. * * @return $this */ public function asFunction(): static { return $this->setTemplate('datatables::function'); } public function getAttributes(): array { return $this->attributes; } public function getAttribute(string $key, mixed $default = ''): mixed { return $this->attributes[$key] ?? $default; } public function getAjax(?string $key = null): array|string { if (! is_null($key)) { return $this->ajax[$key] ?? ''; } return $this->ajax; } /** * Add additional scripts to the DataTables JS initialization. * * @return $this */ public function addScript(string $view): static { $this->additionalScripts[] = $view; return $this; } } laravel-datatables-html/src/Html/ColumnDefinition.php 0000644 00000001736 15060167532 0016724 0 ustar 00 <?php namespace Yajra\DataTables\Html; /** * @see https://datatables.net/reference/option/columnDefs */ class ColumnDefinition extends Column { /** * @param array $attributes */ public function __construct($attributes = []) { parent::__construct($attributes); $this->attributes = $attributes; } /** * @return $this * * @see https://datatables.net/reference/option/columnDefs.targets */ public function targets(array|string|int $value): static { $this->attributes['targets'] = $value; return $this; } /** * @return $this * * @see https://datatables.net/reference/option/columns */ public function columns(array $value): static { $this->attributes['columns'] = $value; return $this; } public function toArray(): array { $array = parent::toArray(); unset($array['attributes']); return $array; } } laravel-datatables-html/src/Html/Button.php 0000755 00000022530 15060167532 0014727 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Support\Fluent; class Button extends Fluent implements Arrayable { use HasAuthorizations; /** * Make a new button instance. */ public static function make(array|string $options = []): static { if (is_string($options)) { return new static(['extend' => $options]); } return new static($options); } /** * Make a raw button that does not extend anything. */ public static function raw(array|string $options = []): static { if (is_string($options)) { return new static(['text' => $options]); } return new static($options); } /** * Set attr option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.attr */ public function attr(array $value): static { $this->attributes['attr'] = $value; return $this; } /** * Set available option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.available */ public function available(string $value): static { if ($this->isFunction($value)) { $this->attributes['available'] = $value; } else { $this->attributes['available'] = "function(dt, config) { $value }"; } return $this; } /** * Check if a given value is a function. */ protected function isFunction(string $value): bool { return str_starts_with($value, 'function'); } /** * Set enabled option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.enabled */ public function enabled(bool $value = true): static { $this->attributes['enabled'] = $value; return $this; } /** * Set init option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.init */ public function init(string $value): static { if ($this->isFunction($value)) { $this->attributes['init'] = $value; } else { $this->attributes['init'] = "function(dt, node, config) { $value }"; } return $this; } /** * Set key option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.key */ public function key(array|string $value): static { $this->attributes['key'] = $value; return $this; } /** * Set extend option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.extend */ public function extend(string $value): static { $this->attributes['extend'] = $value; return $this; } /** * Set editor option value. * * @return $this * * @see https://editor.datatables.net/reference/button */ public function editor(string $value): static { $this->attributes['editor'] = $value; return $this; } /** * Set buttons option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons */ public function buttons(array $buttons): static { foreach ($buttons as $key => $button) { if ($button instanceof Arrayable) { $buttons[$key] = $button->toArray(); } } $this->attributes['buttons'] = $buttons; return $this; } /** * @return $this * * @see https://editor.datatables.net/examples/api/cancelButton */ public function formButtons(array $buttons): static { foreach ($buttons as $key => $button) { if ($button instanceof Arrayable) { $buttons[$key] = $button->toArray(); } } $this->attributes['formButtons'] = $buttons; return $this; } /** * @return $this * * @see https://editor.datatables.net/examples/api/removeMessage * @see https://editor.datatables.net/reference/button/create * @see https://editor.datatables.net/reference/button/edit * @see https://editor.datatables.net/reference/button/remove */ public function formMessage(string $message): static { $this->attributes['formMessage'] = $message; return $this; } /** * @return $this * * @see https://editor.datatables.net/reference/button/create * @see https://editor.datatables.net/reference/button/edit * @see https://editor.datatables.net/reference/button/remove */ public function formTitle(string $title): static { $this->attributes['formTitle'] = $title; return $this; } /** * Set className option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.className */ public function className(string $value): static { $this->attributes['className'] = $value; return $this; } /** * Set destroy option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.destroy */ public function destroy(string $value): static { if ($this->isFunction($value)) { $this->attributes['destroy'] = $value; } else { $this->attributes['destroy'] = "function(dt, node, config) { $value }"; } return $this; } /** * Set customize option value. * * @return $this * * @see https://datatables.net/reference/button/excelHtml5 */ public function customize(string $value): static { $this->attributes['customize'] = $value; return $this; } /** * Append a class name to column. * * @return $this */ public function addClass(string $class): static { if (! isset($this->attributes['className'])) { $this->attributes['className'] = $class; } else { $this->attributes['className'] .= " $class"; } return $this; } /** * Set text option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.text */ public function text(string $value): static { $this->attributes['text'] = $value; return $this; } /** * Set titleAttr option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.titleAttr */ public function titleAttr(string $value): static { $this->attributes['titleAttr'] = $value; return $this; } /** * Set name option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.name */ public function name(string $value): static { $this->attributes['name'] = $value; return $this; } /** * Set namespace option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.namespace */ public function namespace(string $value): static { $this->attributes['namespace'] = $value; return $this; } /** * Set tag option value. * * @return $this * * @see https://datatables.net/reference/option/buttons.buttons.tag */ public function tag(string $value): static { $this->attributes['tag'] = $value; return $this; } /** * Set columns option value. * * @return $this */ public function columns(array|string $value): static { $this->attributes['columns'] = $value; return $this; } /** * Set exportOptions option value. * * @return $this */ public function exportOptions(array|string $value): static { $this->attributes['exportOptions'] = $value; return $this; } /** * Set action to submit the form. * * @return $this */ public function actionSubmit(): static { return $this->action('function() { this.submit(); }'); } /** * Set action option value. * * @return $this */ public function action(string $value): static { if (str_starts_with($value, 'function')) { $this->attributes['action'] = $value; } else { $this->attributes['action'] = "function(e, dt, node, config) { $value }"; } return $this; } /** * Set editor class action handler. * * @return $this */ public function actionHandler(string $action): static { return $this->action("function() { this.submit(null, null, function(data) { data.action = '{$action}'; return data; }) }"); } /** * Set action to close the form. * * @return $this */ public function actionClose(): static { return $this->action('function() { this.close(); }'); } /** * Set button alignment. * * @return $this */ public function align(string $align = 'button-left'): static { $this->attributes['align'] = $align; return $this; } } laravel-datatables-html/src/Html/Parameters.php 0000644 00000000456 15060167532 0015557 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Illuminate\Support\Fluent; class Parameters extends Fluent { /** * @var array<string, mixed> */ protected $attributes = [ 'serverSide' => true, 'processing' => true, 'ajax' => '', 'columns' => [], ]; } laravel-datatables-html/src/Html/Columns/Checkbox.php 0000644 00000002403 15060167532 0016614 0 ustar 00 <?php namespace Yajra\DataTables\Html\Columns; use Yajra\DataTables\Html\Column; trait Checkbox { /** * Add a checkbox column. * * @param bool|int $position true to prepend, false to append or a zero-based index for positioning * @return $this */ public function addCheckbox(array $attributes = [], bool|int $position = false): static { $attributes = array_merge([ 'defaultContent' => '<input type="checkbox" '.$this->html->attributes($attributes).'/>', 'title' => '<input type="checkbox" '.$this->html->attributes($attributes + ['id' => 'dataTablesCheckbox']).'/>', 'data' => 'checkbox', 'name' => 'checkbox', 'orderable' => false, 'searchable' => false, 'exportable' => false, 'printable' => true, 'width' => '10px', ], $attributes); $column = new Column($attributes); if ($position === true) { $this->collection->prepend($column); } elseif ($position === false || $position >= $this->collection->count()) { $this->collection->push($column); } else { $this->collection->splice($position, 0, [$column]); } return $this; } } laravel-datatables-html/src/Html/Columns/Action.php 0000644 00000001536 15060167532 0016311 0 ustar 00 <?php namespace Yajra\DataTables\Html\Columns; use Yajra\DataTables\Html\Column; trait Action { /** * Add an action column. * * @return $this */ public function addAction(array $attributes = [], bool $prepend = false): static { $attributes = array_merge([ 'defaultContent' => '', 'data' => 'action', 'name' => 'action', 'title' => 'Action', 'render' => null, 'orderable' => false, 'searchable' => false, 'exportable' => false, 'printable' => true, 'footer' => '', ], $attributes); if ($prepend) { $this->collection->prepend(new Column($attributes)); } else { $this->collection->push(new Column($attributes)); } return $this; } } laravel-datatables-html/src/Html/Columns/Index.php 0000644 00000001443 15060167532 0016140 0 ustar 00 <?php namespace Yajra\DataTables\Html\Columns; use Yajra\DataTables\Html\Column; trait Index { /** * Add a index column. * * @return $this */ public function addIndex(array $attributes = []): static { $indexColumn = $this->config->get('datatables.index_column', 'DT_RowIndex'); $attributes = array_merge([ 'defaultContent' => '', 'data' => $indexColumn, 'name' => $indexColumn, 'title' => '', 'render' => null, 'orderable' => false, 'searchable' => false, 'exportable' => false, 'printable' => true, 'footer' => '', ], $attributes); $this->collection->push(new Column($attributes)); return $this; } } laravel-datatables-html/src/Html/HasEditor.php 0000644 00000002717 15060167532 0015340 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Yajra\DataTables\Html\Editor\Editor; trait HasEditor { /** * Collection of Editors. */ protected array $editors = []; /** * Attach multiple editors to builder. * * @param array|mixed ...$editors * @return $this * * @see https://editor.datatables.net/ */ public function editors(...$editors): static { if (is_array($editors[0])) { $editors = $editors[0]; } $this->editors = []; foreach ($editors as $editor) { if ($editor instanceof Editor) { $this->editor($editor); } else { $this->editor(new Editor($editor)); } } return $this; } /** * Integrate with DataTables Editor. * * @return $this * * @see https://editor.datatables.net/ */ public function editor(Editor $editor): static { /** @var string $template */ $template = $this->config->get('datatables-html.editor', 'datatables::editor'); $this->setTemplate($template); if (! $editor->table) { $editor->table('#'.$this->getTableAttribute('id')); } if (! $editor->ajax) { $editor->ajax($this->getAjaxUrl()); } $this->editors[] = $editor; return $this; } public function getEditors(): array { return $this->editors; } } laravel-datatables-html/src/Html/HtmlBuilder.php 0000644 00000027575 15060167532 0015702 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Illuminate\Contracts\Routing\UrlGenerator; use Illuminate\Contracts\View\Factory; use Illuminate\Support\HtmlString; class HtmlBuilder { /** * Create a new HTML builder instance. */ public function __construct( /** * The URL generator instance. */ protected UrlGenerator $url, /** * The View Factory instance. */ protected Factory $view ) { } /** * Convert entities to HTML characters. */ public function decode(string $value): string { return html_entity_decode($value, ENT_QUOTES, 'UTF-8'); } /** * Generate a link to a JavaScript file. */ public function script(string $url, array $attributes = [], ?bool $secure = null): HtmlString { $attributes['src'] = $this->url->asset($url, $secure); return $this->toHtmlString('<script'.$this->attributes($attributes).'></script>'); } /** * Transform the string to an Html serializable object */ protected function toHtmlString(string $html): HtmlString { return new HtmlString($html); } /** * Build an HTML attribute string from an array. */ public function attributes(array $attributes): string { $html = []; foreach ($attributes as $key => $value) { $element = $this->attributeElement($key, $value); if (! is_null($element)) { $html[] = $element; } } return ! empty($html) ? ' '.implode(' ', $html) : ''; } /** * Build a single attribute element. */ protected function attributeElement(string $key, mixed $value): mixed { // For numeric keys we will assume that the value is a boolean attribute // where the presence of the attribute represents a true value and the // absence represents a false value. // This will convert HTML attributes such as "required" to a correct // form instead of using incorrect numerics. if (is_numeric($key)) { return $value; } // Treat boolean attributes as HTML properties if (is_bool($value) && $key !== 'value') { return $value ? $key : ''; } if (is_array($value) && $key === 'class') { return 'class="'.implode(' ', $value).'"'; } if (is_bool($value) || is_float($value) || is_int($value) || is_resource($value) || is_string($value)) { return $key.'="'.e(strval($value), false).'"'; } return null; } /** * Generate a link to a CSS file. */ public function style(string $url, array $attributes = [], ?bool $secure = null): HtmlString { $defaults = ['media' => 'all', 'type' => 'text/css', 'rel' => 'stylesheet']; $attributes = array_merge($defaults, $attributes); $attributes['href'] = $this->url->asset($url, $secure); return $this->toHtmlString('<link'.$this->attributes($attributes).'>'); } /** * Generate an HTML image element. */ public function image(string $url, ?string $alt = null, array $attributes = [], ?bool $secure = null): HtmlString { $attributes['alt'] = $alt; return $this->toHtmlString('<img src="'.$this->url->asset($url, $secure).'"'.$this->attributes($attributes).'>'); } /** * Generate a link to a Favicon file. */ public function favicon(string $url, array $attributes = [], ?bool $secure = null): HtmlString { $defaults = ['rel' => 'shortcut icon', 'type' => 'image/x-icon']; $attributes = array_merge($defaults, $attributes); $attributes['href'] = $this->url->asset($url, $secure); return $this->toHtmlString('<link'.$this->attributes($attributes).'>'); } /** * Generate a HTTPS HTML link. */ public function secureLink( string $url, ?string $title = null, array $attributes = [], bool $escape = true ): HtmlString { return $this->link($url, $title, $attributes, true, $escape); } /** * Generate a HTML link. */ public function link( string $url, ?string $title = null, array $attributes = [], ?bool $secure = null, bool $escape = true ): HtmlString { $url = $this->url->to($url, [], $secure); if (is_null($title)) { $title = $url; } if ($escape) { $title = $this->entities($title); } return $this->toHtmlString( '<a href="'.$this->entities($url).'"'.$this->attributes($attributes).'>'.$title.'</a>' ); } /** * Convert an HTML string to entities. */ public function entities(string $value): string { return htmlentities($value, ENT_QUOTES, 'UTF-8', false); } /** * Generate a HTTPS HTML link to an asset. */ public function linkSecureAsset( string $url, ?string $title = null, array $attributes = [], bool $escape = true ): HtmlString { return $this->linkAsset($url, $title, $attributes, true, $escape); } /** * Generate a HTML link to an asset. */ public function linkAsset( string $url, ?string $title = null, array $attributes = [], ?bool $secure = null, bool $escape = true ): HtmlString { $url = $this->url->asset($url, $secure); return $this->link($url, $title ?: $url, $attributes, $secure, $escape); } /** * Generate a HTML link to a named route. */ public function linkRoute( string $name, ?string $title = null, array $parameters = [], array $attributes = [], ?bool $secure = null, bool $escape = true ): HtmlString { return $this->link($this->url->route($name, $parameters), $title, $attributes, $secure, $escape); } /** * Generate a HTML link to a controller action. */ public function linkAction( string $action, ?string $title = null, array $parameters = [], array $attributes = [], ?bool $secure = null, bool $escape = true ): HtmlString { return $this->link($this->url->action($action, $parameters), $title, $attributes, $secure, $escape); } /** * Generate a HTML link to an email address. */ public function mailto(string $email, ?string $title = null, array $attributes = [], bool $escape = true): HtmlString { $email = $this->email($email); $title = $title ?: $email; if ($escape) { $title = $this->entities($title); } $email = $this->obfuscate('mailto:').$email; return $this->toHtmlString('<a href="'.$email.'"'.$this->attributes($attributes).'>'.$title.'</a>'); } /** * Obfuscate an e-mail address to prevent spam-bots from sniffing it. */ public function email(string $email): string { return str_replace('@', '@', $this->obfuscate($email)); } /** * Obfuscate a string to prevent spam-bots from sniffing it. * * @throws \Exception */ public function obfuscate(string $value): string { $safe = ''; foreach (str_split($value) as $letter) { if (ord($letter) > 128) { return $letter; } // To properly obfuscate the value, we will randomly convert each letter to // its entity or hexadecimal representation, keeping a bot from sniffing // the randomly obfuscated letters out of the string on the responses. switch (random_int(1, 3)) { case 1: $safe .= '&#'.ord($letter).';'; break; case 2: $safe .= '&#x'.dechex(ord($letter)).';'; break; case 3: $safe .= $letter; } } return $safe; } /** * Generates non-breaking space entities based on number supplied. */ public function nbsp(int $num = 1): string { return str_repeat(' ', $num); } /** * Generate an ordered list of items. */ public function ol(array $list, array $attributes = []): HtmlString|string { return $this->listing('ol', $list, $attributes); } /** * Create a listing HTML element. */ protected function listing(string $type, array $list, array $attributes = []): HtmlString|string { $html = ''; if (empty($list)) { return $html; } // Essentially we will just spin through the list and build the list of the HTML // elements from the array. We will also handled nested lists in case that is // present in the array. Then we will build out the final listing elements. foreach ($list as $key => $value) { $html .= $this->listingElement($key, $type, $value); } $attributes = $this->attributes($attributes); return $this->toHtmlString("<{$type}{$attributes}>{$html}</{$type}>"); } /** * Create the HTML for a listing element. */ protected function listingElement(mixed $key, string $type, mixed $value): HtmlString|string { if (is_array($value)) { return $this->nestedListing($key, $type, $value); } else { if (is_bool($value) || is_float($value) || is_int($value) || is_resource($value) || is_string($value) || is_null($value) ) { return '<li>'.e(strval($value), false).'</li>'; } } return '<li>'.$value.'</li>'; } /** * Create the HTML for a nested listing attribute. */ protected function nestedListing(mixed $key, string $type, array $value): HtmlString|string { if (is_int($key)) { return $this->listing($type, $value); } else { return '<li>'.$key.$this->listing($type, $value).'</li>'; } } /** * Generate an un-ordered list of items. */ public function ul(array $list, array $attributes = []): HtmlString|string { return $this->listing('ul', $list, $attributes); } /** * Generate a description list of items. */ public function dl(array $list, array $attributes = []): HtmlString { $attributes = $this->attributes($attributes); $html = "<dl{$attributes}>"; foreach ($list as $key => $value) { $value = (array) $value; $html .= "<dt>$key</dt>"; foreach ($value as $v_value) { $html .= "<dd>$v_value</dd>"; } } $html .= '</dl>'; return $this->toHtmlString($html); } /** * Generate a meta tag. */ public function meta(string $name, string $content, array $attributes = []): HtmlString { $defaults = compact('name', 'content'); $attributes = array_merge($defaults, $attributes); return $this->toHtmlString('<meta'.$this->attributes($attributes).'>'); } /** * Generate an html tag. */ public function tag(string $tag, mixed $content, array $attributes = []): HtmlString { $content = is_array($content) ? implode('', $content) : $content; if (is_bool($content) || is_float($content) || is_int($content) || is_resource($content) || is_string($content) || is_null($content) ) { return $this->toHtmlString( '<'.$tag.$this->attributes($attributes).'>'.$this->toHtmlString(strval($content)).'</'.$tag.'>' ); } return $this->toHtmlString('<'.$tag.$this->attributes($attributes).'>'.$content.'</'.$tag.'>'); } } laravel-datatables-html/src/Html/HasAuthorizations.php 0000644 00000004156 15060167532 0017134 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Illuminate\Contracts\Auth\Access\Authorizable; trait HasAuthorizations { /** * Flag to check if user is authorized to use the button. */ protected bool $authorized = true; /** * Make a button if condition is true. */ public static function makeIf(callable|bool $condition, array|string $options = []): static { if (is_callable($condition)) { $condition = value($condition); } if ($condition === true) { return static::make($options); } return app(static::class)->authorized(false); } /** * Set authorization status of the button. */ public function authorized(callable|bool $bool): static { $this->authorized = (bool) value($bool); return $this; } /** * Make a button if the user is authorized. */ public static function makeIfCan(string $permission, array|string $options = [], ?Authorizable $user = null): static { if (is_null($user)) { $user = auth()->user(); } if ($user instanceof Authorizable && $user->can($permission)) { return static::make($options); } return static::make([])->authorized(false); } /** * Make a button if the user is not authorized. */ public static function makeIfCannot( string $permission, array|string $options = [], ?Authorizable $user = null ): static { if (is_null($user)) { $user = auth()->user(); } if ($user instanceof Authorizable && ! $user->can($permission)) { return static::make($options); } return app(static::class)->authorized(false); } /** * Convert the Fluent instance to an array. */ public function toArray(): array { if (! $this->isAuthorized()) { return []; } return parent::toArray(); } /** * Check if instance is authorized */ public function isAuthorized(): bool { return $this->authorized; } } laravel-datatables-html/src/Html/HasOptions.php 0000644 00000021637 15060167532 0015547 0 ustar 00 <?php namespace Yajra\DataTables\Html; /** * DataTables - Options builder. * * @see https://datatables.net/reference/option/ */ trait HasOptions { use Options\HasAjax; use Options\HasCallbacks; use Options\HasColumns; use Options\HasFeatures; use Options\HasInternationalisation; use Options\Plugins\AutoFill; use Options\Plugins\Buttons; use Options\Plugins\ColReorder; use Options\Plugins\FixedColumns; use Options\Plugins\FixedHeader; use Options\Plugins\KeyTable; use Options\Plugins\Responsive; use Options\Plugins\RowGroup; use Options\Plugins\RowReorder; use Options\Plugins\Scroller; use Options\Plugins\SearchPanes; use Options\Plugins\Select; /** * Set deferLoading option value. * * @return $this * * @see https://datatables.net/reference/option/deferLoading */ public function deferLoading(array|int|null $value = null): static { $this->attributes['deferLoading'] = $value; return $this; } /** * Set destroy option value. * * @return $this * * @see https://datatables.net/reference/option/destroy */ public function destroy(bool $value = false): static { $this->attributes['destroy'] = $value; return $this; } /** * Set displayStart option value. * * @return $this * * @see https://datatables.net/reference/option/displayStart */ public function displayStart(int $value = 0): static { $this->attributes['displayStart'] = $value; return $this; } /** * Set dom option value. * * @return $this * * @deprecated Use layout() method instead. * @see https://datatables.net/reference/option/dom */ public function dom(string $value): static { $this->attributes['dom'] = $value; return $this; } /** * Set layout option value. * * @return $this * * @see https://datatables.net/reference/option/layout */ public function layout(array|Layout|callable $value): static { if ($value instanceof Layout) { $value = $value->toArray(); } if (is_callable($value)) { $layout = new Layout; $value($layout); $value = $layout->toArray(); } $this->attributes['layout'] = $value; return $this; } /** * Set lengthMenu option value. * * @return $this * * @see https://datatables.net/reference/option/lengthMenu */ public function lengthMenu(array $value = [10, 25, 50, 100]): static { $this->attributes['lengthMenu'] = $value; return $this; } /** * Set orders option value. * * @return $this * * @see https://datatables.net/reference/option/order */ public function orders(array $value): static { $this->attributes['order'] = $value; return $this; } /** * Set orderCellsTop option value. * * @return $this * * @see https://datatables.net/reference/option/orderCellsTop */ public function orderCellsTop(bool $value = false): static { $this->attributes['orderCellsTop'] = $value; return $this; } /** * Set orderClasses option value. * * @return $this * * @see https://datatables.net/reference/option/orderClasses */ public function orderClasses(bool $value = true): static { $this->attributes['orderClasses'] = $value; return $this; } /** * Order option builder. * * @return $this * * @see https://datatables.net/reference/option/order */ public function orderBy(array|int $index, string $direction = 'desc'): static { if ($direction != 'desc') { $direction = 'asc'; } if (is_array($index)) { $this->attributes['order'][] = $index; } else { $this->attributes['order'][] = [$index, $direction]; } return $this; } /** * Order Fixed option builder. * * @return $this * * @see https://datatables.net/reference/option/orderFixed */ public function orderByFixed(array|int $index, string $direction = 'desc'): static { if ($direction != 'desc') { $direction = 'asc'; } if (is_array($index)) { $this->attributes['orderFixed'][] = $index; } else { $this->attributes['orderFixed'][] = [$index, $direction]; } return $this; } /** * Set orderMulti option value. * * @return $this * * @see https://datatables.net/reference/option/orderMulti */ public function orderMulti(bool $value = true): static { $this->attributes['orderMulti'] = $value; return $this; } /** * Set pageLength option value. * * @return $this * * @see https://datatables.net/reference/option/pageLength */ public function pageLength(int $value = 10): static { $this->attributes['pageLength'] = $value; return $this; } /** * Set pagingType option value. * * @return $this * * @see https://datatables.net/reference/option/pagingType */ public function pagingType(string $value = 'simple_numbers'): static { $this->attributes['pagingType'] = $value; return $this; } /** * Set renderer option value. * * @return $this * * @see https://datatables.net/reference/option/renderer */ public function renderer(string $value = 'bootstrap'): static { $this->attributes['renderer'] = $value; return $this; } /** * Set retrieve option value. * * @return $this * * @see https://datatables.net/reference/option/retrieve */ public function retrieve(bool $value = false): static { $this->attributes['retrieve'] = $value; return $this; } /** * Set rowId option value. * * @return $this * * @see https://datatables.net/reference/option/rowId */ public function rowId(string $value = 'DT_RowId'): static { $this->attributes['rowId'] = $value; return $this; } /** * Set scrollCollapse option value. * * @return $this * * @see https://datatables.net/reference/option/scrollCollapse */ public function scrollCollapse(bool $value = false): static { $this->attributes['scrollCollapse'] = $value; return $this; } /** * Set search option value. * * @return $this * * @see https://datatables.net/reference/option/search */ public function search(array $value): static { $this->attributes['search'] = $value; return $this; } /** * Set searchCols option value. * * @return $this * * @see https://datatables.net/reference/option/searchCols */ public function searchCols(array $value): static { $this->attributes['searchCols'] = $value; return $this; } /** * Set searchDelay option value. * * @return $this * * @see https://datatables.net/reference/option/searchDelay */ public function searchDelay(int $value): static { $this->attributes['searchDelay'] = $value; return $this; } /** * Set stateDuration option value. * * @return $this * * @see https://datatables.net/reference/option/stateDuration */ public function stateDuration(int $value): static { $this->attributes['stateDuration'] = $value; return $this; } /** * Set stripeClasses option value. * * @return $this * * @see https://datatables.net/reference/option/stripeClasses */ public function stripeClasses(array $value): static { $this->attributes['stripeClasses'] = $value; return $this; } /** * Set tabIndex option value. * * @return $this * * @see https://datatables.net/reference/option/tabIndex */ public function tabIndex(int $value = 0): static { $this->attributes['tabIndex'] = $value; return $this; } /** * @return $this */ public function setPluginAttribute(string $key, array|bool $value): static { if (is_array($value)) { $this->attributes[$key] = array_merge((array) ($this->attributes[$key] ?? []), $value); } else { $this->attributes[$key] = $value; } return $this; } public function getPluginAttribute(string $plugin, ?string $key = null): mixed { if (is_null($key)) { return $this->attributes[$plugin] ?? true; } return $this->attributes[$plugin][$key] ?? false; } } laravel-datatables-html/src/Html/Enums/LayoutPosition.php 0000644 00000001073 15060167532 0017541 0 ustar 00 <?php declare(strict_types=1); namespace Yajra\DataTables\Html\Enums; use Illuminate\Support\Str; enum LayoutPosition: string { case Top = 'top'; case TopStart = 'topStart'; case TopEnd = 'topEnd'; case Bottom = 'bottom'; case BottomStart = 'bottomStart'; case BottomEnd = 'bottomEnd'; public function withOrder(?int $order): string { if ($order && $order > 0) { $parts = Str::of($this->value)->ucsplit(); return $parts->shift().$order.$parts->first(); } return $this->value; } } laravel-datatables-html/src/Html/Layout.php 0000644 00000010241 15060167532 0014722 0 ustar 00 <?php declare(strict_types=1); namespace Yajra\DataTables\Html; use Illuminate\Contracts\Support\Renderable; use Illuminate\Support\Facades\Blade; use Illuminate\Support\Fluent; use Illuminate\Support\Traits\Macroable; use Illuminate\View\Component; use InvalidArgumentException; use Livewire\Livewire; use Throwable; use Yajra\DataTables\Html\Enums\LayoutPosition; class Layout extends Fluent { use Macroable; public static function make(array $options = []): static { return new static($options); } public function top(array|string|null $options, ?int $order = null): static { $this->attributes[LayoutPosition::Top->withOrder($order)] = $options; return $this; } public function topStart(string|array|null $options, ?int $order = null): static { $this->attributes[LayoutPosition::TopStart->withOrder($order)] = $options; return $this; } public function topEnd(string|array|null $options, ?int $order = null): static { $this->attributes[LayoutPosition::TopEnd->withOrder($order)] = $options; return $this; } public function topView(string $selector, ?int $order = null): static { return $this->top($this->renderCustomElement($selector), $order); } public function topStartView(string $selector, ?int $order = null): static { return $this->topStart($this->renderCustomElement($selector), $order); } public function topEndView(string $selector, ?int $order = null): static { return $this->topEnd($this->renderCustomElement($selector), $order); } public function bottom(array|string|null $options, ?int $order = null): static { $this->attributes[LayoutPosition::Bottom->withOrder($order)] = $options; return $this; } public function bottomStart(string|array|null $options, ?int $order = null): static { $this->attributes[LayoutPosition::BottomStart->withOrder($order)] = $options; return $this; } public function bottomEnd(string|array|null $options, ?int $order = null): static { $this->attributes[LayoutPosition::BottomEnd->withOrder($order)] = $options; return $this; } public function bottomView(string $selector, ?int $order = null): static { return $this->bottom($this->renderCustomElement($selector), $order); } public function bottomStartView(string $selector, ?int $order = null): static { return $this->bottomStart($this->renderCustomElement($selector), $order); } public function bottomEndView(string $selector, ?int $order = null): static { return $this->bottomEnd($this->renderCustomElement($selector), $order); } /** * @throws Throwable */ public function addView( Component|Renderable|string $view, LayoutPosition $layoutPosition, ?int $order = null ): static { if ($view instanceof Component) { $view = Blade::renderComponent($view); } $html = $view instanceof Renderable ? $view->render() : Blade::render($view); $element = json_encode($html); if ($element === false) { throw new InvalidArgumentException("Cannot render view [$html] to json."); } $this->attributes[$layoutPosition->withOrder($order)] = $this->renderCustomElement($element, false); return $this; } /** * @param class-string $component * * @throws Throwable */ public function addLivewire( string $component, LayoutPosition $layoutPosition, ?int $order = null ): static { $html = json_encode(Livewire::mount($component)); if ($html === false) { throw new InvalidArgumentException("Cannot render Livewire component [$component] to json."); } $this->attributes[$layoutPosition->withOrder($order)] = $this->renderCustomElement($html, false); return $this; } private function renderCustomElement(string $element, bool $asJsSelector = true): string { $html = $asJsSelector ? "$('{$element}').html()" : $element; return "function() { return $html; }"; } } laravel-datatables-html/src/Html/Options/Languages/Select.php 0000644 00000002426 15060167532 0020233 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Languages; trait Select { /** * Set language select option value. * * @return $this * * @see https://datatables.net/reference/option/language.select */ public function languageSelect(array $value): static { return $this->language(['select' => $value]); } /** * Set language select cells option value. * * @return $this * * @see https://datatables.net/reference/option/language.select.cells */ public function languageSelectCells(array|string $value): static { return $this->languageSelect(['cells' => $value]); } /** * Set language select columns option value. * * @return $this * * @see https://datatables.net/reference/option/language.select.columns */ public function languageSelectColumns(array|string $value): static { return $this->languageSelect(['columns' => $value]); } /** * Set language select rows option value. * * @return $this * * @see https://datatables.net/reference/option/language.select.rows */ public function languageSelectRows(array|string $value): static { return $this->languageSelect(['rows' => $value]); } } laravel-datatables-html/src/Html/Options/Languages/Aria.php 0000644 00000005145 15060167532 0017671 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Languages; trait Aria { /** * Set language aria option value. * * @return $this * * @see https://datatables.net/reference/option/language.aria */ public function languageAria(array $value): static { return $this->language(['aria' => $value]); } /** * Set language aria paginate option value. * * @return $this * * @see https://datatables.net/reference/option/language.aria.paginate */ public function languageAriaPaginate(array $value): static { return $this->languageAria(['paginate' => $value]); } /** * Set language aria paginate first option value. * * @return $this * * @see https://datatables.net/reference/option/language.aria.paginate.first */ public function languageAriaPaginateFirst(string $value): static { return $this->languageAriaPaginate(['first' => $value]); } /** * Set language aria paginate last option value. * * @return $this * * @see https://datatables.net/reference/option/language.aria.paginate.last */ public function languageAriaPaginateLast(string $value): static { return $this->languageAriaPaginate(['last' => $value]); } /** * Set language aria paginate next option value. * * @return $this * * @see https://datatables.net/reference/option/language.aria.paginate.next */ public function languageAriaPaginateNext(string $value): static { return $this->languageAriaPaginate(['next' => $value]); } /** * Set language aria paginate previous option value. * * @return $this * * @see https://datatables.net/reference/option/language.aria.paginate.previous */ public function languageAriaPaginatePrevious(string $value): static { return $this->languageAriaPaginate(['previous' => $value]); } /** * Set language aria sortAscending option value. * * @return $this * * @see https://datatables.net/reference/option/language.aria.sortAscending */ public function languageAriaSortAscending(string $value): static { return $this->languageAria(['sortAscending' => $value]); } /** * Set language aria sortDescending option value. * * @return $this * * @see https://datatables.net/reference/option/language.aria.sortDescending */ public function languageAriaSortDescending(string $value): static { return $this->languageAria(['sortDescending' => $value]); } } laravel-datatables-html/src/Html/Options/Languages/Paginate.php 0000644 00000003172 15060167532 0020543 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Languages; trait Paginate { /** * Set language aria paginate option value. * * @return $this * * @see https://datatables.net/reference/option/language.paginate */ public function languagePaginate(array $value): static { return $this->language(['paginate' => $value]); } /** * Set language aria paginate first option value. * * @return $this * * @see https://datatables.net/reference/option/language.paginate.first */ public function languagePaginateFirst(string $value): static { return $this->languagePaginate(['first' => $value]); } /** * Set language aria paginate last option value. * * @return $this * * @see https://datatables.net/reference/option/language.paginate.last */ public function languagePaginateLast(string $value): static { return $this->languagePaginate(['last' => $value]); } /** * Set language aria paginate next option value. * * @return $this * * @see https://datatables.net/reference/option/language.paginate.next */ public function languagePaginateNext(string $value): static { return $this->languagePaginate(['next' => $value]); } /** * Set language aria paginate previous option value. * * @return $this * * @see https://datatables.net/reference/option/language.paginate.previous */ public function languagePaginatePrevious(string $value): static { return $this->languagePaginate(['previous' => $value]); } } laravel-datatables-html/src/Html/Options/Languages/AutoFill.php 0000644 00000005136 15060167532 0020534 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Languages; trait AutoFill { /** * Set language autoFill option value. * * @return $this * * @see https://datatables.net/reference/option/language.autoFill */ public function languageAutoFill(array $value): static { return $this->language(['autoFill' => $value]); } /** * Set language autoFill button option value. * * @return $this * * @see https://datatables.net/reference/option/language.autoFill.button */ public function languageAutoFillButton(string $value): static { return $this->languageAutoFill(['button' => $value]); } /** * Set language autoFill cancel option value. * * @return $this * * @see https://datatables.net/reference/option/language.autoFill.cancel */ public function languageAutoFillCancel(string $value): static { return $this->languageAutoFill(['cancel' => $value]); } /** * Set language autoFill fill option value. * * @return $this * * @see https://datatables.net/reference/option/language.autoFill.fill */ public function languageAutoFillFill(string $value): static { return $this->languageAutoFill(['fill' => $value]); } /** * Set language autoFill fillHorizontal option value. * * @return $this * * @see https://datatables.net/reference/option/language.autoFill.fillHorizontal */ public function languageAutoFillFillHorizontal(string $value): static { return $this->languageAutoFill(['fillHorizontal' => $value]); } /** * Set language autoFill fillVertical option value. * * @return $this * * @see https://datatables.net/reference/option/language.autoFill.fillVertical */ public function languageAutoFillFillVertical(string $value): static { return $this->languageAutoFill(['fillVertical' => $value]); } /** * Set language autoFill increment option value. * * @return $this * * @see https://datatables.net/reference/option/language.autoFill.increment */ public function languageAutoFillIncrement(string $value): static { return $this->languageAutoFill(['increment' => $value]); } /** * Set language autoFill info option value. * * @return $this * * @see https://datatables.net/reference/option/language.autoFill.info */ public function languageAutoFillInfo(string $value): static { return $this->languageAutoFill(['info' => $value]); } } laravel-datatables-html/src/Html/Options/Plugins/Select.php 0000644 00000012224 15060167532 0017743 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; use Yajra\DataTables\Html\Builder; /** * DataTables - Select plugin option builder. * * @see https://datatables.net/extensions/select * @see https://datatables.net/reference/option/select */ trait Select { /** * Set select blurable option value. * * @return $this * * @see https://datatables.net/reference/option/select.blurable */ public function selectBlurable(bool $value = true): static { return $this->select(['blurable' => $value]); } /** * Set select className option value. * * @return $this * * @see https://datatables.net/reference/option/select.className */ public function selectClassName(string $value = 'selected'): static { return $this->select(['className' => $value]); } /** * Append a class name to className option value. * * @return $this */ public function selectAddClassName(string $class): static { if (! isset($this->attributes['select']['className'])) { $this->attributes['select']['className'] = $class; } else { $this->attributes['select']['className'] .= " $class"; } return $this; } /** * Set select info option value. * * @return $this * * @see https://datatables.net/reference/option/select.info */ public function selectInfo(bool $value = true): static { return $this->select(['info' => $value]); } /** * Set select items option value. * * @return $this * * @see https://datatables.net/reference/option/select.items */ public function selectItems(string $value = 'row'): static { return $this->select(['items' => $value]); } /** * Set select items option value to row. * * @return $this * * @see https://datatables.net/reference/option/select.items */ public function selectItemsRow(): static { return $this->select(['items' => Builder::SELECT_ITEMS_ROW]); } /** * Set select items option value to column. * * @return $this * * @see https://datatables.net/reference/option/select.items */ public function selectItemsColumn(): static { return $this->select(['items' => Builder::SELECT_ITEMS_COLUMN]); } /** * Set select items option value to cell. * * @return $this * * @see https://datatables.net/reference/option/select.items */ public function selectItemsCell(): static { return $this->select(['items' => Builder::SELECT_ITEMS_CELL]); } /** * Set select selector option value. * * @return $this * * @see https://datatables.net/reference/option/select.selector */ public function selectSelector(string $value = 'td'): static { return $this->select(['selector' => $value]); } /** * Set select style option value. * * @return $this * * @see https://datatables.net/reference/option/select.style */ public function selectStyle(string $value = 'os'): static { return $this->select(['style' => $value]); } /** * Set select style option value to api. * * @return $this * * @see https://datatables.net/reference/option/select.style */ public function selectStyleApi(): static { return $this->select(['style' => Builder::SELECT_STYLE_API]); } /** * Set select style option value to single. * * @return $this * * @see https://datatables.net/reference/option/select.style */ public function selectStyleSingle(): static { return $this->select(['style' => Builder::SELECT_STYLE_SINGLE]); } /** * Set select option value. * * @return $this * * @see https://datatables.net/reference/option/select */ public function select(bool|array $value = true): static { return $this->setPluginAttribute('select', $value); } /** * Set select style option value to multi. * * @return $this * * @see https://datatables.net/reference/option/select.style */ public function selectStyleMulti(): static { return $this->select(['style' => Builder::SELECT_STYLE_MULTI]); } /** * Set select style option value to os. * * @return $this * * @see https://datatables.net/reference/option/select.style */ public function selectStyleOS(): static { return $this->select(['style' => Builder::SELECT_STYLE_OS]); } /** * Set select style option value to multi+shift. * * @return $this * * @see https://datatables.net/reference/option/select.style */ public function selectStyleMultiShift(): static { return $this->select(['style' => Builder::SELECT_STYLE_MULTI_SHIFT]); } public function getSelect(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['select'] ?? true; } return $this->attributes['select'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/Responsive.php 0000644 00000006363 15060167532 0020670 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; /** * DataTables - Responsive plugin option builder. * * @see https://datatables.net/extensions/responsive * @see https://datatables.net/reference/option/responsive * @see https://datatables.net/reference/option/#responsive */ trait Responsive { /** * Set responsive breakpoints option value. * * @return $this * * @see https://datatables.net/reference/option/responsive.breakpoints */ public function responsiveBreakpoints(array $value): static { return $this->responsive(['breakpoints' => $value]); } /** * Set responsive option value. * * @return $this * * @see https://datatables.net/reference/option/responsive */ public function responsive(array|bool $value = true): static { return $this->setPluginAttribute('responsive', $value); } /** * Set responsive details display option value. * * @return $this * * @see https://datatables.net/reference/option/responsive.details.display */ public function responsiveDetailsDisplay(array|string $value): static { return $this->responsiveDetails(['display' => $value]); } /** * Set responsive details option value. * * @return $this * * @see https://datatables.net/reference/option/responsive.details */ public function responsiveDetails(bool|array $value): static { $responsive = (array) $this->getResponsive(); if (is_array($value)) { $responsive['details'] = array_merge((array) ($responsive['details'] ?? []), $value); } else { $responsive['details'] = $value; } return $this->responsive($responsive); } /** * Set responsive details renderer option value. * * @return $this * * @see https://datatables.net/reference/option/responsive.details.renderer */ public function responsiveDetailsRenderer(string $value): static { return $this->responsiveDetails(['renderer' => $value]); } /** * Set responsive details target option value. * * @return $this * * @see https://datatables.net/reference/option/responsive.details.target */ public function responsiveDetailsTarget(int|string $value): static { return $this->responsiveDetails(['target' => $value]); } /** * Set responsive details type option value. * * @return $this * * @see https://datatables.net/reference/option/responsive.details.type */ public function responsiveDetailsType(string $value): static { return $this->responsiveDetails(['type' => $value]); } /** * Set responsive orthogonal option value. * * @return $this * * @see https://datatables.net/reference/option/responsive.orthogonal */ public function responsiveOrthogonal(string $value): static { return $this->responsive(['orthogonal' => $value]); } public function getResponsive(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['responsive'] ?? true; } return $this->attributes['responsive'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/SearchPanes.php 0000644 00000002250 15060167532 0020716 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; use Illuminate\Contracts\Support\Arrayable; use Yajra\DataTables\Html\SearchPane; /** * DataTables - Search panes plugin option builder. * * @see https://datatables.net/extensions/searchpanes * @see https://datatables.net/reference/option/searchPanes */ trait SearchPanes { /** * Set searchPane option value. * * @return $this * * @see https://datatables.net/reference/option/searchPanes */ public function searchPanes(array|Arrayable|bool|callable $value = true): static { if (is_callable($value)) { $value = app()->call($value); } if ($value instanceof Arrayable) { $value = $value->toArray(); } if (is_bool($value)) { $value = SearchPane::make()->show($value)->toArray(); } $this->attributes['searchPanes'] = $value; return $this; } public function getSearchPanes(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['searchPanes'] ?? true; } return $this->attributes['searchPanes'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/KeyTable.php 0000644 00000010212 15060167532 0020217 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; /** * DataTables - KeyTable plugin option builder. * * @see https://datatables.net/extensions/keytable/ * @see https://datatables.net/reference/option/keys * @see https://datatables.net/reference/option/#keys */ trait KeyTable { /** * Set keys blurable option value. * * @return $this * * @see https://datatables.net/reference/option/keys.blurable */ public function keysBlurable(bool $value = true): static { return $this->keys(['blurable' => $value]); } /** * Set keys option value. * * @return $this * * @see https://datatables.net/reference/option/keys */ public function keys(array|bool $value = true): static { return $this->setPluginAttribute('keys', $value); } /** * Set keys className option value. * * @return $this * * @see https://datatables.net/reference/option/keys.className */ public function keysClassName(string $value = 'focus'): static { return $this->keys(['className' => $value]); } /** * Set keys clipboard option value. * * @return $this * * @see https://datatables.net/reference/option/keys.clipboard */ public function keysClipboard(bool $value = true): static { return $this->keys(['clipboard' => $value]); } /** * Set keys clipboardOrthogonal option value. * * @return $this * * @see https://datatables.net/reference/option/keys.clipboardOrthogonal */ public function keysClipboardOrthogonal(string $value = 'display'): static { return $this->keys(['clipboardOrthogonal' => $value]); } /** * Set keys columns option value. * * @return $this * * @see https://datatables.net/reference/option/keys.columns */ public function keysColumns(array|string $value): static { return $this->keys(['columns' => $value]); } /** * Set keys editAutoSelect option value. * * @return $this * * @see https://datatables.net/reference/option/keys.editAutoSelect */ public function keysEditAutoSelect(bool $value = true): static { return $this->keys(['editAutoSelect' => $value]); } /** * Set keys editOnFocus option value. * * @return $this * * @see https://datatables.net/reference/option/keys.editOnFocus */ public function keysEditOnFocus(bool $value = true): static { return $this->keys(['editOnFocus' => $value]); } /** * Set keys editor option value. * * @return $this * * @see https://datatables.net/reference/option/keys.editor */ public function keysEditor(string $value): static { return $this->keys(['editor' => $value]); } /** * Set keys editorKeys option value. * * @return $this * * @see https://datatables.net/reference/option/keys.editorKeys */ public function keysEditorKeys(string $value = 'navigation-only'): static { return $this->keys(['editorKeys' => $value]); } /** * Set keys focus option value. * * @return $this * * @see https://datatables.net/reference/option/keys.focus */ public function keysFocus(string $value): static { return $this->keys(['focus' => $value]); } /** * Set key's keys option value. * * @return $this * * @see https://datatables.net/reference/option/keys.keys */ public function keysKeys(?array $value = null): static { return $this->keys(['keys' => $value]); } /** * Set keys tabIndex option value. * * @return $this * * @see https://datatables.net/reference/option/keys.tabIndex */ public function keysTabIndex(int $value): static { return $this->keys(['tabIndex' => $value]); } public function getKeys(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['keys'] ?? true; } return $this->attributes['keys'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/FixedColumns.php 0000644 00000003467 15060167532 0021135 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; /** * DataTables - FixedColumns plugin option builder. * * @see https://datatables.net/extensions/fixedcolumns/ * @see https://datatables.net/reference/option/fixedColumns * @see https://datatables.net/reference/option/#fixedColumns */ trait FixedColumns { /** * Set fixedColumns heightMatch option value. * * @return $this * * @see https://datatables.net/reference/option/fixedColumns.heightMatch */ public function fixedColumnsHeightMatch(string $value = 'semiauto'): static { return $this->fixedColumns(['heightMatch' => $value]); } /** * Set fixedColumns option value. * * @return $this * * @see https://datatables.net/reference/option/fixedColumns */ public function fixedColumns(array|bool $value = true): static { return $this->setPluginAttribute('fixedColumns', $value); } /** * Set fixedColumns leftColumns option value. * * @return $this * * @see https://datatables.net/reference/option/fixedColumns.leftColumns */ public function fixedColumnsLeftColumns(int $value = 1): static { return $this->fixedColumns(['leftColumns' => $value]); } /** * Set fixedColumns rightColumns option value. * * @return $this * * @see https://datatables.net/reference/option/fixedColumns.rightColumns */ public function fixedColumnsRightColumns(int $value = 0): static { return $this->fixedColumns(['rightColumns' => $value]); } public function getFixedColumns(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['fixedColumns'] ?? true; } return $this->attributes['fixedColumns'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/RowReorder.php 0000644 00000005633 15060167532 0020624 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; /** * DataTables - RowReorder plugin option builder. * * @see https://datatables.net/extensions/rowreorder * @see https://datatables.net/reference/option/rowReorder * @see https://datatables.net/reference/option/#rowReorder */ trait RowReorder { /** * Set rowReorder dataSrc option value. * * @return $this * * @see https://datatables.net/reference/option/rowReorder.dataSrc */ public function rowReorderDataSrc(array|int $value = 0): static { return $this->rowReorder(['dataSrc' => $value]); } /** * Set rowReorder option value. * * @return $this * * @see https://datatables.net/reference/option/rowReorder */ public function rowReorder(array|bool $value = true): static { return $this->setPluginAttribute('rowReorder', $value); } /** * Set rowReorder editor option value. * * @return $this * * @see https://datatables.net/reference/option/rowReorder.editor */ public function rowReorderEditor(?string $value = null): static { return $this->rowReorder(['editor' => $value]); } /** * Set rowReorder enable option value. * * @return $this * * @see https://datatables.net/reference/option/rowReorder.enable */ public function rowReorderEnable(bool $value = true): static { return $this->rowReorder(['enable' => $value]); } /** * Set rowReorder formOptions option value. * * @return $this * * @see https://datatables.net/reference/option/rowReorder.formOptions */ public function rowReorderFormOptions(array $value): static { return $this->rowReorder(['formOptions' => $value]); } /** * Set rowReorder selector option value. * * @return $this * * @see https://datatables.net/reference/option/rowReorder.selector */ public function rowReorderSelector(string $value = 'td:first-child'): static { return $this->rowReorder(['selector' => $value]); } /** * Set rowReorder snapX option value. * * @return $this * * @see https://datatables.net/reference/option/rowReorder.snapX */ public function rowReorderSnapX(bool|int $value = true): static { return $this->rowReorder(['snapX' => $value]); } /** * Set rowReorder update option value. * * @return $this * * @see https://datatables.net/reference/option/rowReorder.update */ public function rowReorderUpdate(bool $value = true): static { return $this->rowReorder(['update' => $value]); } public function getRowReorder(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['rowReorder'] ?? true; } return $this->attributes['rowReorder'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/Scroller.php 0000644 00000004530 15060167532 0020312 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; /** * DataTables - Scroller plugin option builder. * * @see https://datatables.net/extensions/scroller * @see https://datatables.net/reference/option/scroller * @see https://datatables.net/reference/option/#scroller */ trait Scroller { /** * Set scroller boundaryScale option value. * * @return $this * * @see https://datatables.net/reference/option/scroller.boundaryScale */ public function scrollerBoundaryScale(float $value = 0.5): static { return $this->scroller(['boundaryScale' => $value]); } /** * Set scroller option value. * * @return $this * * @see https://datatables.net/reference/option/scroller */ public function scroller(array|bool $value = true): static { return $this->setPluginAttribute('scroller', $value); } /** * Set scroller displayBuffer option value. * * @return $this * * @see https://datatables.net/reference/option/scroller.displayBuffer */ public function scrollerDisplayBuffer(int $value = 9): static { return $this->scroller(['displayBuffer' => $value]); } /** * Set scroller loadingIndicator option value. * * @return $this * * @see https://datatables.net/reference/option/scroller.loadingIndicator */ public function scrollerLoadingIndicator(bool $value = true): static { return $this->scroller(['loadingIndicator' => $value]); } /** * Set scroller rowHeight option value. * * @return $this * * @see https://datatables.net/reference/option/scroller.rowHeight */ public function scrollerRowHeight(int|string $value = 'auto'): static { return $this->scroller(['rowHeight' => $value]); } /** * Set scroller serverWait option value. * * @return $this * * @see https://datatables.net/reference/option/scroller.serverWait */ public function scrollerServerWait(int $value = 200): static { return $this->scroller(['serverWait' => $value]); } public function getScroller(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['scroller'] ?? true; } return $this->attributes['scroller'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/AutoFill.php 0000644 00000006247 15060167532 0020253 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; /** * DataTables - AutoFill plugin option builder. * * @see https://datatables.net/extensions/autofill/ * @see https://datatables.net/reference/option/autoFill * @see https://datatables.net/reference/option/#autoFill */ trait AutoFill { /** * Set autoFill alwaysAsk option value. * * @return $this * * @see https://datatables.net/reference/option/autoFill.alwaysAsk */ public function autoFillAlwaysAsk(bool $value = true): static { return $this->autoFill(['alwaysAsk' => $value]); } /** * Set autoFill option value. * Enable and configure the AutoFill extension for DataTables. * * @return $this * * @see https://datatables.net/reference/option/autoFill */ public function autoFill(array|bool $value = true): static { return $this->setPluginAttribute('autoFill', $value); } /** * Set autoFill columns option value. * * @return $this * * @see https://datatables.net/reference/option/autoFill.columns */ public function autoFillColumns(array|string $value): static { return $this->autoFill(['columns' => $value]); } /** * Set autoFill editor option value. * * @return $this * * @see https://datatables.net/reference/option/autoFill.editor */ public function autoFillEditor(string $value): static { return $this->autoFill(['editor' => $value]); } /** * Set autoFill enable option value. * * @return $this * * @see https://datatables.net/reference/option/autoFill.enable */ public function autoFillEnable(bool $value = true): static { return $this->autoFill(['enable' => $value]); } /** * Set autoFill focus option value. * * @return $this * * @see https://datatables.net/reference/option/autoFill.focus */ public function autoFillFocus(?string $value = null): static { return $this->autoFill(['focus' => $value]); } /** * Set autoFill horizontal option value. * * @return $this * * @see https://datatables.net/reference/option/autoFill.horizontal */ public function autoFillHorizontal(bool $value = true): static { return $this->autoFill(['horizontal' => $value]); } /** * Set autoFill update option value. * * @return $this * * @see https://datatables.net/reference/option/autoFill.update */ public function autoFillUpdate(bool $value = true): static { return $this->autoFill(['update' => $value]); } /** * Set autoFill vertical option value. * * @return $this * * @see https://datatables.net/reference/option/autoFill.vertical */ public function autoFillVertical(bool $value = true): static { return $this->autoFill(['vertical' => $value]); } public function getAutoFill(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['autoFill'] ?? true; } return $this->attributes['autoFill'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/FixedHeader.php 0000644 00000004065 15060167532 0020700 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; /** * DataTables - FixedHeader plugin option builder. * * @see https://datatables.net/extensions/fixedheader/ * @see https://datatables.net/reference/option/fixedHeader * @see https://datatables.net/reference/option/#fixedHeader */ trait FixedHeader { /** * Set fixedHeader footer option value. * * @return $this * * @see https://datatables.net/reference/option/fixedHeader.footer */ public function fixedHeaderFooter(bool $value = true): static { return $this->fixedHeader(['footer' => $value]); } /** * Set fixedHeader option value. * * @return $this * * @see https://datatables.net/reference/option/fixedHeader */ public function fixedHeader(array|bool $value = true): static { return $this->setPluginAttribute('fixedHeader', $value); } /** * Set fixedHeader footerOffset option value. * * @return $this * * @see https://datatables.net/reference/option/fixedHeader.footerOffset */ public function fixedHeaderFooterOffset(int $value = 0): static { return $this->fixedHeader(['footerOffset' => $value]); } /** * Set fixedHeader header option value. * * @return $this * * @see https://datatables.net/reference/option/fixedHeader.header */ public function fixedHeaderHeader(bool $value = true): static { return $this->fixedHeader(['header' => $value]); } /** * Set fixedHeader headerOffset option value. * * @return $this * * @see https://datatables.net/reference/option/fixedHeader.headerOffset */ public function fixedHeaderHeaderOffset(int $value = 0): static { return $this->fixedHeader(['headerOffset' => $value]); } public function getFixedHeader(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['fixedHeader'] ?? true; } return $this->attributes['fixedHeader'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/Buttons.php 0000644 00000002300 15060167532 0020154 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; use Illuminate\Contracts\Support\Arrayable; use Yajra\DataTables\Html\Button; /** * DataTables - Buttons plugin option builder. * * @see https://datatables.net/extensions/buttons/ * @see https://datatables.net/reference/option/buttons */ trait Buttons { /** * Attach multiple buttons to builder. * * @param array|mixed ...$buttons * @return $this * * @see https://www.datatables.net/extensions/buttons/ */ public function buttons(...$buttons): static { $this->attributes['buttons'] = []; if (is_array($buttons[0])) { $buttons = $buttons[0]; } foreach ($buttons as $button) { $this->attributes['buttons'][] = $button instanceof Arrayable ? $button->toArray() : $button; } return $this; } /** * @return $this */ public function addButton(Button $button): static { $this->attributes['buttons'][] = $button->toArray(); return $this; } /** * Get builder buttons. */ public function getButtons(): array { return $this->attributes['buttons'] ?? []; } } laravel-datatables-html/src/Html/Options/Plugins/RowGroup.php 0000644 00000006355 15060167532 0020320 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; /** * DataTables - RowGroup plugin option builder. * * @see https://datatables.net/extensions/rowgroup * @see https://datatables.net/reference/option/rowGroup * @see https://datatables.net/reference/option/#rowGroup */ trait RowGroup { /** * Set rowGroup className option value. * * @return $this * * @see https://datatables.net/reference/option/rowGroup.className */ public function rowGroupUpdate(string $value = 'group'): static { return $this->rowGroup(['className' => $value]); } /** * Set rowGroup option value. * * @return $this * * @see https://datatables.net/reference/option/rowGroup */ public function rowGroup(array|bool $value = true): static { return $this->setPluginAttribute('rowGroup', $value); } /** * Set rowGroup dataSrc option value. * * @return $this * * @see https://datatables.net/reference/option/rowGroup.dataSrc */ public function rowGroupDataSrc(array|int|string $value = 0): static { return $this->rowGroup(['dataSrc' => $value]); } /** * Set rowGroup emptyDataGroup option value. * * @return $this * * @see https://datatables.net/reference/option/rowGroup.emptyDataGroup */ public function rowGroupEmptyDataGroup(string $value = 'No Group'): static { return $this->rowGroup(['emptyDataGroup' => $value]); } /** * Set rowGroup enable option value. * * @return $this * * @see https://datatables.net/reference/option/rowGroup.enable */ public function rowGroupEnable(bool $value = true): static { return $this->rowGroup(['enable' => $value]); } /** * Set rowGroup endClassName option value. * * @return $this * * @see https://datatables.net/reference/option/rowGroup.endClassName */ public function rowGroupEndClassName(string $value = 'group-end'): static { return $this->rowGroup(['endClassName' => $value]); } /** * Set rowGroup endRender option value. * * @return $this * * @see https://datatables.net/reference/option/rowGroup.endRender */ public function rowGroupEndRender(string $value): static { return $this->rowGroup(['endRender' => $value]); } /** * Set rowGroup startClassName option value. * * @return $this * * @see https://datatables.net/reference/option/rowGroup.startClassName */ public function rowGroupStartClassName(string $value = 'group-start'): static { return $this->rowGroup(['startClassName' => $value]); } /** * Set rowGroup startRender option value. * * @return $this * * @see https://datatables.net/reference/option/rowGroup.startRender */ public function rowGroupStartRender(?string $value = null): static { return $this->rowGroup(['startRender' => $value]); } public function getRowGroup(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['rowGroup'] ?? true; } return $this->attributes['rowGroup'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/Plugins/ColReorder.php 0000644 00000004655 15060167532 0020575 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options\Plugins; /** * DataTables - ColReorder plugin option builder. * * @see https://datatables.net/extensions/colreorder/ * @see https://datatables.net/reference/option/colReorder * @see https://datatables.net/reference/option/#colReorder */ trait ColReorder { /** * Set colReorder enable option value. * * @return $this * * @see https://datatables.net/reference/option/colReorder.enable */ public function colReorderEnable(bool $value = true): static { return $this->colReorder(['enable' => $value]); } /** * Set colReorder option value. * Enable and configure the AutoFill extension for DataTables. * * @return $this * * @see https://datatables.net/reference/option/colReorder */ public function colReorder(array|bool $value = true): static { return $this->setPluginAttribute('colReorder', $value); } /** * Set colReorder fixedColumnsLeft option value. * * @return $this * * @see https://datatables.net/reference/option/colReorder.fixedColumnsLeft */ public function colReorderFixedColumnsLeft(int $value = 0): static { return $this->colReorder(['fixedColumnsLeft' => $value]); } /** * Set colReorder fixedColumnsRight option value. * * @return $this * * @see https://datatables.net/reference/option/colReorder.fixedColumnsRight */ public function colReorderFixedColumnsRight(int $value = 0): static { return $this->colReorder(['fixedColumnsRight' => $value]); } /** * Set colReorder order option value. * * @return $this * * @see https://datatables.net/reference/option/colReorder.order */ public function colReorderOrder(array $value = []): static { return $this->colReorder(['order' => $value]); } /** * Set colReorder realtime option value. * * @return $this * * @see https://datatables.net/reference/option/colReorder.realtime */ public function colReorderRealtime(bool $value = true): static { return $this->colReorder(['realtime' => $value]); } public function getColReorder(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['colReorder'] ?? true; } return $this->attributes['colReorder'][$key] ?? false; } } laravel-datatables-html/src/Html/Options/HasInternationalisation.php 0000644 00000012101 15060167532 0021727 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options; /** * DataTables - Internationalisation option builder. * * @see https://datatables.net/reference/option/ */ trait HasInternationalisation { use Languages\Aria; use Languages\AutoFill; use Languages\Paginate; use Languages\Select; /** * Set language decimal option value. * * @return $this * * @see https://datatables.net/reference/option/language.decimal */ public function languageDecimal(string $value): static { return $this->language(['decimal' => $value]); } /** * Set language option value. * * @return $this * * @see https://datatables.net/reference/option/language */ public function language(array|string $value): static { if (is_array($value)) { $this->attributes['language'] = array_merge((array) ($this->attributes['language'] ?? []), $value); } else { $this->attributes['language']['url'] = $value; } return $this; } /** * Set language emptyTable option value. * * @return $this * * @see https://datatables.net/reference/option/language.emptyTable */ public function languageEmptyTable(string $value): static { return $this->language(['emptyTable' => $value]); } /** * Set language info option value. * * @return $this * * @see https://datatables.net/reference/option/language.info */ public function languageInfo(string $value): static { return $this->language(['info' => $value]); } /** * Set language infoEmpty option value. * * @return $this * * @see https://datatables.net/reference/option/language.infoEmpty */ public function languageInfoEmpty(string $value): static { return $this->language(['infoEmpty' => $value]); } /** * Set language infoFiltered option value. * * @return $this * * @see https://datatables.net/reference/option/language.infoFiltered */ public function languageInfoFiltered(string $value): static { return $this->language(['infoFiltered' => $value]); } /** * Set language infoPostFix option value. * * @return $this * * @see https://datatables.net/reference/option/language.infoPostFix */ public function languageInfoPostFix(string $value): static { return $this->language(['infoPostFix' => $value]); } /** * Set language lengthMenu option value. * * @return $this * * @see https://datatables.net/reference/option/language.lengthMenu */ public function languageLengthMenu(string $value): static { return $this->language(['lengthMenu' => $value]); } /** * Set language loadingRecords option value. * * @return $this * * @see https://datatables.net/reference/option/language.loadingRecords */ public function languageLoadingRecords(string $value): static { return $this->language(['loadingRecords' => $value]); } /** * Set language processing option value. * * @return $this * * @see https://datatables.net/reference/option/language.processing */ public function languageProcessing(string $value): static { return $this->language(['processing' => $value]); } /** * Set language search option value. * * @return $this * * @see https://datatables.net/reference/option/language.search */ public function languageSearch(string $value): static { return $this->language(['search' => $value]); } /** * Set language searchPlaceholder option value. * * @return $this * * @see https://datatables.net/reference/option/language.searchPlaceholder */ public function languageSearchPlaceholder(string $value): static { return $this->language(['searchPlaceholder' => $value]); } /** * Set language thousands option value. * * @return $this * * @see https://datatables.net/reference/option/language.thousands */ public function languageThousands(string $value): static { return $this->language(['thousands' => $value]); } /** * Set language url option value. * * @return $this * * @see https://datatables.net/reference/option/language.url */ public function languageUrl(string $value): static { return $this->language(['url' => $value]); } /** * Set language zeroRecords option value. * * @return $this * * @see https://datatables.net/reference/option/language.zeroRecords */ public function languageZeroRecords(string $value): static { return $this->language(['zeroRecords' => $value]); } public function getLanguage(?string $key = null): mixed { if (is_null($key)) { return $this->attributes['language'] ?? []; } return $this->attributes['language'][$key] ?? ''; } } laravel-datatables-html/src/Html/Options/HasCallbacks.php 0000644 00000011656 15060167532 0017426 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options; /** * DataTables - Callbacks option builder. * * @see https://datatables.net/reference/option/ */ trait HasCallbacks { /** * Set createdRow option value. * * @return $this * * @see https://datatables.net/reference/option/createdRow */ public function createdRow(string $script): static { $this->attributes['createdRow'] = $script; return $this; } /** * Set drawCallback option value. * * @return $this * * @see https://datatables.net/reference/option/drawCallback */ public function drawCallback(string $script): static { $this->attributes['drawCallback'] = $script; return $this; } /** * Set drawCallback option value with Livewire integration. * Solution as per issue https://github.com/yajra/laravel-datatables/issues/2401. * * @return $this * * @see https://datatables.net/reference/option/drawCallback */ public function drawCallbackWithLivewire(?string $script = null): static { $js = "function(settings) { if (window.livewire) { window.livewire.rescan(); } $script }"; $this->attributes['drawCallback'] = $js; return $this; } /** * Set footerCallback option value. * * @return $this * * @see https://datatables.net/reference/option/footerCallback */ public function footerCallback(string $script): static { $this->attributes['footerCallback'] = $script; return $this; } /** * Set formatNumber option value. * * @return $this * * @see https://datatables.net/reference/option/formatNumber */ public function formatNumber(string $script): static { $this->attributes['formatNumber'] = $script; return $this; } /** * Set headerCallback option value. * * @return $this * * @see https://datatables.net/reference/option/headerCallback */ public function headerCallback(string $script): static { $this->attributes['headerCallback'] = $script; return $this; } /** * Set infoCallback option value. * * @return $this * * @see https://datatables.net/reference/option/infoCallback */ public function infoCallback(string $script): static { $this->attributes['infoCallback'] = $script; return $this; } /** * Set initComplete option value. * * @return $this * * @see https://datatables.net/reference/option/initComplete */ public function initComplete(string $script): static { $this->attributes['initComplete'] = $script; return $this; } /** * Set preDrawCallback option value. * * @return $this * * @see https://datatables.net/reference/option/preDrawCallback */ public function preDrawCallback(string $script): static { $this->attributes['preDrawCallback'] = $script; return $this; } /** * Set rowCallback option value. * * @return $this * * @see https://datatables.net/reference/option/rowCallback */ public function rowCallback(string $script): static { $this->attributes['rowCallback'] = $script; return $this; } /** * Set stateLoadCallback option value. * * @return $this * * @see https://datatables.net/reference/option/stateLoadCallback */ public function stateLoadCallback(string $script): static { $this->attributes['stateLoadCallback'] = $script; return $this; } /** * Set stateLoaded option value. * * @return $this * * @see https://datatables.net/reference/option/stateLoaded */ public function stateLoaded(string $script): static { $this->attributes['stateLoaded'] = $script; return $this; } /** * Set stateLoadParams option value. * * @return $this * * @see https://datatables.net/reference/option/stateLoadParams */ public function stateLoadParams(string $script): static { $this->attributes['stateLoadParams'] = $script; return $this; } /** * Set stateSaveCallback option value. * * @return $this * * @see https://datatables.net/reference/option/stateSaveCallback */ public function stateSaveCallback(string $script): static { $this->attributes['stateSaveCallback'] = $script; return $this; } /** * Set stateSaveParams option value. * * @return $this * * @see https://datatables.net/reference/option/stateSaveParams */ public function stateSaveParams(string $script): static { $this->attributes['stateSaveParams'] = $script; return $this; } } laravel-datatables-html/src/Html/Options/HasFeatures.php 0000644 00000007076 15060167532 0017326 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options; /** * DataTables - Features option builder. * * @see https://datatables.net/reference/option/ */ trait HasFeatures { /** * Set autoWidth option value. * * @return $this * * @see https://datatables.net/reference/option/autoWidth */ public function autoWidth(bool $value = true): static { $this->attributes['autoWidth'] = $value; return $this; } /** * Set deferRender option value. * * @return $this * * @see https://datatables.net/reference/option/deferRender */ public function deferRender(bool $value = true): static { $this->attributes['deferRender'] = $value; return $this; } /** * Set info option value. * * @return $this * * @see https://datatables.net/reference/option/info */ public function info(bool $value = true): static { $this->attributes['info'] = $value; return $this; } /** * Set lengthChange option value. * * @return $this * * @see https://datatables.net/reference/option/lengthChange */ public function lengthChange(bool $value = true): static { $this->attributes['lengthChange'] = $value; return $this; } /** * Set ordering option value. * * @return $this * * @see https://datatables.net/reference/option/ordering */ public function ordering(bool $value = true): static { $this->attributes['ordering'] = $value; return $this; } /** * Set processing option value. * * @return $this * * @see https://datatables.net/reference/option/processing */ public function processing(bool $value = true): static { $this->attributes['processing'] = $value; return $this; } /** * Set scrollX option value. * * @return $this * * @see https://datatables.net/reference/option/scrollX */ public function scrollX(bool $value = true): static { $this->attributes['scrollX'] = $value; return $this; } /** * Set scrollY option value. * * @return $this * * @see https://datatables.net/reference/option/scrollY */ public function scrollY(bool|string $value = true): static { $this->attributes['scrollY'] = $value; return $this; } /** * Set paging option value. * * @return $this * * @see https://datatables.net/reference/option/paging */ public function paging(bool $value = true): static { $this->attributes['paging'] = $value; return $this; } /** * Set searching option value. * * @return $this * * @see https://datatables.net/reference/option/searching */ public function searching(bool $value = true): static { $this->attributes['searching'] = $value; return $this; } /** * Set serverSide option value. * * @return $this * * @see https://datatables.net/reference/option/serverSide */ public function serverSide(bool $value = true): static { $this->attributes['serverSide'] = $value; return $this; } /** * Set stateSave option value. * * @return $this * * @see https://datatables.net/reference/option/stateSave */ public function stateSave(bool $value = true): static { $this->attributes['stateSave'] = $value; return $this; } } laravel-datatables-html/src/Html/Options/HasColumns.php 0000644 00000010255 15060167532 0017161 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Support\Collection; use Yajra\DataTables\Html\Column; /** * DataTables - Columns option builder. * * @see https://datatables.net/reference/option/ */ trait HasColumns { /** * Set columnDefs option value. * * @return $this * * @see https://datatables.net/reference/option/columnDefs */ public function columnDefs(array|Arrayable|callable $value): static { if (is_callable($value)) { $value = app()->call($value); } if ($value instanceof Arrayable) { $value = $value->toArray(); } if (is_array($value)) { foreach ($value as $key => $def) { if ($def instanceof Arrayable) { $value[$key] = $def->toArray(); } } } $this->attributes['columnDefs'] = $value; return $this; } /** * Add a columnDef option. * * @return $this * * @see https://datatables.net/reference/option/columnDefs */ public function addColumnDef(array|Arrayable|callable $value): static { if (is_callable($value)) { $value = app()->call($value); } if ($value instanceof Arrayable) { $value = $value->toArray(); } $this->attributes['columnDefs'][] = $value; return $this; } /** * Set columns option value. * * @return $this * * @see https://datatables.net/reference/option/columns */ public function columns(array $columns): static { $this->collection = new Collection; foreach ($columns as $key => $value) { if (! is_a($value, Column::class)) { if (is_array($value)) { $attributes = array_merge($value, [ 'name' => $value['name'] ?? $value['data'] ?? $key, 'data' => $value['data'] ?? $key, ]); } else { $attributes = [ 'name' => $value, 'data' => $value, ]; } $this->collection->push(new Column($attributes)); } else { $this->collection->push($value); } } return $this; } /** * Add a column in collection using attributes. * * @return $this */ public function addColumn(array|Column $attributes): static { if (is_array($attributes)) { $this->collection->push(new Column($attributes)); } else { $this->add($attributes); } return $this; } /** * Add a Column object in collection. * * @return $this */ public function add(Column $column): static { $this->collection->push($column); return $this; } /** * Add a Column object at the beginning of collection. * * @return $this */ public function addBefore(Column $column): static { $this->collection->prepend($column); return $this; } /** * Add a column at the beginning of collection using attributes. * * @return $this */ public function addColumnBefore(array|Column $attributes): static { if (is_array($attributes)) { $this->collection->prepend(new Column($attributes)); } else { $this->addBefore($attributes); } return $this; } /** * Get collection of columns. * * @return \Illuminate\Support\Collection<array-key, Column> */ public function getColumns(): Collection { return $this->collection; } /** * Remove column by name. * * @param array $names * @return $this */ public function removeColumn(...$names): static { foreach ($names as $name) { // @phpstan-ignore-next-line $this->collection = $this->collection->filter(fn (Column $column) => $column->name !== $name)->flatten(); } return $this; } } laravel-datatables-html/src/Html/Options/HasAjax.php 0000644 00000011110 15060167532 0016413 0 ustar 00 <?php namespace Yajra\DataTables\Html\Options; use Illuminate\Support\Arr; use Yajra\DataTables\Utilities\Helper; /** * DataTables - Data option builder. * * @see https://datatables.net/reference/option/ */ trait HasAjax { /** * Setup "ajax" parameter with POST method. * * @return $this */ public function postAjax(array|string $attributes = ''): static { if (! is_array($attributes)) { $attributes = ['url' => $attributes]; } unset($attributes['method']); Arr::set($attributes, 'type', 'POST'); Arr::set($attributes, 'headers.X-HTTP-Method-Override', 'GET'); return $this->ajax($attributes); } /** * Setup ajax parameter. * * @return $this */ public function ajax(array|string $attributes = ''): static { $this->ajax = $attributes; return $this; } /** * @return $this */ public function postAjaxWithForm(string $url, string $formSelector): static { $attributes = ['url' => $url]; Arr::set($attributes, 'type', 'POST'); Arr::set($attributes, 'headers.X-HTTP-Method-Override', 'GET'); $script = $this->getScriptWithFormSelector($formSelector); $attributes['data'] = "function(data) { $script }"; return $this->ajax($attributes); } protected function getScriptWithFormSelector(string $formSelector): string { return <<<CDATA var formData = _.groupBy($("$formSelector").find("input, select, textarea").serializeArray(), function(d) { return d.name; } ); $.each(formData, function(i, group){ if (group.length > 1) { data[group[0].name] = []; $.each(group, function(i, obj) { data[obj.name].push(obj.value) }) } else { data[group[0].name] = group[0].value; } }); CDATA; } /** * Setup ajax parameter for datatables pipeline plugin. * * @return $this * * @see https://datatables.net/examples/server_side/pipeline.html */ public function pipeline(string $url, int $pages = 5): static { return $this->ajax("$.fn.dataTable.pipeline({ url: '$url', pages: $pages })"); } /** * Get ajax url. */ public function getAjaxUrl(): string { if (is_array($this->ajax)) { return $this->ajax['url'] ?: url()->current(); } return $this->ajax ?: url()->current(); } /** * Set ajax url with data added from form. * * @return $this */ public function ajaxWithForm(string $url, string $formSelector): static { return $this->minifiedAjax($url, $this->getScriptWithFormSelector($formSelector)); } /** * Minify ajax url generated when using get request * by deleting unnecessary url params. * * @return $this */ public function minifiedAjax( string $url = '', ?string $script = null, array $data = [], array $ajaxParameters = [] ): static { $this->ajax = []; $appendData = $this->makeDataScript($data); $this->ajax['url'] = empty($url) ? url()->full() : $url; $this->ajax['type'] = 'GET'; if (! isset($this->attributes['serverSide']) || $this->attributes['serverSide']) { $this->ajax['data'] = 'function(data) { for (var i = 0, len = data.columns.length; i < len; i++) { if (!data.columns[i].search.value) delete data.columns[i].search; if (data.columns[i].searchable === true) delete data.columns[i].searchable; if (data.columns[i].orderable === true) delete data.columns[i].orderable; if (data.columns[i].data === data.columns[i].name) delete data.columns[i].name; } delete data.search.regex;'; } else { $this->ajax['data'] = 'function(data){'; } if ($appendData) { $this->ajax['data'] .= $appendData; } if ($script) { $this->ajax['data'] .= $script; } $this->ajax['data'] .= '}'; $this->ajax = array_merge($this->ajax, $ajaxParameters); return $this; } /** * Make a data script to be appended on ajax request of dataTables. */ protected function makeDataScript(array $data): string { $script = ''; foreach ($data as $key => $value) { $dataValue = Helper::isJavascript($value, $key) ? $value : (is_string($value) ? "'$value'" : $value); $script .= PHP_EOL."data.$key = $dataValue;"; } return $script; } } laravel-datatables-html/src/Html/HasTable.php 0000644 00000011263 15060167532 0015135 0 ustar 00 <?php namespace Yajra\DataTables\Html; use Illuminate\Support\Arr; trait HasTable { protected ?string $theadClass = null; /** * Get table computed table attributes. */ public function getTableAttributes(): array { return $this->tableAttributes; } /** * Sets HTML table "id" attribute. * * @return $this */ public function setTableId(string $id): static { return $this->setTableAttribute('id', $id); } /** * Sets HTML table attribute(s). * * @return $this */ public function setTableAttribute(array|string $attribute, ?string $value = null): static { if (is_array($attribute)) { return $this->setTableAttributes($attribute); } $this->tableAttributes[$attribute] = $value; return $this; } /** * Sets multiple HTML table attributes at once. * * @return $this */ public function setTableAttributes(array $attributes): static { foreach ($attributes as $attribute => $value) { $this->tableAttributes[$attribute] = $value; } return $this; } /** * Get HTML table "id" attribute. */ public function getTableId(): string { return $this->getTableAttribute('id'); } /** * Retrieves HTML table attribute value. */ public function getTableAttribute(string $attribute): string { return $this->tableAttributes[$attribute] ?? ''; } /** * Add class names to the "class" attribute of HTML table. * * @return $this */ public function addTableClass(array|string $class): static { $class = is_array($class) ? implode(' ', $class) : $class; $currentClass = Arr::get(array_change_key_case($this->tableAttributes), 'class'); $classes = preg_split('#\s+#', $currentClass.' '.$class, -1, PREG_SPLIT_NO_EMPTY); $class = implode(' ', array_unique((array) $classes)); return $this->setTableAttribute('class', $class); } /** * Set table > thead class names. * * @return $this */ public function setTableHeadClass(string $class): static { $this->theadClass = " class=\"$class\""; return $this; } /** * Remove class names from the "class" attribute of HTML table. * * @return $this */ public function removeTableClass(array|string $class): static { $class = is_array($class) ? implode(' ', $class) : $class; $currentClass = $this->getTableAttribute('class'); $classes = array_diff( (array) preg_split('#\s+#', (string) $currentClass, -1, PREG_SPLIT_NO_EMPTY), (array) preg_split('#\s+#', $class, -1, PREG_SPLIT_NO_EMPTY) ); $class = implode(' ', array_unique($classes)); return $this->setTableAttribute('class', $class); } /** * Compile table headers and to support responsive extension. */ protected function compileTableHeaders(): array { $th = []; $this->collection->each(function (Column $column) use (&$th) { $only = Arr::only( $column->toArray(), ['class', 'id', 'title', 'width', 'style', 'data-class', 'data-hide'] ); $attributes = array_merge( $only, $column->attributes, isset($column['titleAttr']) ? ['title' => $column['titleAttr']] : [] ); $thAttr = $this->html->attributes($attributes); $th[] = '<th'.$thAttr.'>'.$column['title'].'</th>'; }); return $th; } /** * Compile table search headers. */ protected function compileTableSearchHeaders(): array { $search = []; $this->collection->each(function (Column $column) use (&$search) { $search[] = $column['searchable'] ? '<th>'.($column['search'] ?? '').'</th>' : '<th></th>'; }); return $search; } /** * Compile table footer contents. */ protected function compileTableFooter(): array { $footer = []; $this->collection->each(function (Column $column) use (&$footer) { if (is_array($column->footer)) { $footerAttr = $this->html->attributes( Arr::only($column->footer, ['class', 'id', 'title', 'width', 'style', 'data-class', 'data-hide']) ); $title = $column->footer['title'] ?? ''; $footer[] = '<th '.$footerAttr.'>'.$title.'</th>'; } else { $footer[] = '<th>'.$column->footer.'</th>'; } }); return $footer; } } laravel-datatables-html/src/HtmlServiceProvider.php 0000644 00000002147 15060167532 0016507 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Support\ServiceProvider; class HtmlServiceProvider extends ServiceProvider { /** * Bootstrap the application events. */ public function boot(): void { $this->loadViewsFrom(__DIR__.'/resources/views', 'datatables'); if ($this->app->runningInConsole()) { $this->publishAssets(); } } /** * Publish datatables assets. */ protected function publishAssets(): void { $this->publishes([ __DIR__.'/resources/views' => base_path('/resources/views/vendor/datatables'), __DIR__.'/resources/config/config.php' => config_path('datatables-html.php'), ], 'datatables-html'); } /** * Register the service provider. */ public function register(): void { $this->mergeConfigFrom(__DIR__.'/resources/config/config.php', 'datatables-html'); $this->app->bind('datatables.html', fn () => $this->app->make(Html\Builder::class)); DataTables::macro('getHtmlBuilder', fn (): Html\Builder => app('datatables.html')); } } laravel-datatables-html/LICENSE.md 0000644 00000002117 15060167532 0012650 0 ustar 00 (The MIT License) Copyright (c) 2013-2022 Arjay Angeles <aqangeles@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. laravel-datatables-html/phpunit.xml 0000644 00000001001 15060167532 0013444 0 ustar 00 <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" bootstrap="vendor/autoload.php" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/11.0/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false"> <testsuites> <testsuite name="Package Test Suite"> <directory suffix="Test.php">./tests/</directory> </testsuite> </testsuites> </phpunit> laravel-datatables-html/rector.php 0000644 00000001032 15060167532 0013246 0 ustar 00 <?php declare(strict_types=1); use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; use Rector\Config\RectorConfig; use Rector\Set\ValueObject\LevelSetList; return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths([ __DIR__.'/src', __DIR__.'/tests', ]); // register a single rule $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); // define sets of rules $rectorConfig->sets([ LevelSetList::UP_TO_PHP_82, ]); }; laravel-datatables-html/UPGRADE.md 0000644 00000000131 15060167532 0012647 0 ustar 00 # Upgrade Notes ## v10 to v11 - Editor `scope` method has been renamed to `formScope`. laravel-datatables-html/CHANGELOG.md 0000644 00000001221 15060167532 0013050 0 ustar 00 # Laravel DataTables Html Plugin. ## CHANGELOG ### UNRELEASED ### v11.4.0 (2024-05-31) - feat: add className method to Editor Field #220 ### v11.3.0 (2024-05-18) - feat: Allow passing view and livewire components to layout builder #219 ### v11.2.1 (2024-04-29) - fix: multiple config option of select2 #218 ### v11.2.0 (2024-04-24) - feat: load layout from view using selector #217 ### v11.1.0 (2024-04-24) - feat: layout builder #216 - https://datatables.net/reference/option/layout ### v11.0.0 (2024-03-14) - Add support for Laravel 11.x - Fix editor scope compatibility with Fluent class scope - Rename Editor `scope` method to `formScope` laravel-datatables-html/composer.json 0000644 00000003234 15060167532 0013767 0 ustar 00 { "name": "yajra/laravel-datatables-html", "description": "Laravel DataTables HTML builder plugin", "keywords": [ "yajra", "laravel", "dataTables", "jquery", "html", "js" ], "license": "MIT", "authors": [ { "name": "Arjay Angeles", "email": "aqangeles@gmail.com" } ], "require": { "php": "^8.2", "ext-json": "*", "yajra/laravel-datatables-oracle": "^11.0" }, "require-dev": { "larastan/larastan": "^2.9.1", "orchestra/testbench": "^9", "laravel/pint": "^1.14", "rector/rector": "^1.0", "livewire/livewire": "^3.4" }, "suggest": { "laravel/livewire": "Required for Livewire layout support." }, "autoload": { "psr-4": { "Yajra\\DataTables\\": "src/" } }, "autoload-dev": { "psr-4": { "Yajra\\DataTables\\Html\\Tests\\": "tests/" } }, "extra": { "branch-alias": { "dev-master": "11.0-dev" }, "laravel": { "providers": [ "Yajra\\DataTables\\HtmlServiceProvider" ] } }, "scripts": { "test": "./vendor/bin/phpunit", "pint": "./vendor/bin/pint", "rector": "./vendor/bin/rector", "stan": "./vendor/bin/phpstan analyse --memory-limit=2G --ansi --no-progress --no-interaction --configuration=phpstan.neon.dist", "pr": [ "@rector", "@pint", "@stan", "@test" ] }, "minimum-stability": "dev", "prefer-stable": true } laravel-datatables-html/pint.json 0000644 00000000034 15060167532 0013105 0 ustar 00 { "preset": "laravel" } laravel-datatables-html/README.md 0000644 00000006366 15060167532 0012535 0 ustar 00 # Laravel DataTables Html Plugin [](http://laravel.com) [](https://packagist.org/packages/yajra/laravel-datatables-html) [](https://scrutinizer-ci.com/g/yajra/laravel-datatables-html/?branch=master) [](https://packagist.org/packages/yajra/laravel-datatables-html) [](https://packagist.org/packages/yajra/laravel-datatables-html) [](https://github.com/yajra/laravel-datatables-html/actions/workflows/continuous-integration.yml) [](https://github.com/yajra/laravel-datatables-html/actions/workflows/static-analysis.yml) [](https://github.com/yajra/laravel-datatables-html/actions/workflows/pint.yml) This package is a plugin of [Laravel DataTables](https://github.com/yajra/laravel-datatables) for generating dataTables script using PHP. ## Requirements - [Laravel 11.x](https://github.com/laravel/framework) - [Laravel DataTables](https://github.com/yajra/laravel-datatables) ## Documentations - [Laravel DataTables Documentation](http://yajrabox.com/docs/laravel-datatables) ## Laravel Version Compatibility | Laravel | Package | |:--------------|:--------| | 8.x and below | 4.x | | 9.x | 9.x | | 10.x | 10.x | | 11.x | 11.x | ## Quick Installation `composer require yajra/laravel-datatables-html:^11` #### Setup scripts with ViteJS Set the default javascript type to `module` by setting `Builder::useVite()` in the `AppServiceProvider`. ```php namespace App\Providers; use Illuminate\Pagination\Paginator; use Illuminate\Support\ServiceProvider; use Yajra\DataTables\Html\Builder; class AppServiceProvider extends ServiceProvider { /** * Bootstrap any application services. */ public function boot(): void { Paginator::useBootstrapFive(); Builder::useVite(); } } ``` #### Publish Assets (Optional) `$ php artisan vendor:publish --tag=datatables-html` And that's it! Start building out some awesome DataTables! ## Contributing Please see [CONTRIBUTING](https://github.com/yajra/laravel-datatables-html/blob/master/.github/CONTRIBUTING.md) for details. ## Security If you discover any security related issues, please email [aqangeles@gmail.com](mailto:aqangeles@gmail.com) instead of using the issue tracker. ## Credits - [Arjay Angeles](https://github.com/yajra) - [All Contributors](https://github.com/yajra/laravel-datatables-html/graphs/contributors) ## License The MIT License (MIT). Please see [License File](https://github.com/yajra/laravel-datatables-html/blob/master/LICENSE.md) for more information. laravel-datatables-html/CONDUCT.md 0000644 00000004146 15060167532 0012671 0 ustar 00 # Contributor Code of Conduct As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality. Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery * Personal attacks * Trolling or insulting/derogatory comments * Public or private harassment * Publishing other's private information, such as physical or electronic addresses, without explicit permission * Other unethical or unprofessional conduct. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team. This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community in a direct capacity. Personal views, beliefs and values of individuals do not necessarily reflect those of the organisation or affiliated individuals and organisations. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.2.0, available at [http://contributor-covenant.org/version/1/2/0/](http://contributor-covenant.org/version/1/2/0/) laravel-datatables-editor/phpstan.neon.dist 0000644 00000000301 15060167532 0015057 0 ustar 00 includes: - ./vendor/larastan/larastan/extension.neon parameters: paths: - src level: max ignoreErrors: excludePaths: checkMissingIterableValueType: false laravel-datatables-editor/src/Concerns/WithRestoreAction.php 0000644 00000000552 15060167532 0020256 0 ustar 00 <?php declare(strict_types=1); namespace Yajra\DataTables\Concerns; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; trait WithRestoreAction { /** * Process restore action request. */ public function restore(Request $request): JsonResponse { $this->restoring = true; return $this->edit($request); } } laravel-datatables-editor/src/Concerns/WithForceDeleteAction.php 0000644 00000000636 15060167532 0021017 0 ustar 00 <?php declare(strict_types=1); namespace Yajra\DataTables\Concerns; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; trait WithForceDeleteAction { /** * Process force delete action request. * * @throws \Exception */ public function forceDelete(Request $request): JsonResponse { $this->forceDeleting = true; return $this->remove($request); } } laravel-datatables-editor/src/Concerns/WithEditAction.php 0000644 00000004311 15060167532 0017515 0 ustar 00 <?php declare(strict_types=1); namespace Yajra\DataTables\Concerns; use Illuminate\Database\Eloquent\Model; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; trait WithEditAction { /** * Process edit action request. */ public function edit(Request $request): JsonResponse { $connection = $this->getBuilder()->getConnection(); $affected = []; $errors = []; $connection->beginTransaction(); foreach ($this->dataFromRequest($request) as $key => $data) { $this->currentData = $data; $model = $this->getBuilder()->findOrFail($key); $validator = $this->getValidationFactory() ->make( $data, $this->editRules($model), $this->messages() + $this->editMessages(), $this->attributes() ); if ($validator->fails()) { foreach ($this->formatErrors($validator) as $error) { $errors[] = $error; } continue; } $data = $this->updating($model, $data); $data = $this->saving($model, $data); if ($this->restoring && method_exists($model, 'restore')) { $model->restore(); } else { $model->fill($data)->save(); } $model = $this->updated($model, $data); $model = $this->saved($model, $data); $model->setAttribute('DT_RowId', $model->getKey()); $affected[] = $model; } if (! $errors) { $connection->commit(); } else { $connection->rollBack(); } return $this->toJson($affected, $errors); } /** * Get edit action validation rules. */ public function editRules(Model $model): array { return []; } /** * Get edit validation messages. */ protected function editMessages(): array { return []; } public function updating(Model $model, array $data): array { return $data; } public function updated(Model $model, array $data): Model { return $model; } } laravel-datatables-editor/src/Concerns/WithRemoveAction.php 0000644 00000005161 15060167532 0020071 0 ustar 00 <?php declare(strict_types=1); namespace Yajra\DataTables\Concerns; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\QueryException; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; trait WithRemoveAction { /** * Process remove action request. */ public function remove(Request $request): JsonResponse { $connection = $this->getBuilder()->getConnection(); $affected = []; $errors = []; $connection->beginTransaction(); foreach ($this->dataFromRequest($request) as $key => $data) { $this->currentData = $data; $model = $this->getBuilder()->findOrFail($key); $validator = $this->getValidationFactory() ->make( $data, $this->removeRules($model), $this->messages() + $this->removeMessages(), $this->attributes() ); if ($validator->fails()) { foreach ($this->formatErrors($validator) as $error) { $errors[] = $error['status']; } continue; } try { $deleted = clone $model; $data = $this->deleting($model, $data); $this->forceDeleting ? $model->forceDelete() : $model->delete(); $deleted = $this->deleted($deleted, $data); } catch (QueryException $exception) { $error = config('app.debug') ? $exception->getMessage() : $this->removeExceptionMessage($exception, $model); $errors[] = $error; } $affected[] = $deleted; } if (! $errors) { $connection->commit(); } else { $connection->rollBack(); } return $this->toJson($affected, [], $errors); } /** * Get remove action validation rules. */ public function removeRules(Model $model): array { return []; } /** * Get remove validation messages. */ protected function removeMessages(): array { return []; } public function deleting(Model $model, array $data): array { return $data; } public function deleted(Model $model, array $data): Model { return $model; } /** * Get remove query exception message. */ protected function removeExceptionMessage(QueryException $exception, Model $model): string { // @phpstan-ignore-next-line return "Record {$model->getKey()} is protected and cannot be deleted!"; } } laravel-datatables-editor/src/Concerns/WithUploadAction.php 0000644 00000006525 15060167532 0020065 0 ustar 00 <?php declare(strict_types=1); namespace Yajra\DataTables\Concerns; use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Filesystem\FilesystemAdapter; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage; use Illuminate\Validation\ValidationException; trait WithUploadAction { /** * Handle uploading of file. */ public function upload(Request $request): JsonResponse { $field = $request->input('uploadField'); if (! $field || ! is_string($field)) { $field = 'file'; } try { $storage = $this->getDisk(); $rules = $this->uploadRules(); $fieldRules = ['upload' => $rules[$field] ?? []]; $this->validate($request, $fieldRules, $this->messages(), $this->attributes()); /** @var UploadedFile $uploadedFile */ $uploadedFile = $request->file('upload'); $id = $this->storeUploadedFile($field, $uploadedFile); $id = $this->uploaded($id); return new JsonResponse([ 'action' => $this->action, 'data' => [], 'files' => [ 'files' => [ $id => [ 'filename' => $id, 'original_name' => $uploadedFile->getClientOriginalName(), 'size' => $uploadedFile->getSize(), 'directory' => $this->getUploadDirectory(), 'disk' => $this->disk, 'url' => $storage->url($id), ], ], ], 'upload' => [ 'id' => $id, ], ]); } catch (ValidationException $exception) { return new JsonResponse([ 'action' => $this->action, 'data' => [], 'fieldErrors' => [ [ 'name' => $field, 'status' => str_replace('upload', $field, (string) $exception->errors()['upload'][0]), ], ], ]); } } protected function getDisk(): Filesystem|FilesystemAdapter { return Storage::disk($this->disk); } /** * Upload validation rules. */ public function uploadRules(): array { return []; } protected function storeUploadedFile(string $field, UploadedFile $uploadedFile): string { $filename = $this->getUploadedFilename($field, $uploadedFile); $path = $this->getDisk()->putFileAs($this->getUploadDirectory(), $uploadedFile, $filename); if (! is_string($path)) { throw ValidationException::withMessages([ 'upload' => 'Failed to store uploaded file.', ]); } return $path; } protected function getUploadedFilename(string $field, UploadedFile $uploadedFile): string { return date('Ymd_His').'_'.$uploadedFile->getClientOriginalName(); } protected function getUploadDirectory(): string { return $this->uploadDir; } /** * Upload event hook. */ public function uploaded(string $id): string { return $id; } } laravel-datatables-editor/src/Concerns/WithCreateAction.php 0000644 00000004174 15060167532 0020042 0 ustar 00 <?php declare(strict_types=1); namespace Yajra\DataTables\Concerns; use Illuminate\Database\Eloquent\Model; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; trait WithCreateAction { /** * Process create action request. * * @throws \Throwable */ public function create(Request $request): JsonResponse { $model = $this->resolveModel(); $connection = $model->getConnection(); $affected = []; $errors = []; $connection->beginTransaction(); foreach ($this->dataFromRequest($request) as $data) { $this->currentData = $data; $instance = $model->newInstance(); $validator = $this->getValidationFactory() ->make( $data, $this->createRules(), $this->messages() + $this->createMessages(), $this->attributes() ); if ($validator->fails()) { foreach ($this->formatErrors($validator) as $error) { $errors[] = $error; } continue; } $data = $this->creating($instance, $data); $data = $this->saving($instance, $data); $instance->fill($data)->save(); $instance = $this->created($instance, $data); $instance = $this->saved($instance, $data); $instance->setAttribute('DT_RowId', $instance->getKey()); $affected[] = $instance; } if (! $errors) { $connection->commit(); } else { $connection->rollBack(); } return $this->toJson($affected, $errors); } /** * Get create action validation rules. */ public function createRules(): array { return []; } /** * Get create validation messages. */ protected function createMessages(): array { return []; } public function creating(Model $model, array $data): array { return $data; } public function created(Model $model, array $data): Model { return $model; } } laravel-datatables-editor/src/Generators/stubs/editor.stub 0000644 00000003363 15060167532 0020017 0 ustar 00 <?php declare(strict_types=1); namespace DummyNamespace; use DummyModel; use Illuminate\Database\Eloquent\Model; use Illuminate\Validation\Rule; use Yajra\DataTables\DataTablesEditor; class DummyClass extends DataTablesEditor { protected $model = ModelName::class; /** * Get create action validation rules. */ public function createRules(): array { return [ 'email' => 'required|email|max:255|unique:'.$this->resolveModel()->getTable(), 'name' => 'required|max:255', 'password' => 'required||max:255|confirmed', ]; } /** * Get edit action validation rules. */ public function editRules(Model $model): array { return [ 'email' => 'sometimes|required|max:255|email|'.Rule::unique($model->getTable())->ignore($model->getKey()), 'name' => 'sometimes|required|max:255', 'password' => 'sometimes|required|max:255', ]; } /** * Get remove action validation rules. */ public function removeRules(Model $model): array { return []; } /** * Event hook that is fired after `creating` and `updating` hooks, but before * the model is saved to the database. */ public function saving(Model $model, array $data): array { // Before saving the model, hash the password. if (! empty(data_get($data, 'password'))) { data_set($data, 'password', bcrypt($data['password'])); } return $data; } /** * Event hook that is fired after `created` and `updated` events. */ public function saved(Model $model, array $data): Model { // do something after saving the model return $model; } } laravel-datatables-editor/src/Generators/DataTablesEditorCommand.php 0000644 00000007305 15060167532 0021655 0 ustar 00 <?php namespace Yajra\DataTables\Generators; use Illuminate\Console\GeneratorCommand; use Illuminate\Support\Str; class DataTablesEditorCommand extends GeneratorCommand { /** * The name and signature of the console command. * * @var string */ protected $signature = 'datatables:editor {name : The name of the dataTable editor.} {--model : The name given will be used as the model is singular form.} {--model-namespace= : The namespace of the model to be used.}'; /** * The console command description. * * @var string */ protected $description = 'Create a new DataTables Editor class.'; /** * The type of class being generated. * * @var string */ protected $type = 'DataTableEditor'; /** * Build the class with the given name. * * @param string $name * * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException */ protected function buildClass($name): string { $stub = parent::buildClass($name); return $this->replaceModelImport($stub)->replaceModel($stub); } /** * Replace model name. */ protected function replaceModel(string &$stub): string { $model = explode('\\', $this->getModel()); $model = array_pop($model); $stub = str_replace('ModelName', $model, $stub); return $stub; } /** * Get model name to use. */ protected function getModel(): string { $name = $this->getNameInput(); $rootNamespace = $this->laravel->getNamespace(); $model = $this->option('model') || $this->option('model-namespace'); $modelNamespace = $this->option('model-namespace') ?: config('datatables-buttons.namespace.model'); return $model ? ($modelNamespace ?? $rootNamespace).'\\'.Str::singular($name) : $rootNamespace.'\\Models\\User'; } /** * Replace model import. */ protected function replaceModelImport(string &$stub): DataTablesEditorCommand { $stub = str_replace( 'DummyModel', str_replace('\\\\', '\\', $this->getModel()), $stub ); return $this; } /** * Get the stub file for the generator. */ protected function getStub(): string { $path = config('datatables-buttons.stub'); if ($path && is_string($path)) { return base_path($path).'/editor.stub'; } return __DIR__.'/stubs/editor.stub'; } /** * Replace the filename. */ protected function replaceFilename(string &$stub): string { $stub = str_replace( 'DummyFilename', Str::slug($this->getNameInput()), $stub ); return $stub; } /** * Parse the name and format according to the root namespace. * * @param string $name */ protected function qualifyClass($name): string { $rootNamespace = $this->laravel->getNamespace(); if (Str::startsWith($name, $rootNamespace)) { return $name; } if (Str::contains($name, '/')) { $name = str_replace('/', '\\', $name); } if (! Str::contains(Str::lower($name), 'datatable')) { $name .= $this->type; } return $this->getDefaultNamespace(trim((string) $rootNamespace, '\\')).'\\'.$name; } /** * Get the default namespace for the class. * * @param string $rootNamespace */ protected function getDefaultNamespace($rootNamespace): string { return $rootNamespace.'\\'.config('datatables-buttons.namespace.base', 'DataTables'); } } laravel-datatables-editor/src/EditorServiceProvider.php 0000644 00000000772 15060167532 0017355 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Support\ServiceProvider; use Yajra\DataTables\Generators\DataTablesEditorCommand; class EditorServiceProvider extends ServiceProvider { /** * Bootstrap the application events. * * @return void */ public function boot() { // } /** * Register the service provider. * * @return void */ public function register() { $this->commands(DataTablesEditorCommand::class); } } laravel-datatables-editor/src/DataTablesEditor.php 0000644 00000013331 15060167532 0016241 0 ustar 00 <?php declare(strict_types=1); namespace Yajra\DataTables; use Exception; use Illuminate\Contracts\Validation\Validator; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; /** * @template TModelClass of Model */ abstract class DataTablesEditor { use Concerns\WithCreateAction; use Concerns\WithEditAction; use Concerns\WithForceDeleteAction; use Concerns\WithRemoveAction; use Concerns\WithUploadAction; use ValidatesRequests; /** * Action performed by the editor. */ protected ?string $action = null; /** * Allowed dataTables editor actions. * * @var string[] */ protected array $actions = [ 'create', 'edit', 'remove', 'upload', 'forceDelete', 'restore', ]; /** * List of custom editor actions. * * @var string[] */ protected array $customActions = []; /** * @var null|class-string<\Illuminate\Database\Eloquent\Model>|Model */ protected $model = null; /** * Indicates if all mass assignment is enabled on model. */ protected bool $unguarded = false; /** * Upload directory relative to storage path. */ protected string $uploadDir = 'editor'; /** * Flag to force delete a model. */ protected bool $forceDeleting = false; /** * Flag to restore a model from deleted state. */ protected bool $restoring = false; /** * Filesystem disk config to use for upload. */ protected string $disk = 'public'; /** * Current request data that is being processed. */ protected array $currentData = []; /** * Process dataTables editor action request. * * @return JsonResponse * * @throws DataTablesEditorException */ public function process(Request $request): mixed { if ($request->get('action') && is_string($request->get('action'))) { $this->action = $request->get('action'); } else { throw new DataTablesEditorException('Invalid action requested!'); } if (! in_array($this->action, array_merge($this->actions, $this->customActions))) { throw new DataTablesEditorException(sprintf('Requested action (%s) not supported!', $this->action)); } try { return $this->{$this->action}($request); } catch (Exception $exception) { $error = config('app.debug') ? '<strong>Server Error:</strong> '.$exception->getMessage() : $this->getUseFriendlyErrorMessage(); app('log')->error($exception); return $this->toJson([], [], $error); } } protected function getUseFriendlyErrorMessage(): string { return 'An error occurs while processing your request.'; } /** * Display success data in dataTables editor format. */ protected function toJson(array $data, array $errors = [], string|array $error = ''): JsonResponse { $code = 200; $response = [ 'action' => $this->action, 'data' => $data, ]; if ($error) { $code = 422; $response['error'] = $error; } if ($errors) { $code = 422; $response['fieldErrors'] = $errors; } return new JsonResponse($response, $code); } /** * Get custom attributes for validator errors. */ public function attributes(): array { return []; } /** * Get dataTables model. */ public function getModel(): Model|string|null { return $this->model; } /** * Set the dataTables model on runtime. * * @param class-string<Model>|Model $model */ public function setModel(Model|string $model): static { $this->model = $model; return $this; } /** * Get validation messages. */ protected function messages(): array { return []; } protected function formatErrors(Validator $validator): array { $errors = []; collect($validator->errors())->each(function ($error, $key) use (&$errors) { $errors[] = [ 'name' => $key, 'status' => $error[0], ]; }); return $errors; } /** * Get eloquent builder of the model. * * @return \Illuminate\Database\Eloquent\Builder<TModelClass> */ protected function getBuilder(): Builder { $model = $this->resolveModel(); if (in_array(SoftDeletes::class, class_uses($model))) { // @phpstan-ignore-next-line return $model->newQuery()->withTrashed(); } return $model->newQuery(); } /** * Resolve model to used. */ protected function resolveModel(): Model { if (! $this->model instanceof Model) { $this->model = new $this->model; } $this->model->unguard($this->unguarded); return $this->model; } /** * Set model unguard state. * * @return $this */ public function unguard(bool $state = true): static { $this->unguarded = $state; return $this; } protected function dataFromRequest(Request $request): array { return (array) $request->get('data'); } public function saving(Model $model, array $data): array { return $data; } public function saved(Model $model, array $data): Model { return $model; } } laravel-datatables-editor/src/DataTablesEditorException.php 0000644 00000000152 15060167532 0020115 0 ustar 00 <?php namespace Yajra\DataTables; use Exception; class DataTablesEditorException extends Exception { } laravel-datatables-editor/CONTRIBUTING.md 0000644 00000001652 15060167532 0014022 0 ustar 00 # Contributing Contributions are **welcome** and will be fully **credited**. We accept contributions via Pull Requests on [Github](https://github.com/yajra/laravel-datatables-editor). ## Pull Requests - **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting. **Happy coding**! laravel-datatables-editor/LICENSE.md 0000644 00000002117 15060167532 0013172 0 ustar 00 (The MIT License) Copyright (c) 2013-2022 Arjay Angeles <aqangeles@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. laravel-datatables-editor/rector.php 0000644 00000001032 15060167532 0013570 0 ustar 00 <?php declare(strict_types=1); use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; use Rector\Config\RectorConfig; use Rector\Set\ValueObject\LevelSetList; return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths([ __DIR__.'/src', __DIR__.'/tests', ]); // register a single rule $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); // define sets of rules $rectorConfig->sets([ LevelSetList::UP_TO_PHP_82, ]); }; laravel-datatables-editor/UPGRADE.md 0000644 00000000020 15060167532 0013166 0 ustar 00 # Upgrade Notes laravel-datatables-editor/CHANGELOG.md 0000644 00000000673 15060167532 0013404 0 ustar 00 # Laravel DataTables Editor CHANGELOG ## [Unreleased](https://github.com/yajra/laravel-datatables-editor/compare/v11.0.0...master) ## [v11.0.0](https://github.com/yajra/laravel-datatables-editor/compare/1,x...v11.0.0) - 2024-03-16 - Laravel 11 support - CRUD Event hooks methods are now added by default. - Added pint for code style - Added phpstan - Added rector - Code updated with PHP8.2 syntax. Type hints might cause a breaking change laravel-datatables-editor/composer.json 0000644 00000003362 15060167532 0014313 0 ustar 00 { "name": "yajra/laravel-datatables-editor", "description": "Laravel DataTables Editor plugin for Laravel 5.5+.", "keywords": [ "laravel", "dataTables", "editor", "jquery", "html", "js" ], "license": "MIT", "authors": [ { "name": "Arjay Angeles", "email": "aqangeles@gmail.com" } ], "require": { "php": "^8.2", "illuminate/console": "^11", "illuminate/database": "^11", "illuminate/http": "^11", "illuminate/validation": "^11" }, "require-dev": { "larastan/larastan": "^2.9.1", "laravel/pint": "^1.14", "orchestra/testbench": "^9.0", "rector/rector": "^1.0" }, "autoload": { "psr-4": { "Yajra\\DataTables\\": "src/" } }, "autoload-dev": { "psr-4": { "Yajra\\DataTables\\Tests\\": "tests/" } }, "config": { "sort-packages": true, "allow-plugins": { "php-http/discovery": true } }, "scripts": { "test": "./vendor/bin/phpunit", "pint": "./vendor/bin/pint", "rector": "./vendor/bin/rector", "stan": "./vendor/bin/phpstan analyse --memory-limit=2G --ansi --no-progress --no-interaction --configuration=phpstan.neon.dist", "pr": [ "@rector", "@pint", "@stan", "@test" ] }, "extra": { "branch-alias": { "dev-master": "11.x-dev" }, "laravel": { "providers": [ "Yajra\\DataTables\\EditorServiceProvider" ] } }, "minimum-stability": "dev", "prefer-stable": true } laravel-datatables-editor/pint.json 0000644 00000000034 15060167532 0013427 0 ustar 00 { "preset": "laravel" } laravel-datatables-editor/README.md 0000644 00000006304 15060167532 0013047 0 ustar 00 # Laravel DataTables Editor Plugin. [](http://laravel.com) [](https://packagist.org/packages/yajra/laravel-datatables-editor) [](https://github.com/yajra/laravel-datatables-editor/actions/workflows/continuous-integration.yml) [](https://github.com/yajra/laravel-datatables-editor/actions/workflows/static-analysis.yml) [](https://scrutinizer-ci.com/g/yajra/laravel-datatables-editor/?branch=master) [](https://packagist.org/packages/yajra/laravel-datatables-editor) [](https://packagist.org/packages/yajra/laravel-datatables-editor) This package is a plugin of [Laravel DataTables](https://github.com/yajra/laravel-datatables) for processing [DataTables Editor](https://editor.datatables.net/) library. > Special thanks to [@bellwood](https://github.com/bellwood) and [@DataTables](https://github.com/datatables) for being [generous](https://github.com/yajra/laravel-datatables/issues/1548) for providing a license to support the development of this package. **NOTE:** A [premium license](https://editor.datatables.net/purchase/index) is required to be able to use [DataTables Editor](https://editor.datatables.net/) library. ## Requirements - [Laravel 11.x](https://github.com/laravel/framework) - [Laravel DataTables 11.x](https://github.com/yajra/laravel-datatables) ## Documentations - [Laravel DataTables Editor Manual](https://yajrabox.com/docs/laravel-datatables/editor-installation) - [jQuery DataTables Editor Manual](https://editor.datatables.net/manual/index) ## Laravel Version Compatibility | Laravel | Package | |:--------|:--------| | 5-10 | 1.x | | 11.x | 11.x | ## Features - DataTables Editor CRUD actions supported. - Inline editing. - Bulk edit & delete function. - CRUD validation. - CRUD pre / post events hooks. - Artisan command for DataTables Editor generation. ## Quick Installation `composer require yajra/laravel-datatables-editor:^11` And that's it! Start building out some awesome DataTables Editor! ## Contributing Please see [CONTRIBUTING](https://github.com/yajra/laravel-datatables-editor/blob/master/.github/CONTRIBUTING.md) for details. ## Security If you discover any security related issues, please email [aqangeles@gmail.com](mailto:aqangeles@gmail.com) instead of using the issue tracker. ## Credits - [Arjay Angeles](https://github.com/yajra) - [All Contributors](https://github.com/yajra/laravel-datatables-editor/graphs/contributors) ## License The MIT License (MIT). Please see [License File](https://github.com/yajra/laravel-datatables-editor/blob/master/LICENSE.md) for more information. laravel-datatables-editor/CONDUCT.md 0000644 00000011734 15060167532 0013214 0 ustar 00 # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others’ private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning Community Impact: A violation through a single incident or series of actions. Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban Community Impact: A serious violation of community standards, including sustained inappropriate behavior. Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. Consequence: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. Community Impact Guidelines were inspired by Mozilla’s code of conduct enforcement ladder. For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. laravel-datatables-oracle/sonar-project.properties 0000644 00000000143 15060167532 0016446 0 ustar 00 # Define separate root directories for sources and tests sonar.sources = src/ sonar.tests = tests/ laravel-datatables-oracle/src/QueryDataTable.php 0000644 00000071462 15060167532 0015725 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Contracts\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Contracts\Database\Query\Builder as QueryBuilder; use Illuminate\Database\Connection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Query\Expression; use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use Yajra\DataTables\Utilities\Helper; class QueryDataTable extends DataTableAbstract { /** * Flag for ordering NULLS LAST option. */ protected bool $nullsLast = false; /** * Flag to check if query preparation was already done. */ protected bool $prepared = false; /** * Query callback for custom pagination using limit without offset. * * @var callable|null */ protected $limitCallback = null; /** * Flag to keep the select bindings. */ protected bool $keepSelectBindings = false; /** * Flag to ignore the selects in count query. */ protected bool $ignoreSelectInCountQuery = false; /** * Enable scout search and use this model for searching. */ protected ?Model $scoutModel = null; /** * Maximum number of hits to return from scout. */ protected int $scoutMaxHits = 1000; /** * Add dynamic filters to scout search. * * @var callable|null */ protected $scoutFilterCallback = null; /** * Flag if scout search was performed. */ protected bool $scoutSearched = false; /** * Scout index name. */ protected string $scoutIndex; /** * Scout key name. */ protected string $scoutKey; /** * Flag to disable user ordering if a fixed ordering was performed (e.g. scout search). * Only works with corresponding javascript listener. */ protected bool $disableUserOrdering = false; public function __construct(protected QueryBuilder $query) { $this->request = app('datatables.request'); $this->config = app('datatables.config'); $this->columns = $this->query->getColumns(); if ($this->config->isDebugging()) { $this->getConnection()->enableQueryLog(); } } public function getConnection(): Connection { /** @var Connection $connection */ $connection = $this->query->getConnection(); return $connection; } /** * Can the DataTable engine be created with these parameters. * * @param mixed $source */ public static function canCreate($source): bool { return $source instanceof QueryBuilder && ! ($source instanceof EloquentBuilder); } /** * Organizes works. * * @throws \Exception */ public function make(bool $mDataSupport = true): JsonResponse { try { $results = $this->prepareQuery()->results(); $processed = $this->processResults($results, $mDataSupport); $data = $this->transform($results, $processed); return $this->render($data); } catch (\Exception $exception) { return $this->errorResponse($exception); } } /** * Get paginated results. * * @return \Illuminate\Support\Collection<int, array> */ public function results(): Collection { return $this->query->get(); } /** * Prepare query by executing count, filter, order and paginate. * * @return $this */ public function prepareQuery(): static { if (! $this->prepared) { $this->totalRecords = $this->totalCount(); $this->filterRecords(); $this->ordering(); $this->paginate(); } $this->prepared = true; return $this; } /** * Counts current query. */ public function count(): int { return $this->prepareCountQuery()->count(); } /** * Prepare count query builder. */ public function prepareCountQuery(): QueryBuilder { $builder = clone $this->query; if ($this->isComplexQuery($builder)) { $builder->select(DB::raw('1 as dt_row_count')); $clone = $builder->clone(); $clone->setBindings([]); if ($clone instanceof EloquentBuilder) { $clone->getQuery()->wheres = []; } else { $clone->wheres = []; } if ($this->isComplexQuery($clone)) { if (! $this->ignoreSelectInCountQuery) { $builder = clone $this->query; } return $this->getConnection() ->query() ->fromRaw('('.$builder->toSql().') count_row_table') ->setBindings($builder->getBindings()); } } $row_count = $this->wrap('row_count'); $builder->select($this->getConnection()->raw("'1' as {$row_count}")); if (! $this->keepSelectBindings) { $builder->setBindings([], 'select'); } return $builder; } /** * Check if builder query uses complex sql. * * @param QueryBuilder|EloquentBuilder $query */ protected function isComplexQuery($query): bool { return Str::contains(Str::lower($query->toSql()), ['union', 'having', 'distinct', 'order by', 'group by']); } /** * Wrap column with DB grammar. */ protected function wrap(string $column): string { return $this->getConnection()->getQueryGrammar()->wrap($column); } /** * Keep the select bindings. * * @return $this */ public function keepSelectBindings(): static { $this->keepSelectBindings = true; return $this; } /** * Perform column search. */ protected function filterRecords(): void { $initialQuery = clone $this->query; if ($this->autoFilter && $this->request->isSearchable()) { $this->filtering(); } if (is_callable($this->filterCallback)) { call_user_func_array($this->filterCallback, $this->resolveCallbackParameter()); } $this->columnSearch(); $this->searchPanesSearch(); // If no modification between the original query and the filtered one has been made // the filteredRecords equals the totalRecords if ($this->query == $initialQuery) { $this->filteredRecords ??= $this->totalRecords; } else { $this->filteredCount(); } } /** * Perform column search. */ public function columnSearch(): void { $columns = $this->request->columns(); foreach ($columns as $index => $column) { $column = $this->getColumnName($index); if (is_null($column)) { continue; } if (! $this->request->isColumnSearchable($index) || $this->isBlacklisted($column) && ! $this->hasFilterColumn($column)) { continue; } if ($this->hasFilterColumn($column)) { $keyword = $this->getColumnSearchKeyword($index, true); $this->applyFilterColumn($this->getBaseQueryBuilder(), $column, $keyword); } else { $column = $this->resolveRelationColumn($column); $keyword = $this->getColumnSearchKeyword($index); $this->compileColumnSearch($index, $column, $keyword); } } } /** * Check if column has custom filter handler. */ public function hasFilterColumn(string $columnName): bool { return isset($this->columnDef['filter'][$columnName]); } /** * Get column keyword to use for search. */ protected function getColumnSearchKeyword(int $i, bool $raw = false): string { $keyword = $this->request->columnKeyword($i); if ($raw || $this->request->isRegex($i)) { return $keyword; } return $this->setupKeyword($keyword); } protected function getColumnNameByIndex(int $index): string { $name = (isset($this->columns[$index]) && $this->columns[$index] != '*') ? $this->columns[$index] : $this->getPrimaryKeyName(); if ($name instanceof Expression) { $name = $name->getValue($this->query->getGrammar()); } return in_array($name, $this->extraColumns, true) ? $this->getPrimaryKeyName() : $name; } /** * Apply filterColumn api search. * * @param QueryBuilder $query */ protected function applyFilterColumn($query, string $columnName, string $keyword, string $boolean = 'and'): void { $query = $this->getBaseQueryBuilder($query); $callback = $this->columnDef['filter'][$columnName]['method']; if ($this->query instanceof EloquentBuilder) { $builder = $this->query->newModelInstance()->newQuery(); } else { $builder = $this->query->newQuery(); } $callback($builder, $keyword); /** @var \Illuminate\Database\Query\Builder $baseQueryBuilder */ $baseQueryBuilder = $this->getBaseQueryBuilder($builder); $query->addNestedWhereQuery($baseQueryBuilder, $boolean); } /** * Get the base query builder instance. * * @param QueryBuilder|EloquentBuilder|null $instance */ protected function getBaseQueryBuilder($instance = null): QueryBuilder { if (! $instance) { $instance = $this->query; } if ($instance instanceof EloquentBuilder) { return $instance->getQuery(); } return $instance; } /** * Get query builder instance. */ public function getQuery(): QueryBuilder { return $this->query; } /** * Resolve the proper column name be used. */ protected function resolveRelationColumn(string $column): string { return $column; } /** * Compile queries for column search. */ protected function compileColumnSearch(int $i, string $column, string $keyword): void { if ($this->request->isRegex($i)) { $this->regexColumnSearch($column, $keyword); } else { $this->compileQuerySearch($this->query, $column, $keyword, ''); } } /** * Compile regex query column search. */ protected function regexColumnSearch(string $column, string $keyword): void { $column = $this->wrap($column); switch ($this->getConnection()->getDriverName()) { case 'oracle': $sql = ! $this->config->isCaseInsensitive() ? 'REGEXP_LIKE( '.$column.' , ? )' : 'REGEXP_LIKE( LOWER('.$column.') , ?, \'i\' )'; break; case 'pgsql': $column = $this->castColumn($column); $sql = ! $this->config->isCaseInsensitive() ? $column.' ~ ?' : $column.' ~* ? '; break; default: $sql = ! $this->config->isCaseInsensitive() ? $column.' REGEXP ?' : 'LOWER('.$column.') REGEXP ?'; $keyword = Str::lower($keyword); } $this->query->whereRaw($sql, [$keyword]); } /** * Wrap a column and cast based on database driver. */ protected function castColumn(string $column): string { return match ($this->getConnection()->getDriverName()) { 'pgsql' => 'CAST('.$column.' as TEXT)', 'firebird' => 'CAST('.$column.' as VARCHAR(255))', default => $column, }; } /** * Compile query builder where clause depending on configurations. * * @param QueryBuilder|EloquentBuilder $query */ protected function compileQuerySearch($query, string $column, string $keyword, string $boolean = 'or'): void { $column = $this->addTablePrefix($query, $column); $column = $this->castColumn($column); $sql = $column.' LIKE ?'; if ($this->config->isCaseInsensitive()) { $sql = 'LOWER('.$column.') LIKE ?'; } $query->{$boolean.'WhereRaw'}($sql, [$this->prepareKeyword($keyword)]); } /** * Patch for fix about ambiguous field. * Ambiguous field error will appear when query use join table and search with keyword. * * @param QueryBuilder|EloquentBuilder $query */ protected function addTablePrefix($query, string $column): string { if (! str_contains($column, '.')) { $q = $this->getBaseQueryBuilder($query); $from = $q->from ?? ''; if (! $from instanceof Expression) { if (str_contains((string) $from, ' as ')) { $from = explode(' as ', (string) $from)[1]; } $column = $from.'.'.$column; } } return $this->wrap($column); } /** * Prepare search keyword based on configurations. */ protected function prepareKeyword(string $keyword): string { if ($this->config->isCaseInsensitive()) { $keyword = Str::lower($keyword); } if ($this->config->isStartsWithSearch()) { return "$keyword%"; } if ($this->config->isWildcard()) { $keyword = Helper::wildcardLikeString($keyword); } if ($this->config->isSmartSearch()) { $keyword = "%$keyword%"; } return $keyword; } /** * Add custom filter handler for the give column. * * @param string $column * @return $this */ public function filterColumn($column, callable $callback): static { $this->columnDef['filter'][$column] = ['method' => $callback]; return $this; } /** * Order each given columns versus the given custom sql. * * @param string $sql * @param array $bindings * @return $this */ public function orderColumns(array $columns, $sql, $bindings = []): static { foreach ($columns as $column) { $this->orderColumn($column, str_replace(':column', $column, $sql), $bindings); } return $this; } /** * Override default column ordering. * * @param string $column * @param string|\Closure $sql * @param array $bindings * @return $this * * @internal string $1 Special variable that returns the requested order direction of the column. */ public function orderColumn($column, $sql, $bindings = []): static { $this->columnDef['order'][$column] = compact('sql', 'bindings'); return $this; } /** * Set datatables to do ordering with NULLS LAST option. * * @return $this */ public function orderByNullsLast(): static { $this->nullsLast = true; return $this; } /** * Perform pagination. */ public function paging(): void { $start = $this->request->start(); $length = $this->request->length(); $limit = $length > 0 ? $length : 10; if (is_callable($this->limitCallback)) { $this->query->limit($limit); call_user_func_array($this->limitCallback, [$this->query]); } else { $this->query->skip($start)->take($limit); } } /** * Paginate dataTable using limit without offset * with additional where clause via callback. * * @return $this */ public function limit(callable $callback): static { $this->limitCallback = $callback; return $this; } /** * Add column in collection. * * @param string $name * @param string|callable $content * @param bool|int $order * @return $this */ public function addColumn($name, $content, $order = false): static { $this->pushToBlacklist($name); return parent::addColumn($name, $content, $order); } /** * Perform search using search pane values. * * * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface */ protected function searchPanesSearch(): void { /** @var string[] $columns */ $columns = $this->request->get('searchPanes', []); foreach ($columns as $column => $values) { if ($this->isBlacklisted($column)) { continue; } if ($this->searchPanes[$column] && $callback = $this->searchPanes[$column]['builder']) { $callback($this->query, $values); } else { $this->query->whereIn($column, $values); } } } /** * Resolve callback parameter instance. * * @return array<int|string, mixed> */ protected function resolveCallbackParameter(): array { return [$this->query, $this->scoutSearched]; } /** * Perform default query orderBy clause. * * * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface */ protected function defaultOrdering(): void { collect($this->request->orderableColumns()) ->map(function ($orderable) { $orderable['name'] = $this->getColumnName($orderable['column'], true); return $orderable; }) ->reject(fn ($orderable) => $this->isBlacklisted($orderable['name']) && ! $this->hasOrderColumn($orderable['name'])) ->each(function ($orderable) { $column = $this->resolveRelationColumn($orderable['name']); if ($this->hasOrderColumn($orderable['name'])) { $this->applyOrderColumn($orderable['name'], $orderable); } elseif ($this->hasOrderColumn($column)) { $this->applyOrderColumn($column, $orderable); } else { $nullsLastSql = $this->getNullsLastSql($column, $orderable['direction']); $normalSql = $this->wrap($column).' '.$orderable['direction']; $sql = $this->nullsLast ? $nullsLastSql : $normalSql; $this->query->orderByRaw($sql); } }); } /** * Check if column has custom sort handler. */ protected function hasOrderColumn(string $column): bool { return isset($this->columnDef['order'][$column]); } /** * Apply orderColumn custom query. */ protected function applyOrderColumn(string $column, array $orderable): void { $sql = $this->columnDef['order'][$column]['sql']; if ($sql === false) { return; } if (is_callable($sql)) { call_user_func($sql, $this->query, $orderable['direction']); } else { $sql = str_replace('$1', $orderable['direction'], (string) $sql); $bindings = $this->columnDef['order'][$column]['bindings']; $this->query->orderByRaw($sql, $bindings); } } /** * Get NULLS LAST SQL. * * @param string $column * @param string $direction * * @throws \Psr\Container\ContainerExceptionInterface * @throws \Psr\Container\NotFoundExceptionInterface */ protected function getNullsLastSql($column, $direction): string { /** @var string $sql */ $sql = $this->config->get('datatables.nulls_last_sql', '%s %s NULLS LAST'); return str_replace( [':column', ':direction'], [$column, $direction], sprintf($sql, $column, $direction) ); } /** * Perform global search for the given keyword. */ protected function globalSearch(string $keyword): void { // Try scout search first & fall back to default search if disabled/failed if ($this->applyScoutSearch($keyword)) { return; } $this->query->where(function ($query) use ($keyword) { collect($this->request->searchableColumnIndex()) ->map(fn ($index) => $this->getColumnName($index)) ->filter() ->reject(fn ($column) => $this->isBlacklisted($column) && ! $this->hasFilterColumn($column)) ->each(function ($column) use ($keyword, $query) { if ($this->hasFilterColumn($column)) { $this->applyFilterColumn($query, $column, $keyword, 'or'); } else { $this->compileQuerySearch($query, $column, $keyword); } }); }); } /** * Perform multi-term search by splitting keyword into * individual words and searches for each of them. * * @param string $keyword */ protected function smartGlobalSearch($keyword): void { // Try scout search first & fall back to default search if disabled/failed if ($this->applyScoutSearch($keyword)) { return; } parent::smartGlobalSearch($keyword); } /** * Append debug parameters on output. */ protected function showDebugger(array $output): array { $query_log = $this->getConnection()->getQueryLog(); array_walk_recursive($query_log, function (&$item) { if (is_string($item) && extension_loaded('iconv')) { $item = iconv('iso-8859-1', 'utf-8', $item); } }); $output['queries'] = $query_log; $output['input'] = $this->request->all(); return $output; } /** * Attach custom with meta on response. */ protected function attachAppends(array $data): array { $appends = []; foreach ($this->appends as $key => $value) { if (is_callable($value)) { $appends[$key] = value($value($this->getFilteredQuery())); } else { $appends[$key] = $value; } } // Set flag to disable ordering $appends['disableOrdering'] = $this->disableUserOrdering; return array_merge($data, $appends); } /** * Get filtered, ordered and paginated query. */ public function getFilteredQuery(): QueryBuilder { $this->prepareQuery(); return $this->getQuery(); } /** * Ignore the selects in count query. * * @return $this */ public function ignoreSelectsInCountQuery(): static { $this->ignoreSelectInCountQuery = true; return $this; } /** * Perform sorting of columns. */ public function ordering(): void { // Skip if user ordering is disabled (e.g. scout search) if ($this->disableUserOrdering) { return; } parent::ordering(); } /** * Enable scout search and use provided model for searching. * $max_hits is the maximum number of hits to return from scout. * * @return $this * * @throws \Exception */ public function enableScoutSearch(string $model, int $max_hits = 1000): static { $scout_model = new $model; if (! class_exists($model) || ! ($scout_model instanceof Model)) { throw new \Exception("$model must be an Eloquent Model."); } if (! method_exists($scout_model, 'searchableAs') || ! method_exists($scout_model, 'getScoutKeyName')) { throw new \Exception("$model must use the Searchable trait."); } $this->scoutModel = $scout_model; $this->scoutMaxHits = $max_hits; $this->scoutIndex = $this->scoutModel->searchableAs(); $this->scoutKey = $this->scoutModel->getScoutKeyName(); return $this; } /** * Add dynamic filters to scout search. * * @return $this */ public function scoutFilter(callable $callback): static { $this->scoutFilterCallback = $callback; return $this; } /** * Apply scout search to query if enabled. */ protected function applyScoutSearch(string $search_keyword): bool { if ($this->scoutModel == null) { return false; } try { // Perform scout search $search_filters = ''; if (is_callable($this->scoutFilterCallback)) { $search_filters = ($this->scoutFilterCallback)($search_keyword); } $search_results = $this->performScoutSearch($search_keyword, $search_filters); // Apply scout search results to query $this->query->where(function ($query) use ($search_results) { $this->query->whereIn($this->scoutKey, $search_results); }); // Order by scout search results & disable user ordering (if db driver is supported) if (count($search_results) > 0 && $this->applyFixedOrderingToQuery($this->scoutKey, $search_results)) { // Disable user ordering because we already ordered by search relevancy $this->disableUserOrdering = true; } $this->scoutSearched = true; return true; } catch (\Exception) { // Scout search failed, fallback to default search return false; } } /** * Apply fixed ordering to query by a fixed set of values depending on database driver (used for scout search). * * Currently supported drivers: MySQL * * @return bool */ protected function applyFixedOrderingToQuery(string $keyName, array $orderedKeys) { $connection = $this->getConnection(); $driverName = $connection->getDriverName(); // Escape keyName and orderedKeys $keyName = $connection->getQueryGrammar()->wrap($keyName); $orderedKeys = collect($orderedKeys) ->map(fn ($value) => $connection->escape($value)); switch ($driverName) { case 'mariadb': case 'mysql': $this->query->orderByRaw("FIELD($keyName, ".$orderedKeys->implode(',').')'); return true; case 'pgsql': case 'oracle': $this->query->orderByRaw( 'CASE ' . $orderedKeys ->map(fn ($value, $index) => "WHEN $keyName=$value THEN $index") ->implode(' ') . ' END' ); return true; case 'sqlite': case 'sqlsrv': $this->query->orderByRaw( "CASE $keyName " . $orderedKeys ->map(fn ($value, $index) => "WHEN $value THEN $index") ->implode(' ') . ' END' ); return true; default: return false; } } /** * Perform a scout search with the configured engine and given parameters. Return matching model IDs. * * * @throws \Exception */ protected function performScoutSearch(string $searchKeyword, mixed $searchFilters = []): array { if (! class_exists(\Laravel\Scout\EngineManager::class)) { throw new \Exception('Laravel Scout is not installed.'); } $engine = app(\Laravel\Scout\EngineManager::class)->engine(); if ($engine instanceof \Laravel\Scout\Engines\MeilisearchEngine) { /** @var \Meilisearch\Client $engine */ $search_results = $engine ->index($this->scoutIndex) ->rawSearch($searchKeyword, [ 'limit' => $this->scoutMaxHits, 'attributesToRetrieve' => [$this->scoutKey], 'filter' => $searchFilters, ]); /** @var array<int, array<string, mixed>> $hits */ $hits = $search_results['hits'] ?? []; return collect($hits) ->pluck($this->scoutKey) ->all(); } elseif ($engine instanceof \Laravel\Scout\Engines\AlgoliaEngine) { /** @var \Algolia\AlgoliaSearch\SearchClient $engine */ $algolia = $engine->initIndex($this->scoutIndex); $search_results = $algolia->search($searchKeyword, [ 'offset' => 0, 'length' => $this->scoutMaxHits, 'attributesToRetrieve' => [$this->scoutKey], 'attributesToHighlight' => [], 'filters' => $searchFilters, ]); /** @var array<int, array<string, mixed>> $hits */ $hits = $search_results['hits'] ?? []; return collect($hits) ->pluck($this->scoutKey) ->all(); } else { throw new \Exception('Unsupported Scout Engine. Currently supported: Meilisearch, Algolia'); } } } laravel-datatables-oracle/src/Processors/DataProcessor.php 0000644 00000015465 15060167532 0017772 0 ustar 00 <?php namespace Yajra\DataTables\Processors; use Illuminate\Contracts\Support\Htmlable; use Illuminate\Support\Arr; use Yajra\DataTables\Contracts\Formatter; use Yajra\DataTables\Utilities\Helper; class DataProcessor { protected array $output = []; /** * @var array<array-key, array{name: string, content: mixed}> */ protected array $appendColumns = []; /** * @var array<array-key, array{name: string, content: mixed}> */ protected array $editColumns = []; protected array $rawColumns = []; /** * @var array|string[] */ protected array $exceptions = ['DT_RowId', 'DT_RowClass', 'DT_RowData', 'DT_RowAttr']; protected array $onlyColumns = []; protected array $makeHidden = []; protected array $makeVisible = []; protected array $excessColumns = []; /** * @var string|array */ protected mixed $escapeColumns = []; protected bool $includeIndex = false; protected bool $ignoreGetters = false; public function __construct(protected iterable $results, array $columnDef, protected array $templates, protected int $start = 0) { $this->appendColumns = $columnDef['append'] ?? []; $this->editColumns = $columnDef['edit'] ?? []; $this->excessColumns = $columnDef['excess'] ?? []; $this->onlyColumns = $columnDef['only'] ?? []; $this->escapeColumns = $columnDef['escape'] ?? []; $this->includeIndex = $columnDef['index'] ?? false; $this->rawColumns = $columnDef['raw'] ?? []; $this->makeHidden = $columnDef['hidden'] ?? []; $this->makeVisible = $columnDef['visible'] ?? []; $this->ignoreGetters = $columnDef['ignore_getters'] ?? false; } /** * Process data to output on browser. * * @param bool $object */ public function process($object = false): array { $this->output = []; $indexColumn = config('datatables.index_column', 'DT_RowIndex'); foreach ($this->results as $row) { $data = Helper::convertToArray($row, ['hidden' => $this->makeHidden, 'visible' => $this->makeVisible, 'ignore_getters' => $this->ignoreGetters]); $value = $this->addColumns($data, $row); $value = $this->editColumns($value, $row); $value = $this->setupRowVariables($value, $row); $value = $this->selectOnlyNeededColumns($value); $value = $this->removeExcessColumns($value); if ($this->includeIndex) { $value[$indexColumn] = ++$this->start; } $this->output[] = $object ? $value : $this->flatten($value); } return $this->escapeColumns($this->output); } /** * Process add columns. * * @param array|object|\Illuminate\Database\Eloquent\Model $row */ protected function addColumns(array $data, $row): array { foreach ($this->appendColumns as $value) { $content = $value['content']; if ($content instanceof Formatter) { $column = str_replace('_formatted', '', $value['name']); $value['content'] = $content->format($data[$column], $row); if (isset($data[$column])) { $value['content'] = $content->format($data[$column], $row); } } else { $value['content'] = Helper::compileContent($content, $data, $row); } $data = Helper::includeInArray($value, $data); } return $data; } /** * Process edit columns. */ protected function editColumns(array $data, object|array $row): array { foreach ($this->editColumns as $value) { $value['content'] = Helper::compileContent($value['content'], $data, $row); Arr::set($data, $value['name'], $value['content']); } return $data; } /** * Setup additional DT row variables. */ protected function setupRowVariables(array $data, object|array $row): array { $processor = new RowProcessor($data, $row); return $processor ->rowValue('DT_RowId', $this->templates['DT_RowId']) ->rowValue('DT_RowClass', $this->templates['DT_RowClass']) ->rowData('DT_RowData', $this->templates['DT_RowData']) ->rowData('DT_RowAttr', $this->templates['DT_RowAttr']) ->getData(); } /** * Get only needed columns. */ protected function selectOnlyNeededColumns(array $data): array { if (empty($this->onlyColumns)) { return $data; } else { $results = []; foreach ($this->onlyColumns as $onlyColumn) { Arr::set($results, $onlyColumn, Arr::get($data, $onlyColumn)); } foreach ($this->exceptions as $exception) { if ($column = Arr::get($data, $exception)) { Arr::set($results, $exception, $column); } } return $results; } } /** * Remove declared hidden columns. */ protected function removeExcessColumns(array $data): array { foreach ($this->excessColumns as $value) { Arr::forget($data, $value); } return $data; } /** * Flatten array with exceptions. */ public function flatten(array $array): array { $return = []; foreach ($array as $key => $value) { if (in_array($key, $this->exceptions)) { $return[$key] = $value; } else { $return[] = $value; } } return $return; } /** * Escape column values as declared. */ protected function escapeColumns(array $output): array { return array_map(function ($row) { if ($this->escapeColumns == '*') { $row = $this->escapeRow($row); } elseif (is_array($this->escapeColumns)) { $columns = array_diff($this->escapeColumns, $this->rawColumns); foreach ($columns as $key) { /** @var string $content */ $content = Arr::get($row, $key); Arr::set($row, $key, e($content)); } } return $row; }, $output); } /** * Escape all string or Htmlable values of row. */ protected function escapeRow(array $row): array { $arrayDot = array_filter(Arr::dot($row)); foreach ($arrayDot as $key => $value) { if (! in_array($key, $this->rawColumns)) { $arrayDot[$key] = (is_string($value) || $value instanceof Htmlable) ? e($value) : $value; } } foreach ($arrayDot as $key => $value) { Arr::set($row, $key, $value); } return $row; } } laravel-datatables-oracle/src/Processors/RowProcessor.php 0000644 00000002752 15060167532 0017663 0 ustar 00 <?php namespace Yajra\DataTables\Processors; use Illuminate\Support\Arr; use Yajra\DataTables\Utilities\Helper; class RowProcessor { /** * @param array|object $row */ public function __construct(protected array $data, protected $row) { } /** * Process DT RowId and Class value. * * @param string $attribute * @param string|callable $template * @return $this * * @throws \ReflectionException */ public function rowValue($attribute, $template) { if (! empty($template)) { if (! is_callable($template) && Arr::get($this->data, $template)) { $this->data[$attribute] = Arr::get($this->data, $template); } else { $this->data[$attribute] = Helper::compileContent($template, $this->data, $this->row); } } return $this; } /** * Process DT Row Data and Attr. * * @param string $attribute * @return $this * * @throws \ReflectionException */ public function rowData($attribute, array $template) { if (count($template)) { $this->data[$attribute] = []; foreach ($template as $key => $value) { $this->data[$attribute][$key] = Helper::compileContent($value, $this->data, $this->row); } } return $this; } /** * @return array */ public function getData() { return $this->data; } } laravel-datatables-oracle/src/DataTables.php 0000644 00000010562 15060167532 0015054 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Contracts\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Contracts\Database\Query\Builder as QueryBuilder; use Illuminate\Support\Traits\Macroable; use Yajra\DataTables\Exceptions\Exception; use Yajra\DataTables\Utilities\Config; use Yajra\DataTables\Utilities\Request; class DataTables { use Macroable; /** * DataTables request object. */ protected Utilities\Request $request; /** * Make a DataTable instance from source. * Alias of make for backward compatibility. * * @param object $source * @return DataTableAbstract * * @throws \Exception */ public static function of($source) { return self::make($source); } /** * Make a DataTable instance from source. * * @param object $source * @return DataTableAbstract * * @throws \Yajra\DataTables\Exceptions\Exception */ public static function make($source) { $engines = (array) config('datatables.engines'); $builders = (array) config('datatables.builders'); $args = func_get_args(); foreach ($builders as $class => $engine) { if ($source instanceof $class) { $callback = [$engines[$engine], 'create']; if (is_callable($callback)) { /** @var \Yajra\DataTables\DataTableAbstract $instance */ $instance = call_user_func_array($callback, $args); return $instance; } } } foreach ($engines as $engine) { $canCreate = [$engine, 'canCreate']; if (is_callable($canCreate) && call_user_func_array($canCreate, $args)) { $create = [$engine, 'create']; if (is_callable($create)) { /** @var \Yajra\DataTables\DataTableAbstract $instance */ $instance = call_user_func_array($create, $args); return $instance; } } } throw new Exception('No available engine for '.$source::class); } /** * Get request object. */ public function getRequest(): Request { return app('datatables.request'); } /** * Get config instance. */ public function getConfig(): Config { return app('datatables.config'); } /** * DataTables using query builder. * * @throws \Yajra\DataTables\Exceptions\Exception */ public function query(QueryBuilder $builder): QueryDataTable { /** @var string $dataTable */ $dataTable = config('datatables.engines.query'); $this->validateDataTable($dataTable, QueryDataTable::class); return $dataTable::create($builder); } /** * DataTables using Eloquent Builder. * * @throws \Yajra\DataTables\Exceptions\Exception */ public function eloquent(EloquentBuilder $builder): EloquentDataTable { /** @var string $dataTable */ $dataTable = config('datatables.engines.eloquent'); $this->validateDataTable($dataTable, EloquentDataTable::class); return $dataTable::create($builder); } /** * DataTables using Collection. * * @param \Illuminate\Support\Collection<array-key, array>|array $collection * * @throws \Yajra\DataTables\Exceptions\Exception */ public function collection($collection): CollectionDataTable { /** @var string $dataTable */ $dataTable = config('datatables.engines.collection'); $this->validateDataTable($dataTable, CollectionDataTable::class); return $dataTable::create($collection); } /** * DataTables using Collection. * * @param \Illuminate\Http\Resources\Json\AnonymousResourceCollection<array-key, array>|array $resource * @return ApiResourceDataTable|DataTableAbstract */ public function resource($resource) { return ApiResourceDataTable::create($resource); } /** * @throws \Yajra\DataTables\Exceptions\Exception */ public function validateDataTable(string $engine, string $parent): void { if (! ($engine == $parent || is_subclass_of($engine, $parent))) { throw new Exception("The given datatable engine `$engine` is not compatible with `$parent`."); } } } laravel-datatables-oracle/src/helper.php 0000644 00000001356 15060167532 0014330 0 ustar 00 <?php if (! function_exists('datatables')) { /** * Helper to make a new DataTable instance from source. * Or return the factory if source is not set. * * @param \Illuminate\Contracts\Database\Query\Builder|\Illuminate\Contracts\Database\Eloquent\Builder|\Illuminate\Support\Collection|array|null $source * @return \Yajra\DataTables\DataTables|\Yajra\DataTables\DataTableAbstract * * @throws \Yajra\DataTables\Exceptions\Exception */ function datatables($source = null) { /** @var Yajra\DataTables\DataTables $dataTable */ $dataTable = app('datatables'); if (is_null($source)) { return $dataTable; } return $dataTable->make($source); } } laravel-datatables-oracle/src/Utilities/Request.php 0000644 00000013333 15060167532 0016452 0 ustar 00 <?php namespace Yajra\DataTables\Utilities; use Illuminate\Http\Request as BaseRequest; /** * @mixin \Illuminate\Http\Request */ class Request { protected BaseRequest $request; /** * Request constructor. */ public function __construct() { $this->request = app('request'); } /** * Proxy non-existing method calls to base request class. * * @param string $name * @param array $arguments * @return mixed */ public function __call($name, $arguments) { $callback = [$this->request, $name]; if (is_callable($callback)) { return call_user_func_array($callback, $arguments); } } /** * Get attributes from request instance. * * @param string $name * @return mixed */ public function __get($name) { return $this->request->__get($name); } /** * Get all columns request input. */ public function columns(): array { return (array) $this->request->input('columns'); } /** * Check if DataTables is searchable. */ public function isSearchable(): bool { return $this->request->input('search.value') != ''; } /** * Check if DataTables must uses regular expressions. */ public function isRegex(int $index): bool { return $this->request->input("columns.$index.search.regex") === 'true'; } /** * Get orderable columns. */ public function orderableColumns(): array { if (! $this->isOrderable()) { return []; } $orderable = []; for ($i = 0, $c = count((array) $this->request->input('order')); $i < $c; $i++) { /** @var int $order_col */ $order_col = $this->request->input("order.$i.column"); /** @var string $direction */ $direction = $this->request->input("order.$i.dir"); $order_dir = strtolower($direction) === 'asc' ? 'asc' : 'desc'; if ($this->isColumnOrderable($order_col)) { $orderable[] = ['column' => $order_col, 'direction' => $order_dir]; } } return $orderable; } /** * Check if DataTables ordering is enabled. */ public function isOrderable(): bool { return $this->request->input('order') && count((array) $this->request->input('order')) > 0; } /** * Check if a column is orderable. */ public function isColumnOrderable(int $index): bool { return $this->request->input("columns.$index.orderable", 'true') == 'true'; } /** * Get searchable column indexes. * * @return array */ public function searchableColumnIndex() { $searchable = []; $columns = (array) $this->request->input('columns'); for ($i = 0, $c = count($columns); $i < $c; $i++) { if ($this->isColumnSearchable($i, false)) { $searchable[] = $i; } } return $searchable; } /** * Check if a column is searchable. */ public function isColumnSearchable(int $i, bool $column_search = true): bool { if ($column_search) { return ( $this->request->input("columns.$i.searchable", 'true') === 'true' || $this->request->input("columns.$i.searchable", 'true') === true ) && $this->columnKeyword($i) != ''; } return $this->request->input("columns.$i.searchable", 'true') === 'true' || $this->request->input("columns.$i.searchable", 'true') === true; } /** * Get column's search value. */ public function columnKeyword(int $index): string { /** @var string $keyword */ $keyword = $this->request->input("columns.$index.search.value") ?? ''; return $this->prepareKeyword($keyword); } /** * Prepare keyword string value. */ protected function prepareKeyword(float|array|int|string $keyword): string { if (is_array($keyword)) { return implode(' ', $keyword); } return (string) $keyword; } /** * Get global search keyword. */ public function keyword(): string { /** @var string $keyword */ $keyword = $this->request->input('search.value') ?? ''; return $this->prepareKeyword($keyword); } /** * Get column name by index. */ public function columnName(int $i): ?string { /** @var string[] $column */ $column = $this->request->input("columns.$i"); return (isset($column['name']) && $column['name'] != '') ? $column['name'] : $column['data']; } /** * Check if DataTables allow pagination. */ public function isPaginationable(): bool { return ! is_null($this->request->input('start')) && ! is_null($this->request->input('length')) && $this->request->input('length') != -1; } public function getBaseRequest(): BaseRequest { return $this->request; } /** * Get starting record value. */ public function start(): int { $start = $this->request->input('start', 0); return is_numeric($start) ? intval($start) : 0; } /** * Get per page length. */ public function length(): int { $length = $this->request->input('length', 10); return is_numeric($length) ? intval($length) : 10; } /** * Get draw request. */ public function draw(): int { $draw = $this->request->input('draw', 0); return is_numeric($draw) ? intval($draw) : 0; } } laravel-datatables-oracle/src/Utilities/Helper.php 0000644 00000025100 15060167532 0016234 0 ustar 00 <?php namespace Yajra\DataTables\Utilities; use Closure; use DateTime; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Support\Arr; use Illuminate\Support\Str; use ReflectionFunction; use ReflectionMethod; class Helper { /** * Places item of extra columns into results by care of their order. */ public static function includeInArray(array $item, array $array): array { if (self::isItemOrderInvalid($item, $array)) { return array_merge($array, [$item['name'] => $item['content']]); } $count = 0; $last = $array; $first = []; foreach ($array as $key => $value) { if ($count == $item['order']) { continue; } unset($last[$key]); $first[$key] = $value; $count++; } return array_merge($first, [$item['name'] => $item['content']], $last); } /** * Check if item order is valid. */ protected static function isItemOrderInvalid(array $item, array $array): bool { return $item['order'] === false || $item['order'] >= count($array); } /** * Gets the parameter of a callable thing (from is_callable) and returns it's arguments using reflection. * * @param callable $callable * @return \ReflectionParameter[] * * @throws \ReflectionException * @throws \InvalidArgumentException */ private static function reflectCallableParameters($callable) { /* loosely after https://github.com/technically-php/callable-reflection/blob/main/src/CallableReflection.php#L72-L86. Licence is compatible, both project use MIT */ if ($callable instanceof Closure) { $reflection = new ReflectionFunction($callable); } elseif (is_string($callable) && function_exists($callable)) { $reflection = new ReflectionFunction($callable); } elseif (is_string($callable) && str_contains($callable, '::')) { $reflection = new ReflectionMethod($callable); } elseif (is_object($callable) && method_exists($callable, '__invoke')) { $reflection = new ReflectionMethod($callable, '__invoke'); } else { throw new \InvalidArgumentException('argument is not callable or the code is wrong'); } return $reflection->getParameters(); } /** * Determines if content is callable or blade string, processes and returns. * * @param mixed $content Pre-processed content * @param array $data data to use with blade template * @param array|object $param parameter to call with callable * @return mixed * * @throws \ReflectionException */ public static function compileContent(mixed $content, array $data, array|object $param) { if (is_string($content)) { return static::compileBlade($content, static::getMixedValue($data, $param)); } if (is_callable($content)) { $arguments = self::reflectCallableParameters($content); if (count($arguments) > 0) { return app()->call($content, [$arguments[0]->name => $param]); } return $content($param); } if (is_array($content)) { [$view, $viewData] = $content; return static::compileBlade($view, static::getMixedValue($data, $param) + $viewData); } return $content; } /** * Parses and compiles strings by using Blade Template System. * * * @throws \Throwable */ public static function compileBlade(string $str, array $data = []): false|string { if (view()->exists($str)) { /** @var view-string $str */ return view($str, $data)->render(); } ob_start() && extract($data, EXTR_SKIP); eval('?>'.app('blade.compiler')->compileString($str)); $str = ob_get_contents(); ob_end_clean(); return $str; } /** * Get a mixed value of custom data and the parameters. */ public static function getMixedValue(array $data, array|object $param): array { $casted = self::castToArray($param); $data['model'] = $param; foreach ($data as $key => $value) { if (isset($casted[$key])) { $data[$key] = $casted[$key]; } } return $data; } /** * Cast the parameter into an array. */ public static function castToArray(array|object $param): array { if ($param instanceof Arrayable) { return $param->toArray(); } return (array) $param; } /** * Get equivalent or method of query builder. */ public static function getOrMethod(string $method): string { if (! Str::contains(Str::lower($method), 'or')) { return 'or'.ucfirst($method); } return $method; } /** * Converts array object values to associative array. */ public static function convertToArray(mixed $row, array $filters = []): array { if (Arr::get($filters, 'ignore_getters') && is_object($row) && method_exists($row, 'getAttributes')) { $data = $row->getAttributes(); if (method_exists($row, 'getRelations')) { foreach ($row->getRelations() as $relationName => $relation) { if (is_iterable($relation)) { foreach ($relation as $relationItem) { $data[$relationName][] = self::convertToArray($relationItem, ['ignore_getters' => true]); } } else { $data[$relationName] = self::convertToArray($relation, ['ignore_getters' => true]); } } } return $data; } $row = is_object($row) && method_exists($row, 'makeHidden') ? $row->makeHidden(Arr::get($filters, 'hidden', [])) : $row; $row = is_object($row) && method_exists($row, 'makeVisible') ? $row->makeVisible(Arr::get($filters, 'visible', [])) : $row; $data = $row instanceof Arrayable ? $row->toArray() : (array) $row; foreach ($data as &$value) { if (is_object($value) || is_array($value)) { $value = self::convertToArray($value); } unset($value); } return $data; } public static function transform(array $data): array { return array_map(fn ($row) => self::transformRow($row), $data); } /** * Transform row data into an array. * * @param array $row */ protected static function transformRow($row): array { foreach ($row as $key => $value) { if ($value instanceof DateTime) { $row[$key] = $value->format('Y-m-d H:i:s'); } else { if (is_object($value) && method_exists($value, '__toString')) { $row[$key] = $value->__toString(); } else { $row[$key] = $value; } } } return $row; } /** * Build parameters depending on # of arguments passed. */ public static function buildParameters(array $args): array { $parameters = []; if (count($args) > 2) { $parameters[] = $args[0]; foreach ($args[1] as $param) { $parameters[] = $param; } } else { foreach ($args[0] as $param) { $parameters[] = $param; } } return $parameters; } /** * Replace all pattern occurrences with keyword. */ public static function replacePatternWithKeyword(array $subject, string $keyword, string $pattern = '$1'): array { $parameters = []; foreach ($subject as $param) { if (is_array($param)) { $parameters[] = self::replacePatternWithKeyword($param, $keyword, $pattern); } else { $parameters[] = str_replace($pattern, $keyword, (string) $param); } } return $parameters; } /** * Get column name from string. */ public static function extractColumnName(string $str, bool $wantsAlias): string { $matches = explode(' as ', Str::lower($str)); if (count($matches) > 1) { if ($wantsAlias) { return array_pop($matches); } return array_shift($matches); } elseif (strpos($str, '.')) { $array = explode('.', $str); return array_pop($array); } return $str; } /** * Adds % wildcards to the given string. */ public static function wildcardLikeString(string $str, bool $lowercase = true): string { return static::wildcardString($str, '%', $lowercase); } /** * Adds wildcards to the given string. */ public static function wildcardString(string $str, string $wildcard, bool $lowercase = true): string { $wild = $wildcard; $chars = (array) preg_split('//u', $str, -1, PREG_SPLIT_NO_EMPTY); if (count($chars) > 0) { foreach ($chars as $char) { $wild .= $char.$wildcard; } } if ($lowercase) { $wild = Str::lower($wild); } return $wild; } public static function toJsonScript(array $parameters, int $options = 0): string { $values = []; $replacements = []; foreach (Arr::dot($parameters) as $key => $value) { if (self::isJavascript($value, $key)) { $values[] = trim((string) $value); Arr::set($parameters, $key, '%'.$key.'%'); $replacements[] = '"%'.$key.'%"'; } } $new = []; foreach ($parameters as $key => $value) { Arr::set($new, $key, $value); } $json = (string) json_encode($new, $options); return str_replace($replacements, $values, $json); } public static function isJavascript(string|array|object|null $value, string $key): bool { if (empty($value) || is_array($value) || is_object($value)) { return false; } /** @var array $callbacks */ $callbacks = config('datatables.callback', ['$', '$.', 'function']); if (Str::startsWith($key, 'language.')) { return false; } return Str::startsWith(trim($value), $callbacks) || Str::contains($key, ['editor', 'minDate', 'maxDate']); } } laravel-datatables-oracle/src/Utilities/Config.php 0000644 00000004277 15060167532 0016236 0 ustar 00 <?php namespace Yajra\DataTables\Utilities; use Illuminate\Contracts\Config\Repository; class Config { /** * Config constructor. */ public function __construct(private readonly Repository $repository) { } /** * Check if config uses wild card search. */ public function isWildcard(): bool { return (bool) $this->repository->get('datatables.search.use_wildcards', false); } /** * Check if config uses smart search. */ public function isSmartSearch(): bool { return (bool) $this->repository->get('datatables.search.smart', true); } /** * Check if config uses case-insensitive search. */ public function isCaseInsensitive(): bool { return (bool) $this->repository->get('datatables.search.case_insensitive', false); } /** * Check if app is in debug mode. */ public function isDebugging(): bool { return (bool) $this->repository->get('app.debug', false); } /** * Get the specified configuration value. * * @param string $key * @return mixed */ public function get($key, mixed $default = null) { return $this->repository->get($key, $default); } /** * Set a given configuration value. * * @param array|string $key * @return void */ public function set($key, mixed $value = null) { $this->repository->set($key, $value); } /** * Check if dataTable config uses multi-term searching. */ public function isMultiTerm(): bool { return (bool) $this->repository->get('datatables.search.multi_term', true); } /** * Check if dataTable config uses starts_with searching. */ public function isStartsWithSearch(): bool { return (bool) $this->repository->get('datatables.search.starts_with', false); } public function jsonOptions(): int { /** @var int $options */ $options = $this->repository->get('datatables.json.options', 0); return $options; } public function jsonHeaders(): array { return (array) $this->repository->get('datatables.json.header', []); } } laravel-datatables-oracle/src/DataTableAbstract.php 0000644 00000054515 15060167532 0016363 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Http\JsonResponse; use Illuminate\Support\Arr; use Illuminate\Support\Str; use Illuminate\Support\Traits\Macroable; use Psr\Log\LoggerInterface; use Yajra\DataTables\Contracts\DataTable; use Yajra\DataTables\Contracts\Formatter; use Yajra\DataTables\Processors\DataProcessor; use Yajra\DataTables\Utilities\Helper; /** * @method static setTransformer($transformer) * @method static setSerializer($transformer) * * @property-read mixed $transformer * @property-read mixed $serializer * * @see https://github.com/yajra/laravel-datatables-fractal for transformer related methods. */ abstract class DataTableAbstract implements DataTable { use Macroable; /** * DataTables Request object. */ public Utilities\Request $request; protected ?LoggerInterface $logger = null; /** * Array of result columns/fields. */ protected ?array $columns = []; /** * DT columns definitions container (add/edit/remove/filter/order/escape). */ protected array $columnDef = [ 'index' => false, 'ignore_getters' => false, 'append' => [], 'edit' => [], 'filter' => [], 'order' => [], 'only' => null, 'hidden' => [], 'visible' => [], ]; /** * Extra/Added columns. */ protected array $extraColumns = []; /** * Total records. */ protected ?int $totalRecords = null; /** * Total filtered records. */ protected ?int $filteredRecords = null; /** * Auto-filter flag. */ protected bool $autoFilter = true; /** * Callback to override global search. * * @var callable */ protected $filterCallback = null; /** * DT row templates container. */ protected array $templates = [ 'DT_RowId' => '', 'DT_RowClass' => '', 'DT_RowData' => [], 'DT_RowAttr' => [], ]; /** * Custom ordering callback. * * @var callable|null */ protected $orderCallback = null; /** * Skip pagination as needed. */ protected bool $skipPaging = false; /** * Array of data to append on json response. */ protected array $appends = []; protected Utilities\Config $config; protected mixed $serializer; protected array $searchPanes = []; protected mixed $transformer; protected bool $editOnlySelectedColumns = false; /** * Can the DataTable engine be created with these parameters. * * @return bool */ public static function canCreate(mixed $source) { return false; } /** * Factory method, create and return an instance for the DataTable engine. * * @return static */ public static function create(mixed $source) { return new static($source); } /** * @param string|array $columns * @param string|callable|\Yajra\DataTables\Contracts\Formatter $formatter * @return $this */ public function formatColumn($columns, $formatter): static { if (is_string($formatter) && class_exists($formatter)) { $formatter = app($formatter); } if ($formatter instanceof Formatter) { foreach ((array) $columns as $column) { $this->addColumn($column.'_formatted', $formatter); } return $this; } if (is_callable($formatter)) { foreach ((array) $columns as $column) { $this->addColumn( $column.'_formatted', fn ($row) => $formatter(data_get($row, $column), $row) ); } return $this; } foreach ((array) $columns as $column) { $this->addColumn( $column.'_formatted', fn ($row) => data_get($row, $column) ); } return $this; } /** * Add column in collection. * * @param string $name * @param string|callable|Formatter $content * @param bool|int $order * @return $this */ public function addColumn($name, $content, $order = false): static { $this->extraColumns[] = $name; $this->columnDef['append'][] = ['name' => $name, 'content' => $content, 'order' => $order]; return $this; } /** * Add DT row index column on response. * * @return $this */ public function addIndexColumn(): static { $this->columnDef['index'] = true; return $this; } /** * Prevent the getters Mutators to be applied when converting a collection * of the Models into the final JSON. * * @return $this */ public function ignoreGetters(): static { $this->columnDef['ignore_getters'] = true; return $this; } /** * Edit column's content. * * @param string $name * @param string|callable $content * @return $this */ public function editColumn($name, $content): static { if ($this->editOnlySelectedColumns) { if (! count($this->request->columns()) || in_array($name, Arr::pluck($this->request->columns(), 'name'))) { $this->columnDef['edit'][] = ['name' => $name, 'content' => $content]; } } else { $this->columnDef['edit'][] = ['name' => $name, 'content' => $content]; } return $this; } /** * Remove column from collection. * * @return $this */ public function removeColumn(): static { $names = func_get_args(); $this->columnDef['excess'] = array_merge($this->getColumnsDefinition()['excess'], $names); return $this; } /** * Get columns definition. */ protected function getColumnsDefinition(): array { $config = (array) $this->config->get('datatables.columns'); $allowed = ['excess', 'escape', 'raw', 'blacklist', 'whitelist']; return array_replace_recursive(Arr::only($config, $allowed), $this->columnDef); } /** * Get only selected columns in response. * * @return $this */ public function only(array $columns = []): static { $this->columnDef['only'] = $columns; return $this; } /** * Declare columns to escape values. * * @param string|array $columns * @return $this */ public function escapeColumns($columns = '*'): static { $this->columnDef['escape'] = $columns; return $this; } /** * Add a makeHidden() to the row object. * * @return $this */ public function makeHidden(array $attributes = []): static { $hidden = (array) Arr::get($this->columnDef, 'hidden', []); $this->columnDef['hidden'] = array_merge_recursive($hidden, $attributes); return $this; } /** * Add a makeVisible() to the row object. * * @return $this */ public function makeVisible(array $attributes = []): static { $visible = (array) Arr::get($this->columnDef, 'visible', []); $this->columnDef['visible'] = array_merge_recursive($visible, $attributes); return $this; } /** * Set columns that should not be escaped. * Optionally merge the defaults from config. * * @param bool $merge * @return $this */ public function rawColumns(array $columns, $merge = false): static { if ($merge) { /** @var array[] $config */ $config = $this->config->get('datatables.columns'); $this->columnDef['raw'] = array_merge($config['raw'], $columns); } else { $this->columnDef['raw'] = $columns; } return $this; } /** * Sets DT_RowClass template. * result: <tr class="output_from_your_template">. * * @param string|callable $content * @return $this */ public function setRowClass($content): static { $this->templates['DT_RowClass'] = $content; return $this; } /** * Sets DT_RowId template. * result: <tr id="output_from_your_template">. * * @param string|callable $content * @return $this */ public function setRowId($content): static { $this->templates['DT_RowId'] = $content; return $this; } /** * Set DT_RowData templates. * * @return $this */ public function setRowData(array $data): static { $this->templates['DT_RowData'] = $data; return $this; } /** * Add DT_RowData template. * * @param string $key * @param string|callable $value * @return $this */ public function addRowData($key, $value): static { $this->templates['DT_RowData'][$key] = $value; return $this; } /** * Set DT_RowAttr templates. * result: <tr attr1="attr1" attr2="attr2">. * * @return $this */ public function setRowAttr(array $data): static { $this->templates['DT_RowAttr'] = $data; return $this; } /** * Add DT_RowAttr template. * * @param string $key * @param string|callable $value * @return $this */ public function addRowAttr($key, $value): static { $this->templates['DT_RowAttr'][$key] = $value; return $this; } /** * Append data on json response. * * @return $this */ public function with(mixed $key, mixed $value = ''): static { if (is_array($key)) { $this->appends = $key; } else { $this->appends[$key] = value($value); } return $this; } /** * Add with query callback value on response. * * @return $this */ public function withQuery(string $key, callable $value): static { $this->appends[$key] = $value; return $this; } /** * Override default ordering method with a closure callback. * * @return $this */ public function order(callable $closure): static { $this->orderCallback = $closure; return $this; } /** * Update list of columns that is not allowed for search/sort. * * @return $this */ public function blacklist(array $blacklist): static { $this->columnDef['blacklist'] = $blacklist; return $this; } /** * Update list of columns that is allowed for search/sort. * * @return $this */ public function whitelist(array|string $whitelist = '*'): static { $this->columnDef['whitelist'] = $whitelist; return $this; } /** * Set smart search config at runtime. * * @return $this */ public function smart(bool $state = true): static { $this->config->set('datatables.search.smart', $state); return $this; } /** * Set starts_with search config at runtime. * * @return $this */ public function startsWithSearch(bool $state = true): static { $this->config->set('datatables.search.starts_with', $state); return $this; } /** * Set multi_term search config at runtime. * * @return $this */ public function setMultiTerm(bool $multiTerm = true): static { $this->config->set('datatables.search.multi_term', $multiTerm); return $this; } /** * Set total records manually. * * @return $this */ public function setTotalRecords(int $total): static { $this->totalRecords = $total; return $this; } /** * Skip total records and set the recordsTotal equals to recordsFiltered. * This will improve the performance by skipping the total count query. * * @return $this * * @deprecated Just use setTotalRecords instead. */ public function skipTotalRecords(): static { $this->totalRecords = 0; return $this; } /** * Set filtered records manually. * * @return $this */ public function setFilteredRecords(int $total): static { $this->filteredRecords = $total; return $this; } /** * Skip pagination as needed. * * @return $this */ public function skipPaging(): static { $this->skipPaging = true; return $this; } /** * Skip auto filtering as needed. * * @return $this */ public function skipAutoFilter(): static { $this->autoFilter = false; return $this; } /** * Push a new column name to blacklist. * * @param string $column * @return $this */ public function pushToBlacklist($column): static { if (! $this->isBlacklisted($column)) { $this->columnDef['blacklist'][] = $column; } return $this; } /** * Check if column is blacklisted. * * @param string $column */ protected function isBlacklisted($column): bool { $colDef = $this->getColumnsDefinition(); if (in_array($column, $colDef['blacklist'])) { return true; } if ($colDef['whitelist'] === '*' || in_array($column, $colDef['whitelist'])) { return false; } return true; } /** * Perform sorting of columns. */ public function ordering(): void { if ($this->orderCallback) { call_user_func_array($this->orderCallback, $this->resolveCallbackParameter()); } else { $this->defaultOrdering(); } } /** * Resolve callback parameter instance. * * @return array<int|string, mixed> */ abstract protected function resolveCallbackParameter(); /** * Perform default query orderBy clause. */ abstract protected function defaultOrdering(): void; /** * Set auto filter off and run your own filter. * Overrides global search. * * @return $this */ public function filter(callable $callback, bool $globalSearch = false): self { $this->autoFilter = $globalSearch; $this->filterCallback = $callback; return $this; } /** * Convert the object to its JSON representation. * * @param int $options * @return \Illuminate\Http\JsonResponse */ public function toJson($options = 0) { if ($options) { $this->config->set('datatables.json.options', $options); } return $this->make(); } /** * Add a search pane options on response. * * @param string $column * @return $this */ public function searchPane($column, mixed $options, ?callable $builder = null): static { $options = value($options); if ($options instanceof Arrayable) { $options = $options->toArray(); } $this->searchPanes[$column]['options'] = $options; $this->searchPanes[$column]['builder'] = $builder; return $this; } /** * Convert instance to array. */ public function toArray(): array { return (array) $this->make()->getData(true); } /** * Count total items. */ public function totalCount(): int { return $this->totalRecords ??= $this->count(); } public function editOnlySelectedColumns(): static { $this->editOnlySelectedColumns = true; return $this; } /** * Perform necessary filters. */ protected function filterRecords(): void { if ($this->autoFilter && $this->request->isSearchable()) { $this->filtering(); } if (is_callable($this->filterCallback)) { call_user_func_array($this->filterCallback, $this->resolveCallbackParameter()); } $this->columnSearch(); $this->searchPanesSearch(); $this->filteredCount(); } /** * Perform global search. */ public function filtering(): void { $keyword = $this->request->keyword(); if ($this->config->isMultiTerm()) { $this->smartGlobalSearch($keyword); return; } $this->globalSearch($keyword); } /** * Perform multi-term search by splitting keyword into * individual words and searches for each of them. * * @param string $keyword */ protected function smartGlobalSearch($keyword): void { collect(explode(' ', $keyword)) ->reject(fn ($keyword) => trim((string) $keyword) === '') ->each(function ($keyword) { $this->globalSearch($keyword); }); } /** * Perform global search for the given keyword. */ abstract protected function globalSearch(string $keyword): void; /** * Perform search using search pane values. */ protected function searchPanesSearch(): void { // Add support for search pane. } /** * Count filtered items. */ protected function filteredCount(): int { return $this->filteredRecords ??= $this->count(); } /** * Apply pagination. */ protected function paginate(): void { if ($this->request->isPaginationable() && ! $this->skipPaging) { $this->paging(); } } /** * Transform output. * * @param iterable $results * @param array $processed */ protected function transform($results, $processed): array { if (isset($this->transformer) && class_exists('Yajra\\DataTables\\Transformers\\FractalTransformer')) { return app('datatables.transformer')->transform( $results, $this->transformer, $this->serializer ?? null ); } return Helper::transform($processed); } /** * Get processed data. * * @param iterable $results * @param bool $object * * @throws \Exception */ protected function processResults($results, $object = false): array { $processor = new DataProcessor( $results, $this->getColumnsDefinition(), $this->templates, $this->request->start() ); return $processor->process($object); } /** * Render json response. */ protected function render(array $data): JsonResponse { $output = $this->attachAppends([ 'draw' => $this->request->draw(), 'recordsTotal' => $this->totalRecords, 'recordsFiltered' => $this->filteredRecords ?? 0, 'data' => $data, ]); if ($this->config->isDebugging()) { $output = $this->showDebugger($output); } foreach ($this->searchPanes as $column => $searchPane) { $output['searchPanes']['options'][$column] = $searchPane['options']; } return new JsonResponse( $output, 200, $this->config->jsonHeaders(), $this->config->jsonOptions() ); } /** * Attach custom with meta on response. */ protected function attachAppends(array $data): array { return array_merge($data, $this->appends); } /** * Append debug parameters on output. */ protected function showDebugger(array $output): array { $output['input'] = $this->request->all(); return $output; } /** * Return an error json response. * * @throws \Yajra\DataTables\Exceptions\Exception|\Exception */ protected function errorResponse(\Exception $exception): JsonResponse { /** @var string $error */ $error = $this->config->get('datatables.error'); $debug = $this->config->get('app.debug'); if ($error === 'throw' || (! $error && ! $debug)) { throw $exception; } $this->getLogger()->error($exception); return new JsonResponse([ 'draw' => $this->request->draw(), 'recordsTotal' => $this->totalRecords, 'recordsFiltered' => 0, 'data' => [], 'error' => $error ? __($error) : 'Exception Message:'.PHP_EOL.PHP_EOL.$exception->getMessage(), ]); } /** * Get monolog/logger instance. * * @return \Psr\Log\LoggerInterface */ public function getLogger() { $this->logger = $this->logger ?: app(LoggerInterface::class); return $this->logger; } /** * Set monolog/logger instance. * * @return $this */ public function setLogger(LoggerInterface $logger): static { $this->logger = $logger; return $this; } /** * Setup search keyword. */ protected function setupKeyword(string $value): string { if ($this->config->isSmartSearch()) { $keyword = '%'.$value.'%'; if ($this->config->isWildcard()) { $keyword = Helper::wildcardLikeString($value); } // remove escaping slash added on js script request return str_replace('\\', '%', $keyword); } return $value; } /** * Get column name to be used for filtering and sorting. */ protected function getColumnName(int $index, bool $wantsAlias = false): ?string { $column = $this->request->columnName($index); if (is_null($column)) { return null; } // DataTables is using make(false) if (is_numeric($column)) { $column = $this->getColumnNameByIndex($index); } if (Str::contains(Str::upper($column), ' AS ')) { $column = Helper::extractColumnName($column, $wantsAlias); } return $column; } /** * Get column name by order column index. */ protected function getColumnNameByIndex(int $index): string { $name = (isset($this->columns[$index]) && $this->columns[$index] != '*') ? $this->columns[$index] : $this->getPrimaryKeyName(); return in_array($name, $this->extraColumns, true) ? $this->getPrimaryKeyName() : $name; } /** * If column name could not be resolved then use primary key. */ protected function getPrimaryKeyName(): string { return 'id'; } } laravel-datatables-oracle/src/ApiResourceDataTable.php 0000644 00000002666 15060167532 0017041 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Http\Resources\Json\AnonymousResourceCollection; class ApiResourceDataTable extends CollectionDataTable { /** * Can the DataTable engine be created with these parameters. * * @param mixed $source * @return bool */ public static function canCreate($source) { return $source instanceof AnonymousResourceCollection; } /** * Factory method, create and return an instance for the DataTable engine. * * @param \Illuminate\Http\Resources\Json\AnonymousResourceCollection<array-key, array>|array $source * @return ApiResourceDataTable|DataTableAbstract */ public static function create($source) { return parent::create($source); } /** * CollectionEngine constructor. * * @param \Illuminate\Http\Resources\Json\AnonymousResourceCollection<array-key, array> $resourceCollection */ public function __construct(AnonymousResourceCollection $resourceCollection) { /** @var \Illuminate\Support\Collection<(int|string), array> $collection */ $collection = collect($resourceCollection)->pluck('resource'); $this->request = app('datatables.request'); $this->config = app('datatables.config'); $this->collection = $collection; $this->original = $collection; $this->columns = array_keys($this->serialize($collection->first())); } } laravel-datatables-oracle/src/Facades/DataTables.php 0000644 00000001147 15060167532 0016401 0 ustar 00 <?php namespace Yajra\DataTables\Facades; use Illuminate\Support\Facades\Facade; /** * @mixin \Yajra\DataTables\DataTables * * @method static \Yajra\DataTables\EloquentDataTable eloquent($builder) * @method static \Yajra\DataTables\QueryDataTable query($builder) * @method static \Yajra\DataTables\CollectionDataTable collection($collection) * * @see \Yajra\DataTables\DataTables */ class DataTables extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'datatables'; } } laravel-datatables-oracle/src/lumen.php 0000644 00000001051 15060167532 0014161 0 ustar 00 <?php if (! function_exists('config_path')) { /** * Get the configuration path. * * @param string $path * @return string */ function config_path($path = '') { return app()->basePath().'/config'.($path ? '/'.$path : $path); } } if (! function_exists('public_path')) { /** * Return the path to public dir. * * @param null $path * @return string */ function public_path($path = null) { return rtrim((string) app()->basePath('public/'.$path), '/'); } } laravel-datatables-oracle/src/CollectionDataTable.php 0000644 00000021405 15060167532 0016703 0 ustar 00 <?php namespace Yajra\DataTables; use Closure; use Exception; use Illuminate\Contracts\Support\Arrayable; use Illuminate\Http\JsonResponse; use Illuminate\Http\Resources\Json\AnonymousResourceCollection; use Illuminate\Support\Arr; use Illuminate\Support\Collection; use Illuminate\Support\Str; class CollectionDataTable extends DataTableAbstract { /** * Collection object. * * @var \Illuminate\Support\Collection<array-key, array> */ public Collection $original; /** * The offset of the first record in the full dataset. */ private int $offset = 0; /** * CollectionEngine constructor. * * @param \Illuminate\Support\Collection<array-key, array> $collection */ public function __construct(public Collection $collection) { $this->request = app('datatables.request'); $this->config = app('datatables.config'); $this->original = $this->collection; $this->columns = array_keys($this->serialize($this->collection->first())); } /** * Serialize collection. */ protected function serialize(mixed $collection): array { return $collection instanceof Arrayable ? $collection->toArray() : (array) $collection; } /** * Can the DataTable engine be created with these parameters. * * @param mixed $source * @return bool */ public static function canCreate($source) { return is_array($source) || $source instanceof Collection; } /** * Factory method, create and return an instance for the DataTable engine. * * @param AnonymousResourceCollection|array|\Illuminate\Support\Collection<array-key, array> $source * @return static */ public static function create($source) { if (is_array($source)) { $source = new Collection($source); } return parent::create($source); } /** * Count results. */ public function count(): int { return $this->collection->count(); } /** * Perform column search. */ public function columnSearch(): void { for ($i = 0, $c = count($this->request->columns()); $i < $c; $i++) { $column = $this->getColumnName($i); if (is_null($column)) { continue; } if (! $this->request->isColumnSearchable($i) || $this->isBlacklisted($column)) { continue; } $regex = $this->request->isRegex($i); $keyword = $this->request->columnKeyword($i); $this->collection = $this->collection->filter( function ($row) use ($column, $keyword, $regex) { $data = $this->serialize($row); /** @var string $value */ $value = Arr::get($data, $column); if ($this->config->isCaseInsensitive()) { if ($regex) { return preg_match('/'.$keyword.'/i', $value) == 1; } return str_contains(Str::lower($value), Str::lower($keyword)); } if ($regex) { return preg_match('/'.$keyword.'/', $value) == 1; } return str_contains($value, $keyword); } ); } } /** * Perform pagination. */ public function paging(): void { $offset = $this->request->start() - $this->offset; $length = $this->request->length() > 0 ? $this->request->length() : 10; $this->collection = $this->collection->slice($offset, $length); } /** * Organizes works. * * @throws \Exception */ public function make(bool $mDataSupport = true): JsonResponse { try { $this->totalRecords = $this->totalCount(); if ($this->totalRecords) { $results = $this->results(); $processed = $this->processResults($results, $mDataSupport); $output = $this->transform($results, $processed); $this->collection = collect($output); $this->ordering(); $this->filterRecords(); $this->paginate(); $this->revertIndexColumn($mDataSupport); } return $this->render($this->collection->values()->all()); } catch (Exception $exception) { return $this->errorResponse($exception); } } /** * Get results. * * @return \Illuminate\Support\Collection<array-key, array> */ public function results(): Collection { return $this->collection; } /** * Revert transformed DT_RowIndex back to its original values. * * @param bool $mDataSupport */ private function revertIndexColumn($mDataSupport): void { if ($this->columnDef['index']) { $indexColumn = config('datatables.index_column', 'DT_RowIndex'); $index = $mDataSupport ? $indexColumn : 0; $start = $this->request->start(); $this->collection->transform(function ($data) use ($index, &$start) { $data[$index] = ++$start; return $data; }); } } /** * Define the offset of the first item of the collection with respect to * the FULL dataset the collection was sliced from. It effectively allows the * collection to be "pre-sliced". * * @return static */ public function setOffset(int $offset): self { $this->offset = $offset; return $this; } /** * Perform global search for the given keyword. */ protected function globalSearch(string $keyword): void { $keyword = $this->config->isCaseInsensitive() ? Str::lower($keyword) : $keyword; $this->collection = $this->collection->filter(function ($row) use ($keyword) { $data = $this->serialize($row); foreach ($this->request->searchableColumnIndex() as $index) { $column = $this->getColumnName($index); $value = Arr::get($data, $column); if (! is_string($value)) { continue; } else { $value = $this->config->isCaseInsensitive() ? Str::lower($value) : $value; } if (Str::contains($value, $keyword)) { return true; } } return false; }); } /** * Perform default query orderBy clause. */ protected function defaultOrdering(): void { $criteria = $this->request->orderableColumns(); if (! empty($criteria)) { $sorter = $this->getSorter($criteria); $this->collection = $this->collection ->map(fn ($data) => Arr::dot($data)) ->sort($sorter) ->map(function ($data) { foreach ($data as $key => $value) { unset($data[$key]); Arr::set($data, $key, $value); } return $data; }); } } /** * Get array sorter closure. */ protected function getSorter(array $criteria): Closure { return function ($a, $b) use ($criteria) { foreach ($criteria as $orderable) { $column = $this->getColumnName($orderable['column']); $direction = $orderable['direction']; if ($direction === 'desc') { $first = $b; $second = $a; } else { $first = $a; $second = $b; } if (is_numeric($first[$column] ?? null) && is_numeric($second[$column] ?? null)) { if ($first[$column] < $second[$column]) { $cmp = -1; } elseif ($first[$column] > $second[$column]) { $cmp = 1; } else { $cmp = 0; } } elseif ($this->config->isCaseInsensitive()) { $cmp = strnatcasecmp($first[$column] ?? '', $second[$column] ?? ''); } else { $cmp = strnatcmp($first[$column] ?? '', $second[$column] ?? ''); } if ($cmp != 0) { return $cmp; } } // all elements were equal return 0; }; } /** * Resolve callback parameter instance. * * @return array<int|string, mixed> */ protected function resolveCallbackParameter(): array { return [$this, false]; } } laravel-datatables-oracle/src/DataTablesServiceProvider.php 0000644 00000004307 15060167532 0020110 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; use Yajra\DataTables\Utilities\Config; use Yajra\DataTables\Utilities\Request; class DataTablesServiceProvider extends ServiceProvider { /** * Register the service provider. * * @return void */ public function register() { if ($this->isLumen()) { require_once 'lumen.php'; } $this->setupAssets(); $this->app->alias('datatables', DataTables::class); $this->app->singleton('datatables', fn () => new DataTables); $this->app->singleton('datatables.request', fn () => new Request); $this->app->singleton('datatables.config', Config::class); } /** * Boot the instance, add macros for datatable engines. * * @return void */ public function boot() { $engines = (array) config('datatables.engines'); foreach ($engines as $engine => $class) { $engine = Str::camel($engine); if (! method_exists(DataTables::class, $engine) && ! DataTables::hasMacro($engine)) { DataTables::macro($engine, function () use ($class) { $canCreate = [$class, 'canCreate']; if (is_callable($canCreate) && ! call_user_func_array($canCreate, func_get_args())) { throw new \InvalidArgumentException(); } $create = [$class, 'create']; if (is_callable($create)) { return call_user_func_array($create, func_get_args()); } }); } } } /** * Setup package assets. * * @return void */ protected function setupAssets() { $this->mergeConfigFrom($config = __DIR__.'/config/datatables.php', 'datatables'); if ($this->app->runningInConsole()) { $this->publishes([$config => config_path('datatables.php')], 'datatables'); } } /** * Check if app uses Lumen. * * @return bool */ protected function isLumen() { return Str::contains($this->app->version(), 'Lumen'); } } laravel-datatables-oracle/src/Contracts/Formatter.php 0000644 00000000342 15060167532 0016746 0 ustar 00 <?php namespace Yajra\DataTables\Contracts; interface Formatter { /** * @param array|\Illuminate\Database\Eloquent\Model|object $row * @return string */ public function format(mixed $value, $row); } laravel-datatables-oracle/src/Contracts/DataTable.php 0000644 00000002120 15060167532 0016620 0 ustar 00 <?php namespace Yajra\DataTables\Contracts; use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; interface DataTable { /** * Get results. * * @return \Illuminate\Support\Collection<int, array> */ public function results(): Collection; /** * Count results. */ public function count(): int; /** * Count total items. */ public function totalCount(): int; /** * Set auto filter off and run your own filter. * Overrides global search. * * @return static */ public function filter(callable $callback, bool $globalSearch = false): self; /** * Perform global search. */ public function filtering(): void; /** * Perform column search. */ public function columnSearch(): void; /** * Perform pagination. */ public function paging(): void; /** * Perform sorting of columns. */ public function ordering(): void; /** * Organizes works. */ public function make(bool $mDataSupport = true): JsonResponse; } laravel-datatables-oracle/src/config/datatables.php 0000644 00000007662 15060167532 0016430 0 ustar 00 <?php return [ /* * DataTables search options. */ 'search' => [ /* * Smart search will enclose search keyword with wildcard string "%keyword%". * SQL: column LIKE "%keyword%" */ 'smart' => true, /* * Multi-term search will explode search keyword using spaces resulting into multiple term search. */ 'multi_term' => true, /* * Case insensitive will search the keyword in lower case format. * SQL: LOWER(column) LIKE LOWER(keyword) */ 'case_insensitive' => true, /* * Wild card will add "%" in between every characters of the keyword. * SQL: column LIKE "%k%e%y%w%o%r%d%" */ 'use_wildcards' => false, /* * Perform a search which starts with the given keyword. * SQL: column LIKE "keyword%" */ 'starts_with' => false, ], /* * DataTables internal index id response column name. */ 'index_column' => 'DT_RowIndex', /* * List of available builders for DataTables. * This is where you can register your custom dataTables builder. */ 'engines' => [ 'eloquent' => Yajra\DataTables\EloquentDataTable::class, 'query' => Yajra\DataTables\QueryDataTable::class, 'collection' => Yajra\DataTables\CollectionDataTable::class, 'resource' => Yajra\DataTables\ApiResourceDataTable::class, ], /* * DataTables accepted builder to engine mapping. * This is where you can override which engine a builder should use * Note, only change this if you know what you are doing! */ 'builders' => [ //Illuminate\Database\Eloquent\Relations\Relation::class => 'eloquent', //Illuminate\Database\Eloquent\Builder::class => 'eloquent', //Illuminate\Database\Query\Builder::class => 'query', //Illuminate\Support\Collection::class => 'collection', ], /* * Nulls last sql pattern for PostgreSQL & Oracle. * For MySQL, use 'CASE WHEN :column IS NULL THEN 1 ELSE 0 END, :column :direction' */ 'nulls_last_sql' => ':column :direction NULLS LAST', /* * User friendly message to be displayed on user if error occurs. * Possible values: * null - The exception message will be used on error response. * 'throw' - Throws a \Yajra\DataTables\Exceptions\Exception. Use your custom error handler if needed. * 'custom message' - Any friendly message to be displayed to the user. You can also use translation key. */ 'error' => env('DATATABLES_ERROR', null), /* * Default columns definition of dataTable utility functions. */ 'columns' => [ /* * List of columns hidden/removed on json response. */ 'excess' => ['rn', 'row_num'], /* * List of columns to be escaped. If set to *, all columns are escape. * Note: You can set the value to empty array to disable XSS protection. */ 'escape' => '*', /* * List of columns that are allowed to display html content. * Note: Adding columns to list will make us available to XSS attacks. */ 'raw' => ['action'], /* * List of columns are forbidden from being searched/sorted. */ 'blacklist' => ['password', 'remember_token'], /* * List of columns that are only allowed fo search/sort. * If set to *, all columns are allowed. */ 'whitelist' => '*', ], /* * JsonResponse header and options config. */ 'json' => [ 'header' => [], 'options' => 0, ], /* * Default condition to determine if a parameter is a callback or not. * Callbacks needs to start by those terms, or they will be cast to string. */ 'callback' => ['$', '$.', 'function'], ]; laravel-datatables-oracle/src/EloquentDataTable.php 0000644 00000021122 15060167532 0016400 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Contracts\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasOneOrMany; use Illuminate\Database\Eloquent\Relations\HasOneThrough; use Illuminate\Database\Eloquent\Relations\MorphTo; use Illuminate\Database\Eloquent\Relations\Relation; use Yajra\DataTables\Exceptions\Exception; /** * @property EloquentBuilder $query */ class EloquentDataTable extends QueryDataTable { /** * EloquentEngine constructor. */ public function __construct(Model|EloquentBuilder $model) { $builder = match (true) { $model instanceof Model => $model->newQuery(), $model instanceof Relation => $model->getQuery(), $model instanceof EloquentBuilder => $model, }; parent::__construct($builder->getQuery()); $this->query = $builder; } /** * Can the DataTable engine be created with these parameters. * * @param mixed $source */ public static function canCreate($source): bool { return $source instanceof EloquentBuilder; } /** * Add columns in collection. * * @param bool|int $order * @return $this */ public function addColumns(array $names, $order = false) { foreach ($names as $name => $attribute) { if (is_int($name)) { $name = $attribute; } $this->addColumn($name, fn ($model) => $model->getAttribute($attribute), is_int($order) ? $order++ : $order); } return $this; } /** * If column name could not be resolved then use primary key. */ protected function getPrimaryKeyName(): string { return $this->query->getModel()->getKeyName(); } /** * {@inheritDoc} */ protected function compileQuerySearch($query, string $column, string $keyword, string $boolean = 'or', bool $nested = false): void { if (substr_count($column, '.') > 1) { $parts = explode('.', $column); $firstRelation = array_shift($parts); $column = implode('.', $parts); if ($this->isMorphRelation($firstRelation)) { $query->{$boolean.'WhereHasMorph'}( $firstRelation, '*', function (EloquentBuilder $query) use ($column, $keyword) { parent::compileQuerySearch($query, $column, $keyword, ''); } ); } else { $query->{$boolean.'WhereHas'}($firstRelation, function (EloquentBuilder $query) use ($column, $keyword) { self::compileQuerySearch($query, $column, $keyword, '', true); }); } return; } $parts = explode('.', $column); $newColumn = array_pop($parts); $relation = implode('.', $parts); if (! $nested && $this->isNotEagerLoaded($relation)) { parent::compileQuerySearch($query, $column, $keyword, $boolean); return; } if ($this->isMorphRelation($relation)) { $query->{$boolean.'WhereHasMorph'}( $relation, '*', function (EloquentBuilder $query) use ($newColumn, $keyword) { parent::compileQuerySearch($query, $newColumn, $keyword, ''); } ); } else { $query->{$boolean.'WhereHas'}($relation, function (EloquentBuilder $query) use ($newColumn, $keyword) { parent::compileQuerySearch($query, $newColumn, $keyword, ''); }); } } /** * Check if a relation was not used on eager loading. * * @param string $relation * @return bool */ protected function isNotEagerLoaded($relation) { return ! $relation || ! array_key_exists($relation, $this->query->getEagerLoads()) || $relation === $this->query->getModel()->getTable(); } /** * Check if a relation is a morphed one or not. * * @param string $relation * @return bool */ protected function isMorphRelation($relation) { $isMorph = false; if ($relation !== null && $relation !== '') { $relationParts = explode('.', $relation); $firstRelation = array_shift($relationParts); $model = $this->query->getModel(); $isMorph = method_exists($model, $firstRelation) && $model->$firstRelation() instanceof MorphTo; } return $isMorph; } /** * Resolve the proper column name be used. * * * @throws \Yajra\DataTables\Exceptions\Exception */ protected function resolveRelationColumn(string $column): string { $parts = explode('.', $column); $columnName = array_pop($parts); $relation = implode('.', $parts); if ($this->isNotEagerLoaded($relation)) { return $column; } return $this->joinEagerLoadedColumn($relation, $columnName); } /** * Join eager loaded relation and get the related column name. * * @param string $relation * @param string $relationColumn * @return string * * @throws \Yajra\DataTables\Exceptions\Exception */ protected function joinEagerLoadedColumn($relation, $relationColumn) { $table = ''; $lastQuery = $this->query; foreach (explode('.', $relation) as $eachRelation) { $model = $lastQuery->getRelation($eachRelation); switch (true) { case $model instanceof BelongsToMany: $pivot = $model->getTable(); $pivotPK = $model->getExistenceCompareKey(); $pivotFK = $model->getQualifiedParentKeyName(); $this->performJoin($pivot, $pivotPK, $pivotFK); $related = $model->getRelated(); $table = $related->getTable(); $tablePK = $model->getRelatedPivotKeyName(); $foreign = $pivot.'.'.$tablePK; $other = $related->getQualifiedKeyName(); $lastQuery->addSelect($table.'.'.$relationColumn); $this->performJoin($table, $foreign, $other); break; case $model instanceof HasOneThrough: $pivot = explode('.', $model->getQualifiedParentKeyName())[0]; // extract pivot table from key $pivotPK = $pivot.'.'.$model->getFirstKeyName(); $pivotFK = $model->getQualifiedLocalKeyName(); $this->performJoin($pivot, $pivotPK, $pivotFK); $related = $model->getRelated(); $table = $related->getTable(); $tablePK = $model->getSecondLocalKeyName(); $foreign = $pivot.'.'.$tablePK; $other = $related->getQualifiedKeyName(); $lastQuery->addSelect($lastQuery->getModel()->getTable().'.*'); break; case $model instanceof HasOneOrMany: $table = $model->getRelated()->getTable(); $foreign = $model->getQualifiedForeignKeyName(); $other = $model->getQualifiedParentKeyName(); break; case $model instanceof BelongsTo: $table = $model->getRelated()->getTable(); $foreign = $model->getQualifiedForeignKeyName(); $other = $model->getQualifiedOwnerKeyName(); break; default: throw new Exception('Relation '.$model::class.' is not yet supported.'); } $this->performJoin($table, $foreign, $other); $lastQuery = $model->getQuery(); } return $table.'.'.$relationColumn; } /** * Perform join query. * * @param string $table * @param string $foreign * @param string $other * @param string $type */ protected function performJoin($table, $foreign, $other, $type = 'left'): void { $joins = []; $builder = $this->getBaseQueryBuilder(); foreach ($builder->joins ?? [] as $join) { $joins[] = $join->table; } if (! in_array($table, $joins)) { $this->getBaseQueryBuilder()->join($table, $foreign, '=', $other, $type); } } } laravel-datatables-oracle/src/Exceptions/Exception.php 0000644 00000000126 15060167532 0017122 0 ustar 00 <?php namespace Yajra\DataTables\Exceptions; class Exception extends \Exception { } laravel-datatables-oracle/LICENSE.md 0000644 00000002117 15060167532 0013151 0 ustar 00 (The MIT License) Copyright (c) 2013-2022 Arjay Angeles <aqangeles@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. laravel-datatables-oracle/rector.php 0000644 00000001032 15060167532 0013547 0 ustar 00 <?php declare(strict_types=1); use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector; use Rector\Config\RectorConfig; use Rector\Set\ValueObject\LevelSetList; return static function (RectorConfig $rectorConfig): void { $rectorConfig->paths([ __DIR__.'/src', __DIR__.'/tests', ]); // register a single rule $rectorConfig->rule(InlineConstructorDefaultToPropertyRector::class); // define sets of rules $rectorConfig->sets([ LevelSetList::UP_TO_PHP_82, ]); }; laravel-datatables-oracle/UPGRADE.md 0000644 00000002441 15060167532 0013156 0 ustar 00 # UPGRADE GUIDE ## Upgrading from v9.x to v10.x - `ApiResourceDataTable` support dropped, use `CollectionDataTable` instead. - `queryBuilder()` deprecated method removed, use `query()` instead. - Methods signature were updated to PHP8 syntax, adjust as needed if you extended the package. ## Upgrading from v8.x to v9.x No breaking changes with only a bump on php version requirements. ## Upgrading from v7.x to v8.x There are breaking changes since DataTables v8.x. If you are upgrading from v7.x to v8.x, please see [upgrade guide](https://yajrabox.com/docs/laravel-datatables/master/upgrade). ## Upgrading from v6.x to v7.x - composer require yajra/laravel-datatables-oracle - composer require yajra/laravel-datatables-buttons - php artisan vendor:publish --tag=datatables --force - php artisan vendor:publish --tag=datatables-buttons --force ## Upgrading from v5.x to v6.x - Change all occurrences of `yajra\Datatables` to `Yajra\Datatables`. (Use Sublime's find and replace all for faster update). - Remove `Datatables` facade registration. - Temporarily comment out `Yajra\Datatables\DatatablesServiceProvider`. - Update package version on your composer.json and use `yajra/laravel-datatables-oracle: ~6.0` - Uncomment the provider `Yajra\Datatables\DatatablesServiceProvider`. laravel-datatables-oracle/CHANGELOG.md 0000644 00000001055 15060167532 0013356 0 ustar 00 # Laravel DataTables ## CHANGELOG ### [Unreleased] ### [v11.1.1](https://github.com/yajra/laravel-datatables/compare/v11.1.0...v11.1.1) - 2024-04-16 - fix: mariadb support for scout search #3146 ### [v11.1.0](https://github.com/yajra/laravel-datatables/compare/v11.0.0...v11.1.0) - 2024-04-16 - feat: Optimize simple queries #3135 - fix: #3133 ### [v11.0.0](https://github.com/yajra/laravel-datatables/compare/v11.0.0...master) - 2024-03-14 - Laravel 11 support [Unreleased]: https://github.com/yajra/laravel-datatables/compare/v11.0.0...master laravel-datatables-oracle/composer.json 0000644 00000005243 15060167532 0014272 0 ustar 00 { "name": "yajra/laravel-datatables-oracle", "description": "jQuery DataTables API for Laravel", "keywords": [ "yajra", "laravel", "dataTables", "jquery" ], "license": "MIT", "authors": [ { "name": "Arjay Angeles", "email": "aqangeles@gmail.com" } ], "require": { "php": "^8.2", "illuminate/database": "^11", "illuminate/filesystem": "^11", "illuminate/http": "^11", "illuminate/support": "^11", "illuminate/view": "^11" }, "require-dev": { "algolia/algoliasearch-client-php": "^3.4.1", "larastan/larastan": "^2.9.1", "laravel/pint": "^1.14", "laravel/scout": "^10.8.3", "meilisearch/meilisearch-php": "^1.6.1", "orchestra/testbench": "^9", "rector/rector": "^1.0" }, "suggest": { "yajra/laravel-datatables-export": "Plugin for server-side exporting using livewire and queue worker.", "yajra/laravel-datatables-buttons": "Plugin for server-side exporting of dataTables.", "yajra/laravel-datatables-html": "Plugin for server-side HTML builder of dataTables.", "yajra/laravel-datatables-fractal": "Plugin for server-side response using Fractal.", "yajra/laravel-datatables-editor": "Plugin to use DataTables Editor (requires a license)." }, "autoload": { "psr-4": { "Yajra\\DataTables\\": "src/" }, "files": [ "src/helper.php" ] }, "autoload-dev": { "psr-4": { "Yajra\\DataTables\\Tests\\": "tests/" } }, "extra": { "branch-alias": { "dev-master": "11.x-dev" }, "laravel": { "providers": [ "Yajra\\DataTables\\DataTablesServiceProvider" ], "aliases": { "DataTables": "Yajra\\DataTables\\Facades\\DataTables" } } }, "config": { "sort-packages": true, "allow-plugins": { "php-http/discovery": true } }, "scripts": { "test": "./vendor/bin/phpunit", "pint": "./vendor/bin/pint", "rector": "./vendor/bin/rector", "stan": "./vendor/bin/phpstan analyse --memory-limit=2G --ansi --no-progress --no-interaction --configuration=phpstan.neon.dist", "pr": [ "@rector", "@pint", "@stan", "@test" ] }, "minimum-stability": "dev", "prefer-stable": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/yajra" } ] } laravel-datatables-oracle/pint.json 0000644 00000000034 15060167532 0013406 0 ustar 00 { "preset": "laravel" } laravel-datatables-oracle/README.md 0000644 00000012701 15060167532 0013024 0 ustar 00 # jQuery DataTables API for Laravel [](https://gitter.im/yajra/laravel-datatables?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://www.paypal.me/yajra) [](https://www.patreon.com/bePatron?u=4521203) [](http://laravel.com) [](https://packagist.org/packages/yajra/laravel-datatables-oracle) [](https://github.com/yajra/laravel-datatables/actions/workflows/continuous-integration.yml) [](https://github.com/yajra/laravel-datatables/actions/workflows/static-analysis.yml) [](https://packagist.org/packages/yajra/laravel-datatables-oracle) [](https://packagist.org/packages/yajra/laravel-datatables-oracle) Laravel package for handling [server-side](https://www.datatables.net/manual/server-side) works of [DataTables](http://datatables.net) jQuery Plugin via [AJAX option](https://datatables.net/reference/option/ajax) by using Eloquent ORM, Fluent Query Builder or Collection. ```php use Yajra\DataTables\Facades\DataTables; return DataTables::eloquent(User::query())->toJson(); return DataTables::query(DB::table('users'))->toJson(); return DataTables::collection(User::all())->toJson(); return DataTables::make(User::query())->toJson(); return DataTables::make(DB::table('users'))->toJson(); return DataTables::make(User::all())->toJson(); ``` ## Sponsors <a href="https://editor.datatables.net?utm_source=laravel-datatables&utm_medium=github_readme&utm_campaign=logo"> <img src="http://datatables.net/media/images/logo.png" alt="DataTables" height="64"> </a> <a href="https://jb.gg/OpenSourceSupport"> <img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jb_beam.png" alt="JetBrains.com" height="128"> </a> <a href="https://blackfire.io/docs/introduction?utm_source=laravel-datatables&utm_medium=github_readme&utm_campaign=logo"> <img src="https://i.imgur.com/zR8rsqk.png" alt="Blackfire.io" height="64"> </a> ## Requirements - [PHP >= 8.2](http://php.net/) - [Laravel Framework](https://github.com/laravel/framework) - [jQuery DataTables](http://datatables.net/) ## Documentations - [Github Docs](https://github.com/yajra/laravel-datatables-docs) - [Laravel DataTables Quick Starter](https://yajrabox.com/docs/laravel-datatables/master/quick-starter) - [Laravel DataTables Documentation](https://yajrabox.com/docs/laravel-datatables) ## Laravel Version Compatibility | Laravel | Package | |:--------|:---------| | 4.2.x | 3.x | | 5.0.x | 6.x | | 5.1.x | 6.x | | 5.2.x | 6.x | | 5.3.x | 6.x | | 5.4.x | 7.x, 8.x | | 5.5.x | 8.x | | 5.6.x | 8.x | | 5.7.x | 8.x | | 5.8.x | 9.x | | 6.x | 9.x | | 7.x | 9.x | | 8.x | 9.x | | 9.x | 10.x | | 10.x | 10.x | | 11.x | 11.x | ## Quick Installation ```bash composer require yajra/laravel-datatables-oracle:"^11" ``` #### Service Provider & Facade (Optional on Laravel 5.5+) Register provider and facade on your `config/app.php` file. ```php 'providers' => [ ..., Yajra\DataTables\DataTablesServiceProvider::class, ] 'aliases' => [ ..., 'DataTables' => Yajra\DataTables\Facades\DataTables::class, ] ``` #### Configuration (Optional) ```bash php artisan vendor:publish --provider="Yajra\DataTables\DataTablesServiceProvider" ``` And that's it! Start building out some awesome DataTables! ## Debugging Mode To enable debugging mode, just set `APP_DEBUG=true` and the package will include the queries and inputs used when processing the table. **IMPORTANT:** Please make sure that APP_DEBUG is set to false when your app is on production. ## PHP ARTISAN SERVE BUG Please avoid using `php artisan serve` when developing with the package. There are known bugs when using this where Laravel randomly returns a redirect and 401 (Unauthorized) if the route requires authentication and a 404 NotFoundHttpException on valid routes. It is advised to use [Homestead](https://laravel.com/docs/5.4/homestead) or [Valet](https://laravel.com/docs/5.4/valet) when working with the package. ## Contributing Please see [CONTRIBUTING](https://github.com/yajra/laravel-datatables/blob/master/.github/CONTRIBUTING.md) for details. ## Security If you discover any security related issues, please email [aqangeles@gmail.com](mailto:aqangeles@gmail.com) instead of using the issue tracker. ## Credits - [Arjay Angeles](https://github.com/yajra) - [bllim/laravel4-datatables-package](https://github.com/bllim/laravel4-datatables-package) - [All Contributors](https://github.com/yajra/laravel-datatables/graphs/contributors) ## License The MIT License (MIT). Please see [License File](https://github.com/yajra/laravel-datatables/blob/master/LICENSE.md) for more information. laravel-datatables-oracle/CONDUCT.md 0000644 00000012243 15060167532 0013167 0 ustar 00 # Contributor Covenant Code of Conduct ## Our Pledge We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation. We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. ## Our Standards Examples of behavior that contributes to a positive environment for our community include: * Demonstrating empathy and kindness toward other people * Being respectful of differing opinions, viewpoints, and experiences * Giving and gracefully accepting constructive feedback * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience * Focusing on what is best not just for us as individuals, but for the overall community Examples of unacceptable behavior include: * The use of sexualized language or imagery, and sexual attention or advances of any kind * Trolling, insulting or derogatory comments, and personal or political attacks * Public or private harassment * Publishing others’ private information, such as a physical or email address, without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Enforcement Responsibilities Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. ## Scope This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [INSERT CONTACT METHOD]. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the reporter of any incident. ## Enforcement Guidelines Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: ### 1. Correction Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. ### 2. Warning Community Impact: A violation through a single incident or series of actions. Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. ### 3. Temporary Ban Community Impact: A serious violation of community standards, including sustained inappropriate behavior. Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. ### 4. Permanent Ban Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. Consequence: A permanent ban from any sort of public interaction within the community. ## Attribution This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html. Community Impact Guidelines were inspired by Mozilla’s code of conduct enforcement ladder. For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. For answers to common questions about this code of conduct, see the FAQ at https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations. laravel-datatables-fractal/src/Transformers/FractalTransformer.php 0000644 00000004673 15060167532 0021511 0 ustar 00 <?php namespace Yajra\DataTables\Transformers; use Closure; use Illuminate\Support\Collection as LaravelCollection; use League\Fractal\Manager; use League\Fractal\Resource\Collection; use League\Fractal\Serializer\SerializerAbstract; use League\Fractal\TransformerAbstract; class FractalTransformer { protected Manager $fractal; /** * FractalTransformer constructor. */ public function __construct(Manager $fractal) { $this->fractal = $fractal; } /** * Transform output using the given transformer and serializer. */ public function transform( array|LaravelCollection $output, iterable $transformer, ?SerializerAbstract $serializer = null ): array { if ($serializer !== null) { $this->fractal->setSerializer($this->createSerializer($serializer)); } $collector = []; foreach ($transformer as $transform) { if ($transform != null) { $resource = new Collection($output, $this->createTransformer($transform)); $collection = $this->fractal->createData($resource)->toArray(); $transformed = $collection['data'] ?? $collection; $collector = array_map( function ($item_collector, $item_transformed) { if (! is_array($item_collector)) { $item_collector = []; } return array_merge($item_collector, $item_transformed); }, $collector, $transformed ); } } return $collector; } /** * Get or create transformer serializer instance. * * @param class-string|SerializerAbstract $serializer */ protected function createSerializer(SerializerAbstract|string $serializer): SerializerAbstract { if ($serializer instanceof SerializerAbstract) { return $serializer; } return new $serializer(); } /** * Get or create transformer instance. * * @param \Closure|class-string|TransformerAbstract $transformer */ protected function createTransformer(Closure|string|TransformerAbstract $transformer): Closure|TransformerAbstract { if ($transformer instanceof TransformerAbstract || $transformer instanceof Closure) { return $transformer; } return new $transformer(); } } laravel-datatables-fractal/src/Commands/stubs/transformer.inc.stub 0000644 00000001163 15060167532 0021415 0 ustar 00 <?php namespace DummyNamespace; use League\Fractal\TransformerAbstract; use App\Dummy; use App\Item; class DummyClass extends TransformerAbstract { protected $availableIncludes = ['item']; /** * @param \App\Dummy $dummy * @return array */ public function transform(Dummy $dummy): array { return [ 'id' => (int) $dummy->id, ]; } /** * @param \App\Dummy $dummy * @return \League\Fractal\Resource\Collection */ public function includeItem(Dummy $dummy) { return $this->collection($dummy->item, new ItemTransformer); } } laravel-datatables-fractal/src/Commands/stubs/transformer.stub 0000644 00000000520 15060167532 0020641 0 ustar 00 <?php namespace DummyNamespace; use League\Fractal\TransformerAbstract; use App\Dummy; class DummyClass extends TransformerAbstract { /** * @param \App\Dummy $dummy * @return array */ public function transform(Dummy $dummy): array { return [ 'id' => (int) $dummy->id, ]; } } laravel-datatables-fractal/src/Commands/TransformerMakeCommand.php 0000644 00000004353 15060167532 0021360 0 ustar 00 <?php namespace Yajra\DataTables\Commands; use Illuminate\Console\GeneratorCommand; use Illuminate\Support\Str; class TransformerMakeCommand extends GeneratorCommand { /** * The name and signature of the console command. * * @var string */ protected $signature = 'make:transformer {name : The name of the class} {include? : Name of the class to include.}'; /** * The console command description. * * @var string */ protected $description = 'Create a new Transformer Class'; /** * The type of class being generated. * * @var string */ protected $type = 'Transformer'; /** * Replace the class name for the given stub. * * @param string $stub Contents of the stub * @param string $name The class name */ protected function replaceClass($stub, $name): string { $stub = parent::replaceClass($stub, $name.'Transformer'); $stub = str_replace('Dummy', ucfirst($this->argument('name')), $stub); $stub = str_replace('dummy', lcfirst($this->argument('name')), $stub); if ($this->argument('include')) { $stub = str_replace('Item', ucfirst($this->argument('include')), $stub); $stub = str_replace('item', lcfirst($this->argument('include')), $stub); } return $stub; } /** * Get the stub file for the generator. */ protected function getStub(): string { return $this->argument('include') ? __DIR__.'/stubs/transformer.inc.stub' : __DIR__.'/stubs/transformer.stub'; } /** * Get the default namespace for the class. * * @param string $rootNamespace The root namespace */ protected function getDefaultNamespace($rootNamespace): string { return $rootNamespace.'\Transformers'; } /** * Get the destination class path. * * @param string $name Name of the class with namespace */ protected function getPath($name): string { $name = Str::replaceFirst($this->rootNamespace(), '', $name); return $this->laravel['path'].'/'.str_replace('\\', '/', $name).'Transformer.php'; } } laravel-datatables-fractal/src/FractalServiceProvider.php 0000644 00000005151 15060167532 0017625 0 ustar 00 <?php namespace Yajra\DataTables; use Illuminate\Support\ServiceProvider; use League\Fractal\Manager; use League\Fractal\Serializer\DataArraySerializer; use Yajra\DataTables\Commands\TransformerMakeCommand; use Yajra\DataTables\Transformers\FractalTransformer; class FractalServiceProvider extends ServiceProvider { /** * Bootstrap the application events. */ public function boot(): void { $this->mergeConfigFrom(__DIR__.'/../config/datatables-fractal.php', 'datatables-fractal'); $this->publishAssets(); $this->registerMacro(); } /** * Publish datatables assets. */ protected function publishAssets(): void { $this->publishes( [ __DIR__.'/../config/datatables-fractal.php' => config_path('datatables-fractal.php'), ], 'datatables-fractal' ); } /** * Register DataTables macro methods. */ protected function registerMacro(): void { DataTableAbstract::macro('setTransformer', function ($transformer) { $this->transformer = [$transformer]; return $this; }); DataTableAbstract::macro('addTransformer', function ($transformer) { $this->transformer[] = $transformer; return $this; }); DataTableAbstract::macro('setSerializer', function ($serializer) { $this->serializer = $serializer; return $this; }); } /** * Register the service provider. */ public function register(): void { $this->app->singleton('datatables.fractal', function () { $fractal = new Manager; $config = $this->app['config']; $request = $this->app['request']; $includesKey = $config->get('datatables-fractal.includes', 'include'); if ($request->get($includesKey)) { $fractal->parseIncludes($request->get($includesKey)); } $serializer = $config->get('datatables-fractal.serializer', DataArraySerializer::class); $fractal->setSerializer(new $serializer); return $fractal; }); $this->app->singleton('datatables.transformer', function () { return new FractalTransformer($this->app->make('datatables.fractal')); }); $this->commands([ TransformerMakeCommand::class, ]); } /** * Get the services provided by the provider. */ public function provides(): array { return [ 'datatables.fractal', 'datatables.transformer', ]; } } laravel-datatables-fractal/LICENSE.md 0000644 00000002117 15060167532 0013320 0 ustar 00 (The MIT License) Copyright (c) 2013-2018 Arjay Angeles <aqangeles@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. laravel-datatables-fractal/CHANGELOG.md 0000644 00000000663 15060167532 0013531 0 ustar 00 # Laravel DataTables Fractal Plugin ## Changelog ### v11.0.0 - 2024-03-14 - Add support for Laravel 11 ### v10.0.0 - 2023-02-07 - Add support for Laravel 10 ### v9.1.0 - 2022-06-20 - Update league/fractal to latest version #30 ### v9.0.0 - 2022-05-07 - Add support for Laravel 9 - Fix https://github.com/yajra/laravel-datatables-fractal/issues/27 - Add phpstan static analysis - Bump major version to match with the framework laravel-datatables-fractal/composer.json 0000644 00000001642 15060167532 0014440 0 ustar 00 { "name": "yajra/laravel-datatables-fractal", "description": "Laravel DataTables Fractal Plugin.", "keywords": [ "laravel", "datatables", "fractal", "api" ], "license": "MIT", "authors": [ { "name": "Arjay Angeles", "email": "aqangeles@gmail.com" } ], "require": { "php": "^8.2", "yajra/laravel-datatables-oracle": "^11.0", "league/fractal": "^0.20.1" }, "require-dev": { "nunomaduro/larastan": "^2.9.2", "orchestra/testbench": "^9" }, "autoload": { "psr-4": { "Yajra\\DataTables\\": "src/" } }, "autoload-dev": { "psr-4": { "Yajra\\DataTables\\Fractal\\Tests\\": "tests/" } }, "extra": { "branch-alias": { "dev-master": "11.x-dev" }, "laravel": { "providers": [ "Yajra\\DataTables\\FractalServiceProvider" ] } }, "minimum-stability": "dev", "prefer-stable": true } laravel-datatables-fractal/config/datatables-fractal.php 0000644 00000000362 15060167532 0017410 0 ustar 00 <?php return [ /* * Request key name to parse includes on fractal. */ 'includes' => 'include', /* * Default fractal serializer. */ 'serializer' => League\Fractal\Serializer\DataArraySerializer::class, ]; laravel-datatables-fractal/README.md 0000644 00000005073 15060167532 0013177 0 ustar 00 # Laravel DataTables Fractal Plugin [](http://laravel.com) [](https://packagist.org/packages/yajra/laravel-datatables-fractal) [](https://travis-ci.org/yajra/laravel-datatables-fractal) [](https://scrutinizer-ci.com/g/yajra/laravel-datatables-fractal/?branch=master) [](https://packagist.org/packages/yajra/laravel-datatables-fractal) [](https://packagist.org/packages/yajra/laravel-datatables-fractal) This package is a plugin of [Laravel DataTables](https://github.com/yajra/laravel-datatables) for transforming server-side response using [Fractal](https://github.com/thephpleague/fractal). ## Requirements - [PHP >= 8.2](http://php.net/) - [Laravel 11.x](https://github.com/laravel/framework) - [Laravel DataTables](https://github.com/yajra/laravel-datatables) ## Documentations - [Laravel DataTables Fractal Documentation](https://yajrabox.com/docs/laravel-datatables/master/response-fractal) ## Laravel Version Compatibility | Laravel | Package | |:--------------|:--------| | 8.x and below | 1.x | | 9.x | 9.x | | 10.x | 10.x | | 11.x | 11.x | ## Quick Installation `composer require yajra/laravel-datatables-fractal:^11.0` ### Register Service Provider (Optional on Laravel 5.5+) `Yajra\DataTables\FractalServiceProvider::class` ### Configuration and Assets (Optional) `$ php artisan vendor:publish --tag=datatables-fractal --force` And that's it! Start building out some awesome DataTables! ## Contributing Please see [CONTRIBUTING](https://github.com/yajra/laravel-datatables-fractal/blob/master/.github/CONTRIBUTING.md) for details. ## Security If you discover any security related issues, please email [aqangeles@gmail.com](mailto:aqangeles@gmail.com) instead of using the issue tracker. ## Credits - [Arjay Angeles](https://github.com/yajra) - [All Contributors](https://github.com/yajra/laravel-datatables-fractal/graphs/contributors) ## License The MIT License (MIT). Please see [License File](https://github.com/yajra/laravel-datatables-fractal/blob/master/LICENSE.md) for more information.
| ver. 1.4 |
Github
|
.
| PHP 8.2.29 | Ð“ÐµÐ½ÐµÑ€Ð°Ñ†Ð¸Ñ Ñтраницы: 0.02 |
proxy
|
phpinfo
|
ÐаÑтройка